diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2005-05-24 08:54:15 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2005-05-24 08:54:15 +0000 |
commit | ff2639010cb1371801085656e8ad8fe07817cded (patch) | |
tree | ac843629d3d65c7cdbc1033ada89104e9d204edc /sys/arch/i386 | |
parent | ea81cc749111e144e86ba09a80ae9aec8ae86c0e (diff) |
hlt hlt is not a good idea. Rework APM to do what the spec actually says. Run actual BIOS calls whenever we are actually idle. Tovarisch!
ok deraadt@ toby@ beck@ weingart@ art@
Diffstat (limited to 'sys/arch/i386')
-rw-r--r-- | sys/arch/i386/i386/apm.c | 59 | ||||
-rw-r--r-- | sys/arch/i386/i386/locore.s | 28 |
2 files changed, 58 insertions, 29 deletions
diff --git a/sys/arch/i386/i386/apm.c b/sys/arch/i386/i386/apm.c index 03a3a1bb880..14b9af1b773 100644 --- a/sys/arch/i386/i386/apm.c +++ b/sys/arch/i386/i386/apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apm.c,v 1.64 2005/04/29 01:12:27 deraadt Exp $ */ +/* $OpenBSD: apm.c,v 1.65 2005/05/24 08:54:14 marco Exp $ */ /*- * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. @@ -147,6 +147,7 @@ u_char apm_minver; int apm_dobusy = 1; int apm_doidle = 1; int apm_bebatt = 0; +int apm_idle_called = 0; struct { u_int32_t entry; @@ -624,34 +625,65 @@ apm_set_powstate(dev, state) } void -apm_cpu_busy() +apm_cpu_busy(void) { struct apmregs regs; - if (!apm_cd.cd_ndevs || !apm_doidle) + + if (!apm_cd.cd_ndevs) /* No APM device, punt */ + return; + if (!apm_dobusy) + return; + if (!apm_idle_called) return; - bzero(®s, sizeof(regs)); - if ((apm_flags & APM_IDLE_SLOWS) && - apmcall(APM_CPU_BUSY, 0, ®s) != 0) { + if (apm_flags & APM_IDLE_SLOWS) { + bzero(®s, sizeof(regs)); + if (apmcall(APM_CPU_BUSY, 0, ®s) != 0) { #ifdef DIAGNOSTIC - apm_perror("set CPU busy", ®s); + apm_perror("set CPU busy", ®s); #endif + } + apm_idle_called = 0; } } void -apm_cpu_idle() +apm_cpu_idle(void) { struct apmregs regs; - if (!apm_cd.cd_ndevs || !apm_doidle) + static int call_apm = 0; + + if (!apm_cd.cd_ndevs) { /* No APM device, wait for next interrupt */ + __asm __volatile("sti;hlt"); return; + } - bzero(®s, sizeof(regs)); - if (apmcall(APM_CPU_IDLE, 0, ®s) != 0) { + if (!apm_doidle) { + __asm __volatile("sti;hlt"); + return; + } + + /* + * We call the bios APM_IDLE routine here only when we + * have been idle for some time - otherwise we just hlt. + */ + if (call_apm != curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]) { + /* Always call BIOS halt/idle stuff */ + bzero(®s, sizeof(regs)); + if (apmcall(APM_CPU_IDLE, 0, ®s) != 0) { #ifdef APMDEBUG - apm_perror("set CPU idle", ®s); + apm_perror("set CPU idle", ®s); #endif + } + apm_idle_called = 1; + /* If BIOS did halt, don't do it again! */ + if (apm_flags & APM_IDLE_SLOWS) { + __asm __volatile("sti;hlt"); + } + call_apm = curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]; + } else { + __asm __volatile("sti;hlt"); } } @@ -893,6 +925,9 @@ apmattach(parent, self, aux) setgdt(GAPM16CODE_SEL, NULL, 0, 0, 0, 0, 0); setgdt(GAPMDATA_SEL, NULL, 0, 0, 0, 0, 0); } + /* XXX - To go away */ + printf("apm0: flags %x dobusy %d doidle %d\n", + apm_flags, apm_dobusy, apm_doidle); } void diff --git a/sys/arch/i386/i386/locore.s b/sys/arch/i386/i386/locore.s index 5254c3e7932..99ba37aacd8 100644 --- a/sys/arch/i386/i386/locore.s +++ b/sys/arch/i386/i386/locore.s @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.s,v 1.83 2005/04/17 07:33:13 tedu Exp $ */ +/* $OpenBSD: locore.s,v 1.84 2005/05/24 08:54:14 marco Exp $ */ /* $NetBSD: locore.s,v 1.145 1996/05/03 19:41:19 christos Exp $ */ /*- @@ -1599,22 +1599,22 @@ ENTRY(idle) movl $IPL_NONE,CPL # spl0() call _C_LABEL(Xspllower) # process pending interrupts -ENTRY(idle_loop) cmpl $0,_C_LABEL(whichqs) jnz _C_LABEL(idle_exit) -#if NAPM > 0 - call _C_LABEL(apm_cpu_idle) - cmpl $0,_C_LABEL(apm_dobusy) - je 1f - call _C_LABEL(apm_cpu_busy) -1: -#endif + +ENTRY(idle_loop) #if NPCTR > 0 && NAPM == 0 addl $1,_C_LABEL(pctr_idlcnt) adcl $0,_C_LABEL(pctr_idlcnt)+4 +#endif +#if NAPM > 0 + call _C_LABEL(apm_cpu_idle) #else + sti hlt #endif + cmpl $0,_C_LABEL(whichqs) + jnz _C_LABEL(idle_exit) jmp _C_LABEL(idle_loop) ENTRY(idle_exit) @@ -1622,16 +1622,10 @@ ENTRY(idle_exit) #if defined(MULTIPROCESSOR) || defined(LOCKDEBUG) call _C_LABEL(sched_lock_idle) #endif -#if 0 - GET_CPUINFO(%ebx) - leal CPU_INFO_NAME(%ebx),%ebx - pushl %ebx - pushl $1f - call _C_LABEL(printf) - addl $8,%esp +#if NAPM > 0 + call _C_LABEL(apm_cpu_busy) #endif jmp switch_search -1: .asciz "%s: unidle\n" #ifdef DIAGNOSTIC NENTRY(switch_error) |