]> Devi Nivas Git - cs3210-lab1.git/commitdiff
Clean up lapic code.
authorrsc <rsc>
Mon, 27 Aug 2007 16:57:13 +0000 (16:57 +0000)
committerrsc <rsc>
Mon, 27 Aug 2007 16:57:13 +0000 (16:57 +0000)
One initialization function now, not three.
Use #defines instead of enums (consistent with other code, but sigh).

Still boots in Bochs in SMP mode.

defs.h
lapic.c
main.c

diff --git a/defs.h b/defs.h
index b81ef31bc1597d1e7f17e278f59199b6ed41dd1a..8c4c6651f0159e8bb517e74ad79c7d5271dfc7d8 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -69,12 +69,12 @@ void            kinit(void);
 
 // lapic.c
 int             cpu(void);
-extern uint*    lapicaddr;
+extern volatile uint*    lapic;
 void            lapic_disableintr(void);
 void            lapic_enableintr(void);
 void            lapic_eoi(void);
 void            lapic_init(int);
-void            lapic_startap(uchar, int);
+void            lapic_startap(uchar, uint);
 void            lapic_timerinit(void);
 void            lapic_timerintr(void);
 
diff --git a/lapic.c b/lapic.c
index e781499564a49b19ac6551bc136570ceae454404..7f2940c196724b3e16cfb3c06641c55b0befd402 100644 (file)
--- a/lapic.c
+++ b/lapic.c
 #include "traps.h"
 #include "mmu.h"
 #include "proc.h"
