* [PATCH qemu v5 1/1] Honor guest PAT on x86, absent Bochs display
2025-08-17 5:55 [PATCH qemu v5 0/1] Honor guest PAT on x86, absent Bochs display ~myrslint
@ 2025-08-17 5:37 ` ~myrslint
2025-10-09 4:03 ` Dmitry Osipenko
0 siblings, 1 reply; 3+ messages in thread
From: ~myrslint @ 2025-08-17 5:37 UTC (permalink / raw)
To: qemu-devel; +Cc: Paolo Bonzini, Gerd Hoffmann
From: myrslint <qemu.haziness801@passinbox.com>
On x86_64, where most CPUs support self-snoop, it is preferrable to
always honor guest PAT. Not doing so is a quirk. There is a default
enabled KVM quirk flag which enforces not doing so due to a former bug
in Bochs display driver.
The bug has been fixed but not enough has yet passed since so we only
disable said quirk flag if a Bochs display is not configured for the
virtual machine.
This commit also moves around a bit of code that would be called when
the initialization of a VM is done.
---
hw/display/bochs-display.c | 4 +++
include/system/kvm.h | 1 +
target/i386/kvm/kvm.c | 52 ++++++++++++++++++++++++++++++++------
3 files changed, 49 insertions(+), 8 deletions(-)
diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c
index ad2821c974..4059373df3 100644
--- a/hw/display/bochs-display.c
+++ b/hw/display/bochs-display.c
@@ -20,6 +20,8 @@
#include "ui/qemu-pixman.h"
#include "qom/object.h"
+#include "system/kvm.h"
+
typedef struct BochsDisplayMode {
pixman_format_code_t format;
uint32_t bytepp;
@@ -309,6 +311,8 @@ static void bochs_display_realize(PCIDevice *dev, Error **errp)
}
memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
+
+ kvm_hack_do_not_enable_guest_pat();
}
static bool bochs_display_get_big_endian_fb(Object *obj, Error **errp)
diff --git a/include/system/kvm.h b/include/system/kvm.h
index 3c7d314736..c6ba3905dc 100644
--- a/include/system/kvm.h
+++ b/include/system/kvm.h
@@ -208,6 +208,7 @@ void kvm_close(void);
*/
bool kvm_arm_supports_user_irq(void);
+void kvm_hack_do_not_enable_guest_pat(void);
int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
int kvm_on_sigbus(int code, void *addr);
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 369626f8c8..0f8af92962 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -188,6 +188,8 @@ static KVMMSRHandlers msr_handlers[KVM_MSR_FILTER_MAX_RANGES];
static RateLimit bus_lock_ratelimit_ctrl;
static int kvm_get_one_msr(X86CPU *cpu, int index, uint64_t *value);
+bool kvm_has_bochs_drm = false;
+
static const char *vm_type_name[] = {
[KVM_X86_DEFAULT_VM] = "default",
[KVM_X86_SEV_VM] = "SEV",
@@ -2696,13 +2698,13 @@ static bool kvm_rdmsr_pkg_energy_status(X86CPU *cpu,
return true;
}
-static Notifier smram_machine_done;
+static Notifier kvm_machine_done;
static KVMMemoryListener smram_listener;
static AddressSpace smram_address_space;
static MemoryRegion smram_as_root;
static MemoryRegion smram_as_mem;
-static void register_smram_listener(Notifier *n, void *unused)
+static void register_smram_listener(void)
{
MemoryRegion *smram =
(MemoryRegion *) object_resolve_path("/machine/smram", NULL);
@@ -2730,6 +2732,44 @@ static void register_smram_listener(Notifier *n, void *unused)
&smram_address_space, 1, "kvm-smram");
}
+void kvm_hack_do_not_enable_guest_pat(void)
+{
+ kvm_has_bochs_drm = true;
+}
+
+static bool kvm_x86_smm_enabled(void)
+{
+ return kvm_has_smm() &&
+ object_dynamic_cast(OBJECT(current_machine), TYPE_X86_MACHINE) &&
+ x86_machine_is_smm_enabled(X86_MACHINE(current_machine));
+}
+
+static int kvm_x86_disable_quirsk2_mask(void)
+{
+ return kvm_check_extension(kvm_state, KVM_CAP_DISABLE_QUIRKS2);
+}
+
+static int kvm_disable_ignore_guest_pat(void)
+{
+ return kvm_vm_enable_cap(kvm_state, KVM_CAP_DISABLE_QUIRKS2, 0, \
+ KVM_X86_QUIRK_IGNORE_GUEST_PAT);
+}
+
+static void handle_machine_done(Notifier *n, void *unused)
+{
+ if (kvm_x86_smm_enabled()) {
+ register_smram_listener();
+ }
+ if (!kvm_has_bochs_drm && \
+ (kvm_x86_disable_quirsk2_mask() & KVM_X86_QUIRK_IGNORE_GUEST_PAT)) {
+ if (kvm_disable_ignore_guest_pat()) {
+ error_report("KVM_X86_QUIRK_IGNORE_GUEST_PAT available and "
+ "modifiable but we failed to disable it\n");
+ }
+ }
+}
+
+
static void *kvm_msr_energy_thread(void *data)
{
KVMState *s = data;
@@ -3310,12 +3350,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
return ret;
}
- if (kvm_check_extension(s, KVM_CAP_X86_SMM) &&
- object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE) &&
- x86_machine_is_smm_enabled(X86_MACHINE(ms))) {
- smram_machine_done.notify = register_smram_listener;
- qemu_add_machine_init_done_notifier(&smram_machine_done);
- }
+ kvm_machine_done.notify = handle_machine_done;
+ qemu_add_machine_init_done_notifier(&kvm_machine_done);
if (enable_cpu_pm) {
ret = kvm_vm_enable_disable_exits(s);
--
2.49.1
^ permalink raw reply related [flat|nested] 3+ messages in thread