From 3cf8b3f9c645a4d2120c752576dde4cfb5bcc213 Mon Sep 17 00:00:00 2001 From: Theo de Raadt Date: Sun, 25 Jul 2010 21:43:39 +0000 Subject: in the clock drivers, seperate the soft-state and hard-state which was all jumbled up in the same functions. the rtc (mc chip) and clock (i8243) startup was also mixed up. they the soft state and hardware state can be started in the right order, and it is easy to restart just the neccessary parts upon resume. tested in numerous cases: (apic, pic) * (GENERIC.MP, GENERIC) * (mp, non-mp) * (i386, amd64) ok kettenis --- sys/arch/i386/i386/acpi_machdep.c | 9 ++++-- sys/arch/i386/i386/apm.c | 8 +++-- sys/arch/i386/i386/autoconf.c | 4 +-- sys/arch/i386/i386/cpu.c | 4 +-- sys/arch/i386/i386/lapic.c | 13 ++++++-- sys/arch/i386/i386/machdep.c | 11 ++----- sys/arch/i386/include/cpu.h | 9 +++--- sys/arch/i386/include/i82489var.h | 3 +- sys/arch/i386/isa/clock.c | 68 ++++++++++++++++++--------------------- 9 files changed, 66 insertions(+), 63 deletions(-) (limited to 'sys/arch/i386') diff --git a/sys/arch/i386/i386/acpi_machdep.c b/sys/arch/i386/i386/acpi_machdep.c index 29cefc5a72b..671fe794171 100644 --- a/sys/arch/i386/i386/acpi_machdep.c +++ b/sys/arch/i386/i386/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_machdep.c,v 1.34 2010/07/06 06:25:55 deraadt Exp $ */ +/* $OpenBSD: acpi_machdep.c,v 1.35 2010/07/25 21:43:35 deraadt Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * @@ -273,7 +273,8 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) #if NLAPIC > 0 lapic_enable(); - lapic_initclocks(); + if (initclock_func == lapic_initclocks) + lapic_startclock(); lapic_set_lvt(); #endif @@ -286,7 +287,9 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) #if NIOAPIC > 0 ioapic_enable(); #endif - initrtclock(); + i8254_startclock(); + if (initclock_func == i8254_initclocks) + rtcstart(); /* in i8254 mode, rtc is profclock */ inittodr(time_second); return (0); diff --git a/sys/arch/i386/i386/apm.c b/sys/arch/i386/i386/apm.c index 22243f7f573..830e998196f 100644 --- a/sys/arch/i386/i386/apm.c +++ b/sys/arch/i386/i386/apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apm.c,v 1.87 2010/07/20 12:23:00 deraadt Exp $ */ +/* $OpenBSD: apm.c,v 1.88 2010/07/25 21:43:35 deraadt Exp $ */ /*- * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. @@ -356,8 +356,10 @@ apm_resume(struct apm_softc *sc, struct apmregs *regs) apm_resumes = APM_RESUME_HOLDOFF; - /* they say that some machines may require reinitializing the clock */ - initrtclock(); + /* they say that some machines may require reinitializing the clocks */ + i8254_startclock(); + if (initclock_func == i8254_initclocks) + rtcstart(); /* in i8254 mode, rtc is profclock */ inittodr(time_second); /* lower bit in cx means pccard was powered down */ diff --git a/sys/arch/i386/i386/autoconf.c b/sys/arch/i386/i386/autoconf.c index 9d49b0988fb..7ded3b3a53f 100644 --- a/sys/arch/i386/i386/autoconf.c +++ b/sys/arch/i386/i386/autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.c,v 1.84 2010/06/28 22:20:12 deraadt Exp $ */ +/* $OpenBSD: autoconf.c,v 1.85 2010/07/25 21:43:35 deraadt Exp $ */ /* $NetBSD: autoconf.c,v 1.20 1996/05/03 19:41:56 christos Exp $ */ /*- @@ -105,8 +105,6 @@ cpu_configure(void) * architectures. This fact is used by the pcmcia irq line probing. */ - startrtclock(); - gdt_init(); /* XXX - pcibios uses gdt stuff */ /* Set up proc0's TSS and LDT */ diff --git a/sys/arch/i386/i386/cpu.c b/sys/arch/i386/i386/cpu.c index 751e2d05875..8a9898b08a8 100644 --- a/sys/arch/i386/i386/cpu.c +++ b/sys/arch/i386/i386/cpu.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.c,v 1.40 2010/06/26 23:24:43 guenther Exp $ */ +/* $OpenBSD: cpu.c,v 1.41 2010/07/25 21:43:35 deraadt Exp $ */ /* $NetBSD: cpu.c,v 1.1.2.7 2000/06/26 02:04:05 sommerfeld Exp $ */ /*- @@ -470,7 +470,7 @@ cpu_hatch(void *v) cpu_init_idt(); lapic_enable(); - lapic_initclocks(); + lapic_startclock(); lapic_set_lvt(); gdt_init_cpu(ci); cpu_init_ldt(ci); diff --git a/sys/arch/i386/i386/lapic.c b/sys/arch/i386/i386/lapic.c index b4675c19029..b0c6e5f01c1 100644 --- a/sys/arch/i386/i386/lapic.c +++ b/sys/arch/i386/i386/lapic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lapic.c,v 1.29 2010/07/23 07:21:02 matthew Exp $ */ +/* $OpenBSD: lapic.c,v 1.30 2010/07/25 21:43:35 deraadt Exp $ */ /* $NetBSD: lapic.c,v 1.1.2.8 2000/02/23 06:10:50 sommerfeld Exp $ */ /*- @@ -247,7 +247,7 @@ lapic_clockintr(void *arg) } void -lapic_initclocks(void) +lapic_startclock(void) { /* * Start local apic countdown timer running, in repeated mode. @@ -262,8 +262,15 @@ lapic_initclocks(void) i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_TIMER_VECTOR); } +void +lapic_initclocks(void) +{ + lapic_startclock(); + + i8254_inittimecounter_simple(); +} + extern int gettick(void); /* XXX put in header file */ -extern void (*initclock_func)(void); /* XXX put in header file */ /* * Calibrate the local apic count-down timer (which is running at diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index af304a22335..73da8f7d959 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.479 2010/07/23 14:56:31 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.480 2010/07/25 21:43:35 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -401,7 +401,7 @@ cpu_startup() initmsgbuf((caddr_t)msgbufp, round_page(MSGBUFSIZE)); printf("%s", version); - startrtclock(); + startclocks(); /* * We need to call identifycpu here early, so users have at least some @@ -3291,12 +3291,7 @@ cpu_reset() void cpu_initclocks(void) { - (*initclock_func)(); - - if (initclock_func == i8254_initclocks) - i8254_inittimecounter(); - else - i8254_inittimecounter_simple(); + (*initclock_func)(); /* lapic or i8254 */ } void diff --git a/sys/arch/i386/include/cpu.h b/sys/arch/i386/include/cpu.h index d6c0e6ef89d..04ee23d9986 100644 --- a/sys/arch/i386/include/cpu.h +++ b/sys/arch/i386/include/cpu.h @@ -1,4 +1,4 @@ -/* $OpenBSD: cpu.h,v 1.111 2010/07/21 14:08:09 kettenis Exp $ */ +/* $OpenBSD: cpu.h,v 1.112 2010/07/25 21:43:37 deraadt Exp $ */ /* $NetBSD: cpu.h,v 1.35 1996/05/05 19:29:26 christos Exp $ */ /*- @@ -371,15 +371,16 @@ void switch_exit(struct proc *); void proc_trampoline(void); /* clock.c */ -void initrtclock(void); -void startrtclock(void); +extern void (*initclock_func)(void); +void startclocks(void); void rtcdrain(void *); +void rtcstart(void); void i8254_delay(int); void i8254_initclocks(void); +void i8254_startclock(void); void i8254_inittimecounter(void); void i8254_inittimecounter_simple(void); - #if !defined(SMALL_KERNEL) /* est.c */ void est_init(const char *, int); diff --git a/sys/arch/i386/include/i82489var.h b/sys/arch/i386/include/i82489var.h index 6af9d3ed971..6a81e1a9b05 100644 --- a/sys/arch/i386/include/i82489var.h +++ b/sys/arch/i386/include/i82489var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i82489var.h,v 1.10 2009/06/03 00:49:12 art Exp $ */ +/* $OpenBSD: i82489var.h,v 1.11 2010/07/25 21:43:37 deraadt Exp $ */ /* $NetBSD: i82489var.h,v 1.1.2.2 2000/02/21 18:46:14 sommerfeld Exp $ */ /*- @@ -119,6 +119,7 @@ extern void (*apichandler[])(void); struct cpu_info; extern void lapic_boot_init(paddr_t); +extern void lapic_startclock(void); extern void lapic_initclocks(void); extern void lapic_set_lvt(void); extern void lapic_set_softvectors(void); diff --git a/sys/arch/i386/isa/clock.c b/sys/arch/i386/isa/clock.c index dd2cc70c26a..da380bb9f7b 100644 --- a/sys/arch/i386/isa/clock.c +++ b/sys/arch/i386/isa/clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clock.c,v 1.42 2009/01/29 13:36:17 kettenis Exp $ */ +/* $OpenBSD: clock.c,v 1.43 2010/07/25 21:43:37 deraadt Exp $ */ /* $NetBSD: clock.c,v 1.39 1996/05/12 23:11:54 mycroft Exp $ */ /*- @@ -167,11 +167,14 @@ mc146818_write(void *sc, u_int reg, u_int datum) } void -startrtclock(void) +startclocks(void) { int s; - initrtclock(); + mtx_enter(&timer_mutex); + rtclock_tval = TIMER_DIV(hz); + i8254_startclock(); + mtx_leave(&timer_mutex); /* Check diagnostic status */ if ((s = mc146818_read(NULL, NVRAM_DIAG)) != 0) /* XXX softc */ @@ -195,22 +198,6 @@ rtcdrain(void *v) ; /* Nothing. */ } -void -initrtclock(void) -{ - mtx_enter(&timer_mutex); - - /* initialize 8253 clock */ - outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); - - /* Correct rounding will buy us a better precision in timekeeping */ - outb(IO_TIMER1, TIMER_DIV(hz) % 256); - outb(IO_TIMER1, TIMER_DIV(hz) / 256); - - rtclock_tval = TIMER_DIV(hz); - mtx_leave(&timer_mutex); -} - int clockintr(void *arg) { @@ -400,16 +387,21 @@ calibrate_cyclecounter(void) void i8254_initclocks(void) { - static struct timeout rtcdrain_timeout; + /* When using i8254 for clock, we also use the rtc for profclock */ + (void)isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK, + clockintr, 0, "clock"); + (void)isa_intr_establish(NULL, 8, IST_PULSE, IPL_CLOCK, + rtcintr, 0, "rtc"); - /* - * XXX If you're doing strange things with multiple clocks, you might - * want to keep track of clock handlers. - */ - (void)isa_intr_establish(NULL, 0, IST_PULSE, IPL_CLOCK, clockintr, - 0, "clock"); - (void)isa_intr_establish(NULL, 8, IST_PULSE, IPL_CLOCK, rtcintr, - 0, "rtc"); + rtcstart(); /* start the mc146818 clock */ + + i8254_inittimecounter(); /* hook the interrupt-based i8254 tc */ +} + +void +rtcstart(void) +{ + static struct timeout rtcdrain_timeout; mc146818_write(NULL, MC_REGA, MC_BASE_32_KHz | MC_RATE_128_Hz); mc146818_write(NULL, MC_REGB, MC_REGB_24HR | MC_REGB_PIE); @@ -691,24 +683,28 @@ i8254_inittimecounter(void) void i8254_inittimecounter_simple(void) { - u_long tval = 0x8000; - i8254_timecounter.tc_get_timecount = i8254_simple_get_timecount; i8254_timecounter.tc_counter_mask = 0x7fff; - i8254_timecounter.tc_frequency = TIMER_FREQ; mtx_enter(&timer_mutex); - outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); - outb(IO_TIMER1, tval & 0xff); - outb(IO_TIMER1, tval >> 8); - - rtclock_tval = tval; + rtclock_tval = 0x8000; + i8254_startclock(); mtx_leave(&timer_mutex); tc_init(&i8254_timecounter); } +void +i8254_startclock(void) +{ + u_long tval = rtclock_tval; + + outb(IO_TIMER1 + TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT); + outb(IO_TIMER1 + TIMER_CNTR0, tval & 0xff); + outb(IO_TIMER1 + TIMER_CNTR0, tval >> 8); +} + u_int i8254_simple_get_timecount(struct timecounter *tc) { -- cgit v1.2.3