-
-enum {  // Local APIC registers
-  LAPIC_ID  = 0x0020,   // ID
-  LAPIC_VER = 0x0030,   // Version
-  LAPIC_TPR = 0x0080,   // Task Priority
-  LAPIC_APR = 0x0090,   // Arbitration Priority
-  LAPIC_PPR = 0x00A0,   // Processor Priority
-  LAPIC_EOI = 0x00B0,   // EOI
-  LAPIC_LDR = 0x00D0,   // Logical Destination
-  LAPIC_DFR = 0x00E0,   // Destination Format
-  LAPIC_SVR = 0x00F0,   // Spurious Interrupt Vector
-  LAPIC_ISR = 0x0100,   // Interrupt Status (8 registers)
-  LAPIC_TMR = 0x0180,   // Trigger Mode (8 registers)
-  LAPIC_IRR = 0x0200,   // Interrupt Request (8 registers)
-  LAPIC_ESR = 0x0280,   // Error Status
-  LAPIC_ICRLO = 0x0300, // Interrupt Command
-  LAPIC_ICRHI = 0x0310, // Interrupt Command [63:32]
-  LAPIC_TIMER = 0x0320, // Local Vector Table 0 (TIMER)
-  LAPIC_PCINT = 0x0340, // Performance Counter LVT
-  LAPIC_LINT0 = 0x0350, // Local Vector Table 1 (LINT0)
-  LAPIC_LINT1 = 0x0360, // Local Vector Table 2 (LINT1)
-  LAPIC_ERROR = 0x0370, // Local Vector Table 3 (ERROR)
-  LAPIC_TICR = 0x0380,  // Timer Initial Count
-  LAPIC_TCCR = 0x0390,  // Timer Current Count
-  LAPIC_TDCR = 0x03E0,  // Timer Divide Configuration
-};
-
-enum {  // LAPIC_SVR
-  LAPIC_ENABLE  = 0x00000100,   // Unit Enable
-  LAPIC_FOCUS   = 0x00000200,   // Focus Processor Checking Disable
-};
-
-enum {  // LAPIC_ICRLO
-  // [14] IPI Trigger Mode Level (RW)
-  LAPIC_DEASSERT = 0x00000000,  // Deassert level-sensitive interrupt
-  LAPIC_ASSERT  = 0x00004000,   // Assert level-sensitive interrupt
-
-  // [17:16] Remote Read Status
-  LAPIC_INVALID = 0x00000000,   // Invalid
-  LAPIC_WAIT    = 0x00010000,   // In-Progress
-  LAPIC_VALID   = 0x00020000,   // Valid
-
-  // [19:18] Destination Shorthand
-  LAPIC_FIELD   = 0x00000000,   // No shorthand
-  LAPIC_SELF    = 0x00040000,   // Self is single destination
-  LAPIC_ALLINC  = 0x00080000,   // All including self
-  LAPIC_ALLEXC  = 0x000C0000,   // All Excluding self
-};
-
-enum {  // LAPIC_ESR
-  LAPIC_SENDCS  = 0x00000001,     // Send CS Error
-  LAPIC_RCVCS   = 0x00000002,     // Receive CS Error
-  LAPIC_SENDACCEPT = 0x00000004,  // Send Accept Error
-  LAPIC_RCVACCEPT = 0x00000008,   // Receive Accept Error
-  LAPIC_SENDVECTOR = 0x00000020,  // Send Illegal Vector
-  LAPIC_RCVVECTOR = 0x00000040,   // Receive Illegal Vector
-  LAPIC_REGISTER = 0x00000080,    // Illegal Register Address
-};
-
-enum {  // LAPIC_TIMER
-  // [17] Timer Mode (RW)
-  LAPIC_ONESHOT = 0x00000000,   // One-shot
-  LAPIC_PERIODIC = 0x00020000,  // Periodic
-
-  // [19:18] Timer Base (RW)
-  LAPIC_CLKIN   = 0x00000000,   // use CLKIN as input
-  LAPIC_TMBASE  = 0x00040000,   // use TMBASE
-  LAPIC_DIVIDER = 0x00080000,   // use output of the divider
-};
-
-enum {  // LAPIC_TDCR
-  LAPIC_X2 = 0x00000000,        // divide by 2
-  LAPIC_X4 = 0x00000001,        // divide by 4
-  LAPIC_X8 = 0x00000002,        // divide by 8
-  LAPIC_X16 = 0x00000003,       // divide by 16
-  LAPIC_X32 = 0x00000008,       // divide by 32
-  LAPIC_X64 = 0x00000009,       // divide by 64
-  LAPIC_X128 = 0x0000000A,      // divide by 128
-  LAPIC_X1 = 0x0000000B,        // divide by 1
-};
-
-uint *lapicaddr;
-
-static int
-lapic_read(int r)
-{
-  return *(lapicaddr+(r/sizeof(*lapicaddr)));
-}
-
-static void
-lapic_write(int r, int data)
-{
-  *(lapicaddr+(r/sizeof(*lapicaddr))) = data;
-}
-
-
-void
-lapic_timerinit(void)
-{
-  if(!lapicaddr) 
-    return;
-
-  lapic_write(LAPIC_TDCR, LAPIC_X1);
-  lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
-             (IRQ_OFFSET + IRQ_TIMER));
-  lapic_write(LAPIC_TCCR, 10000000);
-  lapic_write(LAPIC_TICR, 10000000);
-}
-
-void
-lapic_timerintr(void)
-{
-  if(lapicaddr) 
-    lapic_write(LAPIC_EOI, 0);
-}
+#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 ESR     (0x0280/4)   // Error Status
+#define ICRLO   (0x0300/4)   // Interrupt Command
+#define ICRHI   (0x0310/4)   // Interrupt Command [63:32]
+#define TIMER   (0x0320/4)   // Local Vector Table 0 (TIMER)
+#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 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
 
 void
 lapic_init(int c)
 {
   uint r, lvt;
 
-  if(!lapicaddr
+  if(!lapic) 
     return;
 
-  lapic_write(LAPIC_DFR, 0xFFFFFFFF);    // Set dst format register
-  r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
-  lapic_write(LAPIC_LDR, (1<<r)<<24);    // Set logical dst register to r
-  lapic_write(LAPIC_TPR, 0xFF);          // No interrupts for now
+  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
-  lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS));
+  lapic[SVR] = ENABLE | (IRQ_OFFSET+IRQ_SPURIOUS);
 
   // In virtual wire mode, set up the LINT0 and LINT1 as follows:
-  lapic_write(LAPIC_LINT0, APIC_IMASK | APIC_EXTINT);
-  lapic_write(LAPIC_LINT1, APIC_IMASK | APIC_NMI);
+  lapic[LINT0] = APIC_IMASK | APIC_EXTINT;
+  lapic[LINT1] = APIC_IMASK | APIC_NMI;
 
-  lapic_write(LAPIC_EOI, 0); // Ack any outstanding interrupts.
+  lapic[EOI] = 0; // Ack any outstanding interrupts.
 
-  lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF;
+  lvt = (lapic[VER]>>16) & 0xFF;
   if(lvt >= 4)
