aboutsummaryrefslogtreecommitdiffstats
path: root/src/fw/shadow.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2015-11-09 15:00:19 -0500
committerKevin O'Connor <kevin@koconnor.net>2016-01-12 14:01:07 -0500
commitb837e68d5a6c1a5945513f1995875445a1594c8a (patch)
tree47afc3c7cc77702367764067bcea656b00585618 /src/fw/shadow.c
parent3e8d75f3bef0f36a807303d58523ef5eba4a386f (diff)
downloadseabios-b837e68d5a6c1a5945513f1995875445a1594c8a.tar.gz
resume: Make KVM soft reboot loop detection more flexible
Move the check for soft reboot loops from resume.c to shadow.c and directly check for the case where the copy of the BIOS in flash appears to be a memory alias instead. This prevents a hang if an external reboot request occurs during the BIOS memcpy. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/fw/shadow.c')
-rw-r--r--src/fw/shadow.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/fw/shadow.c b/src/fw/shadow.c
index ee87d36e..4486884b 100644
--- a/src/fw/shadow.c
+++ b/src/fw/shadow.c
@@ -163,7 +163,18 @@ qemu_prep_reset(void)
return;
// QEMU doesn't map 0xc0000-0xfffff back to the original rom on a
// reset, so do that manually before invoking a hard reset.
+ void *cstart = VSYMBOL(code32flat_start), *cend = VSYMBOL(code32flat_end);
+ void *hrp = &HaveRunPost;
+ if (readl(hrp + BIOS_SRC_OFFSET)) {
+ // Some old versions of KVM don't store a pristine copy of the
+ // BIOS in high memory. Try to shutdown the machine instead.
+ dprintf(1, "Unable to hard-reboot machine - attempting shutdown.\n");
+ apm_shutdown();
+ }
+ // Copy the BIOS making sure to only reset HaveRunPost at end
make_bios_writable();
- memcpy(VSYMBOL(code32flat_start), VSYMBOL(code32flat_start) + BIOS_SRC_OFFSET
- , SYMBOL(code32flat_end) - SYMBOL(code32flat_start));
+ memcpy(cstart, cstart + BIOS_SRC_OFFSET, hrp - cstart);
+ memcpy(hrp + 4, hrp + 4 + BIOS_SRC_OFFSET, cend - (hrp + 4));
+ barrier();
+ HaveRunPost = 0;
}