diff options
author | jhb <jhb@FreeBSD.org> | 2004-12-23 20:42:53 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2004-12-23 20:42:53 +0000 |
commit | f79ca8546cde4ec274482bbfb1c1cd64a5bbb2e1 (patch) | |
tree | f5c55a9d8b2a3daf183eda5ebcf4c57953a0a604 /sys/i386 | |
parent | 59abe64294440bcd98e9b525e9a7ff41300ff011 (diff) | |
download | FreeBSD-src-f79ca8546cde4ec274482bbfb1c1cd64a5bbb2e1.zip FreeBSD-src-f79ca8546cde4ec274482bbfb1c1cd64a5bbb2e1.tar.gz |
- Give the timer, thermal, and error LVT entries an interrupt vector even
though these aren't used yet.
- Add missing function prototypes for some static functions.
- Allow lvt_mode() to handle an LVT entry with a delivery mode of fixed.
- Consolidate code duplicated in lapic_init() and lapic_setup() to program
the spurious vector register of a local APIC in a static lapic_enable()
function.
- Dump the timer, thermal, error, and performance counter LVT entries
during lapic_dump().
- Program LVT pins (currently only LINT0 and LINT1) after the local
APIC has been software enabled via lapic_enable() since otherwise the
LVT programming will not be able to unmask LVT sources.
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/i386/local_apic.c | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/sys/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c index f7e5d28..cc008e6 100644 --- a/sys/i386/i386/local_apic.c +++ b/sys/i386/i386/local_apic.c @@ -97,10 +97,10 @@ struct lapic { static struct lvt lvts[LVT_MAX + 1] = { { 1, 1, 1, 1, APIC_LVT_DM_EXTINT, 0 }, /* LINT0: masked ExtINT */ { 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 }, /* LINT1: NMI */ - { 1, 1, 1, 1, APIC_LVT_DM_FIXED, 0 }, /* Timer: needs a vector */ - { 1, 1, 1, 1, APIC_LVT_DM_FIXED, 0 }, /* Error: needs a vector */ + { 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_TIMER_INT }, /* Timer */ + { 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT }, /* Error */ { 1, 1, 1, 1, APIC_LVT_DM_FIXED, 0 }, /* PMC */ - { 1, 1, 1, 1, APIC_LVT_DM_FIXED, 0 }, /* Thermal: needs a vector */ + { 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_THERMAL_INT }, /* Thermal */ }; static inthand_t *ioint_handlers[] = { @@ -116,6 +116,9 @@ static inthand_t *ioint_handlers[] = { volatile lapic_t *lapic; +static void lapic_enable(void); +static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value); + static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value) { @@ -149,11 +152,7 @@ lvt_mode(struct lapic *la, u_int pin, uint32_t value) /* Use a vector of 0. */ break; case APIC_LVT_DM_FIXED: -#if 0 value |= lvt->lvt_vector; -#else - panic("Fixed LINT pins not supported"); -#endif break; default: panic("bad APIC LVT delivery mode: %#x\n", value); @@ -167,7 +166,6 @@ lvt_mode(struct lapic *la, u_int pin, uint32_t value) void lapic_init(uintptr_t addr) { - u_int32_t value; /* Map the local APIC and setup the spurious interrupt handler. */ KASSERT(trunc_page(addr) == addr, @@ -177,10 +175,7 @@ lapic_init(uintptr_t addr) GSEL(GCODE_SEL, SEL_KPL)); /* Perform basic initialization of the BSP's local APIC. */ - value = lapic->svr; - value &= ~(APIC_SVR_VECTOR | APIC_SVR_FOCUS); - value |= (APIC_SVR_FEN | APIC_SVR_SWEN | APIC_SPURIOUS_INT); - lapic->svr = value; + lapic_enable(); /* Set BSP's per-CPU local APIC ID. */ PCPU_SET(apic_id, lapic_id()); @@ -233,6 +228,9 @@ lapic_dump(const char* str) lapic->id, lapic->version, lapic->ldr, lapic->dfr); printf(" lint0: 0x%08x lint1: 0x%08x TPR: 0x%08x SVR: 0x%08x\n", lapic->lvt_lint0, lapic->lvt_lint1, lapic->tpr, lapic->svr); + printf(" timer: 0x%08x therm: 0x%08x err: 0x%08x pcm: 0x%08x\n", + lapic->lvt_timer, lapic->lvt_thermal, lapic->lvt_error, + lapic->lvt_pcint); } void @@ -260,12 +258,6 @@ lapic_setup(void) eflags = intr_disable(); maxlvt = (lapic->version & APIC_VER_MAXLVT) >> MAXLVTSHIFT; - /* Program LINT[01] LVT entries. */ - lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0); - lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1); - - /* XXX: more LVT entries */ - /* Initialize the TPR to allow all interrupts. */ lapic_set_tpr(0); @@ -283,10 +275,14 @@ lapic_setup(void) lapic->ldr = value; /* Setup spurious vector and enable the local APIC. */ - value = lapic->svr; - value &= ~(APIC_SVR_VECTOR | APIC_SVR_FOCUS); - value |= (APIC_SVR_FEN | APIC_SVR_SWEN | APIC_SPURIOUS_INT); - lapic->svr = value; + lapic_enable(); + + /* Program LINT[01] LVT entries. */ + lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0); + lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1); + + /* XXX: more LVT entries */ + intr_restore(eflags); } @@ -301,6 +297,18 @@ lapic_disable(void) lapic->svr = value; } +static void +lapic_enable(void) +{ + u_int32_t value; + + /* Program the spurious vector to enable the local APIC. */ + value = lapic->svr; + value &= ~(APIC_SVR_VECTOR | APIC_SVR_FOCUS); + value |= (APIC_SVR_FEN | APIC_SVR_SWEN | APIC_SPURIOUS_INT); + lapic->svr = value; +} + int lapic_id(void) { |