[syslinux:pathbased] core: move idle handling into protected mode

syslinux-bot for H. Peter Anvin hpa at linux.intel.com
Tue Mar 30 16:15:11 PDT 2010


Commit-ID:  d6fb0861c55f062797c8706f484bd47ae0f94568
Gitweb:     http://syslinux.zytor.com/commit/d6fb0861c55f062797c8706f484bd47ae0f94568
Author:     H. Peter Anvin <hpa at linux.intel.com>
AuthorDate: Tue, 30 Mar 2010 16:06:39 -0700
Committer:  H. Peter Anvin <hpa at linux.intel.com>
CommitDate: Tue, 30 Mar 2010 16:10:13 -0700

core: move idle handling into protected mode

Do the actual idling in protected mode.  This both allows PM code a
more efficient interface, but also handles bugs in HVM implementations
which don't handle HLT in real mode.

Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>


---
 com32/include/sys/cpu.h        |    5 +++-
 com32/include/syslinux/idle.h  |    1 +
 com32/include/syslinux/pmapi.h |    3 ++
 com32/lib/syslinux/idle.c      |   24 +++++--------------
 core/fs/pxe/idle.c             |    4 ++-
 core/idle.c                    |   49 ++++++++++++++++++++++++++++++++++++++++
 core/idle.inc                  |   30 ++++++++++--------------
 core/include/core.h            |    8 ++++--
 core/pmapi.c                   |    3 ++
 9 files changed, 88 insertions(+), 39 deletions(-)

diff --git a/com32/include/sys/cpu.h b/com32/include/sys/cpu.h
index d96ec66..a798a84 100644
--- a/com32/include/sys/cpu.h
+++ b/com32/include/sys/cpu.h
@@ -105,7 +105,10 @@ static inline void cpu_relax(void)
     asm volatile ("rep ; nop");
 }
 
