root/mp.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. sum
  2. mpsearch1
  3. mpsearch
  4. mpconfig
  5. mpinit

   1 // Multiprocessor support
   2 // Search memory for MP description structures.
   3 // http://developer.intel.com/design/pentium/datashts/24201606.pdf
   4 
   5 #include "types.h"
   6 #include "defs.h"
   7 #include "param.h"
   8 #include "memlayout.h"
   9 #include "mp.h"
  10 #include "x86.h"
  11 #include "mmu.h"
  12 #include "proc.h"
  13 
  14 struct cpu cpus[NCPU];
  15 int ncpu;
  16 uchar ioapicid;
  17 
  18 static uchar
  19 sum(uchar *addr, int len)
     /* [previous][next][first][last][top][bottom][index][help]  */
  20 {
  21   int i, sum;
  22 
  23   sum = 0;
  24   for(i=0; i<len; i++)
  25     sum += addr[i];
  26   return sum;
  27 }
  28 
  29 // Look for an MP structure in the len bytes at addr.
  30 static struct mp*
  31 mpsearch1(uint a, int len)
     /* [previous][next][first][last][top][bottom][index][help]  */
  32 {
  33   uchar *e, *p, *addr;
  34 
  35   addr = P2V(a);
  36   e = addr+len;
  37   for(p = addr; p < e; p += sizeof(struct mp))
  38     if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
  39       return (struct mp*)p;
  40   return 0;
  41 }
  42 
  43 // Search for the MP Floating Pointer Structure, which according to the
  44 // spec is in one of the following three locations:
  45 // 1) in the first KB of the EBDA;
  46 // 2) in the last KB of system base memory;
  47 // 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
  48 static struct mp*
  49 mpsearch(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  50 {
  51   uchar *bda;
  52   uint p;
  53   struct mp *mp;
  54 
  55   bda = (uchar *) P2V(0x400);
  56   if((p = ((bda[0x0F]<<8)| bda[0x0E]) << 4)){
  57     if((mp = mpsearch1(p, 1024)))
  58       return mp;
  59   } else {
  60     p = ((bda[0x14]<<8)|bda[0x13])*1024;
  61     if((mp = mpsearch1(p-1024, 1024)))
  62       return mp;
  63   }
  64   return mpsearch1(0xF0000, 0x10000);
  65 }
  66 
  67 // Search for an MP configuration table.  For now,
  68 // don't accept the default configurations (physaddr == 0).
  69 // Check for correct signature, calculate the checksum and,
  70 // if correct, check the version.
  71 // To do: check extended table checksum.
  72 static struct mpconf*
  73 mpconfig(struct mp **pmp)
     /* [previous][next][first][last][top][bottom][index][help]  */
  74 {
  75   struct mpconf *conf;
  76   struct mp *mp;
  77 
  78   if((mp = mpsearch()) == 0 || mp->physaddr == 0)
  79     return 0;
  80   conf = (struct mpconf*) P2V((uint) mp->physaddr);
  81   if(memcmp(conf, "PCMP", 4) != 0)
  82     return 0;
  83   if(conf->version != 1 && conf->version != 4)
  84     return 0;
  85   if(sum((uchar*)conf, conf->length) != 0)
  86     return 0;
  87   *pmp = mp;
  88   return conf;
  89 }
  90 
  91 void
  92 mpinit(void)
     /* [previous][next][first][last][top][bottom][index][help]  */
  93 {
  94   uchar *p, *e;
  95   int ismp;
  96   struct mp *mp;
  97   struct mpconf *conf;
  98   struct mpproc *proc;
  99   struct mpioapic *ioapic;
 100 
 101   if((conf = mpconfig(&mp)) == 0)
 102     panic("Expect to run on an SMP");
 103   ismp = 1;
 104   lapic = (uint*)conf->lapicaddr;
 105   for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; p<e; ){
 106     switch(*p){
 107     case MPPROC:
 108       proc = (struct mpproc*)p;
 109       if(ncpu < NCPU) {
 110         cpus[ncpu].apicid = proc->apicid;  // apicid may differ from ncpu
 111         ncpu++;
 112       }
 113       p += sizeof(struct mpproc);
 114       continue;
 115     case MPIOAPIC:
 116       ioapic = (struct mpioapic*)p;
 117       ioapicid = ioapic->apicno;
 118       p += sizeof(struct mpioapic);
 119       continue;
 120     case MPBUS:
 121     case MPIOINTR:
 122     case MPLINTR:
 123       p += 8;
 124       continue;
 125     default:
 126       ismp = 0;
 127       break;
 128     }
 129   }
 130   if(!ismp)
 131     panic("Didn't find a suitable machine");
 132 
 133   if(mp->imcrp){
 134     // Bochs doesn't support IMCR, so this doesn't run on Bochs.
 135     // But it would on real hardware.
 136     outb(0x22, 0x70);   // Select IMCR
 137     outb(0x23, inb(0x23) | 1);  // Mask external interrupts.
 138   }
 139 }

/* [previous][next][first][last][top][bottom][index][help]  */