summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2008-01-26 11:18:43 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2008-01-26 11:18:43 +0000
commit2f64695cdefc2b134b7ca6233bc27835f2059b8d (patch)
tree392367c80731ebfd493ca5523008bb721b85e862
parent178c8c5808c4199182548cdb763a8d1eb70ecb47 (diff)
Unify i386 and amd64 lapic code, and calibrate lapic timer with interrupts
disabled (as suggested by mickey). ok krw@, marco@
-rw-r--r--sys/arch/amd64/amd64/lapic.c77
-rw-r--r--sys/arch/i386/i386/lapic.c130
2 files changed, 94 insertions, 113 deletions
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c
index a1145435be1..b915c21e594 100644
--- a/sys/arch/amd64/amd64/lapic.c
+++ b/sys/arch/amd64/amd64/lapic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lapic.c,v 1.12 2007/11/29 10:53:54 deraadt Exp $ */
+/* $OpenBSD: lapic.c,v 1.13 2008/01/26 11:18:42 kettenis Exp $ */
/* $NetBSD: lapic.c,v 1.2 2003/05/08 01:04:35 fvdl Exp $ */
/*-
@@ -47,8 +47,6 @@
#include <uvm/uvm_extern.h>
-#include <dev/ic/i8253reg.h>
-
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/cpuvar.h>
@@ -63,6 +61,8 @@
#include <machine/i82489reg.h>
#include <machine/i82489var.h>
+#include <dev/ic/i8253reg.h>
+
#include "ioapic.h"
#if NIOAPIC > 0
@@ -72,10 +72,11 @@
struct evcount clk_count;
struct evcount ipi_count;
-void lapic_delay(int);
+void lapic_delay(int);
static u_int32_t lapic_gettick(void);
-void lapic_clockintr(void *, struct intrframe);
-void lapic_map(paddr_t);
+void lapic_clockintr(void *, struct intrframe);
+void lapic_initclocks(void);
+void lapic_map(paddr_t);
void lapic_hwmask(struct pic *, int);
void lapic_hwunmask(struct pic *, int);
@@ -145,9 +146,9 @@ lapic_set_lvt(void)
#ifdef MULTIPROCESSOR
if (mp_verbose) {
- apic_format_redir (ci->ci_dev->dv_xname, "prelint", 0, 0,
+ apic_format_redir(ci->ci_dev->dv_xname, "prelint", 0, 0,
i82489_readreg(LAPIC_LVINT0));
- apic_format_redir (ci->ci_dev->dv_xname, "prelint", 1, 0,
+ apic_format_redir(ci->ci_dev->dv_xname, "prelint", 1, 0,
i82489_readreg(LAPIC_LVINT1));
}
#endif
@@ -181,15 +182,15 @@ lapic_set_lvt(void)
#ifdef MULTIPROCESSOR
if (mp_verbose) {
- apic_format_redir (ci->ci_dev->dv_xname, "timer", 0, 0,
+ apic_format_redir(ci->ci_dev->dv_xname, "timer", 0, 0,
i82489_readreg(LAPIC_LVTT));
- apic_format_redir (ci->ci_dev->dv_xname, "pcint", 0, 0,
+ apic_format_redir(ci->ci_dev->dv_xname, "pcint", 0, 0,
i82489_readreg(LAPIC_PCINT));
- apic_format_redir (ci->ci_dev->dv_xname, "lint", 0, 0,
+ apic_format_redir(ci->ci_dev->dv_xname, "lint", 0, 0,
i82489_readreg(LAPIC_LVINT0));
- apic_format_redir (ci->ci_dev->dv_xname, "lint", 1, 0,
+ apic_format_redir(ci->ci_dev->dv_xname, "lint", 1, 0,
i82489_readreg(LAPIC_LVINT1));
- apic_format_redir (ci->ci_dev->dv_xname, "err", 0, 0,
+ apic_format_redir(ci->ci_dev->dv_xname, "err", 0, 0,
i82489_readreg(LAPIC_LVERR));
}
#endif
@@ -226,7 +227,7 @@ lapic_boot_init(paddr_t lapic_base)
evcount_attach(&ipi_count, "ipi", (void *)&ipi_irq, &evcount_intr);
}
-static inline u_int32_t
+static __inline u_int32_t
lapic_gettick(void)
{
return i82489_readreg(LAPIC_CCR_TIMER);
@@ -263,10 +264,10 @@ lapic_initclocks(void)
* then set divisor,
* then unmask and set the vector.
*/
- i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_LVTT_M);
- i82489_writereg (LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
- i82489_writereg (LAPIC_ICR_TIMER, lapic_tval);
- i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_TIMER_VECTOR);
+ i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_LVTT_M);
+ i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+ i82489_writereg(LAPIC_ICR_TIMER, lapic_tval);
+ i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_TIMER_VECTOR);
}
extern int gettick(void); /* XXX put in header file */
@@ -290,6 +291,7 @@ lapic_calibrate_timer(struct cpu_info *ci)
unsigned int starttick, tick1, tick2, endtick;
unsigned int startapic, apic1, apic2, endapic;
u_int64_t dtick, dapic, tmp;
+ long rf = read_rflags();
int i;
if (mp_verbose)
@@ -299,20 +301,21 @@ lapic_calibrate_timer(struct cpu_info *ci)
* Configure timer to one-shot, interrupt masked,
* large positive number.
*/
- i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_M);
- i82489_writereg (LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
- i82489_writereg (LAPIC_ICR_TIMER, 0x80000000);
+ i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_M);
+ i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+ i82489_writereg(LAPIC_ICR_TIMER, 0x80000000);
+ disable_intr();
starttick = gettick();
startapic = lapic_gettick();
- for (i=0; i<hz; i++) {
- DELAY(2);
+ for (i = 0; i < hz; i++) {
+ i8254_delay(2);
do {
tick1 = gettick();
apic1 = lapic_gettick();
} while (tick1 < starttick);
- DELAY(2);
+ i8254_delay(2);
do {
tick2 = gettick();
apic2 = lapic_gettick();
@@ -321,6 +324,7 @@ lapic_calibrate_timer(struct cpu_info *ci)
endtick = gettick();
endapic = lapic_gettick();
+ write_rflags(rf);
dtick = hz * rtclock_tval + (starttick-endtick);
dapic = startapic-endapic;
@@ -344,10 +348,10 @@ lapic_calibrate_timer(struct cpu_info *ci)
lapic_tval = (lapic_per_second * 2) / hz;
lapic_tval = (lapic_tval / 2) + (lapic_tval & 0x1);
- i82489_writereg (LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_LVTT_M
- |LAPIC_TIMER_VECTOR);
- i82489_writereg (LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
- i82489_writereg (LAPIC_ICR_TIMER, lapic_tval);
+ i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_LVTT_M |
+ LAPIC_TIMER_VECTOR);
+ i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
+ i82489_writereg(LAPIC_ICR_TIMER, lapic_tval);
/*
* Compute fixed-point ratios between cycles and
@@ -355,17 +359,17 @@ lapic_calibrate_timer(struct cpu_info *ci)
* in lapic_delay.
*/
- tmp = (1000000 * (u_int64_t)1<<32) / lapic_per_second;
+ tmp = (1000000 * (u_int64_t)1 << 32) / lapic_per_second;
lapic_frac_usec_per_cycle = tmp;
- tmp = (lapic_per_second * (u_int64_t)1<<32) / 1000000;
+ tmp = (lapic_per_second * (u_int64_t)1 << 32) / 1000000;
lapic_frac_cycle_per_usec = tmp;
/*
* Compute delay in cycles for likely short delays in usec.
*/
- for (i=0; i<26; i++)
+ for (i = 0; i < 26; i++)
lapic_delaytab[i] = (lapic_frac_cycle_per_usec * i) >>
32;
@@ -423,7 +427,7 @@ i82489_icr_wait(void)
#endif /* DIAGNOSTIC */
while ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) != 0) {
- x86_pause();
+ __asm __volatile("pause": : :"memory");
#ifdef DIAGNOSTIC
j--;
if (j == 0)
@@ -436,23 +440,22 @@ int
x86_ipi_init(int target)
{
- if ((target&LAPIC_DEST_MASK)==0) {
- i82489_writereg(LAPIC_ICRHI, target<<LAPIC_ID_SHIFT);
- }
+ if ((target & LAPIC_DEST_MASK) == 0)
+ i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_LVL_ASSERT );
i82489_icr_wait();
- delay(10000);
+ i8254_delay(10000);
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_LVL_TRIG | LAPIC_LVL_DEASSERT);
i82489_icr_wait();
- return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY)?EBUSY:0;
+ return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0;
}
int
diff --git a/sys/arch/i386/i386/lapic.c b/sys/arch/i386/i386/lapic.c
index 6031b1f4f3f..517129f84c0 100644
--- a/sys/arch/i386/i386/lapic.c
+++ b/sys/arch/i386/i386/lapic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lapic.c,v 1.19 2007/11/29 10:53:54 deraadt Exp $ */
+/* $OpenBSD: lapic.c,v 1.20 2008/01/26 11:18:42 kettenis Exp $ */
/* $NetBSD: lapic.c,v 1.1.2.8 2000/02/23 06:10:50 sommerfeld Exp $ */
/*-
@@ -44,7 +44,6 @@
#include <sys/user.h>
#include <sys/systm.h>
#include <sys/device.h>
-#include <sys/timetc.h>
#include <uvm/uvm_extern.h>
@@ -69,14 +68,13 @@ struct evcount clk_count;
struct evcount ipi_count;
void lapic_delay(int);
-static __inline u_int32_t lapic_gettick(void);
+static u_int32_t lapic_gettick(void);
void lapic_clockintr(void *);
void lapic_initclocks(void);
-void lapic_map(paddr_t);
+void lapic_map(paddr_t);
void
-lapic_map(lapic_base)
- paddr_t lapic_base;
+lapic_map(paddr_t lapic_base)
{
int s;
pt_entry_t *pte;
@@ -110,13 +108,13 @@ lapic_map(lapic_base)
* enable local apic
*/
void
-lapic_enable()
+lapic_enable(void)
{
i82489_writereg(LAPIC_SVR, LAPIC_SVR_ENABLE | LAPIC_SPURIOUS_VECTOR);
}
void
-lapic_set_softvectors()
+lapic_set_softvectors(void)
{
idt_vec_set(LAPIC_SOFTCLOCK_VECTOR, Xintrsoftclock);
idt_vec_set(LAPIC_SOFTNET_VECTOR, Xintrsoftnet);
@@ -125,7 +123,7 @@ lapic_set_softvectors()
}
void
-lapic_set_lvt()
+lapic_set_lvt(void)
{
struct cpu_info *ci = curcpu();
int i;
@@ -198,9 +196,9 @@ lapic_boot_init(paddr_t lapic_base)
}
static __inline u_int32_t
-lapic_gettick()
+lapic_gettick(void)
{
- return (i82489_readreg(LAPIC_CCR_TIMER));
+ return i82489_readreg(LAPIC_CCR_TIMER);
}
#include <sys/kernel.h> /* for hz */
@@ -227,7 +225,7 @@ lapic_clockintr(void *arg)
}
void
-lapic_initclocks()
+lapic_initclocks(void)
{
/*
* Start local apic countdown timer running, in repeated mode.
@@ -262,8 +260,7 @@ lapic_calibrate_timer(struct cpu_info *ci)
unsigned int starttick, tick1, tick2, endtick;
unsigned int startapic, apic1, apic2, endapic;
u_int64_t dtick, dapic, tmp;
- int i;
- char tbuf[9];
+ int i, ef = read_eflags();
if (mp_verbose)
printf("%s: calibrating local timer\n", ci->ci_dev.dv_xname);
@@ -276,17 +273,17 @@ lapic_calibrate_timer(struct cpu_info *ci)
i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
i82489_writereg(LAPIC_ICR_TIMER, 0x80000000);
+ disable_intr();
starttick = gettick();
startapic = lapic_gettick();
- DELAY(2); /* using "old" delay here.. */
-
- for (i=0; i<hz; i++) {
+ for (i = 0; i < hz; i++) {
+ i8254_delay(2);
do {
tick1 = gettick();
apic1 = lapic_gettick();
} while (tick1 < starttick);
-
+ i8254_delay(2);
do {
tick2 = gettick();
apic2 = lapic_gettick();
@@ -295,6 +292,7 @@ lapic_calibrate_timer(struct cpu_info *ci)
endtick = gettick();
endapic = lapic_gettick();
+ write_eflags(ef);
dtick = hz * TIMER_DIV(hz) + (starttick-endtick);
dapic = startapic-endapic;
@@ -307,41 +305,8 @@ lapic_calibrate_timer(struct cpu_info *ci)
lapic_per_second = tmp;
-#if 0
- humanize_number(tbuf, sizeof(tbuf), tmp, "Hz", 1000);
-#else /* XXX: from NetBSD sources... sigh. */
- {
- /* prefixes are: (none), Kilo, Mega, Giga, Tera, Peta, Exa */
- static const char prefixes[] = " KMGTPE";
-
- int i;
- u_int64_t max;
- size_t suffixlen;
-
- if (tbuf == NULL)
- goto out;
- if (sizeof(tbuf) > 0)
- tbuf[0] = '\0';
- suffixlen = sizeof "Hz" - 1;
- /* check if enough room for `x y' + suffix + `\0' */
- if (sizeof(tbuf) < 4 + suffixlen)
- goto out;
-
- max = 1;
- for (i = 0; i < sizeof(tbuf) - suffixlen - 3; i++)
- max *= 10;
- for (i = 0; tmp >= max && i < sizeof(prefixes); i++)
- tmp /= 1000;
-
- snprintf(tbuf, sizeof(tbuf), "%qu%s%c%s",
- (unsigned long long)tmp, i == 0 ? "" : " ", prefixes[i],
- "Hz");
- out:
- ;
- }
-#endif
-
- printf("%s: apic clock running at %s\n", ci->ci_dev.dv_xname, tbuf);
+ printf("%s: apic clock running at %lldMHz\n",
+ ci->ci_dev.dv_xname, tmp / (1000 * 1000));
if (lapic_per_second != 0) {
/*
@@ -420,11 +385,28 @@ lapic_delay(int usec)
* XXX the following belong mostly or partly elsewhere..
*/
+static __inline void i82489_icr_wait(void);
+
+static __inline void
+i82489_icr_wait(void)
+{
+#ifdef DIAGNOSTIC
+ unsigned j = 100000;
+#endif /* DIAGNOSTIC */
+
+ while ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) != 0) {
+ __asm __volatile("pause": : :"memory");
+#ifdef DIAGNOSTIC
+ j--;
+ if (j == 0)
+ panic("i82489_icr_wait: busy");
+#endif /* DIAGNOSTIC */
+ }
+}
+
int
-i386_ipi_init(target)
- int target;
+i386_ipi_init(int target)
{
- unsigned j;
if ((target & LAPIC_DEST_MASK) == 0)
i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
@@ -432,31 +414,26 @@ i386_ipi_init(target)
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_LVL_ASSERT );
- for (j = 100000; j > 0; j--) {
- __asm __volatile("pause": : :"memory");
- if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) == 0)
- break;
- }
+ i82489_icr_wait();
- delay(10000);
+ i8254_delay(10000);
i82489_writereg(LAPIC_ICRLO, (target & LAPIC_DEST_MASK) |
LAPIC_DLMODE_INIT | LAPIC_LVL_TRIG | LAPIC_LVL_DEASSERT);
- for (j = 100000; j > 0; j--) {
- __asm __volatile("pause": : :"memory");
- if ((i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) == 0)
- break;
- }
+ i82489_icr_wait();
- return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY)?EBUSY:0;
+ return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0;
}
int
-i386_ipi(vec,target,dl)
- int vec,target,dl;
+i386_ipi(int vec, int target, int dl)
{
- unsigned j;
+ int result, s;
+
+ s = splclock();
+
+ i82489_icr_wait();
if ((target & LAPIC_DEST_MASK) == 0)
i82489_writereg(LAPIC_ICRHI, target << LAPIC_ID_SHIFT);
@@ -464,10 +441,11 @@ i386_ipi(vec,target,dl)
i82489_writereg(LAPIC_ICRLO,
(target & LAPIC_DEST_MASK) | vec | dl | LAPIC_LVL_ASSERT);
- for (j = 100000;
- j > 0 && (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY);
- j--)
- SPINLOCK_SPIN_HOOK;
+ i82489_icr_wait();
- return (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0;
+ result = (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0;
+
+ splx(s);
+
+ return result;
}