run without lapic and ioapic, if they are not present
if no lapic available, use 8253pit for clock now xv6 runs both on qemu (uniprocessor) and bochs (uniprocessor and MP)feat/start
parent
f9bc4452b5
commit
f70172129c
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include "types.h"
|
||||||
|
#include "x86.h"
|
||||||
|
#include "defs.h"
|
||||||
|
#include "traps.h"
|
||||||
|
|
||||||
|
// Register definitions for the Intel
|
||||||
|
// 8253/8254/82C54 Programmable Interval Timer (PIT).
|
||||||
|
|
||||||
|
#define IO_TIMER1 0x040 /* 8253 Timer #1 */
|
||||||
|
#define IO_TIMER2 0x048 /* 8253 Timer #2 (EISA only) */
|
||||||
|
|
||||||
|
//
|
||||||
|
// Frequency of all three count-down timers; (TIMER_FREQ/freq) is the
|
||||||
|
// appropriate count to generate a frequency of freq hz.
|
||||||
|
|
||||||
|
#define TIMER_FREQ 1193182
|
||||||
|
#define TIMER_DIV(x) ((TIMER_FREQ+(x)/2)/(x))
|
||||||
|
|
||||||
|
#define TIMER_CNTR0 (IO_TIMER1 + 0) /* timer 0 counter port */
|
||||||
|
#define TIMER_CNTR1 (IO_TIMER1 + 1) /* timer 1 counter port */
|
||||||
|
#define TIMER_CNTR2 (IO_TIMER1 + 2) /* timer 2 counter port */
|
||||||
|
#define TIMER_MODE (IO_TIMER1 + 3) /* timer mode port */
|
||||||
|
#define TIMER_SEL0 0x00 /* select counter 0 */
|
||||||
|
#define TIMER_SEL1 0x40 /* select counter 1 */
|
||||||
|
#define TIMER_SEL2 0x80 /* select counter 2 */
|
||||||
|
#define TIMER_INTTC 0x00 /* mode 0, intr on terminal cnt */
|
||||||
|
#define TIMER_ONESHOT 0x02 /* mode 1, one shot */
|
||||||
|
#define TIMER_RATEGEN 0x04 /* mode 2, rate generator */
|
||||||
|
#define TIMER_SQWAVE 0x06 /* mode 3, square wave */
|
||||||
|
#define TIMER_SWSTROBE 0x08 /* mode 4, s/w triggered strobe */
|
||||||
|
#define TIMER_HWSTROBE 0x0a /* mode 5, h/w triggered strobe */
|
||||||
|
#define TIMER_LATCH 0x00 /* latch counter for reading */
|
||||||
|
#define TIMER_LSB 0x10 /* r/w counter LSB */
|
||||||
|
#define TIMER_MSB 0x20 /* r/w counter MSB */
|
||||||
|
#define TIMER_16BIT 0x30 /* r/w counter 16 bits, LSB first */
|
||||||
|
#define TIMER_BCD 0x01 /* count in BCD */
|
||||||
|
|
||||||
|
void
|
||||||
|
pit8253_timerinit(void)
|
||||||
|
{
|
||||||
|
// initialize 8253 clock to interrupt 100 times/sec
|
||||||
|
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
|
||||||
|
outb(IO_TIMER1, TIMER_DIV(100) % 256);
|
||||||
|
outb(IO_TIMER1, TIMER_DIV(100) / 256);
|
||||||
|
irq_setmask_8259A(irq_mask_8259A & ~(1<<IRQ_TIMER));
|
||||||
|
}
|
||||||
1
Makefile
1
Makefile
|
|
@ -21,6 +21,7 @@ OBJS = \
|
||||||
vectors.o\
|
vectors.o\
|
||||||
bio.o\
|
bio.o\
|
||||||
fs.o\
|
fs.o\
|
||||||
|
8253pit.o\
|
||||||
|
|
||||||
# Cross-compiling (e.g., on Mac OS X)
|
# Cross-compiling (e.g., on Mac OS X)
|
||||||
TOOLPREFIX = i386-jos-elf-
|
TOOLPREFIX = i386-jos-elf-
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,7 @@ console_init()
|
||||||
devsw[CONSOLE].d_write = console_write;
|
devsw[CONSOLE].d_write = console_write;
|
||||||
devsw[CONSOLE].d_read = console_read;
|
devsw[CONSOLE].d_read = console_read;
|
||||||
|
|
||||||
|
irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_KBD));
|
||||||
ioapic_enable(IRQ_KBD, 0);
|
ioapic_enable(IRQ_KBD, 0);
|
||||||
|
|
||||||
use_console_lock = 1;
|
use_console_lock = 1;
|
||||||
|
|
|
||||||
6
defs.h
6
defs.h
|
|
@ -49,9 +49,15 @@ int checkstring(uint);
|
||||||
int putint(struct proc*, uint, int);
|
int putint(struct proc*, uint, int);
|
||||||
|
|
||||||
// picirq.c
|
// picirq.c
|
||||||
|
extern ushort irq_mask_8259A;
|
||||||
void pic_init(void);
|
void pic_init(void);
|
||||||
|
void irq_setmask_8259A(ushort);
|
||||||
|
|
||||||
|
// 8253pit.c
|
||||||
|
void pit8253_timerinit(void);
|
||||||
|
|
||||||
// mp.c
|
// mp.c
|
||||||
|
extern int ismp;
|
||||||
void mp_init(void);
|
void mp_init(void);
|
||||||
void mp_startthem(void);
|
void mp_startthem(void);
|
||||||
int mp_bcpu(void);
|
int mp_bcpu(void);
|
||||||
|
|
|
||||||
1
ide.c
1
ide.c
|
|
@ -50,6 +50,7 @@ void
|
||||||
ide_init(void)
|
ide_init(void)
|
||||||
{
|
{
|
||||||
initlock(&ide_lock, "ide");
|
initlock(&ide_lock, "ide");
|
||||||
|
irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_IDE));
|
||||||
ioapic_enable (IRQ_IDE, ncpu - 1);
|
ioapic_enable (IRQ_IDE, ncpu - 1);
|
||||||
ide_wait_ready(0);
|
ide_wait_ready(0);
|
||||||
disk_1_present = ide_probe_disk1();
|
disk_1_present = ide_probe_disk1();
|
||||||
|
|
|
||||||
66
ioapic.c
66
ioapic.c
|
|
@ -37,28 +37,30 @@ ioapic_init(void)
|
||||||
uchar id;
|
uchar id;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
io = (struct ioapic*) IO_APIC_BASE;
|
if (ismp) {
|
||||||
l = ioapic_read(io, IOAPIC_VER);
|
io = (struct ioapic*) IO_APIC_BASE;
|
||||||
nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
|
l = ioapic_read(io, IOAPIC_VER);
|
||||||
id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
|
nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
|
||||||
if(id != ioapic_id)
|
id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
|
||||||
panic("ioapic_init: id isn't equal to ioapic_id\n");
|
if(id != ioapic_id)
|
||||||
for(i = 0; i < nintr; i++) {
|
cprintf("ioapic_init: id isn't equal to ioapic_id; not a MP\n");
|
||||||
// active-hi and edge-triggered for ISA interrupts
|
for(i = 0; i < nintr; i++) {
|
||||||
// Assume that pin 0 on the first I/O APIC is an ExtINT pin.
|
// active-hi and edge-triggered for ISA interrupts
|
||||||
// Assume that pins 1-15 are ISA interrupts
|
// Assume that pin 0 on the first I/O APIC is an ExtINT pin.
|
||||||
l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
|
// Assume that pins 1-15 are ISA interrupts
|
||||||
l = l & ~IOART_INTMASK; // allow INTs
|
l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
|
||||||
l |= IOART_INTMSET;
|
l = l & ~IOART_INTMASK; // allow INTs
|
||||||
l = l & ~IOART_INTPOL; // active hi
|
l |= IOART_INTMSET;
|
||||||
l = l & ~IOART_TRGRMOD; // edgee triggered
|
l = l & ~IOART_INTPOL; // active hi
|
||||||
l = l & ~IOART_DELMOD; // fixed
|
l = l & ~IOART_TRGRMOD; // edgee triggered
|
||||||
l = l & ~IOART_DESTMOD; // physical mode
|
l = l & ~IOART_DELMOD; // fixed
|
||||||
l = l | (IRQ_OFFSET + i); // vector
|
l = l & ~IOART_DESTMOD; // physical mode
|
||||||
ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
|
l = l | (IRQ_OFFSET + i); // vector
|
||||||
h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
|
ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
|
||||||
h &= ~IOART_DEST;
|
h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
|
||||||
ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
|
h &= ~IOART_DEST;
|
||||||
|
ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,13 +69,15 @@ ioapic_enable (int irq, int cpunum)
|
||||||
{
|
{
|
||||||
uint l, h;
|
uint l, h;
|
||||||
struct ioapic *io;
|
struct ioapic *io;
|
||||||
|
|
||||||
io = (struct ioapic*) IO_APIC_BASE;
|
if (ismp) {
|
||||||
l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
|
io = (struct ioapic*) IO_APIC_BASE;
|
||||||
l = l & ~IOART_INTMASK; // allow INTs
|
l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
|
||||||
ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
|
l = l & ~IOART_INTMASK; // allow INTs
|
||||||
h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
|
ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
|
||||||
h &= ~IOART_DEST;
|
h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
|
||||||
h |= (cpunum << APIC_ID_SHIFT);
|
h &= ~IOART_DEST;
|
||||||
ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
|
h |= (cpunum << APIC_ID_SHIFT);
|
||||||
|
ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
lapic.c
33
lapic.c
|
|
@ -105,17 +105,20 @@ lapic_write(int r, int data)
|
||||||
void
|
void
|
||||||
lapic_timerinit(void)
|
lapic_timerinit(void)
|
||||||
{
|
{
|
||||||
lapic_write(LAPIC_TDCR, LAPIC_X1);
|
if (lapicaddr) {
|
||||||
lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
|
lapic_write(LAPIC_TDCR, LAPIC_X1);
|
||||||
(IRQ_OFFSET + IRQ_TIMER));
|
lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
|
||||||
lapic_write(LAPIC_TCCR, 10000000);
|
(IRQ_OFFSET + IRQ_TIMER));
|
||||||
lapic_write(LAPIC_TICR, 10000000);
|
lapic_write(LAPIC_TCCR, 10000000);
|
||||||
|
lapic_write(LAPIC_TICR, 10000000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lapic_timerintr(void)
|
lapic_timerintr(void)
|
||||||
{
|
{
|
||||||
lapic_write(LAPIC_EOI, 0);
|
if (lapicaddr)
|
||||||
|
lapic_write(LAPIC_EOI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -123,6 +126,9 @@ lapic_init(int c)
|
||||||
{
|
{
|
||||||
uint r, lvt;
|
uint r, lvt;
|
||||||
|
|
||||||
|
if (lapicaddr == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
lapic_write(LAPIC_DFR, 0xFFFFFFFF); // Set dst format register
|
lapic_write(LAPIC_DFR, 0xFFFFFFFF); // Set dst format register
|
||||||
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
|
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
|
||||||
lapic_write(LAPIC_LDR, (1<<r)<<24); // Set logical dst register to r
|
lapic_write(LAPIC_LDR, (1<<r)<<24); // Set logical dst register to r
|
||||||
|
|
@ -155,25 +161,32 @@ lapic_init(int c)
|
||||||
void
|
void
|
||||||
lapic_enableintr(void)
|
lapic_enableintr(void)
|
||||||
{
|
{
|
||||||
lapic_write(LAPIC_TPR, 0);
|
if (lapicaddr)
|
||||||
|
lapic_write(LAPIC_TPR, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lapic_disableintr(void)
|
lapic_disableintr(void)
|
||||||
{
|
{
|
||||||
lapic_write(LAPIC_TPR, 0xFF);
|
if (lapicaddr)
|
||||||
|
lapic_write(LAPIC_TPR, 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
lapic_eoi(void)
|
lapic_eoi(void)
|
||||||
{
|
{
|
||||||
lapic_write(LAPIC_EOI, 0);
|
if (lapicaddr)
|
||||||
|
lapic_write(LAPIC_EOI, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cpu(void)
|
cpu(void)
|
||||||
{
|
{
|
||||||
int x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
|
int x;
|
||||||
|
if (lapicaddr)
|
||||||
|
x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
|
||||||
|
else
|
||||||
|
x = 0;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
7
main.c
7
main.c
|
|
@ -71,8 +71,11 @@ main0(void)
|
||||||
// start other CPUs
|
// start other CPUs
|
||||||
mp_startthem();
|
mp_startthem();
|
||||||
|
|
||||||
// turn on timer and enable interrupts on the local APIC
|
// turn on timer
|
||||||
lapic_timerinit();
|
if (ismp) lapic_timerinit();
|
||||||
|
else pit8253_timerinit();
|
||||||
|
|
||||||
|
// enable interrupts on the local APIC
|
||||||
lapic_enableintr();
|
lapic_enableintr();
|
||||||
|
|
||||||
// Enable interrupts on this processor.
|
// Enable interrupts on this processor.
|
||||||
|
|
|
||||||
8
mp.c
8
mp.c
|
|
@ -30,6 +30,7 @@ static char *buses[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpu cpus[NCPU];
|
struct cpu cpus[NCPU];
|
||||||
|
int ismp;
|
||||||
int ncpu;
|
int ncpu;
|
||||||
uchar ioapic_id;
|
uchar ioapic_id;
|
||||||
|
|
||||||
|
|
@ -124,8 +125,11 @@ mp_init(void)
|
||||||
uchar byte;
|
uchar byte;
|
||||||
|
|
||||||
ncpu = 0;
|
ncpu = 0;
|
||||||
if((r = mp_detect()) != 0)
|
if((r = mp_detect()) != 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ismp = 1;
|
||||||
|
|
||||||
// Run through the table saving information needed for starting
|
// Run through the table saving information needed for starting
|
||||||
// application processors and initialising any I/O APICs. The table
|
// application processors and initialising any I/O APICs. The table
|
||||||
|
|
@ -165,7 +169,7 @@ mp_init(void)
|
||||||
p += sizeof(struct mpie);
|
p += sizeof(struct mpie);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
cprintf("mpinit: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
|
cprintf("mp_init: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
|
||||||
while(p < e){
|
while(p < e){
|
||||||
cprintf("%uX ", *p);
|
cprintf("%uX ", *p);
|
||||||
p++;
|
p++;
|
||||||
|
|
|
||||||
4
picirq.c
4
picirq.c
|
|
@ -11,9 +11,9 @@
|
||||||
|
|
||||||
// Current IRQ mask.
|
// Current IRQ mask.
|
||||||
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
|
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
|
||||||
static ushort irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
|
ushort irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
|
||||||
|
|
||||||
static void
|
void
|
||||||
irq_setmask_8259A(ushort mask)
|
irq_setmask_8259A(ushort mask)
|
||||||
{
|
{
|
||||||
irq_mask_8259A = mask;
|
irq_mask_8259A = mask;
|
||||||
|
|
|
||||||
|
|
@ -60,3 +60,4 @@ lapic.c
|
||||||
ioapic.c
|
ioapic.c
|
||||||
picirq.c
|
picirq.c
|
||||||
console.c
|
console.c
|
||||||
|
8253pit.c
|
||||||
2
traps.h
2
traps.h
|
|
@ -27,8 +27,8 @@
|
||||||
|
|
||||||
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
|
#define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
|
||||||
|
|
||||||
|
#define IRQ_TIMER 0
|
||||||
#define IRQ_KBD 1
|
#define IRQ_KBD 1
|
||||||
#define IRQ_IDE 14
|
#define IRQ_IDE 14
|
||||||
#define IRQ_TIMER 18
|
|
||||||
#define IRQ_ERROR 19
|
#define IRQ_ERROR 19
|
||||||
#define IRQ_SPURIOUS 31
|
#define IRQ_SPURIOUS 31
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue