aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2017-05-16 11:47:27 -0400
committerKevin O'Connor <kevin@koconnor.net>2017-05-16 12:13:32 -0400
commit8ebb33b1588d6be4241a70e7daabdab4eb076cd8 (patch)
treec33661243dc30366b5fe3360a0ae513637834cb6
parent5869a6b58745e3e83f4b9257cf6f64216d5e61dc (diff)
downloadseabios-hppa-8ebb33b1588d6be4241a70e7daabdab4eb076cd8.zip
seabios-hppa-8ebb33b1588d6be4241a70e7daabdab4eb076cd8.tar.gz
seabios-hppa-8ebb33b1588d6be4241a70e7daabdab4eb076cd8.tar.bz2
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.c6
-rw-r--r--src/stacks.c4
-rw-r--r--src/x86.h7
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