Last active
March 17, 2024 17:45
-
-
Save PiMaker/70d01cc27792418e8e14e9b2b442129c to your computer and use it in GitHub Desktop.
This file contains 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
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). | |
--- | |
hw/core/machine-qmp-cmds.c | 38 ++++++++++++++++++++++++++++++++++++++ | |
qapi/machine.json | 9 +++++++++ | |
target/i386/cpu.h | 4 ++++ | |
target/i386/kvm.c | 6 ++++-- | |
4 files changed, 55 insertions(+), 2 deletions(-) | |
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c | |
index 963088b798..6c571a5af1 100644 | |
--- a/hw/core/machine-qmp-cmds.c | |
+++ b/hw/core/machine-qmp-cmds.c | |
@@ -23,6 +23,44 @@ | |
#include "sysemu/numa.h" | |
#include "sysemu/runstate.h" | |
#include "sysemu/sysemu.h" | |
+#include "sysemu/cpus.h" | |
+#include <linux/kvm.h> | |
+ | |
+void qmp_hide_hypervisor(Error **errp) | |
+{ | |
+ int32_t r; | |
+ CPUState *cpu; | |
+ | |
+ 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(); | |
+} | |
CpuInfoList *qmp_query_cpus(Error **errp) | |
{ | |
diff --git a/qapi/machine.json b/qapi/machine.json | |
index 481b1f07ec..b256a17846 100644 | |
--- a/qapi/machine.json | |
+++ b/qapi/machine.json | |
@@ -934,3 +934,12 @@ | |
'data': 'NumaOptions', | |
'allow-preconfig': true | |
} | |
+ | |
+## | |
+# @hide-hypervisor: | |
+# | |
+# Hides the 'hypervisor' cpuid flag on all vCPUs at runtime. | |
+## | |
+{ | |
+ 'command': 'hide-hypervisor' | |
+} | |
diff --git a/target/i386/cpu.h b/target/i386/cpu.h | |
index e1a5c174dc..5bc79c2bce 100644 | |
--- a/target/i386/cpu.h | |
+++ b/target/i386/cpu.h | |
@@ -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) | |
@@ -1759,6 +1761,8 @@ struct X86CPU { | |
int32_t thread_id; | |
int32_t hv_max_vps; | |
+ | |
+ void *cpuid_data; | |
}; | |
diff --git a/target/i386/kvm.c b/target/i386/kvm.c | |
index f305474058..faa2c61d86 100644 | |
--- a/target/i386/kvm.c | |
+++ b/target/i386/kvm.c | |
@@ -1456,8 +1456,6 @@ static int hyperv_init_vcpu(X86CPU *cpu) | |
static Error *invtsc_mig_blocker; | |
-#define KVM_MAX_CPUID_ENTRIES 100 | |
- | |
int kvm_arch_init_vcpu(CPUState *cs) | |
{ | |
struct { | |
@@ -1822,6 +1820,10 @@ int kvm_arch_init_vcpu(CPUState *cs) | |
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; | |
-- | |
2.29.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
make sure to configure with
../configure --target-list=x86_64-softmmu
so it doesn't try to build all targets and fail.