Simplify MP hardware code.
Mainly delete unused constants and code. Move mp_startthem to main.c as bootothers.
This commit is contained in:
		
							parent
							
								
									b63bb0fd00
								
							
						
					
					
						commit
						99b11b6c64
					
				
					 6 changed files with 213 additions and 453 deletions
				
			
		
							
								
								
									
										97
									
								
								ioapic.c
									
										
									
									
									
								
							
							
						
						
									
										97
									
								
								ioapic.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,85 +1,82 @@
 | 
			
		|||
// The I/O APIC manages hardware interrupts for an SMP system.
 | 
			
		||||
// http://www.intel.com/design/chipsets/datashts/29056601.pdf
 | 
			
		||||
 | 
			
		||||
#include "types.h"
 | 
			
		||||
#include "mp.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "traps.h"
 | 
			
		||||
#include "ioapic.h"
 | 
			
		||||
 | 
			
		||||
#define IOAPIC  0xFEC00000   // Default physical address of IO APIC
 | 
			
		||||
 | 
			
		||||
#define REG_ID     0x00  // Register index: ID
 | 
			
		||||
#define REG_VER    0x01  // Register index: version
 | 
			
		||||
#define REG_TABLE  0x10  // Redirection table base
 | 
			
		||||
 | 
			
		||||
// The redirection table starts at REG_TABLE and uses
 | 
			
		||||
// two registers to configure each interrupt.  
 | 
			
		||||
// The first (low) register in a pair contains configuration bits.
 | 
			
		||||
// The second (high) register contains a bitmask telling which
 | 
			
		||||
// CPUs can serve that interrupt.
 | 
			
		||||
#define INT_DISABLED   0x00100000  // Interrupt disabled
 | 
			
		||||
#define INT_LEVEL      0x00008000  // Level-triggered (vs edge-)
 | 
			
		||||
#define INT_ACTIVELOW  0x00002000  // Active low (vs high)
 | 
			
		||||
#define INT_LOGICAL    0x00000800  // Destination is CPU id (vs APIC ID)
 | 
			
		||||
 | 
			
		||||
volatile struct ioapic *ioapic;
 | 
			
		||||
 | 
			
		||||
// IO APIC MMIO structure: write reg, then read or write data.
 | 
			
		||||
struct ioapic {
 | 
			
		||||
  uint ioregsel;  uint p01; uint p02; uint p03;
 | 
			
		||||
  uint iowin;     uint p11; uint p12; uint p13;
 | 
			
		||||
  uint reg;
 | 
			
		||||
  uint pad[3];
 | 
			
		||||
  uint data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define IOAPIC_REDTBL_LO(i)  (IOAPIC_REDTBL + (i) * 2)
 | 
			
		||||
#define IOAPIC_REDTBL_HI(i)  (IOAPIC_REDTBL_LO(i) + 1)
 | 
			
		||||
 | 
			
		||||
static uint
 | 
			
		||||
ioapic_read(struct ioapic *io, int reg)
 | 
			
		||||
ioapic_read(int reg)
 | 
			
