Skip to content

Instantly share code, notes, and snippets.

@PiMaker
Last active March 17, 2024 17:45
Show Gist options
  • Save PiMaker/70d01cc27792418e8e14e9b2b442129c to your computer and use it in GitHub Desktop.
Save PiMaker/70d01cc27792418e8e14e9b2b442129c to your computer and use it in GitHub Desktop.
From 28e67537895c4b46b9721f19609ee4f2ccb8c132 Mon Sep 17 00:00:00 2001
From: pi <secret@hidden.mail>
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
@LWSS
Copy link

LWSS commented Feb 12, 2021

make sure to configure with ../configure --target-list=x86_64-softmmu so it doesn't try to build all targets and fail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment