forked from rpms/qemu-kvm
Compare commits
No commits in common. 'i10c-beta' and 'c9' have entirely different histories.
@ -0,0 +1,544 @@
|
|||||||
|
From fb905dbe5b51ed899062ef99a2dd7f238d3e3384 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
Date: Fri, 19 Oct 2018 13:27:13 +0200
|
||||||
|
Subject: Add ppc64 machine types
|
||||||
|
|
||||||
|
Adding changes to add RHEL machine types for ppc64 architecture.
|
||||||
|
|
||||||
|
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
|
||||||
|
Rebase notes (6.2.0):
|
||||||
|
- Fixed rebase conflict relicts
|
||||||
|
- Update machine type compat for 6.2 (from MR 66)
|
||||||
|
|
||||||
|
Merged patches (6.1.0):
|
||||||
|
- c438c25ac3 redhat: Define pseries-rhel8.5.0 machine type
|
||||||
|
- a3995e2eff Remove RHEL 7.0.0 machine type (only ppc64 changes)
|
||||||
|
- ad3190a79b Remove RHEL 7.1.0 machine type (only ppc64 changes)
|
||||||
|
- 84bbe15d4e Remove RHEL 7.2.0 machine type (only ppc64 changes)
|
||||||
|
- 0215eb3356 Remove RHEL 7.3.0 machine types (only ppc64 changes)
|
||||||
|
- af69d1ca6e Remove RHEL 7.4.0 machine types (only ppc64 changes)
|
||||||
|
- 8f7a74ab78 Remove RHEL 7.5.0 machine types (only ppc64 changes)
|
||||||
|
|
||||||
|
Merged patches (7.1.0):
|
||||||
|
- baa6790171 target/ppc/cpu-models: Fix ppc_cpu_aliases list for RHEL
|
||||||
|
---
|
||||||
|
hw/ppc/spapr.c | 243 ++++++++++++++++++++++++++++++++++++++++
|
||||||
|
hw/ppc/spapr_cpu_core.c | 13 +++
|
||||||
|
include/hw/ppc/spapr.h | 4 +
|
||||||
|
target/ppc/compat.c | 13 ++-
|
||||||
|
target/ppc/cpu-models.c | 1 +
|
||||||
|
target/ppc/cpu.h | 1 +
|
||||||
|
target/ppc/kvm.c | 27 +++++
|
||||||
|
target/ppc/kvm_ppc.h | 13 +++
|
||||||
|
8 files changed, 314 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
|
||||||
|
index e9bc97fee0..a258d81846 100644
|
||||||
|
--- a/hw/ppc/spapr.c
|
||||||
|
+++ b/hw/ppc/spapr.c
|
||||||
|
@@ -1718,6 +1718,9 @@ static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||||
|
pef_kvm_reset(machine->cgs, &error_fatal);
|
||||||
|
spapr_caps_apply(spapr);
|
||||||
|
spapr_nested_reset(spapr);
|
||||||
|
+ if (spapr->svm_allowed) {
|
||||||
|
+ kvmppc_svm_allow(&error_fatal);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
first_ppc_cpu = POWERPC_CPU(first_cpu);
|
||||||
|
if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
|
||||||
|
@@ -3421,6 +3424,20 @@ static void spapr_set_host_serial(Object *obj, const char *value, Error **errp)
|
||||||
|
spapr->host_serial = g_strdup(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool spapr_get_svm_allowed(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||||
|
+
|
||||||
|
+ return spapr->svm_allowed;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void spapr_set_svm_allowed(Object *obj, bool value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||||
|
+
|
||||||
|
+ spapr->svm_allowed = value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void spapr_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
|
||||||
|
@@ -3499,6 +3516,12 @@ static void spapr_instance_init(Object *obj)
|
||||||
|
spapr_get_host_serial, spapr_set_host_serial);
|
||||||
|
object_property_set_description(obj, "host-serial",
|
||||||
|
"Host serial number to advertise in guest device tree");
|
||||||
|
+ object_property_add_bool(obj, "x-svm-allowed",
|
||||||
|
+ spapr_get_svm_allowed,
|
||||||
|
+ spapr_set_svm_allowed);
|
||||||
|
+ object_property_set_description(obj, "x-svm-allowed",
|
||||||
|
+ "Allow the guest to become a Secure Guest"
|
||||||
|
+ " (experimental only)");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spapr_machine_finalizefn(Object *obj)
|
||||||
|
@@ -4754,6 +4777,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
vmc->client_architecture_support = spapr_vof_client_architecture_support;
|
||||||
|
vmc->quiesce = spapr_vof_quiesce;
|
||||||
|
vmc->setprop = spapr_vof_setprop;
|
||||||
|
+ smc->has_power9_support = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo spapr_machine_info = {
|
||||||
|
@@ -4805,6 +4829,7 @@ static void spapr_machine_latest_class_options(MachineClass *mc)
|
||||||
|
} \
|
||||||
|
type_init(spapr_machine_register_##suffix)
|
||||||
|
|
||||||
|
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||||
|
/*
|
||||||
|
* pseries-9.0
|
||||||
|
*/
|
||||||
|
@@ -4998,6 +5023,7 @@ static void spapr_machine_4_1_class_options(MachineClass *mc)
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_SPAPR_MACHINE(4_1, "4.1", false);
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pseries-4.0
|
||||||
|
@@ -5013,6 +5039,8 @@ static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||||
|
static void spapr_machine_4_0_class_options(MachineClass *mc)
|
||||||
|
{
|
||||||
|
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
@@ -5338,6 +5366,221 @@ static void spapr_machine_2_1_class_options(MachineClass *mc)
|
||||||
|
compat_props_add(mc->compat_props, hw_compat_2_1, hw_compat_2_1_len);
|
||||||
|
}
|
||||||
|
DEFINE_SPAPR_MACHINE(2_1, "2.1", false);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel_default_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * Defaults for the latest behaviour inherited from the base class
|
||||||
|
+ * can be overriden here for all pseries-rhel* machines.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+ /* Maximum supported VCPU count */
|
||||||
|
+ mc->max_cpus = 384;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel8.5.0
|
||||||
|
+ * like pseries-6.0
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel850_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
+
|
||||||
|
+ /* The default machine type must apply the RHEL specific defaults */
|
||||||
|
+ spapr_machine_rhel_default_class_options(mc);
|
||||||
|
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_5,
|
||||||
|
+ hw_compat_rhel_8_5_len);
|
||||||
|
+ smc->pre_6_2_numa_affinity = true;
|
||||||
|
+ mc->smp_props.prefer_sockets = true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel850, "rhel8.5.0", true);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel8.4.0
|
||||||
|
+ * like pseries-5.2
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel840_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ spapr_machine_rhel850_class_options(mc);
|
||||||
|
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_4,
|
||||||
|
+ hw_compat_rhel_8_4_len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel840, "rhel8.4.0", false);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel8.3.0
|
||||||
|
+ * like pseries-5.1
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel830_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
+
|
||||||
|
+ spapr_machine_rhel840_class_options(mc);
|
||||||
|
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_3,
|
||||||
|
+ hw_compat_rhel_8_3_len);
|
||||||
|
+
|
||||||
|
+ /* from pseries-5.1 */
|
||||||
|
+ smc->pre_5_2_numa_associativity = true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel830, "rhel8.3.0", false);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel8.2.0
|
||||||
|
+ * like pseries-4.2 + pseries-5.0
|
||||||
|
+ * except SPAPR_CAP_CCF_ASSIST that has been backported to pseries-rhel8.1.0
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel820_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
+ /* from pseries-5.0 */
|
||||||
|
+ static GlobalProperty compat[] = {
|
||||||
|
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "pre-5.1-associativity", "on" },
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ spapr_machine_rhel830_class_options(mc);
|
||||||
|
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_2,
|
||||||
|
+ hw_compat_rhel_8_2_len);
|
||||||
|
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||||
|
+
|
||||||
|
+ /* from pseries-4.2 */
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_OFF;
|
||||||
|
+ smc->rma_limit = 16 * GiB;
|
||||||
|
+ mc->nvdimm_supported = false;
|
||||||
|
+
|
||||||
|
+ /* from pseries-5.0 */
|
||||||
|
+ mc->numa_mem_supported = true;
|
||||||
|
+ smc->pre_5_1_assoc_refpoints = true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel820, "rhel8.2.0", false);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel8.1.0
|
||||||
|
+ * like pseries-4.1
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel810_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
+ static GlobalProperty compat[] = {
|
||||||
|
+ /* Only allow 4kiB and 64kiB IOMMU pagesizes */
|
||||||
|
+ { TYPE_SPAPR_PCI_HOST_BRIDGE, "pgsz", "0x11000" },
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ spapr_machine_rhel820_class_options(mc);
|
||||||
|
+
|
||||||
|
+ /* from pseries-4.1 */
|
||||||
|
+ smc->linux_pci_probe = false;
|
||||||
|
+ smc->smp_threads_vsmt = false;
|
||||||
|
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_1,
|
||||||
|
+ hw_compat_rhel_8_1_len);
|
||||||
|
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||||
|
+
|
||||||
|
+ /* from pseries-4.2 */
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel810, "rhel8.1.0", false);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel8.0.0
|
||||||
|
+ * like pseries-3.1 and pseries-4.0
|
||||||
|
+ * except SPAPR_CAP_CFPC, SPAPR_CAP_SBBC and SPAPR_CAP_IBS
|
||||||
|
+ * that have been backported to pseries-rhel8.0.0
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel800_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
+
|
||||||
|
+ spapr_machine_rhel810_class_options(mc);
|
||||||
|
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_0,
|
||||||
|
+ hw_compat_rhel_8_0_len);
|
||||||
|
+
|
||||||
|
+ /* pseries-4.0 */
|
||||||
|
+ smc->phb_placement = phb_placement_4_0;
|
||||||
|
+ smc->irq = &spapr_irq_xics;
|
||||||
|
+ smc->pre_4_1_migration = true;
|
||||||
|
+
|
||||||
|
+ /* pseries-3.1 */
|
||||||
|
+ mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0");
|
||||||
|
+ smc->update_dt_enabled = false;
|
||||||
|
+ smc->dr_phb_enabled = false;
|
||||||
|
+ smc->broken_host_serial_model = true;
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_OFF;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel800, "rhel8.0.0", false);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel7.6.0
|
||||||
|
+ * like spapr_compat_2_12 and spapr_compat_3_0
|
||||||
|
+ * spapr_compat_0 is empty
|
||||||
|
+ */
|
||||||
|
+GlobalProperty spapr_compat_rhel7_6[] = {
|
||||||
|
+ { TYPE_POWERPC_CPU, "pre-3.0-migration", "on" },
|
||||||
|
+ { TYPE_SPAPR_CPU_CORE, "pre-3.0-migration", "on" },
|
||||||
|
+};
|
||||||
|
+const size_t spapr_compat_rhel7_6_len = G_N_ELEMENTS(spapr_compat_rhel7_6);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel760_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
+
|
||||||
|
+ spapr_machine_rhel800_class_options(mc);
|
||||||
|
+ compat_props_add(mc->compat_props, hw_compat_rhel_7_6, hw_compat_rhel_7_6_len);
|
||||||
|
+ compat_props_add(mc->compat_props, spapr_compat_rhel7_6, spapr_compat_rhel7_6_len);
|
||||||
|
+
|
||||||
|
+ /* from spapr_machine_3_0_class_options() */
|
||||||
|
+ smc->legacy_irq_allocation = true;
|
||||||
|
+ smc->nr_xirqs = 0x400;
|
||||||
|
+ smc->irq = &spapr_irq_xics_legacy;
|
||||||
|
+
|
||||||
|
+ /* from spapr_machine_2_12_class_options() */
|
||||||
|
+ /* We depend on kvm_enabled() to choose a default value for the
|
||||||
|
+ * hpt-max-page-size capability. Of course we can't do it here
|
||||||
|
+ * because this is too early and the HW accelerator isn't initialzed
|
||||||
|
+ * yet. Postpone this to machine init (see default_caps_with_cpu()).
|
||||||
|
+ */
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 0;
|
||||||
|
+
|
||||||
|
+ /* SPAPR_CAP_WORKAROUND enabled in pseries-rhel800 by
|
||||||
|
+ * f21757edc554
|
||||||
|
+ * "Enable mitigations by default for pseries-4.0 machine type")
|
||||||
|
+ */
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_BROKEN;
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel760, "rhel7.6.0", false);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * pseries-rhel7.6.0-sxxm
|
||||||
|
+ *
|
||||||
|
+ * pseries-rhel7.6.0 with speculative execution exploit mitigations enabled by default
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void spapr_machine_rhel760sxxm_class_options(MachineClass *mc)
|
||||||
|
+{
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||||
|
+
|
||||||
|
+ spapr_machine_rhel760_class_options(mc);
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_CFPC] = SPAPR_CAP_WORKAROUND;
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_WORKAROUND;
|
||||||
|
+ smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_FIXED_CCD;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+DEFINE_SPAPR_MACHINE(rhel760sxxm, "rhel7.6.0-sxxm", false);
|
||||||
|
|
||||||
|
static void spapr_machine_register_types(void)
|
||||||
|
{
|
||||||
|
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
|
||||||
|
index 3b0a47a28c..375e0c8e45 100644
|
||||||
|
--- a/hw/ppc/spapr_cpu_core.c
|
||||||
|
+++ b/hw/ppc/spapr_cpu_core.c
|
||||||
|
@@ -25,6 +25,7 @@
|
||||||
|
#include "sysemu/reset.h"
|
||||||
|
#include "sysemu/hw_accel.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
+#include "cpu-models.h"
|
||||||
|
|
||||||
|
static void spapr_reset_vcpu(PowerPCCPU *cpu)
|
||||||
|
{
|
||||||
|
@@ -264,6 +265,7 @@ static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||||
|
{
|
||||||
|
CPUPPCState *env = &cpu->env;
|
||||||
|
CPUState *cs = CPU(cpu);
|
||||||
|
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
|
||||||
|
|
||||||
|
if (!qdev_realize(DEVICE(cpu), NULL, errp)) {
|
||||||
|
return false;
|
||||||
|
@@ -280,6 +282,17 @@ static bool spapr_realize_vcpu(PowerPCCPU *cpu, SpaprMachineState *spapr,
|
||||||
|
/* Set time-base frequency to 512 MHz. vhyp must be set first. */
|
||||||
|
cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
|
||||||
|
|
||||||
|
+ if (!smc->has_power9_support &&
|
||||||
|
+ (((spapr->max_compat_pvr &&
|
||||||
|
+ ppc_compat_cmp(spapr->max_compat_pvr,
|
||||||
|
+ CPU_POWERPC_LOGICAL_3_00) >= 0)) ||
|
||||||
|
+ (!spapr->max_compat_pvr &&
|
||||||
|
+ ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_00, 0, 0)))) {
|
||||||
|
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||||
|
+ "POWER9 CPU is not supported by this machine class");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (spapr_irq_cpu_intc_create(spapr, cpu, errp) < 0) {
|
||||||
|
qdev_unrealize(DEVICE(cpu));
|
||||||
|
return false;
|
||||||
|
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
|
||||||
|
index 4aaf23d28f..3233c54d11 100644
|
||||||
|
--- a/include/hw/ppc/spapr.h
|
||||||
|
+++ b/include/hw/ppc/spapr.h
|
||||||
|
@@ -157,6 +157,7 @@ struct SpaprMachineClass {
|
||||||
|
bool pre_5_2_numa_associativity;
|
||||||
|
bool pre_6_2_numa_affinity;
|
||||||
|
|
||||||
|
+ bool has_power9_support;
|
||||||
|
bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
|
||||||
|
uint64_t *buid, hwaddr *pio,
|
||||||
|
hwaddr *mmio32, hwaddr *mmio64,
|
||||||
|
@@ -259,6 +260,9 @@ struct SpaprMachineState {
|
||||||
|
/* Set by -boot */
|
||||||
|
char *boot_device;
|
||||||
|
|
||||||
|
+ /* Secure Guest support via x-svm-allowed */
|
||||||
|
+ bool svm_allowed;
|
||||||
|
+
|
||||||
|
/*< public >*/
|
||||||
|
char *kvm_type;
|
||||||
|
char *host_model;
|
||||||
|
diff --git a/target/ppc/compat.c b/target/ppc/compat.c
|
||||||
|
index ebef2cccec..ff2c00c60e 100644
|
||||||
|
--- a/target/ppc/compat.c
|
||||||
|
+++ b/target/ppc/compat.c
|
||||||
|
@@ -114,8 +114,19 @@ static const CompatInfo *compat_by_pvr(uint32_t pvr)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
+long ppc_compat_cmp(uint32_t pvr1, uint32_t pvr2)
|
||||||
|
+{
|
||||||
|
+ const CompatInfo *compat1 = compat_by_pvr(pvr1);
|
||||||
|
+ const CompatInfo *compat2 = compat_by_pvr(pvr2);
|
||||||
|
+
|
||||||
|
+ g_assert(compat1);
|
||||||
|
+ g_assert(compat2);
|
||||||
|
+
|
||||||
|
+ return compat1 - compat2;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static bool pcc_compat(PowerPCCPUClass *pcc, uint32_t compat_pvr,
|
||||||
|
- uint32_t min_compat_pvr, uint32_t max_compat_pvr)
|
||||||
|
+ uint32_t min_compat_pvr, uint32_t max_compat_pvr)
|
||||||
|
{
|
||||||
|
const CompatInfo *compat = compat_by_pvr(compat_pvr);
|
||||||
|
const CompatInfo *min = compat_by_pvr(min_compat_pvr);
|
||||||
|
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
|
||||||
|
index f77ebfcc81..18e9422006 100644
|
||||||
|
--- a/target/ppc/cpu-models.c
|
||||||
|
+++ b/target/ppc/cpu-models.c
|
||||||
|
@@ -744,6 +744,7 @@
|
||||||
|
/* PowerPC CPU aliases */
|
||||||
|
|
||||||
|
PowerPCCPUAlias ppc_cpu_aliases[] = {
|
||||||
|
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||||
|
{ "405", "405d4" },
|
||||||
|
{ "405cr", "405crc" },
|
||||||
|
{ "405gp", "405gpd" },
|
||||||
|
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
|
||||||
|
index 67e6b2effd..11187aeb93 100644
|
||||||
|
--- a/target/ppc/cpu.h
|
||||||
|
+++ b/target/ppc/cpu.h
|
||||||
|
@@ -1655,6 +1655,7 @@ static inline int ppc_env_mmu_index(CPUPPCState *env, bool ifetch)
|
||||||
|
|
||||||
|
/* Compatibility modes */
|
||||||
|
#if defined(TARGET_PPC64)
|
||||||
|
+long ppc_compat_cmp(uint32_t pvr1, uint32_t pvr2);
|
||||||
|
bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr,
|
||||||
|
uint32_t min_compat_pvr, uint32_t max_compat_pvr);
|
||||||
|
bool ppc_type_check_compat(const char *cputype, uint32_t compat_pvr,
|
||||||
|
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
|
||||||
|
index 8231feb2d4..59f640cf7b 100644
|
||||||
|
--- a/target/ppc/kvm.c
|
||||||
|
+++ b/target/ppc/kvm.c
|
||||||
|
@@ -89,6 +89,7 @@ static int cap_large_decr;
|
||||||
|
static int cap_fwnmi;
|
||||||
|
static int cap_rpt_invalidate;
|
||||||
|
static int cap_ail_mode_3;
|
||||||
|
+static int cap_ppc_secure_guest;
|
||||||
|
|
||||||
|
static uint32_t debug_inst_opcode;
|
||||||
|
|
||||||
|
@@ -141,6 +142,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||||
|
cap_resize_hpt = kvm_vm_check_extension(s, KVM_CAP_SPAPR_RESIZE_HPT);
|
||||||
|
kvmppc_get_cpu_characteristics(s);
|
||||||
|
cap_ppc_nested_kvm_hv = kvm_vm_check_extension(s, KVM_CAP_PPC_NESTED_HV);
|
||||||
|
+ cap_ppc_secure_guest = kvm_vm_check_extension(s, KVM_CAP_PPC_SECURE_GUEST);
|
||||||
|
cap_large_decr = kvmppc_get_dec_bits();
|
||||||
|
cap_fwnmi = kvm_vm_check_extension(s, KVM_CAP_PPC_FWNMI);
|
||||||
|
/*
|
||||||
|
@@ -2564,6 +2566,16 @@ bool kvmppc_supports_ail_3(void)
|
||||||
|
return cap_ail_mode_3;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool kvmppc_has_cap_secure_guest(void)
|
||||||
|
+{
|
||||||
|
+ return !!cap_ppc_secure_guest;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int kvmppc_enable_cap_secure_guest(void)
|
||||||
|
+{
|
||||||
|
+ return kvm_vm_enable_cap(kvm_state, KVM_CAP_PPC_SECURE_GUEST, 0, 1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void)
|
||||||
|
{
|
||||||
|
uint32_t host_pvr = mfpvr();
|
||||||
|
@@ -2964,3 +2976,18 @@ bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
void kvm_arch_accel_class_init(ObjectClass *oc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void kvmppc_svm_allow(Error **errp)
|
||||||
|
+{
|
||||||
|
+ if (!kvm_enabled()) {
|
||||||
|
+ error_setg(errp, "No PEF support in tcg, try x-svm-allowed=off");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!kvmppc_has_cap_secure_guest()) {
|
||||||
|
+ error_setg(errp, "KVM implementation does not support secure guests, "
|
||||||
|
+ "try x-svm-allowed=off");
|
||||||
|
+ } else if (kvmppc_enable_cap_secure_guest() < 0) {
|
||||||
|
+ error_setg(errp, "Error enabling x-svm-allowed, try x-svm-allowed=off");
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
|
||||||
|
index 1975fb5ee6..d1017f98be 100644
|
||||||
|
--- a/target/ppc/kvm_ppc.h
|
||||||
|
+++ b/target/ppc/kvm_ppc.h
|
||||||
|
@@ -46,6 +46,7 @@ int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu);
|
||||||
|
target_ulong kvmppc_configure_v3_mmu(PowerPCCPU *cpu,
|
||||||
|
bool radix, bool gtse,
|
||||||
|
uint64_t proc_tbl);
|
||||||
|
+void kvmppc_svm_allow(Error **errp);
|
||||||
|
bool kvmppc_spapr_use_multitce(void);
|
||||||
|
int kvmppc_spapr_enable_inkernel_multitce(void);
|
||||||
|
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
|
||||||
|
@@ -79,6 +80,8 @@ int kvmppc_enable_cap_large_decr(PowerPCCPU *cpu, int enable);
|
||||||
|
int kvmppc_has_cap_rpt_invalidate(void);
|
||||||
|
bool kvmppc_supports_ail_3(void);
|
||||||
|
int kvmppc_enable_hwrng(void);
|
||||||
|
+bool kvmppc_has_cap_secure_guest(void);
|
||||||
|
+int kvmppc_enable_cap_secure_guest(void);
|
||||||
|
int kvmppc_put_books_sregs(PowerPCCPU *cpu);
|
||||||
|
PowerPCCPUClass *kvm_ppc_get_host_cpu_class(void);
|
||||||
|
void kvmppc_check_papr_resize_hpt(Error **errp);
|
||||||
|
@@ -427,6 +430,16 @@ static inline bool kvmppc_supports_ail_3(void)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline bool kvmppc_has_cap_secure_guest(void)
|
||||||
|
+{
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int kvmppc_enable_cap_secure_guest(void)
|
||||||
|
+{
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static inline int kvmppc_enable_hwrng(void)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,8 +1,17 @@
|
|||||||
From 7bc7a2d39bb2c00bcc8e573f05e629f5f21edc35 Mon Sep 17 00:00:00 2001
|
From b467dc6a24ef41fa574260429807711f6802a54d Mon Sep 17 00:00:00 2001
|
||||||
From: Eduardo Habkost <ehabkost@redhat.com>
|
From: Eduardo Habkost <ehabkost@redhat.com>
|
||||||
Date: Wed, 4 Dec 2013 18:53:17 +0100
|
Date: Wed, 4 Dec 2013 18:53:17 +0100
|
||||||
Subject: Add support statement to -help output
|
Subject: Add support statement to -help output
|
||||||
|
|
||||||
|
RH-Author: Eduardo Habkost <ehabkost@redhat.com>
|
||||||
|
Message-id: <1386183197-27761-1-git-send-email-ehabkost@redhat.com>
|
||||||
|
Patchwork-id: 55994
|
||||||
|
O-Subject: [qemu-kvm RHEL7 PATCH] Add support statement to -help output
|
||||||
|
Bugzilla: 972773
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Acked-by: knoel@redhat.com
|
||||||
|
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
|
||||||
Add support statement to -help output, reporting direct qemu-kvm usage
|
Add support statement to -help output, reporting direct qemu-kvm usage
|
||||||
as unsupported by Red Hat, and advising users to use libvirt instead.
|
as unsupported by Red Hat, and advising users to use libvirt instead.
|
||||||
|
|
@ -1,8 +1,17 @@
|
|||||||
From ec651d300d350a37219b09f5baab827ae6891006 Mon Sep 17 00:00:00 2001
|
From 20cc3a6d9bce3e40d165f865b5e398c300cae7bf Mon Sep 17 00:00:00 2001
|
||||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
Date: Wed, 8 Jul 2020 08:35:50 +0200
|
Date: Wed, 8 Jul 2020 08:35:50 +0200
|
||||||
Subject: Use qemu-kvm in documentation instead of qemu-system-<arch>
|
Subject: Use qemu-kvm in documentation instead of qemu-system-<arch>
|
||||||
|
|
||||||
|
Patchwork-id: 62380
|
||||||
|
O-Subject: [RHEV-7.1 qemu-kvm-rhev PATCHv4] Use qemu-kvm in documentation instead of qemu-system-i386
|
||||||
|
Bugzilla: 1140620
|
||||||
|
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
|
||||||
|
RH-Acked-by: Markus Armbruster <armbru@redhat.com>
|
||||||
|
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
|
||||||
|
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
|
||||||
We change the name and location of qemu-kvm binaries. Update documentation
|
We change the name and location of qemu-kvm binaries. Update documentation
|
||||||
to reflect this change. Only architectures available in RHEL are updated.
|
to reflect this change. Only architectures available in RHEL are updated.
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
From f24c7a1feef2a6f153582c06f10871b78a014bf1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
Date: Fri, 26 Apr 2024 05:58:31 -0400
|
|
||||||
Subject: Disable FDC devices
|
|
||||||
|
|
||||||
---
|
|
||||||
configs/devices/x86_64-softmmu/x86_64-rh-devices.mak | 6 +++---
|
|
||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
index d60ff1bcfc..ee75bb4c21 100644
|
|
||||||
--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
@@ -19,9 +19,9 @@ CONFIG_DIMM=y
|
|
||||||
CONFIG_E1000E_PCI_EXPRESS=y
|
|
||||||
CONFIG_E1000_PCI=y
|
|
||||||
CONFIG_EDU=y
|
|
||||||
-CONFIG_FDC=y
|
|
||||||
-CONFIG_FDC_SYSBUS=y
|
|
||||||
-CONFIG_FDC_ISA=y
|
|
||||||
+#CONFIG_FDC=y
|
|
||||||
+#CONFIG_FDC_SYSBUS=y
|
|
||||||
+#CONFIG_FDC_ISA=y
|
|
||||||
CONFIG_FW_CFG_DMA=y
|
|
||||||
CONFIG_HDA=y
|
|
||||||
CONFIG_HYPERV=y
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
From fe8c6cb1cecb3cde16871c4ec7368e4d004fa42a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
Date: Fri, 26 Apr 2024 05:59:53 -0400
|
|
||||||
Subject: Disable vga-cirrus device
|
|
||||||
|
|
||||||
---
|
|
||||||
configs/devices/x86_64-softmmu/x86_64-rh-devices.mak | 1 -
|
|
||||||
1 file changed, 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
index ee75bb4c21..fe69f04ead 100644
|
|
||||||
--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
@@ -87,7 +87,6 @@ CONFIG_USB_XHCI_PCI=y
|
|
||||||
CONFIG_VFIO=y
|
|
||||||
CONFIG_VFIO_PCI=y
|
|
||||||
CONFIG_VGA=y
|
|
||||||
-CONFIG_VGA_CIRRUS=y
|
|
||||||
CONFIG_VGA_PCI=y
|
|
||||||
CONFIG_VHOST_USER=y
|
|
||||||
CONFIG_VHOST_USER_BLK=y
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From ba574acacf679850e337ec2d5e7836b8277cf393 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sebastian Ott <sebott@redhat.com>
|
||||||
|
Date: Thu, 18 Apr 2024 15:04:28 +0200
|
||||||
|
Subject: x86: rhel 9.4.0 machine type compat fix
|
||||||
|
|
||||||
|
Fix up the compatibility for 9.4.0. Ensure that pc-q35-rhel9.4.0
|
||||||
|
still uses SMBIOS 3.X by default.
|
||||||
|
|
||||||
|
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_q35.c | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index 2b54944c0f..2f11f9af7d 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -734,6 +734,9 @@ static void pc_q35_machine_rhel940_options(MachineClass *m)
|
||||||
|
pcmc->smbios_stream_product = "RHEL";
|
||||||
|
pcmc->smbios_stream_version = "9.4.0";
|
||||||
|
|
||||||
|
+ /* From pc_q35_8_2_machine_options() - use SMBIOS 3.X by default */
|
||||||
|
+ pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64;
|
||||||
|
+
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||||
|
hw_compat_rhel_9_5_len);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
From ca89f2eb9588bfebe2796a579a563bd974dadf72 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
Date: Wed, 24 Jul 2024 07:31:12 -0400
|
|
||||||
Subject: [PATCH] Enable vhost-user-scmi devices
|
|
||||||
|
|
||||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-MergeRequest: 258: Enable vhost-user-scmi devices
|
|
||||||
RH-Jira: RHEL-50165
|
|
||||||
RH-Acked-by: Sandro Bonazzola <None>
|
|
||||||
RH-Commit: [1/1] edf95ef0fab99eb079beb16409fdab2a3cb0b94b (mrezanin/centos-src-qemu-kvm)
|
|
||||||
|
|
||||||
Enabling vhost-user-scmi and vhost-user-scmi-pci devices for qemu-kvm.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
---
|
|
||||||
configs/devices/aarch64-softmmu/aarch64-rh-devices.mak | 1 +
|
|
||||||
configs/devices/s390x-softmmu/s390x-rh-devices.mak | 1 +
|
|
||||||
configs/devices/x86_64-softmmu/x86_64-rh-devices.mak | 1 +
|
|
||||||
3 files changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak b/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
index 0a95438e25..4495d033e5 100644
|
|
||||||
--- a/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
@@ -41,3 +41,4 @@ CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
CONFIG_IOMMUFD=y
|
|
||||||
CONFIG_VHOST_USER_SND=y
|
|
||||||
+CONFIG_VHOST_USER_SCMI=y
|
|
||||||
diff --git a/configs/devices/s390x-softmmu/s390x-rh-devices.mak b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
index 719f802565..963ec43b6c 100644
|
|
||||||
--- a/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
+++ b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
@@ -18,3 +18,4 @@ CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
CONFIG_IOMMUFD=y
|
|
||||||
CONFIG_VHOST_USER_SND=y
|
|
||||||
+CONFIG_VHOST_USER_SCMI=y
|
|
||||||
diff --git a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
index b85bb1fe53..276397f3be 100644
|
|
||||||
--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
@@ -110,3 +110,4 @@ CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
CONFIG_IOMMUFD=y
|
|
||||||
CONFIG_VHOST_USER_SND=y
|
|
||||||
+CONFIG_VHOST_USER_SCMI=y
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
From d7256c0d15a3ae142c80462c66e0d68120ebd001 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
Date: Wed, 22 May 2024 03:56:55 -0400
|
|
||||||
Subject: [PATCH] Enable vhost-user-snd-pci device
|
|
||||||
|
|
||||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-MergeRequest: 242: Enable vhost-user-snd-pci device
|
|
||||||
RH-Jira: RHEL-37563
|
|
||||||
RH-Acked-by: Sandro Bonazzola <None>
|
|
||||||
RH-Commit: [1/1] 014f47770fc9f7d4bd0e7fac9a072911325f3283 (mrezanin/centos-src-qemu-kvm)
|
|
||||||
|
|
||||||
RHIVOS requires vhost-user-snd-pci device. Enabling it for aarch64 and x86_64 only.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
---
|
|
||||||
configs/devices/aarch64-softmmu/aarch64-rh-devices.mak | 1 +
|
|
||||||
configs/devices/s390x-softmmu/s390x-rh-devices.mak | 1 +
|
|
||||||
configs/devices/x86_64-softmmu/x86_64-rh-devices.mak | 1 +
|
|
||||||
3 files changed, 3 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak b/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
index b0191d3c69..0a95438e25 100644
|
|
||||||
--- a/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
@@ -40,3 +40,4 @@ CONFIG_VHOST_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
CONFIG_IOMMUFD=y
|
|
||||||
+CONFIG_VHOST_USER_SND=y
|
|
||||||
diff --git a/configs/devices/s390x-softmmu/s390x-rh-devices.mak b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
index 24cf6dbd03..719f802565 100644
|
|
||||||
--- a/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
+++ b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
@@ -17,3 +17,4 @@ CONFIG_VHOST_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
CONFIG_IOMMUFD=y
|
|
||||||
+CONFIG_VHOST_USER_SND=y
|
|
||||||
diff --git a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
index fe69f04ead..b85bb1fe53 100644
|
|
||||||
--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
@@ -109,3 +109,4 @@ CONFIG_VHOST_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
CONFIG_IOMMUFD=y
|
|
||||||
+CONFIG_VHOST_USER_SND=y
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,139 @@
|
|||||||
|
From 93ea86ac8849ad9ca365b1646313dde9a34ba59c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:03 -0500
|
||||||
|
Subject: [PATCH 031/100] HostMem: Add mechanism to opt in kvm guest memfd via
|
||||||
|
MachineState
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [31/91] 43ce32aef954479cdb736301d1adcb919602c321 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add a new member "guest_memfd" to memory backends. When it's set
|
||||||
|
to true, it enables RAM_GUEST_MEMFD in ram_flags, thus private kvm
|
||||||
|
guest_memfd will be allocated during RAMBlock allocation.
|
||||||
|
|
||||||
|
Memory backend's @guest_memfd is wired with @require_guest_memfd
|
||||||
|
field of MachineState. It avoid looking up the machine in phymem.c.
|
||||||
|
|
||||||
|
MachineState::require_guest_memfd is supposed to be set by any VMs
|
||||||
|
that requires KVM guest memfd as private memory, e.g., TDX VM.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||||
|
Message-ID: <20240320083945.991426-8-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 37662d85b0b7dded0ebdf6747bef6c3bb7ed6a0c)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
backends/hostmem-file.c | 1 +
|
||||||
|
backends/hostmem-memfd.c | 1 +
|
||||||
|
backends/hostmem-ram.c | 1 +
|
||||||
|
backends/hostmem.c | 1 +
|
||||||
|
hw/core/machine.c | 5 +++++
|
||||||
|
include/hw/boards.h | 2 ++
|
||||||
|
include/sysemu/hostmem.h | 1 +
|
||||||
|
7 files changed, 12 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
|
||||||
|
index ac3e433cbd..3c69db7946 100644
|
||||||
|
--- a/backends/hostmem-file.c
|
||||||
|
+++ b/backends/hostmem-file.c
|
||||||
|
@@ -85,6 +85,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||||
|
ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
|
||||||
|
ram_flags |= fb->rom == ON_OFF_AUTO_ON ? RAM_READONLY : 0;
|
||||||
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
|
+ ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||||
|
ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
|
||||||
|
ram_flags |= RAM_NAMED_FILE;
|
||||||
|
return memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
|
||||||
|
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
|
||||||
|
index 3923ea9364..745ead0034 100644
|
||||||
|
--- a/backends/hostmem-memfd.c
|
||||||
|
+++ b/backends/hostmem-memfd.c
|
||||||
|
@@ -55,6 +55,7 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||||
|
name = host_memory_backend_get_name(backend);
|
||||||
|
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||||
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
|
+ ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||||
|
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
||||||
|
backend->size, ram_flags, fd, 0, errp);
|
||||||
|
}
|
||||||
|
diff --git a/backends/hostmem-ram.c b/backends/hostmem-ram.c
|
||||||
|
index d121249f0f..f7d81af783 100644
|
||||||
|
--- a/backends/hostmem-ram.c
|
||||||
|
+++ b/backends/hostmem-ram.c
|
||||||
|
@@ -30,6 +30,7 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||||
|
name = host_memory_backend_get_name(backend);
|
||||||
|
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||||
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
|
+ ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||||
|
return memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend),
|
||||||
|
name, backend->size,
|
||||||
|
ram_flags, errp);
|
||||||
|
diff --git a/backends/hostmem.c b/backends/hostmem.c
|
||||||
|
index 81a72ce40b..eb9682b4a8 100644
|
||||||
|
--- a/backends/hostmem.c
|
||||||
|
+++ b/backends/hostmem.c
|
||||||
|
@@ -277,6 +277,7 @@ static void host_memory_backend_init(Object *obj)
|
||||||
|
/* TODO: convert access to globals to compat properties */
|
||||||
|
backend->merge = machine_mem_merge(machine);
|
||||||
|
backend->dump = machine_dump_guest_core(machine);
|
||||||
|
+ backend->guest_memfd = machine_require_guest_memfd(machine);
|
||||||
|
backend->reserve = true;
|
||||||
|
backend->prealloc_threads = machine->smp.cpus;
|
||||||
|
}
|
||||||
|
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||||
|
index 92609aae27..07b994e136 100644
|
||||||
|
--- a/hw/core/machine.c
|
||||||
|
+++ b/hw/core/machine.c
|
||||||
|
@@ -1480,6 +1480,11 @@ bool machine_mem_merge(MachineState *machine)
|
||||||
|
return machine->mem_merge;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool machine_require_guest_memfd(MachineState *machine)
|
||||||
|
+{
|
||||||
|
+ return machine->require_guest_memfd;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static char *cpu_slot_to_string(const CPUArchId *cpu)
|
||||||
|
{
|
||||||
|
GString *s = g_string_new(NULL);
|
||||||
|
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||||
|
index cca62f906b..815a1c4b26 100644
|
||||||
|
--- a/include/hw/boards.h
|
||||||
|
+++ b/include/hw/boards.h
|
||||||
|
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
|
||||||
|
int machine_phandle_start(MachineState *machine);
|
||||||
|
bool machine_dump_guest_core(MachineState *machine);
|
||||||
|
bool machine_mem_merge(MachineState *machine);
|
||||||
|
+bool machine_require_guest_memfd(MachineState *machine);
|
||||||
|
HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine);
|
||||||
|
void machine_set_cpu_numa_node(MachineState *machine,
|
||||||
|
const CpuInstanceProperties *props,
|
||||||
|
@@ -372,6 +373,7 @@ struct MachineState {
|
||||||
|
char *dt_compatible;
|
||||||
|
bool dump_guest_core;
|
||||||
|
bool mem_merge;
|
||||||
|
+ bool require_guest_memfd;
|
||||||
|
bool usb;
|
||||||
|
bool usb_disabled;
|
||||||
|
char *firmware;
|
||||||
|
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
|
||||||
|
index 0e411aaa29..04b884bf42 100644
|
||||||
|
--- a/include/sysemu/hostmem.h
|
||||||
|
+++ b/include/sysemu/hostmem.h
|
||||||
|
@@ -74,6 +74,7 @@ struct HostMemoryBackend {
|
||||||
|
uint64_t size;
|
||||||
|
bool merge, dump, use_canonical_path;
|
||||||
|
bool prealloc, is_mapped, share, reserve;
|
||||||
|
+ bool guest_memfd;
|
||||||
|
uint32_t prealloc_threads;
|
||||||
|
ThreadContext *prealloc_context;
|
||||||
|
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,203 @@
|
|||||||
|
From c46ac3db0a4db60e667edeabc9ed451c6e8e0ccf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Mon, 18 Mar 2024 14:41:33 -0400
|
||||||
|
Subject: [PATCH 020/100] KVM: remove kvm_arch_cpu_check_are_resettable
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [20/91] d7745bd1a0ed1b215847f150f4a1bb2e912beabc (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Board reset requires writing a fresh CPU state. As far as KVM is
|
||||||
|
concerned, the only thing that blocks reset is that CPU state is
|
||||||
|
encrypted; therefore, kvm_cpus_are_resettable() can simply check
|
||||||
|
if that is the case.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a99c0c66ebe7d8db3af6f16689ade9375247e43e)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-accel-ops.c | 2 +-
|
||||||
|
accel/kvm/kvm-all.c | 5 -----
|
||||||
|
include/sysemu/kvm.h | 10 ----------
|
||||||
|
target/arm/kvm.c | 5 -----
|
||||||
|
target/i386/kvm/kvm.c | 5 -----
|
||||||
|
target/loongarch/kvm/kvm.c | 5 -----
|
||||||
|
target/mips/kvm.c | 5 -----
|
||||||
|
target/ppc/kvm.c | 5 -----
|
||||||
|
target/riscv/kvm/kvm-cpu.c | 5 -----
|
||||||
|
target/s390x/kvm/kvm.c | 5 -----
|
||||||
|
10 files changed, 1 insertion(+), 51 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c
|
||||||
|
index b3c946dc4b..74e3c5785b 100644
|
||||||
|
--- a/accel/kvm/kvm-accel-ops.c
|
||||||
|
+++ b/accel/kvm/kvm-accel-ops.c
|
||||||
|
@@ -82,7 +82,7 @@ static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
|
||||||
|
|
||||||
|
static bool kvm_cpus_are_resettable(void)
|
||||||
|
{
|
||||||
|
- return !kvm_enabled() || kvm_cpu_check_are_resettable();
|
||||||
|
+ return !kvm_enabled() || !kvm_state->guest_state_protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index ec0f6df7c5..b51e09a583 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -2696,11 +2696,6 @@ void kvm_flush_coalesced_mmio_buffer(void)
|
||||||
|
s->coalesced_flush_in_progress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return kvm_arch_cpu_check_are_resettable();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
{
|
||||||
|
if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index 302e8f6f1e..54f4d83a37 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -525,16 +525,6 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target);
|
||||||
|
/* Notify resamplefd for EOI of specific interrupts. */
|
||||||
|
void kvm_resample_fd_notify(int gsi);
|
||||||
|
|
||||||
|
-/**
|
||||||
|
- * kvm_cpu_check_are_resettable - return whether CPUs can be reset
|
||||||
|
- *
|
||||||
|
- * Returns: true: CPUs are resettable
|
||||||
|
- * false: CPUs are not resettable
|
||||||
|
- */
|
||||||
|
-bool kvm_cpu_check_are_resettable(void);
|
||||||
|
-
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void);
|
||||||
|
-
|
||||||
|
bool kvm_dirty_ring_enabled(void);
|
||||||
|
|
||||||
|
uint32_t kvm_dirty_ring_size(void);
|
||||||
|
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
|
||||||
|
index ab85d628a8..21ebbf3b8f 100644
|
||||||
|
--- a/target/arm/kvm.c
|
||||||
|
+++ b/target/arm/kvm.c
|
||||||
|
@@ -1598,11 +1598,6 @@ int kvm_arch_msi_data_to_gsi(uint32_t data)
|
||||||
|
return (data - 32) & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void kvm_arch_get_eager_split_size(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index e271652620..a12207a8ee 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -5623,11 +5623,6 @@ bool kvm_has_waitpkg(void)
|
||||||
|
return has_msr_umwait;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return !sev_es_enabled();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
#define ARCH_REQ_XCOMP_GUEST_PERM 0x1025
|
||||||
|
|
||||||
|
void kvm_request_xsave_components(X86CPU *cpu, uint64_t mask)
|
||||||
|
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
|
||||||
|
index d630cc39cb..8224d94333 100644
|
||||||
|
--- a/target/loongarch/kvm/kvm.c
|
||||||
|
+++ b/target/loongarch/kvm/kvm.c
|
||||||
|
@@ -733,11 +733,6 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
|
||||||
|
index 6c52e59f55..a631ab544f 100644
|
||||||
|
--- a/target/mips/kvm.c
|
||||||
|
+++ b/target/mips/kvm.c
|
||||||
|
@@ -1273,11 +1273,6 @@ int kvm_arch_get_default_type(MachineState *machine)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void kvm_arch_accel_class_init(ObjectClass *oc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
|
||||||
|
index 59f640cf7b..9d9d9f0d79 100644
|
||||||
|
--- a/target/ppc/kvm.c
|
||||||
|
+++ b/target/ppc/kvm.c
|
||||||
|
@@ -2968,11 +2968,6 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void kvm_arch_accel_class_init(ObjectClass *oc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
|
||||||
|
index 6a6c6cae80..49d2f3ad58 100644
|
||||||
|
--- a/target/riscv/kvm/kvm-cpu.c
|
||||||
|
+++ b/target/riscv/kvm/kvm-cpu.c
|
||||||
|
@@ -1475,11 +1475,6 @@ void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int aia_mode;
|
||||||
|
|
||||||
|
static const char *kvm_aia_mode_str(uint64_t mode)
|
||||||
|
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
|
||||||
|
index 55fb4855b1..4db59658e1 100644
|
||||||
|
--- a/target/s390x/kvm/kvm.c
|
||||||
|
+++ b/target/s390x/kvm/kvm.c
|
||||||
|
@@ -2630,11 +2630,6 @@ void kvm_s390_stop_interrupt(S390CPU *cpu)
|
||||||
|
kvm_s390_vcpu_interrupt(cpu, &irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int kvm_s390_get_zpci_op(void)
|
||||||
|
{
|
||||||
|
return cap_zpci_op;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,127 @@
|
|||||||
|
From 50399796da938c4ea7c69058fde84695bce9d794 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Mon, 18 Mar 2024 14:41:10 -0400
|
||||||
|
Subject: [PATCH 019/100] KVM: track whether guest state is encrypted
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [19/91] 685b9c54d43d0043d15c33d13afc3a420cbe139b (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
So far, KVM has allowed KVM_GET/SET_* ioctls to execute even if the
|
||||||
|
guest state is encrypted, in which case they do nothing. For the new
|
||||||
|
API using VM types, instead, the ioctls will fail which is a safer and
|
||||||
|
more robust approach.
|
||||||
|
|
||||||
|
The new API will be the only one available for SEV-SNP and TDX, but it
|
||||||
|
is also usable for SEV and SEV-ES. In preparation for that, require
|
||||||
|
architecture-specific KVM code to communicate the point at which guest
|
||||||
|
state is protected (which must be after kvm_cpu_synchronize_post_init(),
|
||||||
|
though that might change in the future in order to suppor migration).
|
||||||
|
From that point, skip reading registers so that cpu->vcpu_dirty is
|
||||||
|
never true: if it ever becomes true, kvm_arch_put_registers() will
|
||||||
|
fail miserably.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 5c3131c392f84c660033d511ec39872d8beb4b1e)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 17 ++++++++++++++---
|
||||||
|
include/sysemu/kvm.h | 2 ++
|
||||||
|
include/sysemu/kvm_int.h | 1 +
|
||||||
|
target/i386/sev.c | 1 +
|
||||||
|
4 files changed, 18 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 931f74256e..ec0f6df7c5 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -2703,7 +2703,7 @@ bool kvm_cpu_check_are_resettable(void)
|
||||||
|
|
||||||
|
static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
{
|
||||||
|
- if (!cpu->vcpu_dirty) {
|
||||||
|
+ if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
|
||||||
|
int ret = kvm_arch_get_registers(cpu);
|
||||||
|
if (ret) {
|
||||||
|
error_report("Failed to get registers: %s", strerror(-ret));
|
||||||
|
@@ -2717,7 +2717,7 @@ static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
|
||||||
|
void kvm_cpu_synchronize_state(CPUState *cpu)
|
||||||
|
{
|
||||||
|
- if (!cpu->vcpu_dirty) {
|
||||||
|
+ if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
|
||||||
|
run_on_cpu(cpu, do_kvm_cpu_synchronize_state, RUN_ON_CPU_NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2752,7 +2752,13 @@ static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
|
||||||
|
void kvm_cpu_synchronize_post_init(CPUState *cpu)
|
||||||
|
{
|
||||||
|
- run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
|
||||||
|
+ if (!kvm_state->guest_state_protected) {
|
||||||
|
+ /*
|
||||||
|
+ * This runs before the machine_init_done notifiers, and is the last
|
||||||
|
+ * opportunity to synchronize the state of confidential guests.
|
||||||
|
+ */
|
||||||
|
+ run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_kvm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
@@ -4099,3 +4105,8 @@ void query_stats_schemas_cb(StatsSchemaList **result, Error **errp)
|
||||||
|
query_stats_schema_vcpu(first_cpu, &stats_args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void kvm_mark_guest_state_protected(void)
|
||||||
|
+{
|
||||||
|
+ kvm_state->guest_state_protected = true;
|
||||||
|
+}
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index fad9a7e8ff..302e8f6f1e 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -539,6 +539,8 @@ bool kvm_dirty_ring_enabled(void);
|
||||||
|
|
||||||
|
uint32_t kvm_dirty_ring_size(void);
|
||||||
|
|
||||||
|
+void kvm_mark_guest_state_protected(void);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* kvm_hwpoisoned_mem - indicate if there is any hwpoisoned page
|
||||||
|
* reported for the VM.
|
||||||
|
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
|
||||||
|
index 882e37e12c..3496be7997 100644
|
||||||
|
--- a/include/sysemu/kvm_int.h
|
||||||
|
+++ b/include/sysemu/kvm_int.h
|
||||||
|
@@ -87,6 +87,7 @@ struct KVMState
|
||||||
|
bool kernel_irqchip_required;
|
||||||
|
OnOffAuto kernel_irqchip_split;
|
||||||
|
bool sync_mmu;
|
||||||
|
+ bool guest_state_protected;
|
||||||
|
uint64_t manual_dirty_log_protect;
|
||||||
|
/* The man page (and posix) say ioctl numbers are signed int, but
|
||||||
|
* they're not. Linux, glibc and *BSD all treat ioctl numbers as
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index b8f79d34d1..c49a8fd55e 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -755,6 +755,7 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
|
||||||
|
if (ret) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
+ kvm_mark_guest_state_protected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the measurement blob length */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,329 @@
|
|||||||
|
From f4b01d645926faab2cab86fadb7398c26d6b8285 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:02 -0500
|
||||||
|
Subject: [PATCH 028/100] RAMBlock: Add support of KVM private guest memfd
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [28/91] 95fdf196afcb67113834c20fa354ee1397411bfd (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add KVM guest_memfd support to RAMBlock so both normal hva based memory
|
||||||
|
and kvm guest memfd based private memory can be associated in one RAMBlock.
|
||||||
|
|
||||||
|
Introduce new flag RAM_GUEST_MEMFD. When it's set, it calls KVM ioctl to
|
||||||
|
create private guest_memfd during RAMBlock setup.
|
||||||
|
|
||||||
|
Allocating a new RAM_GUEST_MEMFD flag to instruct the setup of guest memfd
|
||||||
|
is more flexible and extensible than simply relying on the VM type because
|
||||||
|
in the future we may have the case that not all the memory of a VM need
|
||||||
|
guest memfd. As a benefit, it also avoid getting MachineState in memory
|
||||||
|
subsystem.
|
||||||
|
|
||||||
|
Note, RAM_GUEST_MEMFD is supposed to be set for memory backends of
|
||||||
|
confidential guests, such as TDX VM. How and when to set it for memory
|
||||||
|
backends will be implemented in the following patches.
|
||||||
|
|
||||||
|
Introduce memory_region_has_guest_memfd() to query if the MemoryRegion has
|
||||||
|
KVM guest_memfd allocated.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||||
|
Message-ID: <20240320083945.991426-7-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 15f7a80c49cb3637f62fa37fa4a17da913bd91ff)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 28 ++++++++++++++++++++++++++++
|
||||||
|
accel/stubs/kvm-stub.c | 5 +++++
|
||||||
|
include/exec/memory.h | 20 +++++++++++++++++---
|
||||||
|
include/exec/ram_addr.h | 2 +-
|
||||||
|
include/exec/ramblock.h | 1 +
|
||||||
|
include/sysemu/kvm.h | 2 ++
|
||||||
|
system/memory.c | 5 +++++
|
||||||
|
system/physmem.c | 34 +++++++++++++++++++++++++++++++---
|
||||||
|
8 files changed, 90 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 272e945f52..a7b9a127dd 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -92,6 +92,7 @@ static bool kvm_has_guest_debug;
|
||||||
|
static int kvm_sstep_flags;
|
||||||
|
static bool kvm_immediate_exit;
|
||||||
|
static uint64_t kvm_supported_memory_attributes;
|
||||||
|
+static bool kvm_guest_memfd_supported;
|
||||||
|
static hwaddr kvm_max_slot_size = ~0;
|
||||||
|
|
||||||
|
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||||
|
@@ -2419,6 +2420,11 @@ static int kvm_init(MachineState *ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
kvm_supported_memory_attributes = kvm_check_extension(s, KVM_CAP_MEMORY_ATTRIBUTES);
|
||||||
|
+ kvm_guest_memfd_supported =
|
||||||
|
+ kvm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
|
||||||
|
+ kvm_check_extension(s, KVM_CAP_USER_MEMORY2) &&
|
||||||
|
+ (kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE);
|
||||||
|
+
|
||||||
|
kvm_immediate_exit = kvm_check_extension(s, KVM_CAP_IMMEDIATE_EXIT);
|
||||||
|
s->nr_slots = kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
|
||||||
|
|
||||||
|
@@ -4138,3 +4144,25 @@ void kvm_mark_guest_state_protected(void)
|
||||||
|
{
|
||||||
|
kvm_state->guest_state_protected = true;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
|
||||||
|
+{
|
||||||
|
+ int fd;
|
||||||
|
+ struct kvm_create_guest_memfd guest_memfd = {
|
||||||
|
+ .size = size,
|
||||||
|
+ .flags = flags,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ if (!kvm_guest_memfd_supported) {
|
||||||
|
+ error_setg(errp, "KVM does not support guest_memfd");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
|
||||||
|
+ if (fd < 0) {
|
||||||
|
+ error_setg_errno(errp, errno, "Error creating KVM guest_memfd");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return fd;
|
||||||
|
+}
|
||||||
|
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
|
||||||
|
index ca38172884..8e0eb22e61 100644
|
||||||
|
--- a/accel/stubs/kvm-stub.c
|
||||||
|
+++ b/accel/stubs/kvm-stub.c
|
||||||
|
@@ -129,3 +129,8 @@ bool kvm_hwpoisoned_mem(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
|
||||||
|
+{
|
||||||
|
+ return -ENOSYS;
|
||||||
|
+}
|
||||||
|
diff --git a/include/exec/memory.h b/include/exec/memory.h
|
||||||
|
index 8626a355b3..679a847685 100644
|
||||||
|
--- a/include/exec/memory.h
|
||||||
|
+++ b/include/exec/memory.h
|
||||||
|
@@ -243,6 +243,9 @@ typedef struct IOMMUTLBEvent {
|
||||||
|
/* RAM FD is opened read-only */
|
||||||
|
#define RAM_READONLY_FD (1 << 11)
|
||||||
|
|
||||||
|
+/* RAM can be private that has kvm guest memfd backend */
|
||||||
|
+#define RAM_GUEST_MEMFD (1 << 12)
|
||||||
|
+
|
||||||
|
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
|
||||||
|
IOMMUNotifierFlag flags,
|
||||||
|
hwaddr start, hwaddr end,
|
||||||
|
@@ -1307,7 +1310,8 @@ bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
|
||||||
|
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||||
|
* must be unique within any device
|
||||||
|
* @size: size of the region.
|
||||||
|
- * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_NORESERVE.
|
||||||
|
+ * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_NORESERVE,
|
||||||
|
+ * RAM_GUEST_MEMFD.
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
|
*
|
||||||
|
* Note that this function does not do anything to cause the data in the
|
||||||
|
@@ -1369,7 +1373,7 @@ bool memory_region_init_resizeable_ram(MemoryRegion *mr,
|
||||||
|
* (getpagesize()) will be used.
|
||||||
|
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||||
|
* RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
|
||||||
|
- * RAM_READONLY_FD
|
||||||
|
+ * RAM_READONLY_FD, RAM_GUEST_MEMFD
|
||||||
|
* @path: the path in which to allocate the RAM.
|
||||||
|
* @offset: offset within the file referenced by path
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
|
@@ -1399,7 +1403,7 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr,
|
||||||
|
* @size: size of the region.
|
||||||
|
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||||
|
* RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
|
||||||
|
- * RAM_READONLY_FD
|
||||||
|
+ * RAM_READONLY_FD, RAM_GUEST_MEMFD
|
||||||
|
* @fd: the fd to mmap.
|
||||||
|
* @offset: offset within the file referenced by fd
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
|
@@ -1722,6 +1726,16 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
|
||||||
|
*/
|
||||||
|
bool memory_region_is_protected(MemoryRegion *mr);
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * memory_region_has_guest_memfd: check whether a memory region has guest_memfd
|
||||||
|
+ * associated
|
||||||
|
+ *
|
||||||
|
+ * Returns %true if a memory region's ram_block has valid guest_memfd assigned.
|
||||||
|
+ *
|
||||||
|
+ * @mr: the memory region being queried
|
||||||
|
+ */
|
||||||
|
+bool memory_region_has_guest_memfd(MemoryRegion *mr);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* memory_region_get_iommu: check whether a memory region is an iommu
|
||||||
|
*
|
||||||
|
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
|
||||||
|
index de45ba7bc9..07c8f86375 100644
|
||||||
|
--- a/include/exec/ram_addr.h
|
||||||
|
+++ b/include/exec/ram_addr.h
|
||||||
|
@@ -110,7 +110,7 @@ long qemu_maxrampagesize(void);
|
||||||
|
* @mr: the memory region where the ram block is
|
||||||
|
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||||
|
* RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
|
||||||
|
- * RAM_READONLY_FD
|
||||||
|
+ * RAM_READONLY_FD, RAM_GUEST_MEMFD
|
||||||
|
* @mem_path or @fd: specify the backing file or device
|
||||||
|
* @offset: Offset into target file
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens
|
||||||
|
diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h
|
||||||
|
index 848915ea5b..459c8917de 100644
|
||||||
|
--- a/include/exec/ramblock.h
|
||||||
|
+++ b/include/exec/ramblock.h
|
||||||
|
@@ -41,6 +41,7 @@ struct RAMBlock {
|
||||||
|
QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers;
|
||||||
|
int fd;
|
||||||
|
uint64_t fd_offset;
|
||||||
|
+ int guest_memfd;
|
||||||
|
size_t page_size;
|
||||||
|
/* dirty bitmap used during migration */
|
||||||
|
unsigned long *bmap;
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index f114ff6986..9e4ab7ae89 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -537,6 +537,8 @@ void kvm_mark_guest_state_protected(void);
|
||||||
|
*/
|
||||||
|
bool kvm_hwpoisoned_mem(void);
|
||||||
|
|
||||||
|
+int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp);
|
||||||
|
+
|
||||||
|
int kvm_set_memory_attributes_private(hwaddr start, uint64_t size);
|
||||||
|
int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size);
|
||||||
|
|
||||||
|
diff --git a/system/memory.c b/system/memory.c
|
||||||
|
index a229a79988..c756950c0c 100644
|
||||||
|
--- a/system/memory.c
|
||||||
|
+++ b/system/memory.c
|
||||||
|
@@ -1850,6 +1850,11 @@ bool memory_region_is_protected(MemoryRegion *mr)
|
||||||
|
return mr->ram && (mr->ram_block->flags & RAM_PROTECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool memory_region_has_guest_memfd(MemoryRegion *mr)
|
||||||
|
+{
|
||||||
|
+ return mr->ram_block && mr->ram_block->guest_memfd >= 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
|
||||||
|
{
|
||||||
|
uint8_t mask = mr->dirty_log_mask;
|
||||||
|
diff --git a/system/physmem.c b/system/physmem.c
|
||||||
|
index a4fe3d2bf8..f5dfa20e57 100644
|
||||||
|
--- a/system/physmem.c
|
||||||
|
+++ b/system/physmem.c
|
||||||
|
@@ -1808,6 +1808,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
const bool shared = qemu_ram_is_shared(new_block);
|
||||||
|
RAMBlock *block;
|
||||||
|
RAMBlock *last_block = NULL;
|
||||||
|
+ bool free_on_error = false;
|
||||||
|
ram_addr_t old_ram_size, new_ram_size;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
@@ -1837,6 +1838,19 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memory_try_enable_merging(new_block->host, new_block->max_length);
|
||||||
|
+ free_on_error = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (new_block->flags & RAM_GUEST_MEMFD) {
|
||||||
|
+ assert(kvm_enabled());
|
||||||
|
+ assert(new_block->guest_memfd < 0);
|
||||||
|
+
|
||||||
|
+ new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
|
||||||
|
+ 0, errp);
|
||||||
|
+ if (new_block->guest_memfd < 0) {
|
||||||
|
+ qemu_mutex_unlock_ramlist();
|
||||||
|
+ goto out_free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1888,6 +1902,13 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
ram_block_notify_add(new_block->host, new_block->used_length,
|
||||||
|
new_block->max_length);
|
||||||
|
}
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+out_free:
|
||||||
|
+ if (free_on_error) {
|
||||||
|
+ qemu_anon_ram_free(new_block->host, new_block->max_length);
|
||||||
|
+ new_block->host = NULL;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_POSIX
|
||||||
|
@@ -1902,7 +1923,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
||||||
|
/* Just support these ram flags by now. */
|
||||||
|
assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE |
|
||||||
|
RAM_PROTECTED | RAM_NAMED_FILE | RAM_READONLY |
|
||||||
|
- RAM_READONLY_FD)) == 0);
|
||||||
|
+ RAM_READONLY_FD | RAM_GUEST_MEMFD)) == 0);
|
||||||
|
|
||||||
|
if (xen_enabled()) {
|
||||||
|
error_setg(errp, "-mem-path not supported with Xen");
|
||||||
|
@@ -1939,6 +1960,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
||||||
|
new_block->used_length = size;
|
||||||
|
new_block->max_length = size;
|
||||||
|
new_block->flags = ram_flags;
|
||||||
|
+ new_block->guest_memfd = -1;
|
||||||
|
new_block->host = file_ram_alloc(new_block, size, fd, !file_size, offset,
|
||||||
|
errp);
|
||||||
|
if (!new_block->host) {
|
||||||
|
@@ -2018,7 +2040,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
|
||||||
|
int align;
|
||||||
|
|
||||||
|
assert((ram_flags & ~(RAM_SHARED | RAM_RESIZEABLE | RAM_PREALLOC |
|
||||||
|
- RAM_NORESERVE)) == 0);
|
||||||
|
+ RAM_NORESERVE | RAM_GUEST_MEMFD)) == 0);
|
||||||
|
assert(!host ^ (ram_flags & RAM_PREALLOC));
|
||||||
|
|
||||||
|
align = qemu_real_host_page_size();
|
||||||
|
@@ -2033,6 +2055,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
|
||||||
|
new_block->max_length = max_size;
|
||||||
|
assert(max_size >= size);
|
||||||
|
new_block->fd = -1;
|
||||||
|
+ new_block->guest_memfd = -1;
|
||||||
|
new_block->page_size = qemu_real_host_page_size();
|
||||||
|
new_block->host = host;
|
||||||
|
new_block->flags = ram_flags;
|
||||||
|
@@ -2055,7 +2078,7 @@ RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
||||||
|
RAMBlock *qemu_ram_alloc(ram_addr_t size, uint32_t ram_flags,
|
||||||
|
MemoryRegion *mr, Error **errp)
|
||||||
|
{
|
||||||
|
- assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE)) == 0);
|
||||||
|
+ assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE | RAM_GUEST_MEMFD)) == 0);
|
||||||
|
return qemu_ram_alloc_internal(size, size, NULL, NULL, ram_flags, mr, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2083,6 +2106,11 @@ static void reclaim_ramblock(RAMBlock *block)
|
||||||
|
} else {
|
||||||
|
qemu_anon_ram_free(block->host, block->max_length);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (block->guest_memfd >= 0) {
|
||||||
|
+ close(block->guest_memfd);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
g_free(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,82 @@
|
|||||||
|
From bd289293604d6f33e9fb89196f0b19117ce81f89 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Wed, 20 Mar 2024 17:45:29 +0100
|
||||||
|
Subject: [PATCH 032/100] RAMBlock: make guest_memfd require uncoordinated
|
||||||
|
discard
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [32/91] 0c005849026c334737b88cbd20a0ac237dfca37e (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Some subsystems like VFIO might disable ram block discard, but guest_memfd
|
||||||
|
uses discard operations to implement conversions between private and
|
||||||
|
shared memory. Because of this, sequences like the following can result
|
||||||
|
in stale IOMMU mappings:
|
||||||
|
|
||||||
|
1. allocate shared page
|
||||||
|
2. convert page shared->private
|
||||||
|
3. discard shared page
|
||||||
|
4. convert page private->shared
|
||||||
|
5. allocate shared page
|
||||||
|
6. issue DMA operations against that shared page
|
||||||
|
|
||||||
|
This is not a use-after-free, because after step 3 VFIO is still pinning
|
||||||
|
the page. However, DMA operations in step 6 will hit the old mapping
|
||||||
|
that was allocated in step 1.
|
||||||
|
|
||||||
|
Address this by taking ram_block_discard_is_enabled() into account when
|
||||||
|
deciding whether or not to discard pages.
|
||||||
|
|
||||||
|
Since kvm_convert_memory()/guest_memfd doesn't implement a
|
||||||
|
RamDiscardManager handler to convey and replay discard operations,
|
||||||
|
this is a case of uncoordinated discard, which is blocked/released
|
||||||
|
by ram_block_discard_require(). Interestingly, this function had
|
||||||
|
no use so far.
|
||||||
|
|
||||||
|
Alternative approaches would be to block discard of shared pages, but
|
||||||
|
this would cause guests to consume twice the memory if they use VFIO;
|
||||||
|
or to implement a RamDiscardManager and only block uncoordinated
|
||||||
|
discard, i.e. use ram_block_coordinated_discard_require().
|
||||||
|
|
||||||
|
[Commit message mostly by Michael Roth <michael.roth@amd.com>]
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 852f0048f3ea9f14de18eb279a99fccb6d250e8f)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
system/physmem.c | 8 ++++++++
|
||||||
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/system/physmem.c b/system/physmem.c
|
||||||
|
index f5dfa20e57..5ebcf5be11 100644
|
||||||
|
--- a/system/physmem.c
|
||||||
|
+++ b/system/physmem.c
|
||||||
|
@@ -1846,6 +1846,13 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
assert(kvm_enabled());
|
||||||
|
assert(new_block->guest_memfd < 0);
|
||||||
|
|
||||||
|
+ if (ram_block_discard_require(true) < 0) {
|
||||||
|
+ error_setg_errno(errp, errno,
|
||||||
|
+ "cannot set up private guest memory: discard currently blocked");
|
||||||
|
+ error_append_hint(errp, "Are you using assigned devices?\n");
|
||||||
|
+ goto out_free;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
|
||||||
|
0, errp);
|
||||||
|
if (new_block->guest_memfd < 0) {
|
||||||
|
@@ -2109,6 +2116,7 @@ static void reclaim_ramblock(RAMBlock *block)
|
||||||
|
|
||||||
|
if (block->guest_memfd >= 0) {
|
||||||
|
close(block->guest_memfd);
|
||||||
|
+ ram_block_discard_require(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(block);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
From bcbc897cb19b3a6523de611f48f6bac6cea16c97 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sebastian Ott <sebott@redhat.com>
|
||||||
|
Date: Thu, 2 May 2024 13:17:03 +0200
|
||||||
|
Subject: [PATCH 2/2] Revert "x86: rhel 9.4.0 machine type compat fix"
|
||||||
|
|
||||||
|
RH-Author: Sebastian Ott <sebott@redhat.com>
|
||||||
|
RH-MergeRequest: 237: Revert "x86: rhel 9.4.0 machine type compat fix"
|
||||||
|
RH-Jira: RHEL-30362
|
||||||
|
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [1/1] 858ec153e65e96c39ca4db17ed93fd58c77dc2eb (seott1/cos-qemu-kvm)
|
||||||
|
|
||||||
|
This reverts commit c46e44f0f4e861fe412ce679b0b0204881c1c2f5.
|
||||||
|
|
||||||
|
pc-q35-rhel9.4.0 and newer should stay with SMBIOS_ENTRY_POINT_TYPE_AUTO.
|
||||||
|
|
||||||
|
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_q35.c | 3 ---
|
||||||
|
1 file changed, 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index 2f11f9af7d..2b54944c0f 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -734,9 +734,6 @@ static void pc_q35_machine_rhel940_options(MachineClass *m)
|
||||||
|
pcmc->smbios_stream_product = "RHEL";
|
||||||
|
pcmc->smbios_stream_version = "9.4.0";
|
||||||
|
|
||||||
|
- /* From pc_q35_8_2_machine_options() - use SMBIOS 3.X by default */
|
||||||
|
- pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64;
|
||||||
|
-
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||||
|
hw_compat_rhel_9_5_len);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,330 @@
|
|||||||
|
From a67edfb4b591acdffc5b4987601a30224376996f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Mon, 27 May 2024 11:58:50 -0400
|
||||||
|
Subject: [PATCH 4/5] block/crypto: create ciphers on demand
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
RH-MergeRequest: 251: block/crypto: create ciphers on demand
|
||||||
|
RH-Jira: RHEL-36159
|
||||||
|
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [1/2] 22a4c87fef774cad98a6f5a79f27df50a208013d (stefanha/centos-stream-qemu-kvm)
|
||||||
|
|
||||||
|
Ciphers are pre-allocated by qcrypto_block_init_cipher() depending on
|
||||||
|
the given number of threads. The -device
|
||||||
|
virtio-blk-pci,iothread-vq-mapping= feature allows users to assign
|
||||||
|
multiple IOThreads to a virtio-blk device, but the association between
|
||||||
|
the virtio-blk device and the block driver happens after the block
|
||||||
|
driver is already open.
|
||||||
|
|
||||||
|
When the number of threads given to qcrypto_block_init_cipher() is
|
||||||
|
smaller than the actual number of threads at runtime, the
|
||||||
|
block->n_free_ciphers > 0 assertion in qcrypto_block_pop_cipher() can
|
||||||
|
fail.
|
||||||
|
|
||||||
|
Get rid of qcrypto_block_init_cipher() n_thread's argument and allocate
|
||||||
|
ciphers on demand.
|
||||||
|
|
||||||
|
Reported-by: Qing Wang <qinwang@redhat.com>
|
||||||
|
Buglink: https://issues.redhat.com/browse/RHEL-36159
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Message-ID: <20240527155851.892885-2-stefanha@redhat.com>
|
||||||
|
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
(cherry picked from commit af206c284e4c1b17cdfb0f17e898b288c0fc1751)
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
crypto/block-luks.c | 3 +-
|
||||||
|
crypto/block-qcow.c | 2 +-
|
||||||
|
crypto/block.c | 111 ++++++++++++++++++++++++++------------------
|
||||||
|
crypto/blockpriv.h | 12 +++--
|
||||||
|
4 files changed, 78 insertions(+), 50 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
|
||||||
|
index 3ee928fb5a..3357852c0a 100644
|
||||||
|
--- a/crypto/block-luks.c
|
||||||
|
+++ b/crypto/block-luks.c
|
||||||
|
@@ -1262,7 +1262,6 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||||
|
luks->cipher_mode,
|
||||||
|
masterkey,
|
||||||
|
luks->header.master_key_len,
|
||||||
|
- n_threads,
|
||||||
|
errp) < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
@@ -1456,7 +1455,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
||||||
|
/* Setup the block device payload encryption objects */
|
||||||
|
if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
|
||||||
|
luks_opts.cipher_mode, masterkey,
|
||||||
|
- luks->header.master_key_len, 1, errp) < 0) {
|
||||||
|
+ luks->header.master_key_len, errp) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
|
||||||
|
index 4d7cf36a8f..02305058e3 100644
|
||||||
|
--- a/crypto/block-qcow.c
|
||||||
|
+++ b/crypto/block-qcow.c
|
||||||
|
@@ -75,7 +75,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
|
||||||
|
ret = qcrypto_block_init_cipher(block, QCRYPTO_CIPHER_ALG_AES_128,
|
||||||
|
QCRYPTO_CIPHER_MODE_CBC,
|
||||||
|
keybuf, G_N_ELEMENTS(keybuf),
|
||||||
|
- n_threads, errp);
|
||||||
|
+ errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -ENOTSUP;
|
||||||
|
goto fail;
|
||||||
|
diff --git a/crypto/block.c b/crypto/block.c
|
||||||
|
index 506ea1d1a3..ba6d1cebc7 100644
|
||||||
|
--- a/crypto/block.c
|
||||||
|
+++ b/crypto/block.c
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
+#include "qemu/lockable.h"
|
||||||
|
#include "blockpriv.h"
|
||||||
|
#include "block-qcow.h"
|
||||||
|
#include "block-luks.h"
|
||||||
|
@@ -57,6 +58,8 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
{
|
||||||
|
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
||||||
|
|
||||||
|
+ qemu_mutex_init(&block->mutex);
|
||||||
|
+
|
||||||
|
block->format = options->format;
|
||||||
|
|
||||||
|
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||||
|
@@ -76,8 +79,6 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- qemu_mutex_init(&block->mutex);
|
||||||
|
-
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -92,6 +93,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||||
|
{
|
||||||
|
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
||||||
|
|
||||||
|
+ qemu_mutex_init(&block->mutex);
|
||||||
|
+
|
||||||
|
block->format = options->format;
|
||||||
|
|
||||||
|
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||||
|
@@ -111,8 +114,6 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- qemu_mutex_init(&block->mutex);
|
||||||
|
-
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -227,37 +228,42 @@ QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
|
||||||
|
* This function is used only in test with one thread (it's safe to skip
|
||||||
|
* pop/push interface), so it's enough to assert it here:
|
||||||
|
*/
|
||||||
|
- assert(block->n_ciphers <= 1);
|
||||||
|
- return block->ciphers ? block->ciphers[0] : NULL;
|
||||||
|
+ assert(block->max_free_ciphers <= 1);
|
||||||
|
+ return block->free_ciphers ? block->free_ciphers[0] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block)
|
||||||
|
+static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- QCryptoCipher *cipher;
|
||||||
|
-
|
||||||
|
- qemu_mutex_lock(&block->mutex);
|
||||||
|
-
|
||||||
|
- assert(block->n_free_ciphers > 0);
|
||||||
|
- block->n_free_ciphers--;
|
||||||
|
- cipher = block->ciphers[block->n_free_ciphers];
|
||||||
|
-
|
||||||
|
- qemu_mutex_unlock(&block->mutex);
|
||||||
|
+ /* Usually there is a free cipher available */
|
||||||
|
+ WITH_QEMU_LOCK_GUARD(&block->mutex) {
|
||||||
|
+ if (block->n_free_ciphers > 0) {
|
||||||
|
+ block->n_free_ciphers--;
|
||||||
|
+ return block->free_ciphers[block->n_free_ciphers];
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- return cipher;
|
||||||
|
+ /* Otherwise allocate a new cipher */
|
||||||
|
+ return qcrypto_cipher_new(block->alg, block->mode, block->key,
|
||||||
|
+ block->nkey, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void qcrypto_block_push_cipher(QCryptoBlock *block,
|
||||||
|
QCryptoCipher *cipher)
|
||||||
|
{
|
||||||
|
- qemu_mutex_lock(&block->mutex);
|
||||||
|
+ QEMU_LOCK_GUARD(&block->mutex);
|
||||||
|
|
||||||
|
- assert(block->n_free_ciphers < block->n_ciphers);
|
||||||
|
- block->ciphers[block->n_free_ciphers] = cipher;
|
||||||
|
- block->n_free_ciphers++;
|
||||||
|
+ if (block->n_free_ciphers == block->max_free_ciphers) {
|
||||||
|
+ block->max_free_ciphers++;
|
||||||
|
+ block->free_ciphers = g_renew(QCryptoCipher *,
|
||||||
|
+ block->free_ciphers,
|
||||||
|
+ block->max_free_ciphers);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- qemu_mutex_unlock(&block->mutex);
|
||||||
|
+ block->free_ciphers[block->n_free_ciphers] = cipher;
|
||||||
|
+ block->n_free_ciphers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -265,24 +271,31 @@ int qcrypto_block_init_cipher(QCryptoBlock *block,
|
||||||
|
QCryptoCipherAlgorithm alg,
|
||||||
|
QCryptoCipherMode mode,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
- size_t n_threads, Error **errp)
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- size_t i;
|
||||||
|
+ QCryptoCipher *cipher;
|
||||||
|
|
||||||
|
- assert(!block->ciphers && !block->n_ciphers && !block->n_free_ciphers);
|
||||||
|
+ assert(!block->free_ciphers && !block->max_free_ciphers &&
|
||||||
|
+ !block->n_free_ciphers);
|
||||||
|
|
||||||
|
- block->ciphers = g_new0(QCryptoCipher *, n_threads);
|
||||||
|
+ /* Stash away cipher parameters for qcrypto_block_pop_cipher() */
|
||||||
|
+ block->alg = alg;
|
||||||
|
+ block->mode = mode;
|
||||||
|
+ block->key = g_memdup2(key, nkey);
|
||||||
|
+ block->nkey = nkey;
|
||||||
|
|
||||||
|
- for (i = 0; i < n_threads; i++) {
|
||||||
|
- block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp);
|
||||||
|
- if (!block->ciphers[i]) {
|
||||||
|
- qcrypto_block_free_cipher(block);
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
- block->n_ciphers++;
|
||||||
|
- block->n_free_ciphers++;
|
||||||
|
+ /*
|
||||||
|
+ * Create a new cipher to validate the parameters now. This reduces the
|
||||||
|
+ * chance of cipher creation failing at I/O time.
|
||||||
|
+ */
|
||||||
|
+ cipher = qcrypto_block_pop_cipher(block, errp);
|
||||||
|
+ if (!cipher) {
|
||||||
|
+ g_free(block->key);
|
||||||
|
+ block->key = NULL;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ qcrypto_block_push_cipher(block, cipher);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -291,19 +304,23 @@ void qcrypto_block_free_cipher(QCryptoBlock *block)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
- if (!block->ciphers) {
|
||||||
|
+ g_free(block->key);
|
||||||
|
+ block->key = NULL;
|
||||||
|
+
|
||||||
|
+ if (!block->free_ciphers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- assert(block->n_ciphers == block->n_free_ciphers);
|
||||||
|
+ /* All popped ciphers were eventually pushed back */
|
||||||
|
+ assert(block->n_free_ciphers == block->max_free_ciphers);
|
||||||
|
|
||||||
|
- for (i = 0; i < block->n_ciphers; i++) {
|
||||||
|
- qcrypto_cipher_free(block->ciphers[i]);
|
||||||
|
+ for (i = 0; i < block->max_free_ciphers; i++) {
|
||||||
|
+ qcrypto_cipher_free(block->free_ciphers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- g_free(block->ciphers);
|
||||||
|
- block->ciphers = NULL;
|
||||||
|
- block->n_ciphers = block->n_free_ciphers = 0;
|
||||||
|
+ g_free(block->free_ciphers);
|
||||||
|
+ block->free_ciphers = NULL;
|
||||||
|
+ block->max_free_ciphers = block->n_free_ciphers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
|
||||||
|
@@ -311,7 +328,7 @@ QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
|
||||||
|
/* ivgen should be accessed under mutex. However, this function is used only
|
||||||
|
* in test with one thread, so it's enough to assert it here:
|
||||||
|
*/
|
||||||
|
- assert(block->n_ciphers <= 1);
|
||||||
|
+ assert(block->max_free_ciphers <= 1);
|
||||||
|
return block->ivgen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -446,7 +463,10 @@ int qcrypto_block_decrypt_helper(QCryptoBlock *block,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
- QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
|
||||||
|
+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
|
||||||
|
+ if (!cipher) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
|
||||||
|
&block->mutex, sectorsize, offset, buf,
|
||||||
|
@@ -465,7 +485,10 @@ int qcrypto_block_encrypt_helper(QCryptoBlock *block,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
- QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
|
||||||
|
+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
|
||||||
|
+ if (!cipher) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
|
||||||
|
&block->mutex, sectorsize, offset, buf,
|
||||||
|
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
|
||||||
|
index 836f3b4726..4bf6043d5d 100644
|
||||||
|
--- a/crypto/blockpriv.h
|
||||||
|
+++ b/crypto/blockpriv.h
|
||||||
|
@@ -32,8 +32,14 @@ struct QCryptoBlock {
|
||||||
|
const QCryptoBlockDriver *driver;
|
||||||
|
void *opaque;
|
||||||
|
|
||||||
|
- QCryptoCipher **ciphers;
|
||||||
|
- size_t n_ciphers;
|
||||||
|
+ /* Cipher parameters */
|
||||||
|
+ QCryptoCipherAlgorithm alg;
|
||||||
|
+ QCryptoCipherMode mode;
|
||||||
|
+ uint8_t *key;
|
||||||
|
+ size_t nkey;
|
||||||
|
+
|
||||||
|
+ QCryptoCipher **free_ciphers;
|
||||||
|
+ size_t max_free_ciphers;
|
||||||
|
size_t n_free_ciphers;
|
||||||
|
QCryptoIVGen *ivgen;
|
||||||
|
QemuMutex mutex;
|
||||||
|
@@ -130,7 +136,7 @@ int qcrypto_block_init_cipher(QCryptoBlock *block,
|
||||||
|
QCryptoCipherAlgorithm alg,
|
||||||
|
QCryptoCipherMode mode,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
- size_t n_threads, Error **errp);
|
||||||
|
+ Error **errp);
|
||||||
|
|
||||||
|
void qcrypto_block_free_cipher(QCryptoBlock *block);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,90 @@
|
|||||||
|
From 0f0a3a860a07addea21a0282556a5022b9cb8b2c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Thu, 29 Feb 2024 01:00:35 -0500
|
||||||
|
Subject: [PATCH 011/100] confidential guest support: Add kvm_init() and
|
||||||
|
kvm_reset() in class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [11/91] 21d2178178bf181a8e4d0b051f64bd983f0d0cf1 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Different confidential VMs in different architectures all have the same
|
||||||
|
needs to do their specific initialization (and maybe resetting) stuffs
|
||||||
|
with KVM. Currently each of them exposes individual *_kvm_init()
|
||||||
|
functions and let machine code or kvm code to call it.
|
||||||
|
|
||||||
|
To facilitate the introduction of confidential guest technology from
|
||||||
|
different x86 vendors, add two virtual functions, kvm_init() and kvm_reset()
|
||||||
|
in ConfidentialGuestSupportClass, and expose two helpers functions for
|
||||||
|
invodking them.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-Id: <20240229060038.606591-1-xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 41a605944e3fecae43ca18ded95ec31f28e0c7fe)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
include/exec/confidential-guest-support.h | 34 ++++++++++++++++++++++-
|
||||||
|
1 file changed, 33 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||||
|
index ba2dd4b5df..e5b188cffb 100644
|
||||||
|
--- a/include/exec/confidential-guest-support.h
|
||||||
|
+++ b/include/exec/confidential-guest-support.h
|
||||||
|
@@ -23,7 +23,10 @@
|
||||||
|
#include "qom/object.h"
|
||||||
|
|
||||||
|
#define TYPE_CONFIDENTIAL_GUEST_SUPPORT "confidential-guest-support"
|
||||||
|
-OBJECT_DECLARE_SIMPLE_TYPE(ConfidentialGuestSupport, CONFIDENTIAL_GUEST_SUPPORT)
|
||||||
|
+OBJECT_DECLARE_TYPE(ConfidentialGuestSupport,
|
||||||
|
+ ConfidentialGuestSupportClass,
|
||||||
|
+ CONFIDENTIAL_GUEST_SUPPORT)
|
||||||
|
+
|
||||||
|
|
||||||
|
struct ConfidentialGuestSupport {
|
||||||
|
Object parent;
|
||||||
|
@@ -55,8 +58,37 @@ struct ConfidentialGuestSupport {
|
||||||
|
|
||||||
|
typedef struct ConfidentialGuestSupportClass {
|
||||||
|
ObjectClass parent;
|
||||||
|
+
|
||||||
|
+ int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
+ int (*kvm_reset)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
} ConfidentialGuestSupportClass;
|
||||||
|
|
||||||
|
+static inline int confidential_guest_kvm_init(ConfidentialGuestSupport *cgs,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ ConfidentialGuestSupportClass *klass;
|
||||||
|
+
|
||||||
|
+ klass = CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs);
|
||||||
|
+ if (klass->kvm_init) {
|
||||||
|
+ return klass->kvm_init(cgs, errp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int confidential_guest_kvm_reset(ConfidentialGuestSupport *cgs,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ ConfidentialGuestSupportClass *klass;
|
||||||
|
+
|
||||||
|
+ klass = CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs);
|
||||||
|
+ if (klass->kvm_reset) {
|
||||||
|
+ return klass->kvm_reset(cgs, errp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
|
#endif /* QEMU_CONFIDENTIAL_GUEST_SUPPORT_H */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,228 @@
|
|||||||
|
From 117486e0820f135f191e19f8ebb8838a98b121c6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Mon, 27 May 2024 11:58:51 -0400
|
||||||
|
Subject: [PATCH 5/5] crypto/block: drop qcrypto_block_open() n_threads
|
||||||
|
argument
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
RH-MergeRequest: 251: block/crypto: create ciphers on demand
|
||||||
|
RH-Jira: RHEL-36159
|
||||||
|
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [2/2] 68290935b174b1f2b76aa857a926da9011e54abe (stefanha/centos-stream-qemu-kvm)
|
||||||
|
|
||||||
|
The n_threads argument is no longer used since the previous commit.
|
||||||
|
Remove it.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Message-ID: <20240527155851.892885-3-stefanha@redhat.com>
|
||||||
|
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
(cherry picked from commit 3ab0f063e58ed9224237d69c4211ca83335164c4)
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
block/crypto.c | 1 -
|
||||||
|
block/qcow.c | 2 +-
|
||||||
|
block/qcow2.c | 5 ++---
|
||||||
|
crypto/block-luks.c | 1 -
|
||||||
|
crypto/block-qcow.c | 6 ++----
|
||||||
|
crypto/block.c | 3 +--
|
||||||
|
crypto/blockpriv.h | 1 -
|
||||||
|
include/crypto/block.h | 2 --
|
||||||
|
tests/unit/test-crypto-block.c | 4 ----
|
||||||
|
9 files changed, 6 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/block/crypto.c b/block/crypto.c
|
||||||
|
index 21eed909c1..4eed3ffa6a 100644
|
||||||
|
--- a/block/crypto.c
|
||||||
|
+++ b/block/crypto.c
|
||||||
|
@@ -363,7 +363,6 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||||
|
block_crypto_read_func,
|
||||||
|
bs,
|
||||||
|
cflags,
|
||||||
|
- 1,
|
||||||
|
errp);
|
||||||
|
|
||||||
|
if (!crypto->block) {
|
||||||
|
diff --git a/block/qcow.c b/block/qcow.c
|
||||||
|
index ca8e1d5ec8..c2f89db055 100644
|
||||||
|
--- a/block/qcow.c
|
||||||
|
+++ b/block/qcow.c
|
||||||
|
@@ -211,7 +211,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
|
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
||||||
|
}
|
||||||
|
s->crypto = qcrypto_block_open(crypto_opts, "encrypt.",
|
||||||
|
- NULL, NULL, cflags, 1, errp);
|
||||||
|
+ NULL, NULL, cflags, errp);
|
||||||
|
if (!s->crypto) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||||
|
index 0e8b2f7518..0ebd455dc8 100644
|
||||||
|
--- a/block/qcow2.c
|
||||||
|
+++ b/block/qcow2.c
|
||||||
|
@@ -321,7 +321,7 @@ qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||||
|
}
|
||||||
|
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
||||||
|
qcow2_crypto_hdr_read_func,
|
||||||
|
- bs, cflags, QCOW2_MAX_THREADS, errp);
|
||||||
|
+ bs, cflags, errp);
|
||||||
|
if (!s->crypto) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
@@ -1707,8 +1707,7 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
|
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
||||||
|
}
|
||||||
|
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
||||||
|
- NULL, NULL, cflags,
|
||||||
|
- QCOW2_MAX_THREADS, errp);
|
||||||
|
+ NULL, NULL, cflags, errp);
|
||||||
|
if (!s->crypto) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
|
||||||
|
index 3357852c0a..5b777c15d3 100644
|
||||||
|
--- a/crypto/block-luks.c
|
||||||
|
+++ b/crypto/block-luks.c
|
||||||
|
@@ -1189,7 +1189,6 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlockLUKS *luks = NULL;
|
||||||
|
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
|
||||||
|
index 02305058e3..42e9556e42 100644
|
||||||
|
--- a/crypto/block-qcow.c
|
||||||
|
+++ b/crypto/block-qcow.c
|
||||||
|
@@ -44,7 +44,6 @@ qcrypto_block_qcow_has_format(const uint8_t *buf G_GNUC_UNUSED,
|
||||||
|
static int
|
||||||
|
qcrypto_block_qcow_init(QCryptoBlock *block,
|
||||||
|
const char *keysecret,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
char *password;
|
||||||
|
@@ -100,7 +99,6 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc G_GNUC_UNUSED,
|
||||||
|
void *opaque G_GNUC_UNUSED,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
|
||||||
|
@@ -115,7 +113,7 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return qcrypto_block_qcow_init(block, options->u.qcow.key_secret,
|
||||||
|
- n_threads, errp);
|
||||||
|
+ errp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -135,7 +133,7 @@ qcrypto_block_qcow_create(QCryptoBlock *block,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* QCow2 has no special header, since everything is hardwired */
|
||||||
|
- return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, 1, errp);
|
||||||
|
+ return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/crypto/block.c b/crypto/block.c
|
||||||
|
index ba6d1cebc7..3bcc4270c3 100644
|
||||||
|
--- a/crypto/block.c
|
||||||
|
+++ b/crypto/block.c
|
||||||
|
@@ -53,7 +53,6 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
||||||
|
@@ -73,7 +72,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
block->driver = qcrypto_block_drivers[options->format];
|
||||||
|
|
||||||
|
if (block->driver->open(block, options, optprefix,
|
||||||
|
- readfunc, opaque, flags, n_threads, errp) < 0)
|
||||||
|
+ readfunc, opaque, flags, errp) < 0)
|
||||||
|
{
|
||||||
|
g_free(block);
|
||||||
|
return NULL;
|
||||||
|
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
|
||||||
|
index 4bf6043d5d..b8f77cb5eb 100644
|
||||||
|
--- a/crypto/blockpriv.h
|
||||||
|
+++ b/crypto/blockpriv.h
|
||||||
|
@@ -59,7 +59,6 @@ struct QCryptoBlockDriver {
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
int (*create)(QCryptoBlock *block,
|
||||||
|
diff --git a/include/crypto/block.h b/include/crypto/block.h
|
||||||
|
index 92e823c9f2..5b5d039800 100644
|
||||||
|
--- a/include/crypto/block.h
|
||||||
|
+++ b/include/crypto/block.h
|
||||||
|
@@ -76,7 +76,6 @@ typedef enum {
|
||||||
|
* @readfunc: callback for reading data from the volume
|
||||||
|
* @opaque: data to pass to @readfunc
|
||||||
|
* @flags: bitmask of QCryptoBlockOpenFlags values
|
||||||
|
- * @n_threads: allow concurrent I/O from up to @n_threads threads
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Create a new block encryption object for an existing
|
||||||
|
@@ -113,7 +112,6 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
diff --git a/tests/unit/test-crypto-block.c b/tests/unit/test-crypto-block.c
|
||||||
|
index 6cfc817a92..42cfab6067 100644
|
||||||
|
--- a/tests/unit/test-crypto-block.c
|
||||||
|
+++ b/tests/unit/test-crypto-block.c
|
||||||
|
@@ -303,7 +303,6 @@ static void test_block(gconstpointer opaque)
|
||||||
|
test_block_read_func,
|
||||||
|
&header,
|
||||||
|
0,
|
||||||
|
- 1,
|
||||||
|
NULL);
|
||||||
|
g_assert(blk == NULL);
|
||||||
|
|
||||||
|
@@ -312,7 +311,6 @@ static void test_block(gconstpointer opaque)
|
||||||
|
test_block_read_func,
|
||||||
|
&header,
|
||||||
|
QCRYPTO_BLOCK_OPEN_NO_IO,
|
||||||
|
- 1,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
g_assert(qcrypto_block_get_cipher(blk) == NULL);
|
||||||
|
@@ -327,7 +325,6 @@ static void test_block(gconstpointer opaque)
|
||||||
|
test_block_read_func,
|
||||||
|
&header,
|
||||||
|
0,
|
||||||
|
- 1,
|
||||||
|
&error_abort);
|
||||||
|
g_assert(blk);
|
||||||
|
|
||||||
|
@@ -384,7 +381,6 @@ test_luks_bad_header(gconstpointer data)
|
||||||
|
test_block_read_func,
|
||||||
|
&buf,
|
||||||
|
0,
|
||||||
|
- 1,
|
||||||
|
&err);
|
||||||
|
g_assert(!blk);
|
||||||
|
g_assert(err);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,120 @@
|
|||||||
|
From 41c4083269ec772b406c6c57b496ca2011f928c7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||||
|
Date: Tue, 9 Jul 2024 23:08:59 -0400
|
||||||
|
Subject: [PATCH 2/2] hw/arm/virt: Avoid unexpected warning from Linux guest on
|
||||||
|
host with Fujitsu CPUs
|
||||||
|
|
||||||
|
RH-Author: zhenyzha <None>
|
||||||
|
RH-MergeRequest: 256: hw/arm/virt: Avoid unexpected warning from Linux guest on host with Fujitsu CPUs
|
||||||
|
RH-Jira: RHEL-39936
|
||||||
|
RH-Acked-by: Gavin Shan <gshan@redhat.com>
|
||||||
|
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
||||||
|
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
||||||
|
RH-Commit: [1/1] fdf156fd05b219a06e2e2ca409fff0f728c1e2cf (zhenyzha/qemu-kvm)
|
||||||
|
|
||||||
|
JIRA: https://issues.redhat.com/browse/RHEL-39936
|
||||||
|
|
||||||
|
Multiple warning messages and corresponding backtraces are observed when Linux
|
||||||
|
guest is booted on the host with Fujitsu CPUs. One of them is shown as below.
|
||||||
|
|
||||||
|
[ 0.032443] ------------[ cut here ]------------
|
||||||
|
[ 0.032446] uart-pl011 9000000.pl011: ARCH_DMA_MINALIGN smaller than
|
||||||
|
CTR_EL0.CWG (128 < 256)
|
||||||
|
[ 0.032454] WARNING: CPU: 0 PID: 1 at arch/arm64/mm/dma-mapping.c:54
|
||||||
|
arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032470] Modules linked in:
|
||||||
|
[ 0.032475] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0-452.el9.aarch64
|
||||||
|
[ 0.032481] Hardware name: linux,dummy-virt (DT)
|
||||||
|
[ 0.032484] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
|
||||||
|
[ 0.032490] pc : arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032496] lr : arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032501] sp : ffff80008003b860
|
||||||
|
[ 0.032503] x29: ffff80008003b860 x28: 0000000000000000 x27: ffffaae4b949049c
|
||||||
|
[ 0.032510] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
|
||||||
|
[ 0.032517] x23: 0000000000000100 x22: 0000000000000000 x21: 0000000000000000
|
||||||
|
[ 0.032523] x20: 0000000100000000 x19: ffff2f06c02ea400 x18: ffffffffffffffff
|
||||||
|
[ 0.032529] x17: 00000000208a5f76 x16: 000000006589dbcb x15: ffffaae4ba071c89
|
||||||
|
[ 0.032535] x14: 0000000000000000 x13: ffffaae4ba071c84 x12: 455f525443206e61
|
||||||
|
[ 0.032541] x11: 68742072656c6c61 x10: 0000000000000029 x9 : ffffaae4b7d21da4
|
||||||
|
[ 0.032547] x8 : 0000000000000029 x7 : 4c414e494d5f414d x6 : 0000000000000029
|
||||||
|
[ 0.032553] x5 : 000000000000000f x4 : ffffaae4b9617a00 x3 : 0000000000000001
|
||||||
|
[ 0.032558] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff2f06c029be40
|
||||||
|
[ 0.032564] Call trace:
|
||||||
|
[ 0.032566] arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032572] of_dma_configure_id+0x138/0x300
|
||||||
|
[ 0.032591] amba_dma_configure+0x34/0xc0
|
||||||
|
[ 0.032600] really_probe+0x78/0x3dc
|
||||||
|
[ 0.032614] __driver_probe_device+0x108/0x160
|
||||||
|
[ 0.032619] driver_probe_device+0x44/0x114
|
||||||
|
[ 0.032624] __device_attach_driver+0xb8/0x14c
|
||||||
|
[ 0.032629] bus_for_each_drv+0x88/0xe4
|
||||||
|
[ 0.032634] __device_attach+0xb0/0x1e0
|
||||||
|
[ 0.032638] device_initial_probe+0x18/0x20
|
||||||
|
[ 0.032643] bus_probe_device+0xa8/0xb0
|
||||||
|
[ 0.032648] device_add+0x4b4/0x6c0
|
||||||
|
[ 0.032652] amba_device_try_add.part.0+0x48/0x360
|
||||||
|
[ 0.032657] amba_device_add+0x104/0x144
|
||||||
|
[ 0.032662] of_amba_device_create.isra.0+0x100/0x1c4
|
||||||
|
[ 0.032666] of_platform_bus_create+0x294/0x35c
|
||||||
|
[ 0.032669] of_platform_populate+0x5c/0x150
|
||||||
|
[ 0.032672] of_platform_default_populate_init+0xd0/0xec
|
||||||
|
[ 0.032697] do_one_initcall+0x4c/0x2e0
|
||||||
|
[ 0.032701] do_initcalls+0x100/0x13c
|
||||||
|
[ 0.032707] kernel_init_freeable+0x1c8/0x21c
|
||||||
|
[ 0.032712] kernel_init+0x28/0x140
|
||||||
|
[ 0.032731] ret_from_fork+0x10/0x20
|
||||||
|
[ 0.032735] ---[ end trace 0000000000000000 ]---
|
||||||
|
|
||||||
|
In Linux, a check is applied to every device which is exposed through
|
||||||
|
device-tree node. The warning message is raised when the device isn't
|
||||||
|
DMA coherent and the cache line size is larger than ARCH_DMA_MINALIGN
|
||||||
|
(128 bytes). The cache line is sorted from CTR_EL0[CWG], which corresponds
|
||||||
|
to 256 bytes on the guest CPUs. The DMA coherent capability is claimed
|
||||||
|
through 'dma-coherent' in their device-tree nodes or parent nodes.
|
||||||
|
This happens even when the device doesn't implement or use DMA at all,
|
||||||
|
for legacy reasons.
|
||||||
|
|
||||||
|
Fix the issue by adding 'dma-coherent' property to the device-tree root
|
||||||
|
node, meaning all devices are capable of DMA coherent by default.
|
||||||
|
This both suppresses the spurious kernel warnings and also guards
|
||||||
|
against possible future QEMU bugs where we add a DMA-capable device
|
||||||
|
and forget to mark it as dma-coherent.
|
||||||
|
|
||||||
|
Signed-off-by: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||||
|
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||||
|
Reviewed-by: Donald Dutile <ddutile@redhat.com
|
||||||
|
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||||
|
Message-id: 20240612020506.307793-1-zhenyzha@redhat.com
|
||||||
|
[PMM: tweaked commit message]
|
||||||
|
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
(cherry picked from commit dda533087ad5559674ff486e7031c88dc01e0abd)
|
||||||
|
Signed-off-by: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/arm/virt.c | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||||
|
index 3f0496cdb9..6ece67f11d 100644
|
||||||
|
--- a/hw/arm/virt.c
|
||||||
|
+++ b/hw/arm/virt.c
|
||||||
|
@@ -330,6 +330,17 @@ static void create_fdt(VirtMachineState *vms)
|
||||||
|
qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
|
||||||
|
qemu_fdt_setprop_string(fdt, "/", "model", "linux,dummy-virt");
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * For QEMU, all DMA is coherent. Advertising this in the root node
|
||||||
|
+ * has two benefits:
|
||||||
|
+ *
|
||||||
|
+ * - It avoids potential bugs where we forget to mark a DMA
|
||||||
|
+ * capable device as being dma-coherent
|
||||||
|
+ * - It avoids spurious warnings from the Linux kernel about
|
||||||
|
+ * devices which can't do DMA at all
|
||||||
|
+ */
|
||||||
|
+ qemu_fdt_setprop(fdt, "/", "dma-coherent", NULL, 0);
|
||||||
|
+
|
||||||
|
/* /chosen must exist for load_dtb to fill in necessary properties later */
|
||||||
|
qemu_fdt_add_subnode(fdt, "/chosen");
|
||||||
|
if (vms->dtb_randomness) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,59 @@
|
|||||||
|
From e3360c415f7de923d27c3167260a93cb679afabe Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Auger <eric.auger@redhat.com>
|
||||||
|
Date: Mon, 6 May 2024 15:09:43 +0200
|
||||||
|
Subject: [PATCH 1/2] hw/arm/virt: Fix spurious call to arm_virt_compat_set()
|
||||||
|
|
||||||
|
RH-Author: Eric Auger <eric.auger@redhat.com>
|
||||||
|
RH-MergeRequest: 238: hw/arm/virt: Fix spurious call to arm_virt_compat_set()
|
||||||
|
RH-Jira: RHEL-34945
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
||||||
|
RH-Acked-by: Gavin Shan <gshan@redhat.com>
|
||||||
|
RH-Commit: [1/1] a858a3e1dff12b28e14f7e4bd2b896a9f06eacbb (eauger1/centos-qemu-kvm)
|
||||||
|
|
||||||
|
JIRA: https://issues.redhat.com/browse/RHEL-34945
|
||||||
|
Status: RHEL-only
|
||||||
|
|
||||||
|
Downstream, we apply arm_rhel_compat in place of arm_virt_compat.
|
||||||
|
This is done though arm_rhel_compat_set() transparently called in
|
||||||
|
DEFINE_RHEL_MACHINE_LATEST(). So there is no need to call
|
||||||
|
arm_virt_compat_set() in rhel_machine_class_init(). Besides
|
||||||
|
this triggers a "GLib: g_ptr_array_add: assertion 'rarray' failed"
|
||||||
|
warning.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
||||||
|
---
|
||||||
|
hw/arm/virt.c | 3 +--
|
||||||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||||
|
index f1af9495c6..3f0496cdb9 100644
|
||||||
|
--- a/hw/arm/virt.c
|
||||||
|
+++ b/hw/arm/virt.c
|
||||||
|
@@ -85,6 +85,7 @@
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
#include "qemu/guest-random.h"
|
||||||
|
|
||||||
|
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||||
|
static GlobalProperty arm_virt_compat[] = {
|
||||||
|
{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
|
||||||
|
};
|
||||||
|
@@ -101,7 +102,6 @@ static void arm_virt_compat_set(MachineClass *mc)
|
||||||
|
arm_virt_compat_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||||
|
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
|
||||||
|
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
|
||||||
|
void *data) \
|
||||||
|
@@ -3536,7 +3536,6 @@ static void rhel_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
|
||||||
|
- arm_virt_compat_set(mc);
|
||||||
|
|
||||||
|
mc->family = "virt-rhel-Z";
|
||||||
|
mc->init = machvirt_init;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,73 @@
|
|||||||
|
From e74980be81d641736ea9d44d0fe9af02af63a220 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:40 -0500
|
||||||
|
Subject: [PATCH 083/100] hw/i386: Add support for loading BIOS using
|
||||||
|
guest_memfd
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [83/91] 7b77d212ef7d83b66ad9d8348179ee84e64fb911 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When guest_memfd is enabled, the BIOS is generally part of the initial
|
||||||
|
encrypted guest image and will be accessed as private guest memory. Add
|
||||||
|
the necessary changes to set up the associated RAM region with a
|
||||||
|
guest_memfd backend to allow for this.
|
||||||
|
|
||||||
|
Current support centers around using -bios to load the BIOS data.
|
||||||
|
Support for loading the BIOS via pflash requires additional enablement
|
||||||
|
since those interfaces rely on the use of ROM memory regions which make
|
||||||
|
use of the KVM_MEM_READONLY memslot flag, which is not supported for
|
||||||
|
guest_memfd-backed memslots.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-29-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit fc7a69e177e4ba26d11fcf47b853f85115b35a11)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86-common.c | 17 ++++++++++++-----
|
||||||
|
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
|
||||||
|
index 35fe6eabea..6cbb76c25c 100644
|
||||||
|
--- a/hw/i386/x86-common.c
|
||||||
|
+++ b/hw/i386/x86-common.c
|
||||||
|
@@ -969,8 +969,13 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
(bios_size % 65536) != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
}
|
||||||
|
- memory_region_init_ram(&x86ms->bios, NULL, "pc.bios", bios_size,
|
||||||
|
- &error_fatal);
|
||||||
|
+ if (machine_require_guest_memfd(MACHINE(x86ms))) {
|
||||||
|
+ memory_region_init_ram_guest_memfd(&x86ms->bios, NULL, "pc.bios",
|
||||||
|
+ bios_size, &error_fatal);
|
||||||
|
+ } else {
|
||||||
|
+ memory_region_init_ram(&x86ms->bios, NULL, "pc.bios",
|
||||||
|
+ bios_size, &error_fatal);
|
||||||
|
+ }
|
||||||
|
if (sev_enabled()) {
|
||||||
|
/*
|
||||||
|
* The concept of a "reset" simply doesn't exist for
|
||||||
|
@@ -991,9 +996,11 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
}
|
||||||
|
g_free(filename);
|
||||||
|
|
||||||
|
- /* map the last 128KB of the BIOS in ISA space */
|
||||||
|
- x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
|
||||||
|
- !isapc_ram_fw);
|
||||||
|
+ if (!machine_require_guest_memfd(MACHINE(x86ms))) {
|
||||||
|
+ /* map the last 128KB of the BIOS in ISA space */
|
||||||
|
+ x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
|
||||||
|
+ !isapc_ram_fw);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,106 @@
|
|||||||
|
From c1e615d6b8f609b72a94ffe6d31a9848a41744ef Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Tue, 30 Apr 2024 17:06:39 +0200
|
||||||
|
Subject: [PATCH 038/100] hw/i386: Have x86_bios_rom_init() take
|
||||||
|
X86MachineState rather than MachineState
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [38/91] 59f388b1dffc5d0aa2f0fff768194d755bc3efbb (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
The function creates and leaks two MemoryRegion objects regarding the BIOS which
|
||||||
|
will be moved into X86MachineState in the next steps to avoid the leakage.
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Message-ID: <20240430150643.111976-3-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 848351840148f8c3b53ddf6210194506547d3ffd)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/microvm.c | 2 +-
|
||||||
|
hw/i386/pc_sysfw.c | 4 ++--
|
||||||
|
hw/i386/x86.c | 4 ++--
|
||||||
|
include/hw/i386/x86.h | 2 +-
|
||||||
|
4 files changed, 6 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
|
||||||
|
index 61a772dfe6..fec63cacfa 100644
|
||||||
|
--- a/hw/i386/microvm.c
|
||||||
|
+++ b/hw/i386/microvm.c
|
||||||
|
@@ -278,7 +278,7 @@ static void microvm_devices_init(MicrovmMachineState *mms)
|
||||||
|
default_firmware = x86_machine_is_acpi_enabled(x86ms)
|
||||||
|
? MICROVM_BIOS_FILENAME
|
||||||
|
: MICROVM_QBOOT_FILENAME;
|
||||||
|
- x86_bios_rom_init(MACHINE(mms), default_firmware, get_system_memory(), true);
|
||||||
|
+ x86_bios_rom_init(x86ms, default_firmware, get_system_memory(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void microvm_memory_init(MicrovmMachineState *mms)
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 3efabbbab2..ef7dea9798 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -206,7 +206,7 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||||
|
BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)];
|
||||||
|
|
||||||
|
if (!pcmc->pci_enabled) {
|
||||||
|
- x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, true);
|
||||||
|
+ x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -227,7 +227,7 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (!pflash_blk[0]) {
|
||||||
|
/* Machine property pflash0 not set, use ROM mode */
|
||||||
|
- x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, false);
|
||||||
|
+ x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, false);
|
||||||
|
} else {
|
||||||
|
if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
|
||||||
|
/*
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 2a4f3ee285..6d3c72f124 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1128,7 +1128,7 @@ void x86_load_linux(X86MachineState *x86ms,
|
||||||
|
nb_option_roms++;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
+void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw)
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
@@ -1138,7 +1138,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
/* BIOS load */
|
||||||
|
- bios_name = ms->firmware ?: default_firmware;
|
||||||
|
+ bios_name = MACHINE(x86ms)->firmware ?: default_firmware;
|
||||||
|
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||||
|
if (filename) {
|
||||||
|
bios_size = get_image_size(filename);
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index 4dc30dcb4d..cb07618d19 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -116,7 +116,7 @@ void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
|
void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
|
DeviceState *dev, Error **errp);
|
||||||
|
|
||||||
|
-void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
+void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw);
|
||||||
|
|
||||||
|
void x86_load_linux(X86MachineState *x86ms,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,51 @@
|
|||||||
|
From 7bb1f124413891bc5d2187f12cd19da6e794904b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 3 Apr 2024 10:59:53 -0400
|
||||||
|
Subject: [PATCH 010/100] hw/i386/acpi: Set PCAT_COMPAT bit only when pic is
|
||||||
|
not disabled
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [10/91] 62110e4bf52cb3e106c8d2a902bbd31548beba00 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
A value 1 of PCAT_COMPAT (bit 0) of MADT.Flags indicates that the system
|
||||||
|
also has a PC-AT-compatible dual-8259 setup, i.e., the PIC. When PIC
|
||||||
|
is not enabled (pic=off) for x86 machine, the PCAT_COMPAT bit needs to
|
||||||
|
be cleared. The PIC probe should then print:
|
||||||
|
|
||||||
|
[ 0.155970] Using NULL legacy PIC
|
||||||
|
|
||||||
|
However, no such log printed in guest kernel unless PCAT_COMPAT is
|
||||||
|
cleared.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240403145953.3082491-1-xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 292dd287e78e0cbafde9d1522c729349d132d844)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/acpi-common.c | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
|
||||||
|
index 20f19269da..0cc2919bb8 100644
|
||||||
|
--- a/hw/i386/acpi-common.c
|
||||||
|
+++ b/hw/i386/acpi-common.c
|
||||||
|
@@ -107,7 +107,9 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
|
||||||
|
acpi_table_begin(&table, table_data);
|
||||||
|
/* Local APIC Address */
|
||||||
|
build_append_int_noprefix(table_data, APIC_DEFAULT_ADDRESS, 4);
|
||||||
|
- build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
|
||||||
|
+ /* Flags. bit 0: PCAT_COMPAT */
|
||||||
|
+ build_append_int_noprefix(table_data,
|
||||||
|
+ x86ms->pic != ON_OFF_AUTO_OFF ? 1 : 0 , 4);
|
||||||
|
|
||||||
|
for (i = 0; i < apic_ids->len; i++) {
|
||||||
|
pc_madt_cpu_entry(i, apic_ids, table_data, false);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,164 @@
|
|||||||
|
From fd6de3c5e97bdf13a39342fc71815a20c66867ae Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:07 +0200
|
||||||
|
Subject: [PATCH 043/100] hw/i386/pc_sysfw: Alias rather than copy isa-bios
|
||||||
|
region
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [43/91] f64dab2a091838a10a9b94e3d09ea11432b0809f (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
In the -bios case the "isa-bios" memory region is an alias to the BIOS mapped
|
||||||
|
to the top of the 4G memory boundary. Do the same in the -pflash case, but only
|
||||||
|
for new machine versions for migration compatibility. This establishes common
|
||||||
|
behavior and makes pflash commands work in the "isa-bios" region which some
|
||||||
|
real-world legacy bioses rely on.
|
||||||
|
|
||||||
|
Note that in the sev_enabled() case, the "isa-bios" memory region in the -pflash
|
||||||
|
case will now also point to encrypted memory, just like it already does in the
|
||||||
|
-bios case.
|
||||||
|
|
||||||
|
When running `info mtree` before and after this commit with
|
||||||
|
`qemu-system-x86_64 -S -drive \
|
||||||
|
if=pflash,format=raw,readonly=on,file=/usr/share/qemu/bios-256k.bin` and running
|
||||||
|
`diff -u before.mtree after.mtree` results in the following changes in the
|
||||||
|
memory tree:
|
||||||
|
|
||||||
|
| --- before.mtree
|
||||||
|
| +++ after.mtree
|
||||||
|
| @@ -71,7 +71,7 @@
|
||||||
|
| 0000000000000000-ffffffffffffffff (prio -1, i/o): pci
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): vga-lowmem
|
||||||
|
| 00000000000c0000-00000000000dffff (prio 1, rom): pc.rom
|
||||||
|
| - 00000000000e0000-00000000000fffff (prio 1, rom): isa-bios
|
||||||
|
| + 00000000000e0000-00000000000fffff (prio 1, romd): alias isa-bios @system.flash0 0000000000020000-000000000003ffff
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): alias smram-region @pci 00000000000a0000-00000000000bffff
|
||||||
|
| 00000000000c0000-00000000000c3fff (prio 1, i/o): alias pam-pci @pci 00000000000c0000-00000000000c3fff
|
||||||
|
| 00000000000c4000-00000000000c7fff (prio 1, i/o): alias pam-pci @pci 00000000000c4000-00000000000c7fff
|
||||||
|
| @@ -108,7 +108,7 @@
|
||||||
|
| 0000000000000000-ffffffffffffffff (prio -1, i/o): pci
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): vga-lowmem
|
||||||
|
| 00000000000c0000-00000000000dffff (prio 1, rom): pc.rom
|
||||||
|
| - 00000000000e0000-00000000000fffff (prio 1, rom): isa-bios
|
||||||
|
| + 00000000000e0000-00000000000fffff (prio 1, romd): alias isa-bios @system.flash0 0000000000020000-000000000003ffff
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): alias smram-region @pci 00000000000a0000-00000000000bffff
|
||||||
|
| 00000000000c0000-00000000000c3fff (prio 1, i/o): alias pam-pci @pci 00000000000c0000-00000000000c3fff
|
||||||
|
| 00000000000c4000-00000000000c7fff (prio 1, i/o): alias pam-pci @pci 00000000000c4000-00000000000c7fff
|
||||||
|
| @@ -131,11 +131,14 @@
|
||||||
|
| memory-region: pc.ram
|
||||||
|
| 0000000000000000-0000000007ffffff (prio 0, ram): pc.ram
|
||||||
|
|
|
||||||
|
| +memory-region: system.flash0
|
||||||
|
| + 00000000fffc0000-00000000ffffffff (prio 0, romd): system.flash0
|
||||||
|
| +
|
||||||
|
| memory-region: pci
|
||||||
|
| 0000000000000000-ffffffffffffffff (prio -1, i/o): pci
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): vga-lowmem
|
||||||
|
| 00000000000c0000-00000000000dffff (prio 1, rom): pc.rom
|
||||||
|
| - 00000000000e0000-00000000000fffff (prio 1, rom): isa-bios
|
||||||
|
| + 00000000000e0000-00000000000fffff (prio 1, romd): alias isa-bios @system.flash0 0000000000020000-000000000003ffff
|
||||||
|
|
|
||||||
|
| memory-region: smram
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 0, ram): alias smram-low @pc.ram 00000000000a0000-00000000000bffff
|
||||||
|
|
||||||
|
Note that in both cases the "system" memory region contains the entry
|
||||||
|
|
||||||
|
00000000fffc0000-00000000ffffffff (prio 0, romd): system.flash0
|
||||||
|
|
||||||
|
but the "system.flash0" memory region only appears standalone when "isa-bios" is
|
||||||
|
an alias.
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-7-shentey@gmail.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a44ea3fa7f2aa1d809fdca1b84a52695b53d8ad0)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 1 +
|
||||||
|
hw/i386/pc_piix.c | 1 +
|
||||||
|
hw/i386/pc_q35.c | 1 +
|
||||||
|
hw/i386/pc_sysfw.c | 8 +++++++-
|
||||||
|
include/hw/i386/pc.h | 1 +
|
||||||
|
5 files changed, 11 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index 1a34bc4522..660a59c63b 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -1967,6 +1967,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
pcmc->has_reserved_memory = true;
|
||||||
|
pcmc->enforce_aligned_dimm = true;
|
||||||
|
pcmc->enforce_amd_1tb_hole = true;
|
||||||
|
+ pcmc->isa_bios_alias = true;
|
||||||
|
/* BIOS ACPI tables: 128K. Other BIOS datastructures: less than 4K reported
|
||||||
|
* to be used at the moment, 32K should be enough for a while. */
|
||||||
|
pcmc->acpi_data_size = 0x20000 + 0x8000;
|
||||||
|
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||||
|
index bef3e8b73e..dbb7f2ed17 100644
|
||||||
|
--- a/hw/i386/pc_piix.c
|
||||||
|
+++ b/hw/i386/pc_piix.c
|
||||||
|
@@ -975,6 +975,7 @@ static void pc_machine_rhel7_options(MachineClass *m)
|
||||||
|
m->alias = "pc";
|
||||||
|
m->is_default = 1;
|
||||||
|
m->smp_props.prefer_sockets = true;
|
||||||
|
+ pcmc->isa_bios_alias = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pc_init_rhel760(MachineState *machine)
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index dedc86eec9..f9900ad798 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -735,6 +735,7 @@ static void pc_q35_machine_rhel940_options(MachineClass *m)
|
||||||
|
m->desc = "RHEL-9.4.0 PC (Q35 + ICH9, 2009)";
|
||||||
|
pcmc->smbios_stream_product = "RHEL";
|
||||||
|
pcmc->smbios_stream_version = "9.4.0";
|
||||||
|
+ pcmc->isa_bios_alias = false;
|
||||||
|
|
||||||
|
compat_props_add(m->compat_props, pc_rhel_9_5_compat,
|
||||||
|
pc_rhel_9_5_compat_len);
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 82d37cb376..ac88ad4eb9 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -135,6 +135,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
MemoryRegion *rom_memory)
|
||||||
|
{
|
||||||
|
X86MachineState *x86ms = X86_MACHINE(pcms);
|
||||||
|
+ PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
||||||
|
hwaddr total_size = 0;
|
||||||
|
int i;
|
||||||
|
BlockBackend *blk;
|
||||||
|
@@ -184,7 +185,12 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
- pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
+ if (pcmc->isa_bios_alias) {
|
||||||
|
+ x86_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem,
|
||||||
|
+ true);
|
||||||
|
+ } else {
|
||||||
|
+ pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
if (sev_enabled()) {
|
||||||
|
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||||
|
index 467e7fb52f..3f53ec73ac 100644
|
||||||
|
--- a/include/hw/i386/pc.h
|
||||||
|
+++ b/include/hw/i386/pc.h
|
||||||
|
@@ -122,6 +122,7 @@ struct PCMachineClass {
|
||||||
|
bool enforce_aligned_dimm;
|
||||||
|
bool broken_reserved_end;
|
||||||
|
bool enforce_amd_1tb_hole;
|
||||||
|
+ bool isa_bios_alias;
|
||||||
|
|
||||||
|
/* generate legacy CPU hotplug AML */
|
||||||
|
bool legacy_cpu_hotplug;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
From 9bf1d368c4b53139db39649833d475e097fc98d1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Mon, 22 Apr 2024 22:06:22 +0200
|
||||||
|
Subject: [PATCH 039/100] hw/i386/pc_sysfw: Remove unused parameter from
|
||||||
|
pc_isa_bios_init()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [39/91] c0019dc2706a8e3f40486fd4a4c0dd1fbe23237b (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Message-ID: <20240422200625.2768-2-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit f4b63768b91811cdcf1fb7b270587123251dfea5)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 5 ++---
|
||||||
|
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index ef7dea9798..59c7a81692 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -41,8 +41,7 @@
|
||||||
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
|
|
||||||
|
static void pc_isa_bios_init(MemoryRegion *rom_memory,
|
||||||
|
- MemoryRegion *flash_mem,
|
||||||
|
- int ram_size)
|
||||||
|
+ MemoryRegion *flash_mem)
|
||||||
|
{
|
||||||
|
int isa_bios_size;
|
||||||
|
MemoryRegion *isa_bios;
|
||||||
|
@@ -186,7 +185,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
- pc_isa_bios_init(rom_memory, flash_mem, size);
|
||||||
|
+ pc_isa_bios_init(rom_memory, flash_mem);
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
if (sev_enabled()) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,158 @@
|
|||||||
|
From e6472ff46cbed97c2a238a8ef7d321351931333a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:30 -0500
|
||||||
|
Subject: [PATCH 070/100] hw/i386/sev: Add function to get SEV metadata from
|
||||||
|
OVMF header
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [70/91] ba818dade96119c8a51ca1fb222f4f69e2752396 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
A recent version of OVMF expanded the reset vector GUID list to add
|
||||||
|
SEV-specific metadata GUID. The SEV metadata describes the reserved
|
||||||
|
memory regions such as the secrets and CPUID page used during the SEV-SNP
|
||||||
|
guest launch.
|
||||||
|
|
||||||
|
The pc_system_get_ovmf_sev_metadata_ptr() is used to retieve the SEV
|
||||||
|
metadata pointer from the OVMF GUID list.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-19-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit f3c30c575d34122573b7370a7da5ca3a27dde481)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 4 ++++
|
||||||
|
include/hw/i386/pc.h | 26 ++++++++++++++++++++++++++
|
||||||
|
target/i386/sev-sysemu-stub.c | 4 ++++
|
||||||
|
target/i386/sev.c | 32 ++++++++++++++++++++++++++++++++
|
||||||
|
target/i386/sev.h | 2 ++
|
||||||
|
5 files changed, 68 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index ac88ad4eb9..9b8671c441 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -260,6 +260,10 @@ void x86_firmware_configure(void *ptr, int size)
|
||||||
|
pc_system_parse_ovmf_flash(ptr, size);
|
||||||
|
|
||||||
|
if (sev_enabled()) {
|
||||||
|
+
|
||||||
|
+ /* Copy the SEV metadata table (if it exists) */
|
||||||
|
+ pc_system_parse_sev_metadata(ptr, size);
|
||||||
|
+
|
||||||
|
ret = sev_es_save_reset_vector(ptr, size);
|
||||||
|
if (ret) {
|
||||||
|
error_report("failed to locate and/or save reset vector");
|
||||||
|
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||||
|
index 3f53ec73ac..94b49310f5 100644
|
||||||
|
--- a/include/hw/i386/pc.h
|
||||||
|
+++ b/include/hw/i386/pc.h
|
||||||
|
@@ -167,6 +167,32 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
|
||||||
|
#define PCI_HOST_ABOVE_4G_MEM_SIZE "above-4g-mem-size"
|
||||||
|
#define PCI_HOST_PROP_SMM_RANGES "smm-ranges"
|
||||||
|
|
||||||
|
+typedef enum {
|
||||||
|
+ SEV_DESC_TYPE_UNDEF,
|
||||||
|
+ /* The section contains the region that must be validated by the VMM. */
|
||||||
|
+ SEV_DESC_TYPE_SNP_SEC_MEM,
|
||||||
|
+ /* The section contains the SNP secrets page */
|
||||||
|
+ SEV_DESC_TYPE_SNP_SECRETS,
|
||||||
|
+ /* The section contains address that can be used as a CPUID page */
|
||||||
|
+ SEV_DESC_TYPE_CPUID,
|
||||||
|
+
|
||||||
|
+} ovmf_sev_metadata_desc_type;
|
||||||
|
+
|
||||||
|
+typedef struct __attribute__((__packed__)) OvmfSevMetadataDesc {
|
||||||
|
+ uint32_t base;
|
||||||
|
+ uint32_t len;
|
||||||
|
+ ovmf_sev_metadata_desc_type type;
|
||||||
|
+} OvmfSevMetadataDesc;
|
||||||
|
+
|
||||||
|
+typedef struct __attribute__((__packed__)) OvmfSevMetadata {
|
||||||
|
+ uint8_t signature[4];
|
||||||
|
+ uint32_t len;
|
||||||
|
+ uint32_t version;
|
||||||
|
+ uint32_t num_desc;
|
||||||
|
+ OvmfSevMetadataDesc descs[];
|
||||||
|
+} OvmfSevMetadata;
|
||||||
|
+
|
||||||
|
+OvmfSevMetadata *pc_system_get_ovmf_sev_metadata_ptr(void);
|
||||||
|
|
||||||
|
void pc_pci_as_mapping_init(MemoryRegion *system_memory,
|
||||||
|
MemoryRegion *pci_address_space);
|
||||||
|
diff --git a/target/i386/sev-sysemu-stub.c b/target/i386/sev-sysemu-stub.c
|
||||||
|
index 96e1c15cc3..fc1c57c411 100644
|
||||||
|
--- a/target/i386/sev-sysemu-stub.c
|
||||||
|
+++ b/target/i386/sev-sysemu-stub.c
|
||||||
|
@@ -67,3 +67,7 @@ void hmp_info_sev(Monitor *mon, const QDict *qdict)
|
||||||
|
{
|
||||||
|
monitor_printf(mon, "SEV is not available in this QEMU\n");
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void pc_system_parse_sev_metadata(uint8_t *flash_ptr, size_t flash_size)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index e84e4395a5..17281bb2c7 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -597,6 +597,38 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
|
||||||
|
return sev_get_capabilities(errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static OvmfSevMetadata *ovmf_sev_metadata_table;
|
||||||
|
+
|
||||||
|
+#define OVMF_SEV_META_DATA_GUID "dc886566-984a-4798-A75e-5585a7bf67cc"
|
||||||
|
+typedef struct __attribute__((__packed__)) OvmfSevMetadataOffset {
|
||||||
|
+ uint32_t offset;
|
||||||
|
+} OvmfSevMetadataOffset;
|
||||||
|
+
|
||||||
|
+OvmfSevMetadata *pc_system_get_ovmf_sev_metadata_ptr(void)
|
||||||
|
+{
|
||||||
|
+ return ovmf_sev_metadata_table;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void pc_system_parse_sev_metadata(uint8_t *flash_ptr, size_t flash_size)
|
||||||
|
+{
|
||||||
|
+ OvmfSevMetadata *metadata;
|
||||||
|
+ OvmfSevMetadataOffset *data;
|
||||||
|
+
|
||||||
|
+ if (!pc_system_ovmf_table_find(OVMF_SEV_META_DATA_GUID, (uint8_t **)&data,
|
||||||
|
+ NULL)) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ metadata = (OvmfSevMetadata *)(flash_ptr + flash_size - data->offset);
|
||||||
|
+ if (memcmp(metadata->signature, "ASEV", 4) != 0 ||
|
||||||
|
+ metadata->len < sizeof(OvmfSevMetadata) ||
|
||||||
|
+ metadata->len > flash_size - data->offset) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ovmf_sev_metadata_table = g_memdup2(metadata, metadata->len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static SevAttestationReport *sev_get_attestation_report(const char *mnonce,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index 5dc4767b1e..cc12824dd6 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -66,4 +66,6 @@ int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||||
|
int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size);
|
||||||
|
void sev_es_set_reset_vector(CPUState *cpu);
|
||||||
|
|
||||||
|
+void pc_system_parse_sev_metadata(uint8_t *flash_ptr, size_t flash_size);
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,165 @@
|
|||||||
|
From 226cf6c3d3e2fd1a35422043dbe0b73d1216df83 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:36 -0500
|
||||||
|
Subject: [PATCH 073/100] hw/i386/sev: Add support to encrypt BIOS when SEV-SNP
|
||||||
|
is enabled
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [73/91] 844afd322c12c3e8992cf6ec692c94e70747bd0c (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
As with SEV, an SNP guest requires that the BIOS be part of the initial
|
||||||
|
encrypted/measured guest payload. Extend sev_encrypt_flash() to handle
|
||||||
|
the SNP case and plumb through the GPA of the BIOS location since this
|
||||||
|
is needed for SNP.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-25-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 77d1abd91e5352ad30ae2f83790f95fa6a3c0b6b)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 12 +++++++-----
|
||||||
|
hw/i386/x86-common.c | 2 +-
|
||||||
|
include/hw/i386/x86.h | 2 +-
|
||||||
|
target/i386/sev-sysemu-stub.c | 2 +-
|
||||||
|
target/i386/sev.c | 5 +++--
|
||||||
|
target/i386/sev.h | 2 +-
|
||||||
|
6 files changed, 14 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 9b8671c441..7cdbafc8d2 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -148,6 +148,8 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
|
||||||
|
+ hwaddr gpa;
|
||||||
|
+
|
||||||
|
system_flash = pcms->flash[i];
|
||||||
|
blk = pflash_cfi01_get_blk(system_flash);
|
||||||
|
if (!blk) {
|
||||||
|
@@ -177,11 +179,11 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
}
|
||||||
|
|
||||||
|
total_size += size;
|
||||||
|
+ gpa = 0x100000000ULL - total_size; /* where the flash is mapped */
|
||||||
|
qdev_prop_set_uint32(DEVICE(system_flash), "num-blocks",
|
||||||
|
size / FLASH_SECTOR_SIZE);
|
||||||
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(system_flash), &error_fatal);
|
||||||
|
- sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0,
|
||||||
|
- 0x100000000ULL - total_size);
|
||||||
|
+ sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, gpa);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
@@ -196,7 +198,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
if (sev_enabled()) {
|
||||||
|
flash_ptr = memory_region_get_ram_ptr(flash_mem);
|
||||||
|
flash_size = memory_region_size(flash_mem);
|
||||||
|
- x86_firmware_configure(flash_ptr, flash_size);
|
||||||
|
+ x86_firmware_configure(gpa, flash_ptr, flash_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -249,7 +251,7 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||||
|
pc_system_flash_cleanup_unused(pcms);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void x86_firmware_configure(void *ptr, int size)
|
||||||
|
+void x86_firmware_configure(hwaddr gpa, void *ptr, int size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
@@ -270,6 +272,6 @@ void x86_firmware_configure(void *ptr, int size)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sev_encrypt_flash(ptr, size, &error_fatal);
|
||||||
|
+ sev_encrypt_flash(gpa, ptr, size, &error_fatal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
|
||||||
|
index 67b03c913a..35fe6eabea 100644
|
||||||
|
--- a/hw/i386/x86-common.c
|
||||||
|
+++ b/hw/i386/x86-common.c
|
||||||
|
@@ -981,7 +981,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
*/
|
||||||
|
void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
|
||||||
|
load_image_size(filename, ptr, bios_size);
|
||||||
|
- x86_firmware_configure(ptr, bios_size);
|
||||||
|
+ x86_firmware_configure(0x100000000ULL - bios_size, ptr, bios_size);
|
||||||
|
} else {
|
||||||
|
memory_region_set_readonly(&x86ms->bios, !isapc_ram_fw);
|
||||||
|
ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index b006f16b8d..d43cb3908e 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -154,6 +154,6 @@ void ioapic_init_gsi(GSIState *gsi_state, Object *parent);
|
||||||
|
DeviceState *ioapic_init_secondary(GSIState *gsi_state);
|
||||||
|
|
||||||
|
/* pc_sysfw.c */
|
||||||
|
-void x86_firmware_configure(void *ptr, int size);
|
||||||
|
+void x86_firmware_configure(hwaddr gpa, void *ptr, int size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff --git a/target/i386/sev-sysemu-stub.c b/target/i386/sev-sysemu-stub.c
|
||||||
|
index fc1c57c411..d5bf886e79 100644
|
||||||
|
--- a/target/i386/sev-sysemu-stub.c
|
||||||
|
+++ b/target/i386/sev-sysemu-stub.c
|
||||||
|
@@ -42,7 +42,7 @@ void qmp_sev_inject_launch_secret(const char *packet_header, const char *secret,
|
||||||
|
error_setg(errp, "SEV is not available in this QEMU");
|
||||||
|
}
|
||||||
|
|
||||||
|
-int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
+int sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 06401f0526..7b5c4b4874 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1484,7 +1484,7 @@ static int sev_snp_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
+sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
|
||||||
|
@@ -1841,7 +1841,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
/* zero the excess data so the measurement can be reliably calculated */
|
||||||
|
memset(padded_ht->padding, 0, sizeof(padded_ht->padding));
|
||||||
|
|
||||||
|
- if (sev_encrypt_flash((uint8_t *)padded_ht, sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
+ sizeof(*padded_ht), errp) < 0) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index cc12824dd6..858005a119 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -59,7 +59,7 @@ uint32_t sev_get_cbit_position(void);
|
||||||
|
uint32_t sev_get_reduced_phys_bits(void);
|
||||||
|
bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp);
|
||||||
|
|
||||||
|
-int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
|
||||||
|
+int sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp);
|
||||||
|
int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||||
|
uint64_t gpa, Error **errp);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,123 @@
|
|||||||
|
From a20b2e3e52b9589ac1abc8b9b818d526c86368cf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:39 -0500
|
||||||
|
Subject: [PATCH 082/100] hw/i386/sev: Use guest_memfd for legacy ROMs
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [82/91] a591e85e00c353009803b143c80852b8c9b1f15e (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Current SNP guest kernels will attempt to access these regions with
|
||||||
|
with C-bit set, so guest_memfd is needed to handle that. Otherwise,
|
||||||
|
kvm_convert_memory() will fail when the guest kernel tries to access it
|
||||||
|
and QEMU attempts to call KVM_SET_MEMORY_ATTRIBUTES to set these ranges
|
||||||
|
to private.
|
||||||
|
|
||||||
|
Whether guests should actually try to access ROM regions in this way (or
|
||||||
|
need to deal with legacy ROM regions at all), is a separate issue to be
|
||||||
|
addressed on kernel side, but current SNP guest kernels will exhibit
|
||||||
|
this behavior and so this handling is needed to allow QEMU to continue
|
||||||
|
running existing SNP guest kernels.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
[pankaj: Added sev_snp_enabled() check]
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-28-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 413a67450750e0459efeffc3db3ba9759c3e381c)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 14 ++++++++++----
|
||||||
|
hw/i386/pc_sysfw.c | 19 +++++++++++++------
|
||||||
|
2 files changed, 23 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index 0aca0cc79e..b25d075b59 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -62,6 +62,7 @@
|
||||||
|
#include "hw/mem/memory-device.h"
|
||||||
|
#include "e820_memory_layout.h"
|
||||||
|
#include "trace.h"
|
||||||
|
+#include "sev.h"
|
||||||
|
#include CONFIG_DEVICES
|
||||||
|
|
||||||
|
#ifdef CONFIG_XEN_EMU
|
||||||
|
@@ -1173,10 +1174,15 @@ void pc_memory_init(PCMachineState *pcms,
|
||||||
|
pc_system_firmware_init(pcms, rom_memory);
|
||||||
|
|
||||||
|
option_rom_mr = g_malloc(sizeof(*option_rom_mr));
|
||||||
|
- memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE,
|
||||||
|
- &error_fatal);
|
||||||
|
- if (pcmc->pci_enabled) {
|
||||||
|
- memory_region_set_readonly(option_rom_mr, true);
|
||||||
|
+ if (machine_require_guest_memfd(machine)) {
|
||||||
|
+ memory_region_init_ram_guest_memfd(option_rom_mr, NULL, "pc.rom",
|
||||||
|
+ PC_ROM_SIZE, &error_fatal);
|
||||||
|
+ } else {
|
||||||
|
+ memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE,
|
||||||
|
+ &error_fatal);
|
||||||
|
+ if (pcmc->pci_enabled) {
|
||||||
|
+ memory_region_set_readonly(option_rom_mr, true);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
PC_ROM_MIN_VGA,
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 7cdbafc8d2..ef80281d28 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -40,8 +40,8 @@
|
||||||
|
|
||||||
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
|
|
||||||
|
-static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
- MemoryRegion *flash_mem)
|
||||||
|
+static void pc_isa_bios_init(PCMachineState *pcms, MemoryRegion *isa_bios,
|
||||||
|
+ MemoryRegion *rom_memory, MemoryRegion *flash_mem)
|
||||||
|
{
|
||||||
|
int isa_bios_size;
|
||||||
|
uint64_t flash_size;
|
||||||
|
@@ -51,8 +51,13 @@ static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(flash_size, 128 * KiB);
|
||||||
|
- memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
|
||||||
|
- &error_fatal);
|
||||||
|
+ if (machine_require_guest_memfd(MACHINE(pcms))) {
|
||||||
|
+ memory_region_init_ram_guest_memfd(isa_bios, NULL, "isa-bios",
|
||||||
|
+ isa_bios_size, &error_fatal);
|
||||||
|
+ } else {
|
||||||
|
+ memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
|
||||||
|
+ &error_fatal);
|
||||||
|
+ }
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
isa_bios,
|
||||||
|
@@ -65,7 +70,9 @@ static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
((uint8_t*)flash_ptr) + (flash_size - isa_bios_size),
|
||||||
|
isa_bios_size);
|
||||||
|
|
||||||
|
- memory_region_set_readonly(isa_bios, true);
|
||||||
|
+ if (!machine_require_guest_memfd(current_machine)) {
|
||||||
|
+ memory_region_set_readonly(isa_bios, true);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static PFlashCFI01 *pc_pflash_create(PCMachineState *pcms,
|
||||||
|
@@ -191,7 +198,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
x86_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem,
|
||||||
|
true);
|
||||||
|
} else {
|
||||||
|
- pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
+ pc_isa_bios_init(pcms, &x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
From 4331180aa09e44550ff8de781c618bae5e99bb70 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Tue, 9 Apr 2024 18:07:43 -0500
|
||||||
|
Subject: [PATCH 025/100] hw/i386/sev: Use legacy SEV VM types for older
|
||||||
|
machine types
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [25/91] 8c73cd312736ccb0818b4d3216fd13712f21f3c9 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Newer 9.1 machine types will default to using the KVM_SEV_INIT2 API for
|
||||||
|
creating SEV/SEV-ES going forward. However, this API results in guest
|
||||||
|
measurement changes which are generally not expected for users of these
|
||||||
|
older guest types and can cause disruption if they switch to a newer
|
||||||
|
QEMU/kernel version. Avoid this by continuing to use the older
|
||||||
|
KVM_SEV_INIT/KVM_SEV_ES_INIT APIs for older machine types.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Message-ID: <20240409230743.962513-4-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit ea7fbd37537b3a598335c21ccb2ea674630fc810)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 1 +
|
||||||
|
target/i386/sev.c | 1 +
|
||||||
|
2 files changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index b9fde3cec1..1a34bc4522 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -351,6 +351,7 @@ const size_t pc_rhel_compat_len = G_N_ELEMENTS(pc_rhel_compat);
|
||||||
|
GlobalProperty pc_rhel_9_5_compat[] = {
|
||||||
|
/* pc_rhel_9_5_compat from pc_compat_pc_9_0 (backported from 9.1) */
|
||||||
|
{ TYPE_X86_CPU, "guest-phys-bits", "0" },
|
||||||
|
+ { "sev-guest", "legacy-vm-type", "true" },
|
||||||
|
};
|
||||||
|
const size_t pc_rhel_9_5_compat_len = G_N_ELEMENTS(pc_rhel_9_5_compat);
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index f4ee317cb0..d30b68c11e 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1417,6 +1417,7 @@ sev_guest_instance_init(Object *obj)
|
||||||
|
object_property_add_uint32_ptr(obj, "reduced-phys-bits",
|
||||||
|
&sev->reduced_phys_bits,
|
||||||
|
OBJ_PROP_FLAG_READWRITE);
|
||||||
|
+ object_apply_compat_props(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sev guest info */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,133 @@
|
|||||||
|
From ebf08d2a822576acfa60fbd5f552d26de1e4c4be Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:04 +0200
|
||||||
|
Subject: [PATCH 040/100] hw/i386/x86: Don't leak "isa-bios" memory regions
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [40/91] bb595357c6cc2d5a80bf3873853c69553c5feee5 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Fix the leaking in x86_bios_rom_init() and pc_isa_bios_init() by adding an
|
||||||
|
"isa_bios" attribute to X86MachineState.
|
||||||
|
|
||||||
|
Suggested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-4-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 32d3ee87a17fc91e981a23dba94855bff89f5920)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 7 +++----
|
||||||
|
hw/i386/x86.c | 9 ++++-----
|
||||||
|
include/hw/i386/x86.h | 7 +++++++
|
||||||
|
3 files changed, 14 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 59c7a81692..82d37cb376 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -40,11 +40,10 @@
|
||||||
|
|
||||||
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
|
|
||||||
|
-static void pc_isa_bios_init(MemoryRegion *rom_memory,
|
||||||
|
+static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
MemoryRegion *flash_mem)
|
||||||
|
{
|
||||||
|
int isa_bios_size;
|
||||||
|
- MemoryRegion *isa_bios;
|
||||||
|
uint64_t flash_size;
|
||||||
|
void *flash_ptr, *isa_bios_ptr;
|
||||||
|
|
||||||
|
@@ -52,7 +51,6 @@ static void pc_isa_bios_init(MemoryRegion *rom_memory,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(flash_size, 128 * KiB);
|
||||||
|
- isa_bios = g_malloc(sizeof(*isa_bios));
|
||||||
|
memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
|
||||||
|
&error_fatal);
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
@@ -136,6 +134,7 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms)
|
||||||
|
static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
MemoryRegion *rom_memory)
|
||||||
|
{
|
||||||
|
+ X86MachineState *x86ms = X86_MACHINE(pcms);
|
||||||
|
hwaddr total_size = 0;
|
||||||
|
int i;
|
||||||
|
BlockBackend *blk;
|
||||||
|
@@ -185,7 +184,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
- pc_isa_bios_init(rom_memory, flash_mem);
|
||||||
|
+ pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
if (sev_enabled()) {
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 6d3c72f124..457e8a34a5 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1133,7 +1133,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
char *filename;
|
||||||
|
- MemoryRegion *bios, *isa_bios;
|
||||||
|
+ MemoryRegion *bios;
|
||||||
|
int bios_size, isa_bios_size;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
@@ -1173,14 +1173,13 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
- isa_bios = g_malloc(sizeof(*isa_bios));
|
||||||
|
- memory_region_init_alias(isa_bios, NULL, "isa-bios", bios,
|
||||||
|
+ memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", bios,
|
||||||
|
bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
- isa_bios,
|
||||||
|
+ &x86ms->isa_bios,
|
||||||
|
1);
|
||||||
|
- memory_region_set_readonly(isa_bios, !isapc_ram_fw);
|
||||||
|
+ memory_region_set_readonly(&x86ms->isa_bios, !isapc_ram_fw);
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index cb07618d19..a07de79167 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -18,6 +18,7 @@
|
||||||
|
#define HW_I386_X86_H
|
||||||
|
|
||||||
|
#include "exec/hwaddr.h"
|
||||||
|
+#include "exec/memory.h"
|
||||||
|
|
||||||
|
#include "hw/boards.h"
|
||||||
|
#include "hw/intc/ioapic.h"
|
||||||
|
@@ -52,6 +53,12 @@ struct X86MachineState {
|
||||||
|
GMappedFile *initrd_mapped_file;
|
||||||
|
HotplugHandler *acpi_dev;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Map the upper 128 KiB of the BIOS just underneath the 1 MiB address
|
||||||
|
+ * boundary.
|
||||||
|
+ */
|
||||||
|
+ MemoryRegion isa_bios;
|
||||||
|
+
|
||||||
|
/* RAM information (sizes, addresses, configuration): */
|
||||||
|
ram_addr_t below_4g_mem_size, above_4g_mem_size;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,105 @@
|
|||||||
|
From e1f2265b5f6bf5b63bf3808bb540888f3cf8badb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:05 +0200
|
||||||
|
Subject: [PATCH 041/100] hw/i386/x86: Don't leak "pc.bios" memory region
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [41/91] a9cd61d8d240134c09c46e244efb89217cadf60c (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Fix the leaking in x86_bios_rom_init() by adding a "bios" attribute to
|
||||||
|
X86MachineState. Note that it is only used in the -bios case.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-5-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 865d95321ffc8d9941e33000b10140550f094556)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86.c | 13 ++++++-------
|
||||||
|
include/hw/i386/x86.h | 6 ++++++
|
||||||
|
2 files changed, 12 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 457e8a34a5..29167de97d 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1133,7 +1133,6 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
char *filename;
|
||||||
|
- MemoryRegion *bios;
|
||||||
|
int bios_size, isa_bios_size;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
@@ -1149,8 +1148,8 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
(bios_size % 65536) != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
}
|
||||||
|
- bios = g_malloc(sizeof(*bios));
|
||||||
|
- memory_region_init_ram(bios, NULL, "pc.bios", bios_size, &error_fatal);
|
||||||
|
+ memory_region_init_ram(&x86ms->bios, NULL, "pc.bios", bios_size,
|
||||||
|
+ &error_fatal);
|
||||||
|
if (sev_enabled()) {
|
||||||
|
/*
|
||||||
|
* The concept of a "reset" simply doesn't exist for
|
||||||
|
@@ -1159,11 +1158,11 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
* the firmware as rom to properly re-initialize on reset.
|
||||||
|
* Just go for a straight file load instead.
|
||||||
|
*/
|
||||||
|
- void *ptr = memory_region_get_ram_ptr(bios);
|
||||||
|
+ void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
|
||||||
|
load_image_size(filename, ptr, bios_size);
|
||||||
|
x86_firmware_configure(ptr, bios_size);
|
||||||
|
} else {
|
||||||
|
- memory_region_set_readonly(bios, !isapc_ram_fw);
|
||||||
|
+ memory_region_set_readonly(&x86ms->bios, !isapc_ram_fw);
|
||||||
|
ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
|
||||||
|
if (ret != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
@@ -1173,7 +1172,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
- memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", bios,
|
||||||
|
+ memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", &x86ms->bios,
|
||||||
|
bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
@@ -1184,7 +1183,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
(uint32_t)(-bios_size),
|
||||||
|
- bios);
|
||||||
|
+ &x86ms->bios);
|
||||||
|
return;
|
||||||
|
|
||||||
|
bios_error:
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index a07de79167..55c6809ae0 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -53,6 +53,12 @@ struct X86MachineState {
|
||||||
|
GMappedFile *initrd_mapped_file;
|
||||||
|
HotplugHandler *acpi_dev;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Map the whole BIOS just underneath the 4 GiB address boundary. Only used
|
||||||
|
+ * in the ROM (-bios) case.
|
||||||
|
+ */
|
||||||
|
+ MemoryRegion bios;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Map the upper 128 KiB of the BIOS just underneath the 1 MiB address
|
||||||
|
* boundary.
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
From b9d0c78f04160fbc1eee6cfd94b17f1133a35d83 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Tue, 30 Apr 2024 17:06:38 +0200
|
||||||
|
Subject: [PATCH 037/100] hw/i386/x86: Eliminate two if statements in
|
||||||
|
x86_bios_rom_init()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [37/91] 1ef6a13214e85f6ef773f5c894c720f20330912b (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Given that memory_region_set_readonly() is a no-op when the readonlyness is
|
||||||
|
already as requested it is possible to simplify the pattern
|
||||||
|
|
||||||
|
if (condition) {
|
||||||
|
foo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
to
|
||||||
|
|
||||||
|
foo(condition);
|
||||||
|
|
||||||
|
which is shorter and allows to see the invariant of the code more easily.
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Message-ID: <20240430150643.111976-2-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 014dbdac8798799d081abc9dff3e4876ca54f49e)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86.c | 8 ++------
|
||||||
|
1 file changed, 2 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 3d5b51e92d..2a4f3ee285 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1163,9 +1163,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
load_image_size(filename, ptr, bios_size);
|
||||||
|
x86_firmware_configure(ptr, bios_size);
|
||||||
|
} else {
|
||||||
|
- if (!isapc_ram_fw) {
|
||||||
|
- memory_region_set_readonly(bios, true);
|
||||||
|
- }
|
||||||
|
+ memory_region_set_readonly(bios, !isapc_ram_fw);
|
||||||
|
ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
|
||||||
|
if (ret != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
@@ -1182,9 +1180,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
isa_bios,
|
||||||
|
1);
|
||||||
|
- if (!isapc_ram_fw) {
|
||||||
|
- memory_region_set_readonly(isa_bios, true);
|
||||||
|
- }
|
||||||
|
+ memory_region_set_readonly(isa_bios, !isapc_ram_fw);
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
From 1baf67564d4227d6ba98923217a15814c438c32b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:06 +0200
|
||||||
|
Subject: [PATCH 042/100] hw/i386/x86: Extract x86_isa_bios_init() from
|
||||||
|
x86_bios_rom_init()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [42/91] 1db417a5995480924f7fd0661a306f2d2bfa0a77 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
The function is inspired by pc_isa_bios_init() and should eventually replace it.
|
||||||
|
Using x86_isa_bios_init() rather than pc_isa_bios_init() fixes pflash commands
|
||||||
|
to work in the isa-bios region.
|
||||||
|
|
||||||
|
While at it convert the magic number 0x100000 (== 1MiB) to increase readability.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-6-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 5c5ffec12c30d2017cbdee6798f54d8fad3f9656)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86.c | 25 ++++++++++++++++---------
|
||||||
|
include/hw/i386/x86.h | 2 ++
|
||||||
|
2 files changed, 18 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 29167de97d..c61f4ebfa6 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1128,12 +1128,25 @@ void x86_load_linux(X86MachineState *x86ms,
|
||||||
|
nb_option_roms++;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void x86_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *isa_memory,
|
||||||
|
+ MemoryRegion *bios, bool read_only)
|
||||||
|
+{
|
||||||
|
+ uint64_t bios_size = memory_region_size(bios);
|
||||||
|
+ uint64_t isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
+
|
||||||
|
+ memory_region_init_alias(isa_bios, NULL, "isa-bios", bios,
|
||||||
|
+ bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
+ memory_region_add_subregion_overlap(isa_memory, 1 * MiB - isa_bios_size,
|
||||||
|
+ isa_bios, 1);
|
||||||
|
+ memory_region_set_readonly(isa_bios, read_only);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw)
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
char *filename;
|
||||||
|
- int bios_size, isa_bios_size;
|
||||||
|
+ int bios_size;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
/* BIOS load */
|
||||||
|
@@ -1171,14 +1184,8 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
g_free(filename);
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
- isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
- memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", &x86ms->bios,
|
||||||
|
- bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
- memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
- 0x100000 - isa_bios_size,
|
||||||
|
- &x86ms->isa_bios,
|
||||||
|
- 1);
|
||||||
|
- memory_region_set_readonly(&x86ms->isa_bios, !isapc_ram_fw);
|
||||||
|
+ x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
|
||||||
|
+ !isapc_ram_fw);
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index 55c6809ae0..d7b7d3f3ce 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -129,6 +129,8 @@ void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
|
void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
|
DeviceState *dev, Error **errp);
|
||||||
|
|
||||||
|
+void x86_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *isa_memory,
|
||||||
|
+ MemoryRegion *bios, bool read_only);
|
||||||
|
void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,108 @@
|
|||||||
|
From c554f8768a18ceba173aedbd582c1cae43a41e2c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Thomas Huth <thuth@redhat.com>
|
||||||
|
Date: Tue, 18 Jun 2024 14:19:58 +0200
|
||||||
|
Subject: [PATCH 1/2] hw/virtio: Fix the de-initialization of vhost-user
|
||||||
|
devices
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-MergeRequest: 255: hw/virtio: Fix the de-initialization of vhost-user devices
|
||||||
|
RH-Jira: RHEL-40708
|
||||||
|
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [1/1] c7815a249ec135993f45934cab1c1f2c038b80ea (thuth/qemu-kvm-cs9)
|
||||||
|
|
||||||
|
JIRA: https://issues.redhat.com/browse/RHEL-40708
|
||||||
|
|
||||||
|
The unrealize functions of the various vhost-user devices are
|
||||||
|
calling the corresponding vhost_*_set_status() functions with a
|
||||||
|
status of 0 to shut down the device correctly.
|
||||||
|
|
||||||
|
Now these vhost_*_set_status() functions all follow this scheme:
|
||||||
|
|
||||||
|
bool should_start = virtio_device_should_start(vdev, status);
|
||||||
|
|
||||||
|
if (vhost_dev_is_started(&vvc->vhost_dev) == should_start) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_start) {
|
||||||
|
/* ... do the initialization stuff ... */
|
||||||
|
} else {
|
||||||
|
/* ... do the cleanup stuff ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
The problem here is virtio_device_should_start(vdev, 0) currently
|
||||||
|
always returns "true" since it internally only looks at vdev->started
|
||||||
|
instead of looking at the "status" parameter. Thus once the device
|
||||||
|
got started once, virtio_device_should_start() always returns true
|
||||||
|
and thus the vhost_*_set_status() functions return early, without
|
||||||
|
ever doing any clean-up when being called with status == 0. This
|
||||||
|
causes e.g. problems when trying to hot-plug and hot-unplug a vhost
|
||||||
|
user devices multiple times since the de-initialization step is
|
||||||
|
completely skipped during the unplug operation.
|
||||||
|
|
||||||
|
This bug has been introduced in commit 9f6bcfd99f ("hw/virtio: move
|
||||||
|
vm_running check to virtio_device_started") which replaced
|
||||||
|
|
||||||
|
should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
should_start = virtio_device_started(vdev, status);
|
||||||
|
|
||||||
|
which later got replaced by virtio_device_should_start(). This blocked
|
||||||
|
the possibility to set should_start to false in case the status flag
|
||||||
|
VIRTIO_CONFIG_S_DRIVER_OK was not set.
|
||||||
|
|
||||||
|
Fix it by adjusting the virtio_device_should_start() function to
|
||||||
|
only consider the status flag instead of vdev->started. Since this
|
||||||
|
function is only used in the various vhost_*_set_status() functions
|
||||||
|
for exactly the same purpose, it should be fine to fix it in this
|
||||||
|
central place there without any risk to change the behavior of other
|
||||||
|
code.
|
||||||
|
|
||||||
|
Fixes: 9f6bcfd99f ("hw/virtio: move vm_running check to virtio_device_started")
|
||||||
|
Buglink: https://issues.redhat.com/browse/RHEL-40708
|
||||||
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
Message-Id: <20240618121958.88673-1-thuth@redhat.com>
|
||||||
|
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||||
|
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||||
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||||
|
(cherry picked from commit d72479b11797c28893e1e3fc565497a9cae5ca16)
|
||||||
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
---
|
||||||
|
include/hw/virtio/virtio.h | 8 ++++----
|
||||||
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
|
||||||
|
index 7d5ffdc145..2eafad17b8 100644
|
||||||
|
--- a/include/hw/virtio/virtio.h
|
||||||
|
+++ b/include/hw/virtio/virtio.h
|
||||||
|
@@ -470,9 +470,9 @@ static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status)
|
||||||
|
* @vdev - the VirtIO device
|
||||||
|
* @status - the devices status bits
|
||||||
|
*
|
||||||
|
- * This is similar to virtio_device_started() but also encapsulates a
|
||||||
|
- * check on the VM status which would prevent a device starting
|
||||||
|
- * anyway.
|
||||||
|
+ * This is similar to virtio_device_started() but ignores vdev->started
|
||||||
|
+ * and also encapsulates a check on the VM status which would prevent a
|
||||||
|
+ * device from starting anyway.
|
||||||
|
*/
|
||||||
|
static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status)
|
||||||
|
{
|
||||||
|
@@ -480,7 +480,7 @@ static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return virtio_device_started(vdev, status);
|
||||||
|
+ return status & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void virtio_set_started(VirtIODevice *vdev, bool started)
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,68 @@
|
|||||||
|
From f572a40924c7138072e387111d0f092185972477 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Thu, 9 May 2024 19:00:39 +0200
|
||||||
|
Subject: [PATCH 044/100] i386: correctly select code in hw/i386 that depends
|
||||||
|
on other components
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [44/91] 1327a5eb2b91edacf56cc4e93255cad456abbbeb (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
fw_cfg.c and vapic.c are currently included unconditionally but
|
||||||
|
depend on other components. vapic.c depends on the local APIC,
|
||||||
|
while fw_cfg.c includes a piece of AML builder code that depends
|
||||||
|
on CONFIG_ACPI.
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||||
|
Message-ID: <20240509170044.190795-9-pbonzini@redhat.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 7974e51342775c87f6e759a8c525db1045ddfa24)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/fw_cfg.c | 2 ++
|
||||||
|
hw/i386/meson.build | 2 +-
|
||||||
|
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
|
||||||
|
index 283c3f4c16..7f97d40616 100644
|
||||||
|
--- a/hw/i386/fw_cfg.c
|
||||||
|
+++ b/hw/i386/fw_cfg.c
|
||||||
|
@@ -204,6 +204,7 @@ void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg)
|
||||||
|
fw_cfg_add_file(fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_ACPI
|
||||||
|
void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
@@ -230,3 +231,4 @@ void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
|
||||||
|
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||||
|
aml_append(scope, dev);
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
|
||||||
|
index d8b70ef3e9..d9da676038 100644
|
||||||
|
--- a/hw/i386/meson.build
|
||||||
|
+++ b/hw/i386/meson.build
|
||||||
|
@@ -1,12 +1,12 @@
|
||||||
|
i386_ss = ss.source_set()
|
||||||
|
i386_ss.add(files(
|
||||||
|
'fw_cfg.c',
|
||||||
|
- 'vapic.c',
|
||||||
|
'e820_memory_layout.c',
|
||||||
|
'multiboot.c',
|
||||||
|
'x86.c',
|
||||||
|
))
|
||||||
|
|
||||||
|
+i386_ss.add(when: 'CONFIG_APIC', if_true: files('vapic.c'))
|
||||||
|
i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
|
||||||
|
if_false: files('x86-iommu-stub.c'))
|
||||||
|
i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'),
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
From 127f3c60668e1bd08ec00856a317cb841adf0440 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:23 -0500
|
||||||
|
Subject: [PATCH 063/100] i386/cpu: Set SEV-SNP CPUID bit when SNP enabled
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [63/91] 0f834a6897c5cdc0e29a5b1862e621f8ce309657 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SNP guests will rely on this bit to determine certain feature support.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-12-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 7831221941cccbde922412c1550ed8b4bce7c361)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/cpu.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||||
|
index 489c853b42..13737cd703 100644
|
||||||
|
--- a/target/i386/cpu.c
|
||||||
|
+++ b/target/i386/cpu.c
|
||||||
|
@@ -6822,6 +6822,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||||
|
if (sev_enabled()) {
|
||||||
|
*eax = 0x2;
|
||||||
|
*eax |= sev_es_enabled() ? 0x8 : 0;
|
||||||
|
+ *eax |= sev_snp_enabled() ? 0x10 : 0;
|
||||||
|
*ebx = sev_get_cbit_position() & 0x3f; /* EBX[5:0] */
|
||||||
|
*ebx |= (sev_get_reduced_phys_bits() & 0x3f) << 6; /* EBX[11:6] */
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,145 @@
|
|||||||
|
From 14aa42bbacde75b2ce9a59d1267f73d613026461 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:42 -0500
|
||||||
|
Subject: [PATCH 076/100] i386/kvm: Add KVM_EXIT_HYPERCALL handling for
|
||||||
|
KVM_HC_MAP_GPA_RANGE
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [76/91] 3e1201c330dc826af1ec4650974d47053270eb16 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
KVM_HC_MAP_GPA_RANGE will be used to send requests to userspace for
|
||||||
|
private/shared memory attribute updates requested by the guest.
|
||||||
|
Implement handling for that use-case along with some basic
|
||||||
|
infrastructure for enabling specific hypercall events.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-31-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 47e76d03b155e43beca550251a6eb7ea926c059f)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm.c | 55 ++++++++++++++++++++++++++++++++++++
|
||||||
|
target/i386/kvm/kvm_i386.h | 1 +
|
||||||
|
target/i386/kvm/trace-events | 1 +
|
||||||
|
3 files changed, 57 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index 75e75d9772..2935e3931a 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -21,6 +21,7 @@
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include <linux/kvm.h>
|
||||||
|
+#include <linux/kvm_para.h>
|
||||||
|
#include "standard-headers/asm-x86/kvm_para.h"
|
||||||
|
#include "hw/xen/interface/arch-x86/cpuid.h"
|
||||||
|
|
||||||
|
@@ -208,6 +209,13 @@ int kvm_get_vm_type(MachineState *ms)
|
||||||
|
return kvm_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool kvm_enable_hypercall(uint64_t enable_mask)
|
||||||
|
+{
|
||||||
|
+ KVMState *s = KVM_STATE(current_accel());
|
||||||
|
+
|
||||||
|
+ return !kvm_vm_enable_cap(s, KVM_CAP_EXIT_HYPERCALL, 0, enable_mask);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool kvm_has_smm(void)
|
||||||
|
{
|
||||||
|
return kvm_vm_check_extension(kvm_state, KVM_CAP_X86_SMM);
|
||||||
|
@@ -5325,6 +5333,50 @@ static bool host_supports_vmx(void)
|
||||||
|
return ecx & CPUID_EXT_VMX;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Currently the handling here only supports use of KVM_HC_MAP_GPA_RANGE
|
||||||
|
+ * to service guest-initiated memory attribute update requests so that
|
||||||
|
+ * KVM_SET_MEMORY_ATTRIBUTES can update whether or not a page should be
|
||||||
|
+ * backed by the private memory pool provided by guest_memfd, and as such
|
||||||
|
+ * is only applicable to guest_memfd-backed guests (e.g. SNP/TDX).
|
||||||
|
+ *
|
||||||
|
+ * Other other use-cases for KVM_HC_MAP_GPA_RANGE, such as for SEV live
|
||||||
|
+ * migration, are not implemented here currently.
|
||||||
|
+ *
|
||||||
|
+ * For the guest_memfd use-case, these exits will generally be synthesized
|
||||||
|
+ * by KVM based on platform-specific hypercalls, like GHCB requests in the
|
||||||
|
+ * case of SEV-SNP, and not issued directly within the guest though the
|
||||||
|
+ * KVM_HC_MAP_GPA_RANGE hypercall. So in this case, KVM_HC_MAP_GPA_RANGE is
|
||||||
|
+ * not actually advertised to guests via the KVM CPUID feature bit, as
|
||||||
|
+ * opposed to SEV live migration where it would be. Since it is unlikely the
|
||||||
|
+ * SEV live migration use-case would be useful for guest-memfd backed guests,
|
||||||
|
+ * because private/shared page tracking is already provided through other
|
||||||
|
+ * means, these 2 use-cases should be treated as being mutually-exclusive.
|
||||||
|
+ */
|
||||||
|
+static int kvm_handle_hc_map_gpa_range(struct kvm_run *run)
|
||||||
|
+{
|
||||||
|
+ uint64_t gpa, size, attributes;
|
||||||
|
+
|
||||||
|
+ if (!machine_require_guest_memfd(current_machine))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ gpa = run->hypercall.args[0];
|
||||||
|
+ size = run->hypercall.args[1] * TARGET_PAGE_SIZE;
|
||||||
|
+ attributes = run->hypercall.args[2];
|
||||||
|
+
|
||||||
|
+ trace_kvm_hc_map_gpa_range(gpa, size, attributes, run->hypercall.flags);
|
||||||
|
+
|
||||||
|
+ return kvm_convert_memory(gpa, size, attributes & KVM_MAP_GPA_RANGE_ENCRYPTED);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int kvm_handle_hypercall(struct kvm_run *run)
|
||||||
|
+{
|
||||||
|
+ if (run->hypercall.nr == KVM_HC_MAP_GPA_RANGE)
|
||||||
|
+ return kvm_handle_hc_map_gpa_range(run);
|
||||||
|
+
|
||||||
|
+ return -EINVAL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#define VMX_INVALID_GUEST_STATE 0x80000021
|
||||||
|
|
||||||
|
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
|
@@ -5420,6 +5472,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
|
ret = kvm_xen_handle_exit(cpu, &run->xen);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
+ case KVM_EXIT_HYPERCALL:
|
||||||
|
+ ret = kvm_handle_hypercall(run);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
||||||
|
ret = -1;
|
||||||
|
diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h
|
||||||
|
index 6b44844d95..34fc60774b 100644
|
||||||
|
--- a/target/i386/kvm/kvm_i386.h
|
||||||
|
+++ b/target/i386/kvm/kvm_i386.h
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
bool kvm_has_smm(void);
|
||||||
|
bool kvm_enable_x2apic(void);
|
||||||
|
bool kvm_hv_vpindex_settable(void);
|
||||||
|
+bool kvm_enable_hypercall(uint64_t enable_mask);
|
||||||
|
|
||||||
|
bool kvm_enable_sgx_provisioning(KVMState *s);
|
||||||
|
bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp);
|
||||||
|
diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
|
||||||
|
index b365a8e8e2..74a6234ff7 100644
|
||||||
|
--- a/target/i386/kvm/trace-events
|
||||||
|
+++ b/target/i386/kvm/trace-events
|
||||||
|
@@ -5,6 +5,7 @@ kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %"
|
||||||
|
kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
|
||||||
|
kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
|
||||||
|
kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
|
||||||
|
+kvm_hc_map_gpa_range(uint64_t gpa, uint64_t size, uint64_t attributes, uint64_t flags) "gpa 0x%" PRIx64 " size 0x%" PRIx64 " attributes 0x%" PRIx64 " flags 0x%" PRIx64
|
||||||
|
|
||||||
|
# xen-emu.c
|
||||||
|
kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,536 @@
|
|||||||
|
From 5ead79f45e8e90b7a04586c89e70cb9d0b66b730 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sean Christopherson <sean.j.christopherson@intel.com>
|
||||||
|
Date: Thu, 29 Feb 2024 01:36:43 -0500
|
||||||
|
Subject: [PATCH 004/100] i386/kvm: Move architectural CPUID leaf generation to
|
||||||
|
separate helper
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [4/91] 06ecdbcf05ad3d658273980b114f02477d0b0475 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Move the architectural (for lack of a better term) CPUID leaf generation
|
||||||
|
to a separate helper so that the generation code can be reused by TDX,
|
||||||
|
which needs to generate a canonical VM-scoped configuration.
|
||||||
|
|
||||||
|
For now this is just a cleanup, so keep the function static.
|
||||||
|
|
||||||
|
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240229063726.610065-23-xiaoyao.li@intel.com>
|
||||||
|
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a5acf4f26c208a05d05ef1bde65553ce2ab5e5d0)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm.c | 417 +++++++++++++++++++++---------------------
|
||||||
|
1 file changed, 211 insertions(+), 206 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index 739f33db47..5f30b649a0 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -1706,195 +1706,22 @@ static void kvm_init_nested_state(CPUX86State *env)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
+static uint32_t kvm_x86_build_cpuid(CPUX86State *env,
|
||||||
|
+ struct kvm_cpuid_entry2 *entries,
|
||||||
|
+ uint32_t cpuid_i)
|
||||||
|
{
|
||||||
|
- struct {
|
||||||
|
- struct kvm_cpuid2 cpuid;
|
||||||
|
- struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
|
||||||
|
- } cpuid_data;
|
||||||
|
- /*
|
||||||
|
- * The kernel defines these structs with padding fields so there
|
||||||
|
- * should be no extra padding in our cpuid_data struct.
|
||||||
|
- */
|
||||||
|
- QEMU_BUILD_BUG_ON(sizeof(cpuid_data) !=
|
||||||
|
- sizeof(struct kvm_cpuid2) +
|
||||||
|
- sizeof(struct kvm_cpuid_entry2) * KVM_MAX_CPUID_ENTRIES);
|
||||||
|
-
|
||||||
|
- X86CPU *cpu = X86_CPU(cs);
|
||||||
|
- CPUX86State *env = &cpu->env;
|
||||||
|
- uint32_t limit, i, j, cpuid_i;
|
||||||
|
+ uint32_t limit, i, j;
|
||||||
|
uint32_t unused;
|
||||||
|
struct kvm_cpuid_entry2 *c;
|
||||||
|
- uint32_t signature[3];
|
||||||
|
- int kvm_base = KVM_CPUID_SIGNATURE;
|
||||||
|
- int max_nested_state_len;
|
||||||
|
- int r;
|
||||||
|
- Error *local_err = NULL;
|
||||||
|
-
|
||||||
|
- memset(&cpuid_data, 0, sizeof(cpuid_data));
|
||||||
|
-
|
||||||
|
- cpuid_i = 0;
|
||||||
|
-
|
||||||
|
- has_xsave2 = kvm_check_extension(cs->kvm_state, KVM_CAP_XSAVE2);
|
||||||
|
-
|
||||||
|
- r = kvm_arch_set_tsc_khz(cs);
|
||||||
|
- if (r < 0) {
|
||||||
|
- return r;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* vcpu's TSC frequency is either specified by user, or following
|
||||||
|
- * the value used by KVM if the former is not present. In the
|
||||||
|
- * latter case, we query it from KVM and record in env->tsc_khz,
|
||||||
|
- * so that vcpu's TSC frequency can be migrated later via this field.
|
||||||
|
- */
|
||||||
|
- if (!env->tsc_khz) {
|
||||||
|
- r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
|
||||||
|
- kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
|
||||||
|
- -ENOTSUP;
|
||||||
|
- if (r > 0) {
|
||||||
|
- env->tsc_khz = r;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * kvm_hyperv_expand_features() is called here for the second time in case
|
||||||
|
- * KVM_CAP_SYS_HYPERV_CPUID is not supported. While we can't possibly handle
|
||||||
|
- * 'query-cpu-model-expansion' in this case as we don't have a KVM vCPU to
|
||||||
|
- * check which Hyper-V enlightenments are supported and which are not, we
|
||||||
|
- * can still proceed and check/expand Hyper-V enlightenments here so legacy
|
||||||
|
- * behavior is preserved.
|
||||||
|
- */
|
||||||
|
- if (!kvm_hyperv_expand_features(cpu, &local_err)) {
|
||||||
|
- error_report_err(local_err);
|
||||||
|
- return -ENOSYS;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (hyperv_enabled(cpu)) {
|
||||||
|
- r = hyperv_init_vcpu(cpu);
|
||||||
|
- if (r) {
|
||||||
|
- return r;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- cpuid_i = hyperv_fill_cpuids(cs, cpuid_data.entries);
|
||||||
|
- kvm_base = KVM_CPUID_SIGNATURE_NEXT;
|
||||||
|
- has_msr_hv_hypercall = true;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (cs->kvm_state->xen_version) {
|
||||||
|
-#ifdef CONFIG_XEN_EMU
|
||||||
|
- struct kvm_cpuid_entry2 *xen_max_leaf;
|
||||||
|
-
|
||||||
|
- memcpy(signature, "XenVMMXenVMM", 12);
|
||||||
|
-
|
||||||
|
- xen_max_leaf = c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_SIGNATURE;
|
||||||
|
- c->eax = kvm_base + XEN_CPUID_TIME;
|
||||||
|
- c->ebx = signature[0];
|
||||||
|
- c->ecx = signature[1];
|
||||||
|
- c->edx = signature[2];
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_VENDOR;
|
||||||
|
- c->eax = cs->kvm_state->xen_version;
|
||||||
|
- c->ebx = 0;
|
||||||
|
- c->ecx = 0;
|
||||||
|
- c->edx = 0;
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_HVM_MSR;
|
||||||
|
- /* Number of hypercall-transfer pages */
|
||||||
|
- c->eax = 1;
|
||||||
|
- /* Hypercall MSR base address */
|
||||||
|
- if (hyperv_enabled(cpu)) {
|
||||||
|
- c->ebx = XEN_HYPERCALL_MSR_HYPERV;
|
||||||
|
- kvm_xen_init(cs->kvm_state, c->ebx);
|
||||||
|
- } else {
|
||||||
|
- c->ebx = XEN_HYPERCALL_MSR;
|
||||||
|
- }
|
||||||
|
- c->ecx = 0;
|
||||||
|
- c->edx = 0;
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_TIME;
|
||||||
|
- c->eax = ((!!tsc_is_stable_and_known(env) << 1) |
|
||||||
|
- (!!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP) << 2));
|
||||||
|
- /* default=0 (emulate if necessary) */
|
||||||
|
- c->ebx = 0;
|
||||||
|
- /* guest tsc frequency */
|
||||||
|
- c->ecx = env->user_tsc_khz;
|
||||||
|
- /* guest tsc incarnation (migration count) */
|
||||||
|
- c->edx = 0;
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
- xen_max_leaf->eax = kvm_base + XEN_CPUID_HVM;
|
||||||
|
- if (cs->kvm_state->xen_version >= XEN_VERSION(4, 5)) {
|
||||||
|
- c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
-
|
||||||
|
- if (cpu->xen_vapic) {
|
||||||
|
- c->eax |= XEN_HVM_CPUID_APIC_ACCESS_VIRT;
|
||||||
|
- c->eax |= XEN_HVM_CPUID_X2APIC_VIRT;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- c->eax |= XEN_HVM_CPUID_IOMMU_MAPPINGS;
|
||||||
|
-
|
||||||
|
- if (cs->kvm_state->xen_version >= XEN_VERSION(4, 6)) {
|
||||||
|
- c->eax |= XEN_HVM_CPUID_VCPU_ID_PRESENT;
|
||||||
|
- c->ebx = cs->cpu_index;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (cs->kvm_state->xen_version >= XEN_VERSION(4, 17)) {
|
||||||
|
- c->eax |= XEN_HVM_CPUID_UPCALL_VECTOR;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- r = kvm_xen_init_vcpu(cs);
|
||||||
|
- if (r) {
|
||||||
|
- return r;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- kvm_base += 0x100;
|
||||||
|
-#else /* CONFIG_XEN_EMU */
|
||||||
|
- /* This should never happen as kvm_arch_init() would have died first. */
|
||||||
|
- fprintf(stderr, "Cannot enable Xen CPUID without Xen support\n");
|
||||||
|
- abort();
|
||||||
|
-#endif
|
||||||
|
- } else if (cpu->expose_kvm) {
|
||||||
|
- memcpy(signature, "KVMKVMKVM\0\0\0", 12);
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = KVM_CPUID_SIGNATURE | kvm_base;
|
||||||
|
- c->eax = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
- c->ebx = signature[0];
|
||||||
|
- c->ecx = signature[1];
|
||||||
|
- c->edx = signature[2];
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
- c->eax = env->features[FEAT_KVM];
|
||||||
|
- c->edx = env->features[FEAT_KVM_HINTS];
|
||||||
|
- }
|
||||||
|
|
||||||
|
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
|
||||||
|
|
||||||
|
- if (cpu->kvm_pv_enforce_cpuid) {
|
||||||
|
- r = kvm_vcpu_enable_cap(cs, KVM_CAP_ENFORCE_PV_FEATURE_CPUID, 0, 1);
|
||||||
|
- if (r < 0) {
|
||||||
|
- fprintf(stderr,
|
||||||
|
- "failed to enable KVM_CAP_ENFORCE_PV_FEATURE_CPUID: %s",
|
||||||
|
- strerror(-r));
|
||||||
|
- abort();
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
for (i = 0; i <= limit; i++) {
|
||||||
|
+ j = 0;
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "unsupported level value: 0x%x\n", limit);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
-
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
switch (i) {
|
||||||
|
case 2: {
|
||||||
|
/* Keep reading function 2 till all the input is received */
|
||||||
|
@@ -1908,11 +1735,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
|
||||||
|
for (j = 1; j < times; ++j) {
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:2):eax & 0xf = 0x%x\n", times);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
c->function = i;
|
||||||
|
c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC;
|
||||||
|
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
|
||||||
|
@@ -1951,11 +1776,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x12:
|
||||||
|
@@ -1970,11 +1793,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x12,ecx:0x%x)\n", j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x7:
|
||||||
|
@@ -1991,11 +1812,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
|
||||||
|
for (j = 1; j <= times; ++j) {
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
c->function = i;
|
||||||
|
c->index = j;
|
||||||
|
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
|
||||||
|
@@ -2048,11 +1867,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused);
|
||||||
|
|
||||||
|
for (i = 0x80000000; i <= limit; i++) {
|
||||||
|
+ j = 0;
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "unsupported xlevel value: 0x%x\n", limit);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 0x8000001d:
|
||||||
|
@@ -2067,11 +1886,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
@@ -2094,11 +1911,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
cpu_x86_cpuid(env, 0xC0000000, 0, &limit, &unused, &unused, &unused);
|
||||||
|
|
||||||
|
for (i = 0xC0000000; i <= limit; i++) {
|
||||||
|
+ j = 0;
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "unsupported xlevel2 value: 0x%x\n", limit);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
|
||||||
|
c->function = i;
|
||||||
|
c->flags = 0;
|
||||||
|
@@ -2106,6 +1923,194 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ return cpuid_i;
|
||||||
|
+
|
||||||
|
+full:
|
||||||
|
+ fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
+ "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
+ abort();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
+{
|
||||||
|
+ struct {
|
||||||
|
+ struct kvm_cpuid2 cpuid;
|
||||||
|
+ struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
|
||||||
|
+ } cpuid_data;
|
||||||
|
+ /*
|
||||||
|
+ * The kernel defines these structs with padding fields so there
|
||||||
|
+ * should be no extra padding in our cpuid_data struct.
|
||||||
|
+ */
|
||||||
|
+ QEMU_BUILD_BUG_ON(sizeof(cpuid_data) !=
|
||||||
|
+ sizeof(struct kvm_cpuid2) +
|
||||||
|
+ sizeof(struct kvm_cpuid_entry2) * KVM_MAX_CPUID_ENTRIES);
|
||||||
|
+
|
||||||
|
+ X86CPU *cpu = X86_CPU(cs);
|
||||||
|
+ CPUX86State *env = &cpu->env;
|
||||||
|
+ uint32_t cpuid_i;
|
||||||
|
+ struct kvm_cpuid_entry2 *c;
|
||||||
|
+ uint32_t signature[3];
|
||||||
|
+ int kvm_base = KVM_CPUID_SIGNATURE;
|
||||||
|
+ int max_nested_state_len;
|
||||||
|
+ int r;
|
||||||
|
+ Error *local_err = NULL;
|
||||||
|
+
|
||||||
|
+ memset(&cpuid_data, 0, sizeof(cpuid_data));
|
||||||
|
+
|
||||||
|
+ cpuid_i = 0;
|
||||||
|
+
|
||||||
|
+ has_xsave2 = kvm_check_extension(cs->kvm_state, KVM_CAP_XSAVE2);
|
||||||
|
+
|
||||||
|
+ r = kvm_arch_set_tsc_khz(cs);
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* vcpu's TSC frequency is either specified by user, or following
|
||||||
|
+ * the value used by KVM if the former is not present. In the
|
||||||
|
+ * latter case, we query it from KVM and record in env->tsc_khz,
|
||||||
|
+ * so that vcpu's TSC frequency can be migrated later via this field.
|
||||||
|
+ */
|
||||||
|
+ if (!env->tsc_khz) {
|
||||||
|
+ r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
|
||||||
|
+ kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
|
||||||
|
+ -ENOTSUP;
|
||||||
|
+ if (r > 0) {
|
||||||
|
+ env->tsc_khz = r;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * kvm_hyperv_expand_features() is called here for the second time in case
|
||||||
|
+ * KVM_CAP_SYS_HYPERV_CPUID is not supported. While we can't possibly handle
|
||||||
|
+ * 'query-cpu-model-expansion' in this case as we don't have a KVM vCPU to
|
||||||
|
+ * check which Hyper-V enlightenments are supported and which are not, we
|
||||||
|
+ * can still proceed and check/expand Hyper-V enlightenments here so legacy
|
||||||
|
+ * behavior is preserved.
|
||||||
|
+ */
|
||||||
|
+ if (!kvm_hyperv_expand_features(cpu, &local_err)) {
|
||||||
|
+ error_report_err(local_err);
|
||||||
|
+ return -ENOSYS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (hyperv_enabled(cpu)) {
|
||||||
|
+ r = hyperv_init_vcpu(cpu);
|
||||||
|
+ if (r) {
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cpuid_i = hyperv_fill_cpuids(cs, cpuid_data.entries);
|
||||||
|
+ kvm_base = KVM_CPUID_SIGNATURE_NEXT;
|
||||||
|
+ has_msr_hv_hypercall = true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cs->kvm_state->xen_version) {
|
||||||
|
+#ifdef CONFIG_XEN_EMU
|
||||||
|
+ struct kvm_cpuid_entry2 *xen_max_leaf;
|
||||||
|
+
|
||||||
|
+ memcpy(signature, "XenVMMXenVMM", 12);
|
||||||
|
+
|
||||||
|
+ xen_max_leaf = c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_SIGNATURE;
|
||||||
|
+ c->eax = kvm_base + XEN_CPUID_TIME;
|
||||||
|
+ c->ebx = signature[0];
|
||||||
|
+ c->ecx = signature[1];
|
||||||
|
+ c->edx = signature[2];
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_VENDOR;
|
||||||
|
+ c->eax = cs->kvm_state->xen_version;
|
||||||
|
+ c->ebx = 0;
|
||||||
|
+ c->ecx = 0;
|
||||||
|
+ c->edx = 0;
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_HVM_MSR;
|
||||||
|
+ /* Number of hypercall-transfer pages */
|
||||||
|
+ c->eax = 1;
|
||||||
|
+ /* Hypercall MSR base address */
|
||||||
|
+ if (hyperv_enabled(cpu)) {
|
||||||
|
+ c->ebx = XEN_HYPERCALL_MSR_HYPERV;
|
||||||
|
+ kvm_xen_init(cs->kvm_state, c->ebx);
|
||||||
|
+ } else {
|
||||||
|
+ c->ebx = XEN_HYPERCALL_MSR;
|
||||||
|
+ }
|
||||||
|
+ c->ecx = 0;
|
||||||
|
+ c->edx = 0;
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_TIME;
|
||||||
|
+ c->eax = ((!!tsc_is_stable_and_known(env) << 1) |
|
||||||
|
+ (!!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP) << 2));
|
||||||
|
+ /* default=0 (emulate if necessary) */
|
||||||
|
+ c->ebx = 0;
|
||||||
|
+ /* guest tsc frequency */
|
||||||
|
+ c->ecx = env->user_tsc_khz;
|
||||||
|
+ /* guest tsc incarnation (migration count) */
|
||||||
|
+ c->edx = 0;
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
+ xen_max_leaf->eax = kvm_base + XEN_CPUID_HVM;
|
||||||
|
+ if (cs->kvm_state->xen_version >= XEN_VERSION(4, 5)) {
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
+
|
||||||
|
+ if (cpu->xen_vapic) {
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_APIC_ACCESS_VIRT;
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_X2APIC_VIRT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_IOMMU_MAPPINGS;
|
||||||
|
+
|
||||||
|
+ if (cs->kvm_state->xen_version >= XEN_VERSION(4, 6)) {
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_VCPU_ID_PRESENT;
|
||||||
|
+ c->ebx = cs->cpu_index;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cs->kvm_state->xen_version >= XEN_VERSION(4, 17)) {
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_UPCALL_VECTOR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ r = kvm_xen_init_vcpu(cs);
|
||||||
|
+ if (r) {
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kvm_base += 0x100;
|
||||||
|
+#else /* CONFIG_XEN_EMU */
|
||||||
|
+ /* This should never happen as kvm_arch_init() would have died first. */
|
||||||
|
+ fprintf(stderr, "Cannot enable Xen CPUID without Xen support\n");
|
||||||
|
+ abort();
|
||||||
|
+#endif
|
||||||
|
+ } else if (cpu->expose_kvm) {
|
||||||
|
+ memcpy(signature, "KVMKVMKVM\0\0\0", 12);
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = KVM_CPUID_SIGNATURE | kvm_base;
|
||||||
|
+ c->eax = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
+ c->ebx = signature[0];
|
||||||
|
+ c->ecx = signature[1];
|
||||||
|
+ c->edx = signature[2];
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
+ c->eax = env->features[FEAT_KVM];
|
||||||
|
+ c->edx = env->features[FEAT_KVM_HINTS];
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cpu->kvm_pv_enforce_cpuid) {
|
||||||
|
+ r = kvm_vcpu_enable_cap(cs, KVM_CAP_ENFORCE_PV_FEATURE_CPUID, 0, 1);
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "failed to enable KVM_CAP_ENFORCE_PV_FEATURE_CPUID: %s",
|
||||||
|
+ strerror(-r));
|
||||||
|
+ abort();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cpuid_i = kvm_x86_build_cpuid(env, cpuid_data.entries, cpuid_i);
|
||||||
|
cpuid_data.cpuid.nent = cpuid_i;
|
||||||
|
|
||||||
|
if (((env->cpuid_version >> 8)&0xF) >= 6
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,91 @@
|
|||||||
|
From 03e275023b482ac79b4f92ca4ceef6de3caa634f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Thu, 9 May 2024 19:00:40 +0200
|
||||||
|
Subject: [PATCH 045/100] i386: pc: remove unnecessary MachineClass overrides
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [45/91] c03d5b57014d0d02f6ce0cdfb19a34996d100dea (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
There is no need to override these fields of MachineClass because they are
|
||||||
|
already set to the right value in the superclass.
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||||
|
Message-ID: <20240509170044.190795-10-pbonzini@redhat.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit b348fdcdac9f9fc70be9ae56c54e41765e9aae24)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 3 ---
|
||||||
|
hw/i386/x86.c | 6 +++---
|
||||||
|
include/hw/i386/x86.h | 4 ----
|
||||||
|
3 files changed, 3 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index 660a59c63b..0aca0cc79e 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -1979,9 +1979,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
mc->async_pf_vmexit_disable = false;
|
||||||
|
mc->get_hotplug_handler = pc_get_hotplug_handler;
|
||||||
|
mc->hotplug_allowed = pc_hotplug_allowed;
|
||||||
|
- 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->auto_enable_numa_with_memhp = true;
|
||||||
|
mc->auto_enable_numa_with_memdev = true;
|
||||||
|
mc->has_hotpluggable_cpus = true;
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index c61f4ebfa6..fcef652c1e 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -443,7 +443,7 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
|
numa_cpu_pre_plug(cpu_slot, dev, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
-CpuInstanceProperties
|
||||||
|
+static CpuInstanceProperties
|
||||||
|
x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||||
|
@@ -453,7 +453,7 @@ x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
|
||||||
|
return possible_cpus->cpus[cpu_index].props;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||||
|
+static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||||
|
{
|
||||||
|
X86CPUTopoIDs topo_ids;
|
||||||
|
X86MachineState *x86ms = X86_MACHINE(ms);
|
||||||
|
@@ -467,7 +467,7 @@ int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||||
|
return topo_ids.pkg_id % ms->numa_state->num_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
|
||||||
|
+static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
|
||||||
|
{
|
||||||
|
X86MachineState *x86ms = X86_MACHINE(ms);
|
||||||
|
unsigned int max_cpus = ms->smp.max_cpus;
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index d7b7d3f3ce..c2062db13f 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -114,10 +114,6 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
|
||||||
|
|
||||||
|
void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
|
||||||
|
void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
|
||||||
|
-CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms,
|
||||||
|
- unsigned cpu_index);
|
||||||
|
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx);
|
||||||
|
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms);
|
||||||
|
CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
|
||||||
|
void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
|
||||||
|
void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
From 652793962000d6906e219ceae36348a476b78c28 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Fri, 31 May 2024 12:44:44 +0200
|
||||||
|
Subject: [PATCH 065/100] i386/sev: Add a class method to determine KVM VM type
|
||||||
|
for SNP guests
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [65/91] c6cbeac0a6f691138df212b80efaa9b1143fdaa8 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SEV guests can use either KVM_X86_DEFAULT_VM, KVM_X86_SEV_VM,
|
||||||
|
or KVM_X86_SEV_ES_VM depending on the configuration and what
|
||||||
|
the host kernel supports. SNP guests on the other hand can only
|
||||||
|
ever use KVM_X86_SNP_VM, so split determination of VM type out
|
||||||
|
into a separate class method that can be set accordingly for
|
||||||
|
sev-guest vs. sev-snp-guest objects and add handling for SNP.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-14-pankaj.gupta@amd.com>
|
||||||
|
[Remove unnecessary function pointer declaration. - Paolo]
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a808132f6d8e855bd83a400570ec91d2e00bebe3)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm.c | 1 +
|
||||||
|
target/i386/sev.c | 15 ++++++++++++---
|
||||||
|
2 files changed, 13 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index 408568d053..75e75d9772 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -166,6 +166,7 @@ static const char *vm_type_name[] = {
|
||||||
|
[KVM_X86_DEFAULT_VM] = "default",
|
||||||
|
[KVM_X86_SEV_VM] = "SEV",
|
||||||
|
[KVM_X86_SEV_ES_VM] = "SEV-ES",
|
||||||
|
+ [KVM_X86_SNP_VM] = "SEV-SNP",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool kvm_is_vm_type_supported(int type)
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index c3daaf1ad5..072cc4f853 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -885,6 +885,11 @@ out:
|
||||||
|
return sev_common->kvm_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int sev_snp_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
+{
|
||||||
|
+ return KVM_X86_SNP_VM;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
{
|
||||||
|
char *devname;
|
||||||
|
@@ -894,6 +899,8 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs);
|
||||||
|
+ X86ConfidentialGuestClass *x86_klass =
|
||||||
|
+ X86_CONFIDENTIAL_GUEST_GET_CLASS(cgs);
|
||||||
|
|
||||||
|
sev_common->state = SEV_STATE_UNINIT;
|
||||||
|
|
||||||
|
@@ -964,7 +971,7 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_kvm_sev_init();
|
||||||
|
- if (sev_kvm_type(X86_CONFIDENTIAL_GUEST(sev_common)) == KVM_X86_DEFAULT_VM) {
|
||||||
|
+ if (x86_klass->kvm_type(X86_CONFIDENTIAL_GUEST(sev_common)) == KVM_X86_DEFAULT_VM) {
|
||||||
|
cmd = sev_es_enabled() ? KVM_SEV_ES_INIT : KVM_SEV_INIT;
|
||||||
|
|
||||||
|
ret = sev_ioctl(sev_common->sev_fd, cmd, NULL, &fw_error);
|
||||||
|
@@ -1441,10 +1448,8 @@ static void
|
||||||
|
sev_common_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
|
||||||
|
- X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->kvm_init = sev_common_kvm_init;
|
||||||
|
- x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "sev-device",
|
||||||
|
sev_common_get_sev_device,
|
||||||
|
@@ -1529,10 +1534,12 @@ static void
|
||||||
|
sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
+ X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
klass->kvm_init = sev_kvm_init;
|
||||||
|
+ x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
sev_guest_get_dh_cert_file,
|
||||||
|
@@ -1770,8 +1777,10 @@ static void
|
||||||
|
sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
+ X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
+ x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,84 @@
|
|||||||
|
From 82a714b79851b5c2d1389d2fa7a01548c486a854 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:20 -0500
|
||||||
|
Subject: [PATCH 060/100] i386/sev: Add a sev_snp_enabled() helper
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [60/91] c35ead095028ccfb1e1be0fe010ca4f7688530a0 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add a simple helper to check if the current guest type is SNP. Also have
|
||||||
|
SNP-enabled imply that SEV-ES is enabled as well, and fix up any places
|
||||||
|
where the sev_es_enabled() check is expecting a pure/non-SNP guest.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-9-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 99190f805dca9475fe244fbd8041961842657dc2)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 13 ++++++++++++-
|
||||||
|
target/i386/sev.h | 2 ++
|
||||||
|
2 files changed, 14 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index a81b3228d4..4edfedc139 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -325,12 +325,21 @@ sev_enabled(void)
|
||||||
|
return !!object_dynamic_cast(OBJECT(cgs), TYPE_SEV_COMMON);
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool
|
||||||
|
+sev_snp_enabled(void)
|
||||||
|
+{
|
||||||
|
+ ConfidentialGuestSupport *cgs = MACHINE(qdev_get_machine())->cgs;
|
||||||
|
+
|
||||||
|
+ return !!object_dynamic_cast(OBJECT(cgs), TYPE_SEV_SNP_GUEST);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool
|
||||||
|
sev_es_enabled(void)
|
||||||
|
{
|
||||||
|
ConfidentialGuestSupport *cgs = MACHINE(qdev_get_machine())->cgs;
|
||||||
|
|
||||||
|
- return sev_enabled() && (SEV_GUEST(cgs)->policy & SEV_POLICY_ES);
|
||||||
|
+ return sev_snp_enabled() ||
|
||||||
|
+ (sev_enabled() && SEV_GUEST(cgs)->policy & SEV_POLICY_ES);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
@@ -946,7 +955,9 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
"support", __func__);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ if (sev_es_enabled() && !sev_snp_enabled()) {
|
||||||
|
if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
|
||||||
|
error_setg(errp, "%s: guest policy requires SEV-ES, but "
|
||||||
|
"host SEV-ES support unavailable",
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index bedc667eeb..94295ee74f 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -45,9 +45,11 @@ typedef struct SevKernelLoaderContext {
|
||||||
|
#ifdef CONFIG_SEV
|
||||||
|
bool sev_enabled(void);
|
||||||
|
bool sev_es_enabled(void);
|
||||||
|
+bool sev_snp_enabled(void);
|
||||||
|
#else
|
||||||
|
#define sev_enabled() 0
|
||||||
|
#define sev_es_enabled() 0
|
||||||
|
+#define sev_snp_enabled() 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t sev_get_cbit_position(void);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,187 @@
|
|||||||
|
From 0e435819540b0d39da2c828aacc0f35ecaadbdf6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:28 -0500
|
||||||
|
Subject: [PATCH 068/100] i386/sev: Add handling to encrypt/finalize guest
|
||||||
|
launch data
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [68/91] fe77931d279aa8df061823da88a320fb5f72ffea (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Process any queued up launch data and encrypt/measure it into the SNP
|
||||||
|
guest instance prior to initial guest launch.
|
||||||
|
|
||||||
|
This also updates the KVM_SEV_SNP_LAUNCH_UPDATE call to handle partial
|
||||||
|
update responses.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Co-developed-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-17-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 9f3a6999f9730a694d7db448a99f9c9cb6515992)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 112 ++++++++++++++++++++++++++++++++++++++-
|
||||||
|
target/i386/trace-events | 2 +
|
||||||
|
2 files changed, 113 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index e89b87d2f5..ef2e592ca7 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -756,6 +756,76 @@ out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static const char *
|
||||||
|
+snp_page_type_to_str(int type)
|
||||||
|
+{
|
||||||
|
+ switch (type) {
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_NORMAL: return "Normal";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_ZERO: return "Zero";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_UNMEASURED: return "Unmeasured";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_SECRETS: return "Secrets";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_CPUID: return "Cpuid";
|
||||||
|
+ default: return "unknown";
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
+ SevLaunchUpdateData *data)
|
||||||
|
+{
|
||||||
|
+ int ret, fw_error;
|
||||||
|
+ struct kvm_sev_snp_launch_update update = {0};
|
||||||
|
+
|
||||||
|
+ if (!data->hva || !data->len) {
|
||||||
|
+ error_report("SNP_LAUNCH_UPDATE called with invalid address"
|
||||||
|
+ "/ length: %p / %lx",
|
||||||
|
+ data->hva, data->len);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ update.uaddr = (__u64)(unsigned long)data->hva;
|
||||||
|
+ update.gfn_start = data->gpa >> TARGET_PAGE_BITS;
|
||||||
|
+ update.len = data->len;
|
||||||
|
+ update.type = data->type;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * KVM_SEV_SNP_LAUNCH_UPDATE requires that GPA ranges have the private
|
||||||
|
+ * memory attribute set in advance.
|
||||||
|
+ */
|
||||||
|
+ ret = kvm_set_memory_attributes_private(data->gpa, data->len);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SEV-SNP: failed to configure initial"
|
||||||
|
+ "private guest memory");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (update.len || ret == -EAGAIN) {
|
||||||
|
+ trace_kvm_sev_snp_launch_update(update.uaddr, update.gfn_start <<
|
||||||
|
+ TARGET_PAGE_BITS, update.len,
|
||||||
|
+ snp_page_type_to_str(update.type));
|
||||||
|
+
|
||||||
|
+ ret = sev_ioctl(SEV_COMMON(sev_snp_guest)->sev_fd,
|
||||||
|
+ KVM_SEV_SNP_LAUNCH_UPDATE,
|
||||||
|
+ &update, &fw_error);
|
||||||
|
+ if (ret && ret != -EAGAIN) {
|
||||||
|
+ error_report("SNP_LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
|
||||||
|
+ ret, fw_error, fw_error_to_str(fw_error));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ if (!ret && update.gfn_start << TARGET_PAGE_BITS != data->gpa + data->len) {
|
||||||
|
+ error_report("SEV-SNP: expected update of GPA range %lx-%lx,"
|
||||||
|
+ "got GPA range %lx-%llx",
|
||||||
|
+ data->gpa, data->gpa + data->len, data->gpa,
|
||||||
|
+ update.gfn_start << TARGET_PAGE_BITS);
|
||||||
|
+ ret = -EIO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_launch_update_data(SevGuestState *sev_guest, uint8_t *addr, uint64_t len)
|
||||||
|
{
|
||||||
|
@@ -901,6 +971,46 @@ sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
migrate_add_blocker(&sev_mig_blocker, &error_fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+sev_snp_launch_finish(SevCommonState *sev_common)
|
||||||
|
+{
|
||||||
|
+ int ret, error;
|
||||||
|
+ Error *local_err = NULL;
|
||||||
|
+ SevLaunchUpdateData *data;
|
||||||
|
+ SevSnpGuestState *sev_snp = SEV_SNP_GUEST(sev_common);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp->kvm_finish_conf;
|
||||||
|
+
|
||||||
|
+ QTAILQ_FOREACH(data, &launch_update, next) {
|
||||||
|
+ ret = sev_snp_launch_update(sev_snp, data);
|
||||||
|
+ if (ret) {
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ trace_kvm_sev_snp_launch_finish(sev_snp->id_block, sev_snp->id_auth,
|
||||||
|
+ sev_snp->host_data);
|
||||||
|
+ ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_LAUNCH_FINISH,
|
||||||
|
+ finish, &error);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SNP_LAUNCH_FINISH ret=%d fw_error=%d '%s'",
|
||||||
|
+ ret, error, fw_error_to_str(error));
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sev_set_guest_state(sev_common, SEV_STATE_RUNNING);
|
||||||
|
+
|
||||||
|
+ /* add migration blocker */
|
||||||
|
+ error_setg(&sev_mig_blocker,
|
||||||
|
+ "SEV-SNP: Migration is not implemented");
|
||||||
|
+ ret = migrate_add_blocker(&sev_mig_blocker, &local_err);
|
||||||
|
+ if (local_err) {
|
||||||
|
+ error_report_err(local_err);
|
||||||
|
+ error_free(sev_mig_blocker);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
|
{
|
||||||
|
@@ -1832,10 +1942,10 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->launch_start = sev_snp_launch_start;
|
||||||
|
+ klass->launch_finish = sev_snp_launch_finish;
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
-
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||||||
|
index cb26d8a925..06b44ead2e 100644
|
||||||
|
--- a/target/i386/trace-events
|
||||||
|
+++ b/target/i386/trace-events
|
||||||
|
@@ -12,3 +12,5 @@ kvm_sev_launch_finish(void) ""
|
||||||
|
kvm_sev_launch_secret(uint64_t hpa, uint64_t hva, uint64_t secret, int len) "hpa 0x%" PRIx64 " hva 0x%" PRIx64 " data 0x%" PRIx64 " len %d"
|
||||||
|
kvm_sev_attestation_report(const char *mnonce, const char *data) "mnonce %s data %s"
|
||||||
|
kvm_sev_snp_launch_start(uint64_t policy, char *gosvw) "policy 0x%" PRIx64 " gosvw %s"
|
||||||
|
+kvm_sev_snp_launch_update(uint64_t src, uint64_t gpa, uint64_t len, const char *type) "src 0x%" PRIx64 " gpa 0x%" PRIx64 " len 0x%" PRIx64 " (%s page)"
|
||||||
|
+kvm_sev_snp_launch_finish(char *id_block, char *id_auth, char *host_data) "id_block %s id_auth %s host_data %s"
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,127 @@
|
|||||||
|
From 2872c423fa44dcbf50b581a5c3feac064a0473a0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Tue, 9 Apr 2024 18:07:41 -0500
|
||||||
|
Subject: [PATCH 024/100] i386/sev: Add 'legacy-vm-type' parameter for SEV
|
||||||
|
guest objects
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [24/91] ce35d1b09fe8aa8772ff149543f7760455c1e6b5 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
QEMU will currently automatically make use of the KVM_SEV_INIT2 API for
|
||||||
|
initializing SEV and SEV-ES guests verses the older
|
||||||
|
KVM_SEV_INIT/KVM_SEV_ES_INIT interfaces.
|
||||||
|
|
||||||
|
However, the older interfaces will silently avoid sync'ing FPU/XSAVE
|
||||||
|
state to the VMSA prior to encryption, thus relying on behavior and
|
||||||
|
measurements that assume the related fields to be allow zero.
|
||||||
|
|
||||||
|
With KVM_SEV_INIT2, this state is now synced into the VMSA, resulting in
|
||||||
|
measurements changes and, theoretically, behaviorial changes, though the
|
||||||
|
latter are unlikely to be seen in practice.
|
||||||
|
|
||||||
|
To allow a smooth transition to the newer interface, while still
|
||||||
|
providing a mechanism to maintain backward compatibility with VMs
|
||||||
|
created using the older interfaces, provide a new command-line
|
||||||
|
parameter:
|
||||||
|
|
||||||
|
-object sev-guest,legacy-vm-type=true,...
|
||||||
|
|
||||||
|
and have it default to false.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Message-ID: <20240409230743.962513-2-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 023267334da375226720e62963df9545aa8fc2fd)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
qapi/qom.json | 11 ++++++++++-
|
||||||
|
target/i386/sev.c | 18 +++++++++++++++++-
|
||||||
|
2 files changed, 27 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/qapi/qom.json b/qapi/qom.json
|
||||||
|
index 85e6b4f84a..38dde6d785 100644
|
||||||
|
--- a/qapi/qom.json
|
||||||
|
+++ b/qapi/qom.json
|
||||||
|
@@ -898,6 +898,14 @@
|
||||||
|
# designated guest firmware page for measured boot with -kernel
|
||||||
|
# (default: false) (since 6.2)
|
||||||
|
#
|
||||||
|
+# @legacy-vm-type: Use legacy KVM_SEV_INIT KVM interface for creating the VM.
|
||||||
|
+# The newer KVM_SEV_INIT2 interface syncs additional vCPU
|
||||||
|
+# state when initializing the VMSA structures, which will
|
||||||
|
+# result in a different guest measurement. Set this to
|
||||||
|
+# maintain compatibility with older QEMU or kernel versions
|
||||||
|
+# that rely on legacy KVM_SEV_INIT behavior.
|
||||||
|
+# (default: false) (since 9.1)
|
||||||
|
+#
|
||||||
|
# Since: 2.12
|
||||||
|
##
|
||||||
|
{ 'struct': 'SevGuestProperties',
|
||||||
|
@@ -908,7 +916,8 @@
|
||||||
|
'*handle': 'uint32',
|
||||||
|
'*cbitpos': 'uint32',
|
||||||
|
'reduced-phys-bits': 'uint32',
|
||||||
|
- '*kernel-hashes': 'bool' } }
|
||||||
|
+ '*kernel-hashes': 'bool',
|
||||||
|
+ '*legacy-vm-type': 'bool' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @ThreadContextProperties:
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 9dab4060b8..f4ee317cb0 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -67,6 +67,7 @@ struct SevGuestState {
|
||||||
|
uint32_t cbitpos;
|
||||||
|
uint32_t reduced_phys_bits;
|
||||||
|
bool kernel_hashes;
|
||||||
|
+ bool legacy_vm_type;
|
||||||
|
|
||||||
|
/* runtime state */
|
||||||
|
uint32_t handle;
|
||||||
|
@@ -356,6 +357,16 @@ static void sev_guest_set_kernel_hashes(Object *obj, bool value, Error **errp)
|
||||||
|
sev->kernel_hashes = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool sev_guest_get_legacy_vm_type(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ return SEV_GUEST(obj)->legacy_vm_type;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void sev_guest_set_legacy_vm_type(Object *obj, bool value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SEV_GUEST(obj)->legacy_vm_type = value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool
|
||||||
|
sev_enabled(void)
|
||||||
|
{
|
||||||
|
@@ -863,7 +874,7 @@ static int sev_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
}
|
||||||
|
|
||||||
|
kvm_type = (sev->policy & SEV_POLICY_ES) ? KVM_X86_SEV_ES_VM : KVM_X86_SEV_VM;
|
||||||
|
- if (kvm_is_vm_type_supported(kvm_type)) {
|
||||||
|
+ if (kvm_is_vm_type_supported(kvm_type) && !sev->legacy_vm_type) {
|
||||||
|
sev->kvm_type = kvm_type;
|
||||||
|
} else {
|
||||||
|
sev->kvm_type = KVM_X86_DEFAULT_VM;
|
||||||
|
@@ -1381,6 +1392,11 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
sev_guest_set_kernel_hashes);
|
||||||
|
object_class_property_set_description(oc, "kernel-hashes",
|
||||||
|
"add kernel hashes to guest firmware for measured Linux boot");
|
||||||
|
+ object_class_property_add_bool(oc, "legacy-vm-type",
|
||||||
|
+ sev_guest_get_legacy_vm_type,
|
||||||
|
+ sev_guest_set_legacy_vm_type);
|
||||||
|
+ object_class_property_set_description(oc, "legacy-vm-type",
|
||||||
|
+ "use legacy VM type to maintain measurement compatibility with older QEMU or kernel versions.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,203 @@
|
|||||||
|
From a236548a903aa8350fff9601d481b2f529c8d4a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:21 -0500
|
||||||
|
Subject: [PATCH 061/100] i386/sev: Add sev_kvm_init() override for SEV class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [61/91] b24fcbc8712e7394e029312229da023c63803969 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Some aspects of the init routine SEV are specific to SEV and not
|
||||||
|
applicable for SNP guests, so move the SEV-specific bits into
|
||||||
|
separate class method and retain only the common functionality.
|
||||||
|
|
||||||
|
Co-developed-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-10-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 990da8d243a8c59dafcbed78b56a0e4ffb1605d9)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 72 +++++++++++++++++++++++++++++++++--------------
|
||||||
|
1 file changed, 51 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 4edfedc139..5519de1c6b 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -73,6 +73,7 @@ struct SevCommonStateClass {
|
||||||
|
/* public */
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
+ int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -882,7 +883,7 @@ out:
|
||||||
|
return sev_common->kvm_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
+static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
char *devname;
|
||||||
|
@@ -892,12 +893,6 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs);
|
||||||
|
|
||||||
|
- ret = ram_block_discard_disable(true);
|
||||||
|
- if (ret) {
|
||||||
|
- error_report("%s: cannot disable RAM discard", __func__);
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
sev_common->state = SEV_STATE_UNINIT;
|
||||||
|
|
||||||
|
host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
|
||||||
|
@@ -911,7 +906,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
if (host_cbitpos != sev_common->cbitpos) {
|
||||||
|
error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
|
||||||
|
__func__, host_cbitpos, sev_common->cbitpos);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -924,7 +919,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: reduced_phys_bits check failed,"
|
||||||
|
" it should be in the range of 1 to 63, requested '%d'",
|
||||||
|
__func__, sev_common->reduced_phys_bits);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
devname = object_property_get_str(OBJECT(sev_common), "sev-device", NULL);
|
||||||
|
@@ -933,7 +928,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: Failed to open %s '%s'", __func__,
|
||||||
|
devname, strerror(errno));
|
||||||
|
g_free(devname);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
g_free(devname);
|
||||||
|
|
||||||
|
@@ -943,7 +938,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: failed to get platform status ret=%d "
|
||||||
|
"fw_error='%d: %s'", __func__, ret, fw_error,
|
||||||
|
fw_error_to_str(fw_error));
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
sev_common->build_id = status.build;
|
||||||
|
sev_common->api_major = status.api_major;
|
||||||
|
@@ -953,7 +948,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
if (!kvm_kernel_irqchip_allowed()) {
|
||||||
|
error_setg(errp, "%s: SEV-ES guests require in-kernel irqchip"
|
||||||
|
"support", __func__);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -962,7 +957,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: guest policy requires SEV-ES, but "
|
||||||
|
"host SEV-ES support unavailable",
|
||||||
|
__func__);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -980,25 +975,59 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
if (ret) {
|
||||||
|
error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
|
||||||
|
__func__, ret, fw_error, fw_error_to_str(fw_error));
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = klass->launch_start(sev_common);
|
||||||
|
if (ret) {
|
||||||
|
error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (klass->kvm_init && klass->kvm_init(cgs, errp)) {
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ram_block_notifier_add(&sev_ram_notifier);
|
||||||
|
- qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
|
||||||
|
qemu_add_vm_change_state_handler(sev_vm_state_change, sev_common);
|
||||||
|
|
||||||
|
cgs->ready = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
-err:
|
||||||
|
- ram_block_discard_disable(false);
|
||||||
|
- return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * SEV/SEV-ES rely on pinned memory to back guest RAM so discarding
|
||||||
|
+ * isn't actually possible. With SNP, only guest_memfd pages are used
|
||||||
|
+ * for private guest memory, so discarding of shared memory is still
|
||||||
|
+ * possible..
|
||||||
|
+ */
|
||||||
|
+ ret = ram_block_discard_disable(true);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_setg(errp, "%s: cannot disable RAM discard", __func__);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * SEV uses these notifiers to register/pin pages prior to guest use,
|
||||||
|
+ * but SNP relies on guest_memfd for private pages, which has its
|
||||||
|
+ * own internal mechanisms for registering/pinning private memory.
|
||||||
|
+ */
|
||||||
|
+ ram_block_notifier_add(&sev_ram_notifier);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The machine done notify event is used for SEV guests to get the
|
||||||
|
+ * measurement of the encrypted images. When SEV-SNP is enabled, the
|
||||||
|
+ * measurement is part of the guest attestation process where it can
|
||||||
|
+ * be collected without any reliance on the VMM. So skip registering
|
||||||
|
+ * the notifier for SNP in favor of using guest attestation instead.
|
||||||
|
+ */
|
||||||
|
+ qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
@@ -1397,7 +1426,7 @@ sev_common_class_init(ObjectClass *oc, void *data)
|
||||||
|
ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
- klass->kvm_init = sev_kvm_init;
|
||||||
|
+ klass->kvm_init = sev_common_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "sev-device",
|
||||||
|
@@ -1486,6 +1515,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
+ klass->kvm_init = sev_kvm_init;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
sev_guest_get_dh_cert_file,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,94 @@
|
|||||||
|
From 35ceebdeccbf5dceb374c6f89a12e9981def570b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:22 -0500
|
||||||
|
Subject: [PATCH 062/100] i386/sev: Add snp_kvm_init() override for SNP class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [62/91] 8fa537961c9262b99a4ffb99e1c25f080d76d1de (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SNP does not support SMM and requires guest_memfd for
|
||||||
|
private guest memory, so add SNP specific kvm_init()
|
||||||
|
functionality in snp_kvm_init() class method.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-11-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 125b95a6d465a03ff30816eff0b1889aec01f0c3)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 24 +++++++++++++++++++++++-
|
||||||
|
1 file changed, 23 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 5519de1c6b..6525b3c1a0 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -885,12 +885,12 @@ out:
|
||||||
|
|
||||||
|
static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
{
|
||||||
|
- SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
char *devname;
|
||||||
|
int ret, fw_error, cmd;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t host_cbitpos;
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
+ SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs);
|
||||||
|
|
||||||
|
sev_common->state = SEV_STATE_UNINIT;
|
||||||
|
@@ -1030,6 +1030,21 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int sev_snp_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
+{
|
||||||
|
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||||
|
+ X86MachineState *x86ms = X86_MACHINE(ms);
|
||||||
|
+
|
||||||
|
+ if (x86ms->smm == ON_OFF_AUTO_AUTO) {
|
||||||
|
+ x86ms->smm = ON_OFF_AUTO_OFF;
|
||||||
|
+ } else if (x86ms->smm == ON_OFF_AUTO_ON) {
|
||||||
|
+ error_setg(errp, "SEV-SNP does not support SMM.");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
@@ -1752,6 +1767,10 @@ sev_snp_guest_set_host_data(Object *obj, const char *value, Error **errp)
|
||||||
|
static void
|
||||||
|
sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
+
|
||||||
|
+ klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
+
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
@@ -1778,8 +1797,11 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
static void
|
||||||
|
sev_snp_guest_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
+ ConfidentialGuestSupport *cgs = CONFIDENTIAL_GUEST_SUPPORT(obj);
|
||||||
|
SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
|
||||||
|
+ cgs->require_guest_memfd = true;
|
||||||
|
+
|
||||||
|
/* default init/start/finish params for kvm */
|
||||||
|
sev_snp_guest->kvm_start_conf.policy = DEFAULT_SEV_SNP_POLICY;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,262 @@
|
|||||||
|
From 4013364679757161d6b9754bfc33ae38be0a1b7f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:32 -0500
|
||||||
|
Subject: [PATCH 072/100] i386/sev: Add support for SNP CPUID validation
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [72/91] 080e2942552dc7de8966e69d0d0d3b8951392030 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SEV-SNP firmware allows a special guest page to be populated with a
|
||||||
|
table of guest CPUID values so that they can be validated through
|
||||||
|
firmware before being loaded into encrypted guest memory where they can
|
||||||
|
be used in place of hypervisor-provided values[1].
|
||||||
|
|
||||||
|
As part of SEV-SNP guest initialization, use this interface to validate
|
||||||
|
the CPUID entries reported by KVM_GET_CPUID2 prior to initial guest
|
||||||
|
start and populate the CPUID page reserved by OVMF with the resulting
|
||||||
|
encrypted data.
|
||||||
|
|
||||||
|
[1] SEV SNP Firmware ABI Specification, Rev. 0.8, 8.13.2.6
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-21-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 70943ad8e4dfbe5f77006b880290219be9d03553)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 164 +++++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 162 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index c57534fca2..06401f0526 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -200,6 +200,36 @@ static const char *const sev_fw_errlist[] = {
|
||||||
|
|
||||||
|
#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
|
||||||
|
|
||||||
|
+/* <linux/kvm.h> doesn't expose this, so re-use the max from kvm.c */
|
||||||
|
+#define KVM_MAX_CPUID_ENTRIES 100
|
||||||
|
+
|
||||||
|
+typedef struct KvmCpuidInfo {
|
||||||
|
+ struct kvm_cpuid2 cpuid;
|
||||||
|
+ struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
|
||||||
|
+} KvmCpuidInfo;
|
||||||
|
+
|
||||||
|
+#define SNP_CPUID_FUNCTION_MAXCOUNT 64
|
||||||
|
+#define SNP_CPUID_FUNCTION_UNKNOWN 0xFFFFFFFF
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ uint32_t eax_in;
|
||||||
|
+ uint32_t ecx_in;
|
||||||
|
+ uint64_t xcr0_in;
|
||||||
|
+ uint64_t xss_in;
|
||||||
|
+ uint32_t eax;
|
||||||
|
+ uint32_t ebx;
|
||||||
|
+ uint32_t ecx;
|
||||||
|
+ uint32_t edx;
|
||||||
|
+ uint64_t reserved;
|
||||||
|
+} __attribute__((packed)) SnpCpuidFunc;
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ uint32_t count;
|
||||||
|
+ uint32_t reserved1;
|
||||||
|
+ uint64_t reserved2;
|
||||||
|
+ SnpCpuidFunc entries[SNP_CPUID_FUNCTION_MAXCOUNT];
|
||||||
|
+} __attribute__((packed)) SnpCpuidInfo;
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_ioctl(int fd, int cmd, void *data, int *error)
|
||||||
|
{
|
||||||
|
@@ -788,6 +818,35 @@ out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+sev_snp_cpuid_report_mismatches(SnpCpuidInfo *old,
|
||||||
|
+ SnpCpuidInfo *new)
|
||||||
|
+{
|
||||||
|
+ size_t i;
|
||||||
|
+
|
||||||
|
+ if (old->count != new->count) {
|
||||||
|
+ error_report("SEV-SNP: CPUID validation failed due to count mismatch,"
|
||||||
|
+ "provided: %d, expected: %d", old->count, new->count);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < old->count; i++) {
|
||||||
|
+ SnpCpuidFunc *old_func, *new_func;
|
||||||
|
+
|
||||||
|
+ old_func = &old->entries[i];
|
||||||
|
+ new_func = &new->entries[i];
|
||||||
|
+
|
||||||
|
+ if (memcmp(old_func, new_func, sizeof(SnpCpuidFunc))) {
|
||||||
|
+ error_report("SEV-SNP: CPUID validation failed for function 0x%x, index: 0x%x"
|
||||||
|
+ "provided: eax:0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x"
|
||||||
|
+ "expected: eax:0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x",
|
||||||
|
+ old_func->eax_in, old_func->ecx_in,
|
||||||
|
+ old_func->eax, old_func->ebx, old_func->ecx, old_func->edx,
|
||||||
|
+ new_func->eax, new_func->ebx, new_func->ecx, new_func->edx);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const char *
|
||||||
|
snp_page_type_to_str(int type)
|
||||||
|
{
|
||||||
|
@@ -806,6 +865,7 @@ sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
SevLaunchUpdateData *data)
|
||||||
|
{
|
||||||
|
int ret, fw_error;
|
||||||
|
+ SnpCpuidInfo snp_cpuid_info;
|
||||||
|
struct kvm_sev_snp_launch_update update = {0};
|
||||||
|
|
||||||
|
if (!data->hva || !data->len) {
|
||||||
|
@@ -815,6 +875,11 @@ sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (data->type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
+ /* Save a copy for comparison in case the LAUNCH_UPDATE fails */
|
||||||
|
+ memcpy(&snp_cpuid_info, data->hva, sizeof(snp_cpuid_info));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
update.uaddr = (__u64)(unsigned long)data->hva;
|
||||||
|
update.gfn_start = data->gpa >> TARGET_PAGE_BITS;
|
||||||
|
update.len = data->len;
|
||||||
|
@@ -842,6 +907,11 @@ sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
if (ret && ret != -EAGAIN) {
|
||||||
|
error_report("SNP_LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
|
||||||
|
ret, fw_error, fw_error_to_str(fw_error));
|
||||||
|
+
|
||||||
|
+ if (data->type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
+ sev_snp_cpuid_report_mismatches(&snp_cpuid_info, data->hva);
|
||||||
|
+ error_report("SEV-SNP: failed update CPUID page");
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1004,7 +1074,8 @@ sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-snp_launch_update_data(uint64_t gpa, void *hva, uint32_t len, int type)
|
||||||
|
+snp_launch_update_data(uint64_t gpa, void *hva,
|
||||||
|
+ uint32_t len, int type)
|
||||||
|
{
|
||||||
|
SevLaunchUpdateData *data;
|
||||||
|
|
||||||
|
@@ -1019,6 +1090,90 @@ snp_launch_update_data(uint64_t gpa, void *hva, uint32_t len, int type)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sev_snp_cpuid_info_fill(SnpCpuidInfo *snp_cpuid_info,
|
||||||
|
+ const KvmCpuidInfo *kvm_cpuid_info)
|
||||||
|
+{
|
||||||
|
+ size_t i;
|
||||||
|
+
|
||||||
|
+ if (kvm_cpuid_info->cpuid.nent > SNP_CPUID_FUNCTION_MAXCOUNT) {
|
||||||
|
+ error_report("SEV-SNP: CPUID entry count (%d) exceeds max (%d)",
|
||||||
|
+ kvm_cpuid_info->cpuid.nent, SNP_CPUID_FUNCTION_MAXCOUNT);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memset(snp_cpuid_info, 0, sizeof(*snp_cpuid_info));
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < kvm_cpuid_info->cpuid.nent; i++) {
|
||||||
|
+ const struct kvm_cpuid_entry2 *kvm_cpuid_entry;
|
||||||
|
+ SnpCpuidFunc *snp_cpuid_entry;
|
||||||
|
+
|
||||||
|
+ kvm_cpuid_entry = &kvm_cpuid_info->entries[i];
|
||||||
|
+ snp_cpuid_entry = &snp_cpuid_info->entries[i];
|
||||||
|
+
|
||||||
|
+ snp_cpuid_entry->eax_in = kvm_cpuid_entry->function;
|
||||||
|
+ if (kvm_cpuid_entry->flags == KVM_CPUID_FLAG_SIGNIFCANT_INDEX) {
|
||||||
|
+ snp_cpuid_entry->ecx_in = kvm_cpuid_entry->index;
|
||||||
|
+ }
|
||||||
|
+ snp_cpuid_entry->eax = kvm_cpuid_entry->eax;
|
||||||
|
+ snp_cpuid_entry->ebx = kvm_cpuid_entry->ebx;
|
||||||
|
+ snp_cpuid_entry->ecx = kvm_cpuid_entry->ecx;
|
||||||
|
+ snp_cpuid_entry->edx = kvm_cpuid_entry->edx;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Guest kernels will calculate EBX themselves using the 0xD
|
||||||
|
+ * subfunctions corresponding to the individual XSAVE areas, so only
|
||||||
|
+ * encode the base XSAVE size in the initial leaves, corresponding
|
||||||
|
+ * to the initial XCR0=1 state.
|
||||||
|
+ */
|
||||||
|
+ if (snp_cpuid_entry->eax_in == 0xD &&
|
||||||
|
+ (snp_cpuid_entry->ecx_in == 0x0 || snp_cpuid_entry->ecx_in == 0x1)) {
|
||||||
|
+ snp_cpuid_entry->ebx = 0x240;
|
||||||
|
+ snp_cpuid_entry->xcr0_in = 1;
|
||||||
|
+ snp_cpuid_entry->xss_in = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ snp_cpuid_info->count = i;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+snp_launch_update_cpuid(uint32_t cpuid_addr, void *hva, uint32_t cpuid_len)
|
||||||
|
+{
|
||||||
|
+ KvmCpuidInfo kvm_cpuid_info = {0};
|
||||||
|
+ SnpCpuidInfo snp_cpuid_info;
|
||||||
|
+ CPUState *cs = first_cpu;
|
||||||
|
+ int ret;
|
||||||
|
+ uint32_t i = 0;
|
||||||
|
+
|
||||||
|
+ assert(sizeof(snp_cpuid_info) <= cpuid_len);
|
||||||
|
+
|
||||||
|
+ /* get the cpuid list from KVM */
|
||||||
|
+ do {
|
||||||
|
+ kvm_cpuid_info.cpuid.nent = ++i;
|
||||||
|
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_CPUID2, &kvm_cpuid_info);
|
||||||
|
+ } while (ret == -E2BIG);
|
||||||
|
+
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SEV-SNP: unable to query CPUID values for CPU: '%s'",
|
||||||
|
+ strerror(-ret));
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = sev_snp_cpuid_info_fill(&snp_cpuid_info, &kvm_cpuid_info);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SEV-SNP: failed to generate CPUID table information");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(hva, &snp_cpuid_info, sizeof(snp_cpuid_info));
|
||||||
|
+
|
||||||
|
+ return snp_launch_update_data(cpuid_addr, hva, cpuid_len,
|
||||||
|
+ KVM_SEV_SNP_PAGE_TYPE_CPUID);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
snp_metadata_desc_to_page_type(int desc_type)
|
||||||
|
{
|
||||||
|
@@ -1053,7 +1208,12 @@ snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
+ if (type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
+ ret = snp_launch_update_cpuid(desc->base, hva, desc->len);
|
||||||
|
+ } else {
|
||||||
|
+ ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (ret) {
|
||||||
|
error_report("%s: Failed to add metadata page gpa 0x%x+%x type %d",
|
||||||
|
__func__, desc->base, desc->len, desc->type);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,127 @@
|
|||||||
|
From b2cfd4d89026e76ba86ea7adea323f2c3a588790 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:31 -0500
|
||||||
|
Subject: [PATCH 071/100] i386/sev: Add support for populating OVMF metadata
|
||||||
|
pages
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [71/91] b563442c0e2f6ea01937425d300b56d9e641fd57 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
OVMF reserves various pages so they can be pre-initialized/validated
|
||||||
|
prior to launching the guest. Add support for populating these pages
|
||||||
|
with the expected content.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-20-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 3d8c2a7f4806ff39423312e503737fd76c34dcae)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 74 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 17281bb2c7..c57534fca2 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1003,15 +1003,89 @@ sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
migrate_add_blocker(&sev_mig_blocker, &error_fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+snp_launch_update_data(uint64_t gpa, void *hva, uint32_t len, int type)
|
||||||
|
+{
|
||||||
|
+ SevLaunchUpdateData *data;
|
||||||
|
+
|
||||||
|
+ data = g_new0(SevLaunchUpdateData, 1);
|
||||||
|
+ data->gpa = gpa;
|
||||||
|
+ data->hva = hva;
|
||||||
|
+ data->len = len;
|
||||||
|
+ data->type = type;
|
||||||
|
+
|
||||||
|
+ QTAILQ_INSERT_TAIL(&launch_update, data, next);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+snp_metadata_desc_to_page_type(int desc_type)
|
||||||
|
+{
|
||||||
|
+ switch (desc_type) {
|
||||||
|
+ /* Add the umeasured prevalidated pages as a zero page */
|
||||||
|
+ case SEV_DESC_TYPE_SNP_SEC_MEM: return KVM_SEV_SNP_PAGE_TYPE_ZERO;
|
||||||
|
+ case SEV_DESC_TYPE_SNP_SECRETS: return KVM_SEV_SNP_PAGE_TYPE_SECRETS;
|
||||||
|
+ case SEV_DESC_TYPE_CPUID: return KVM_SEV_SNP_PAGE_TYPE_CPUID;
|
||||||
|
+ default:
|
||||||
|
+ return KVM_SEV_SNP_PAGE_TYPE_ZERO;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
|
||||||
|
+ OvmfSevMetadata *metadata)
|
||||||
|
+{
|
||||||
|
+ OvmfSevMetadataDesc *desc;
|
||||||
|
+ int type, ret, i;
|
||||||
|
+ void *hva;
|
||||||
|
+ MemoryRegion *mr = NULL;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < metadata->num_desc; i++) {
|
||||||
|
+ desc = &metadata->descs[i];
|
||||||
|
+
|
||||||
|
+ type = snp_metadata_desc_to_page_type(desc->type);
|
||||||
|
+
|
||||||
|
+ hva = gpa2hva(&mr, desc->base, desc->len, NULL);
|
||||||
|
+ if (!hva) {
|
||||||
|
+ error_report("%s: Failed to get HVA for GPA 0x%x sz 0x%x",
|
||||||
|
+ __func__, desc->base, desc->len);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("%s: Failed to add metadata page gpa 0x%x+%x type %d",
|
||||||
|
+ __func__, desc->base, desc->len, desc->type);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sev_snp_launch_finish(SevCommonState *sev_common)
|
||||||
|
{
|
||||||
|
int ret, error;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
+ OvmfSevMetadata *metadata;
|
||||||
|
SevLaunchUpdateData *data;
|
||||||
|
SevSnpGuestState *sev_snp = SEV_SNP_GUEST(sev_common);
|
||||||
|
struct kvm_sev_snp_launch_finish *finish = &sev_snp->kvm_finish_conf;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * To boot the SNP guest, the hypervisor is required to populate the CPUID
|
||||||
|
+ * and Secrets page before finalizing the launch flow. The location of
|
||||||
|
+ * the secrets and CPUID page is available through the OVMF metadata GUID.
|
||||||
|
+ */
|
||||||
|
+ metadata = pc_system_get_ovmf_sev_metadata_ptr();
|
||||||
|
+ if (metadata == NULL) {
|
||||||
|
+ error_report("%s: Failed to locate SEV metadata header", __func__);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Populate all the metadata pages */
|
||||||
|
+ snp_populate_metadata_pages(sev_snp, metadata);
|
||||||
|
+
|
||||||
|
QTAILQ_FOREACH(data, &launch_update, next) {
|
||||||
|
ret = sev_snp_launch_update(sev_snp, data);
|
||||||
|
if (ret) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,122 @@
|
|||||||
|
From 0f7432f2b968298b64fd243df793b176f67a538f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:27 -0500
|
||||||
|
Subject: [PATCH 067/100] i386/sev: Add the SNP launch start context
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [67/91] 63759a25a413a7a9a7274fb4c3b8bc2528634855 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
The SNP_LAUNCH_START is called first to create a cryptographic launch
|
||||||
|
context within the firmware.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-16-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit d3107f882ec22cfb211eab7efa0c4e95f5ce11bb)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||||
|
target/i386/trace-events | 1 +
|
||||||
|
2 files changed, 40 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 43d1c48bd9..e89b87d2f5 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -39,6 +39,7 @@
|
||||||
|
#include "confidential-guest.h"
|
||||||
|
#include "hw/i386/pc.h"
|
||||||
|
#include "exec/address-spaces.h"
|
||||||
|
+#include "qemu/queue.h"
|
||||||
|
|
||||||
|
OBJECT_DECLARE_TYPE(SevCommonState, SevCommonStateClass, SEV_COMMON)
|
||||||
|
OBJECT_DECLARE_TYPE(SevGuestState, SevCommonStateClass, SEV_GUEST)
|
||||||
|
@@ -115,6 +116,16 @@ struct SevSnpGuestState {
|
||||||
|
#define DEFAULT_SEV_DEVICE "/dev/sev"
|
||||||
|
#define DEFAULT_SEV_SNP_POLICY 0x30000
|
||||||
|
|
||||||
|
+typedef struct SevLaunchUpdateData {
|
||||||
|
+ QTAILQ_ENTRY(SevLaunchUpdateData) next;
|
||||||
|
+ hwaddr gpa;
|
||||||
|
+ void *hva;
|
||||||
|
+ uint64_t len;
|
||||||
|
+ int type;
|
||||||
|
+} SevLaunchUpdateData;
|
||||||
|
+
|
||||||
|
+static QTAILQ_HEAD(, SevLaunchUpdateData) launch_update;
|
||||||
|
+
|
||||||
|
#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
|
||||||
|
typedef struct __attribute__((__packed__)) SevInfoBlock {
|
||||||
|
/* SEV-ES Reset Vector Address */
|
||||||
|
@@ -674,6 +685,31 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sev_snp_launch_start(SevCommonState *sev_common)
|
||||||
|
+{
|
||||||
|
+ int fw_error, rc;
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(sev_common);
|
||||||
|
+ struct kvm_sev_snp_launch_start *start = &sev_snp_guest->kvm_start_conf;
|
||||||
|
+
|
||||||
|
+ trace_kvm_sev_snp_launch_start(start->policy,
|
||||||
|
+ sev_snp_guest->guest_visible_workarounds);
|
||||||
|
+
|
||||||
|
+ rc = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_LAUNCH_START,
|
||||||
|
+ start, &fw_error);
|
||||||
|
+ if (rc < 0) {
|
||||||
|
+ error_report("%s: SNP_LAUNCH_START ret=%d fw_error=%d '%s'",
|
||||||
|
+ __func__, rc, fw_error, fw_error_to_str(fw_error));
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ QTAILQ_INIT(&launch_update);
|
||||||
|
+
|
||||||
|
+ sev_set_guest_state(sev_common, SEV_STATE_LAUNCH_UPDATE);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_launch_start(SevCommonState *sev_common)
|
||||||
|
{
|
||||||
|
@@ -1003,6 +1039,7 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = klass->launch_start(sev_common);
|
||||||
|
+
|
||||||
|
if (ret) {
|
||||||
|
error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||||
|
return -1;
|
||||||
|
@@ -1794,9 +1831,11 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
+ klass->launch_start = sev_snp_launch_start;
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
+
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||||||
|
index 2cd8726eeb..cb26d8a925 100644
|
||||||
|
--- a/target/i386/trace-events
|
||||||
|
+++ b/target/i386/trace-events
|
||||||
|
@@ -11,3 +11,4 @@ kvm_sev_launch_measurement(const char *value) "data %s"
|
||||||
|
kvm_sev_launch_finish(void) ""
|
||||||
|
kvm_sev_launch_secret(uint64_t hpa, uint64_t hva, uint64_t secret, int len) "hpa 0x%" PRIx64 " hva 0x%" PRIx64 " data 0x%" PRIx64 " len %d"
|
||||||
|
kvm_sev_attestation_report(const char *mnonce, const char *data) "mnonce %s data %s"
|
||||||
|
+kvm_sev_snp_launch_start(uint64_t policy, char *gosvw) "policy 0x%" PRIx64 " gosvw %s"
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,237 @@
|
|||||||
|
From ec786a1ec0a76775e980862d77500f5196a937e3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:35 -0500
|
||||||
|
Subject: [PATCH 080/100] i386/sev: Allow measured direct kernel boot on SNP
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [80/91] 11c629862519c1a279566febf5a537c63c5fcf61 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
In SNP, the hashes page designated with a specific metadata entry
|
||||||
|
published in AmdSev OVMF.
|
||||||
|
|
||||||
|
Therefore, if the user enabled kernel hashes (for measured direct boot),
|
||||||
|
QEMU should prepare the content of hashes table, and during the
|
||||||
|
processing of the metadata entry it copy the content into the designated
|
||||||
|
page and encrypt it.
|
||||||
|
|
||||||
|
Note that in SNP (unlike SEV and SEV-ES) the measurements is done in
|
||||||
|
whole 4KB pages. Therefore QEMU zeros the whole page that includes the
|
||||||
|
hashes table, and fills in the kernel hashes area in that page, and then
|
||||||
|
encrypts the whole page. The rest of the page is reserved for SEV
|
||||||
|
launch secrets which are not usable anyway on SNP.
|
||||||
|
|
||||||
|
If the user disabled kernel hashes, QEMU pre-validates the kernel hashes
|
||||||
|
page as a zero page.
|
||||||
|
|
||||||
|
Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-24-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit c1996992cc882b00139f78067d6a64e2ec9cb0d8)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
include/hw/i386/pc.h | 2 +
|
||||||
|
target/i386/sev.c | 111 ++++++++++++++++++++++++++++++++-----------
|
||||||
|
2 files changed, 85 insertions(+), 28 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||||
|
index 94b49310f5..ee3bfb7be9 100644
|
||||||
|
--- a/include/hw/i386/pc.h
|
||||||
|
+++ b/include/hw/i386/pc.h
|
||||||
|
@@ -175,6 +175,8 @@ typedef enum {
|
||||||
|
SEV_DESC_TYPE_SNP_SECRETS,
|
||||||
|
/* The section contains address that can be used as a CPUID page */
|
||||||
|
SEV_DESC_TYPE_CPUID,
|
||||||
|
+ /* The section contains the region for kernel hashes for measured direct boot */
|
||||||
|
+ SEV_DESC_TYPE_SNP_KERNEL_HASHES = 0x10,
|
||||||
|
|
||||||
|
} ovmf_sev_metadata_desc_type;
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 3fce4c08eb..004c667ac1 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -115,6 +115,10 @@ struct SevCommonStateClass {
|
||||||
|
X86ConfidentialGuestClass parent_class;
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
+ bool (*build_kernel_loader_hashes)(SevCommonState *sev_common,
|
||||||
|
+ SevHashTableDescriptor *area,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp);
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
int (*launch_update_data)(SevCommonState *sev_common, hwaddr gpa, uint8_t *ptr, uint64_t len);
|
||||||
|
@@ -154,6 +158,9 @@ struct SevSnpGuestState {
|
||||||
|
|
||||||
|
struct kvm_sev_snp_launch_start kvm_start_conf;
|
||||||
|
struct kvm_sev_snp_launch_finish kvm_finish_conf;
|
||||||
|
+
|
||||||
|
+ uint32_t kernel_hashes_offset;
|
||||||
|
+ PaddedSevHashTable *kernel_hashes_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
|
||||||
|
@@ -1189,6 +1196,23 @@ snp_launch_update_cpuid(uint32_t cpuid_addr, void *hva, uint32_t cpuid_len)
|
||||||
|
KVM_SEV_SNP_PAGE_TYPE_CPUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+snp_launch_update_kernel_hashes(SevSnpGuestState *sev_snp, uint32_t addr,
|
||||||
|
+ void *hva, uint32_t len)
|
||||||
|
+{
|
||||||
|
+ int type = KVM_SEV_SNP_PAGE_TYPE_ZERO;
|
||||||
|
+ if (sev_snp->parent_obj.kernel_hashes) {
|
||||||
|
+ assert(sev_snp->kernel_hashes_data);
|
||||||
|
+ assert((sev_snp->kernel_hashes_offset +
|
||||||
|
+ sizeof(*sev_snp->kernel_hashes_data)) <= len);
|
||||||
|
+ memset(hva, 0, len);
|
||||||
|
+ memcpy(hva + sev_snp->kernel_hashes_offset, sev_snp->kernel_hashes_data,
|
||||||
|
+ sizeof(*sev_snp->kernel_hashes_data));
|
||||||
|
+ type = KVM_SEV_SNP_PAGE_TYPE_NORMAL;
|
||||||
|
+ }
|
||||||
|
+ return snp_launch_update_data(addr, hva, len, type);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
snp_metadata_desc_to_page_type(int desc_type)
|
||||||
|
{
|
||||||
|
@@ -1225,6 +1249,9 @@ snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
|
||||||
|
|
||||||
|
if (type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
ret = snp_launch_update_cpuid(desc->base, hva, desc->len);
|
||||||
|
+ } else if (desc->type == SEV_DESC_TYPE_SNP_KERNEL_HASHES) {
|
||||||
|
+ ret = snp_launch_update_kernel_hashes(sev_snp, desc->base, hva,
|
||||||
|
+ desc->len);
|
||||||
|
} else {
|
||||||
|
ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
}
|
||||||
|
@@ -1823,6 +1850,58 @@ static bool build_kernel_loader_hashes(PaddedSevHashTable *padded_ht,
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool sev_snp_build_kernel_loader_hashes(SevCommonState *sev_common,
|
||||||
|
+ SevHashTableDescriptor *area,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * SNP: Populate the hashes table in an area that later in
|
||||||
|
+ * snp_launch_update_kernel_hashes() will be copied to the guest memory
|
||||||
|
+ * and encrypted.
|
||||||
|
+ */
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(sev_common);
|
||||||
|
+ sev_snp_guest->kernel_hashes_offset = area->base & ~TARGET_PAGE_MASK;
|
||||||
|
+ sev_snp_guest->kernel_hashes_data = g_new0(PaddedSevHashTable, 1);
|
||||||
|
+ return build_kernel_loader_hashes(sev_snp_guest->kernel_hashes_data, ctx, errp);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool sev_build_kernel_loader_hashes(SevCommonState *sev_common,
|
||||||
|
+ SevHashTableDescriptor *area,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ PaddedSevHashTable *padded_ht;
|
||||||
|
+ hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
+ MemTxAttrs attrs = { 0 };
|
||||||
|
+ bool ret = true;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
+ * area for the SEV hashes table
|
||||||
|
+ */
|
||||||
|
+ padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
+ &mapped_len, true, attrs);
|
||||||
|
+ if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
+ error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (build_kernel_loader_hashes(padded_ht, ctx, errp)) {
|
||||||
|
+ if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
+ sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ ret = false;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ ret = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ address_space_unmap(&address_space_memory, padded_ht,
|
||||||
|
+ mapped_len, true, mapped_len);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
|
||||||
|
* which is included in SEV's initial memory measurement.
|
||||||
|
@@ -1831,11 +1910,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
{
|
||||||
|
uint8_t *data;
|
||||||
|
SevHashTableDescriptor *area;
|
||||||
|
- PaddedSevHashTable *padded_ht;
|
||||||
|
- hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
- MemTxAttrs attrs = { 0 };
|
||||||
|
- bool ret = true;
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only add the kernel hashes if the sev-guest configuration explicitly
|
||||||
|
@@ -1858,30 +1934,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
- * area for the SEV hashes table
|
||||||
|
- */
|
||||||
|
- padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
- &mapped_len, true, attrs);
|
||||||
|
- if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
- error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (build_kernel_loader_hashes(padded_ht, ctx, errp)) {
|
||||||
|
- if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
- sizeof(*padded_ht), errp) < 0) {
|
||||||
|
- ret = false;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- ret = false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- address_space_unmap(&address_space_memory, padded_ht,
|
||||||
|
- mapped_len, true, mapped_len);
|
||||||
|
-
|
||||||
|
- return ret;
|
||||||
|
+ return klass->build_kernel_loader_hashes(sev_common, area, ctx, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
@@ -1998,6 +2051,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
+ klass->build_kernel_loader_hashes = sev_build_kernel_loader_hashes;
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
klass->launch_update_data = sev_launch_update_data;
|
||||||
|
@@ -2242,6 +2296,7 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
+ klass->build_kernel_loader_hashes = sev_snp_build_kernel_loader_hashes;
|
||||||
|
klass->launch_start = sev_snp_launch_start;
|
||||||
|
klass->launch_finish = sev_snp_launch_finish;
|
||||||
|
klass->launch_update_data = sev_snp_launch_update_data;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,268 @@
|
|||||||
|
From ab6197309551bd6ddd9f8239191f68dfac23684b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Tue, 9 Jul 2024 23:10:05 -0500
|
||||||
|
Subject: [PATCH 090/100] i386/sev: Don't allow automatic fallback to legacy
|
||||||
|
KVM_SEV*_INIT
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [90/91] 2b1345faa56f993bb6e13d63e11656c784e20412 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Currently if the 'legacy-vm-type' property of the sev-guest object is
|
||||||
|
'on', QEMU will attempt to use the newer KVM_SEV_INIT2 kernel
|
||||||
|
interface in conjunction with the newer KVM_X86_SEV_VM and
|
||||||
|
KVM_X86_SEV_ES_VM KVM VM types.
|
||||||
|
|
||||||
|
This can lead to measurement changes if, for instance, an SEV guest was
|
||||||
|
created on a host that originally had an older kernel that didn't
|
||||||
|
support KVM_SEV_INIT2, but is booted on the same host later on after the
|
||||||
|
host kernel was upgraded.
|
||||||
|
|
||||||
|
Instead, if legacy-vm-type is 'off', QEMU should fail if the
|
||||||
|
KVM_SEV_INIT2 interface is not provided by the current host kernel.
|
||||||
|
Modify the fallback handling accordingly.
|
||||||
|
|
||||||
|
In the future, VMSA features and other flags might be added to QEMU
|
||||||
|
which will require legacy-vm-type to be 'off' because they will rely
|
||||||
|
on the newer KVM_SEV_INIT2 interface. It may be difficult to convey to
|
||||||
|
users what values of legacy-vm-type are compatible with which
|
||||||
|
features/options, so as part of this rework, switch legacy-vm-type to a
|
||||||
|
tri-state OnOffAuto option. 'auto' in this case will automatically
|
||||||
|
switch to using the newer KVM_SEV_INIT2, but only if it is required to
|
||||||
|
make use of new VMSA features or other options only available via
|
||||||
|
KVM_SEV_INIT2.
|
||||||
|
|
||||||
|
Defining 'auto' in this way would avoid inadvertantly breaking
|
||||||
|
compatibility with older kernels since it would only be used in cases
|
||||||
|
where users opt into newer features that are only available via
|
||||||
|
KVM_SEV_INIT2 and newer kernels, and provide better default behavior
|
||||||
|
than the legacy-vm-type=off behavior that was previously in place, so
|
||||||
|
make it the default for 9.1+ machine types.
|
||||||
|
|
||||||
|
Cc: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Cc: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
cc: kvm@vger.kernel.org
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Link: https://lore.kernel.org/r/20240710041005.83720-1-michael.roth@amd.com
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 9d38d9dca2a81aaf5752d45d221021ef96d496cd)
|
||||||
|
|
||||||
|
RHEL: adjust compatiility setting, applying it to 9.4 machine type
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 2 +-
|
||||||
|
qapi/qom.json | 18 ++++++----
|
||||||
|
target/i386/sev.c | 85 +++++++++++++++++++++++++++++++++++++++--------
|
||||||
|
3 files changed, 83 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index b25d075b59..e9c5ea5d8f 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -352,7 +352,7 @@ const size_t pc_rhel_compat_len = G_N_ELEMENTS(pc_rhel_compat);
|
||||||
|
GlobalProperty pc_rhel_9_5_compat[] = {
|
||||||
|
/* pc_rhel_9_5_compat from pc_compat_pc_9_0 (backported from 9.1) */
|
||||||
|
{ TYPE_X86_CPU, "guest-phys-bits", "0" },
|
||||||
|
- { "sev-guest", "legacy-vm-type", "true" },
|
||||||
|
+ { "sev-guest", "legacy-vm-type", "on" },
|
||||||
|
};
|
||||||
|
const size_t pc_rhel_9_5_compat_len = G_N_ELEMENTS(pc_rhel_9_5_compat);
|
||||||
|
|
||||||
|
diff --git a/qapi/qom.json b/qapi/qom.json
|
||||||
|
index 8bd299265e..17bd5a0cf7 100644
|
||||||
|
--- a/qapi/qom.json
|
||||||
|
+++ b/qapi/qom.json
|
||||||
|
@@ -912,12 +912,16 @@
|
||||||
|
# @handle: SEV firmware handle (default: 0)
|
||||||
|
#
|
||||||
|
# @legacy-vm-type: Use legacy KVM_SEV_INIT KVM interface for creating the VM.
|
||||||
|
-# The newer KVM_SEV_INIT2 interface syncs additional vCPU
|
||||||
|
-# state when initializing the VMSA structures, which will
|
||||||
|
-# result in a different guest measurement. Set this to
|
||||||
|
-# maintain compatibility with older QEMU or kernel versions
|
||||||
|
-# that rely on legacy KVM_SEV_INIT behavior.
|
||||||
|
-# (default: false) (since 9.1)
|
||||||
|
+# The newer KVM_SEV_INIT2 interface, from Linux >= 6.10, syncs
|
||||||
|
+# additional vCPU state when initializing the VMSA structures,
|
||||||
|
+# which will result in a different guest measurement. Set
|
||||||
|
+# this to 'on' to force compatibility with older QEMU or kernel
|
||||||
|
+# versions that rely on legacy KVM_SEV_INIT behavior. 'auto'
|
||||||
|
+# will behave identically to 'on', but will automatically
|
||||||
|
+# switch to using KVM_SEV_INIT2 if the user specifies any
|
||||||
|
+# additional options that require it. If set to 'off', QEMU
|
||||||
|
+# will require KVM_SEV_INIT2 unconditionally.
|
||||||
|
+# (default: off) (since 9.1)
|
||||||
|
#
|
||||||
|
# Since: 2.12
|
||||||
|
##
|
||||||
|
@@ -927,7 +931,7 @@
|
||||||
|
'*session-file': 'str',
|
||||||
|
'*policy': 'uint32',
|
||||||
|
'*handle': 'uint32',
|
||||||
|
- '*legacy-vm-type': 'bool' } }
|
||||||
|
+ '*legacy-vm-type': 'OnOffAuto' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @SevSnpGuestProperties:
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 491fab74fd..b921defb63 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -144,7 +144,7 @@ struct SevGuestState {
|
||||||
|
uint32_t policy;
|
||||||
|
char *dh_cert_file;
|
||||||
|
char *session_file;
|
||||||
|
- bool legacy_vm_type;
|
||||||
|
+ OnOffAuto legacy_vm_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SevSnpGuestState {
|
||||||
|
@@ -1334,6 +1334,17 @@ sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * This helper is to examine sev-guest properties and determine if any options
|
||||||
|
+ * have been set which rely on the newer KVM_SEV_INIT2 interface and associated
|
||||||
|
+ * KVM VM types.
|
||||||
|
+ */
|
||||||
|
+static bool sev_init2_required(SevGuestState *sev_guest)
|
||||||
|
+{
|
||||||
|
+ /* Currently no KVM_SEV_INIT2-specific options are exposed via QEMU */
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int sev_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(cg);
|
||||||
|
@@ -1344,14 +1355,39 @@ static int sev_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* These are the only cases where legacy VM types can be used. */
|
||||||
|
+ if (sev_guest->legacy_vm_type == ON_OFF_AUTO_ON ||
|
||||||
|
+ (sev_guest->legacy_vm_type == ON_OFF_AUTO_AUTO &&
|
||||||
|
+ !sev_init2_required(sev_guest))) {
|
||||||
|
+ sev_common->kvm_type = KVM_X86_DEFAULT_VM;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Newer VM types are required, either explicitly via legacy-vm-type=on, or
|
||||||
|
+ * implicitly via legacy-vm-type=auto along with additional sev-guest
|
||||||
|
+ * properties that require the newer VM types.
|
||||||
|
+ */
|
||||||
|
kvm_type = (sev_guest->policy & SEV_POLICY_ES) ?
|
||||||
|
KVM_X86_SEV_ES_VM : KVM_X86_SEV_VM;
|
||||||
|
- if (kvm_is_vm_type_supported(kvm_type) && !sev_guest->legacy_vm_type) {
|
||||||
|
- sev_common->kvm_type = kvm_type;
|
||||||
|
- } else {
|
||||||
|
- sev_common->kvm_type = KVM_X86_DEFAULT_VM;
|
||||||
|
+ if (!kvm_is_vm_type_supported(kvm_type)) {
|
||||||
|
+ if (sev_guest->legacy_vm_type == ON_OFF_AUTO_AUTO) {
|
||||||
|
+ error_report("SEV: host kernel does not support requested %s VM type, which is required "
|
||||||
|
+ "for the set of options specified. To allow use of the legacy "
|
||||||
|
+ "KVM_X86_DEFAULT_VM VM type, please disable any options that are not "
|
||||||
|
+ "compatible with the legacy VM type, or upgrade your kernel.",
|
||||||
|
+ kvm_type == KVM_X86_SEV_VM ? "KVM_X86_SEV_VM" : "KVM_X86_SEV_ES_VM");
|
||||||
|
+ } else {
|
||||||
|
+ error_report("SEV: host kernel does not support requested %s VM type. To allow use of "
|
||||||
|
+ "the legacy KVM_X86_DEFAULT_VM VM type, the 'legacy-vm-type' argument "
|
||||||
|
+ "must be set to 'on' or 'auto' for the sev-guest object.",
|
||||||
|
+ kvm_type == KVM_X86_SEV_VM ? "KVM_X86_SEV_VM" : "KVM_X86_SEV_ES_VM");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ sev_common->kvm_type = kvm_type;
|
||||||
|
out:
|
||||||
|
return sev_common->kvm_type;
|
||||||
|
}
|
||||||
|
@@ -1442,14 +1478,24 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_kvm_sev_init();
|
||||||
|
- if (x86_klass->kvm_type(X86_CONFIDENTIAL_GUEST(sev_common)) == KVM_X86_DEFAULT_VM) {
|
||||||
|
+ switch (x86_klass->kvm_type(X86_CONFIDENTIAL_GUEST(sev_common))) {
|
||||||
|
+ case KVM_X86_DEFAULT_VM:
|
||||||
|
cmd = sev_es_enabled() ? KVM_SEV_ES_INIT : KVM_SEV_INIT;
|
||||||
|
|
||||||
|
ret = sev_ioctl(sev_common->sev_fd, cmd, NULL, &fw_error);
|
||||||
|
- } else {
|
||||||
|
+ break;
|
||||||
|
+ case KVM_X86_SEV_VM:
|
||||||
|
+ case KVM_X86_SEV_ES_VM:
|
||||||
|
+ case KVM_X86_SNP_VM: {
|
||||||
|
struct kvm_sev_init args = { 0 };
|
||||||
|
|
||||||
|
ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_INIT2, &args, &fw_error);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ default:
|
||||||
|
+ error_setg(errp, "%s: host kernel does not support the requested SEV configuration.",
|
||||||
|
+ __func__);
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
@@ -2037,14 +2083,23 @@ sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
|
||||||
|
SEV_GUEST(obj)->session_file = g_strdup(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool sev_guest_get_legacy_vm_type(Object *obj, Error **errp)
|
||||||
|
+static void sev_guest_get_legacy_vm_type(Object *obj, Visitor *v,
|
||||||
|
+ const char *name, void *opaque,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- return SEV_GUEST(obj)->legacy_vm_type;
|
||||||
|
+ SevGuestState *sev_guest = SEV_GUEST(obj);
|
||||||
|
+ OnOffAuto legacy_vm_type = sev_guest->legacy_vm_type;
|
||||||
|
+
|
||||||
|
+ visit_type_OnOffAuto(v, name, &legacy_vm_type, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void sev_guest_set_legacy_vm_type(Object *obj, bool value, Error **errp)
|
||||||
|
+static void sev_guest_set_legacy_vm_type(Object *obj, Visitor *v,
|
||||||
|
+ const char *name, void *opaque,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- SEV_GUEST(obj)->legacy_vm_type = value;
|
||||||
|
+ SevGuestState *sev_guest = SEV_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ visit_type_OnOffAuto(v, name, &sev_guest->legacy_vm_type, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -2070,9 +2125,9 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
sev_guest_set_session_file);
|
||||||
|
object_class_property_set_description(oc, "session-file",
|
||||||
|
"guest owners session parameters (encoded with base64)");
|
||||||
|
- object_class_property_add_bool(oc, "legacy-vm-type",
|
||||||
|
- sev_guest_get_legacy_vm_type,
|
||||||
|
- sev_guest_set_legacy_vm_type);
|
||||||
|
+ object_class_property_add(oc, "legacy-vm-type", "OnOffAuto",
|
||||||
|
+ sev_guest_get_legacy_vm_type,
|
||||||
|
+ sev_guest_set_legacy_vm_type, NULL, NULL);
|
||||||
|
object_class_property_set_description(oc, "legacy-vm-type",
|
||||||
|
"use legacy VM type to maintain measurement compatibility with older QEMU or kernel versions.");
|
||||||
|
}
|
||||||
|
@@ -2088,6 +2143,8 @@ sev_guest_instance_init(Object *obj)
|
||||||
|
object_property_add_uint32_ptr(obj, "policy", &sev_guest->policy,
|
||||||
|
OBJ_PROP_FLAG_READWRITE);
|
||||||
|
object_apply_compat_props(obj);
|
||||||
|
+
|
||||||
|
+ sev_guest->legacy_vm_type = ON_OFF_AUTO_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* guest info specific sev/sev-es */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,46 @@
|
|||||||
|
From ebb3c3536366c383fa09b0987a4efb68d018b7b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:24 -0500
|
||||||
|
Subject: [PATCH 064/100] i386/sev: Don't return launch measurements for
|
||||||
|
SEV-SNP guests
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [64/91] 5a29bb2d8b5a07aec6fd271ec37345e665e9cce4 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
For SEV-SNP guests, launch measurement is queried from within the guest
|
||||||
|
during attestation, so don't attempt to return it as part of
|
||||||
|
query-sev-launch-measure.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-13-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 73ae63b162fc1fed520f53ad200712964d7d0264)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 6525b3c1a0..c3daaf1ad5 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -795,7 +795,9 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
|
||||||
|
|
||||||
|
static char *sev_get_launch_measurement(void)
|
||||||
|
{
|
||||||
|
- SevGuestState *sev_guest = SEV_GUEST(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+ ConfidentialGuestSupport *cgs = MACHINE(qdev_get_machine())->cgs;
|
||||||
|
+ SevGuestState *sev_guest =
|
||||||
|
+ (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
|
||||||
|
|
||||||
|
if (sev_guest &&
|
||||||
|
SEV_COMMON(sev_guest)->state >= SEV_STATE_LAUNCH_SECRET) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From 0612c7ed587422ec7e07c27c8ca11b89c7aa8b02 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:43 -0500
|
||||||
|
Subject: [PATCH 077/100] i386/sev: Enable KVM_HC_MAP_GPA_RANGE hcall for SNP
|
||||||
|
guests
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [77/91] 3c494eb54499c24121cc2c47045626478b8bb41e (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
KVM will forward GHCB page-state change requests to userspace in the
|
||||||
|
form of KVM_HC_MAP_GPA_RANGE, so make sure the hypercall handling is
|
||||||
|
enabled for SNP guests.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-32-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit e3cddff93c1f88fea3b26841e792dc0be6b6fae8)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index eaf5fc6c6b..abb63062ac 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -14,6 +14,7 @@
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
#include <linux/kvm.h>
|
||||||
|
+#include <linux/kvm_para.h>
|
||||||
|
#include <linux/psp-sev.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
@@ -758,6 +759,10 @@ sev_snp_launch_start(SevCommonState *sev_common)
|
||||||
|
trace_kvm_sev_snp_launch_start(start->policy,
|
||||||
|
sev_snp_guest->guest_visible_workarounds);
|
||||||
|
|
||||||
|
+ if (!kvm_enable_hypercall(BIT_ULL(KVM_HC_MAP_GPA_RANGE))) {
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
rc = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_LAUNCH_START,
|
||||||
|
start, &fw_error);
|
||||||
|
if (rc < 0) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,167 @@
|
|||||||
|
From eed17520567c202f53ab767bfd42cfe303838772 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:33 -0500
|
||||||
|
Subject: [PATCH 078/100] i386/sev: Extract build_kernel_loader_hashes
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [78/91] 291ea10e774178826d1afd38fc8292d67c5fd42d (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Extract the building of the kernel hashes table out from
|
||||||
|
sev_add_kernel_loader_hashes() to allow building it in
|
||||||
|
other memory areas (for SNP support).
|
||||||
|
|
||||||
|
No functional change intended.
|
||||||
|
|
||||||
|
Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-22-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 06cbd66cecaa3230cccb330facac241a677b29d5)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 102 ++++++++++++++++++++++++++--------------------
|
||||||
|
1 file changed, 58 insertions(+), 44 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index abb63062ac..73f9406715 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1754,45 +1754,16 @@ static const QemuUUID sev_cmdline_entry_guid = {
|
||||||
|
0x4d, 0x36, 0xab, 0x2a)
|
||||||
|
};
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
|
||||||
|
- * which is included in SEV's initial memory measurement.
|
||||||
|
- */
|
||||||
|
-bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
+static bool build_kernel_loader_hashes(PaddedSevHashTable *padded_ht,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- uint8_t *data;
|
||||||
|
- SevHashTableDescriptor *area;
|
||||||
|
SevHashTable *ht;
|
||||||
|
- PaddedSevHashTable *padded_ht;
|
||||||
|
uint8_t cmdline_hash[HASH_SIZE];
|
||||||
|
uint8_t initrd_hash[HASH_SIZE];
|
||||||
|
uint8_t kernel_hash[HASH_SIZE];
|
||||||
|
uint8_t *hashp;
|
||||||
|
size_t hash_len = HASH_SIZE;
|
||||||
|
- hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
- MemTxAttrs attrs = { 0 };
|
||||||
|
- bool ret = true;
|
||||||
|
- SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * Only add the kernel hashes if the sev-guest configuration explicitly
|
||||||
|
- * stated kernel-hashes=on.
|
||||||
|
- */
|
||||||
|
- if (!sev_common->kernel_hashes) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
|
||||||
|
- error_setg(errp, "SEV: kernel specified but guest firmware "
|
||||||
|
- "has no hashes table GUID");
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
- area = (SevHashTableDescriptor *)data;
|
||||||
|
- if (!area->base || area->size < sizeof(PaddedSevHashTable)) {
|
||||||
|
- error_setg(errp, "SEV: guest firmware hashes table area is invalid "
|
||||||
|
- "(base=0x%x size=0x%x)", area->base, area->size);
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate hash of kernel command-line with the terminating null byte. If
|
||||||
|
@@ -1829,16 +1800,6 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
}
|
||||||
|
assert(hash_len == HASH_SIZE);
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
- * area for the SEV hashes table
|
||||||
|
- */
|
||||||
|
- padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
- &mapped_len, true, attrs);
|
||||||
|
- if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
- error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
ht = &padded_ht->ht;
|
||||||
|
|
||||||
|
ht->guid = sev_hash_table_header_guid;
|
||||||
|
@@ -1859,8 +1820,61 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
/* zero the excess data so the measurement can be reliably calculated */
|
||||||
|
memset(padded_ht->padding, 0, sizeof(padded_ht->padding));
|
||||||
|
|
||||||
|
- if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
- sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
|
||||||
|
+ * which is included in SEV's initial memory measurement.
|
||||||
|
+ */
|
||||||
|
+bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
+{
|
||||||
|
+ uint8_t *data;
|
||||||
|
+ SevHashTableDescriptor *area;
|
||||||
|
+ PaddedSevHashTable *padded_ht;
|
||||||
|
+ hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
+ MemTxAttrs attrs = { 0 };
|
||||||
|
+ bool ret = true;
|
||||||
|
+ SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Only add the kernel hashes if the sev-guest configuration explicitly
|
||||||
|
+ * stated kernel-hashes=on.
|
||||||
|
+ */
|
||||||
|
+ if (!sev_common->kernel_hashes) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
|
||||||
|
+ error_setg(errp, "SEV: kernel specified but guest firmware "
|
||||||
|
+ "has no hashes table GUID");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ area = (SevHashTableDescriptor *)data;
|
||||||
|
+ if (!area->base || area->size < sizeof(PaddedSevHashTable)) {
|
||||||
|
+ error_setg(errp, "SEV: guest firmware hashes table area is invalid "
|
||||||
|
+ "(base=0x%x size=0x%x)", area->base, area->size);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
+ * area for the SEV hashes table
|
||||||
|
+ */
|
||||||
|
+ padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
+ &mapped_len, true, attrs);
|
||||||
|
+ if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
+ error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (build_kernel_loader_hashes(padded_ht, ctx, errp)) {
|
||||||
|
+ if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
+ sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ ret = false;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,65 @@
|
|||||||
|
From a9530c89225fce9e381929c4cd8e372068827acf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Date: Mon, 24 Jun 2024 10:52:49 +0200
|
||||||
|
Subject: [PATCH 089/100] i386/sev: Fallback to the default SEV device if none
|
||||||
|
provided in sev_get_capabilities()
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [89/91] 22318c20d7102815f754cec0efaf383e05ef79c1 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When management tools (e.g. libvirt) query QEMU capabilities,
|
||||||
|
they start QEMU with a minimalistic configuration and issue
|
||||||
|
various commands on monitor. One of the command issued is/might
|
||||||
|
be "query-sev-capabilities" to learn values like cbitpos or
|
||||||
|
reduced-phys-bits. But as of v9.0.0-1145-g16dcf200dc the monitor
|
||||||
|
command returns an error instead.
|
||||||
|
|
||||||
|
This creates a chicken-egg problem because in order to query
|
||||||
|
those aforementioned values QEMU needs to be started with a
|
||||||
|
'sev-guest' object. But to start QEMU with the values must be
|
||||||
|
known.
|
||||||
|
|
||||||
|
I think it's safe to assume that the default path ("/dev/sev")
|
||||||
|
provides the same data as user provided one. So fall back to it.
|
||||||
|
|
||||||
|
Fixes: 16dcf200dc951c1cde3e5b442457db5f690b8cf0
|
||||||
|
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Link: https://lore.kernel.org/r/157f93712c23818be193ce785f648f0060b33dee.1719218926.git.mprivozn@redhat.com
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 3fb24530b2bb1346a44e17becefc9865b40a2257)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 10 +++++-----
|
||||||
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 53b7f7315b..491fab74fd 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -585,13 +585,13 @@ static SevCapability *sev_get_capabilities(Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
- if (!sev_common) {
|
||||||
|
- error_setg(errp, "SEV is not configured");
|
||||||
|
- return NULL;
|
||||||
|
+ if (sev_common) {
|
||||||
|
+ sev_device = object_property_get_str(OBJECT(sev_common), "sev-device",
|
||||||
|
+ &error_abort);
|
||||||
|
+ } else {
|
||||||
|
+ sev_device = g_strdup(DEFAULT_SEV_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sev_device = object_property_get_str(OBJECT(sev_common), "sev-device",
|
||||||
|
- &error_abort);
|
||||||
|
fd = open(sev_device, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
error_setg_errno(errp, errno, "SEV: Failed to open %s",
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
From b672cdf8c10a530b5bcf6dd4489632891eb2c731 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Date: Mon, 24 Jun 2024 10:52:48 +0200
|
||||||
|
Subject: [PATCH 088/100] i386/sev: Fix error message in sev_get_capabilities()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [88/91] ff8a8b27af02e565172ffe39d0571c234317713d (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When a custom path is provided to sev-guest object and opening
|
||||||
|
the path fails an error message is reported. But the error
|
||||||
|
message still mentions DEFAULT_SEV_DEVICE ("/dev/sev") instead of
|
||||||
|
the custom path.
|
||||||
|
|
||||||
|
Fixes: 16dcf200dc951c1cde3e5b442457db5f690b8cf0
|
||||||
|
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Link: https://lore.kernel.org/r/b4648905d399780063dc70851d3d6a3cd28719a5.1719218926.git.mprivozn@redhat.com
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit e306ae87e0ef04bc7a5dec6db693f6ea09d64d45)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 37de80adc7..53b7f7315b 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -595,7 +595,7 @@ static SevCapability *sev_get_capabilities(Error **errp)
|
||||||
|
fd = open(sev_device, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
error_setg_errno(errp, errno, "SEV: Failed to open %s",
|
||||||
|
- DEFAULT_SEV_DEVICE);
|
||||||
|
+ sev_device);
|
||||||
|
g_free(sev_device);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,530 @@
|
|||||||
|
From 900859fd3445b9a71f1a9a8befda17f0c33f3923 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:19 -0500
|
||||||
|
Subject: [PATCH 059/100] i386/sev: Introduce 'sev-snp-guest' object
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [59/91] 3e585113d209176c2b97ad5e4fe943f19dfdcaeb (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SEV-SNP support relies on a different set of properties/state than the
|
||||||
|
existing 'sev-guest' object. This patch introduces the 'sev-snp-guest'
|
||||||
|
object, which can be used to configure an SEV-SNP guest. For example,
|
||||||
|
a default-configured SEV-SNP guest with no additional information
|
||||||
|
passed in for use with attestation:
|
||||||
|
|
||||||
|
-object sev-snp-guest,id=sev0
|
||||||
|
|
||||||
|
or a fully-specified SEV-SNP guest where all spec-defined binary
|
||||||
|
blobs are passed in as base64-encoded strings:
|
||||||
|
|
||||||
|
-object sev-snp-guest,id=sev0, \
|
||||||
|
policy=0x30000, \
|
||||||
|
init-flags=0, \
|
||||||
|
id-block=YWFhYWFhYWFhYWFhYWFhCg==, \
|
||||||
|
id-auth=CxHK/OKLkXGn/KpAC7Wl1FSiisWDbGTEKz..., \
|
||||||
|
author-key-enabled=on, \
|
||||||
|
host-data=LNkCWBRC5CcdGXirbNUV1OrsR28s..., \
|
||||||
|
guest-visible-workarounds=AA==, \
|
||||||
|
|
||||||
|
See the QAPI schema updates included in this patch for more usage
|
||||||
|
details.
|
||||||
|
|
||||||
|
In some cases these blobs may be up to 4096 characters, but this is
|
||||||
|
generally well below the default limit for linux hosts where
|
||||||
|
command-line sizes are defined by the sysconf-configurable ARG_MAX
|
||||||
|
value, which defaults to 2097152 characters for Ubuntu hosts, for
|
||||||
|
example.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Co-developed-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Acked-by: Markus Armbruster <armbru@redhat.com> (for QAPI schema)
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-8-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 7b34df44260b391e33bc3acf1ced30019d9aadf1)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
docs/system/i386/amd-memory-encryption.rst | 70 +++++-
|
||||||
|
qapi/qom.json | 58 +++++
|
||||||
|
target/i386/sev.c | 253 +++++++++++++++++++++
|
||||||
|
target/i386/sev.h | 1 +
|
||||||
|
4 files changed, 380 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/system/i386/amd-memory-encryption.rst b/docs/system/i386/amd-memory-encryption.rst
|
||||||
|
index e9bc142bc1..748f5094ba 100644
|
||||||
|
--- a/docs/system/i386/amd-memory-encryption.rst
|
||||||
|
+++ b/docs/system/i386/amd-memory-encryption.rst
|
||||||
|
@@ -25,8 +25,8 @@ support for notifying a guest's operating system when certain types of VMEXITs
|
||||||
|
are about to occur. This allows the guest to selectively share information with
|
||||||
|
the hypervisor to satisfy the requested function.
|
||||||
|
|
||||||
|
-Launching
|
||||||
|
----------
|
||||||
|
+Launching (SEV and SEV-ES)
|
||||||
|
+--------------------------
|
||||||
|
|
||||||
|
Boot images (such as bios) must be encrypted before a guest can be booted. The
|
||||||
|
``MEMORY_ENCRYPT_OP`` ioctl provides commands to encrypt the images: ``LAUNCH_START``,
|
||||||
|
@@ -161,6 +161,72 @@ The value of GCTX.LD is
|
||||||
|
If kernel hashes are not used, or SEV-ES is disabled, use empty blobs for
|
||||||
|
``kernel_hashes_blob`` and ``vmsas_blob`` as needed.
|
||||||
|
|
||||||
|
+Launching (SEV-SNP)
|
||||||
|
+-------------------
|
||||||
|
+Boot images (such as bios) must be encrypted before a guest can be booted. The
|
||||||
|
+``MEMORY_ENCRYPT_OP`` ioctl provides commands to encrypt the images:
|
||||||
|
+``SNP_LAUNCH_START``, ``SNP_LAUNCH_UPDATE``, and ``SNP_LAUNCH_FINISH``. These
|
||||||
|
+three commands communicate with SEV-SNP firmware to generate a fresh memory
|
||||||
|
+encryption key for the VM, encrypt the boot images for a successful launch. For
|
||||||
|
+more details on the SEV-SNP firmware interfaces used by these commands please
|
||||||
|
+see the SEV-SNP Firmware ABI.
|
||||||
|
+
|
||||||
|
+``SNP_LAUNCH_START`` is called first to create a cryptographic launch context
|
||||||
|
+within the firmware. To create this context, the guest owner must provide a
|
||||||
|
+guest policy and other parameters as described in the SEV-SNP firmware
|
||||||
|
+specification. The launch parameters should be specified as described in the
|
||||||
|
+QAPI schema for the sev-snp-guest object.
|
||||||
|
+
|
||||||
|
+The ``SNP_LAUNCH_START`` uses the following parameters, which can be configured
|
||||||
|
+by the corresponding parameters documented in the QAPI schema for the
|
||||||
|
+'sev-snp-guest' object.
|
||||||
|
+
|
||||||
|
++--------+-------+----------+-------------------------------------------------+
|
||||||
|
+| key | type | default | meaning |
|
||||||
|
++---------------------------+-------------------------------------------------+
|
||||||
|
+| policy | hex | 0x30000 | a 64-bit guest policy |
|
||||||
|
++---------------------------+-------------------------------------------------+
|
||||||
|
+| guest-visible-workarounds | string| 0 | 16-byte base64 encoded string|
|
||||||
|
+| | | | for guest OS visible |
|
||||||
|
+| | | | workarounds. |
|
||||||
|
++---------------------------+-------------------------------------------------+
|
||||||
|
+
|
||||||
|
+``SNP_LAUNCH_UPDATE`` encrypts the memory region using the cryptographic context
|
||||||
|
+created via the ``SNP_LAUNCH_START`` command. If required, this command can be
|
||||||
|
+called multiple times to encrypt different memory regions. The command also
|
||||||
|
+calculates the measurement of the memory contents as it encrypts.
|
||||||
|
+
|
||||||
|
+``SNP_LAUNCH_FINISH`` finalizes the guest launch flow. Optionally, while
|
||||||
|
+finalizing the launch the firmware can perform checks on the launch digest
|
||||||
|
+computing through the ``SNP_LAUNCH_UPDATE``. To perform the check the user must
|
||||||
|
+supply the id block, authentication blob and host data that should be included
|
||||||
|
+in the attestation report. See the SEV-SNP spec for further details.
|
||||||
|
+
|
||||||
|
+The ``SNP_LAUNCH_FINISH`` uses the following parameters, which can be configured
|
||||||
|
+by the corresponding parameters documented in the QAPI schema for the
|
||||||
|
+'sev-snp-guest' object.
|
||||||
|
+
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| key | type | default | meaning |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| id-block | string| none | base64 encoded ID block |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| id-auth | string| none | base64 encoded authentication |
|
||||||
|
+| | | | information |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| author-key-enabled | bool | 0 | auth block contains author key |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| host_data | string| none | host provided data |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+
|
||||||
|
+To launch a SEV-SNP guest (additional parameters are documented in the QAPI
|
||||||
|
+schema for the 'sev-snp-guest' object)::
|
||||||
|
+
|
||||||
|
+ # ${QEMU} \
|
||||||
|
+ -machine ...,confidential-guest-support=sev0 \
|
||||||
|
+ -object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1
|
||||||
|
+
|
||||||
|
+
|
||||||
|
Debugging
|
||||||
|
---------
|
||||||
|
|
||||||
|
diff --git a/qapi/qom.json b/qapi/qom.json
|
||||||
|
index 056b38f491..8bd299265e 100644
|
||||||
|
--- a/qapi/qom.json
|
||||||
|
+++ b/qapi/qom.json
|
||||||
|
@@ -929,6 +929,62 @@
|
||||||
|
'*handle': 'uint32',
|
||||||
|
'*legacy-vm-type': 'bool' } }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @SevSnpGuestProperties:
|
||||||
|
+#
|
||||||
|
+# Properties for sev-snp-guest objects. Most of these are direct
|
||||||
|
+# arguments for the KVM_SNP_* interfaces documented in the Linux
|
||||||
|
+# kernel source under
|
||||||
|
+# Documentation/arch/x86/amd-memory-encryption.rst, which are in turn
|
||||||
|
+# closely coupled with the SNP_INIT/SNP_LAUNCH_* firmware commands
|
||||||
|
+# documented in the SEV-SNP Firmware ABI Specification (Rev 0.9).
|
||||||
|
+#
|
||||||
|
+# More usage information is also available in the QEMU source tree
|
||||||
|
+# under docs/amd-memory-encryption.
|
||||||
|
+#
|
||||||
|
+# @policy: the 'POLICY' parameter to the SNP_LAUNCH_START command, as
|
||||||
|
+# defined in the SEV-SNP firmware ABI (default: 0x30000)
|
||||||
|
+#
|
||||||
|
+# @guest-visible-workarounds: 16-byte, base64-encoded blob to report
|
||||||
|
+# hypervisor-defined workarounds, corresponding to the 'GOSVW'
|
||||||
|
+# parameter of the SNP_LAUNCH_START command defined in the SEV-SNP
|
||||||
|
+# firmware ABI (default: all-zero)
|
||||||
|
+#
|
||||||
|
+# @id-block: 96-byte, base64-encoded blob to provide the 'ID Block'
|
||||||
|
+# structure for the SNP_LAUNCH_FINISH command defined in the
|
||||||
|
+# SEV-SNP firmware ABI (default: all-zero)
|
||||||
|
+#
|
||||||
|
+# @id-auth: 4096-byte, base64-encoded blob to provide the 'ID
|
||||||
|
+# Authentication Information Structure' for the SNP_LAUNCH_FINISH
|
||||||
|
+# command defined in the SEV-SNP firmware ABI (default: all-zero)
|
||||||
|
+#
|
||||||
|
+# @author-key-enabled: true if 'id-auth' blob contains the 'AUTHOR_KEY'
|
||||||
|
+# field defined SEV-SNP firmware ABI (default: false)
|
||||||
|
+#
|
||||||
|
+# @host-data: 32-byte, base64-encoded, user-defined blob to provide to
|
||||||
|
+# the guest, as documented for the 'HOST_DATA' parameter of the
|
||||||
|
+# SNP_LAUNCH_FINISH command in the SEV-SNP firmware ABI (default:
|
||||||
|
+# all-zero)
|
||||||
|
+#
|
||||||
|
+# @vcek-disabled: Guests are by default allowed to choose between VLEK
|
||||||
|
+# (Versioned Loaded Endorsement Key) or VCEK (Versioned Chip
|
||||||
|
+# Endorsement Key) when requesting attestation reports from
|
||||||
|
+# firmware. Set this to true to disable the use of VCEK.
|
||||||
|
+# (default: false) (since: 9.1)
|
||||||
|
+#
|
||||||
|
+# Since: 9.1
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'SevSnpGuestProperties',
|
||||||
|
+ 'base': 'SevCommonProperties',
|
||||||
|
+ 'data': {
|
||||||
|
+ '*policy': 'uint64',
|
||||||
|
+ '*guest-visible-workarounds': 'str',
|
||||||
|
+ '*id-block': 'str',
|
||||||
|
+ '*id-auth': 'str',
|
||||||
|
+ '*author-key-enabled': 'bool',
|
||||||
|
+ '*host-data': 'str',
|
||||||
|
+ '*vcek-disabled': 'bool' } }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @ThreadContextProperties:
|
||||||
|
#
|
||||||
|
@@ -1007,6 +1063,7 @@
|
||||||
|
{ 'name': 'secret_keyring',
|
||||||
|
'if': 'CONFIG_SECRET_KEYRING' },
|
||||||
|
'sev-guest',
|
||||||
|
+ 'sev-snp-guest',
|
||||||
|
'thread-context',
|
||||||
|
's390-pv-guest',
|
||||||
|
'throttle-group',
|
||||||
|
@@ -1077,6 +1134,7 @@
|
||||||
|
'secret_keyring': { 'type': 'SecretKeyringProperties',
|
||||||
|
'if': 'CONFIG_SECRET_KEYRING' },
|
||||||
|
'sev-guest': 'SevGuestProperties',
|
||||||
|
+ 'sev-snp-guest': 'SevSnpGuestProperties',
|
||||||
|
'thread-context': 'ThreadContextProperties',
|
||||||
|
'throttle-group': 'ThrottleGroupProperties',
|
||||||
|
'tls-creds-anon': 'TlsCredsAnonProperties',
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 28a018ed83..a81b3228d4 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -42,6 +42,7 @@
|
||||||
|
|
||||||
|
OBJECT_DECLARE_TYPE(SevCommonState, SevCommonStateClass, SEV_COMMON)
|
||||||
|
OBJECT_DECLARE_TYPE(SevGuestState, SevCommonStateClass, SEV_GUEST)
|
||||||
|
+OBJECT_DECLARE_TYPE(SevSnpGuestState, SevCommonStateClass, SEV_SNP_GUEST)
|
||||||
|
|
||||||
|
struct SevCommonState {
|
||||||
|
X86ConfidentialGuest parent_obj;
|
||||||
|
@@ -96,8 +97,22 @@ struct SevGuestState {
|
||||||
|
bool legacy_vm_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct SevSnpGuestState {
|
||||||
|
+ SevCommonState parent_obj;
|
||||||
|
+
|
||||||
|
+ /* configuration parameters */
|
||||||
|
+ char *guest_visible_workarounds;
|
||||||
|
+ char *id_block;
|
||||||
|
+ char *id_auth;
|
||||||
|
+ char *host_data;
|
||||||
|
+
|
||||||
|
+ struct kvm_sev_snp_launch_start kvm_start_conf;
|
||||||
|
+ struct kvm_sev_snp_launch_finish kvm_finish_conf;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
|
||||||
|
#define DEFAULT_SEV_DEVICE "/dev/sev"
|
||||||
|
+#define DEFAULT_SEV_SNP_POLICY 0x30000
|
||||||
|
|
||||||
|
#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
|
||||||
|
typedef struct __attribute__((__packed__)) SevInfoBlock {
|
||||||
|
@@ -1500,11 +1515,249 @@ static const TypeInfo sev_guest_info = {
|
||||||
|
.class_init = sev_guest_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_get_policy(Object *obj, Visitor *v, const char *name,
|
||||||
|
+ void *opaque, Error **errp)
|
||||||
|
+{
|
||||||
|
+ visit_type_uint64(v, name,
|
||||||
|
+ (uint64_t *)&SEV_SNP_GUEST(obj)->kvm_start_conf.policy,
|
||||||
|
+ errp);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_policy(Object *obj, Visitor *v, const char *name,
|
||||||
|
+ void *opaque, Error **errp)
|
||||||
|
+{
|
||||||
|
+ visit_type_uint64(v, name,
|
||||||
|
+ (uint64_t *)&SEV_SNP_GUEST(obj)->kvm_start_conf.policy,
|
||||||
|
+ errp);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_guest_visible_workarounds(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ return g_strdup(SEV_SNP_GUEST(obj)->guest_visible_workarounds);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_guest_visible_workarounds(Object *obj, const char *value,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_start *start = &sev_snp_guest->kvm_start_conf;
|
||||||
|
+ g_autofree guchar *blob;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->guest_visible_workarounds);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->guest_visible_workarounds = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ blob = qbase64_decode(sev_snp_guest->guest_visible_workarounds,
|
||||||
|
+ -1, &len, errp);
|
||||||
|
+ if (!blob) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len != sizeof(start->gosvw)) {
|
||||||
|
+ error_setg(errp, "parameter length of %lu exceeds max of %lu",
|
||||||
|
+ len, sizeof(start->gosvw));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(start->gosvw, blob, len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_id_block(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return g_strdup(sev_snp_guest->id_block);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_id_block(Object *obj, const char *value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->id_block);
|
||||||
|
+ g_free((guchar *)finish->id_block_uaddr);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->id_block = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ finish->id_block_uaddr =
|
||||||
|
+ (uint64_t)qbase64_decode(sev_snp_guest->id_block, -1, &len, errp);
|
||||||
|
+
|
||||||
|
+ if (!finish->id_block_uaddr) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len != KVM_SEV_SNP_ID_BLOCK_SIZE) {
|
||||||
|
+ error_setg(errp, "parameter length of %lu not equal to %u",
|
||||||
|
+ len, KVM_SEV_SNP_ID_BLOCK_SIZE);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ finish->id_block_en = (len) ? 1 : 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_id_auth(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return g_strdup(sev_snp_guest->id_auth);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_id_auth(Object *obj, const char *value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->id_auth);
|
||||||
|
+ g_free((guchar *)finish->id_auth_uaddr);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->id_auth = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ finish->id_auth_uaddr =
|
||||||
|
+ (uint64_t)qbase64_decode(sev_snp_guest->id_auth, -1, &len, errp);
|
||||||
|
+
|
||||||
|
+ if (!finish->id_auth_uaddr) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len > KVM_SEV_SNP_ID_AUTH_SIZE) {
|
||||||
|
+ error_setg(errp, "parameter length:ID_AUTH %lu exceeds max of %u",
|
||||||
|
+ len, KVM_SEV_SNP_ID_AUTH_SIZE);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+sev_snp_guest_get_author_key_enabled(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return !!sev_snp_guest->kvm_finish_conf.auth_key_en;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_author_key_enabled(Object *obj, bool value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ sev_snp_guest->kvm_finish_conf.auth_key_en = value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+sev_snp_guest_get_vcek_disabled(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return !!sev_snp_guest->kvm_finish_conf.vcek_disabled;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_vcek_disabled(Object *obj, bool value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ sev_snp_guest->kvm_finish_conf.vcek_disabled = value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_host_data(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return g_strdup(sev_snp_guest->host_data);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_host_data(Object *obj, const char *value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
|
||||||
|
+ g_autofree guchar *blob;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->host_data);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->host_data = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ blob = qbase64_decode(sev_snp_guest->host_data, -1, &len, errp);
|
||||||
|
+
|
||||||
|
+ if (!blob) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len != sizeof(finish->host_data)) {
|
||||||
|
+ error_setg(errp, "parameter length of %lu not equal to %lu",
|
||||||
|
+ len, sizeof(finish->host_data));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(finish->host_data, blob, len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
+{
|
||||||
|
+ object_class_property_add(oc, "policy", "uint64",
|
||||||
|
+ sev_snp_guest_get_policy,
|
||||||
|
+ sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
+ object_class_property_add_str(oc, "guest-visible-workarounds",
|
||||||
|
+ sev_snp_guest_get_guest_visible_workarounds,
|
||||||
|
+ sev_snp_guest_set_guest_visible_workarounds);
|
||||||
|
+ object_class_property_add_str(oc, "id-block",
|
||||||
|
+ sev_snp_guest_get_id_block,
|
||||||
|
+ sev_snp_guest_set_id_block);
|
||||||
|
+ object_class_property_add_str(oc, "id-auth",
|
||||||
|
+ sev_snp_guest_get_id_auth,
|
||||||
|
+ sev_snp_guest_set_id_auth);
|
||||||
|
+ object_class_property_add_bool(oc, "author-key-enabled",
|
||||||
|
+ sev_snp_guest_get_author_key_enabled,
|
||||||
|
+ sev_snp_guest_set_author_key_enabled);
|
||||||
|
+ object_class_property_add_bool(oc, "vcek-required",
|
||||||
|
+ sev_snp_guest_get_vcek_disabled,
|
||||||
|
+ sev_snp_guest_set_vcek_disabled);
|
||||||
|
+ object_class_property_add_str(oc, "host-data",
|
||||||
|
+ sev_snp_guest_get_host_data,
|
||||||
|
+ sev_snp_guest_set_host_data);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_instance_init(Object *obj)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ /* default init/start/finish params for kvm */
|
||||||
|
+ sev_snp_guest->kvm_start_conf.policy = DEFAULT_SEV_SNP_POLICY;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* guest info specific to sev-snp */
|
||||||
|
+static const TypeInfo sev_snp_guest_info = {
|
||||||
|
+ .parent = TYPE_SEV_COMMON,
|
||||||
|
+ .name = TYPE_SEV_SNP_GUEST,
|
||||||
|
+ .instance_size = sizeof(SevSnpGuestState),
|
||||||
|
+ .class_init = sev_snp_guest_class_init,
|
||||||
|
+ .instance_init = sev_snp_guest_instance_init,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sev_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&sev_common_info);
|
||||||
|
type_register_static(&sev_guest_info);
|
||||||
|
+ type_register_static(&sev_snp_guest_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(sev_register_types);
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index 668374eef3..bedc667eeb 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -22,6 +22,7 @@
|
||||||
|
|
||||||
|
#define TYPE_SEV_COMMON "sev-common"
|
||||||
|
#define TYPE_SEV_GUEST "sev-guest"
|
||||||
|
+#define TYPE_SEV_SNP_GUEST "sev-snp-guest"
|
||||||
|
|
||||||
|
#define SEV_POLICY_NODBG 0x1
|
||||||
|
#define SEV_POLICY_NOKS 0x2
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
From be37914ae54c8aebc218cf41b37bc0ea1563daae Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Fri, 31 May 2024 12:51:44 +0200
|
||||||
|
Subject: [PATCH 074/100] i386/sev: Invoke launch_updata_data() for SEV class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [74/91] f1b588a9ffecd6944a78186d88a6be3849698710 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add launch_update_data() in SevCommonStateClass and
|
||||||
|
invoke as sev_launch_update_data() for SEV object.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-26-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 9861405a8f845133b7984322c2df0c43a45553c3)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 11 ++++++++---
|
||||||
|
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 7b5c4b4874..8834cf9441 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -74,6 +74,7 @@ struct SevCommonStateClass {
|
||||||
|
/* public */
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
+ int (*launch_update_data)(SevCommonState *sev_common, hwaddr gpa, uint8_t *ptr, uint64_t len);
|
||||||
|
int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -929,7 +930,7 @@ out:
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-sev_launch_update_data(SevGuestState *sev_guest, uint8_t *addr, uint64_t len)
|
||||||
|
+sev_launch_update_data(SevCommonState *sev_common, hwaddr gpa, uint8_t *addr, uint64_t len)
|
||||||
|
{
|
||||||
|
int ret, fw_error;
|
||||||
|
struct kvm_sev_launch_update_data update;
|
||||||
|
@@ -941,7 +942,7 @@ sev_launch_update_data(SevGuestState *sev_guest, uint8_t *addr, uint64_t len)
|
||||||
|
update.uaddr = (uintptr_t)addr;
|
||||||
|
update.len = len;
|
||||||
|
trace_kvm_sev_launch_update_data(addr, len);
|
||||||
|
- ret = sev_ioctl(SEV_COMMON(sev_guest)->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
|
||||||
|
+ ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
|
||||||
|
&update, &fw_error);
|
||||||
|
if (ret) {
|
||||||
|
error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
|
||||||
|
@@ -1487,6 +1488,7 @@ int
|
||||||
|
sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
|
||||||
|
if (!sev_common) {
|
||||||
|
return 0;
|
||||||
|
@@ -1494,7 +1496,9 @@ sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
|
||||||
|
/* if SEV is in update state then encrypt the data else do nothing */
|
||||||
|
if (sev_check_state(sev_common, SEV_STATE_LAUNCH_UPDATE)) {
|
||||||
|
- int ret = sev_launch_update_data(SEV_GUEST(sev_common), ptr, len);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = klass->launch_update_data(sev_common, gpa, ptr, len);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "SEV: Failed to encrypt pflash rom");
|
||||||
|
return ret;
|
||||||
|
@@ -1968,6 +1972,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
+ klass->launch_update_data = sev_launch_update_data;
|
||||||
|
klass->kvm_init = sev_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
From 32899eb4fa5143b795b107de4857adce2cf1d434 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:38 -0500
|
||||||
|
Subject: [PATCH 075/100] i386/sev: Invoke launch_updata_data() for SNP class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [75/91] 3520af5847f8dddb6d7fe7ad5feb308230f387b9 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Invoke as sev_snp_launch_update_data() for SNP object.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-27-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 0765d136eba400ad1cb7cae18438bb10eace64dc)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 10 ++++++++++
|
||||||
|
1 file changed, 10 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 8834cf9441..eaf5fc6c6b 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1091,6 +1091,15 @@ snp_launch_update_data(uint64_t gpa, void *hva,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sev_snp_launch_update_data(SevCommonState *sev_common, hwaddr gpa,
|
||||||
|
+ uint8_t *ptr, uint64_t len)
|
||||||
|
+{
|
||||||
|
+ int ret = snp_launch_update_data(gpa, ptr, len,
|
||||||
|
+ KVM_SEV_SNP_PAGE_TYPE_NORMAL);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_snp_cpuid_info_fill(SnpCpuidInfo *snp_cpuid_info,
|
||||||
|
const KvmCpuidInfo *kvm_cpuid_info)
|
||||||
|
@@ -2216,6 +2225,7 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
|
||||||
|
klass->launch_start = sev_snp_launch_start;
|
||||||
|
klass->launch_finish = sev_snp_launch_finish;
|
||||||
|
+ klass->launch_update_data = sev_snp_launch_update_data;
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
From fa6076291eb45255bc2fe523399d7d0647fc5570 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Fri, 7 Jun 2024 13:36:10 -0500
|
||||||
|
Subject: [PATCH 085/100] i386/sev: Move SEV_COMMON null check before
|
||||||
|
dereferencing
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [85/91] e8d2bfd077766a5e7777b9337d0e77146f883224 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Fixes Coverity CID 1546886.
|
||||||
|
|
||||||
|
Fixes: 9861405a8f ("i386/sev: Invoke launch_updata_data() for SEV class")
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240607183611.1111100-3-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 48779faef3c8e2fe70bd8285bffa731bd76dc844)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 7c9df621de..f18432f58e 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1529,11 +1529,12 @@ int
|
||||||
|
sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
- SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
+ SevCommonStateClass *klass;
|
||||||
|
|
||||||
|
if (!sev_common) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+ klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
|
||||||
|
/* if SEV is in update state then encrypt the data else do nothing */
|
||||||
|
if (sev_check_state(sev_common, SEV_STATE_LAUNCH_UPDATE)) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,88 @@
|
|||||||
|
From 4d96ca893126d4c17c9fe03c76973b1d4a414f21 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:18 -0500
|
||||||
|
Subject: [PATCH 058/100] i386/sev: Move sev_launch_finish to separate class
|
||||||
|
method
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [58/91] 7865710d320a6df7038ef7016d350aa9cdcea326 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When sev-snp-guest objects are introduced there will be a number of
|
||||||
|
differences in how the launch finish is handled compared to the existing
|
||||||
|
sev-guest object. Move sev_launch_finish() to a class method to make it
|
||||||
|
easier to implement SNP-specific launch update functionality later.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-7-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit bce615a14aec07cab0488e5a242f6a91e641efcb)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 11 +++++++----
|
||||||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index b2aa0d6f99..28a018ed83 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -71,6 +71,7 @@ struct SevCommonStateClass {
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
+ void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -801,12 +802,12 @@ static Notifier sev_machine_done_notify = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
-sev_launch_finish(SevGuestState *sev_guest)
|
||||||
|
+sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
{
|
||||||
|
int ret, error;
|
||||||
|
|
||||||
|
trace_kvm_sev_launch_finish();
|
||||||
|
- ret = sev_ioctl(SEV_COMMON(sev_guest)->sev_fd, KVM_SEV_LAUNCH_FINISH, 0,
|
||||||
|
+ ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_LAUNCH_FINISH, 0,
|
||||||
|
&error);
|
||||||
|
if (ret) {
|
||||||
|
error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
|
||||||
|
@@ -814,7 +815,7 @@ sev_launch_finish(SevGuestState *sev_guest)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sev_set_guest_state(SEV_COMMON(sev_guest), SEV_STATE_RUNNING);
|
||||||
|
+ sev_set_guest_state(sev_common, SEV_STATE_RUNNING);
|
||||||
|
|
||||||
|
/* add migration blocker */
|
||||||
|
error_setg(&sev_mig_blocker,
|
||||||
|
@@ -826,10 +827,11 @@ static void
|
||||||
|
sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = opaque;
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(opaque);
|
||||||
|
|
||||||
|
if (running) {
|
||||||
|
if (!sev_check_state(sev_common, SEV_STATE_RUNNING)) {
|
||||||
|
- sev_launch_finish(SEV_GUEST(sev_common));
|
||||||
|
+ klass->launch_finish(sev_common);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1457,6 +1459,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
+ klass->launch_finish = sev_launch_finish;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
sev_guest_get_dh_cert_file,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,91 @@
|
|||||||
|
From a170ba2c7dbf2775eb9047779d3643a2a81bb372 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:17 -0500
|
||||||
|
Subject: [PATCH 057/100] i386/sev: Move sev_launch_update to separate class
|
||||||
|
method
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [57/91] 4f31e7afaec6f2c2a7c06cda4d7d27d4037e53e0 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When sev-snp-guest objects are introduced there will be a number of
|
||||||
|
differences in how the launch data is handled compared to the existing
|
||||||
|
sev-guest object. Move sev_launch_start() to a class method to make it
|
||||||
|
easier to implement SNP-specific launch update functionality later.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-6-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 6600f1ac0c81cbe67faf048ea07f78542dea925f)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 13 ++++++++++---
|
||||||
|
1 file changed, 10 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 33e606eea0..b2aa0d6f99 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -69,6 +69,8 @@ struct SevCommonState {
|
||||||
|
struct SevCommonStateClass {
|
||||||
|
X86ConfidentialGuestClass parent_class;
|
||||||
|
|
||||||
|
+ /* public */
|
||||||
|
+ int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -632,16 +634,16 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-sev_launch_start(SevGuestState *sev_guest)
|
||||||
|
+sev_launch_start(SevCommonState *sev_common)
|
||||||
|
{
|
||||||
|
gsize sz;
|
||||||
|
int ret = 1;
|
||||||
|
int fw_error, rc;
|
||||||
|
+ SevGuestState *sev_guest = SEV_GUEST(sev_common);
|
||||||
|
struct kvm_sev_launch_start start = {
|
||||||
|
.handle = sev_guest->handle, .policy = sev_guest->policy
|
||||||
|
};
|
||||||
|
guchar *session = NULL, *dh_cert = NULL;
|
||||||
|
- SevCommonState *sev_common = SEV_COMMON(sev_guest);
|
||||||
|
|
||||||
|
if (sev_guest->session_file) {
|
||||||
|
if (sev_read_file_base64(sev_guest->session_file, &session, &sz) < 0) {
|
||||||
|
@@ -862,6 +864,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t host_cbitpos;
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs);
|
||||||
|
|
||||||
|
ret = ram_block_discard_disable(true);
|
||||||
|
if (ret) {
|
||||||
|
@@ -952,7 +955,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
- sev_launch_start(SEV_GUEST(sev_common));
|
||||||
|
+ ret = klass->launch_start(sev_common);
|
||||||
|
if (ret) {
|
||||||
|
error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||||
|
goto err;
|
||||||
|
@@ -1451,6 +1454,10 @@ static void sev_guest_set_legacy_vm_type(Object *obj, bool value, Error **errp)
|
||||||
|
static void
|
||||||
|
sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
+
|
||||||
|
+ klass->launch_start = sev_launch_start;
|
||||||
|
+
|
||||||
|
object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
sev_guest_get_dh_cert_file,
|
||||||
|
sev_guest_set_dh_cert_file);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,134 @@
|
|||||||
|
From d009fa2cebebd1da80f4f2f5d0c4fffb87e02afc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:34 -0500
|
||||||
|
Subject: [PATCH 079/100] i386/sev: Reorder struct declarations
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [79/91] 1274d4620e88dda99ec10173ca5e3cd4184c8fb6 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Move the declaration of PaddedSevHashTable before SevSnpGuest so
|
||||||
|
we can add a new such field to the latter.
|
||||||
|
|
||||||
|
No functional change intended.
|
||||||
|
|
||||||
|
Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-23-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit cc483bf911931f405dea682c74a3d8b9b6c54369)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 84 +++++++++++++++++++++++------------------------
|
||||||
|
1 file changed, 42 insertions(+), 42 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 73f9406715..3fce4c08eb 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -46,6 +46,48 @@ OBJECT_DECLARE_TYPE(SevCommonState, SevCommonStateClass, SEV_COMMON)
|
||||||
|
OBJECT_DECLARE_TYPE(SevGuestState, SevCommonStateClass, SEV_GUEST)
|
||||||
|
OBJECT_DECLARE_TYPE(SevSnpGuestState, SevCommonStateClass, SEV_SNP_GUEST)
|
||||||
|
|
||||||
|
+/* hard code sha256 digest size */
|
||||||
|
+#define HASH_SIZE 32
|
||||||
|
+
|
||||||
|
+typedef struct QEMU_PACKED SevHashTableEntry {
|
||||||
|
+ QemuUUID guid;
|
||||||
|
+ uint16_t len;
|
||||||
|
+ uint8_t hash[HASH_SIZE];
|
||||||
|
+} SevHashTableEntry;
|
||||||
|
+
|
||||||
|
+typedef struct QEMU_PACKED SevHashTable {
|
||||||
|
+ QemuUUID guid;
|
||||||
|
+ uint16_t len;
|
||||||
|
+ SevHashTableEntry cmdline;
|
||||||
|
+ SevHashTableEntry initrd;
|
||||||
|
+ SevHashTableEntry kernel;
|
||||||
|
+} SevHashTable;
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Data encrypted by sev_encrypt_flash() must be padded to a multiple of
|
||||||
|
+ * 16 bytes.
|
||||||
|
+ */
|
||||||
|
+typedef struct QEMU_PACKED PaddedSevHashTable {
|
||||||
|
+ SevHashTable ht;
|
||||||
|
+ uint8_t padding[ROUND_UP(sizeof(SevHashTable), 16) - sizeof(SevHashTable)];
|
||||||
|
+} PaddedSevHashTable;
|
||||||
|
+
|
||||||
|
+QEMU_BUILD_BUG_ON(sizeof(PaddedSevHashTable) % 16 != 0);
|
||||||
|
+
|
||||||
|
+#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
|
||||||
|
+typedef struct __attribute__((__packed__)) SevInfoBlock {
|
||||||
|
+ /* SEV-ES Reset Vector Address */
|
||||||
|
+ uint32_t reset_addr;
|
||||||
|
+} SevInfoBlock;
|
||||||
|
+
|
||||||
|
+#define SEV_HASH_TABLE_RV_GUID "7255371f-3a3b-4b04-927b-1da6efa8d454"
|
||||||
|
+typedef struct QEMU_PACKED SevHashTableDescriptor {
|
||||||
|
+ /* SEV hash table area guest address */
|
||||||
|
+ uint32_t base;
|
||||||
|
+ /* SEV hash table area size (in bytes) */
|
||||||
|
+ uint32_t size;
|
||||||
|
+} SevHashTableDescriptor;
|
||||||
|
+
|
||||||
|
struct SevCommonState {
|
||||||
|
X86ConfidentialGuest parent_obj;
|
||||||
|
|
||||||
|
@@ -128,48 +170,6 @@ typedef struct SevLaunchUpdateData {
|
||||||
|
|
||||||
|
static QTAILQ_HEAD(, SevLaunchUpdateData) launch_update;
|
||||||
|
|
||||||
|
-#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
|
||||||
|
-typedef struct __attribute__((__packed__)) SevInfoBlock {
|
||||||
|
- /* SEV-ES Reset Vector Address */
|
||||||
|
- uint32_t reset_addr;
|
||||||
|
-} SevInfoBlock;
|
||||||
|
-
|
||||||
|
-#define SEV_HASH_TABLE_RV_GUID "7255371f-3a3b-4b04-927b-1da6efa8d454"
|
||||||
|
-typedef struct QEMU_PACKED SevHashTableDescriptor {
|
||||||
|
- /* SEV hash table area guest address */
|
||||||
|
- uint32_t base;
|
||||||
|
- /* SEV hash table area size (in bytes) */
|
||||||
|
- uint32_t size;
|
||||||
|
-} SevHashTableDescriptor;
|
||||||
|
-
|
||||||
|
-/* hard code sha256 digest size */
|
||||||
|
-#define HASH_SIZE 32
|
||||||
|
-
|
||||||
|
-typedef struct QEMU_PACKED SevHashTableEntry {
|
||||||
|
- QemuUUID guid;
|
||||||
|
- uint16_t len;
|
||||||
|
- uint8_t hash[HASH_SIZE];
|
||||||
|
-} SevHashTableEntry;
|
||||||
|
-
|
||||||
|
-typedef struct QEMU_PACKED SevHashTable {
|
||||||
|
- QemuUUID guid;
|
||||||
|
- uint16_t len;
|
||||||
|
- SevHashTableEntry cmdline;
|
||||||
|
- SevHashTableEntry initrd;
|
||||||
|
- SevHashTableEntry kernel;
|
||||||
|
-} SevHashTable;
|
||||||
|
-
|
||||||
|
-/*
|
||||||
|
- * Data encrypted by sev_encrypt_flash() must be padded to a multiple of
|
||||||
|
- * 16 bytes.
|
||||||
|
- */
|
||||||
|
-typedef struct QEMU_PACKED PaddedSevHashTable {
|
||||||
|
- SevHashTable ht;
|
||||||
|
- uint8_t padding[ROUND_UP(sizeof(SevHashTable), 16) - sizeof(SevHashTable)];
|
||||||
|
-} PaddedSevHashTable;
|
||||||
|
-
|
||||||
|
-QEMU_BUILD_BUG_ON(sizeof(PaddedSevHashTable) % 16 != 0);
|
||||||
|
-
|
||||||
|
static Error *sev_mig_blocker;
|
||||||
|
|
||||||
|
static const char *const sev_fw_errlist[] = {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,46 @@
|
|||||||
|
From 80c1d78e31b2567d1c610c8939b75d159ff6ea27 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:13 -0500
|
||||||
|
Subject: [PATCH 055/100] i386/sev: Replace error_report with error_setg
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [55/91] 1e15fc2458687e564af9fa5022c29e79ddc8edfd (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-2-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 18c453409a3a84cf7b2c764c5a03fb429a73bbeb)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 6 +++---
|
||||||
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index d30b68c11e..67ed32e5ea 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -952,13 +952,13 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
|
||||||
|
if (sev_es_enabled()) {
|
||||||
|
if (!kvm_kernel_irqchip_allowed()) {
|
||||||
|
- error_report("%s: SEV-ES guests require in-kernel irqchip support",
|
||||||
|
- __func__);
|
||||||
|
+ error_setg(errp, "%s: SEV-ES guests require in-kernel irqchip"
|
||||||
|
+ "support", __func__);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
|
||||||
|
- error_report("%s: guest policy requires SEV-ES, but "
|
||||||
|
+ error_setg(errp, "%s: guest policy requires SEV-ES, but "
|
||||||
|
"host SEV-ES support unavailable",
|
||||||
|
__func__);
|
||||||
|
goto err;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
From 88da6d01b1de2b92adb5c47c6d482876a054705f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Fri, 7 Jun 2024 13:36:11 -0500
|
||||||
|
Subject: [PATCH 086/100] i386/sev: Return when sev_common is null
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [86/91] 02ce4a6a51ce9fd961f417c13db0a760673591ba (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Fixes Coverity CID 1546885.
|
||||||
|
|
||||||
|
Fixes: 16dcf200dc ("i386/sev: Introduce "sev-common" type to encapsulate common SEV state")
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240607183611.1111100-4-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit cd7093a7a168a823d07671348996f049d45e8f67)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index f18432f58e..c40562dce3 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -587,6 +587,7 @@ static SevCapability *sev_get_capabilities(Error **errp)
|
||||||
|
sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
if (!sev_common) {
|
||||||
|
error_setg(errp, "SEV is not configured");
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sev_device = object_property_get_str(OBJECT(sev_common), "sev-device",
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
From c7649ac1b958dc48de50f32b1ad80d84b17945a8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:29 -0500
|
||||||
|
Subject: [PATCH 069/100] i386/sev: Set CPU state to protected once SNP guest
|
||||||
|
payload is finalized
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [69/91] 09280f987a186511ec7d62c3f340b2148e8556d7 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Once KVM_SNP_LAUNCH_FINISH is called the vCPU state is copied into the
|
||||||
|
vCPU's VMSA page and measured/encrypted. Any attempt to read/write CPU
|
||||||
|
state afterward will only be acting on the initial data and so are
|
||||||
|
effectively no-ops.
|
||||||
|
|
||||||
|
Set the vCPU state to protected at this point so that QEMU don't
|
||||||
|
continue trying to re-sync vCPU data during guest runtime.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-18-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 3d44fdff60ea66fbd7a33f5d32b50843cd80f48a)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index ef2e592ca7..e84e4395a5 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -997,6 +997,7 @@ sev_snp_launch_finish(SevCommonState *sev_common)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ kvm_mark_guest_state_protected();
|
||||||
|
sev_set_guest_state(sev_common, SEV_STATE_RUNNING);
|
||||||
|
|
||||||
|
/* add migration blocker */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,268 @@
|
|||||||
|
From 5540bb5ca052531563df1ade68995e268ae65224 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Thu, 29 Feb 2024 01:00:36 -0500
|
||||||
|
Subject: [PATCH 012/100] i386/sev: Switch to use confidential_guest_kvm_init()
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [12/91] 6f5f8d1b818826f7ee4b6ae527963ef23c97f531 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Use confidential_guest_kvm_init() instead of calling SEV
|
||||||
|
specific sev_kvm_init(). This allows the introduction of multiple
|
||||||
|
confidential-guest-support subclasses for different x86 vendors.
|
||||||
|
|
||||||
|
As a bonus, stubs are not needed anymore since there is no
|
||||||
|
direct call from target/i386/kvm/kvm.c to SEV code.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-Id: <20240229060038.606591-1-xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 637c95b37b106c2eeba313e0abb38ec12e918a59)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm.c | 10 +--
|
||||||
|
target/i386/kvm/meson.build | 2 -
|
||||||
|
target/i386/kvm/sev-stub.c | 21 ------
|
||||||
|
target/i386/sev.c | 127 ++++++++++++++++++------------------
|
||||||
|
target/i386/sev.h | 2 -
|
||||||
|
5 files changed, 69 insertions(+), 93 deletions(-)
|
||||||
|
delete mode 100644 target/i386/kvm/sev-stub.c
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index 5f30b649a0..e271652620 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -2543,10 +2543,12 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||||
|
* mechanisms are supported in future (e.g. TDX), they'll need
|
||||||
|
* their own initialization either here or elsewhere.
|
||||||
|
*/
|
||||||
|
- ret = sev_kvm_init(ms->cgs, &local_err);
|
||||||
|
- if (ret < 0) {
|
||||||
|
- error_report_err(local_err);
|
||||||
|
- return ret;
|
||||||
|
+ if (ms->cgs) {
|
||||||
|
+ ret = confidential_guest_kvm_init(ms->cgs, &local_err);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ error_report_err(local_err);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
has_xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
|
||||||
|
diff --git a/target/i386/kvm/meson.build b/target/i386/kvm/meson.build
|
||||||
|
index 84d9143e60..e7850981e6 100644
|
||||||
|
--- a/target/i386/kvm/meson.build
|
||||||
|
+++ b/target/i386/kvm/meson.build
|
||||||
|
@@ -7,8 +7,6 @@ i386_kvm_ss.add(files(
|
||||||
|
|
||||||
|
i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files('xen-emu.c'))
|
||||||
|
|
||||||
|
-i386_kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
|
||||||
|
-
|
||||||
|
i386_system_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
|
||||||
|
|
||||||
|
i386_system_ss.add_all(when: 'CONFIG_KVM', if_true: i386_kvm_ss)
|
||||||
|
diff --git a/target/i386/kvm/sev-stub.c b/target/i386/kvm/sev-stub.c
|
||||||
|
deleted file mode 100644
|
||||||
|
index 1be5341e8a..0000000000
|
||||||
|
--- a/target/i386/kvm/sev-stub.c
|
||||||
|
+++ /dev/null
|
||||||
|
@@ -1,21 +0,0 @@
|
||||||
|
-/*
|
||||||
|
- * QEMU SEV stub
|
||||||
|
- *
|
||||||
|
- * Copyright Advanced Micro Devices 2018
|
||||||
|
- *
|
||||||
|
- * Authors:
|
||||||
|
- * Brijesh Singh <brijesh.singh@amd.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 "sev.h"
|
||||||
|
-
|
||||||
|
-int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
-{
|
||||||
|
- /* If we get here, cgs must be some non-SEV thing */
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 72930ff0dc..b8f79d34d1 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -353,63 +353,6 @@ static void sev_guest_set_kernel_hashes(Object *obj, bool value, Error **errp)
|
||||||
|
sev->kernel_hashes = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
-{
|
||||||
|
- object_class_property_add_str(oc, "sev-device",
|
||||||
|
- sev_guest_get_sev_device,
|
||||||
|
- sev_guest_set_sev_device);
|
||||||
|
- object_class_property_set_description(oc, "sev-device",
|
||||||
|
- "SEV device to use");
|
||||||
|
- object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
- sev_guest_get_dh_cert_file,
|
||||||
|
- sev_guest_set_dh_cert_file);
|
||||||
|
- object_class_property_set_description(oc, "dh-cert-file",
|
||||||
|
- "guest owners DH certificate (encoded with base64)");
|
||||||
|
- object_class_property_add_str(oc, "session-file",
|
||||||
|
- sev_guest_get_session_file,
|
||||||
|
- sev_guest_set_session_file);
|
||||||
|
- object_class_property_set_description(oc, "session-file",
|
||||||
|
- "guest owners session parameters (encoded with base64)");
|
||||||
|
- object_class_property_add_bool(oc, "kernel-hashes",
|
||||||
|
- sev_guest_get_kernel_hashes,
|
||||||
|
- sev_guest_set_kernel_hashes);
|
||||||
|
- object_class_property_set_description(oc, "kernel-hashes",
|
||||||
|
- "add kernel hashes to guest firmware for measured Linux boot");
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-sev_guest_instance_init(Object *obj)
|
||||||
|
-{
|
||||||
|
- SevGuestState *sev = SEV_GUEST(obj);
|
||||||
|
-
|
||||||
|
- sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
|
||||||
|
- sev->policy = DEFAULT_GUEST_POLICY;
|
||||||
|
- object_property_add_uint32_ptr(obj, "policy", &sev->policy,
|
||||||
|
- OBJ_PROP_FLAG_READWRITE);
|
||||||
|
- object_property_add_uint32_ptr(obj, "handle", &sev->handle,
|
||||||
|
- OBJ_PROP_FLAG_READWRITE);
|
||||||
|
- object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
|
||||||
|
- OBJ_PROP_FLAG_READWRITE);
|
||||||
|
- object_property_add_uint32_ptr(obj, "reduced-phys-bits",
|
||||||
|
- &sev->reduced_phys_bits,
|
||||||
|
- OBJ_PROP_FLAG_READWRITE);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-/* sev guest info */
|
||||||
|
-static const TypeInfo sev_guest_info = {
|
||||||
|
- .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
|
||||||
|
- .name = TYPE_SEV_GUEST,
|
||||||
|
- .instance_size = sizeof(SevGuestState),
|
||||||
|
- .instance_finalize = sev_guest_finalize,
|
||||||
|
- .class_init = sev_guest_class_init,
|
||||||
|
- .instance_init = sev_guest_instance_init,
|
||||||
|
- .interfaces = (InterfaceInfo[]) {
|
||||||
|
- { TYPE_USER_CREATABLE },
|
||||||
|
- { }
|
||||||
|
- }
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
bool
|
||||||
|
sev_enabled(void)
|
||||||
|
{
|
||||||
|
@@ -906,20 +849,15 @@ sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
+static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
{
|
||||||
|
- SevGuestState *sev
|
||||||
|
- = (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
|
||||||
|
+ SevGuestState *sev = SEV_GUEST(cgs);
|
||||||
|
char *devname;
|
||||||
|
int ret, fw_error, cmd;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t host_cbitpos;
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
|
||||||
|
- if (!sev) {
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
ret = ram_block_discard_disable(true);
|
||||||
|
if (ret) {
|
||||||
|
error_report("%s: cannot disable RAM discard", __func__);
|
||||||
|
@@ -1384,6 +1322,67 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
+{
|
||||||
|
+ ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
|
||||||
|
+
|
||||||
|
+ klass->kvm_init = sev_kvm_init;
|
||||||
|
+
|
||||||
|
+ object_class_property_add_str(oc, "sev-device",
|
||||||
|
+ sev_guest_get_sev_device,
|
||||||
|
+ sev_guest_set_sev_device);
|
||||||
|
+ object_class_property_set_description(oc, "sev-device",
|
||||||
|
+ "SEV device to use");
|
||||||
|
+ object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
+ sev_guest_get_dh_cert_file,
|
||||||
|
+ sev_guest_set_dh_cert_file);
|
||||||
|
+ object_class_property_set_description(oc, "dh-cert-file",
|
||||||
|
+ "guest owners DH certificate (encoded with base64)");
|
||||||
|
+ object_class_property_add_str(oc, "session-file",
|
||||||
|
+ sev_guest_get_session_file,
|
||||||
|
+ sev_guest_set_session_file);
|
||||||
|
+ object_class_property_set_description(oc, "session-file",
|
||||||
|
+ "guest owners session parameters (encoded with base64)");
|
||||||
|
+ object_class_property_add_bool(oc, "kernel-hashes",
|
||||||
|
+ sev_guest_get_kernel_hashes,
|
||||||
|
+ sev_guest_set_kernel_hashes);
|
||||||
|
+ object_class_property_set_description(oc, "kernel-hashes",
|
||||||
|
+ "add kernel hashes to guest firmware for measured Linux boot");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_guest_instance_init(Object *obj)
|
||||||
|
+{
|
||||||
|
+ SevGuestState *sev = SEV_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ sev->sev_device = g_strdup(DEFAULT_SEV_DEVICE);
|
||||||
|
+ sev->policy = DEFAULT_GUEST_POLICY;
|
||||||
|
+ object_property_add_uint32_ptr(obj, "policy", &sev->policy,
|
||||||
|
+ OBJ_PROP_FLAG_READWRITE);
|
||||||
|
+ object_property_add_uint32_ptr(obj, "handle", &sev->handle,
|
||||||
|
+ OBJ_PROP_FLAG_READWRITE);
|
||||||
|
+ object_property_add_uint32_ptr(obj, "cbitpos", &sev->cbitpos,
|
||||||
|
+ OBJ_PROP_FLAG_READWRITE);
|
||||||
|
+ object_property_add_uint32_ptr(obj, "reduced-phys-bits",
|
||||||
|
+ &sev->reduced_phys_bits,
|
||||||
|
+ OBJ_PROP_FLAG_READWRITE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* sev guest info */
|
||||||
|
+static const TypeInfo sev_guest_info = {
|
||||||
|
+ .parent = TYPE_CONFIDENTIAL_GUEST_SUPPORT,
|
||||||
|
+ .name = TYPE_SEV_GUEST,
|
||||||
|
+ .instance_size = sizeof(SevGuestState),
|
||||||
|
+ .instance_finalize = sev_guest_finalize,
|
||||||
|
+ .class_init = sev_guest_class_init,
|
||||||
|
+ .instance_init = sev_guest_instance_init,
|
||||||
|
+ .interfaces = (InterfaceInfo[]) {
|
||||||
|
+ { TYPE_USER_CREATABLE },
|
||||||
|
+ { }
|
||||||
|
+ }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sev_register_types(void)
|
||||||
|
{
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index e7499c95b1..9e10d09539 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -57,6 +57,4 @@ int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||||
|
int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size);
|
||||||
|
void sev_es_set_reset_vector(CPUState *cpu);
|
||||||
|
|
||||||
|
-int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
-
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,240 @@
|
|||||||
|
From a870e7c31d9605baea4741d82521612b6164c99b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:26 -0500
|
||||||
|
Subject: [PATCH 066/100] i386/sev: Update query-sev QAPI format to handle
|
||||||
|
SEV-SNP
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [66/91] a19b3e226e857f3995176e7d2ef1ce2e4329a885 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Most of the current 'query-sev' command is relevant to both legacy
|
||||||
|
SEV/SEV-ES guests and SEV-SNP guests, with 2 exceptions:
|
||||||
|
|
||||||
|
- 'policy' is a 64-bit field for SEV-SNP, not 32-bit, and
|
||||||
|
the meaning of the bit positions has changed
|
||||||
|
- 'handle' is not relevant to SEV-SNP
|
||||||
|
|
||||||
|
To address this, this patch adds a new 'sev-type' field that can be
|
||||||
|
used as a discriminator to select between SEV and SEV-SNP-specific
|
||||||
|
fields/formats without breaking compatibility for existing management
|
||||||
|
tools (so long as management tools that add support for launching
|
||||||
|
SEV-SNP guest update their handling of query-sev appropriately).
|
||||||
|
|
||||||
|
The corresponding HMP command has also been fixed up similarly.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by:Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-15-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 59d3740cb4ac0f010ce35877572904f6297284b4)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
qapi/misc-target.json | 72 ++++++++++++++++++++++++++++++++++---------
|
||||||
|
target/i386/sev.c | 55 +++++++++++++++++++++------------
|
||||||
|
target/i386/sev.h | 3 ++
|
||||||
|
3 files changed, 96 insertions(+), 34 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
|
||||||
|
index 4e0a6492a9..2d7d4d89bd 100644
|
||||||
|
--- a/qapi/misc-target.json
|
||||||
|
+++ b/qapi/misc-target.json
|
||||||
|
@@ -47,6 +47,50 @@
|
||||||
|
'send-update', 'receive-update' ],
|
||||||
|
'if': 'TARGET_I386' }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @SevGuestType:
|
||||||
|
+#
|
||||||
|
+# An enumeration indicating the type of SEV guest being run.
|
||||||
|
+#
|
||||||
|
+# @sev: The guest is a legacy SEV or SEV-ES guest.
|
||||||
|
+#
|
||||||
|
+# @sev-snp: The guest is an SEV-SNP guest.
|
||||||
|
+#
|
||||||
|
+# Since: 6.2
|
||||||
|
+##
|
||||||
|
+{ 'enum': 'SevGuestType',
|
||||||
|
+ 'data': [ 'sev', 'sev-snp' ],
|
||||||
|
+ 'if': 'TARGET_I386' }
|
||||||
|
+
|
||||||
|
+##
|
||||||
|
+# @SevGuestInfo:
|
||||||
|
+#
|
||||||
|
+# Information specific to legacy SEV/SEV-ES guests.
|
||||||
|
+#
|
||||||
|
+# @policy: SEV policy value
|
||||||
|
+#
|
||||||
|
+# @handle: SEV firmware handle
|
||||||
|
+#
|
||||||
|
+# Since: 2.12
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'SevGuestInfo',
|
||||||
|
+ 'data': { 'policy': 'uint32',
|
||||||
|
+ 'handle': 'uint32' },
|
||||||
|
+ 'if': 'TARGET_I386' }
|
||||||
|
+
|
||||||
|
+##
|
||||||
|
+# @SevSnpGuestInfo:
|
||||||
|
+#
|
||||||
|
+# Information specific to SEV-SNP guests.
|
||||||
|
+#
|
||||||
|
+# @snp-policy: SEV-SNP policy value
|
||||||
|
+#
|
||||||
|
+# Since: 9.1
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'SevSnpGuestInfo',
|
||||||
|
+ 'data': { 'snp-policy': 'uint64' },
|
||||||
|
+ 'if': 'TARGET_I386' }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @SevInfo:
|
||||||
|
#
|
||||||
|
@@ -60,25 +104,25 @@
|
||||||
|
#
|
||||||
|
# @build-id: SEV FW build id
|
||||||
|
#
|
||||||
|
-# @policy: SEV policy value
|
||||||
|
-#
|
||||||
|
# @state: SEV guest state
|
||||||
|
#
|
||||||
|
-# @handle: SEV firmware handle
|
||||||
|
+# @sev-type: Type of SEV guest being run
|
||||||
|
#
|
||||||
|
# Since: 2.12
|
||||||
|
##
|
||||||
|
-{ 'struct': 'SevInfo',
|
||||||
|
- 'data': { 'enabled': 'bool',
|
||||||
|
- 'api-major': 'uint8',
|
||||||
|
- 'api-minor' : 'uint8',
|
||||||
|
- 'build-id' : 'uint8',
|
||||||
|
- 'policy' : 'uint32',
|
||||||
|
- 'state' : 'SevState',
|
||||||
|
- 'handle' : 'uint32'
|
||||||
|
- },
|
||||||
|
- 'if': 'TARGET_I386'
|
||||||
|
-}
|
||||||
|
+{ 'union': 'SevInfo',
|
||||||
|
+ 'base': { 'enabled': 'bool',
|
||||||
|
+ 'api-major': 'uint8',
|
||||||
|
+ 'api-minor' : 'uint8',
|
||||||
|
+ 'build-id' : 'uint8',
|
||||||
|
+ 'state' : 'SevState',
|
||||||
|
+ 'sev-type' : 'SevGuestType' },
|
||||||
|
+ 'discriminator': 'sev-type',
|
||||||
|
+ 'data': {
|
||||||
|
+ 'sev': 'SevGuestInfo',
|
||||||
|
+ 'sev-snp': 'SevSnpGuestInfo' },
|
||||||
|
+ 'if': 'TARGET_I386' }
|
||||||
|
+
|
||||||
|
|
||||||
|
##
|
||||||
|
# @query-sev:
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 072cc4f853..43d1c48bd9 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -363,25 +363,27 @@ static SevInfo *sev_get_info(void)
|
||||||
|
{
|
||||||
|
SevInfo *info;
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
- SevGuestState *sev_guest =
|
||||||
|
- (SevGuestState *)object_dynamic_cast(OBJECT(sev_common),
|
||||||
|
- TYPE_SEV_GUEST);
|
||||||
|
|
||||||
|
info = g_new0(SevInfo, 1);
|
||||||
|
info->enabled = sev_enabled();
|
||||||
|
|
||||||
|
if (info->enabled) {
|
||||||
|
- if (sev_guest) {
|
||||||
|
- info->handle = sev_guest->handle;
|
||||||
|
- }
|
||||||
|
info->api_major = sev_common->api_major;
|
||||||
|
info->api_minor = sev_common->api_minor;
|
||||||
|
info->build_id = sev_common->build_id;
|
||||||
|
info->state = sev_common->state;
|
||||||
|
- /* we only report the lower 32-bits of policy for SNP, ok for now... */
|
||||||
|
- info->policy =
|
||||||
|
- (uint32_t)object_property_get_uint(OBJECT(sev_common),
|
||||||
|
- "policy", NULL);
|
||||||
|
+
|
||||||
|
+ if (sev_snp_enabled()) {
|
||||||
|
+ info->sev_type = SEV_GUEST_TYPE_SEV_SNP;
|
||||||
|
+ info->u.sev_snp.snp_policy =
|
||||||
|
+ object_property_get_uint(OBJECT(sev_common), "policy", NULL);
|
||||||
|
+ } else {
|
||||||
|
+ info->sev_type = SEV_GUEST_TYPE_SEV;
|
||||||
|
+ info->u.sev.handle = SEV_GUEST(sev_common)->handle;
|
||||||
|
+ info->u.sev.policy =
|
||||||
|
+ (uint32_t)object_property_get_uint(OBJECT(sev_common),
|
||||||
|
+ "policy", NULL);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
@@ -404,20 +406,33 @@ void hmp_info_sev(Monitor *mon, const QDict *qdict)
|
||||||
|
{
|
||||||
|
SevInfo *info = sev_get_info();
|
||||||
|
|
||||||
|
- if (info && info->enabled) {
|
||||||
|
- monitor_printf(mon, "handle: %d\n", info->handle);
|
||||||
|
- monitor_printf(mon, "state: %s\n", SevState_str(info->state));
|
||||||
|
- monitor_printf(mon, "build: %d\n", info->build_id);
|
||||||
|
- monitor_printf(mon, "api version: %d.%d\n",
|
||||||
|
- info->api_major, info->api_minor);
|
||||||
|
+ if (!info || !info->enabled) {
|
||||||
|
+ monitor_printf(mon, "SEV is not enabled\n");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ monitor_printf(mon, "SEV type: %s\n", SevGuestType_str(info->sev_type));
|
||||||
|
+ monitor_printf(mon, "state: %s\n", SevState_str(info->state));
|
||||||
|
+ monitor_printf(mon, "build: %d\n", info->build_id);
|
||||||
|
+ monitor_printf(mon, "api version: %d.%d\n", info->api_major,
|
||||||
|
+ info->api_minor);
|
||||||
|
+
|
||||||
|
+ if (sev_snp_enabled()) {
|
||||||
|
monitor_printf(mon, "debug: %s\n",
|
||||||
|
- info->policy & SEV_POLICY_NODBG ? "off" : "on");
|
||||||
|
- monitor_printf(mon, "key-sharing: %s\n",
|
||||||
|
- info->policy & SEV_POLICY_NOKS ? "off" : "on");
|
||||||
|
+ info->u.sev_snp.snp_policy & SEV_SNP_POLICY_DBG ? "on"
|
||||||
|
+ : "off");
|
||||||
|
+ monitor_printf(mon, "SMT allowed: %s\n",
|
||||||
|
+ info->u.sev_snp.snp_policy & SEV_SNP_POLICY_SMT ? "on"
|
||||||
|
+ : "off");
|
||||||
|
} else {
|
||||||
|
- monitor_printf(mon, "SEV is not enabled\n");
|
||||||
|
+ monitor_printf(mon, "handle: %d\n", info->u.sev.handle);
|
||||||
|
+ monitor_printf(mon, "debug: %s\n",
|
||||||
|
+ info->u.sev.policy & SEV_POLICY_NODBG ? "off" : "on");
|
||||||
|
+ monitor_printf(mon, "key-sharing: %s\n",
|
||||||
|
+ info->u.sev.policy & SEV_POLICY_NOKS ? "off" : "on");
|
||||||
|
}
|
||||||
|
|
||||||
|
+out:
|
||||||
|
qapi_free_SevInfo(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index 94295ee74f..5dc4767b1e 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -31,6 +31,9 @@
|
||||||
|
#define SEV_POLICY_DOMAIN 0x10
|
||||||
|
#define SEV_POLICY_SEV 0x20
|
||||||
|
|
||||||
|
+#define SEV_SNP_POLICY_SMT 0x10000
|
||||||
|
+#define SEV_SNP_POLICY_DBG 0x80000
|
||||||
|
+
|
||||||
|
typedef struct SevKernelLoaderContext {
|
||||||
|
char *setup_data;
|
||||||
|
size_t setup_size;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,51 @@
|
|||||||
|
From 98057e3adafa052b21a4fe5ef22835d30df3e644 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Fri, 7 Jun 2024 13:36:09 -0500
|
||||||
|
Subject: [PATCH 084/100] i386/sev: fix unreachable code coverity issue
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [84/91] dc7bf28f491bf675b22a98ea593fba72d8bc415a (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Set 'finish->id_block_en' early, so that it is properly reset.
|
||||||
|
|
||||||
|
Fixes coverity CID 1546887.
|
||||||
|
|
||||||
|
Fixes: 7b34df4426 ("i386/sev: Introduce 'sev-snp-guest' object")
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240607183611.1111100-2-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit c94eb5db8e409c932da9eb187e68d4cdc14acc5b)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 004c667ac1..7c9df621de 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -2165,6 +2165,7 @@ sev_snp_guest_set_id_block(Object *obj, const char *value, Error **errp)
|
||||||
|
struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
|
||||||
|
gsize len;
|
||||||
|
|
||||||
|
+ finish->id_block_en = 0;
|
||||||
|
g_free(sev_snp_guest->id_block);
|
||||||
|
g_free((guchar *)finish->id_block_uaddr);
|
||||||
|
|
||||||
|
@@ -2184,7 +2185,7 @@ sev_snp_guest_set_id_block(Object *obj, const char *value, Error **errp)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- finish->id_block_en = (len) ? 1 : 0;
|
||||||
|
+ finish->id_block_en = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,81 @@
|
|||||||
|
From deae6c3b57c3919946a5ce1613e667a3240cf158 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Mon, 15 Apr 2024 12:45:09 +0200
|
||||||
|
Subject: [PATCH 001/100] introduce pc_rhel_9_5_compat
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [1/91] cfd402fa5080eddba7c954e81ed79f9a1dd654cf (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Allow undoing backported changes that impact guest ABI.
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 4 ++++
|
||||||
|
hw/i386/pc_piix.c | 2 ++
|
||||||
|
hw/i386/pc_q35.c | 2 ++
|
||||||
|
include/hw/i386/pc.h | 3 +++
|
||||||
|
4 files changed, 11 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index 4a154c1a9a..648762d908 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -348,6 +348,10 @@ GlobalProperty pc_rhel_compat[] = {
|
||||||
|
};
|
||||||
|
const size_t pc_rhel_compat_len = G_N_ELEMENTS(pc_rhel_compat);
|
||||||
|
|
||||||
|
+GlobalProperty pc_rhel_9_5_compat[] = {
|
||||||
|
+};
|
||||||
|
+const size_t pc_rhel_9_5_compat_len = G_N_ELEMENTS(pc_rhel_9_5_compat);
|
||||||
|
+
|
||||||
|
GlobalProperty pc_rhel_9_3_compat[] = {
|
||||||
|
/* pc_rhel_9_3_compat from pc_compat_8_0 */
|
||||||
|
{ "virtio-mem", "unplugged-inaccessible", "auto" },
|
||||||
|
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||||
|
index 6b260682eb..bef3e8b73e 100644
|
||||||
|
--- a/hw/i386/pc_piix.c
|
||||||
|
+++ b/hw/i386/pc_piix.c
|
||||||
|
@@ -1015,6 +1015,8 @@ static void pc_machine_rhel760_options(MachineClass *m)
|
||||||
|
object_class_property_set_description(oc, "x-south-bridge",
|
||||||
|
"Use a different south bridge than PIIX3");
|
||||||
|
|
||||||
|
+ compat_props_add(m->compat_props, pc_rhel_9_5_compat,
|
||||||
|
+ pc_rhel_9_5_compat_len);
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||||
|
hw_compat_rhel_9_5_len);
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_9_4,
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index 2b54944c0f..9adcdadce8 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -734,6 +734,8 @@ static void pc_q35_machine_rhel940_options(MachineClass *m)
|
||||||
|
pcmc->smbios_stream_product = "RHEL";
|
||||||
|
pcmc->smbios_stream_version = "9.4.0";
|
||||||
|
|
||||||
|
+ compat_props_add(m->compat_props, pc_rhel_9_5_compat,
|
||||||
|
+ pc_rhel_9_5_compat_len);
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||||
|
hw_compat_rhel_9_5_len);
|
||||||
|
}
|
||||||
|
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||||
|
index a984c951ad..87420783ab 100644
|
||||||
|
--- a/include/hw/i386/pc.h
|
||||||
|
+++ b/include/hw/i386/pc.h
|
||||||
|
@@ -294,6 +294,9 @@ extern const size_t pc_compat_2_0_len;
|
||||||
|
extern GlobalProperty pc_rhel_compat[];
|
||||||
|
extern const size_t pc_rhel_compat_len;
|
||||||
|
|
||||||
|
+extern GlobalProperty pc_rhel_9_5_compat[];
|
||||||
|
+extern const size_t pc_rhel_9_5_compat_len;
|
||||||
|
+
|
||||||
|
extern GlobalProperty pc_rhel_9_3_compat[];
|
||||||
|
extern const size_t pc_rhel_9_3_compat_len;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,153 @@
|
|||||||
|
From 120157257ac239050779fdddc9abb56bd39958b3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Chao Peng <chao.p.peng@linux.intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:05 -0500
|
||||||
|
Subject: [PATCH 029/100] kvm: Enable KVM_SET_USER_MEMORY_REGION2 for memslot
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [29/91] 9a08c8699f632cd046a6307e33bd053a7cc7db46 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Switch to KVM_SET_USER_MEMORY_REGION2 when supported by KVM.
|
||||||
|
|
||||||
|
With KVM_SET_USER_MEMORY_REGION2, QEMU can set up memory region that
|
||||||
|
backend'ed both by hva-based shared memory and guest memfd based private
|
||||||
|
memory.
|
||||||
|
|
||||||
|
Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
|
||||||
|
Co-developed-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240320083945.991426-10-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit ce5a983233b4ca94ced88c9581014346509b5c71)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 46 +++++++++++++++++++++++++++++++++-------
|
||||||
|
accel/kvm/trace-events | 2 +-
|
||||||
|
include/sysemu/kvm_int.h | 2 ++
|
||||||
|
3 files changed, 41 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index a7b9a127dd..5ef55e4dd7 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -284,35 +284,58 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
|
||||||
|
static int kvm_set_user_memory_region(KVMMemoryListener *kml, KVMSlot *slot, bool new)
|
||||||
|
{
|
||||||
|
KVMState *s = kvm_state;
|
||||||
|
- struct kvm_userspace_memory_region mem;
|
||||||
|
+ struct kvm_userspace_memory_region2 mem;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mem.slot = slot->slot | (kml->as_id << 16);
|
||||||
|
mem.guest_phys_addr = slot->start_addr;
|
||||||
|
mem.userspace_addr = (unsigned long)slot->ram;
|
||||||
|
mem.flags = slot->flags;
|
||||||
|
+ mem.guest_memfd = slot->guest_memfd;
|
||||||
|
+ mem.guest_memfd_offset = slot->guest_memfd_offset;
|
||||||
|
|
||||||
|
if (slot->memory_size && !new && (mem.flags ^ slot->old_flags) & KVM_MEM_READONLY) {
|
||||||
|
/* Set the slot size to 0 before setting the slot to the desired
|
||||||
|
* value. This is needed based on KVM commit 75d61fbc. */
|
||||||
|
mem.memory_size = 0;
|
||||||
|
- ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
|
||||||
|
+
|
||||||
|
+ if (kvm_guest_memfd_supported) {
|
||||||
|
+ ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION2, &mem);
|
||||||
|
+ } else {
|
||||||
|
+ ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
|
||||||
|
+ }
|
||||||
|
if (ret < 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mem.memory_size = slot->memory_size;
|
||||||
|
- ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
|
||||||
|
+ if (kvm_guest_memfd_supported) {
|
||||||
|
+ ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION2, &mem);
|
||||||
|
+ } else {
|
||||||
|
+ ret = kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, &mem);
|
||||||
|
+ }
|
||||||
|
slot->old_flags = mem.flags;
|
||||||
|
err:
|
||||||
|
trace_kvm_set_user_memory(mem.slot >> 16, (uint16_t)mem.slot, mem.flags,
|
||||||
|
mem.guest_phys_addr, mem.memory_size,
|
||||||
|
- mem.userspace_addr, ret);
|
||||||
|
+ mem.userspace_addr, mem.guest_memfd,
|
||||||
|
+ mem.guest_memfd_offset, ret);
|
||||||
|
if (ret < 0) {
|
||||||
|
- error_report("%s: KVM_SET_USER_MEMORY_REGION failed, slot=%d,"
|
||||||
|
- " start=0x%" PRIx64 ", size=0x%" PRIx64 ": %s",
|
||||||
|
- __func__, mem.slot, slot->start_addr,
|
||||||
|
- (uint64_t)mem.memory_size, strerror(errno));
|
||||||
|
+ if (kvm_guest_memfd_supported) {
|
||||||
|
+ error_report("%s: KVM_SET_USER_MEMORY_REGION2 failed, slot=%d,"
|
||||||
|
+ " start=0x%" PRIx64 ", size=0x%" PRIx64 ","
|
||||||
|
+ " flags=0x%" PRIx32 ", guest_memfd=%" PRId32 ","
|
||||||
|
+ " guest_memfd_offset=0x%" PRIx64 ": %s",
|
||||||
|
+ __func__, mem.slot, slot->start_addr,
|
||||||
|
+ (uint64_t)mem.memory_size, mem.flags,
|
||||||
|
+ mem.guest_memfd, (uint64_t)mem.guest_memfd_offset,
|
||||||
|
+ strerror(errno));
|
||||||
|
+ } else {
|
||||||
|
+ error_report("%s: KVM_SET_USER_MEMORY_REGION failed, slot=%d,"
|
||||||
|
+ " start=0x%" PRIx64 ", size=0x%" PRIx64 ": %s",
|
||||||
|
+ __func__, mem.slot, slot->start_addr,
|
||||||
|
+ (uint64_t)mem.memory_size, strerror(errno));
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -467,6 +490,10 @@ static int kvm_mem_flags(MemoryRegion *mr)
|
||||||
|
if (readonly && kvm_readonly_mem_allowed) {
|
||||||
|
flags |= KVM_MEM_READONLY;
|
||||||
|
}
|
||||||
|
+ if (memory_region_has_guest_memfd(mr)) {
|
||||||
|
+ assert(kvm_guest_memfd_supported);
|
||||||
|
+ flags |= KVM_MEM_GUEST_MEMFD;
|
||||||
|
+ }
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1394,6 +1421,9 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||||
|
mem->ram_start_offset = ram_start_offset;
|
||||||
|
mem->ram = ram;
|
||||||
|
mem->flags = kvm_mem_flags(mr);
|
||||||
|
+ mem->guest_memfd = mr->ram_block->guest_memfd;
|
||||||
|
+ mem->guest_memfd_offset = (uint8_t*)ram - mr->ram_block->host;
|
||||||
|
+
|
||||||
|
kvm_slot_init_dirty_bitmap(mem);
|
||||||
|
err = kvm_set_user_memory_region(kml, mem, true);
|
||||||
|
if (err) {
|
||||||
|
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
|
||||||
|
index 9f599abc17..e8c52cb9e7 100644
|
||||||
|
--- a/accel/kvm/trace-events
|
||||||
|
+++ b/accel/kvm/trace-events
|
||||||
|
@@ -15,7 +15,7 @@ kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
|
||||||
|
kvm_irqchip_release_virq(int virq) "virq %d"
|
||||||
|
kvm_set_ioeventfd_mmio(int fd, uint64_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%" PRIx64 " val=0x%x assign: %d size: %d match: %d"
|
||||||
|
kvm_set_ioeventfd_pio(int fd, uint16_t addr, uint32_t val, bool assign, uint32_t size, bool datamatch) "fd: %d @0x%x val=0x%x assign: %d size: %d match: %d"
|
||||||
|
-kvm_set_user_memory(uint16_t as, uint16_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, int ret) "AddrSpace#%d Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " ret=%d"
|
||||||
|
+kvm_set_user_memory(uint16_t as, uint16_t slot, uint32_t flags, uint64_t guest_phys_addr, uint64_t memory_size, uint64_t userspace_addr, uint32_t fd, uint64_t fd_offset, int ret) "AddrSpace#%d Slot#%d flags=0x%x gpa=0x%"PRIx64 " size=0x%"PRIx64 " ua=0x%"PRIx64 " guest_memfd=%d" " guest_memfd_offset=0x%" PRIx64 " ret=%d"
|
||||||
|
kvm_clear_dirty_log(uint32_t slot, uint64_t start, uint32_t size) "slot#%"PRId32" start 0x%"PRIx64" size 0x%"PRIx32
|
||||||
|
kvm_resample_fd_notify(int gsi) "gsi %d"
|
||||||
|
kvm_dirty_ring_full(int id) "vcpu %d"
|
||||||
|
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
|
||||||
|
index 3496be7997..a5a3fee411 100644
|
||||||
|
--- a/include/sysemu/kvm_int.h
|
||||||
|
+++ b/include/sysemu/kvm_int.h
|
||||||
|
@@ -30,6 +30,8 @@ typedef struct KVMSlot
|
||||||
|
int as_id;
|
||||||
|
/* Cache of the offset in ram address space */
|
||||||
|
ram_addr_t ram_start_offset;
|
||||||
|
+ int guest_memfd;
|
||||||
|
+ hwaddr guest_memfd_offset;
|
||||||
|
} KVMSlot;
|
||||||
|
|
||||||
|
typedef struct KVMMemoryUpdate {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,103 @@
|
|||||||
|
From 37e6c98987bb2d4be7ce1fdda4475cd0266271c3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:06 -0500
|
||||||
|
Subject: [PATCH 027/100] kvm: Introduce support for memory_attributes
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [27/91] 1b4428289949478f7390196ae4b098c5e6f36bb0 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Introduce the helper functions to set the attributes of a range of
|
||||||
|
memory to private or shared.
|
||||||
|
|
||||||
|
This is necessary to notify KVM the private/shared attribute of each gpa
|
||||||
|
range. KVM needs the information to decide the GPA needs to be mapped at
|
||||||
|
hva-based shared memory or guest_memfd based private memory.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240320083945.991426-11-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 0811baed49010a9b651b8029ab6b9828b09a884f)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 32 ++++++++++++++++++++++++++++++++
|
||||||
|
include/sysemu/kvm.h | 4 ++++
|
||||||
|
2 files changed, 36 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 9bd235c969..272e945f52 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -91,6 +91,7 @@ bool kvm_msi_use_devid;
|
||||||
|
static bool kvm_has_guest_debug;
|
||||||
|
static int kvm_sstep_flags;
|
||||||
|
static bool kvm_immediate_exit;
|
||||||
|
+static uint64_t kvm_supported_memory_attributes;
|
||||||
|
static hwaddr kvm_max_slot_size = ~0;
|
||||||
|
|
||||||
|
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||||
|
@@ -1266,6 +1267,36 @@ void kvm_set_max_memslot_size(hwaddr max_slot_size)
|
||||||
|
kvm_max_slot_size = max_slot_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int kvm_set_memory_attributes(hwaddr start, uint64_t size, uint64_t attr)
|
||||||
|
+{
|
||||||
|
+ struct kvm_memory_attributes attrs;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ assert((attr & kvm_supported_memory_attributes) == attr);
|
||||||
|
+ attrs.attributes = attr;
|
||||||
|
+ attrs.address = start;
|
||||||
|
+ attrs.size = size;
|
||||||
|
+ attrs.flags = 0;
|
||||||
|
+
|
||||||
|
+ r = kvm_vm_ioctl(kvm_state, KVM_SET_MEMORY_ATTRIBUTES, &attrs);
|
||||||
|
+ if (r) {
|
||||||
|
+ error_report("failed to set memory (0x%" HWADDR_PRIx "+0x%" PRIx64 ") "
|
||||||
|
+ "with attr 0x%" PRIx64 " error '%s'",
|
||||||
|
+ start, size, attr, strerror(errno));
|
||||||
|
+ }
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int kvm_set_memory_attributes_private(hwaddr start, uint64_t size)
|
||||||
|
+{
|
||||||
|
+ return kvm_set_memory_attributes(start, size, KVM_MEMORY_ATTRIBUTE_PRIVATE);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size)
|
||||||
|
+{
|
||||||
|
+ return kvm_set_memory_attributes(start, size, 0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Called with KVMMemoryListener.slots_lock held */
|
||||||
|
static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||||
|
MemoryRegionSection *section, bool add)
|
||||||
|
@@ -2387,6 +2418,7 @@ static int kvm_init(MachineState *ms)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ kvm_supported_memory_attributes = kvm_check_extension(s, KVM_CAP_MEMORY_ATTRIBUTES);
|
||||||
|
kvm_immediate_exit = kvm_check_extension(s, KVM_CAP_IMMEDIATE_EXIT);
|
||||||
|
s->nr_slots = kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
|
||||||
|
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index 54f4d83a37..f114ff6986 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -536,4 +536,8 @@ void kvm_mark_guest_state_protected(void);
|
||||||
|
* reported for the VM.
|
||||||
|
*/
|
||||||
|
bool kvm_hwpoisoned_mem(void);
|
||||||
|
+
|
||||||
|
+int kvm_set_memory_attributes_private(hwaddr start, uint64_t size);
|
||||||
|
+int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size);
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
From 31cc494d69449811f4d995326479372da7c1241e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
Date: Mon, 18 Mar 2024 16:53:35 +0100
|
||||||
|
Subject: [PATCH 003/100] kvm: add support for guest physical bits
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [3/91] abb1ba3a584152d8efabd8255b86afe609f8ffbd (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Query kvm for supported guest physical address bits, in cpuid
|
||||||
|
function 80000008, eax[23:16]. Usually this is identical to host
|
||||||
|
physical address bits. With NPT or EPT being used this might be
|
||||||
|
restricted to 48 (max 4-level paging address space size) even if
|
||||||
|
the host cpu supports more physical address bits.
|
||||||
|
|
||||||
|
When set pass this to the guest, using cpuid too. Guest firmware
|
||||||
|
can use this to figure how big the usable guest physical address
|
||||||
|
space is, so PCI bar mapping are actually reachable.
|
||||||
|
|
||||||
|
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||||
|
Message-ID: <20240318155336.156197-2-kraxel@redhat.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 0d08c423688edcca857f88dab20f1fc56de2b281)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm-cpu.c | 50 ++++++++++++++++++++++++++++++++-------
|
||||||
|
1 file changed, 42 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c
|
||||||
|
index b91af5051f..7ef94c681f 100644
|
||||||
|
--- a/target/i386/kvm/kvm-cpu.c
|
||||||
|
+++ b/target/i386/kvm/kvm-cpu.c
|
||||||
|
@@ -18,10 +18,32 @@
|
||||||
|
#include "kvm_i386.h"
|
||||||
|
#include "hw/core/accel-cpu.h"
|
||||||
|
|
||||||
|
+static void kvm_set_guest_phys_bits(CPUState *cs)
|
||||||
|
+{
|
||||||
|
+ X86CPU *cpu = X86_CPU(cs);
|
||||||
|
+ uint32_t eax, guest_phys_bits;
|
||||||
|
+
|
||||||
|
+ eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x80000008, 0, R_EAX);
|
||||||
|
+ guest_phys_bits = (eax >> 16) & 0xff;
|
||||||
|
+ if (!guest_phys_bits) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ cpu->guest_phys_bits = guest_phys_bits;
|
||||||
|
+ if (cpu->guest_phys_bits > cpu->phys_bits) {
|
||||||
|
+ cpu->guest_phys_bits = cpu->phys_bits;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cpu->host_phys_bits && cpu->host_phys_bits_limit &&
|
||||||
|
+ cpu->guest_phys_bits > cpu->host_phys_bits_limit) {
|
||||||
|
+ cpu->guest_phys_bits = cpu->host_phys_bits_limit;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
|
||||||
|
{
|
||||||
|
X86CPU *cpu = X86_CPU(cs);
|
||||||
|
CPUX86State *env = &cpu->env;
|
||||||
|
+ bool ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The realize order is important, since x86_cpu_realize() checks if
|
||||||
|
@@ -32,13 +54,15 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
|
||||||
|
*
|
||||||
|
* realize order:
|
||||||
|
*
|
||||||
|
- * x86_cpu_realize():
|
||||||
|
- * -> x86_cpu_expand_features()
|
||||||
|
- * -> cpu_exec_realizefn():
|
||||||
|
- * -> accel_cpu_common_realize()
|
||||||
|
- * kvm_cpu_realizefn() -> host_cpu_realizefn()
|
||||||
|
- * -> cpu_common_realizefn()
|
||||||
|
- * -> check/update ucode_rev, phys_bits, mwait
|
||||||
|
+ * x86_cpu_realizefn():
|
||||||
|
+ * x86_cpu_expand_features()
|
||||||
|
+ * cpu_exec_realizefn():
|
||||||
|
+ * accel_cpu_common_realize()
|
||||||
|
+ * kvm_cpu_realizefn()
|
||||||
|
+ * host_cpu_realizefn()
|
||||||
|
+ * kvm_set_guest_phys_bits()
|
||||||
|
+ * check/update ucode_rev, phys_bits, guest_phys_bits, mwait
|
||||||
|
+ * cpu_common_realizefn() (via xcc->parent_realize)
|
||||||
|
*/
|
||||||
|
if (cpu->max_features) {
|
||||||
|
if (enable_cpu_pm && kvm_has_waitpkg()) {
|
||||||
|
@@ -50,7 +74,17 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp)
|
||||||
|
MSR_IA32_UCODE_REV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- return host_cpu_realizefn(cs, errp);
|
||||||
|
+ ret = host_cpu_realizefn(cs, errp);
|
||||||
|
+ if (!ret) {
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if ((env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) &&
|
||||||
|
+ cpu->guest_phys_bits == -1) {
|
||||||
|
+ kvm_set_guest_phys_bits(cs);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool lmce_supported(void)
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,194 @@
|
|||||||
|
From 33cc1b469689ee2bb7c4f745189472c74a0a98ab Mon Sep 17 00:00:00 2001
|
||||||
|
From: Chao Peng <chao.p.peng@linux.intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:08 -0500
|
||||||
|
Subject: [PATCH 034/100] kvm: handle KVM_EXIT_MEMORY_FAULT
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [34/91] 59c672f6b19a3afcb61878775eb6425c6fdea6d5 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Upon an KVM_EXIT_MEMORY_FAULT exit, userspace needs to do the memory
|
||||||
|
conversion on the RAMBlock to turn the memory into desired attribute,
|
||||||
|
switching between private and shared.
|
||||||
|
|
||||||
|
Currently only KVM_MEMORY_EXIT_FLAG_PRIVATE in flags is valid when
|
||||||
|
KVM_EXIT_MEMORY_FAULT happens.
|
||||||
|
|
||||||
|
Note, KVM_EXIT_MEMORY_FAULT makes sense only when the RAMBlock has
|
||||||
|
guest_memfd memory backend.
|
||||||
|
|
||||||
|
Note, KVM_EXIT_MEMORY_FAULT returns with -EFAULT, so special handling is
|
||||||
|
added.
|
||||||
|
|
||||||
|
When page is converted from shared to private, the original shared
|
||||||
|
memory can be discarded via ram_block_discard_range(). Note, shared
|
||||||
|
memory can be discarded only when it's not back'ed by hugetlb because
|
||||||
|
hugetlb is supposed to be pre-allocated and no need for discarding.
|
||||||
|
|
||||||
|
Signed-off-by: Chao Peng <chao.p.peng@linux.intel.com>
|
||||||
|
Co-developed-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
|
||||||
|
Message-ID: <20240320083945.991426-13-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit c15e5684071d93174e446be318f49d8d59b15d6d)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 98 +++++++++++++++++++++++++++++++++++++-----
|
||||||
|
accel/kvm/trace-events | 2 +
|
||||||
|
include/sysemu/kvm.h | 2 +
|
||||||
|
3 files changed, 92 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 3f99efc8cc..09164e346c 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -2900,6 +2900,69 @@ static void kvm_eat_signals(CPUState *cpu)
|
||||||
|
} while (sigismember(&chkset, SIG_IPI));
|
||||||
|
}
|
||||||
|
|
||||||
|
+int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
|
||||||
|
+{
|
||||||
|
+ MemoryRegionSection section;
|
||||||
|
+ ram_addr_t offset;
|
||||||
|
+ MemoryRegion *mr;
|
||||||
|
+ RAMBlock *rb;
|
||||||
|
+ void *addr;
|
||||||
|
+ int ret = -1;
|
||||||
|
+
|
||||||
|
+ trace_kvm_convert_memory(start, size, to_private ? "shared_to_private" : "private_to_shared");
|
||||||
|
+
|
||||||
|
+ if (!QEMU_PTR_IS_ALIGNED(start, qemu_real_host_page_size()) ||
|
||||||
|
+ !QEMU_PTR_IS_ALIGNED(size, qemu_real_host_page_size())) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!size) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ section = memory_region_find(get_system_memory(), start, size);
|
||||||
|
+ mr = section.mr;
|
||||||
|
+ if (!mr) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!memory_region_has_guest_memfd(mr)) {
|
||||||
|
+ error_report("Converting non guest_memfd backed memory region "
|
||||||
|
+ "(0x%"HWADDR_PRIx" ,+ 0x%"HWADDR_PRIx") to %s",
|
||||||
|
+ start, size, to_private ? "private" : "shared");
|
||||||
|
+ goto out_unref;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (to_private) {
|
||||||
|
+ ret = kvm_set_memory_attributes_private(start, size);
|
||||||
|
+ } else {
|
||||||
|
+ ret = kvm_set_memory_attributes_shared(start, size);
|
||||||
|
+ }
|
||||||
|
+ if (ret) {
|
||||||
|
+ goto out_unref;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ addr = memory_region_get_ram_ptr(mr) + section.offset_within_region;
|
||||||
|
+ rb = qemu_ram_block_from_host(addr, false, &offset);
|
||||||
|
+
|
||||||
|
+ if (to_private) {
|
||||||
|
+ if (rb->page_size != qemu_real_host_page_size()) {
|
||||||
|
+ /*
|
||||||
|
+ * shared memory is backed by hugetlb, which is supposed to be
|
||||||
|
+ * pre-allocated and doesn't need to be discarded
|
||||||
|
+ */
|
||||||
|
+ goto out_unref;
|
||||||
|
+ }
|
||||||
|
+ ret = ram_block_discard_range(rb, offset, size);
|
||||||
|
+ } else {
|
||||||
|
+ ret = ram_block_discard_guest_memfd_range(rb, offset, size);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out_unref:
|
||||||
|
+ memory_region_unref(mr);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int kvm_cpu_exec(CPUState *cpu)
|
||||||
|
{
|
||||||
|
struct kvm_run *run = cpu->kvm_run;
|
||||||
|
@@ -2967,18 +3030,20 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||||
|
ret = EXCP_INTERRUPT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
- fprintf(stderr, "error: kvm run failed %s\n",
|
||||||
|
- strerror(-run_ret));
|
||||||
|
+ if (!(run_ret == -EFAULT && run->exit_reason == KVM_EXIT_MEMORY_FAULT)) {
|
||||||
|
+ fprintf(stderr, "error: kvm run failed %s\n",
|
||||||
|
+ strerror(-run_ret));
|
||||||
|
#ifdef TARGET_PPC
|
||||||
|
- if (run_ret == -EBUSY) {
|
||||||
|
- fprintf(stderr,
|
||||||
|
- "This is probably because your SMT is enabled.\n"
|
||||||
|
- "VCPU can only run on primary threads with all "
|
||||||
|
- "secondary threads offline.\n");
|
||||||
|
- }
|
||||||
|
+ if (run_ret == -EBUSY) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "This is probably because your SMT is enabled.\n"
|
||||||
|
+ "VCPU can only run on primary threads with all "
|
||||||
|
+ "secondary threads offline.\n");
|
||||||
|
+ }
|
||||||
|
#endif
|
||||||
|
- ret = -1;
|
||||||
|
- break;
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_kvm_run_exit(cpu->cpu_index, run->exit_reason);
|
||||||
|
@@ -3061,6 +3126,19 @@ int kvm_cpu_exec(CPUState *cpu)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
+ case KVM_EXIT_MEMORY_FAULT:
|
||||||
|
+ trace_kvm_memory_fault(run->memory_fault.gpa,
|
||||||
|
+ run->memory_fault.size,
|
||||||
|
+ run->memory_fault.flags);
|
||||||
|
+ if (run->memory_fault.flags & ~KVM_MEMORY_EXIT_FLAG_PRIVATE) {
|
||||||
|
+ error_report("KVM_EXIT_MEMORY_FAULT: Unknown flag 0x%" PRIx64,
|
||||||
|
+ (uint64_t)run->memory_fault.flags);
|
||||||
|
+ ret = -1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ ret = kvm_convert_memory(run->memory_fault.gpa, run->memory_fault.size,
|
||||||
|
+ run->memory_fault.flags & KVM_MEMORY_EXIT_FLAG_PRIVATE);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
ret = kvm_arch_handle_exit(cpu, run);
|
||||||
|
break;
|
||||||
|
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
|
||||||
|
index e8c52cb9e7..681ccb667d 100644
|
||||||
|
--- a/accel/kvm/trace-events
|
||||||
|
+++ b/accel/kvm/trace-events
|
||||||
|
@@ -31,3 +31,5 @@ kvm_cpu_exec(void) ""
|
||||||
|
kvm_interrupt_exit_request(void) ""
|
||||||
|
kvm_io_window_exit(void) ""
|
||||||
|
kvm_run_exit_system_event(int cpu_index, uint32_t event_type) "cpu_index %d, system_even_type %"PRIu32
|
||||||
|
+kvm_convert_memory(uint64_t start, uint64_t size, const char *msg) "start 0x%" PRIx64 " size 0x%" PRIx64 " %s"
|
||||||
|
+kvm_memory_fault(uint64_t start, uint64_t size, uint64_t flags) "start 0x%" PRIx64 " size 0x%" PRIx64 " flags 0x%" PRIx64
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index 9e4ab7ae89..74f23dff9c 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -542,4 +542,6 @@ int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp);
|
||||||
|
int kvm_set_memory_attributes_private(hwaddr start, uint64_t size);
|
||||||
|
int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size);
|
||||||
|
|
||||||
|
+int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private);
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,56 @@
|
|||||||
|
From f9dc55dd179bb534d589af371c5c2a7886bd461e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:11 -0500
|
||||||
|
Subject: [PATCH 030/100] kvm/memory: Make memory type private by default if it
|
||||||
|
has guest memfd backend
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [30/91] 5e21edf844b5629ee32c4075843b028561b97ae2 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
KVM side leaves the memory to shared by default, which may incur the
|
||||||
|
overhead of paging conversion on the first visit of each page. Because
|
||||||
|
the expectation is that page is likely to private for the VMs that
|
||||||
|
require private memory (has guest memfd).
|
||||||
|
|
||||||
|
Explicitly set the memory to private when memory region has valid
|
||||||
|
guest memfd backend.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Message-ID: <20240320083945.991426-16-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit bd3bcf6962b664ca3bf9c60fdcc4534e8e3d0641)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 10 ++++++++++
|
||||||
|
1 file changed, 10 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 5ef55e4dd7..3f99efc8cc 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -1431,6 +1431,16 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||||
|
strerror(-err));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (memory_region_has_guest_memfd(mr)) {
|
||||||
|
+ err = kvm_set_memory_attributes_private(start_addr, slot_size);
|
||||||
|
+ if (err) {
|
||||||
|
+ error_report("%s: failed to set memory attribute private: %s",
|
||||||
|
+ __func__, strerror(-err));
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
start_addr += slot_size;
|
||||||
|
ram_start_offset += slot_size;
|
||||||
|
ram += slot_size;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,61 @@
|
|||||||
|
From aeaa7061139202448d466b7e18682081f9cd2097 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Isaku Yamahata <isaku.yamahata@intel.com>
|
||||||
|
Date: Thu, 29 Feb 2024 01:36:54 -0500
|
||||||
|
Subject: [PATCH 035/100] kvm/tdx: Don't complain when converting vMMIO region
|
||||||
|
to shared
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [35/91] c42870771d7af5badc2e10d42be9b5620d72f95d (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Because vMMIO region needs to be shared region, guest TD may explicitly
|
||||||
|
convert such region from private to shared. Don't complain such
|
||||||
|
conversion.
|
||||||
|
|
||||||
|
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240229063726.610065-34-xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit c5d9425ef4da9f43fc0903905ad415456d1ab843)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 19 ++++++++++++++++---
|
||||||
|
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 09164e346c..6efaff90a7 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -2927,9 +2927,22 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!memory_region_has_guest_memfd(mr)) {
|
||||||
|
- error_report("Converting non guest_memfd backed memory region "
|
||||||
|
- "(0x%"HWADDR_PRIx" ,+ 0x%"HWADDR_PRIx") to %s",
|
||||||
|
- start, size, to_private ? "private" : "shared");
|
||||||
|
+ /*
|
||||||
|
+ * Because vMMIO region must be shared, guest TD may convert vMMIO
|
||||||
|
+ * region to shared explicitly. Don't complain such case. See
|
||||||
|
+ * memory_region_type() for checking if the region is MMIO region.
|
||||||
|
+ */
|
||||||
|
+ if (!to_private &&
|
||||||
|
+ !memory_region_is_ram(mr) &&
|
||||||
|
+ !memory_region_is_ram_device(mr) &&
|
||||||
|
+ !memory_region_is_rom(mr) &&
|
||||||
|
+ !memory_region_is_romd(mr)) {
|
||||||
|
+ ret = 0;
|
||||||
|
+ } else {
|
||||||
|
+ error_report("Convert non guest_memfd backed memory region "
|
||||||
|
+ "(0x%"HWADDR_PRIx" ,+ 0x%"HWADDR_PRIx") to %s",
|
||||||
|
+ start, size, to_private ? "private" : "shared");
|
||||||
|
+ }
|
||||||
|
goto out_unref;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,62 @@
|
|||||||
|
From 2b2dfff3e383c99d0f759a8c12659d1a0ce50e8e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Isaku Yamahata <isaku.yamahata@intel.com>
|
||||||
|
Date: Thu, 29 Feb 2024 01:36:55 -0500
|
||||||
|
Subject: [PATCH 036/100] kvm/tdx: Ignore memory conversion to shared of
|
||||||
|
unassigned region
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [36/91] 84515b9dcfc2e07b272bb2477acf6430e9d33f28 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
TDX requires vMMIO region to be shared. For KVM, MMIO region is the region
|
||||||
|
which kvm memslot isn't assigned to (except in-kernel emulation).
|
||||||
|
qemu has the memory region for vMMIO at each device level.
|
||||||
|
|
||||||
|
While OVMF issues MapGPA(to-shared) conservatively on 32bit PCI MMIO
|
||||||
|
region, qemu doesn't find corresponding vMMIO region because it's before
|
||||||
|
PCI device allocation and memory_region_find() finds the device region, not
|
||||||
|
PCI bus region. It's safe to ignore MapGPA(to-shared) because when guest
|
||||||
|
accesses those region they use GPA with shared bit set for vMMIO. Ignore
|
||||||
|
memory conversion request of non-assigned region to shared and return
|
||||||
|
success. Otherwise OVMF is confused and panics there.
|
||||||
|
|
||||||
|
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240229063726.610065-35-xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 565f4768bb9cf840b2f8cca41483bb91aa3196a3)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 12 ++++++++++++
|
||||||
|
1 file changed, 12 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 6efaff90a7..f6268855b4 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -2923,6 +2923,18 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private)
|
||||||
|
section = memory_region_find(get_system_memory(), start, size);
|
||||||
|
mr = section.mr;
|
||||||
|
if (!mr) {
|
||||||
|
+ /*
|
||||||
|
+ * Ignore converting non-assigned region to shared.
|
||||||
|
+ *
|
||||||
|
+ * TDX requires vMMIO region to be shared to inject #VE to guest.
|
||||||
|
+ * OVMF issues conservatively MapGPA(shared) on 32bit PCI MMIO region,
|
||||||
|
+ * and vIO-APIC 0xFEC00000 4K page.
|
||||||
|
+ * OVMF assigns 32bit PCI MMIO region to
|
||||||
|
+ * [top of low memory: typically 2GB=0xC000000, 0xFC00000)
|
||||||
|
+ */
|
||||||
|
+ if (!to_private) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,189 @@
|
|||||||
|
From c3e2bc3319882c16fa36eafc7a613073746cfc8b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:14 -0500
|
||||||
|
Subject: [PATCH 052/100] linux-headers: Update to current kvm/next
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [52/91] df77e867072f60110b8387a54ba2db6226b35007 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
This updates kernel headers to commit 6f627b425378 ("KVM: SVM: Add module
|
||||||
|
parameter to enable SEV-SNP", 2024-05-12). The SNP host patches will
|
||||||
|
be included in Linux 6.11, to be released next July.
|
||||||
|
|
||||||
|
Also brings in an linux-headers/linux/vhost.h fix from v6.9-rc4.
|
||||||
|
|
||||||
|
Co-developed-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-3-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 5f69e42da5b40a2213f4db70ca461f554abca686)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
linux-headers/asm-loongarch/kvm.h | 4 +++
|
||||||
|
linux-headers/asm-riscv/kvm.h | 1 +
|
||||||
|
linux-headers/asm-x86/kvm.h | 52 ++++++++++++++++++++++++++++++-
|
||||||
|
linux-headers/linux/vhost.h | 15 ++++-----
|
||||||
|
4 files changed, 64 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/linux-headers/asm-loongarch/kvm.h b/linux-headers/asm-loongarch/kvm.h
|
||||||
|
index 109785922c..f9abef3823 100644
|
||||||
|
--- a/linux-headers/asm-loongarch/kvm.h
|
||||||
|
+++ b/linux-headers/asm-loongarch/kvm.h
|
||||||
|
@@ -17,6 +17,8 @@
|
||||||
|
#define KVM_COALESCED_MMIO_PAGE_OFFSET 1
|
||||||
|
#define KVM_DIRTY_LOG_PAGE_OFFSET 64
|
||||||
|
|
||||||
|
+#define KVM_GUESTDBG_USE_SW_BP 0x00010000
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* for KVM_GET_REGS and KVM_SET_REGS
|
||||||
|
*/
|
||||||
|
@@ -72,6 +74,8 @@ struct kvm_fpu {
|
||||||
|
|
||||||
|
#define KVM_REG_LOONGARCH_COUNTER (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 1)
|
||||||
|
#define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 2)
|
||||||
|
+/* Debugging: Special instruction for software breakpoint */
|
||||||
|
+#define KVM_REG_LOONGARCH_DEBUG_INST (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 3)
|
||||||
|
|
||||||
|
#define LOONGARCH_REG_SHIFT 3
|
||||||
|
#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT))
|
||||||
|
diff --git a/linux-headers/asm-riscv/kvm.h b/linux-headers/asm-riscv/kvm.h
|
||||||
|
index b1c503c295..e878e7cc39 100644
|
||||||
|
--- a/linux-headers/asm-riscv/kvm.h
|
||||||
|
+++ b/linux-headers/asm-riscv/kvm.h
|
||||||
|
@@ -167,6 +167,7 @@ enum KVM_RISCV_ISA_EXT_ID {
|
||||||
|
KVM_RISCV_ISA_EXT_ZFA,
|
||||||
|
KVM_RISCV_ISA_EXT_ZTSO,
|
||||||
|
KVM_RISCV_ISA_EXT_ZACAS,
|
||||||
|
+ KVM_RISCV_ISA_EXT_SSCOFPMF,
|
||||||
|
KVM_RISCV_ISA_EXT_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h
|
||||||
|
index 31c95c2dfe..1c8f918234 100644
|
||||||
|
--- a/linux-headers/asm-x86/kvm.h
|
||||||
|
+++ b/linux-headers/asm-x86/kvm.h
|
||||||
|
@@ -695,6 +695,11 @@ enum sev_cmd_id {
|
||||||
|
/* Second time is the charm; improved versions of the above ioctls. */
|
||||||
|
KVM_SEV_INIT2,
|
||||||
|
|
||||||
|
+ /* SNP-specific commands */
|
||||||
|
+ KVM_SEV_SNP_LAUNCH_START = 100,
|
||||||
|
+ KVM_SEV_SNP_LAUNCH_UPDATE,
|
||||||
|
+ KVM_SEV_SNP_LAUNCH_FINISH,
|
||||||
|
+
|
||||||
|
KVM_SEV_NR_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -709,7 +714,9 @@ struct kvm_sev_cmd {
|
||||||
|
struct kvm_sev_init {
|
||||||
|
__u64 vmsa_features;
|
||||||
|
__u32 flags;
|
||||||
|
- __u32 pad[9];
|
||||||
|
+ __u16 ghcb_version;
|
||||||
|
+ __u16 pad1;
|
||||||
|
+ __u32 pad2[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kvm_sev_launch_start {
|
||||||
|
@@ -820,6 +827,48 @@ struct kvm_sev_receive_update_data {
|
||||||
|
__u32 pad2;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct kvm_sev_snp_launch_start {
|
||||||
|
+ __u64 policy;
|
||||||
|
+ __u8 gosvw[16];
|
||||||
|
+ __u16 flags;
|
||||||
|
+ __u8 pad0[6];
|
||||||
|
+ __u64 pad1[4];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* Kept in sync with firmware values for simplicity. */
|
||||||
|
+#define KVM_SEV_SNP_PAGE_TYPE_NORMAL 0x1
|
||||||
|
+#define KVM_SEV_SNP_PAGE_TYPE_ZERO 0x3
|
||||||
|
+#define KVM_SEV_SNP_PAGE_TYPE_UNMEASURED 0x4
|
||||||
|
+#define KVM_SEV_SNP_PAGE_TYPE_SECRETS 0x5
|
||||||
|
+#define KVM_SEV_SNP_PAGE_TYPE_CPUID 0x6
|
||||||
|
+
|
||||||
|
+struct kvm_sev_snp_launch_update {
|
||||||
|
+ __u64 gfn_start;
|
||||||
|
+ __u64 uaddr;
|
||||||
|
+ __u64 len;
|
||||||
|
+ __u8 type;
|
||||||
|
+ __u8 pad0;
|
||||||
|
+ __u16 flags;
|
||||||
|
+ __u32 pad1;
|
||||||
|
+ __u64 pad2[4];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#define KVM_SEV_SNP_ID_BLOCK_SIZE 96
|
||||||
|
+#define KVM_SEV_SNP_ID_AUTH_SIZE 4096
|
||||||
|
+#define KVM_SEV_SNP_FINISH_DATA_SIZE 32
|
||||||
|
+
|
||||||
|
+struct kvm_sev_snp_launch_finish {
|
||||||
|
+ __u64 id_block_uaddr;
|
||||||
|
+ __u64 id_auth_uaddr;
|
||||||
|
+ __u8 id_block_en;
|
||||||
|
+ __u8 auth_key_en;
|
||||||
|
+ __u8 vcek_disabled;
|
||||||
|
+ __u8 host_data[KVM_SEV_SNP_FINISH_DATA_SIZE];
|
||||||
|
+ __u8 pad0[3];
|
||||||
|
+ __u16 flags;
|
||||||
|
+ __u64 pad1[4];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
|
||||||
|
#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
|
||||||
|
|
||||||
|
@@ -870,5 +919,6 @@ struct kvm_hyperv_eventfd {
|
||||||
|
#define KVM_X86_SW_PROTECTED_VM 1
|
||||||
|
#define KVM_X86_SEV_VM 2
|
||||||
|
#define KVM_X86_SEV_ES_VM 3
|
||||||
|
+#define KVM_X86_SNP_VM 4
|
||||||
|
|
||||||
|
#endif /* _ASM_X86_KVM_H */
|
||||||
|
diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h
|
||||||
|
index bea6973906..b95dd84eef 100644
|
||||||
|
--- a/linux-headers/linux/vhost.h
|
||||||
|
+++ b/linux-headers/linux/vhost.h
|
||||||
|
@@ -179,12 +179,6 @@
|
||||||
|
/* Get the config size */
|
||||||
|
#define VHOST_VDPA_GET_CONFIG_SIZE _IOR(VHOST_VIRTIO, 0x79, __u32)
|
||||||
|
|
||||||
|
-/* Get the count of all virtqueues */
|
||||||
|
-#define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32)
|
||||||
|
-
|
||||||
|
-/* Get the number of virtqueue groups. */
|
||||||
|
-#define VHOST_VDPA_GET_GROUP_NUM _IOR(VHOST_VIRTIO, 0x81, __u32)
|
||||||
|
-
|
||||||
|
/* Get the number of address spaces. */
|
||||||
|
#define VHOST_VDPA_GET_AS_NUM _IOR(VHOST_VIRTIO, 0x7A, unsigned int)
|
||||||
|
|
||||||
|
@@ -228,10 +222,17 @@
|
||||||
|
#define VHOST_VDPA_GET_VRING_DESC_GROUP _IOWR(VHOST_VIRTIO, 0x7F, \
|
||||||
|
struct vhost_vring_state)
|
||||||
|
|
||||||
|
+
|
||||||
|
+/* Get the count of all virtqueues */
|
||||||
|
+#define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32)
|
||||||
|
+
|
||||||
|
+/* Get the number of virtqueue groups. */
|
||||||
|
+#define VHOST_VDPA_GET_GROUP_NUM _IOR(VHOST_VIRTIO, 0x81, __u32)
|
||||||
|
+
|
||||||
|
/* Get the queue size of a specific virtqueue.
|
||||||
|
* userspace set the vring index in vhost_vring_state.index
|
||||||
|
* kernel set the queue size in vhost_vring_state.num
|
||||||
|
*/
|
||||||
|
-#define VHOST_VDPA_GET_VRING_SIZE _IOWR(VHOST_VIRTIO, 0x80, \
|
||||||
|
+#define VHOST_VDPA_GET_VRING_SIZE _IOWR(VHOST_VIRTIO, 0x82, \
|
||||||
|
struct vhost_vring_state)
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,71 @@
|
|||||||
|
From 9f485c8df885bcd1ff6c5692463c6168bfec07fb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Fri, 31 May 2024 13:29:53 +0200
|
||||||
|
Subject: [PATCH 054/100] machine: allow early use of
|
||||||
|
machine_require_guest_memfd
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [54/91] fd8c1a6624d5f27268215c8aa70dfc9d37bdb981 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Ask the ConfidentialGuestSupport object whether to use guest_memfd
|
||||||
|
for KVM-backend private memory. This bool can be set in instance_init
|
||||||
|
(or user_complete) so that it is available when the machine is created.
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit dc0d28ca46c0e7ee3c055ad4da24022995bd3765)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/core/machine.c | 2 +-
|
||||||
|
include/exec/confidential-guest-support.h | 5 +++++
|
||||||
|
include/hw/boards.h | 1 -
|
||||||
|
3 files changed, 6 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||||
|
index 07b994e136..2055e0d312 100644
|
||||||
|
--- a/hw/core/machine.c
|
||||||
|
+++ b/hw/core/machine.c
|
||||||
|
@@ -1482,7 +1482,7 @@ bool machine_mem_merge(MachineState *machine)
|
||||||
|
|
||||||
|
bool machine_require_guest_memfd(MachineState *machine)
|
||||||
|
{
|
||||||
|
- return machine->require_guest_memfd;
|
||||||
|
+ return machine->cgs && machine->cgs->require_guest_memfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *cpu_slot_to_string(const CPUArchId *cpu)
|
||||||
|
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||||
|
index e5b188cffb..02dc4e518f 100644
|
||||||
|
--- a/include/exec/confidential-guest-support.h
|
||||||
|
+++ b/include/exec/confidential-guest-support.h
|
||||||
|
@@ -31,6 +31,11 @@ OBJECT_DECLARE_TYPE(ConfidentialGuestSupport,
|
||||||
|
struct ConfidentialGuestSupport {
|
||||||
|
Object parent;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * True if the machine should use guest_memfd for RAM.
|
||||||
|
+ */
|
||||||
|
+ bool require_guest_memfd;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* ready: flag set by CGS initialization code once it's ready to
|
||||||
|
* start executing instructions in a potentially-secure
|
||||||
|
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||||
|
index 815a1c4b26..0d1f9533ef 100644
|
||||||
|
--- a/include/hw/boards.h
|
||||||
|
+++ b/include/hw/boards.h
|
||||||
|
@@ -373,7 +373,6 @@ struct MachineState {
|
||||||
|
char *dt_compatible;
|
||||||
|
bool dump_guest_core;
|
||||||
|
bool mem_merge;
|
||||||
|
- bool require_guest_memfd;
|
||||||
|
bool usb;
|
||||||
|
bool usb_disabled;
|
||||||
|
char *firmware;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
From 331c58d87dde8b4757e1d1e09d9b16bac2952d22 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:15 -0500
|
||||||
|
Subject: [PATCH 081/100] memory: Introduce
|
||||||
|
memory_region_init_ram_guest_memfd()
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [81/91] d5b0898d791f3f90d1acda0230f96ca9bf5be5e4 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Introduce memory_region_init_ram_guest_memfd() to allocate private
|
||||||
|
guset memfd on the MemoryRegion initialization. It's for the use case of
|
||||||
|
TDVF, which must be private on TDX case.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-4-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a0aa6db7ce72a08703774107185e639e73e7754c)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
include/exec/memory.h | 6 ++++++
|
||||||
|
system/memory.c | 24 ++++++++++++++++++++++++
|
||||||
|
2 files changed, 30 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/include/exec/memory.h b/include/exec/memory.h
|
||||||
|
index 679a847685..1e351f6fc8 100644
|
||||||
|
--- a/include/exec/memory.h
|
||||||
|
+++ b/include/exec/memory.h
|
||||||
|
@@ -1603,6 +1603,12 @@ bool memory_region_init_ram(MemoryRegion *mr,
|
||||||
|
uint64_t size,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
+bool memory_region_init_ram_guest_memfd(MemoryRegion *mr,
|
||||||
|
+ Object *owner,
|
||||||
|
+ const char *name,
|
||||||
|
+ uint64_t size,
|
||||||
|
+ Error **errp);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* memory_region_init_rom: Initialize a ROM memory region.
|
||||||
|
*
|
||||||
|
diff --git a/system/memory.c b/system/memory.c
|
||||||
|
index c756950c0c..b09065eef3 100644
|
||||||
|
--- a/system/memory.c
|
||||||
|
+++ b/system/memory.c
|
||||||
|
@@ -3606,6 +3606,30 @@ bool memory_region_init_ram(MemoryRegion *mr,
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool memory_region_init_ram_guest_memfd(MemoryRegion *mr,
|
||||||
|
+ Object *owner,
|
||||||
|
+ const char *name,
|
||||||
|
+ uint64_t size,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ DeviceState *owner_dev;
|
||||||
|
+
|
||||||
|
+ if (!memory_region_init_ram_flags_nomigrate(mr, owner, name, size,
|
||||||
|
+ RAM_GUEST_MEMFD, errp)) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ /* This will assert if owner is neither NULL nor a DeviceState.
|
||||||
|
+ * We only want the owner here for the purposes of defining a
|
||||||
|
+ * unique name for migration. TODO: Ideally we should implement
|
||||||
|
+ * a naming scheme for Objects which are not DeviceStates, in
|
||||||
|
+ * which case we can relax this restriction.
|
||||||
|
+ */
|
||||||
|
+ owner_dev = DEVICE(owner);
|
||||||
|
+ vmstate_register_ram(mr, owner_dev);
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool memory_region_init_rom(MemoryRegion *mr,
|
||||||
|
Object *owner,
|
||||||
|
const char *name,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue