From: myrslint <qemu.haziness...@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