Clean up lapic code.
One initialization function now, not three. Use #defines instead of enums (consistent with other code, but sigh). Still boots in Bochs in SMP mode.
This commit is contained in:
parent
112873bc65
commit
b63bb0fd00
3 changed files with 115 additions and 169 deletions
4
defs.h
4
defs.h
|
@ -69,12 +69,12 @@ void kinit(void);
|
||||||
|
|
||||||
// lapic.c
|
// lapic.c
|
||||||
int cpu(void);
|
int cpu(void);
|
||||||
extern uint* lapicaddr;
|
extern volatile uint* lapic;
|
||||||
void lapic_disableintr(void);
|
void lapic_disableintr(void);
|
||||||
void lapic_enableintr(void);
|
void lapic_enableintr(void);
|
||||||
void lapic_eoi(void);
|
void lapic_eoi(void);
|
||||||
void lapic_init(int);
|
void lapic_init(int);
|
||||||
void lapic_startap(uchar, int);
|
void lapic_startap(uchar, uint);
|
||||||
void lapic_timerinit(void);
|
void lapic_timerinit(void);
|
||||||
void lapic_timerintr(void);
|
void lapic_timerintr(void);
|
||||||
|
|
||||||
|
|
262
lapic.c
262
lapic.c
|
@ -6,210 +6,162 @@
|
||||||
#include "traps.h"
|
#include "traps.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
|
#include "lapic.h"
|
||||||
|
|
||||||
enum { // Local APIC registers
|
// Local APIC registers, divided by 4 for use as uint[] indices.
|
||||||
LAPIC_ID = 0x0020, // ID
|
#define ID (0x0020/4) // ID
|
||||||
LAPIC_VER = 0x0030, // Version
|
#define VER (0x0030/4) // Version
|
||||||
LAPIC_TPR = 0x0080, // Task Priority
|
#define TPR (0x0080/4) // Task Priority
|
||||||
LAPIC_APR = 0x0090, // Arbitration Priority
|
#define APR (0x0090/4) // Arbitration Priority
|
||||||
LAPIC_PPR = 0x00A0, // Processor Priority
|
#define PPR (0x00A0/4) // Processor Priority
|
||||||
LAPIC_EOI = 0x00B0, // EOI
|
#define EOI (0x00B0/4) // EOI
|
||||||
LAPIC_LDR = 0x00D0, // Logical Destination
|
#define LDR (0x00D0/4) // Logical Destination
|
||||||
LAPIC_DFR = 0x00E0, // Destination Format
|
#define DFR (0x00E0/4) // Destination Format
|
||||||
LAPIC_SVR = 0x00F0, // Spurious Interrupt Vector
|
#define SVR (0x00F0/4) // Spurious Interrupt Vector
|
||||||
LAPIC_ISR = 0x0100, // Interrupt Status (8 registers)
|
#define ISR (0x0100/4) // Interrupt Status (8 registers)
|
||||||
LAPIC_TMR = 0x0180, // Trigger Mode (8 registers)
|
#define TMR (0x0180/4) // Trigger Mode (8 registers)
|
||||||
LAPIC_IRR = 0x0200, // Interrupt Request (8 registers)
|
#define IRR (0x0200/4) // Interrupt Request (8 registers)
|
||||||
LAPIC_ESR = 0x0280, // Error Status
|
#define ESR (0x0280/4) // Error Status
|
||||||
LAPIC_ICRLO = 0x0300, // Interrupt Command
|
#define ICRLO (0x0300/4) // Interrupt Command
|
||||||
LAPIC_ICRHI = 0x0310, // Interrupt Command [63:32]
|
#define ICRHI (0x0310/4) // Interrupt Command [63:32]
|
||||||
LAPIC_TIMER = 0x0320, // Local Vector Table 0 (TIMER)
|
#define TIMER (0x0320/4) // Local Vector Table 0 (TIMER)
|
||||||
LAPIC_PCINT = 0x0340, // Performance Counter LVT
|
#define PCINT (0x0340/4) // Performance Counter LVT
|
||||||
LAPIC_LINT0 = 0x0350, // Local Vector Table 1 (LINT0)
|
#define LINT0 (0x0350/4) // Local Vector Table 1 (LINT0)
|
||||||
LAPIC_LINT1 = 0x0360, // Local Vector Table 2 (LINT1)
|
#define LINT1 (0x0360/4) // Local Vector Table 2 (LINT1)
|
||||||
LAPIC_ERROR = 0x0370, // Local Vector Table 3 (ERROR)
|
#define ERROR (0x0370/4) // Local Vector Table 3 (ERROR)
|
||||||
LAPIC_TICR = 0x0380, // Timer Initial Count
|
#define TICR (0x0380/4) // Timer Initial Count
|
||||||
LAPIC_TCCR = 0x0390, // Timer Current Count
|
#define TCCR (0x0390/4) // Timer Current Count
|
||||||
LAPIC_TDCR = 0x03E0, // Timer Divide Configuration
|
#define TDCR (0x03E0/4) // Timer Divide Configuration
|
||||||
};
|
|
||||||
|
|
||||||
enum { // LAPIC_SVR
|
// SVR
|
||||||
LAPIC_ENABLE = 0x00000100, // Unit Enable
|
#define ENABLE 0x00000100 // Unit Enable
|
||||||
LAPIC_FOCUS = 0x00000200, // Focus Processor Checking Disable
|
#define FOCUS 0x00000200 // Focus Processor Checking Disable
|
||||||
};
|
|
||||||
|
|
||||||
enum { // LAPIC_ICRLO
|
// ICRLO
|
||||||
// [14] IPI Trigger Mode Level (RW)
|
// [14] IPI Trigger Mode Level (RW)
|
||||||
LAPIC_DEASSERT = 0x00000000, // Deassert level-sensitive interrupt
|
#define DEASSERT 0x00000000 // Deassert level-sensitive interrupt
|
||||||
LAPIC_ASSERT = 0x00004000, // Assert level-sensitive interrupt
|
#define ASSERT 0x00004000 // Assert level-sensitive interrupt
|
||||||
|
|
||||||
// [17:16] Remote Read Status
|
// [17:16] Remote Read Status
|
||||||
LAPIC_INVALID = 0x00000000, // Invalid
|
#define INVALID 0x00000000 // Invalid
|
||||||
LAPIC_WAIT = 0x00010000, // In-Progress
|
#define WAIT 0x00010000 // In-Progress
|
||||||
LAPIC_VALID = 0x00020000, // Valid
|
#define VALID 0x00020000 // Valid
|
||||||
|
|
||||||
// [19:18] Destination Shorthand
|
// [19:18] Destination Shorthand
|
||||||
LAPIC_FIELD = 0x00000000, // No shorthand
|
#define FIELD 0x00000000 // No shorthand
|
||||||
LAPIC_SELF = 0x00040000, // Self is single destination
|
#define SELF 0x00040000 // Self is single destination
|
||||||
LAPIC_ALLINC = 0x00080000, // All including self
|
#define ALLINC 0x00080000 // All including self
|
||||||
LAPIC_ALLEXC = 0x000C0000, // All Excluding self
|
#define ALLEXC 0x000C0000 // All Excluding self
|
||||||
};
|
|
||||||
|
|
||||||
enum { // LAPIC_ESR
|
// ESR
|
||||||
LAPIC_SENDCS = 0x00000001, // Send CS Error
|
#define SENDCS 0x00000001 // Send CS Error
|
||||||
LAPIC_RCVCS = 0x00000002, // Receive CS Error
|
#define RCVCS 0x00000002 // Receive CS Error
|
||||||
LAPIC_SENDACCEPT = 0x00000004, // Send Accept Error
|
#define SENDACCEPT 0x00000004 // Send Accept Error
|
||||||
LAPIC_RCVACCEPT = 0x00000008, // Receive Accept Error
|
#define RCVACCEPT 0x00000008 // Receive Accept Error
|
||||||
LAPIC_SENDVECTOR = 0x00000020, // Send Illegal Vector
|
#define SENDVECTOR 0x00000020 // Send Illegal Vector
|
||||||
LAPIC_RCVVECTOR = 0x00000040, // Receive Illegal Vector
|
#define RCVVECTOR 0x00000040 // Receive Illegal Vector
|
||||||
LAPIC_REGISTER = 0x00000080, // Illegal Register Address
|
#define REGISTER 0x00000080 // Illegal Register Address
|
||||||
};
|
|
||||||
|
|
||||||
enum { // LAPIC_TIMER
|
|
||||||
// [17] Timer Mode (RW)
|
// [17] Timer Mode (RW)
|
||||||
LAPIC_ONESHOT = 0x00000000, // One-shot
|
#define ONESHOT 0x00000000 // One-shot
|
||||||
LAPIC_PERIODIC = 0x00020000, // Periodic
|
#define PERIODIC 0x00020000 // Periodic
|
||||||
|
|
||||||
// [19:18] Timer Base (RW)
|
// [19:18] Timer Base (RW)
|
||||||
LAPIC_CLKIN = 0x00000000, // use CLKIN as input
|
#define CLKIN 0x00000000 // use CLKIN as input
|
||||||
LAPIC_TMBASE = 0x00040000, // use TMBASE
|
#define TMBASE 0x00040000 // use TMBASE
|
||||||
LAPIC_DIVIDER = 0x00080000, // use output of the divider
|
#define DIVIDER 0x00080000 // use output of the divider
|
||||||
};
|
|
||||||
|
|
||||||
enum { // LAPIC_TDCR
|
#define X2 0x00000000 // divide by 2
|
||||||
LAPIC_X2 = 0x00000000, // divide by 2
|
#define X4 0x00000001 // divide by 4
|
||||||
LAPIC_X4 = 0x00000001, // divide by 4
|
#define X8 0x00000002 // divide by 8
|
||||||
LAPIC_X8 = 0x00000002, // divide by 8
|
#define X16 0x00000003 // divide by 16
|
||||||
LAPIC_X16 = 0x00000003, // divide by 16
|
#define X32 0x00000008 // divide by 32
|
||||||
LAPIC_X32 = 0x00000008, // divide by 32
|
#define X64 0x00000009 // divide by 64
|
||||||
LAPIC_X64 = 0x00000009, // divide by 64
|
#define X128 0x0000000A // divide by 128
|
||||||
LAPIC_X128 = 0x0000000A, // divide by 128
|
#define X1 0x0000000B // divide by 1
|
||||||
LAPIC_X1 = 0x0000000B, // divide by 1
|
|
||||||
};
|
|
||||||
|
|
||||||
uint *lapicaddr;
|
//PAGEBREAK!
|
||||||
|
volatile uint *lapic; // Initialized in mp.c
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
lapic_init(int c)
|
lapic_init(int c)
|
||||||
{
|
{
|
||||||
uint r, lvt;
|
uint r, lvt;
|
||||||
|
|
||||||
if(!lapicaddr)
|
if(!lapic)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lapic_write(LAPIC_DFR, 0xFFFFFFFF); // Set dst format register
|
lapic[DFR] = 0xFFFFFFFF; // Set dst format register
|
||||||
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
|
r = (lapic[ID]>>24) & 0xFF; // Read APIC ID
|
||||||
lapic_write(LAPIC_LDR, (1<<r)<<24); // Set logical dst register to r
|
lapic[LDR] = (1<<r) << 24;
|
||||||
lapic_write(LAPIC_TPR, 0xFF); // No interrupts for now
|
lapic[TPR] = 0xFF; // No interrupts for now
|
||||||
|
|
||||||
// Enable APIC
|
// 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:
|
// In virtual wire mode, set up the LINT0 and LINT1 as follows:
|
||||||
lapic_write(LAPIC_LINT0, APIC_IMASK | APIC_EXTINT);
|
lapic[LINT0] = APIC_IMASK | APIC_EXTINT;
|
||||||
lapic_write(LAPIC_LINT1, APIC_IMASK | APIC_NMI);
|
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)
|
if(lvt >= 4)
|
||||||
lapic_write(LAPIC_PCINT, APIC_IMASK);
|
lapic[PCINT] = APIC_IMASK;
|
||||||
lapic_write(LAPIC_ERROR, IRQ_OFFSET+IRQ_ERROR);
|
lapic[ERROR] = IRQ_OFFSET+IRQ_ERROR;
|
||||||
lapic_write(LAPIC_ESR, 0);
|
lapic[ESR] = 0;
|
||||||
lapic_read(LAPIC_ESR);
|
lapic[ESR];
|
||||||
|
|
||||||
// Issue an INIT Level De-Assert to synchronise arbitration ID's.
|
// Issue an INIT Level De-Assert to synchronise arbitration ID's.
|
||||||
lapic_write(LAPIC_ICRHI, 0);
|
lapic[ICRHI] = 0;
|
||||||
lapic_write(LAPIC_ICRLO, LAPIC_ALLINC|APIC_LEVEL|
|
lapic[ICRLO] = ALLINC | APIC_LEVEL |
|
||||||
LAPIC_DEASSERT|APIC_INIT);
|
DEASSERT | APIC_INIT;
|
||||||
while(lapic_read(LAPIC_ICRLO) & APIC_DELIVS)
|
while(lapic[ICRLO] & APIC_DELIVS)
|
||||||
;
|
;
|
||||||
}
|
|
||||||
|
|
||||||
void
|
// Initialize the interrupt timer.
|
||||||
lapic_enableintr(void)
|
// On real hardware would need to do more XXX.
|
||||||
{
|
lapic[TDCR] = X1;
|
||||||
if(lapicaddr)
|
lapic[TIMER] = CLKIN | PERIODIC | (IRQ_OFFSET + IRQ_TIMER);
|
||||||
lapic_write(LAPIC_TPR, 0);
|
lapic[TCCR] = 10000000;
|
||||||
}
|
lapic[TICR] = 10000000;
|
||||||
|
|
||||||
void
|
// Enable interrupts on the APIC (but not on processor).
|
||||||
lapic_disableintr(void)
|
lapic[TPR] = 0;
|
||||||
{
|
|
||||||
if(lapicaddr)
|
|
||||||
lapic_write(LAPIC_TPR, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
lapic_eoi(void)
|
|
||||||
{
|
|
||||||
if(lapicaddr)
|
|
||||||
lapic_write(LAPIC_EOI, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cpu(void)
|
cpu(void)
|
||||||
{
|
{
|
||||||
int x;
|
if(lapic)
|
||||||
if(lapicaddr)
|
return lapic[ID]>>24;
|
||||||
x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
|
return 0;
|
||||||
else
|
|
||||||
x = 0;
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acknowledge interrupt.
|
||||||
void
|
void
|
||||||
lapic_startap(uchar apicid, int v)
|
lapic_eoi(void)
|
||||||
{
|
{
|
||||||
int crhi, i;
|
if(lapic)
|
||||||
|
lapic[EOI] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start additional processor running bootstrap code at addr.
|
||||||
|
void
|
||||||
|
lapic_startap(uchar apicid, uint addr)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
volatile int j = 0;
|
volatile int j = 0;
|
||||||
|
|
||||||
crhi = apicid<<24;
|
lapic[ICRHI] = apicid<<24;
|
||||||
lapic_write(LAPIC_ICRHI, crhi);
|
lapic[ICRLO] = FIELD | APIC_LEVEL | ASSERT | APIC_INIT;
|
||||||
lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|
|
|
||||||
LAPIC_ASSERT|APIC_INIT);
|
|
||||||
for(j=0; j<10000; j++); // 200us
|
for(j=0; j<10000; j++); // 200us
|
||||||
lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|
|
lapic[ICRLO] = FIELD | APIC_LEVEL | DEASSERT | APIC_INIT;
|
||||||
LAPIC_DEASSERT|APIC_INIT);
|
|
||||||
for(j=0; j<1000000; j++); // 10ms
|
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 < 2; i++){
|
||||||
for(i = 0; i < 1; i++){
|
lapic[ICRHI] = apicid<<24;
|
||||||
lapic_write(LAPIC_ICRHI, crhi);
|
lapic[ICRLO] = FIELD | APIC_EDGE | APIC_STARTUP | (addr/4096);
|
||||||
lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_EDGE|APIC_STARTUP|(v/4096));
|
|
||||||
for(j=0; j<10000; j++); // 200us
|
for(j=0; j<10000; j++); // 200us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
main.c
8
main.c
|
@ -37,7 +37,6 @@ main0(void)
|
||||||
asm volatile("movl %0, %%ebp" : : "r" (cpus[bcpu].mpstack+MPSTACK));
|
asm volatile("movl %0, %%ebp" : : "r" (cpus[bcpu].mpstack+MPSTACK));
|
||||||
|
|
||||||
lapic_init(bcpu);
|
lapic_init(bcpu);
|
||||||
|
|
||||||
cprintf("\ncpu%d: starting xv6\n\n", cpu());
|
cprintf("\ncpu%d: starting xv6\n\n", cpu());
|
||||||
|
|
||||||
pinit(); // process table
|
pinit(); // process table
|
||||||
|
@ -53,10 +52,7 @@ main0(void)
|
||||||
console_init(); // I/O devices & their interrupts
|
console_init(); // I/O devices & their interrupts
|
||||||
ide_init(); // disk
|
ide_init(); // disk
|
||||||
mp_startthem(); // other CPUs
|
mp_startthem(); // other CPUs
|
||||||
if(ismp){
|
if(!ismp)
|
||||||
lapic_timerinit(); // smp timer
|
|
||||||
lapic_enableintr(); // local interrupts
|
|
||||||
}else
|
|
||||||
pit8253_timerinit(); // uniprocessor timer
|
pit8253_timerinit(); // uniprocessor timer
|
||||||
userinit(); // first user process
|
userinit(); // first user process
|
||||||
|
|
||||||
|
@ -74,8 +70,6 @@ mpmain(void)
|
||||||
cprintf("cpu%d: starting\n", cpu());
|
cprintf("cpu%d: starting\n", cpu());
|
||||||
idtinit();
|
idtinit();
|
||||||
lapic_init(cpu());
|
lapic_init(cpu());
|
||||||
lapic_timerinit();
|
|
||||||
lapic_enableintr();
|
|
||||||
setupsegs(0);
|
setupsegs(0);
|
||||||
|
|
||||||
cpuid(0, 0, 0, 0, 0); // memory barrier
|
cpuid(0, 0, 0, 0, 0); // memory barrier
|
||||||
|
|
Loading…
Reference in a new issue