Compare commits
No commits in common. 'c9' and 'i10-beta' have entirely different histories.
@ -1 +1 @@
|
||||
SOURCES/qemu-9.0.0.tar.xz
|
||||
SOURCES/qemu-9.1.0.tar.xz
|
||||
|
@ -1 +1 @@
|
||||
6699bb03d6da21159b89668bca01c6c958b95d07 SOURCES/qemu-9.0.0.tar.xz
|
||||
d5bcdca53341c29470ef323191a3388fdb0571ed SOURCES/qemu-9.1.0.tar.xz
|
||||
|
@ -1,496 +0,0 @@
|
||||
From cf398296f3fcee185a00f23de5deae57c97d648e Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
Date: Fri, 19 Oct 2018 12:53:31 +0200
|
||||
Subject: Add aarch64 machine types
|
||||
|
||||
Adding changes to add RHEL machine types for aarch64 architecture.
|
||||
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
---
|
||||
Rebase notes (6.1.0):
|
||||
- Use CONFIG_TPM check when using TPM structures
|
||||
- Add support for default_bus_bypass_iommu
|
||||
- ea4c0b32d9 arm/virt: Register highmem and gic-version as class properties
|
||||
- 895e1fa86a hw/arm/virt: Add 8.5 and 9.0 machine types and remove older ones
|
||||
|
||||
Rebase notes (7.0.0):
|
||||
- Added dtb-kaslr-seed option
|
||||
- Set no_tcg_lpa2 to true
|
||||
|
||||
Rebase notes (7.1.0):
|
||||
- replace dtb_kaslr_seed by dtb_randomness
|
||||
- Updated dtb_randomness comment
|
||||
|
||||
Rebase notes (7.2.0):
|
||||
- Disabled cortex-a35
|
||||
|
||||
Rebase notes (8.0.0):
|
||||
- Moved changed code from target/arm/helper.c to target/arm/arm-qmp-cmds.c
|
||||
|
||||
Rebase notes (8.1.0):
|
||||
- Added setting default_nic
|
||||
|
||||
Rebase notes (9.0.0 rc0):
|
||||
- call arm_virt_compat_set on rhel type class_init
|
||||
|
||||
Merged patches (6.2.0):
|
||||
- 9a3d4fde0e hw/arm/virt: Remove 9.0 machine type
|
||||
- f7d04d6695 hw: arm: virt: Add hw_compat_rhel_8_5 to 8.5 machine type
|
||||
|
||||
Merged patches (7.0.0):
|
||||
- 3b82be3dd3 redhat: virt-rhel8.5.0: Update machine type compatibility for QEMU 6.2.0 update
|
||||
- c354a86c9b hw/arm/virt: Register "iommu" as a class property
|
||||
- c1a2630dc9 hw/arm/virt: Register "its" as a class property
|
||||
- 9d8c61dc93 hw/arm/virt: Rename default_bus_bypass_iommu
|
||||
- a1d1b6eeb6 hw/arm/virt: Expose the 'RAS' option
|
||||
- 47f8fe1b82 hw/arm/virt: Add 9.0 machine type and remove 8.5 one
|
||||
- ed2346788f hw/arm/virt: Check no_tcg_its and minor style changes
|
||||
|
||||
Merged patches (7.0.0):
|
||||
- f79b31bdef hw/arm/virt: Remove the dtb-kaslr-seed machine option
|
||||
- b6fca85f4a hw/arm/virt: Fix missing initialization in instance/class_init()
|
||||
|
||||
Merged patches (7.1.0):
|
||||
- ac97dd4f9f RHEL-only: AArch64: Drop unsupported CPU types
|
||||
- e9c0a70664 target/arm: deprecate named CPU models
|
||||
|
||||
Merged patches (7.2.0):
|
||||
- 0be2889fa2 Introduce upstream 7.0 compat changes (only applicable parts)
|
||||
|
||||
Merged patches (8.0.0):
|
||||
- c1a21266d8 redhat: aarch64: add rhel9.2.0 virt machine type
|
||||
- d97cd7c513 redhat: fix virt-rhel9.2.0 compat props
|
||||
|
||||
Merged patches (8.1.0):
|
||||
- bd5d81d286 Add RHEL 9.2.0 compat structure (arm part)
|
||||
- c07f666086 hw/arm/virt: Validate cluster and NUMA node boundary for RHEL machines
|
||||
|
||||
Merged patches (8.2.0):
|
||||
- 4ee284aca9 Add machine types compat bits. (partial)
|
||||
|
||||
Merged patches (9.0.0 rc0):
|
||||
- 117068376a hw/arm/virt: Fix compats
|
||||
- 8bcccfabc4 hw/arm/virt: Add properties to disable high memory regions
|
||||
- 0005a8b93a hw/arm/virt: deprecate virt-rhel9.{0,2}.0 machine types
|
||||
---
|
||||
hw/arm/virt.c | 299 +++++++++++++++++++++++++++++++++++++++++-
|
||||
include/hw/arm/virt.h | 8 ++
|
||||
2 files changed, 306 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 36e9b4b4e9..22bc345137 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -101,6 +101,7 @@ 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) \
|
||||
@@ -128,7 +129,63 @@ static void arm_virt_compat_set(MachineClass *mc)
|
||||
DEFINE_VIRT_MACHINE_LATEST(major, minor, true)
|
||||
#define DEFINE_VIRT_MACHINE(major, minor) \
|
||||
DEFINE_VIRT_MACHINE_LATEST(major, minor, false)
|
||||
+#endif /* disabled for RHEL */
|
||||
+
|
||||
+/*
|
||||
+ * This variable is for changes to properties that are RHEL specific,
|
||||
+ * different to the current upstream and to be applied to the latest
|
||||
+ * machine type. They may be overriden by older machine compats.
|
||||
+ *
|
||||
+ * virtio-net-pci variant romfiles are not needed because edk2 does
|
||||
+ * fully support the pxe boot. Besides virtio romfiles are not shipped
|
||||
+ * on rhel/aarch64.
|
||||
+ */
|
||||
+GlobalProperty arm_rhel_compat[] = {
|
||||
+ {"virtio-net-pci", "romfile", "" },
|
||||
+ {"virtio-net-pci-transitional", "romfile", "" },
|
||||
+ {"virtio-net-pci-non-transitional", "romfile", "" },
|
||||
+};
|
||||
+const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat);
|
||||
|
||||
+/*
|
||||
+ * This cannot be called from the rhel_virt_class_init() because
|
||||
+ * TYPE_RHEL_MACHINE is abstract and mc->compat_props g_ptr_array_new()
|
||||
+ * only is called on virt-rhelm.n.s non abstract class init.
|
||||
+ */
|
||||
+static void arm_rhel_compat_set(MachineClass *mc)
|
||||
+{
|
||||
+ compat_props_add(mc->compat_props, arm_rhel_compat,
|
||||
+ arm_rhel_compat_len);
|
||||
+}
|
||||
+
|
||||
+#define DEFINE_RHEL_MACHINE_LATEST(m, n, s, latest) \
|
||||
+ static void rhel##m##n##s##_virt_class_init(ObjectClass *oc, \
|
||||
+ void *data) \
|
||||
+ { \
|
||||
+ MachineClass *mc = MACHINE_CLASS(oc); \
|
||||
+ arm_rhel_compat_set(mc); \
|
||||
+ rhel##m##n##s##_virt_options(mc); \
|
||||
+ mc->desc = "RHEL " # m "." # n "." # s " ARM Virtual Machine"; \
|
||||
+ if (latest) { \
|
||||
+ mc->alias = "virt"; \
|
||||
+ mc->is_default = 1; \
|
||||
+ } \
|
||||
+ } \
|
||||
+ static const TypeInfo rhel##m##n##s##_machvirt_info = { \
|
||||
+ .name = MACHINE_TYPE_NAME("virt-rhel" # m "." # n "." # s), \
|
||||
+ .parent = TYPE_RHEL_MACHINE, \
|
||||
+ .class_init = rhel##m##n##s##_virt_class_init, \
|
||||
+ }; \
|
||||
+ static void rhel##m##n##s##_machvirt_init(void) \
|
||||
+ { \
|
||||
+ type_register_static(&rhel##m##n##s##_machvirt_info); \
|
||||
+ } \
|
||||
+ type_init(rhel##m##n##s##_machvirt_init);
|
||||
+
|
||||
+#define DEFINE_RHEL_MACHINE_AS_LATEST(major, minor, subminor) \
|
||||
+ DEFINE_RHEL_MACHINE_LATEST(major, minor, subminor, true)
|
||||
+#define DEFINE_RHEL_MACHINE(major, minor, subminor) \
|
||||
+ DEFINE_RHEL_MACHINE_LATEST(major, minor, subminor, false)
|
||||
|
||||
/* Number of external interrupt lines to configure the GIC with */
|
||||
#define NUM_IRQS 256
|
||||
@@ -2355,6 +2412,7 @@ static void machvirt_init(MachineState *machine)
|
||||
qemu_add_machine_init_done_notifier(&vms->machine_done);
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_secure(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2382,6 +2440,7 @@ static void virt_set_virt(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->virt = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static bool virt_get_highmem(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -2397,6 +2456,7 @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
|
||||
vms->highmem = value;
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_compact_highmem(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2410,6 +2470,7 @@ static void virt_set_compact_highmem(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->highmem_compact = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static bool virt_get_highmem_redists(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -2453,7 +2514,6 @@ static void virt_set_highmem_mmio(Object *obj, bool value, Error **errp)
|
||||
vms->highmem_mmio = value;
|
||||
}
|
||||
|
||||
-
|
||||
static bool virt_get_its(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2468,6 +2528,7 @@ static void virt_set_its(Object *obj, bool value, Error **errp)
|
||||
vms->its = value;
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_dtb_randomness(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2481,6 +2542,7 @@ static void virt_set_dtb_randomness(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->dtb_randomness = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static char *virt_get_oem_id(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -2564,6 +2626,7 @@ static void virt_set_ras(Object *obj, bool value, Error **errp)
|
||||
vms->ras = value;
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_mte(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2577,6 +2640,7 @@ static void virt_set_mte(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->mte = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static char *virt_get_gic_version(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -2949,6 +3013,7 @@ static int virt_kvm_type(MachineState *ms, const char *type_str)
|
||||
return fixed_ipa ? 0 : requested_pa_size;
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
@@ -3463,3 +3528,235 @@ static void virt_machine_2_6_options(MachineClass *mc)
|
||||
vmc->no_pmu = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 6)
|
||||
+#endif /* disabled for RHEL */
|
||||
+
|
||||
+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;
|
||||
+ /* Maximum supported VCPU count for all virt-rhel* machines */
|
||||
+ mc->max_cpus = 384;
|
||||
+#ifdef CONFIG_TPM
|
||||
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
|
||||
+#endif
|
||||
+ mc->block_default_type = IF_VIRTIO;
|
||||
+ mc->no_cdrom = 1;
|
||||
+ mc->pci_allow_0_address = true;
|
||||
+ /* We know we will never create a pre-ARMv7 CPU which needs 1K pages */
|
||||
+ mc->minimum_page_bits = 12;
|
||||
+ mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
|
||||
+ mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
|
||||
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
|
||||
+ mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
|
||||
+ mc->kvm_type = virt_kvm_type;
|
||||
+ assert(!mc->get_hotplug_handler);
|
||||
+ mc->get_hotplug_handler = virt_machine_get_hotplug_handler;
|
||||
+ hc->pre_plug = virt_machine_device_pre_plug_cb;
|
||||
+ hc->plug = virt_machine_device_plug_cb;
|
||||
+ hc->unplug_request = virt_machine_device_unplug_request_cb;
|
||||
+ hc->unplug = virt_machine_device_unplug_cb;
|
||||
+ mc->nvdimm_supported = true;
|
||||
+ mc->smp_props.clusters_supported = true;
|
||||
+ mc->auto_enable_numa_with_memhp = true;
|
||||
+ mc->auto_enable_numa_with_memdev = true;
|
||||
+ /* platform instead of architectural choice */
|
||||
+ mc->cpu_cluster_has_numa_boundary = true;
|
||||
+ mc->default_ram_id = "mach-virt.ram";
|
||||
+ mc->default_nic = "virtio-net-pci";
|
||||
+
|
||||
+ object_class_property_add(oc, "acpi", "OnOffAuto",
|
||||
+ virt_get_acpi, virt_set_acpi,
|
||||
+ NULL, NULL);
|
||||
+ object_class_property_set_description(oc, "acpi",
|
||||
+ "Enable ACPI");
|
||||
+
|
||||
+ object_class_property_add_bool(oc, "highmem", virt_get_highmem,
|
||||
+ virt_set_highmem);
|
||||
+ object_class_property_set_description(oc, "highmem",
|
||||
+ "Set on/off to enable/disable using "
|
||||
+ "physical address space above 32 bits");
|
||||
+
|
||||
+ object_class_property_add_bool(oc, "highmem-redists",
|
||||
+ virt_get_highmem_redists,
|
||||
+ virt_set_highmem_redists);
|
||||
+ object_class_property_set_description(oc, "highmem-redists",
|
||||
+ "Set on/off to enable/disable high "
|
||||
+ "memory region for GICv3 or GICv4 "
|
||||
+ "redistributor");
|
||||
+
|
||||
+ object_class_property_add_bool(oc, "highmem-ecam",
|
||||
+ virt_get_highmem_ecam,
|
||||
+ virt_set_highmem_ecam);
|
||||
+ object_class_property_set_description(oc, "highmem-ecam",
|
||||
+ "Set on/off to enable/disable high "
|
||||
+ "memory region for PCI ECAM");
|
||||
+
|
||||
+ object_class_property_add_bool(oc, "highmem-mmio",
|
||||
+ virt_get_highmem_mmio,
|
||||
+ virt_set_highmem_mmio);
|
||||
+ object_class_property_set_description(oc, "highmem-mmio",
|
||||
+ "Set on/off to enable/disable high "
|
||||
+ "memory region for PCI MMIO");
|
||||
+
|
||||
+ object_class_property_add_str(oc, "gic-version", virt_get_gic_version,
|
||||
+ virt_set_gic_version);
|
||||
+ object_class_property_set_description(oc, "gic-version",
|
||||
+ "Set GIC version. "
|
||||
+ "Valid values are 2, 3, host and max");
|
||||
+
|
||||
+ object_class_property_add_str(oc, "iommu", virt_get_iommu, virt_set_iommu);
|
||||
+ object_class_property_set_description(oc, "iommu",
|
||||
+ "Set the IOMMU type. "
|
||||
+ "Valid values are none and smmuv3");
|
||||
+
|
||||
+ object_class_property_add_bool(oc, "default-bus-bypass-iommu",
|
||||
+ virt_get_default_bus_bypass_iommu,
|
||||
+ virt_set_default_bus_bypass_iommu);
|
||||
+ object_class_property_set_description(oc, "default-bus-bypass-iommu",
|
||||
+ "Set on/off to enable/disable "
|
||||
+ "bypass_iommu for default root bus");
|
||||
+
|
||||
+ object_class_property_add_bool(oc, "ras", virt_get_ras,
|
||||
+ virt_set_ras);
|
||||
+ object_class_property_set_description(oc, "ras",
|
||||
+ "Set on/off to enable/disable reporting host memory errors "
|
||||
+ "to a KVM guest using ACPI and guest external abort exceptions");
|
||||
+
|
||||
+ object_class_property_add_bool(oc, "its", virt_get_its,
|
||||
+ virt_set_its);
|
||||
+ object_class_property_set_description(oc, "its",
|
||||
+ "Set on/off to enable/disable "
|
||||
+ "ITS instantiation");
|
||||
+
|
||||
+ object_class_property_add_str(oc, "x-oem-id",
|
||||
+ virt_get_oem_id,
|
||||
+ virt_set_oem_id);
|
||||
+ object_class_property_set_description(oc, "x-oem-id",
|
||||
+ "Override the default value of field OEMID "
|
||||
+ "in ACPI table header."
|
||||
+ "The string may be up to 6 bytes in size");
|
||||
+
|
||||
+
|
||||
+ object_class_property_add_str(oc, "x-oem-table-id",
|
||||
+ virt_get_oem_table_id,
|
||||
+ virt_set_oem_table_id);
|
||||
+ object_class_property_set_description(oc, "x-oem-table-id",
|
||||
+ "Override the default value of field OEM Table ID "
|
||||
+ "in ACPI table header."
|
||||
+ "The string may be up to 8 bytes in size");
|
||||
+}
|
||||
+
|
||||
+static void rhel_virt_instance_init(Object *obj)
|
||||
+{
|
||||
+ VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
+ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
|
||||
+
|
||||
+ /* EL3 is disabled by default and non-configurable for RHEL */
|
||||
+ vms->secure = false;
|
||||
+
|
||||
+ /* EL2 is disabled by default and non-configurable for RHEL */
|
||||
+ vms->virt = false;
|
||||
+
|
||||
+ /* High memory is enabled by default */
|
||||
+ vms->highmem = true;
|
||||
+ vms->highmem_compact = !vmc->no_highmem_compact;
|
||||
+ vms->gic_version = VIRT_GIC_VERSION_NOSEL;
|
||||
+
|
||||
+ vms->highmem_ecam = !vmc->no_highmem_ecam;
|
||||
+ vms->highmem_mmio = true;
|
||||
+ vms->highmem_redists = true;
|
||||
+
|
||||
+ if (vmc->no_its) {
|
||||
+ vms->its = false;
|
||||
+ } else {
|
||||
+ /* Default allows ITS instantiation */
|
||||
+ vms->its = true;
|
||||
+
|
||||
+ if (vmc->no_tcg_its) {
|
||||
+ vms->tcg_its = false;
|
||||
+ } else {
|
||||
+ vms->tcg_its = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Default disallows iommu instantiation */
|
||||
+ vms->iommu = VIRT_IOMMU_NONE;
|
||||
+
|
||||
+ /* The default root bus is attached to iommu by default */
|
||||
+ vms->default_bus_bypass_iommu = false;
|
||||
+
|
||||
+ /* Default disallows RAS instantiation and is non-configurable for RHEL */
|
||||
+ vms->ras = false;
|
||||
+
|
||||
+ /* MTE is disabled by default and non-configurable for RHEL */
|
||||
+ vms->mte = false;
|
||||
+
|
||||
+ /* Supply kaslr-seed and rng-seed by default, non-configurable for RHEL */
|
||||
+ vms->dtb_randomness = true;
|
||||
+
|
||||
+ vms->irqmap = a15irqmap;
|
||||
+
|
||||
+ virt_flash_create(vms);
|
||||
+
|
||||
+ vms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
|
||||
+ vms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
|
||||
+}
|
||||
+
|
||||
+static const TypeInfo rhel_machine_info = {
|
||||
+ .name = TYPE_RHEL_MACHINE,
|
||||
+ .parent = TYPE_MACHINE,
|
||||
+ .abstract = true,
|
||||
+ .instance_size = sizeof(VirtMachineState),
|
||||
+ .class_size = sizeof(VirtMachineClass),
|
||||
+ .class_init = rhel_machine_class_init,
|
||||
+ .instance_init = rhel_virt_instance_init,
|
||||
+ .interfaces = (InterfaceInfo[]) {
|
||||
+ { TYPE_HOTPLUG_HANDLER },
|
||||
+ { }
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void rhel_machine_init(void)
|
||||
+{
|
||||
+ type_register_static(&rhel_machine_info);
|
||||
+}
|
||||
+type_init(rhel_machine_init);
|
||||
+
|
||||
+static void rhel940_virt_options(MachineClass *mc)
|
||||
+{
|
||||
+}
|
||||
+DEFINE_RHEL_MACHINE_AS_LATEST(9, 4, 0)
|
||||
+
|
||||
+static void rhel920_virt_options(MachineClass *mc)
|
||||
+{
|
||||
+ rhel940_virt_options(mc);
|
||||
+
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_4, hw_compat_rhel_9_4_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_3, hw_compat_rhel_9_3_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_2, hw_compat_rhel_9_2_len);
|
||||
+
|
||||
+ /* RHEL 9.4 is the first supported release */
|
||||
+ mc->deprecation_reason =
|
||||
+ "machine types for versions prior to 9.4 are deprecated";
|
||||
+}
|
||||
+DEFINE_RHEL_MACHINE(9, 2, 0)
|
||||
+
|
||||
+static void rhel900_virt_options(MachineClass *mc)
|
||||
+{
|
||||
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
+
|
||||
+ rhel920_virt_options(mc);
|
||||
+
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_1, hw_compat_rhel_9_1_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_0, hw_compat_rhel_9_0_len);
|
||||
+
|
||||
+ /* Disable FEAT_LPA2 since old kernels (<= v5.12) don't boot with that feature */
|
||||
+ vmc->no_tcg_lpa2 = true;
|
||||
+ /* Compact layout for high memory regions was introduced with 9.2.0 */
|
||||
+ vmc->no_highmem_compact = true;
|
||||
+}
|
||||
+DEFINE_RHEL_MACHINE(9, 0, 0)
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index bb486d36b1..237fc77bda 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -179,9 +179,17 @@ struct VirtMachineState {
|
||||
|
||||
#define VIRT_ECAM_ID(high) (high ? VIRT_HIGH_PCIE_ECAM : VIRT_PCIE_ECAM)
|
||||
|
||||
+#if 0 /* disabled for Red Hat Enterprise Linux */
|
||||
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
|
||||
OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)
|
||||
|
||||
+#else
|
||||
+#define TYPE_RHEL_MACHINE MACHINE_TYPE_NAME("virt-rhel")
|
||||
+typedef struct VirtMachineClass VirtMachineClass;
|
||||
+typedef struct VirtMachineState VirtMachineState;
|
||||
+DECLARE_OBJ_CHECKERS(VirtMachineState, VirtMachineClass, VIRT_MACHINE, TYPE_RHEL_MACHINE)
|
||||
+#endif
|
||||
+
|
||||
void virt_acpi_setup(VirtMachineState *vms);
|
||||
bool virt_is_acpi_enabled(VirtMachineState *vms);
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,36 @@
|
||||
From 16946c2c7be0ae23dc1f267323cfc7630a1c9e87 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 3 Jul 2024 13:32:32 +0100
|
||||
Subject: meson: temporarily disable -Wunused-function
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Deleting the upstream versioned machine types will leave some functions
|
||||
unused until RHEL machine types are added once again. Temporarily
|
||||
disable the -Wunused-function warning to preserve bisectability with
|
||||
fine grained patch splits.
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
|
||||
Rebase notes (9.1.0 rc0)
|
||||
- New patch
|
||||
---
|
||||
meson.build | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index fbda17c987..161d496d55 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -651,6 +651,7 @@ warn_flags = [
|
||||
'-Wno-string-plus-int',
|
||||
'-Wno-tautological-type-limit-compare',
|
||||
'-Wno-typedef-redefinition',
|
||||
+ '-Wno-unused-function',
|
||||
]
|
||||
|
||||
if host_os != 'darwin'
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,544 +0,0 @@
|
||||
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
|
||||
|
@ -0,0 +1,101 @@
|
||||
From 2f0ba1a1ed66a8ae32e7a92f3d3b744d8b59b879 Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
Date: Wed, 10 Jul 2024 02:25:51 -0400
|
||||
Subject: Remove upstream machine types for aarch64, s390x and x86_64
|
||||
architectures
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We will replace upstream machine types on supported architectures with RHEL
|
||||
machine types.
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
|
||||
Rebase notes (9.1.0 rc0):
|
||||
- Split off commits adding RHEL machine types
|
||||
---
|
||||
hw/arm/virt.c | 2 ++
|
||||
hw/i386/pc_piix.c | 2 ++
|
||||
hw/i386/pc_q35.c | 2 ++
|
||||
hw/s390x/s390-virtio-ccw.c | 2 ++
|
||||
4 files changed, 8 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index b2aa3f1355..5396e7cb24 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3306,6 +3306,7 @@ static void machvirt_machine_init(void)
|
||||
}
|
||||
type_init(machvirt_machine_init);
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static void virt_machine_9_1_options(MachineClass *mc)
|
||||
{
|
||||
}
|
||||
@@ -3552,3 +3553,4 @@ static void virt_machine_2_6_options(MachineClass *mc)
|
||||
vmc->no_pmu = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 6)
|
||||
+#endif /* disabled for RHEL */
|
||||
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||
index 347afa4c37..67107b174a 100644
|
||||
--- a/hw/i386/pc_piix.c
|
||||
+++ b/hw/i386/pc_piix.c
|
||||
@@ -448,6 +448,7 @@ static void pc_i440fx_init(MachineState *machine)
|
||||
#define DEFINE_I440FX_MACHINE(major, minor) \
|
||||
DEFINE_PC_VER_MACHINE(pc_i440fx, "pc-i440fx", pc_i440fx_init, major, minor);
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static void pc_i440fx_machine_options(MachineClass *m)
|
||||
{
|
||||
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||
@@ -775,6 +776,7 @@ static void pc_i440fx_machine_2_4_options(MachineClass *m)
|
||||
}
|
||||
|
||||
DEFINE_I440FX_MACHINE(2, 4);
|
||||
+#endif /* Disabled for Red Hat Enterprise Linux */
|
||||
|
||||
#ifdef CONFIG_ISAPC
|
||||
static void isapc_machine_options(MachineClass *m)
|
||||
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||
index f2d8edfa84..5fb283f2df 100644
|
||||
--- a/hw/i386/pc_q35.c
|
||||
+++ b/hw/i386/pc_q35.c
|
||||
@@ -356,6 +356,7 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||
pc_q35_compat_defaults, pc_q35_compat_defaults_len);
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static void pc_q35_machine_9_1_options(MachineClass *m)
|
||||
{
|
||||
pc_q35_machine_options(m);
|
||||
@@ -668,3 +669,4 @@ static void pc_q35_machine_2_4_options(MachineClass *m)
|
||||
}
|
||||
|
||||
DEFINE_Q35_MACHINE(2, 4);
|
||||
+#endif /* Disabled for Red Hat Enterprise Linux */
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index c483ff8064..86bfc9d2eb 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -871,6 +871,7 @@ static const TypeInfo ccw_machine_info = {
|
||||
DEFINE_CCW_MACHINE_IMPL(false, major, minor)
|
||||
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static void ccw_machine_9_1_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
@@ -1305,6 +1306,7 @@ static void ccw_machine_2_4_class_options(MachineClass *mc)
|
||||
DEFINE_CCW_MACHINE(2, 4);
|
||||
|
||||
#endif
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static void ccw_machine_register_types(void)
|
||||
{
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,197 @@
|
||||
From ccb1eaa95ce9c92a196fe034c033502f582a324b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 3 Jul 2024 15:27:03 +0100
|
||||
Subject: Adapt versioned machine type macros for RHEL
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The versioned machine type macros are changed thus:
|
||||
|
||||
* All symbol names get 'rhel' inserted eg 'virt_rhel_macine_9_4_0_<blah>'
|
||||
* All machine type names get 'rhel' inserted eg 'virt-rhel9.4.0-machine'
|
||||
* Lifecycle is changed to deprecate after 1 major RHEL release,
|
||||
force non-registration (effectively deletion) after 2 major releases
|
||||
* Custom message to explain RHEL deprecation/deletion policy
|
||||
* Remove upstream logic that temporarily disabled deletion since
|
||||
the upstream constraints in this area don't apply to RHEL
|
||||
* For automatic deprecation/deletion, RHEL_VERSION is defined
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
---
|
||||
.distro/Makefile | 2 +-
|
||||
.distro/Makefile.common | 1 +
|
||||
.distro/qemu-kvm.spec.template | 1 +
|
||||
.distro/scripts/process-patches.sh | 3 ++
|
||||
include/hw/boards.h | 60 ++++++++++--------------------
|
||||
meson.build | 1 +
|
||||
meson_options.txt | 2 +
|
||||
scripts/meson-buildoptions.sh | 2 +
|
||||
8 files changed, 30 insertions(+), 42 deletions(-)
|
||||
|
||||
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||
index ccfc3e10eb..7f7eb4ec40 100644
|
||||
--- a/include/hw/boards.h
|
||||
+++ b/include/hw/boards.h
|
||||
@@ -548,16 +548,16 @@ struct MachineState {
|
||||
* "{prefix}-{major}.{minor}.{micro}-{tag}"
|
||||
*/
|
||||
#define _MACHINE_VER_TYPE_NAME2(prefix, major, minor) \
|
||||
- prefix "-" #major "." #minor TYPE_MACHINE_SUFFIX
|
||||
+ prefix "-rhel" #major "." #minor TYPE_MACHINE_SUFFIX
|
||||
|
||||
#define _MACHINE_VER_TYPE_NAME3(prefix, major, minor, micro) \
|
||||
- prefix "-" #major "." #minor "." #micro TYPE_MACHINE_SUFFIX
|
||||
+ prefix "-rhel" #major "." #minor "." #micro TYPE_MACHINE_SUFFIX
|
||||
|
||||
#define _MACHINE_VER_TYPE_NAME4(prefix, major, minor, _unused_, tag) \
|
||||
- prefix "-" #major "." #minor "-" #tag TYPE_MACHINE_SUFFIX
|
||||
+ prefix "-rhel" #major "." #minor "-" #tag TYPE_MACHINE_SUFFIX
|
||||
|
||||
#define _MACHINE_VER_TYPE_NAME5(prefix, major, minor, micro, _unused_, tag) \
|
||||
- prefix "-" #major "." #minor "." #micro "-" #tag TYPE_MACHINE_SUFFIX
|
||||
+ prefix "-rhel" #major "." #minor "." #micro "-" #tag TYPE_MACHINE_SUFFIX
|
||||
|
||||
#define MACHINE_VER_TYPE_NAME(prefix, ...) \
|
||||
_MACHINE_VER_PICK(__VA_ARGS__, \
|
||||
@@ -585,16 +585,16 @@ struct MachineState {
|
||||
* {prefix}_machine_{major}_{minor}_{micro}_{tag}_{sym}
|
||||
*/
|
||||
#define _MACHINE_VER_SYM2(sym, prefix, major, minor) \
|
||||
- prefix ## _machine_ ## major ## _ ## minor ## _ ## sym
|
||||
+ prefix ## _rhel_machine_ ## major ## _ ## minor ## _ ## sym
|
||||
|
||||
#define _MACHINE_VER_SYM3(sym, prefix, major, minor, micro) \
|
||||
- prefix ## _machine_ ## major ## _ ## minor ## _ ## micro ## _ ## sym
|
||||
+ prefix ## _rhel_machine_ ## major ## _ ## minor ## _ ## micro ## _ ## sym
|
||||
|
||||
#define _MACHINE_VER_SYM4(sym, prefix, major, minor, _unused_, tag) \
|
||||
- prefix ## _machine_ ## major ## _ ## minor ## _ ## tag ## _ ## sym
|
||||
+ prefix ## _rhel_machine_ ## major ## _ ## minor ## _ ## tag ## _ ## sym
|
||||
|
||||
#define _MACHINE_VER_SYM5(sym, prefix, major, minor, micro, _unused_, tag) \
|
||||
- prefix ## _machine_ ## major ## _ ## minor ## _ ## micro ## _ ## tag ## _ ## sym
|
||||
+ prefix ## _rhel_machine_ ## major ## _ ## minor ## _ ## micro ## _ ## tag ## _ ## sym
|
||||
|
||||
#define MACHINE_VER_SYM(sym, prefix, ...) \
|
||||
_MACHINE_VER_PICK(__VA_ARGS__, \
|
||||
@@ -605,26 +605,22 @@ struct MachineState {
|
||||
|
||||
|
||||
/*
|
||||
- * How many years/major releases for each phase
|
||||
- * of the life cycle. Assumes use of versioning
|
||||
- * scheme where major is bumped each year
|
||||
+ * How many RHEL major releases for each phase
|
||||
+ * of the life cycle.
|
||||
*/
|
||||
-#define MACHINE_VER_DELETION_MAJOR 6
|
||||
-#define MACHINE_VER_DEPRECATION_MAJOR 3
|
||||
+#define MACHINE_VER_DELETION_MAJOR 2
|
||||
+#define MACHINE_VER_DEPRECATION_MAJOR 1
|
||||
|
||||
/*
|
||||
* Expands to a static string containing a deprecation
|
||||
* message for a versioned machine type
|
||||
*/
|
||||
#define MACHINE_VER_DEPRECATION_MSG \
|
||||
- "machines more than " stringify(MACHINE_VER_DEPRECATION_MAJOR) \
|
||||
- " years old are subject to deletion after " \
|
||||
- stringify(MACHINE_VER_DELETION_MAJOR) " years"
|
||||
+ "machines from the previous RHEL major release are " \
|
||||
+ "subject to deletion in the next RHEL major release"
|
||||
|
||||
#define _MACHINE_VER_IS_EXPIRED_IMPL(cutoff, major, minor) \
|
||||
- (((QEMU_VERSION_MAJOR - major) > cutoff) || \
|
||||
- (((QEMU_VERSION_MAJOR - major) == cutoff) && \
|
||||
- (QEMU_VERSION_MINOR - minor) >= 0))
|
||||
+ ((RHEL_VERSION - major) >= cutoff)
|
||||
|
||||
#define _MACHINE_VER_IS_EXPIRED2(cutoff, major, minor) \
|
||||
_MACHINE_VER_IS_EXPIRED_IMPL(cutoff, major, minor)
|
||||
@@ -686,32 +682,14 @@ struct MachineState {
|
||||
* This must be unconditionally used in the register
|
||||
* method for all machine types which support versioning.
|
||||
*
|
||||
- * Inijtially it will effectively be a no-op, but after a
|
||||
- * suitable period of time has passed, it will cause
|
||||
- * execution of the method to return, avoiding registration
|
||||
- * of the machine
|
||||
- *
|
||||
- * The new deprecation and deletion policy for versioned
|
||||
- * machine types was introduced in QEMU 9.1.0.
|
||||
- *
|
||||
- * Under the new policy a number of old machine types (any
|
||||
- * prior to 2.12) would be liable for immediate deletion
|
||||
- * which would be a violation of our historical deprecation
|
||||
- * and removal policy
|
||||
- *
|
||||
- * Thus deletions are temporarily gated on existance of
|
||||
- * the env variable "QEMU_DELETE_MACHINES" / QEMU version
|
||||
- * number >= 10.1.0. This gate can be deleted in the 10.1.0
|
||||
- * dev cycle
|
||||
+ * It will automatically avoid registration of machines
|
||||
+ * that should have been deleted at the start of this
|
||||
+ * RHEL release
|
||||
*/
|
||||
#define MACHINE_VER_DELETION(...) \
|
||||
do { \
|
||||
if (MACHINE_VER_SHOULD_DELETE(__VA_ARGS__)) { \
|
||||
- if (getenv("QEMU_DELETE_MACHINES") || \
|
||||
- QEMU_VERSION_MAJOR > 10 || (QEMU_VERSION_MAJOR == 10 && \
|
||||
- QEMU_VERSION_MINOR >= 1)) { \
|
||||
- return; \
|
||||
- } \
|
||||
+ return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 161d496d55..2de5ab024f 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -2440,6 +2440,7 @@ config_host_data.set('QEMU_VERSION', '"@0@"'.format(meson.project_version()))
|
||||
config_host_data.set('QEMU_VERSION_MAJOR', meson.project_version().split('.')[0])
|
||||
config_host_data.set('QEMU_VERSION_MINOR', meson.project_version().split('.')[1])
|
||||
config_host_data.set('QEMU_VERSION_MICRO', meson.project_version().split('.')[2])
|
||||
+config_host_data.set('RHEL_VERSION', get_option('rhel_version').split('.')[0])
|
||||
|
||||
config_host_data.set_quoted('CONFIG_HOST_DSOSUF', host_dsosuf)
|
||||
config_host_data.set('HAVE_HOST_BLOCK_DEVICE', have_host_block_device)
|
||||
diff --git a/meson_options.txt b/meson_options.txt
|
||||
index 0269fa0f16..aa2ba0baef 100644
|
||||
--- a/meson_options.txt
|
||||
+++ b/meson_options.txt
|
||||
@@ -2,6 +2,8 @@
|
||||
# on the configure script command line. If you add more, list them in
|
||||
# scripts/meson-buildoptions.py's SKIP_OPTIONS constant too.
|
||||
|
||||
+option('rhel_version', type: 'string', value: '0.0',
|
||||
+ description: 'RHEL major/minor version')
|
||||
option('qemu_suffix', type : 'string', value: 'qemu',
|
||||
description: 'Suffix for QEMU data/modules/config directories (can be empty)')
|
||||
option('docdir', type : 'string', value : 'share/doc',
|
||||
diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh
|
||||
index c97079a38c..5f0cbfc725 100644
|
||||
--- a/scripts/meson-buildoptions.sh
|
||||
+++ b/scripts/meson-buildoptions.sh
|
||||
@@ -71,6 +71,7 @@ meson_options_help() {
|
||||
printf "%s\n" ' "manufacturer" name for qemu-ga registry entries'
|
||||
printf "%s\n" ' [QEMU]'
|
||||
printf "%s\n" ' --qemu-ga-version=VALUE version number for qemu-ga installer'
|
||||
+ printf "%s\n" ' --rhel-version=VALUE RHEL major/minor version [0.0]'
|
||||
printf "%s\n" ' --smbd=VALUE Path to smbd for slirp networking'
|
||||
printf "%s\n" ' --sysconfdir=VALUE Sysconf data directory [etc]'
|
||||
printf "%s\n" ' --tls-priority=VALUE Default TLS protocol/cipher priority string'
|
||||
@@ -450,6 +451,7 @@ _meson_option_parse() {
|
||||
--disable-relocatable) printf "%s" -Drelocatable=false ;;
|
||||
--enable-replication) printf "%s" -Dreplication=enabled ;;
|
||||
--disable-replication) printf "%s" -Dreplication=disabled ;;
|
||||
+ --rhel-version=*) quote_sh "-Drhel_version=$2" ;;
|
||||
--enable-rng-none) printf "%s" -Drng_none=true ;;
|
||||
--disable-rng-none) printf "%s" -Drng_none=false ;;
|
||||
--enable-rutabaga-gfx) printf "%s" -Drutabaga_gfx=enabled ;;
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,308 +0,0 @@
|
||||
From 04178c77cfe188b4eed9c08a0bf66842e61fe5dc Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
Date: Fri, 19 Oct 2018 13:47:32 +0200
|
||||
Subject: Add s390x machine types
|
||||
|
||||
Adding changes to add RHEL machine types for s390x architecture.
|
||||
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
--
|
||||
|
||||
Rebase changes (7.1.0):
|
||||
- Moved adding rhel_old_machine_deprecation variable to general machine types commit
|
||||
|
||||
Merged patches (6.1.0):
|
||||
- 64a9a5c971 hw/s390x: Remove the RHEL7-only machine type
|
||||
- 395516d62b redhat: s390x: add rhel-8.5.0 compat machine
|
||||
|
||||
Merged patches (6.2.0):
|
||||
- 3bf66f4520 redhat: Add s390x machine type compatibility update for 6.1 rebase
|
||||
|
||||
Merged patches (7.0.0):
|
||||
- e6ff4de4f7 redhat: Add s390x machine type compatibility handling for the rebase to v6.2
|
||||
- 4b0efa7e21 redhat: Add rhel8.6.0 and rhel9.0.0 machine types for s390x
|
||||
- dcc64971bf RHEL: mark old machine types as deprecated (partialy)
|
||||
|
||||
Merged patches (7.1.0):
|
||||
- 1d6439527a WRB: Introduce RHEL 9.0.0 hw compat structure (only hw/s390x/s390-virtio-ccw.c chunk)
|
||||
- c8ad21ca31 redhat: Update s390x machine type compatibility for rebase to QEMU 7.0.0
|
||||
- 5bcf8d874c target/s390x: deprecate CPUs older than z14
|
||||
|
||||
Merged patches (7.2.0):
|
||||
- 0be2889fa2 Introduce upstream 7.0 compat changes (only applicable parts)
|
||||
|
||||
Merged patches (8.0.0):
|
||||
- 27c188c6a4 redhat: Update s390x machine type compatibility for QEMU 7.2.0 update
|
||||
- a932b8d429 redhat: Add new rhel-9.2.0 s390x machine type
|
||||
- ac88104bad s390x/s390-virtio-ccw: Activate zPCI features on s390-ccw-virtio-rhel8.6.0
|
||||
|
||||
Merged patches (8.1.0):
|
||||
- bd5d81d286 Add RHEL 9.2.0 compat structure (s390x part)
|
||||
|
||||
Merged patches (8.2.0):
|
||||
- 4ee284aca9 Add machine types compat bits. (partial)
|
||||
---
|
||||
hw/s390x/s390-virtio-ccw.c | 159 +++++++++++++++++++++++++++++++
|
||||
target/s390x/cpu_models.c | 11 +++
|
||||
target/s390x/cpu_models.h | 2 +
|
||||
target/s390x/cpu_models_sysemu.c | 2 +
|
||||
4 files changed, 174 insertions(+)
|
||||
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index b1dcb3857f..ff753a29e0 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -859,6 +859,7 @@ bool css_migration_enabled(void)
|
||||
} \
|
||||
type_init(ccw_machine_register_##suffix)
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static void ccw_machine_9_0_instance_options(MachineState *machine)
|
||||
{
|
||||
}
|
||||
@@ -1272,6 +1273,164 @@ static void ccw_machine_2_4_class_options(MachineClass *mc)
|
||||
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||
}
|
||||
DEFINE_CCW_MACHINE(2_4, "2.4", false);
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+static void ccw_machine_rhel940_instance_options(MachineState *machine)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel940_class_options(MachineClass *mc)
|
||||
+{
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel940, "rhel9.4.0", true);
|
||||
+
|
||||
+static void ccw_machine_rhel920_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ ccw_machine_rhel940_instance_options(machine);
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel920_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ ccw_machine_rhel940_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_4, hw_compat_rhel_9_4_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_3, hw_compat_rhel_9_3_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_2, hw_compat_rhel_9_2_len);
|
||||
+ mc->smp_props.drawers_supported = false; /* from ccw_machine_8_1 */
|
||||
+ mc->smp_props.books_supported = false; /* from ccw_machine_8_1 */
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel920, "rhel9.2.0", false);
|
||||
+
|
||||
+static void ccw_machine_rhel900_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_2 };
|
||||
+
|
||||
+ ccw_machine_rhel920_instance_options(machine);
|
||||
+
|
||||
+ s390_set_qemu_cpu_model(0x3906, 14, 2, qemu_cpu_feat);
|
||||
+ s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAIE);
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel900_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
|
||||
+ static GlobalProperty compat[] = {
|
||||
+ { TYPE_S390_PCI_DEVICE, "interpret", "off", },
|
||||
+ { TYPE_S390_PCI_DEVICE, "forwarding-assist", "off", },
|
||||
+ };
|
||||
+
|
||||
+ ccw_machine_rhel920_class_options(mc);
|
||||
+
|
||||
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_1, hw_compat_rhel_9_1_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_0, hw_compat_rhel_9_0_len);
|
||||
+ s390mc->max_threads = S390_MAX_CPUS;
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel900, "rhel9.0.0", false);
|
||||
+
|
||||
+static void ccw_machine_rhel860_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ /* Note: The -rhel8.6.0 and -rhel9.0.0 machines are technically identical */
|
||||
+ ccw_machine_rhel900_instance_options(machine);
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel860_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ static GlobalProperty compat[] = {
|
||||
+ { TYPE_S390_PCI_DEVICE, "interpret", "on", },
|
||||
+ { TYPE_S390_PCI_DEVICE, "forwarding-assist", "on", },
|
||||
+ };
|
||||
+
|
||||
+ ccw_machine_rhel900_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_6, hw_compat_rhel_8_6_len);
|
||||
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||
+
|
||||
+ /* All RHEL machines for prior major releases are deprecated */
|
||||
+ mc->deprecation_reason = rhel_old_machine_deprecation;
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel860, "rhel8.6.0", false);
|
||||
+
|
||||
+static void ccw_machine_rhel850_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_0 };
|
||||
+
|
||||
+ ccw_machine_rhel860_instance_options(machine);
|
||||
+
|
||||
+ s390_set_qemu_cpu_model(0x2964, 13, 2, qemu_cpu_feat);
|
||||
+
|
||||
+ s390_cpudef_featoff_greater(16, 1, S390_FEAT_NNPA);
|
||||
+ s390_cpudef_featoff_greater(16, 1, S390_FEAT_VECTOR_PACKED_DECIMAL_ENH2);
|
||||
+ s390_cpudef_featoff_greater(16, 1, S390_FEAT_BEAR_ENH);
|
||||
+ s390_cpudef_featoff_greater(16, 1, S390_FEAT_RDP);
|
||||
+ s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAI);
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel850_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ static GlobalProperty compat[] = {
|
||||
+ { TYPE_S390_PCI_DEVICE, "interpret", "off", },
|
||||
+ { TYPE_S390_PCI_DEVICE, "forwarding-assist", "off", },
|
||||
+ };
|
||||
+
|
||||
+ ccw_machine_rhel860_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_5, hw_compat_rhel_8_5_len);
|
||||
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||
+ mc->smp_props.prefer_sockets = true;
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel850, "rhel8.5.0", false);
|
||||
+
|
||||
+static void ccw_machine_rhel840_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ ccw_machine_rhel850_instance_options(machine);
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel840_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ ccw_machine_rhel850_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_4, hw_compat_rhel_8_4_len);
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel840, "rhel8.4.0", false);
|
||||
+
|
||||
+static void ccw_machine_rhel820_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ ccw_machine_rhel840_instance_options(machine);
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel820_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ ccw_machine_rhel840_class_options(mc);
|
||||
+ mc->fixup_ram_size = s390_fixup_ram_size;
|
||||
+ /* we did not publish a rhel8.3.0 machine */
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_3, hw_compat_rhel_8_3_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_2, hw_compat_rhel_8_2_len);
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel820, "rhel8.2.0", false);
|
||||
+
|
||||
+static void ccw_machine_rhel760_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V3_1 };
|
||||
+
|
||||
+ ccw_machine_rhel820_instance_options(machine);
|
||||
+
|
||||
+ s390_set_qemu_cpu_model(0x2827, 12, 2, qemu_cpu_feat);
|
||||
+
|
||||
+ /* The multiple-epoch facility was not available with rhel7.6.0 on z14GA1 */
|
||||
+ s390_cpudef_featoff(14, 1, S390_FEAT_MULTIPLE_EPOCH);
|
||||
+ s390_cpudef_featoff(14, 1, S390_FEAT_PTFF_QSIE);
|
||||
+ s390_cpudef_featoff(14, 1, S390_FEAT_PTFF_QTOUE);
|
||||
+ s390_cpudef_featoff(14, 1, S390_FEAT_PTFF_STOE);
|
||||
+ s390_cpudef_featoff(14, 1, S390_FEAT_PTFF_STOUE);
|
||||
+}
|
||||
+
|
||||
+static void ccw_machine_rhel760_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ ccw_machine_rhel820_class_options(mc);
|
||||
+ /* We never published the s390x version of RHEL-AV 8.0 and 8.1, so add this here */
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_1, hw_compat_rhel_8_1_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_8_0, hw_compat_rhel_8_0_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_7_6, hw_compat_rhel_7_6_len);
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(rhel760, "rhel7.6.0", false);
|
||||
|
||||
static void ccw_machine_register_types(void)
|
||||
{
|
||||
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
|
||||
index 8ed3bb6a27..370b3b3065 100644
|
||||
--- a/target/s390x/cpu_models.c
|
||||
+++ b/target/s390x/cpu_models.c
|
||||
@@ -46,6 +46,9 @@
|
||||
* of a following release have been a superset of the previous release. With
|
||||
* generation 15 one base feature and one optional feature have been deprecated.
|
||||
*/
|
||||
+
|
||||
+#define RHEL_CPU_DEPRECATION "use at least 'z14', or 'host' / 'qemu' / 'max'"
|
||||
+
|
||||
static S390CPUDef s390_cpu_defs[] = {
|
||||
CPUDEF_INIT(0x2064, 7, 1, 38, 0x00000000U, "z900", "IBM zSeries 900 GA1"),
|
||||
CPUDEF_INIT(0x2064, 7, 2, 38, 0x00000000U, "z900.2", "IBM zSeries 900 GA2"),
|
||||
@@ -866,22 +869,30 @@ static void s390_host_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
static void s390_base_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390CPUClass *xcc = S390_CPU_CLASS(oc);
|
||||
+ CPUClass *cc = CPU_CLASS(oc);
|
||||
|
||||
/* all base models are migration safe */
|
||||
xcc->cpu_def = (const S390CPUDef *) data;
|
||||
xcc->is_migration_safe = true;
|
||||
xcc->is_static = true;
|
||||
xcc->desc = xcc->cpu_def->desc;
|
||||
+ if (xcc->cpu_def->gen < 14) {
|
||||
+ cc->deprecation_note = RHEL_CPU_DEPRECATION;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void s390_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390CPUClass *xcc = S390_CPU_CLASS(oc);
|
||||
+ CPUClass *cc = CPU_CLASS(oc);
|
||||
|
||||
/* model that can change between QEMU versions */
|
||||
xcc->cpu_def = (const S390CPUDef *) data;
|
||||
xcc->is_migration_safe = true;
|
||||
xcc->desc = xcc->cpu_def->desc;
|
||||
+ if (xcc->cpu_def->gen < 14) {
|
||||
+ cc->deprecation_note = RHEL_CPU_DEPRECATION;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void s390_qemu_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h
|
||||
index d7b8912989..1a806a97c4 100644
|
||||
--- a/target/s390x/cpu_models.h
|
||||
+++ b/target/s390x/cpu_models.h
|
||||
@@ -38,6 +38,8 @@ typedef struct S390CPUDef {
|
||||
S390FeatBitmap full_feat;
|
||||
/* used to init full_feat from generated data */
|
||||
S390FeatInit full_init;
|
||||
+ /* if deprecated, provides a suggestion */
|
||||
+ const char *deprecation_note;
|
||||
} S390CPUDef;
|
||||
|
||||
/* CPU model based on a CPU definition */
|
||||
diff --git a/target/s390x/cpu_models_sysemu.c b/target/s390x/cpu_models_sysemu.c
|
||||
index 0728bfcc20..ca2e5d91e2 100644
|
||||
--- a/target/s390x/cpu_models_sysemu.c
|
||||
+++ b/target/s390x/cpu_models_sysemu.c
|
||||
@@ -59,6 +59,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
|
||||
CpuDefinitionInfo *info;
|
||||
char *name = g_strdup(object_class_get_name(klass));
|
||||
S390CPUClass *scc = S390_CPU_CLASS(klass);
|
||||
+ CPUClass *cc = CPU_CLASS(klass);
|
||||
|
||||
/* strip off the -s390x-cpu */
|
||||
g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0;
|
||||
@@ -68,6 +69,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
|
||||
info->migration_safe = scc->is_migration_safe;
|
||||
info->q_static = scc->is_static;
|
||||
info->q_typename = g_strdup(object_class_get_name(klass));
|
||||
+ info->deprecated = !!cc->deprecation_note;
|
||||
/* check for unavailable features */
|
||||
if (cpu_list_data->model) {
|
||||
Object *obj;
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,37 @@
|
||||
From 551632921a8330cff09e7d92429aa45cf51c75e6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 3 Jul 2024 18:45:58 +0100
|
||||
Subject: Increase deletion schedule to 4 releases
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Until RHEL 10 pc machine type is introduced, we have to keep
|
||||
7.6.0 machine types as a special exception to our normal rule of
|
||||
deleting machine types after 2 releases due to being a default
|
||||
machine type.
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
|
||||
Rebase notes (9.1.0 rc0)
|
||||
- New patch
|
||||
---
|
||||
include/hw/boards.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||
index 7f7eb4ec40..fd5a957cad 100644
|
||||
--- a/include/hw/boards.h
|
||||
+++ b/include/hw/boards.h
|
||||
@@ -608,7 +608,7 @@ struct MachineState {
|
||||
* How many RHEL major releases for each phase
|
||||
* of the life cycle.
|
||||
*/
|
||||
-#define MACHINE_VER_DELETION_MAJOR 2
|
||||
+#define MACHINE_VER_DELETION_MAJOR 4
|
||||
#define MACHINE_VER_DEPRECATION_MAJOR 1
|
||||
|
||||
/*
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,301 @@
|
||||
From 6cb1d3cf4ac08fe8c435e98500224a022d019e55 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 3 Jul 2024 13:25:47 +0100
|
||||
Subject: Add downstream aarch64 versioned 'virt' machine types
|
||||
|
||||
Adding changes to add RHEL machine types for aarch64 architecture.
|
||||
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
---
|
||||
Rebase notes (9.1.0 rc0):
|
||||
- Merge copy+pasted base machine definition back with upstream
|
||||
base machine definition to reduce RHEL delta, as is done with
|
||||
other targets
|
||||
- Convert to new DEFINE_VIRT_MACHINE macros
|
||||
|
||||
Rebase notes (9.1.0 rc1):
|
||||
- do not remove cpu validation (review comment)
|
||||
|
||||
Rebase notes (9.1.0 rc2):
|
||||
- use ifdef instead of removal for disabling unwanted upstream code
|
||||
|
||||
Merged patches (9.1.0 rc0):
|
||||
- 043ad5ce97 Add upstream compatibility bits (partial)
|
||||
---
|
||||
hw/arm/virt.c | 101 ++++++++++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 81 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 5396e7cb24..903c0f2e9f 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -90,6 +90,22 @@ static GlobalProperty arm_virt_compat[] = {
|
||||
};
|
||||
static const size_t arm_virt_compat_len = G_N_ELEMENTS(arm_virt_compat);
|
||||
|
||||
+/*
|
||||
+ * This variable is for changes to properties that are RHEL specific,
|
||||
+ * different to the current upstream and to be applied to the latest
|
||||
+ * machine type. They may be overriden by older machine compats.
|
||||
+ *
|
||||
+ * virtio-net-pci variant romfiles are not needed because edk2 does
|
||||
+ * fully support the pxe boot. Besides virtio romfiles are not shipped
|
||||
+ * on rhel/aarch64.
|
||||
+ */
|
||||
+GlobalProperty arm_rhel_compat[] = {
|
||||
+ {"virtio-net-pci", "romfile", "" },
|
||||
+ {"virtio-net-pci-transitional", "romfile", "" },
|
||||
+ {"virtio-net-pci-non-transitional", "romfile", "" },
|
||||
+};
|
||||
+const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat);
|
||||
+
|
||||
/*
|
||||
* This cannot be called from the virt_machine_class_init() because
|
||||
* TYPE_VIRT_MACHINE is abstract and mc->compat_props g_ptr_array_new()
|
||||
@@ -99,6 +115,8 @@ static void arm_virt_compat_set(MachineClass *mc)
|
||||
{
|
||||
compat_props_add(mc->compat_props, arm_virt_compat,
|
||||
arm_virt_compat_len);
|
||||
+ compat_props_add(mc->compat_props, arm_rhel_compat,
|
||||
+ arm_rhel_compat_len);
|
||||
}
|
||||
|
||||
#define DEFINE_VIRT_MACHINE_IMPL(latest, ...) \
|
||||
@@ -109,10 +127,11 @@ static void arm_virt_compat_set(MachineClass *mc)
|
||||
MachineClass *mc = MACHINE_CLASS(oc); \
|
||||
arm_virt_compat_set(mc); \
|
||||
MACHINE_VER_SYM(options, virt, __VA_ARGS__)(mc); \
|
||||
- mc->desc = "QEMU " MACHINE_VER_STR(__VA_ARGS__) " ARM Virtual Machine"; \
|
||||
+ mc->desc = "RHEL " MACHINE_VER_STR(__VA_ARGS__) " ARM Virtual Machine"; \
|
||||
MACHINE_VER_DEPRECATION(__VA_ARGS__); \
|
||||
if (latest) { \
|
||||
mc->alias = "virt"; \
|
||||
+ mc->is_default = 1; \
|
||||
} \
|
||||
} \
|
||||
static const TypeInfo MACHINE_VER_SYM(info, virt, __VA_ARGS__) = \
|
||||
@@ -128,10 +147,10 @@ static void arm_virt_compat_set(MachineClass *mc)
|
||||
} \
|
||||
type_init(MACHINE_VER_SYM(register, virt, __VA_ARGS__));
|
||||
|
||||
-#define DEFINE_VIRT_MACHINE_AS_LATEST(major, minor) \
|
||||
- DEFINE_VIRT_MACHINE_IMPL(true, major, minor)
|
||||
-#define DEFINE_VIRT_MACHINE(major, minor) \
|
||||
- DEFINE_VIRT_MACHINE_IMPL(false, major, minor)
|
||||
+#define DEFINE_VIRT_MACHINE_AS_LATEST(major, minor, micro) \
|
||||
+ DEFINE_VIRT_MACHINE_IMPL(true, major, minor, micro)
|
||||
+#define DEFINE_VIRT_MACHINE(major, minor, micro) \
|
||||
+ DEFINE_VIRT_MACHINE_IMPL(false, major, minor, micro)
|
||||
|
||||
|
||||
/* Number of external interrupt lines to configure the GIC with */
|
||||
@@ -2434,6 +2453,7 @@ static void machvirt_init(MachineState *machine)
|
||||
qemu_add_machine_init_done_notifier(&vms->machine_done);
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_secure(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2461,6 +2481,7 @@ static void virt_set_virt(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->virt = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static bool virt_get_highmem(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -2476,6 +2497,7 @@ static void virt_set_highmem(Object *obj, bool value, Error **errp)
|
||||
vms->highmem = value;
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_compact_highmem(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2489,6 +2511,7 @@ static void virt_set_compact_highmem(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->highmem_compact = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static bool virt_get_highmem_redists(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -2547,6 +2570,7 @@ static void virt_set_its(Object *obj, bool value, Error **errp)
|
||||
vms->its = value;
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_dtb_randomness(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2560,6 +2584,7 @@ static void virt_set_dtb_randomness(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->dtb_randomness = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static char *virt_get_oem_id(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -2643,6 +2668,7 @@ static void virt_set_ras(Object *obj, bool value, Error **errp)
|
||||
vms->ras = value;
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static bool virt_get_mte(Object *obj, Error **errp)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(obj);
|
||||
@@ -2656,6 +2682,7 @@ static void virt_set_mte(Object *obj, bool value, Error **errp)
|
||||
|
||||
vms->mte = value;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static char *virt_get_gic_version(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -3063,16 +3090,10 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
NULL
|
||||
};
|
||||
|
||||
+ mc->family = "virt-rhel-Z";
|
||||
mc->init = machvirt_init;
|
||||
- /* Start with max_cpus set to 512, which is the maximum supported by KVM.
|
||||
- * The value may be reduced later when we have more information about the
|
||||
- * configuration of the particular instance.
|
||||
- */
|
||||
- mc->max_cpus = 512;
|
||||
- machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_CALXEDA_XGMAC);
|
||||
- machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
|
||||
- machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
|
||||
- machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
|
||||
+ /* Maximum supported VCPU count for all virt-rhel* machines */
|
||||
+ mc->max_cpus = 384;
|
||||
#ifdef CONFIG_TPM
|
||||
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
|
||||
#endif
|
||||
@@ -3083,11 +3104,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->minimum_page_bits = 12;
|
||||
mc->possible_cpu_arch_ids = virt_possible_cpu_arch_ids;
|
||||
mc->cpu_index_to_instance_props = virt_cpu_index_to_props;
|
||||
-#ifdef CONFIG_TCG
|
||||
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a15");
|
||||
-#else
|
||||
- mc->default_cpu_type = ARM_CPU_TYPE_NAME("max");
|
||||
-#endif
|
||||
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-a57");
|
||||
mc->valid_cpu_types = valid_cpu_types;
|
||||
mc->get_default_cpu_node_id = virt_get_default_cpu_node_id;
|
||||
mc->kvm_type = virt_kvm_type;
|
||||
@@ -3111,6 +3128,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
NULL, NULL);
|
||||
object_class_property_set_description(oc, "acpi",
|
||||
"Enable ACPI");
|
||||
+#if 0 /* disabled for RHEL */
|
||||
object_class_property_add_bool(oc, "secure", virt_get_secure,
|
||||
virt_set_secure);
|
||||
object_class_property_set_description(oc, "secure",
|
||||
@@ -3123,6 +3141,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
"Set on/off to enable/disable emulating a "
|
||||
"guest CPU which implements the ARM "
|
||||
"Virtualization Extensions");
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
object_class_property_add_bool(oc, "highmem", virt_get_highmem,
|
||||
virt_set_highmem);
|
||||
@@ -3130,12 +3149,14 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
"Set on/off to enable/disable using "
|
||||
"physical address space above 32 bits");
|
||||
|
||||
+#if 0 /* disabled for RHEL */
|
||||
object_class_property_add_bool(oc, "compact-highmem",
|
||||
virt_get_compact_highmem,
|
||||
virt_set_compact_highmem);
|
||||
object_class_property_set_description(oc, "compact-highmem",
|
||||
"Set on/off to enable/disable compact "
|
||||
"layout for high memory regions");
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
object_class_property_add_bool(oc, "highmem-redists",
|
||||
virt_get_highmem_redists,
|
||||
@@ -3163,7 +3184,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
virt_set_gic_version);
|
||||
object_class_property_set_description(oc, "gic-version",
|
||||
"Set GIC version. "
|
||||
- "Valid values are 2, 3, 4, host and max");
|
||||
+ "Valid values are 2, 3, host and max");
|
||||
|
||||
object_class_property_add_str(oc, "iommu", virt_get_iommu, virt_set_iommu);
|
||||
object_class_property_set_description(oc, "iommu",
|
||||
@@ -3183,11 +3204,13 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
"Set on/off to enable/disable reporting host memory errors "
|
||||
"to a KVM guest using ACPI and guest external abort exceptions");
|
||||
|
||||
+#if 0 /* disabled for RHEL */
|
||||
object_class_property_add_bool(oc, "mte", virt_get_mte, virt_set_mte);
|
||||
object_class_property_set_description(oc, "mte",
|
||||
"Set on/off to enable/disable emulating a "
|
||||
"guest CPU which implements the ARM "
|
||||
"Memory Tagging Extension");
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
object_class_property_add_bool(oc, "its", virt_get_its,
|
||||
virt_set_its);
|
||||
@@ -3195,6 +3218,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
"Set on/off to enable/disable "
|
||||
"ITS instantiation");
|
||||
|
||||
+#if 0 /* disabled for RHEL */
|
||||
object_class_property_add_bool(oc, "dtb-randomness",
|
||||
virt_get_dtb_randomness,
|
||||
virt_set_dtb_randomness);
|
||||
@@ -3207,6 +3231,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
virt_set_dtb_randomness);
|
||||
object_class_property_set_description(oc, "dtb-kaslr-seed",
|
||||
"Deprecated synonym of dtb-randomness");
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
object_class_property_add_str(oc, "x-oem-id",
|
||||
virt_get_oem_id,
|
||||
@@ -3554,3 +3579,39 @@ static void virt_machine_2_6_options(MachineClass *mc)
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(2, 6)
|
||||
#endif /* disabled for RHEL */
|
||||
+
|
||||
+static void virt_rhel_machine_9_4_0_options(MachineClass *mc)
|
||||
+{
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
+}
|
||||
+DEFINE_VIRT_MACHINE_AS_LATEST(9, 4, 0)
|
||||
+
|
||||
+static void virt_rhel_machine_9_2_0_options(MachineClass *mc)
|
||||
+{
|
||||
+ virt_rhel_machine_9_4_0_options(mc);
|
||||
+
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_4, hw_compat_rhel_9_4_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_3, hw_compat_rhel_9_3_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_2, hw_compat_rhel_9_2_len);
|
||||
+
|
||||
+ /* RHEL 9.4 is the first supported release */
|
||||
+ mc->deprecation_reason =
|
||||
+ "machine types for versions prior to 9.4 are deprecated";
|
||||
+}
|
||||
+DEFINE_VIRT_MACHINE(9, 2, 0)
|
||||
+
|
||||
+static void virt_rhel_machine_9_0_0_options(MachineClass *mc)
|
||||
+{
|
||||
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
+
|
||||
+ virt_rhel_machine_9_2_0_options(mc);
|
||||
+
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_1, hw_compat_rhel_9_1_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_0, hw_compat_rhel_9_0_len);
|
||||
+
|
||||
+ /* Disable FEAT_LPA2 since old kernels (<= v5.12) don't boot with that feature */
|
||||
+ vmc->no_tcg_lpa2 = true;
|
||||
+ /* Compact layout for high memory regions was introduced with 9.2.0 */
|
||||
+ vmc->no_highmem_compact = true;
|
||||
+}
|
||||
+DEFINE_VIRT_MACHINE(9, 0, 0)
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,208 @@
|
||||
From 24d6b22e10c87e9a4bf4df834738f42caa1d5014 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 3 Jul 2024 13:44:36 +0100
|
||||
Subject: Add downstream s390x versioned 's390-ccw-virtio' machine types
|
||||
|
||||
Adding changes to add RHEL machine types for s390x architecture.
|
||||
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
--
|
||||
Rebase notes(9.1.0 rc0):
|
||||
- Convert to new DEFINE_CCW_MACHINE macros
|
||||
|
||||
Merged patches (9.1.0 rc0):
|
||||
- 043ad5ce97 Add upstream compatibility bits (partial)
|
||||
- 04596b496e s390x: remove deprecated rhel machine types
|
||||
---
|
||||
hw/s390x/s390-virtio-ccw.c | 65 +++++++++++++++++++++++++++++---
|
||||
target/s390x/cpu_models.c | 11 ++++++
|
||||
target/s390x/cpu_models.h | 2 +
|
||||
target/s390x/cpu_models_sysemu.c | 2 +
|
||||
4 files changed, 75 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index 86bfc9d2eb..451017c50e 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -617,6 +617,7 @@ static void s390_nmi(NMIState *n, int cpu_index, Error **errp)
|
||||
s390_cpu_restart(S390_CPU(cs));
|
||||
}
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static ram_addr_t s390_fixup_ram_size(ram_addr_t sz)
|
||||
{
|
||||
/* same logic as in sclp.c */
|
||||
@@ -636,6 +637,7 @@ static ram_addr_t s390_fixup_ram_size(ram_addr_t sz)
|
||||
}
|
||||
return newsz;
|
||||
}
|
||||
+#endif /* disabled for RHEL */
|
||||
|
||||
static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -837,7 +839,7 @@ static const TypeInfo ccw_machine_info = {
|
||||
{ \
|
||||
MachineClass *mc = MACHINE_CLASS(oc); \
|
||||
MACHINE_VER_SYM(class_options, ccw, __VA_ARGS__)(mc); \
|
||||
- mc->desc = "Virtual s390x machine (version " MACHINE_VER_STR(__VA_ARGS__) ")"; \
|
||||
+ mc->desc = "Virtual s390x machine (version rhel" MACHINE_VER_STR(__VA_ARGS__) ")"; \
|
||||
MACHINE_VER_DEPRECATION(__VA_ARGS__); \
|
||||
if (latest) { \
|
||||
mc->alias = "s390-ccw-virtio"; \
|
||||
@@ -864,11 +866,11 @@ static const TypeInfo ccw_machine_info = {
|
||||
} \
|
||||
type_init(MACHINE_VER_SYM(register, ccw, __VA_ARGS__))
|
||||
|
||||
-#define DEFINE_CCW_MACHINE_AS_LATEST(major, minor) \
|
||||
- DEFINE_CCW_MACHINE_IMPL(true, major, minor)
|
||||
+#define DEFINE_CCW_MACHINE_AS_LATEST(major, minor, micro) \
|
||||
+ DEFINE_CCW_MACHINE_IMPL(true, major, minor, micro)
|
||||
|
||||
-#define DEFINE_CCW_MACHINE(major, minor) \
|
||||
- DEFINE_CCW_MACHINE_IMPL(false, major, minor)
|
||||
+#define DEFINE_CCW_MACHINE(major, minor, micro) \
|
||||
+ DEFINE_CCW_MACHINE_IMPL(false, major, minor, micro)
|
||||
|
||||
|
||||
#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
@@ -1308,6 +1310,59 @@ DEFINE_CCW_MACHINE(2, 4);
|
||||
#endif
|
||||
#endif /* disabled for RHEL */
|
||||
|
||||
+static void ccw_rhel_machine_9_4_0_instance_options(MachineState *machine)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void ccw_rhel_machine_9_4_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE_AS_LATEST(9, 4, 0);
|
||||
+
|
||||
+static void ccw_rhel_machine_9_2_0_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ ccw_rhel_machine_9_4_0_instance_options(machine);
|
||||
+}
|
||||
+
|
||||
+static void ccw_rhel_machine_9_2_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ ccw_rhel_machine_9_4_0_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_4, hw_compat_rhel_9_4_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_3, hw_compat_rhel_9_3_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_2, hw_compat_rhel_9_2_len);
|
||||
+ mc->smp_props.drawers_supported = false; /* from ccw_machine_8_1 */
|
||||
+ mc->smp_props.books_supported = false; /* from ccw_machine_8_1 */
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(9, 2, 0);
|
||||
+
|
||||
+static void ccw_rhel_machine_9_0_0_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V6_2 };
|
||||
+
|
||||
+ ccw_rhel_machine_9_2_0_instance_options(machine);
|
||||
+
|
||||
+ s390_set_qemu_cpu_model(0x3906, 14, 2, qemu_cpu_feat);
|
||||
+ s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAIE);
|
||||
+}
|
||||
+
|
||||
+static void ccw_rhel_machine_9_0_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc);
|
||||
+ static GlobalProperty compat[] = {
|
||||
+ { TYPE_S390_PCI_DEVICE, "interpret", "off", },
|
||||
+ { TYPE_S390_PCI_DEVICE, "forwarding-assist", "off", },
|
||||
+ };
|
||||
+
|
||||
+ ccw_rhel_machine_9_2_0_class_options(mc);
|
||||
+
|
||||
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_1, hw_compat_rhel_9_1_len);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_0, hw_compat_rhel_9_0_len);
|
||||
+ s390mc->max_threads = S390_MAX_CPUS;
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(9, 0, 0);
|
||||
+
|
||||
static void ccw_machine_register_types(void)
|
||||
{
|
||||
type_register_static(&ccw_machine_info);
|
||||
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
|
||||
index 798c18f940..8afa9af1a5 100644
|
||||
--- a/target/s390x/cpu_models.c
|
||||
+++ b/target/s390x/cpu_models.c
|
||||
@@ -47,6 +47,9 @@
|
||||
* of a following release have been a superset of the previous release. With
|
||||
* generation 15 one base feature and one optional feature have been deprecated.
|
||||
*/
|
||||
+
|
||||
+#define RHEL_CPU_DEPRECATION "use at least 'z14', or 'host' / 'qemu' / 'max'"
|
||||
+
|
||||
static S390CPUDef s390_cpu_defs[] = {
|
||||
/*
|
||||
* Linux requires at least z10 nowadays, and IBM only supports recent CPUs
|
||||
@@ -871,22 +874,30 @@ static void s390_host_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
static void s390_base_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390CPUClass *xcc = S390_CPU_CLASS(oc);
|
||||
+ CPUClass *cc = CPU_CLASS(oc);
|
||||
|
||||
/* all base models are migration safe */
|
||||
xcc->cpu_def = (const S390CPUDef *) data;
|
||||
xcc->is_migration_safe = true;
|
||||
xcc->is_static = true;
|
||||
xcc->desc = xcc->cpu_def->desc;
|
||||
+ if (xcc->cpu_def->gen < 14) {
|
||||
+ cc->deprecation_note = RHEL_CPU_DEPRECATION;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void s390_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
S390CPUClass *xcc = S390_CPU_CLASS(oc);
|
||||
+ CPUClass *cc = CPU_CLASS(oc);
|
||||
|
||||
/* model that can change between QEMU versions */
|
||||
xcc->cpu_def = (const S390CPUDef *) data;
|
||||
xcc->is_migration_safe = true;
|
||||
xcc->desc = xcc->cpu_def->desc;
|
||||
+ if (xcc->cpu_def->gen < 14) {
|
||||
+ cc->deprecation_note = RHEL_CPU_DEPRECATION;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void s390_qemu_cpu_model_class_init(ObjectClass *oc, void *data)
|
||||
diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h
|
||||
index 71d4bc2dd4..d6c7c2cb50 100644
|
||||
--- a/target/s390x/cpu_models.h
|
||||
+++ b/target/s390x/cpu_models.h
|
||||
@@ -38,6 +38,8 @@ typedef struct S390CPUDef {
|
||||
S390FeatBitmap full_feat;
|
||||
/* used to init full_feat from generated data */
|
||||
S390FeatInit full_init;
|
||||
+ /* if deprecated, provides a suggestion */
|
||||
+ const char *deprecation_note;
|
||||
} S390CPUDef;
|
||||
|
||||
/* CPU model based on a CPU definition */
|
||||
diff --git a/target/s390x/cpu_models_sysemu.c b/target/s390x/cpu_models_sysemu.c
|
||||
index f6df691b66..b8de04de99 100644
|
||||
--- a/target/s390x/cpu_models_sysemu.c
|
||||
+++ b/target/s390x/cpu_models_sysemu.c
|
||||
@@ -56,6 +56,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
|
||||
CpuDefinitionInfo *info;
|
||||
char *name = g_strdup(object_class_get_name(klass));
|
||||
S390CPUClass *scc = S390_CPU_CLASS(klass);
|
||||
+ CPUClass *cc = CPU_CLASS(klass);
|
||||
|
||||
/* strip off the -s390x-cpu */
|
||||
g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0;
|
||||
@@ -65,6 +66,7 @@ static void create_cpu_model_list(ObjectClass *klass, void *opaque)
|
||||
info->migration_safe = scc->is_migration_safe;
|
||||
info->q_static = scc->is_static;
|
||||
info->q_typename = g_strdup(object_class_get_name(klass));
|
||||
+ info->deprecated = !!cc->deprecation_note;
|
||||
/* check for unavailable features */
|
||||
if (cpu_list_data->model) {
|
||||
Object *obj;
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,32 @@
|
||||
From bd6f1170d3a011c475ec4a8315512c7c190de3e4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
|
||||
Date: Wed, 3 Jul 2024 13:47:04 +0100
|
||||
Subject: Revert "meson: temporarily disable -Wunused-function"
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This reverts commit c682111eaa73d9b985187b8be330338f50b78a7a.
|
||||
|
||||
No longer needed after introduction of downstream machines.
|
||||
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
---
|
||||
meson.build | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 2de5ab024f..b3529aa0e1 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -651,7 +651,6 @@ warn_flags = [
|
||||
'-Wno-string-plus-int',
|
||||
'-Wno-tautological-type-limit-compare',
|
||||
'-Wno-typedef-redefinition',
|
||||
- '-Wno-unused-function',
|
||||
]
|
||||
|
||||
if host_os != 'darwin'
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,121 +0,0 @@
|
||||
From 59470e8ab849f22b407f55292e540e16a8cad01a Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
Date: Wed, 20 Mar 2024 05:34:32 -0400
|
||||
Subject: Add upstream compatibility bits
|
||||
|
||||
Adding new compats structure for changes introduced during rebase to QEMU 9.0.0.
|
||||
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
|
||||
---
|
||||
|
||||
Rebase notes (9.0.0 rc2):
|
||||
- Add aw-bits setting for aarch compat record (overwritten for 9.4 and older)
|
||||
---
|
||||
hw/arm/virt.c | 3 +++
|
||||
hw/core/machine.c | 10 ++++++++++
|
||||
hw/i386/pc_piix.c | 3 ++-
|
||||
hw/i386/pc_q35.c | 3 +++
|
||||
hw/s390x/s390-virtio-ccw.c | 1 +
|
||||
include/hw/boards.h | 3 +++
|
||||
6 files changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 22bc345137..f1af9495c6 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -144,6 +144,8 @@ GlobalProperty arm_rhel_compat[] = {
|
||||
{"virtio-net-pci", "romfile", "" },
|
||||
{"virtio-net-pci-transitional", "romfile", "" },
|
||||
{"virtio-net-pci-non-transitional", "romfile", "" },
|
||||
+ /* arm_rhel_compat from arm_virt_compat, added for 9.0.0 rebase */
|
||||
+ { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
|
||||
};
|
||||
const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat);
|
||||
|
||||
@@ -3728,6 +3730,7 @@ type_init(rhel_machine_init);
|
||||
|
||||
static void rhel940_virt_options(MachineClass *mc)
|
||||
{
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
}
|
||||
DEFINE_RHEL_MACHINE_AS_LATEST(9, 4, 0)
|
||||
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index 695cb89a46..0f256d9633 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -302,6 +302,16 @@ const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
|
||||
const char *rhel_old_machine_deprecation =
|
||||
"machine types for previous major releases are deprecated";
|
||||
|
||||
+GlobalProperty hw_compat_rhel_9_5[] = {
|
||||
+ /* hw_compat_rhel_9_5 from hw_compat_8_2 */
|
||||
+ { "migration", "zero-page-detection", "legacy"},
|
||||
+ /* hw_compat_rhel_9_5 from hw_compat_8_2 */
|
||||
+ { TYPE_VIRTIO_IOMMU_PCI, "granule", "4k" },
|
||||
+ /* hw_compat_rhel_9_5 from hw_compat_8_2 */
|
||||
+ { TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "64" },
|
||||
+};
|
||||
+const size_t hw_compat_rhel_9_5_len = G_N_ELEMENTS(hw_compat_rhel_9_5);
|
||||
+
|
||||
GlobalProperty hw_compat_rhel_9_4[] = {
|
||||
/* hw_compat_rhel_9_4 from hw_compat_8_0 */
|
||||
{ TYPE_VIRTIO_NET, "host_uso", "off"},
|
||||
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||
index a647262d63..6b260682eb 100644
|
||||
--- a/hw/i386/pc_piix.c
|
||||
+++ b/hw/i386/pc_piix.c
|
||||
@@ -1015,7 +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, hw_compat_rhel_9_5,
|
||||
+ hw_compat_rhel_9_5_len);
|
||||
compat_props_add(m->compat_props, hw_compat_rhel_9_4,
|
||||
hw_compat_rhel_9_4_len);
|
||||
compat_props_add(m->compat_props, hw_compat_rhel_9_3,
|
||||
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||
index e872dc7e46..2b54944c0f 100644
|
||||
--- a/hw/i386/pc_q35.c
|
||||
+++ b/hw/i386/pc_q35.c
|
||||
@@ -733,6 +733,9 @@ 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";
|
||||
+
|
||||
+ compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||
+ hw_compat_rhel_9_5_len);
|
||||
}
|
||||
|
||||
DEFINE_PC_MACHINE(q35_rhel940, "pc-q35-rhel9.4.0", pc_q35_init_rhel940,
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index ff753a29e0..9ad54682c6 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -1282,6 +1282,7 @@ static void ccw_machine_rhel940_instance_options(MachineState *machine)
|
||||
|
||||
static void ccw_machine_rhel940_class_options(MachineClass *mc)
|
||||
{
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
}
|
||||
DEFINE_CCW_MACHINE(rhel940, "rhel9.4.0", true);
|
||||
|
||||
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||
index 46b8725c41..cca62f906b 100644
|
||||
--- a/include/hw/boards.h
|
||||
+++ b/include/hw/boards.h
|
||||
@@ -514,6 +514,9 @@ extern const size_t hw_compat_2_2_len;
|
||||
extern GlobalProperty hw_compat_2_1[];
|
||||
extern const size_t hw_compat_2_1_len;
|
||||
|
||||
+extern GlobalProperty hw_compat_rhel_9_5[];
|
||||
+extern const size_t hw_compat_rhel_9_5_len;
|
||||
+
|
||||
extern GlobalProperty hw_compat_rhel_9_4[];
|
||||
extern const size_t hw_compat_rhel_9_4_len;
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,30 +0,0 @@
|
||||
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
|
||||
|
@ -0,0 +1,109 @@
|
||||
From 03502faf7012e20fb7c4f1efee7e429ad3727fd1 Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
Date: Wed, 15 May 2024 01:41:13 -0400
|
||||
Subject: Add upstream compatibility bits
|
||||
|
||||
---
|
||||
hw/arm/virt.c | 1 +
|
||||
hw/core/machine.c | 17 +++++++++++++++++
|
||||
hw/i386/pc_piix.c | 2 ++
|
||||
hw/i386/pc_q35.c | 2 ++
|
||||
hw/s390x/s390-virtio-ccw.c | 1 +
|
||||
include/hw/boards.h | 3 +++
|
||||
6 files changed, 26 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 903c0f2e9f..3374d3b0bc 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3582,6 +3582,7 @@ DEFINE_VIRT_MACHINE(2, 6)
|
||||
|
||||
static void virt_rhel_machine_9_4_0_options(MachineClass *mc)
|
||||
{
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_10_0, hw_compat_rhel_10_0_len);
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
}
|
||||
DEFINE_VIRT_MACHINE_AS_LATEST(9, 4, 0)
|
||||
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||
index f7fed78e4b..9cf8242b32 100644
|
||||
--- a/hw/core/machine.c
|
||||
+++ b/hw/core/machine.c
|
||||
@@ -311,6 +311,23 @@ const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1);
|
||||
const char *rhel_old_machine_deprecation =
|
||||
"machine types for previous major releases are deprecated";
|
||||
|
||||
+GlobalProperty hw_compat_rhel_10_0[] = {
|
||||
+ /* hw_compat_rhel_10_0 from hw_compat_9_0 */
|
||||
+ {"arm-cpu", "backcompat-cntfrq", "true" },
|
||||
+ /* hw_compat_rhel_10_0 from hw_compat_9_0 */
|
||||
+ { "scsi-hd", "migrate-emulated-scsi-request", "false" },
|
||||
+ /* hw_compat_rhel_10_0 from hw_compat_9_0 */
|
||||
+ { "scsi-cd", "migrate-emulated-scsi-request", "false" },
|
||||
+ /* hw_compat_rhel_10_0 from hw_compat_9_0 */
|
||||
+ {"vfio-pci", "skip-vsc-check", "false" },
|
||||
+ /* hw_compat_rhel_10_0 from hw_compat_9_0 */
|
||||
+ { "virtio-pci", "x-pcie-pm-no-soft-reset", "off" },
|
||||
+ /* hw_compat_rhel_10_0 from hw_compat_9_0 */
|
||||
+ {"sd-card", "spec_version", "2" },
|
||||
+};
|
||||
+const size_t hw_compat_rhel_10_0_len = G_N_ELEMENTS(hw_compat_rhel_10_0);
|
||||
+
|
||||
+
|
||||
GlobalProperty hw_compat_rhel_9_5[] = {
|
||||
/* hw_compat_rhel_9_5 from hw_compat_8_2 */
|
||||
{ "migration", "zero-page-detection", "legacy"},
|
||||
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||
index 5535e1ffbf..447f98b438 100644
|
||||
--- a/hw/i386/pc_piix.c
|
||||
+++ b/hw/i386/pc_piix.c
|
||||
@@ -879,6 +879,8 @@ static void pc_i440fx_rhel_machine_7_6_0_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, hw_compat_rhel_10_0,
|
||||
+ hw_compat_rhel_10_0_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 2ca9ff3747..849b231a74 100644
|
||||
--- a/hw/i386/pc_q35.c
|
||||
+++ b/hw/i386/pc_q35.c
|
||||
@@ -680,6 +680,8 @@ static void pc_q35_rhel_machine_9_4_0_options(MachineClass *m)
|
||||
pcmc->smbios_stream_product = "RHEL";
|
||||
pcmc->smbios_stream_version = "9.4.0";
|
||||
|
||||
+ compat_props_add(m->compat_props, hw_compat_rhel_10_0,
|
||||
+ hw_compat_rhel_10_0_len);
|
||||
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||
hw_compat_rhel_9_5_len);
|
||||
}
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index 451017c50e..5db5fed1bf 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -1316,6 +1316,7 @@ static void ccw_rhel_machine_9_4_0_instance_options(MachineState *machine)
|
||||
|
||||
static void ccw_rhel_machine_9_4_0_class_options(MachineClass *mc)
|
||||
{
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_10_0, hw_compat_rhel_10_0_len);
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
}
|
||||
DEFINE_CCW_MACHINE_AS_LATEST(9, 4, 0);
|
||||
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||
index 3dea5cee73..6d98aaf4c7 100644
|
||||
--- a/include/hw/boards.h
|
||||
+++ b/include/hw/boards.h
|
||||
@@ -802,6 +802,9 @@ extern const size_t hw_compat_2_2_len;
|
||||
extern GlobalProperty hw_compat_2_1[];
|
||||
extern const size_t hw_compat_2_1_len;
|
||||
|
||||
+extern GlobalProperty hw_compat_rhel_10_0[];
|
||||
+extern const size_t hw_compat_rhel_10_0_len;
|
||||
+
|
||||
extern GlobalProperty hw_compat_rhel_9_5[];
|
||||
extern const size_t hw_compat_rhel_9_5_len;
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,37 @@
|
||||
From d27437e5baba347cb3392280399d402414dcb21c Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Mon, 26 Aug 2024 14:27:49 +0200
|
||||
Subject: redhat: Add QEMU 9.1 compat handling to the s390x machine types
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-52319
|
||||
|
||||
Upstream changed the amount of information that is migrated for
|
||||
the S390 interrupt controller (FLIC), so we have to switch on
|
||||
a compatibility property for older machine types.
|
||||
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
---
|
||||
hw/s390x/s390-virtio-ccw.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index 5db5fed1bf..feef81ed8b 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -1316,8 +1316,13 @@ static void ccw_rhel_machine_9_4_0_instance_options(MachineState *machine)
|
||||
|
||||
static void ccw_rhel_machine_9_4_0_class_options(MachineClass *mc)
|
||||
{
|
||||
+ static GlobalProperty compat[] = {
|
||||
+ { TYPE_QEMU_S390_FLIC, "migrate-all-state", "off", },
|
||||
+ };
|
||||
+
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_10_0, hw_compat_rhel_10_0_len);
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||
}
|
||||
DEFINE_CCW_MACHINE_AS_LATEST(9, 4, 0);
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,66 @@
|
||||
From 926a9d0ca2437b4c4270062f707ed24284ad469f Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Mon, 26 Aug 2024 14:42:24 +0200
|
||||
Subject: redhat: Add rhel9.6.0 and rhel10.0.0 machine types
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-52319
|
||||
|
||||
Add a new machine types to enable the latest features by default.
|
||||
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
---
|
||||
hw/s390x/s390-virtio-ccw.c | 25 ++++++++++++++++++++++++-
|
||||
1 file changed, 24 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index feef81ed8b..b61392bac1 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -1310,8 +1310,29 @@ DEFINE_CCW_MACHINE(2, 4);
|
||||
#endif
|
||||
#endif /* disabled for RHEL */
|
||||
|
||||
+static void ccw_rhel_machine_10_0_0_instance_options(MachineState *machine)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static void ccw_rhel_machine_10_0_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE_AS_LATEST(10, 0, 0);
|
||||
+
|
||||
+static void ccw_rhel_machine_9_6_0_instance_options(MachineState *machine)
|
||||
+{
|
||||
+ ccw_rhel_machine_10_0_0_instance_options(machine);
|
||||
+}
|
||||
+
|
||||
+static void ccw_rhel_machine_9_6_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ ccw_rhel_machine_10_0_0_class_options(mc);
|
||||
+}
|
||||
+DEFINE_CCW_MACHINE(9, 6, 0);
|
||||
+
|
||||
static void ccw_rhel_machine_9_4_0_instance_options(MachineState *machine)
|
||||
{
|
||||
+ ccw_rhel_machine_9_6_0_instance_options(machine);
|
||||
}
|
||||
|
||||
static void ccw_rhel_machine_9_4_0_class_options(MachineClass *mc)
|
||||
@@ -1320,11 +1341,13 @@ static void ccw_rhel_machine_9_4_0_class_options(MachineClass *mc)
|
||||
{ TYPE_QEMU_S390_FLIC, "migrate-all-state", "off", },
|
||||
};
|
||||
|
||||
+ ccw_rhel_machine_9_6_0_class_options(mc);
|
||||
+
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_10_0, hw_compat_rhel_10_0_len);
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
|
||||
}
|
||||
-DEFINE_CCW_MACHINE_AS_LATEST(9, 4, 0);
|
||||
+DEFINE_CCW_MACHINE(9, 4, 0);
|
||||
|
||||
static void ccw_rhel_machine_9_2_0_instance_options(MachineState *machine)
|
||||
{
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,28 @@
|
||||
From 6be70c681bf7a1b9666ed5896b5be8be7df2bf50 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Ott <sebott@redhat.com>
|
||||
Date: Wed, 4 Sep 2024 15:46:53 +0200
|
||||
Subject: x86: ensure compatibility of pc-q35-rhel9*
|
||||
|
||||
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||
---
|
||||
hw/i386/pc_q35.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||
index 849b231a74..a05df61cfc 100644
|
||||
--- a/hw/i386/pc_q35.c
|
||||
+++ b/hw/i386/pc_q35.c
|
||||
@@ -680,6 +680,10 @@ static void pc_q35_rhel_machine_9_4_0_options(MachineClass *m)
|
||||
pcmc->smbios_stream_product = "RHEL";
|
||||
pcmc->smbios_stream_version = "9.4.0";
|
||||
|
||||
+ /* From pc_q35_machine_9_0_options() */
|
||||
+ pcmc->isa_bios_alias = false;
|
||||
+ m->smbios_memory_device_size = 16 * GiB;
|
||||
+
|
||||
compat_props_add(m->compat_props, hw_compat_rhel_10_0,
|
||||
hw_compat_rhel_10_0_len);
|
||||
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,27 @@
|
||||
From 17c3bccf2f2804772ab60bf4f04d7437f13ed48a Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Ott <sebott@redhat.com>
|
||||
Date: Wed, 4 Sep 2024 15:52:00 +0200
|
||||
Subject: arm: ensure compatibility of virt-rhel9*
|
||||
|
||||
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||
---
|
||||
hw/arm/virt.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 3374d3b0bc..31a71a7f45 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3582,6 +3582,9 @@ DEFINE_VIRT_MACHINE(2, 6)
|
||||
|
||||
static void virt_rhel_machine_9_4_0_options(MachineClass *mc)
|
||||
{
|
||||
+ /* From virt_machine_9_0_options() */
|
||||
+ mc->smbios_memory_device_size = 16 * GiB;
|
||||
+
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_10_0, hw_compat_rhel_10_0_len);
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
}
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,507 @@
|
||||
From eb742e8a7c75e3be5c158cb19185d9cf6ae4862c Mon Sep 17 00:00:00 2001
|
||||
From: eabdullin <ed.abdullin.1@gmail.com>
|
||||
Date: Tue, 15 Oct 2024 10:48:05 +0300
|
||||
Subject: [PATCH] Add ppc64 support
|
||||
|
||||
---
|
||||
.../ppc64-softmmu/ppc64-rh-devices.mak | 39 ++++++
|
||||
hw/ppc/spapr.c | 125 +++++++++++++++++-
|
||||
hw/ppc/spapr_cpu_core.c | 16 +++
|
||||
include/hw/ppc/spapr.h | 3 +
|
||||
target/ppc/compat.c | 11 ++
|
||||
target/ppc/cpu-models.c | 9 +-
|
||||
target/ppc/cpu.h | 1 +
|
||||
target/ppc/kvm.c | 27 ++++
|
||||
target/ppc/kvm_ppc.h | 13 ++
|
||||
9 files changed, 237 insertions(+), 7 deletions(-)
|
||||
create mode 100644 configs/devices/ppc64-softmmu/ppc64-rh-devices.mak
|
||||
|
||||
diff --git a/configs/devices/ppc64-softmmu/ppc64-rh-devices.mak b/configs/devices/ppc64-softmmu/ppc64-rh-devices.mak
|
||||
new file mode 100644
|
||||
index 000000000..4b801b126
|
||||
--- /dev/null
|
||||
+++ b/configs/devices/ppc64-softmmu/ppc64-rh-devices.mak
|
||||
@@ -0,0 +1,39 @@
|
||||
+include ../rh-virtio.mak
|
||||
+
|
||||
+CONFIG_DIMM=y
|
||||
+CONFIG_MEM_DEVICE=y
|
||||
+CONFIG_NVDIMM=y
|
||||
+CONFIG_PCI=y
|
||||
+CONFIG_PCI_DEVICES=y
|
||||
+CONFIG_PCI_TESTDEV=y
|
||||
+CONFIG_PCI_EXPRESS=y
|
||||
+CONFIG_PSERIES=y
|
||||
+CONFIG_SCSI=y
|
||||
+CONFIG_SPAPR_VSCSI=y
|
||||
+CONFIG_TEST_DEVICES=y
|
||||
+CONFIG_USB=y
|
||||
+CONFIG_USB_OHCI=y
|
||||
+CONFIG_USB_OHCI_PCI=y
|
||||
+CONFIG_USB_SMARTCARD=y
|
||||
+CONFIG_USB_STORAGE_CORE=y
|
||||
+CONFIG_USB_STORAGE_CLASSIC=y
|
||||
+CONFIG_USB_XHCI=y
|
||||
+CONFIG_USB_XHCI_NEC=y
|
||||
+CONFIG_USB_XHCI_PCI=y
|
||||
+CONFIG_USB_HUB=y
|
||||
+CONFIG_USB_HID=y
|
||||
+CONFIG_VFIO=y
|
||||
+CONFIG_VFIO_PCI=y
|
||||
+CONFIG_VGA=y
|
||||
+CONFIG_VGA_PCI=y
|
||||
+CONFIG_VHOST_USER=y
|
||||
+CONFIG_VIRTIO_PCI=y
|
||||
+CONFIG_VIRTIO_VGA=y
|
||||
+CONFIG_WDT_IB6300ESB=y
|
||||
+CONFIG_XICS=y
|
||||
+CONFIG_XIVE=y
|
||||
+CONFIG_TPM=y
|
||||
+CONFIG_TPM_SPAPR=y
|
||||
+CONFIG_TPM_EMULATOR=y
|
||||
+CONFIG_VHOST_VSOCK=y
|
||||
+CONFIG_VHOST_USER_VSOCK=y
|
||||
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
|
||||
index 370d7c35d..aed36a4de 100644
|
||||
--- a/hw/ppc/spapr.c
|
||||
+++ b/hw/ppc/spapr.c
|
||||
@@ -1746,6 +1746,13 @@ static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
|
||||
}
|
||||
spapr_caps_apply(spapr);
|
||||
spapr_nested_reset(spapr);
|
||||
+ if (spapr->svm_allowed) {
|
||||
+#ifdef CONFIG_KVM
|
||||
+ kvmppc_svm_allow(&error_fatal);
|
||||
+#else
|
||||
+ error_setg(&error_fatal, "No PEF support in tcg, try x-svm-allowed=off");
|
||||
+#endif
|
||||
+ }
|
||||
|
||||
first_ppc_cpu = POWERPC_CPU(first_cpu);
|
||||
if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
|
||||
@@ -3452,6 +3459,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);
|
||||
@@ -3530,6 +3551,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)
|
||||
@@ -4775,6 +4802,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 = {
|
||||
@@ -4830,13 +4858,14 @@ static void spapr_machine_latest_class_options(MachineClass *mc)
|
||||
} \
|
||||
type_init(MACHINE_VER_SYM(register, spapr, __VA_ARGS__))
|
||||
|
||||
-#define DEFINE_SPAPR_MACHINE_AS_LATEST(major, minor) \
|
||||
- DEFINE_SPAPR_MACHINE_IMPL(true, major, minor)
|
||||
-#define DEFINE_SPAPR_MACHINE(major, minor) \
|
||||
- DEFINE_SPAPR_MACHINE_IMPL(false, major, minor)
|
||||
-#define DEFINE_SPAPR_MACHINE_TAGGED(major, minor, tag) \
|
||||
- DEFINE_SPAPR_MACHINE_IMPL(false, major, minor, _, tag)
|
||||
+#define DEFINE_SPAPR_MACHINE_AS_LATEST(major, minor, micro) \
|
||||
+ DEFINE_SPAPR_MACHINE_IMPL(true, major, minor, micro)
|
||||
+#define DEFINE_SPAPR_MACHINE(major, minor, micro) \
|
||||
+ DEFINE_SPAPR_MACHINE_IMPL(false, major, minor, micro)
|
||||
+#define DEFINE_SPAPR_MACHINE_TAGGED(major, minor, micro, tag) \
|
||||
+ DEFINE_SPAPR_MACHINE_IMPL(false, major, minor, micro, _, tag)
|
||||
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
/*
|
||||
* pseries-9.1
|
||||
*/
|
||||
@@ -5056,6 +5085,9 @@ static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
+#endif
|
||||
+
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
static void spapr_machine_4_0_class_options(MachineClass *mc)
|
||||
{
|
||||
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||
@@ -5380,6 +5412,87 @@ 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);
|
||||
+#endif /* disabled for RHEL */
|
||||
+
|
||||
+static void spapr_rhel_machine_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;
|
||||
+}
|
||||
+
|
||||
+static void spapr_rhel_machine_10_0_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
||||
+
|
||||
+ /* The default machine type must apply the RHEL specific defaults */
|
||||
+ spapr_rhel_machine_default_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_10_0,
|
||||
+ hw_compat_rhel_10_0_len);
|
||||
+ smc->pre_6_2_numa_affinity = true;
|
||||
+ mc->smp_props.prefer_sockets = true;
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE_AS_LATEST(10, 0, 0);
|
||||
+
|
||||
+static void spapr_rhel_machine_9_5_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ spapr_rhel_machine_10_0_0_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_5,
|
||||
+ hw_compat_rhel_9_5_len);
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE(9, 5, 0);
|
||||
+
|
||||
+static void spapr_rhel_machine_9_4_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ spapr_rhel_machine_9_5_0_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_4,
|
||||
+ hw_compat_rhel_9_4_len);
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE(9, 4, 0);
|
||||
+
|
||||
+static void spapr_rhel_machine_9_3_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ spapr_rhel_machine_9_4_0_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_3,
|
||||
+ hw_compat_rhel_9_3_len);
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE(9, 3, 0);
|
||||
+
|
||||
+static void spapr_rhel_machine_9_2_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ spapr_rhel_machine_9_3_0_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_2,
|
||||
+ hw_compat_rhel_9_2_len);
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE(9, 2, 0);
|
||||
+
|
||||
+static void spapr_rhel_machine_9_1_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ spapr_rhel_machine_9_2_0_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_1,
|
||||
+ hw_compat_rhel_9_1_len);
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE(9, 1, 0);
|
||||
+
|
||||
+static void spapr_rhel_machine_9_0_0_class_options(MachineClass *mc)
|
||||
+{
|
||||
+ spapr_rhel_machine_9_1_0_class_options(mc);
|
||||
+ compat_props_add(mc->compat_props, hw_compat_rhel_9_0,
|
||||
+ hw_compat_rhel_9_0_len);
|
||||
+}
|
||||
+
|
||||
+DEFINE_SPAPR_MACHINE(9, 0, 0);
|
||||
+
|
||||
|
||||
static void spapr_machine_register_types(void)
|
||||
{
|
||||
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
|
||||
index 56090abcd..e3371b24f 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,18 @@ 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;
|
||||
@@ -399,10 +413,12 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
|
||||
.instance_size = sizeof(SpaprCpuCore),
|
||||
.class_size = sizeof(SpaprCpuCoreClass),
|
||||
},
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
DEFINE_SPAPR_CPU_CORE_TYPE("970_v2.2"),
|
||||
DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.0"),
|
||||
DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.1"),
|
||||
DEFINE_SPAPR_CPU_CORE_TYPE("power5p_v2.1"),
|
||||
+#endif
|
||||
DEFINE_SPAPR_CPU_CORE_TYPE("power7_v2.3"),
|
||||
DEFINE_SPAPR_CPU_CORE_TYPE("power7p_v2.1"),
|
||||
DEFINE_SPAPR_CPU_CORE_TYPE("power8_v2.0"),
|
||||
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
|
||||
index f6de3e997..3cc7ef0c0 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,
|
||||
@@ -258,6 +259,8 @@ struct SpaprMachineState {
|
||||
|
||||
/* Set by -boot */
|
||||
char *boot_device;
|
||||
+ /* Secure Guest support via x-svm-allowed */
|
||||
+ bool svm_allowed;
|
||||
|
||||
/*< public >*/
|
||||
char *kvm_type;
|
||||
diff --git a/target/ppc/compat.c b/target/ppc/compat.c
|
||||
index ebef2ccce..ab7ed7680 100644
|
||||
--- a/target/ppc/compat.c
|
||||
+++ b/target/ppc/compat.c
|
||||
@@ -114,6 +114,17 @@ 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)
|
||||
{
|
||||
diff --git a/target/ppc/cpu-models.c b/target/ppc/cpu-models.c
|
||||
index f2301b43f..4c38fa517 100644
|
||||
--- a/target/ppc/cpu-models.c
|
||||
+++ b/target/ppc/cpu-models.c
|
||||
@@ -66,6 +66,7 @@
|
||||
#define POWERPC_DEF(_name, _pvr, _type, _desc) \
|
||||
POWERPC_DEF_SVR(_name, _desc, _pvr, POWERPC_SVR_NONE, _type)
|
||||
|
||||
+#if 0 /* Embedded and 32-bit CPUs disabled for Red Hat Enterprise Linux */
|
||||
/* Embedded PowerPC */
|
||||
/* PowerPC 405 family */
|
||||
/* PowerPC 405 cores */
|
||||
@@ -698,8 +699,10 @@
|
||||
"PowerPC 7447A v1.2 (G4)")
|
||||
POWERPC_DEF("7457a_v1.2", CPU_POWERPC_74x7A_v12, 7455,
|
||||
"PowerPC 7457A v1.2 (G4)")
|
||||
+#endif
|
||||
/* 64 bits PowerPC */
|
||||
#if defined(TARGET_PPC64)
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970,
|
||||
"PowerPC 970 v2.2")
|
||||
POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970,
|
||||
@@ -718,6 +721,7 @@
|
||||
"PowerPC 970MP v1.1")
|
||||
POWERPC_DEF("power5p_v2.1", CPU_POWERPC_POWER5P_v21, POWER5P,
|
||||
"POWER5+ v2.1")
|
||||
+#endif
|
||||
POWERPC_DEF("power7_v2.3", CPU_POWERPC_POWER7_v23, POWER7,
|
||||
"POWER7 v2.3")
|
||||
POWERPC_DEF("power7p_v2.1", CPU_POWERPC_POWER7P_v21, POWER7,
|
||||
@@ -895,12 +899,14 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
|
||||
{ "7457a", "7457a_v1.2" },
|
||||
{ "apollo7pm", "7457a_v1.0" },
|
||||
#if defined(TARGET_PPC64)
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
{ "970", "970_v2.2" },
|
||||
{ "970fx", "970fx_v3.1" },
|
||||
{ "970mp", "970mp_v1.1" },
|
||||
{ "power5+", "power5p_v2.1" },
|
||||
{ "power5+_v2.1", "power5p_v2.1" },
|
||||
{ "power5gs", "power5+_v2.1" },
|
||||
+#endif
|
||||
{ "power7", "power7_v2.3" },
|
||||
{ "power7+", "power7p_v2.1" },
|
||||
{ "power7+_v2.1", "power7p_v2.1" },
|
||||
@@ -910,13 +916,14 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
|
||||
{ "power9", "power9_v2.2" },
|
||||
{ "power10", "power10_v2.0" },
|
||||
#endif
|
||||
-
|
||||
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||
/* Generic PowerPCs */
|
||||
#if defined(TARGET_PPC64)
|
||||
{ "ppc64", "970fx_v3.1" },
|
||||
#endif
|
||||
{ "ppc32", "604" },
|
||||
{ "ppc", "604" },
|
||||
+#endif
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
|
||||
index 321ed2da7..e35a99762 100644
|
||||
--- a/target/ppc/cpu.h
|
||||
+++ b/target/ppc/cpu.h
|
||||
@@ -1673,6 +1673,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 907dba60d..c942ff55b 100644
|
||||
--- a/target/ppc/kvm.c
|
||||
+++ b/target/ppc/kvm.c
|
||||
@@ -92,6 +92,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;
|
||||
|
||||
#ifdef CONFIG_PSERIES
|
||||
static int cap_papr;
|
||||
@@ -150,6 +151,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);
|
||||
/*
|
||||
@@ -2597,6 +2599,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();
|
||||
@@ -3012,3 +3024,18 @@ static void kvm_cpu_accel_register_types(void)
|
||||
type_register_static(&kvm_cpu_accel_type_info);
|
||||
}
|
||||
type_init(kvm_cpu_accel_register_types);
|
||||
+
|
||||
+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 1975fb5ee..d1017f98b 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.5 (Apple Git-154)
|
@ -0,0 +1,21 @@
|
||||
From 32c5296efbb9e9a4e7ede9591e37bd307f3b1ced Mon Sep 17 00:00:00 2001
|
||||
From: Andrew Lukoshko <alukoshko@almalinux.org>
|
||||
Date: Sat, 26 Oct 2024 20:09:06 +0000
|
||||
Subject: [PATCH] Enable QXL device build
|
||||
|
||||
---
|
||||
configs/devices/x86_64-softmmu/x86_64-rh-devices.mak | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
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 45a8a1529..2769c1eb4 100644
|
||||
--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
||||
+++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
||||
@@ -112,3 +112,4 @@ CONFIG_VHOST_USER_VSOCK=y
|
||||
CONFIG_VHOST_USER_FS=y
|
||||
CONFIG_IOMMUFD=y
|
||||
CONFIG_VHOST_USER_SND=y
|
||||
+CONFIG_QXL=y
|
||||
--
|
||||
2.43.5
|
||||
|
@ -1,139 +0,0 @@
|
||||
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,50 @@
|
||||
From 111d70a5bdc3ee0dde0a6def9e0c75ed20b4f093 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Xu <peterx@redhat.com>
|
||||
Date: Tue, 17 Sep 2024 12:38:33 -0400
|
||||
Subject: [PATCH 6/9] KVM: Define KVM_MEMSLOTS_NUM_MAX_DEFAULT
|
||||
|
||||
RH-Author: Peter Xu <peterx@redhat.com>
|
||||
RH-MergeRequest: 285: KVM: Dynamic sized kvm memslots array
|
||||
RH-Jira: RHEL-57685
|
||||
RH-Acked-by: Juraj Marcin <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [5/7] e4c2a2c2f3a809c8efb709521c7a94ba0627c69b (peterx/qemu-kvm)
|
||||
|
||||
Make the default max nr_slots a macro, it's only used when KVM reports
|
||||
nothing.
|
||||
|
||||
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20240917163835.194664-3-peterx@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit b34a908c8f24eedb0a8e5ff486b059b58fd793f4)
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 38393bc86b..87db0f9494 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -71,6 +71,8 @@
|
||||
|
||||
/* Default num of memslots to be allocated when VM starts */
|
||||
#define KVM_MEMSLOTS_NR_ALLOC_DEFAULT 16
|
||||
+/* Default max allowed memslots if kernel reported nothing */
|
||||
+#define KVM_MEMSLOTS_NR_MAX_DEFAULT 32
|
||||
|
||||
struct KVMParkedVcpu {
|
||||
unsigned long vcpu_id;
|
||||
@@ -2617,7 +2619,7 @@ static int kvm_init(MachineState *ms)
|
||||
|
||||
/* If unspecified, use the default value */
|
||||
if (!s->nr_slots) {
|
||||
- s->nr_slots = 32;
|
||||
+ s->nr_slots_max = KVM_MEMSLOTS_NR_MAX_DEFAULT;
|
||||
}
|
||||
|
||||
s->nr_as = kvm_check_extension(s, KVM_CAP_MULTI_ADDRESS_SPACE);
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,251 @@
|
||||
From c77a30265b8d0db43174b040ea82103f8fdb9911 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Xu <peterx@redhat.com>
|
||||
Date: Tue, 17 Sep 2024 12:38:32 -0400
|
||||
Subject: [PATCH 5/9] KVM: Dynamic sized kvm memslots array
|
||||
|
||||
RH-Author: Peter Xu <peterx@redhat.com>
|
||||
RH-MergeRequest: 285: KVM: Dynamic sized kvm memslots array
|
||||
RH-Jira: RHEL-57685
|
||||
RH-Acked-by: Juraj Marcin <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [4/7] 46d4abec352a92112e593ea61b7cbf5ce5f94cdc (peterx/qemu-kvm)
|
||||
|
||||
Zhiyi reported an infinite loop issue in VFIO use case. The cause of that
|
||||
was a separate discussion, however during that I found a regression of
|
||||
dirty sync slowness when profiling.
|
||||
|
||||
Each KVMMemoryListerner maintains an array of kvm memslots. Currently it's
|
||||
statically allocated to be the max supported by the kernel. However after
|
||||
Linux commit 4fc096a99e ("KVM: Raise the maximum number of user memslots"),
|
||||
the max supported memslots reported now grows to some number large enough
|
||||
so that it may not be wise to always statically allocate with the max
|
||||
reported.
|
||||
|
||||
What's worse, QEMU kvm code still walks all the allocated memslots entries
|
||||
to do any form of lookups. It can drastically slow down all memslot
|
||||
operations because each of such loop can run over 32K times on the new
|
||||
kernels.
|
||||
|
||||
Fix this issue by making the memslots to be allocated dynamically.
|
||||
|
||||
Here the initial size was set to 16 because it should cover the basic VM
|
||||
usages, so that the hope is the majority VM use case may not even need to
|
||||
grow at all (e.g. if one starts a VM with ./qemu-system-x86_64 by default
|
||||
it'll consume 9 memslots), however not too large to waste memory.
|
||||
|
||||
There can also be even better way to address this, but so far this is the
|
||||
simplest and should be already better even than before we grow the max
|
||||
supported memslots. For example, in the case of above issue when VFIO was
|
||||
attached on a 32GB system, there are only ~10 memslots used. So it could
|
||||
be good enough as of now.
|
||||
|
||||
In the above VFIO context, measurement shows that the precopy dirty sync
|
||||
shrinked from ~86ms to ~3ms after this patch applied. It should also apply
|
||||
to any KVM enabled VM even without VFIO.
|
||||
|
||||
NOTE: we don't have a FIXES tag for this patch because there's no real
|
||||
commit that regressed this in QEMU. Such behavior existed for a long time,
|
||||
but only start to be a problem when the kernel reports very large
|
||||
nr_slots_max value. However that's pretty common now (the kernel change
|
||||
was merged in 2021) so we attached cc:stable because we'll want this change
|
||||
to be backported to stable branches.
|
||||
|
||||
Cc: qemu-stable <qemu-stable@nongnu.org>
|
||||
Reported-by: Zhiyi Guo <zhguo@redhat.com>
|
||||
Tested-by: Zhiyi Guo <zhguo@redhat.com>
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
Acked-by: David Hildenbrand <david@redhat.com>
|
||||
Reviewed-by: Fabiano Rosas <farosas@suse.de>
|
||||
Link: https://lore.kernel.org/r/20240917163835.194664-2-peterx@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit 5504a8126115d173687b37e657312a8ffe29fc0c)
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 87 +++++++++++++++++++++++++++++++++-------
|
||||
accel/kvm/trace-events | 1 +
|
||||
include/sysemu/kvm_int.h | 1 +
|
||||
3 files changed, 74 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 8187ad3964..38393bc86b 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -69,6 +69,9 @@
|
||||
#define KVM_GUESTDBG_BLOCKIRQ 0
|
||||
#endif
|
||||
|
||||
+/* Default num of memslots to be allocated when VM starts */
|
||||
+#define KVM_MEMSLOTS_NR_ALLOC_DEFAULT 16
|
||||
+
|
||||
struct KVMParkedVcpu {
|
||||
unsigned long vcpu_id;
|
||||
int kvm_fd;
|
||||
@@ -165,6 +168,57 @@ void kvm_resample_fd_notify(int gsi)
|
||||
}
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * kvm_slots_grow(): Grow the slots[] array in the KVMMemoryListener
|
||||
+ *
|
||||
+ * @kml: The KVMMemoryListener* to grow the slots[] array
|
||||
+ * @nr_slots_new: The new size of slots[] array
|
||||
+ *
|
||||
+ * Returns: True if the array grows larger, false otherwise.
|
||||
+ */
|
||||
+static bool kvm_slots_grow(KVMMemoryListener *kml, unsigned int nr_slots_new)
|
||||
+{
|
||||
+ unsigned int i, cur = kml->nr_slots_allocated;
|
||||
+ KVMSlot *slots;
|
||||
+
|
||||
+ if (nr_slots_new > kvm_state->nr_slots) {
|
||||
+ nr_slots_new = kvm_state->nr_slots;
|
||||
+ }
|
||||
+
|
||||
+ if (cur >= nr_slots_new) {
|
||||
+ /* Big enough, no need to grow, or we reached max */
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (cur == 0) {
|
||||
+ slots = g_new0(KVMSlot, nr_slots_new);
|
||||
+ } else {
|
||||
+ assert(kml->slots);
|
||||
+ slots = g_renew(KVMSlot, kml->slots, nr_slots_new);
|
||||
+ /*
|
||||
+ * g_renew() doesn't initialize extended buffers, however kvm
|
||||
+ * memslots require fields to be zero-initialized. E.g. pointers,
|
||||
+ * memory_size field, etc.
|
||||
+ */
|
||||
+ memset(&slots[cur], 0x0, sizeof(slots[0]) * (nr_slots_new - cur));
|
||||
+ }
|
||||
+
|
||||
+ for (i = cur; i < nr_slots_new; i++) {
|
||||
+ slots[i].slot = i;
|
||||
+ }
|
||||
+
|
||||
+ kml->slots = slots;
|
||||
+ kml->nr_slots_allocated = nr_slots_new;
|
||||
+ trace_kvm_slots_grow(cur, nr_slots_new);
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool kvm_slots_double(KVMMemoryListener *kml)
|
||||
+{
|
||||
+ return kvm_slots_grow(kml, kml->nr_slots_allocated * 2);
|
||||
+}
|
||||
+
|
||||
unsigned int kvm_get_max_memslots(void)
|
||||
{
|
||||
KVMState *s = KVM_STATE(current_accel());
|
||||
@@ -193,15 +247,26 @@ unsigned int kvm_get_free_memslots(void)
|
||||
/* Called with KVMMemoryListener.slots_lock held */
|
||||
static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
|
||||
{
|
||||
- KVMState *s = kvm_state;
|
||||
+ unsigned int n;
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < s->nr_slots; i++) {
|
||||
+ for (i = 0; i < kml->nr_slots_allocated; i++) {
|
||||
if (kml->slots[i].memory_size == 0) {
|
||||
return &kml->slots[i];
|
||||
}
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * If no free slots, try to grow first by doubling. Cache the old size
|
||||
+ * here to avoid another round of search: if the grow succeeded, it
|
||||
+ * means slots[] now must have the existing "n" slots occupied,
|
||||
+ * followed by one or more free slots starting from slots[n].
|
||||
+ */
|
||||
+ n = kml->nr_slots_allocated;
|
||||
+ if (kvm_slots_double(kml)) {
|
||||
+ return &kml->slots[n];
|
||||
+ }
|
||||
+
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -222,10 +287,9 @@ static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
|
||||
hwaddr start_addr,
|
||||
hwaddr size)
|
||||
{
|
||||
- KVMState *s = kvm_state;
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < s->nr_slots; i++) {
|
||||
+ for (i = 0; i < kml->nr_slots_allocated; i++) {
|
||||
KVMSlot *mem = &kml->slots[i];
|
||||
|
||||
if (start_addr == mem->start_addr && size == mem->memory_size) {
|
||||
@@ -267,7 +331,7 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
|
||||
int i, ret = 0;
|
||||
|
||||
kvm_slots_lock();
|
||||
- for (i = 0; i < s->nr_slots; i++) {
|
||||
+ for (i = 0; i < kml->nr_slots_allocated; i++) {
|
||||
KVMSlot *mem = &kml->slots[i];
|
||||
|
||||
if (ram >= mem->ram && ram < mem->ram + mem->memory_size) {
|
||||
@@ -1071,7 +1135,7 @@ static int kvm_physical_log_clear(KVMMemoryListener *kml,
|
||||
|
||||
kvm_slots_lock();
|
||||
|
||||
- for (i = 0; i < s->nr_slots; i++) {
|
||||
+ for (i = 0; i < kml->nr_slots_allocated; i++) {
|
||||
mem = &kml->slots[i];
|
||||
/* Discard slots that are empty or do not overlap the section */
|
||||
if (!mem->memory_size ||
|
||||
@@ -1719,12 +1783,8 @@ static void kvm_log_sync_global(MemoryListener *l, bool last_stage)
|
||||
/* Flush all kernel dirty addresses into KVMSlot dirty bitmap */
|
||||
kvm_dirty_ring_flush();
|
||||
|
||||
- /*
|
||||
- * TODO: make this faster when nr_slots is big while there are
|
||||
- * only a few used slots (small VMs).
|
||||
- */
|
||||
kvm_slots_lock();
|
||||
- for (i = 0; i < s->nr_slots; i++) {
|
||||
+ for (i = 0; i < kml->nr_slots_allocated; i++) {
|
||||
mem = &kml->slots[i];
|
||||
if (mem->memory_size && mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
|
||||
kvm_slot_sync_dirty_pages(mem);
|
||||
@@ -1839,12 +1899,9 @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
|
||||
{
|
||||
int i;
|
||||
|
||||
- kml->slots = g_new0(KVMSlot, s->nr_slots);
|
||||
kml->as_id = as_id;
|
||||
|
||||
- for (i = 0; i < s->nr_slots; i++) {
|
||||
- kml->slots[i].slot = i;
|
||||
- }
|
||||
+ kvm_slots_grow(kml, KVM_MEMSLOTS_NR_ALLOC_DEFAULT);
|
||||
|
||||
QSIMPLEQ_INIT(&kml->transaction_add);
|
||||
QSIMPLEQ_INIT(&kml->transaction_del);
|
||||
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
|
||||
index 37626c1ac5..ad2ae6fca5 100644
|
||||
--- a/accel/kvm/trace-events
|
||||
+++ b/accel/kvm/trace-events
|
||||
@@ -36,3 +36,4 @@ 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
|
||||
+kvm_slots_grow(unsigned int old, unsigned int new) "%u -> %u"
|
||||
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
|
||||
index 1d8fb1473b..48e496b3d4 100644
|
||||
--- a/include/sysemu/kvm_int.h
|
||||
+++ b/include/sysemu/kvm_int.h
|
||||
@@ -46,6 +46,7 @@ typedef struct KVMMemoryListener {
|
||||
MemoryListener listener;
|
||||
KVMSlot *slots;
|
||||
unsigned int nr_used_slots;
|
||||
+ unsigned int nr_slots_allocated;
|
||||
int as_id;
|
||||
QSIMPLEQ_HEAD(, KVMMemoryUpdate) transaction_add;
|
||||
QSIMPLEQ_HEAD(, KVMMemoryUpdate) transaction_del;
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,73 @@
|
||||
From b1d082cfad79245ac0ffed45f723092388d1cf45 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Xu <peterx@redhat.com>
|
||||
Date: Tue, 17 Sep 2024 12:38:34 -0400
|
||||
Subject: [PATCH 7/9] KVM: Rename KVMMemoryListener.nr_used_slots to
|
||||
nr_slots_used
|
||||
|
||||
RH-Author: Peter Xu <peterx@redhat.com>
|
||||
RH-MergeRequest: 285: KVM: Dynamic sized kvm memslots array
|
||||
RH-Jira: RHEL-57685
|
||||
RH-Acked-by: Juraj Marcin <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [6/7] ed173123ee23edcf62a6c1940ca74cdfd6b545e9 (peterx/qemu-kvm)
|
||||
|
||||
This will make all nr_slots counters to be named in the same manner.
|
||||
|
||||
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20240917163835.194664-4-peterx@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit dbdc00ba5b136bba80d850f61cc79a9cafaae1cd)
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 6 +++---
|
||||
include/sysemu/kvm_int.h | 2 +-
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 87db0f9494..e99aaba486 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -239,7 +239,7 @@ unsigned int kvm_get_free_memslots(void)
|
||||
if (!s->as[i].ml) {
|
||||
continue;
|
||||
}
|
||||
- used_slots = MAX(used_slots, s->as[i].ml->nr_used_slots);
|
||||
+ used_slots = MAX(used_slots, s->as[i].ml->nr_slots_used);
|
||||
}
|
||||
kvm_slots_unlock();
|
||||
|
||||
@@ -1516,7 +1516,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
}
|
||||
start_addr += slot_size;
|
||||
size -= slot_size;
|
||||
- kml->nr_used_slots--;
|
||||
+ kml->nr_slots_used--;
|
||||
} while (size);
|
||||
return;
|
||||
}
|
||||
@@ -1555,7 +1555,7 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
ram_start_offset += slot_size;
|
||||
ram += slot_size;
|
||||
size -= slot_size;
|
||||
- kml->nr_used_slots++;
|
||||
+ kml->nr_slots_used++;
|
||||
} while (size);
|
||||
}
|
||||
|
||||
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
|
||||
index 48e496b3d4..b705dfc9b4 100644
|
||||
--- a/include/sysemu/kvm_int.h
|
||||
+++ b/include/sysemu/kvm_int.h
|
||||
@@ -45,7 +45,7 @@ typedef struct KVMMemoryUpdate {
|
||||
typedef struct KVMMemoryListener {
|
||||
MemoryListener listener;
|
||||
KVMSlot *slots;
|
||||
- unsigned int nr_used_slots;
|
||||
+ unsigned int nr_slots_used;
|
||||
unsigned int nr_slots_allocated;
|
||||
int as_id;
|
||||
QSIMPLEQ_HEAD(, KVMMemoryUpdate) transaction_add;
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,90 @@
|
||||
From 891fb13363d168760cd21d0c57368e1a413cad27 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Xu <peterx@redhat.com>
|
||||
Date: Tue, 17 Sep 2024 12:38:35 -0400
|
||||
Subject: [PATCH 8/9] KVM: Rename KVMState->nr_slots to nr_slots_max
|
||||
|
||||
RH-Author: Peter Xu <peterx@redhat.com>
|
||||
RH-MergeRequest: 285: KVM: Dynamic sized kvm memslots array
|
||||
RH-Jira: RHEL-57685
|
||||
RH-Acked-by: Juraj Marcin <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [7/7] 7a1b28f04ee6a2c80b07db241fc88cb40f54e376 (peterx/qemu-kvm)
|
||||
|
||||
This value used to reflect the maximum supported memslots from KVM kernel.
|
||||
Rename it to be clearer.
|
||||
|
||||
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20240917163835.194664-5-peterx@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit 943c742868c739c0b14fd996bad3adf744156fec)
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 12 ++++++------
|
||||
include/sysemu/kvm_int.h | 4 ++--
|
||||
2 files changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index e99aaba486..dc6253895d 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -183,8 +183,8 @@ static bool kvm_slots_grow(KVMMemoryListener *kml, unsigned int nr_slots_new)
|
||||
unsigned int i, cur = kml->nr_slots_allocated;
|
||||
KVMSlot *slots;
|
||||
|
||||
- if (nr_slots_new > kvm_state->nr_slots) {
|
||||
- nr_slots_new = kvm_state->nr_slots;
|
||||
+ if (nr_slots_new > kvm_state->nr_slots_max) {
|
||||
+ nr_slots_new = kvm_state->nr_slots_max;
|
||||
}
|
||||
|
||||
if (cur >= nr_slots_new) {
|
||||
@@ -225,7 +225,7 @@ unsigned int kvm_get_max_memslots(void)
|
||||
{
|
||||
KVMState *s = KVM_STATE(current_accel());
|
||||
|
||||
- return s->nr_slots;
|
||||
+ return s->nr_slots_max;
|
||||
}
|
||||
|
||||
unsigned int kvm_get_free_memslots(void)
|
||||
@@ -243,7 +243,7 @@ unsigned int kvm_get_free_memslots(void)
|
||||
}
|
||||
kvm_slots_unlock();
|
||||
|
||||
- return s->nr_slots - used_slots;
|
||||
+ return s->nr_slots_max - used_slots;
|
||||
}
|
||||
|
||||
/* Called with KVMMemoryListener.slots_lock held */
|
||||
@@ -2615,10 +2615,10 @@ static int kvm_init(MachineState *ms)
|
||||
(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);
|
||||
+ s->nr_slots_max = kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
|
||||
|
||||
/* If unspecified, use the default value */
|
||||
- if (!s->nr_slots) {
|
||||
+ if (!s->nr_slots_max) {
|
||||
s->nr_slots_max = KVM_MEMSLOTS_NR_MAX_DEFAULT;
|
||||
}
|
||||
|
||||
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
|
||||
index b705dfc9b4..2c57194b6b 100644
|
||||
--- a/include/sysemu/kvm_int.h
|
||||
+++ b/include/sysemu/kvm_int.h
|
||||
@@ -103,8 +103,8 @@ struct KVMDirtyRingReaper {
|
||||
struct KVMState
|
||||
{
|
||||
AccelState parent_obj;
|
||||
-
|
||||
- int nr_slots;
|
||||
+ /* Max number of KVM slots supported */
|
||||
+ int nr_slots_max;
|
||||
int fd;
|
||||
int vmfd;
|
||||
int coalesced_mmio;
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,203 +0,0 @@
|
||||
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
|
||||
|
@ -1,127 +0,0 @@
|
||||
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
|
||||
|
@ -1,329 +0,0 @@
|
||||
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
|
||||
|
@ -1,82 +0,0 @@
|
||||
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,76 @@
|
||||
From 5110e137294163ae43a61376485a7f610bf496f3 Mon Sep 17 00:00:00 2001
|
||||
From: Shaoqin Huang <shahuang@redhat.com>
|
||||
Date: Wed, 22 May 2024 03:23:28 -0400
|
||||
Subject: [PATCH 8/9] RH-Author: Shaoqin Huang <shahuang@redhat.com >
|
||||
RH-MergeRequest: 271: hw/arm/virt: Fix Manufacturer and Product Name in
|
||||
emulated SMBIOS mode RH-Jira: RHEL-38374 RH-Acked-by: Cornelia Huck
|
||||
<cohuck@redhat.com> RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com> RH-Commit: [8/8]
|
||||
d1daacc6ed427094cf92a9ecc66af8171950c718 (shahuang/qemu-kvm)
|
||||
|
||||
---
|
||||
hw/arm/virt.c | 15 +++++++++++++--
|
||||
include/hw/arm/virt.h | 1 +
|
||||
2 files changed, 14 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 907c26c635..078098ec3a 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -1711,14 +1711,21 @@ static void virt_build_smbios(VirtMachineState *vms)
|
||||
uint8_t *smbios_tables, *smbios_anchor;
|
||||
size_t smbios_tables_len, smbios_anchor_len;
|
||||
struct smbios_phys_mem_area mem_array;
|
||||
+ const char *manufacturer = "QEMU";
|
||||
const char *product = "QEMU Virtual Machine";
|
||||
+ const char *version = vmc->smbios_old_sys_ver ? "1.0" : mc->name;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
product = "KVM Virtual Machine";
|
||||
}
|
||||
|
||||
- smbios_set_defaults("QEMU", product,
|
||||
- vmc->smbios_old_sys_ver ? "1.0" : mc->name,
|
||||
+ if (!vmc->manufacturer_product_compat) {
|
||||
+ manufacturer = "Red Hat";
|
||||
+ product = "KVM";
|
||||
+ version = mc->desc;
|
||||
+ }
|
||||
+
|
||||
+ smbios_set_defaults(manufacturer, product, version,
|
||||
NULL, NULL);
|
||||
|
||||
/* build the array of physical mem area from base_memmap */
|
||||
@@ -3593,6 +3600,8 @@ DEFINE_VIRT_MACHINE(9, 6, 0)
|
||||
|
||||
static void virt_rhel_machine_9_4_0_options(MachineClass *mc)
|
||||
{
|
||||
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
|
||||
+
|
||||
virt_rhel_machine_9_6_0_options(mc);
|
||||
|
||||
/* From virt_machine_9_0_options() */
|
||||
@@ -3600,6 +3609,8 @@ static void virt_rhel_machine_9_4_0_options(MachineClass *mc)
|
||||
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_10_0, hw_compat_rhel_10_0_len);
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
+
|
||||
+ vmc->manufacturer_product_compat = true;
|
||||
}
|
||||
DEFINE_VIRT_MACHINE(9, 4, 0)
|
||||
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index a4d937ed45..2fc30a7626 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -134,6 +134,7 @@ struct VirtMachineClass {
|
||||
bool no_cpu_topology;
|
||||
bool no_tcg_lpa2;
|
||||
bool no_ns_el2_virt_timer_irq;
|
||||
+ bool manufacturer_product_compat;
|
||||
};
|
||||
|
||||
struct VirtMachineState {
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,67 +0,0 @@
|
||||
From d4e6f7105b00ba2536d5d733b7c03116f28ce116 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Mon, 6 May 2024 15:06:21 -0400
|
||||
Subject: [PATCH 2/5] Revert "monitor: use aio_co_reschedule_self()"
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 248: Revert "monitor: use aio_co_reschedule_self()"
|
||||
RH-Jira: RHEL-34618 RHEL-38697
|
||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/2] b6a2ebd4a69dbcd2bd56c61e7c747f8f8f42337e (kmwolf/centos-qemu-kvm)
|
||||
|
||||
Commit 1f25c172f837 ("monitor: use aio_co_reschedule_self()") was a code
|
||||
cleanup that uses aio_co_reschedule_self() instead of open coding
|
||||
coroutine rescheduling.
|
||||
|
||||
Bug RHEL-34618 was reported and Kevin Wolf <kwolf@redhat.com> identified
|
||||
the root cause. I missed that aio_co_reschedule_self() ->
|
||||
qemu_get_current_aio_context() only knows about
|
||||
qemu_aio_context/IOThread AioContexts and not about iohandler_ctx. It
|
||||
does not function correctly when going back from the iohandler_ctx to
|
||||
qemu_aio_context.
|
||||
|
||||
Go back to open coding the AioContext transitions to avoid this bug.
|
||||
|
||||
This reverts commit 1f25c172f83704e350c0829438d832384084a74d.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Buglink: https://issues.redhat.com/browse/RHEL-34618
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-ID: <20240506190622.56095-2-stefanha@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit 719c6819ed9a9838520fa732f9861918dc693bda)
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
qapi/qmp-dispatch.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
|
||||
index f3488afeef..176b549473 100644
|
||||
--- a/qapi/qmp-dispatch.c
|
||||
+++ b/qapi/qmp-dispatch.c
|
||||
@@ -212,7 +212,8 @@ QDict *coroutine_mixed_fn qmp_dispatch(const QmpCommandList *cmds, QObject *requ
|
||||
* executing the command handler so that it can make progress if it
|
||||
* involves an AIO_WAIT_WHILE().
|
||||
*/
|
||||
- aio_co_reschedule_self(qemu_get_aio_context());
|
||||
+ aio_co_schedule(qemu_get_aio_context(), qemu_coroutine_self());
|
||||
+ qemu_coroutine_yield();
|
||||
}
|
||||
|
||||
monitor_set_cur(qemu_coroutine_self(), cur_mon);
|
||||
@@ -226,7 +227,9 @@ QDict *coroutine_mixed_fn qmp_dispatch(const QmpCommandList *cmds, QObject *requ
|
||||
* Move back to iohandler_ctx so that nested event loops for
|
||||
* qemu_aio_context don't start new monitor commands.
|
||||
*/
|
||||
- aio_co_reschedule_self(iohandler_get_aio_context());
|
||||
+ aio_co_schedule(iohandler_get_aio_context(),
|
||||
+ qemu_coroutine_self());
|
||||
+ qemu_coroutine_yield();
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,38 +0,0 @@
|
||||
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,56 @@
|
||||
From 2b4558ec338adde1b9735128bb8d2f81db303a93 Mon Sep 17 00:00:00 2001
|
||||
From: Avadhut Naik <avnaik@redhat.com>
|
||||
Date: Wed, 23 Oct 2024 12:25:28 -0500
|
||||
Subject: [PATCH 01/38] accel/kvm: check for KVM_CAP_READONLY_MEM on VM
|
||||
|
||||
RH-Author: avnaik1 <None>
|
||||
RH-MergeRequest: 276: accel/kvm: check for KVM_CAP_READONLY_MEM on VM
|
||||
RH-Jira: RHEL-58928
|
||||
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||
RH-Commit: [1/1] 1d392a9e47e68bb71dc44635c494d161585a885c (avnaik1/avnaik-qemu-kvm-fork)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-58928
|
||||
|
||||
commit 64e0e63ea16aa0122dc0c41a0679da0ae4616208
|
||||
Author: Tom Dohrmann <erbse.13@gmx.de>
|
||||
Date: Tue Sep 3 06:29:53 2024 +0000
|
||||
|
||||
accel/kvm: check for KVM_CAP_READONLY_MEM on VM
|
||||
|
||||
KVM_CAP_READONLY_MEM used to be a global capability, but with the
|
||||
introduction of AMD SEV-SNP confidential VMs, this extension is not
|
||||
always available on all VM types [1,2].
|
||||
|
||||
Query the extension on the VM level instead of on the KVM level.
|
||||
|
||||
[1] https://patchwork.kernel.org/project/kvm/patch/20240809190319.1710470-2-seanjc@google.com/
|
||||
[2] https://patchwork.kernel.org/project/kvm/patch/20240902144219.3716974-1-erbse.13@gmx.de/
|
||||
|
||||
Cc: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Tom Dohrmann <erbse.13@gmx.de>
|
||||
Link: https://lore.kernel.org/r/20240903062953.3926498-1-erbse.13@gmx.de
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
|
||||
Signed-off-by: Avadhut Naik <avnaik@redhat.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 75d11a07b2..acc23092e7 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -2603,7 +2603,7 @@ static int kvm_init(MachineState *ms)
|
||||
}
|
||||
|
||||
kvm_readonly_mem_allowed =
|
||||
- (kvm_check_extension(s, KVM_CAP_READONLY_MEM) > 0);
|
||||
+ (kvm_vm_check_extension(s, KVM_CAP_READONLY_MEM) > 0);
|
||||
|
||||
kvm_resamplefds_allowed =
|
||||
(kvm_check_extension(s, KVM_CAP_IRQFD_RESAMPLE) > 0);
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,144 @@
|
||||
From 00a2dbf483a077bb31b1c9f70cced36319d22628 Mon Sep 17 00:00:00 2001
|
||||
From: Ani Sinha <anisinha@redhat.com>
|
||||
Date: Thu, 12 Sep 2024 11:48:38 +0530
|
||||
Subject: [PATCH 4/9] accel/kvm: refactor dirty ring setup
|
||||
|
||||
RH-Author: Peter Xu <peterx@redhat.com>
|
||||
RH-MergeRequest: 285: KVM: Dynamic sized kvm memslots array
|
||||
RH-Jira: RHEL-57685
|
||||
RH-Acked-by: Juraj Marcin <None>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [3/7] 94f345d1e7ad6437dd2ce67ca7cad224c67aa48f (peterx/qemu-kvm)
|
||||
|
||||
Refactor setting up of dirty ring code in kvm_init() so that is can be
|
||||
reused in the future patchsets.
|
||||
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
Link: https://lore.kernel.org/r/20240912061838.4501-1-anisinha@redhat.com
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
(cherry picked from commit 28ed7f9761eb273e7dedcfdc0507d158106d0451)
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 88 +++++++++++++++++++++++++--------------------
|
||||
1 file changed, 50 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index d86d1b515a..8187ad3964 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -2439,6 +2439,55 @@ static int find_kvm_machine_type(MachineState *ms)
|
||||
return type;
|
||||
}
|
||||
|
||||
+static int kvm_setup_dirty_ring(KVMState *s)
|
||||
+{
|
||||
+ uint64_t dirty_log_manual_caps;
|
||||
+ int ret;
|
||||
+
|
||||
+ /*
|
||||
+ * Enable KVM dirty ring if supported, otherwise fall back to
|
||||
+ * dirty logging mode
|
||||
+ */
|
||||
+ ret = kvm_dirty_ring_init(s);
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is not needed when dirty ring is
|
||||
+ * enabled. More importantly, KVM_DIRTY_LOG_INITIALLY_SET will assume no
|
||||
+ * page is wr-protected initially, which is against how kvm dirty ring is
|
||||
+ * usage - kvm dirty ring requires all pages are wr-protected at the very
|
||||
+ * beginning. Enabling this feature for dirty ring causes data corruption.
|
||||
+ *
|
||||
+ * TODO: Without KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 and kvm clear dirty log,
|
||||
+ * we may expect a higher stall time when starting the migration. In the
|
||||
+ * future we can enable KVM_CLEAR_DIRTY_LOG to work with dirty ring too:
|
||||
+ * instead of clearing dirty bit, it can be a way to explicitly wr-protect
|
||||
+ * guest pages.
|
||||
+ */
|
||||
+ if (!s->kvm_dirty_ring_size) {
|
||||
+ dirty_log_manual_caps =
|
||||
+ kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
|
||||
+ dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
|
||||
+ KVM_DIRTY_LOG_INITIALLY_SET);
|
||||
+ s->manual_dirty_log_protect = dirty_log_manual_caps;
|
||||
+ if (dirty_log_manual_caps) {
|
||||
+ ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0,
|
||||
+ dirty_log_manual_caps);
|
||||
+ if (ret) {
|
||||
+ warn_report("Trying to enable capability %"PRIu64" of "
|
||||
+ "KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. "
|
||||
+ "Falling back to the legacy mode. ",
|
||||
+ dirty_log_manual_caps);
|
||||
+ s->manual_dirty_log_protect = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int kvm_init(MachineState *ms)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
@@ -2458,7 +2507,6 @@ static int kvm_init(MachineState *ms)
|
||||
const KVMCapabilityInfo *missing_cap;
|
||||
int ret;
|
||||
int type;
|
||||
- uint64_t dirty_log_manual_caps;
|
||||
|
||||
qemu_mutex_init(&kml_slots_lock);
|
||||
|
||||
@@ -2570,47 +2618,11 @@ static int kvm_init(MachineState *ms)
|
||||
s->coalesced_pio = s->coalesced_mmio &&
|
||||
kvm_check_extension(s, KVM_CAP_COALESCED_PIO);
|
||||
|
||||
- /*
|
||||
- * Enable KVM dirty ring if supported, otherwise fall back to
|
||||
- * dirty logging mode
|
||||
- */
|
||||
- ret = kvm_dirty_ring_init(s);
|
||||
+ ret = kvm_setup_dirty_ring(s);
|
||||
if (ret < 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 is not needed when dirty ring is
|
||||
- * enabled. More importantly, KVM_DIRTY_LOG_INITIALLY_SET will assume no
|
||||
- * page is wr-protected initially, which is against how kvm dirty ring is
|
||||
- * usage - kvm dirty ring requires all pages are wr-protected at the very
|
||||
- * beginning. Enabling this feature for dirty ring causes data corruption.
|
||||
- *
|
||||
- * TODO: Without KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 and kvm clear dirty log,
|
||||
- * we may expect a higher stall time when starting the migration. In the
|
||||
- * future we can enable KVM_CLEAR_DIRTY_LOG to work with dirty ring too:
|
||||
- * instead of clearing dirty bit, it can be a way to explicitly wr-protect
|
||||
- * guest pages.
|
||||
- */
|
||||
- if (!s->kvm_dirty_ring_size) {
|
||||
- dirty_log_manual_caps =
|
||||
- kvm_check_extension(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2);
|
||||
- dirty_log_manual_caps &= (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE |
|
||||
- KVM_DIRTY_LOG_INITIALLY_SET);
|
||||
- s->manual_dirty_log_protect = dirty_log_manual_caps;
|
||||
- if (dirty_log_manual_caps) {
|
||||
- ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0,
|
||||
- dirty_log_manual_caps);
|
||||
- if (ret) {
|
||||
- warn_report("Trying to enable capability %"PRIu64" of "
|
||||
- "KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 but failed. "
|
||||
- "Falling back to the legacy mode. ",
|
||||
- dirty_log_manual_caps);
|
||||
- s->manual_dirty_log_protect = 0;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
#ifdef KVM_CAP_VCPU_EVENTS
|
||||
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
||||
#endif
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,64 +0,0 @@
|
||||
From 0e3934e89ad1dda21681f64ff38da69b07d1b531 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Date: Mon, 6 May 2024 15:06:22 -0400
|
||||
Subject: [PATCH 3/5] aio: warn about iohandler_ctx special casing
|
||||
|
||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-MergeRequest: 248: Revert "monitor: use aio_co_reschedule_self()"
|
||||
RH-Jira: RHEL-34618 RHEL-38697
|
||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [2/2] cc316d70b2c187ee0412d6560ca1a03e381a69c1 (kmwolf/centos-qemu-kvm)
|
||||
|
||||
The main loop has two AioContexts: qemu_aio_context and iohandler_ctx.
|
||||
The main loop runs them both, but nested aio_poll() calls on
|
||||
qemu_aio_context exclude iohandler_ctx.
|
||||
|
||||
Which one should qemu_get_current_aio_context() return when called from
|
||||
the main loop? Document that it's always qemu_aio_context.
|
||||
|
||||
This has subtle effects on functions that use
|
||||
qemu_get_current_aio_context(). For example, aio_co_reschedule_self()
|
||||
does not work when moving from iohandler_ctx to qemu_aio_context because
|
||||
qemu_get_current_aio_context() does not differentiate these two
|
||||
AioContexts.
|
||||
|
||||
Document this in order to reduce the chance of future bugs.
|
||||
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Message-ID: <20240506190622.56095-3-stefanha@redhat.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
(cherry picked from commit e669e800fc9ef8806af5c5578249ab758a4f8a5a)
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
---
|
||||
include/block/aio.h | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/include/block/aio.h b/include/block/aio.h
|
||||
index 8378553eb9..4ee81936ed 100644
|
||||
--- a/include/block/aio.h
|
||||
+++ b/include/block/aio.h
|
||||
@@ -629,6 +629,9 @@ void aio_co_schedule(AioContext *ctx, Coroutine *co);
|
||||
*
|
||||
* Move the currently running coroutine to new_ctx. If the coroutine is already
|
||||
* running in new_ctx, do nothing.
|
||||
+ *
|
||||
+ * Note that this function cannot reschedule from iohandler_ctx to
|
||||
+ * qemu_aio_context.
|
||||
*/
|
||||
void coroutine_fn aio_co_reschedule_self(AioContext *new_ctx);
|
||||
|
||||
@@ -661,6 +664,9 @@ void aio_co_enter(AioContext *ctx, Coroutine *co);
|
||||
* If called from an IOThread this will be the IOThread's AioContext. If
|
||||
* called from the main thread or with the "big QEMU lock" taken it
|
||||
* will be the main loop AioContext.
|
||||
+ *
|
||||
+ * Note that the return value is never the main loop's iohandler_ctx and the
|
||||
+ * return value is the main loop AioContext instead.
|
||||
*/
|
||||
AioContext *qemu_get_current_aio_context(void);
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,49 @@
|
||||
From 60d59db99f0527eaf0ce8d3a18d8333aa77a03f2 Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Ott <sebott@redhat.com>
|
||||
Date: Thu, 5 Sep 2024 13:53:13 +0200
|
||||
Subject: [PATCH 2/9] arm: create new virt machine type for rhel 9.6
|
||||
|
||||
RH-Author: Sebastian Ott <sebott@redhat.com>
|
||||
RH-MergeRequest: 270: RHEL10 machine types
|
||||
RH-Jira: RHEL-29002 RHEL-29003 RHEL-35587 RHEL-38411 RHEL-45141 RHEL-52318 RHEL-52320
|
||||
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
||||
RH-Commit: [2/7] 0179f5a7a177f53b58ff9b82bd09217e183f258b (seott1/cos-qemu-kvm)
|
||||
|
||||
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||
---
|
||||
hw/arm/virt.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index 31a71a7f45..f94be8656c 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3580,15 +3580,22 @@ static void virt_machine_2_6_options(MachineClass *mc)
|
||||
DEFINE_VIRT_MACHINE(2, 6)
|
||||
#endif /* disabled for RHEL */
|
||||
|
||||
+static void virt_rhel_machine_9_6_0_options(MachineClass *mc)
|
||||
+{
|
||||
+}
|
||||
+DEFINE_VIRT_MACHINE_AS_LATEST(9, 6, 0)
|
||||
+
|
||||
static void virt_rhel_machine_9_4_0_options(MachineClass *mc)
|
||||
{
|
||||
+ virt_rhel_machine_9_6_0_options(mc);
|
||||
+
|
||||
/* From virt_machine_9_0_options() */
|
||||
mc->smbios_memory_device_size = 16 * GiB;
|
||||
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_10_0, hw_compat_rhel_10_0_len);
|
||||
compat_props_add(mc->compat_props, hw_compat_rhel_9_5, hw_compat_rhel_9_5_len);
|
||||
}
|
||||
-DEFINE_VIRT_MACHINE_AS_LATEST(9, 4, 0)
|
||||
+DEFINE_VIRT_MACHINE(9, 4, 0)
|
||||
|
||||
static void virt_rhel_machine_9_2_0_options(MachineClass *mc)
|
||||
{
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,45 @@
|
||||
From 704596b05f7dcdfa98857b71fed295d0005d4acc Mon Sep 17 00:00:00 2001
|
||||
From: Sebastian Ott <sebott@redhat.com>
|
||||
Date: Thu, 22 Aug 2024 17:08:26 +0200
|
||||
Subject: [PATCH 5/9] arm: create virt machine type for rhel10
|
||||
|
||||
RH-Author: Sebastian Ott <sebott@redhat.com>
|
||||
RH-MergeRequest: 270: RHEL10 machine types
|
||||
RH-Jira: RHEL-29002 RHEL-29003 RHEL-35587 RHEL-38411 RHEL-45141 RHEL-52318 RHEL-52320
|
||||
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
||||
RH-Commit: [5/7] cd8f31de4cd189cd1de69e68c84d823e43473e8c (seott1/cos-qemu-kvm)
|
||||
|
||||
Create a new default virt machine type for rhel 10.
|
||||
|
||||
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||
---
|
||||
hw/arm/virt.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index f94be8656c..907c26c635 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -3580,10 +3580,16 @@ static void virt_machine_2_6_options(MachineClass *mc)
|
||||
DEFINE_VIRT_MACHINE(2, 6)
|
||||
#endif /* disabled for RHEL */
|
||||
|
||||
+static void virt_rhel_machine_10_0_0_options(MachineClass *mc)
|
||||
+{
|
||||
+}
|
||||
+DEFINE_VIRT_MACHINE_AS_LATEST(10, 0, 0)
|
||||
+
|
||||
static void virt_rhel_machine_9_6_0_options(MachineClass *mc)
|
||||
{
|
||||
+ virt_rhel_machine_10_0_0_options(mc);
|
||||
}
|
||||
-DEFINE_VIRT_MACHINE_AS_LATEST(9, 6, 0)
|
||||
+DEFINE_VIRT_MACHINE(9, 6, 0)
|
||||
|
||||
static void virt_rhel_machine_9_4_0_options(MachineClass *mc)
|
||||
{
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,252 +0,0 @@
|
||||
From 2ee645a339e9ef9cd92620a8b784d18d512326be Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Wolf <kwolf@redhat.com>
|
||||
Date: Thu, 25 Apr 2024 14:56:02 +0200
|
||||
Subject: [PATCH 4/4] block: Parse filenames only when explicitly requested
|
||||
|
||||
RH-Author: Hana Czenczek <hczenczek@redhat.com>
|
||||
RH-MergeRequest: 1: CVE 2024-4467 (PRDSC)
|
||||
RH-Jira: RHEL-35611
|
||||
RH-CVE: CVE-2024-4467
|
||||
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
RH-Acked-by: Eric Blake <eblake@redhat.com>
|
||||
RH-Commit: [4/4] f44c2941d4419e60f16dea3e9adca164e75aa78d
|
||||
|
||||
When handling image filenames from legacy options such as -drive or from
|
||||
tools, these filenames are parsed for protocol prefixes, including for
|
||||
the json:{} pseudo-protocol.
|
||||
|
||||
This behaviour is intended for filenames that come directly from the
|
||||
command line and for backing files, which may come from the image file
|
||||
itself. Higher level management tools generally take care to verify that
|
||||
untrusted images don't contain a bad (or any) backing file reference;
|
||||
'qemu-img info' is a suitable tool for this.
|
||||
|
||||
However, for other files that can be referenced in images, such as
|
||||
qcow2 data files or VMDK extents, the string from the image file is
|
||||
usually not verified by management tools - and 'qemu-img info' wouldn't
|
||||
be suitable because in contrast to backing files, it already opens these
|
||||
other referenced files. So here the string should be interpreted as a
|
||||
literal local filename. More complex configurations need to be specified
|
||||
explicitly on the command line or in QMP.
|
||||
|
||||
This patch changes bdrv_open_inherit() so that it only parses filenames
|
||||
if a new parameter parse_filename is true. It is set for the top level
|
||||
in bdrv_open(), for the file child and for the backing file child. All
|
||||
other callers pass false and disable filename parsing this way.
|
||||
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Reviewed-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
Upstream: N/A, embargoed
|
||||
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
|
||||
---
|
||||
block.c | 90 ++++++++++++++++++++++++++++++++++++---------------------
|
||||
1 file changed, 57 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/block.c b/block.c
|
||||
index 468cf5e67d..50bdd197b7 100644
|
||||
--- a/block.c
|
||||
+++ b/block.c
|
||||
@@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
|
||||
BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class,
|
||||
BdrvChildRole child_role,
|
||||
+ bool parse_filename,
|
||||
Error **errp);
|
||||
|
||||
static bool bdrv_recurse_has_child(BlockDriverState *bs,
|
||||
@@ -2058,7 +2059,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename,
|
||||
* block driver has been specified explicitly.
|
||||
*/
|
||||
static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
- int *flags, Error **errp)
|
||||
+ int *flags, bool allow_parse_filename,
|
||||
+ Error **errp)
|
||||
{
|
||||
const char *drvname;
|
||||
bool protocol = *flags & BDRV_O_PROTOCOL;
|
||||
@@ -2100,7 +2102,7 @@ static int bdrv_fill_options(QDict **options, const char *filename,
|
||||
if (protocol && filename) {
|
||||
if (!qdict_haskey(*options, "filename")) {
|
||||
qdict_put_str(*options, "filename", filename);
|
||||
- parse_filename = true;
|
||||
+ parse_filename = allow_parse_filename;
|
||||
} else {
|
||||
error_setg(errp, "Can't specify 'file' and 'filename' options at "
|
||||
"the same time");
|
||||
@@ -3663,7 +3665,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
||||
}
|
||||
|
||||
backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs,
|
||||
- &child_of_bds, bdrv_backing_role(bs), errp);
|
||||
+ &child_of_bds, bdrv_backing_role(bs), true,
|
||||
+ errp);
|
||||
if (!backing_hd) {
|
||||
bs->open_flags |= BDRV_O_NO_BACKING;
|
||||
error_prepend(errp, "Could not open backing file: ");
|
||||
@@ -3697,7 +3700,8 @@ free_exit:
|
||||
static BlockDriverState *
|
||||
bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
BlockDriverState *parent, const BdrvChildClass *child_class,
|
||||
- BdrvChildRole child_role, bool allow_none, Error **errp)
|
||||
+ BdrvChildRole child_role, bool allow_none,
|
||||
+ bool parse_filename, Error **errp)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
QDict *image_options;
|
||||
@@ -3728,7 +3732,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key,
|
||||
}
|
||||
|
||||
bs = bdrv_open_inherit(filename, reference, image_options, 0,
|
||||
- parent, child_class, child_role, errp);
|
||||
+ parent, child_class, child_role, parse_filename,
|
||||
+ errp);
|
||||
if (!bs) {
|
||||
goto done;
|
||||
}
|
||||
@@ -3738,6 +3743,33 @@ done:
|
||||
return bs;
|
||||
}
|
||||
|
||||
+static BdrvChild *bdrv_open_child_common(const char *filename,
|
||||
+ QDict *options, const char *bdref_key,
|
||||
+ BlockDriverState *parent,
|
||||
+ const BdrvChildClass *child_class,
|
||||
+ BdrvChildRole child_role,
|
||||
+ bool allow_none, bool parse_filename,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ BlockDriverState *bs;
|
||||
+ BdrvChild *child;
|
||||
+
|
||||
+ GLOBAL_STATE_CODE();
|
||||
+
|
||||
+ bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
+ child_role, allow_none, parse_filename, errp);
|
||||
+ if (bs == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ bdrv_graph_wrlock();
|
||||
+ child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
+ errp);
|
||||
+ bdrv_graph_wrunlock();
|
||||
+
|
||||
+ return child;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Opens a disk image whose options are given as BlockdevRef in another block
|
||||
* device's options.
|
||||
@@ -3761,27 +3793,15 @@ BdrvChild *bdrv_open_child(const char *filename,
|
||||
BdrvChildRole child_role,
|
||||
bool allow_none, Error **errp)
|
||||
{
|
||||
- BlockDriverState *bs;
|
||||
- BdrvChild *child;
|
||||
-
|
||||
- GLOBAL_STATE_CODE();
|
||||
-
|
||||
- bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class,
|
||||
- child_role, allow_none, errp);
|
||||
- if (bs == NULL) {
|
||||
- return NULL;
|
||||
- }
|
||||
-
|
||||
- bdrv_graph_wrlock();
|
||||
- child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role,
|
||||
- errp);
|
||||
- bdrv_graph_wrunlock();
|
||||
-
|
||||
- return child;
|
||||
+ return bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
+ child_class, child_role, allow_none, false,
|
||||
+ errp);
|
||||
}
|
||||
|
||||
/*
|
||||
- * Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
||||
+ * This does mostly the same as bdrv_open_child(), but for opening the primary
|
||||
+ * child of a node. A notable difference from bdrv_open_child() is that it
|
||||
+ * enables filename parsing for protocol names (including json:).
|
||||
*
|
||||
* @parent can move to a different AioContext in this function.
|
||||
*/
|
||||
@@ -3796,8 +3816,8 @@ int bdrv_open_file_child(const char *filename,
|
||||
role = parent->drv->is_filter ?
|
||||
(BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE;
|
||||
|
||||
- if (!bdrv_open_child(filename, options, bdref_key, parent,
|
||||
- &child_of_bds, role, false, errp))
|
||||
+ if (!bdrv_open_child_common(filename, options, bdref_key, parent,
|
||||
+ &child_of_bds, role, false, true, errp))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -3842,7 +3862,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
|
||||
|
||||
}
|
||||
|
||||
- bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp);
|
||||
+ bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false,
|
||||
+ errp);
|
||||
obj = NULL;
|
||||
qobject_unref(obj);
|
||||
visit_free(v);
|
||||
@@ -3932,7 +3953,7 @@ static BlockDriverState * no_coroutine_fn
|
||||
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
int flags, BlockDriverState *parent,
|
||||
const BdrvChildClass *child_class, BdrvChildRole child_role,
|
||||
- Error **errp)
|
||||
+ bool parse_filename, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
BlockBackend *file = NULL;
|
||||
@@ -3980,9 +4001,11 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
}
|
||||
|
||||
/* json: syntax counts as explicit options, as if in the QDict */
|
||||
- parse_json_protocol(options, &filename, &local_err);
|
||||
- if (local_err) {
|
||||
- goto fail;
|
||||
+ if (parse_filename) {
|
||||
+ parse_json_protocol(options, &filename, &local_err);
|
||||
+ if (local_err) {
|
||||
+ goto fail;
|
||||
+ }
|
||||
}
|
||||
|
||||
bs->explicit_options = qdict_clone_shallow(options);
|
||||
@@ -4007,7 +4030,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
parent->open_flags, parent->options);
|
||||
}
|
||||
|
||||
- ret = bdrv_fill_options(&options, filename, &flags, &local_err);
|
||||
+ ret = bdrv_fill_options(&options, filename, &flags, parse_filename,
|
||||
+ &local_err);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4076,7 +4100,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
||||
|
||||
file_bs = bdrv_open_child_bs(filename, options, "file", bs,
|
||||
&child_of_bds, BDRV_CHILD_IMAGE,
|
||||
- true, &local_err);
|
||||
+ true, true, &local_err);
|
||||
if (local_err) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -4225,7 +4249,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
||||
GLOBAL_STATE_CODE();
|
||||
|
||||
return bdrv_open_inherit(filename, reference, options, flags, NULL,
|
||||
- NULL, 0, errp);
|
||||
+ NULL, 0, true, errp);
|
||||
}
|
||||
|
||||
/* Return true if the NULL-terminated @list contains @str */
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,330 +0,0 @@
|
||||
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
|
||||
|
@ -1,90 +0,0 @@
|
||||
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
|
||||
|
@ -1,228 +0,0 @@
|
||||
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,76 @@
|
||||
From f1359f43bbc61f31c292ca1770688b6db6b959af Mon Sep 17 00:00:00 2001
|
||||
From: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Date: Sat, 19 Oct 2024 21:29:52 -0400
|
||||
Subject: [PATCH 20/38] docs/system: Update documentation for s390x IPL
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 278: Full boot order support for s390x [Centos 10]
|
||||
RH-Jira: RHEL-58153
|
||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [19/23] 8dfc0357ec42e9baac741670f6e7da3127de0e50 (thuth/qemu-kvm-cs9)
|
||||
|
||||
Update docs to show that s390x PC BIOS can support more than one boot device.
|
||||
|
||||
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Message-ID: <20241020012953.1380075-19-jrossi@linux.ibm.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit 0bd107138ff0b171e3cd314dbc200950bcab2b05)
|
||||
---
|
||||
docs/system/bootindex.rst | 7 ++++---
|
||||
docs/system/s390x/bootdevices.rst | 9 ++++++---
|
||||
2 files changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/docs/system/bootindex.rst b/docs/system/bootindex.rst
|
||||
index 8b057f812f..988f7b3beb 100644
|
||||
--- a/docs/system/bootindex.rst
|
||||
+++ b/docs/system/bootindex.rst
|
||||
@@ -49,10 +49,11 @@ Limitations
|
||||
-----------
|
||||
|
||||
Some firmware has limitations on which devices can be considered for
|
||||
-booting. For instance, the PC BIOS boot specification allows only one
|
||||
-disk to be bootable. If boot from disk fails for some reason, the BIOS
|
||||
+booting. For instance, the x86 PC BIOS boot specification allows only one
|
||||
+disk to be bootable. If boot from disk fails for some reason, the x86 BIOS
|
||||
won't retry booting from other disk. It can still try to boot from
|
||||
-floppy or net, though.
|
||||
+floppy or net, though. In the case of s390x BIOS, the BIOS will try up to
|
||||
+8 total devices, any number of which may be disks.
|
||||
|
||||
Sometimes, firmware cannot map the device path QEMU wants firmware to
|
||||
boot from to a boot method. It doesn't happen for devices the firmware
|
||||
diff --git a/docs/system/s390x/bootdevices.rst b/docs/system/s390x/bootdevices.rst
|
||||
index c97efb8fc0..1a1a764c1c 100644
|
||||
--- a/docs/system/s390x/bootdevices.rst
|
||||
+++ b/docs/system/s390x/bootdevices.rst
|
||||
@@ -6,9 +6,7 @@ Booting with bootindex parameter
|
||||
|
||||
For classical mainframe guests (i.e. LPAR or z/VM installations), you always
|
||||
have to explicitly specify the disk where you want to boot from (or "IPL" from,
|
||||
-in s390x-speak -- IPL means "Initial Program Load"). In particular, there can
|
||||
-also be only one boot device according to the architecture specification, thus
|
||||
-specifying multiple boot devices is not possible (yet).
|
||||
+in s390x-speak -- IPL means "Initial Program Load").
|
||||
|
||||
So for booting an s390x guest in QEMU, you should always mark the
|
||||
device where you want to boot from with the ``bootindex`` property, for
|
||||
@@ -17,6 +15,11 @@ example::
|
||||
qemu-system-s390x -drive if=none,id=dr1,file=guest.qcow2 \
|
||||
-device virtio-blk,drive=dr1,bootindex=1
|
||||
|
||||
+Multiple devices may have a bootindex. The lowest bootindex is assigned to the
|
||||
+device to IPL first. If the IPL fails for the first, the device with the second
|
||||
+lowest bootindex will be tried and so on until IPL is successful or there are no
|
||||
+remaining boot devices to try.
|
||||
+
|
||||
For booting from a CD-ROM ISO image (which needs to include El-Torito boot
|
||||
information in order to be bootable), it is recommended to specify a ``scsi-cd``
|
||||
device, for example like this::
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,41 @@
|
||||
From ba9b7c8375aac784fbe23beaeb91484ddd8e6829 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Mon, 11 Nov 2024 11:55:06 +0100
|
||||
Subject: [PATCH 3/9] docs/system/bootindex: Make it clear that s390x can also
|
||||
boot from virtio-net
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 297: [c10s] Fixes for the new s390x "boot order" feature
|
||||
RH-Jira: RHEL-68444
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [2/8] ae20c66e424d64840012b4725166a1bde2579cbc (thuth/qemu-kvm-cs9)
|
||||
|
||||
Let's make it clear that s390x can also boot from virtio-net, to avoid
|
||||
that people think that s390x can only boot from disk devices.
|
||||
|
||||
Reported-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
|
||||
Message-ID: <20241111105506.264640-1-thuth@redhat.com>
|
||||
Reviewed-by: Prasad Pandit <pjp@fedoraproject.org>
|
||||
Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit b8c5fdc6588f82d95807be0eb2215d215a3ba16e)
|
||||
---
|
||||
docs/system/bootindex.rst | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/system/bootindex.rst b/docs/system/bootindex.rst
|
||||
index 988f7b3beb..5e1b33ee22 100644
|
||||
--- a/docs/system/bootindex.rst
|
||||
+++ b/docs/system/bootindex.rst
|
||||
@@ -53,7 +53,7 @@ booting. For instance, the x86 PC BIOS boot specification allows only one
|
||||
disk to be bootable. If boot from disk fails for some reason, the x86 BIOS
|
||||
won't retry booting from other disk. It can still try to boot from
|
||||
floppy or net, though. In the case of s390x BIOS, the BIOS will try up to
|
||||
-8 total devices, any number of which may be disks.
|
||||
+8 total devices, any number of which may be disks or virtio-net devices.
|
||||
|
||||
Sometimes, firmware cannot map the device path QEMU wants firmware to
|
||||
boot from to a boot method. It doesn't happen for devices the firmware
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,61 @@
|
||||
From 3c57b3a6d48d7ddad44b67fdf9ccaebc40e5c125 Mon Sep 17 00:00:00 2001
|
||||
From: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Date: Thu, 14 Nov 2024 19:27:42 -0500
|
||||
Subject: [PATCH 2/9] docs/system/s390x/bootdevices: Update loadparm
|
||||
documentation
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 297: [c10s] Fixes for the new s390x "boot order" feature
|
||||
RH-Jira: RHEL-68444
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/8] bd74a0794bf0f2872061850ca410bab819c6a0d6 (thuth/qemu-kvm-cs9)
|
||||
|
||||
Update documentation to include per-device loadparm support.
|
||||
|
||||
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Message-ID: <20241115002742.3576842-1-jrossi@linux.ibm.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit 0271fdc650b212533b8aeaecbedfe8ccf6bbbef3)
|
||||
---
|
||||
docs/system/s390x/bootdevices.rst | 24 +++++++++++++++++++++++-
|
||||
1 file changed, 23 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/system/s390x/bootdevices.rst b/docs/system/s390x/bootdevices.rst
|
||||
index 1a1a764c1c..97b3914785 100644
|
||||
--- a/docs/system/s390x/bootdevices.rst
|
||||
+++ b/docs/system/s390x/bootdevices.rst
|
||||
@@ -79,7 +79,29 @@ The second way to use this parameter is to use a number in the range from 0
|
||||
to 31. The numbers that can be used here correspond to the numbers that are
|
||||
shown when using the ``PROMPT`` option, and the s390-ccw bios will then try
|
||||
to automatically boot the kernel that is associated with the given number.
|
||||
-Note that ``0`` can be used to boot the default entry.
|
||||
+Note that ``0`` can be used to boot the default entry. If the machine
|
||||
+``loadparm`` is not assigned a value, then the default entry is used.
|
||||
+
|
||||
+By default, the machine ``loadparm`` applies to all boot devices. If multiple
|
||||
+devices are assigned a ``bootindex`` and the ``loadparm`` is to be different
|
||||
+between them, an independent ``loadparm`` may be assigned on a per-device basis.
|
||||
+
|
||||
+An example guest using per-device ``loadparm``::
|
||||
+
|
||||
+ qemu-system-s390x -drive if=none,id=dr1,file=primary.qcow2 \
|
||||
+ -device virtio-blk,drive=dr1,bootindex=1 \
|
||||
+ -drive if=none,id=dr2,file=secondary.qcow2 \
|
||||
+ -device virtio-blk,drive=dr2,bootindex=2,loadparm=3
|
||||
+
|
||||
+In this case, the primary boot device will attempt to IPL using the default
|
||||
+entry (because no ``loadparm`` is specified for this device or for the
|
||||
+machine). If that device fails to boot, the secondary device will attempt to
|
||||
+IPL using entry number 3.
|
||||
+
|
||||
+If a ``loadparm`` is specified on both the machine and a device, the per-device
|
||||
+value will superseded the machine value. Per-device ``loadparm`` values are
|
||||
+only used for devices with an assigned ``bootindex``. The machine ``loadparm``
|
||||
+is used when attempting to boot without a ``bootindex``.
|
||||
|
||||
|
||||
Booting from a network device
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,66 @@
|
||||
From c8e615cf130743ee95a61d7e21bb4b753eb082fb Mon Sep 17 00:00:00 2001
|
||||
From: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Date: Sat, 19 Oct 2024 21:29:40 -0400
|
||||
Subject: [PATCH 08/38] docs/system/s390x/bootdevices: Update the documentation
|
||||
about network booting
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 278: Full boot order support for s390x [Centos 10]
|
||||
RH-Jira: RHEL-58153
|
||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [7/23] 52d357df45400b983e17cc6b1eeac691131bf5e5 (thuth/qemu-kvm-cs9)
|
||||
|
||||
Remove the information about the separate s390-netboot.img from
|
||||
the documentation.
|
||||
|
||||
Co-authored by: Thomas Huth <thuth@redhat.com>
|
||||
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Message-ID: <20241020012953.1380075-7-jrossi@linux.ibm.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit ab2691b6c7ff360875e0af86ff463278f17786f5)
|
||||
---
|
||||
docs/system/s390x/bootdevices.rst | 20 +++++++-------------
|
||||
1 file changed, 7 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/docs/system/s390x/bootdevices.rst b/docs/system/s390x/bootdevices.rst
|
||||
index 1a7a18b43b..c97efb8fc0 100644
|
||||
--- a/docs/system/s390x/bootdevices.rst
|
||||
+++ b/docs/system/s390x/bootdevices.rst
|
||||
@@ -82,23 +82,17 @@ Note that ``0`` can be used to boot the default entry.
|
||||
Booting from a network device
|
||||
-----------------------------
|
||||
|
||||
-Beside the normal guest firmware (which is loaded from the file ``s390-ccw.img``
|
||||
-in the data directory of QEMU, or via the ``-bios`` option), QEMU ships with
|
||||
-a small TFTP network bootloader firmware for virtio-net-ccw devices, too. This
|
||||
-firmware is loaded from a file called ``s390-netboot.img`` in the QEMU data
|
||||
-directory. In case you want to load it from a different filename instead,
|
||||
-you can specify it via the ``-global s390-ipl.netboot_fw=filename``
|
||||
-command line option.
|
||||
-
|
||||
-The ``bootindex`` property is especially important for booting via the network.
|
||||
-If you don't specify the ``bootindex`` property here, the network bootloader
|
||||
-firmware code won't get loaded into the guest memory so that the network boot
|
||||
-will fail. For a successful network boot, try something like this::
|
||||
+The firmware that ships with QEMU includes a small TFTP network bootloader
|
||||
+for virtio-net-ccw devices. The ``bootindex`` property is especially
|
||||
+important for booting via the network. If you don't specify the ``bootindex``
|
||||
+property here, the network bootloader won't be taken into consideration and
|
||||
+the network boot will fail. For a successful network boot, try something
|
||||
+like this::
|
||||
|
||||
qemu-system-s390x -netdev user,id=n1,tftp=...,bootfile=... \
|
||||
-device virtio-net-ccw,netdev=n1,bootindex=1
|
||||
|
||||
-The network bootloader firmware also has basic support for pxelinux.cfg-style
|
||||
+The network bootloader also has basic support for pxelinux.cfg-style
|
||||
configuration files. See the `PXELINUX Configuration page
|
||||
<https://wiki.syslinux.org/wiki/index.php?title=PXELINUX#Configuration>`__
|
||||
for details how to set up the configuration file on your TFTP server.
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,61 @@
|
||||
From d0163127a47250170e01e39f48250a2725f531c0 Mon Sep 17 00:00:00 2001
|
||||
From: Gavin Shan <gshan@redhat.com>
|
||||
Date: Tue, 1 Oct 2024 16:58:57 +1000
|
||||
Subject: [PATCH] hostmem: Apply merge property after the memory region is
|
||||
initialized
|
||||
|
||||
RH-Author: Gavin Shan <gshan@redhat.com>
|
||||
RH-MergeRequest: 272: hostmem: Apply merge property after the memory region is initialized
|
||||
RH-Jira: RHEL-58936
|
||||
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
||||
RH-Acked-by: David Hildenbrand <david@redhat.com>
|
||||
RH-Commit: [1/1] aa47bedf64698b277bb8835f4689d4f1d5eca53c (gwshan/qemu-centos)
|
||||
|
||||
JIRA: https://issues.redhat.com/browse/RHEL-58936
|
||||
|
||||
The semantic change has been introduced by commit 5becdc0ab0 ("hostmem:
|
||||
simplify the code for merge and dump properties") even it clarifies that
|
||||
no senmatic change has been introduced. After the commit, the merge
|
||||
property can be applied even the corresponding memory region isn't
|
||||
initialized yet. This leads to crash dump by the following command
|
||||
lines.
|
||||
|
||||
# /home/gavin/sandbox/qemu.main/build/qemu-system-aarch64 \
|
||||
-accel kvm -machine virt -cpu host \
|
||||
-object memory-backend-ram,id=mem-memN0,size=4096M,merge=off
|
||||
:
|
||||
qemu-system-aarch64: ../system/memory.c:2419: memory_region_get_ram_ptr: \
|
||||
Assertion `mr->ram_block' failed.
|
||||
|
||||
Fix it by applying the merge property only when the memory region is
|
||||
initialized.
|
||||
|
||||
Message-ID: <20240915233117.478169-1-gshan@redhat.com>
|
||||
Fixes: 5becdc0ab083 ("hostmem: simplify the code for merge and dump properties")
|
||||
Reported-by: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||
Tested-by: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
||||
(cherry picked from commit 78c8f780d3f0d6d17aa93d6f99ff72960080fdd7)
|
||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
||||
---
|
||||
backends/hostmem.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/backends/hostmem.c b/backends/hostmem.c
|
||||
index 4e5576a4ad..181446626a 100644
|
||||
--- a/backends/hostmem.c
|
||||
+++ b/backends/hostmem.c
|
||||
@@ -178,7 +178,7 @@ static void host_memory_backend_set_merge(Object *obj, bool value, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
- if (!host_memory_backend_mr_inited(backend) &&
|
||||
+ if (host_memory_backend_mr_inited(backend) &&
|
||||
value != backend->merge) {
|
||||
void *ptr = memory_region_get_ram_ptr(&backend->mr);
|
||||
uint64_t sz = memory_region_size(&backend->mr);
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,217 @@
|
||||
From 4c90ff4c0b48df312c10defba45c9f182b535524 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Fri, 15 Nov 2024 15:12:02 +0100
|
||||
Subject: [PATCH 5/9] hw: Add "loadparm" property to scsi disk devices for
|
||||
booting on s390x
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 297: [c10s] Fixes for the new s390x "boot order" feature
|
||||
RH-Jira: RHEL-68444
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [4/8] 4b5e2afa65f7a529e0bb5509b36c9bf81894caee (thuth/qemu-kvm-cs9)
|
||||
|
||||
While adding the new flexible boot order feature on s390x recently,
|
||||
we missed to add the "loadparm" property to the scsi-hd and scsi-cd
|
||||
devices. This property is required on s390x to pass the information
|
||||
to the boot loader about which kernel should be started or whether
|
||||
the boot menu should be shown. But even more serious: The missing
|
||||
property is now causing trouble with the corresponding libvirt patches
|
||||
that assume that the "loadparm" property is either settable for all
|
||||
bootable devices (when the "boot order" feature is implemented in
|
||||
QEMU), or none (meaning the behaviour of older QEMUs that only allowed
|
||||
one "loadparm" at the machine level). To fix this broken situation,
|
||||
let's implement the "loadparm" property in for the SCSI devices, too.
|
||||
|
||||
Message-ID: <20241115141202.1877294-1-thuth@redhat.com>
|
||||
Acked-by: Eric Farman <farman@linux.ibm.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit 429442e52d94f890fa194a151e8cd649b04e9e63)
|
||||
---
|
||||
hw/core/qdev-properties-system.c | 26 +++++++++++++++++
|
||||
hw/s390x/ipl.c | 19 ++++---------
|
||||
hw/scsi/scsi-disk.c | 43 +++++++++++++++++++++++++++++
|
||||
include/hw/qdev-properties-system.h | 3 ++
|
||||
4 files changed, 78 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c
|
||||
index f13350b4fb..5cd527cdba 100644
|
||||
--- a/hw/core/qdev-properties-system.c
|
||||
+++ b/hw/core/qdev-properties-system.c
|
||||
@@ -58,6 +58,32 @@ static bool check_prop_still_unset(Object *obj, const char *name,
|
||||
return false;
|
||||
}
|
||||
|
||||
+bool qdev_prop_sanitize_s390x_loadparm(uint8_t *loadparm, const char *str,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ int i, len;
|
||||
+
|
||||
+ len = strlen(str);
|
||||
+ if (len > 8) {
|
||||
+ error_setg(errp, "'loadparm' can only contain up to 8 characters");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < len; i++) {
|
||||
+ uint8_t c = qemu_toupper(str[i]); /* mimic HMC */
|
||||
+
|
||||
+ if (qemu_isalnum(c) || c == '.' || c == ' ') {
|
||||
+ loadparm[i] = c;
|
||||
+ } else {
|
||||
+ error_setg(errp,
|
||||
+ "invalid character in 'loadparm': '%c' (ASCII 0x%02x)",
|
||||
+ c, c);
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
|
||||
/* --- drive --- */
|
||||
|
||||
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
|
||||
index 5fbd43c346..8101825dfe 100644
|
||||
--- a/hw/s390x/ipl.c
|
||||
+++ b/hw/s390x/ipl.c
|
||||
@@ -418,21 +418,9 @@ static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain)
|
||||
|
||||
void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp)
|
||||
{
|
||||
- int i;
|
||||
-
|
||||
/* Initialize the loadparm with spaces */
|
||||
memset(loadparm, ' ', LOADPARM_LEN);
|
||||
- for (i = 0; i < LOADPARM_LEN && str[i]; i++) {
|
||||
- uint8_t c = qemu_toupper(str[i]); /* mimic HMC */
|
||||
-
|
||||
- if (qemu_isalnum(c) || c == '.' || c == ' ') {
|
||||
- loadparm[i] = c;
|
||||
- } else {
|
||||
- error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)",
|
||||
- c, c);
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
+ qdev_prop_sanitize_s390x_loadparm(loadparm, str, errp);
|
||||
}
|
||||
|
||||
void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp)
|
||||
@@ -452,6 +440,7 @@ static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb)
|
||||
SCSIDevice *sd;
|
||||
int devtype;
|
||||
uint8_t *lp;
|
||||
+ g_autofree void *scsi_lp = NULL;
|
||||
|
||||
/*
|
||||
* Currently allow IPL only from CCW devices.
|
||||
@@ -463,6 +452,10 @@ static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb)
|
||||
switch (devtype) {
|
||||
case CCW_DEVTYPE_SCSI:
|
||||
sd = SCSI_DEVICE(dev_st);
|
||||
+ scsi_lp = object_property_get_str(OBJECT(sd), "loadparm", NULL);
|
||||
+ if (scsi_lp && strlen(scsi_lp) > 0) {
|
||||
+ lp = scsi_lp;
|
||||
+ }
|
||||
iplb->len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
|
||||
iplb->blk0_len =
|
||||
cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
|
||||
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
|
||||
index 4d94b2b816..7566a5f531 100644
|
||||
--- a/hw/scsi/scsi-disk.c
|
||||
+++ b/hw/scsi/scsi-disk.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "migration/vmstate.h"
|
||||
#include "hw/scsi/emulation.h"
|
||||
#include "scsi/constants.h"
|
||||
+#include "sysemu/arch_init.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/block/block.h"
|
||||
@@ -111,6 +112,7 @@ struct SCSIDiskState {
|
||||
char *vendor;
|
||||
char *product;
|
||||
char *device_id;
|
||||
+ char *loadparm; /* only for s390x */
|
||||
bool tray_open;
|
||||
bool tray_locked;
|
||||
/*
|
||||
@@ -3135,6 +3137,43 @@ BlockAIOCB *scsi_dma_writev(int64_t offset, QEMUIOVector *iov,
|
||||
return blk_aio_pwritev(s->qdev.conf.blk, offset, iov, 0, cb, cb_opaque);
|
||||
}
|
||||
|
||||
+static char *scsi_property_get_loadparm(Object *obj, Error **errp)
|
||||
+{
|
||||
+ return g_strdup(SCSI_DISK_BASE(obj)->loadparm);
|
||||
+}
|
||||
+
|
||||
+static void scsi_property_set_loadparm(Object *obj, const char *value,
|
||||
+ Error **errp)
|
||||
+{
|
||||
+ void *lp_str;
|
||||
+
|
||||
+ if (object_property_get_int(obj, "bootindex", NULL) < 0) {
|
||||
+ error_setg(errp, "'loadparm' is only valid for boot devices");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ lp_str = g_malloc0(strlen(value));
|
||||
+ if (!qdev_prop_sanitize_s390x_loadparm(lp_str, value, errp)) {
|
||||
+ g_free(lp_str);
|
||||
+ return;
|
||||
+ }
|
||||
+ SCSI_DISK_BASE(obj)->loadparm = lp_str;
|
||||
+}
|
||||
+
|
||||
+static void scsi_property_add_specifics(DeviceClass *dc)
|
||||
+{
|
||||
+ ObjectClass *oc = OBJECT_CLASS(dc);
|
||||
+
|
||||
+ /* The loadparm property is only supported on s390x */
|
||||
+ if (arch_type & QEMU_ARCH_S390X) {
|
||||
+ object_class_property_add_str(oc, "loadparm",
|
||||
+ scsi_property_get_loadparm,
|
||||
+ scsi_property_set_loadparm);
|
||||
+ object_class_property_set_description(oc, "loadparm",
|
||||
+ "load parameter (s390x only)");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void scsi_disk_base_class_initfn(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@@ -3218,6 +3257,8 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
|
||||
dc->desc = "virtual SCSI disk";
|
||||
device_class_set_props(dc, scsi_hd_properties);
|
||||
dc->vmsd = &vmstate_scsi_disk_state;
|
||||
+
|
||||
+ scsi_property_add_specifics(dc);
|
||||
}
|
||||
|
||||
static const TypeInfo scsi_hd_info = {
|
||||
@@ -3258,6 +3299,8 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
|
||||
dc->desc = "virtual SCSI CD-ROM";
|
||||
device_class_set_props(dc, scsi_cd_properties);
|
||||
dc->vmsd = &vmstate_scsi_disk_state;
|
||||
+
|
||||
+ scsi_property_add_specifics(dc);
|
||||
}
|
||||
|
||||
static const TypeInfo scsi_cd_info = {
|
||||
diff --git a/include/hw/qdev-properties-system.h b/include/hw/qdev-properties-system.h
|
||||
index 438f65389f..88e4257ad0 100644
|
||||
--- a/include/hw/qdev-properties-system.h
|
||||
+++ b/include/hw/qdev-properties-system.h
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
#include "hw/qdev-properties.h"
|
||||
|
||||
+bool qdev_prop_sanitize_s390x_loadparm(uint8_t *loadparm, const char *str,
|
||||
+ Error **errp);
|
||||
+
|
||||
extern const PropertyInfo qdev_prop_chr;
|
||||
extern const PropertyInfo qdev_prop_macaddr;
|
||||
extern const PropertyInfo qdev_prop_reserved_region;
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,120 +0,0 @@
|
||||
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
|
||||
|
@ -1,59 +0,0 @@
|
||||
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
|
||||
|
@ -1,73 +0,0 @@
|
||||
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
|
||||
|
@ -1,106 +0,0 @@
|
||||
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
|
||||
|
@ -1,51 +0,0 @@
|
||||
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
|
||||
|
@ -1,164 +0,0 @@
|
||||
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
|
||||
|
@ -1,53 +0,0 @@
|
||||
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
|
||||
|
@ -1,158 +0,0 @@
|
||||
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
|
||||
|
@ -1,165 +0,0 @@
|
||||
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
|
||||
|
@ -1,123 +0,0 @@
|
||||
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
|
||||
|
@ -1,58 +0,0 @@
|
||||
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
@ -1,133 +0,0 @@
|
||||
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
|
||||
|
@ -1,105 +0,0 @@
|
||||
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
|
||||
|
@ -1,69 +0,0 @@
|
||||
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
|
||||
|
@ -1,98 +0,0 @@
|
||||
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,270 @@
|
||||
From 416ee0a87ee4bfedf07bc37d328066375b36fdc1 Mon Sep 17 00:00:00 2001
|
||||
From: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Date: Sat, 19 Oct 2024 21:29:49 -0400
|
||||
Subject: [PATCH 17/38] hw/s390x: Build an IPLB for each boot device
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 278: Full boot order support for s390x [Centos 10]
|
||||
RH-Jira: RHEL-58153
|
||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [16/23] 40a579b400cebd1470bb632869ad4a5581e3c41f (thuth/qemu-kvm-cs9)
|
||||
|
||||
Build an IPLB for any device with a bootindex (up to a maximum of 8 devices).
|
||||
|
||||
The IPLB chain is placed immediately before the BIOS in memory. Because this
|
||||
is not a fixed address, the location of the next IPLB and number of remaining
|
||||
boot devices is stored in the QIPL global variable for possible later access by
|
||||
the guest during IPL.
|
||||
|
||||
Signed-off-by: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Message-ID: <20241020012953.1380075-16-jrossi@linux.ibm.com>
|
||||
[thuth: Fix endianness problem when accessing the qipl structure]
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit 0927875e704e93ace03bb7533c0877bf97e4bda9)
|
||||
---
|
||||
hw/s390x/ipl.c | 129 ++++++++++++++++++++++++++++--------
|
||||
hw/s390x/ipl.h | 1 +
|
||||
include/hw/s390x/ipl/qipl.h | 4 +-
|
||||
3 files changed, 105 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
|
||||
index d83832d975..f4576f8822 100644
|
||||
--- a/hw/s390x/ipl.c
|
||||
+++ b/hw/s390x/ipl.c
|
||||
@@ -56,6 +56,13 @@ static bool iplb_extended_needed(void *opaque)
|
||||
return ipl->iplbext_migration;
|
||||
}
|
||||
|
||||
+/* Place the IPLB chain immediately before the BIOS in memory */
|
||||
+static uint64_t find_iplb_chain_addr(uint64_t bios_addr, uint16_t count)
|
||||
+{
|
||||
+ return (bios_addr & TARGET_PAGE_MASK)
|
||||
+ - (count * sizeof(IplParameterBlock));
|
||||
+}
|
||||
+
|
||||
static const VMStateDescription vmstate_iplb_extended = {
|
||||
.name = "ipl/iplb_extended",
|
||||
.version_id = 0,
|
||||
@@ -398,6 +405,17 @@ static CcwDevice *s390_get_ccw_device(DeviceState *dev_st, int *devtype)
|
||||
return ccw_dev;
|
||||
}
|
||||
|
||||
+static uint64_t s390_ipl_map_iplb_chain(IplParameterBlock *iplb_chain)
|
||||
+{
|
||||
+ S390IPLState *ipl = get_ipl_device();
|
||||
+ uint16_t count = be16_to_cpu(ipl->qipl.chain_len);
|
||||
+ uint64_t len = sizeof(IplParameterBlock) * count;
|
||||
+ uint64_t chain_addr = find_iplb_chain_addr(ipl->bios_start_addr, count);
|
||||
+
|
||||
+ cpu_physical_memory_write(chain_addr, iplb_chain, len);
|
||||
+ return chain_addr;
|
||||
+}
|
||||
+
|
||||
void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp)
|
||||
{
|
||||
int i;
|
||||
@@ -428,54 +446,51 @@ void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp)
|
||||
}
|
||||
}
|
||||
|
||||
-static bool s390_gen_initial_iplb(S390IPLState *ipl)
|
||||
+static bool s390_build_iplb(DeviceState *dev_st, IplParameterBlock *iplb)
|
||||
{
|
||||
- DeviceState *dev_st;
|
||||
+ S390IPLState *ipl = get_ipl_device();
|
||||
CcwDevice *ccw_dev = NULL;
|
||||
SCSIDevice *sd;
|
||||
int devtype;
|
||||
uint8_t *lp;
|
||||
|
||||
- dev_st = get_boot_device(0);
|
||||
- if (dev_st) {
|
||||
- ccw_dev = s390_get_ccw_device(dev_st, &devtype);
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Currently allow IPL only from CCW devices.
|
||||
*/
|
||||
+ ccw_dev = s390_get_ccw_device(dev_st, &devtype);
|
||||
if (ccw_dev) {
|
||||
lp = ccw_dev->loadparm;
|
||||
|
||||
switch (devtype) {
|
||||
case CCW_DEVTYPE_SCSI:
|
||||
sd = SCSI_DEVICE(dev_st);
|
||||
- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
|
||||
- ipl->iplb.blk0_len =
|
||||
+ iplb->len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
|
||||
+ iplb->blk0_len =
|
||||
cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN);
|
||||
- ipl->iplb.pbt = S390_IPL_TYPE_QEMU_SCSI;
|
||||
- ipl->iplb.scsi.lun = cpu_to_be32(sd->lun);
|
||||
- ipl->iplb.scsi.target = cpu_to_be16(sd->id);
|
||||
- ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
|
||||
- ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||
- ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
|
||||
+ iplb->pbt = S390_IPL_TYPE_QEMU_SCSI;
|
||||
+ iplb->scsi.lun = cpu_to_be32(sd->lun);
|
||||
+ iplb->scsi.target = cpu_to_be16(sd->id);
|
||||
+ iplb->scsi.channel = cpu_to_be16(sd->channel);
|
||||
+ iplb->scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||
+ iplb->scsi.ssid = ccw_dev->sch->ssid & 3;
|
||||
break;
|
||||
case CCW_DEVTYPE_VFIO:
|
||||
- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
|
||||
- ipl->iplb.pbt = S390_IPL_TYPE_CCW;
|
||||
- ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||
- ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
|
||||
+ iplb->len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
|
||||
+ iplb->pbt = S390_IPL_TYPE_CCW;
|
||||
+ iplb->ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||
+ iplb->ccw.ssid = ccw_dev->sch->ssid & 3;
|
||||
break;
|
||||
case CCW_DEVTYPE_VIRTIO_NET:
|
||||
+ /* The S390IPLState netboot is true if ANY IPLB may use netboot */
|
||||
ipl->netboot = true;
|
||||
/* Fall through to CCW_DEVTYPE_VIRTIO case */
|
||||
case CCW_DEVTYPE_VIRTIO:
|
||||
- ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
|
||||
- ipl->iplb.blk0_len =
|
||||
+ iplb->len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN);
|
||||
+ iplb->blk0_len =
|
||||
cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN);
|
||||
- ipl->iplb.pbt = S390_IPL_TYPE_CCW;
|
||||
- ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||
- ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
|
||||
+ iplb->pbt = S390_IPL_TYPE_CCW;
|
||||
+ iplb->ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
|
||||
+ iplb->ccw.ssid = ccw_dev->sch->ssid & 3;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -484,8 +499,8 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
|
||||
lp = S390_CCW_MACHINE(qdev_get_machine())->loadparm;
|
||||
}
|
||||
|
||||
- s390_ipl_convert_loadparm((char *)lp, ipl->iplb.loadparm);
|
||||
- ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
|
||||
+ s390_ipl_convert_loadparm((char *)lp, iplb->loadparm);
|
||||
+ iplb->flags |= DIAG308_FLAGS_LP_VALID;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -493,6 +508,62 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
|
||||
return false;
|
||||
}
|
||||
|
||||
+static bool s390_init_all_iplbs(S390IPLState *ipl)
|
||||
+{
|
||||
+ int iplb_num = 0;
|
||||
+ IplParameterBlock iplb_chain[7];
|
||||
+ DeviceState *dev_st = get_boot_device(0);
|
||||
+ Object *machine = qdev_get_machine();
|
||||
+
|
||||
+ /*
|
||||
+ * Parse the boot devices. Generate an IPLB for only the first boot device
|
||||
+ * which will later be set with DIAG308.
|
||||
+ */
|
||||
+ if (!dev_st) {
|
||||
+ ipl->qipl.chain_len = 0;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* If no machine loadparm was defined fill it with spaces */
|
||||
+ if (memcmp(S390_CCW_MACHINE(machine)->loadparm, NO_LOADPARM, 8) == 0) {
|
||||
+ object_property_set_str(machine, "loadparm", " ", NULL);
|
||||
+ }
|
||||
+
|
||||
+ iplb_num = 1;
|
||||
+ s390_build_iplb(dev_st, &ipl->iplb);
|
||||
+
|
||||
+ /* Index any fallback boot devices */
|
||||
+ while (get_boot_device(iplb_num)) {
|
||||
+ iplb_num++;
|
||||
+ }
|
||||
+
|
||||
+ if (iplb_num > MAX_BOOT_DEVS) {
|
||||
+ warn_report("Excess boot devices defined! %d boot devices found, "
|
||||
+ "but only the first %d will be considered.",
|
||||
+ iplb_num, MAX_BOOT_DEVS);
|
||||
+
|
||||
+ iplb_num = MAX_BOOT_DEVS;
|
||||
+ }
|
||||
+
|
||||
+ ipl->qipl.chain_len = cpu_to_be16(iplb_num - 1);
|
||||
+
|
||||
+ /*
|
||||
+ * Build fallback IPLBs for any boot devices above index 0, up to a
|
||||
+ * maximum amount as defined in ipl.h
|
||||
+ */
|
||||
+ if (iplb_num > 1) {
|
||||
+ /* Start at 1 because the IPLB for boot index 0 is not chained */
|
||||
+ for (int i = 1; i < iplb_num; i++) {
|
||||
+ dev_st = get_boot_device(i);
|
||||
+ s390_build_iplb(dev_st, &iplb_chain[i - 1]);
|
||||
+ }
|
||||
+
|
||||
+ ipl->qipl.next_iplb = cpu_to_be64(s390_ipl_map_iplb_chain(iplb_chain));
|
||||
+ }
|
||||
+
|
||||
+ return iplb_num;
|
||||
+}
|
||||
+
|
||||
static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb,
|
||||
int virtio_id)
|
||||
{
|
||||
@@ -620,7 +691,7 @@ void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type)
|
||||
* this is the original boot device's SCSI
|
||||
* so restore IPL parameter info from it
|
||||
*/
|
||||
- ipl->iplb_valid = s390_gen_initial_iplb(ipl);
|
||||
+ ipl->iplb_valid = s390_build_iplb(get_boot_device(0), &ipl->iplb);
|
||||
}
|
||||
}
|
||||
if (reset_type == S390_RESET_MODIFIED_CLEAR ||
|
||||
@@ -714,7 +785,9 @@ void s390_ipl_prepare_cpu(S390CPU *cpu)
|
||||
if (!ipl->kernel || ipl->iplb_valid) {
|
||||
cpu->env.psw.addr = ipl->bios_start_addr;
|
||||
if (!ipl->iplb_valid) {
|
||||
- ipl->iplb_valid = s390_gen_initial_iplb(ipl);
|
||||
+ ipl->iplb_valid = s390_init_all_iplbs(ipl);
|
||||
+ } else {
|
||||
+ ipl->qipl.chain_len = 0;
|
||||
}
|
||||
}
|
||||
s390_ipl_set_boot_menu(ipl);
|
||||
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
|
||||
index b670bad551..54eb48fd6e 100644
|
||||
--- a/hw/s390x/ipl.h
|
||||
+++ b/hw/s390x/ipl.h
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "qom/object.h"
|
||||
|
||||
#define DIAG308_FLAGS_LP_VALID 0x80
|
||||
+#define MAX_BOOT_DEVS 8 /* Max number of devices that may have a bootindex */
|
||||
|
||||
void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp);
|
||||
void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp);
|
||||
diff --git a/include/hw/s390x/ipl/qipl.h b/include/hw/s390x/ipl/qipl.h
|
||||
index b67d2ae061..1da4f75aa8 100644
|
||||
--- a/include/hw/s390x/ipl/qipl.h
|
||||
+++ b/include/hw/s390x/ipl/qipl.h
|
||||
@@ -32,7 +32,9 @@ struct QemuIplParameters {
|
||||
uint8_t reserved1[3];
|
||||
uint64_t reserved2;
|
||||
uint32_t boot_menu_timeout;
|
||||
- uint8_t reserved3[12];
|
||||
+ uint8_t reserved3[2];
|
||||
+ uint16_t chain_len;
|
||||
+ uint64_t next_iplb;
|
||||
} QEMU_PACKED;
|
||||
typedef struct QemuIplParameters QemuIplParameters;
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,201 @@
|
||||
From 36f64f38b39f2a2e0f0682f62f669d5e23074875 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Thu, 20 Jun 2024 16:59:28 +0200
|
||||
Subject: [PATCH 06/38] hw/s390x: Remove the possibility to load the
|
||||
s390-netboot.img binary
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 278: Full boot order support for s390x [Centos 10]
|
||||
RH-Jira: RHEL-58153
|
||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [5/23] ff245b81b45ddd3a78343d1a8cfdd725a8255d87 (thuth/qemu-kvm-cs9)
|
||||
|
||||
Since the netboot code has now been merged into the main s390-ccw.img
|
||||
binary, we don't need the separate s390-netboot.img anymore. Remove
|
||||
it and the code that was responsible for loading it.
|
||||
|
||||
Message-Id: <20240621082422.136217-6-thuth@redhat.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit 188e255bf8ed68fa64bcb63577cb100eeb326254)
|
||||
---
|
||||
hw/s390x/ipl.c | 55 --------------------------------------
|
||||
hw/s390x/ipl.h | 12 +++------
|
||||
hw/s390x/s390-virtio-ccw.c | 10 ++-----
|
||||
pc-bios/meson.build | 1 -
|
||||
4 files changed, 6 insertions(+), 72 deletions(-)
|
||||
|
||||
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
|
||||
index 9362de0b6f..8a0a3e6961 100644
|
||||
--- a/hw/s390x/ipl.c
|
||||
+++ b/hw/s390x/ipl.c
|
||||
@@ -288,7 +288,6 @@ static Property s390_ipl_properties[] = {
|
||||
DEFINE_PROP_STRING("initrd", S390IPLState, initrd),
|
||||
DEFINE_PROP_STRING("cmdline", S390IPLState, cmdline),
|
||||
DEFINE_PROP_STRING("firmware", S390IPLState, firmware),
|
||||
- DEFINE_PROP_STRING("netboot_fw", S390IPLState, netboot_fw),
|
||||
DEFINE_PROP_BOOL("enforce_bios", S390IPLState, enforce_bios, false),
|
||||
DEFINE_PROP_BOOL("iplbext_migration", S390IPLState, iplbext_migration,
|
||||
true),
|
||||
@@ -480,56 +479,6 @@ int s390_ipl_set_loadparm(uint8_t *loadparm)
|
||||
return -1;
|
||||
}
|
||||
|
||||
-static int load_netboot_image(Error **errp)
|
||||
-{
|
||||
- MachineState *ms = MACHINE(qdev_get_machine());
|
||||
- S390IPLState *ipl = get_ipl_device();
|
||||
- char *netboot_filename;
|
||||
- MemoryRegion *sysmem = get_system_memory();
|
||||
- MemoryRegion *mr = NULL;
|
||||
- void *ram_ptr = NULL;
|
||||
- int img_size = -1;
|
||||
-
|
||||
- mr = memory_region_find(sysmem, 0, 1).mr;
|
||||
- if (!mr) {
|
||||
- error_setg(errp, "Failed to find memory region at address 0");
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- ram_ptr = memory_region_get_ram_ptr(mr);
|
||||
- if (!ram_ptr) {
|
||||
- error_setg(errp, "No RAM found");
|
||||
- goto unref_mr;
|
||||
- }
|
||||
-
|
||||
- netboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->netboot_fw);
|
||||
- if (netboot_filename == NULL) {
|
||||
- error_setg(errp, "Could not find network bootloader '%s'",
|
||||
- ipl->netboot_fw);
|
||||
- goto unref_mr;
|
||||
- }
|
||||
-
|
||||
- img_size = load_elf_ram(netboot_filename, NULL, NULL, NULL,
|
||||
- &ipl->start_addr,
|
||||
- NULL, NULL, NULL, 1, EM_S390, 0, 0, NULL,
|
||||
- false);
|
||||
-
|
||||
- if (img_size < 0) {
|
||||
- img_size = load_image_size(netboot_filename, ram_ptr, ms->ram_size);
|
||||
- ipl->start_addr = KERN_IMAGE_START;
|
||||
- }
|
||||
-
|
||||
- if (img_size < 0) {
|
||||
- error_setg(errp, "Failed to load network bootloader");
|
||||
- }
|
||||
-
|
||||
- g_free(netboot_filename);
|
||||
-
|
||||
-unref_mr:
|
||||
- memory_region_unref(mr);
|
||||
- return img_size;
|
||||
-}
|
||||
-
|
||||
static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb,
|
||||
int virtio_id)
|
||||
{
|
||||
@@ -754,10 +703,6 @@ void s390_ipl_prepare_cpu(S390CPU *cpu)
|
||||
ipl->iplb_valid = s390_gen_initial_iplb(ipl);
|
||||
}
|
||||
}
|
||||
- if (ipl->netboot) {
|
||||
- load_netboot_image(&error_fatal);
|
||||
- ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr);
|
||||
- }
|
||||
s390_ipl_set_boot_menu(ipl);
|
||||
s390_ipl_prepare_qipl(cpu);
|
||||
}
|
||||
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
|
||||
index 57cd125769..b2105b616a 100644
|
||||
--- a/hw/s390x/ipl.h
|
||||
+++ b/hw/s390x/ipl.h
|
||||
@@ -134,11 +134,8 @@ void s390_ipl_clear_reset_request(void);
|
||||
/*
|
||||
* The QEMU IPL Parameters will be stored at absolute address
|
||||
* 204 (0xcc) which means it is 32-bit word aligned but not
|
||||
- * double-word aligned.
|
||||
- * Placement of data fields in this area must account for
|
||||
- * their alignment needs. E.g., netboot_start_address must
|
||||
- * have an offset of 4 + n * 8 bytes within the struct in order
|
||||
- * to keep it double-word aligned.
|
||||
+ * double-word aligned. Placement of 64-bit data fields in this
|
||||
+ * area must account for their alignment needs.
|
||||
* The total size of the struct must never exceed 28 bytes.
|
||||
* This definition must be kept in sync with the definition
|
||||
* in pc-bios/s390-ccw/iplb.h.
|
||||
@@ -146,9 +143,9 @@ void s390_ipl_clear_reset_request(void);
|
||||
struct QemuIplParameters {
|
||||
uint8_t qipl_flags;
|
||||
uint8_t reserved1[3];
|
||||
- uint64_t netboot_start_addr;
|
||||
+ uint64_t reserved2;
|
||||
uint32_t boot_menu_timeout;
|
||||
- uint8_t reserved2[12];
|
||||
+ uint8_t reserved3[12];
|
||||
} QEMU_PACKED;
|
||||
typedef struct QemuIplParameters QemuIplParameters;
|
||||
|
||||
@@ -178,7 +175,6 @@ struct S390IPLState {
|
||||
char *initrd;
|
||||
char *cmdline;
|
||||
char *firmware;
|
||||
- char *netboot_fw;
|
||||
uint8_t cssid;
|
||||
uint8_t ssid;
|
||||
uint16_t devno;
|
||||
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
|
||||
index b61392bac1..29a89a0c31 100644
|
||||
--- a/hw/s390x/s390-virtio-ccw.c
|
||||
+++ b/hw/s390x/s390-virtio-ccw.c
|
||||
@@ -197,11 +197,10 @@ static void s390_memory_init(MemoryRegion *ram)
|
||||
static void s390_init_ipl_dev(const char *kernel_filename,
|
||||
const char *kernel_cmdline,
|
||||
const char *initrd_filename, const char *firmware,
|
||||
- const char *netboot_fw, bool enforce_bios)
|
||||
+ bool enforce_bios)
|
||||
{
|
||||
Object *new = object_new(TYPE_S390_IPL);
|
||||
DeviceState *dev = DEVICE(new);
|
||||
- char *netboot_fw_prop;
|
||||
|
||||
if (kernel_filename) {
|
||||
qdev_prop_set_string(dev, "kernel", kernel_filename);
|
||||
@@ -212,11 +211,6 @@ static void s390_init_ipl_dev(const char *kernel_filename,
|
||||
qdev_prop_set_string(dev, "cmdline", kernel_cmdline);
|
||||
qdev_prop_set_string(dev, "firmware", firmware);
|
||||
qdev_prop_set_bit(dev, "enforce_bios", enforce_bios);
|
||||
- netboot_fw_prop = object_property_get_str(new, "netboot_fw", &error_abort);
|
||||
- if (!strlen(netboot_fw_prop)) {
|
||||
- qdev_prop_set_string(dev, "netboot_fw", netboot_fw);
|
||||
- }
|
||||
- g_free(netboot_fw_prop);
|
||||
object_property_add_child(qdev_get_machine(), TYPE_S390_IPL,
|
||||
new);
|
||||
object_unref(new);
|
||||
@@ -284,7 +278,7 @@ static void ccw_init(MachineState *machine)
|
||||
s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline,
|
||||
machine->initrd_filename,
|
||||
machine->firmware ?: "s390-ccw.img",
|
||||
- "s390-netboot.img", true);
|
||||
+ true);
|
||||
|
||||
dev = qdev_new(TYPE_S390_PCI_HOST_BRIDGE);
|
||||
object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE,
|
||||
diff --git a/pc-bios/meson.build b/pc-bios/meson.build
|
||||
index 8602b45b9b..ea85c54c86 100644
|
||||
--- a/pc-bios/meson.build
|
||||
+++ b/pc-bios/meson.build
|
||||
@@ -66,7 +66,6 @@ blobs = [
|
||||
'kvmvapic.bin',
|
||||
'pvh.bin',
|
||||
's390-ccw.img',
|
||||
- 's390-netboot.img',
|
||||
'slof.bin',
|
||||
'skiboot.lid',
|
||||
'palcode-clipper',
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,112 @@
|
||||
From b9950c32c2845c9592650df49183c431a4190e7f Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Wed, 13 Nov 2024 12:47:41 +0100
|
||||
Subject: [PATCH 4/9] hw/s390x: Restrict "loadparm" property to devices that
|
||||
can be used for booting
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 297: [c10s] Fixes for the new s390x "boot order" feature
|
||||
RH-Jira: RHEL-68444
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [3/8] 7b0fee6a1508649d66b913e6ebf23b4af29628dd (thuth/qemu-kvm-cs9)
|
||||
|
||||
Commit bb185de423 ("s390x: Add individual loadparm assignment to
|
||||
CCW device") added a "loadparm" property to all CCW devices. This
|
||||
was a little bit unfortunate, since this property is only useful
|
||||
for devices that can be used for booting, but certainly it is not
|
||||
useful for devices like virtio-gpu or virtio-tablet.
|
||||
|
||||
Thus let's restrict the property to CCW devices that we can boot from
|
||||
(i.e. virtio-block, virtio-net and vfio-ccw devices).
|
||||
|
||||
Message-ID: <20241113114741.681096-1-thuth@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Jared Rossi <jrossi@linux.ibm.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit 6e7c96ae61e0542e97d385084f1f2281a0331054)
|
||||
---
|
||||
hw/s390x/ccw-device.c | 4 +---
|
||||
hw/s390x/ccw-device.h | 5 +++++
|
||||
hw/s390x/virtio-ccw-blk.c | 1 +
|
||||
hw/s390x/virtio-ccw-net.c | 1 +
|
||||
hw/vfio/ccw.c | 1 +
|
||||
5 files changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/s390x/ccw-device.c b/hw/s390x/ccw-device.c
|
||||
index 4e54f34b1c..d7bb364579 100644
|
||||
--- a/hw/s390x/ccw-device.c
|
||||
+++ b/hw/s390x/ccw-device.c
|
||||
@@ -73,7 +73,7 @@ static void ccw_device_set_loadparm(Object *obj, Visitor *v,
|
||||
s390_ipl_fmt_loadparm(dev->loadparm, val, errp);
|
||||
}
|
||||
|
||||
-static const PropertyInfo ccw_loadparm = {
|
||||
+const PropertyInfo ccw_loadparm = {
|
||||
.name = "ccw_loadparm",
|
||||
.description = "Up to 8 chars in set of [A-Za-z0-9. ] to pass"
|
||||
" to the guest loader/kernel",
|
||||
@@ -85,8 +85,6 @@ static Property ccw_device_properties[] = {
|
||||
DEFINE_PROP_CSS_DEV_ID("devno", CcwDevice, devno),
|
||||
DEFINE_PROP_CSS_DEV_ID_RO("dev_id", CcwDevice, dev_id),
|
||||
DEFINE_PROP_CSS_DEV_ID_RO("subch_id", CcwDevice, subch_id),
|
||||
- DEFINE_PROP("loadparm", CcwDevice, loadparm, ccw_loadparm,
|
||||
- typeof(uint8_t[8])),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
diff --git a/hw/s390x/ccw-device.h b/hw/s390x/ccw-device.h
|
||||
index 1e1737c0f3..4439feb140 100644
|
||||
--- a/hw/s390x/ccw-device.h
|
||||
+++ b/hw/s390x/ccw-device.h
|
||||
@@ -51,4 +51,9 @@ static inline CcwDevice *to_ccw_dev_fast(DeviceState *d)
|
||||
|
||||
OBJECT_DECLARE_TYPE(CcwDevice, CCWDeviceClass, CCW_DEVICE)
|
||||
|
||||
+extern const PropertyInfo ccw_loadparm;
|
||||
+
|
||||
+#define DEFINE_PROP_CCW_LOADPARM(_n, _s, _f) \
|
||||
+ DEFINE_PROP(_n, _s, _f, ccw_loadparm, typeof(uint8_t[8]))
|
||||
+
|
||||
#endif
|
||||
diff --git a/hw/s390x/virtio-ccw-blk.c b/hw/s390x/virtio-ccw-blk.c
|
||||
index 8e0e58b77d..2364432c6e 100644
|
||||
--- a/hw/s390x/virtio-ccw-blk.c
|
||||
+++ b/hw/s390x/virtio-ccw-blk.c
|
||||
@@ -48,6 +48,7 @@ static Property virtio_ccw_blk_properties[] = {
|
||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||
VIRTIO_CCW_MAX_REV),
|
||||
+ DEFINE_PROP_CCW_LOADPARM("loadparm", CcwDevice, loadparm),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
diff --git a/hw/s390x/virtio-ccw-net.c b/hw/s390x/virtio-ccw-net.c
|
||||
index 484e617659..a4a3f65c7e 100644
|
||||
--- a/hw/s390x/virtio-ccw-net.c
|
||||
+++ b/hw/s390x/virtio-ccw-net.c
|
||||
@@ -51,6 +51,7 @@ static Property virtio_ccw_net_properties[] = {
|
||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||
DEFINE_PROP_UINT32("max_revision", VirtioCcwDevice, max_rev,
|
||||
VIRTIO_CCW_MAX_REV),
|
||||
+ DEFINE_PROP_CCW_LOADPARM("loadparm", CcwDevice, loadparm),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
|
||||
index 115862f430..99f16614ad 100644
|
||||
--- a/hw/vfio/ccw.c
|
||||
+++ b/hw/vfio/ccw.c
|
||||
@@ -662,6 +662,7 @@ static Property vfio_ccw_properties[] = {
|
||||
DEFINE_PROP_LINK("iommufd", VFIOCCWDevice, vdev.iommufd,
|
||||
TYPE_IOMMUFD_BACKEND, IOMMUFDBackend *),
|
||||
#endif
|
||||
+ DEFINE_PROP_CCW_LOADPARM("loadparm", CcwDevice, loadparm),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,61 @@
|
||||
From ce0d8bc163952ce177c37ea431cacf60889017f2 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Huth <thuth@redhat.com>
|
||||
Date: Fri, 21 Jun 2024 10:24:17 +0200
|
||||
Subject: [PATCH 02/38] hw/s390x/ipl: Provide more memory to the s390-ccw.img
|
||||
firmware
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||
RH-MergeRequest: 278: Full boot order support for s390x [Centos 10]
|
||||
RH-Jira: RHEL-58153
|
||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/23] c33a2769b041e62285eb7840f8a7c05ac32aca7b (thuth/qemu-kvm-cs9)
|
||||
|
||||
We are going to link the SLOF libc into the s390-ccw.img, and this
|
||||
libc needs more memory for providing space for malloc() and friends.
|
||||
Thus bump the memory size that we reserve for the bios to 3 MiB
|
||||
instead of only 2 MiB. While we're at it, add a proper check that
|
||||
there is really enough memory assigned to the machine before blindly
|
||||
using it.
|
||||
|
||||
Message-ID: <20240621082422.136217-3-thuth@redhat.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
(cherry picked from commit abaabb2e601adfe296a64471746a997eabcc607f)
|
||||
---
|
||||
hw/s390x/ipl.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
|
||||
index e934bf89d1..9362de0b6f 100644
|
||||
--- a/hw/s390x/ipl.c
|
||||
+++ b/hw/s390x/ipl.c
|
||||
@@ -45,6 +45,7 @@
|
||||
#define INITRD_PARM_START 0x010408UL
|
||||
#define PARMFILE_START 0x001000UL
|
||||
#define ZIPL_IMAGE_START 0x009000UL
|
||||
+#define BIOS_MAX_SIZE 0x300000UL
|
||||
#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64)
|
||||
|
||||
static bool iplb_extended_needed(void *opaque)
|
||||
@@ -144,7 +145,14 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp)
|
||||
* even if an external kernel has been defined.
|
||||
*/
|
||||
if (!ipl->kernel || ipl->enforce_bios) {
|
||||
- uint64_t fwbase = (MIN(ms->ram_size, 0x80000000U) - 0x200000) & ~0xffffUL;
|
||||
+ uint64_t fwbase;
|
||||
+
|
||||
+ if (ms->ram_size < BIOS_MAX_SIZE) {
|
||||
+ error_setg(errp, "not enough RAM to load the BIOS file");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ fwbase = (MIN(ms->ram_size, 0x80000000U) - BIOS_MAX_SIZE) & ~0xffffUL;
|
||||
|
||||
bios_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, ipl->firmware);
|
||||
if (bios_filename == NULL) {
|
||||
--
|
||||
2.39.3
|
||||
|
@ -1,108 +0,0 @@
|
||||
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
|
||||
|
@ -1,68 +0,0 @@
|
||||
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
|
||||
|
@ -1,40 +0,0 @@
|
||||
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
|
||||
|
@ -1,145 +0,0 @@
|
||||
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
|
||||
|
@ -1,536 +0,0 @@
|
||||
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
|
||||
|
@ -1,91 +0,0 @@
|
||||
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
|
||||
|
@ -1,116 +0,0 @@
|
||||
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
|
||||
|
@ -1,84 +0,0 @@
|
||||
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
|
||||
|
@ -1,187 +0,0 @@
|
||||
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
|
||||
|
@ -1,127 +0,0 @@
|
||||
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
|
||||
|
@ -1,203 +0,0 @@
|
||||
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
|
||||
|
@ -1,94 +0,0 @@
|
||||
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
|
||||
|
@ -1,262 +0,0 @@
|
||||
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
|
||||
|
@ -1,127 +0,0 @@
|
||||
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
|
||||
|
@ -1,122 +0,0 @@
|
||||
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
|
||||
|
@ -1,237 +0,0 @@
|
||||
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
|
||||
|
@ -1,268 +0,0 @@
|
||||
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
|
||||
|
@ -1,46 +0,0 @@
|
||||
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
|
||||
|
@ -1,54 +0,0 @@
|
||||
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
|
||||
|
@ -1,167 +0,0 @@
|
||||
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
|
||||
|
@ -1,65 +0,0 @@
|
||||
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
|
||||
|
@ -1,48 +0,0 @@
|
||||
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
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue