mm/efi_pt: Preserve interrupt flag across efi_pt_set_fb_wc/efi_pt_restore
diff --git a/common/mm/efi_pt.c b/common/mm/efi_pt.c
index 6d253748..9bdfe026 100644
--- a/common/mm/efi_pt.c
+++ b/common/mm/efi_pt.c
@@ -289,7 +289,7 @@ void efi_pt_set_fb_wc(uint64_t base, uint64_t size) {
saved_pte_val = ext_mem_alloc(SAVED_PTES_MAX * sizeof(uint64_t));
}
- asm volatile ("cli");
+ bool ints = disable_interrupts();
if (!ensure_wc_pat_slot()) {
goto out;
@@ -310,7 +310,9 @@ void efi_pt_set_fb_wc(uint64_t base, uint64_t size) {
wp_on(old_cr0);
out:
- asm volatile ("sti");
+ if (ints) {
+ enable_interrupts();
+ }
}
void efi_pt_restore(void) {
@@ -318,7 +320,7 @@ void efi_pt_restore(void) {
goto out;
}
- asm volatile ("cli");
+ bool ints = disable_interrupts();
if (saved_pte_i != 0) {
uint64_t old_cr0;
@@ -336,7 +338,9 @@ void efi_pt_restore(void) {
cache_on(old_cr0);
}
- asm volatile ("sti");
+ if (ints) {
+ enable_interrupts();
+ }
saved_pte_i = 0;
pat_modified = false;
diff --git a/common/sys/cpu.h b/common/sys/cpu.h
index a91ed5e2..c3cb433a 100644
--- a/common/sys/cpu.h
+++ b/common/sys/cpu.h
@@ -154,6 +154,32 @@ static inline void wrmsr(uint32_t msr, uint64_t value) {
: "memory");
}
+static inline bool disable_interrupts(void) {
+ uintptr_t flags;
+ asm volatile (
+ "pushf\n\t"
+ "pop %0\n\t"
+ "cli\n\t"
+ : "=r" (flags)
+ :
+ : "memory"
+ );
+ return !!(flags & ((uintptr_t)1 << 9));
+}
+
+static inline bool enable_interrupts(void) {
+ uintptr_t flags;
+ asm volatile (
+ "pushf\n\t"
+ "pop %0\n\t"
+ "sti\n\t"
+ : "=r" (flags)
+ :
+ : "memory"
+ );
+ return !!(flags & ((uintptr_t)1 << 9));
+}
+
static inline uint64_t rdtsc(void) {
uint32_t edx, eax;
asm volatile ("rdtsc" : "=a" (eax), "=d" (edx) :: "memory");
