On 12/07/17 19:50, Heinrich Schuchardt wrote:
On 07/12/2017 08:35 PM, Michael Brown wrote:
On 12/07/17 19:15, Heinrich Schuchardt wrote:
Nope. Interrupts are not supported by U-Boot. To get them running every
architecture implementation would have to be changed.

U-Boot simply uses a call inside the waiting loop to check if new data
is available.

E.g. in UEFI WaitForEvent it will check if new data becomes available on
the serial console or on the network interface inside a loop. In
CheckEvent it will do the same. If data becomes available it will fire
the UEFI event.

OK.  What facility does U-Boot provide to allow the CPU to sleep (i.e.
to allow an idling program to avoid running with 100% CPU usage)?

None. U-Boot loads grub or the OS kernel within a few seconds. So why
bother about reducing CPU load of the only core that is running?

E.g. on the Davinci boards the waiting routine udelay is implemented using

while (get_ticks() < endtime)
   ;

iPXE similarly doesn't bother about reducing CPU load while downloading the OS since it will generally be finished in under a second, but we do sleep the CPU when we have nothing to do for long periods of time (e.g. when waiting for user input, or in the middle of an explicit "sleep" command).

You could add code in efiarm_nap.c and/or efix86_nap.c to detect whether or not it is safe to sleep the CPU. The attached (completely untested) patch demonstrates this idea: modify the cpu_nap() implementation in efix86_nap.c to execute "hlt" only if the platform firmware has enabled interrupts.

Michael
diff --git a/src/arch/x86/include/registers.h b/src/arch/x86/include/registers.h
index dd3b59f..952116b 100644
--- a/src/arch/x86/include/registers.h
+++ b/src/arch/x86/include/registers.h
@@ -183,6 +183,7 @@ struct i386_all_regs {
 #define AF ( 1 <<  4 )
 #define ZF ( 1 <<  6 )
 #define SF ( 1 <<  7 )
+#define IF ( 1 <<  9 )
 #define OF ( 1 << 11 )
 
 /* Segment:offset structure.  Note that the order within the structure
diff --git a/src/arch/x86/interface/efi/efix86_nap.c b/src/arch/x86/interface/efi/efix86_nap.c
index 3ebf0bd..4a0549b 100644
--- a/src/arch/x86/interface/efi/efix86_nap.c
+++ b/src/arch/x86/interface/efi/efix86_nap.c
@@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <ipxe/nap.h>
 #include <ipxe/efi/efi.h>
+#include <registers.h>
 
 /** @file
  *
@@ -33,6 +34,22 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  */
 
 /**
+ * Check if interrupts are enabled
+ *
+ * @ret enabled		Interrupts are enabled
+ */
+static inline int interrupts_enabled ( void ) {
+	unsigned long flags;
+
+	/* Read CPU flags */
+	__asm__ ( "pushf\n\t"
+		  "pop %0\n\t"
+		  : "=r" ( flags ) );
+
+	return ( flags & IF );
+}
+
+/**
  * Sleep until next interrupt
  *
  */
@@ -47,7 +64,8 @@ static void efix86_cpu_nap ( void ) {
 	 * just sits there idly burning power.
 	 *
 	 */
-	__asm__ __volatile__ ( "hlt" );
+	if ( interrupts_enabled() )
+		__asm__ __volatile__ ( "hlt" );
 }
 
 PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );
_______________________________________________
ipxe-devel mailing list
[email protected]
https://lists.ipxe.org/mailman/listinfo.cgi/ipxe-devel

Reply via email to