summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrans Kaashoek <[email protected]>2010-07-23 07:41:13 -0400
committerFrans Kaashoek <[email protected]>2010-07-23 07:41:13 -0400
commit4714c20521a047fba652854e5bf59158b5d85a4e (patch)
tree236507e7a400cc93db3a25d2aba3837d6176184f
parent74c82bc1584dda4cee6b0788055a52c32a10b2e0 (diff)
downloadxv6-labs-4714c20521a047fba652854e5bf59158b5d85a4e.tar.gz
xv6-labs-4714c20521a047fba652854e5bf59158b5d85a4e.tar.bz2
xv6-labs-4714c20521a047fba652854e5bf59158b5d85a4e.zip
Checkpoint page-table version for SMP
Includes code for TLB shootdown (which actually seems unnecessary for xv6)
-rw-r--r--defs.h3
-rw-r--r--exec.c6
-rw-r--r--lapic.c40
-rw-r--r--main.c23
-rw-r--r--proc.c1
-rw-r--r--trap.c4
-rw-r--r--traps.h3
-rw-r--r--x86.h5
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().