diff options
| author | kaashoek <kaashoek> | 2006-06-21 01:53:07 +0000 | 
|---|---|---|
| committer | kaashoek <kaashoek> | 2006-06-21 01:53:07 +0000 | 
| commit | 7baa34a421e4c970ee90c2537ceacd7230f2474e (patch) | |
| tree | 5cc26d0b33d22588eea93abe9ad5cfea24cecede | |
| parent | ae6e8aa730fa410118c0532938d4a9e62b08bbe8 (diff) | |
| download | xv6-labs-7baa34a421e4c970ee90c2537ceacd7230f2474e.tar.gz xv6-labs-7baa34a421e4c970ee90c2537ceacd7230f2474e.tar.bz2 xv6-labs-7baa34a421e4c970ee90c2537ceacd7230f2474e.zip | |
start on MP; detect MP configuration
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | defs.h | 5 | ||||
| -rw-r--r-- | main.c | 3 | ||||
| -rw-r--r-- | memlayout.h | 3 | ||||
| -rw-r--r-- | mp.c | 139 | ||||
| -rw-r--r-- | mp.h | 158 | ||||
| -rw-r--r-- | string.c | 15 | 
7 files changed, 323 insertions, 2 deletions
| @@ -1,5 +1,5 @@  OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o \ -       syscall.o ide.o picirq.o +       syscall.o ide.o picirq.o mp.o  CC = i386-jos-elf-gcc  LD = i386-jos-elf-ld @@ -21,6 +21,7 @@ void tinit(void);  // string.c  void * memcpy(void *dst, void *src, unsigned n);  void * memset(void *dst, int c, unsigned n); +int memcmp(const void *v1, const void *v2, unsigned n);  // syscall.c  void syscall(void); @@ -28,3 +29,7 @@ void syscall(void);  // picirq.c  void irq_setmask_8259A(uint16_t mask);  void pic_init(void); + +// mp.c +void mpinit(void); + @@ -22,6 +22,7 @@ main()    cprintf("\nxV6\n\n"); +  mpinit(); // multiprocessor    kinit(); // physical memory allocator    tinit(); // traps and interrupts    pic_init(); @@ -47,7 +48,7 @@ main()    write_eflags(read_eflags() | FL_IF);    irq_setmask_8259A(0); -#if 1 +#if 0    ide_read(0, buf, 1);    cprintf("sec0.0 %x\n", buf[0] & 0xff);  #endif diff --git a/memlayout.h b/memlayout.h new file mode 100644 index 0000000..a33f347 --- /dev/null +++ b/memlayout.h @@ -0,0 +1,3 @@ +#define EXTPHYSMEM 0x100000 + +#define KADDR(a) ((void *) a) @@ -0,0 +1,139 @@ +#include "types.h" +#include "mp.h" +#include "defs.h" +#include "memlayout.h" + +static struct _MP_* _mp_;  /* The MP floating point structure */ +static int ncpu; + +static struct _MP_* +mp_scan(uint8_t *addr, int len) +{ +  uint8_t *e, *p, sum; +  int i; + +  cprintf("scanning: 0x%x\n", (uint32_t)addr); +  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; +  } +  return 0; +} + +static struct _MP_* +mp_search(void) +{ +  uint8_t *bda; +  uint32_t 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. +   */ +  bda = KADDR(0x400); +  if((p = (bda[0x0F]<<8)|bda[0x0E])){ +    if((mp = mp_scan(KADDR(p), 1024))) +      return mp; +  } +  else{ +    p = ((bda[0x14]<<8)|bda[0x13])*1024; +    if((mp = mp_scan(KADDR(p-1024), 1024))) +      return mp; +  } +  return mp_scan(KADDR(0xF0000), 0x10000); +} + +static int  +mp_detect(void) +{ +  struct PCMP *pcmp; +  uint8_t *p, sum; +  uint32_t 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) +    return 1; + +  pcmp = KADDR(_mp_->physaddr); +  if(memcmp(pcmp, "PCMP", 4)) +    return 2; + +  length = pcmp->length; +  sum = 0; +  for(p = (uint8_t*)pcmp; length; length--) +    sum += *p++; + +  if(sum || (pcmp->version != 1 && pcmp->version != 4)) +    return 3; + +  cprintf("MP spec rev #: %x\n", _mp_->specrev); +  return 0; +} + +void +mpinit() +{  +  int r; +  uint8_t *p, *e; +  struct PCMP *pcmp; + +  ncpu = 0; +  if ((r = mp_detect()) != 0) return; +  cprintf ("This computer is multiprocessor!\n"); + +  /* +   * 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. +   */ +  pcmp = KADDR(_mp_->physaddr); +  p = ((uint8_t*)pcmp)+sizeof(struct PCMP); +  e = ((uint8_t*)pcmp)+pcmp->length; + +  while(p < e) { +    switch(*p){ +    case PcmpPROCESSOR: +      cprintf("a processor\n"); +      ncpu++; +      p += sizeof(struct PCMPprocessor); +      continue; +    case PcmpBUS: +      cprintf("a bus\n"); +      p += sizeof(struct PCMPbus); +      continue; +    case PcmpIOAPIC: +      cprintf("an IO APIC\n"); +      p += sizeof(struct PCMPioapic); +      continue; +    case PcmpIOINTR: +      cprintf("an IO interrupt assignment\n"); +      p += sizeof(struct PCMPintr); +      continue; +    default: +      cprintf("mpinit: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p); +      while(p < e){ +	cprintf("%uX ", *p); +	p++; +      } +      break; +    } +  } + +  cprintf("ncpu: %d\n", ncpu); +} @@ -0,0 +1,158 @@ +/* + * MultiProcessor Specification Version 1.[14]. + */ +struct _MP_ {			/* floating pointer */ +  uint8_t signature[4];		/* "_MP_" */ +  physaddr_t physaddr;	        /* physical address of MP configuration table */ +  uint8_t length;		/* 1 */ +  uint8_t specrev;		/* [14] */ +  uint8_t checksum;		/* all bytes must add up to 0 */ +  uint8_t type;			/* MP system configuration type */ +  uint8_t imcrp; +  uint8_t reserved[3]; +}; + +struct PCMP {			/* configuration table header */ +  uint8_t signature[4];		/* "PCMP" */ +  uint16_t length;		/* total table length */ +  uint8_t version;		/* [14] */ +  uint8_t checksum;		/* all bytes must add up to 0 */ +  uint8_t product[20];		/* product id */ +  uintptr_t oemtable;		/* OEM table pointer */ +  uint16_t oemlength;		/* OEM table length */ +  uint16_t entry;		/* entry count */ +  uintptr_t lapicbase;		/* address of local APIC */ +  uint16_t xlength;		/* extended table length */ +  uint8_t xchecksum;		/* extended table checksum */ +  uint8_t reserved; +}; + +struct PCMPprocessor {		/* processor table entry */ +  uint8_t type;			/* entry type (0) */ +  uint8_t apicno;		/* local APIC id */ +  uint8_t version;		/* local APIC verison */ +  uint8_t flags;		/* CPU flags */ +  uint8_t signature[4];		/* CPU signature */ +  uint32_t feature;		/* feature flags from CPUID instruction */ +  uint8_t reserved[8]; +}; + +struct PCMPbus {		/* bus table entry */ +  uint8_t type;			/* entry type (1) */ +  uint8_t busno;		/* bus id */ +  char string[6];		/* bus type string */ +}; + +struct PCMPioapic {		/* I/O APIC table entry */ +  uint8_t type;			/* entry type (2) */ +  uint8_t apicno;		/* I/O APIC id */ +  uint8_t version;		/* I/O APIC version */ +  uint8_t flags;		/* I/O APIC flags */ +  uintptr_t addr;		/* I/O APIC address */ +}; + +struct PCMPintr {		/* interrupt table entry */ +  uint8_t type;			/* entry type ([34]) */ +  uint8_t intr;			/* interrupt type */ +  uint16_t flags;		/* interrupt flag */ +  uint8_t busno;		/* source bus id */ +  uint8_t irq;			/* source bus irq */ +  uint8_t apicno;		/* destination APIC id */ +  uint8_t intin;		/* destination APIC [L]INTIN# */ +}; + +struct PCMPsasm {		/* system address space mapping entry */ +  uint8_t type;			/* entry type (128) */ +  uint8_t length;		/* of this entry (20) */ +  uint8_t busno;		/* bus id */ +  uint8_t addrtype; +  uintptr_t addrbase[2]; +  uint32_t addrlength[2]; +}; + +struct PCMPhierarchy {		/* bus hierarchy descriptor entry */ +  uint8_t type;			/* entry type (129) */ +  uint8_t length;		/* of this entry (8) */ +  uint8_t busno;		/* bus id */ +  uint8_t info;			/* bus info */ +  uint8_t parent;		/* parent bus */ +  uint8_t reserved[3]; +}; + +struct PCMPcbasm {		/* compatibility bus address space modifier entry */ +  uint8_t type;			/* entry type (130) */ +  uint8_t length;		/* of this entry (8) */ +  uint8_t busno;		/* bus id */ +  uint8_t modifier;		/* address modifier */ +  uint32_t range;		/* predefined range list */ +}; + +enum {				/* table entry types */ +  PcmpPROCESSOR	= 0x00,		/* one entry per processor */ +  PcmpBUS = 0x01,		/* one entry per bus */ +  PcmpIOAPIC = 0x02,		/* one entry per I/O APIC */ +  PcmpIOINTR = 0x03,		/* one entry per bus interrupt source */ +  PcmpLINTR = 0x04,		/* one entry per system interrupt source */ + +  PcmpSASM = 0x80, +  PcmpHIERARCHY	= 0x81, +  PcmpCBASM = 0x82, + +  /* PCMPprocessor and PCMPioapic flags */ +  PcmpEN = 0x01,		/* enabled */ +  PcmpBP = 0x02,		/* bootstrap processor */ + +				/* PCMPiointr and PCMPlintr flags */ +  PcmpPOMASK = 0x03,		/* polarity conforms to specifications of bus */ +  PcmpHIGH = 0x01,		/* active high */ +  PcmpLOW = 0x03,		/* active low */ +  PcmpELMASK = 0x0C,		/* trigger mode of APIC input signals */ +  PcmpEDGE = 0x04,		/* edge-triggered */ +  PcmpLEVEL = 0x0C,		/* level-triggered */ + +  /* PCMPiointr and PCMPlintr interrupt type */ +  PcmpINT = 0x00,		/* vectored interrupt from APIC Rdt */ +  PcmpNMI = 0x01,		/* non-maskable interrupt */ +  PcmpSMI = 0x02,		/* system management interrupt */ +  PcmpExtINT = 0x03,		/* vectored interrupt from external PIC */ + +  /* PCMPsasm addrtype */ +  PcmpIOADDR = 0x00,		/* I/O address */ +  PcmpMADDR = 0x01,		/* memory address */ +  PcmpPADDR = 0x02,		/* prefetch address */ + +  /* PCMPhierarchy info */ +  PcmpSD = 0x01,		/* subtractive decode bus */ + +				/* PCMPcbasm modifier */ +  PcmpPR = 0x01,		/* predefined range list */ +}; + +/* + * Common bits for + *	I/O APIC Redirection Table Entry; + *	Local APIC Local Interrupt Vector Table; + *	Local APIC Inter-Processor Interrupt; + *	Local APIC Timer Vector Table. + */ +enum { +  ApicFIXED = 0x00000000,	/* [10:8] Delivery Mode */ +  ApicLOWEST = 0x00000100,	/* Lowest priority */ +  ApicSMI = 0x00000200,	        /* System Management Interrupt */ +  ApicRR = 0x00000300,	        /* Remote Read */ +  ApicNMI = 0x00000400, +  ApicINIT = 0x00000500,	/* INIT/RESET */ +  ApicSTARTUP = 0x00000600,	/* Startup IPI */ +  ApicExtINT = 0x00000700, + +  ApicPHYSICAL = 0x00000000,	/* [11] Destination Mode (RW) */ +  ApicLOGICAL = 0x00000800, + +  ApicDELIVS = 0x00001000,	/* [12] Delivery Status (RO) */ +  ApicHIGH = 0x00000000,	/* [13] Interrupt Input Pin Polarity (RW) */ +  ApicLOW = 0x00002000, +  ApicRemoteIRR	= 0x00004000,	/* [14] Remote IRR (RO) */ +  ApicEDGE = 0x00000000,	/* [15] Trigger Mode (RW) */ +  ApicLEVEL = 0x00008000, +  ApicIMASK = 0x00010000,	/* [16] Interrupt Mask */ +}; @@ -23,3 +23,18 @@ memset(void *dst, int c, unsigned n)    return dst;  } + +int +memcmp(const void *v1, const void *v2, unsigned n) +{ +  const uint8_t *s1 = (const uint8_t *) v1; +  const uint8_t *s2 = (const uint8_t *) v2; + +  while (n-- > 0) { +    if (*s1 != *s2) +      return (int) *s1 - (int) *s2; +    s1++, s2++; +  } + +  return 0; +} | 
