grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] try2, Enable grub_cpu_idle for i386/pc to halt the CPU


From: David Fries
Subject: [PATCH] try2, Enable grub_cpu_idle for i386/pc to halt the CPU
Date: Thu, 14 Aug 2008 22:27:07 -0500
User-agent: Mutt/1.5.4i

Compared to the last patch I've removed util/user-stub.c in favor of
testing GRUB_UTIL in the header files, do while with while and a fix,
ChangeLog, and compiled it with both coreboot and elf targets in
addition to i386/pc.


Enable grub_cpu_idle for i386/pc to halt the CPU.  Modified the menu
to call grub_cpu_idle.  This will save power when booting.  Or maybe I
should say it will keep the CPU from running so hot when the timer is
counting down.  The static Linux user grub_cpu_idle is in i386/time.h,
the grub versions are in platform specific time.h files.

It isn't safe to call halt in protected mode as interrupts are
disabled.  I assume it is becaus the interrupts handlers aren't setup
to work in protected mode.  But interrupts are enabled in real mode,
and the timer is running, so the only two things of interest in the
menu countdown is time has elapsed or a key is pressed, which both
produce interrupts and are checked.  I assume any other call to
grub_cpu_idle will have an interrupt or the timer to wake it up.



On Wed, Aug 13, 2008 at 11:34:22AM +0200, Marco Gerards wrote:
> David Fries <address@hidden> writes:
>
> > As grub_cpu_idle is exported instead of inline, some of the utility
> > programs failed to compile because the symbol wasn't defined.  I
> > created util/user-stub.c for common stub functions instead of adding
> > it to multiple utility program source files.
>
> Why didn't you use util/misc.c?

Really, I was just trying to not follow the example of grub_getkey
which is defined in, grub-editenv.c and returns 0, while
the other redefinitions in grub-fstest.c, grub-probe.c, and
i386/pc/grub-setup.c returns -1.  Now it's in the header using
GRUB_UTIL.

> Please do not add .mk changes in a patch, it is a generated file :-)

What's a generated file doing in the repository if people aren't
supposed to send in diffs against it?

menu.c do while changed to while.  The entire menu.c needs a code
style checkup.  The indends are set for two characters, but with mixed
spaces and tabs that are eight characters it's not easy to edit.

-- 
David Fries <address@hidden>
http://fries.net/~david/ (PGP encryption key available)

Index: kern/i386/pc/startup.S
===================================================================
--- kern/i386/pc/startup.S      (revision 1798)
+++ kern/i386/pc/startup.S      (working copy)
@@ -1502,8 +1502,28 @@
        popl    %ebx
        popl    %ebp
        ret
-               
+
+
 /*
+ * void grub_cpu_idle (void)
+ * Change to real mode to enable interrupts and hlt until the next interrupt.
+ */
+FUNCTION(grub_cpu_idle)
+       pushl   %ebp
+
+       call    prot_to_real    /* enter real mode */
+       .code16
+
+       hlt
+
+       DATA32  call    real_to_prot
+       .code32
+
+       popl    %ebp
+       ret
+
+
+/*
  * grub_getrtsecs()
  *     if a seconds value can be read, read it and return it (BCD),
  *      otherwise return 0xFF
Index: NEWS
===================================================================
--- NEWS        (revision 1798)
+++ NEWS        (working copy)
@@ -1,5 +1,8 @@
 New in 1.97 - :
 
+* Enable grub_cpu_idle for i386/pc to halt the CPU and modify the menu code
+  to make use of it.  This will save power when booting.
+
 * When booting from PXE, PXE can be used to load files.
 
 * High resolution timer support.
Index: include/grub/i386/time.h
===================================================================
--- include/grub/i386/time.h    (revision 1802)
+++ include/grub/i386/time.h    (working copy)
@@ -19,11 +19,21 @@
 #ifndef KERNEL_CPU_TIME_HEADER
 #define KERNEL_CPU_TIME_HEADER 1
 
-static __inline void
-grub_cpu_idle (void)
+#ifdef GRUB_UTIL
+#include <config.h>
+#include <stdio.h>
+#include <time.h>
+
+static void
+grub_cpu_idle ()
 {
-  /* FIXME: this can't work until we handle interrupts.  */
-/*  __asm__ __volatile__ ("hlt"); */
+  struct timespec req={0,1};
+  nanosleep (&req, NULL);
 }
