[SeaBIOS] [PATCH 3/4] stacks: Don't update the A20 settings if they haven't changed

Kevin O'Connor kevin at koconnor.net
Tue May 16 18:14:50 CEST 2017


The A20 setting is almost always enabled - only issue an outb() if the
A20 is actually changing.  This reduces the number of outb() calls.

Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
---
 src/fw/smm.c | 6 ++++--
 src/stacks.c | 4 +++-
 src/x86.h    | 7 ++++---
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/src/fw/smm.c b/src/fw/smm.c
index 178959c..d90e43a 100644
--- a/src/fw/smm.c
+++ b/src/fw/smm.c
@@ -109,7 +109,8 @@ handle_smi(u16 cs)
                 dprintf(9, "smm cpu ret %x esp=%x\n", regs[3], regs[4]);
                 memcpy(&smm->cpu, &smm->backup2, sizeof(smm->cpu));
                 memcpy(&smm->cpu.i32.eax, regs, sizeof(regs));
-                set_a20(smm->backup_a20);
+                if (!smm->backup_a20)
+                    set_a20(0);
                 smm->cpu.i32.eip = regs[3];
             }
         } else if (rev == SMM_REV_I64) {
@@ -125,7 +126,8 @@ handle_smi(u16 cs)
             } else if ((u32)smm->cpu.i64.rcx == CALL32SMM_RETURNID) {
                 memcpy(&smm->cpu, &smm->backup2, sizeof(smm->cpu));
                 memcpy(&smm->cpu.i64.rdi, regs, sizeof(regs));
-                set_a20(smm->backup_a20);
+                if (!smm->backup_a20)
+                    set_a20(0);
                 smm->cpu.i64.rip = (u32)regs[4];
             }
         }
diff --git a/src/stacks.c b/src/stacks.c
index 9fec2fb..f4d15ce 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -84,7 +84,9 @@ call32_post(void)
 
     if (!CONFIG_CALL32_SMM || method != C16_SMM) {
         // Restore a20
-        set_a20(GET_LOW(Call16Data.a20));
+        u8 a20 = GET_LOW(Call16Data.a20);
+        if (!a20)
+            set_a20(0);
 
         // Restore gdt and fs/gs
         struct descloc_s gdt;
diff --git a/src/x86.h b/src/x86.h
index a770e6f..4aea65c 100644
--- a/src/x86.h
+++ b/src/x86.h
@@ -258,9 +258,10 @@ static inline u8 get_a20(void) {
 }
 
 static inline u8 set_a20(u8 cond) {
-    u8 val = inb(PORT_A20);
-    outb((val & ~A20_ENABLE_BIT) | (cond ? A20_ENABLE_BIT : 0), PORT_A20);
-    return (val & A20_ENABLE_BIT) != 0;
+    u8 val = inb(PORT_A20), a20_enabled = (val & A20_ENABLE_BIT) != 0;
+    if (a20_enabled != !!cond)
+        outb(val ^ A20_ENABLE_BIT, PORT_A20);
+    return a20_enabled;
 }
 
 // x86.c
-- 
2.9.3




More information about the SeaBIOS mailing list