extract lapic code from mp.c
This commit is contained in:
parent
6eb6f10c56
commit
f27a68a24a
4 changed files with 18 additions and 206 deletions
2
Makefile
2
Makefile
|
@ -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 mp.o spinlock.o fd.o pipe.o swtch.o
|
||||
syscall.o ide.o picirq.o mp.o lapic.o spinlock.o fd.o pipe.o swtch.o
|
||||
|
||||
# Cross-compiling (e.g., on Mac OS X)
|
||||
TOOLPREFIX = i386-jos-elf-
|
||||
|
|
8
defs.h
8
defs.h
|
@ -49,13 +49,17 @@ void pic_init(void);
|
|||
// mp.c
|
||||
void mp_init(void);
|
||||
void mp_startthem(void);
|
||||
int cpu(void);
|
||||
int mp_isbcpu(void);
|
||||
int mp_bcpu(void);
|
||||
|
||||
// lapic
|
||||
extern uint32_t *lapicaddr;
|
||||
void lapic_init(int);
|
||||
void lapic_startap(uint8_t, int);
|
||||
void lapic_timerinit(void);
|
||||
void lapic_timerintr(void);
|
||||
void lapic_enableintr(void);
|
||||
void lapic_disableintr(void);
|
||||
int cpu(void);
|
||||
|
||||
// spinlock.c
|
||||
struct spinlock;
|
||||
|
|
5
main.c
5
main.c
|
@ -38,11 +38,14 @@ main()
|
|||
// clear BSS
|
||||
memset(edata, 0, end - edata);
|
||||
|
||||
mp_init(); // just set up apic so cpu() works
|
||||
mp_init(); // collect info about this machine
|
||||
|
||||
use_printf_lock = 1;
|
||||
|
||||
cpus[cpu()].clis = 1; // cpu starts as if we had called cli()
|
||||
|
||||
lapic_init(mp_bcpu());
|
||||
|
||||
cprintf("\nxV6\n\n");
|
||||
|
||||
pic_init(); // initialize PIC
|
||||
|
|
209
mp.c
209
mp.c
|
@ -8,90 +8,6 @@
|
|||
#include "mmu.h"
|
||||
#include "proc.h"
|
||||
|
||||
/*
|
||||
* Credit: Plan 9 sources, Intel MP spec, and Cliff Frey
|
||||
*/
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
static char* buses[] = {
|
||||
"CBUSI ",
|
||||
"CBUSII",
|
||||
|
@ -117,119 +33,10 @@ static char* buses[] = {
|
|||
#define APBOOTCODE 0x7000 // XXX hack
|
||||
|
||||
static struct MP* mp; // The MP floating point structure
|
||||
static uint32_t *lapicaddr;
|
||||
struct cpu cpus[NCPU];
|
||||
int ncpu;
|
||||
static struct cpu *bcpu;
|
||||
|
||||
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()
|
||||
{
|
||||
cprintf("%d: init timer\n", cpu());
|
||||
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()
|
||||
{
|
||||
cprintf("%d: timer interrupt!\n", cpu());
|
||||
lapic_write (LAPIC_EOI, 0);
|
||||
}
|
||||
|
||||
void
|
||||
lapic_init(int c)
|
||||
{
|
||||
uint32_t r, lvt;
|
||||
|
||||
cprintf("lapic_init %d\n", c);
|
||||
|
||||
lapic_write(LAPIC_DFR, 0xFFFFFFFF); // set destination format register
|
||||
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // read APIC ID
|
||||
lapic_write(LAPIC_LDR, (1<<r)<<24); // set logical destination register to r
|
||||
lapic_write(LAPIC_TPR, 0xFF); // no interrupts for now
|
||||
lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS)); // enable APIC
|
||||
|
||||
// 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_write(LAPIC_EOI, 0); // acknowledge any outstanding interrupts.
|
||||
|
||||
lvt = (lapic_read(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);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
;
|
||||
|
||||
cprintf("Done init of an apic\n");
|
||||
}
|
||||
|
||||
void
|
||||
lapic_enableintr(void)
|
||||
{
|
||||
lapic_write(LAPIC_TPR, 0);
|
||||
}
|
||||
|
||||
void
|
||||
lapic_disableintr(void)
|
||||
{
|
||||
lapic_write(LAPIC_TPR, 0xFF);
|
||||
}
|
||||
|
||||
int
|
||||
cpu(void)
|
||||
{
|
||||
return (lapic_read(LAPIC_ID)>>24) & 0xFF;
|
||||
}
|
||||
|
||||
static void
|
||||
lapic_startap(struct cpu *c, int v)
|
||||
{
|
||||
int crhi, i;
|
||||
volatile int j = 0;
|
||||
|
||||
crhi = c->apicid<<24;
|
||||
lapic_write(LAPIC_ICRHI, crhi);
|
||||
lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|LAPIC_ASSERT|APIC_INIT);
|
||||
|
||||
while (j++ < 10000) {;}
|
||||
lapic_write(LAPIC_ICRLO, LAPIC_FIELD|APIC_LEVEL|LAPIC_DEASSERT|APIC_INIT);
|
||||
|
||||
while (j++ < 1000000) {;}
|
||||
|
||||
// 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/PGSIZE));
|
||||
while (j++ < 100000) {;}
|
||||
}
|
||||
}
|
||||
|
||||
static struct MP*
|
||||
mp_scan(uint8_t *addr, int len)
|
||||
{
|
||||
|
@ -310,13 +117,6 @@ mp_detect(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mp_isbcpu()
|
||||
{
|
||||
if (bcpu == 0) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mp_init()
|
||||
{
|
||||
|
@ -382,10 +182,15 @@ mp_init()
|
|||
}
|
||||
}
|
||||
|
||||
lapic_init(bcpu-cpus);
|
||||
cprintf("ncpu: %d boot %d\n", ncpu, bcpu-cpus);
|
||||
}
|
||||
|
||||
int
|
||||
mp_bcpu(void)
|
||||
{
|
||||
return bcpu-cpus;
|
||||
}
|
||||
|
||||
void
|
||||
mp_startthem()
|
||||
{
|
||||
|
@ -401,6 +206,6 @@ mp_startthem()
|
|||
cprintf ("starting processor %d\n", c);
|
||||
*(unsigned *)(APBOOTCODE-4) = (unsigned) (cpus[c].mpstack) + MPSTACK; // tell it what to use for %esp
|
||||
*(unsigned *)(APBOOTCODE-8) = (unsigned)&main; // tell it where to jump to
|
||||
lapic_startap(cpus + c, (uint32_t) APBOOTCODE);
|
||||
lapic_startap(cpus[c].apicid, (uint32_t) APBOOTCODE);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue