diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2017-05-16 11:47:27 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-05-16 12:13:32 -0400 |
commit | 8ebb33b1588d6be4241a70e7daabdab4eb076cd8 (patch) | |
tree | c33661243dc30366b5fe3360a0ae513637834cb6 | |
parent | 5869a6b58745e3e83f4b9257cf6f64216d5e61dc (diff) | |
download | seabios-8ebb33b1588d6be4241a70e7daabdab4eb076cd8.tar.gz |
stacks: Don't update the A20 settings if they haven't changed
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@koconnor.net>
-rw-r--r-- | src/fw/smm.c | 6 | ||||
-rw-r--r-- | src/stacks.c | 4 | ||||
-rw-r--r-- | src/x86.h | 7 |
3 files changed, 11 insertions, 6 deletions
diff --git a/src/fw/smm.c b/src/fw/smm.c index 178959c4..d90e43a9 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 9fec2fb7..f4d15ce9 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; @@ -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 |