@@ -18,6 +18,7 @@
#CONFIG_QXL=n
#CONFIG_SEV=n
#CONFIG_SGA=n
+#CONFIG_TDX=n
#CONFIG_TEST_DEVICES=n
#CONFIG_TPM_CRB=n
#CONFIG_TPM_TIS_ISA=n
@@ -2,6 +2,10 @@ config SEV
bool
depends on KVM
+config TDX
+ bool
+ depends on KVM
+
config PC
bool
imply APPLESMC
@@ -17,6 +21,7 @@ config PC
imply PVPANIC_ISA
imply QXL
imply SEV
+ imply TDX
imply SGA
imply TEST_DEVICES
imply TPM_CRB
@@ -21,6 +21,7 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include <linux/kvm.h>
#include "qemu/error-report.h"
#include "qemu/option.h"
#include "qemu/cutils.h"
@@ -31,6 +32,7 @@
#include "qapi/qmp/qerror.h"
#include "qapi/qapi-visit-common.h"
#include "qapi/visitor.h"
+#include "sysemu/kvm_int.h"
#include "sysemu/qtest.h"
#include "sysemu/whpx.h"
#include "sysemu/numa.h"
@@ -1199,6 +1201,43 @@ static void x86_machine_set_acpi(Object *obj, Visitor *v, const char *name,
visit_type_OnOffAuto(v, name, &x86ms->acpi, errp);
}
+static char *x86_get_kvm_type(Object *obj, Error **errp)
+{
+ X86MachineState *x86ms = X86_MACHINE(obj);
+
+ return g_strdup(x86ms->kvm_type);
+}
+
+
+static void x86_set_kvm_type(Object *obj, const char *value, Error **errp)
+{
+ X86MachineState *x86ms = X86_MACHINE(obj);
+
+ g_free(x86ms->kvm_type);
+ x86ms->kvm_type = g_strdup(value);
+}
+
+static int x86_kvm_type(MachineState *ms, const char *vm_type)
+{
+ int kvm_type;
+
+ if (!vm_type || !strcmp(vm_type, "") ||
+ !g_ascii_strcasecmp(vm_type, "legacy")) {
+ kvm_type = KVM_X86_LEGACY_VM;
+ } else if (!g_ascii_strcasecmp(vm_type, "tdx")) {
+ kvm_type = KVM_X86_TDX_VM;
+ } else {
+ error_report("Unknown kvm-type specified '%s'", vm_type);
+ exit(1);
+ }
+ if (kvm_set_vm_type(ms, kvm_type)) {
+ error_report("kvm-type '%s' not supported by KVM", vm_type);
+ exit(1);
+ }
+
+ return kvm_type;
+}
+
static void x86_machine_initfn(Object *obj)
{
X86MachineState *x86ms = X86_MACHINE(obj);
@@ -1207,6 +1246,12 @@ static void x86_machine_initfn(Object *obj)
x86ms->acpi = ON_OFF_AUTO_AUTO;
x86ms->smp_dies = 1;
x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS;
+
+
+ object_property_add_str(obj, "kvm-type",
+ x86_get_kvm_type, x86_set_kvm_type);
+ object_property_set_description(obj, "kvm-type",
+ "KVM guest type (legacy, tdx)");
}
static void x86_machine_class_init(ObjectClass *oc, void *data)
@@ -1218,6 +1263,7 @@ static void x86_machine_class_init(ObjectClass *oc, void *data)
mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
+ mc->kvm_type = x86_kvm_type;
x86mc->compat_apic_id_mode = false;
x86mc->save_tsc_khz = true;
nc->nmi_monitor_handler = x86_nmi;
@@ -56,6 +56,7 @@ struct X86MachineState {
/* RAM information (sizes, addresses, configuration): */
ram_addr_t below_4g_mem_size, above_4g_mem_size;
+ char *kvm_type;
/* CPU and apic information: */
bool apic_xrupt_override;
new file mode 100644
@@ -0,0 +1,10 @@
+#ifndef QEMU_TDX_H
+#define QEMU_TDX_H
+
+#ifndef CONFIG_USER_ONLY
+#include "sysemu/kvm.h"
+
+bool kvm_has_tdx(KVMState *s);
+#endif
+
+#endif
@@ -39,3 +39,8 @@ bool kvm_hv_vpindex_settable(void)
{
return false;
}
+
+int kvm_set_vm_type(MachineState *ms, int kvm_type)
+{
+ return 0;
+}
@@ -26,6 +26,7 @@
#include "sysemu/hw_accel.h"
#include "sysemu/kvm_int.h"
#include "sysemu/runstate.h"
+#include "sysemu/tdx.h"
#include "kvm_i386.h"
#include "hyperv.h"
#include "hyperv-proto.h"
@@ -129,6 +130,20 @@ static bool has_msr_mcg_ext_ctl;
static struct kvm_cpuid2 *cpuid_cache;
static struct kvm_msr_list *kvm_feature_msrs;
+static int vm_type;
+
+int kvm_set_vm_type(MachineState *ms, int kvm_type)
+{
+ if (kvm_type == KVM_X86_LEGACY_VM ||
+ (kvm_type == KVM_X86_TDX_VM &&
+ kvm_has_tdx(KVM_STATE(ms->accelerator)))) {
+ vm_type = kvm_type;
+ return 0;
+ }
+
+ return -ENOTSUP;
+}
+
int kvm_has_pit_state2(void)
{
return has_pit_state2;
@@ -41,6 +41,7 @@ bool kvm_has_adjust_clock(void);
bool kvm_has_adjust_clock_stable(void);
bool kvm_has_exception_payload(void);
void kvm_synchronize_all_tsc(void);
+int kvm_set_vm_type(MachineState *ms, int kvm_type);
void kvm_arch_reset_vcpu(X86CPU *cs);
void kvm_arch_do_init_vcpu(X86CPU *cs);
@@ -1,3 +1,4 @@
i386_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
i386_softmmu_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
i386_softmmu_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
+i386_ss.add(when: 'CONFIG_TDX', if_true: files('tdx.c'), if_false: files('tdx-stub.c'))
new file mode 100644
@@ -0,0 +1,10 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "sysemu/tdx.h"
+
+#ifndef CONFIG_USER_ONLY
+bool kvm_has_tdx(KVMState *s)
+{
+ return false;
+}
+#endif
new file mode 100644
@@ -0,0 +1,30 @@
+/*
+ * QEMU TDX support
+ *
+ * Copyright Intel
+ *
+ * Author:
+ * Xiaoyao Li <xiaoyao.li@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include <linux/kvm.h>
+
+#include "cpu.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "qom/object_interfaces.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/kvm.h"
+#include "sysemu/kvm_int.h"
+#include "sysemu/tdx.h"
+
+bool kvm_has_tdx(KVMState *s)
+{
+ return !!(kvm_check_extension(s, KVM_CAP_VM_TYPES) & BIT(KVM_X86_TDX_VM));
+}