diff --git a/arch/arm64/kernel/cpu.c b/arch/arm64/kernel/cpu.c index 84ad30e3..9e1faef0 100644 --- a/arch/arm64/kernel/cpu.c +++ b/arch/arm64/kernel/cpu.c @@ -796,6 +796,21 @@ unsigned long cpu_disable_interrupt_save(void) return flags; } +/* save ICC_PMR_EL1 & enable interrupt (ICC_PMR_EL1 <= ICC_PMR_EL1_UNMASKED) */ +unsigned long cpu_enable_interrupt_save(void) +{ + unsigned long flags; + unsigned long masked = ICC_PMR_EL1_UNMASKED; + + asm volatile( + "mrs_s %0, " __stringify(ICC_PMR_EL1) "\n" + "msr_s " __stringify(ICC_PMR_EL1) ",%1" + : "=&r" (flags) + : "r" (masked) + : "memory"); + return flags; +} + #else /* defined(CONFIG_HAS_NMI) */ /* @ref.impl arch/arm64/include/asm/irqflags.h::arch_local_irq_enable */ @@ -844,6 +859,20 @@ unsigned long cpu_disable_interrupt_save(void) : "memory"); return flags; } + +/* save PSTATE.DAIF & enable interrupt (PSTATE.DAIF I bit set) */ +unsigned long cpu_enable_interrupt_save(void) +{ + unsigned long flags; + + asm volatile( + "mrs %0, daif // arch_local_irq_save\n" + "msr daifclr, #2" + : "=r" (flags) + : + : "memory"); + return flags; +} #endif /* defined(CONFIG_HAS_NMI) */ /* we not have "pause" instruction, instead "yield" instruction */ diff --git a/arch/x86_64/kernel/cpu.c b/arch/x86_64/kernel/cpu.c index 007f162d..69853205 100644 --- a/arch/x86_64/kernel/cpu.c +++ b/arch/x86_64/kernel/cpu.c @@ -1203,6 +1203,15 @@ unsigned long cpu_disable_interrupt_save(void) return flags; } +unsigned long cpu_enable_interrupt_save(void) +{ + unsigned long flags; + + asm volatile("pushf; pop %0; sti" : "=r"(flags) : : "memory", "cc"); + + return flags; +} + /*@ @ behavior valid_vector: @ assumes 32 <= vector <= 255; diff --git a/kernel/freeze.c b/kernel/freeze.c index 30da050c..7b547883 100644 --- a/kernel/freeze.c +++ b/kernel/freeze.c @@ -14,14 +14,17 @@ extern void __freeze(); void freeze() { + unsigned long flags; struct ihk_os_cpu_monitor *monitor = cpu_local_var(monitor); monitor->status_bak = monitor->status; monitor->status = IHK_OS_MONITOR_KERNEL_FROZEN; + flags = cpu_enable_interrupt_save(); while (monitor->status == IHK_OS_MONITOR_KERNEL_FROZEN) { cpu_halt(); cpu_pause(); } + cpu_restore_interrupt(flags); monitor->status = monitor->status_bak; } diff --git a/lib/include/ihk/cpu.h b/lib/include/ihk/cpu.h index 1890a4d1..40581315 100644 --- a/lib/include/ihk/cpu.h +++ b/lib/include/ihk/cpu.h @@ -9,7 +9,7 @@ /* * HISTORY */ -/* cpu.h COPYRIGHT FUJITSU LIMITED 2015-2016 */ +/* cpu.h COPYRIGHT FUJITSU LIMITED 2015-2019 */ #ifndef IHK_CPU_H #define IHK_CPU_H @@ -28,6 +28,7 @@ void cpu_restore_interrupt(unsigned long); void cpu_pause(void); unsigned long cpu_disable_interrupt_save(void); +unsigned long cpu_enable_interrupt_save(void); struct ihk_mc_interrupt_handler { struct list_head list;