Eliminate code for gs trick to track per-cpu state. We rely on lapiccpunum()
to find a per-cpu id with which we locate a cpu's cpu struct.
This commit is contained in:
		
							parent
							
								
									fbb4c09444
								
							
						
					
					
						commit
						ed396c068b
					
				
					 8 changed files with 33 additions and 67 deletions
				
			
		
							
								
								
									
										1
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								defs.h
									
										
									
									
									
								
							|  | @ -108,6 +108,7 @@ void            exit(void); | |||
| int             fork(void); | ||||
| int             growproc(int); | ||||
| int             kill(int); | ||||
| struct cpu*     mycpu(void); | ||||
| struct proc*    myproc(); | ||||
| void            pinit(void); | ||||
| void            procdump(void); | ||||
|  |  | |||
							
								
								
									
										14
									
								
								lapic.c
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								lapic.c
									
										
									
									
									
								
							|  | @ -98,22 +98,12 @@ lapicinit(void) | |||
|   lapicw(TPR, 0); | ||||
| } | ||||
| 
 | ||||
| // Should be called with interrupts disabled: the calling thread shouldn't be
 | ||||
| // rescheduled between reading lapic[ID] and checking against cpu array.
 | ||||
| int | ||||
| lapiccpunum(void) | ||||
| { | ||||
|   int apicid, i; | ||||
|    | ||||
|   // Cannot call cpunum when interrupts are enabled:
 | ||||
|   // result not guaranteed to last long enough to be used!
 | ||||
|   // Would prefer to panic but even printing is chancy here:
 | ||||
|   // almost everything, including cprintf and panic, calls cpu,
 | ||||
|   // often indirectly through acquire and release.
 | ||||
|   if(readeflags()&FL_IF){ | ||||
|     static int n; | ||||
|     if(n++ == 0) | ||||
|       cprintf("cpunum called from %x with interrupts enabled\n", | ||||
|         __builtin_return_address(0)); | ||||
|   } | ||||
| 
 | ||||
|   if (!lapic) | ||||
|     return 0; | ||||
|  |  | |||
							
								
								
									
										2
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								main.c
									
										
									
									
									
								
							|  | @ -53,7 +53,7 @@ mpenter(void) | |||
| static void | ||||
| mpmain(void) | ||||
| { | ||||
|   cprintf("cpu%d: starting %d\n", cpuid(), lapiccpunum()); | ||||
|   cprintf("cpu%d: starting %d\n", cpuid(), cpuid()); | ||||
|   idtinit();       // load idt register
 | ||||
|   xchg(&(mycpu()->started), 1); // tell startothers() we're up
 | ||||
|   scheduler();     // start running processes
 | ||||
|  |  | |||
							
								
								
									
										9
									
								
								mmu.h
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								mmu.h
									
										
									
									
									
								
							|  | @ -42,13 +42,12 @@ | |||
| // various segment selectors.
 | ||||
| #define SEG_KCODE 1  // kernel code
 | ||||
| #define SEG_KDATA 2  // kernel data+stack
 | ||||
| #define SEG_KCPU  3  // kernel per-cpu data
 | ||||
| #define SEG_UCODE 4  // user code
 | ||||
| #define SEG_UDATA 5  // user data+stack
 | ||||
| #define SEG_TSS   6  // this process's task state
 | ||||
| #define SEG_UCODE 3  // user code
 | ||||
| #define SEG_UDATA 4  // user data+stack
 | ||||
| #define SEG_TSS   5  // this process's task state
 | ||||
| 
 | ||||
| // cpu->gdt[NSEGS] holds the above segments.
 | ||||
| #define NSEGS     7 | ||||
| #define NSEGS     6 | ||||
| 
 | ||||
| //PAGEBREAK!
 | ||||
| #ifndef __ASSEMBLER__ | ||||
|  |  | |||
							
								
								
									
										34
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								proc.c
									
										
									
									
									
								
							|  | @ -26,12 +26,29 @@ pinit(void) | |||
|   initlock(&ptable.lock, "ptable"); | ||||
| } | ||||
| 
 | ||||
| // XXX get rid off?
 | ||||
| // Must be called with interrupts disabled
 | ||||
| int | ||||
| cpuid() { | ||||
|   return mycpu()-cpus; | ||||
| } | ||||
| 
 | ||||
| // Must be called with interrupts disabled
 | ||||
| struct cpu* | ||||
| mycpu(void) | ||||
| { | ||||
|   // Would prefer to panic but even printing is chancy here: almost everything,
 | ||||
|   // including cprintf and panic, calls mycpu(), often indirectly through
 | ||||
|   // acquire and release.
 | ||||
|   if(readeflags()&FL_IF){ | ||||
|     static int n; | ||||
|     if(n++ == 0) | ||||
|       cprintf("mycpu called from %x with interrupts enabled\n", | ||||
|         __builtin_return_address(0)); | ||||
|   } | ||||
| 
 | ||||
|   return &cpus[lapiccpunum()]; | ||||
| } | ||||
| 
 | ||||
| // Disable interrupts so that we are not rescheduled
 | ||||
| // while reading proc from the cpu structure
 | ||||
| struct proc* | ||||
|  | @ -304,7 +321,8 @@ scheduler(void) | |||
| { | ||||
|   struct proc *p; | ||||
|   struct cpu *c = mycpu(); | ||||
| 
 | ||||
|   c->proc = 0; | ||||
|    | ||||
|   for(;;){ | ||||
|     // Enable interrupts on this processor.
 | ||||
|     sti(); | ||||
|  | @ -321,15 +339,13 @@ scheduler(void) | |||
|       c->proc = p; | ||||
|       switchuvm(p); | ||||
|       p->state = RUNNING; | ||||
|       p->cpu = c; | ||||
|       // cprintf("%d: switch to %d\n", c-cpus, p->pid);
 | ||||
|       swtch(&(p->cpu->scheduler), p->context); | ||||
| 
 | ||||
|       swtch(&(c->scheduler), p->context); | ||||
|       switchkvm(); | ||||
| 
 | ||||
|       // Process is done running for now.
 | ||||
|       // It should have changed its p->state before coming back.
 | ||||
|       c->proc = 0; | ||||
|       p->cpu = 0; | ||||
|     } | ||||
|     release(&ptable.lock); | ||||
| 
 | ||||
|  | @ -358,9 +374,7 @@ sched(void) | |||
|   if(readeflags()&FL_IF) | ||||
|     panic("sched interruptible"); | ||||
|   intena = mycpu()->intena; | ||||
|   // cprintf("%d: before swtch %d %x\n", p->cpu-cpus, p->pid, * (int *) 0x1d);
 | ||||
|   swtch(&p->context, p->cpu->scheduler); | ||||
|   // cprintf("%d/%d: after swtch %d %x\n", cpuid(), p->cpu-cpus, p->pid, * (int *) 0x1d);
 | ||||
|   swtch(&p->context, mycpu()->scheduler); | ||||
|   mycpu()->intena = intena; | ||||
| } | ||||
| 
 | ||||
|  | @ -422,8 +436,6 @@ sleep(void *chan, struct spinlock *lk) | |||
|   p->chan = chan; | ||||
|   p->state = SLEEPING; | ||||
| 
 | ||||
|   // cprintf("sleep %d\n", p->pid);
 | ||||
|    | ||||
|   sched(); | ||||
| 
 | ||||
|   // Tidy up.
 | ||||
|  |  | |||
							
								
								
									
										30
									
								
								proc.h
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								proc.h
									
										
									
									
									
								
							|  | @ -7,39 +7,12 @@ struct cpu { | |||
|   volatile uint started;       // Has the CPU started?
 | ||||
|   int ncli;                    // Depth of pushcli nesting.
 | ||||
|   int intena;                  // Were interrupts enabled before pushcli?
 | ||||
|   // Per-CPU variables, holding pointers to the current cpu and to the current
 | ||||
|   // process (see cpu() and proc() in proc.c)
 | ||||
|   struct cpu *cpu;             // On cpu 0, cpu = &cpus[0]; on cpu 1, cpu=&cpus[1], etc.
 | ||||
|   struct proc *proc;           // The currently-running process on this cpu
 | ||||
|   struct proc *proc;           // The process running on this cpu or null
 | ||||
| }; | ||||
| 
 | ||||
| extern struct cpu cpus[NCPU]; | ||||
| extern int ncpu; | ||||
| 
 | ||||
| // The asm suffix tells gcc to use "%gs:0" to refer to cpu
 | ||||
| // and "%gs:4" to refer to proc.  seginit sets up the
 | ||||
| // %gs segment register so that %gs refers to the memory
 | ||||
| // holding those two variables in the local cpu's struct cpu.
 | ||||
| // This is similar to how thread-local variables are implemented
 | ||||
| // in thread libraries such as Linux pthreads.
 | ||||
| 
 | ||||
| static inline struct cpu* | ||||
| mycpu(void) { | ||||
|   struct cpu *cpu; | ||||
|   asm("movl %%gs:0, %0" : "=r"(cpu)); | ||||
|   return cpu; | ||||
| } | ||||
| 
 | ||||
| #if 0 | ||||
| static inline struct proc* | ||||
| myproc(void) { | ||||
|   struct proc *proc; | ||||
|   asm("movl %%gs:4, %0" : "=r"(proc)); | ||||
|   return proc; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| //PAGEBREAK: 17
 | ||||
| // Saved registers for kernel context switches.
 | ||||
| // Don't need to save all the segment registers (%cs, etc),
 | ||||
|  | @ -76,7 +49,6 @@ struct proc { | |||
|   struct file *ofile[NOFILE];  // Open files
 | ||||
|   struct inode *cwd;           // Current directory
 | ||||
|   char name[16];               // Process name (debugging)
 | ||||
|   struct cpu *cpu;             // If running, which cpu.
 | ||||
| }; | ||||
| 
 | ||||
| // Process memory is laid out contiguously, low addresses first:
 | ||||
|  |  | |||
|  | @ -14,9 +14,6 @@ alltraps: | |||
|   movw $(SEG_KDATA<<3), %ax | ||||
|   movw %ax, %ds | ||||
|   movw %ax, %es | ||||
|   movw $(SEG_KCPU<<3), %ax | ||||
|   movw %ax, %fs | ||||
|   movw %ax, %gs | ||||
| 
 | ||||
|   # Call trap(tf), where tf=%esp | ||||
|   pushl %esp | ||||
|  |  | |||
							
								
								
									
										7
									
								
								vm.c
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								vm.c
									
										
									
									
									
								
							|  | @ -21,17 +21,12 @@ seginit(void) | |||
|   // Cannot share a CODE descriptor for both kernel and user
 | ||||
|   // because it would have to have DPL_USR, but the CPU forbids
 | ||||
|   // an interrupt from CPL=0 to DPL=3.
 | ||||
|   c = &cpus[lapiccpunum()]; | ||||
|   c = &cpus[cpuid()]; | ||||
|   c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0); | ||||
|   c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); | ||||
|   c->gdt[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); | ||||
|   c->gdt[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER); | ||||
|   c->cpu = c; | ||||
|   c->proc = 0; | ||||
|   // Map cpu and proc -- these are private per cpu.
 | ||||
|   c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 4, 0); | ||||
|   lgdt(c->gdt, sizeof(c->gdt)); | ||||
|   loadgs(SEG_KCPU << 3); | ||||
| } | ||||
| 
 | ||||
| // Return the address of the PTE in page table pgdir
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Frans Kaashoek
						Frans Kaashoek