Checkpoint page-table version for SMP
Includes code for TLB shootdown (which actually seems unnecessary for xv6)
This commit is contained in:
		
							parent
							
								
									74c82bc158
								
							
						
					
					
						commit
						4714c20521
					
				
					 8 changed files with 65 additions and 20 deletions
				
			
		
							
								
								
									
										3
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								defs.h
									
										
									
									
									
								
							| 
						 | 
					@ -73,6 +73,7 @@ int             cpunum(void);
 | 
				
			||||||
extern volatile uint*    lapic;
 | 
					extern volatile uint*    lapic;
 | 
				
			||||||
void            lapiceoi(void);
 | 
					void            lapiceoi(void);
 | 
				
			||||||
void            lapicinit(int);
 | 
					void            lapicinit(int);
 | 
				
			||||||
 | 
					void            lapic_tlbflush(uint);
 | 
				
			||||||
void            lapicstartap(uchar, uint);
 | 
					void            lapicstartap(uchar, uint);
 | 
				
			||||||
void            microdelay(int);
 | 
					void            microdelay(int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,6 +157,8 @@ void            uartputc(int);
 | 
				
			||||||
#define PGROUNDUP(sz)  ((sz+PGSIZE-1) & ~(PGSIZE-1))
 | 
					#define PGROUNDUP(sz)  ((sz+PGSIZE-1) & ~(PGSIZE-1))
 | 
				
			||||||
void            pminit(void);
 | 
					void            pminit(void);
 | 
				
			||||||
void            ksegment(void);
 | 
					void            ksegment(void);
 | 
				
			||||||
 | 
					void            kvmalloc(void);
 | 
				
			||||||
 | 
					void            loadkvm(void);
 | 
				
			||||||
void            vminit(void);
 | 
					void            vminit(void);
 | 
				
			||||||
void            jkstack();
 | 
					void            jkstack();
 | 
				
			||||||
void            printstack(void);
 | 
					void            printstack(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								exec.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								exec.c
									
										
									
									
									
								
							| 
						 | 
					@ -95,14 +95,10 @@ exec(char *path, char **argv)
 | 
				
			||||||
  proc->tf->eip = elf.entry;  // main
 | 
					  proc->tf->eip = elf.entry;  // main
 | 
				
			||||||
  proc->tf->esp = sp;
 | 
					  proc->tf->esp = sp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // printstack();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  loadvm(proc); 
 | 
					  loadvm(proc); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  freevm(oldpgdir);
 | 
					  freevm(oldpgdir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // printstack(); 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 bad:
 | 
					 bad:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										40
									
								
								lapic.c
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								lapic.c
									
										
									
									
									
								
							| 
						 | 
					@ -20,8 +20,11 @@
 | 
				
			||||||
  #define STARTUP    0x00000600   // Startup IPI
 | 
					  #define STARTUP    0x00000600   // Startup IPI
 | 
				
			||||||
  #define DELIVS     0x00001000   // Delivery status
 | 
					  #define DELIVS     0x00001000   // Delivery status
 | 
				
			||||||
  #define ASSERT     0x00004000   // Assert interrupt (vs deassert)
 | 
					  #define ASSERT     0x00004000   // Assert interrupt (vs deassert)
 | 
				
			||||||
 | 
					  #define DEASSERT   0x00000000
 | 
				
			||||||
  #define LEVEL      0x00008000   // Level triggered
 | 
					  #define LEVEL      0x00008000   // Level triggered
 | 
				
			||||||
  #define BCAST      0x00080000   // Send to all APICs, including self.
 | 
					  #define BCAST      0x00080000   // Send to all APICs, including self.
 | 
				
			||||||
 | 
					  #define BUSY       0x00001000
 | 
				
			||||||
 | 
					  #define FIXED      0x00000000
 | 
				
			||||||
#define ICRHI   (0x0310/4)   // Interrupt Command [63:32]
 | 
					#define ICRHI   (0x0310/4)   // Interrupt Command [63:32]
 | 
				
			||||||
#define TIMER   (0x0320/4)   // Local Vector Table 0 (TIMER)
 | 
					#define TIMER   (0x0320/4)   // Local Vector Table 0 (TIMER)
 | 
				
			||||||
  #define X1         0x0000000B   // divide counts by 1
 | 
					  #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
 | 
					  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!
 | 
					//PAGEBREAK!
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
lapicinit(int c)
 | 
					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
 | 
					#define IO_RTC  0x70
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Start additional processor running bootstrap code at addr.
 | 
					// Start additional processor running bootstrap code at addr.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										19
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								main.c
									
										
									
									
									
								
							| 
						 | 
					@ -6,7 +6,8 @@
 | 
				
			||||||
#include "x86.h"
 | 
					#include "x86.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void bootothers(void);
 | 
					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.
 | 
					// Bootstrap processor starts running C code here.
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
| 
						 | 
					@ -28,18 +29,17 @@ mainc(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  cprintf("cpus %p cpu %p\n", cpus, cpu);
 | 
					  cprintf("cpus %p cpu %p\n", cpus, cpu);
 | 
				
			||||||
  cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
 | 
					  cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
 | 
				
			||||||
  vminit();        // virtual memory
 | 
					  kvmalloc();      // allocate the kernel page table
 | 
				
			||||||
  pinit();         // process table
 | 
					  pinit();         // process table
 | 
				
			||||||
  tvinit();        // trap vectors
 | 
					  tvinit();        // trap vectors
 | 
				
			||||||
  binit();         // buffer cache
 | 
					  binit();         // buffer cache
 | 
				
			||||||
  fileinit();      // file table
 | 
					  fileinit();      // file table
 | 
				
			||||||
  iinit();         // inode cache
 | 
					  iinit();         // inode cache
 | 
				
			||||||
  ideinit();       // disk
 | 
					  ideinit();       // disk
 | 
				
			||||||
  cprintf("ismp: %d\n", ismp);
 | 
					 | 
				
			||||||
  if(!ismp)
 | 
					  if(!ismp)
 | 
				
			||||||
    timerinit();   // uniprocessor timer
 | 
					    timerinit();   // uniprocessor timer
 | 
				
			||||||
  userinit();      // first user process
 | 
					  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.
 | 
					  // Finish setting up this processor in mpmain.
 | 
				
			||||||
  mpmain();
 | 
					  mpmain();
 | 
				
			||||||
| 
						 | 
					@ -53,13 +53,12 @@ mpmain(void)
 | 
				
			||||||
  if(cpunum() != mpbcpu()) {
 | 
					  if(cpunum() != mpbcpu()) {
 | 
				
			||||||
    ksegment();
 | 
					    ksegment();
 | 
				
			||||||
    cprintf("other cpu\n");
 | 
					    cprintf("other cpu\n");
 | 
				
			||||||
    vminit();
 | 
					 | 
				
			||||||
    lapicinit(cpunum());
 | 
					    lapicinit(cpunum());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  vminit();        // Run with paging on each processor
 | 
				
			||||||
  cprintf("cpu%d: mpmain\n", cpu->id);
 | 
					  cprintf("cpu%d: mpmain\n", cpu->id);
 | 
				
			||||||
  idtinit();
 | 
					  idtinit();
 | 
				
			||||||
  xchg(&cpu->booted, 1);
 | 
					  xchg(&cpu->booted, 1);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  cprintf("cpu%d: scheduling\n", cpu->id);
 | 
					  cprintf("cpu%d: scheduling\n", cpu->id);
 | 
				
			||||||
  scheduler();
 | 
					  scheduler();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -72,10 +71,10 @@ bootothers(void)
 | 
				
			||||||
  struct cpu *c;
 | 
					  struct cpu *c;
 | 
				
			||||||
  char *stack;
 | 
					  char *stack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Write bootstrap code to unused memory at 0x7000.
 | 
					  // Write bootstrap code to unused memory at 0x7000.  The linker has
 | 
				
			||||||
 | 
					  // placed the start of bootother.S there.
 | 
				
			||||||
  code = (uchar *) 0x7000;
 | 
					  code = (uchar *) 0x7000;
 | 
				
			||||||
  memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
 | 
					  memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  for(c = cpus; c < cpus+ncpu; c++){
 | 
					  for(c = cpus; c < cpus+ncpu; c++){
 | 
				
			||||||
    if(c == cpus+cpunum())  // We've started already.
 | 
					    if(c == cpus+cpunum())  // We've started already.
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
| 
						 | 
					@ -84,15 +83,11 @@ bootothers(void)
 | 
				
			||||||
    stack = kalloc(KSTACKSIZE);
 | 
					    stack = kalloc(KSTACKSIZE);
 | 
				
			||||||
    *(void**)(code-4) = stack + KSTACKSIZE;
 | 
					    *(void**)(code-4) = stack + KSTACKSIZE;
 | 
				
			||||||
    *(void**)(code-8) = mpmain;
 | 
					    *(void**)(code-8) = mpmain;
 | 
				
			||||||
    cprintf("lapicstartap\n");
 | 
					 | 
				
			||||||
    lapicstartap(c->id, (uint)code);
 | 
					    lapicstartap(c->id, (uint)code);
 | 
				
			||||||
    cprintf("lapicstartap done\n");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Wait for cpu to get through bootstrap.
 | 
					    // Wait for cpu to get through bootstrap.
 | 
				
			||||||
    while(c->booted == 0)
 | 
					    while(c->booted == 0)
 | 
				
			||||||
      ;
 | 
					      ;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    cprintf("lapicstartap booted\n");
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								proc.c
									
										
									
									
									
								
							| 
						 | 
					@ -242,6 +242,7 @@ sched(void)
 | 
				
			||||||
    panic("sched running");
 | 
					    panic("sched running");
 | 
				
			||||||
  if(readeflags()&FL_IF)
 | 
					  if(readeflags()&FL_IF)
 | 
				
			||||||
    panic("sched interruptible");
 | 
					    panic("sched interruptible");
 | 
				
			||||||
 | 
					  loadkvm();    // Switch to the kernel page table
 | 
				
			||||||
  intena = cpu->intena;
 | 
					  intena = cpu->intena;
 | 
				
			||||||
  swtch(&proc->context, cpu->scheduler);
 | 
					  swtch(&proc->context, cpu->scheduler);
 | 
				
			||||||
  cpu->intena = intena;
 | 
					  cpu->intena = intena;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								trap.c
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								trap.c
									
										
									
									
									
								
							| 
						 | 
					@ -73,6 +73,10 @@ trap(struct trapframe *tf)
 | 
				
			||||||
            cpu->id, tf->cs, tf->eip);
 | 
					            cpu->id, tf->cs, tf->eip);
 | 
				
			||||||
    lapiceoi();
 | 
					    lapiceoi();
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
 | 
					  case T_TLBFLUSH:
 | 
				
			||||||
 | 
					    lapiceoi();
 | 
				
			||||||
 | 
					    lcr3(rcr3());
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
  //PAGEBREAK: 13
 | 
					  //PAGEBREAK: 13
 | 
				
			||||||
  default:
 | 
					  default:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								traps.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								traps.h
									
										
									
									
									
								
							| 
						 | 
					@ -25,6 +25,7 @@
 | 
				
			||||||
// These are arbitrarily chosen, but with care not to overlap
 | 
					// These are arbitrarily chosen, but with care not to overlap
 | 
				
			||||||
// processor defined exceptions or interrupt vectors.
 | 
					// 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_DEFAULT      500      // catchall
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define T_IRQ0          32      // IRQ 0 corresponds to int T_IRQ
 | 
					#define T_IRQ0          32      // IRQ 0 corresponds to int T_IRQ
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										5
									
								
								x86.h
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								x86.h
									
										
									
									
									
								
							| 
						 | 
					@ -176,6 +176,11 @@ static inline uint resp(void)
 | 
				
			||||||
  return val;
 | 
					  return val;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void nop_pause(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  asm volatile("pause" : :);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//PAGEBREAK: 36
 | 
					//PAGEBREAK: 36
 | 
				
			||||||
// Layout of the trap frame built on the stack by the
 | 
					// Layout of the trap frame built on the stack by the
 | 
				
			||||||
// hardware and by trapasm.S, and passed to trap().
 | 
					// hardware and by trapasm.S, and passed to trap().
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue