mm/mtrr: Disable interrupts across mtrr_save/mtrr_restore
diff --git a/common/mm/mtrr.c b/common/mm/mtrr.c
index 602bbeaf..8dbadb40 100644
--- a/common/mm/mtrr.c
+++ b/common/mm/mtrr.c
@@ -27,6 +27,11 @@ void mtrr_save(void) {
return;
}
+ /* IRQs off across the MSR work; re-enable only if they were on */
+ uintptr_t eflags;
+ asm volatile ("pushf\n\tpop %0" : "=r"(eflags) :: "memory");
+ asm volatile ("cli" ::: "memory");
+
uint64_t ia32_mtrrcap = rdmsr(0xfe);
uint8_t var_reg_count = ia32_mtrrcap & 0xff;
@@ -64,6 +69,10 @@ void mtrr_save(void) {
/* make sure that the saved MTRR default has MTRRs off */
saved_mtrrs[var_reg_count * 2 + 11] &= ~((uint64_t)1 << 11);
+
+ if (eflags & ((uintptr_t)1 << 9)) {
+ asm volatile ("sti" ::: "memory");
+ }
}
void mtrr_restore(void) {
@@ -80,6 +89,11 @@ void mtrr_restore(void) {
return;
}
+ /* IRQs off across the MSR/cache dance; re-enable only if they were on */
+ uintptr_t eflags;
+ asm volatile ("pushf\n\tpop %0" : "=r"(eflags) :: "memory");
+ asm volatile ("cli" ::: "memory");
+
/* according to the Intel SDM 12.11.7.2 "MemTypeSet() Function",
we need to follow this procedure before changing MTRR set up */
@@ -142,6 +156,10 @@ void mtrr_restore(void) {
/* restore old value of cr0 */
asm volatile ("mov %0, %%cr0" :: "r"(old_cr0) : "memory");
+
+ if (eflags & ((uintptr_t)1 << 9)) {
+ asm volatile ("sti" ::: "memory");
+ }
}
#define MTRR_TYPE_WC 1