-/* These are local cli/sti; not SMP-safe!!! */
+static inline void hlt(void)
+{
+    asm volatile ("hlt");
+}
 
 static inline void cli(void)
 {
diff --git a/com32/include/syslinux/idle.h b/com32/include/syslinux/idle.h
index 4c5947b..6a45236 100644
--- a/com32/include/syslinux/idle.h
+++ b/com32/include/syslinux/idle.h
@@ -33,5 +33,6 @@
 #define _SYSLINUX_IDLE_H
 
 void syslinux_idle(void);
+void syslinux_reset_idle(void);
 
 #endif
diff --git a/com32/include/syslinux/pmapi.h b/com32/include/syslinux/pmapi.h
index 5631dcb..f583dea 100644
--- a/com32/include/syslinux/pmapi.h
+++ b/com32/include/syslinux/pmapi.h
@@ -62,6 +62,9 @@ struct com32_pmapi {
     struct _DIR_ *(*opendir)(const char *);
     struct dirent *(*readdir)(struct _DIR_ *);
     int (*closedir)(struct _DIR_ *);
+
+    void (*idle)(void);
+    void (*reset_idle)(void);
 };
 
 #endif /* _SYSLINUX_PMAPI_H */
diff --git a/com32/lib/syslinux/idle.c b/com32/lib/syslinux/idle.c
index 8a0d206..ddaa7fc 100644
--- a/com32/lib/syslinux/idle.c
+++ b/com32/lib/syslinux/idle.c
@@ -33,25 +33,15 @@
 
 #include <stddef.h>
 #include <com32.h>
-#include <sys/cpu.h>
+#include <syslinux/pmapi.h>
 #include <syslinux/idle.h>
 
-void syslinux_idle(void)
+void syslinux_reset_idle(void)
 {
-    static int do_idle = 1;
-    static const com32sys_t sys_idle = {
-	.eax.l = 0x0013,
-    };
-    com32sys_t idle_result;
-
-    /* This call isn't supported on SYSLINUX < 3.08, but all it does
-       is return an error, so we don't care. */
-
-    if (do_idle) {
-	__intcall(0x22, &sys_idle, &idle_result);
-
-	do_idle = ~idle_result.eflags.l & EFLAGS_CF;
-    }
+    __com32.cs_pm->reset_idle();
+}
 
-    cpu_relax();
+void syslinux_idle(void)
+{
+    __com32.cs_pm->idle();
 }
diff --git a/core/fs/pxe/idle.c b/core/fs/pxe/idle.c
index 5393ae1..0538b16 100644
--- a/core/fs/pxe/idle.c
+++ b/core/fs/pxe/idle.c
@@ -19,7 +19,7 @@
 #include <sys/cpu.h>
 #include "pxe.h"
 
-static void pxe_idle_poll(void)
+static int pxe_idle_poll(void)
 {
     static __lowmem char junk_pkt[PKTBUF_SIZE];
     static __lowmem t_PXENV_UDP_READ read_buf;
@@ -34,6 +34,8 @@ static void pxe_idle_poll(void)
     read_buf.buffer  = FAR_PTR(junk_pkt);
 
     pxe_call(PXENV_UDP_READ, &read_buf);
+
+    return 0;
 }
 
 static uint32_t pxe_detect_nic_type(void)
diff --git a/core/idle.c b/core/idle.c
new file mode 100644
index 0000000..3f57393
--- /dev/null
+++ b/core/idle.c
@@ -0,0 +1,49 @@
+/* -*- fundamental -*- ---------------------------------------------------
+ *
+ *   Copyright 2008 H. Peter Anvin - All Rights Reserved
+ *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *   Boston MA 02110-1301, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * idle.c:
+ *
+ * This function provided protected-mode access to the idle handling.
+ * It needs to be carefully coordinated with idle.inc, which provides
+ * idle services to real-mode code.
+ */
+
+#include "core.h"
+#include <sys/cpu.h>
+
+#define TICKS_TO_IDLE	4	/* Also in idle.inc */
+
+extern uint32_t _IdleTimer;
+extern uint16_t NoHalt;
+
+int (*idle_hook_func)(void);
+
+void reset_idle(void)
+{
+    _IdleTimer = jiffies();
+}
+
+void __idle(void)
+{
+    if (jiffies() - _IdleTimer < TICKS_TO_IDLE)
+	return;
+
+    if (idle_hook_func && idle_hook_func())
+	return;			/* Nonzero return = do not idle */
+
+    if (NoHalt)
+	cpu_relax();
+    else
+	hlt();
+}
diff --git a/core/idle.inc b/core/idle.inc
index 8d69973..0da03ef 100644
--- a/core/idle.inc
+++ b/core/idle.inc
@@ -1,7 +1,7 @@
 ;; -*- fundamental -*- ---------------------------------------------------
 ;;
 ;;   Copyright 2008 H. Peter Anvin - All Rights Reserved
-;;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+;;   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
 ;;
 ;;   This program is free software; you can redistribute it and/or modify
 ;;   it under the terms of the GNU General Public License as published by
@@ -12,12 +12,12 @@
 ;; -----------------------------------------------------------------------
 
 		section .text16
-TICKS_TO_IDLE	equ 4
+TICKS_TO_IDLE	equ 4		; Also in idle.c
 
 reset_idle:
 		push eax
 		mov eax,[cs:__jiffies]
-		mov [cs:IdleTimer],eax
+		mov [cs:_IdleTimer],eax
 		pop eax
 		sti		; Guard against BIOS/PXE brokenness...
 		ret
@@ -54,19 +54,15 @@ do_idle:
 		pop si
 		sti
 .ok:
+		; Don't spend time jumping to PM unless we're actually idle...
+
 		mov eax,[__jiffies]
-		sub eax,[IdleTimer]
+		sub eax,[_IdleTimer]
 		cmp eax,TICKS_TO_IDLE
 		jb .done
-		
-		mov eax,[idle_hook_func]
-		and eax,eax
-		jz .no_idle_hook
-		pm_call eax
-.no_idle_hook:
-		cmp word [NoHalt],0
-		jne .done
-		hlt
+
+		extern __idle
+		pm_call __idle
 .done:
 		pop es
 		pop ds
@@ -74,13 +70,13 @@ do_idle:
 .ret:		ret
 
 		section .data16
-		alignz 4
-		global idle_hook_func
-idle_hook_func	dd 0
+		alignz 2
+		global NoHalt
 NoHalt		dw 0
 
 hlt_err		db 'ERROR: idle with IF=0', CR, LF, 0 
 
 		section .bss16
+		global _IdleTimer
 		alignb 4
-IdleTimer	resd 1
+_IdleTimer	resd 1
diff --git a/core/include/core.h b/core/include/core.h
index f03da81..eb7bfcd 100644
--- a/core/include/core.h
+++ b/core/include/core.h
@@ -21,12 +21,14 @@ extern void getlinsec(void);
 /* getc.inc */
 extern void core_open(void);
 
-/* idle.inc */
-extern void (*idle_hook_func)(void);
-
 /* hello.c */
 extern void myputs(const char*);
 
+/* idle.c */
+extern int (*idle_hook_func)(void);
+extern void __idle(void);
+extern void reset_idle(void);
+
 /* mem/malloc.c, mem/free.c, mem/init.c */
 extern void *malloc(size_t);
 extern void *lmalloc(size_t);
diff --git a/core/pmapi.c b/core/pmapi.c
index 88a7f34..3313cea 100644
--- a/core/pmapi.c
+++ b/core/pmapi.c
@@ -29,4 +29,7 @@ const struct com32_pmapi pm_api_vector =
     .opendir	= opendir,
     .readdir	= readdir,
     .closedir	= closedir,
+
+    .idle	= __idle,
+    .reset_idle	= reset_idle,
 };



More information about the Syslinux-commits mailing list