-    lapic_write(LAPIC_PCINT, APIC_IMASK);
-  lapic_write(LAPIC_ERROR, IRQ_OFFSET+IRQ_ERROR);
-  lapic_write(LAPIC_ESR, 0);
-  lapic_read(LAPIC_ESR);
+    lapic[PCINT] = APIC_IMASK;
+  lapic[ERROR] = IRQ_OFFSET+IRQ_ERROR;
+  lapic[ESR] = 0;
+  lapic[ESR];
 
   // Issue an INIT Level De-Assert to synchronise arbitration ID's.
-  lapic_write(LAPIC_ICRHI, 0);
-  lapic_write(LAPIC_ICRLO, LAPIC_ALLINC|APIC_LEVEL|
-                           LAPIC_DEASSERT|APIC_INIT);
-  while(lapic_read(LAPIC_ICRLO) & APIC_DELIVS)
+  lapic[ICRHI] = 0;
+  lapic[ICRLO] = ALLINC | APIC_LEVEL |
+                       DEASSERT | APIC_INIT;
+  while(lapic[ICRLO] & APIC_DELIVS)
     ;
-}
 
-void
-lapic_enableintr(void)
-{
-  if(lapicaddr)
-    lapic_write(LAPIC_TPR, 0);
+  // 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).
+  lapic[TPR] = 0;
 }
 
-void
-lapic_disableintr(void)
+int
+cpu(void)
 {
-  if(lapicaddr)
-    lapic_write(LAPIC_TPR, 0xFF);
+  if(lapic)
+    return lapic[ID]>>24;
+  return 0;
 }
 
+// Acknowledge interrupt.
 void
 lapic_eoi(void)
 {
-  if(lapicaddr)
-    lapic_write(LAPIC_EOI, 0);
-}
-
-int
-cpu(void)
-{
-  int x;
-  if(lapicaddr) 
-    x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
-  else 
-    x = 0;
-  return x;
+  if(lapic)
+    lapic[EOI] = 0;
 }
 
+// Start additional processor running bootstrap code at addr.
 void
-lapic_startap(uchar apicid, int v)
+lapic_startap(uchar apicid, uint addr)
 {
-  int crhi, i;
+  int i;
   volatile int j = 0;
 
-  crhi = apicid<<24;
-  lapic_write(LAPIC_ICRHI, crhi);
-  lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|
-                           LAPIC_ASSERT|APIC_INIT);
+  lapic[ICRHI] = apicid<<24;
+  lapic[ICRLO] = FIELD | APIC_LEVEL | ASSERT | APIC_INIT;
   for(j=0; j<10000; j++);  // 200us
-  lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|
-                           LAPIC_DEASSERT|APIC_INIT);
+  lapic[ICRLO] = FIELD | APIC_LEVEL | DEASSERT | APIC_INIT;
   for(j=0; j<1000000; j++);  // 10ms
 
-  // in p9 code, this was i < 2, which is what the spec says on page B-3
-  for(i = 0; i < 1; i++){
-    lapic_write(LAPIC_ICRHI, crhi);
-    lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_EDGE|APIC_STARTUP|(v/4096));
+  for(i = 0; i < 2; i++){
+    lapic[ICRHI] = apicid<<24;
+    lapic[ICRLO] = FIELD | APIC_EDGE | APIC_STARTUP | (addr/4096);
     for(j=0; j<10000; j++);  // 200us
   }
 }
diff --git a/main.c b/main.c
index d467217a898d34774ba83ba9db6c255d3658eb0e..29a8d346ec152cda87530b70ef9766f4e49b62c4 100644 (file)
--- a/main.c
+++ b/main.c
@@ -37,7 +37,6 @@ main0(void)
   asm volatile("movl %0, %%ebp" : : "r" (cpus[bcpu].mpstack+MPSTACK));
 
   lapic_init(bcpu);
-
   cprintf("\ncpu%d: starting xv6\n\n", cpu());
 
   pinit();         // process table
@@ -53,10 +52,7 @@ main0(void)
   console_init();  // I/O devices & their interrupts
   ide_init();      // disk
   mp_startthem();  // other CPUs
-  if(ismp){
-    lapic_timerinit();   // smp timer
-    lapic_enableintr();  // local interrupts
-  }else
+  if(!ismp)
     pit8253_timerinit(); // uniprocessor timer
   userinit();      // first user process
 
@@ -74,8 +70,6 @@ mpmain(void)
   cprintf("cpu%d: starting\n", cpu());
   idtinit();
   lapic_init(cpu());
-  lapic_timerinit();
-  lapic_enableintr();
   setupsegs(0);
 
   cpuid(0, 0, 0, 0, 0);  // memory barrier