version 1.20, 2007/02/09 21:55:14 |
version 1.20.22.5, 2007/09/06 00:55:03 |
Line 67 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 67 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <machine/pcb.h> |
#include <machine/pcb.h> |
#include <machine/specialreg.h> |
#include <machine/specialreg.h> |
#include <machine/segments.h> |
#include <machine/segments.h> |
#ifdef _HAVE_TIMECOUNTER |
|
#include <x86/x86/tsc.h> |
#include <x86/x86/tsc.h> |
#endif |
|
|
|
#include <machine/apicvar.h> |
#include <machine/apicvar.h> |
#include <machine/i82489reg.h> |
#include <machine/i82489reg.h> |
Line 77 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 75 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
void lapic_delay(int); |
void lapic_delay(int); |
void lapic_microtime(struct timeval *); |
void lapic_microtime(struct timeval *); |
static u_int32_t lapic_gettick(void); |
static uint32_t lapic_gettick(void); |
void lapic_clockintr(void *, struct intrframe *); |
void lapic_clockintr(void *, struct intrframe *); |
static void lapic_map(paddr_t); |
static void lapic_map(paddr_t); |
|
|
Line 85 static void lapic_hwmask(struct pic *, i |
|
Line 83 static void lapic_hwmask(struct pic *, i |
|
static void lapic_hwunmask(struct pic *, int); |
static void lapic_hwunmask(struct pic *, int); |
static void lapic_setup(struct pic *, struct cpu_info *, int, int, int); |
static void lapic_setup(struct pic *, struct cpu_info *, int, int, int); |
|
|
|
static const struct lapic_state { |
|
uint32_t id, |
|
tpri, |
|
ldr, |
|
dfr, |
|
svr; |
|
} lapic_state; |
|
|
extern char idt_allocmap[]; |
extern char idt_allocmap[]; |
|
|
struct pic local_pic = { |
struct pic local_pic = { |
Line 100 struct pic local_pic = { |
|
Line 106 struct pic local_pic = { |
|
}; |
}; |
|
|
static void |
static void |
lapic_map(lapic_base) |
lapic_map(paddr_t lapic_base) |
paddr_t lapic_base; |
|
{ |
{ |
int s; |
int s; |
pt_entry_t *pte; |
pt_entry_t *pte; |
Line 135 lapic_map(lapic_base) |
|
Line 140 lapic_map(lapic_base) |
|
* enable local apic |
* enable local apic |
*/ |
*/ |
void |
void |
lapic_enable() |
lapic_enable(void) |
{ |
{ |
i82489_writereg(LAPIC_SVR, LAPIC_SVR_ENABLE | LAPIC_SPURIOUS_VECTOR); |
i82489_writereg(LAPIC_SVR, LAPIC_SVR_ENABLE | LAPIC_SPURIOUS_VECTOR); |
} |
} |
|
|
void |
void |
lapic_set_lvt() |
lapic_suspend(void) |
|
{ |
|
} |
|
|
|
void |
|
lapic_set_lvt(void) |
{ |
{ |
struct cpu_info *ci = curcpu(); |
struct cpu_info *ci = curcpu(); |
int i; |
int i; |
|
|
* Initialize fixed idt vectors for use by local apic. |
* Initialize fixed idt vectors for use by local apic. |
*/ |
*/ |
void |
void |
lapic_boot_init(lapic_base) |
lapic_boot_init(paddr_t lapic_base) |
paddr_t lapic_base; |
|
{ |
{ |
lapic_map(lapic_base); |
lapic_map(lapic_base); |
|
|
#ifdef MULTIPROCESSOR |
#ifdef MULTIPROCESSOR |
idt_allocmap[LAPIC_IPI_VECTOR] = 1; |
idt_allocmap[LAPIC_IPI_VECTOR] = 1; |
idt_vec_set(LAPIC_IPI_VECTOR, Xintr_lapic_ipi); |
idt_vec_set(LAPIC_IPI_VECTOR, Xintr_lapic_ipi); |
|
idt_allocmap[LAPIC_TLB_MCAST_VECTOR] = 1; |
|
idt_vec_set(LAPIC_TLB_MCAST_VECTOR, Xintr_lapic_tlb_mcast); |
|
idt_allocmap[LAPIC_TLB_BCAST_VECTOR] = 1; |
|
idt_vec_set(LAPIC_TLB_BCAST_VECTOR, Xintr_lapic_tlb_bcast); |
#endif |
#endif |
idt_allocmap[LAPIC_SPURIOUS_VECTOR] = 1; |
idt_allocmap[LAPIC_SPURIOUS_VECTOR] = 1; |
idt_vec_set(LAPIC_SPURIOUS_VECTOR, Xintrspurious); |
idt_vec_set(LAPIC_SPURIOUS_VECTOR, Xintrspurious); |
Line 219 lapic_boot_init(lapic_base) |
|
Line 232 lapic_boot_init(lapic_base) |
|
idt_vec_set(LAPIC_TIMER_VECTOR, Xintr_lapic_ltimer); |
idt_vec_set(LAPIC_TIMER_VECTOR, Xintr_lapic_ltimer); |
} |
} |
|
|
static inline u_int32_t lapic_gettick() |
static uint32_t |
|
lapic_gettick(void) |
{ |
{ |
return i82489_readreg(LAPIC_CCR_TIMER); |
return i82489_readreg(LAPIC_CCR_TIMER); |
} |
} |
Line 227 static inline u_int32_t lapic_gettick() |
|
Line 241 static inline u_int32_t lapic_gettick() |
|
#include <sys/kernel.h> /* for hz */ |
#include <sys/kernel.h> /* for hz */ |
|
|
int lapic_timer = 0; |
int lapic_timer = 0; |
u_int32_t lapic_tval; |
uint32_t lapic_tval; |
|
|
/* |
/* |
* this gets us up to a 4GHz busclock.... |
* this gets us up to a 4GHz busclock.... |
*/ |
*/ |
u_int32_t lapic_per_second; |
uint32_t lapic_per_second; |
u_int32_t lapic_frac_usec_per_cycle; |
uint32_t lapic_frac_usec_per_cycle; |
u_int64_t lapic_frac_cycle_per_usec; |
uint64_t lapic_frac_cycle_per_usec; |
u_int32_t lapic_delaytab[26]; |
uint32_t lapic_delaytab[26]; |
|
|
|
extern u_int i8254_get_timecount(struct timecounter *); |
|
|
void |
void |
lapic_clockintr(void *arg, struct intrframe *frame) |
lapic_clockintr(void *arg, struct intrframe *frame) |
{ |
{ |
#if defined(I586_CPU) || defined(I686_CPU) || defined(__x86_64__) |
#if defined(I586_CPU) || defined(I686_CPU) || defined(__x86_64__) |
#ifndef __HAVE_TIMECOUNTER |
#if defined(TIMECOUNTER_DEBUG) |
static int microset_iter; /* call cc_microset once/sec */ |
|
#endif /* __HAVE_TIMECOUNTER */ |
|
#if defined(TIMECOUNTER_DEBUG) && defined(__HAVE_TIMECOUNTER) |
|
static u_int last_count[X86_MAXPROCS], |
static u_int last_count[X86_MAXPROCS], |
last_delta[X86_MAXPROCS], |
last_delta[X86_MAXPROCS], |
last_tsc[X86_MAXPROCS], |
last_tsc[X86_MAXPROCS], |
last_tscdelta[X86_MAXPROCS], |
last_tscdelta[X86_MAXPROCS], |
last_factor[X86_MAXPROCS]; |
last_factor[X86_MAXPROCS]; |
#endif /* TIMECOUNTER_DEBUG && __HAVE_TIMECOUNTER */ |
#endif /* TIMECOUNTER_DEBUG */ |
struct cpu_info *ci = curcpu(); |
struct cpu_info *ci = curcpu(); |
|
|
ci->ci_isources[LIR_TIMER]->is_evcnt.ev_count++; |
ci->ci_isources[LIR_TIMER]->is_evcnt.ev_count++; |
|
|
#if defined(TIMECOUNTER_DEBUG) && defined(__HAVE_TIMECOUNTER) |
#if defined(TIMECOUNTER_DEBUG) |
{ |
{ |
int cid = ci->ci_cpuid; |
int cid = ci->ci_cpuid; |
extern u_int i8254_get_timecount(struct timecounter *); |
|
u_int c_count = i8254_get_timecount(NULL); |
u_int c_count = i8254_get_timecount(NULL); |
u_int c_tsc = cpu_counter32(); |
u_int c_tsc = cpu_counter32(); |
u_int delta, ddelta, tsc_delta, factor = 0; |
u_int delta, ddelta, tsc_delta, factor = 0; |
Line 314 lapic_clockintr(void *arg, struct intrfr |
|
Line 326 lapic_clockintr(void *arg, struct intrfr |
|
last_tsc[cid] = c_tsc; |
last_tsc[cid] = c_tsc; |
last_tscdelta[cid] = tsc_delta; |
last_tscdelta[cid] = tsc_delta; |
} |
} |
#endif /* TIMECOUNTER_DEBUG && __HAVE_TIMECOUNTER */ |
#endif /* TIMECOUNTER_DEBUG */ |
|
|
#ifndef __HAVE_TIMECOUNTER |
|
/* |
|
* If we have a cycle counter, do the microset thing. |
|
*/ |
|
if (ci->ci_feature_flags & CPUID_TSC) { |
|
if (CPU_IS_PRIMARY(ci) && (microset_iter--) == 0) { |
|
microset_iter = hz - 1; |
|
cc_microset_time = time; |
|
#if defined(MULTIPROCESSOR) |
|
x86_broadcast_ipi(X86_IPI_MICROSET); |
|
#endif |
|
cc_microset(ci); |
|
} |
|
} |
|
#endif /* !__HAVE_TIMECOUNTER */ |
|
#endif /* I586_CPU || I686_CPU || __x86_64__ */ |
#endif /* I586_CPU || I686_CPU || __x86_64__ */ |
|
|
hardclock((struct clockframe *)frame); |
hardclock((struct clockframe *)frame); |
} |
} |
|
|
#if !defined(__HAVE_TIMECOUNTER) && defined(NTP) |
|
extern int fixtick; |
|
#endif /* !__HAVE_TIMECOUNTER && NTP */ |
|
|
|
void |
void |
lapic_initclocks() |
lapic_initclocks(void) |
{ |
{ |
|
|
#if !defined(__HAVE_TIMECOUNTER) && defined(NTP) |
|
/* |
|
* we'll actually get (lapic_per_second/lapic_tval) interrupts/sec. |
|
*/ |
|
fixtick = 1000000 - |
|
((int64_t)tick * lapic_per_second + lapic_tval / 2) / lapic_tval; |
|
#endif /* !__HAVE_TIMECOUNTER && NTP */ |
|
|
|
/* |
/* |
* Start local apic countdown timer running, in repeated mode. |
* Start local apic countdown timer running, in repeated mode. |
* |
* |
Line 381 extern void (*initclock_func)(void); /* |
|
Line 365 extern void (*initclock_func)(void); /* |
|
* We're actually using the IRQ0 timer. Hmm. |
* We're actually using the IRQ0 timer. Hmm. |
*/ |
*/ |
void |
void |
lapic_calibrate_timer(ci) |
lapic_calibrate_timer(struct cpu_info *ci) |
struct cpu_info *ci; |
|
{ |
{ |
unsigned int starttick, tick1, tick2, endtick; |
unsigned int starttick, tick1, tick2, endtick; |
unsigned int startapic, apic1, apic2, endapic; |
unsigned int startapic, apic1, apic2, endapic; |
u_int64_t dtick, dapic, tmp; |
uint64_t dtick, dapic, tmp; |
int i; |
int i; |
char tbuf[9]; |
char tbuf[9]; |
|
|
Line 474 lapic_calibrate_timer(ci) |
|
Line 457 lapic_calibrate_timer(ci) |
|
*/ |
*/ |
delay_func = lapic_delay; |
delay_func = lapic_delay; |
initclock_func = lapic_initclocks; |
initclock_func = lapic_initclocks; |
#ifdef __HAVE_TIMECOUNTER |
|
initrtclock(0); |
initrtclock(0); |
#else |
|
initrtclock(); |
|
#endif |
|
} |
} |
} |
} |
|
|
Line 486 lapic_calibrate_timer(ci) |
|
Line 465 lapic_calibrate_timer(ci) |
|
* delay for N usec. |
* delay for N usec. |
*/ |
*/ |
|
|
void lapic_delay(usec) |
void |
int usec; |
lapic_delay(int usec) |
{ |
{ |
int32_t xtick, otick; |
int32_t xtick, otick; |
int64_t deltat; /* XXX may want to be 64bit */ |
int64_t deltat; /* XXX may want to be 64bit */ |
Line 517 void lapic_delay(usec) |
|
Line 496 void lapic_delay(usec) |
|
* XXX the following belong mostly or partly elsewhere.. |
* XXX the following belong mostly or partly elsewhere.. |
*/ |
*/ |
|
|
static inline void i82489_icr_wait(void); |
static void |
|
i82489_icr_wait(void) |
static inline void |
|
i82489_icr_wait() |
|
{ |
{ |
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
unsigned j = 100000; |
unsigned j = 100000; |
Line 537 i82489_icr_wait() |
|
Line 514 i82489_icr_wait() |
|
} |
} |
|
|
int |
int |
x86_ipi_init(target) |
x86_ipi_init(int target) |
int target; |
|
{ |
{ |
|
|
if ((target&LAPIC_DEST_MASK)==0) { |
if ((target&LAPIC_DEST_MASK)==0) { |
Line 561 x86_ipi_init(target) |
|
Line 537 x86_ipi_init(target) |
|
} |
} |
|
|
int |
int |
x86_ipi(vec,target,dl) |
x86_ipi(int vec, int target, int dl) |
int vec,target,dl; |
|
{ |
{ |
int result, s; |
int result, s; |
|
|
Line 576 x86_ipi(vec,target,dl) |
|
Line 551 x86_ipi(vec,target,dl) |
|
i82489_writereg(LAPIC_ICRLO, |
i82489_writereg(LAPIC_ICRLO, |
(target & LAPIC_DEST_MASK) | vec | dl | LAPIC_LVL_ASSERT); |
(target & LAPIC_DEST_MASK) | vec | dl | LAPIC_LVL_ASSERT); |
|
|
|
#ifdef DIAGNOSTIC |
i82489_icr_wait(); |
i82489_icr_wait(); |
|
|
result = (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0; |
result = (i82489_readreg(LAPIC_ICRLO) & LAPIC_DLSTAT_BUSY) ? EBUSY : 0; |
|
#else |
|
/* Don't wait - if it doesn't go, we're in big trouble anyway. */ |
|
result = 0; |
|
#endif |
splx(s); |
splx(s); |
|
|
return result; |
return result; |