+#else
+/* When all the various subtypes of i386 have interrupts enabled
+   grub_cpu_idle can be static and call "hlt" directly, until then
+   it is platform specific. */
+#endif
 
 #endif /* ! KERNEL_CPU_TIME_HEADER */
Index: include/grub/i386/pc/time.h
===================================================================
--- include/grub/i386/pc/time.h (revision 1798)
+++ include/grub/i386/pc/time.h (working copy)
@@ -21,9 +21,17 @@
 
 #include <grub/symbol.h>
 
+/* i386/coreboot and i386/pc have the same clock rate */
 #define GRUB_TICKS_PER_SECOND  18
 
 /* Return the real time in ticks.  */
 grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
 
+#ifndef GRUB_UTIL
+/* Call into assembly to change to real mode and enable interrupts so it
+   can halt until the next interrupt is received. */
+void
+EXPORT_FUNC(grub_cpu_idle) (void);
+#endif
+
 #endif /* ! KERNEL_MACHINE_TIME_HEADER */
Index: include/grub/i386/coreboot/time.h
===================================================================
--- include/grub/i386/coreboot/time.h   (revision 1798)
+++ include/grub/i386/coreboot/time.h   (working copy)
@@ -1 +1,39 @@
-#include <grub/i386/pc/time.h>
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008  Free Software Foundation, Inc.
+ *
+ *  GRUB 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, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KERNEL_MACHINE_TIME_HEADER
+#define KERNEL_MACHINE_TIME_HEADER     1
+
+#include <grub/symbol.h>
+
+/* i386/coreboot and i386/pc have the same clock rate */
+#define GRUB_TICKS_PER_SECOND  18
+
+/* Return the real time in ticks.  */
+grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void);
+
+#ifndef GRUB_UTIL
+static __inline void
+grub_cpu_idle (void)
+{
+  /* FIXME: this can't work until we handle interrupts.  */
+/*  __asm__ __volatile__ ("hlt"); */
+}
+#endif
+
+#endif /* ! KERNEL_MACHINE_TIME_HEADER */
Index: ChangeLog
===================================================================
--- ChangeLog   (revision 1798)
+++ ChangeLog   (working copy)
@@ -1,3 +1,18 @@
+2008-08-10  David Fries <address@hidden>
+
+       Enable hlt in grub_cpu_idle for i386/pc.
+
+       * NEWS: Update.
+       * kern/i386/pc/startup.S (grub_cpu_idle): New function location.
+       * include/grub/i386/time.h (grub_cpu_idle): Moved inside [GRUB_UTIL]
+       calls nanosleep().
+       * include/grub/i386/pc/time.h (grub_cpu_idle): New export location.
+       * include/grub/i386/coreboot/time.h [GRUB_TICKS_PER_SECOND]
+       (grub_get_rtc, grub_cpu_idle): New macro, export, and function
+       location.
+       * normal/menu.c (run_menu): Add calls to grub_get_time_ms(),
+       grub_checkkey(), and grub_cpu_idle().
+
 2008-08-09  Christian Franke  <address@hidden>
 
        * Makefile.in: Add `target_os' and `enable_grub_pe2elf'.
Index: normal/menu.c
===================================================================
--- normal/menu.c       (revision 1798)
+++ normal/menu.c       (working copy)
@@ -24,6 +24,7 @@
 #include <grub/time.h>
 #include <grub/env.h>
 #include <grub/script.h>
+#include <grub/machine/time.h>
 
 static grub_uint8_t grub_color_menu_normal;
 static grub_uint8_t grub_color_menu_highlight;
@@ -381,6 +382,10 @@
              saved_time = current_time;
              print_timeout (timeout, offset, 1);
            }
+          /* Sleep until a second has passed or a key is pressed. */
+          while (grub_get_time_ms () - saved_time < 1000
+              && grub_checkkey () == -1)
+            grub_cpu_idle ();
        }
 
       if (timeout == 0)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]