		||||
{
 | 
			
		||||
  io->ioregsel = reg;
 | 
			
		||||
  return io->iowin;
 | 
			
		||||
  ioapic->reg = reg;
 | 
			
		||||
  return ioapic->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
ioapic_write(struct ioapic *io, int reg, uint val)
 | 
			
		||||
ioapic_write(int reg, uint data)
 | 
			
		||||
{
 | 
			
		||||
  io->ioregsel = reg;
 | 
			
		||||
  io->iowin = val;
 | 
			
		||||
  ioapic->reg = reg;
 | 
			
		||||
  ioapic->data = data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ioapic_init(void)
 | 
			
		||||
{
 | 
			
		||||
  struct ioapic *io;
 | 
			
		||||
  uint l, h;
 | 
			
		||||
  int nintr;
 | 
			
		||||
  uchar id;
 | 
			
		||||
  int i;
 | 
			
		||||
  int i, id, maxintr;
 | 
			
		||||
 | 
			
		||||
  if(!ismp)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  io = (struct ioapic*) IO_APIC_BASE;
 | 
			
		||||
  l = ioapic_read(io, IOAPIC_VER);
 | 
			
		||||
  nintr =  ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
 | 
			
		||||
  id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
 | 
			
		||||
  ioapic = (volatile struct ioapic*)IOAPIC;
 | 
			
		||||
  maxintr = (ioapic_read(REG_VER) >> 16) & 0xFF;
 | 
			
		||||
  id = ioapic_read(REG_ID) >> 24;
 | 
			
		||||
  if(id != ioapic_id)
 | 
			
		||||
    cprintf("ioapic_init: id isn't equal to ioapic_id; not a MP\n");
 | 
			
		||||
  for(i = 0; i < nintr; i++) {
 | 
			
		||||
    // active-hi and edge-triggered for ISA interrupts
 | 
			
		||||
    // Assume that pin 0 on the first I/O APIC is an ExtINT pin.
 | 
			
		||||
    // Assume that pins 1-15 are ISA interrupts
 | 
			
		||||
    l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
 | 
			
		||||
    l = l & ~IOART_INTMASK;  // allow INTs
 | 
			
		||||
    l |= IOART_INTMSET;
 | 
			
		||||
    l = l & ~IOART_INTPOL;   // active hi
 | 
			
		||||
    l = l & ~IOART_TRGRMOD;  // edgee triggered
 | 
			
		||||
    l = l & ~IOART_DELMOD;   // fixed
 | 
			
		||||
    l = l & ~IOART_DESTMOD;  // physical mode
 | 
			
		||||
    l = l | (IRQ_OFFSET + i); // vector
 | 
			
		||||
    ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
 | 
			
		||||
    h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
 | 
			
		||||
    h &= ~IOART_DEST;
 | 
			
		||||
    ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
 | 
			
		||||
 | 
			
		||||
  // Mark all interrupts edge-triggered, active high, disabled,
 | 
			
		||||
  // and not routed to any CPUs.
 | 
			
		||||
  for(i = 0; i <= maxintr; i++){
 | 
			
		||||
    ioapic_write(REG_TABLE+2*i, INT_DISABLED | (IRQ_OFFSET + i));
 | 
			
		||||
    ioapic_write(REG_TABLE+2*i+1, 0);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
ioapic_enable (int irq, int cpunum)
 | 
			
		||||
ioapic_enable(int irq, int cpunum)
 | 
			
		||||
{
 | 
			
		||||
  uint l, h;
 | 
			
		||||
  struct ioapic *io;
 | 
			
		||||
  
 | 
			
		||||
  if(!ismp)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  io = (struct ioapic*) IO_APIC_BASE;
 | 
			
		||||
  l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
 | 
			
		||||
  l = l & ~IOART_INTMASK;  // allow INTs
 | 
			
		||||
  ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
 | 
			
		||||
  h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
 | 
			
		||||
  h &= ~IOART_DEST;
 | 
			
		||||
  h |= (cpunum << APIC_ID_SHIFT);
 | 
			
		||||
  ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
 | 
			
		||||
  // Mark interrupt edge-triggered, active high,
 | 
			
		||||
  // enabled, and routed to the given cpunum,
 | 
			
		||||
  // which happens to be that cpu's APIC ID.
 | 
			
		||||
  ioapic_write(REG_TABLE+2*irq, IRQ_OFFSET + irq);
 | 
			
		||||
  ioapic_write(REG_TABLE+2*irq+1, cpunum << 24);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										88
									
								
								ioapic.h
									
										
									
									
									
								
							
							
						
						
									
										88
									
								
								ioapic.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,88 +0,0 @@
 | 
			
		|||
#define IO_APIC_BASE   0xFEC00000   // Default phys addr of IO APIC
 | 
			
		||||
#define IOAPIC_WINDOW        0x10   // Window register offset
 | 
			
		||||
 | 
			
		||||
// Constants relating to APIC ID registers
 | 
			
		||||
#define APIC_ID_MASK            0xff000000
 | 
			
		||||
#define APIC_ID_SHIFT           24
 | 
			
		||||
#define APIC_ID_CLUSTER         0xf0
 | 
			
		||||
#define APIC_ID_CLUSTER_ID      0x0f
 | 
			
		||||
#define APIC_MAX_CLUSTER        0xe
 | 
			
		||||
#define APIC_MAX_INTRACLUSTER_ID 3
 | 
			
		||||
#define APIC_ID_CLUSTER_SHIFT   4
 | 
			
		||||
 | 
			
		||||
// Fields in VER
 | 
			
		||||
#define APIC_VER_VERSION        0x000000ff
 | 
			
		||||
#define APIC_VER_MAXLVT         0x00ff0000
 | 
			
		||||
#define MAXLVTSHIFT             16
 | 
			
		||||
 | 
			
		||||
// Indexes into IO APIC
 | 
			
		||||
#define IOAPIC_ID               0x00
 | 
			
		||||
#define IOAPIC_VER              0x01
 | 
			
		||||
#define IOAPIC_ARB              0x02
 | 
			
		||||
#define IOAPIC_REDTBL           0x10
 | 
			
		||||
#define IOAPIC_REDTBL0          IOAPIC_REDTBL
 | 
			
		||||
#define IOAPIC_REDTBL1          (IOAPIC_REDTBL+0x02)
 | 
			
		||||
#define IOAPIC_REDTBL2          (IOAPIC_REDTBL+0x04)
 | 
			
		||||
#define IOAPIC_REDTBL3          (IOAPIC_REDTBL+0x06)
 | 
			
		||||
#define IOAPIC_REDTBL4          (IOAPIC_REDTBL+0x08)
 | 
			
		||||
#define IOAPIC_REDTBL5          (IOAPIC_REDTBL+0x0a)
 | 
			
		||||
#define IOAPIC_REDTBL6          (IOAPIC_REDTBL+0x0c)
 | 
			
		||||
#define IOAPIC_REDTBL7          (IOAPIC_REDTBL+0x0e)
 | 
			
		||||
#define IOAPIC_REDTBL8          (IOAPIC_REDTBL+0x10)
 | 
			
		||||
#define IOAPIC_REDTBL9          (IOAPIC_REDTBL+0x12)
 | 
			
		||||
#define IOAPIC_REDTBL10         (IOAPIC_REDTBL+0x14)
 | 
			
		||||
#define IOAPIC_REDTBL11         (IOAPIC_REDTBL+0x16)
 | 
			
		||||
#define IOAPIC_REDTBL12         (IOAPIC_REDTBL+0x18)
 | 
			
		||||
#define IOAPIC_REDTBL13         (IOAPIC_REDTBL+0x1a)
 | 
			
		||||
#define IOAPIC_REDTBL14         (IOAPIC_REDTBL+0x1c)
 | 
			
		||||
#define IOAPIC_REDTBL15         (IOAPIC_REDTBL+0x1e)
 | 
			
		||||
#define IOAPIC_REDTBL16         (IOAPIC_REDTBL+0x20)
 | 
			
		||||
#define IOAPIC_REDTBL17         (IOAPIC_REDTBL+0x22)
 | 
			
		||||
#define IOAPIC_REDTBL18         (IOAPIC_REDTBL+0x24)
 | 
			
		||||
#define IOAPIC_REDTBL19         (IOAPIC_REDTBL+0x26)
 | 
			
		||||
#define IOAPIC_REDTBL20         (IOAPIC_REDTBL+0x28)
 | 
			
		||||
#define IOAPIC_REDTBL21         (IOAPIC_REDTBL+0x2a)
 | 
			
		||||
#define IOAPIC_REDTBL22         (IOAPIC_REDTBL+0x2c)
 | 
			
		||||
#define IOAPIC_REDTBL23         (IOAPIC_REDTBL+0x2e)
 | 
			
		||||
 | 
			
		||||
// Fields in the IO APIC's redirection table entries
 | 
			
		||||
#define IOART_DEST      APIC_ID_MASK    // broadcast addr: all APICs
 | 
			
		||||
 | 
			
		||||
#define IOART_RESV      0x00fe0000      // reserved
 | 
			
		||||
 | 
			
		||||
#define IOART_INTMASK   0x00010000      // R/W: INTerrupt mask
 | 
			
		||||
#define IOART_INTMCLR   0x00000000      //       clear, allow INTs
 | 
			
		||||
#define IOART_INTMSET   0x00010000      //       set, inhibit INTs
 | 
			
		||||
 | 
			
		||||
#define IOART_TRGRMOD   0x00008000      // R/W: trigger mode
 | 
			
		||||
#define IOART_TRGREDG   0x00000000      //       edge
 | 
			
		||||
#define IOART_TRGRLVL   0x00008000      //       level
 | 
			
		||||
 | 
			
		||||
#define IOART_REM_IRR   0x00004000      // RO: remote IRR
 | 
			
		||||
 | 
			
		||||
#define IOART_INTPOL    0x00002000      // R/W: INT input pin polarity
 | 
			
		||||
#define IOART_INTAHI    0x00000000      //      active high
 | 
			
		||||
#define IOART_INTALO    0x00002000      //      active low
 | 
			
		||||
 | 
			
		||||
#define IOART_DELIVS    0x00001000      // RO: delivery status
 | 
			
		||||
 | 
			
		||||
#define IOART_DESTMOD   0x00000800      // R/W: destination mode
 | 
			
		||||
#define IOART_DESTPHY   0x00000000      //      physical
 | 
			
		||||
#define IOART_DESTLOG   0x00000800      //      logical
 | 
			
		||||
 | 
			
		||||
#define IOART_DELMOD    0x00000700      // R/W: delivery mode
 | 
			
		||||
#define IOART_DELFIXED  0x00000000      //       fixed
 | 
			
		||||
#define IOART_DELLOPRI  0x00000100      //       lowest priority
 | 
			
		||||
#define IOART_DELSMI    0x00000200      //       System Management INT
 | 
			
		||||
#define IOART_DELRSV1   0x00000300      //       reserved
 | 
			
		||||
#define IOART_DELNMI    0x00000400      //       NMI signal
 | 
			
		||||
#define IOART_DELINIT   0x00000500      //       INIT signal
 | 
			
		||||
#define IOART_DELRSV2   0x00000600      //       reserved
 | 
			
		||||
#define IOART_DELEXINT  0x00000700      //       External INTerrupt
 | 
			
		||||
 | 
			
		||||
#define IOART_INTVEC    0x000000ff      // R/W: INTerrupt vector field
 | 
			
		||||
 | 
			
		||||
// Fields in VER
 | 
			
		||||
#define IOART_VER_VERSION       0x000000ff
 | 
			
		||||
#define IOART_VER_MAXREDIR      0x00ff0000
 | 
			
		||||
#define MAXREDIRSHIFT           16
 | 
			
		||||
							
								
								
									
										153
									
								
								lapic.c
									
										
									
									
									
								
							
							
						
						
									
										153
									
								
								lapic.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,132 +1,91 @@
 | 
			
		|||
// The local APIC manages internal (non-I/O) interrupts.
 | 
			
		||||
// See Chapter 8 & Appendix C of Intel processor manual volume 3.
 | 
			
		||||
 | 
			
		||||
#include "types.h"
 | 
			
		||||
#include "mp.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
#include "param.h"
 | 
			
		||||
#include "x86.h"
 | 
			
		||||
#include "traps.h"
 | 
			
		||||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
#include "lapic.h"
 | 
			
		||||
 | 
			
		||||
// Local APIC registers, divided by 4 for use as uint[] indices.
 | 
			
		||||
#define ID      (0x0020/4)   // ID
 | 
			
		||||
#define VER     (0x0030/4)   // Version
 | 
			
		||||
#define TPR     (0x0080/4)   // Task Priority
 | 
			
		||||
#define APR     (0x0090/4)   // Arbitration Priority
 | 
			
		||||
#define PPR     (0x00A0/4)   // Processor Priority
 | 
			
		||||
#define EOI     (0x00B0/4)   // EOI
 | 
			
		||||
#define LDR     (0x00D0/4)   // Logical Destination
 | 
			
		||||
#define DFR     (0x00E0/4)   // Destination Format
 | 
			
		||||
#define SVR     (0x00F0/4)   // Spurious Interrupt Vector
 | 
			
		||||
#define ISR     (0x0100/4)   // Interrupt Status (8 registers)
 | 
			
		||||
#define TMR     (0x0180/4)   // Trigger Mode (8 registers)
 | 
			
		||||
#define IRR     (0x0200/4)   // Interrupt Request (8 registers)
 | 
			
		||||
  #define ENABLE     0x00000100   // Unit Enable
 | 
			
		||||
#define ESR     (0x0280/4)   // Error Status
 | 
			
		||||
#define ICRLO   (0x0300/4)   // Interrupt Command
 | 
			
		||||
  #define INIT       0x00000500   // INIT/RESET
 | 
			
		||||
  #define STARTUP    0x00000600   // Startup IPI
 | 
			
		||||
  #define DELIVS     0x00001000   // Delivery status
 | 
			
		||||
  #define ASSERT     0x00004000   // Assert interrupt (vs deassert)
 | 
			
		||||
  #define LEVEL      0x00008000   // Level triggered
 | 
			
		||||
  #define BCAST      0x00080000   // Send to all APICs, including self.
 | 
			
		||||
#define ICRHI   (0x0310/4)   // Interrupt Command [63:32]
 | 
			
		||||
#define TIMER   (0x0320/4)   // Local Vector Table 0 (TIMER)
 | 
			
		||||
  #define X1         0x0000000B   // divide counts by 1
 | 
			
		||||
  #define PERIODIC   0x00020000   // Periodic
 | 
			
		||||
#define PCINT   (0x0340/4)   // Performance Counter LVT
 | 
			
		||||
#define LINT0   (0x0350/4)   // Local Vector Table 1 (LINT0)
 | 
			
		||||
#define LINT1   (0x0360/4)   // Local Vector Table 2 (LINT1)
 | 
			
		||||
#define ERROR   (0x0370/4)   // Local Vector Table 3 (ERROR)
 | 
			
		||||
  #define MASKED     0x00010000   // Interrupt masked
 | 
			
		||||
#define TICR    (0x0380/4)   // Timer Initial Count
 | 
			
		||||
#define TCCR    (0x0390/4)   // Timer Current Count
 | 
			
		||||
#define TDCR    (0x03E0/4)   // Timer Divide Configuration
 | 
			
		||||
 | 
			
		||||
// SVR  
 | 
			
		||||
#define ENABLE     0x00000100   // Unit Enable
 | 
			
		||||
#define FOCUS      0x00000200   // Focus Processor Checking Disable
 | 
			
		||||
 | 
			
		||||
// ICRLO
 | 
			
		||||
// [14] IPI Trigger Mode Level (RW)
 | 
			
		||||
#define DEASSERT   0x00000000   // Deassert level-sensitive interrupt
 | 
			
		||||
#define ASSERT     0x00004000   // Assert level-sensitive interrupt
 | 
			
		||||
 | 
			
		||||
// [17:16] Remote Read Status
 | 
			
		||||
#define INVALID    0x00000000   // Invalid
 | 
			
		||||
#define WAIT       0x00010000   // In-Progress
 | 
			
		||||
#define VALID      0x00020000   // Valid
 | 
			
		||||
 | 
			
		||||
// [19:18] Destination Shorthand
 | 
			
		||||
#define FIELD      0x00000000   // No shorthand
 | 
			
		||||
#define SELF       0x00040000   // Self is single destination
 | 
			
		||||
#define ALLINC     0x00080000   // All including self
 | 
			
		||||
#define ALLEXC     0x000C0000   // All Excluding self
 | 
			
		||||
 | 
			
		||||
// ESR
 | 
			
		||||
#define SENDCS     0x00000001   // Send CS Error
 | 
			
		||||
#define RCVCS      0x00000002   // Receive CS Error
 | 
			
		||||
#define SENDACCEPT 0x00000004   // Send Accept Error
 | 
			
		||||
#define RCVACCEPT  0x00000008   // Receive Accept Error
 | 
			
		||||
#define SENDVECTOR 0x00000020   // Send Illegal Vector
 | 
			
		||||
#define RCVVECTOR  0x00000040   // Receive Illegal Vector
 | 
			
		||||
#define REGISTER   0x00000080   // Illegal Register Address
 | 
			
		||||
 | 
			
		||||
// [17] Timer Mode (RW)
 | 
			
		||||
#define ONESHOT    0x00000000   // One-shot
 | 
			
		||||
#define PERIODIC   0x00020000   // Periodic
 | 
			
		||||
 | 
			
		||||
// [19:18] Timer Base (RW)
 | 
			
		||||
#define CLKIN      0x00000000   // use CLKIN as input
 | 
			
		||||
#define TMBASE     0x00040000   // use TMBASE
 | 
			
		||||
#define DIVIDER    0x00080000   // use output of the divider
 | 
			
		||||
 | 
			
		||||
#define X2         0x00000000   // divide by 2
 | 
			
		||||
#define X4         0x00000001   // divide by 4
 | 
			
		||||
#define X8         0x00000002   // divide by 8
 | 
			
		||||
#define X16        0x00000003   // divide by 16
 | 
			
		||||
#define X32        0x00000008   // divide by 32
 | 
			
		||||
#define X64        0x00000009   // divide by 64
 | 
			
		||||
#define X128       0x0000000A   // divide by 128
 | 
			
		||||
#define X1         0x0000000B   // divide by 1
 | 
			
		||||
 | 
			
		||||
//PAGEBREAK!
 | 
			
		||||
volatile uint *lapic;  // Initialized in mp.c
 | 
			
		||||
 | 
			
		||||
//PAGEBREAK!
 | 
			
		||||
void
 | 
			
		||||
lapic_init(int c)
 | 
			
		||||
{
 | 
			
		||||
  uint r, lvt;
 | 
			
		||||
 | 
			
		||||
  if(!lapic) 
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  lapic[DFR] = 0xFFFFFFFF;    // Set dst format register
 | 
			
		||||
  r = (lapic[ID]>>24) & 0xFF; // Read APIC ID
 | 
			
		||||
  lapic[LDR] = (1<<r) << 24;
 | 
			
		||||
  lapic[TPR] = 0xFF;          // No interrupts for now
 | 
			
		||||
 | 
			
		||||
  // Enable APIC
 | 
			
		||||
  // Enable local APIC; set spurious interrupt vector.
 | 
			
		||||
  lapic[SVR] = ENABLE | (IRQ_OFFSET+IRQ_SPURIOUS);
 | 
			
		||||
 | 
			
		||||
  // In virtual wire mode, set up the LINT0 and LINT1 as follows:
 | 
			
		||||
  lapic[LINT0] = APIC_IMASK | APIC_EXTINT;
 | 
			
		||||
  lapic[LINT1] = APIC_IMASK | APIC_NMI;
 | 
			
		||||
  // The timer repeatedly counts down at bus frequency
 | 
			
		||||
  // from lapic[TICR] and then issues an interrupt.  
 | 
			
		||||
  // Lapic[TCCR] is the current counter value.
 | 
			
		||||
  // If xv6 cared more about precise timekeeping, the
 | 
			
		||||
  // values of TICR and TCCR would be calibrated using
 | 
			
		||||
  // an external time source.
 | 
			
		||||
  lapic[TDCR] = X1;
 | 
			
		||||
  lapic[TICR] = 10000000;
 | 
			
		||||
  lapic[TCCR] = 10000000;
 | 
			
		||||
  lapic[TIMER] = PERIODIC | (IRQ_OFFSET + IRQ_TIMER);
 | 
			
		||||
 | 
			
		||||
  lapic[EOI] = 0; // Ack any outstanding interrupts.
 | 
			
		||||
  // Disable logical interrupt lines.
 | 
			
		||||
  lapic[LINT0] = MASKED;
 | 
			
		||||
  lapic[LINT1] = MASKED;
 | 
			
		||||
 | 
			
		||||
  lvt = (lapic[VER]>>16) & 0xFF;
 | 
			
		||||
  if(lvt >= 4)
 | 
			
		||||
    lapic[PCINT] = APIC_IMASK;
 | 
			
		||||
  // Disable performance counter overflow interrupts
 | 
			
		||||
  // on machines that provide that interrupt entry.
 | 
			
		||||
  if(((lapic[VER]>>16) & 0xFF) >= 4)
 | 
			
		||||
    lapic[PCINT] = MASKED;
 | 
			
		||||
 | 
			
		||||
  // Map error interrupt to IRQ_ERROR.
 | 
			
		||||
  lapic[ERROR] = IRQ_OFFSET+IRQ_ERROR;
 | 
			
		||||
  lapic[ESR] = 0;
 | 
			
		||||
  lapic[ESR];
 | 
			
		||||
 | 
			
		||||
  // Issue an INIT Level De-Assert to synchronise arbitration ID's.
 | 
			
		||||
  // Clear error status register (requires back-to-back writes).
 | 
			
		||||
  lapic[ESR] = 0;
 | 
			
		||||
  lapic[ESR] = 0;
 | 
			
		||||
 | 
			
		||||
  // Ack any outstanding interrupts.
 | 
			
		||||
  lapic[EOI] = 0;
 | 
			
		||||
 | 
			
		||||
  // Send an Init Level De-Assert to synchronise arbitration ID's.
 | 
			
		||||
  lapic[ICRHI] = 0;
 | 
			
		||||
  lapic[ICRLO] = ALLINC | APIC_LEVEL |
 | 
			
		||||
                       DEASSERT | APIC_INIT;
 | 
			
		||||
  while(lapic[ICRLO] & APIC_DELIVS)
 | 
			
		||||
  lapic[ICRLO] = BCAST | INIT | LEVEL;
 | 
			
		||||
  while(lapic[ICRLO] & DELIVS)
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
  // Initialize the interrupt timer.
 | 
			
		||||
  // On real hardware would need to do more XXX.
 | 
			
		||||
  lapic[TDCR] = X1;
 | 
			
		||||
  lapic[TIMER] = CLKIN | PERIODIC | (IRQ_OFFSET + IRQ_TIMER);
 | 
			
		||||
  lapic[TCCR] = 10000000;
 | 
			
		||||
  lapic[TICR] = 10000000;
 | 
			
		||||
 | 
			
		||||
  // Enable interrupts on the APIC (but not on processor).
 | 
			
		||||
  // Enable interrupts on the APIC (but not on the processor).
 | 
			
		||||
  lapic[TPR] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -146,22 +105,34 @@ lapic_eoi(void)
 | 
			
		|||
    lapic[EOI] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Spin for a given number of microseconds.
 | 
			
		||||
// On real hardware would want to tune this dynamically.
 | 
			
		||||
static void
 | 
			
		||||
microdelay(int us)
 | 
			
		||||
{
 | 
			
		||||
  volatile int j = 0;
 | 
			
		||||
  
 | 
			
		||||
  while(us-- > 0)
 | 
			
		||||
    for(j=0; j<10000; j++);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Start additional processor running bootstrap code at addr.
 | 
			
		||||
// See Appendix B of MultiProcessor Specification.
 | 
			
		||||
void
 | 
			
		||||
lapic_startap(uchar apicid, uint addr)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  volatile int j = 0;
 | 
			
		||||
 | 
			
		||||
  // Send INIT interrupt to reset other CPU.
 | 
			
		||||
  lapic[ICRHI] = apicid<<24;
 | 
			
		||||
  lapic[ICRLO] = FIELD | APIC_LEVEL | ASSERT | APIC_INIT;
 | 
			
		||||
  for(j=0; j<10000; j++);  // 200us
 | 
			
		||||
  lapic[ICRLO] = FIELD | APIC_LEVEL | DEASSERT | APIC_INIT;
 | 
			
		||||
  for(j=0; j<1000000; j++);  // 10ms
 | 
			
		||||
  lapic[ICRLO] = INIT | LEVEL;
 | 
			
		||||
  microdelay(10);
 | 
			
		||||
  
 | 
			
		||||
  // Send startup IPI (twice!) to enter bootstrap code.
 | 
			
		||||
  for(i = 0; i < 2; i++){
 | 
			
		||||
    lapic[ICRHI] = apicid<<24;
 | 
			
		||||
    lapic[ICRLO] = FIELD | APIC_EDGE | APIC_STARTUP | (addr/4096);
 | 
			
		||||
    lapic[ICRLO] = STARTUP | (addr>>12);
 | 
			
		||||
    for(j=0; j<10000; j++);  // 200us
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										34
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								main.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -12,6 +12,8 @@
 | 
			
		|||
 | 
			
		||||
extern char edata[], end[];
 | 
			
		||||
 | 
			
		||||
void bootothers(void);
 | 
			
		||||
 | 
			
		||||
// Bootstrap processor starts running C code here.
 | 
			
		||||
// This is called main0 not main so that it can have
 | 
			
		||||
// a void return type.  Gcc can't handle functions named
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +39,7 @@ main0(void)
 | 
			
		|||
  asm volatile("movl %0, %%ebp" : : "r" (cpus[bcpu].mpstack+MPSTACK));
 | 
			
		||||
 | 
			
		||||
  lapic_init(bcpu);
 | 
			
		||||
  cprintf("\ncpu%d: starting xv6\n\n", cpu());
 | 
			
		||||
  cprintf("\\ncpu%d: starting xv6\\n\\n", cpu());
 | 
			
		||||
 | 
			
		||||
  pinit();         // process table
 | 
			
		||||
  binit();         // buffer cache
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +53,7 @@ main0(void)
 | 
			
		|||
  setupsegs(0);    // segments & TSS
 | 
			
		||||
  console_init();  // I/O devices & their interrupts
 | 
			
		||||
  ide_init();      // disk
 | 
			
		||||
  mp_startthem();  // other CPUs
 | 
			
		||||
  bootothers();    // boot other CPUs
 | 
			
		||||
  if(!ismp)
 | 
			
		||||
    pit8253_timerinit(); // uniprocessor timer
 | 
			
		||||
  userinit();      // first user process
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +69,7 @@ main0(void)
 | 
			
		|||
void
 | 
			
		||||
mpmain(void)
 | 
			
		||||
{
 | 
			
		||||
  cprintf("cpu%d: starting\n", cpu());
 | 
			
		||||
  cprintf("cpu%d: starting\\n", cpu());
 | 
			
		||||
  idtinit();
 | 
			
		||||
  lapic_init(cpu());
 | 
			
		||||
  setupsegs(0);
 | 
			
		||||
| 
						 | 
				
			
			@ -82,3 +84,29 @@ mpmain(void)
 | 
			
		|||
  scheduler();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
bootothers(void)
 | 
			
		||||
{
 | 
			
		||||
  extern uchar _binary_bootother_start[], _binary_bootother_size[];
 | 
			
		||||
  uchar *code;
 | 
			
		||||
  struct cpu *c;
 | 
			
		||||
 | 
			
		||||
  // Write bootstrap code to unused memory at 0x7000.
 | 
			
		||||
  code = (uchar*)0x7000;
 | 
			
		||||
  memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
 | 
			
		||||
 | 
			
		||||
  for(c = cpus; c < cpus+ncpu; c++){
 | 
			
		||||
    if(c == cpus+cpu())  // We've started already.
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    // Set target %esp, %eip
 | 
			
		||||
    *(void**)(code-4) = c->mpstack + MPSTACK;
 | 
			
		||||
    *(void**)(code-8) = mpmain;
 | 
			
		||||
    lapic_startap(c->apicid, (uint)code);
 | 
			
		||||
 | 
			
		||||
    // Wait for cpu to get through bootstrap.
 | 
			
		||||
    while(c->booted == 0)
 | 
			
		||||
      ;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										208
									
								
								mp.c
									
										
									
									
									
								
							
							
						
						
									
										208
									
								
								mp.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// http://developer.intel.com/design/pentium/datashts/24201606.pdf
 | 
			
		||||
 | 
			
		||||
#include "types.h"
 | 
			
		||||
#include "mp.h"
 | 
			
		||||
#include "defs.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -7,52 +9,39 @@
 | 
			
		|||
#include "mmu.h"
 | 
			
		||||
#include "proc.h"
 | 
			
		||||
 | 
			
		||||
static char *buses[] = {
 | 
			
		||||
  "CBUSI ",
 | 
			
		||||
  "CBUSII",
 | 
			
		||||
  "EISA  ",
 | 
			
		||||
  "FUTURE",
 | 
			
		||||
  "INTERN",
 | 
			
		||||
  "ISA   ",
 | 
			
		||||
  "MBI   ",
 | 
			
		||||
  "MBII  ",
 | 
			
		||||
  "MCA   ",
 | 
			
		||||
  "MPI   ",
 | 
			
		||||
  "MPSA  ",
 | 
			
		||||
  "NUBUS ",
 | 
			
		||||
  "PCI   ",
 | 
			
		||||
  "PCMCIA",
 | 
			
		||||
  "TC    ",
 | 
			
		||||
  "VL    ",
 | 
			
		||||
  "VME   ",
 | 
			
		||||
  "XPRESS",
 | 
			
		||||
  0,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct cpu cpus[NCPU];
 | 
			
		||||
static struct cpu *bcpu;
 | 
			
		||||
int ismp;
 | 
			
		||||
int ncpu;
 | 
			
		||||
uchar ioapic_id;
 | 
			
		||||
 | 
			
		||||
static struct cpu *bcpu;
 | 
			
		||||
static struct mp *mp;  // The floating MP structure
 | 
			
		||||
 | 
			
		||||
static struct mp*
 | 
			
		||||
mp_scan(uchar *addr, int len)
 | 
			
		||||
int
 | 
			
		||||
mp_bcpu(void)
 | 
			
		||||
{
 | 
			
		||||
  uchar *e, *p, sum;
 | 
			
		||||
  int i;
 | 
			
		||||
  return bcpu-cpus;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uchar
 | 
			
		||||
sum(uchar *addr, int len)
 | 
			
		||||
{
 | 
			
		||||
  int i, sum;
 | 
			
		||||
  
 | 
			
		||||
  sum = 0;
 | 
			
		||||
  for(i=0; i<len; i++)
 | 
			
		||||
    sum += addr[i];
 | 
			
		||||
  return sum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Look for an MP structure in the len bytes at addr.
 | 
			
		||||
static struct mp*
 | 
			
		||||
mp_search1(uchar *addr, int len)
 | 
			
		||||
{
 | 
			
		||||
  uchar *e, *p;
 | 
			
		||||
 | 
			
		||||
  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)
 | 
			
		||||
  for(p = addr; p < e; p += sizeof(struct mp))
 | 
			
		||||
    if(memcmp(p, "_MP_", 4) == 0 && sum(p, sizeof(struct mp)) == 0)
 | 
			
		||||
      return (struct mp*)p;
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -68,110 +57,81 @@ mp_search(void)
 | 
			
		|||
  uint p;
 | 
			
		||||
  struct mp *mp;
 | 
			
		||||
 | 
			
		||||
  bda = (uchar*) 0x400;
 | 
			
		||||
  bda = (uchar*)0x400;
 | 
			
		||||
  if((p = (bda[0x0F]<<8)|bda[0x0E])){
 | 
			
		||||
    if((mp = mp_scan((uchar*) p, 1024)))
 | 
			
		||||
    if((mp = mp_search1((uchar*)p, 1024)))
 | 
			
		||||
      return mp;
 | 
			
		||||
  }else{
 | 
			
		||||
    p = ((bda[0x14]<<8)|bda[0x13])*1024;
 | 
			
		||||
    if((mp = mp_scan((uchar*)p-1024, 1024)))
 | 
			
		||||
    if((mp = mp_search1((uchar*)p-1024, 1024)))
 | 
			
		||||
      return mp;
 | 
			
		||||
  }
 | 
			
		||||
  return mp_scan((uchar*)0xF0000, 0x10000);
 | 
			
		||||
  return mp_search1((uchar*)0xF0000, 0x10000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Search for an MP configuration table. For now,
 | 
			
		||||
// 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.
 | 
			
		||||
static int
 | 
			
		||||
mp_detect(void)
 | 
			
		||||
static struct mpconf*
 | 
			
		||||
mp_config(struct mp **pmp)
 | 
			
		||||
{
 | 
			
		||||
  struct mpctb *pcmp;
 | 
			
		||||
  uchar *p, sum;
 | 
			
		||||
  uint length;
 | 
			
		||||
  struct mpconf *conf;
 | 
			
		||||
  struct mp *mp;
 | 
			
		||||
 | 
			
		||||
  if((mp = mp_search()) == 0 || mp->physaddr == 0)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  pcmp = (struct mpctb*) mp->physaddr;
 | 
			
		||||
  if(memcmp(pcmp, "PCMP", 4) != 0)
 | 
			
		||||
    return -1;
 | 
			
		||||
  if(pcmp->version != 1 && pcmp->version != 4)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  length = pcmp->length;
 | 
			
		||||
  sum = 0;
 | 
			
		||||
  for(p = (uchar*)pcmp; length; length--)
 | 
			
		||||
    sum += *p++;
 | 
			
		||||
  if(sum != 0)
 | 
			
		||||
    return -1;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
    return 0;
 | 
			
		||||
  conf = (struct mpconf*)mp->physaddr;
 | 
			
		||||
  if(memcmp(conf, "PCMP", 4) != 0)
 | 
			
		||||
    return 0;
 | 
			
		||||
  if(conf->version != 1 && conf->version != 4)
 | 
			
		||||
    return 0;
 | 
			
		||||
  if(sum((uchar*)conf, conf->length) != 0)
 | 
			
		||||
    return 0;
 | 
			
		||||
  *pmp = mp;
 | 
			
		||||
  return conf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mp_init(void)
 | 
			
		||||
{
 | 
			
		||||
  int i;
 | 
			
		||||
  uchar *p, *e;
 | 
			
		||||
  struct mpctb *mpctb;
 | 
			
		||||
  struct mppe *proc;
 | 
			
		||||
  struct mpbe *bus;
 | 
			
		||||
  struct mp *mp;
 | 
			
		||||
  struct mpconf *conf;
 | 
			
		||||
  struct mpproc *proc;
 | 
			
		||||
  struct mpioapic *ioapic;
 | 
			
		||||
  struct mpie *intr;
 | 
			
		||||
 | 
			
		||||
  ncpu = 0;
 | 
			
		||||
  if(mp_detect() < 0)
 | 
			
		||||
  bcpu = &cpus[ncpu];
 | 
			
		||||
  if((conf = mp_config(&mp)) == 0)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  ismp = 1;
 | 
			
		||||
  lapic = (uint*)conf->lapicaddr;
 | 
			
		||||
 | 
			
		||||
  // 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;
 | 
			
		||||
  lapic = (uint*)mpctb->lapicaddr;
 | 
			
		||||
  p = (uchar*)mpctb + sizeof(*mpctb);
 | 
			
		||||
  e = (uchar*)mpctb + mpctb->length;
 | 
			
		||||
 | 
			
		||||
  while(p < e) {
 | 
			
		||||
  for(p=(uchar*)(conf+1), e=(uchar*)conf+conf->length; p<e; ){
 | 
			
		||||
    switch(*p){
 | 
			
		||||
    case MPPROCESSOR:
 | 
			
		||||
      proc = (struct mppe*) p;
 | 
			
		||||
    case MPPROC:
 | 
			
		||||
      proc = (struct mpproc*)p;
 | 
			
		||||
      cpus[ncpu].apicid = proc->apicid;
 | 
			
		||||
      if(proc->flags & MPBP) {
 | 
			
		||||
      if(proc->flags & MPBOOT)
 | 
			
		||||
        bcpu = &cpus[ncpu];
 | 
			
		||||
      }
 | 
			
		||||
      ncpu++;
 | 
			
		||||
      p += sizeof(struct mppe);
 | 
			
		||||
      continue;
 | 
			
		||||
    case MPBUS:
 | 
			
		||||
      bus = (struct mpbe*) p;
 | 
			
		||||
      for(i = 0; buses[i]; i++){
 | 
			
		||||
        if(strncmp(buses[i], bus->string, sizeof(bus->string)) == 0)
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
      p += sizeof(struct mpbe);
 | 
			
		||||
      p += sizeof(struct mpproc);
 | 
			
		||||
      continue;
 | 
			
		||||
    case MPIOAPIC:
 | 
			
		||||
      ioapic = (struct mpioapic*) p;
 | 
			
		||||
      ioapic = (struct mpioapic*)p;
 | 
			
		||||
      ioapic_id = ioapic->apicno;
 | 
			
		||||
      p += sizeof(struct mpioapic);
 | 
			
		||||
      continue;
 | 
			
		||||
    case MPBUS:
 | 
			
		||||
    case MPIOINTR:
 | 
			
		||||
      intr = (struct mpie*) p;
 | 
			
		||||
      p += sizeof(struct mpie);
 | 
			
		||||
    case MPLINTR:
 | 
			
		||||
      p += 8;
 | 
			
		||||
      continue;
 | 
			
		||||
    default:
 | 
			
		||||
      cprintf("mp_init: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
 | 
			
		||||
      while(p < e){
 | 
			
		||||
        cprintf("%uX ", *p);
 | 
			
		||||
        p++;
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
      cprintf("mp_init: unknown config type %x\n", *p);
 | 
			
		||||
      panic("mp_init");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -182,47 +142,3 @@ mp_init(void)
 | 
			
		|||
    outb(0x23, inb(0x23) | 1);  // Mask external interrupts.
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
mp_bcpu(void)
 | 
			
		||||
{
 | 
			
		||||
  if(ismp)
 | 
			
		||||
    return bcpu-cpus;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern void mpmain(void);
 | 
			
		||||
 | 
			
		||||
// Write bootstrap code to unused memory at 0x7000.
 | 
			
		||||
#define APBOOTCODE 0x7000
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
mp_startthem(void)
 | 
			
		||||
{
 | 
			
		||||
  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++){
 | 
			
		||||
    // Our current cpu has already started.
 | 
			
		||||
    if(c == cpu())
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    // Set target %esp
 | 
			
		||||
    *(uint*)(APBOOTCODE-4) = (uint) (cpus[c].mpstack) + MPSTACK;
 | 
			
		||||
 | 
			
		||||
    // Set target %eip
 | 
			
		||||
    *(uint*)(APBOOTCODE-8) = (uint)mpmain;
 | 
			
		||||
 | 
			
		||||
    // Go!
 | 
			
		||||
    lapic_startap(cpus[c].apicid, (uint)APBOOTCODE);
 | 
			
		||||
 | 
			
		||||
    // Wait for cpu to get through bootstrap.
 | 
			
		||||
    while(cpus[c].booted == 0)
 | 
			
		||||
      ;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										84
									
								
								mp.h
									
										
									
									
									
								
							
							
						
						
									
										84
									
								
								mp.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// See MultiProcessor Specification Version 1.[14].
 | 
			
		||||
// See MultiProcessor Specification Version 1.[14]
 | 
			
		||||
 | 
			
		||||
struct mp {             // floating pointer
 | 
			
		||||
  uchar signature[4];           // "_MP_"
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ struct mp {             // floating pointer
 | 
			
		|||
  uchar reserved[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mpctb {          // configuration table header
 | 
			
		||||
struct mpconf {         // configuration table header
 | 
			
		||||
  uchar signature[4];           // "PCMP"
 | 
			
		||||
  ushort length;                // total table length
 | 
			
		||||
  uchar version;                // [14]
 | 
			
		||||
| 
						 | 
				
			
			@ -26,22 +26,17 @@ struct mpctb {          // configuration table header
 | 
			
		|||
  uchar reserved;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mppe {           // processor table entry
 | 
			
		||||
struct mpproc {         // processor table entry
 | 
			
		||||
  uchar type;                   // entry type (0)
 | 
			
		||||
  uchar apicid;                 // local APIC id
 | 
			
		||||
  uchar version;                // local APIC verison
 | 
			
		||||
  uchar flags;                  // CPU flags
 | 
			
		||||
    #define MPBOOT 0x02           // This proc is the bootstrap processor.
 | 
			
		||||
  uchar signature[4];           // CPU signature
 | 
			
		||||
  uint feature;                 // feature flags from CPUID instruction
 | 
			
		||||
  uchar reserved[8];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mpbe {           // bus table entry
 | 
			
		||||
  uchar type;                   // entry type (1)
 | 
			
		||||
  uchar busno;                  // bus id
 | 
			
		||||
  char string[6];               // bus type string
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mpioapic {       // I/O APIC table entry
 | 
			
		||||
  uchar type;                   // entry type (2)
 | 
			
		||||
  uchar apicno;                 // I/O APIC id
 | 
			
		||||
| 
						 | 
				
			
			@ -50,69 +45,10 @@ struct mpioapic {       // I/O APIC table entry
 | 
			
		|||
  uint *addr;                  // I/O APIC address
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mpie {           // interrupt table entry
 | 
			
		||||
  uchar type;                   // entry type ([34])
 | 
			
		||||
  uchar intr;                   // interrupt type
 | 
			
		||||
  ushort flags;                 // interrupt flag
 | 
			
		||||
  uchar busno;                  // source bus id
 | 
			
		||||
  uchar irq;                    // source bus irq
 | 
			
		||||
  uchar apicno;                 // destination APIC id
 | 
			
		||||
  uchar intin;                  // destination APIC [L]INTIN#
 | 
			
		||||
};
 | 
			
		||||
// Table entry types
 | 
			
		||||
#define MPPROC    0x00  // One per processor
 | 
			
		||||
#define MPBUS     0x01  // One per bus
 | 
			
		||||
#define MPIOAPIC  0x02  // One per I/O APIC
 | 
			
		||||
#define MPIOINTR  0x03  // One per bus interrupt source
 | 
			
		||||
#define MPLINTR   0x04  // One per system interrupt source
 | 
			
		||||
 | 
			
		||||
enum {                  // table entry types
 | 
			
		||||
  MPPROCESSOR   = 0x00,         // one entry per processor
 | 
			
		||||
  MPBUS = 0x01,                 // one entry per bus
 | 
			
		||||
  MPIOAPIC = 0x02,              // one entry per I/O APIC
 | 
			
		||||
  MPIOINTR = 0x03,              // one entry per bus interrupt source
 | 
			
		||||
  MPLINTR = 0x04,               // one entry per system interrupt source
 | 
			
		||||
 | 
			
		||||
  MPSASM = 0x80,
 | 
			
		||||
  MPHIERARCHY   = 0x81,
 | 
			
		||||
  MPCBASM = 0x82,
 | 
			
		||||
 | 
			
		||||
                        // PCMPprocessor and PCMPioapic flags
 | 
			
		||||
  MPEN = 0x01,                  // enabled
 | 
			
		||||
  MPBP = 0x02,                  // bootstrap processor
 | 
			
		||||
 | 
			
		||||
                        // PCMPiointr and PCMPlintr flags
 | 
			
		||||
  MPPOMASK = 0x03,              // polarity conforms to bus specs
 | 
			
		||||
  MPHIGH = 0x01,                // active high
 | 
			
		||||
  MPLOW = 0x03,                 // active low
 | 
			
		||||
  MPELMASK = 0x0C,              // trigger mode of APIC input signals
 | 
			
		||||
  MPEDGE = 0x04,                // edge-triggered
 | 
			
		||||
  MPLEVEL = 0x0C,               // level-triggered
 | 
			
		||||
 | 
			
		||||
                        // PCMPiointr and PCMPlintr interrupt type
 | 
			
		||||
  MPINT = 0x00,                 // vectored interrupt from APIC Rdt
 | 
			
		||||
  MPNMI = 0x01,                 // non-maskable interrupt
 | 
			
		||||
  MPSMI = 0x02,                 // system management interrupt
 | 
			
		||||
  MPExtINT = 0x03,              // vectored interrupt from external PIC
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
  APIC_FIXED     = 0x00000000,  // [10:8] Delivery Mode
 | 
			
		||||
  APIC_LOWEST    = 0x00000100,  // Lowest priority
 | 
			
		||||
  APIC_SMI       = 0x00000200,  // System Management Interrupt
 | 
			
		||||
  APIC_RR        = 0x00000300,  // Remote Read
 | 
			
		||||
  APIC_NMI       = 0x00000400,
 | 
			
		||||
  APIC_INIT      = 0x00000500,  // INIT/RESET
 | 
			
		||||
  APIC_STARTUP   = 0x00000600,  // Startup IPI
 | 
			
		||||
  APIC_EXTINT    = 0x00000700,
 | 
			
		||||
 | 
			
		||||
  APIC_PHYSICAL  = 0x00000000,  // [11] Destination Mode (RW)
 | 
			
		||||
  APIC_LOGICAL   = 0x00000800,
 | 
			
		||||
 | 
			
		||||
  APIC_DELIVS    = 0x00001000,  // [12] Delivery Status (RO)
 | 
			
		||||
  APIC_HIGH      = 0x00000000,  // [13] Interrupt Input Pin Polarity (RW)
 | 
			
		||||
  APIC_LOW       = 0x00002000,
 | 
			
		||||
  APIC_REMOTEIRR = 0x00004000,  // [14] Remote IRR (RO)
 | 
			
		||||
  APIC_EDGE      = 0x00000000,  // [15] Trigger Mode (RW)
 | 
			
		||||
  APIC_LEVEL     = 0x00008000,
 | 
			
		||||
  APIC_IMASK     = 0x00010000,  // [16] Interrupt Mask
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue