summaryrefslogtreecommitdiff
path: root/sys/arch/i386
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2005-05-24 08:54:15 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2005-05-24 08:54:15 +0000
commitff2639010cb1371801085656e8ad8fe07817cded (patch)
treeac843629d3d65c7cdbc1033ada89104e9d204edc /sys/arch/i386
parentea81cc749111e144e86ba09a80ae9aec8ae86c0e (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.c59
-rw-r--r--sys/arch/i386/i386/locore.s28
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(&regs, sizeof(regs));
- if ((apm_flags & APM_IDLE_SLOWS) &&
- apmcall(APM_CPU_BUSY, 0, &regs) != 0) {
+ if (apm_flags & APM_IDLE_SLOWS) {
+ bzero(&regs, sizeof(regs));
+ if (apmcall(APM_CPU_BUSY, 0, &regs) != 0) {
#ifdef DIAGNOSTIC
- apm_perror("set CPU busy", &regs);
+ apm_perror("set CPU busy", &regs);
#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(&regs, sizeof(regs));
- if (apmcall(APM_CPU_IDLE, 0, &regs) != 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(&regs, sizeof(regs));
+ if (apmcall(APM_CPU_IDLE, 0, &regs) != 0) {
#ifdef APMDEBUG
- apm_perror("set CPU idle", &regs);
+ apm_perror("set CPU idle", &regs);
#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)