asm volatile("sti" : : : "memory"); \
})
+#define __sti_hlt() \
+({ \
+ asm volatile("sti; hlt" : : : "memory"); \
+})
+
#define __save_flags(x) \
do { \
unsigned long __f; \
#define local_save_flags(x) __save_flags(x)
#define local_irq_disable() __cli()
#define local_irq_enable() __sti()
+#define local_irq_enable_halt() __sti_hlt()
#define __MAX_IRQ 16
#include <uk/plat/common/cpu.h>
#include <uk/plat/common/_time.h>
-
void ukplat_lcpu_halt(void)
{
ukplat_lcpu_disable_irq();
halt();
}
-void ukplat_lcpu_halt_irq(void)
-{
- ukplat_lcpu_enable_irq();
- halt();
- ukplat_lcpu_disable_irq();
-}
-
void ukplat_lcpu_halt_to(__snsec until)
{
unsigned long flags;
local_irq_disable();
}
+void ukplat_lcpu_halt_irq(void)
+{
+ ukplat_lcpu_enable_irq();
+ halt();
+ ukplat_lcpu_disable_irq();
+}
+
unsigned long ukplat_lcpu_save_irqf(void)
{
unsigned long flags;
#include <uk/plat/lcpu.h>
#include <x86/irq.h>
-
void ukplat_lcpu_enable_irq(void)
{
local_irq_enable();
local_irq_disable();
}
+void ukplat_lcpu_halt_irq(void)
+{
+ /*
+ * We have to be careful when enabling interrupts before entering a
+ * halt state. If we want to wait for an interrupt (e.g., a timer)
+ * the interrupt may fire in the short window between sti and hlt and
+ * we are going to halt forever. As sti only enables interrupts after
+ * the following instruction, we can avoid the race condition by
+ * ensuring that hlt immediately follows sti. There must be no
+ * instruction in between.
+ */
+ local_irq_enable_halt();
+ local_irq_disable();
+}
+
unsigned long ukplat_lcpu_save_irqf(void)
{
unsigned long flags;
irq_enabled = 0;
}
+void ukplat_lcpu_halt_irq(void)
+{
+ ukplat_lcpu_enable_irq();
+ halt();
+ ukplat_lcpu_disable_irq();
+}
+
int ukplat_lcpu_irqs_disabled(void)
{
return (irq_enabled == 0);
local_irq_disable();
}
+void ukplat_lcpu_halt_irq(void)
+{
+ ukplat_lcpu_enable_irq();
+ halt();
+ ukplat_lcpu_disable_irq();
+}
+
unsigned long ukplat_lcpu_save_irqf(void)
{
unsigned long flags;