APIC IDs may not be consecutive and start from zero, so we cannot really use it
as a direct index into cpus. Record apicid in struct cpu and have cpunum() look for it. Replace cpu->id with cpunum() everywhere, and replace cpu->id with cpu->apicid. Thanks to Xi Wang.
This commit is contained in:
		
							parent
							
								
									37939f24c2
								
							
						
					
					
						commit
						ae15515d80
					
				
					 6 changed files with 26 additions and 18 deletions
				
			
		| 
						 | 
				
			
			@ -110,7 +110,7 @@ panic(char *s)
 | 
			
		|||
 | 
			
		||||
  cli();
 | 
			
		||||
  cons.locking = 0;
 | 
			
		||||
  cprintf("cpu%d: panic: ", cpu->id);
 | 
			
		||||
  cprintf("cpu with apicid %d: panic: ", cpu->apicid);
 | 
			
		||||
  cprintf(s);
 | 
			
		||||
  cprintf("\n");
 | 
			
		||||
  getcallerpcs(&s, pcs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								lapic.c
									
										
									
									
									
								
							
							
						
						
									
										16
									
								
								lapic.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
// The local APIC manages internal (non-I/O) interrupts.
 | 
			
		||||
// See Chapter 8 & Appendix C of Intel processor manual volume 3.
 | 
			
		||||
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "types.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "date.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +9,7 @@
 | 
			
		|||
#include "traps.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "proc.h"  // ncpu
 | 
			
		||||
 | 
			
		||||
// Local APIC registers, divided by 4 for use as uint[] indices.
 | 
			
		||||
#define ID      (0x0020/4)   // ID
 | 
			
		||||
| 
						 | 
				
			
			@ -99,6 +101,8 @@ lapicinit(void)
 | 
			
		|||
int
 | 
			
		||||
cpunum(void)
 | 
			
		||||
{
 | 
			
		||||
  int apicid, i;
 | 
			
		||||
  
 | 
			
		||||
  // Cannot call cpu when interrupts are enabled:
 | 
			
		||||
  // result not guaranteed to last long enough to be used!
 | 
			
		||||
  // Would prefer to panic but even printing is chancy here:
 | 
			
		||||
| 
						 | 
				
			
			@ -111,9 +115,15 @@ cpunum(void)
 | 
			
		|||
        __builtin_return_address(0));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if(lapic)
 | 
			
		||||
    return lapic[ID]>>24;
 | 
			
		||||
  return 0;
 | 
			
		||||
  if (!lapic)
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
  apicid = lapic[ID] >> 24;
 | 
			
		||||
  for (i = 0; i < ncpu; ++i) {
 | 
			
		||||
    if (cpus[i].apicid == apicid)
 | 
			
		||||
      return i;
 | 
			
		||||
  }
 | 
			
		||||
  panic("unknown apicid\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Acknowledge interrupt.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								main.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -22,7 +22,7 @@ main(void)
 | 
			
		|||
  mpinit();        // detect other processors
 | 
			
		||||
  lapicinit();     // interrupt controller
 | 
			
		||||
  seginit();       // segment descriptors
 | 
			
		||||
  cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
 | 
			
		||||
  cprintf("\ncpu%d: starting xv6\n\n", cpunum());
 | 
			
		||||
  picinit();       // another interrupt controller
 | 
			
		||||
  ioapicinit();    // another interrupt controller
 | 
			
		||||
  consoleinit();   // console hardware
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ mpenter(void)
 | 
			
		|||
static void
 | 
			
		||||
mpmain(void)
 | 
			
		||||
{
 | 
			
		||||
  cprintf("cpu%d: starting\n", cpu->id);
 | 
			
		||||
  cprintf("cpu%d: starting\n", cpunum());
 | 
			
		||||
  idtinit();       // load idt register
 | 
			
		||||
  xchg(&cpu->started, 1); // tell startothers() we're up
 | 
			
		||||
  scheduler();     // start running processes
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +89,7 @@ startothers(void)
 | 
			
		|||
    *(void**)(code-8) = mpenter;
 | 
			
		||||
    *(int**)(code-12) = (void *) V2P(entrypgdir);
 | 
			
		||||
 | 
			
		||||
    lapicstartap(c->id, V2P(code));
 | 
			
		||||
    lapicstartap(c->apicid, V2P(code));
 | 
			
		||||
 | 
			
		||||
    // wait for cpu to finish mpmain()
 | 
			
		||||
    while(c->started == 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										10
									
								
								mp.c
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								mp.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -106,12 +106,10 @@ mpinit(void)
 | 
			
		|||
    switch(*p){
 | 
			
		||||
    case MPPROC:
 | 
			
		||||
      proc = (struct mpproc*)p;
 | 
			
		||||
      if(ncpu != proc->apicid){
 | 
			
		||||
        cprintf("mpinit: ncpu=%d apicid=%d\n", ncpu, proc->apicid);
 | 
			
		||||
        ismp = 0;
 | 
			
		||||
      if(ncpu < NCPU) {
 | 
			
		||||
        cpus[ncpu].apicid = proc->apicid;  // apicid may differ from ncpu
 | 
			
		||||
        ncpu++;
 | 
			
		||||
      }
 | 
			
		||||
      cpus[ncpu].id = ncpu;
 | 
			
		||||
      ncpu++;
 | 
			
		||||
      p += sizeof(struct mpproc);
 | 
			
		||||
      continue;
 | 
			
		||||
    case MPIOAPIC:
 | 
			
		||||
| 
						 | 
				
			
			@ -125,8 +123,8 @@ mpinit(void)
 | 
			
		|||
      p += 8;
 | 
			
		||||
      continue;
 | 
			
		||||
    default:
 | 
			
		||||
      cprintf("mpinit: unknown config type %x\n", *p);
 | 
			
		||||
      ismp = 0;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if(!ismp){
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								proc.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								proc.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
// Per-CPU state
 | 
			
		||||
struct cpu {
 | 
			
		||||
  uchar id;                    // Local APIC ID; index into cpus[] below
 | 
			
		||||
  uchar apicid;                // Local APIC ID
 | 
			
		||||
  struct context *scheduler;   // swtch() here to enter scheduler
 | 
			
		||||
  struct taskstate ts;         // Used by x86 to find stack for interrupt
 | 
			
		||||
  struct segdesc gdt[NSEGS];   // x86 global descriptor table
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								trap.c
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								trap.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -48,7 +48,7 @@ trap(struct trapframe *tf)
 | 
			
		|||
 | 
			
		||||
  switch(tf->trapno){
 | 
			
		||||
  case T_IRQ0 + IRQ_TIMER:
 | 
			
		||||
    if(cpu->id == 0){
 | 
			
		||||
    if(cpunum() == 0){
 | 
			
		||||
      acquire(&tickslock);
 | 
			
		||||
      ticks++;
 | 
			
		||||
      wakeup(&ticks);
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +74,7 @@ trap(struct trapframe *tf)
 | 
			
		|||
  case T_IRQ0 + 7:
 | 
			
		||||
  case T_IRQ0 + IRQ_SPURIOUS:
 | 
			
		||||
    cprintf("cpu%d: spurious interrupt at %x:%x\n",
 | 
			
		||||
            cpu->id, tf->cs, tf->eip);
 | 
			
		||||
            cpunum(), tf->cs, tf->eip);
 | 
			
		||||
    lapiceoi();
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,13 +83,13 @@ trap(struct trapframe *tf)
 | 
			
		|||
    if(proc == 0 || (tf->cs&3) == 0){
 | 
			
		||||
      // In kernel, it must be our mistake.
 | 
			
		||||
      cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
 | 
			
		||||
              tf->trapno, cpu->id, tf->eip, rcr2());
 | 
			
		||||
              tf->trapno, cpunum(), tf->eip, rcr2());
 | 
			
		||||
      panic("trap");
 | 
			
		||||
    }
 | 
			
		||||
    // In user space, assume process misbehaved.
 | 
			
		||||
    cprintf("pid %d %s: trap %d err %d on cpu %d "
 | 
			
		||||
            "eip 0x%x addr 0x%x--kill proc\n",
 | 
			
		||||
            proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip,
 | 
			
		||||
            proc->pid, proc->name, tf->trapno, tf->err, cpunum(), tf->eip,
 | 
			
		||||
            rcr2());
 | 
			
		||||
    proc->killed = 1;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue