diff options
author | cheloha <cheloha@cvs.openbsd.org> | 2020-09-03 21:38:47 +0000 |
---|---|---|
committer | cheloha <cheloha@cvs.openbsd.org> | 2020-09-03 21:38:47 +0000 |
commit | 98b143791729f70e6115ce14146b19285ece2a27 (patch) | |
tree | 92b21e4a484fc6b7473c6db78912045aa0dd4d36 /sys | |
parent | ddb7f46e254d5477cd1b386367aa37747a95e3d8 (diff) |
amd64: lapic: refactor timer programming
We reprogram the lapic timer by hand in three separate places.
This is error-prone and difficult to read.
To clean things up, introduce routines for reprogramming the lapic
timer in a given mode. lapic_timer_oneshot() starts a oneshot
countdown. lapic_timer_periodic() starts a repeating countdown.
Both of these routines call lapic_timer_start(), wherein we actually
write the lapic registers.
With input from dlg@.
Earlier version eyeballed by mlarkin@.
Suspend/resume tested by gnezdo@.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/amd64/amd64/lapic.c | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c index 31863b2b0ac..25f90b69508 100644 --- a/sys/arch/amd64/amd64/lapic.c +++ b/sys/arch/amd64/amd64/lapic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lapic.c,v 1.55 2019/08/03 14:57:51 jcs Exp $ */ +/* $OpenBSD: lapic.c,v 1.56 2020/09/03 21:38:46 cheloha Exp $ */ /* $NetBSD: lapic.c,v 1.2 2003/05/08 01:04:35 fvdl Exp $ */ /*- @@ -413,6 +413,36 @@ u_int32_t lapic_frac_usec_per_cycle; u_int64_t lapic_frac_cycle_per_usec; u_int32_t lapic_delaytab[26]; +void lapic_timer_oneshot(uint32_t, uint32_t); +void lapic_timer_periodic(uint32_t, uint32_t); + +/* + * Start the local apic countdown timer. + * + * First set the mode, mask, and vector. Then set the + * divisor. Last, set the cycle count: this restarts + * the countdown. + */ +static inline void +lapic_timer_start(uint32_t mode, uint32_t mask, uint32_t cycles) +{ + lapic_writereg(LAPIC_LVTT, mode | mask | LAPIC_TIMER_VECTOR); + lapic_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1); + lapic_writereg(LAPIC_ICR_TIMER, cycles); +} + +void +lapic_timer_oneshot(uint32_t mask, uint32_t cycles) +{ + lapic_timer_start(LAPIC_LVTT_TM_ONESHOT, mask, cycles); +} + +void +lapic_timer_periodic(uint32_t mask, uint32_t cycles) +{ + lapic_timer_start(LAPIC_LVTT_TM_PERIODIC, mask, cycles); +} + void lapic_clockintr(void *arg, struct intrframe frame) { @@ -430,17 +460,7 @@ lapic_clockintr(void *arg, struct intrframe frame) void lapic_startclock(void) { - /* - * Start local apic countdown timer running, in repeated mode. - * - * Mask the clock interrupt and set mode, - * then set divisor, - * then unmask and set the vector. - */ - lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_LVTT_M); - lapic_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1); - lapic_writereg(LAPIC_ICR_TIMER, lapic_tval); - lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_TIMER_VECTOR); + lapic_timer_periodic(0, lapic_tval); } void @@ -498,9 +518,7 @@ lapic_calibrate_timer(struct cpu_info *ci) * Configure timer to one-shot, interrupt masked, * large positive number. */ - lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_M); - lapic_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1); - lapic_writereg(LAPIC_ICR_TIMER, 0x80000000); + lapic_timer_oneshot(LAPIC_LVTT_M, 0x80000000); s = intr_disable(); @@ -540,10 +558,7 @@ skip_calibration: lapic_tval = (lapic_per_second * 2) / hz; lapic_tval = (lapic_tval / 2) + (lapic_tval & 0x1); - lapic_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_LVTT_M | - LAPIC_TIMER_VECTOR); - lapic_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1); - lapic_writereg(LAPIC_ICR_TIMER, lapic_tval); + lapic_timer_periodic(LAPIC_LVTT_M, lapic_tval); /* * Compute fixed-point ratios between cycles and |