Skip to content
Snippets Groups Projects
Commit 4714c205 authored by Frans Kaashoek's avatar Frans Kaashoek
Browse files

Checkpoint page-table version for SMP

Includes code for TLB shootdown (which actually seems unnecessary for xv6)
parent 74c82bc1
No related branches found
No related tags found
No related merge requests found
......@@ -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);
......
......@@ -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:
......
......@@ -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.
......
......@@ -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");
}
}
......@@ -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;
......
......@@ -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:
......
......@@ -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
......
......@@ -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().
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment