From f70172129c94e4d53b56fc10a7d859679b581bd2 Mon Sep 17 00:00:00 2001 From: kaashoek Date: Thu, 7 Sep 2006 01:37:58 +0000 Subject: [PATCH] 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) --- 8253pit.c | 46 +++++++++++++++++++++++++++++++++++++ Makefile | 1 + console.c | 1 + defs.h | 6 +++++ ide.c | 1 + ioapic.c | 66 ++++++++++++++++++++++++++++------------------------- lapic.c | 33 +++++++++++++++++++-------- main.c | 7 ++++-- mp.c | 8 +++++-- picirq.c | 4 ++-- runoff.list | 1 + traps.h | 2 +- 12 files changed, 128 insertions(+), 48 deletions(-) create mode 100644 8253pit.c diff --git a/8253pit.c b/8253pit.c new file mode 100644 index 0000000..0b82e29 --- /dev/null +++ b/8253pit.c @@ -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<> MAXREDIRSHIFT) + 1; - id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT; - if(id != ioapic_id) - panic("ioapic_init: id isn't equal to ioapic_id\n"); - for(i = 0; i < nintr; i++) { - // active-hi and edge-triggered for ISA interrupts - // Assume that pin 0 on the first I/O APIC is an ExtINT pin. - // Assume that pins 1-15 are ISA interrupts - l = ioapic_read(io, IOAPIC_REDTBL_LO(i)); - l = l & ~IOART_INTMASK; // allow INTs - l |= IOART_INTMSET; - l = l & ~IOART_INTPOL; // active hi - l = l & ~IOART_TRGRMOD; // edgee triggered - l = l & ~IOART_DELMOD; // fixed - l = l & ~IOART_DESTMOD; // physical mode - l = l | (IRQ_OFFSET + i); // vector - ioapic_write(io, IOAPIC_REDTBL_LO(i), l); - h = ioapic_read(io, IOAPIC_REDTBL_HI(i)); - h &= ~IOART_DEST; - ioapic_write(io, IOAPIC_REDTBL_HI(i), h); + if (ismp) { + io = (struct ioapic*) IO_APIC_BASE; + l = ioapic_read(io, IOAPIC_VER); + nintr = ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; + id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT; + if(id != ioapic_id) + cprintf("ioapic_init: id isn't equal to ioapic_id; not a MP\n"); + for(i = 0; i < nintr; i++) { + // active-hi and edge-triggered for ISA interrupts + // Assume that pin 0 on the first I/O APIC is an ExtINT pin. + // Assume that pins 1-15 are ISA interrupts + l = ioapic_read(io, IOAPIC_REDTBL_LO(i)); + l = l & ~IOART_INTMASK; // allow INTs + l |= IOART_INTMSET; + l = l & ~IOART_INTPOL; // active hi + l = l & ~IOART_TRGRMOD; // edgee triggered + l = l & ~IOART_DELMOD; // fixed + l = l & ~IOART_DESTMOD; // physical mode + l = l | (IRQ_OFFSET + i); // vector + ioapic_write(io, IOAPIC_REDTBL_LO(i), l); + h = ioapic_read(io, IOAPIC_REDTBL_HI(i)); + h &= ~IOART_DEST; + ioapic_write(io, IOAPIC_REDTBL_HI(i), h); + } } } @@ -67,13 +69,15 @@ ioapic_enable (int irq, int cpunum) { uint l, h; struct ioapic *io; - - io = (struct ioapic*) IO_APIC_BASE; - l = ioapic_read(io, IOAPIC_REDTBL_LO(irq)); - l = l & ~IOART_INTMASK; // allow INTs - ioapic_write(io, IOAPIC_REDTBL_LO(irq), l); - h = ioapic_read(io, IOAPIC_REDTBL_HI(irq)); - h &= ~IOART_DEST; - h |= (cpunum << APIC_ID_SHIFT); - ioapic_write(io, IOAPIC_REDTBL_HI(irq), h); + + if (ismp) { + io = (struct ioapic*) IO_APIC_BASE; + l = ioapic_read(io, IOAPIC_REDTBL_LO(irq)); + l = l & ~IOART_INTMASK; // allow INTs + ioapic_write(io, IOAPIC_REDTBL_LO(irq), l); + h = ioapic_read(io, IOAPIC_REDTBL_HI(irq)); + h &= ~IOART_DEST; + h |= (cpunum << APIC_ID_SHIFT); + ioapic_write(io, IOAPIC_REDTBL_HI(irq), h); + } } diff --git a/lapic.c b/lapic.c index 8dc6d82..7777929 100644 --- a/lapic.c +++ b/lapic.c @@ -105,17 +105,20 @@ lapic_write(int r, int data) void lapic_timerinit(void) { - lapic_write(LAPIC_TDCR, LAPIC_X1); - lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC | - (IRQ_OFFSET + IRQ_TIMER)); - lapic_write(LAPIC_TCCR, 10000000); - lapic_write(LAPIC_TICR, 10000000); + if (lapicaddr) { + lapic_write(LAPIC_TDCR, LAPIC_X1); + lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC | + (IRQ_OFFSET + IRQ_TIMER)); + lapic_write(LAPIC_TCCR, 10000000); + lapic_write(LAPIC_TICR, 10000000); + } } void lapic_timerintr(void) { - lapic_write(LAPIC_EOI, 0); + if (lapicaddr) + lapic_write(LAPIC_EOI, 0); } void @@ -123,6 +126,9 @@ lapic_init(int c) { uint r, lvt; + if (lapicaddr == 0) + return; + lapic_write(LAPIC_DFR, 0xFFFFFFFF); // Set dst format register r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID lapic_write(LAPIC_LDR, (1<>24) & 0xFF; + int x; + if (lapicaddr) + x = (lapic_read(LAPIC_ID)>>24) & 0xFF; + else + x = 0; return x; } diff --git a/main.c b/main.c index dba8bdd..876c20a 100644 --- a/main.c +++ b/main.c @@ -71,8 +71,11 @@ main0(void) // start other CPUs mp_startthem(); - // turn on timer and enable interrupts on the local APIC - lapic_timerinit(); + // turn on timer + if (ismp) lapic_timerinit(); + else pit8253_timerinit(); + + // enable interrupts on the local APIC lapic_enableintr(); // Enable interrupts on this processor. diff --git a/mp.c b/mp.c index f2bb142..7a0a676 100644 --- a/mp.c +++ b/mp.c @@ -30,6 +30,7 @@ static char *buses[] = { }; struct cpu cpus[NCPU]; +int ismp; int ncpu; uchar ioapic_id; @@ -124,8 +125,11 @@ mp_init(void) uchar byte; ncpu = 0; - if((r = mp_detect()) != 0) + if((r = mp_detect()) != 0) { return; + } + + ismp = 1; // Run through the table saving information needed for starting // application processors and initialising any I/O APICs. The table @@ -165,7 +169,7 @@ mp_init(void) p += sizeof(struct mpie); continue; 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){ cprintf("%uX ", *p); p++; diff --git a/picirq.c b/picirq.c index 184e693..eaac053 100644 --- a/picirq.c +++ b/picirq.c @@ -11,9 +11,9 @@ // Current IRQ mask. // Initial IRQ mask has interrupt 2 enabled (for slave 8259A). -static ushort irq_mask_8259A = 0xFFFF & ~(1<