Skip to content
Snippets Groups Projects
mp.c 4.53 KiB
Newer Older
#include "types.h"
#include "mp.h"
#include "defs.h"
kaashoek's avatar
kaashoek committed
#include "traps.h"
rtm's avatar
rtm committed
#include "proc.h"
kaashoek's avatar
kaashoek committed
static char* buses[] = {
  "CBUSI ",
  "CBUSII",
  "EISA  ",
  "FUTURE",
  "INTERN",
  "ISA   ",
  "MBI   ",
  "MBII  ",
  "MCA   ",
  "MPI   ",
  "MPSA  ",
  "NUBUS ",
  "PCI   ",
  "PCMCIA",
  "TC    ",
  "VL    ",
  "VME   ",
  "XPRESS",
  0,
kaashoek's avatar
kaashoek committed
};

rtm's avatar
rtm committed
struct cpu cpus[NCPU];
int ncpu;
static struct mp* mp;  // The MP floating point structure
static struct mp*
rtm's avatar
rtm committed
mp_scan(uchar *addr, int len)
rtm's avatar
rtm committed
  uchar *e, *p, sum;
  int i;

  e = addr+len;
  for(p = addr; p < e; p += sizeof(struct mp)){
    if(memcmp(p, "_MP_", 4))
      continue;
    sum = 0;
    for(i = 0; i < sizeof(struct mp); i++)
      sum += p[i];
    if(sum == 0)
      return (struct mp *)p;
static struct mp*
mp_search(void)
{
rtm's avatar
rtm committed
  uchar *bda;
  uint p;
  struct mp *mp;

  /*
   * Search for the MP Floating Pointer Structure, which according to the
   * spec is in one of the following three locations:
   * 1) in the first KB of the EBDA;
   * 2) in the last KB of system base memory;
   * 3) in the BIOS ROM between 0xE0000 and 0xFFFFF.
   */
rtm's avatar
rtm committed
  bda = (uchar*) 0x400;
  if((p = (bda[0x0F]<<8)|bda[0x0E])){
rtm's avatar
rtm committed
    if((mp = mp_scan((uchar*) p, 1024)))
      return mp;
  }
  else{
    p = ((bda[0x14]<<8)|bda[0x13])*1024;
rtm's avatar
rtm committed
    if((mp = mp_scan((uchar*)p-1024, 1024)))
      return mp;
  }
rtm's avatar
rtm committed
  return mp_scan((uchar*)0xF0000, 0x10000);
}

static int 
mp_detect(void)
{
  struct mpctb *pcmp;
rtm's avatar
rtm committed
  uchar *p, sum;
  uint length;

  /*
   * Search for an MP configuration table. For now,
   * don't accept the default configurations (physaddr == 0).
   * Check for correct signature, calculate the checksum and,
   * if correct, check the version.
   * To do: check extended table checksum.
   */
  if((mp = mp_search()) == 0 || mp->physaddr == 0)
  pcmp = (struct mpctb *) mp->physaddr;
  if(memcmp(pcmp, "PCMP", 4))
    return 2;

  length = pcmp->length;
  sum = 0;
rtm's avatar
rtm committed
  for(p = (uchar*)pcmp; length; length--)
    sum += *p++;

  if(sum || (pcmp->version != 1 && pcmp->version != 4))
    return 3;

  return 0;
}

void
rsc's avatar
rsc committed
mp_init(void)
rtm's avatar
rtm committed
  uchar *p, *e;
  struct mpctb *mpctb;
  struct mppe *proc;
  struct mpbe *bus;
  struct mpioapic *ioapic;
  struct mpie *intr;
kaashoek's avatar
kaashoek committed
  int i;

  ncpu = 0;
  if ((r = mp_detect()) != 0) return;
  /*
   * Run through the table saving information needed for starting
   * application processors and initialising any I/O APICs. The table
   * is guaranteed to be in order such that only one pass is necessary.
   */
  mpctb = (struct mpctb *) mp->physaddr;
rtm's avatar
rtm committed
  lapicaddr = (uint *) mpctb->lapicaddr;
  p = ((uchar*)mpctb)+sizeof(struct mpctb);
  e = ((uchar*)mpctb)+mpctb->length;

  while(p < e) {
    switch(*p){
      proc = (struct mppe *) p;
rtm's avatar
rtm committed
      cpus[ncpu].apicid = proc->apicid;
        bcpu = &cpus[ncpu];
      ncpu++;
      p += sizeof(struct mppe);
      continue;
      bus = (struct mpbe *) p;
kaashoek's avatar
kaashoek committed
      for(i = 0; buses[i]; i++){
        if(strncmp(buses[i], bus->string, sizeof(bus->string)) == 0)
          break;
kaashoek's avatar
kaashoek committed
      }
      p += sizeof(struct mpbe);
      continue;
      ioapic = (struct mpioapic *) p;
      ioapic_id = ioapic->apicno;
      p += sizeof(struct mpioapic);
      continue;
      intr = (struct mpie *) p;
      p += sizeof(struct mpie);
      continue;
    default:
      cprintf("mpinit: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
      while(p < e){
        cprintf("%uX ", *p);
        p++;

  if (mp->imcrp) {  // it appears that bochs doesn't support IMCR, and code won't run
    outb(0x22, 0x70);   /* select IMCR */
    byte = inb(0x23);   /* current contents */
    byte |= 0x01;       /* mask external INTR */
    outb(0x23, byte);   /* disconnect 8259s/NMI */
kaashoek's avatar
kaashoek committed
int
mp_bcpu(void)
{
  return bcpu-cpus;
}

extern void mpmain(void);

#define APBOOTCODE 0x7000 // XXX hack

rsc's avatar
rsc committed
mp_startthem(void)
rtm's avatar
rtm committed
  extern uchar _binary_bootother_start[], _binary_bootother_size[];
  extern int main();
  int c;

  memmove((void *) APBOOTCODE,_binary_bootother_start, 
          (uint) _binary_bootother_size);
  for(c = 0; c < ncpu; c++){
    if (c == cpu()) continue;
    *(uint *)(APBOOTCODE-4) = (uint) (cpus[c].mpstack) + MPSTACK; // tell it what to use for %esp
    *(uint *)(APBOOTCODE-8) = (uint)mpmain; // tell it where to jump to
rtm's avatar
rtm committed
    lapic_startap(cpus[c].apicid, (uint) APBOOTCODE);
    while(cpus[c].booted == 0)
      ;