From 4714c20521a047fba652854e5bf59158b5d85a4e Mon Sep 17 00:00:00 2001 From: Frans Kaashoek Date: Fri, 23 Jul 2010 07:41:13 -0400 Subject: [PATCH] Checkpoint page-table version for SMP Includes code for TLB shootdown (which actually seems unnecessary for xv6) --- defs.h | 3 +++ exec.c | 6 +----- lapic.c | 40 ++++++++++++++++++++++++++++++++++++++++ main.c | 23 +++++++++-------------- proc.c | 1 + trap.c | 4 ++++ traps.h | 3 ++- x86.h | 5 +++++ 8 files changed, 65 insertions(+), 20 deletions(-) diff --git a/defs.h b/defs.h index d0750de..d6d68ad 100644 --- a/defs.h +++ b/defs.h @@ -73,6 +73,7 @@ int cpunum(void); extern volatile uint* lapic; void lapiceoi(void); void lapicinit(int); +void lapic_tlbflush(uint); void lapicstartap(uchar, uint); void microdelay(int); @@ -156,6 +157,8 @@ void uartputc(int); #define PGROUNDUP(sz) ((sz+PGSIZE-1) & ~(PGSIZE-1)) void pminit(void); void ksegment(void); +void kvmalloc(void); +void loadkvm(void); void vminit(void); void jkstack(); void printstack(void); diff --git a/exec.c b/exec.c index 65de312..6ded59f 100644 --- a/exec.c +++ b/exec.c @@ -95,14 +95,10 @@ exec(char *path, char **argv) proc->tf->eip = elf.entry; // main proc->tf->esp = sp; - // printstack(); - - loadvm(proc); + loadvm(proc); freevm(oldpgdir); - // printstack(); - return 0; bad: diff --git a/lapic.c b/lapic.c index 4fe4ace..c1cd7f3 100644 --- a/lapic.c +++ b/lapic.c @@ -20,8 +20,11 @@ #define STARTUP 0x00000600 // Startup IPI #define DELIVS 0x00001000 // Delivery status #define ASSERT 0x00004000 // Assert interrupt (vs deassert) + #define DEASSERT 0x00000000 #define LEVEL 0x00008000 // Level triggered #define BCAST 0x00080000 // Send to all APICs, including self. + #define BUSY 0x00001000 + #define FIXED 0x00000000 #define ICRHI (0x0310/4) // Interrupt Command [63:32] #define TIMER (0x0320/4) // Local Vector Table 0 (TIMER) #define X1 0x0000000B // divide counts by 1 @@ -44,6 +47,27 @@ lapicw(int index, int value) lapic[ID]; // wait for write to finish, by reading } +static uint +lapicr(uint off) +{ + return lapic[off]; +} + +static int +apic_icr_wait() +{ + uint i = 100000; + while ((lapicr(ICRLO) & BUSY) != 0) { + nop_pause(); + i--; + if (i == 0) { + cprintf("apic_icr_wait: wedged?\n"); + return -1; + } + } + return 0; +} + //PAGEBREAK! void lapicinit(int c) @@ -128,6 +152,22 @@ microdelay(int us) } +// Send IPI +void +lapic_ipi(int cpu, int ino) +{ + lapicw(ICRHI, cpu << 24); + lapicw(ICRLO, FIXED | DEASSERT | ino); + if (apic_icr_wait() < 0) + panic("lapic_ipi: icr_wait failure"); +} + +void +lapic_tlbflush(uint cpu) +{ + lapic_ipi(cpu, T_TLBFLUSH); +} + #define IO_RTC 0x70 // Start additional processor running bootstrap code at addr. diff --git a/main.c b/main.c index 319aad9..78cd334 100644 --- a/main.c +++ b/main.c @@ -6,13 +6,14 @@ #include "x86.h" static void bootothers(void); -static void mpmain(void) __attribute__((noreturn)); +static void mpmain(void); +void jkstack(void) __attribute__((noreturn)); // Bootstrap processor starts running C code here. int main(void) { - mpinit(); // collect info about this machine + mpinit(); // collect info about this machine lapicinit(mpbcpu()); ksegment(); picinit(); // interrupt controller @@ -28,18 +29,17 @@ mainc(void) { cprintf("cpus %p cpu %p\n", cpus, cpu); cprintf("\ncpu%d: starting xv6\n\n", cpu->id); - vminit(); // virtual memory + kvmalloc(); // allocate the kernel page table pinit(); // process table tvinit(); // trap vectors binit(); // buffer cache fileinit(); // file table iinit(); // inode cache ideinit(); // disk - cprintf("ismp: %d\n", ismp); if(!ismp) timerinit(); // uniprocessor timer userinit(); // first user process - // bootothers(); // start other processors XXX fix where to boot from + bootothers(); // start other processors // Finish setting up this processor in mpmain. mpmain(); @@ -53,13 +53,12 @@ mpmain(void) if(cpunum() != mpbcpu()) { ksegment(); cprintf("other cpu\n"); - vminit(); lapicinit(cpunum()); } + vminit(); // Run with paging on each processor cprintf("cpu%d: mpmain\n", cpu->id); idtinit(); xchg(&cpu->booted, 1); - cprintf("cpu%d: scheduling\n", cpu->id); scheduler(); } @@ -72,10 +71,10 @@ bootothers(void) struct cpu *c; char *stack; - // Write bootstrap code to unused memory at 0x7000. - code = (uchar*)0x7000; + // Write bootstrap code to unused memory at 0x7000. The linker has + // placed the start of bootother.S there. + code = (uchar *) 0x7000; memmove(code, _binary_bootother_start, (uint)_binary_bootother_size); - for(c = cpus; c < cpus+ncpu; c++){ if(c == cpus+cpunum()) // We've started already. continue; @@ -84,15 +83,11 @@ bootothers(void) stack = kalloc(KSTACKSIZE); *(void**)(code-4) = stack + KSTACKSIZE; *(void**)(code-8) = mpmain; - cprintf("lapicstartap\n"); lapicstartap(c->id, (uint)code); - cprintf("lapicstartap done\n"); // Wait for cpu to get through bootstrap. while(c->booted == 0) ; - - cprintf("lapicstartap booted\n"); } } diff --git a/proc.c b/proc.c index a38a9e6..3e28200 100644 --- a/proc.c +++ b/proc.c @@ -242,6 +242,7 @@ sched(void) panic("sched running"); if(readeflags()&FL_IF) panic("sched interruptible"); + loadkvm(); // Switch to the kernel page table intena = cpu->intena; swtch(&proc->context, cpu->scheduler); cpu->intena = intena; diff --git a/trap.c b/trap.c index 1f35708..f0f016f 100644 --- a/trap.c +++ b/trap.c @@ -73,6 +73,10 @@ trap(struct trapframe *tf) cpu->id, tf->cs, tf->eip); lapiceoi(); break; + case T_TLBFLUSH: + lapiceoi(); + lcr3(rcr3()); + break; //PAGEBREAK: 13 default: diff --git a/traps.h b/traps.h index f450c2d..4422d74 100644 --- a/traps.h +++ b/traps.h @@ -24,7 +24,8 @@ // These are arbitrarily chosen, but with care not to overlap // processor defined exceptions or interrupt vectors. -#define T_SYSCALL 64 // system call +#define T_SYSCALL 64 // system call +#define T_TLBFLUSH 65 // flush TLB #define T_DEFAULT 500 // catchall #define T_IRQ0 32 // IRQ 0 corresponds to int T_IRQ diff --git a/x86.h b/x86.h index 986e1b0..b9fa8b8 100644 --- a/x86.h +++ b/x86.h @@ -176,6 +176,11 @@ static inline uint resp(void) return val; } +static inline void nop_pause(void) +{ + asm volatile("pause" : :); +} + //PAGEBREAK: 36 // Layout of the trap frame built on the stack by the // hardware and by trapasm.S, and passed to trap().