aboutsummaryrefslogtreecommitdiff
path: root/target/i386
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw@amazon.co.uk>2022-12-12 14:03:41 +0000
committerDavid Woodhouse <dwmw@amazon.co.uk>2023-03-01 08:22:49 +0000
commit110a0ea59f263b6e382ee22c70c31c2364d11eb0 (patch)
tree76da7af19618d7457e471d9efe6a7acf0702231e /target/i386
parente21be724eaf5dfdf1ac3595e0c808b775ec262f2 (diff)
downloadqemu-110a0ea59f263b6e382ee22c70c31c2364d11eb0.zip
qemu-110a0ea59f263b6e382ee22c70c31c2364d11eb0.tar.gz
qemu-110a0ea59f263b6e382ee22c70c31c2364d11eb0.tar.bz2
i386/xen: manage and save/restore Xen guest long_mode setting
Xen will "latch" the guest's 32-bit or 64-bit ("long mode") setting when the guest writes the MSR to fill in the hypercall page, or when the guest sets the event channel callback in HVM_PARAM_CALLBACK_IRQ. KVM handles the former and sets the kernel's long_mode flag accordingly. The latter will be handled in userspace. Keep them in sync by noticing when a hypercall is made in a mode that doesn't match qemu's idea of the guest mode, and resyncing from the kernel. Do that same sync right before serialization too, in case the guest has set the hypercall page but hasn't yet made a system call. Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Reviewed-by: Paul Durrant <paul@xen.org>
Diffstat (limited to 'target/i386')
-rw-r--r--target/i386/kvm/xen-emu.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c
index ebea27c..be6d85f 100644
--- a/target/i386/kvm/xen-emu.c
+++ b/target/i386/kvm/xen-emu.c
@@ -20,6 +20,8 @@
#include "trace.h"
#include "sysemu/runstate.h"
+#include "hw/i386/kvm/xen_overlay.h"
+
#include "hw/xen/interface/version.h"
#include "hw/xen/interface/sched.h"
@@ -282,6 +284,16 @@ int kvm_xen_handle_exit(X86CPU *cpu, struct kvm_xen_exit *exit)
return -1;
}
+ /*
+ * The kernel latches the guest 32/64 mode when the MSR is used to fill
+ * the hypercall page. So if we see a hypercall in a mode that doesn't
+ * match our own idea of the guest mode, fetch the kernel's idea of the
+ * "long mode" to remain in sync.
+ */
+ if (exit->u.hcall.longmode != xen_is_long_mode()) {
+ xen_sync_long_mode();
+ }
+
if (!do_kvm_xen_handle_exit(cpu, exit)) {
/*
* Some hypercalls will be deliberately "implemented" by returning