Forked from tezeta/Add-hide-hypervisor-QMP-command.patch
Created
July 14, 2022 19:26
-
-
Save RigoLigoRLC/b3a5fe627e149daed96eb4c4db7e5a0f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Update note: Linux kernel commit feb627e8d6f69c9a319fe279710959efb3eba873 | |
breaks this patch and will need to be reverted in order for this to work on | |
kernels starting with 5.16. | |
From 28e67537895c4b46b9721f19609ee4f2ccb8c132 Mon Sep 17 00:00:00 2001 | |
From: pi <[email protected]> | |
Date: Sat, 7 Nov 2020 18:41:42 +0100 | |
Subject: [PATCH] Add 'hide-hypervisor' QMP command | |
CAUTION: Extremely hacky stuff below. Use at own risk of bugs, breakage and | |
bear attacks. | |
Introduce a new QMP call to disable the hypervisor CPUID flag at runtime on | |
x86 KVM. Allows the guest OS to initialize with full hypervisor/PV support | |
while allowing broken guest applications that require a bare metal machine | |
to function. Enable 'hypervisor' flag on boot command, then wait for guest | |
boot, then run 'hide-hypervisor' via QMP. Might break guests that depend on | |
CPUID never changing at runtime, as is the case on real hardware (excluding | |
microcode updates, which are magic anyway). | |
--- | |
diff --color -Naur qemu-6.1.0-orig/hw/core/machine-qmp-cmds.c qemu-6.1.0/hw/core/machine-qmp-cmds.c | |
--- qemu-6.1.0-orig/hw/core/machine-qmp-cmds.c 2021-12-24 20:10:34.724541848 -0500 | |
+++ qemu-6.1.0/hw/core/machine-qmp-cmds.c 2021-12-24 20:11:32.218538421 -0500 | |
@@ -21,6 +21,45 @@ | |
#include "sysemu/hw_accel.h" | |
#include "sysemu/numa.h" | |
#include "sysemu/runstate.h" | |
+#include "sysemu/cpus.h" | |
+#include <linux/kvm.h> | |
+ | |
+void qmp_hide_hypervisor(Error **errp) | |
+{ | |
+ int32_t r; | |
+ CPUState *cpu; | |
+#if defined(TARGET_I386) | |
+ pause_all_vcpus(); | |
+ | |
+ CPU_FOREACH(cpu) { | |
+ X86CPU *x86_cpu = X86_CPU(cpu); | |
+ cpu_synchronize_state(cpu); | |
+ | |
+ struct { | |
+ struct kvm_cpuid2 cpuid; | |
+ struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES]; | |
+ } *cpuid_data = x86_cpu->cpuid_data; | |
+ | |
+ for (int32_t i = 0; i < cpuid_data->cpuid.nent; i++) { | |
+ struct kvm_cpuid_entry2 *entry = &cpuid_data->entries[i]; | |
+ | |
+ if (entry->function == 1) { | |
+ /* eax is 1, unset hypervisor bit */ | |
+ entry->ecx &= ~CPUID_EXT_HYPERVISOR; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ r = kvm_vcpu_ioctl(cpu, KVM_SET_CPUID2, cpuid_data); | |
+ if (r) { | |
+ error_setg(errp, "KVM_SET_CPUID2 error"); | |
+ break; | |
+ } | |
+ } | |
+ | |
+ resume_all_vcpus(); | |
+#endif | |
+} | |
static void cpustate_to_cpuinfo_s390(CpuInfoS390 *info, const CPUState *cpu) | |
{ | |
diff --color -Naur qemu-6.1.0-orig/qapi/machine.json qemu-6.1.0/qapi/machine.json | |
--- qemu-6.1.0-orig/qapi/machine.json 2021-12-24 20:10:34.774541845 -0500 | |
+++ qemu-6.1.0/qapi/machine.json 2021-12-24 20:10:52.998540759 -0500 | |
@@ -962,6 +962,14 @@ | |
## | |
{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'], | |
'allow-preconfig': true } | |
+## | |
+# @hide-hypervisor: | |
+# | |
+# Hides the 'hypervisor' cpuid flag on all vCPUs at runtime. | |
+## | |
+{ | |
+ 'command': 'hide-hypervisor' | |
+} | |
## | |
# @set-numa-node: | |
diff --color -Naur qemu-6.1.0-orig/target/i386/cpu.h qemu-6.1.0/target/i386/cpu.h | |
--- qemu-6.1.0-orig/target/i386/cpu.h 2021-12-24 20:10:34.843541841 -0500 | |
+++ qemu-6.1.0/target/i386/cpu.h 2021-12-24 20:10:52.999540759 -0500 | |
@@ -26,6 +26,8 @@ | |
#include "exec/cpu-defs.h" | |
#include "qapi/qapi-types-common.h" | |
+#define KVM_MAX_CPUID_ENTRIES 100 | |
+ | |
/* The x86 has a strong memory model with some store-after-load re-ordering */ | |
#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) | |
@@ -1800,6 +1802,8 @@ | |
int32_t thread_id; | |
int32_t hv_max_vps; | |
+ | |
+ void *cpuid_data; | |
}; | |
diff --color -Naur qemu-6.1.0-orig/target/i386/kvm/kvm.c qemu-6.1.0/target/i386/kvm/kvm.c | |
--- qemu-6.1.0-orig/target/i386/kvm/kvm.c 2021-12-24 20:10:34.843541841 -0500 | |
+++ qemu-6.1.0/target/i386/kvm/kvm.c 2021-12-24 20:10:52.999540759 -0500 | |
@@ -1538,8 +1538,6 @@ | |
static Error *invtsc_mig_blocker; | |
-#define KVM_MAX_CPUID_ENTRIES 100 | |
- | |
int kvm_arch_init_vcpu(CPUState *cs) | |
{ | |
struct { | |
@@ -1919,6 +1917,10 @@ | |
cpuid_data.cpuid.nent = cpuid_i; | |
cpuid_data.cpuid.padding = 0; | |
+ | |
+ cpu->cpuid_data = malloc(sizeof(cpuid_data)); | |
+ memcpy(cpu->cpuid_data, &cpuid_data, sizeof(cpuid_data)); | |
+ | |
r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data); | |
if (r) { | |
goto fail; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment