forked from rpms/qemu-kvm
Compare commits
No commits in common. 'c9-beta' and 'c9' have entirely different histories.
@ -1 +1 @@
|
|||||||
SOURCES/qemu-8.2.0.tar.xz
|
SOURCES/qemu-9.0.0.tar.xz
|
||||||
|
@ -1 +1 @@
|
|||||||
1615e59b1bd68324e0819245fe003e33c14a52f9 SOURCES/qemu-8.2.0.tar.xz
|
6699bb03d6da21159b89668bca01c6c958b95d07 SOURCES/qemu-9.0.0.tar.xz
|
||||||
|
@ -0,0 +1,121 @@
|
|||||||
|
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,44 +0,0 @@
|
|||||||
From 3b9b38339346ebfaf3e8ddf0822eba1cc9e78408 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
Date: Thu, 14 Dec 2023 04:42:01 -0500
|
|
||||||
Subject: Introduce RHEL 9.4.0 qemu-kvm machine type for aarch64
|
|
||||||
|
|
||||||
Jira: https://issues.redhat.com/browse/RHEL-17168
|
|
||||||
|
|
||||||
Adding new machine type to support enabling new features.
|
|
||||||
|
|
||||||
Signed-off-by: Miroslav Rezanina <mrezanin@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 c541efee5e..0b17c94ad7 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -3630,14 +3630,21 @@ static void rhel_machine_init(void)
|
|
||||||
}
|
|
||||||
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, arm_rhel_compat, arm_rhel_compat_len);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
-DEFINE_RHEL_MACHINE_AS_LATEST(9, 2, 0)
|
|
||||||
+DEFINE_RHEL_MACHINE(9, 2, 0)
|
|
||||||
|
|
||||||
static void rhel900_virt_options(MachineClass *mc)
|
|
||||||
{
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
From ba574acacf679850e337ec2d5e7836b8277cf393 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sebastian Ott <sebott@redhat.com>
|
||||||
|
Date: Thu, 18 Apr 2024 15:04:28 +0200
|
||||||
|
Subject: x86: rhel 9.4.0 machine type compat fix
|
||||||
|
|
||||||
|
Fix up the compatibility for 9.4.0. Ensure that pc-q35-rhel9.4.0
|
||||||
|
still uses SMBIOS 3.X by default.
|
||||||
|
|
||||||
|
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_q35.c | 3 +++
|
||||||
|
1 file changed, 3 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index 2b54944c0f..2f11f9af7d 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -734,6 +734,9 @@ static void pc_q35_machine_rhel940_options(MachineClass *m)
|
||||||
|
pcmc->smbios_stream_product = "RHEL";
|
||||||
|
pcmc->smbios_stream_version = "9.4.0";
|
||||||
|
|
||||||
|
+ /* From pc_q35_8_2_machine_options() - use SMBIOS 3.X by default */
|
||||||
|
+ pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64;
|
||||||
|
+
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||||
|
hw_compat_rhel_9_5_len);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
From 363d6aedc82314a70bdfbe9fa23b7e8fdda50138 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Date: Thu, 11 Jan 2024 12:26:19 -0500
|
|
||||||
Subject: [PATCH 066/101] Compile IOMMUFD object on aarch64
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [65/67] 9358030fdd499c5fe122dee3bb4f114966fac9c2 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Upstream: RHEL only
|
|
||||||
|
|
||||||
Compiles the IOMMUFD object on aarch64 to be able to use
|
|
||||||
the IOMMUFD VFIO backend.
|
|
||||||
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
configs/devices/aarch64-softmmu/aarch64-rh-devices.mak | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak b/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
index aec1831199..b0191d3c69 100644
|
|
||||||
--- a/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/aarch64-softmmu/aarch64-rh-devices.mak
|
|
||||||
@@ -39,3 +39,4 @@ CONFIG_PXB=y
|
|
||||||
CONFIG_VHOST_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
+CONFIG_IOMMUFD=y
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
From c1e9ddf8d0ea6d358fcaa5cacd3a91920f36e73b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Date: Thu, 11 Jan 2024 12:33:17 -0500
|
|
||||||
Subject: [PATCH 067/101] Compile IOMMUFD on s390x
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [66/67] d3004aafca2bb76d817ac99c3d65973b8fbd4557 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Upstream: RHEL only
|
|
||||||
|
|
||||||
Compiles the IOMMUFD object on s390x to be able to use
|
|
||||||
the IOMMUFD VFIO backend.
|
|
||||||
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
configs/devices/s390x-softmmu/s390x-rh-devices.mak | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/configs/devices/s390x-softmmu/s390x-rh-devices.mak b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
index 69a799adbd..24cf6dbd03 100644
|
|
||||||
--- a/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
+++ b/configs/devices/s390x-softmmu/s390x-rh-devices.mak
|
|
||||||
@@ -16,3 +16,4 @@ CONFIG_WDT_DIAG288=y
|
|
||||||
CONFIG_VHOST_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
+CONFIG_IOMMUFD=y
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
|||||||
From be2c3d9bbee1bdec061c901f507bc999fa40a53e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Date: Thu, 11 Jan 2024 12:34:44 -0500
|
|
||||||
Subject: [PATCH 068/101] Compile IOMMUFD on x86_64
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [67/67] 411d48a5cc7ce1f05be793fd9a89c143ce34c91a (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Upstream: RHEL only
|
|
||||||
|
|
||||||
Compiles the IOMMUFD object on s390x to be able to use
|
|
||||||
the IOMMUFD VFIO backend.
|
|
||||||
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
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 ce5be73633..ba41108e0c 100644
|
|
||||||
--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
+++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak
|
|
||||||
@@ -108,3 +108,4 @@ CONFIG_SGX=y
|
|
||||||
CONFIG_VHOST_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_VSOCK=y
|
|
||||||
CONFIG_VHOST_USER_FS=y
|
|
||||||
+CONFIG_IOMMUFD=y
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,139 @@
|
|||||||
|
From 93ea86ac8849ad9ca365b1646313dde9a34ba59c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:03 -0500
|
||||||
|
Subject: [PATCH 031/100] HostMem: Add mechanism to opt in kvm guest memfd via
|
||||||
|
MachineState
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [31/91] 43ce32aef954479cdb736301d1adcb919602c321 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add a new member "guest_memfd" to memory backends. When it's set
|
||||||
|
to true, it enables RAM_GUEST_MEMFD in ram_flags, thus private kvm
|
||||||
|
guest_memfd will be allocated during RAMBlock allocation.
|
||||||
|
|
||||||
|
Memory backend's @guest_memfd is wired with @require_guest_memfd
|
||||||
|
field of MachineState. It avoid looking up the machine in phymem.c.
|
||||||
|
|
||||||
|
MachineState::require_guest_memfd is supposed to be set by any VMs
|
||||||
|
that requires KVM guest memfd as private memory, e.g., TDX VM.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||||
|
Message-ID: <20240320083945.991426-8-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 37662d85b0b7dded0ebdf6747bef6c3bb7ed6a0c)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
backends/hostmem-file.c | 1 +
|
||||||
|
backends/hostmem-memfd.c | 1 +
|
||||||
|
backends/hostmem-ram.c | 1 +
|
||||||
|
backends/hostmem.c | 1 +
|
||||||
|
hw/core/machine.c | 5 +++++
|
||||||
|
include/hw/boards.h | 2 ++
|
||||||
|
include/sysemu/hostmem.h | 1 +
|
||||||
|
7 files changed, 12 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
|
||||||
|
index ac3e433cbd..3c69db7946 100644
|
||||||
|
--- a/backends/hostmem-file.c
|
||||||
|
+++ b/backends/hostmem-file.c
|
||||||
|
@@ -85,6 +85,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||||
|
ram_flags |= fb->readonly ? RAM_READONLY_FD : 0;
|
||||||
|
ram_flags |= fb->rom == ON_OFF_AUTO_ON ? RAM_READONLY : 0;
|
||||||
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
|
+ ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||||
|
ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
|
||||||
|
ram_flags |= RAM_NAMED_FILE;
|
||||||
|
return memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
|
||||||
|
diff --git a/backends/hostmem-memfd.c b/backends/hostmem-memfd.c
|
||||||
|
index 3923ea9364..745ead0034 100644
|
||||||
|
--- a/backends/hostmem-memfd.c
|
||||||
|
+++ b/backends/hostmem-memfd.c
|
||||||
|
@@ -55,6 +55,7 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||||
|
name = host_memory_backend_get_name(backend);
|
||||||
|
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||||
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
|
+ ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||||
|
return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
||||||
|
backend->size, ram_flags, fd, 0, errp);
|
||||||
|
}
|
||||||
|
diff --git a/backends/hostmem-ram.c b/backends/hostmem-ram.c
|
||||||
|
index d121249f0f..f7d81af783 100644
|
||||||
|
--- a/backends/hostmem-ram.c
|
||||||
|
+++ b/backends/hostmem-ram.c
|
||||||
|
@@ -30,6 +30,7 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||||
|
name = host_memory_backend_get_name(backend);
|
||||||
|
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||||
|
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||||
|
+ ram_flags |= backend->guest_memfd ? RAM_GUEST_MEMFD : 0;
|
||||||
|
return memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend),
|
||||||
|
name, backend->size,
|
||||||
|
ram_flags, errp);
|
||||||
|
diff --git a/backends/hostmem.c b/backends/hostmem.c
|
||||||
|
index 81a72ce40b..eb9682b4a8 100644
|
||||||
|
--- a/backends/hostmem.c
|
||||||
|
+++ b/backends/hostmem.c
|
||||||
|
@@ -277,6 +277,7 @@ static void host_memory_backend_init(Object *obj)
|
||||||
|
/* TODO: convert access to globals to compat properties */
|
||||||
|
backend->merge = machine_mem_merge(machine);
|
||||||
|
backend->dump = machine_dump_guest_core(machine);
|
||||||
|
+ backend->guest_memfd = machine_require_guest_memfd(machine);
|
||||||
|
backend->reserve = true;
|
||||||
|
backend->prealloc_threads = machine->smp.cpus;
|
||||||
|
}
|
||||||
|
diff --git a/hw/core/machine.c b/hw/core/machine.c
|
||||||
|
index 92609aae27..07b994e136 100644
|
||||||
|
--- a/hw/core/machine.c
|
||||||
|
+++ b/hw/core/machine.c
|
||||||
|
@@ -1480,6 +1480,11 @@ bool machine_mem_merge(MachineState *machine)
|
||||||
|
return machine->mem_merge;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool machine_require_guest_memfd(MachineState *machine)
|
||||||
|
+{
|
||||||
|
+ return machine->require_guest_memfd;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static char *cpu_slot_to_string(const CPUArchId *cpu)
|
||||||
|
{
|
||||||
|
GString *s = g_string_new(NULL);
|
||||||
|
diff --git a/include/hw/boards.h b/include/hw/boards.h
|
||||||
|
index cca62f906b..815a1c4b26 100644
|
||||||
|
--- a/include/hw/boards.h
|
||||||
|
+++ b/include/hw/boards.h
|
||||||
|
@@ -36,6 +36,7 @@ bool machine_usb(MachineState *machine);
|
||||||
|
int machine_phandle_start(MachineState *machine);
|
||||||
|
bool machine_dump_guest_core(MachineState *machine);
|
||||||
|
bool machine_mem_merge(MachineState *machine);
|
||||||
|
+bool machine_require_guest_memfd(MachineState *machine);
|
||||||
|
HotpluggableCPUList *machine_query_hotpluggable_cpus(MachineState *machine);
|
||||||
|
void machine_set_cpu_numa_node(MachineState *machine,
|
||||||
|
const CpuInstanceProperties *props,
|
||||||
|
@@ -372,6 +373,7 @@ struct MachineState {
|
||||||
|
char *dt_compatible;
|
||||||
|
bool dump_guest_core;
|
||||||
|
bool mem_merge;
|
||||||
|
+ bool require_guest_memfd;
|
||||||
|
bool usb;
|
||||||
|
bool usb_disabled;
|
||||||
|
char *firmware;
|
||||||
|
diff --git a/include/sysemu/hostmem.h b/include/sysemu/hostmem.h
|
||||||
|
index 0e411aaa29..04b884bf42 100644
|
||||||
|
--- a/include/sysemu/hostmem.h
|
||||||
|
+++ b/include/sysemu/hostmem.h
|
||||||
|
@@ -74,6 +74,7 @@ struct HostMemoryBackend {
|
||||||
|
uint64_t size;
|
||||||
|
bool merge, dump, use_canonical_path;
|
||||||
|
bool prealloc, is_mapped, share, reserve;
|
||||||
|
+ bool guest_memfd;
|
||||||
|
uint32_t prealloc_threads;
|
||||||
|
ThreadContext *prealloc_context;
|
||||||
|
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,203 @@
|
|||||||
|
From c46ac3db0a4db60e667edeabc9ed451c6e8e0ccf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Mon, 18 Mar 2024 14:41:33 -0400
|
||||||
|
Subject: [PATCH 020/100] KVM: remove kvm_arch_cpu_check_are_resettable
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [20/91] d7745bd1a0ed1b215847f150f4a1bb2e912beabc (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Board reset requires writing a fresh CPU state. As far as KVM is
|
||||||
|
concerned, the only thing that blocks reset is that CPU state is
|
||||||
|
encrypted; therefore, kvm_cpus_are_resettable() can simply check
|
||||||
|
if that is the case.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a99c0c66ebe7d8db3af6f16689ade9375247e43e)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-accel-ops.c | 2 +-
|
||||||
|
accel/kvm/kvm-all.c | 5 -----
|
||||||
|
include/sysemu/kvm.h | 10 ----------
|
||||||
|
target/arm/kvm.c | 5 -----
|
||||||
|
target/i386/kvm/kvm.c | 5 -----
|
||||||
|
target/loongarch/kvm/kvm.c | 5 -----
|
||||||
|
target/mips/kvm.c | 5 -----
|
||||||
|
target/ppc/kvm.c | 5 -----
|
||||||
|
target/riscv/kvm/kvm-cpu.c | 5 -----
|
||||||
|
target/s390x/kvm/kvm.c | 5 -----
|
||||||
|
10 files changed, 1 insertion(+), 51 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c
|
||||||
|
index b3c946dc4b..74e3c5785b 100644
|
||||||
|
--- a/accel/kvm/kvm-accel-ops.c
|
||||||
|
+++ b/accel/kvm/kvm-accel-ops.c
|
||||||
|
@@ -82,7 +82,7 @@ static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
|
||||||
|
|
||||||
|
static bool kvm_cpus_are_resettable(void)
|
||||||
|
{
|
||||||
|
- return !kvm_enabled() || kvm_cpu_check_are_resettable();
|
||||||
|
+ return !kvm_enabled() || !kvm_state->guest_state_protected;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KVM_CAP_SET_GUEST_DEBUG
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index ec0f6df7c5..b51e09a583 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -2696,11 +2696,6 @@ void kvm_flush_coalesced_mmio_buffer(void)
|
||||||
|
s->coalesced_flush_in_progress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return kvm_arch_cpu_check_are_resettable();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
{
|
||||||
|
if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index 302e8f6f1e..54f4d83a37 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -525,16 +525,6 @@ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target);
|
||||||
|
/* Notify resamplefd for EOI of specific interrupts. */
|
||||||
|
void kvm_resample_fd_notify(int gsi);
|
||||||
|
|
||||||
|
-/**
|
||||||
|
- * kvm_cpu_check_are_resettable - return whether CPUs can be reset
|
||||||
|
- *
|
||||||
|
- * Returns: true: CPUs are resettable
|
||||||
|
- * false: CPUs are not resettable
|
||||||
|
- */
|
||||||
|
-bool kvm_cpu_check_are_resettable(void);
|
||||||
|
-
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void);
|
||||||
|
-
|
||||||
|
bool kvm_dirty_ring_enabled(void);
|
||||||
|
|
||||||
|
uint32_t kvm_dirty_ring_size(void);
|
||||||
|
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
|
||||||
|
index ab85d628a8..21ebbf3b8f 100644
|
||||||
|
--- a/target/arm/kvm.c
|
||||||
|
+++ b/target/arm/kvm.c
|
||||||
|
@@ -1598,11 +1598,6 @@ int kvm_arch_msi_data_to_gsi(uint32_t data)
|
||||||
|
return (data - 32) & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void kvm_arch_get_eager_split_size(Object *obj, Visitor *v,
|
||||||
|
const char *name, void *opaque,
|
||||||
|
Error **errp)
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index e271652620..a12207a8ee 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -5623,11 +5623,6 @@ bool kvm_has_waitpkg(void)
|
||||||
|
return has_msr_umwait;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return !sev_es_enabled();
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
#define ARCH_REQ_XCOMP_GUEST_PERM 0x1025
|
||||||
|
|
||||||
|
void kvm_request_xsave_components(X86CPU *cpu, uint64_t mask)
|
||||||
|
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
|
||||||
|
index d630cc39cb..8224d94333 100644
|
||||||
|
--- a/target/loongarch/kvm/kvm.c
|
||||||
|
+++ b/target/loongarch/kvm/kvm.c
|
||||||
|
@@ -733,11 +733,6 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
|
||||||
|
index 6c52e59f55..a631ab544f 100644
|
||||||
|
--- a/target/mips/kvm.c
|
||||||
|
+++ b/target/mips/kvm.c
|
||||||
|
@@ -1273,11 +1273,6 @@ int kvm_arch_get_default_type(MachineState *machine)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void kvm_arch_accel_class_init(ObjectClass *oc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
|
||||||
|
index 59f640cf7b..9d9d9f0d79 100644
|
||||||
|
--- a/target/ppc/kvm.c
|
||||||
|
+++ b/target/ppc/kvm.c
|
||||||
|
@@ -2968,11 +2968,6 @@ void kvmppc_set_reg_tb_offset(PowerPCCPU *cpu, int64_t tb_offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
void kvm_arch_accel_class_init(ObjectClass *oc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
|
||||||
|
index 6a6c6cae80..49d2f3ad58 100644
|
||||||
|
--- a/target/riscv/kvm/kvm-cpu.c
|
||||||
|
+++ b/target/riscv/kvm/kvm-cpu.c
|
||||||
|
@@ -1475,11 +1475,6 @@ void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int aia_mode;
|
||||||
|
|
||||||
|
static const char *kvm_aia_mode_str(uint64_t mode)
|
||||||
|
diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
|
||||||
|
index 55fb4855b1..4db59658e1 100644
|
||||||
|
--- a/target/s390x/kvm/kvm.c
|
||||||
|
+++ b/target/s390x/kvm/kvm.c
|
||||||
|
@@ -2630,11 +2630,6 @@ void kvm_s390_stop_interrupt(S390CPU *cpu)
|
||||||
|
kvm_s390_vcpu_interrupt(cpu, &irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
-bool kvm_arch_cpu_check_are_resettable(void)
|
||||||
|
-{
|
||||||
|
- return true;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
int kvm_s390_get_zpci_op(void)
|
||||||
|
{
|
||||||
|
return cap_zpci_op;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,127 @@
|
|||||||
|
From 50399796da938c4ea7c69058fde84695bce9d794 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Mon, 18 Mar 2024 14:41:10 -0400
|
||||||
|
Subject: [PATCH 019/100] KVM: track whether guest state is encrypted
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [19/91] 685b9c54d43d0043d15c33d13afc3a420cbe139b (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
So far, KVM has allowed KVM_GET/SET_* ioctls to execute even if the
|
||||||
|
guest state is encrypted, in which case they do nothing. For the new
|
||||||
|
API using VM types, instead, the ioctls will fail which is a safer and
|
||||||
|
more robust approach.
|
||||||
|
|
||||||
|
The new API will be the only one available for SEV-SNP and TDX, but it
|
||||||
|
is also usable for SEV and SEV-ES. In preparation for that, require
|
||||||
|
architecture-specific KVM code to communicate the point at which guest
|
||||||
|
state is protected (which must be after kvm_cpu_synchronize_post_init(),
|
||||||
|
though that might change in the future in order to suppor migration).
|
||||||
|
From that point, skip reading registers so that cpu->vcpu_dirty is
|
||||||
|
never true: if it ever becomes true, kvm_arch_put_registers() will
|
||||||
|
fail miserably.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 5c3131c392f84c660033d511ec39872d8beb4b1e)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 17 ++++++++++++++---
|
||||||
|
include/sysemu/kvm.h | 2 ++
|
||||||
|
include/sysemu/kvm_int.h | 1 +
|
||||||
|
target/i386/sev.c | 1 +
|
||||||
|
4 files changed, 18 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 931f74256e..ec0f6df7c5 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -2703,7 +2703,7 @@ bool kvm_cpu_check_are_resettable(void)
|
||||||
|
|
||||||
|
static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
{
|
||||||
|
- if (!cpu->vcpu_dirty) {
|
||||||
|
+ if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
|
||||||
|
int ret = kvm_arch_get_registers(cpu);
|
||||||
|
if (ret) {
|
||||||
|
error_report("Failed to get registers: %s", strerror(-ret));
|
||||||
|
@@ -2717,7 +2717,7 @@ static void do_kvm_cpu_synchronize_state(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
|
||||||
|
void kvm_cpu_synchronize_state(CPUState *cpu)
|
||||||
|
{
|
||||||
|
- if (!cpu->vcpu_dirty) {
|
||||||
|
+ if (!cpu->vcpu_dirty && !kvm_state->guest_state_protected) {
|
||||||
|
run_on_cpu(cpu, do_kvm_cpu_synchronize_state, RUN_ON_CPU_NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -2752,7 +2752,13 @@ static void do_kvm_cpu_synchronize_post_init(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
|
||||||
|
void kvm_cpu_synchronize_post_init(CPUState *cpu)
|
||||||
|
{
|
||||||
|
- run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
|
||||||
|
+ if (!kvm_state->guest_state_protected) {
|
||||||
|
+ /*
|
||||||
|
+ * This runs before the machine_init_done notifiers, and is the last
|
||||||
|
+ * opportunity to synchronize the state of confidential guests.
|
||||||
|
+ */
|
||||||
|
+ run_on_cpu(cpu, do_kvm_cpu_synchronize_post_init, RUN_ON_CPU_NULL);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_kvm_cpu_synchronize_pre_loadvm(CPUState *cpu, run_on_cpu_data arg)
|
||||||
|
@@ -4099,3 +4105,8 @@ void query_stats_schemas_cb(StatsSchemaList **result, Error **errp)
|
||||||
|
query_stats_schema_vcpu(first_cpu, &stats_args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void kvm_mark_guest_state_protected(void)
|
||||||
|
+{
|
||||||
|
+ kvm_state->guest_state_protected = true;
|
||||||
|
+}
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index fad9a7e8ff..302e8f6f1e 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -539,6 +539,8 @@ bool kvm_dirty_ring_enabled(void);
|
||||||
|
|
||||||
|
uint32_t kvm_dirty_ring_size(void);
|
||||||
|
|
||||||
|
+void kvm_mark_guest_state_protected(void);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* kvm_hwpoisoned_mem - indicate if there is any hwpoisoned page
|
||||||
|
* reported for the VM.
|
||||||
|
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
|
||||||
|
index 882e37e12c..3496be7997 100644
|
||||||
|
--- a/include/sysemu/kvm_int.h
|
||||||
|
+++ b/include/sysemu/kvm_int.h
|
||||||
|
@@ -87,6 +87,7 @@ struct KVMState
|
||||||
|
bool kernel_irqchip_required;
|
||||||
|
OnOffAuto kernel_irqchip_split;
|
||||||
|
bool sync_mmu;
|
||||||
|
+ bool guest_state_protected;
|
||||||
|
uint64_t manual_dirty_log_protect;
|
||||||
|
/* The man page (and posix) say ioctl numbers are signed int, but
|
||||||
|
* they're not. Linux, glibc and *BSD all treat ioctl numbers as
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index b8f79d34d1..c49a8fd55e 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -755,6 +755,7 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
|
||||||
|
if (ret) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
+ kvm_mark_guest_state_protected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* query the measurement blob length */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,329 @@
|
|||||||
|
From f4b01d645926faab2cab86fadb7398c26d6b8285 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 20 Mar 2024 03:39:02 -0500
|
||||||
|
Subject: [PATCH 028/100] RAMBlock: Add support of KVM private guest memfd
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [28/91] 95fdf196afcb67113834c20fa354ee1397411bfd (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add KVM guest_memfd support to RAMBlock so both normal hva based memory
|
||||||
|
and kvm guest memfd based private memory can be associated in one RAMBlock.
|
||||||
|
|
||||||
|
Introduce new flag RAM_GUEST_MEMFD. When it's set, it calls KVM ioctl to
|
||||||
|
create private guest_memfd during RAMBlock setup.
|
||||||
|
|
||||||
|
Allocating a new RAM_GUEST_MEMFD flag to instruct the setup of guest memfd
|
||||||
|
is more flexible and extensible than simply relying on the VM type because
|
||||||
|
in the future we may have the case that not all the memory of a VM need
|
||||||
|
guest memfd. As a benefit, it also avoid getting MachineState in memory
|
||||||
|
subsystem.
|
||||||
|
|
||||||
|
Note, RAM_GUEST_MEMFD is supposed to be set for memory backends of
|
||||||
|
confidential guests, such as TDX VM. How and when to set it for memory
|
||||||
|
backends will be implemented in the following patches.
|
||||||
|
|
||||||
|
Introduce memory_region_has_guest_memfd() to query if the MemoryRegion has
|
||||||
|
KVM guest_memfd allocated.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||||
|
Message-ID: <20240320083945.991426-7-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 15f7a80c49cb3637f62fa37fa4a17da913bd91ff)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
accel/kvm/kvm-all.c | 28 ++++++++++++++++++++++++++++
|
||||||
|
accel/stubs/kvm-stub.c | 5 +++++
|
||||||
|
include/exec/memory.h | 20 +++++++++++++++++---
|
||||||
|
include/exec/ram_addr.h | 2 +-
|
||||||
|
include/exec/ramblock.h | 1 +
|
||||||
|
include/sysemu/kvm.h | 2 ++
|
||||||
|
system/memory.c | 5 +++++
|
||||||
|
system/physmem.c | 34 +++++++++++++++++++++++++++++++---
|
||||||
|
8 files changed, 90 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||||
|
index 272e945f52..a7b9a127dd 100644
|
||||||
|
--- a/accel/kvm/kvm-all.c
|
||||||
|
+++ b/accel/kvm/kvm-all.c
|
||||||
|
@@ -92,6 +92,7 @@ static bool kvm_has_guest_debug;
|
||||||
|
static int kvm_sstep_flags;
|
||||||
|
static bool kvm_immediate_exit;
|
||||||
|
static uint64_t kvm_supported_memory_attributes;
|
||||||
|
+static bool kvm_guest_memfd_supported;
|
||||||
|
static hwaddr kvm_max_slot_size = ~0;
|
||||||
|
|
||||||
|
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||||
|
@@ -2419,6 +2420,11 @@ static int kvm_init(MachineState *ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
kvm_supported_memory_attributes = kvm_check_extension(s, KVM_CAP_MEMORY_ATTRIBUTES);
|
||||||
|
+ kvm_guest_memfd_supported =
|
||||||
|
+ kvm_check_extension(s, KVM_CAP_GUEST_MEMFD) &&
|
||||||
|
+ kvm_check_extension(s, KVM_CAP_USER_MEMORY2) &&
|
||||||
|
+ (kvm_supported_memory_attributes & KVM_MEMORY_ATTRIBUTE_PRIVATE);
|
||||||
|
+
|
||||||
|
kvm_immediate_exit = kvm_check_extension(s, KVM_CAP_IMMEDIATE_EXIT);
|
||||||
|
s->nr_slots = kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS);
|
||||||
|
|
||||||
|
@@ -4138,3 +4144,25 @@ void kvm_mark_guest_state_protected(void)
|
||||||
|
{
|
||||||
|
kvm_state->guest_state_protected = true;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
|
||||||
|
+{
|
||||||
|
+ int fd;
|
||||||
|
+ struct kvm_create_guest_memfd guest_memfd = {
|
||||||
|
+ .size = size,
|
||||||
|
+ .flags = flags,
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ if (!kvm_guest_memfd_supported) {
|
||||||
|
+ error_setg(errp, "KVM does not support guest_memfd");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_GUEST_MEMFD, &guest_memfd);
|
||||||
|
+ if (fd < 0) {
|
||||||
|
+ error_setg_errno(errp, errno, "Error creating KVM guest_memfd");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return fd;
|
||||||
|
+}
|
||||||
|
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
|
||||||
|
index ca38172884..8e0eb22e61 100644
|
||||||
|
--- a/accel/stubs/kvm-stub.c
|
||||||
|
+++ b/accel/stubs/kvm-stub.c
|
||||||
|
@@ -129,3 +129,8 @@ bool kvm_hwpoisoned_mem(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp)
|
||||||
|
+{
|
||||||
|
+ return -ENOSYS;
|
||||||
|
+}
|
||||||
|
diff --git a/include/exec/memory.h b/include/exec/memory.h
|
||||||
|
index 8626a355b3..679a847685 100644
|
||||||
|
--- a/include/exec/memory.h
|
||||||
|
+++ b/include/exec/memory.h
|
||||||
|
@@ -243,6 +243,9 @@ typedef struct IOMMUTLBEvent {
|
||||||
|
/* RAM FD is opened read-only */
|
||||||
|
#define RAM_READONLY_FD (1 << 11)
|
||||||
|
|
||||||
|
+/* RAM can be private that has kvm guest memfd backend */
|
||||||
|
+#define RAM_GUEST_MEMFD (1 << 12)
|
||||||
|
+
|
||||||
|
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
|
||||||
|
IOMMUNotifierFlag flags,
|
||||||
|
hwaddr start, hwaddr end,
|
||||||
|
@@ -1307,7 +1310,8 @@ bool memory_region_init_ram_nomigrate(MemoryRegion *mr,
|
||||||
|
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||||
|
* must be unique within any device
|
||||||
|
* @size: size of the region.
|
||||||
|
- * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_NORESERVE.
|
||||||
|
+ * @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_NORESERVE,
|
||||||
|
+ * RAM_GUEST_MEMFD.
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
|
*
|
||||||
|
* Note that this function does not do anything to cause the data in the
|
||||||
|
@@ -1369,7 +1373,7 @@ bool memory_region_init_resizeable_ram(MemoryRegion *mr,
|
||||||
|
* (getpagesize()) will be used.
|
||||||
|
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||||
|
* RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
|
||||||
|
- * RAM_READONLY_FD
|
||||||
|
+ * RAM_READONLY_FD, RAM_GUEST_MEMFD
|
||||||
|
* @path: the path in which to allocate the RAM.
|
||||||
|
* @offset: offset within the file referenced by path
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
|
@@ -1399,7 +1403,7 @@ bool memory_region_init_ram_from_file(MemoryRegion *mr,
|
||||||
|
* @size: size of the region.
|
||||||
|
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||||
|
* RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
|
||||||
|
- * RAM_READONLY_FD
|
||||||
|
+ * RAM_READONLY_FD, RAM_GUEST_MEMFD
|
||||||
|
* @fd: the fd to mmap.
|
||||||
|
* @offset: offset within the file referenced by fd
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
|
@@ -1722,6 +1726,16 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
|
||||||
|
*/
|
||||||
|
bool memory_region_is_protected(MemoryRegion *mr);
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * memory_region_has_guest_memfd: check whether a memory region has guest_memfd
|
||||||
|
+ * associated
|
||||||
|
+ *
|
||||||
|
+ * Returns %true if a memory region's ram_block has valid guest_memfd assigned.
|
||||||
|
+ *
|
||||||
|
+ * @mr: the memory region being queried
|
||||||
|
+ */
|
||||||
|
+bool memory_region_has_guest_memfd(MemoryRegion *mr);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* memory_region_get_iommu: check whether a memory region is an iommu
|
||||||
|
*
|
||||||
|
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
|
||||||
|
index de45ba7bc9..07c8f86375 100644
|
||||||
|
--- a/include/exec/ram_addr.h
|
||||||
|
+++ b/include/exec/ram_addr.h
|
||||||
|
@@ -110,7 +110,7 @@ long qemu_maxrampagesize(void);
|
||||||
|
* @mr: the memory region where the ram block is
|
||||||
|
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||||
|
* RAM_NORESERVE, RAM_PROTECTED, RAM_NAMED_FILE, RAM_READONLY,
|
||||||
|
- * RAM_READONLY_FD
|
||||||
|
+ * RAM_READONLY_FD, RAM_GUEST_MEMFD
|
||||||
|
* @mem_path or @fd: specify the backing file or device
|
||||||
|
* @offset: Offset into target file
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens
|
||||||
|
diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h
|
||||||
|
index 848915ea5b..459c8917de 100644
|
||||||
|
--- a/include/exec/ramblock.h
|
||||||
|
+++ b/include/exec/ramblock.h
|
||||||
|
@@ -41,6 +41,7 @@ struct RAMBlock {
|
||||||
|
QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers;
|
||||||
|
int fd;
|
||||||
|
uint64_t fd_offset;
|
||||||
|
+ int guest_memfd;
|
||||||
|
size_t page_size;
|
||||||
|
/* dirty bitmap used during migration */
|
||||||
|
unsigned long *bmap;
|
||||||
|
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||||
|
index f114ff6986..9e4ab7ae89 100644
|
||||||
|
--- a/include/sysemu/kvm.h
|
||||||
|
+++ b/include/sysemu/kvm.h
|
||||||
|
@@ -537,6 +537,8 @@ void kvm_mark_guest_state_protected(void);
|
||||||
|
*/
|
||||||
|
bool kvm_hwpoisoned_mem(void);
|
||||||
|
|
||||||
|
+int kvm_create_guest_memfd(uint64_t size, uint64_t flags, Error **errp);
|
||||||
|
+
|
||||||
|
int kvm_set_memory_attributes_private(hwaddr start, uint64_t size);
|
||||||
|
int kvm_set_memory_attributes_shared(hwaddr start, uint64_t size);
|
||||||
|
|
||||||
|
diff --git a/system/memory.c b/system/memory.c
|
||||||
|
index a229a79988..c756950c0c 100644
|
||||||
|
--- a/system/memory.c
|
||||||
|
+++ b/system/memory.c
|
||||||
|
@@ -1850,6 +1850,11 @@ bool memory_region_is_protected(MemoryRegion *mr)
|
||||||
|
return mr->ram && (mr->ram_block->flags & RAM_PROTECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool memory_region_has_guest_memfd(MemoryRegion *mr)
|
||||||
|
+{
|
||||||
|
+ return mr->ram_block && mr->ram_block->guest_memfd >= 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
|
||||||
|
{
|
||||||
|
uint8_t mask = mr->dirty_log_mask;
|
||||||
|
diff --git a/system/physmem.c b/system/physmem.c
|
||||||
|
index a4fe3d2bf8..f5dfa20e57 100644
|
||||||
|
--- a/system/physmem.c
|
||||||
|
+++ b/system/physmem.c
|
||||||
|
@@ -1808,6 +1808,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
const bool shared = qemu_ram_is_shared(new_block);
|
||||||
|
RAMBlock *block;
|
||||||
|
RAMBlock *last_block = NULL;
|
||||||
|
+ bool free_on_error = false;
|
||||||
|
ram_addr_t old_ram_size, new_ram_size;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
@@ -1837,6 +1838,19 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memory_try_enable_merging(new_block->host, new_block->max_length);
|
||||||
|
+ free_on_error = true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (new_block->flags & RAM_GUEST_MEMFD) {
|
||||||
|
+ assert(kvm_enabled());
|
||||||
|
+ assert(new_block->guest_memfd < 0);
|
||||||
|
+
|
||||||
|
+ new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
|
||||||
|
+ 0, errp);
|
||||||
|
+ if (new_block->guest_memfd < 0) {
|
||||||
|
+ qemu_mutex_unlock_ramlist();
|
||||||
|
+ goto out_free;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1888,6 +1902,13 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
ram_block_notify_add(new_block->host, new_block->used_length,
|
||||||
|
new_block->max_length);
|
||||||
|
}
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+out_free:
|
||||||
|
+ if (free_on_error) {
|
||||||
|
+ qemu_anon_ram_free(new_block->host, new_block->max_length);
|
||||||
|
+ new_block->host = NULL;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_POSIX
|
||||||
|
@@ -1902,7 +1923,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
||||||
|
/* Just support these ram flags by now. */
|
||||||
|
assert((ram_flags & ~(RAM_SHARED | RAM_PMEM | RAM_NORESERVE |
|
||||||
|
RAM_PROTECTED | RAM_NAMED_FILE | RAM_READONLY |
|
||||||
|
- RAM_READONLY_FD)) == 0);
|
||||||
|
+ RAM_READONLY_FD | RAM_GUEST_MEMFD)) == 0);
|
||||||
|
|
||||||
|
if (xen_enabled()) {
|
||||||
|
error_setg(errp, "-mem-path not supported with Xen");
|
||||||
|
@@ -1939,6 +1960,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
||||||
|
new_block->used_length = size;
|
||||||
|
new_block->max_length = size;
|
||||||
|
new_block->flags = ram_flags;
|
||||||
|
+ new_block->guest_memfd = -1;
|
||||||
|
new_block->host = file_ram_alloc(new_block, size, fd, !file_size, offset,
|
||||||
|
errp);
|
||||||
|
if (!new_block->host) {
|
||||||
|
@@ -2018,7 +2040,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
|
||||||
|
int align;
|
||||||
|
|
||||||
|
assert((ram_flags & ~(RAM_SHARED | RAM_RESIZEABLE | RAM_PREALLOC |
|
||||||
|
- RAM_NORESERVE)) == 0);
|
||||||
|
+ RAM_NORESERVE | RAM_GUEST_MEMFD)) == 0);
|
||||||
|
assert(!host ^ (ram_flags & RAM_PREALLOC));
|
||||||
|
|
||||||
|
align = qemu_real_host_page_size();
|
||||||
|
@@ -2033,6 +2055,7 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size,
|
||||||
|
new_block->max_length = max_size;
|
||||||
|
assert(max_size >= size);
|
||||||
|
new_block->fd = -1;
|
||||||
|
+ new_block->guest_memfd = -1;
|
||||||
|
new_block->page_size = qemu_real_host_page_size();
|
||||||
|
new_block->host = host;
|
||||||
|
new_block->flags = ram_flags;
|
||||||
|
@@ -2055,7 +2078,7 @@ RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
||||||
|
RAMBlock *qemu_ram_alloc(ram_addr_t size, uint32_t ram_flags,
|
||||||
|
MemoryRegion *mr, Error **errp)
|
||||||
|
{
|
||||||
|
- assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE)) == 0);
|
||||||
|
+ assert((ram_flags & ~(RAM_SHARED | RAM_NORESERVE | RAM_GUEST_MEMFD)) == 0);
|
||||||
|
return qemu_ram_alloc_internal(size, size, NULL, NULL, ram_flags, mr, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2083,6 +2106,11 @@ static void reclaim_ramblock(RAMBlock *block)
|
||||||
|
} else {
|
||||||
|
qemu_anon_ram_free(block->host, block->max_length);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (block->guest_memfd >= 0) {
|
||||||
|
+ close(block->guest_memfd);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
g_free(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,82 @@
|
|||||||
|
From bd289293604d6f33e9fb89196f0b19117ce81f89 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Wed, 20 Mar 2024 17:45:29 +0100
|
||||||
|
Subject: [PATCH 032/100] RAMBlock: make guest_memfd require uncoordinated
|
||||||
|
discard
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [32/91] 0c005849026c334737b88cbd20a0ac237dfca37e (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Some subsystems like VFIO might disable ram block discard, but guest_memfd
|
||||||
|
uses discard operations to implement conversions between private and
|
||||||
|
shared memory. Because of this, sequences like the following can result
|
||||||
|
in stale IOMMU mappings:
|
||||||
|
|
||||||
|
1. allocate shared page
|
||||||
|
2. convert page shared->private
|
||||||
|
3. discard shared page
|
||||||
|
4. convert page private->shared
|
||||||
|
5. allocate shared page
|
||||||
|
6. issue DMA operations against that shared page
|
||||||
|
|
||||||
|
This is not a use-after-free, because after step 3 VFIO is still pinning
|
||||||
|
the page. However, DMA operations in step 6 will hit the old mapping
|
||||||
|
that was allocated in step 1.
|
||||||
|
|
||||||
|
Address this by taking ram_block_discard_is_enabled() into account when
|
||||||
|
deciding whether or not to discard pages.
|
||||||
|
|
||||||
|
Since kvm_convert_memory()/guest_memfd doesn't implement a
|
||||||
|
RamDiscardManager handler to convey and replay discard operations,
|
||||||
|
this is a case of uncoordinated discard, which is blocked/released
|
||||||
|
by ram_block_discard_require(). Interestingly, this function had
|
||||||
|
no use so far.
|
||||||
|
|
||||||
|
Alternative approaches would be to block discard of shared pages, but
|
||||||
|
this would cause guests to consume twice the memory if they use VFIO;
|
||||||
|
or to implement a RamDiscardManager and only block uncoordinated
|
||||||
|
discard, i.e. use ram_block_coordinated_discard_require().
|
||||||
|
|
||||||
|
[Commit message mostly by Michael Roth <michael.roth@amd.com>]
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 852f0048f3ea9f14de18eb279a99fccb6d250e8f)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
system/physmem.c | 8 ++++++++
|
||||||
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/system/physmem.c b/system/physmem.c
|
||||||
|
index f5dfa20e57..5ebcf5be11 100644
|
||||||
|
--- a/system/physmem.c
|
||||||
|
+++ b/system/physmem.c
|
||||||
|
@@ -1846,6 +1846,13 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
|
||||||
|
assert(kvm_enabled());
|
||||||
|
assert(new_block->guest_memfd < 0);
|
||||||
|
|
||||||
|
+ if (ram_block_discard_require(true) < 0) {
|
||||||
|
+ error_setg_errno(errp, errno,
|
||||||
|
+ "cannot set up private guest memory: discard currently blocked");
|
||||||
|
+ error_append_hint(errp, "Are you using assigned devices?\n");
|
||||||
|
+ goto out_free;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
new_block->guest_memfd = kvm_create_guest_memfd(new_block->max_length,
|
||||||
|
0, errp);
|
||||||
|
if (new_block->guest_memfd < 0) {
|
||||||
|
@@ -2109,6 +2116,7 @@ static void reclaim_ramblock(RAMBlock *block)
|
||||||
|
|
||||||
|
if (block->guest_memfd >= 0) {
|
||||||
|
close(block->guest_memfd);
|
||||||
|
+ ram_block_discard_require(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(block);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,67 @@
|
|||||||
|
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
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
From bcbc897cb19b3a6523de611f48f6bac6cea16c97 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sebastian Ott <sebott@redhat.com>
|
||||||
|
Date: Thu, 2 May 2024 13:17:03 +0200
|
||||||
|
Subject: [PATCH 2/2] Revert "x86: rhel 9.4.0 machine type compat fix"
|
||||||
|
|
||||||
|
RH-Author: Sebastian Ott <sebott@redhat.com>
|
||||||
|
RH-MergeRequest: 237: Revert "x86: rhel 9.4.0 machine type compat fix"
|
||||||
|
RH-Jira: RHEL-30362
|
||||||
|
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [1/1] 858ec153e65e96c39ca4db17ed93fd58c77dc2eb (seott1/cos-qemu-kvm)
|
||||||
|
|
||||||
|
This reverts commit c46e44f0f4e861fe412ce679b0b0204881c1c2f5.
|
||||||
|
|
||||||
|
pc-q35-rhel9.4.0 and newer should stay with SMBIOS_ENTRY_POINT_TYPE_AUTO.
|
||||||
|
|
||||||
|
Signed-off-by: Sebastian Ott <sebott@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_q35.c | 3 ---
|
||||||
|
1 file changed, 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index 2f11f9af7d..2b54944c0f 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -734,9 +734,6 @@ static void pc_q35_machine_rhel940_options(MachineClass *m)
|
||||||
|
pcmc->smbios_stream_product = "RHEL";
|
||||||
|
pcmc->smbios_stream_version = "9.4.0";
|
||||||
|
|
||||||
|
- /* From pc_q35_8_2_machine_options() - use SMBIOS 3.X by default */
|
||||||
|
- pcmc->default_smbios_ep_type = SMBIOS_ENTRY_POINT_TYPE_64;
|
||||||
|
-
|
||||||
|
compat_props_add(m->compat_props, hw_compat_rhel_9_5,
|
||||||
|
hw_compat_rhel_9_5_len);
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,60 +0,0 @@
|
|||||||
From 6b5cfed21e20b372090046a934387255ff4bda58 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Tue, 5 Dec 2023 13:20:01 -0500
|
|
||||||
Subject: [PATCH 084/101] aio: make aio_context_acquire()/aio_context_release()
|
|
||||||
a no-op
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [15/26] 723dcada900aaf08862e8221921be22506b561a8 (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
aio_context_acquire()/aio_context_release() has been replaced by
|
|
||||||
fine-grained locking to protect state shared by multiple threads. The
|
|
||||||
AioContext lock still plays the role of balancing locking in
|
|
||||||
AIO_WAIT_WHILE() and many functions in QEMU either require that the
|
|
||||||
AioContext lock is held or not held for this reason. In other words, the
|
|
||||||
AioContext lock is purely there for consistency with itself and serves
|
|
||||||
no real purpose anymore.
|
|
||||||
|
|
||||||
Stop actually acquiring/releasing the lock in
|
|
||||||
aio_context_acquire()/aio_context_release() so that subsequent patches
|
|
||||||
can remove callers across the codebase incrementally.
|
|
||||||
|
|
||||||
I have performed "make check" and qemu-iotests stress tests across
|
|
||||||
x86-64, ppc64le, and aarch64 to confirm that there are no failures as a
|
|
||||||
result of eliminating the lock.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Message-ID: <20231205182011.1976568-5-stefanha@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
util/async.c | 4 ++--
|
|
||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/util/async.c b/util/async.c
|
|
||||||
index 8f90ddc304..04ee83d220 100644
|
|
||||||
--- a/util/async.c
|
|
||||||
+++ b/util/async.c
|
|
||||||
@@ -725,12 +725,12 @@ void aio_context_unref(AioContext *ctx)
|
|
||||||
|
|
||||||
void aio_context_acquire(AioContext *ctx)
|
|
||||||
{
|
|
||||||
- qemu_rec_mutex_lock(&ctx->lock);
|
|
||||||
+ /* TODO remove this function */
|
|
||||||
}
|
|
||||||
|
|
||||||
void aio_context_release(AioContext *ctx)
|
|
||||||
{
|
|
||||||
- qemu_rec_mutex_unlock(&ctx->lock);
|
|
||||||
+ /* TODO remove this function */
|
|
||||||
}
|
|
||||||
|
|
||||||
QEMU_DEFINE_STATIC_CO_TLS(AioContext *, my_aiocontext)
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
|||||||
From 14913d8970090c8914dc19dad14f3b9f91985ec3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Tue, 5 Dec 2023 13:20:07 -0500
|
|
||||||
Subject: [PATCH 090/101] aio: remove
|
|
||||||
aio_context_acquire()/aio_context_release() API
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [21/26] 4b6d4afcac79d3248a6722b063b5fc777dc418df (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Delete these functions because nothing calls these functions anymore.
|
|
||||||
|
|
||||||
I introduced these APIs in commit 98563fc3ec44 ("aio: add
|
|
||||||
aio_context_acquire() and aio_context_release()") in 2014. It's with a
|
|
||||||
sigh of relief that I delete these APIs almost 10 years later.
|
|
||||||
|
|
||||||
Thanks to Paolo Bonzini's vision for multi-queue QEMU, we got an
|
|
||||||
understanding of where the code needed to go in order to remove the
|
|
||||||
limitations that the original dataplane and the IOThread/AioContext
|
|
||||||
approach that followed it.
|
|
||||||
|
|
||||||
Emanuele Giuseppe Esposito had the splendid determination to convert
|
|
||||||
large parts of the codebase so that they no longer needed the AioContext
|
|
||||||
lock. This was a painstaking process, both in the actual code changes
|
|
||||||
required and the iterations of code review that Emanuele eked out of
|
|
||||||
Kevin and me over many months.
|
|
||||||
|
|
||||||
Kevin Wolf tackled multitudes of graph locking conversions to protect
|
|
||||||
in-flight I/O from run-time changes to the block graph as well as the
|
|
||||||
clang Thread Safety Analysis annotations that allow the compiler to
|
|
||||||
check whether the graph lock is being used correctly.
|
|
||||||
|
|
||||||
And me, well, I'm just here to add some pizzazz to the QEMU multi-queue
|
|
||||||
block layer :). Thank you to everyone who helped with this effort,
|
|
||||||
including Eric Blake, code reviewer extraordinaire, and others who I've
|
|
||||||
forgotten to mention.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Message-ID: <20231205182011.1976568-11-stefanha@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
include/block/aio.h | 17 -----------------
|
|
||||||
util/async.c | 10 ----------
|
|
||||||
2 files changed, 27 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/block/aio.h b/include/block/aio.h
|
|
||||||
index f08b358077..af05512a7d 100644
|
|
||||||
--- a/include/block/aio.h
|
|
||||||
+++ b/include/block/aio.h
|
|
||||||
@@ -278,23 +278,6 @@ void aio_context_ref(AioContext *ctx);
|
|
||||||
*/
|
|
||||||
void aio_context_unref(AioContext *ctx);
|
|
||||||
|
|
||||||
-/* Take ownership of the AioContext. If the AioContext will be shared between
|
|
||||||
- * threads, and a thread does not want to be interrupted, it will have to
|
|
||||||
- * take ownership around calls to aio_poll(). Otherwise, aio_poll()
|
|
||||||
- * automatically takes care of calling aio_context_acquire and
|
|
||||||
- * aio_context_release.
|
|
||||||
- *
|
|
||||||
- * Note that this is separate from bdrv_drained_begin/bdrv_drained_end. A
|
|
||||||
- * thread still has to call those to avoid being interrupted by the guest.
|
|
||||||
- *
|
|
||||||
- * Bottom halves, timers and callbacks can be created or removed without
|
|
||||||
- * acquiring the AioContext.
|
|
||||||
- */
|
|
||||||
-void aio_context_acquire(AioContext *ctx);
|
|
||||||
-
|
|
||||||
-/* Relinquish ownership of the AioContext. */
|
|
||||||
-void aio_context_release(AioContext *ctx);
|
|
||||||
-
|
|
||||||
/**
|
|
||||||
* aio_bh_schedule_oneshot_full: Allocate a new bottom half structure that will
|
|
||||||
* run only once and as soon as possible.
|
|
||||||
diff --git a/util/async.c b/util/async.c
|
|
||||||
index dfd44ef612..460529057c 100644
|
|
||||||
--- a/util/async.c
|
|
||||||
+++ b/util/async.c
|
|
||||||
@@ -719,16 +719,6 @@ void aio_context_unref(AioContext *ctx)
|
|
||||||
g_source_unref(&ctx->source);
|
|
||||||
}
|
|
||||||
|
|
||||||
-void aio_context_acquire(AioContext *ctx)
|
|
||||||
-{
|
|
||||||
- /* TODO remove this function */
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-void aio_context_release(AioContext *ctx)
|
|
||||||
-{
|
|
||||||
- /* TODO remove this function */
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
QEMU_DEFINE_STATIC_CO_TLS(AioContext *, my_aiocontext)
|
|
||||||
|
|
||||||
AioContext *qemu_get_current_aio_context(void)
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
|||||||
From e1e2f3972065c4b5d6fcf37e0e1c4fb92a0d5260 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Tue, 5 Dec 2023 13:20:06 -0500
|
|
||||||
Subject: [PATCH 089/101] aio-wait: draw equivalence between AIO_WAIT_WHILE()
|
|
||||||
and AIO_WAIT_WHILE_UNLOCKED()
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [20/26] 20e49777869714c99769263103f1b0c2c370cfcd (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Now that the AioContext lock no longer exists, AIO_WAIT_WHILE() and
|
|
||||||
AIO_WAIT_WHILE_UNLOCKED() are equivalent.
|
|
||||||
|
|
||||||
A future patch will get rid of AIO_WAIT_WHILE_UNLOCKED().
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Message-ID: <20231205182011.1976568-10-stefanha@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
include/block/aio-wait.h | 16 ++++------------
|
|
||||||
1 file changed, 4 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h
|
|
||||||
index 5449b6d742..157f105916 100644
|
|
||||||
--- a/include/block/aio-wait.h
|
|
||||||
+++ b/include/block/aio-wait.h
|
|
||||||
@@ -63,9 +63,6 @@ extern AioWait global_aio_wait;
|
|
||||||
* @ctx: the aio context, or NULL if multiple aio contexts (for which the
|
|
||||||
* caller does not hold a lock) are involved in the polling condition.
|
|
||||||
* @cond: wait while this conditional expression is true
|
|
||||||
- * @unlock: whether to unlock and then lock again @ctx. This applies
|
|
||||||
- * only when waiting for another AioContext from the main loop.
|
|
||||||
- * Otherwise it's ignored.
|
|
||||||
*
|
|
||||||
* Wait while a condition is true. Use this to implement synchronous
|
|
||||||
* operations that require event loop activity.
|
|
||||||
@@ -78,7 +75,7 @@ extern AioWait global_aio_wait;
|
|
||||||
* wait on conditions between two IOThreads since that could lead to deadlock,
|
|
||||||
* go via the main loop instead.
|
|
||||||
*/
|
|
||||||
-#define AIO_WAIT_WHILE_INTERNAL(ctx, cond, unlock) ({ \
|
|
||||||
+#define AIO_WAIT_WHILE_INTERNAL(ctx, cond) ({ \
|
|
||||||
bool waited_ = false; \
|
|
||||||
AioWait *wait_ = &global_aio_wait; \
|
|
||||||
AioContext *ctx_ = (ctx); \
|
|
||||||
@@ -95,13 +92,7 @@ extern AioWait global_aio_wait;
|
|
||||||
assert(qemu_get_current_aio_context() == \
|
|
||||||
qemu_get_aio_context()); \
|
|
||||||
while ((cond)) { \
|
|
||||||
- if (unlock && ctx_) { \
|
|
||||||
- aio_context_release(ctx_); \
|
|
||||||
- } \
|
|
||||||
aio_poll(qemu_get_aio_context(), true); \
|
|
||||||
- if (unlock && ctx_) { \
|
|
||||||
- aio_context_acquire(ctx_); \
|
|
||||||
- } \
|
|
||||||
waited_ = true; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
@@ -109,10 +100,11 @@ extern AioWait global_aio_wait;
|
|
||||||
waited_; })
|
|
||||||
|
|
||||||
#define AIO_WAIT_WHILE(ctx, cond) \
|
|
||||||
- AIO_WAIT_WHILE_INTERNAL(ctx, cond, true)
|
|
||||||
+ AIO_WAIT_WHILE_INTERNAL(ctx, cond)
|
|
||||||
|
|
||||||
+/* TODO replace this with AIO_WAIT_WHILE() in a future patch */
|
|
||||||
#define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \
|
|
||||||
- AIO_WAIT_WHILE_INTERNAL(ctx, cond, false)
|
|
||||||
+ AIO_WAIT_WHILE_INTERNAL(ctx, cond)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* aio_wait_kick:
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
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
|
||||||
|
|
@ -1,476 +0,0 @@
|
|||||||
From 0d8255c98b3ef6f603ff0279592d3e91de26de0e Mon Sep 17 00:00:00 2001
|
|
||||||
From: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Date: Tue, 21 Nov 2023 16:44:00 +0800
|
|
||||||
Subject: [PATCH 021/101] backends/iommufd: Introduce the iommufd object
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [20/67] 8a56344ab4a2126f248bfa492ccddd19265f39be (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Introduce an iommufd object which allows the interaction
|
|
||||||
with the host /dev/iommu device.
|
|
||||||
|
|
||||||
The /dev/iommu can have been already pre-opened outside of qemu,
|
|
||||||
in which case the fd can be passed directly along with the
|
|
||||||
iommufd object:
|
|
||||||
|
|
||||||
This allows the iommufd object to be shared accross several
|
|
||||||
subsystems (VFIO, VDPA, ...). For example, libvirt would open
|
|
||||||
the /dev/iommu once.
|
|
||||||
|
|
||||||
If no fd is passed along with the iommufd object, the /dev/iommu
|
|
||||||
is opened by the qemu code.
|
|
||||||
|
|
||||||
Suggested-by: Alex Williamson <alex.williamson@redhat.com>
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
|
|
||||||
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Reviewed-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
Tested-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
(cherry picked from commit 6e6d8ac62b5b38dc9d4b69ffdf073f0a0b43b7be)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
MAINTAINERS | 8 ++
|
|
||||||
backends/Kconfig | 4 +
|
|
||||||
backends/iommufd.c | 245 +++++++++++++++++++++++++++++++++++++++
|
|
||||||
backends/meson.build | 1 +
|
|
||||||
backends/trace-events | 10 ++
|
|
||||||
include/sysemu/iommufd.h | 38 ++++++
|
|
||||||
qapi/qom.json | 19 +++
|
|
||||||
qemu-options.hx | 12 ++
|
|
||||||
8 files changed, 337 insertions(+)
|
|
||||||
create mode 100644 backends/iommufd.c
|
|
||||||
create mode 100644 include/sysemu/iommufd.h
|
|
||||||
|
|
||||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
|
||||||
index 695e0bd34f..a5a446914a 100644
|
|
||||||
--- a/MAINTAINERS
|
|
||||||
+++ b/MAINTAINERS
|
|
||||||
@@ -2167,6 +2167,14 @@ F: hw/vfio/ap.c
|
|
||||||
F: docs/system/s390x/vfio-ap.rst
|
|
||||||
L: qemu-s390x@nongnu.org
|
|
||||||
|
|
||||||
+iommufd
|
|
||||||
+M: Yi Liu <yi.l.liu@intel.com>
|
|
||||||
+M: Eric Auger <eric.auger@redhat.com>
|
|
||||||
+M: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
+S: Supported
|
|
||||||
+F: backends/iommufd.c
|
|
||||||
+F: include/sysemu/iommufd.h
|
|
||||||
+
|
|
||||||
vhost
|
|
||||||
M: Michael S. Tsirkin <mst@redhat.com>
|
|
||||||
S: Supported
|
|
||||||
diff --git a/backends/Kconfig b/backends/Kconfig
|
|
||||||
index f35abc1609..2cb23f62fa 100644
|
|
||||||
--- a/backends/Kconfig
|
|
||||||
+++ b/backends/Kconfig
|
|
||||||
@@ -1 +1,5 @@
|
|
||||||
source tpm/Kconfig
|
|
||||||
+
|
|
||||||
+config IOMMUFD
|
|
||||||
+ bool
|
|
||||||
+ depends on VFIO
|
|
||||||
diff --git a/backends/iommufd.c b/backends/iommufd.c
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..ba58a0eb0d
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/backends/iommufd.c
|
|
||||||
@@ -0,0 +1,245 @@
|
|
||||||
+/*
|
|
||||||
+ * iommufd container backend
|
|
||||||
+ *
|
|
||||||
+ * Copyright (C) 2023 Intel Corporation.
|
|
||||||
+ * Copyright Red Hat, Inc. 2023
|
|
||||||
+ *
|
|
||||||
+ * Authors: Yi Liu <yi.l.liu@intel.com>
|
|
||||||
+ * Eric Auger <eric.auger@redhat.com>
|
|
||||||
+ *
|
|
||||||
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include "qemu/osdep.h"
|
|
||||||
+#include "sysemu/iommufd.h"
|
|
||||||
+#include "qapi/error.h"
|
|
||||||
+#include "qapi/qmp/qerror.h"
|
|
||||||
+#include "qemu/module.h"
|
|
||||||
+#include "qom/object_interfaces.h"
|
|
||||||
+#include "qemu/error-report.h"
|
|
||||||
+#include "monitor/monitor.h"
|
|
||||||
+#include "trace.h"
|
|
||||||
+#include <sys/ioctl.h>
|
|
||||||
+#include <linux/iommufd.h>
|
|
||||||
+
|
|
||||||
+static void iommufd_backend_init(Object *obj)
|
|
||||||
+{
|
|
||||||
+ IOMMUFDBackend *be = IOMMUFD_BACKEND(obj);
|
|
||||||
+
|
|
||||||
+ be->fd = -1;
|
|
||||||
+ be->users = 0;
|
|
||||||
+ be->owned = true;
|
|
||||||
+ qemu_mutex_init(&be->lock);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void iommufd_backend_finalize(Object *obj)
|
|
||||||
+{
|
|
||||||
+ IOMMUFDBackend *be = IOMMUFD_BACKEND(obj);
|
|
||||||
+
|
|
||||||
+ if (be->owned) {
|
|
||||||
+ close(be->fd);
|
|
||||||
+ be->fd = -1;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void iommufd_backend_set_fd(Object *obj, const char *str, Error **errp)
|
|
||||||
+{
|
|
||||||
+ IOMMUFDBackend *be = IOMMUFD_BACKEND(obj);
|
|
||||||
+ int fd = -1;
|
|
||||||
+
|
|
||||||
+ fd = monitor_fd_param(monitor_cur(), str, errp);
|
|
||||||
+ if (fd == -1) {
|
|
||||||
+ error_prepend(errp, "Could not parse remote object fd %s:", str);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+ qemu_mutex_lock(&be->lock);
|
|
||||||
+ be->fd = fd;
|
|
||||||
+ be->owned = false;
|
|
||||||
+ qemu_mutex_unlock(&be->lock);
|
|
||||||
+ trace_iommu_backend_set_fd(be->fd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static bool iommufd_backend_can_be_deleted(UserCreatable *uc)
|
|
||||||
+{
|
|
||||||
+ IOMMUFDBackend *be = IOMMUFD_BACKEND(uc);
|
|
||||||
+
|
|
||||||
+ return !be->users;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void iommufd_backend_class_init(ObjectClass *oc, void *data)
|
|
||||||
+{
|
|
||||||
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
|
|
||||||
+
|
|
||||||
+ ucc->can_be_deleted = iommufd_backend_can_be_deleted;
|
|
||||||
+
|
|
||||||
+ object_class_property_add_str(oc, "fd", NULL, iommufd_backend_set_fd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
|
||||||
+{
|
|
||||||
+ int fd, ret = 0;
|
|
||||||
+
|
|
||||||
+ qemu_mutex_lock(&be->lock);
|
|
||||||
+ if (be->users == UINT32_MAX) {
|
|
||||||
+ error_setg(errp, "too many connections");
|
|
||||||
+ ret = -E2BIG;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ if (be->owned && !be->users) {
|
|
||||||
+ fd = qemu_open_old("/dev/iommu", O_RDWR);
|
|
||||||
+ if (fd < 0) {
|
|
||||||
+ error_setg_errno(errp, errno, "/dev/iommu opening failed");
|
|
||||||
+ ret = fd;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ be->fd = fd;
|
|
||||||
+ }
|
|
||||||
+ be->users++;
|
|
||||||
+out:
|
|
||||||
+ trace_iommufd_backend_connect(be->fd, be->owned,
|
|
||||||
+ be->users, ret);
|
|
||||||
+ qemu_mutex_unlock(&be->lock);
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void iommufd_backend_disconnect(IOMMUFDBackend *be)
|
|
||||||
+{
|
|
||||||
+ qemu_mutex_lock(&be->lock);
|
|
||||||
+ if (!be->users) {
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+ be->users--;
|
|
||||||
+ if (!be->users && be->owned) {
|
|
||||||
+ close(be->fd);
|
|
||||||
+ be->fd = -1;
|
|
||||||
+ }
|
|
||||||
+out:
|
|
||||||
+ trace_iommufd_backend_disconnect(be->fd, be->users);
|
|
||||||
+ qemu_mutex_unlock(&be->lock);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
|
|
||||||
+ Error **errp)
|
|
||||||
+{
|
|
||||||
+ int ret, fd = be->fd;
|
|
||||||
+ struct iommu_ioas_alloc alloc_data = {
|
|
||||||
+ .size = sizeof(alloc_data),
|
|
||||||
+ .flags = 0,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ ret = ioctl(fd, IOMMU_IOAS_ALLOC, &alloc_data);
|
|
||||||
+ if (ret) {
|
|
||||||
+ error_setg_errno(errp, errno, "Failed to allocate ioas");
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ *ioas_id = alloc_data.out_ioas_id;
|
|
||||||
+ trace_iommufd_backend_alloc_ioas(fd, *ioas_id, ret);
|
|
||||||
+
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id)
|
|
||||||
+{
|
|
||||||
+ int ret, fd = be->fd;
|
|
||||||
+ struct iommu_destroy des = {
|
|
||||||
+ .size = sizeof(des),
|
|
||||||
+ .id = id,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ ret = ioctl(fd, IOMMU_DESTROY, &des);
|
|
||||||
+ trace_iommufd_backend_free_id(fd, id, ret);
|
|
||||||
+ if (ret) {
|
|
||||||
+ error_report("Failed to free id: %u %m", id);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int iommufd_backend_map_dma(IOMMUFDBackend *be, uint32_t ioas_id, hwaddr iova,
|
|
||||||
+ ram_addr_t size, void *vaddr, bool readonly)
|
|
||||||
+{
|
|
||||||
+ int ret, fd = be->fd;
|
|
||||||
+ struct iommu_ioas_map map = {
|
|
||||||
+ .size = sizeof(map),
|
|
||||||
+ .flags = IOMMU_IOAS_MAP_READABLE |
|
|
||||||
+ IOMMU_IOAS_MAP_FIXED_IOVA,
|
|
||||||
+ .ioas_id = ioas_id,
|
|
||||||
+ .__reserved = 0,
|
|
||||||
+ .user_va = (uintptr_t)vaddr,
|
|
||||||
+ .iova = iova,
|
|
||||||
+ .length = size,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ if (!readonly) {
|
|
||||||
+ map.flags |= IOMMU_IOAS_MAP_WRITEABLE;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = ioctl(fd, IOMMU_IOAS_MAP, &map);
|
|
||||||
+ trace_iommufd_backend_map_dma(fd, ioas_id, iova, size,
|
|
||||||
+ vaddr, readonly, ret);
|
|
||||||
+ if (ret) {
|
|
||||||
+ ret = -errno;
|
|
||||||
+
|
|
||||||
+ /* TODO: Not support mapping hardware PCI BAR region for now. */
|
|
||||||
+ if (errno == EFAULT) {
|
|
||||||
+ warn_report("IOMMU_IOAS_MAP failed: %m, PCI BAR?");
|
|
||||||
+ } else {
|
|
||||||
+ error_report("IOMMU_IOAS_MAP failed: %m");
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int iommufd_backend_unmap_dma(IOMMUFDBackend *be, uint32_t ioas_id,
|
|
||||||
+ hwaddr iova, ram_addr_t size)
|
|
||||||
+{
|
|
||||||
+ int ret, fd = be->fd;
|
|
||||||
+ struct iommu_ioas_unmap unmap = {
|
|
||||||
+ .size = sizeof(unmap),
|
|
||||||
+ .ioas_id = ioas_id,
|
|
||||||
+ .iova = iova,
|
|
||||||
+ .length = size,
|
|
||||||
+ };
|
|
||||||
+
|
|
||||||
+ ret = ioctl(fd, IOMMU_IOAS_UNMAP, &unmap);
|
|
||||||
+ /*
|
|
||||||
+ * IOMMUFD takes mapping as some kind of object, unmapping
|
|
||||||
+ * nonexistent mapping is treated as deleting a nonexistent
|
|
||||||
+ * object and return ENOENT. This is different from legacy
|
|
||||||
+ * backend which allows it. vIOMMU may trigger a lot of
|
|
||||||
+ * redundant unmapping, to avoid flush the log, treat them
|
|
||||||
+ * as succeess for IOMMUFD just like legacy backend.
|
|
||||||
+ */
|
|
||||||
+ if (ret && errno == ENOENT) {
|
|
||||||
+ trace_iommufd_backend_unmap_dma_non_exist(fd, ioas_id, iova, size, ret);
|
|
||||||
+ ret = 0;
|
|
||||||
+ } else {
|
|
||||||
+ trace_iommufd_backend_unmap_dma(fd, ioas_id, iova, size, ret);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (ret) {
|
|
||||||
+ ret = -errno;
|
|
||||||
+ error_report("IOMMU_IOAS_UNMAP failed: %m");
|
|
||||||
+ }
|
|
||||||
+ return ret;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const TypeInfo iommufd_backend_info = {
|
|
||||||
+ .name = TYPE_IOMMUFD_BACKEND,
|
|
||||||
+ .parent = TYPE_OBJECT,
|
|
||||||
+ .instance_size = sizeof(IOMMUFDBackend),
|
|
||||||
+ .instance_init = iommufd_backend_init,
|
|
||||||
+ .instance_finalize = iommufd_backend_finalize,
|
|
||||||
+ .class_size = sizeof(IOMMUFDBackendClass),
|
|
||||||
+ .class_init = iommufd_backend_class_init,
|
|
||||||
+ .interfaces = (InterfaceInfo[]) {
|
|
||||||
+ { TYPE_USER_CREATABLE },
|
|
||||||
+ { }
|
|
||||||
+ }
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static void register_types(void)
|
|
||||||
+{
|
|
||||||
+ type_register_static(&iommufd_backend_info);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+type_init(register_types);
|
|
||||||
diff --git a/backends/meson.build b/backends/meson.build
|
|
||||||
index 914c7c4afb..9a5cea480d 100644
|
|
||||||
--- a/backends/meson.build
|
|
||||||
+++ b/backends/meson.build
|
|
||||||
@@ -20,6 +20,7 @@ if have_vhost_user
|
|
||||||
system_ss.add(when: 'CONFIG_VIRTIO', if_true: files('vhost-user.c'))
|
|
||||||
endif
|
|
||||||
system_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost.c'))
|
|
||||||
+system_ss.add(when: 'CONFIG_IOMMUFD', if_true: files('iommufd.c'))
|
|
||||||
if have_vhost_user_crypto
|
|
||||||
system_ss.add(when: 'CONFIG_VIRTIO_CRYPTO', if_true: files('cryptodev-vhost-user.c'))
|
|
||||||
endif
|
|
||||||
diff --git a/backends/trace-events b/backends/trace-events
|
|
||||||
index 652eb76a57..d45c6e31a6 100644
|
|
||||||
--- a/backends/trace-events
|
|
||||||
+++ b/backends/trace-events
|
|
||||||
@@ -5,3 +5,13 @@ dbus_vmstate_pre_save(void)
|
|
||||||
dbus_vmstate_post_load(int version_id) "version_id: %d"
|
|
||||||
dbus_vmstate_loading(const char *id) "id: %s"
|
|
||||||
dbus_vmstate_saving(const char *id) "id: %s"
|
|
||||||
+
|
|
||||||
+# iommufd.c
|
|
||||||
+iommufd_backend_connect(int fd, bool owned, uint32_t users, int ret) "fd=%d owned=%d users=%d (%d)"
|
|
||||||
+iommufd_backend_disconnect(int fd, uint32_t users) "fd=%d users=%d"
|
|
||||||
+iommu_backend_set_fd(int fd) "pre-opened /dev/iommu fd=%d"
|
|
||||||
+iommufd_backend_map_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, void *vaddr, bool readonly, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" addr=%p readonly=%d (%d)"
|
|
||||||
+iommufd_backend_unmap_dma_non_exist(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " Unmap nonexistent mapping: iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
|
|
||||||
+iommufd_backend_unmap_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" (%d)"
|
|
||||||
+iommufd_backend_alloc_ioas(int iommufd, uint32_t ioas, int ret) " iommufd=%d ioas=%d (%d)"
|
|
||||||
+iommufd_backend_free_id(int iommufd, uint32_t id, int ret) " iommufd=%d id=%d (%d)"
|
|
||||||
diff --git a/include/sysemu/iommufd.h b/include/sysemu/iommufd.h
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..9c5524b0ed
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/sysemu/iommufd.h
|
|
||||||
@@ -0,0 +1,38 @@
|
|
||||||
+#ifndef SYSEMU_IOMMUFD_H
|
|
||||||
+#define SYSEMU_IOMMUFD_H
|
|
||||||
+
|
|
||||||
+#include "qom/object.h"
|
|
||||||
+#include "qemu/thread.h"
|
|
||||||
+#include "exec/hwaddr.h"
|
|
||||||
+#include "exec/cpu-common.h"
|
|
||||||
+
|
|
||||||
+#define TYPE_IOMMUFD_BACKEND "iommufd"
|
|
||||||
+OBJECT_DECLARE_TYPE(IOMMUFDBackend, IOMMUFDBackendClass, IOMMUFD_BACKEND)
|
|
||||||
+
|
|
||||||
+struct IOMMUFDBackendClass {
|
|
||||||
+ ObjectClass parent_class;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct IOMMUFDBackend {
|
|
||||||
+ Object parent;
|
|
||||||
+
|
|
||||||
+ /*< protected >*/
|
|
||||||
+ int fd; /* /dev/iommu file descriptor */
|
|
||||||
+ bool owned; /* is the /dev/iommu opened internally */
|
|
||||||
+ QemuMutex lock;
|
|
||||||
+ uint32_t users;
|
|
||||||
+
|
|
||||||
+ /*< public >*/
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp);
|
|
||||||
+void iommufd_backend_disconnect(IOMMUFDBackend *be);
|
|
||||||
+
|
|
||||||
+int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
|
|
||||||
+ Error **errp);
|
|
||||||
+void iommufd_backend_free_id(IOMMUFDBackend *be, uint32_t id);
|
|
||||||
+int iommufd_backend_map_dma(IOMMUFDBackend *be, uint32_t ioas_id, hwaddr iova,
|
|
||||||
+ ram_addr_t size, void *vaddr, bool readonly);
|
|
||||||
+int iommufd_backend_unmap_dma(IOMMUFDBackend *be, uint32_t ioas_id,
|
|
||||||
+ hwaddr iova, ram_addr_t size);
|
|
||||||
+#endif
|
|
||||||
diff --git a/qapi/qom.json b/qapi/qom.json
|
|
||||||
index c53ef978ff..95516ba325 100644
|
|
||||||
--- a/qapi/qom.json
|
|
||||||
+++ b/qapi/qom.json
|
|
||||||
@@ -794,6 +794,23 @@
|
|
||||||
{ 'struct': 'VfioUserServerProperties',
|
|
||||||
'data': { 'socket': 'SocketAddress', 'device': 'str' } }
|
|
||||||
|
|
||||||
+##
|
|
||||||
+# @IOMMUFDProperties:
|
|
||||||
+#
|
|
||||||
+# Properties for iommufd objects.
|
|
||||||
+#
|
|
||||||
+# @fd: file descriptor name previously passed via 'getfd' command,
|
|
||||||
+# which represents a pre-opened /dev/iommu. This allows the
|
|
||||||
+# iommufd object to be shared accross several subsystems
|
|
||||||
+# (VFIO, VDPA, ...), and the file descriptor to be shared
|
|
||||||
+# with other process, e.g. DPDK. (default: QEMU opens
|
|
||||||
+# /dev/iommu by itself)
|
|
||||||
+#
|
|
||||||
+# Since: 9.0
|
|
||||||
+##
|
|
||||||
+{ 'struct': 'IOMMUFDProperties',
|
|
||||||
+ 'data': { '*fd': 'str' } }
|
|
||||||
+
|
|
||||||
##
|
|
||||||
# @RngProperties:
|
|
||||||
#
|
|
||||||
@@ -934,6 +951,7 @@
|
|
||||||
'input-barrier',
|
|
||||||
{ 'name': 'input-linux',
|
|
||||||
'if': 'CONFIG_LINUX' },
|
|
||||||
+ 'iommufd',
|
|
||||||
'iothread',
|
|
||||||
'main-loop',
|
|
||||||
{ 'name': 'memory-backend-epc',
|
|
||||||
@@ -1003,6 +1021,7 @@
|
|
||||||
'input-barrier': 'InputBarrierProperties',
|
|
||||||
'input-linux': { 'type': 'InputLinuxProperties',
|
|
||||||
'if': 'CONFIG_LINUX' },
|
|
||||||
+ 'iommufd': 'IOMMUFDProperties',
|
|
||||||
'iothread': 'IothreadProperties',
|
|
||||||
'main-loop': 'MainLoopProperties',
|
|
||||||
'memory-backend-epc': { 'type': 'MemoryBackendEpcProperties',
|
|
||||||
diff --git a/qemu-options.hx b/qemu-options.hx
|
|
||||||
index 557118cb1f..0814f43066 100644
|
|
||||||
--- a/qemu-options.hx
|
|
||||||
+++ b/qemu-options.hx
|
|
||||||
@@ -5224,6 +5224,18 @@ SRST
|
|
||||||
|
|
||||||
The ``share`` boolean option is on by default with memfd.
|
|
||||||
|
|
||||||
+ ``-object iommufd,id=id[,fd=fd]``
|
|
||||||
+ Creates an iommufd backend which allows control of DMA mapping
|
|
||||||
+ through the ``/dev/iommu`` device.
|
|
||||||
+
|
|
||||||
+ The ``id`` parameter is a unique ID which frontends (such as
|
|
||||||
+ vfio-pci of vdpa) will use to connect with the iommufd backend.
|
|
||||||
+
|
|
||||||
+ The ``fd`` parameter is an optional pre-opened file descriptor
|
|
||||||
+ resulting from ``/dev/iommu`` opening. Usually the iommufd is shared
|
|
||||||
+ across all subsystems, bringing the benefit of centralized
|
|
||||||
+ reference counting.
|
|
||||||
+
|
|
||||||
``-object rng-builtin,id=id``
|
|
||||||
Creates a random number generator backend which obtains entropy
|
|
||||||
from QEMU builtin functions. The ``id`` parameter is a unique ID
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
|||||||
From da9a24793e876f6f2727d57f939d882be26a47b8 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
|
|
||||||
Date: Fri, 22 Dec 2023 08:55:23 +0100
|
|
||||||
Subject: [PATCH 064/101] backends/iommufd: Remove check on number of backend
|
|
||||||
users
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [63/67] ac4d4589d1f2de5ac3f0adfd8d1f27dbf6bbfdee (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
QOM already has a ref count on objects and it will assert much
|
|
||||||
earlier, when INT_MAX is reached.
|
|
||||||
|
|
||||||
Reviewed-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Reviewed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
(cherry picked from commit c2ab3a6f7411c895e538e8350fee8948ac07c1a0)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
backends/iommufd.c | 5 -----
|
|
||||||
1 file changed, 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/backends/iommufd.c b/backends/iommufd.c
|
|
||||||
index ba58a0eb0d..393c0d9a37 100644
|
|
||||||
--- a/backends/iommufd.c
|
|
||||||
+++ b/backends/iommufd.c
|
|
||||||
@@ -80,11 +80,6 @@ int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
|
||||||
int fd, ret = 0;
|
|
||||||
|
|
||||||
qemu_mutex_lock(&be->lock);
|
|
||||||
- if (be->users == UINT32_MAX) {
|
|
||||||
- error_setg(errp, "too many connections");
|
|
||||||
- ret = -E2BIG;
|
|
||||||
- goto out;
|
|
||||||
- }
|
|
||||||
if (be->owned && !be->users) {
|
|
||||||
fd = qemu_open_old("/dev/iommu", O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
|||||||
From 92aff3cc1a412de01e9563802fa48848eae5283f Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
|
|
||||||
Date: Thu, 21 Dec 2023 16:58:41 +0100
|
|
||||||
Subject: [PATCH 065/101] backends/iommufd: Remove mutex
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [64/67] 65518432b18f18ceadafe1b0698cdaa962e84f61 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Coverity reports a concurrent data access violation because be->users
|
|
||||||
is being accessed in iommufd_backend_can_be_deleted() without holding
|
|
||||||
the mutex.
|
|
||||||
|
|
||||||
However, these routines are called from the QEMU main thread when a
|
|
||||||
device is created. In this case, the code paths should be protected by
|
|
||||||
the BQL lock and it should be safe to drop the IOMMUFD backend mutex.
|
|
||||||
Simply remove it.
|
|
||||||
|
|
||||||
Fixes: CID 1531550
|
|
||||||
Fixes: CID 1531549
|
|
||||||
Reviewed-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Reviewed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
(cherry picked from commit 19368b1905b4b917e915526fcbd5bfa3f7439451)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
backends/iommufd.c | 7 -------
|
|
||||||
include/sysemu/iommufd.h | 2 --
|
|
||||||
2 files changed, 9 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/backends/iommufd.c b/backends/iommufd.c
|
|
||||||
index 393c0d9a37..1ef683c7b0 100644
|
|
||||||
--- a/backends/iommufd.c
|
|
||||||
+++ b/backends/iommufd.c
|
|
||||||
@@ -29,7 +29,6 @@ static void iommufd_backend_init(Object *obj)
|
|
||||||
be->fd = -1;
|
|
||||||
be->users = 0;
|
|
||||||
be->owned = true;
|
|
||||||
- qemu_mutex_init(&be->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void iommufd_backend_finalize(Object *obj)
|
|
||||||
@@ -52,10 +51,8 @@ static void iommufd_backend_set_fd(Object *obj, const char *str, Error **errp)
|
|
||||||
error_prepend(errp, "Could not parse remote object fd %s:", str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
- qemu_mutex_lock(&be->lock);
|
|
||||||
be->fd = fd;
|
|
||||||
be->owned = false;
|
|
||||||
- qemu_mutex_unlock(&be->lock);
|
|
||||||
trace_iommu_backend_set_fd(be->fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -79,7 +76,6 @@ int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
|
||||||
{
|
|
||||||
int fd, ret = 0;
|
|
||||||
|
|
||||||
- qemu_mutex_lock(&be->lock);
|
|
||||||
if (be->owned && !be->users) {
|
|
||||||
fd = qemu_open_old("/dev/iommu", O_RDWR);
|
|
||||||
if (fd < 0) {
|
|
||||||
@@ -93,13 +89,11 @@ int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
|
|
||||||
out:
|
|
||||||
trace_iommufd_backend_connect(be->fd, be->owned,
|
|
||||||
be->users, ret);
|
|
||||||
- qemu_mutex_unlock(&be->lock);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iommufd_backend_disconnect(IOMMUFDBackend *be)
|
|
||||||
{
|
|
||||||
- qemu_mutex_lock(&be->lock);
|
|
||||||
if (!be->users) {
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
@@ -110,7 +104,6 @@ void iommufd_backend_disconnect(IOMMUFDBackend *be)
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
trace_iommufd_backend_disconnect(be->fd, be->users);
|
|
||||||
- qemu_mutex_unlock(&be->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
|
|
||||||
diff --git a/include/sysemu/iommufd.h b/include/sysemu/iommufd.h
|
|
||||||
index 9c5524b0ed..9af27ebd6c 100644
|
|
||||||
--- a/include/sysemu/iommufd.h
|
|
||||||
+++ b/include/sysemu/iommufd.h
|
|
||||||
@@ -2,7 +2,6 @@
|
|
||||||
#define SYSEMU_IOMMUFD_H
|
|
||||||
|
|
||||||
#include "qom/object.h"
|
|
||||||
-#include "qemu/thread.h"
|
|
||||||
#include "exec/hwaddr.h"
|
|
||||||
#include "exec/cpu-common.h"
|
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ struct IOMMUFDBackend {
|
|
||||||
/*< protected >*/
|
|
||||||
int fd; /* /dev/iommu file descriptor */
|
|
||||||
bool owned; /* is the /dev/iommu opened internally */
|
|
||||||
- QemuMutex lock;
|
|
||||||
uint32_t users;
|
|
||||||
|
|
||||||
/*< public >*/
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,252 @@
|
|||||||
|
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,104 +0,0 @@
|
|||||||
From afa842e9fdf6e1d6e5d5785679a22779632142bd Mon Sep 17 00:00:00 2001
|
|
||||||
From: Hanna Czenczek <hreitz@redhat.com>
|
|
||||||
Date: Fri, 2 Feb 2024 15:47:54 +0100
|
|
||||||
Subject: [PATCH 03/22] block-backend: Allow concurrent context changes
|
|
||||||
|
|
||||||
RH-Author: Hanna Czenczek <hreitz@redhat.com>
|
|
||||||
RH-MergeRequest: 222: Allow concurrent BlockBackend context changes
|
|
||||||
RH-Jira: RHEL-24593
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-Commit: [1/2] 9e1b535f60f7afa94a0817dc3e71136e41631c71 (hreitz/qemu-kvm-c-9-s)
|
|
||||||
|
|
||||||
Since AioContext locks have been removed, a BlockBackend's AioContext
|
|
||||||
may really change at any time (only exception is that it is often
|
|
||||||
confined to a drained section, as noted in this patch). Therefore,
|
|
||||||
blk_get_aio_context() cannot rely on its root node's context always
|
|
||||||
matching that of the BlockBackend.
|
|
||||||
|
|
||||||
In practice, whether they match does not matter anymore anyway: Requests
|
|
||||||
can be sent to BDSs from any context, so anyone who requests the BB's
|
|
||||||
context should have no reason to require the root node to have the same
|
|
||||||
context. Therefore, we can and should remove the assertion to that
|
|
||||||
effect.
|
|
||||||
|
|
||||||
In addition, because the context can be set and queried from different
|
|
||||||
threads concurrently, it has to be accessed with atomic operations.
|
|
||||||
|
|
||||||
Buglink: https://issues.redhat.com/browse/RHEL-19381
|
|
||||||
Suggested-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Hanna Czenczek <hreitz@redhat.com>
|
|
||||||
Message-ID: <20240202144755.671354-2-hreitz@redhat.com>
|
|
||||||
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
(cherry picked from commit ad893672027ffe26db498947d70cde6d4f58a111)
|
|
||||||
---
|
|
||||||
block/block-backend.c | 22 +++++++++++-----------
|
|
||||||
1 file changed, 11 insertions(+), 11 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index 209eb07528..9c4de79e6b 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -44,7 +44,7 @@ struct BlockBackend {
|
|
||||||
char *name;
|
|
||||||
int refcnt;
|
|
||||||
BdrvChild *root;
|
|
||||||
- AioContext *ctx;
|
|
||||||
+ AioContext *ctx; /* access with atomic operations only */
|
|
||||||
DriveInfo *legacy_dinfo; /* null unless created by drive_new() */
|
|
||||||
QTAILQ_ENTRY(BlockBackend) link; /* for block_backends */
|
|
||||||
QTAILQ_ENTRY(BlockBackend) monitor_link; /* for monitor_block_backends */
|
|
||||||
@@ -2414,22 +2414,22 @@ void blk_op_unblock_all(BlockBackend *blk, Error *reason)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+/**
|
|
||||||
+ * Return BB's current AioContext. Note that this context may change
|
|
||||||
+ * concurrently at any time, with one exception: If the BB has a root node
|
|
||||||
+ * attached, its context will only change through bdrv_try_change_aio_context(),
|
|
||||||
+ * which creates a drained section. Therefore, incrementing such a BB's
|
|
||||||
+ * in-flight counter will prevent its context from changing.
|
|
||||||
+ */
|
|
||||||
AioContext *blk_get_aio_context(BlockBackend *blk)
|
|
||||||
{
|
|
||||||
- BlockDriverState *bs;
|
|
||||||
IO_CODE();
|
|
||||||
|
|
||||||
if (!blk) {
|
|
||||||
return qemu_get_aio_context();
|
|
||||||
}
|
|
||||||
|
|
||||||
- bs = blk_bs(blk);
|
|
||||||
- if (bs) {
|
|
||||||
- AioContext *ctx = bdrv_get_aio_context(blk_bs(blk));
|
|
||||||
- assert(ctx == blk->ctx);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return blk->ctx;
|
|
||||||
+ return qatomic_read(&blk->ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
|
|
||||||
@@ -2442,7 +2442,7 @@ int blk_set_aio_context(BlockBackend *blk, AioContext *new_context,
|
|
||||||
GLOBAL_STATE_CODE();
|
|
||||||
|
|
||||||
if (!bs) {
|
|
||||||
- blk->ctx = new_context;
|
|
||||||
+ qatomic_set(&blk->ctx, new_context);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2471,7 +2471,7 @@ static void blk_root_set_aio_ctx_commit(void *opaque)
|
|
||||||
AioContext *new_context = s->new_ctx;
|
|
||||||
ThrottleGroupMember *tgm = &blk->public.throttle_group_member;
|
|
||||||
|
|
||||||
- blk->ctx = new_context;
|
|
||||||
+ qatomic_set(&blk->ctx, new_context);
|
|
||||||
if (tgm->throttle_state) {
|
|
||||||
throttle_group_detach_aio_context(tgm);
|
|
||||||
throttle_group_attach_aio_context(tgm, new_context);
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
|||||||
From b1a68aebadecd7d339cf5eaffeda15099c998528 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Tue, 12 Sep 2023 19:10:37 -0400
|
|
||||||
Subject: [PATCH 095/101] block-coroutine-wrapper: use
|
|
||||||
qemu_get_current_aio_context()
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [26/26] cde767bcdc626e90721792e3889952057a548ac5 (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Use qemu_get_current_aio_context() in mixed wrappers and coroutine
|
|
||||||
wrappers so that code runs in the caller's AioContext instead of moving
|
|
||||||
to the BlockDriverState's AioContext. This change is necessary for the
|
|
||||||
multi-queue block layer where any thread can call into the block layer.
|
|
||||||
|
|
||||||
Most wrappers are IO_CODE where it's safe to use the current AioContext
|
|
||||||
nowadays. BlockDrivers and the core block layer use their own locks and
|
|
||||||
no longer depend on the AioContext lock for thread-safety.
|
|
||||||
|
|
||||||
The bdrv_create() wrapper invokes GLOBAL_STATE code. Using the current
|
|
||||||
AioContext is safe because this code is only called with the BQL held
|
|
||||||
from the main loop thread.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Message-ID: <20230912231037.826804-6-stefanha@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
scripts/block-coroutine-wrapper.py | 6 ++----
|
|
||||||
1 file changed, 2 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/scripts/block-coroutine-wrapper.py b/scripts/block-coroutine-wrapper.py
|
|
||||||
index c9c09fcacd..dbbde99e39 100644
|
|
||||||
--- a/scripts/block-coroutine-wrapper.py
|
|
||||||
+++ b/scripts/block-coroutine-wrapper.py
|
|
||||||
@@ -92,8 +92,6 @@ def __init__(self, wrapper_type: str, return_type: str, name: str,
|
|
||||||
f"{self.name}")
|
|
||||||
self.target_name = f'{subsystem}_{subname}'
|
|
||||||
|
|
||||||
- self.ctx = self.gen_ctx()
|
|
||||||
-
|
|
||||||
self.get_result = 's->ret = '
|
|
||||||
self.ret = 'return s.ret;'
|
|
||||||
self.co_ret = 'return '
|
|
||||||
@@ -167,7 +165,7 @@ def create_mixed_wrapper(func: FuncDecl) -> str:
|
|
||||||
{func.co_ret}{name}({ func.gen_list('{name}') });
|
|
||||||
}} else {{
|
|
||||||
{struct_name} s = {{
|
|
||||||
- .poll_state.ctx = {func.ctx},
|
|
||||||
+ .poll_state.ctx = qemu_get_current_aio_context(),
|
|
||||||
.poll_state.in_progress = true,
|
|
||||||
|
|
||||||
{ func.gen_block(' .{name} = {name},') }
|
|
||||||
@@ -191,7 +189,7 @@ def create_co_wrapper(func: FuncDecl) -> str:
|
|
||||||
{func.return_type} {func.name}({ func.gen_list('{decl}') })
|
|
||||||
{{
|
|
||||||
{struct_name} s = {{
|
|
||||||
- .poll_state.ctx = {func.ctx},
|
|
||||||
+ .poll_state.ctx = qemu_get_current_aio_context(),
|
|
||||||
.poll_state.in_progress = true,
|
|
||||||
|
|
||||||
{ func.gen_block(' .{name} = {name},') }
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,330 @@
|
|||||||
|
From a67edfb4b591acdffc5b4987601a30224376996f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Mon, 27 May 2024 11:58:50 -0400
|
||||||
|
Subject: [PATCH 4/5] block/crypto: create ciphers on demand
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
RH-MergeRequest: 251: block/crypto: create ciphers on demand
|
||||||
|
RH-Jira: RHEL-36159
|
||||||
|
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [1/2] 22a4c87fef774cad98a6f5a79f27df50a208013d (stefanha/centos-stream-qemu-kvm)
|
||||||
|
|
||||||
|
Ciphers are pre-allocated by qcrypto_block_init_cipher() depending on
|
||||||
|
the given number of threads. The -device
|
||||||
|
virtio-blk-pci,iothread-vq-mapping= feature allows users to assign
|
||||||
|
multiple IOThreads to a virtio-blk device, but the association between
|
||||||
|
the virtio-blk device and the block driver happens after the block
|
||||||
|
driver is already open.
|
||||||
|
|
||||||
|
When the number of threads given to qcrypto_block_init_cipher() is
|
||||||
|
smaller than the actual number of threads at runtime, the
|
||||||
|
block->n_free_ciphers > 0 assertion in qcrypto_block_pop_cipher() can
|
||||||
|
fail.
|
||||||
|
|
||||||
|
Get rid of qcrypto_block_init_cipher() n_thread's argument and allocate
|
||||||
|
ciphers on demand.
|
||||||
|
|
||||||
|
Reported-by: Qing Wang <qinwang@redhat.com>
|
||||||
|
Buglink: https://issues.redhat.com/browse/RHEL-36159
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Message-ID: <20240527155851.892885-2-stefanha@redhat.com>
|
||||||
|
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
(cherry picked from commit af206c284e4c1b17cdfb0f17e898b288c0fc1751)
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
crypto/block-luks.c | 3 +-
|
||||||
|
crypto/block-qcow.c | 2 +-
|
||||||
|
crypto/block.c | 111 ++++++++++++++++++++++++++------------------
|
||||||
|
crypto/blockpriv.h | 12 +++--
|
||||||
|
4 files changed, 78 insertions(+), 50 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
|
||||||
|
index 3ee928fb5a..3357852c0a 100644
|
||||||
|
--- a/crypto/block-luks.c
|
||||||
|
+++ b/crypto/block-luks.c
|
||||||
|
@@ -1262,7 +1262,6 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||||
|
luks->cipher_mode,
|
||||||
|
masterkey,
|
||||||
|
luks->header.master_key_len,
|
||||||
|
- n_threads,
|
||||||
|
errp) < 0) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
@@ -1456,7 +1455,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
||||||
|
/* Setup the block device payload encryption objects */
|
||||||
|
if (qcrypto_block_init_cipher(block, luks_opts.cipher_alg,
|
||||||
|
luks_opts.cipher_mode, masterkey,
|
||||||
|
- luks->header.master_key_len, 1, errp) < 0) {
|
||||||
|
+ luks->header.master_key_len, errp) < 0) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
|
||||||
|
index 4d7cf36a8f..02305058e3 100644
|
||||||
|
--- a/crypto/block-qcow.c
|
||||||
|
+++ b/crypto/block-qcow.c
|
||||||
|
@@ -75,7 +75,7 @@ qcrypto_block_qcow_init(QCryptoBlock *block,
|
||||||
|
ret = qcrypto_block_init_cipher(block, QCRYPTO_CIPHER_ALG_AES_128,
|
||||||
|
QCRYPTO_CIPHER_MODE_CBC,
|
||||||
|
keybuf, G_N_ELEMENTS(keybuf),
|
||||||
|
- n_threads, errp);
|
||||||
|
+ errp);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -ENOTSUP;
|
||||||
|
goto fail;
|
||||||
|
diff --git a/crypto/block.c b/crypto/block.c
|
||||||
|
index 506ea1d1a3..ba6d1cebc7 100644
|
||||||
|
--- a/crypto/block.c
|
||||||
|
+++ b/crypto/block.c
|
||||||
|
@@ -20,6 +20,7 @@
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
+#include "qemu/lockable.h"
|
||||||
|
#include "blockpriv.h"
|
||||||
|
#include "block-qcow.h"
|
||||||
|
#include "block-luks.h"
|
||||||
|
@@ -57,6 +58,8 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
{
|
||||||
|
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
||||||
|
|
||||||
|
+ qemu_mutex_init(&block->mutex);
|
||||||
|
+
|
||||||
|
block->format = options->format;
|
||||||
|
|
||||||
|
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||||
|
@@ -76,8 +79,6 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- qemu_mutex_init(&block->mutex);
|
||||||
|
-
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -92,6 +93,8 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||||
|
{
|
||||||
|
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
||||||
|
|
||||||
|
+ qemu_mutex_init(&block->mutex);
|
||||||
|
+
|
||||||
|
block->format = options->format;
|
||||||
|
|
||||||
|
if (options->format >= G_N_ELEMENTS(qcrypto_block_drivers) ||
|
||||||
|
@@ -111,8 +114,6 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
- qemu_mutex_init(&block->mutex);
|
||||||
|
-
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -227,37 +228,42 @@ QCryptoCipher *qcrypto_block_get_cipher(QCryptoBlock *block)
|
||||||
|
* This function is used only in test with one thread (it's safe to skip
|
||||||
|
* pop/push interface), so it's enough to assert it here:
|
||||||
|
*/
|
||||||
|
- assert(block->n_ciphers <= 1);
|
||||||
|
- return block->ciphers ? block->ciphers[0] : NULL;
|
||||||
|
+ assert(block->max_free_ciphers <= 1);
|
||||||
|
+ return block->free_ciphers ? block->free_ciphers[0] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block)
|
||||||
|
+static QCryptoCipher *qcrypto_block_pop_cipher(QCryptoBlock *block,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- QCryptoCipher *cipher;
|
||||||
|
-
|
||||||
|
- qemu_mutex_lock(&block->mutex);
|
||||||
|
-
|
||||||
|
- assert(block->n_free_ciphers > 0);
|
||||||
|
- block->n_free_ciphers--;
|
||||||
|
- cipher = block->ciphers[block->n_free_ciphers];
|
||||||
|
-
|
||||||
|
- qemu_mutex_unlock(&block->mutex);
|
||||||
|
+ /* Usually there is a free cipher available */
|
||||||
|
+ WITH_QEMU_LOCK_GUARD(&block->mutex) {
|
||||||
|
+ if (block->n_free_ciphers > 0) {
|
||||||
|
+ block->n_free_ciphers--;
|
||||||
|
+ return block->free_ciphers[block->n_free_ciphers];
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- return cipher;
|
||||||
|
+ /* Otherwise allocate a new cipher */
|
||||||
|
+ return qcrypto_cipher_new(block->alg, block->mode, block->key,
|
||||||
|
+ block->nkey, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void qcrypto_block_push_cipher(QCryptoBlock *block,
|
||||||
|
QCryptoCipher *cipher)
|
||||||
|
{
|
||||||
|
- qemu_mutex_lock(&block->mutex);
|
||||||
|
+ QEMU_LOCK_GUARD(&block->mutex);
|
||||||
|
|
||||||
|
- assert(block->n_free_ciphers < block->n_ciphers);
|
||||||
|
- block->ciphers[block->n_free_ciphers] = cipher;
|
||||||
|
- block->n_free_ciphers++;
|
||||||
|
+ if (block->n_free_ciphers == block->max_free_ciphers) {
|
||||||
|
+ block->max_free_ciphers++;
|
||||||
|
+ block->free_ciphers = g_renew(QCryptoCipher *,
|
||||||
|
+ block->free_ciphers,
|
||||||
|
+ block->max_free_ciphers);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- qemu_mutex_unlock(&block->mutex);
|
||||||
|
+ block->free_ciphers[block->n_free_ciphers] = cipher;
|
||||||
|
+ block->n_free_ciphers++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -265,24 +271,31 @@ int qcrypto_block_init_cipher(QCryptoBlock *block,
|
||||||
|
QCryptoCipherAlgorithm alg,
|
||||||
|
QCryptoCipherMode mode,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
- size_t n_threads, Error **errp)
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- size_t i;
|
||||||
|
+ QCryptoCipher *cipher;
|
||||||
|
|
||||||
|
- assert(!block->ciphers && !block->n_ciphers && !block->n_free_ciphers);
|
||||||
|
+ assert(!block->free_ciphers && !block->max_free_ciphers &&
|
||||||
|
+ !block->n_free_ciphers);
|
||||||
|
|
||||||
|
- block->ciphers = g_new0(QCryptoCipher *, n_threads);
|
||||||
|
+ /* Stash away cipher parameters for qcrypto_block_pop_cipher() */
|
||||||
|
+ block->alg = alg;
|
||||||
|
+ block->mode = mode;
|
||||||
|
+ block->key = g_memdup2(key, nkey);
|
||||||
|
+ block->nkey = nkey;
|
||||||
|
|
||||||
|
- for (i = 0; i < n_threads; i++) {
|
||||||
|
- block->ciphers[i] = qcrypto_cipher_new(alg, mode, key, nkey, errp);
|
||||||
|
- if (!block->ciphers[i]) {
|
||||||
|
- qcrypto_block_free_cipher(block);
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
- block->n_ciphers++;
|
||||||
|
- block->n_free_ciphers++;
|
||||||
|
+ /*
|
||||||
|
+ * Create a new cipher to validate the parameters now. This reduces the
|
||||||
|
+ * chance of cipher creation failing at I/O time.
|
||||||
|
+ */
|
||||||
|
+ cipher = qcrypto_block_pop_cipher(block, errp);
|
||||||
|
+ if (!cipher) {
|
||||||
|
+ g_free(block->key);
|
||||||
|
+ block->key = NULL;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ qcrypto_block_push_cipher(block, cipher);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -291,19 +304,23 @@ void qcrypto_block_free_cipher(QCryptoBlock *block)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
- if (!block->ciphers) {
|
||||||
|
+ g_free(block->key);
|
||||||
|
+ block->key = NULL;
|
||||||
|
+
|
||||||
|
+ if (!block->free_ciphers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- assert(block->n_ciphers == block->n_free_ciphers);
|
||||||
|
+ /* All popped ciphers were eventually pushed back */
|
||||||
|
+ assert(block->n_free_ciphers == block->max_free_ciphers);
|
||||||
|
|
||||||
|
- for (i = 0; i < block->n_ciphers; i++) {
|
||||||
|
- qcrypto_cipher_free(block->ciphers[i]);
|
||||||
|
+ for (i = 0; i < block->max_free_ciphers; i++) {
|
||||||
|
+ qcrypto_cipher_free(block->free_ciphers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- g_free(block->ciphers);
|
||||||
|
- block->ciphers = NULL;
|
||||||
|
- block->n_ciphers = block->n_free_ciphers = 0;
|
||||||
|
+ g_free(block->free_ciphers);
|
||||||
|
+ block->free_ciphers = NULL;
|
||||||
|
+ block->max_free_ciphers = block->n_free_ciphers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
|
||||||
|
@@ -311,7 +328,7 @@ QCryptoIVGen *qcrypto_block_get_ivgen(QCryptoBlock *block)
|
||||||
|
/* ivgen should be accessed under mutex. However, this function is used only
|
||||||
|
* in test with one thread, so it's enough to assert it here:
|
||||||
|
*/
|
||||||
|
- assert(block->n_ciphers <= 1);
|
||||||
|
+ assert(block->max_free_ciphers <= 1);
|
||||||
|
return block->ivgen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -446,7 +463,10 @@ int qcrypto_block_decrypt_helper(QCryptoBlock *block,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
- QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
|
||||||
|
+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
|
||||||
|
+ if (!cipher) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
|
||||||
|
&block->mutex, sectorsize, offset, buf,
|
||||||
|
@@ -465,7 +485,10 @@ int qcrypto_block_encrypt_helper(QCryptoBlock *block,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
- QCryptoCipher *cipher = qcrypto_block_pop_cipher(block);
|
||||||
|
+ QCryptoCipher *cipher = qcrypto_block_pop_cipher(block, errp);
|
||||||
|
+ if (!cipher) {
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
ret = do_qcrypto_block_cipher_encdec(cipher, block->niv, block->ivgen,
|
||||||
|
&block->mutex, sectorsize, offset, buf,
|
||||||
|
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
|
||||||
|
index 836f3b4726..4bf6043d5d 100644
|
||||||
|
--- a/crypto/blockpriv.h
|
||||||
|
+++ b/crypto/blockpriv.h
|
||||||
|
@@ -32,8 +32,14 @@ struct QCryptoBlock {
|
||||||
|
const QCryptoBlockDriver *driver;
|
||||||
|
void *opaque;
|
||||||
|
|
||||||
|
- QCryptoCipher **ciphers;
|
||||||
|
- size_t n_ciphers;
|
||||||
|
+ /* Cipher parameters */
|
||||||
|
+ QCryptoCipherAlgorithm alg;
|
||||||
|
+ QCryptoCipherMode mode;
|
||||||
|
+ uint8_t *key;
|
||||||
|
+ size_t nkey;
|
||||||
|
+
|
||||||
|
+ QCryptoCipher **free_ciphers;
|
||||||
|
+ size_t max_free_ciphers;
|
||||||
|
size_t n_free_ciphers;
|
||||||
|
QCryptoIVGen *ivgen;
|
||||||
|
QemuMutex mutex;
|
||||||
|
@@ -130,7 +136,7 @@ int qcrypto_block_init_cipher(QCryptoBlock *block,
|
||||||
|
QCryptoCipherAlgorithm alg,
|
||||||
|
QCryptoCipherMode mode,
|
||||||
|
const uint8_t *key, size_t nkey,
|
||||||
|
- size_t n_threads, Error **errp);
|
||||||
|
+ Error **errp);
|
||||||
|
|
||||||
|
void qcrypto_block_free_cipher(QCryptoBlock *block);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,217 +0,0 @@
|
|||||||
From 25cce5df341861e8ba8ec57722558e2dee3ce56a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Thu, 14 Sep 2023 10:00:58 -0400
|
|
||||||
Subject: [PATCH 073/101] block/file-posix: set up Linux AIO and io_uring in
|
|
||||||
the current thread
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [4/26] 74c7daf805daefe706378308c3afeb28d861164b (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
The file-posix block driver currently only sets up Linux AIO and
|
|
||||||
io_uring in the BDS's AioContext. In the multi-queue block layer we must
|
|
||||||
be able to submit I/O requests in AioContexts that do not have Linux AIO
|
|
||||||
and io_uring set up yet since any thread can call into the block driver.
|
|
||||||
|
|
||||||
Set up Linux AIO and io_uring for the current AioContext during request
|
|
||||||
submission. We lose the ability to return an error from
|
|
||||||
.bdrv_file_open() when Linux AIO and io_uring setup fails (e.g. due to
|
|
||||||
resource limits). Instead the user only gets warnings and we fall back
|
|
||||||
to aio=threads. This is still better than a fatal error after startup.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Message-ID: <20230914140101.1065008-2-stefanha@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
block/file-posix.c | 103 ++++++++++++++++++++++-----------------------
|
|
||||||
1 file changed, 51 insertions(+), 52 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block/file-posix.c b/block/file-posix.c
|
|
||||||
index b862406c71..35684f7e21 100644
|
|
||||||
--- a/block/file-posix.c
|
|
||||||
+++ b/block/file-posix.c
|
|
||||||
@@ -712,17 +712,11 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
|
||||||
|
|
||||||
#ifdef CONFIG_LINUX_AIO
|
|
||||||
/* Currently Linux does AIO only for files opened with O_DIRECT */
|
|
||||||
- if (s->use_linux_aio) {
|
|
||||||
- if (!(s->open_flags & O_DIRECT)) {
|
|
||||||
- error_setg(errp, "aio=native was specified, but it requires "
|
|
||||||
- "cache.direct=on, which was not specified.");
|
|
||||||
- ret = -EINVAL;
|
|
||||||
- goto fail;
|
|
||||||
- }
|
|
||||||
- if (!aio_setup_linux_aio(bdrv_get_aio_context(bs), errp)) {
|
|
||||||
- error_prepend(errp, "Unable to use native AIO: ");
|
|
||||||
- goto fail;
|
|
||||||
- }
|
|
||||||
+ if (s->use_linux_aio && !(s->open_flags & O_DIRECT)) {
|
|
||||||
+ error_setg(errp, "aio=native was specified, but it requires "
|
|
||||||
+ "cache.direct=on, which was not specified.");
|
|
||||||
+ ret = -EINVAL;
|
|
||||||
+ goto fail;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (s->use_linux_aio) {
|
|
||||||
@@ -733,14 +727,7 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
|
|
||||||
}
|
|
||||||
#endif /* !defined(CONFIG_LINUX_AIO) */
|
|
||||||
|
|
||||||
-#ifdef CONFIG_LINUX_IO_URING
|
|
||||||
- if (s->use_linux_io_uring) {
|
|
||||||
- if (!aio_setup_linux_io_uring(bdrv_get_aio_context(bs), errp)) {
|
|
||||||
- error_prepend(errp, "Unable to use io_uring: ");
|
|
||||||
- goto fail;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-#else
|
|
||||||
+#ifndef CONFIG_LINUX_IO_URING
|
|
||||||
if (s->use_linux_io_uring) {
|
|
||||||
error_setg(errp, "aio=io_uring was specified, but is not supported "
|
|
||||||
"in this build.");
|
|
||||||
@@ -2444,6 +2431,48 @@ static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef CONFIG_LINUX_IO_URING
|
|
||||||
+static inline bool raw_check_linux_io_uring(BDRVRawState *s)
|
|
||||||
+{
|
|
||||||
+ Error *local_err = NULL;
|
|
||||||
+ AioContext *ctx;
|
|
||||||
+
|
|
||||||
+ if (!s->use_linux_io_uring) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ctx = qemu_get_current_aio_context();
|
|
||||||
+ if (unlikely(!aio_setup_linux_io_uring(ctx, &local_err))) {
|
|
||||||
+ error_reportf_err(local_err, "Unable to use linux io_uring, "
|
|
||||||
+ "falling back to thread pool: ");
|
|
||||||
+ s->use_linux_io_uring = false;
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_LINUX_AIO
|
|
||||||
+static inline bool raw_check_linux_aio(BDRVRawState *s)
|
|
||||||
+{
|
|
||||||
+ Error *local_err = NULL;
|
|
||||||
+ AioContext *ctx;
|
|
||||||
+
|
|
||||||
+ if (!s->use_linux_aio) {
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ctx = qemu_get_current_aio_context();
|
|
||||||
+ if (unlikely(!aio_setup_linux_aio(ctx, &local_err))) {
|
|
||||||
+ error_reportf_err(local_err, "Unable to use Linux AIO, "
|
|
||||||
+ "falling back to thread pool: ");
|
|
||||||
+ s->use_linux_aio = false;
|
|
||||||
+ return false;
|
|
||||||
+ }
|
|
||||||
+ return true;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
static int coroutine_fn raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr,
|
|
||||||
uint64_t bytes, QEMUIOVector *qiov, int type)
|
|
||||||
{
|
|
||||||
@@ -2474,13 +2503,13 @@ static int coroutine_fn raw_co_prw(BlockDriverState *bs, int64_t *offset_ptr,
|
|
||||||
if (s->needs_alignment && !bdrv_qiov_is_aligned(bs, qiov)) {
|
|
||||||
type |= QEMU_AIO_MISALIGNED;
|
|
||||||
#ifdef CONFIG_LINUX_IO_URING
|
|
||||||
- } else if (s->use_linux_io_uring) {
|
|
||||||
+ } else if (raw_check_linux_io_uring(s)) {
|
|
||||||
assert(qiov->size == bytes);
|
|
||||||
ret = luring_co_submit(bs, s->fd, offset, qiov, type);
|
|
||||||
goto out;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_LINUX_AIO
|
|
||||||
- } else if (s->use_linux_aio) {
|
|
||||||
+ } else if (raw_check_linux_aio(s)) {
|
|
||||||
assert(qiov->size == bytes);
|
|
||||||
ret = laio_co_submit(s->fd, offset, qiov, type,
|
|
||||||
s->aio_max_batch);
|
|
||||||
@@ -2567,39 +2596,13 @@ static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs)
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef CONFIG_LINUX_IO_URING
|
|
||||||
- if (s->use_linux_io_uring) {
|
|
||||||
+ if (raw_check_linux_io_uring(s)) {
|
|
||||||
return luring_co_submit(bs, s->fd, 0, NULL, QEMU_AIO_FLUSH);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return raw_thread_pool_submit(handle_aiocb_flush, &acb);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void raw_aio_attach_aio_context(BlockDriverState *bs,
|
|
||||||
- AioContext *new_context)
|
|
||||||
-{
|
|
||||||
- BDRVRawState __attribute__((unused)) *s = bs->opaque;
|
|
||||||
-#ifdef CONFIG_LINUX_AIO
|
|
||||||
- if (s->use_linux_aio) {
|
|
||||||
- Error *local_err = NULL;
|
|
||||||
- if (!aio_setup_linux_aio(new_context, &local_err)) {
|
|
||||||
- error_reportf_err(local_err, "Unable to use native AIO, "
|
|
||||||
- "falling back to thread pool: ");
|
|
||||||
- s->use_linux_aio = false;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-#endif
|
|
||||||
-#ifdef CONFIG_LINUX_IO_URING
|
|
||||||
- if (s->use_linux_io_uring) {
|
|
||||||
- Error *local_err = NULL;
|
|
||||||
- if (!aio_setup_linux_io_uring(new_context, &local_err)) {
|
|
||||||
- error_reportf_err(local_err, "Unable to use linux io_uring, "
|
|
||||||
- "falling back to thread pool: ");
|
|
||||||
- s->use_linux_io_uring = false;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
-#endif
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static void raw_close(BlockDriverState *bs)
|
|
||||||
{
|
|
||||||
BDRVRawState *s = bs->opaque;
|
|
||||||
@@ -3896,7 +3899,6 @@ BlockDriver bdrv_file = {
|
|
||||||
.bdrv_co_copy_range_from = raw_co_copy_range_from,
|
|
||||||
.bdrv_co_copy_range_to = raw_co_copy_range_to,
|
|
||||||
.bdrv_refresh_limits = raw_refresh_limits,
|
|
||||||
- .bdrv_attach_aio_context = raw_aio_attach_aio_context,
|
|
||||||
|
|
||||||
.bdrv_co_truncate = raw_co_truncate,
|
|
||||||
.bdrv_co_getlength = raw_co_getlength,
|
|
||||||
@@ -4266,7 +4268,6 @@ static BlockDriver bdrv_host_device = {
|
|
||||||
.bdrv_co_copy_range_from = raw_co_copy_range_from,
|
|
||||||
.bdrv_co_copy_range_to = raw_co_copy_range_to,
|
|
||||||
.bdrv_refresh_limits = raw_refresh_limits,
|
|
||||||
- .bdrv_attach_aio_context = raw_aio_attach_aio_context,
|
|
||||||
|
|
||||||
.bdrv_co_truncate = raw_co_truncate,
|
|
||||||
.bdrv_co_getlength = raw_co_getlength,
|
|
||||||
@@ -4402,7 +4403,6 @@ static BlockDriver bdrv_host_cdrom = {
|
|
||||||
.bdrv_co_pwritev = raw_co_pwritev,
|
|
||||||
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
|
|
||||||
.bdrv_refresh_limits = cdrom_refresh_limits,
|
|
||||||
- .bdrv_attach_aio_context = raw_aio_attach_aio_context,
|
|
||||||
|
|
||||||
.bdrv_co_truncate = raw_co_truncate,
|
|
||||||
.bdrv_co_getlength = raw_co_getlength,
|
|
||||||
@@ -4528,7 +4528,6 @@ static BlockDriver bdrv_host_cdrom = {
|
|
||||||
.bdrv_co_pwritev = raw_co_pwritev,
|
|
||||||
.bdrv_co_flush_to_disk = raw_co_flush_to_disk,
|
|
||||||
.bdrv_refresh_limits = cdrom_refresh_limits,
|
|
||||||
- .bdrv_attach_aio_context = raw_aio_attach_aio_context,
|
|
||||||
|
|
||||||
.bdrv_co_truncate = raw_co_truncate,
|
|
||||||
.bdrv_co_getlength = raw_co_getlength,
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,97 +0,0 @@
|
|||||||
From d0514c7d5d6cc1aa140119c95d5ea2c1591b01e9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Tue, 5 Dec 2023 13:20:04 -0500
|
|
||||||
Subject: [PATCH 087/101] block: remove bdrv_co_lock()
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [18/26] a303f861ea5e84d8e89fd51e530fd0cb2da17b89 (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
The bdrv_co_lock() and bdrv_co_unlock() functions are already no-ops.
|
|
||||||
Remove them.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Message-ID: <20231205182011.1976568-8-stefanha@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
block.c | 10 ----------
|
|
||||||
blockdev.c | 5 -----
|
|
||||||
include/block/block-global-state.h | 14 --------------
|
|
||||||
3 files changed, 29 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block.c b/block.c
|
|
||||||
index 91ace5d2d5..434b7f4d72 100644
|
|
||||||
--- a/block.c
|
|
||||||
+++ b/block.c
|
|
||||||
@@ -7431,16 +7431,6 @@ void coroutine_fn bdrv_co_leave(BlockDriverState *bs, AioContext *old_ctx)
|
|
||||||
bdrv_dec_in_flight(bs);
|
|
||||||
}
|
|
||||||
|
|
||||||
-void coroutine_fn bdrv_co_lock(BlockDriverState *bs)
|
|
||||||
-{
|
|
||||||
- /* TODO removed in next patch */
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-void coroutine_fn bdrv_co_unlock(BlockDriverState *bs)
|
|
||||||
-{
|
|
||||||
- /* TODO removed in next patch */
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
static void bdrv_do_remove_aio_context_notifier(BdrvAioNotifier *ban)
|
|
||||||
{
|
|
||||||
GLOBAL_STATE_CODE();
|
|
||||||
diff --git a/blockdev.c b/blockdev.c
|
|
||||||
index 5d8b3a23eb..3a5e7222ec 100644
|
|
||||||
--- a/blockdev.c
|
|
||||||
+++ b/blockdev.c
|
|
||||||
@@ -2264,18 +2264,13 @@ void coroutine_fn qmp_block_resize(const char *device, const char *node_name,
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
- bdrv_co_lock(bs);
|
|
||||||
bdrv_drained_begin(bs);
|
|
||||||
- bdrv_co_unlock(bs);
|
|
||||||
|
|
||||||
old_ctx = bdrv_co_enter(bs);
|
|
||||||
blk_co_truncate(blk, size, false, PREALLOC_MODE_OFF, 0, errp);
|
|
||||||
bdrv_co_leave(bs, old_ctx);
|
|
||||||
|
|
||||||
- bdrv_co_lock(bs);
|
|
||||||
bdrv_drained_end(bs);
|
|
||||||
- bdrv_co_unlock(bs);
|
|
||||||
-
|
|
||||||
blk_co_unref(blk);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff --git a/include/block/block-global-state.h b/include/block/block-global-state.h
|
|
||||||
index 0327f1c605..4ec0b217f0 100644
|
|
||||||
--- a/include/block/block-global-state.h
|
|
||||||
+++ b/include/block/block-global-state.h
|
|
||||||
@@ -267,20 +267,6 @@ int bdrv_debug_remove_breakpoint(BlockDriverState *bs, const char *tag);
|
|
||||||
int bdrv_debug_resume(BlockDriverState *bs, const char *tag);
|
|
||||||
bool bdrv_debug_is_suspended(BlockDriverState *bs, const char *tag);
|
|
||||||
|
|
||||||
-/**
|
|
||||||
- * Locks the AioContext of @bs if it's not the current AioContext. This avoids
|
|
||||||
- * double locking which could lead to deadlocks: This is a coroutine_fn, so we
|
|
||||||
- * know we already own the lock of the current AioContext.
|
|
||||||
- *
|
|
||||||
- * May only be called in the main thread.
|
|
||||||
- */
|
|
||||||
-void coroutine_fn bdrv_co_lock(BlockDriverState *bs);
|
|
||||||
-
|
|
||||||
-/**
|
|
||||||
- * Unlocks the AioContext of @bs if it's not the current AioContext.
|
|
||||||
- */
|
|
||||||
-void coroutine_fn bdrv_co_unlock(BlockDriverState *bs);
|
|
||||||
-
|
|
||||||
bool bdrv_child_change_aio_context(BdrvChild *c, AioContext *ctx,
|
|
||||||
GHashTable *visited, Transaction *tran,
|
|
||||||
Error **errp);
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,411 +0,0 @@
|
|||||||
From dc4eb64185957a01948217814478abc450ce5f26 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Tue, 5 Dec 2023 13:20:11 -0500
|
|
||||||
Subject: [PATCH 094/101] block: remove outdated AioContext locking comments
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [25/26] 395e18fb40d28d4bc961acee1a00da7f60748076 (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
The AioContext lock no longer exists.
|
|
||||||
|
|
||||||
There is one noteworthy change:
|
|
||||||
|
|
||||||
- * More specifically, these functions use BDRV_POLL_WHILE(bs), which
|
|
||||||
- * requires the caller to be either in the main thread and hold
|
|
||||||
- * the BlockdriverState (bs) AioContext lock, or directly in the
|
|
||||||
- * home thread that runs the bs AioContext. Calling them from
|
|
||||||
- * another thread in another AioContext would cause deadlocks.
|
|
||||||
+ * More specifically, these functions use BDRV_POLL_WHILE(bs), which requires
|
|
||||||
+ * the caller to be either in the main thread or directly in the home thread
|
|
||||||
+ * that runs the bs AioContext. Calling them from another thread in another
|
|
||||||
+ * AioContext would cause deadlocks.
|
|
||||||
|
|
||||||
I am not sure whether deadlocks are still possible. Maybe they have just
|
|
||||||
moved to the fine-grained locks that have replaced the AioContext. Since
|
|
||||||
I am not sure if the deadlocks are gone, I have kept the substance
|
|
||||||
unchanged and just removed mention of the AioContext.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Message-ID: <20231205182011.1976568-15-stefanha@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
block.c | 73 ++++++----------------------
|
|
||||||
block/block-backend.c | 8 ---
|
|
||||||
block/export/vhost-user-blk-server.c | 4 --
|
|
||||||
include/block/block-common.h | 3 --
|
|
||||||
include/block/block-io.h | 9 ++--
|
|
||||||
include/block/block_int-common.h | 2 -
|
|
||||||
tests/qemu-iotests/202 | 2 +-
|
|
||||||
tests/qemu-iotests/203 | 3 +-
|
|
||||||
8 files changed, 22 insertions(+), 82 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/block.c b/block.c
|
|
||||||
index 434b7f4d72..a097772238 100644
|
|
||||||
--- a/block.c
|
|
||||||
+++ b/block.c
|
|
||||||
@@ -1616,11 +1616,6 @@ out:
|
|
||||||
g_free(gen_node_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
-/*
|
|
||||||
- * The caller must always hold @bs AioContext lock, because this function calls
|
|
||||||
- * bdrv_refresh_total_sectors() which polls when called from non-coroutine
|
|
||||||
- * context.
|
|
||||||
- */
|
|
||||||
static int no_coroutine_fn GRAPH_UNLOCKED
|
|
||||||
bdrv_open_driver(BlockDriverState *bs, BlockDriver *drv, const char *node_name,
|
|
||||||
QDict *options, int open_flags, Error **errp)
|
|
||||||
@@ -2901,7 +2896,7 @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
|
|
||||||
* Replaces the node that a BdrvChild points to without updating permissions.
|
|
||||||
*
|
|
||||||
* If @new_bs is non-NULL, the parent of @child must already be drained through
|
|
||||||
- * @child and the caller must hold the AioContext lock for @new_bs.
|
|
||||||
+ * @child.
|
|
||||||
*/
|
|
||||||
static void GRAPH_WRLOCK
|
|
||||||
bdrv_replace_child_noperm(BdrvChild *child, BlockDriverState *new_bs)
|
|
||||||
@@ -3041,9 +3036,8 @@ static TransactionActionDrv bdrv_attach_child_common_drv = {
|
|
||||||
*
|
|
||||||
* Returns new created child.
|
|
||||||
*
|
|
||||||
- * The caller must hold the AioContext lock for @child_bs. Both @parent_bs and
|
|
||||||
- * @child_bs can move to a different AioContext in this function. Callers must
|
|
||||||
- * make sure that their AioContext locking is still correct after this.
|
|
||||||
+ * Both @parent_bs and @child_bs can move to a different AioContext in this
|
|
||||||
+ * function.
|
|
||||||
*/
|
|
||||||
static BdrvChild * GRAPH_WRLOCK
|
|
||||||
bdrv_attach_child_common(BlockDriverState *child_bs,
|
|
||||||
@@ -3142,9 +3136,8 @@ bdrv_attach_child_common(BlockDriverState *child_bs,
|
|
||||||
/*
|
|
||||||
* Function doesn't update permissions, caller is responsible for this.
|
|
||||||
*
|
|
||||||
- * The caller must hold the AioContext lock for @child_bs. Both @parent_bs and
|
|
||||||
- * @child_bs can move to a different AioContext in this function. Callers must
|
|
||||||
- * make sure that their AioContext locking is still correct after this.
|
|
||||||
+ * Both @parent_bs and @child_bs can move to a different AioContext in this
|
|
||||||
+ * function.
|
|
||||||
*
|
|
||||||
* After calling this function, the transaction @tran may only be completed
|
|
||||||
* while holding a writer lock for the graph.
|
|
||||||
@@ -3184,9 +3177,6 @@ bdrv_attach_child_noperm(BlockDriverState *parent_bs,
|
|
||||||
*
|
|
||||||
* On failure NULL is returned, errp is set and the reference to
|
|
||||||
* child_bs is also dropped.
|
|
||||||
- *
|
|
||||||
- * The caller must hold the AioContext lock @child_bs, but not that of @ctx
|
|
||||||
- * (unless @child_bs is already in @ctx).
|
|
||||||
*/
|
|
||||||
BdrvChild *bdrv_root_attach_child(BlockDriverState *child_bs,
|
|
||||||
const char *child_name,
|
|
||||||
@@ -3226,9 +3216,6 @@ out:
|
|
||||||
*
|
|
||||||
* On failure NULL is returned, errp is set and the reference to
|
|
||||||
* child_bs is also dropped.
|
|
||||||
- *
|
|
||||||
- * If @parent_bs and @child_bs are in different AioContexts, the caller must
|
|
||||||
- * hold the AioContext lock for @child_bs, but not for @parent_bs.
|
|
||||||
*/
|
|
||||||
BdrvChild *bdrv_attach_child(BlockDriverState *parent_bs,
|
|
||||||
BlockDriverState *child_bs,
|
|
||||||
@@ -3418,9 +3405,8 @@ static BdrvChildRole bdrv_backing_role(BlockDriverState *bs)
|
|
||||||
*
|
|
||||||
* Function doesn't update permissions, caller is responsible for this.
|
|
||||||
*
|
|
||||||
- * The caller must hold the AioContext lock for @child_bs. Both @parent_bs and
|
|
||||||
- * @child_bs can move to a different AioContext in this function. Callers must
|
|
||||||
- * make sure that their AioContext locking is still correct after this.
|
|
||||||
+ * Both @parent_bs and @child_bs can move to a different AioContext in this
|
|
||||||
+ * function.
|
|
||||||
*
|
|
||||||
* After calling this function, the transaction @tran may only be completed
|
|
||||||
* while holding a writer lock for the graph.
|
|
||||||
@@ -3513,9 +3499,8 @@ out:
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * The caller must hold the AioContext lock for @backing_hd. Both @bs and
|
|
||||||
- * @backing_hd can move to a different AioContext in this function. Callers must
|
|
||||||
- * make sure that their AioContext locking is still correct after this.
|
|
||||||
+ * Both @bs and @backing_hd can move to a different AioContext in this
|
|
||||||
+ * function.
|
|
||||||
*
|
|
||||||
* If a backing child is already present (i.e. we're detaching a node), that
|
|
||||||
* child node must be drained.
|
|
||||||
@@ -3574,8 +3559,6 @@ int bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd,
|
|
||||||
* itself, all options starting with "${bdref_key}." are considered part of the
|
|
||||||
* BlockdevRef.
|
|
||||||
*
|
|
||||||
- * The caller must hold the main AioContext lock.
|
|
||||||
- *
|
|
||||||
* TODO Can this be unified with bdrv_open_image()?
|
|
||||||
*/
|
|
||||||
int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options,
|
|
||||||
@@ -3745,9 +3728,7 @@ done:
|
|
||||||
*
|
|
||||||
* The BlockdevRef will be removed from the options QDict.
|
|
||||||
*
|
|
||||||
- * The caller must hold the lock of the main AioContext and no other AioContext.
|
|
||||||
- * @parent can move to a different AioContext in this function. Callers must
|
|
||||||
- * make sure that their AioContext locking is still correct after this.
|
|
||||||
+ * @parent can move to a different AioContext in this function.
|
|
||||||
*/
|
|
||||||
BdrvChild *bdrv_open_child(const char *filename,
|
|
||||||
QDict *options, const char *bdref_key,
|
|
||||||
@@ -3778,9 +3759,7 @@ BdrvChild *bdrv_open_child(const char *filename,
|
|
||||||
/*
|
|
||||||
* Wrapper on bdrv_open_child() for most popular case: open primary child of bs.
|
|
||||||
*
|
|
||||||
- * The caller must hold the lock of the main AioContext and no other AioContext.
|
|
||||||
- * @parent can move to a different AioContext in this function. Callers must
|
|
||||||
- * make sure that their AioContext locking is still correct after this.
|
|
||||||
+ * @parent can move to a different AioContext in this function.
|
|
||||||
*/
|
|
||||||
int bdrv_open_file_child(const char *filename,
|
|
||||||
QDict *options, const char *bdref_key,
|
|
||||||
@@ -3923,8 +3902,6 @@ out:
|
|
||||||
* The reference parameter may be used to specify an existing block device which
|
|
||||||
* should be opened. If specified, neither options nor a filename may be given,
|
|
||||||
* nor can an existing BDS be reused (that is, *pbs has to be NULL).
|
|
||||||
- *
|
|
||||||
- * The caller must always hold the main AioContext lock.
|
|
||||||
*/
|
|
||||||
static BlockDriverState * no_coroutine_fn
|
|
||||||
bdrv_open_inherit(const char *filename, const char *reference, QDict *options,
|
|
||||||
@@ -4217,7 +4194,6 @@ close_and_fail:
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* The caller must always hold the main AioContext lock. */
|
|
||||||
BlockDriverState *bdrv_open(const char *filename, const char *reference,
|
|
||||||
QDict *options, int flags, Error **errp)
|
|
||||||
{
|
|
||||||
@@ -4665,10 +4641,7 @@ int bdrv_reopen_set_read_only(BlockDriverState *bs, bool read_only,
|
|
||||||
*
|
|
||||||
* Return 0 on success, otherwise return < 0 and set @errp.
|
|
||||||
*
|
|
||||||
- * The caller must hold the AioContext lock of @reopen_state->bs.
|
|
||||||
* @reopen_state->bs can move to a different AioContext in this function.
|
|
||||||
- * Callers must make sure that their AioContext locking is still correct after
|
|
||||||
- * this.
|
|
||||||
*/
|
|
||||||
static int GRAPH_UNLOCKED
|
|
||||||
bdrv_reopen_parse_file_or_backing(BDRVReopenState *reopen_state,
|
|
||||||
@@ -4801,8 +4774,6 @@ out_rdlock:
|
|
||||||
* It is the responsibility of the caller to then call the abort() or
|
|
||||||
* commit() for any other BDS that have been left in a prepare() state
|
|
||||||
*
|
|
||||||
- * The caller must hold the AioContext lock of @reopen_state->bs.
|
|
||||||
- *
|
|
||||||
* After calling this function, the transaction @change_child_tran may only be
|
|
||||||
* completed while holding a writer lock for the graph.
|
|
||||||
*/
|
|
||||||
@@ -5437,8 +5408,6 @@ int bdrv_drop_filter(BlockDriverState *bs, Error **errp)
|
|
||||||
* child.
|
|
||||||
*
|
|
||||||
* This function does not create any image files.
|
|
||||||
- *
|
|
||||||
- * The caller must hold the AioContext lock for @bs_top.
|
|
||||||
*/
|
|
||||||
int bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top,
|
|
||||||
Error **errp)
|
|
||||||
@@ -5545,9 +5514,8 @@ static void bdrv_delete(BlockDriverState *bs)
|
|
||||||
* after the call (even on failure), so if the caller intends to reuse the
|
|
||||||
* dictionary, it needs to use qobject_ref() before calling bdrv_open.
|
|
||||||
*
|
|
||||||
- * The caller holds the AioContext lock for @bs. It must make sure that @bs
|
|
||||||
- * stays in the same AioContext, i.e. @options must not refer to nodes in a
|
|
||||||
- * different AioContext.
|
|
||||||
+ * The caller must make sure that @bs stays in the same AioContext, i.e.
|
|
||||||
+ * @options must not refer to nodes in a different AioContext.
|
|
||||||
*/
|
|
||||||
BlockDriverState *bdrv_insert_node(BlockDriverState *bs, QDict *options,
|
|
||||||
int flags, Error **errp)
|
|
||||||
@@ -7565,10 +7533,6 @@ static TransactionActionDrv set_aio_context = {
|
|
||||||
*
|
|
||||||
* Must be called from the main AioContext.
|
|
||||||
*
|
|
||||||
- * The caller must own the AioContext lock for the old AioContext of bs, but it
|
|
||||||
- * must not own the AioContext lock for new_context (unless new_context is the
|
|
||||||
- * same as the current context of bs).
|
|
||||||
- *
|
|
||||||
* @visited will accumulate all visited BdrvChild objects. The caller is
|
|
||||||
* responsible for freeing the list afterwards.
|
|
||||||
*/
|
|
||||||
@@ -7621,13 +7585,6 @@ static bool bdrv_change_aio_context(BlockDriverState *bs, AioContext *ctx,
|
|
||||||
*
|
|
||||||
* If ignore_child is not NULL, that child (and its subgraph) will not
|
|
||||||
* be touched.
|
|
||||||
- *
|
|
||||||
- * This function still requires the caller to take the bs current
|
|
||||||
- * AioContext lock, otherwise draining will fail since AIO_WAIT_WHILE
|
|
||||||
- * assumes the lock is always held if bs is in another AioContext.
|
|
||||||
- * For the same reason, it temporarily also holds the new AioContext, since
|
|
||||||
- * bdrv_drained_end calls BDRV_POLL_WHILE that assumes the lock is taken too.
|
|
||||||
- * Therefore the new AioContext lock must not be taken by the caller.
|
|
||||||
*/
|
|
||||||
int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
|
|
||||||
BdrvChild *ignore_child, Error **errp)
|
|
||||||
@@ -7653,8 +7610,8 @@ int bdrv_try_change_aio_context(BlockDriverState *bs, AioContext *ctx,
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Linear phase: go through all callbacks collected in the transaction.
|
|
||||||
- * Run all callbacks collected in the recursion to switch all nodes
|
|
||||||
- * AioContext lock (transaction commit), or undo all changes done in the
|
|
||||||
+ * Run all callbacks collected in the recursion to switch every node's
|
|
||||||
+ * AioContext (transaction commit), or undo all changes done in the
|
|
||||||
* recursion (transaction abort).
|
|
||||||
*/
|
|
||||||
|
|
||||||
diff --git a/block/block-backend.c b/block/block-backend.c
|
|
||||||
index f412bed274..209eb07528 100644
|
|
||||||
--- a/block/block-backend.c
|
|
||||||
+++ b/block/block-backend.c
|
|
||||||
@@ -390,8 +390,6 @@ BlockBackend *blk_new(AioContext *ctx, uint64_t perm, uint64_t shared_perm)
|
|
||||||
* Both sets of permissions can be changed later using blk_set_perm().
|
|
||||||
*
|
|
||||||
* Return the new BlockBackend on success, null on failure.
|
|
||||||
- *
|
|
||||||
- * Callers must hold the AioContext lock of @bs.
|
|
||||||
*/
|
|
||||||
BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
|
|
||||||
uint64_t shared_perm, Error **errp)
|
|
||||||
@@ -416,8 +414,6 @@ BlockBackend *blk_new_with_bs(BlockDriverState *bs, uint64_t perm,
|
|
||||||
* Just as with bdrv_open(), after having called this function the reference to
|
|
||||||
* @options belongs to the block layer (even on failure).
|
|
||||||
*
|
|
||||||
- * Called without holding an AioContext lock.
|
|
||||||
- *
|
|
||||||
* TODO: Remove @filename and @flags; it should be possible to specify a whole
|
|
||||||
* BDS tree just by specifying the @options QDict (or @reference,
|
|
||||||
* alternatively). At the time of adding this function, this is not possible,
|
|
||||||
@@ -872,8 +868,6 @@ BlockBackend *blk_by_public(BlockBackendPublic *public)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Disassociates the currently associated BlockDriverState from @blk.
|
|
||||||
- *
|
|
||||||
- * The caller must hold the AioContext lock for the BlockBackend.
|
|
||||||
*/
|
|
||||||
void blk_remove_bs(BlockBackend *blk)
|
|
||||||
{
|
|
||||||
@@ -915,8 +909,6 @@ void blk_remove_bs(BlockBackend *blk)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Associates a new BlockDriverState with @blk.
|
|
||||||
- *
|
|
||||||
- * Callers must hold the AioContext lock of @bs.
|
|
||||||
*/
|
|
||||||
int blk_insert_bs(BlockBackend *blk, BlockDriverState *bs, Error **errp)
|
|
||||||
{
|
|
||||||
diff --git a/block/export/vhost-user-blk-server.c b/block/export/vhost-user-blk-server.c
|
|
||||||
index 16f48388d3..50c358e8cd 100644
|
|
||||||
--- a/block/export/vhost-user-blk-server.c
|
|
||||||
+++ b/block/export/vhost-user-blk-server.c
|
|
||||||
@@ -278,7 +278,6 @@ static void vu_blk_exp_resize(void *opaque)
|
|
||||||
vu_config_change_msg(&vexp->vu_server.vu_dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* Called with vexp->export.ctx acquired */
|
|
||||||
static void vu_blk_drained_begin(void *opaque)
|
|
||||||
{
|
|
||||||
VuBlkExport *vexp = opaque;
|
|
||||||
@@ -287,7 +286,6 @@ static void vu_blk_drained_begin(void *opaque)
|
|
||||||
vhost_user_server_detach_aio_context(&vexp->vu_server);
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* Called with vexp->export.blk AioContext acquired */
|
|
||||||
static void vu_blk_drained_end(void *opaque)
|
|
||||||
{
|
|
||||||
VuBlkExport *vexp = opaque;
|
|
||||||
@@ -300,8 +298,6 @@ static void vu_blk_drained_end(void *opaque)
|
|
||||||
* Ensures that bdrv_drained_begin() waits until in-flight requests complete
|
|
||||||
* and the server->co_trip coroutine has terminated. It will be restarted in
|
|
||||||
* vhost_user_server_attach_aio_context().
|
|
||||||
- *
|
|
||||||
- * Called with vexp->export.ctx acquired.
|
|
||||||
*/
|
|
||||||
static bool vu_blk_drained_poll(void *opaque)
|
|
||||||
{
|
|
||||||
diff --git a/include/block/block-common.h b/include/block/block-common.h
|
|
||||||
index d7599564db..a846023a09 100644
|
|
||||||
--- a/include/block/block-common.h
|
|
||||||
+++ b/include/block/block-common.h
|
|
||||||
@@ -70,9 +70,6 @@
|
|
||||||
* automatically takes the graph rdlock when calling the wrapped function. In
|
|
||||||
* the same way, no_co_wrapper_bdrv_wrlock functions automatically take the
|
|
||||||
* graph wrlock.
|
|
||||||
- *
|
|
||||||
- * If the first parameter of the function is a BlockDriverState, BdrvChild or
|
|
||||||
- * BlockBackend pointer, the AioContext lock for it is taken in the wrapper.
|
|
||||||
*/
|
|
||||||
#define no_co_wrapper
|
|
||||||
#define no_co_wrapper_bdrv_rdlock
|
|
||||||
diff --git a/include/block/block-io.h b/include/block/block-io.h
|
|
||||||
index 8eb39a858b..b49e0537dd 100644
|
|
||||||
--- a/include/block/block-io.h
|
|
||||||
+++ b/include/block/block-io.h
|
|
||||||
@@ -332,11 +332,10 @@ bdrv_co_copy_range(BdrvChild *src, int64_t src_offset,
|
|
||||||
* "I/O or GS" API functions. These functions can run without
|
|
||||||
* the BQL, but only in one specific iothread/main loop.
|
|
||||||
*
|
|
||||||
- * More specifically, these functions use BDRV_POLL_WHILE(bs), which
|
|
||||||
- * requires the caller to be either in the main thread and hold
|
|
||||||
- * the BlockdriverState (bs) AioContext lock, or directly in the
|
|
||||||
- * home thread that runs the bs AioContext. Calling them from
|
|
||||||
- * another thread in another AioContext would cause deadlocks.
|
|
||||||
+ * More specifically, these functions use BDRV_POLL_WHILE(bs), which requires
|
|
||||||
+ * the caller to be either in the main thread or directly in the home thread
|
|
||||||
+ * that runs the bs AioContext. Calling them from another thread in another
|
|
||||||
+ * AioContext would cause deadlocks.
|
|
||||||
*
|
|
||||||
* Therefore, these functions are not proper I/O, because they
|
|
||||||
* can't run in *any* iothreads, but only in a specific one.
|
|
||||||
diff --git a/include/block/block_int-common.h b/include/block/block_int-common.h
|
|
||||||
index 4e31d161c5..151279d481 100644
|
|
||||||
--- a/include/block/block_int-common.h
|
|
||||||
+++ b/include/block/block_int-common.h
|
|
||||||
@@ -1192,8 +1192,6 @@ struct BlockDriverState {
|
|
||||||
/* The error object in use for blocking operations on backing_hd */
|
|
||||||
Error *backing_blocker;
|
|
||||||
|
|
||||||
- /* Protected by AioContext lock */
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* If we are reading a disk image, give its size in sectors.
|
|
||||||
* Generally read-only; it is written to by load_snapshot and
|
|
||||||
diff --git a/tests/qemu-iotests/202 b/tests/qemu-iotests/202
|
|
||||||
index b784dcd791..13304242e5 100755
|
|
||||||
--- a/tests/qemu-iotests/202
|
|
||||||
+++ b/tests/qemu-iotests/202
|
|
||||||
@@ -21,7 +21,7 @@
|
|
||||||
# Check that QMP 'transaction' blockdev-snapshot-sync with multiple drives on a
|
|
||||||
# single IOThread completes successfully. This particular command triggered a
|
|
||||||
# hang due to recursive AioContext locking and BDRV_POLL_WHILE(). Protect
|
|
||||||
-# against regressions.
|
|
||||||
+# against regressions even though the AioContext lock no longer exists.
|
|
||||||
|
|
||||||
import iotests
|
|
||||||
|
|
||||||
diff --git a/tests/qemu-iotests/203 b/tests/qemu-iotests/203
|
|
||||||
index ab80fd0e44..1ba878522b 100755
|
|
||||||
--- a/tests/qemu-iotests/203
|
|
||||||
+++ b/tests/qemu-iotests/203
|
|
||||||
@@ -21,7 +21,8 @@
|
|
||||||
# Check that QMP 'migrate' with multiple drives on a single IOThread completes
|
|
||||||
# successfully. This particular command triggered a hang in the source QEMU
|
|
||||||
# process due to recursive AioContext locking in bdrv_invalidate_all() and
|
|
||||||
-# BDRV_POLL_WHILE().
|
|
||||||
+# BDRV_POLL_WHILE(). Protect against regressions even though the AioContext
|
|
||||||
+# lock no longer exists.
|
|
||||||
|
|
||||||
import iotests
|
|
||||||
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,90 @@
|
|||||||
|
From 0f0a3a860a07addea21a0282556a5022b9cb8b2c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Thu, 29 Feb 2024 01:00:35 -0500
|
||||||
|
Subject: [PATCH 011/100] confidential guest support: Add kvm_init() and
|
||||||
|
kvm_reset() in class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [11/91] 21d2178178bf181a8e4d0b051f64bd983f0d0cf1 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Different confidential VMs in different architectures all have the same
|
||||||
|
needs to do their specific initialization (and maybe resetting) stuffs
|
||||||
|
with KVM. Currently each of them exposes individual *_kvm_init()
|
||||||
|
functions and let machine code or kvm code to call it.
|
||||||
|
|
||||||
|
To facilitate the introduction of confidential guest technology from
|
||||||
|
different x86 vendors, add two virtual functions, kvm_init() and kvm_reset()
|
||||||
|
in ConfidentialGuestSupportClass, and expose two helpers functions for
|
||||||
|
invodking them.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-Id: <20240229060038.606591-1-xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 41a605944e3fecae43ca18ded95ec31f28e0c7fe)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
include/exec/confidential-guest-support.h | 34 ++++++++++++++++++++++-
|
||||||
|
1 file changed, 33 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||||
|
index ba2dd4b5df..e5b188cffb 100644
|
||||||
|
--- a/include/exec/confidential-guest-support.h
|
||||||
|
+++ b/include/exec/confidential-guest-support.h
|
||||||
|
@@ -23,7 +23,10 @@
|
||||||
|
#include "qom/object.h"
|
||||||
|
|
||||||
|
#define TYPE_CONFIDENTIAL_GUEST_SUPPORT "confidential-guest-support"
|
||||||
|
-OBJECT_DECLARE_SIMPLE_TYPE(ConfidentialGuestSupport, CONFIDENTIAL_GUEST_SUPPORT)
|
||||||
|
+OBJECT_DECLARE_TYPE(ConfidentialGuestSupport,
|
||||||
|
+ ConfidentialGuestSupportClass,
|
||||||
|
+ CONFIDENTIAL_GUEST_SUPPORT)
|
||||||
|
+
|
||||||
|
|
||||||
|
struct ConfidentialGuestSupport {
|
||||||
|
Object parent;
|
||||||
|
@@ -55,8 +58,37 @@ struct ConfidentialGuestSupport {
|
||||||
|
|
||||||
|
typedef struct ConfidentialGuestSupportClass {
|
||||||
|
ObjectClass parent;
|
||||||
|
+
|
||||||
|
+ int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
+ int (*kvm_reset)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
} ConfidentialGuestSupportClass;
|
||||||
|
|
||||||
|
+static inline int confidential_guest_kvm_init(ConfidentialGuestSupport *cgs,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ ConfidentialGuestSupportClass *klass;
|
||||||
|
+
|
||||||
|
+ klass = CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs);
|
||||||
|
+ if (klass->kvm_init) {
|
||||||
|
+ return klass->kvm_init(cgs, errp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static inline int confidential_guest_kvm_reset(ConfidentialGuestSupport *cgs,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ ConfidentialGuestSupportClass *klass;
|
||||||
|
+
|
||||||
|
+ klass = CONFIDENTIAL_GUEST_SUPPORT_GET_CLASS(cgs);
|
||||||
|
+ if (klass->kvm_reset) {
|
||||||
|
+ return klass->kvm_reset(cgs, errp);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#endif /* !CONFIG_USER_ONLY */
|
||||||
|
|
||||||
|
#endif /* QEMU_CONFIDENTIAL_GUEST_SUPPORT_H */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,228 @@
|
|||||||
|
From 117486e0820f135f191e19f8ebb8838a98b121c6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Date: Mon, 27 May 2024 11:58:51 -0400
|
||||||
|
Subject: [PATCH 5/5] crypto/block: drop qcrypto_block_open() n_threads
|
||||||
|
argument
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
RH-MergeRequest: 251: block/crypto: create ciphers on demand
|
||||||
|
RH-Jira: RHEL-36159
|
||||||
|
RH-Acked-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [2/2] 68290935b174b1f2b76aa857a926da9011e54abe (stefanha/centos-stream-qemu-kvm)
|
||||||
|
|
||||||
|
The n_threads argument is no longer used since the previous commit.
|
||||||
|
Remove it.
|
||||||
|
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
Message-ID: <20240527155851.892885-3-stefanha@redhat.com>
|
||||||
|
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||||
|
(cherry picked from commit 3ab0f063e58ed9224237d69c4211ca83335164c4)
|
||||||
|
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||||
|
---
|
||||||
|
block/crypto.c | 1 -
|
||||||
|
block/qcow.c | 2 +-
|
||||||
|
block/qcow2.c | 5 ++---
|
||||||
|
crypto/block-luks.c | 1 -
|
||||||
|
crypto/block-qcow.c | 6 ++----
|
||||||
|
crypto/block.c | 3 +--
|
||||||
|
crypto/blockpriv.h | 1 -
|
||||||
|
include/crypto/block.h | 2 --
|
||||||
|
tests/unit/test-crypto-block.c | 4 ----
|
||||||
|
9 files changed, 6 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/block/crypto.c b/block/crypto.c
|
||||||
|
index 21eed909c1..4eed3ffa6a 100644
|
||||||
|
--- a/block/crypto.c
|
||||||
|
+++ b/block/crypto.c
|
||||||
|
@@ -363,7 +363,6 @@ static int block_crypto_open_generic(QCryptoBlockFormat format,
|
||||||
|
block_crypto_read_func,
|
||||||
|
bs,
|
||||||
|
cflags,
|
||||||
|
- 1,
|
||||||
|
errp);
|
||||||
|
|
||||||
|
if (!crypto->block) {
|
||||||
|
diff --git a/block/qcow.c b/block/qcow.c
|
||||||
|
index ca8e1d5ec8..c2f89db055 100644
|
||||||
|
--- a/block/qcow.c
|
||||||
|
+++ b/block/qcow.c
|
||||||
|
@@ -211,7 +211,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
|
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
||||||
|
}
|
||||||
|
s->crypto = qcrypto_block_open(crypto_opts, "encrypt.",
|
||||||
|
- NULL, NULL, cflags, 1, errp);
|
||||||
|
+ NULL, NULL, cflags, errp);
|
||||||
|
if (!s->crypto) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
diff --git a/block/qcow2.c b/block/qcow2.c
|
||||||
|
index 0e8b2f7518..0ebd455dc8 100644
|
||||||
|
--- a/block/qcow2.c
|
||||||
|
+++ b/block/qcow2.c
|
||||||
|
@@ -321,7 +321,7 @@ qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||||
|
}
|
||||||
|
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
||||||
|
qcow2_crypto_hdr_read_func,
|
||||||
|
- bs, cflags, QCOW2_MAX_THREADS, errp);
|
||||||
|
+ bs, cflags, errp);
|
||||||
|
if (!s->crypto) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
@@ -1707,8 +1707,7 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags,
|
||||||
|
cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
|
||||||
|
}
|
||||||
|
s->crypto = qcrypto_block_open(s->crypto_opts, "encrypt.",
|
||||||
|
- NULL, NULL, cflags,
|
||||||
|
- QCOW2_MAX_THREADS, errp);
|
||||||
|
+ NULL, NULL, cflags, errp);
|
||||||
|
if (!s->crypto) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
|
||||||
|
index 3357852c0a..5b777c15d3 100644
|
||||||
|
--- a/crypto/block-luks.c
|
||||||
|
+++ b/crypto/block-luks.c
|
||||||
|
@@ -1189,7 +1189,6 @@ qcrypto_block_luks_open(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlockLUKS *luks = NULL;
|
||||||
|
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
|
||||||
|
index 02305058e3..42e9556e42 100644
|
||||||
|
--- a/crypto/block-qcow.c
|
||||||
|
+++ b/crypto/block-qcow.c
|
||||||
|
@@ -44,7 +44,6 @@ qcrypto_block_qcow_has_format(const uint8_t *buf G_GNUC_UNUSED,
|
||||||
|
static int
|
||||||
|
qcrypto_block_qcow_init(QCryptoBlock *block,
|
||||||
|
const char *keysecret,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
char *password;
|
||||||
|
@@ -100,7 +99,6 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
|
||||||
|
QCryptoBlockReadFunc readfunc G_GNUC_UNUSED,
|
||||||
|
void *opaque G_GNUC_UNUSED,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
|
||||||
|
@@ -115,7 +113,7 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return qcrypto_block_qcow_init(block, options->u.qcow.key_secret,
|
||||||
|
- n_threads, errp);
|
||||||
|
+ errp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -135,7 +133,7 @@ qcrypto_block_qcow_create(QCryptoBlock *block,
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* QCow2 has no special header, since everything is hardwired */
|
||||||
|
- return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, 1, errp);
|
||||||
|
+ return qcrypto_block_qcow_init(block, options->u.qcow.key_secret, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/crypto/block.c b/crypto/block.c
|
||||||
|
index ba6d1cebc7..3bcc4270c3 100644
|
||||||
|
--- a/crypto/block.c
|
||||||
|
+++ b/crypto/block.c
|
||||||
|
@@ -53,7 +53,6 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
|
||||||
|
@@ -73,7 +72,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
block->driver = qcrypto_block_drivers[options->format];
|
||||||
|
|
||||||
|
if (block->driver->open(block, options, optprefix,
|
||||||
|
- readfunc, opaque, flags, n_threads, errp) < 0)
|
||||||
|
+ readfunc, opaque, flags, errp) < 0)
|
||||||
|
{
|
||||||
|
g_free(block);
|
||||||
|
return NULL;
|
||||||
|
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
|
||||||
|
index 4bf6043d5d..b8f77cb5eb 100644
|
||||||
|
--- a/crypto/blockpriv.h
|
||||||
|
+++ b/crypto/blockpriv.h
|
||||||
|
@@ -59,7 +59,6 @@ struct QCryptoBlockDriver {
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
int (*create)(QCryptoBlock *block,
|
||||||
|
diff --git a/include/crypto/block.h b/include/crypto/block.h
|
||||||
|
index 92e823c9f2..5b5d039800 100644
|
||||||
|
--- a/include/crypto/block.h
|
||||||
|
+++ b/include/crypto/block.h
|
||||||
|
@@ -76,7 +76,6 @@ typedef enum {
|
||||||
|
* @readfunc: callback for reading data from the volume
|
||||||
|
* @opaque: data to pass to @readfunc
|
||||||
|
* @flags: bitmask of QCryptoBlockOpenFlags values
|
||||||
|
- * @n_threads: allow concurrent I/O from up to @n_threads threads
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Create a new block encryption object for an existing
|
||||||
|
@@ -113,7 +112,6 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
|
||||||
|
QCryptoBlockReadFunc readfunc,
|
||||||
|
void *opaque,
|
||||||
|
unsigned int flags,
|
||||||
|
- size_t n_threads,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
diff --git a/tests/unit/test-crypto-block.c b/tests/unit/test-crypto-block.c
|
||||||
|
index 6cfc817a92..42cfab6067 100644
|
||||||
|
--- a/tests/unit/test-crypto-block.c
|
||||||
|
+++ b/tests/unit/test-crypto-block.c
|
||||||
|
@@ -303,7 +303,6 @@ static void test_block(gconstpointer opaque)
|
||||||
|
test_block_read_func,
|
||||||
|
&header,
|
||||||
|
0,
|
||||||
|
- 1,
|
||||||
|
NULL);
|
||||||
|
g_assert(blk == NULL);
|
||||||
|
|
||||||
|
@@ -312,7 +311,6 @@ static void test_block(gconstpointer opaque)
|
||||||
|
test_block_read_func,
|
||||||
|
&header,
|
||||||
|
QCRYPTO_BLOCK_OPEN_NO_IO,
|
||||||
|
- 1,
|
||||||
|
&error_abort);
|
||||||
|
|
||||||
|
g_assert(qcrypto_block_get_cipher(blk) == NULL);
|
||||||
|
@@ -327,7 +325,6 @@ static void test_block(gconstpointer opaque)
|
||||||
|
test_block_read_func,
|
||||||
|
&header,
|
||||||
|
0,
|
||||||
|
- 1,
|
||||||
|
&error_abort);
|
||||||
|
g_assert(blk);
|
||||||
|
|
||||||
|
@@ -384,7 +381,6 @@ test_luks_bad_header(gconstpointer data)
|
||||||
|
test_block_read_func,
|
||||||
|
&buf,
|
||||||
|
0,
|
||||||
|
- 1,
|
||||||
|
&err);
|
||||||
|
g_assert(!blk);
|
||||||
|
g_assert(err);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,75 +0,0 @@
|
|||||||
From ac9dc8ea241ef6d3a0447d696620d4d4053b71bf Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Mon, 4 Dec 2023 11:42:59 -0500
|
|
||||||
Subject: [PATCH 080/101] dma-helpers: don't lock AioContext in dma_blk_cb()
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [11/26] a8580463ba6aee4ca248c0b947b9e72bd9e87aab (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Commit abfcd2760b3e ("dma-helpers: prevent dma_blk_cb() vs
|
|
||||||
dma_aio_cancel() race") acquired the AioContext lock inside dma_blk_cb()
|
|
||||||
to avoid a race with scsi_device_purge_requests() running in the main
|
|
||||||
loop thread.
|
|
||||||
|
|
||||||
The SCSI code no longer calls dma_aio_cancel() from the main loop thread
|
|
||||||
while I/O is running in the IOThread AioContext. Therefore it is no
|
|
||||||
longer necessary to take this lock to protect DMAAIOCB fields. The
|
|
||||||
->cb() function also does not require the lock because blk_aio_*() and
|
|
||||||
friends do not need the AioContext lock.
|
|
||||||
|
|
||||||
Both hw/ide/core.c and hw/ide/macio.c also call dma_blk_io() but don't
|
|
||||||
rely on it taking the AioContext lock, so this change is safe.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Message-ID: <20231204164259.1515217-5-stefanha@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
system/dma-helpers.c | 7 ++-----
|
|
||||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/system/dma-helpers.c b/system/dma-helpers.c
|
|
||||||
index 36211acc7e..528117f256 100644
|
|
||||||
--- a/system/dma-helpers.c
|
|
||||||
+++ b/system/dma-helpers.c
|
|
||||||
@@ -119,13 +119,12 @@ static void dma_blk_cb(void *opaque, int ret)
|
|
||||||
|
|
||||||
trace_dma_blk_cb(dbs, ret);
|
|
||||||
|
|
||||||
- aio_context_acquire(ctx);
|
|
||||||
dbs->acb = NULL;
|
|
||||||
dbs->offset += dbs->iov.size;
|
|
||||||
|
|
||||||
if (dbs->sg_cur_index == dbs->sg->nsg || ret < 0) {
|
|
||||||
dma_complete(dbs, ret);
|
|
||||||
- goto out;
|
|
||||||
+ return;
|
|
||||||
}
|
|
||||||
dma_blk_unmap(dbs);
|
|
||||||
|
|
||||||
@@ -168,7 +167,7 @@ static void dma_blk_cb(void *opaque, int ret)
|
|
||||||
trace_dma_map_wait(dbs);
|
|
||||||
dbs->bh = aio_bh_new(ctx, reschedule_dma, dbs);
|
|
||||||
cpu_register_map_client(dbs->bh);
|
|
||||||
- goto out;
|
|
||||||
+ return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!QEMU_IS_ALIGNED(dbs->iov.size, dbs->align)) {
|
|
||||||
@@ -179,8 +178,6 @@ static void dma_blk_cb(void *opaque, int ret)
|
|
||||||
dbs->acb = dbs->io_func(dbs->offset, &dbs->iov,
|
|
||||||
dma_blk_cb, dbs, dbs->io_func_opaque);
|
|
||||||
assert(dbs->acb);
|
|
||||||
-out:
|
|
||||||
- aio_context_release(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dma_aio_cancel(BlockAIOCB *acb)
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,228 +0,0 @@
|
|||||||
From 71aa0219f7c84cbf175eb2a091d48d5fd5daa40b Mon Sep 17 00:00:00 2001
|
|
||||||
From: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Date: Tue, 21 Nov 2023 16:44:26 +0800
|
|
||||||
Subject: [PATCH 047/101] docs/devel: Add VFIO iommufd backend documentation
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [46/67] 6cf49d00e87788f894d690a985bb6798eae24505 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Suggested-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
|
|
||||||
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
(cherry picked from commit 98dad2b01931f6064c6c4b48ca3c2a1d9f542cd8)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
MAINTAINERS | 1 +
|
|
||||||
docs/devel/index-internals.rst | 1 +
|
|
||||||
docs/devel/vfio-iommufd.rst | 166 +++++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 168 insertions(+)
|
|
||||||
create mode 100644 docs/devel/vfio-iommufd.rst
|
|
||||||
|
|
||||||
diff --git a/MAINTAINERS b/MAINTAINERS
|
|
||||||
index ca70bb4e64..0ddb20a35f 100644
|
|
||||||
--- a/MAINTAINERS
|
|
||||||
+++ b/MAINTAINERS
|
|
||||||
@@ -2176,6 +2176,7 @@ F: backends/iommufd.c
|
|
||||||
F: include/sysemu/iommufd.h
|
|
||||||
F: include/qemu/chardev_open.h
|
|
||||||
F: util/chardev_open.c
|
|
||||||
+F: docs/devel/vfio-iommufd.rst
|
|
||||||
|
|
||||||
vhost
|
|
||||||
M: Michael S. Tsirkin <mst@redhat.com>
|
|
||||||
diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst
|
|
||||||
index 6f81df92bc..3def4a138b 100644
|
|
||||||
--- a/docs/devel/index-internals.rst
|
|
||||||
+++ b/docs/devel/index-internals.rst
|
|
||||||
@@ -18,5 +18,6 @@ Details about QEMU's various subsystems including how to add features to them.
|
|
||||||
s390-dasd-ipl
|
|
||||||
tracing
|
|
||||||
vfio-migration
|
|
||||||
+ vfio-iommufd
|
|
||||||
writing-monitor-commands
|
|
||||||
virtio-backends
|
|
||||||
diff --git a/docs/devel/vfio-iommufd.rst b/docs/devel/vfio-iommufd.rst
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000000..3d1c11f175
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/docs/devel/vfio-iommufd.rst
|
|
||||||
@@ -0,0 +1,166 @@
|
|
||||||
+===============================
|
|
||||||
+IOMMUFD BACKEND usage with VFIO
|
|
||||||
+===============================
|
|
||||||
+
|
|
||||||
+(Same meaning for backend/container/BE)
|
|
||||||
+
|
|
||||||
+With the introduction of iommufd, the Linux kernel provides a generic
|
|
||||||
+interface for user space drivers to propagate their DMA mappings to kernel
|
|
||||||
+for assigned devices. While the legacy kernel interface is group-centric,
|
|
||||||
+the new iommufd interface is device-centric, relying on device fd and iommufd.
|
|
||||||
+
|
|
||||||
+To support both interfaces in the QEMU VFIO device, introduce a base container
|
|
||||||
+to abstract the common part of VFIO legacy and iommufd container. So that the
|
|
||||||
+generic VFIO code can use either container.
|
|
||||||
+
|
|
||||||
+The base container implements generic functions such as memory_listener and
|
|
||||||
+address space management whereas the derived container implements callbacks
|
|
||||||
+specific to either legacy or iommufd. Each container has its own way to setup
|
|
||||||
+secure context and dma management interface. The below diagram shows how it
|
|
||||||
+looks like with both containers.
|
|
||||||
+
|
|
||||||
+::
|
|
||||||
+
|
|
||||||
+ VFIO AddressSpace/Memory
|
|
||||||
+ +-------+ +----------+ +-----+ +-----+
|
|
||||||
+ | pci | | platform | | ap | | ccw |
|
|
||||||
+ +---+---+ +----+-----+ +--+--+ +--+--+ +----------------------+
|
|
||||||
+ | | | | | AddressSpace |
|
|
||||||
+ | | | | +------------+---------+
|
|
||||||
+ +---V-----------V-----------V--------V----+ /
|
|
||||||
+ | VFIOAddressSpace | <------------+
|
|
||||||
+ | | | MemoryListener
|
|
||||||
+ | VFIOContainerBase list |
|
|
||||||
+ +-------+----------------------------+----+
|
|
||||||
+ | |
|
|
||||||
+ | |
|
|
||||||
+ +-------V------+ +--------V----------+
|
|
||||||
+ | iommufd | | vfio legacy |
|
|
||||||
+ | container | | container |
|
|
||||||
+ +-------+------+ +--------+----------+
|
|
||||||
+ | |
|
|
||||||
+ | /dev/iommu | /dev/vfio/vfio
|
|
||||||
+ | /dev/vfio/devices/vfioX | /dev/vfio/$group_id
|
|
||||||
+ Userspace | |
|
|
||||||
+ ============+============================+===========================
|
|
||||||
+ Kernel | device fd |
|
|
||||||
+ +---------------+ | group/container fd
|
|
||||||
+ | (BIND_IOMMUFD | | (SET_CONTAINER/SET_IOMMU)
|
|
||||||
+ | ATTACH_IOAS) | | device fd
|
|
||||||
+ | | |
|
|
||||||
+ | +-------V------------V-----------------+
|
|
||||||
+ iommufd | | vfio |
|
|
||||||
+ (map/unmap | +---------+--------------------+-------+
|
|
||||||
+ ioas_copy) | | | map/unmap
|
|
||||||
+ | | |
|
|
||||||
+ +------V------+ +-----V------+ +------V--------+
|
|
||||||
+ | iommfd core | | device | | vfio iommu |
|
|
||||||
+ +-------------+ +------------+ +---------------+
|
|
||||||
+
|
|
||||||
+* Secure Context setup
|
|
||||||
+
|
|
||||||
+ - iommufd BE: uses device fd and iommufd to setup secure context
|
|
||||||
+ (bind_iommufd, attach_ioas)
|
|
||||||
+ - vfio legacy BE: uses group fd and container fd to setup secure context
|
|
||||||
+ (set_container, set_iommu)
|
|
||||||
+
|
|
||||||
+* Device access
|
|
||||||
+
|
|
||||||
+ - iommufd BE: device fd is opened through ``/dev/vfio/devices/vfioX``
|
|
||||||
+ - vfio legacy BE: device fd is retrieved from group fd ioctl
|
|
||||||
+
|
|
||||||
+* DMA Mapping flow
|
|
||||||
+
|
|
||||||
+ 1. VFIOAddressSpace receives MemoryRegion add/del via MemoryListener
|
|
||||||
+ 2. VFIO populates DMA map/unmap via the container BEs
|
|
||||||
+ * iommufd BE: uses iommufd
|
|
||||||
+ * vfio legacy BE: uses container fd
|
|
||||||
+
|
|
||||||
+Example configuration
|
|
||||||
+=====================
|
|
||||||
+
|
|
||||||
+Step 1: configure the host device
|
|
||||||
+---------------------------------
|
|
||||||
+
|
|
||||||
+It's exactly same as the VFIO device with legacy VFIO container.
|
|
||||||
+
|
|
||||||
+Step 2: configure QEMU
|
|
||||||
+----------------------
|
|
||||||
+
|
|
||||||
+Interactions with the ``/dev/iommu`` are abstracted by a new iommufd
|
|
||||||
+object (compiled in with the ``CONFIG_IOMMUFD`` option).
|
|
||||||
+
|
|
||||||
+Any QEMU device (e.g. VFIO device) wishing to use ``/dev/iommu`` must
|
|
||||||
+be linked with an iommufd object. It gets a new optional property
|
|
||||||
+named iommufd which allows to pass an iommufd object. Take ``vfio-pci``
|
|
||||||
+device for example:
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ -object iommufd,id=iommufd0
|
|
||||||
+ -device vfio-pci,host=0000:02:00.0,iommufd=iommufd0
|
|
||||||
+
|
|
||||||
+Note the ``/dev/iommu`` and VFIO cdev can be externally opened by a
|
|
||||||
+management layer. In such a case the fd is passed, the fd supports a
|
|
||||||
+string naming the fd or a number, for example:
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ -object iommufd,id=iommufd0,fd=22
|
|
||||||
+ -device vfio-pci,iommufd=iommufd0,fd=23
|
|
||||||
+
|
|
||||||
+If the ``fd`` property is not passed, the fd is opened by QEMU.
|
|
||||||
+
|
|
||||||
+If no ``iommufd`` object is passed to the ``vfio-pci`` device, iommufd
|
|
||||||
+is not used and the user gets the behavior based on the legacy VFIO
|
|
||||||
+container:
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ -device vfio-pci,host=0000:02:00.0
|
|
||||||
+
|
|
||||||
+Supported platform
|
|
||||||
+==================
|
|
||||||
+
|
|
||||||
+Supports x86, ARM and s390x currently.
|
|
||||||
+
|
|
||||||
+Caveats
|
|
||||||
+=======
|
|
||||||
+
|
|
||||||
+Dirty page sync
|
|
||||||
+---------------
|
|
||||||
+
|
|
||||||
+Dirty page sync with iommufd backend is unsupported yet, live migration is
|
|
||||||
+disabled by default. But it can be force enabled like below, low efficient
|
|
||||||
+though.
|
|
||||||
+
|
|
||||||
+.. code-block:: bash
|
|
||||||
+
|
|
||||||
+ -object iommufd,id=iommufd0
|
|
||||||
+ -device vfio-pci,host=0000:02:00.0,iommufd=iommufd0,enable-migration=on
|
|
||||||
+
|
|
||||||
+P2P DMA
|
|
||||||
+-------
|
|
||||||
+
|
|
||||||
+PCI p2p DMA is unsupported as IOMMUFD doesn't support mapping hardware PCI
|
|
||||||
+BAR region yet. Below warning shows for assigned PCI device, it's not a bug.
|
|
||||||
+
|
|
||||||
+.. code-block:: none
|
|
||||||
+
|
|
||||||
+ qemu-system-x86_64: warning: IOMMU_IOAS_MAP failed: Bad address, PCI BAR?
|
|
||||||
+ qemu-system-x86_64: vfio_container_dma_map(0x560cb6cb1620, 0xe000000021000, 0x3000, 0x7f32ed55c000) = -14 (Bad address)
|
|
||||||
+
|
|
||||||
+FD passing with mdev
|
|
||||||
+--------------------
|
|
||||||
+
|
|
||||||
+``vfio-pci`` device checks sysfsdev property to decide if backend is a mdev.
|
|
||||||
+If FD passing is used, there is no way to know that and the mdev is treated
|
|
||||||
+like a real PCI device. There is an error as below if user wants to enable
|
|
||||||
+RAM discarding for mdev.
|
|
||||||
+
|
|
||||||
+.. code-block:: none
|
|
||||||
+
|
|
||||||
+ qemu-system-x86_64: -device vfio-pci,iommufd=iommufd0,x-balloon-allowed=on,fd=9: vfio VFIO_FD9: x-balloon-allowed only potentially compatible with mdev devices
|
|
||||||
+
|
|
||||||
+``vfio-ap`` and ``vfio-ccw`` devices don't have same issue as their backend
|
|
||||||
+devices are always mdev and RAM discarding is force enabled.
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
|||||||
From fc69df3a70bed5722643cc16828ca20beae3a20d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Date: Tue, 5 Dec 2023 13:20:08 -0500
|
|
||||||
Subject: [PATCH 091/101] docs: remove AioContext lock from IOThread docs
|
|
||||||
|
|
||||||
RH-Author: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
RH-MergeRequest: 214: Remove AioContext lock
|
|
||||||
RH-Jira: RHEL-15965
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
RH-Commit: [22/26] ab89cda483e74ded983d26e1c6e50217405e0a55 (kmwolf/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Encourage the use of locking primitives and stop mentioning the
|
|
||||||
AioContext lock since it is being removed.
|
|
||||||
|
|
||||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
|
||||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
|
||||||
Message-ID: <20231205182011.1976568-12-stefanha@redhat.com>
|
|
||||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
|
||||||
---
|
|
||||||
docs/devel/multiple-iothreads.txt | 47 +++++++++++--------------------
|
|
||||||
1 file changed, 16 insertions(+), 31 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/docs/devel/multiple-iothreads.txt b/docs/devel/multiple-iothreads.txt
|
|
||||||
index a3e949f6b3..4865196bde 100644
|
|
||||||
--- a/docs/devel/multiple-iothreads.txt
|
|
||||||
+++ b/docs/devel/multiple-iothreads.txt
|
|
||||||
@@ -88,27 +88,18 @@ loop, depending on which AioContext instance the caller passes in.
|
|
||||||
|
|
||||||
How to synchronize with an IOThread
|
|
||||||
-----------------------------------
|
|
||||||
-AioContext is not thread-safe so some rules must be followed when using file
|
|
||||||
-descriptors, event notifiers, timers, or BHs across threads:
|
|
||||||
+Variables that can be accessed by multiple threads require some form of
|
|
||||||
+synchronization such as qemu_mutex_lock(), rcu_read_lock(), etc.
|
|
||||||
|
|
||||||
-1. AioContext functions can always be called safely. They handle their
|
|
||||||
-own locking internally.
|
|
||||||
-
|
|
||||||
-2. Other threads wishing to access the AioContext must use
|
|
||||||
-aio_context_acquire()/aio_context_release() for mutual exclusion. Once the
|
|
||||||
-context is acquired no other thread can access it or run event loop iterations
|
|
||||||
-in this AioContext.
|
|
||||||
-
|
|
||||||
-Legacy code sometimes nests aio_context_acquire()/aio_context_release() calls.
|
|
||||||
-Do not use nesting anymore, it is incompatible with the BDRV_POLL_WHILE() macro
|
|
||||||
-used in the block layer and can lead to hangs.
|
|
||||||
-
|
|
||||||
-There is currently no lock ordering rule if a thread needs to acquire multiple
|
|
||||||
-AioContexts simultaneously. Therefore, it is only safe for code holding the
|
|
||||||
-QEMU global mutex to acquire other AioContexts.
|
|
||||||
+AioContext functions like aio_set_fd_handler(), aio_set_event_notifier(),
|
|
||||||
+aio_bh_new(), and aio_timer_new() are thread-safe. They can be used to trigger
|
|
||||||
+activity in an IOThread.
|
|
||||||
|
|
||||||
Side note: the best way to schedule a function call across threads is to call
|
|
||||||
-aio_bh_schedule_oneshot(). No acquire/release or locking is needed.
|
|
||||||
+aio_bh_schedule_oneshot().
|
|
||||||
+
|
|
||||||
+The main loop thread can wait synchronously for a condition using
|
|
||||||
+AIO_WAIT_WHILE().
|
|
||||||
|
|
||||||
AioContext and the block layer
|
|
||||||
------------------------------
|
|
||||||
@@ -124,22 +115,16 @@ Block layer code must therefore expect to run in an IOThread and avoid using
|
|
||||||
old APIs that implicitly use the main loop. See the "How to program for
|
|
||||||
IOThreads" above for information on how to do that.
|
|
||||||
|
|
||||||
-If main loop code such as a QMP function wishes to access a BlockDriverState
|
|
||||||
-it must first call aio_context_acquire(bdrv_get_aio_context(bs)) to ensure
|
|
||||||
-that callbacks in the IOThread do not run in parallel.
|
|
||||||
-
|
|
||||||
Code running in the monitor typically needs to ensure that past
|
|
||||||
requests from the guest are completed. When a block device is running
|
|
||||||
in an IOThread, the IOThread can also process requests from the guest
|
|
||||||
(via ioeventfd). To achieve both objects, wrap the code between
|
|
||||||
bdrv_drained_begin() and bdrv_drained_end(), thus creating a "drained
|
|
||||||
-section". The functions must be called between aio_context_acquire()
|
|
||||||
-and aio_context_release(). You can freely release and re-acquire the
|
|
||||||
-AioContext within a drained section.
|
|
||||||
-
|
|
||||||
-Long-running jobs (usually in the form of coroutines) are best scheduled in
|
|
||||||
-the BlockDriverState's AioContext to avoid the need to acquire/release around
|
|
||||||
-each bdrv_*() call. The functions bdrv_add/remove_aio_context_notifier,
|
|
||||||
-or alternatively blk_add/remove_aio_context_notifier if you use BlockBackends,
|
|
||||||
-can be used to get a notification whenever bdrv_try_change_aio_context() moves a
|
|
||||||
+section".
|
|
||||||
+
|
|
||||||
+Long-running jobs (usually in the form of coroutines) are often scheduled in
|
|
||||||
+the BlockDriverState's AioContext. The functions
|
|
||||||
+bdrv_add/remove_aio_context_notifier, or alternatively
|
|
||||||
+blk_add/remove_aio_context_notifier if you use BlockBackends, can be used to
|
|
||||||
+get a notification whenever bdrv_try_change_aio_context() moves a
|
|
||||||
BlockDriverState to a different AioContext.
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,94 +0,0 @@
|
|||||||
From a5b4eec5f456b1ca3fe753e1d76f96cf3f8914ef Mon Sep 17 00:00:00 2001
|
|
||||||
From: David Hildenbrand <david@redhat.com>
|
|
||||||
Date: Wed, 17 Jan 2024 14:55:53 +0100
|
|
||||||
Subject: [PATCH 01/22] hv-balloon: use get_min_alignment() to express 32 GiB
|
|
||||||
alignment
|
|
||||||
|
|
||||||
RH-Author: David Hildenbrand <david@redhat.com>
|
|
||||||
RH-MergeRequest: 221: memory-device: reintroduce memory region size check
|
|
||||||
RH-Jira: RHEL-20341
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
|
|
||||||
RH-Commit: [1/2] cbe092fe549552928270892253b31cd8fe199825
|
|
||||||
|
|
||||||
https://issues.redhat.com/browse/RHEL-20341
|
|
||||||
|
|
||||||
Let's implement the get_min_alignment() callback for memory devices, and
|
|
||||||
copy for the device memory region the alignment of the host memory
|
|
||||||
region. This mimics what virtio-mem does, and allows for re-introducing
|
|
||||||
proper alignment checks for the memory region size (where we don't care
|
|
||||||
about additional device requirements) in memory device core.
|
|
||||||
|
|
||||||
Message-ID: <20240117135554.787344-2-david@redhat.com>
|
|
||||||
Reviewed-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
|
|
||||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
|
||||||
(cherry picked from commit f77c5f38f49c71bc14cf1019ac92b0b95f572414)
|
|
||||||
Signed-off-by: David Hildenbrand <david@redhat.com>
|
|
||||||
---
|
|
||||||
hw/hyperv/hv-balloon.c | 37 +++++++++++++++++++++----------------
|
|
||||||
1 file changed, 21 insertions(+), 16 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/hyperv/hv-balloon.c b/hw/hyperv/hv-balloon.c
|
|
||||||
index 66f297c1d7..0829c495b0 100644
|
|
||||||
--- a/hw/hyperv/hv-balloon.c
|
|
||||||
+++ b/hw/hyperv/hv-balloon.c
|
|
||||||
@@ -1476,22 +1476,7 @@ static void hv_balloon_ensure_mr(HvBalloon *balloon)
|
|
||||||
balloon->mr = g_new0(MemoryRegion, 1);
|
|
||||||
memory_region_init(balloon->mr, OBJECT(balloon), TYPE_HV_BALLOON,
|
|
||||||
memory_region_size(hostmem_mr));
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * The VM can indicate an alignment up to 32 GiB. Memory device core can
|
|
||||||
- * usually only handle/guarantee 1 GiB alignment. The user will have to
|
|
||||||
- * specify a larger maxmem eventually.
|
|
||||||
- *
|
|
||||||
- * The memory device core will warn the user in case maxmem might have to be
|
|
||||||
- * increased and will fail plugging the device if there is not sufficient
|
|
||||||
- * space after alignment.
|
|
||||||
- *
|
|
||||||
- * TODO: we could do the alignment ourselves in a slightly bigger region.
|
|
||||||
- * But this feels better, although the warning might be annoying. Maybe
|
|
||||||
- * we can optimize that in the future (e.g., with such a device on the
|
|
||||||
- * cmdline place/size the device memory region differently.
|
|
||||||
- */
|
|
||||||
- balloon->mr->align = MAX(32 * GiB, memory_region_get_alignment(hostmem_mr));
|
|
||||||
+ balloon->mr->align = memory_region_get_alignment(hostmem_mr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hv_balloon_free_mr(HvBalloon *balloon)
|
|
||||||
@@ -1653,6 +1638,25 @@ static MemoryRegion *hv_balloon_md_get_memory_region(MemoryDeviceState *md,
|
|
||||||
return balloon->mr;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static uint64_t hv_balloon_md_get_min_alignment(const MemoryDeviceState *md)
|
|
||||||
+{
|
|
||||||
+ /*
|
|
||||||
+ * The VM can indicate an alignment up to 32 GiB. Memory device core can
|
|
||||||
+ * usually only handle/guarantee 1 GiB alignment. The user will have to
|
|
||||||
+ * specify a larger maxmem eventually.
|
|
||||||
+ *
|
|
||||||
+ * The memory device core will warn the user in case maxmem might have to be
|
|
||||||
+ * increased and will fail plugging the device if there is not sufficient
|
|
||||||
+ * space after alignment.
|
|
||||||
+ *
|
|
||||||
+ * TODO: we could do the alignment ourselves in a slightly bigger region.
|
|
||||||
+ * But this feels better, although the warning might be annoying. Maybe
|
|
||||||
+ * we can optimize that in the future (e.g., with such a device on the
|
|
||||||
+ * cmdline place/size the device memory region differently.
|
|
||||||
+ */
|
|
||||||
+ return 32 * GiB;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void hv_balloon_md_fill_device_info(const MemoryDeviceState *md,
|
|
||||||
MemoryDeviceInfo *info)
|
|
||||||
{
|
|
||||||
@@ -1765,5 +1769,6 @@ static void hv_balloon_class_init(ObjectClass *klass, void *data)
|
|
||||||
mdc->get_memory_region = hv_balloon_md_get_memory_region;
|
|
||||||
mdc->decide_memslots = hv_balloon_decide_memslots;
|
|
||||||
mdc->get_memslots = hv_balloon_get_memslots;
|
|
||||||
+ mdc->get_min_alignment = hv_balloon_md_get_min_alignment;
|
|
||||||
mdc->fill_device_info = hv_balloon_md_fill_device_info;
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
From ceaee9c4372bbdc4196cb6808515047388f7aa26 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
|
|
||||||
Date: Tue, 21 Nov 2023 16:44:18 +0800
|
|
||||||
Subject: [PATCH 039/101] hw/arm: Activate IOMMUFD for virt machines
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [38/67] 0a059ae661616e95eb8455e17f35774495cae8e7 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Reviewed-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Tested-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
(cherry picked from commit 0970238343af45a8b547695bfc22f18d4eb7da7e)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
hw/arm/Kconfig | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
|
|
||||||
index 3ada335a24..660f49db49 100644
|
|
||||||
--- a/hw/arm/Kconfig
|
|
||||||
+++ b/hw/arm/Kconfig
|
|
||||||
@@ -8,6 +8,7 @@ config ARM_VIRT
|
|
||||||
imply TPM_TIS_SYSBUS
|
|
||||||
imply TPM_TIS_I2C
|
|
||||||
imply NVDIMM
|
|
||||||
+ imply IOMMUFD
|
|
||||||
select ARM_GIC
|
|
||||||
select ACPI
|
|
||||||
select ARM_SMMUV3
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
|||||||
From e670722b9a6460d41497688d820d5a9a9b51d8e9 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gavin Shan <gshan@redhat.com>
|
|
||||||
Date: Tue, 9 Jan 2024 11:36:42 +1000
|
|
||||||
Subject: [PATCH 001/101] hw/arm/virt: Add properties to disable high memory
|
|
||||||
regions
|
|
||||||
|
|
||||||
RH-Author: Gavin Shan <gshan@redhat.com>
|
|
||||||
RH-MergeRequest: 210: hw/arm/virt: Add properties to disable high memory regions
|
|
||||||
RH-Jira: RHEL-19738
|
|
||||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
||||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-Commit: [1/1] 4097ba5133a67126e30b84202cb40df4e019c5f4
|
|
||||||
|
|
||||||
Upstream: RHEL-only
|
|
||||||
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=57927352
|
|
||||||
|
|
||||||
There are 3 high memory regions for GICv3 or GICv4 redistributor, PCI
|
|
||||||
ECAM and PCI MMIO. Each of them has a property introduced by upstream
|
|
||||||
commit 6a48c64eec ("hw/arm/virt: Add properties to disable high memory
|
|
||||||
regions") so that the corresponding high memory region can be disabled.
|
|
||||||
|
|
||||||
It's notable that another property ("compact-highmem") introduced by
|
|
||||||
upstream commit f40408a9fe ("hw/arm/virt: Add 'compact-highmem' property")
|
|
||||||
so that the compact high memory region layout during assignment can be
|
|
||||||
disabled, compatible to the old machine types. However, we don't have
|
|
||||||
the compatible issue since the compact high memory region layout is
|
|
||||||
always kept as disabled until RHEL9.2.0 machine type and onwards.
|
|
||||||
|
|
||||||
Expose those 3 properties: "highmem-redists", "highmem-ecam" and
|
|
||||||
"highmem-mmio". The property "compact-highmem" is kept as hidden.
|
|
||||||
|
|
||||||
Signed-off-by: Gavin Shan <gshan@redhat.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 24 +++++++++++++++++++++++-
|
|
||||||
1 file changed, 23 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 5cab00b4cd..60f117f0d2 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -2456,6 +2456,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)
|
|
||||||
{
|
|
||||||
@@ -2498,7 +2499,6 @@ static void virt_set_highmem_mmio(Object *obj, bool value, Error **errp)
|
|
||||||
|
|
||||||
vms->highmem_mmio = value;
|
|
||||||
}
|
|
||||||
-#endif /* disabled for RHEL */
|
|
||||||
|
|
||||||
static bool virt_get_its(Object *obj, Error **errp)
|
|
||||||
{
|
|
||||||
@@ -3521,6 +3521,28 @@ static void rhel_machine_class_init(ObjectClass *oc, void *data)
|
|
||||||
"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",
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,120 @@
|
|||||||
|
From 41c4083269ec772b406c6c57b496ca2011f928c7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||||
|
Date: Tue, 9 Jul 2024 23:08:59 -0400
|
||||||
|
Subject: [PATCH 2/2] hw/arm/virt: Avoid unexpected warning from Linux guest on
|
||||||
|
host with Fujitsu CPUs
|
||||||
|
|
||||||
|
RH-Author: zhenyzha <None>
|
||||||
|
RH-MergeRequest: 256: hw/arm/virt: Avoid unexpected warning from Linux guest on host with Fujitsu CPUs
|
||||||
|
RH-Jira: RHEL-39936
|
||||||
|
RH-Acked-by: Gavin Shan <gshan@redhat.com>
|
||||||
|
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
||||||
|
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
||||||
|
RH-Commit: [1/1] fdf156fd05b219a06e2e2ca409fff0f728c1e2cf (zhenyzha/qemu-kvm)
|
||||||
|
|
||||||
|
JIRA: https://issues.redhat.com/browse/RHEL-39936
|
||||||
|
|
||||||
|
Multiple warning messages and corresponding backtraces are observed when Linux
|
||||||
|
guest is booted on the host with Fujitsu CPUs. One of them is shown as below.
|
||||||
|
|
||||||
|
[ 0.032443] ------------[ cut here ]------------
|
||||||
|
[ 0.032446] uart-pl011 9000000.pl011: ARCH_DMA_MINALIGN smaller than
|
||||||
|
CTR_EL0.CWG (128 < 256)
|
||||||
|
[ 0.032454] WARNING: CPU: 0 PID: 1 at arch/arm64/mm/dma-mapping.c:54
|
||||||
|
arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032470] Modules linked in:
|
||||||
|
[ 0.032475] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0-452.el9.aarch64
|
||||||
|
[ 0.032481] Hardware name: linux,dummy-virt (DT)
|
||||||
|
[ 0.032484] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
|
||||||
|
[ 0.032490] pc : arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032496] lr : arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032501] sp : ffff80008003b860
|
||||||
|
[ 0.032503] x29: ffff80008003b860 x28: 0000000000000000 x27: ffffaae4b949049c
|
||||||
|
[ 0.032510] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
|
||||||
|
[ 0.032517] x23: 0000000000000100 x22: 0000000000000000 x21: 0000000000000000
|
||||||
|
[ 0.032523] x20: 0000000100000000 x19: ffff2f06c02ea400 x18: ffffffffffffffff
|
||||||
|
[ 0.032529] x17: 00000000208a5f76 x16: 000000006589dbcb x15: ffffaae4ba071c89
|
||||||
|
[ 0.032535] x14: 0000000000000000 x13: ffffaae4ba071c84 x12: 455f525443206e61
|
||||||
|
[ 0.032541] x11: 68742072656c6c61 x10: 0000000000000029 x9 : ffffaae4b7d21da4
|
||||||
|
[ 0.032547] x8 : 0000000000000029 x7 : 4c414e494d5f414d x6 : 0000000000000029
|
||||||
|
[ 0.032553] x5 : 000000000000000f x4 : ffffaae4b9617a00 x3 : 0000000000000001
|
||||||
|
[ 0.032558] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff2f06c029be40
|
||||||
|
[ 0.032564] Call trace:
|
||||||
|
[ 0.032566] arch_setup_dma_ops+0xbc/0xcc
|
||||||
|
[ 0.032572] of_dma_configure_id+0x138/0x300
|
||||||
|
[ 0.032591] amba_dma_configure+0x34/0xc0
|
||||||
|
[ 0.032600] really_probe+0x78/0x3dc
|
||||||
|
[ 0.032614] __driver_probe_device+0x108/0x160
|
||||||
|
[ 0.032619] driver_probe_device+0x44/0x114
|
||||||
|
[ 0.032624] __device_attach_driver+0xb8/0x14c
|
||||||
|
[ 0.032629] bus_for_each_drv+0x88/0xe4
|
||||||
|
[ 0.032634] __device_attach+0xb0/0x1e0
|
||||||
|
[ 0.032638] device_initial_probe+0x18/0x20
|
||||||
|
[ 0.032643] bus_probe_device+0xa8/0xb0
|
||||||
|
[ 0.032648] device_add+0x4b4/0x6c0
|
||||||
|
[ 0.032652] amba_device_try_add.part.0+0x48/0x360
|
||||||
|
[ 0.032657] amba_device_add+0x104/0x144
|
||||||
|
[ 0.032662] of_amba_device_create.isra.0+0x100/0x1c4
|
||||||
|
[ 0.032666] of_platform_bus_create+0x294/0x35c
|
||||||
|
[ 0.032669] of_platform_populate+0x5c/0x150
|
||||||
|
[ 0.032672] of_platform_default_populate_init+0xd0/0xec
|
||||||
|
[ 0.032697] do_one_initcall+0x4c/0x2e0
|
||||||
|
[ 0.032701] do_initcalls+0x100/0x13c
|
||||||
|
[ 0.032707] kernel_init_freeable+0x1c8/0x21c
|
||||||
|
[ 0.032712] kernel_init+0x28/0x140
|
||||||
|
[ 0.032731] ret_from_fork+0x10/0x20
|
||||||
|
[ 0.032735] ---[ end trace 0000000000000000 ]---
|
||||||
|
|
||||||
|
In Linux, a check is applied to every device which is exposed through
|
||||||
|
device-tree node. The warning message is raised when the device isn't
|
||||||
|
DMA coherent and the cache line size is larger than ARCH_DMA_MINALIGN
|
||||||
|
(128 bytes). The cache line is sorted from CTR_EL0[CWG], which corresponds
|
||||||
|
to 256 bytes on the guest CPUs. The DMA coherent capability is claimed
|
||||||
|
through 'dma-coherent' in their device-tree nodes or parent nodes.
|
||||||
|
This happens even when the device doesn't implement or use DMA at all,
|
||||||
|
for legacy reasons.
|
||||||
|
|
||||||
|
Fix the issue by adding 'dma-coherent' property to the device-tree root
|
||||||
|
node, meaning all devices are capable of DMA coherent by default.
|
||||||
|
This both suppresses the spurious kernel warnings and also guards
|
||||||
|
against possible future QEMU bugs where we add a DMA-capable device
|
||||||
|
and forget to mark it as dma-coherent.
|
||||||
|
|
||||||
|
Signed-off-by: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||||
|
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||||
|
Reviewed-by: Donald Dutile <ddutile@redhat.com
|
||||||
|
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||||
|
Message-id: 20240612020506.307793-1-zhenyzha@redhat.com
|
||||||
|
[PMM: tweaked commit message]
|
||||||
|
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||||
|
(cherry picked from commit dda533087ad5559674ff486e7031c88dc01e0abd)
|
||||||
|
Signed-off-by: Zhenyu Zhang <zhenyzha@redhat.com>
|
||||||
|
---
|
||||||
|
hw/arm/virt.c | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||||
|
index 3f0496cdb9..6ece67f11d 100644
|
||||||
|
--- a/hw/arm/virt.c
|
||||||
|
+++ b/hw/arm/virt.c
|
||||||
|
@@ -330,6 +330,17 @@ static void create_fdt(VirtMachineState *vms)
|
||||||
|
qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2);
|
||||||
|
qemu_fdt_setprop_string(fdt, "/", "model", "linux,dummy-virt");
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * For QEMU, all DMA is coherent. Advertising this in the root node
|
||||||
|
+ * has two benefits:
|
||||||
|
+ *
|
||||||
|
+ * - It avoids potential bugs where we forget to mark a DMA
|
||||||
|
+ * capable device as being dma-coherent
|
||||||
|
+ * - It avoids spurious warnings from the Linux kernel about
|
||||||
|
+ * devices which can't do DMA at all
|
||||||
|
+ */
|
||||||
|
+ qemu_fdt_setprop(fdt, "/", "dma-coherent", NULL, 0);
|
||||||
|
+
|
||||||
|
/* /chosen must exist for load_dtb to fill in necessary properties later */
|
||||||
|
qemu_fdt_add_subnode(fdt, "/chosen");
|
||||||
|
if (vms->dtb_randomness) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,132 +0,0 @@
|
|||||||
From 3f58194f8642a71c47d91d3c00a34faf44ea2c11 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Date: Wed, 3 Jan 2024 05:57:38 -0500
|
|
||||||
Subject: [PATCH] hw/arm/virt: Fix compats
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 209: hw/arm/virt: Fix compats
|
|
||||||
RH-Jira: RHEL-17168
|
|
||||||
RH-Acked-by: Gavin Shan <gshan@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [1/1] bcdf6493bbd6d7b52b0b88ff44441d22aeddfde2 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
arm_rhel_compat is not added for virt-rhel9.4.0 machine causing
|
|
||||||
the efi-virtio.rom to be looked for when instantiating a virtio-net-pci
|
|
||||||
device and it won't be found since not shipped on ARM. This is a
|
|
||||||
regression compared to 9.2.
|
|
||||||
|
|
||||||
Actually we do not need any rom file for any virtio-net-pci variant
|
|
||||||
because edk2 already brings the functionality. So for 9.4 onwards, we
|
|
||||||
want to set romfiles to "" for all of them.
|
|
||||||
|
|
||||||
However at the moment we apply arm_rhel_compat from the latest
|
|
||||||
rhel*_virt_options(). This is not aligned with the generic compat
|
|
||||||
usage which sets compats for a given machine type to accomodate for
|
|
||||||
changes that occured after its advent. Here we are somehow abusing
|
|
||||||
the compat infra to set general driver options that should apply for
|
|
||||||
all machines. On top of that this is really error prone and we have
|
|
||||||
forgotten to add arm_rhel_compat several times in the past.
|
|
||||||
|
|
||||||
So let's introduce set_arm_rhel_compat() being called before any
|
|
||||||
*virt_options in the non abstract machine class. That way the setting
|
|
||||||
will apply to any machine type without any need to add it in any
|
|
||||||
future machine types.
|
|
||||||
|
|
||||||
For < 9.4 machines we don't really care keeping non void romfiles
|
|
||||||
for transitional and non transitional devices because anyway this was
|
|
||||||
not working. So let's keep things simple and apply the new defaults for
|
|
||||||
all RHEL9 machine types.
|
|
||||||
|
|
||||||
Finally, to follow the generic pattern we should set hw_compat_rhel_9_0
|
|
||||||
in 9.0 machine as it is done on x86 or ccw. This has no consequence on
|
|
||||||
aarch64 because it only contains x86 stuff but that helps understanding
|
|
||||||
the consistency.
|
|
||||||
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 43 +++++++++++++++++++++++++++++--------------
|
|
||||||
1 file changed, 29 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 0b17c94ad7..5cab00b4cd 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -111,11 +111,39 @@
|
|
||||||
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) { \
|
|
||||||
@@ -139,19 +167,6 @@
|
|
||||||
#define DEFINE_RHEL_MACHINE(major, minor, subminor) \
|
|
||||||
DEFINE_RHEL_MACHINE_LATEST(major, minor, subminor, false)
|
|
||||||
|
|
||||||
-/* 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.
|
|
||||||
- */
|
|
||||||
-GlobalProperty arm_rhel_compat[] = {
|
|
||||||
- {
|
|
||||||
- .driver = "virtio-net-pci",
|
|
||||||
- .property = "romfile",
|
|
||||||
- .value = "",
|
|
||||||
- },
|
|
||||||
-};
|
|
||||||
-const size_t arm_rhel_compat_len = G_N_ELEMENTS(arm_rhel_compat);
|
|
||||||
-
|
|
||||||
/* Number of external interrupt lines to configure the GIC with */
|
|
||||||
#define NUM_IRQS 256
|
|
||||||
|
|
||||||
@@ -3639,7 +3654,6 @@ static void rhel920_virt_options(MachineClass *mc)
|
|
||||||
{
|
|
||||||
rhel940_virt_options(mc);
|
|
||||||
|
|
||||||
- compat_props_add(mc->compat_props, arm_rhel_compat, arm_rhel_compat_len);
|
|
||||||
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);
|
|
||||||
@@ -3653,6 +3667,7 @@ static void rhel900_virt_options(MachineClass *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;
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
|||||||
|
From e3360c415f7de923d27c3167260a93cb679afabe Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Auger <eric.auger@redhat.com>
|
||||||
|
Date: Mon, 6 May 2024 15:09:43 +0200
|
||||||
|
Subject: [PATCH 1/2] hw/arm/virt: Fix spurious call to arm_virt_compat_set()
|
||||||
|
|
||||||
|
RH-Author: Eric Auger <eric.auger@redhat.com>
|
||||||
|
RH-MergeRequest: 238: hw/arm/virt: Fix spurious call to arm_virt_compat_set()
|
||||||
|
RH-Jira: RHEL-34945
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
|
||||||
|
RH-Acked-by: Gavin Shan <gshan@redhat.com>
|
||||||
|
RH-Commit: [1/1] a858a3e1dff12b28e14f7e4bd2b896a9f06eacbb (eauger1/centos-qemu-kvm)
|
||||||
|
|
||||||
|
JIRA: https://issues.redhat.com/browse/RHEL-34945
|
||||||
|
Status: RHEL-only
|
||||||
|
|
||||||
|
Downstream, we apply arm_rhel_compat in place of arm_virt_compat.
|
||||||
|
This is done though arm_rhel_compat_set() transparently called in
|
||||||
|
DEFINE_RHEL_MACHINE_LATEST(). So there is no need to call
|
||||||
|
arm_virt_compat_set() in rhel_machine_class_init(). Besides
|
||||||
|
this triggers a "GLib: g_ptr_array_add: assertion 'rarray' failed"
|
||||||
|
warning.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
||||||
|
---
|
||||||
|
hw/arm/virt.c | 3 +--
|
||||||
|
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||||
|
index f1af9495c6..3f0496cdb9 100644
|
||||||
|
--- a/hw/arm/virt.c
|
||||||
|
+++ b/hw/arm/virt.c
|
||||||
|
@@ -85,6 +85,7 @@
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
#include "qemu/guest-random.h"
|
||||||
|
|
||||||
|
+#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||||
|
static GlobalProperty arm_virt_compat[] = {
|
||||||
|
{ TYPE_VIRTIO_IOMMU_PCI, "aw-bits", "48" },
|
||||||
|
};
|
||||||
|
@@ -101,7 +102,6 @@ static void arm_virt_compat_set(MachineClass *mc)
|
||||||
|
arm_virt_compat_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
-#if 0 /* Disabled for Red Hat Enterprise Linux */
|
||||||
|
#define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \
|
||||||
|
static void virt_##major##_##minor##_class_init(ObjectClass *oc, \
|
||||||
|
void *data) \
|
||||||
|
@@ -3536,7 +3536,6 @@ static void rhel_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
|
||||||
|
- arm_virt_compat_set(mc);
|
||||||
|
|
||||||
|
mc->family = "virt-rhel-Z";
|
||||||
|
mc->init = machvirt_init;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
From 4c1d07995a7afb6fae68a7e7a8b6b6c94fa0a7bb Mon Sep 17 00:00:00 2001
|
|
||||||
From: Cornelia Huck <cohuck@redhat.com>
|
|
||||||
Date: Mon, 12 Feb 2024 10:37:54 +0100
|
|
||||||
Subject: [PATCH 5/6] hw/arm/virt: deprecate virt-rhel9.{0,2}.0 machine types
|
|
||||||
|
|
||||||
RH-Author: Cornelia Huck <cohuck@redhat.com>
|
|
||||||
RH-MergeRequest: 225: hw/arm/virt: deprecate virt-rhel9.{0,2}.0 machine types
|
|
||||||
RH-Jira: RHEL-24988
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Acked-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-Commit: [1/1] f15579db44808fa8a2d7bc01b3915aa59c064411 (cohuck/qemu-kvm-c9s)
|
|
||||||
|
|
||||||
Jira: https://issues.redhat.com/browse/RHEL-24988
|
|
||||||
Upstream: RHEL only
|
|
||||||
|
|
||||||
We do not plan to support any machine types prior to 9.4.0; leave them
|
|
||||||
in, but mark as deprecated.
|
|
||||||
|
|
||||||
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
|
|
||||||
---
|
|
||||||
hw/arm/virt.c | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
|
||||||
index 60f117f0d2..943c563391 100644
|
|
||||||
--- a/hw/arm/virt.c
|
|
||||||
+++ b/hw/arm/virt.c
|
|
||||||
@@ -3679,6 +3679,10 @@ static void rhel920_virt_options(MachineClass *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)
|
|
||||||
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
From 7a6be312c11911bdd2ce82566be22a3e014947c2 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
|
|
||||||
Date: Tue, 21 Nov 2023 16:44:20 +0800
|
|
||||||
Subject: [PATCH 041/101] hw/i386: Activate IOMMUFD for q35 machines
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [40/67] b15764ab24fd57389a8d219736613484acd7d29e (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Reviewed-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
(cherry picked from commit 64ad06f6eba66c514477f490bcba409439a480d8)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
hw/i386/Kconfig | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
|
|
||||||
index 55850791df..a1846be6f7 100644
|
|
||||||
--- a/hw/i386/Kconfig
|
|
||||||
+++ b/hw/i386/Kconfig
|
|
||||||
@@ -95,6 +95,7 @@ config Q35
|
|
||||||
imply E1000E_PCI_EXPRESS
|
|
||||||
imply VMPORT
|
|
||||||
imply VMMOUSE
|
|
||||||
+ imply IOMMUFD
|
|
||||||
select PC_PCI
|
|
||||||
select PC_ACPI
|
|
||||||
select PCI_EXPRESS_Q35
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
|||||||
|
From e74980be81d641736ea9d44d0fe9af02af63a220 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:40 -0500
|
||||||
|
Subject: [PATCH 083/100] hw/i386: Add support for loading BIOS using
|
||||||
|
guest_memfd
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [83/91] 7b77d212ef7d83b66ad9d8348179ee84e64fb911 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When guest_memfd is enabled, the BIOS is generally part of the initial
|
||||||
|
encrypted guest image and will be accessed as private guest memory. Add
|
||||||
|
the necessary changes to set up the associated RAM region with a
|
||||||
|
guest_memfd backend to allow for this.
|
||||||
|
|
||||||
|
Current support centers around using -bios to load the BIOS data.
|
||||||
|
Support for loading the BIOS via pflash requires additional enablement
|
||||||
|
since those interfaces rely on the use of ROM memory regions which make
|
||||||
|
use of the KVM_MEM_READONLY memslot flag, which is not supported for
|
||||||
|
guest_memfd-backed memslots.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-29-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit fc7a69e177e4ba26d11fcf47b853f85115b35a11)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86-common.c | 17 ++++++++++++-----
|
||||||
|
1 file changed, 12 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
|
||||||
|
index 35fe6eabea..6cbb76c25c 100644
|
||||||
|
--- a/hw/i386/x86-common.c
|
||||||
|
+++ b/hw/i386/x86-common.c
|
||||||
|
@@ -969,8 +969,13 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
(bios_size % 65536) != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
}
|
||||||
|
- memory_region_init_ram(&x86ms->bios, NULL, "pc.bios", bios_size,
|
||||||
|
- &error_fatal);
|
||||||
|
+ if (machine_require_guest_memfd(MACHINE(x86ms))) {
|
||||||
|
+ memory_region_init_ram_guest_memfd(&x86ms->bios, NULL, "pc.bios",
|
||||||
|
+ bios_size, &error_fatal);
|
||||||
|
+ } else {
|
||||||
|
+ memory_region_init_ram(&x86ms->bios, NULL, "pc.bios",
|
||||||
|
+ bios_size, &error_fatal);
|
||||||
|
+ }
|
||||||
|
if (sev_enabled()) {
|
||||||
|
/*
|
||||||
|
* The concept of a "reset" simply doesn't exist for
|
||||||
|
@@ -991,9 +996,11 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
}
|
||||||
|
g_free(filename);
|
||||||
|
|
||||||
|
- /* map the last 128KB of the BIOS in ISA space */
|
||||||
|
- x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
|
||||||
|
- !isapc_ram_fw);
|
||||||
|
+ if (!machine_require_guest_memfd(MACHINE(x86ms))) {
|
||||||
|
+ /* map the last 128KB of the BIOS in ISA space */
|
||||||
|
+ x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
|
||||||
|
+ !isapc_ram_fw);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,106 @@
|
|||||||
|
From c1e615d6b8f609b72a94ffe6d31a9848a41744ef Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Tue, 30 Apr 2024 17:06:39 +0200
|
||||||
|
Subject: [PATCH 038/100] hw/i386: Have x86_bios_rom_init() take
|
||||||
|
X86MachineState rather than MachineState
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [38/91] 59f388b1dffc5d0aa2f0fff768194d755bc3efbb (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
The function creates and leaks two MemoryRegion objects regarding the BIOS which
|
||||||
|
will be moved into X86MachineState in the next steps to avoid the leakage.
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Message-ID: <20240430150643.111976-3-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 848351840148f8c3b53ddf6210194506547d3ffd)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/microvm.c | 2 +-
|
||||||
|
hw/i386/pc_sysfw.c | 4 ++--
|
||||||
|
hw/i386/x86.c | 4 ++--
|
||||||
|
include/hw/i386/x86.h | 2 +-
|
||||||
|
4 files changed, 6 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c
|
||||||
|
index 61a772dfe6..fec63cacfa 100644
|
||||||
|
--- a/hw/i386/microvm.c
|
||||||
|
+++ b/hw/i386/microvm.c
|
||||||
|
@@ -278,7 +278,7 @@ static void microvm_devices_init(MicrovmMachineState *mms)
|
||||||
|
default_firmware = x86_machine_is_acpi_enabled(x86ms)
|
||||||
|
? MICROVM_BIOS_FILENAME
|
||||||
|
: MICROVM_QBOOT_FILENAME;
|
||||||
|
- x86_bios_rom_init(MACHINE(mms), default_firmware, get_system_memory(), true);
|
||||||
|
+ x86_bios_rom_init(x86ms, default_firmware, get_system_memory(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void microvm_memory_init(MicrovmMachineState *mms)
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 3efabbbab2..ef7dea9798 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -206,7 +206,7 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||||
|
BlockBackend *pflash_blk[ARRAY_SIZE(pcms->flash)];
|
||||||
|
|
||||||
|
if (!pcmc->pci_enabled) {
|
||||||
|
- x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, true);
|
||||||
|
+ x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -227,7 +227,7 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (!pflash_blk[0]) {
|
||||||
|
/* Machine property pflash0 not set, use ROM mode */
|
||||||
|
- x86_bios_rom_init(MACHINE(pcms), "bios.bin", rom_memory, false);
|
||||||
|
+ x86_bios_rom_init(X86_MACHINE(pcms), "bios.bin", rom_memory, false);
|
||||||
|
} else {
|
||||||
|
if (kvm_enabled() && !kvm_readonly_mem_enabled()) {
|
||||||
|
/*
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 2a4f3ee285..6d3c72f124 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1128,7 +1128,7 @@ void x86_load_linux(X86MachineState *x86ms,
|
||||||
|
nb_option_roms++;
|
||||||
|
}
|
||||||
|
|
||||||
|
-void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
+void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw)
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
@@ -1138,7 +1138,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
/* BIOS load */
|
||||||
|
- bios_name = ms->firmware ?: default_firmware;
|
||||||
|
+ bios_name = MACHINE(x86ms)->firmware ?: default_firmware;
|
||||||
|
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||||
|
if (filename) {
|
||||||
|
bios_size = get_image_size(filename);
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index 4dc30dcb4d..cb07618d19 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -116,7 +116,7 @@ void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
|
void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
|
DeviceState *dev, Error **errp);
|
||||||
|
|
||||||
|
-void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
+void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw);
|
||||||
|
|
||||||
|
void x86_load_linux(X86MachineState *x86ms,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,51 @@
|
|||||||
|
From 7bb1f124413891bc5d2187f12cd19da6e794904b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Date: Wed, 3 Apr 2024 10:59:53 -0400
|
||||||
|
Subject: [PATCH 010/100] hw/i386/acpi: Set PCAT_COMPAT bit only when pic is
|
||||||
|
not disabled
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [10/91] 62110e4bf52cb3e106c8d2a902bbd31548beba00 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
A value 1 of PCAT_COMPAT (bit 0) of MADT.Flags indicates that the system
|
||||||
|
also has a PC-AT-compatible dual-8259 setup, i.e., the PIC. When PIC
|
||||||
|
is not enabled (pic=off) for x86 machine, the PCAT_COMPAT bit needs to
|
||||||
|
be cleared. The PIC probe should then print:
|
||||||
|
|
||||||
|
[ 0.155970] Using NULL legacy PIC
|
||||||
|
|
||||||
|
However, no such log printed in guest kernel unless PCAT_COMPAT is
|
||||||
|
cleared.
|
||||||
|
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240403145953.3082491-1-xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 292dd287e78e0cbafde9d1522c729349d132d844)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/acpi-common.c | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
|
||||||
|
index 20f19269da..0cc2919bb8 100644
|
||||||
|
--- a/hw/i386/acpi-common.c
|
||||||
|
+++ b/hw/i386/acpi-common.c
|
||||||
|
@@ -107,7 +107,9 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
|
||||||
|
acpi_table_begin(&table, table_data);
|
||||||
|
/* Local APIC Address */
|
||||||
|
build_append_int_noprefix(table_data, APIC_DEFAULT_ADDRESS, 4);
|
||||||
|
- build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
|
||||||
|
+ /* Flags. bit 0: PCAT_COMPAT */
|
||||||
|
+ build_append_int_noprefix(table_data,
|
||||||
|
+ x86ms->pic != ON_OFF_AUTO_OFF ? 1 : 0 , 4);
|
||||||
|
|
||||||
|
for (i = 0; i < apic_ids->len; i++) {
|
||||||
|
pc_madt_cpu_entry(i, apic_ids, table_data, false);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,164 @@
|
|||||||
|
From fd6de3c5e97bdf13a39342fc71815a20c66867ae Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:07 +0200
|
||||||
|
Subject: [PATCH 043/100] hw/i386/pc_sysfw: Alias rather than copy isa-bios
|
||||||
|
region
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [43/91] f64dab2a091838a10a9b94e3d09ea11432b0809f (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
In the -bios case the "isa-bios" memory region is an alias to the BIOS mapped
|
||||||
|
to the top of the 4G memory boundary. Do the same in the -pflash case, but only
|
||||||
|
for new machine versions for migration compatibility. This establishes common
|
||||||
|
behavior and makes pflash commands work in the "isa-bios" region which some
|
||||||
|
real-world legacy bioses rely on.
|
||||||
|
|
||||||
|
Note that in the sev_enabled() case, the "isa-bios" memory region in the -pflash
|
||||||
|
case will now also point to encrypted memory, just like it already does in the
|
||||||
|
-bios case.
|
||||||
|
|
||||||
|
When running `info mtree` before and after this commit with
|
||||||
|
`qemu-system-x86_64 -S -drive \
|
||||||
|
if=pflash,format=raw,readonly=on,file=/usr/share/qemu/bios-256k.bin` and running
|
||||||
|
`diff -u before.mtree after.mtree` results in the following changes in the
|
||||||
|
memory tree:
|
||||||
|
|
||||||
|
| --- before.mtree
|
||||||
|
| +++ after.mtree
|
||||||
|
| @@ -71,7 +71,7 @@
|
||||||
|
| 0000000000000000-ffffffffffffffff (prio -1, i/o): pci
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): vga-lowmem
|
||||||
|
| 00000000000c0000-00000000000dffff (prio 1, rom): pc.rom
|
||||||
|
| - 00000000000e0000-00000000000fffff (prio 1, rom): isa-bios
|
||||||
|
| + 00000000000e0000-00000000000fffff (prio 1, romd): alias isa-bios @system.flash0 0000000000020000-000000000003ffff
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): alias smram-region @pci 00000000000a0000-00000000000bffff
|
||||||
|
| 00000000000c0000-00000000000c3fff (prio 1, i/o): alias pam-pci @pci 00000000000c0000-00000000000c3fff
|
||||||
|
| 00000000000c4000-00000000000c7fff (prio 1, i/o): alias pam-pci @pci 00000000000c4000-00000000000c7fff
|
||||||
|
| @@ -108,7 +108,7 @@
|
||||||
|
| 0000000000000000-ffffffffffffffff (prio -1, i/o): pci
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): vga-lowmem
|
||||||
|
| 00000000000c0000-00000000000dffff (prio 1, rom): pc.rom
|
||||||
|
| - 00000000000e0000-00000000000fffff (prio 1, rom): isa-bios
|
||||||
|
| + 00000000000e0000-00000000000fffff (prio 1, romd): alias isa-bios @system.flash0 0000000000020000-000000000003ffff
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): alias smram-region @pci 00000000000a0000-00000000000bffff
|
||||||
|
| 00000000000c0000-00000000000c3fff (prio 1, i/o): alias pam-pci @pci 00000000000c0000-00000000000c3fff
|
||||||
|
| 00000000000c4000-00000000000c7fff (prio 1, i/o): alias pam-pci @pci 00000000000c4000-00000000000c7fff
|
||||||
|
| @@ -131,11 +131,14 @@
|
||||||
|
| memory-region: pc.ram
|
||||||
|
| 0000000000000000-0000000007ffffff (prio 0, ram): pc.ram
|
||||||
|
|
|
||||||
|
| +memory-region: system.flash0
|
||||||
|
| + 00000000fffc0000-00000000ffffffff (prio 0, romd): system.flash0
|
||||||
|
| +
|
||||||
|
| memory-region: pci
|
||||||
|
| 0000000000000000-ffffffffffffffff (prio -1, i/o): pci
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 1, i/o): vga-lowmem
|
||||||
|
| 00000000000c0000-00000000000dffff (prio 1, rom): pc.rom
|
||||||
|
| - 00000000000e0000-00000000000fffff (prio 1, rom): isa-bios
|
||||||
|
| + 00000000000e0000-00000000000fffff (prio 1, romd): alias isa-bios @system.flash0 0000000000020000-000000000003ffff
|
||||||
|
|
|
||||||
|
| memory-region: smram
|
||||||
|
| 00000000000a0000-00000000000bffff (prio 0, ram): alias smram-low @pc.ram 00000000000a0000-00000000000bffff
|
||||||
|
|
||||||
|
Note that in both cases the "system" memory region contains the entry
|
||||||
|
|
||||||
|
00000000fffc0000-00000000ffffffff (prio 0, romd): system.flash0
|
||||||
|
|
||||||
|
but the "system.flash0" memory region only appears standalone when "isa-bios" is
|
||||||
|
an alias.
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-7-shentey@gmail.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a44ea3fa7f2aa1d809fdca1b84a52695b53d8ad0)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 1 +
|
||||||
|
hw/i386/pc_piix.c | 1 +
|
||||||
|
hw/i386/pc_q35.c | 1 +
|
||||||
|
hw/i386/pc_sysfw.c | 8 +++++++-
|
||||||
|
include/hw/i386/pc.h | 1 +
|
||||||
|
5 files changed, 11 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index 1a34bc4522..660a59c63b 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -1967,6 +1967,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
pcmc->has_reserved_memory = true;
|
||||||
|
pcmc->enforce_aligned_dimm = true;
|
||||||
|
pcmc->enforce_amd_1tb_hole = true;
|
||||||
|
+ pcmc->isa_bios_alias = true;
|
||||||
|
/* BIOS ACPI tables: 128K. Other BIOS datastructures: less than 4K reported
|
||||||
|
* to be used at the moment, 32K should be enough for a while. */
|
||||||
|
pcmc->acpi_data_size = 0x20000 + 0x8000;
|
||||||
|
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
|
||||||
|
index bef3e8b73e..dbb7f2ed17 100644
|
||||||
|
--- a/hw/i386/pc_piix.c
|
||||||
|
+++ b/hw/i386/pc_piix.c
|
||||||
|
@@ -975,6 +975,7 @@ static void pc_machine_rhel7_options(MachineClass *m)
|
||||||
|
m->alias = "pc";
|
||||||
|
m->is_default = 1;
|
||||||
|
m->smp_props.prefer_sockets = true;
|
||||||
|
+ pcmc->isa_bios_alias = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pc_init_rhel760(MachineState *machine)
|
||||||
|
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
|
||||||
|
index dedc86eec9..f9900ad798 100644
|
||||||
|
--- a/hw/i386/pc_q35.c
|
||||||
|
+++ b/hw/i386/pc_q35.c
|
||||||
|
@@ -735,6 +735,7 @@ static void pc_q35_machine_rhel940_options(MachineClass *m)
|
||||||
|
m->desc = "RHEL-9.4.0 PC (Q35 + ICH9, 2009)";
|
||||||
|
pcmc->smbios_stream_product = "RHEL";
|
||||||
|
pcmc->smbios_stream_version = "9.4.0";
|
||||||
|
+ pcmc->isa_bios_alias = false;
|
||||||
|
|
||||||
|
compat_props_add(m->compat_props, pc_rhel_9_5_compat,
|
||||||
|
pc_rhel_9_5_compat_len);
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 82d37cb376..ac88ad4eb9 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -135,6 +135,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
MemoryRegion *rom_memory)
|
||||||
|
{
|
||||||
|
X86MachineState *x86ms = X86_MACHINE(pcms);
|
||||||
|
+ PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
|
||||||
|
hwaddr total_size = 0;
|
||||||
|
int i;
|
||||||
|
BlockBackend *blk;
|
||||||
|
@@ -184,7 +185,12 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
- pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
+ if (pcmc->isa_bios_alias) {
|
||||||
|
+ x86_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem,
|
||||||
|
+ true);
|
||||||
|
+ } else {
|
||||||
|
+ pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
if (sev_enabled()) {
|
||||||
|
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||||
|
index 467e7fb52f..3f53ec73ac 100644
|
||||||
|
--- a/include/hw/i386/pc.h
|
||||||
|
+++ b/include/hw/i386/pc.h
|
||||||
|
@@ -122,6 +122,7 @@ struct PCMachineClass {
|
||||||
|
bool enforce_aligned_dimm;
|
||||||
|
bool broken_reserved_end;
|
||||||
|
bool enforce_amd_1tb_hole;
|
||||||
|
+ bool isa_bios_alias;
|
||||||
|
|
||||||
|
/* generate legacy CPU hotplug AML */
|
||||||
|
bool legacy_cpu_hotplug;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,53 @@
|
|||||||
|
From 9bf1d368c4b53139db39649833d475e097fc98d1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Mon, 22 Apr 2024 22:06:22 +0200
|
||||||
|
Subject: [PATCH 039/100] hw/i386/pc_sysfw: Remove unused parameter from
|
||||||
|
pc_isa_bios_init()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [39/91] c0019dc2706a8e3f40486fd4a4c0dd1fbe23237b (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Message-ID: <20240422200625.2768-2-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit f4b63768b91811cdcf1fb7b270587123251dfea5)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 5 ++---
|
||||||
|
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index ef7dea9798..59c7a81692 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -41,8 +41,7 @@
|
||||||
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
|
|
||||||
|
static void pc_isa_bios_init(MemoryRegion *rom_memory,
|
||||||
|
- MemoryRegion *flash_mem,
|
||||||
|
- int ram_size)
|
||||||
|
+ MemoryRegion *flash_mem)
|
||||||
|
{
|
||||||
|
int isa_bios_size;
|
||||||
|
MemoryRegion *isa_bios;
|
||||||
|
@@ -186,7 +185,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
- pc_isa_bios_init(rom_memory, flash_mem, size);
|
||||||
|
+ pc_isa_bios_init(rom_memory, flash_mem);
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
if (sev_enabled()) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,158 @@
|
|||||||
|
From e6472ff46cbed97c2a238a8ef7d321351931333a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:30 -0500
|
||||||
|
Subject: [PATCH 070/100] hw/i386/sev: Add function to get SEV metadata from
|
||||||
|
OVMF header
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [70/91] ba818dade96119c8a51ca1fb222f4f69e2752396 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
A recent version of OVMF expanded the reset vector GUID list to add
|
||||||
|
SEV-specific metadata GUID. The SEV metadata describes the reserved
|
||||||
|
memory regions such as the secrets and CPUID page used during the SEV-SNP
|
||||||
|
guest launch.
|
||||||
|
|
||||||
|
The pc_system_get_ovmf_sev_metadata_ptr() is used to retieve the SEV
|
||||||
|
metadata pointer from the OVMF GUID list.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-19-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit f3c30c575d34122573b7370a7da5ca3a27dde481)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 4 ++++
|
||||||
|
include/hw/i386/pc.h | 26 ++++++++++++++++++++++++++
|
||||||
|
target/i386/sev-sysemu-stub.c | 4 ++++
|
||||||
|
target/i386/sev.c | 32 ++++++++++++++++++++++++++++++++
|
||||||
|
target/i386/sev.h | 2 ++
|
||||||
|
5 files changed, 68 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index ac88ad4eb9..9b8671c441 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -260,6 +260,10 @@ void x86_firmware_configure(void *ptr, int size)
|
||||||
|
pc_system_parse_ovmf_flash(ptr, size);
|
||||||
|
|
||||||
|
if (sev_enabled()) {
|
||||||
|
+
|
||||||
|
+ /* Copy the SEV metadata table (if it exists) */
|
||||||
|
+ pc_system_parse_sev_metadata(ptr, size);
|
||||||
|
+
|
||||||
|
ret = sev_es_save_reset_vector(ptr, size);
|
||||||
|
if (ret) {
|
||||||
|
error_report("failed to locate and/or save reset vector");
|
||||||
|
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||||
|
index 3f53ec73ac..94b49310f5 100644
|
||||||
|
--- a/include/hw/i386/pc.h
|
||||||
|
+++ b/include/hw/i386/pc.h
|
||||||
|
@@ -167,6 +167,32 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
|
||||||
|
#define PCI_HOST_ABOVE_4G_MEM_SIZE "above-4g-mem-size"
|
||||||
|
#define PCI_HOST_PROP_SMM_RANGES "smm-ranges"
|
||||||
|
|
||||||
|
+typedef enum {
|
||||||
|
+ SEV_DESC_TYPE_UNDEF,
|
||||||
|
+ /* The section contains the region that must be validated by the VMM. */
|
||||||
|
+ SEV_DESC_TYPE_SNP_SEC_MEM,
|
||||||
|
+ /* The section contains the SNP secrets page */
|
||||||
|
+ SEV_DESC_TYPE_SNP_SECRETS,
|
||||||
|
+ /* The section contains address that can be used as a CPUID page */
|
||||||
|
+ SEV_DESC_TYPE_CPUID,
|
||||||
|
+
|
||||||
|
+} ovmf_sev_metadata_desc_type;
|
||||||
|
+
|
||||||
|
+typedef struct __attribute__((__packed__)) OvmfSevMetadataDesc {
|
||||||
|
+ uint32_t base;
|
||||||
|
+ uint32_t len;
|
||||||
|
+ ovmf_sev_metadata_desc_type type;
|
||||||
|
+} OvmfSevMetadataDesc;
|
||||||
|
+
|
||||||
|
+typedef struct __attribute__((__packed__)) OvmfSevMetadata {
|
||||||
|
+ uint8_t signature[4];
|
||||||
|
+ uint32_t len;
|
||||||
|
+ uint32_t version;
|
||||||
|
+ uint32_t num_desc;
|
||||||
|
+ OvmfSevMetadataDesc descs[];
|
||||||
|
+} OvmfSevMetadata;
|
||||||
|
+
|
||||||
|
+OvmfSevMetadata *pc_system_get_ovmf_sev_metadata_ptr(void);
|
||||||
|
|
||||||
|
void pc_pci_as_mapping_init(MemoryRegion *system_memory,
|
||||||
|
MemoryRegion *pci_address_space);
|
||||||
|
diff --git a/target/i386/sev-sysemu-stub.c b/target/i386/sev-sysemu-stub.c
|
||||||
|
index 96e1c15cc3..fc1c57c411 100644
|
||||||
|
--- a/target/i386/sev-sysemu-stub.c
|
||||||
|
+++ b/target/i386/sev-sysemu-stub.c
|
||||||
|
@@ -67,3 +67,7 @@ void hmp_info_sev(Monitor *mon, const QDict *qdict)
|
||||||
|
{
|
||||||
|
monitor_printf(mon, "SEV is not available in this QEMU\n");
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void pc_system_parse_sev_metadata(uint8_t *flash_ptr, size_t flash_size)
|
||||||
|
+{
|
||||||
|
+}
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index e84e4395a5..17281bb2c7 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -597,6 +597,38 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
|
||||||
|
return sev_get_capabilities(errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static OvmfSevMetadata *ovmf_sev_metadata_table;
|
||||||
|
+
|
||||||
|
+#define OVMF_SEV_META_DATA_GUID "dc886566-984a-4798-A75e-5585a7bf67cc"
|
||||||
|
+typedef struct __attribute__((__packed__)) OvmfSevMetadataOffset {
|
||||||
|
+ uint32_t offset;
|
||||||
|
+} OvmfSevMetadataOffset;
|
||||||
|
+
|
||||||
|
+OvmfSevMetadata *pc_system_get_ovmf_sev_metadata_ptr(void)
|
||||||
|
+{
|
||||||
|
+ return ovmf_sev_metadata_table;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void pc_system_parse_sev_metadata(uint8_t *flash_ptr, size_t flash_size)
|
||||||
|
+{
|
||||||
|
+ OvmfSevMetadata *metadata;
|
||||||
|
+ OvmfSevMetadataOffset *data;
|
||||||
|
+
|
||||||
|
+ if (!pc_system_ovmf_table_find(OVMF_SEV_META_DATA_GUID, (uint8_t **)&data,
|
||||||
|
+ NULL)) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ metadata = (OvmfSevMetadata *)(flash_ptr + flash_size - data->offset);
|
||||||
|
+ if (memcmp(metadata->signature, "ASEV", 4) != 0 ||
|
||||||
|
+ metadata->len < sizeof(OvmfSevMetadata) ||
|
||||||
|
+ metadata->len > flash_size - data->offset) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ovmf_sev_metadata_table = g_memdup2(metadata, metadata->len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static SevAttestationReport *sev_get_attestation_report(const char *mnonce,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index 5dc4767b1e..cc12824dd6 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -66,4 +66,6 @@ int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||||
|
int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size);
|
||||||
|
void sev_es_set_reset_vector(CPUState *cpu);
|
||||||
|
|
||||||
|
+void pc_system_parse_sev_metadata(uint8_t *flash_ptr, size_t flash_size);
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,165 @@
|
|||||||
|
From 226cf6c3d3e2fd1a35422043dbe0b73d1216df83 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:36 -0500
|
||||||
|
Subject: [PATCH 073/100] hw/i386/sev: Add support to encrypt BIOS when SEV-SNP
|
||||||
|
is enabled
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [73/91] 844afd322c12c3e8992cf6ec692c94e70747bd0c (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
As with SEV, an SNP guest requires that the BIOS be part of the initial
|
||||||
|
encrypted/measured guest payload. Extend sev_encrypt_flash() to handle
|
||||||
|
the SNP case and plumb through the GPA of the BIOS location since this
|
||||||
|
is needed for SNP.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-25-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 77d1abd91e5352ad30ae2f83790f95fa6a3c0b6b)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 12 +++++++-----
|
||||||
|
hw/i386/x86-common.c | 2 +-
|
||||||
|
include/hw/i386/x86.h | 2 +-
|
||||||
|
target/i386/sev-sysemu-stub.c | 2 +-
|
||||||
|
target/i386/sev.c | 5 +++--
|
||||||
|
target/i386/sev.h | 2 +-
|
||||||
|
6 files changed, 14 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 9b8671c441..7cdbafc8d2 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -148,6 +148,8 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(pcms->flash); i++) {
|
||||||
|
+ hwaddr gpa;
|
||||||
|
+
|
||||||
|
system_flash = pcms->flash[i];
|
||||||
|
blk = pflash_cfi01_get_blk(system_flash);
|
||||||
|
if (!blk) {
|
||||||
|
@@ -177,11 +179,11 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
}
|
||||||
|
|
||||||
|
total_size += size;
|
||||||
|
+ gpa = 0x100000000ULL - total_size; /* where the flash is mapped */
|
||||||
|
qdev_prop_set_uint32(DEVICE(system_flash), "num-blocks",
|
||||||
|
size / FLASH_SECTOR_SIZE);
|
||||||
|
sysbus_realize_and_unref(SYS_BUS_DEVICE(system_flash), &error_fatal);
|
||||||
|
- sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0,
|
||||||
|
- 0x100000000ULL - total_size);
|
||||||
|
+ sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, gpa);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
@@ -196,7 +198,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
if (sev_enabled()) {
|
||||||
|
flash_ptr = memory_region_get_ram_ptr(flash_mem);
|
||||||
|
flash_size = memory_region_size(flash_mem);
|
||||||
|
- x86_firmware_configure(flash_ptr, flash_size);
|
||||||
|
+ x86_firmware_configure(gpa, flash_ptr, flash_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -249,7 +251,7 @@ void pc_system_firmware_init(PCMachineState *pcms,
|
||||||
|
pc_system_flash_cleanup_unused(pcms);
|
||||||
|
}
|
||||||
|
|
||||||
|
-void x86_firmware_configure(void *ptr, int size)
|
||||||
|
+void x86_firmware_configure(hwaddr gpa, void *ptr, int size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
@@ -270,6 +272,6 @@ void x86_firmware_configure(void *ptr, int size)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sev_encrypt_flash(ptr, size, &error_fatal);
|
||||||
|
+ sev_encrypt_flash(gpa, ptr, size, &error_fatal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/hw/i386/x86-common.c b/hw/i386/x86-common.c
|
||||||
|
index 67b03c913a..35fe6eabea 100644
|
||||||
|
--- a/hw/i386/x86-common.c
|
||||||
|
+++ b/hw/i386/x86-common.c
|
||||||
|
@@ -981,7 +981,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
*/
|
||||||
|
void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
|
||||||
|
load_image_size(filename, ptr, bios_size);
|
||||||
|
- x86_firmware_configure(ptr, bios_size);
|
||||||
|
+ x86_firmware_configure(0x100000000ULL - bios_size, ptr, bios_size);
|
||||||
|
} else {
|
||||||
|
memory_region_set_readonly(&x86ms->bios, !isapc_ram_fw);
|
||||||
|
ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index b006f16b8d..d43cb3908e 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -154,6 +154,6 @@ void ioapic_init_gsi(GSIState *gsi_state, Object *parent);
|
||||||
|
DeviceState *ioapic_init_secondary(GSIState *gsi_state);
|
||||||
|
|
||||||
|
/* pc_sysfw.c */
|
||||||
|
-void x86_firmware_configure(void *ptr, int size);
|
||||||
|
+void x86_firmware_configure(hwaddr gpa, void *ptr, int size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
diff --git a/target/i386/sev-sysemu-stub.c b/target/i386/sev-sysemu-stub.c
|
||||||
|
index fc1c57c411..d5bf886e79 100644
|
||||||
|
--- a/target/i386/sev-sysemu-stub.c
|
||||||
|
+++ b/target/i386/sev-sysemu-stub.c
|
||||||
|
@@ -42,7 +42,7 @@ void qmp_sev_inject_launch_secret(const char *packet_header, const char *secret,
|
||||||
|
error_setg(errp, "SEV is not available in this QEMU");
|
||||||
|
}
|
||||||
|
|
||||||
|
-int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
+int sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 06401f0526..7b5c4b4874 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1484,7 +1484,7 @@ static int sev_snp_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
+sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
|
||||||
|
@@ -1841,7 +1841,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
/* zero the excess data so the measurement can be reliably calculated */
|
||||||
|
memset(padded_ht->padding, 0, sizeof(padded_ht->padding));
|
||||||
|
|
||||||
|
- if (sev_encrypt_flash((uint8_t *)padded_ht, sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
+ sizeof(*padded_ht), errp) < 0) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index cc12824dd6..858005a119 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -59,7 +59,7 @@ uint32_t sev_get_cbit_position(void);
|
||||||
|
uint32_t sev_get_reduced_phys_bits(void);
|
||||||
|
bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp);
|
||||||
|
|
||||||
|
-int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
|
||||||
|
+int sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp);
|
||||||
|
int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||||
|
uint64_t gpa, Error **errp);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,123 @@
|
|||||||
|
From a20b2e3e52b9589ac1abc8b9b818d526c86368cf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:39 -0500
|
||||||
|
Subject: [PATCH 082/100] hw/i386/sev: Use guest_memfd for legacy ROMs
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [82/91] a591e85e00c353009803b143c80852b8c9b1f15e (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Current SNP guest kernels will attempt to access these regions with
|
||||||
|
with C-bit set, so guest_memfd is needed to handle that. Otherwise,
|
||||||
|
kvm_convert_memory() will fail when the guest kernel tries to access it
|
||||||
|
and QEMU attempts to call KVM_SET_MEMORY_ATTRIBUTES to set these ranges
|
||||||
|
to private.
|
||||||
|
|
||||||
|
Whether guests should actually try to access ROM regions in this way (or
|
||||||
|
need to deal with legacy ROM regions at all), is a separate issue to be
|
||||||
|
addressed on kernel side, but current SNP guest kernels will exhibit
|
||||||
|
this behavior and so this handling is needed to allow QEMU to continue
|
||||||
|
running existing SNP guest kernels.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
[pankaj: Added sev_snp_enabled() check]
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-28-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 413a67450750e0459efeffc3db3ba9759c3e381c)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 14 ++++++++++----
|
||||||
|
hw/i386/pc_sysfw.c | 19 +++++++++++++------
|
||||||
|
2 files changed, 23 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index 0aca0cc79e..b25d075b59 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -62,6 +62,7 @@
|
||||||
|
#include "hw/mem/memory-device.h"
|
||||||
|
#include "e820_memory_layout.h"
|
||||||
|
#include "trace.h"
|
||||||
|
+#include "sev.h"
|
||||||
|
#include CONFIG_DEVICES
|
||||||
|
|
||||||
|
#ifdef CONFIG_XEN_EMU
|
||||||
|
@@ -1173,10 +1174,15 @@ void pc_memory_init(PCMachineState *pcms,
|
||||||
|
pc_system_firmware_init(pcms, rom_memory);
|
||||||
|
|
||||||
|
option_rom_mr = g_malloc(sizeof(*option_rom_mr));
|
||||||
|
- memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE,
|
||||||
|
- &error_fatal);
|
||||||
|
- if (pcmc->pci_enabled) {
|
||||||
|
- memory_region_set_readonly(option_rom_mr, true);
|
||||||
|
+ if (machine_require_guest_memfd(machine)) {
|
||||||
|
+ memory_region_init_ram_guest_memfd(option_rom_mr, NULL, "pc.rom",
|
||||||
|
+ PC_ROM_SIZE, &error_fatal);
|
||||||
|
+ } else {
|
||||||
|
+ memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE,
|
||||||
|
+ &error_fatal);
|
||||||
|
+ if (pcmc->pci_enabled) {
|
||||||
|
+ memory_region_set_readonly(option_rom_mr, true);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
PC_ROM_MIN_VGA,
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 7cdbafc8d2..ef80281d28 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -40,8 +40,8 @@
|
||||||
|
|
||||||
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
|
|
||||||
|
-static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
- MemoryRegion *flash_mem)
|
||||||
|
+static void pc_isa_bios_init(PCMachineState *pcms, MemoryRegion *isa_bios,
|
||||||
|
+ MemoryRegion *rom_memory, MemoryRegion *flash_mem)
|
||||||
|
{
|
||||||
|
int isa_bios_size;
|
||||||
|
uint64_t flash_size;
|
||||||
|
@@ -51,8 +51,13 @@ static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(flash_size, 128 * KiB);
|
||||||
|
- memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
|
||||||
|
- &error_fatal);
|
||||||
|
+ if (machine_require_guest_memfd(MACHINE(pcms))) {
|
||||||
|
+ memory_region_init_ram_guest_memfd(isa_bios, NULL, "isa-bios",
|
||||||
|
+ isa_bios_size, &error_fatal);
|
||||||
|
+ } else {
|
||||||
|
+ memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
|
||||||
|
+ &error_fatal);
|
||||||
|
+ }
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
isa_bios,
|
||||||
|
@@ -65,7 +70,9 @@ static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
((uint8_t*)flash_ptr) + (flash_size - isa_bios_size),
|
||||||
|
isa_bios_size);
|
||||||
|
|
||||||
|
- memory_region_set_readonly(isa_bios, true);
|
||||||
|
+ if (!machine_require_guest_memfd(current_machine)) {
|
||||||
|
+ memory_region_set_readonly(isa_bios, true);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static PFlashCFI01 *pc_pflash_create(PCMachineState *pcms,
|
||||||
|
@@ -191,7 +198,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
x86_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem,
|
||||||
|
true);
|
||||||
|
} else {
|
||||||
|
- pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
+ pc_isa_bios_init(pcms, &x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
From 4331180aa09e44550ff8de781c618bae5e99bb70 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Tue, 9 Apr 2024 18:07:43 -0500
|
||||||
|
Subject: [PATCH 025/100] hw/i386/sev: Use legacy SEV VM types for older
|
||||||
|
machine types
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [25/91] 8c73cd312736ccb0818b4d3216fd13712f21f3c9 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Newer 9.1 machine types will default to using the KVM_SEV_INIT2 API for
|
||||||
|
creating SEV/SEV-ES going forward. However, this API results in guest
|
||||||
|
measurement changes which are generally not expected for users of these
|
||||||
|
older guest types and can cause disruption if they switch to a newer
|
||||||
|
QEMU/kernel version. Avoid this by continuing to use the older
|
||||||
|
KVM_SEV_INIT/KVM_SEV_ES_INIT APIs for older machine types.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Message-ID: <20240409230743.962513-4-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit ea7fbd37537b3a598335c21ccb2ea674630fc810)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 1 +
|
||||||
|
target/i386/sev.c | 1 +
|
||||||
|
2 files changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index b9fde3cec1..1a34bc4522 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -351,6 +351,7 @@ const size_t pc_rhel_compat_len = G_N_ELEMENTS(pc_rhel_compat);
|
||||||
|
GlobalProperty pc_rhel_9_5_compat[] = {
|
||||||
|
/* pc_rhel_9_5_compat from pc_compat_pc_9_0 (backported from 9.1) */
|
||||||
|
{ TYPE_X86_CPU, "guest-phys-bits", "0" },
|
||||||
|
+ { "sev-guest", "legacy-vm-type", "true" },
|
||||||
|
};
|
||||||
|
const size_t pc_rhel_9_5_compat_len = G_N_ELEMENTS(pc_rhel_9_5_compat);
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index f4ee317cb0..d30b68c11e 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1417,6 +1417,7 @@ sev_guest_instance_init(Object *obj)
|
||||||
|
object_property_add_uint32_ptr(obj, "reduced-phys-bits",
|
||||||
|
&sev->reduced_phys_bits,
|
||||||
|
OBJ_PROP_FLAG_READWRITE);
|
||||||
|
+ object_apply_compat_props(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sev guest info */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,133 @@
|
|||||||
|
From ebf08d2a822576acfa60fbd5f552d26de1e4c4be Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:04 +0200
|
||||||
|
Subject: [PATCH 040/100] hw/i386/x86: Don't leak "isa-bios" memory regions
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [40/91] bb595357c6cc2d5a80bf3873853c69553c5feee5 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Fix the leaking in x86_bios_rom_init() and pc_isa_bios_init() by adding an
|
||||||
|
"isa_bios" attribute to X86MachineState.
|
||||||
|
|
||||||
|
Suggested-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-4-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 32d3ee87a17fc91e981a23dba94855bff89f5920)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc_sysfw.c | 7 +++----
|
||||||
|
hw/i386/x86.c | 9 ++++-----
|
||||||
|
include/hw/i386/x86.h | 7 +++++++
|
||||||
|
3 files changed, 14 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
|
||||||
|
index 59c7a81692..82d37cb376 100644
|
||||||
|
--- a/hw/i386/pc_sysfw.c
|
||||||
|
+++ b/hw/i386/pc_sysfw.c
|
||||||
|
@@ -40,11 +40,10 @@
|
||||||
|
|
||||||
|
#define FLASH_SECTOR_SIZE 4096
|
||||||
|
|
||||||
|
-static void pc_isa_bios_init(MemoryRegion *rom_memory,
|
||||||
|
+static void pc_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *rom_memory,
|
||||||
|
MemoryRegion *flash_mem)
|
||||||
|
{
|
||||||
|
int isa_bios_size;
|
||||||
|
- MemoryRegion *isa_bios;
|
||||||
|
uint64_t flash_size;
|
||||||
|
void *flash_ptr, *isa_bios_ptr;
|
||||||
|
|
||||||
|
@@ -52,7 +51,6 @@ static void pc_isa_bios_init(MemoryRegion *rom_memory,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(flash_size, 128 * KiB);
|
||||||
|
- isa_bios = g_malloc(sizeof(*isa_bios));
|
||||||
|
memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size,
|
||||||
|
&error_fatal);
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
@@ -136,6 +134,7 @@ void pc_system_flash_cleanup_unused(PCMachineState *pcms)
|
||||||
|
static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
MemoryRegion *rom_memory)
|
||||||
|
{
|
||||||
|
+ X86MachineState *x86ms = X86_MACHINE(pcms);
|
||||||
|
hwaddr total_size = 0;
|
||||||
|
int i;
|
||||||
|
BlockBackend *blk;
|
||||||
|
@@ -185,7 +184,7 @@ static void pc_system_flash_map(PCMachineState *pcms,
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
flash_mem = pflash_cfi01_get_memory(system_flash);
|
||||||
|
- pc_isa_bios_init(rom_memory, flash_mem);
|
||||||
|
+ pc_isa_bios_init(&x86ms->isa_bios, rom_memory, flash_mem);
|
||||||
|
|
||||||
|
/* Encrypt the pflash boot ROM */
|
||||||
|
if (sev_enabled()) {
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 6d3c72f124..457e8a34a5 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1133,7 +1133,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
char *filename;
|
||||||
|
- MemoryRegion *bios, *isa_bios;
|
||||||
|
+ MemoryRegion *bios;
|
||||||
|
int bios_size, isa_bios_size;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
@@ -1173,14 +1173,13 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
- isa_bios = g_malloc(sizeof(*isa_bios));
|
||||||
|
- memory_region_init_alias(isa_bios, NULL, "isa-bios", bios,
|
||||||
|
+ memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", bios,
|
||||||
|
bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
- isa_bios,
|
||||||
|
+ &x86ms->isa_bios,
|
||||||
|
1);
|
||||||
|
- memory_region_set_readonly(isa_bios, !isapc_ram_fw);
|
||||||
|
+ memory_region_set_readonly(&x86ms->isa_bios, !isapc_ram_fw);
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index cb07618d19..a07de79167 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -18,6 +18,7 @@
|
||||||
|
#define HW_I386_X86_H
|
||||||
|
|
||||||
|
#include "exec/hwaddr.h"
|
||||||
|
+#include "exec/memory.h"
|
||||||
|
|
||||||
|
#include "hw/boards.h"
|
||||||
|
#include "hw/intc/ioapic.h"
|
||||||
|
@@ -52,6 +53,12 @@ struct X86MachineState {
|
||||||
|
GMappedFile *initrd_mapped_file;
|
||||||
|
HotplugHandler *acpi_dev;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Map the upper 128 KiB of the BIOS just underneath the 1 MiB address
|
||||||
|
+ * boundary.
|
||||||
|
+ */
|
||||||
|
+ MemoryRegion isa_bios;
|
||||||
|
+
|
||||||
|
/* RAM information (sizes, addresses, configuration): */
|
||||||
|
ram_addr_t below_4g_mem_size, above_4g_mem_size;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,105 @@
|
|||||||
|
From e1f2265b5f6bf5b63bf3808bb540888f3cf8badb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:05 +0200
|
||||||
|
Subject: [PATCH 041/100] hw/i386/x86: Don't leak "pc.bios" memory region
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [41/91] a9cd61d8d240134c09c46e244efb89217cadf60c (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Fix the leaking in x86_bios_rom_init() by adding a "bios" attribute to
|
||||||
|
X86MachineState. Note that it is only used in the -bios case.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-5-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 865d95321ffc8d9941e33000b10140550f094556)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86.c | 13 ++++++-------
|
||||||
|
include/hw/i386/x86.h | 6 ++++++
|
||||||
|
2 files changed, 12 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 457e8a34a5..29167de97d 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1133,7 +1133,6 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
char *filename;
|
||||||
|
- MemoryRegion *bios;
|
||||||
|
int bios_size, isa_bios_size;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
@@ -1149,8 +1148,8 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
(bios_size % 65536) != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
}
|
||||||
|
- bios = g_malloc(sizeof(*bios));
|
||||||
|
- memory_region_init_ram(bios, NULL, "pc.bios", bios_size, &error_fatal);
|
||||||
|
+ memory_region_init_ram(&x86ms->bios, NULL, "pc.bios", bios_size,
|
||||||
|
+ &error_fatal);
|
||||||
|
if (sev_enabled()) {
|
||||||
|
/*
|
||||||
|
* The concept of a "reset" simply doesn't exist for
|
||||||
|
@@ -1159,11 +1158,11 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
* the firmware as rom to properly re-initialize on reset.
|
||||||
|
* Just go for a straight file load instead.
|
||||||
|
*/
|
||||||
|
- void *ptr = memory_region_get_ram_ptr(bios);
|
||||||
|
+ void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
|
||||||
|
load_image_size(filename, ptr, bios_size);
|
||||||
|
x86_firmware_configure(ptr, bios_size);
|
||||||
|
} else {
|
||||||
|
- memory_region_set_readonly(bios, !isapc_ram_fw);
|
||||||
|
+ memory_region_set_readonly(&x86ms->bios, !isapc_ram_fw);
|
||||||
|
ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
|
||||||
|
if (ret != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
@@ -1173,7 +1172,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
- memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", bios,
|
||||||
|
+ memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", &x86ms->bios,
|
||||||
|
bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
@@ -1184,7 +1183,7 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
(uint32_t)(-bios_size),
|
||||||
|
- bios);
|
||||||
|
+ &x86ms->bios);
|
||||||
|
return;
|
||||||
|
|
||||||
|
bios_error:
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index a07de79167..55c6809ae0 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -53,6 +53,12 @@ struct X86MachineState {
|
||||||
|
GMappedFile *initrd_mapped_file;
|
||||||
|
HotplugHandler *acpi_dev;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * Map the whole BIOS just underneath the 4 GiB address boundary. Only used
|
||||||
|
+ * in the ROM (-bios) case.
|
||||||
|
+ */
|
||||||
|
+ MemoryRegion bios;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Map the upper 128 KiB of the BIOS just underneath the 1 MiB address
|
||||||
|
* boundary.
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,69 @@
|
|||||||
|
From b9d0c78f04160fbc1eee6cfd94b17f1133a35d83 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Tue, 30 Apr 2024 17:06:38 +0200
|
||||||
|
Subject: [PATCH 037/100] hw/i386/x86: Eliminate two if statements in
|
||||||
|
x86_bios_rom_init()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [37/91] 1ef6a13214e85f6ef773f5c894c720f20330912b (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Given that memory_region_set_readonly() is a no-op when the readonlyness is
|
||||||
|
already as requested it is possible to simplify the pattern
|
||||||
|
|
||||||
|
if (condition) {
|
||||||
|
foo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
to
|
||||||
|
|
||||||
|
foo(condition);
|
||||||
|
|
||||||
|
which is shorter and allows to see the invariant of the code more easily.
|
||||||
|
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Message-ID: <20240430150643.111976-2-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 014dbdac8798799d081abc9dff3e4876ca54f49e)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86.c | 8 ++------
|
||||||
|
1 file changed, 2 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 3d5b51e92d..2a4f3ee285 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1163,9 +1163,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
load_image_size(filename, ptr, bios_size);
|
||||||
|
x86_firmware_configure(ptr, bios_size);
|
||||||
|
} else {
|
||||||
|
- if (!isapc_ram_fw) {
|
||||||
|
- memory_region_set_readonly(bios, true);
|
||||||
|
- }
|
||||||
|
+ memory_region_set_readonly(bios, !isapc_ram_fw);
|
||||||
|
ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
|
||||||
|
if (ret != 0) {
|
||||||
|
goto bios_error;
|
||||||
|
@@ -1182,9 +1180,7 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware,
|
||||||
|
0x100000 - isa_bios_size,
|
||||||
|
isa_bios,
|
||||||
|
1);
|
||||||
|
- if (!isapc_ram_fw) {
|
||||||
|
- memory_region_set_readonly(isa_bios, true);
|
||||||
|
- }
|
||||||
|
+ memory_region_set_readonly(isa_bios, !isapc_ram_fw);
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
From 1baf67564d4227d6ba98923217a15814c438c32b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Date: Wed, 8 May 2024 19:55:06 +0200
|
||||||
|
Subject: [PATCH 042/100] hw/i386/x86: Extract x86_isa_bios_init() from
|
||||||
|
x86_bios_rom_init()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [42/91] 1db417a5995480924f7fd0661a306f2d2bfa0a77 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
The function is inspired by pc_isa_bios_init() and should eventually replace it.
|
||||||
|
Using x86_isa_bios_init() rather than pc_isa_bios_init() fixes pflash commands
|
||||||
|
to work in the isa-bios region.
|
||||||
|
|
||||||
|
While at it convert the magic number 0x100000 (== 1MiB) to increase readability.
|
||||||
|
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
|
||||||
|
Message-ID: <20240508175507.22270-6-shentey@gmail.com>
|
||||||
|
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
(cherry picked from commit 5c5ffec12c30d2017cbdee6798f54d8fad3f9656)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/x86.c | 25 ++++++++++++++++---------
|
||||||
|
include/hw/i386/x86.h | 2 ++
|
||||||
|
2 files changed, 18 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index 29167de97d..c61f4ebfa6 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -1128,12 +1128,25 @@ void x86_load_linux(X86MachineState *x86ms,
|
||||||
|
nb_option_roms++;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void x86_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *isa_memory,
|
||||||
|
+ MemoryRegion *bios, bool read_only)
|
||||||
|
+{
|
||||||
|
+ uint64_t bios_size = memory_region_size(bios);
|
||||||
|
+ uint64_t isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
+
|
||||||
|
+ memory_region_init_alias(isa_bios, NULL, "isa-bios", bios,
|
||||||
|
+ bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
+ memory_region_add_subregion_overlap(isa_memory, 1 * MiB - isa_bios_size,
|
||||||
|
+ isa_bios, 1);
|
||||||
|
+ memory_region_set_readonly(isa_bios, read_only);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw)
|
||||||
|
{
|
||||||
|
const char *bios_name;
|
||||||
|
char *filename;
|
||||||
|
- int bios_size, isa_bios_size;
|
||||||
|
+ int bios_size;
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
/* BIOS load */
|
||||||
|
@@ -1171,14 +1184,8 @@ void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
g_free(filename);
|
||||||
|
|
||||||
|
/* map the last 128KB of the BIOS in ISA space */
|
||||||
|
- isa_bios_size = MIN(bios_size, 128 * KiB);
|
||||||
|
- memory_region_init_alias(&x86ms->isa_bios, NULL, "isa-bios", &x86ms->bios,
|
||||||
|
- bios_size - isa_bios_size, isa_bios_size);
|
||||||
|
- memory_region_add_subregion_overlap(rom_memory,
|
||||||
|
- 0x100000 - isa_bios_size,
|
||||||
|
- &x86ms->isa_bios,
|
||||||
|
- 1);
|
||||||
|
- memory_region_set_readonly(&x86ms->isa_bios, !isapc_ram_fw);
|
||||||
|
+ x86_isa_bios_init(&x86ms->isa_bios, rom_memory, &x86ms->bios,
|
||||||
|
+ !isapc_ram_fw);
|
||||||
|
|
||||||
|
/* map all the bios at the top of memory */
|
||||||
|
memory_region_add_subregion(rom_memory,
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index 55c6809ae0..d7b7d3f3ce 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -129,6 +129,8 @@ void x86_cpu_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
|
void x86_cpu_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
|
DeviceState *dev, Error **errp);
|
||||||
|
|
||||||
|
+void x86_isa_bios_init(MemoryRegion *isa_bios, MemoryRegion *isa_memory,
|
||||||
|
+ MemoryRegion *bios, bool read_only);
|
||||||
|
void x86_bios_rom_init(X86MachineState *x86ms, const char *default_firmware,
|
||||||
|
MemoryRegion *rom_memory, bool isapc_ram_fw);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -1,116 +0,0 @@
|
|||||||
From 84f378c41832602dcf9bad6167b1f532c7c53e37 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= <clg@redhat.com>
|
|
||||||
Date: Tue, 21 Nov 2023 15:03:55 +0100
|
|
||||||
Subject: [PATCH 048/101] hw/ppc/Kconfig: Imply VFIO_PCI
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [47/67] c1a40cdab9bf62b16cb428d57a20b3e0eaa6de38 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
When the legacy and iommufd backends were introduced, a set of common
|
|
||||||
vfio-pci routines were exported in pci.c for both backends to use :
|
|
||||||
|
|
||||||
vfio_pci_pre_reset
|
|
||||||
vfio_pci_get_pci_hot_reset_info
|
|
||||||
vfio_pci_host_match
|
|
||||||
vfio_pci_post_reset
|
|
||||||
|
|
||||||
This introduced a build failure on PPC when --without-default-devices
|
|
||||||
is use because VFIO is always selected in ppc/Kconfig but VFIO_PCI is
|
|
||||||
not.
|
|
||||||
|
|
||||||
Use an 'imply VFIO_PCI' in ppc/Kconfig and bypass compilation of the
|
|
||||||
VFIO EEH hooks routines defined in hw/ppc/spapr_pci_vfio.c with
|
|
||||||
CONFIG_VFIO_PCI.
|
|
||||||
|
|
||||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
|
||||||
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Signed-off-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
(cherry picked from commit 4278df9d1d2383b738338c857406357660f11e42)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
hw/ppc/Kconfig | 2 +-
|
|
||||||
hw/ppc/spapr_pci_vfio.c | 36 ++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 37 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
|
|
||||||
index 56f0475a8e..44263a58c4 100644
|
|
||||||
--- a/hw/ppc/Kconfig
|
|
||||||
+++ b/hw/ppc/Kconfig
|
|
||||||
@@ -3,11 +3,11 @@ config PSERIES
|
|
||||||
imply PCI_DEVICES
|
|
||||||
imply TEST_DEVICES
|
|
||||||
imply VIRTIO_VGA
|
|
||||||
+ imply VFIO_PCI if LINUX # needed by spapr_pci_vfio.c
|
|
||||||
select NVDIMM
|
|
||||||
select DIMM
|
|
||||||
select PCI
|
|
||||||
select SPAPR_VSCSI
|
|
||||||
- select VFIO if LINUX # needed by spapr_pci_vfio.c
|
|
||||||
select XICS
|
|
||||||
select XIVE
|
|
||||||
select MSI_NONBROKEN
|
|
||||||
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
|
|
||||||
index d1d07bec46..76b2a3487b 100644
|
|
||||||
--- a/hw/ppc/spapr_pci_vfio.c
|
|
||||||
+++ b/hw/ppc/spapr_pci_vfio.c
|
|
||||||
@@ -26,10 +26,12 @@
|
|
||||||
#include "hw/pci/pci_device.h"
|
|
||||||
#include "hw/vfio/vfio-common.h"
|
|
||||||
#include "qemu/error-report.h"
|
|
||||||
+#include CONFIG_DEVICES /* CONFIG_VFIO_PCI */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Interfaces for IBM EEH (Enhanced Error Handling)
|
|
||||||
*/
|
|
||||||
+#ifdef CONFIG_VFIO_PCI
|
|
||||||
static bool vfio_eeh_container_ok(VFIOContainer *container)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
@@ -314,3 +316,37 @@ int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
|
|
||||||
|
|
||||||
return RTAS_OUT_SUCCESS;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+#else
|
|
||||||
+
|
|
||||||
+bool spapr_phb_eeh_available(SpaprPhbState *sphb)
|
|
||||||
+{
|
|
||||||
+ return false;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void spapr_phb_vfio_reset(DeviceState *qdev)
|
|
||||||
+{
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
|
|
||||||
+ unsigned int addr, int option)
|
|
||||||
+{
|
|
||||||
+ return RTAS_OUT_NOT_SUPPORTED;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int spapr_phb_vfio_eeh_get_state(SpaprPhbState *sphb, int *state)
|
|
||||||
+{
|
|
||||||
+ return RTAS_OUT_NOT_SUPPORTED;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int spapr_phb_vfio_eeh_reset(SpaprPhbState *sphb, int option)
|
|
||||||
+{
|
|
||||||
+ return RTAS_OUT_NOT_SUPPORTED;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int spapr_phb_vfio_eeh_configure(SpaprPhbState *sphb)
|
|
||||||
+{
|
|
||||||
+ return RTAS_OUT_NOT_SUPPORTED;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#endif /* CONFIG_VFIO_PCI */
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
|||||||
From 8f27893a37e55a31180bb66cd9eae7199911881b Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Volker=20R=C3=BCmelin?= <vr_qemu@t-online.de>
|
|
||||||
Date: Fri, 29 Dec 2023 21:38:54 +0100
|
|
||||||
Subject: [PATCH 060/101] hw/vfio: fix iteration over global VFIODevice list
|
|
||||||
MIME-Version: 1.0
|
|
||||||
Content-Type: text/plain; charset=UTF-8
|
|
||||||
Content-Transfer-Encoding: 8bit
|
|
||||||
|
|
||||||
RH-Author: Eric Auger <eric.auger@redhat.com>
|
|
||||||
RH-MergeRequest: 211: IOMMUFD backend backport
|
|
||||||
RH-Jira: RHEL-19302 RHEL-21057
|
|
||||||
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
RH-Acked-by: Sebastian Ott <sebott@redhat.com>
|
|
||||||
RH-Commit: [59/67] f926e1233c8c5ad418e8794b1a103371c9dc5eb0 (eauger1/centos-qemu-kvm)
|
|
||||||
|
|
||||||
Commit 3d779abafe ("vfio/common: Introduce a global VFIODevice list")
|
|
||||||
introduced a global VFIODevice list, but forgot to update the list
|
|
||||||
element field name when iterating over the new list. Change the code
|
|
||||||
to use the correct list element field.
|
|
||||||
|
|
||||||
Fixes: 3d779abafe ("vfio/common: Introduce a global VFIODevice list")
|
|
||||||
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2061
|
|
||||||
Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
|
|
||||||
Reviewed-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
|
|
||||||
Reviewed-by: Cédric Le Goater <clg@redhat.com>
|
|
||||||
Reviewed-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
(cherry picked from commit 9353b6da430f90e47f352dbf6dc31120c8914da6)
|
|
||||||
Signed-off-by: Eric Auger <eric.auger@redhat.com>
|
|
||||||
---
|
|
||||||
hw/vfio/common.c | 8 ++++----
|
|
||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
|
|
||||||
index 0d4d8b8416..0b3352f2a9 100644
|
|
||||||
--- a/hw/vfio/common.c
|
|
||||||
+++ b/hw/vfio/common.c
|
|
||||||
@@ -73,7 +73,7 @@ bool vfio_mig_active(void)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
|
|
||||||
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
|
|
||||||
if (vbasedev->migration_blocker) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@@ -94,7 +94,7 @@ static bool vfio_multiple_devices_migration_is_supported(void)
|
|
||||||
unsigned int device_num = 0;
|
|
||||||
bool all_support_p2p = true;
|
|
||||||
|
|
||||||
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
|
|
||||||
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
|
|
||||||
if (vbasedev->migration) {
|
|
||||||
device_num++;
|
|
||||||
|
|
||||||
@@ -1366,13 +1366,13 @@ void vfio_reset_handler(void *opaque)
|
|
||||||
{
|
|
||||||
VFIODevice *vbasedev;
|
|
||||||
|
|
||||||
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
|
|
||||||
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
|
|
||||||
if (vbasedev->dev->realized) {
|
|
||||||
vbasedev->ops->vfio_compute_needs_reset(vbasedev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
|
|
||||||
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
|
|
||||||
if (vbasedev->dev->realized && vbasedev->needs_reset) {
|
|
||||||
vbasedev->ops->vfio_hot_reset_multi(vbasedev);
|
|
||||||
}
|
|
||||||
--
|
|
||||||
2.39.3
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
|||||||
|
From c554f8768a18ceba173aedbd582c1cae43a41e2c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Thomas Huth <thuth@redhat.com>
|
||||||
|
Date: Tue, 18 Jun 2024 14:19:58 +0200
|
||||||
|
Subject: [PATCH 1/2] hw/virtio: Fix the de-initialization of vhost-user
|
||||||
|
devices
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-MergeRequest: 255: hw/virtio: Fix the de-initialization of vhost-user devices
|
||||||
|
RH-Jira: RHEL-40708
|
||||||
|
RH-Acked-by: Cédric Le Goater <clg@redhat.com>
|
||||||
|
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||||
|
RH-Commit: [1/1] c7815a249ec135993f45934cab1c1f2c038b80ea (thuth/qemu-kvm-cs9)
|
||||||
|
|
||||||
|
JIRA: https://issues.redhat.com/browse/RHEL-40708
|
||||||
|
|
||||||
|
The unrealize functions of the various vhost-user devices are
|
||||||
|
calling the corresponding vhost_*_set_status() functions with a
|
||||||
|
status of 0 to shut down the device correctly.
|
||||||
|
|
||||||
|
Now these vhost_*_set_status() functions all follow this scheme:
|
||||||
|
|
||||||
|
bool should_start = virtio_device_should_start(vdev, status);
|
||||||
|
|
||||||
|
if (vhost_dev_is_started(&vvc->vhost_dev) == should_start) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_start) {
|
||||||
|
/* ... do the initialization stuff ... */
|
||||||
|
} else {
|
||||||
|
/* ... do the cleanup stuff ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
The problem here is virtio_device_should_start(vdev, 0) currently
|
||||||
|
always returns "true" since it internally only looks at vdev->started
|
||||||
|
instead of looking at the "status" parameter. Thus once the device
|
||||||
|
got started once, virtio_device_should_start() always returns true
|
||||||
|
and thus the vhost_*_set_status() functions return early, without
|
||||||
|
ever doing any clean-up when being called with status == 0. This
|
||||||
|
causes e.g. problems when trying to hot-plug and hot-unplug a vhost
|
||||||
|
user devices multiple times since the de-initialization step is
|
||||||
|
completely skipped during the unplug operation.
|
||||||
|
|
||||||
|
This bug has been introduced in commit 9f6bcfd99f ("hw/virtio: move
|
||||||
|
vm_running check to virtio_device_started") which replaced
|
||||||
|
|
||||||
|
should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
should_start = virtio_device_started(vdev, status);
|
||||||
|
|
||||||
|
which later got replaced by virtio_device_should_start(). This blocked
|
||||||
|
the possibility to set should_start to false in case the status flag
|
||||||
|
VIRTIO_CONFIG_S_DRIVER_OK was not set.
|
||||||
|
|
||||||
|
Fix it by adjusting the virtio_device_should_start() function to
|
||||||
|
only consider the status flag instead of vdev->started. Since this
|
||||||
|
function is only used in the various vhost_*_set_status() functions
|
||||||
|
for exactly the same purpose, it should be fine to fix it in this
|
||||||
|
central place there without any risk to change the behavior of other
|
||||||
|
code.
|
||||||
|
|
||||||
|
Fixes: 9f6bcfd99f ("hw/virtio: move vm_running check to virtio_device_started")
|
||||||
|
Buglink: https://issues.redhat.com/browse/RHEL-40708
|
||||||
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
Message-Id: <20240618121958.88673-1-thuth@redhat.com>
|
||||||
|
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||||
|
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||||
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||||
|
(cherry picked from commit d72479b11797c28893e1e3fc565497a9cae5ca16)
|
||||||
|
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
---
|
||||||
|
include/hw/virtio/virtio.h | 8 ++++----
|
||||||
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
|
||||||
|
index 7d5ffdc145..2eafad17b8 100644
|
||||||
|
--- a/include/hw/virtio/virtio.h
|
||||||
|
+++ b/include/hw/virtio/virtio.h
|
||||||
|
@@ -470,9 +470,9 @@ static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status)
|
||||||
|
* @vdev - the VirtIO device
|
||||||
|
* @status - the devices status bits
|
||||||
|
*
|
||||||
|
- * This is similar to virtio_device_started() but also encapsulates a
|
||||||
|
- * check on the VM status which would prevent a device starting
|
||||||
|
- * anyway.
|
||||||
|
+ * This is similar to virtio_device_started() but ignores vdev->started
|
||||||
|
+ * and also encapsulates a check on the VM status which would prevent a
|
||||||
|
+ * device from starting anyway.
|
||||||
|
*/
|
||||||
|
static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status)
|
||||||
|
{
|
||||||
|
@@ -480,7 +480,7 @@ static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- return virtio_device_started(vdev, status);
|
||||||
|
+ return status & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void virtio_set_started(VirtIODevice *vdev, bool started)
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,68 @@
|
|||||||
|
From f572a40924c7138072e387111d0f092185972477 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Thu, 9 May 2024 19:00:39 +0200
|
||||||
|
Subject: [PATCH 044/100] i386: correctly select code in hw/i386 that depends
|
||||||
|
on other components
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [44/91] 1327a5eb2b91edacf56cc4e93255cad456abbbeb (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
fw_cfg.c and vapic.c are currently included unconditionally but
|
||||||
|
depend on other components. vapic.c depends on the local APIC,
|
||||||
|
while fw_cfg.c includes a piece of AML builder code that depends
|
||||||
|
on CONFIG_ACPI.
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||||
|
Message-ID: <20240509170044.190795-9-pbonzini@redhat.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 7974e51342775c87f6e759a8c525db1045ddfa24)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/fw_cfg.c | 2 ++
|
||||||
|
hw/i386/meson.build | 2 +-
|
||||||
|
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
|
||||||
|
index 283c3f4c16..7f97d40616 100644
|
||||||
|
--- a/hw/i386/fw_cfg.c
|
||||||
|
+++ b/hw/i386/fw_cfg.c
|
||||||
|
@@ -204,6 +204,7 @@ void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg)
|
||||||
|
fw_cfg_add_file(fw_cfg, "etc/msr_feature_control", val, sizeof(*val));
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef CONFIG_ACPI
|
||||||
|
void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
@@ -230,3 +231,4 @@ void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg)
|
||||||
|
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||||
|
aml_append(scope, dev);
|
||||||
|
}
|
||||||
|
+#endif
|
||||||
|
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
|
||||||
|
index d8b70ef3e9..d9da676038 100644
|
||||||
|
--- a/hw/i386/meson.build
|
||||||
|
+++ b/hw/i386/meson.build
|
||||||
|
@@ -1,12 +1,12 @@
|
||||||
|
i386_ss = ss.source_set()
|
||||||
|
i386_ss.add(files(
|
||||||
|
'fw_cfg.c',
|
||||||
|
- 'vapic.c',
|
||||||
|
'e820_memory_layout.c',
|
||||||
|
'multiboot.c',
|
||||||
|
'x86.c',
|
||||||
|
))
|
||||||
|
|
||||||
|
+i386_ss.add(when: 'CONFIG_APIC', if_true: files('vapic.c'))
|
||||||
|
i386_ss.add(when: 'CONFIG_X86_IOMMU', if_true: files('x86-iommu.c'),
|
||||||
|
if_false: files('x86-iommu-stub.c'))
|
||||||
|
i386_ss.add(when: 'CONFIG_AMD_IOMMU', if_true: files('amd_iommu.c'),
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
From 127f3c60668e1bd08ec00856a317cb841adf0440 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:23 -0500
|
||||||
|
Subject: [PATCH 063/100] i386/cpu: Set SEV-SNP CPUID bit when SNP enabled
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [63/91] 0f834a6897c5cdc0e29a5b1862e621f8ce309657 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SNP guests will rely on this bit to determine certain feature support.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-12-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 7831221941cccbde922412c1550ed8b4bce7c361)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/cpu.c | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||||
|
index 489c853b42..13737cd703 100644
|
||||||
|
--- a/target/i386/cpu.c
|
||||||
|
+++ b/target/i386/cpu.c
|
||||||
|
@@ -6822,6 +6822,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||||
|
if (sev_enabled()) {
|
||||||
|
*eax = 0x2;
|
||||||
|
*eax |= sev_es_enabled() ? 0x8 : 0;
|
||||||
|
+ *eax |= sev_snp_enabled() ? 0x10 : 0;
|
||||||
|
*ebx = sev_get_cbit_position() & 0x3f; /* EBX[5:0] */
|
||||||
|
*ebx |= (sev_get_reduced_phys_bits() & 0x3f) << 6; /* EBX[11:6] */
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,145 @@
|
|||||||
|
From 14aa42bbacde75b2ce9a59d1267f73d613026461 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:42 -0500
|
||||||
|
Subject: [PATCH 076/100] i386/kvm: Add KVM_EXIT_HYPERCALL handling for
|
||||||
|
KVM_HC_MAP_GPA_RANGE
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [76/91] 3e1201c330dc826af1ec4650974d47053270eb16 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
KVM_HC_MAP_GPA_RANGE will be used to send requests to userspace for
|
||||||
|
private/shared memory attribute updates requested by the guest.
|
||||||
|
Implement handling for that use-case along with some basic
|
||||||
|
infrastructure for enabling specific hypercall events.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-31-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 47e76d03b155e43beca550251a6eb7ea926c059f)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm.c | 55 ++++++++++++++++++++++++++++++++++++
|
||||||
|
target/i386/kvm/kvm_i386.h | 1 +
|
||||||
|
target/i386/kvm/trace-events | 1 +
|
||||||
|
3 files changed, 57 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index 75e75d9772..2935e3931a 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -21,6 +21,7 @@
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include <linux/kvm.h>
|
||||||
|
+#include <linux/kvm_para.h>
|
||||||
|
#include "standard-headers/asm-x86/kvm_para.h"
|
||||||
|
#include "hw/xen/interface/arch-x86/cpuid.h"
|
||||||
|
|
||||||
|
@@ -208,6 +209,13 @@ int kvm_get_vm_type(MachineState *ms)
|
||||||
|
return kvm_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool kvm_enable_hypercall(uint64_t enable_mask)
|
||||||
|
+{
|
||||||
|
+ KVMState *s = KVM_STATE(current_accel());
|
||||||
|
+
|
||||||
|
+ return !kvm_vm_enable_cap(s, KVM_CAP_EXIT_HYPERCALL, 0, enable_mask);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool kvm_has_smm(void)
|
||||||
|
{
|
||||||
|
return kvm_vm_check_extension(kvm_state, KVM_CAP_X86_SMM);
|
||||||
|
@@ -5325,6 +5333,50 @@ static bool host_supports_vmx(void)
|
||||||
|
return ecx & CPUID_EXT_VMX;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Currently the handling here only supports use of KVM_HC_MAP_GPA_RANGE
|
||||||
|
+ * to service guest-initiated memory attribute update requests so that
|
||||||
|
+ * KVM_SET_MEMORY_ATTRIBUTES can update whether or not a page should be
|
||||||
|
+ * backed by the private memory pool provided by guest_memfd, and as such
|
||||||
|
+ * is only applicable to guest_memfd-backed guests (e.g. SNP/TDX).
|
||||||
|
+ *
|
||||||
|
+ * Other other use-cases for KVM_HC_MAP_GPA_RANGE, such as for SEV live
|
||||||
|
+ * migration, are not implemented here currently.
|
||||||
|
+ *
|
||||||
|
+ * For the guest_memfd use-case, these exits will generally be synthesized
|
||||||
|
+ * by KVM based on platform-specific hypercalls, like GHCB requests in the
|
||||||
|
+ * case of SEV-SNP, and not issued directly within the guest though the
|
||||||
|
+ * KVM_HC_MAP_GPA_RANGE hypercall. So in this case, KVM_HC_MAP_GPA_RANGE is
|
||||||
|
+ * not actually advertised to guests via the KVM CPUID feature bit, as
|
||||||
|
+ * opposed to SEV live migration where it would be. Since it is unlikely the
|
||||||
|
+ * SEV live migration use-case would be useful for guest-memfd backed guests,
|
||||||
|
+ * because private/shared page tracking is already provided through other
|
||||||
|
+ * means, these 2 use-cases should be treated as being mutually-exclusive.
|
||||||
|
+ */
|
||||||
|
+static int kvm_handle_hc_map_gpa_range(struct kvm_run *run)
|
||||||
|
+{
|
||||||
|
+ uint64_t gpa, size, attributes;
|
||||||
|
+
|
||||||
|
+ if (!machine_require_guest_memfd(current_machine))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ gpa = run->hypercall.args[0];
|
||||||
|
+ size = run->hypercall.args[1] * TARGET_PAGE_SIZE;
|
||||||
|
+ attributes = run->hypercall.args[2];
|
||||||
|
+
|
||||||
|
+ trace_kvm_hc_map_gpa_range(gpa, size, attributes, run->hypercall.flags);
|
||||||
|
+
|
||||||
|
+ return kvm_convert_memory(gpa, size, attributes & KVM_MAP_GPA_RANGE_ENCRYPTED);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int kvm_handle_hypercall(struct kvm_run *run)
|
||||||
|
+{
|
||||||
|
+ if (run->hypercall.nr == KVM_HC_MAP_GPA_RANGE)
|
||||||
|
+ return kvm_handle_hc_map_gpa_range(run);
|
||||||
|
+
|
||||||
|
+ return -EINVAL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#define VMX_INVALID_GUEST_STATE 0x80000021
|
||||||
|
|
||||||
|
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
|
@@ -5420,6 +5472,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||||
|
ret = kvm_xen_handle_exit(cpu, &run->xen);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
+ case KVM_EXIT_HYPERCALL:
|
||||||
|
+ ret = kvm_handle_hypercall(run);
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
||||||
|
ret = -1;
|
||||||
|
diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h
|
||||||
|
index 6b44844d95..34fc60774b 100644
|
||||||
|
--- a/target/i386/kvm/kvm_i386.h
|
||||||
|
+++ b/target/i386/kvm/kvm_i386.h
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
bool kvm_has_smm(void);
|
||||||
|
bool kvm_enable_x2apic(void);
|
||||||
|
bool kvm_hv_vpindex_settable(void);
|
||||||
|
+bool kvm_enable_hypercall(uint64_t enable_mask);
|
||||||
|
|
||||||
|
bool kvm_enable_sgx_provisioning(KVMState *s);
|
||||||
|
bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp);
|
||||||
|
diff --git a/target/i386/kvm/trace-events b/target/i386/kvm/trace-events
|
||||||
|
index b365a8e8e2..74a6234ff7 100644
|
||||||
|
--- a/target/i386/kvm/trace-events
|
||||||
|
+++ b/target/i386/kvm/trace-events
|
||||||
|
@@ -5,6 +5,7 @@ kvm_x86_fixup_msi_error(uint32_t gsi) "VT-d failed to remap interrupt for GSI %"
|
||||||
|
kvm_x86_add_msi_route(int virq) "Adding route entry for virq %d"
|
||||||
|
kvm_x86_remove_msi_route(int virq) "Removing route entry for virq %d"
|
||||||
|
kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
|
||||||
|
+kvm_hc_map_gpa_range(uint64_t gpa, uint64_t size, uint64_t attributes, uint64_t flags) "gpa 0x%" PRIx64 " size 0x%" PRIx64 " attributes 0x%" PRIx64 " flags 0x%" PRIx64
|
||||||
|
|
||||||
|
# xen-emu.c
|
||||||
|
kvm_xen_hypercall(int cpu, uint8_t cpl, uint64_t input, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t ret) "xen_hypercall: cpu %d cpl %d input %" PRIu64 " a0 0x%" PRIx64 " a1 0x%" PRIx64 " a2 0x%" PRIx64" ret 0x%" PRIx64
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,536 @@
|
|||||||
|
From 5ead79f45e8e90b7a04586c89e70cb9d0b66b730 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Sean Christopherson <sean.j.christopherson@intel.com>
|
||||||
|
Date: Thu, 29 Feb 2024 01:36:43 -0500
|
||||||
|
Subject: [PATCH 004/100] i386/kvm: Move architectural CPUID leaf generation to
|
||||||
|
separate helper
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [4/91] 06ecdbcf05ad3d658273980b114f02477d0b0475 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Move the architectural (for lack of a better term) CPUID leaf generation
|
||||||
|
to a separate helper so that the generation code can be reused by TDX,
|
||||||
|
which needs to generate a canonical VM-scoped configuration.
|
||||||
|
|
||||||
|
For now this is just a cleanup, so keep the function static.
|
||||||
|
|
||||||
|
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
|
||||||
|
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Message-ID: <20240229063726.610065-23-xiaoyao.li@intel.com>
|
||||||
|
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a5acf4f26c208a05d05ef1bde65553ce2ab5e5d0)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm.c | 417 +++++++++++++++++++++---------------------
|
||||||
|
1 file changed, 211 insertions(+), 206 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index 739f33db47..5f30b649a0 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -1706,195 +1706,22 @@ static void kvm_init_nested_state(CPUX86State *env)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
+static uint32_t kvm_x86_build_cpuid(CPUX86State *env,
|
||||||
|
+ struct kvm_cpuid_entry2 *entries,
|
||||||
|
+ uint32_t cpuid_i)
|
||||||
|
{
|
||||||
|
- struct {
|
||||||
|
- struct kvm_cpuid2 cpuid;
|
||||||
|
- struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
|
||||||
|
- } cpuid_data;
|
||||||
|
- /*
|
||||||
|
- * The kernel defines these structs with padding fields so there
|
||||||
|
- * should be no extra padding in our cpuid_data struct.
|
||||||
|
- */
|
||||||
|
- QEMU_BUILD_BUG_ON(sizeof(cpuid_data) !=
|
||||||
|
- sizeof(struct kvm_cpuid2) +
|
||||||
|
- sizeof(struct kvm_cpuid_entry2) * KVM_MAX_CPUID_ENTRIES);
|
||||||
|
-
|
||||||
|
- X86CPU *cpu = X86_CPU(cs);
|
||||||
|
- CPUX86State *env = &cpu->env;
|
||||||
|
- uint32_t limit, i, j, cpuid_i;
|
||||||
|
+ uint32_t limit, i, j;
|
||||||
|
uint32_t unused;
|
||||||
|
struct kvm_cpuid_entry2 *c;
|
||||||
|
- uint32_t signature[3];
|
||||||
|
- int kvm_base = KVM_CPUID_SIGNATURE;
|
||||||
|
- int max_nested_state_len;
|
||||||
|
- int r;
|
||||||
|
- Error *local_err = NULL;
|
||||||
|
-
|
||||||
|
- memset(&cpuid_data, 0, sizeof(cpuid_data));
|
||||||
|
-
|
||||||
|
- cpuid_i = 0;
|
||||||
|
-
|
||||||
|
- has_xsave2 = kvm_check_extension(cs->kvm_state, KVM_CAP_XSAVE2);
|
||||||
|
-
|
||||||
|
- r = kvm_arch_set_tsc_khz(cs);
|
||||||
|
- if (r < 0) {
|
||||||
|
- return r;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /* vcpu's TSC frequency is either specified by user, or following
|
||||||
|
- * the value used by KVM if the former is not present. In the
|
||||||
|
- * latter case, we query it from KVM and record in env->tsc_khz,
|
||||||
|
- * so that vcpu's TSC frequency can be migrated later via this field.
|
||||||
|
- */
|
||||||
|
- if (!env->tsc_khz) {
|
||||||
|
- r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
|
||||||
|
- kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
|
||||||
|
- -ENOTSUP;
|
||||||
|
- if (r > 0) {
|
||||||
|
- env->tsc_khz = r;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * kvm_hyperv_expand_features() is called here for the second time in case
|
||||||
|
- * KVM_CAP_SYS_HYPERV_CPUID is not supported. While we can't possibly handle
|
||||||
|
- * 'query-cpu-model-expansion' in this case as we don't have a KVM vCPU to
|
||||||
|
- * check which Hyper-V enlightenments are supported and which are not, we
|
||||||
|
- * can still proceed and check/expand Hyper-V enlightenments here so legacy
|
||||||
|
- * behavior is preserved.
|
||||||
|
- */
|
||||||
|
- if (!kvm_hyperv_expand_features(cpu, &local_err)) {
|
||||||
|
- error_report_err(local_err);
|
||||||
|
- return -ENOSYS;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (hyperv_enabled(cpu)) {
|
||||||
|
- r = hyperv_init_vcpu(cpu);
|
||||||
|
- if (r) {
|
||||||
|
- return r;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- cpuid_i = hyperv_fill_cpuids(cs, cpuid_data.entries);
|
||||||
|
- kvm_base = KVM_CPUID_SIGNATURE_NEXT;
|
||||||
|
- has_msr_hv_hypercall = true;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (cs->kvm_state->xen_version) {
|
||||||
|
-#ifdef CONFIG_XEN_EMU
|
||||||
|
- struct kvm_cpuid_entry2 *xen_max_leaf;
|
||||||
|
-
|
||||||
|
- memcpy(signature, "XenVMMXenVMM", 12);
|
||||||
|
-
|
||||||
|
- xen_max_leaf = c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_SIGNATURE;
|
||||||
|
- c->eax = kvm_base + XEN_CPUID_TIME;
|
||||||
|
- c->ebx = signature[0];
|
||||||
|
- c->ecx = signature[1];
|
||||||
|
- c->edx = signature[2];
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_VENDOR;
|
||||||
|
- c->eax = cs->kvm_state->xen_version;
|
||||||
|
- c->ebx = 0;
|
||||||
|
- c->ecx = 0;
|
||||||
|
- c->edx = 0;
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_HVM_MSR;
|
||||||
|
- /* Number of hypercall-transfer pages */
|
||||||
|
- c->eax = 1;
|
||||||
|
- /* Hypercall MSR base address */
|
||||||
|
- if (hyperv_enabled(cpu)) {
|
||||||
|
- c->ebx = XEN_HYPERCALL_MSR_HYPERV;
|
||||||
|
- kvm_xen_init(cs->kvm_state, c->ebx);
|
||||||
|
- } else {
|
||||||
|
- c->ebx = XEN_HYPERCALL_MSR;
|
||||||
|
- }
|
||||||
|
- c->ecx = 0;
|
||||||
|
- c->edx = 0;
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_TIME;
|
||||||
|
- c->eax = ((!!tsc_is_stable_and_known(env) << 1) |
|
||||||
|
- (!!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP) << 2));
|
||||||
|
- /* default=0 (emulate if necessary) */
|
||||||
|
- c->ebx = 0;
|
||||||
|
- /* guest tsc frequency */
|
||||||
|
- c->ecx = env->user_tsc_khz;
|
||||||
|
- /* guest tsc incarnation (migration count) */
|
||||||
|
- c->edx = 0;
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
- xen_max_leaf->eax = kvm_base + XEN_CPUID_HVM;
|
||||||
|
- if (cs->kvm_state->xen_version >= XEN_VERSION(4, 5)) {
|
||||||
|
- c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
-
|
||||||
|
- if (cpu->xen_vapic) {
|
||||||
|
- c->eax |= XEN_HVM_CPUID_APIC_ACCESS_VIRT;
|
||||||
|
- c->eax |= XEN_HVM_CPUID_X2APIC_VIRT;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- c->eax |= XEN_HVM_CPUID_IOMMU_MAPPINGS;
|
||||||
|
-
|
||||||
|
- if (cs->kvm_state->xen_version >= XEN_VERSION(4, 6)) {
|
||||||
|
- c->eax |= XEN_HVM_CPUID_VCPU_ID_PRESENT;
|
||||||
|
- c->ebx = cs->cpu_index;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (cs->kvm_state->xen_version >= XEN_VERSION(4, 17)) {
|
||||||
|
- c->eax |= XEN_HVM_CPUID_UPCALL_VECTOR;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- r = kvm_xen_init_vcpu(cs);
|
||||||
|
- if (r) {
|
||||||
|
- return r;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- kvm_base += 0x100;
|
||||||
|
-#else /* CONFIG_XEN_EMU */
|
||||||
|
- /* This should never happen as kvm_arch_init() would have died first. */
|
||||||
|
- fprintf(stderr, "Cannot enable Xen CPUID without Xen support\n");
|
||||||
|
- abort();
|
||||||
|
-#endif
|
||||||
|
- } else if (cpu->expose_kvm) {
|
||||||
|
- memcpy(signature, "KVMKVMKVM\0\0\0", 12);
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = KVM_CPUID_SIGNATURE | kvm_base;
|
||||||
|
- c->eax = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
- c->ebx = signature[0];
|
||||||
|
- c->ecx = signature[1];
|
||||||
|
- c->edx = signature[2];
|
||||||
|
-
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
- c->function = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
- c->eax = env->features[FEAT_KVM];
|
||||||
|
- c->edx = env->features[FEAT_KVM_HINTS];
|
||||||
|
- }
|
||||||
|
|
||||||
|
cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
|
||||||
|
|
||||||
|
- if (cpu->kvm_pv_enforce_cpuid) {
|
||||||
|
- r = kvm_vcpu_enable_cap(cs, KVM_CAP_ENFORCE_PV_FEATURE_CPUID, 0, 1);
|
||||||
|
- if (r < 0) {
|
||||||
|
- fprintf(stderr,
|
||||||
|
- "failed to enable KVM_CAP_ENFORCE_PV_FEATURE_CPUID: %s",
|
||||||
|
- strerror(-r));
|
||||||
|
- abort();
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
for (i = 0; i <= limit; i++) {
|
||||||
|
+ j = 0;
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "unsupported level value: 0x%x\n", limit);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
-
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
switch (i) {
|
||||||
|
case 2: {
|
||||||
|
/* Keep reading function 2 till all the input is received */
|
||||||
|
@@ -1908,11 +1735,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
|
||||||
|
for (j = 1; j < times; ++j) {
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:2):eax & 0xf = 0x%x\n", times);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
c->function = i;
|
||||||
|
c->flags = KVM_CPUID_FLAG_STATEFUL_FUNC;
|
||||||
|
cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx);
|
||||||
|
@@ -1951,11 +1776,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x12:
|
||||||
|
@@ -1970,11 +1793,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x12,ecx:0x%x)\n", j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x7:
|
||||||
|
@@ -1991,11 +1812,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
|
||||||
|
for (j = 1; j <= times; ++j) {
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
c->function = i;
|
||||||
|
c->index = j;
|
||||||
|
c->flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
|
||||||
|
@@ -2048,11 +1867,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
cpu_x86_cpuid(env, 0x80000000, 0, &limit, &unused, &unused, &unused);
|
||||||
|
|
||||||
|
for (i = 0x80000000; i <= limit; i++) {
|
||||||
|
+ j = 0;
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "unsupported xlevel value: 0x%x\n", limit);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 0x8000001d:
|
||||||
|
@@ -2067,11 +1886,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
- "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
@@ -2094,11 +1911,11 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
cpu_x86_cpuid(env, 0xC0000000, 0, &limit, &unused, &unused, &unused);
|
||||||
|
|
||||||
|
for (i = 0xC0000000; i <= limit; i++) {
|
||||||
|
+ j = 0;
|
||||||
|
if (cpuid_i == KVM_MAX_CPUID_ENTRIES) {
|
||||||
|
- fprintf(stderr, "unsupported xlevel2 value: 0x%x\n", limit);
|
||||||
|
- abort();
|
||||||
|
+ goto full;
|
||||||
|
}
|
||||||
|
- c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c = &entries[cpuid_i++];
|
||||||
|
|
||||||
|
c->function = i;
|
||||||
|
c->flags = 0;
|
||||||
|
@@ -2106,6 +1923,194 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ return cpuid_i;
|
||||||
|
+
|
||||||
|
+full:
|
||||||
|
+ fprintf(stderr, "cpuid_data is full, no space for "
|
||||||
|
+ "cpuid(eax:0x%x,ecx:0x%x)\n", i, j);
|
||||||
|
+ abort();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int kvm_arch_init_vcpu(CPUState *cs)
|
||||||
|
+{
|
||||||
|
+ struct {
|
||||||
|
+ struct kvm_cpuid2 cpuid;
|
||||||
|
+ struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
|
||||||
|
+ } cpuid_data;
|
||||||
|
+ /*
|
||||||
|
+ * The kernel defines these structs with padding fields so there
|
||||||
|
+ * should be no extra padding in our cpuid_data struct.
|
||||||
|
+ */
|
||||||
|
+ QEMU_BUILD_BUG_ON(sizeof(cpuid_data) !=
|
||||||
|
+ sizeof(struct kvm_cpuid2) +
|
||||||
|
+ sizeof(struct kvm_cpuid_entry2) * KVM_MAX_CPUID_ENTRIES);
|
||||||
|
+
|
||||||
|
+ X86CPU *cpu = X86_CPU(cs);
|
||||||
|
+ CPUX86State *env = &cpu->env;
|
||||||
|
+ uint32_t cpuid_i;
|
||||||
|
+ struct kvm_cpuid_entry2 *c;
|
||||||
|
+ uint32_t signature[3];
|
||||||
|
+ int kvm_base = KVM_CPUID_SIGNATURE;
|
||||||
|
+ int max_nested_state_len;
|
||||||
|
+ int r;
|
||||||
|
+ Error *local_err = NULL;
|
||||||
|
+
|
||||||
|
+ memset(&cpuid_data, 0, sizeof(cpuid_data));
|
||||||
|
+
|
||||||
|
+ cpuid_i = 0;
|
||||||
|
+
|
||||||
|
+ has_xsave2 = kvm_check_extension(cs->kvm_state, KVM_CAP_XSAVE2);
|
||||||
|
+
|
||||||
|
+ r = kvm_arch_set_tsc_khz(cs);
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* vcpu's TSC frequency is either specified by user, or following
|
||||||
|
+ * the value used by KVM if the former is not present. In the
|
||||||
|
+ * latter case, we query it from KVM and record in env->tsc_khz,
|
||||||
|
+ * so that vcpu's TSC frequency can be migrated later via this field.
|
||||||
|
+ */
|
||||||
|
+ if (!env->tsc_khz) {
|
||||||
|
+ r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
|
||||||
|
+ kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
|
||||||
|
+ -ENOTSUP;
|
||||||
|
+ if (r > 0) {
|
||||||
|
+ env->tsc_khz = r;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ env->apic_bus_freq = KVM_APIC_BUS_FREQUENCY;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * kvm_hyperv_expand_features() is called here for the second time in case
|
||||||
|
+ * KVM_CAP_SYS_HYPERV_CPUID is not supported. While we can't possibly handle
|
||||||
|
+ * 'query-cpu-model-expansion' in this case as we don't have a KVM vCPU to
|
||||||
|
+ * check which Hyper-V enlightenments are supported and which are not, we
|
||||||
|
+ * can still proceed and check/expand Hyper-V enlightenments here so legacy
|
||||||
|
+ * behavior is preserved.
|
||||||
|
+ */
|
||||||
|
+ if (!kvm_hyperv_expand_features(cpu, &local_err)) {
|
||||||
|
+ error_report_err(local_err);
|
||||||
|
+ return -ENOSYS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (hyperv_enabled(cpu)) {
|
||||||
|
+ r = hyperv_init_vcpu(cpu);
|
||||||
|
+ if (r) {
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cpuid_i = hyperv_fill_cpuids(cs, cpuid_data.entries);
|
||||||
|
+ kvm_base = KVM_CPUID_SIGNATURE_NEXT;
|
||||||
|
+ has_msr_hv_hypercall = true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cs->kvm_state->xen_version) {
|
||||||
|
+#ifdef CONFIG_XEN_EMU
|
||||||
|
+ struct kvm_cpuid_entry2 *xen_max_leaf;
|
||||||
|
+
|
||||||
|
+ memcpy(signature, "XenVMMXenVMM", 12);
|
||||||
|
+
|
||||||
|
+ xen_max_leaf = c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_SIGNATURE;
|
||||||
|
+ c->eax = kvm_base + XEN_CPUID_TIME;
|
||||||
|
+ c->ebx = signature[0];
|
||||||
|
+ c->ecx = signature[1];
|
||||||
|
+ c->edx = signature[2];
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_VENDOR;
|
||||||
|
+ c->eax = cs->kvm_state->xen_version;
|
||||||
|
+ c->ebx = 0;
|
||||||
|
+ c->ecx = 0;
|
||||||
|
+ c->edx = 0;
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_HVM_MSR;
|
||||||
|
+ /* Number of hypercall-transfer pages */
|
||||||
|
+ c->eax = 1;
|
||||||
|
+ /* Hypercall MSR base address */
|
||||||
|
+ if (hyperv_enabled(cpu)) {
|
||||||
|
+ c->ebx = XEN_HYPERCALL_MSR_HYPERV;
|
||||||
|
+ kvm_xen_init(cs->kvm_state, c->ebx);
|
||||||
|
+ } else {
|
||||||
|
+ c->ebx = XEN_HYPERCALL_MSR;
|
||||||
|
+ }
|
||||||
|
+ c->ecx = 0;
|
||||||
|
+ c->edx = 0;
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_TIME;
|
||||||
|
+ c->eax = ((!!tsc_is_stable_and_known(env) << 1) |
|
||||||
|
+ (!!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP) << 2));
|
||||||
|
+ /* default=0 (emulate if necessary) */
|
||||||
|
+ c->ebx = 0;
|
||||||
|
+ /* guest tsc frequency */
|
||||||
|
+ c->ecx = env->user_tsc_khz;
|
||||||
|
+ /* guest tsc incarnation (migration count) */
|
||||||
|
+ c->edx = 0;
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
+ xen_max_leaf->eax = kvm_base + XEN_CPUID_HVM;
|
||||||
|
+ if (cs->kvm_state->xen_version >= XEN_VERSION(4, 5)) {
|
||||||
|
+ c->function = kvm_base + XEN_CPUID_HVM;
|
||||||
|
+
|
||||||
|
+ if (cpu->xen_vapic) {
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_APIC_ACCESS_VIRT;
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_X2APIC_VIRT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_IOMMU_MAPPINGS;
|
||||||
|
+
|
||||||
|
+ if (cs->kvm_state->xen_version >= XEN_VERSION(4, 6)) {
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_VCPU_ID_PRESENT;
|
||||||
|
+ c->ebx = cs->cpu_index;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cs->kvm_state->xen_version >= XEN_VERSION(4, 17)) {
|
||||||
|
+ c->eax |= XEN_HVM_CPUID_UPCALL_VECTOR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ r = kvm_xen_init_vcpu(cs);
|
||||||
|
+ if (r) {
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ kvm_base += 0x100;
|
||||||
|
+#else /* CONFIG_XEN_EMU */
|
||||||
|
+ /* This should never happen as kvm_arch_init() would have died first. */
|
||||||
|
+ fprintf(stderr, "Cannot enable Xen CPUID without Xen support\n");
|
||||||
|
+ abort();
|
||||||
|
+#endif
|
||||||
|
+ } else if (cpu->expose_kvm) {
|
||||||
|
+ memcpy(signature, "KVMKVMKVM\0\0\0", 12);
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = KVM_CPUID_SIGNATURE | kvm_base;
|
||||||
|
+ c->eax = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
+ c->ebx = signature[0];
|
||||||
|
+ c->ecx = signature[1];
|
||||||
|
+ c->edx = signature[2];
|
||||||
|
+
|
||||||
|
+ c = &cpuid_data.entries[cpuid_i++];
|
||||||
|
+ c->function = KVM_CPUID_FEATURES | kvm_base;
|
||||||
|
+ c->eax = env->features[FEAT_KVM];
|
||||||
|
+ c->edx = env->features[FEAT_KVM_HINTS];
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (cpu->kvm_pv_enforce_cpuid) {
|
||||||
|
+ r = kvm_vcpu_enable_cap(cs, KVM_CAP_ENFORCE_PV_FEATURE_CPUID, 0, 1);
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ fprintf(stderr,
|
||||||
|
+ "failed to enable KVM_CAP_ENFORCE_PV_FEATURE_CPUID: %s",
|
||||||
|
+ strerror(-r));
|
||||||
|
+ abort();
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ cpuid_i = kvm_x86_build_cpuid(env, cpuid_data.entries, cpuid_i);
|
||||||
|
cpuid_data.cpuid.nent = cpuid_i;
|
||||||
|
|
||||||
|
if (((env->cpuid_version >> 8)&0xF) >= 6
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,91 @@
|
|||||||
|
From 03e275023b482ac79b4f92ca4ceef6de3caa634f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Thu, 9 May 2024 19:00:40 +0200
|
||||||
|
Subject: [PATCH 045/100] i386: pc: remove unnecessary MachineClass overrides
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [45/91] c03d5b57014d0d02f6ce0cdfb19a34996d100dea (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
There is no need to override these fields of MachineClass because they are
|
||||||
|
already set to the right value in the superclass.
|
||||||
|
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||||
|
Message-ID: <20240509170044.190795-10-pbonzini@redhat.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit b348fdcdac9f9fc70be9ae56c54e41765e9aae24)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 3 ---
|
||||||
|
hw/i386/x86.c | 6 +++---
|
||||||
|
include/hw/i386/x86.h | 4 ----
|
||||||
|
3 files changed, 3 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index 660a59c63b..0aca0cc79e 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -1979,9 +1979,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||||
|
mc->async_pf_vmexit_disable = false;
|
||||||
|
mc->get_hotplug_handler = pc_get_hotplug_handler;
|
||||||
|
mc->hotplug_allowed = pc_hotplug_allowed;
|
||||||
|
- mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
|
||||||
|
- mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
|
||||||
|
- mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
|
||||||
|
mc->auto_enable_numa_with_memhp = true;
|
||||||
|
mc->auto_enable_numa_with_memdev = true;
|
||||||
|
mc->has_hotpluggable_cpus = true;
|
||||||
|
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
|
||||||
|
index c61f4ebfa6..fcef652c1e 100644
|
||||||
|
--- a/hw/i386/x86.c
|
||||||
|
+++ b/hw/i386/x86.c
|
||||||
|
@@ -443,7 +443,7 @@ void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
|
numa_cpu_pre_plug(cpu_slot, dev, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
-CpuInstanceProperties
|
||||||
|
+static CpuInstanceProperties
|
||||||
|
x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||||
|
@@ -453,7 +453,7 @@ x86_cpu_index_to_props(MachineState *ms, unsigned cpu_index)
|
||||||
|
return possible_cpus->cpus[cpu_index].props;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||||
|
+static int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||||
|
{
|
||||||
|
X86CPUTopoIDs topo_ids;
|
||||||
|
X86MachineState *x86ms = X86_MACHINE(ms);
|
||||||
|
@@ -467,7 +467,7 @@ int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||||
|
return topo_ids.pkg_id % ms->numa_state->num_nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
|
||||||
|
+static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)
|
||||||
|
{
|
||||||
|
X86MachineState *x86ms = X86_MACHINE(ms);
|
||||||
|
unsigned int max_cpus = ms->smp.max_cpus;
|
||||||
|
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
|
||||||
|
index d7b7d3f3ce..c2062db13f 100644
|
||||||
|
--- a/include/hw/i386/x86.h
|
||||||
|
+++ b/include/hw/i386/x86.h
|
||||||
|
@@ -114,10 +114,6 @@ uint32_t x86_cpu_apic_id_from_index(X86MachineState *pcms,
|
||||||
|
|
||||||
|
void x86_cpu_new(X86MachineState *pcms, int64_t apic_id, Error **errp);
|
||||||
|
void x86_cpus_init(X86MachineState *pcms, int default_cpu_version);
|
||||||
|
-CpuInstanceProperties x86_cpu_index_to_props(MachineState *ms,
|
||||||
|
- unsigned cpu_index);
|
||||||
|
-int64_t x86_get_default_cpu_node_id(const MachineState *ms, int idx);
|
||||||
|
-const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms);
|
||||||
|
CPUArchId *x86_find_cpu_slot(MachineState *ms, uint32_t id, int *idx);
|
||||||
|
void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count);
|
||||||
|
void x86_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,116 @@
|
|||||||
|
From 652793962000d6906e219ceae36348a476b78c28 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Fri, 31 May 2024 12:44:44 +0200
|
||||||
|
Subject: [PATCH 065/100] i386/sev: Add a class method to determine KVM VM type
|
||||||
|
for SNP guests
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [65/91] c6cbeac0a6f691138df212b80efaa9b1143fdaa8 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SEV guests can use either KVM_X86_DEFAULT_VM, KVM_X86_SEV_VM,
|
||||||
|
or KVM_X86_SEV_ES_VM depending on the configuration and what
|
||||||
|
the host kernel supports. SNP guests on the other hand can only
|
||||||
|
ever use KVM_X86_SNP_VM, so split determination of VM type out
|
||||||
|
into a separate class method that can be set accordingly for
|
||||||
|
sev-guest vs. sev-snp-guest objects and add handling for SNP.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-14-pankaj.gupta@amd.com>
|
||||||
|
[Remove unnecessary function pointer declaration. - Paolo]
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit a808132f6d8e855bd83a400570ec91d2e00bebe3)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/kvm/kvm.c | 1 +
|
||||||
|
target/i386/sev.c | 15 ++++++++++++---
|
||||||
|
2 files changed, 13 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||||
|
index 408568d053..75e75d9772 100644
|
||||||
|
--- a/target/i386/kvm/kvm.c
|
||||||
|
+++ b/target/i386/kvm/kvm.c
|
||||||
|
@@ -166,6 +166,7 @@ static const char *vm_type_name[] = {
|
||||||
|
[KVM_X86_DEFAULT_VM] = "default",
|
||||||
|
[KVM_X86_SEV_VM] = "SEV",
|
||||||
|
[KVM_X86_SEV_ES_VM] = "SEV-ES",
|
||||||
|
+ [KVM_X86_SNP_VM] = "SEV-SNP",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool kvm_is_vm_type_supported(int type)
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index c3daaf1ad5..072cc4f853 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -885,6 +885,11 @@ out:
|
||||||
|
return sev_common->kvm_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int sev_snp_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
+{
|
||||||
|
+ return KVM_X86_SNP_VM;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
{
|
||||||
|
char *devname;
|
||||||
|
@@ -894,6 +899,8 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs);
|
||||||
|
+ X86ConfidentialGuestClass *x86_klass =
|
||||||
|
+ X86_CONFIDENTIAL_GUEST_GET_CLASS(cgs);
|
||||||
|
|
||||||
|
sev_common->state = SEV_STATE_UNINIT;
|
||||||
|
|
||||||
|
@@ -964,7 +971,7 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_kvm_sev_init();
|
||||||
|
- if (sev_kvm_type(X86_CONFIDENTIAL_GUEST(sev_common)) == KVM_X86_DEFAULT_VM) {
|
||||||
|
+ if (x86_klass->kvm_type(X86_CONFIDENTIAL_GUEST(sev_common)) == KVM_X86_DEFAULT_VM) {
|
||||||
|
cmd = sev_es_enabled() ? KVM_SEV_ES_INIT : KVM_SEV_INIT;
|
||||||
|
|
||||||
|
ret = sev_ioctl(sev_common->sev_fd, cmd, NULL, &fw_error);
|
||||||
|
@@ -1441,10 +1448,8 @@ static void
|
||||||
|
sev_common_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
|
||||||
|
- X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->kvm_init = sev_common_kvm_init;
|
||||||
|
- x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "sev-device",
|
||||||
|
sev_common_get_sev_device,
|
||||||
|
@@ -1529,10 +1534,12 @@ static void
|
||||||
|
sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
+ X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
klass->kvm_init = sev_kvm_init;
|
||||||
|
+ x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
sev_guest_get_dh_cert_file,
|
||||||
|
@@ -1770,8 +1777,10 @@ static void
|
||||||
|
sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
+ X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
+ x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,84 @@
|
|||||||
|
From 82a714b79851b5c2d1389d2fa7a01548c486a854 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:20 -0500
|
||||||
|
Subject: [PATCH 060/100] i386/sev: Add a sev_snp_enabled() helper
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [60/91] c35ead095028ccfb1e1be0fe010ca4f7688530a0 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add a simple helper to check if the current guest type is SNP. Also have
|
||||||
|
SNP-enabled imply that SEV-ES is enabled as well, and fix up any places
|
||||||
|
where the sev_es_enabled() check is expecting a pure/non-SNP guest.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-9-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 99190f805dca9475fe244fbd8041961842657dc2)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 13 ++++++++++++-
|
||||||
|
target/i386/sev.h | 2 ++
|
||||||
|
2 files changed, 14 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index a81b3228d4..4edfedc139 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -325,12 +325,21 @@ sev_enabled(void)
|
||||||
|
return !!object_dynamic_cast(OBJECT(cgs), TYPE_SEV_COMMON);
|
||||||
|
}
|
||||||
|
|
||||||
|
+bool
|
||||||
|
+sev_snp_enabled(void)
|
||||||
|
+{
|
||||||
|
+ ConfidentialGuestSupport *cgs = MACHINE(qdev_get_machine())->cgs;
|
||||||
|
+
|
||||||
|
+ return !!object_dynamic_cast(OBJECT(cgs), TYPE_SEV_SNP_GUEST);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool
|
||||||
|
sev_es_enabled(void)
|
||||||
|
{
|
||||||
|
ConfidentialGuestSupport *cgs = MACHINE(qdev_get_machine())->cgs;
|
||||||
|
|
||||||
|
- return sev_enabled() && (SEV_GUEST(cgs)->policy & SEV_POLICY_ES);
|
||||||
|
+ return sev_snp_enabled() ||
|
||||||
|
+ (sev_enabled() && SEV_GUEST(cgs)->policy & SEV_POLICY_ES);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
@@ -946,7 +955,9 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
"support", __func__);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
+ }
|
||||||
|
|
||||||
|
+ if (sev_es_enabled() && !sev_snp_enabled()) {
|
||||||
|
if (!(status.flags & SEV_STATUS_FLAGS_CONFIG_ES)) {
|
||||||
|
error_setg(errp, "%s: guest policy requires SEV-ES, but "
|
||||||
|
"host SEV-ES support unavailable",
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index bedc667eeb..94295ee74f 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -45,9 +45,11 @@ typedef struct SevKernelLoaderContext {
|
||||||
|
#ifdef CONFIG_SEV
|
||||||
|
bool sev_enabled(void);
|
||||||
|
bool sev_es_enabled(void);
|
||||||
|
+bool sev_snp_enabled(void);
|
||||||
|
#else
|
||||||
|
#define sev_enabled() 0
|
||||||
|
#define sev_es_enabled() 0
|
||||||
|
+#define sev_snp_enabled() 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t sev_get_cbit_position(void);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,187 @@
|
|||||||
|
From 0e435819540b0d39da2c828aacc0f35ecaadbdf6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:28 -0500
|
||||||
|
Subject: [PATCH 068/100] i386/sev: Add handling to encrypt/finalize guest
|
||||||
|
launch data
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [68/91] fe77931d279aa8df061823da88a320fb5f72ffea (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Process any queued up launch data and encrypt/measure it into the SNP
|
||||||
|
guest instance prior to initial guest launch.
|
||||||
|
|
||||||
|
This also updates the KVM_SEV_SNP_LAUNCH_UPDATE call to handle partial
|
||||||
|
update responses.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Co-developed-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-17-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 9f3a6999f9730a694d7db448a99f9c9cb6515992)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 112 ++++++++++++++++++++++++++++++++++++++-
|
||||||
|
target/i386/trace-events | 2 +
|
||||||
|
2 files changed, 113 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index e89b87d2f5..ef2e592ca7 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -756,6 +756,76 @@ out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static const char *
|
||||||
|
+snp_page_type_to_str(int type)
|
||||||
|
+{
|
||||||
|
+ switch (type) {
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_NORMAL: return "Normal";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_ZERO: return "Zero";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_UNMEASURED: return "Unmeasured";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_SECRETS: return "Secrets";
|
||||||
|
+ case KVM_SEV_SNP_PAGE_TYPE_CPUID: return "Cpuid";
|
||||||
|
+ default: return "unknown";
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
+ SevLaunchUpdateData *data)
|
||||||
|
+{
|
||||||
|
+ int ret, fw_error;
|
||||||
|
+ struct kvm_sev_snp_launch_update update = {0};
|
||||||
|
+
|
||||||
|
+ if (!data->hva || !data->len) {
|
||||||
|
+ error_report("SNP_LAUNCH_UPDATE called with invalid address"
|
||||||
|
+ "/ length: %p / %lx",
|
||||||
|
+ data->hva, data->len);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ update.uaddr = (__u64)(unsigned long)data->hva;
|
||||||
|
+ update.gfn_start = data->gpa >> TARGET_PAGE_BITS;
|
||||||
|
+ update.len = data->len;
|
||||||
|
+ update.type = data->type;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * KVM_SEV_SNP_LAUNCH_UPDATE requires that GPA ranges have the private
|
||||||
|
+ * memory attribute set in advance.
|
||||||
|
+ */
|
||||||
|
+ ret = kvm_set_memory_attributes_private(data->gpa, data->len);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SEV-SNP: failed to configure initial"
|
||||||
|
+ "private guest memory");
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (update.len || ret == -EAGAIN) {
|
||||||
|
+ trace_kvm_sev_snp_launch_update(update.uaddr, update.gfn_start <<
|
||||||
|
+ TARGET_PAGE_BITS, update.len,
|
||||||
|
+ snp_page_type_to_str(update.type));
|
||||||
|
+
|
||||||
|
+ ret = sev_ioctl(SEV_COMMON(sev_snp_guest)->sev_fd,
|
||||||
|
+ KVM_SEV_SNP_LAUNCH_UPDATE,
|
||||||
|
+ &update, &fw_error);
|
||||||
|
+ if (ret && ret != -EAGAIN) {
|
||||||
|
+ error_report("SNP_LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
|
||||||
|
+ ret, fw_error, fw_error_to_str(fw_error));
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ if (!ret && update.gfn_start << TARGET_PAGE_BITS != data->gpa + data->len) {
|
||||||
|
+ error_report("SEV-SNP: expected update of GPA range %lx-%lx,"
|
||||||
|
+ "got GPA range %lx-%llx",
|
||||||
|
+ data->gpa, data->gpa + data->len, data->gpa,
|
||||||
|
+ update.gfn_start << TARGET_PAGE_BITS);
|
||||||
|
+ ret = -EIO;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_launch_update_data(SevGuestState *sev_guest, uint8_t *addr, uint64_t len)
|
||||||
|
{
|
||||||
|
@@ -901,6 +971,46 @@ sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
migrate_add_blocker(&sev_mig_blocker, &error_fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+sev_snp_launch_finish(SevCommonState *sev_common)
|
||||||
|
+{
|
||||||
|
+ int ret, error;
|
||||||
|
+ Error *local_err = NULL;
|
||||||
|
+ SevLaunchUpdateData *data;
|
||||||
|
+ SevSnpGuestState *sev_snp = SEV_SNP_GUEST(sev_common);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp->kvm_finish_conf;
|
||||||
|
+
|
||||||
|
+ QTAILQ_FOREACH(data, &launch_update, next) {
|
||||||
|
+ ret = sev_snp_launch_update(sev_snp, data);
|
||||||
|
+ if (ret) {
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ trace_kvm_sev_snp_launch_finish(sev_snp->id_block, sev_snp->id_auth,
|
||||||
|
+ sev_snp->host_data);
|
||||||
|
+ ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_LAUNCH_FINISH,
|
||||||
|
+ finish, &error);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SNP_LAUNCH_FINISH ret=%d fw_error=%d '%s'",
|
||||||
|
+ ret, error, fw_error_to_str(error));
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sev_set_guest_state(sev_common, SEV_STATE_RUNNING);
|
||||||
|
+
|
||||||
|
+ /* add migration blocker */
|
||||||
|
+ error_setg(&sev_mig_blocker,
|
||||||
|
+ "SEV-SNP: Migration is not implemented");
|
||||||
|
+ ret = migrate_add_blocker(&sev_mig_blocker, &local_err);
|
||||||
|
+ if (local_err) {
|
||||||
|
+ error_report_err(local_err);
|
||||||
|
+ error_free(sev_mig_blocker);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
|
{
|
||||||
|
@@ -1832,10 +1942,10 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
klass->launch_start = sev_snp_launch_start;
|
||||||
|
+ klass->launch_finish = sev_snp_launch_finish;
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
-
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||||||
|
index cb26d8a925..06b44ead2e 100644
|
||||||
|
--- a/target/i386/trace-events
|
||||||
|
+++ b/target/i386/trace-events
|
||||||
|
@@ -12,3 +12,5 @@ kvm_sev_launch_finish(void) ""
|
||||||
|
kvm_sev_launch_secret(uint64_t hpa, uint64_t hva, uint64_t secret, int len) "hpa 0x%" PRIx64 " hva 0x%" PRIx64 " data 0x%" PRIx64 " len %d"
|
||||||
|
kvm_sev_attestation_report(const char *mnonce, const char *data) "mnonce %s data %s"
|
||||||
|
kvm_sev_snp_launch_start(uint64_t policy, char *gosvw) "policy 0x%" PRIx64 " gosvw %s"
|
||||||
|
+kvm_sev_snp_launch_update(uint64_t src, uint64_t gpa, uint64_t len, const char *type) "src 0x%" PRIx64 " gpa 0x%" PRIx64 " len 0x%" PRIx64 " (%s page)"
|
||||||
|
+kvm_sev_snp_launch_finish(char *id_block, char *id_auth, char *host_data) "id_block %s id_auth %s host_data %s"
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,127 @@
|
|||||||
|
From 2872c423fa44dcbf50b581a5c3feac064a0473a0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Tue, 9 Apr 2024 18:07:41 -0500
|
||||||
|
Subject: [PATCH 024/100] i386/sev: Add 'legacy-vm-type' parameter for SEV
|
||||||
|
guest objects
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [24/91] ce35d1b09fe8aa8772ff149543f7760455c1e6b5 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
QEMU will currently automatically make use of the KVM_SEV_INIT2 API for
|
||||||
|
initializing SEV and SEV-ES guests verses the older
|
||||||
|
KVM_SEV_INIT/KVM_SEV_ES_INIT interfaces.
|
||||||
|
|
||||||
|
However, the older interfaces will silently avoid sync'ing FPU/XSAVE
|
||||||
|
state to the VMSA prior to encryption, thus relying on behavior and
|
||||||
|
measurements that assume the related fields to be allow zero.
|
||||||
|
|
||||||
|
With KVM_SEV_INIT2, this state is now synced into the VMSA, resulting in
|
||||||
|
measurements changes and, theoretically, behaviorial changes, though the
|
||||||
|
latter are unlikely to be seen in practice.
|
||||||
|
|
||||||
|
To allow a smooth transition to the newer interface, while still
|
||||||
|
providing a mechanism to maintain backward compatibility with VMs
|
||||||
|
created using the older interfaces, provide a new command-line
|
||||||
|
parameter:
|
||||||
|
|
||||||
|
-object sev-guest,legacy-vm-type=true,...
|
||||||
|
|
||||||
|
and have it default to false.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Message-ID: <20240409230743.962513-2-michael.roth@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 023267334da375226720e62963df9545aa8fc2fd)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
qapi/qom.json | 11 ++++++++++-
|
||||||
|
target/i386/sev.c | 18 +++++++++++++++++-
|
||||||
|
2 files changed, 27 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/qapi/qom.json b/qapi/qom.json
|
||||||
|
index 85e6b4f84a..38dde6d785 100644
|
||||||
|
--- a/qapi/qom.json
|
||||||
|
+++ b/qapi/qom.json
|
||||||
|
@@ -898,6 +898,14 @@
|
||||||
|
# designated guest firmware page for measured boot with -kernel
|
||||||
|
# (default: false) (since 6.2)
|
||||||
|
#
|
||||||
|
+# @legacy-vm-type: Use legacy KVM_SEV_INIT KVM interface for creating the VM.
|
||||||
|
+# The newer KVM_SEV_INIT2 interface syncs additional vCPU
|
||||||
|
+# state when initializing the VMSA structures, which will
|
||||||
|
+# result in a different guest measurement. Set this to
|
||||||
|
+# maintain compatibility with older QEMU or kernel versions
|
||||||
|
+# that rely on legacy KVM_SEV_INIT behavior.
|
||||||
|
+# (default: false) (since 9.1)
|
||||||
|
+#
|
||||||
|
# Since: 2.12
|
||||||
|
##
|
||||||
|
{ 'struct': 'SevGuestProperties',
|
||||||
|
@@ -908,7 +916,8 @@
|
||||||
|
'*handle': 'uint32',
|
||||||
|
'*cbitpos': 'uint32',
|
||||||
|
'reduced-phys-bits': 'uint32',
|
||||||
|
- '*kernel-hashes': 'bool' } }
|
||||||
|
+ '*kernel-hashes': 'bool',
|
||||||
|
+ '*legacy-vm-type': 'bool' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @ThreadContextProperties:
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 9dab4060b8..f4ee317cb0 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -67,6 +67,7 @@ struct SevGuestState {
|
||||||
|
uint32_t cbitpos;
|
||||||
|
uint32_t reduced_phys_bits;
|
||||||
|
bool kernel_hashes;
|
||||||
|
+ bool legacy_vm_type;
|
||||||
|
|
||||||
|
/* runtime state */
|
||||||
|
uint32_t handle;
|
||||||
|
@@ -356,6 +357,16 @@ static void sev_guest_set_kernel_hashes(Object *obj, bool value, Error **errp)
|
||||||
|
sev->kernel_hashes = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool sev_guest_get_legacy_vm_type(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ return SEV_GUEST(obj)->legacy_vm_type;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void sev_guest_set_legacy_vm_type(Object *obj, bool value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SEV_GUEST(obj)->legacy_vm_type = value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
bool
|
||||||
|
sev_enabled(void)
|
||||||
|
{
|
||||||
|
@@ -863,7 +874,7 @@ static int sev_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
}
|
||||||
|
|
||||||
|
kvm_type = (sev->policy & SEV_POLICY_ES) ? KVM_X86_SEV_ES_VM : KVM_X86_SEV_VM;
|
||||||
|
- if (kvm_is_vm_type_supported(kvm_type)) {
|
||||||
|
+ if (kvm_is_vm_type_supported(kvm_type) && !sev->legacy_vm_type) {
|
||||||
|
sev->kvm_type = kvm_type;
|
||||||
|
} else {
|
||||||
|
sev->kvm_type = KVM_X86_DEFAULT_VM;
|
||||||
|
@@ -1381,6 +1392,11 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
sev_guest_set_kernel_hashes);
|
||||||
|
object_class_property_set_description(oc, "kernel-hashes",
|
||||||
|
"add kernel hashes to guest firmware for measured Linux boot");
|
||||||
|
+ object_class_property_add_bool(oc, "legacy-vm-type",
|
||||||
|
+ sev_guest_get_legacy_vm_type,
|
||||||
|
+ sev_guest_set_legacy_vm_type);
|
||||||
|
+ object_class_property_set_description(oc, "legacy-vm-type",
|
||||||
|
+ "use legacy VM type to maintain measurement compatibility with older QEMU or kernel versions.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,203 @@
|
|||||||
|
From a236548a903aa8350fff9601d481b2f529c8d4a7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:21 -0500
|
||||||
|
Subject: [PATCH 061/100] i386/sev: Add sev_kvm_init() override for SEV class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [61/91] b24fcbc8712e7394e029312229da023c63803969 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Some aspects of the init routine SEV are specific to SEV and not
|
||||||
|
applicable for SNP guests, so move the SEV-specific bits into
|
||||||
|
separate class method and retain only the common functionality.
|
||||||
|
|
||||||
|
Co-developed-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-10-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 990da8d243a8c59dafcbed78b56a0e4ffb1605d9)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 72 +++++++++++++++++++++++++++++++++--------------
|
||||||
|
1 file changed, 51 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 4edfedc139..5519de1c6b 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -73,6 +73,7 @@ struct SevCommonStateClass {
|
||||||
|
/* public */
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
+ int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -882,7 +883,7 @@ out:
|
||||||
|
return sev_common->kvm_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
+static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
char *devname;
|
||||||
|
@@ -892,12 +893,6 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs);
|
||||||
|
|
||||||
|
- ret = ram_block_discard_disable(true);
|
||||||
|
- if (ret) {
|
||||||
|
- error_report("%s: cannot disable RAM discard", __func__);
|
||||||
|
- return -1;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
sev_common->state = SEV_STATE_UNINIT;
|
||||||
|
|
||||||
|
host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL);
|
||||||
|
@@ -911,7 +906,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
if (host_cbitpos != sev_common->cbitpos) {
|
||||||
|
error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'",
|
||||||
|
__func__, host_cbitpos, sev_common->cbitpos);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -924,7 +919,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: reduced_phys_bits check failed,"
|
||||||
|
" it should be in the range of 1 to 63, requested '%d'",
|
||||||
|
__func__, sev_common->reduced_phys_bits);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
devname = object_property_get_str(OBJECT(sev_common), "sev-device", NULL);
|
||||||
|
@@ -933,7 +928,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: Failed to open %s '%s'", __func__,
|
||||||
|
devname, strerror(errno));
|
||||||
|
g_free(devname);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
g_free(devname);
|
||||||
|
|
||||||
|
@@ -943,7 +938,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: failed to get platform status ret=%d "
|
||||||
|
"fw_error='%d: %s'", __func__, ret, fw_error,
|
||||||
|
fw_error_to_str(fw_error));
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
sev_common->build_id = status.build;
|
||||||
|
sev_common->api_major = status.api_major;
|
||||||
|
@@ -953,7 +948,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
if (!kvm_kernel_irqchip_allowed()) {
|
||||||
|
error_setg(errp, "%s: SEV-ES guests require in-kernel irqchip"
|
||||||
|
"support", __func__);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -962,7 +957,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
error_setg(errp, "%s: guest policy requires SEV-ES, but "
|
||||||
|
"host SEV-ES support unavailable",
|
||||||
|
__func__);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -980,25 +975,59 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
if (ret) {
|
||||||
|
error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'",
|
||||||
|
__func__, ret, fw_error, fw_error_to_str(fw_error));
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = klass->launch_start(sev_common);
|
||||||
|
if (ret) {
|
||||||
|
error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||||
|
- goto err;
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (klass->kvm_init && klass->kvm_init(cgs, errp)) {
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ram_block_notifier_add(&sev_ram_notifier);
|
||||||
|
- qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
|
||||||
|
qemu_add_vm_change_state_handler(sev_vm_state_change, sev_common);
|
||||||
|
|
||||||
|
cgs->ready = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
-err:
|
||||||
|
- ram_block_discard_disable(false);
|
||||||
|
- return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * SEV/SEV-ES rely on pinned memory to back guest RAM so discarding
|
||||||
|
+ * isn't actually possible. With SNP, only guest_memfd pages are used
|
||||||
|
+ * for private guest memory, so discarding of shared memory is still
|
||||||
|
+ * possible..
|
||||||
|
+ */
|
||||||
|
+ ret = ram_block_discard_disable(true);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_setg(errp, "%s: cannot disable RAM discard", __func__);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * SEV uses these notifiers to register/pin pages prior to guest use,
|
||||||
|
+ * but SNP relies on guest_memfd for private pages, which has its
|
||||||
|
+ * own internal mechanisms for registering/pinning private memory.
|
||||||
|
+ */
|
||||||
|
+ ram_block_notifier_add(&sev_ram_notifier);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The machine done notify event is used for SEV guests to get the
|
||||||
|
+ * measurement of the encrypted images. When SEV-SNP is enabled, the
|
||||||
|
+ * measurement is part of the guest attestation process where it can
|
||||||
|
+ * be collected without any reliance on the VMM. So skip registering
|
||||||
|
+ * the notifier for SNP in favor of using guest attestation instead.
|
||||||
|
+ */
|
||||||
|
+ qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
@@ -1397,7 +1426,7 @@ sev_common_class_init(ObjectClass *oc, void *data)
|
||||||
|
ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
- klass->kvm_init = sev_kvm_init;
|
||||||
|
+ klass->kvm_init = sev_common_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "sev-device",
|
||||||
|
@@ -1486,6 +1515,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
+ klass->kvm_init = sev_kvm_init;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
sev_guest_get_dh_cert_file,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,94 @@
|
|||||||
|
From 35ceebdeccbf5dceb374c6f89a12e9981def570b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:22 -0500
|
||||||
|
Subject: [PATCH 062/100] i386/sev: Add snp_kvm_init() override for SNP class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [62/91] 8fa537961c9262b99a4ffb99e1c25f080d76d1de (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SNP does not support SMM and requires guest_memfd for
|
||||||
|
private guest memory, so add SNP specific kvm_init()
|
||||||
|
functionality in snp_kvm_init() class method.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-11-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 125b95a6d465a03ff30816eff0b1889aec01f0c3)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 24 +++++++++++++++++++++++-
|
||||||
|
1 file changed, 23 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 5519de1c6b..6525b3c1a0 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -885,12 +885,12 @@ out:
|
||||||
|
|
||||||
|
static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
{
|
||||||
|
- SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
char *devname;
|
||||||
|
int ret, fw_error, cmd;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t host_cbitpos;
|
||||||
|
struct sev_user_data_status status = {};
|
||||||
|
+ SevCommonState *sev_common = SEV_COMMON(cgs);
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs);
|
||||||
|
|
||||||
|
sev_common->state = SEV_STATE_UNINIT;
|
||||||
|
@@ -1030,6 +1030,21 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int sev_snp_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
+{
|
||||||
|
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||||
|
+ X86MachineState *x86ms = X86_MACHINE(ms);
|
||||||
|
+
|
||||||
|
+ if (x86ms->smm == ON_OFF_AUTO_AUTO) {
|
||||||
|
+ x86ms->smm = ON_OFF_AUTO_OFF;
|
||||||
|
+ } else if (x86ms->smm == ON_OFF_AUTO_ON) {
|
||||||
|
+ error_setg(errp, "SEV-SNP does not support SMM.");
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int
|
||||||
|
sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
@@ -1752,6 +1767,10 @@ sev_snp_guest_set_host_data(Object *obj, const char *value, Error **errp)
|
||||||
|
static void
|
||||||
|
sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
+
|
||||||
|
+ klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
+
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
@@ -1778,8 +1797,11 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
static void
|
||||||
|
sev_snp_guest_instance_init(Object *obj)
|
||||||
|
{
|
||||||
|
+ ConfidentialGuestSupport *cgs = CONFIDENTIAL_GUEST_SUPPORT(obj);
|
||||||
|
SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
|
||||||
|
+ cgs->require_guest_memfd = true;
|
||||||
|
+
|
||||||
|
/* default init/start/finish params for kvm */
|
||||||
|
sev_snp_guest->kvm_start_conf.policy = DEFAULT_SEV_SNP_POLICY;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,262 @@
|
|||||||
|
From 4013364679757161d6b9754bfc33ae38be0a1b7f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:32 -0500
|
||||||
|
Subject: [PATCH 072/100] i386/sev: Add support for SNP CPUID validation
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [72/91] 080e2942552dc7de8966e69d0d0d3b8951392030 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SEV-SNP firmware allows a special guest page to be populated with a
|
||||||
|
table of guest CPUID values so that they can be validated through
|
||||||
|
firmware before being loaded into encrypted guest memory where they can
|
||||||
|
be used in place of hypervisor-provided values[1].
|
||||||
|
|
||||||
|
As part of SEV-SNP guest initialization, use this interface to validate
|
||||||
|
the CPUID entries reported by KVM_GET_CPUID2 prior to initial guest
|
||||||
|
start and populate the CPUID page reserved by OVMF with the resulting
|
||||||
|
encrypted data.
|
||||||
|
|
||||||
|
[1] SEV SNP Firmware ABI Specification, Rev. 0.8, 8.13.2.6
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-21-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 70943ad8e4dfbe5f77006b880290219be9d03553)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 164 +++++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 162 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index c57534fca2..06401f0526 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -200,6 +200,36 @@ static const char *const sev_fw_errlist[] = {
|
||||||
|
|
||||||
|
#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
|
||||||
|
|
||||||
|
+/* <linux/kvm.h> doesn't expose this, so re-use the max from kvm.c */
|
||||||
|
+#define KVM_MAX_CPUID_ENTRIES 100
|
||||||
|
+
|
||||||
|
+typedef struct KvmCpuidInfo {
|
||||||
|
+ struct kvm_cpuid2 cpuid;
|
||||||
|
+ struct kvm_cpuid_entry2 entries[KVM_MAX_CPUID_ENTRIES];
|
||||||
|
+} KvmCpuidInfo;
|
||||||
|
+
|
||||||
|
+#define SNP_CPUID_FUNCTION_MAXCOUNT 64
|
||||||
|
+#define SNP_CPUID_FUNCTION_UNKNOWN 0xFFFFFFFF
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ uint32_t eax_in;
|
||||||
|
+ uint32_t ecx_in;
|
||||||
|
+ uint64_t xcr0_in;
|
||||||
|
+ uint64_t xss_in;
|
||||||
|
+ uint32_t eax;
|
||||||
|
+ uint32_t ebx;
|
||||||
|
+ uint32_t ecx;
|
||||||
|
+ uint32_t edx;
|
||||||
|
+ uint64_t reserved;
|
||||||
|
+} __attribute__((packed)) SnpCpuidFunc;
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ uint32_t count;
|
||||||
|
+ uint32_t reserved1;
|
||||||
|
+ uint64_t reserved2;
|
||||||
|
+ SnpCpuidFunc entries[SNP_CPUID_FUNCTION_MAXCOUNT];
|
||||||
|
+} __attribute__((packed)) SnpCpuidInfo;
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_ioctl(int fd, int cmd, void *data, int *error)
|
||||||
|
{
|
||||||
|
@@ -788,6 +818,35 @@ out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+sev_snp_cpuid_report_mismatches(SnpCpuidInfo *old,
|
||||||
|
+ SnpCpuidInfo *new)
|
||||||
|
+{
|
||||||
|
+ size_t i;
|
||||||
|
+
|
||||||
|
+ if (old->count != new->count) {
|
||||||
|
+ error_report("SEV-SNP: CPUID validation failed due to count mismatch,"
|
||||||
|
+ "provided: %d, expected: %d", old->count, new->count);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < old->count; i++) {
|
||||||
|
+ SnpCpuidFunc *old_func, *new_func;
|
||||||
|
+
|
||||||
|
+ old_func = &old->entries[i];
|
||||||
|
+ new_func = &new->entries[i];
|
||||||
|
+
|
||||||
|
+ if (memcmp(old_func, new_func, sizeof(SnpCpuidFunc))) {
|
||||||
|
+ error_report("SEV-SNP: CPUID validation failed for function 0x%x, index: 0x%x"
|
||||||
|
+ "provided: eax:0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x"
|
||||||
|
+ "expected: eax:0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x",
|
||||||
|
+ old_func->eax_in, old_func->ecx_in,
|
||||||
|
+ old_func->eax, old_func->ebx, old_func->ecx, old_func->edx,
|
||||||
|
+ new_func->eax, new_func->ebx, new_func->ecx, new_func->edx);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const char *
|
||||||
|
snp_page_type_to_str(int type)
|
||||||
|
{
|
||||||
|
@@ -806,6 +865,7 @@ sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
SevLaunchUpdateData *data)
|
||||||
|
{
|
||||||
|
int ret, fw_error;
|
||||||
|
+ SnpCpuidInfo snp_cpuid_info;
|
||||||
|
struct kvm_sev_snp_launch_update update = {0};
|
||||||
|
|
||||||
|
if (!data->hva || !data->len) {
|
||||||
|
@@ -815,6 +875,11 @@ sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (data->type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
+ /* Save a copy for comparison in case the LAUNCH_UPDATE fails */
|
||||||
|
+ memcpy(&snp_cpuid_info, data->hva, sizeof(snp_cpuid_info));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
update.uaddr = (__u64)(unsigned long)data->hva;
|
||||||
|
update.gfn_start = data->gpa >> TARGET_PAGE_BITS;
|
||||||
|
update.len = data->len;
|
||||||
|
@@ -842,6 +907,11 @@ sev_snp_launch_update(SevSnpGuestState *sev_snp_guest,
|
||||||
|
if (ret && ret != -EAGAIN) {
|
||||||
|
error_report("SNP_LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
|
||||||
|
ret, fw_error, fw_error_to_str(fw_error));
|
||||||
|
+
|
||||||
|
+ if (data->type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
+ sev_snp_cpuid_report_mismatches(&snp_cpuid_info, data->hva);
|
||||||
|
+ error_report("SEV-SNP: failed update CPUID page");
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1004,7 +1074,8 @@ sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-snp_launch_update_data(uint64_t gpa, void *hva, uint32_t len, int type)
|
||||||
|
+snp_launch_update_data(uint64_t gpa, void *hva,
|
||||||
|
+ uint32_t len, int type)
|
||||||
|
{
|
||||||
|
SevLaunchUpdateData *data;
|
||||||
|
|
||||||
|
@@ -1019,6 +1090,90 @@ snp_launch_update_data(uint64_t gpa, void *hva, uint32_t len, int type)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sev_snp_cpuid_info_fill(SnpCpuidInfo *snp_cpuid_info,
|
||||||
|
+ const KvmCpuidInfo *kvm_cpuid_info)
|
||||||
|
+{
|
||||||
|
+ size_t i;
|
||||||
|
+
|
||||||
|
+ if (kvm_cpuid_info->cpuid.nent > SNP_CPUID_FUNCTION_MAXCOUNT) {
|
||||||
|
+ error_report("SEV-SNP: CPUID entry count (%d) exceeds max (%d)",
|
||||||
|
+ kvm_cpuid_info->cpuid.nent, SNP_CPUID_FUNCTION_MAXCOUNT);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memset(snp_cpuid_info, 0, sizeof(*snp_cpuid_info));
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < kvm_cpuid_info->cpuid.nent; i++) {
|
||||||
|
+ const struct kvm_cpuid_entry2 *kvm_cpuid_entry;
|
||||||
|
+ SnpCpuidFunc *snp_cpuid_entry;
|
||||||
|
+
|
||||||
|
+ kvm_cpuid_entry = &kvm_cpuid_info->entries[i];
|
||||||
|
+ snp_cpuid_entry = &snp_cpuid_info->entries[i];
|
||||||
|
+
|
||||||
|
+ snp_cpuid_entry->eax_in = kvm_cpuid_entry->function;
|
||||||
|
+ if (kvm_cpuid_entry->flags == KVM_CPUID_FLAG_SIGNIFCANT_INDEX) {
|
||||||
|
+ snp_cpuid_entry->ecx_in = kvm_cpuid_entry->index;
|
||||||
|
+ }
|
||||||
|
+ snp_cpuid_entry->eax = kvm_cpuid_entry->eax;
|
||||||
|
+ snp_cpuid_entry->ebx = kvm_cpuid_entry->ebx;
|
||||||
|
+ snp_cpuid_entry->ecx = kvm_cpuid_entry->ecx;
|
||||||
|
+ snp_cpuid_entry->edx = kvm_cpuid_entry->edx;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Guest kernels will calculate EBX themselves using the 0xD
|
||||||
|
+ * subfunctions corresponding to the individual XSAVE areas, so only
|
||||||
|
+ * encode the base XSAVE size in the initial leaves, corresponding
|
||||||
|
+ * to the initial XCR0=1 state.
|
||||||
|
+ */
|
||||||
|
+ if (snp_cpuid_entry->eax_in == 0xD &&
|
||||||
|
+ (snp_cpuid_entry->ecx_in == 0x0 || snp_cpuid_entry->ecx_in == 0x1)) {
|
||||||
|
+ snp_cpuid_entry->ebx = 0x240;
|
||||||
|
+ snp_cpuid_entry->xcr0_in = 1;
|
||||||
|
+ snp_cpuid_entry->xss_in = 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ snp_cpuid_info->count = i;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+snp_launch_update_cpuid(uint32_t cpuid_addr, void *hva, uint32_t cpuid_len)
|
||||||
|
+{
|
||||||
|
+ KvmCpuidInfo kvm_cpuid_info = {0};
|
||||||
|
+ SnpCpuidInfo snp_cpuid_info;
|
||||||
|
+ CPUState *cs = first_cpu;
|
||||||
|
+ int ret;
|
||||||
|
+ uint32_t i = 0;
|
||||||
|
+
|
||||||
|
+ assert(sizeof(snp_cpuid_info) <= cpuid_len);
|
||||||
|
+
|
||||||
|
+ /* get the cpuid list from KVM */
|
||||||
|
+ do {
|
||||||
|
+ kvm_cpuid_info.cpuid.nent = ++i;
|
||||||
|
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_CPUID2, &kvm_cpuid_info);
|
||||||
|
+ } while (ret == -E2BIG);
|
||||||
|
+
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SEV-SNP: unable to query CPUID values for CPU: '%s'",
|
||||||
|
+ strerror(-ret));
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = sev_snp_cpuid_info_fill(&snp_cpuid_info, &kvm_cpuid_info);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("SEV-SNP: failed to generate CPUID table information");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(hva, &snp_cpuid_info, sizeof(snp_cpuid_info));
|
||||||
|
+
|
||||||
|
+ return snp_launch_update_data(cpuid_addr, hva, cpuid_len,
|
||||||
|
+ KVM_SEV_SNP_PAGE_TYPE_CPUID);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
snp_metadata_desc_to_page_type(int desc_type)
|
||||||
|
{
|
||||||
|
@@ -1053,7 +1208,12 @@ snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
+ if (type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
+ ret = snp_launch_update_cpuid(desc->base, hva, desc->len);
|
||||||
|
+ } else {
|
||||||
|
+ ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (ret) {
|
||||||
|
error_report("%s: Failed to add metadata page gpa 0x%x+%x type %d",
|
||||||
|
__func__, desc->base, desc->len, desc->type);
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,127 @@
|
|||||||
|
From b2cfd4d89026e76ba86ea7adea323f2c3a588790 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:31 -0500
|
||||||
|
Subject: [PATCH 071/100] i386/sev: Add support for populating OVMF metadata
|
||||||
|
pages
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [71/91] b563442c0e2f6ea01937425d300b56d9e641fd57 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
OVMF reserves various pages so they can be pre-initialized/validated
|
||||||
|
prior to launching the guest. Add support for populating these pages
|
||||||
|
with the expected content.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-20-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 3d8c2a7f4806ff39423312e503737fd76c34dcae)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 74 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 17281bb2c7..c57534fca2 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1003,15 +1003,89 @@ sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
migrate_add_blocker(&sev_mig_blocker, &error_fatal);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+snp_launch_update_data(uint64_t gpa, void *hva, uint32_t len, int type)
|
||||||
|
+{
|
||||||
|
+ SevLaunchUpdateData *data;
|
||||||
|
+
|
||||||
|
+ data = g_new0(SevLaunchUpdateData, 1);
|
||||||
|
+ data->gpa = gpa;
|
||||||
|
+ data->hva = hva;
|
||||||
|
+ data->len = len;
|
||||||
|
+ data->type = type;
|
||||||
|
+
|
||||||
|
+ QTAILQ_INSERT_TAIL(&launch_update, data, next);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+snp_metadata_desc_to_page_type(int desc_type)
|
||||||
|
+{
|
||||||
|
+ switch (desc_type) {
|
||||||
|
+ /* Add the umeasured prevalidated pages as a zero page */
|
||||||
|
+ case SEV_DESC_TYPE_SNP_SEC_MEM: return KVM_SEV_SNP_PAGE_TYPE_ZERO;
|
||||||
|
+ case SEV_DESC_TYPE_SNP_SECRETS: return KVM_SEV_SNP_PAGE_TYPE_SECRETS;
|
||||||
|
+ case SEV_DESC_TYPE_CPUID: return KVM_SEV_SNP_PAGE_TYPE_CPUID;
|
||||||
|
+ default:
|
||||||
|
+ return KVM_SEV_SNP_PAGE_TYPE_ZERO;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
|
||||||
|
+ OvmfSevMetadata *metadata)
|
||||||
|
+{
|
||||||
|
+ OvmfSevMetadataDesc *desc;
|
||||||
|
+ int type, ret, i;
|
||||||
|
+ void *hva;
|
||||||
|
+ MemoryRegion *mr = NULL;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < metadata->num_desc; i++) {
|
||||||
|
+ desc = &metadata->descs[i];
|
||||||
|
+
|
||||||
|
+ type = snp_metadata_desc_to_page_type(desc->type);
|
||||||
|
+
|
||||||
|
+ hva = gpa2hva(&mr, desc->base, desc->len, NULL);
|
||||||
|
+ if (!hva) {
|
||||||
|
+ error_report("%s: Failed to get HVA for GPA 0x%x sz 0x%x",
|
||||||
|
+ __func__, desc->base, desc->len);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
+ if (ret) {
|
||||||
|
+ error_report("%s: Failed to add metadata page gpa 0x%x+%x type %d",
|
||||||
|
+ __func__, desc->base, desc->len, desc->type);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sev_snp_launch_finish(SevCommonState *sev_common)
|
||||||
|
{
|
||||||
|
int ret, error;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
+ OvmfSevMetadata *metadata;
|
||||||
|
SevLaunchUpdateData *data;
|
||||||
|
SevSnpGuestState *sev_snp = SEV_SNP_GUEST(sev_common);
|
||||||
|
struct kvm_sev_snp_launch_finish *finish = &sev_snp->kvm_finish_conf;
|
||||||
|
|
||||||
|
+ /*
|
||||||
|
+ * To boot the SNP guest, the hypervisor is required to populate the CPUID
|
||||||
|
+ * and Secrets page before finalizing the launch flow. The location of
|
||||||
|
+ * the secrets and CPUID page is available through the OVMF metadata GUID.
|
||||||
|
+ */
|
||||||
|
+ metadata = pc_system_get_ovmf_sev_metadata_ptr();
|
||||||
|
+ if (metadata == NULL) {
|
||||||
|
+ error_report("%s: Failed to locate SEV metadata header", __func__);
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Populate all the metadata pages */
|
||||||
|
+ snp_populate_metadata_pages(sev_snp, metadata);
|
||||||
|
+
|
||||||
|
QTAILQ_FOREACH(data, &launch_update, next) {
|
||||||
|
ret = sev_snp_launch_update(sev_snp, data);
|
||||||
|
if (ret) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,122 @@
|
|||||||
|
From 0f7432f2b968298b64fd243df793b176f67a538f Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:27 -0500
|
||||||
|
Subject: [PATCH 067/100] i386/sev: Add the SNP launch start context
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [67/91] 63759a25a413a7a9a7274fb4c3b8bc2528634855 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
The SNP_LAUNCH_START is called first to create a cryptographic launch
|
||||||
|
context within the firmware.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-16-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit d3107f882ec22cfb211eab7efa0c4e95f5ce11bb)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||||
|
target/i386/trace-events | 1 +
|
||||||
|
2 files changed, 40 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 43d1c48bd9..e89b87d2f5 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -39,6 +39,7 @@
|
||||||
|
#include "confidential-guest.h"
|
||||||
|
#include "hw/i386/pc.h"
|
||||||
|
#include "exec/address-spaces.h"
|
||||||
|
+#include "qemu/queue.h"
|
||||||
|
|
||||||
|
OBJECT_DECLARE_TYPE(SevCommonState, SevCommonStateClass, SEV_COMMON)
|
||||||
|
OBJECT_DECLARE_TYPE(SevGuestState, SevCommonStateClass, SEV_GUEST)
|
||||||
|
@@ -115,6 +116,16 @@ struct SevSnpGuestState {
|
||||||
|
#define DEFAULT_SEV_DEVICE "/dev/sev"
|
||||||
|
#define DEFAULT_SEV_SNP_POLICY 0x30000
|
||||||
|
|
||||||
|
+typedef struct SevLaunchUpdateData {
|
||||||
|
+ QTAILQ_ENTRY(SevLaunchUpdateData) next;
|
||||||
|
+ hwaddr gpa;
|
||||||
|
+ void *hva;
|
||||||
|
+ uint64_t len;
|
||||||
|
+ int type;
|
||||||
|
+} SevLaunchUpdateData;
|
||||||
|
+
|
||||||
|
+static QTAILQ_HEAD(, SevLaunchUpdateData) launch_update;
|
||||||
|
+
|
||||||
|
#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
|
||||||
|
typedef struct __attribute__((__packed__)) SevInfoBlock {
|
||||||
|
/* SEV-ES Reset Vector Address */
|
||||||
|
@@ -674,6 +685,31 @@ sev_read_file_base64(const char *filename, guchar **data, gsize *len)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sev_snp_launch_start(SevCommonState *sev_common)
|
||||||
|
+{
|
||||||
|
+ int fw_error, rc;
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(sev_common);
|
||||||
|
+ struct kvm_sev_snp_launch_start *start = &sev_snp_guest->kvm_start_conf;
|
||||||
|
+
|
||||||
|
+ trace_kvm_sev_snp_launch_start(start->policy,
|
||||||
|
+ sev_snp_guest->guest_visible_workarounds);
|
||||||
|
+
|
||||||
|
+ rc = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_LAUNCH_START,
|
||||||
|
+ start, &fw_error);
|
||||||
|
+ if (rc < 0) {
|
||||||
|
+ error_report("%s: SNP_LAUNCH_START ret=%d fw_error=%d '%s'",
|
||||||
|
+ __func__, rc, fw_error, fw_error_to_str(fw_error));
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ QTAILQ_INIT(&launch_update);
|
||||||
|
+
|
||||||
|
+ sev_set_guest_state(sev_common, SEV_STATE_LAUNCH_UPDATE);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_launch_start(SevCommonState *sev_common)
|
||||||
|
{
|
||||||
|
@@ -1003,6 +1039,7 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = klass->launch_start(sev_common);
|
||||||
|
+
|
||||||
|
if (ret) {
|
||||||
|
error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||||
|
return -1;
|
||||||
|
@@ -1794,9 +1831,11 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
+ klass->launch_start = sev_snp_launch_start;
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
+
|
||||||
|
object_class_property_add(oc, "policy", "uint64",
|
||||||
|
sev_snp_guest_get_policy,
|
||||||
|
sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||||||
|
index 2cd8726eeb..cb26d8a925 100644
|
||||||
|
--- a/target/i386/trace-events
|
||||||
|
+++ b/target/i386/trace-events
|
||||||
|
@@ -11,3 +11,4 @@ kvm_sev_launch_measurement(const char *value) "data %s"
|
||||||
|
kvm_sev_launch_finish(void) ""
|
||||||
|
kvm_sev_launch_secret(uint64_t hpa, uint64_t hva, uint64_t secret, int len) "hpa 0x%" PRIx64 " hva 0x%" PRIx64 " data 0x%" PRIx64 " len %d"
|
||||||
|
kvm_sev_attestation_report(const char *mnonce, const char *data) "mnonce %s data %s"
|
||||||
|
+kvm_sev_snp_launch_start(uint64_t policy, char *gosvw) "policy 0x%" PRIx64 " gosvw %s"
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,237 @@
|
|||||||
|
From ec786a1ec0a76775e980862d77500f5196a937e3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:35 -0500
|
||||||
|
Subject: [PATCH 080/100] i386/sev: Allow measured direct kernel boot on SNP
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [80/91] 11c629862519c1a279566febf5a537c63c5fcf61 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
In SNP, the hashes page designated with a specific metadata entry
|
||||||
|
published in AmdSev OVMF.
|
||||||
|
|
||||||
|
Therefore, if the user enabled kernel hashes (for measured direct boot),
|
||||||
|
QEMU should prepare the content of hashes table, and during the
|
||||||
|
processing of the metadata entry it copy the content into the designated
|
||||||
|
page and encrypt it.
|
||||||
|
|
||||||
|
Note that in SNP (unlike SEV and SEV-ES) the measurements is done in
|
||||||
|
whole 4KB pages. Therefore QEMU zeros the whole page that includes the
|
||||||
|
hashes table, and fills in the kernel hashes area in that page, and then
|
||||||
|
encrypts the whole page. The rest of the page is reserved for SEV
|
||||||
|
launch secrets which are not usable anyway on SNP.
|
||||||
|
|
||||||
|
If the user disabled kernel hashes, QEMU pre-validates the kernel hashes
|
||||||
|
page as a zero page.
|
||||||
|
|
||||||
|
Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-24-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit c1996992cc882b00139f78067d6a64e2ec9cb0d8)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
include/hw/i386/pc.h | 2 +
|
||||||
|
target/i386/sev.c | 111 ++++++++++++++++++++++++++++++++-----------
|
||||||
|
2 files changed, 85 insertions(+), 28 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
|
||||||
|
index 94b49310f5..ee3bfb7be9 100644
|
||||||
|
--- a/include/hw/i386/pc.h
|
||||||
|
+++ b/include/hw/i386/pc.h
|
||||||
|
@@ -175,6 +175,8 @@ typedef enum {
|
||||||
|
SEV_DESC_TYPE_SNP_SECRETS,
|
||||||
|
/* The section contains address that can be used as a CPUID page */
|
||||||
|
SEV_DESC_TYPE_CPUID,
|
||||||
|
+ /* The section contains the region for kernel hashes for measured direct boot */
|
||||||
|
+ SEV_DESC_TYPE_SNP_KERNEL_HASHES = 0x10,
|
||||||
|
|
||||||
|
} ovmf_sev_metadata_desc_type;
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 3fce4c08eb..004c667ac1 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -115,6 +115,10 @@ struct SevCommonStateClass {
|
||||||
|
X86ConfidentialGuestClass parent_class;
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
+ bool (*build_kernel_loader_hashes)(SevCommonState *sev_common,
|
||||||
|
+ SevHashTableDescriptor *area,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp);
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
int (*launch_update_data)(SevCommonState *sev_common, hwaddr gpa, uint8_t *ptr, uint64_t len);
|
||||||
|
@@ -154,6 +158,9 @@ struct SevSnpGuestState {
|
||||||
|
|
||||||
|
struct kvm_sev_snp_launch_start kvm_start_conf;
|
||||||
|
struct kvm_sev_snp_launch_finish kvm_finish_conf;
|
||||||
|
+
|
||||||
|
+ uint32_t kernel_hashes_offset;
|
||||||
|
+ PaddedSevHashTable *kernel_hashes_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
|
||||||
|
@@ -1189,6 +1196,23 @@ snp_launch_update_cpuid(uint32_t cpuid_addr, void *hva, uint32_t cpuid_len)
|
||||||
|
KVM_SEV_SNP_PAGE_TYPE_CPUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+snp_launch_update_kernel_hashes(SevSnpGuestState *sev_snp, uint32_t addr,
|
||||||
|
+ void *hva, uint32_t len)
|
||||||
|
+{
|
||||||
|
+ int type = KVM_SEV_SNP_PAGE_TYPE_ZERO;
|
||||||
|
+ if (sev_snp->parent_obj.kernel_hashes) {
|
||||||
|
+ assert(sev_snp->kernel_hashes_data);
|
||||||
|
+ assert((sev_snp->kernel_hashes_offset +
|
||||||
|
+ sizeof(*sev_snp->kernel_hashes_data)) <= len);
|
||||||
|
+ memset(hva, 0, len);
|
||||||
|
+ memcpy(hva + sev_snp->kernel_hashes_offset, sev_snp->kernel_hashes_data,
|
||||||
|
+ sizeof(*sev_snp->kernel_hashes_data));
|
||||||
|
+ type = KVM_SEV_SNP_PAGE_TYPE_NORMAL;
|
||||||
|
+ }
|
||||||
|
+ return snp_launch_update_data(addr, hva, len, type);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
snp_metadata_desc_to_page_type(int desc_type)
|
||||||
|
{
|
||||||
|
@@ -1225,6 +1249,9 @@ snp_populate_metadata_pages(SevSnpGuestState *sev_snp,
|
||||||
|
|
||||||
|
if (type == KVM_SEV_SNP_PAGE_TYPE_CPUID) {
|
||||||
|
ret = snp_launch_update_cpuid(desc->base, hva, desc->len);
|
||||||
|
+ } else if (desc->type == SEV_DESC_TYPE_SNP_KERNEL_HASHES) {
|
||||||
|
+ ret = snp_launch_update_kernel_hashes(sev_snp, desc->base, hva,
|
||||||
|
+ desc->len);
|
||||||
|
} else {
|
||||||
|
ret = snp_launch_update_data(desc->base, hva, desc->len, type);
|
||||||
|
}
|
||||||
|
@@ -1823,6 +1850,58 @@ static bool build_kernel_loader_hashes(PaddedSevHashTable *padded_ht,
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static bool sev_snp_build_kernel_loader_hashes(SevCommonState *sev_common,
|
||||||
|
+ SevHashTableDescriptor *area,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ /*
|
||||||
|
+ * SNP: Populate the hashes table in an area that later in
|
||||||
|
+ * snp_launch_update_kernel_hashes() will be copied to the guest memory
|
||||||
|
+ * and encrypted.
|
||||||
|
+ */
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(sev_common);
|
||||||
|
+ sev_snp_guest->kernel_hashes_offset = area->base & ~TARGET_PAGE_MASK;
|
||||||
|
+ sev_snp_guest->kernel_hashes_data = g_new0(PaddedSevHashTable, 1);
|
||||||
|
+ return build_kernel_loader_hashes(sev_snp_guest->kernel_hashes_data, ctx, errp);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool sev_build_kernel_loader_hashes(SevCommonState *sev_common,
|
||||||
|
+ SevHashTableDescriptor *area,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ PaddedSevHashTable *padded_ht;
|
||||||
|
+ hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
+ MemTxAttrs attrs = { 0 };
|
||||||
|
+ bool ret = true;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
+ * area for the SEV hashes table
|
||||||
|
+ */
|
||||||
|
+ padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
+ &mapped_len, true, attrs);
|
||||||
|
+ if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
+ error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (build_kernel_loader_hashes(padded_ht, ctx, errp)) {
|
||||||
|
+ if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
+ sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ ret = false;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ ret = false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ address_space_unmap(&address_space_memory, padded_ht,
|
||||||
|
+ mapped_len, true, mapped_len);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
|
||||||
|
* which is included in SEV's initial memory measurement.
|
||||||
|
@@ -1831,11 +1910,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
{
|
||||||
|
uint8_t *data;
|
||||||
|
SevHashTableDescriptor *area;
|
||||||
|
- PaddedSevHashTable *padded_ht;
|
||||||
|
- hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
- MemTxAttrs attrs = { 0 };
|
||||||
|
- bool ret = true;
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only add the kernel hashes if the sev-guest configuration explicitly
|
||||||
|
@@ -1858,30 +1934,7 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
- * area for the SEV hashes table
|
||||||
|
- */
|
||||||
|
- padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
- &mapped_len, true, attrs);
|
||||||
|
- if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
- error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (build_kernel_loader_hashes(padded_ht, ctx, errp)) {
|
||||||
|
- if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
- sizeof(*padded_ht), errp) < 0) {
|
||||||
|
- ret = false;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- ret = false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- address_space_unmap(&address_space_memory, padded_ht,
|
||||||
|
- mapped_len, true, mapped_len);
|
||||||
|
-
|
||||||
|
- return ret;
|
||||||
|
+ return klass->build_kernel_loader_hashes(sev_common, area, ctx, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
@@ -1998,6 +2051,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
+ klass->build_kernel_loader_hashes = sev_build_kernel_loader_hashes;
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
klass->launch_update_data = sev_launch_update_data;
|
||||||
|
@@ -2242,6 +2296,7 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc);
|
||||||
|
|
||||||
|
+ klass->build_kernel_loader_hashes = sev_snp_build_kernel_loader_hashes;
|
||||||
|
klass->launch_start = sev_snp_launch_start;
|
||||||
|
klass->launch_finish = sev_snp_launch_finish;
|
||||||
|
klass->launch_update_data = sev_snp_launch_update_data;
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,268 @@
|
|||||||
|
From ab6197309551bd6ddd9f8239191f68dfac23684b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Tue, 9 Jul 2024 23:10:05 -0500
|
||||||
|
Subject: [PATCH 090/100] i386/sev: Don't allow automatic fallback to legacy
|
||||||
|
KVM_SEV*_INIT
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [90/91] 2b1345faa56f993bb6e13d63e11656c784e20412 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Currently if the 'legacy-vm-type' property of the sev-guest object is
|
||||||
|
'on', QEMU will attempt to use the newer KVM_SEV_INIT2 kernel
|
||||||
|
interface in conjunction with the newer KVM_X86_SEV_VM and
|
||||||
|
KVM_X86_SEV_ES_VM KVM VM types.
|
||||||
|
|
||||||
|
This can lead to measurement changes if, for instance, an SEV guest was
|
||||||
|
created on a host that originally had an older kernel that didn't
|
||||||
|
support KVM_SEV_INIT2, but is booted on the same host later on after the
|
||||||
|
host kernel was upgraded.
|
||||||
|
|
||||||
|
Instead, if legacy-vm-type is 'off', QEMU should fail if the
|
||||||
|
KVM_SEV_INIT2 interface is not provided by the current host kernel.
|
||||||
|
Modify the fallback handling accordingly.
|
||||||
|
|
||||||
|
In the future, VMSA features and other flags might be added to QEMU
|
||||||
|
which will require legacy-vm-type to be 'off' because they will rely
|
||||||
|
on the newer KVM_SEV_INIT2 interface. It may be difficult to convey to
|
||||||
|
users what values of legacy-vm-type are compatible with which
|
||||||
|
features/options, so as part of this rework, switch legacy-vm-type to a
|
||||||
|
tri-state OnOffAuto option. 'auto' in this case will automatically
|
||||||
|
switch to using the newer KVM_SEV_INIT2, but only if it is required to
|
||||||
|
make use of new VMSA features or other options only available via
|
||||||
|
KVM_SEV_INIT2.
|
||||||
|
|
||||||
|
Defining 'auto' in this way would avoid inadvertantly breaking
|
||||||
|
compatibility with older kernels since it would only be used in cases
|
||||||
|
where users opt into newer features that are only available via
|
||||||
|
KVM_SEV_INIT2 and newer kernels, and provide better default behavior
|
||||||
|
than the legacy-vm-type=off behavior that was previously in place, so
|
||||||
|
make it the default for 9.1+ machine types.
|
||||||
|
|
||||||
|
Cc: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Cc: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
cc: kvm@vger.kernel.org
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||||
|
Link: https://lore.kernel.org/r/20240710041005.83720-1-michael.roth@amd.com
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 9d38d9dca2a81aaf5752d45d221021ef96d496cd)
|
||||||
|
|
||||||
|
RHEL: adjust compatiility setting, applying it to 9.4 machine type
|
||||||
|
---
|
||||||
|
hw/i386/pc.c | 2 +-
|
||||||
|
qapi/qom.json | 18 ++++++----
|
||||||
|
target/i386/sev.c | 85 +++++++++++++++++++++++++++++++++++++++--------
|
||||||
|
3 files changed, 83 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
|
||||||
|
index b25d075b59..e9c5ea5d8f 100644
|
||||||
|
--- a/hw/i386/pc.c
|
||||||
|
+++ b/hw/i386/pc.c
|
||||||
|
@@ -352,7 +352,7 @@ const size_t pc_rhel_compat_len = G_N_ELEMENTS(pc_rhel_compat);
|
||||||
|
GlobalProperty pc_rhel_9_5_compat[] = {
|
||||||
|
/* pc_rhel_9_5_compat from pc_compat_pc_9_0 (backported from 9.1) */
|
||||||
|
{ TYPE_X86_CPU, "guest-phys-bits", "0" },
|
||||||
|
- { "sev-guest", "legacy-vm-type", "true" },
|
||||||
|
+ { "sev-guest", "legacy-vm-type", "on" },
|
||||||
|
};
|
||||||
|
const size_t pc_rhel_9_5_compat_len = G_N_ELEMENTS(pc_rhel_9_5_compat);
|
||||||
|
|
||||||
|
diff --git a/qapi/qom.json b/qapi/qom.json
|
||||||
|
index 8bd299265e..17bd5a0cf7 100644
|
||||||
|
--- a/qapi/qom.json
|
||||||
|
+++ b/qapi/qom.json
|
||||||
|
@@ -912,12 +912,16 @@
|
||||||
|
# @handle: SEV firmware handle (default: 0)
|
||||||
|
#
|
||||||
|
# @legacy-vm-type: Use legacy KVM_SEV_INIT KVM interface for creating the VM.
|
||||||
|
-# The newer KVM_SEV_INIT2 interface syncs additional vCPU
|
||||||
|
-# state when initializing the VMSA structures, which will
|
||||||
|
-# result in a different guest measurement. Set this to
|
||||||
|
-# maintain compatibility with older QEMU or kernel versions
|
||||||
|
-# that rely on legacy KVM_SEV_INIT behavior.
|
||||||
|
-# (default: false) (since 9.1)
|
||||||
|
+# The newer KVM_SEV_INIT2 interface, from Linux >= 6.10, syncs
|
||||||
|
+# additional vCPU state when initializing the VMSA structures,
|
||||||
|
+# which will result in a different guest measurement. Set
|
||||||
|
+# this to 'on' to force compatibility with older QEMU or kernel
|
||||||
|
+# versions that rely on legacy KVM_SEV_INIT behavior. 'auto'
|
||||||
|
+# will behave identically to 'on', but will automatically
|
||||||
|
+# switch to using KVM_SEV_INIT2 if the user specifies any
|
||||||
|
+# additional options that require it. If set to 'off', QEMU
|
||||||
|
+# will require KVM_SEV_INIT2 unconditionally.
|
||||||
|
+# (default: off) (since 9.1)
|
||||||
|
#
|
||||||
|
# Since: 2.12
|
||||||
|
##
|
||||||
|
@@ -927,7 +931,7 @@
|
||||||
|
'*session-file': 'str',
|
||||||
|
'*policy': 'uint32',
|
||||||
|
'*handle': 'uint32',
|
||||||
|
- '*legacy-vm-type': 'bool' } }
|
||||||
|
+ '*legacy-vm-type': 'OnOffAuto' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @SevSnpGuestProperties:
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 491fab74fd..b921defb63 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -144,7 +144,7 @@ struct SevGuestState {
|
||||||
|
uint32_t policy;
|
||||||
|
char *dh_cert_file;
|
||||||
|
char *session_file;
|
||||||
|
- bool legacy_vm_type;
|
||||||
|
+ OnOffAuto legacy_vm_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SevSnpGuestState {
|
||||||
|
@@ -1334,6 +1334,17 @@ sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * This helper is to examine sev-guest properties and determine if any options
|
||||||
|
+ * have been set which rely on the newer KVM_SEV_INIT2 interface and associated
|
||||||
|
+ * KVM VM types.
|
||||||
|
+ */
|
||||||
|
+static bool sev_init2_required(SevGuestState *sev_guest)
|
||||||
|
+{
|
||||||
|
+ /* Currently no KVM_SEV_INIT2-specific options are exposed via QEMU */
|
||||||
|
+ return false;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int sev_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(cg);
|
||||||
|
@@ -1344,14 +1355,39 @@ static int sev_kvm_type(X86ConfidentialGuest *cg)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* These are the only cases where legacy VM types can be used. */
|
||||||
|
+ if (sev_guest->legacy_vm_type == ON_OFF_AUTO_ON ||
|
||||||
|
+ (sev_guest->legacy_vm_type == ON_OFF_AUTO_AUTO &&
|
||||||
|
+ !sev_init2_required(sev_guest))) {
|
||||||
|
+ sev_common->kvm_type = KVM_X86_DEFAULT_VM;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Newer VM types are required, either explicitly via legacy-vm-type=on, or
|
||||||
|
+ * implicitly via legacy-vm-type=auto along with additional sev-guest
|
||||||
|
+ * properties that require the newer VM types.
|
||||||
|
+ */
|
||||||
|
kvm_type = (sev_guest->policy & SEV_POLICY_ES) ?
|
||||||
|
KVM_X86_SEV_ES_VM : KVM_X86_SEV_VM;
|
||||||
|
- if (kvm_is_vm_type_supported(kvm_type) && !sev_guest->legacy_vm_type) {
|
||||||
|
- sev_common->kvm_type = kvm_type;
|
||||||
|
- } else {
|
||||||
|
- sev_common->kvm_type = KVM_X86_DEFAULT_VM;
|
||||||
|
+ if (!kvm_is_vm_type_supported(kvm_type)) {
|
||||||
|
+ if (sev_guest->legacy_vm_type == ON_OFF_AUTO_AUTO) {
|
||||||
|
+ error_report("SEV: host kernel does not support requested %s VM type, which is required "
|
||||||
|
+ "for the set of options specified. To allow use of the legacy "
|
||||||
|
+ "KVM_X86_DEFAULT_VM VM type, please disable any options that are not "
|
||||||
|
+ "compatible with the legacy VM type, or upgrade your kernel.",
|
||||||
|
+ kvm_type == KVM_X86_SEV_VM ? "KVM_X86_SEV_VM" : "KVM_X86_SEV_ES_VM");
|
||||||
|
+ } else {
|
||||||
|
+ error_report("SEV: host kernel does not support requested %s VM type. To allow use of "
|
||||||
|
+ "the legacy KVM_X86_DEFAULT_VM VM type, the 'legacy-vm-type' argument "
|
||||||
|
+ "must be set to 'on' or 'auto' for the sev-guest object.",
|
||||||
|
+ kvm_type == KVM_X86_SEV_VM ? "KVM_X86_SEV_VM" : "KVM_X86_SEV_ES_VM");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ sev_common->kvm_type = kvm_type;
|
||||||
|
out:
|
||||||
|
return sev_common->kvm_type;
|
||||||
|
}
|
||||||
|
@@ -1442,14 +1478,24 @@ static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
trace_kvm_sev_init();
|
||||||
|
- if (x86_klass->kvm_type(X86_CONFIDENTIAL_GUEST(sev_common)) == KVM_X86_DEFAULT_VM) {
|
||||||
|
+ switch (x86_klass->kvm_type(X86_CONFIDENTIAL_GUEST(sev_common))) {
|
||||||
|
+ case KVM_X86_DEFAULT_VM:
|
||||||
|
cmd = sev_es_enabled() ? KVM_SEV_ES_INIT : KVM_SEV_INIT;
|
||||||
|
|
||||||
|
ret = sev_ioctl(sev_common->sev_fd, cmd, NULL, &fw_error);
|
||||||
|
- } else {
|
||||||
|
+ break;
|
||||||
|
+ case KVM_X86_SEV_VM:
|
||||||
|
+ case KVM_X86_SEV_ES_VM:
|
||||||
|
+ case KVM_X86_SNP_VM: {
|
||||||
|
struct kvm_sev_init args = { 0 };
|
||||||
|
|
||||||
|
ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_INIT2, &args, &fw_error);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ default:
|
||||||
|
+ error_setg(errp, "%s: host kernel does not support the requested SEV configuration.",
|
||||||
|
+ __func__);
|
||||||
|
+ return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
@@ -2037,14 +2083,23 @@ sev_guest_set_session_file(Object *obj, const char *value, Error **errp)
|
||||||
|
SEV_GUEST(obj)->session_file = g_strdup(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool sev_guest_get_legacy_vm_type(Object *obj, Error **errp)
|
||||||
|
+static void sev_guest_get_legacy_vm_type(Object *obj, Visitor *v,
|
||||||
|
+ const char *name, void *opaque,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- return SEV_GUEST(obj)->legacy_vm_type;
|
||||||
|
+ SevGuestState *sev_guest = SEV_GUEST(obj);
|
||||||
|
+ OnOffAuto legacy_vm_type = sev_guest->legacy_vm_type;
|
||||||
|
+
|
||||||
|
+ visit_type_OnOffAuto(v, name, &legacy_vm_type, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void sev_guest_set_legacy_vm_type(Object *obj, bool value, Error **errp)
|
||||||
|
+static void sev_guest_set_legacy_vm_type(Object *obj, Visitor *v,
|
||||||
|
+ const char *name, void *opaque,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- SEV_GUEST(obj)->legacy_vm_type = value;
|
||||||
|
+ SevGuestState *sev_guest = SEV_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ visit_type_OnOffAuto(v, name, &sev_guest->legacy_vm_type, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
@@ -2070,9 +2125,9 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
sev_guest_set_session_file);
|
||||||
|
object_class_property_set_description(oc, "session-file",
|
||||||
|
"guest owners session parameters (encoded with base64)");
|
||||||
|
- object_class_property_add_bool(oc, "legacy-vm-type",
|
||||||
|
- sev_guest_get_legacy_vm_type,
|
||||||
|
- sev_guest_set_legacy_vm_type);
|
||||||
|
+ object_class_property_add(oc, "legacy-vm-type", "OnOffAuto",
|
||||||
|
+ sev_guest_get_legacy_vm_type,
|
||||||
|
+ sev_guest_set_legacy_vm_type, NULL, NULL);
|
||||||
|
object_class_property_set_description(oc, "legacy-vm-type",
|
||||||
|
"use legacy VM type to maintain measurement compatibility with older QEMU or kernel versions.");
|
||||||
|
}
|
||||||
|
@@ -2088,6 +2143,8 @@ sev_guest_instance_init(Object *obj)
|
||||||
|
object_property_add_uint32_ptr(obj, "policy", &sev_guest->policy,
|
||||||
|
OBJ_PROP_FLAG_READWRITE);
|
||||||
|
object_apply_compat_props(obj);
|
||||||
|
+
|
||||||
|
+ sev_guest->legacy_vm_type = ON_OFF_AUTO_AUTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* guest info specific sev/sev-es */
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,46 @@
|
|||||||
|
From ebb3c3536366c383fa09b0987a4efb68d018b7b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:24 -0500
|
||||||
|
Subject: [PATCH 064/100] i386/sev: Don't return launch measurements for
|
||||||
|
SEV-SNP guests
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [64/91] 5a29bb2d8b5a07aec6fd271ec37345e665e9cce4 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
For SEV-SNP guests, launch measurement is queried from within the guest
|
||||||
|
during attestation, so don't attempt to return it as part of
|
||||||
|
query-sev-launch-measure.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-13-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 73ae63b162fc1fed520f53ad200712964d7d0264)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 6525b3c1a0..c3daaf1ad5 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -795,7 +795,9 @@ sev_launch_get_measure(Notifier *notifier, void *unused)
|
||||||
|
|
||||||
|
static char *sev_get_launch_measurement(void)
|
||||||
|
{
|
||||||
|
- SevGuestState *sev_guest = SEV_GUEST(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+ ConfidentialGuestSupport *cgs = MACHINE(qdev_get_machine())->cgs;
|
||||||
|
+ SevGuestState *sev_guest =
|
||||||
|
+ (SevGuestState *)object_dynamic_cast(OBJECT(cgs), TYPE_SEV_GUEST);
|
||||||
|
|
||||||
|
if (sev_guest &&
|
||||||
|
SEV_COMMON(sev_guest)->state >= SEV_STATE_LAUNCH_SECRET) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From 0612c7ed587422ec7e07c27c8ca11b89c7aa8b02 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michael Roth <michael.roth@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:43 -0500
|
||||||
|
Subject: [PATCH 077/100] i386/sev: Enable KVM_HC_MAP_GPA_RANGE hcall for SNP
|
||||||
|
guests
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [77/91] 3c494eb54499c24121cc2c47045626478b8bb41e (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
KVM will forward GHCB page-state change requests to userspace in the
|
||||||
|
form of KVM_HC_MAP_GPA_RANGE, so make sure the hypercall handling is
|
||||||
|
enabled for SNP guests.
|
||||||
|
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-32-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit e3cddff93c1f88fea3b26841e792dc0be6b6fae8)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 5 +++++
|
||||||
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index eaf5fc6c6b..abb63062ac 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -14,6 +14,7 @@
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
#include <linux/kvm.h>
|
||||||
|
+#include <linux/kvm_para.h>
|
||||||
|
#include <linux/psp-sev.h>
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
@@ -758,6 +759,10 @@ sev_snp_launch_start(SevCommonState *sev_common)
|
||||||
|
trace_kvm_sev_snp_launch_start(start->policy,
|
||||||
|
sev_snp_guest->guest_visible_workarounds);
|
||||||
|
|
||||||
|
+ if (!kvm_enable_hypercall(BIT_ULL(KVM_HC_MAP_GPA_RANGE))) {
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
rc = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_LAUNCH_START,
|
||||||
|
start, &fw_error);
|
||||||
|
if (rc < 0) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,167 @@
|
|||||||
|
From eed17520567c202f53ab767bfd42cfe303838772 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:33 -0500
|
||||||
|
Subject: [PATCH 078/100] i386/sev: Extract build_kernel_loader_hashes
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [78/91] 291ea10e774178826d1afd38fc8292d67c5fd42d (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Extract the building of the kernel hashes table out from
|
||||||
|
sev_add_kernel_loader_hashes() to allow building it in
|
||||||
|
other memory areas (for SNP support).
|
||||||
|
|
||||||
|
No functional change intended.
|
||||||
|
|
||||||
|
Signed-off-by: Dov Murik <dovmurik@linux.ibm.com>
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-22-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 06cbd66cecaa3230cccb330facac241a677b29d5)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 102 ++++++++++++++++++++++++++--------------------
|
||||||
|
1 file changed, 58 insertions(+), 44 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index abb63062ac..73f9406715 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1754,45 +1754,16 @@ static const QemuUUID sev_cmdline_entry_guid = {
|
||||||
|
0x4d, 0x36, 0xab, 0x2a)
|
||||||
|
};
|
||||||
|
|
||||||
|
-/*
|
||||||
|
- * Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
|
||||||
|
- * which is included in SEV's initial memory measurement.
|
||||||
|
- */
|
||||||
|
-bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
+static bool build_kernel_loader_hashes(PaddedSevHashTable *padded_ht,
|
||||||
|
+ SevKernelLoaderContext *ctx,
|
||||||
|
+ Error **errp)
|
||||||
|
{
|
||||||
|
- uint8_t *data;
|
||||||
|
- SevHashTableDescriptor *area;
|
||||||
|
SevHashTable *ht;
|
||||||
|
- PaddedSevHashTable *padded_ht;
|
||||||
|
uint8_t cmdline_hash[HASH_SIZE];
|
||||||
|
uint8_t initrd_hash[HASH_SIZE];
|
||||||
|
uint8_t kernel_hash[HASH_SIZE];
|
||||||
|
uint8_t *hashp;
|
||||||
|
size_t hash_len = HASH_SIZE;
|
||||||
|
- hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
- MemTxAttrs attrs = { 0 };
|
||||||
|
- bool ret = true;
|
||||||
|
- SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * Only add the kernel hashes if the sev-guest configuration explicitly
|
||||||
|
- * stated kernel-hashes=on.
|
||||||
|
- */
|
||||||
|
- if (!sev_common->kernel_hashes) {
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
|
||||||
|
- error_setg(errp, "SEV: kernel specified but guest firmware "
|
||||||
|
- "has no hashes table GUID");
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
- area = (SevHashTableDescriptor *)data;
|
||||||
|
- if (!area->base || area->size < sizeof(PaddedSevHashTable)) {
|
||||||
|
- error_setg(errp, "SEV: guest firmware hashes table area is invalid "
|
||||||
|
- "(base=0x%x size=0x%x)", area->base, area->size);
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate hash of kernel command-line with the terminating null byte. If
|
||||||
|
@@ -1829,16 +1800,6 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
}
|
||||||
|
assert(hash_len == HASH_SIZE);
|
||||||
|
|
||||||
|
- /*
|
||||||
|
- * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
- * area for the SEV hashes table
|
||||||
|
- */
|
||||||
|
- padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
- &mapped_len, true, attrs);
|
||||||
|
- if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
- error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
ht = &padded_ht->ht;
|
||||||
|
|
||||||
|
ht->guid = sev_hash_table_header_guid;
|
||||||
|
@@ -1859,8 +1820,61 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
/* zero the excess data so the measurement can be reliably calculated */
|
||||||
|
memset(padded_ht->padding, 0, sizeof(padded_ht->padding));
|
||||||
|
|
||||||
|
- if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
- sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Add the hashes of the linux kernel/initrd/cmdline to an encrypted guest page
|
||||||
|
+ * which is included in SEV's initial memory measurement.
|
||||||
|
+ */
|
||||||
|
+bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp)
|
||||||
|
+{
|
||||||
|
+ uint8_t *data;
|
||||||
|
+ SevHashTableDescriptor *area;
|
||||||
|
+ PaddedSevHashTable *padded_ht;
|
||||||
|
+ hwaddr mapped_len = sizeof(*padded_ht);
|
||||||
|
+ MemTxAttrs attrs = { 0 };
|
||||||
|
+ bool ret = true;
|
||||||
|
+ SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Only add the kernel hashes if the sev-guest configuration explicitly
|
||||||
|
+ * stated kernel-hashes=on.
|
||||||
|
+ */
|
||||||
|
+ if (!sev_common->kernel_hashes) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!pc_system_ovmf_table_find(SEV_HASH_TABLE_RV_GUID, &data, NULL)) {
|
||||||
|
+ error_setg(errp, "SEV: kernel specified but guest firmware "
|
||||||
|
+ "has no hashes table GUID");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ area = (SevHashTableDescriptor *)data;
|
||||||
|
+ if (!area->base || area->size < sizeof(PaddedSevHashTable)) {
|
||||||
|
+ error_setg(errp, "SEV: guest firmware hashes table area is invalid "
|
||||||
|
+ "(base=0x%x size=0x%x)", area->base, area->size);
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Populate the hashes table in the guest's memory at the OVMF-designated
|
||||||
|
+ * area for the SEV hashes table
|
||||||
|
+ */
|
||||||
|
+ padded_ht = address_space_map(&address_space_memory, area->base,
|
||||||
|
+ &mapped_len, true, attrs);
|
||||||
|
+ if (!padded_ht || mapped_len != sizeof(*padded_ht)) {
|
||||||
|
+ error_setg(errp, "SEV: cannot map hashes table guest memory area");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (build_kernel_loader_hashes(padded_ht, ctx, errp)) {
|
||||||
|
+ if (sev_encrypt_flash(area->base, (uint8_t *)padded_ht,
|
||||||
|
+ sizeof(*padded_ht), errp) < 0) {
|
||||||
|
+ ret = false;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,65 @@
|
|||||||
|
From a9530c89225fce9e381929c4cd8e372068827acf Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Date: Mon, 24 Jun 2024 10:52:49 +0200
|
||||||
|
Subject: [PATCH 089/100] i386/sev: Fallback to the default SEV device if none
|
||||||
|
provided in sev_get_capabilities()
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [89/91] 22318c20d7102815f754cec0efaf383e05ef79c1 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When management tools (e.g. libvirt) query QEMU capabilities,
|
||||||
|
they start QEMU with a minimalistic configuration and issue
|
||||||
|
various commands on monitor. One of the command issued is/might
|
||||||
|
be "query-sev-capabilities" to learn values like cbitpos or
|
||||||
|
reduced-phys-bits. But as of v9.0.0-1145-g16dcf200dc the monitor
|
||||||
|
command returns an error instead.
|
||||||
|
|
||||||
|
This creates a chicken-egg problem because in order to query
|
||||||
|
those aforementioned values QEMU needs to be started with a
|
||||||
|
'sev-guest' object. But to start QEMU with the values must be
|
||||||
|
known.
|
||||||
|
|
||||||
|
I think it's safe to assume that the default path ("/dev/sev")
|
||||||
|
provides the same data as user provided one. So fall back to it.
|
||||||
|
|
||||||
|
Fixes: 16dcf200dc951c1cde3e5b442457db5f690b8cf0
|
||||||
|
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Link: https://lore.kernel.org/r/157f93712c23818be193ce785f648f0060b33dee.1719218926.git.mprivozn@redhat.com
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 3fb24530b2bb1346a44e17becefc9865b40a2257)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 10 +++++-----
|
||||||
|
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 53b7f7315b..491fab74fd 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -585,13 +585,13 @@ static SevCapability *sev_get_capabilities(Error **errp)
|
||||||
|
}
|
||||||
|
|
||||||
|
sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
- if (!sev_common) {
|
||||||
|
- error_setg(errp, "SEV is not configured");
|
||||||
|
- return NULL;
|
||||||
|
+ if (sev_common) {
|
||||||
|
+ sev_device = object_property_get_str(OBJECT(sev_common), "sev-device",
|
||||||
|
+ &error_abort);
|
||||||
|
+ } else {
|
||||||
|
+ sev_device = g_strdup(DEFAULT_SEV_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sev_device = object_property_get_str(OBJECT(sev_common), "sev-device",
|
||||||
|
- &error_abort);
|
||||||
|
fd = open(sev_device, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
error_setg_errno(errp, errno, "SEV: Failed to open %s",
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
From b672cdf8c10a530b5bcf6dd4489632891eb2c731 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Date: Mon, 24 Jun 2024 10:52:48 +0200
|
||||||
|
Subject: [PATCH 088/100] i386/sev: Fix error message in sev_get_capabilities()
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [88/91] ff8a8b27af02e565172ffe39d0571c234317713d (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When a custom path is provided to sev-guest object and opening
|
||||||
|
the path fails an error message is reported. But the error
|
||||||
|
message still mentions DEFAULT_SEV_DEVICE ("/dev/sev") instead of
|
||||||
|
the custom path.
|
||||||
|
|
||||||
|
Fixes: 16dcf200dc951c1cde3e5b442457db5f690b8cf0
|
||||||
|
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
||||||
|
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
|
Link: https://lore.kernel.org/r/b4648905d399780063dc70851d3d6a3cd28719a5.1719218926.git.mprivozn@redhat.com
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit e306ae87e0ef04bc7a5dec6db693f6ea09d64d45)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 37de80adc7..53b7f7315b 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -595,7 +595,7 @@ static SevCapability *sev_get_capabilities(Error **errp)
|
||||||
|
fd = open(sev_device, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
error_setg_errno(errp, errno, "SEV: Failed to open %s",
|
||||||
|
- DEFAULT_SEV_DEVICE);
|
||||||
|
+ sev_device);
|
||||||
|
g_free(sev_device);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,530 @@
|
|||||||
|
From 900859fd3445b9a71f1a9a8befda17f0c33f3923 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:19 -0500
|
||||||
|
Subject: [PATCH 059/100] i386/sev: Introduce 'sev-snp-guest' object
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [59/91] 3e585113d209176c2b97ad5e4fe943f19dfdcaeb (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
SEV-SNP support relies on a different set of properties/state than the
|
||||||
|
existing 'sev-guest' object. This patch introduces the 'sev-snp-guest'
|
||||||
|
object, which can be used to configure an SEV-SNP guest. For example,
|
||||||
|
a default-configured SEV-SNP guest with no additional information
|
||||||
|
passed in for use with attestation:
|
||||||
|
|
||||||
|
-object sev-snp-guest,id=sev0
|
||||||
|
|
||||||
|
or a fully-specified SEV-SNP guest where all spec-defined binary
|
||||||
|
blobs are passed in as base64-encoded strings:
|
||||||
|
|
||||||
|
-object sev-snp-guest,id=sev0, \
|
||||||
|
policy=0x30000, \
|
||||||
|
init-flags=0, \
|
||||||
|
id-block=YWFhYWFhYWFhYWFhYWFhCg==, \
|
||||||
|
id-auth=CxHK/OKLkXGn/KpAC7Wl1FSiisWDbGTEKz..., \
|
||||||
|
author-key-enabled=on, \
|
||||||
|
host-data=LNkCWBRC5CcdGXirbNUV1OrsR28s..., \
|
||||||
|
guest-visible-workarounds=AA==, \
|
||||||
|
|
||||||
|
See the QAPI schema updates included in this patch for more usage
|
||||||
|
details.
|
||||||
|
|
||||||
|
In some cases these blobs may be up to 4096 characters, but this is
|
||||||
|
generally well below the default limit for linux hosts where
|
||||||
|
command-line sizes are defined by the sysconf-configurable ARG_MAX
|
||||||
|
value, which defaults to 2097152 characters for Ubuntu hosts, for
|
||||||
|
example.
|
||||||
|
|
||||||
|
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||||
|
Co-developed-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Acked-by: Markus Armbruster <armbru@redhat.com> (for QAPI schema)
|
||||||
|
Signed-off-by: Michael Roth <michael.roth@amd.com>
|
||||||
|
Co-developed-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-8-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 7b34df44260b391e33bc3acf1ced30019d9aadf1)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
docs/system/i386/amd-memory-encryption.rst | 70 +++++-
|
||||||
|
qapi/qom.json | 58 +++++
|
||||||
|
target/i386/sev.c | 253 +++++++++++++++++++++
|
||||||
|
target/i386/sev.h | 1 +
|
||||||
|
4 files changed, 380 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/docs/system/i386/amd-memory-encryption.rst b/docs/system/i386/amd-memory-encryption.rst
|
||||||
|
index e9bc142bc1..748f5094ba 100644
|
||||||
|
--- a/docs/system/i386/amd-memory-encryption.rst
|
||||||
|
+++ b/docs/system/i386/amd-memory-encryption.rst
|
||||||
|
@@ -25,8 +25,8 @@ support for notifying a guest's operating system when certain types of VMEXITs
|
||||||
|
are about to occur. This allows the guest to selectively share information with
|
||||||
|
the hypervisor to satisfy the requested function.
|
||||||
|
|
||||||
|
-Launching
|
||||||
|
----------
|
||||||
|
+Launching (SEV and SEV-ES)
|
||||||
|
+--------------------------
|
||||||
|
|
||||||
|
Boot images (such as bios) must be encrypted before a guest can be booted. The
|
||||||
|
``MEMORY_ENCRYPT_OP`` ioctl provides commands to encrypt the images: ``LAUNCH_START``,
|
||||||
|
@@ -161,6 +161,72 @@ The value of GCTX.LD is
|
||||||
|
If kernel hashes are not used, or SEV-ES is disabled, use empty blobs for
|
||||||
|
``kernel_hashes_blob`` and ``vmsas_blob`` as needed.
|
||||||
|
|
||||||
|
+Launching (SEV-SNP)
|
||||||
|
+-------------------
|
||||||
|
+Boot images (such as bios) must be encrypted before a guest can be booted. The
|
||||||
|
+``MEMORY_ENCRYPT_OP`` ioctl provides commands to encrypt the images:
|
||||||
|
+``SNP_LAUNCH_START``, ``SNP_LAUNCH_UPDATE``, and ``SNP_LAUNCH_FINISH``. These
|
||||||
|
+three commands communicate with SEV-SNP firmware to generate a fresh memory
|
||||||
|
+encryption key for the VM, encrypt the boot images for a successful launch. For
|
||||||
|
+more details on the SEV-SNP firmware interfaces used by these commands please
|
||||||
|
+see the SEV-SNP Firmware ABI.
|
||||||
|
+
|
||||||
|
+``SNP_LAUNCH_START`` is called first to create a cryptographic launch context
|
||||||
|
+within the firmware. To create this context, the guest owner must provide a
|
||||||
|
+guest policy and other parameters as described in the SEV-SNP firmware
|
||||||
|
+specification. The launch parameters should be specified as described in the
|
||||||
|
+QAPI schema for the sev-snp-guest object.
|
||||||
|
+
|
||||||
|
+The ``SNP_LAUNCH_START`` uses the following parameters, which can be configured
|
||||||
|
+by the corresponding parameters documented in the QAPI schema for the
|
||||||
|
+'sev-snp-guest' object.
|
||||||
|
+
|
||||||
|
++--------+-------+----------+-------------------------------------------------+
|
||||||
|
+| key | type | default | meaning |
|
||||||
|
++---------------------------+-------------------------------------------------+
|
||||||
|
+| policy | hex | 0x30000 | a 64-bit guest policy |
|
||||||
|
++---------------------------+-------------------------------------------------+
|
||||||
|
+| guest-visible-workarounds | string| 0 | 16-byte base64 encoded string|
|
||||||
|
+| | | | for guest OS visible |
|
||||||
|
+| | | | workarounds. |
|
||||||
|
++---------------------------+-------------------------------------------------+
|
||||||
|
+
|
||||||
|
+``SNP_LAUNCH_UPDATE`` encrypts the memory region using the cryptographic context
|
||||||
|
+created via the ``SNP_LAUNCH_START`` command. If required, this command can be
|
||||||
|
+called multiple times to encrypt different memory regions. The command also
|
||||||
|
+calculates the measurement of the memory contents as it encrypts.
|
||||||
|
+
|
||||||
|
+``SNP_LAUNCH_FINISH`` finalizes the guest launch flow. Optionally, while
|
||||||
|
+finalizing the launch the firmware can perform checks on the launch digest
|
||||||
|
+computing through the ``SNP_LAUNCH_UPDATE``. To perform the check the user must
|
||||||
|
+supply the id block, authentication blob and host data that should be included
|
||||||
|
+in the attestation report. See the SEV-SNP spec for further details.
|
||||||
|
+
|
||||||
|
+The ``SNP_LAUNCH_FINISH`` uses the following parameters, which can be configured
|
||||||
|
+by the corresponding parameters documented in the QAPI schema for the
|
||||||
|
+'sev-snp-guest' object.
|
||||||
|
+
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| key | type | default | meaning |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| id-block | string| none | base64 encoded ID block |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| id-auth | string| none | base64 encoded authentication |
|
||||||
|
+| | | | information |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| author-key-enabled | bool | 0 | auth block contains author key |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+| host_data | string| none | host provided data |
|
||||||
|
++--------------------+-------+----------+-------------------------------------+
|
||||||
|
+
|
||||||
|
+To launch a SEV-SNP guest (additional parameters are documented in the QAPI
|
||||||
|
+schema for the 'sev-snp-guest' object)::
|
||||||
|
+
|
||||||
|
+ # ${QEMU} \
|
||||||
|
+ -machine ...,confidential-guest-support=sev0 \
|
||||||
|
+ -object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1
|
||||||
|
+
|
||||||
|
+
|
||||||
|
Debugging
|
||||||
|
---------
|
||||||
|
|
||||||
|
diff --git a/qapi/qom.json b/qapi/qom.json
|
||||||
|
index 056b38f491..8bd299265e 100644
|
||||||
|
--- a/qapi/qom.json
|
||||||
|
+++ b/qapi/qom.json
|
||||||
|
@@ -929,6 +929,62 @@
|
||||||
|
'*handle': 'uint32',
|
||||||
|
'*legacy-vm-type': 'bool' } }
|
||||||
|
|
||||||
|
+##
|
||||||
|
+# @SevSnpGuestProperties:
|
||||||
|
+#
|
||||||
|
+# Properties for sev-snp-guest objects. Most of these are direct
|
||||||
|
+# arguments for the KVM_SNP_* interfaces documented in the Linux
|
||||||
|
+# kernel source under
|
||||||
|
+# Documentation/arch/x86/amd-memory-encryption.rst, which are in turn
|
||||||
|
+# closely coupled with the SNP_INIT/SNP_LAUNCH_* firmware commands
|
||||||
|
+# documented in the SEV-SNP Firmware ABI Specification (Rev 0.9).
|
||||||
|
+#
|
||||||
|
+# More usage information is also available in the QEMU source tree
|
||||||
|
+# under docs/amd-memory-encryption.
|
||||||
|
+#
|
||||||
|
+# @policy: the 'POLICY' parameter to the SNP_LAUNCH_START command, as
|
||||||
|
+# defined in the SEV-SNP firmware ABI (default: 0x30000)
|
||||||
|
+#
|
||||||
|
+# @guest-visible-workarounds: 16-byte, base64-encoded blob to report
|
||||||
|
+# hypervisor-defined workarounds, corresponding to the 'GOSVW'
|
||||||
|
+# parameter of the SNP_LAUNCH_START command defined in the SEV-SNP
|
||||||
|
+# firmware ABI (default: all-zero)
|
||||||
|
+#
|
||||||
|
+# @id-block: 96-byte, base64-encoded blob to provide the 'ID Block'
|
||||||
|
+# structure for the SNP_LAUNCH_FINISH command defined in the
|
||||||
|
+# SEV-SNP firmware ABI (default: all-zero)
|
||||||
|
+#
|
||||||
|
+# @id-auth: 4096-byte, base64-encoded blob to provide the 'ID
|
||||||
|
+# Authentication Information Structure' for the SNP_LAUNCH_FINISH
|
||||||
|
+# command defined in the SEV-SNP firmware ABI (default: all-zero)
|
||||||
|
+#
|
||||||
|
+# @author-key-enabled: true if 'id-auth' blob contains the 'AUTHOR_KEY'
|
||||||
|
+# field defined SEV-SNP firmware ABI (default: false)
|
||||||
|
+#
|
||||||
|
+# @host-data: 32-byte, base64-encoded, user-defined blob to provide to
|
||||||
|
+# the guest, as documented for the 'HOST_DATA' parameter of the
|
||||||
|
+# SNP_LAUNCH_FINISH command in the SEV-SNP firmware ABI (default:
|
||||||
|
+# all-zero)
|
||||||
|
+#
|
||||||
|
+# @vcek-disabled: Guests are by default allowed to choose between VLEK
|
||||||
|
+# (Versioned Loaded Endorsement Key) or VCEK (Versioned Chip
|
||||||
|
+# Endorsement Key) when requesting attestation reports from
|
||||||
|
+# firmware. Set this to true to disable the use of VCEK.
|
||||||
|
+# (default: false) (since: 9.1)
|
||||||
|
+#
|
||||||
|
+# Since: 9.1
|
||||||
|
+##
|
||||||
|
+{ 'struct': 'SevSnpGuestProperties',
|
||||||
|
+ 'base': 'SevCommonProperties',
|
||||||
|
+ 'data': {
|
||||||
|
+ '*policy': 'uint64',
|
||||||
|
+ '*guest-visible-workarounds': 'str',
|
||||||
|
+ '*id-block': 'str',
|
||||||
|
+ '*id-auth': 'str',
|
||||||
|
+ '*author-key-enabled': 'bool',
|
||||||
|
+ '*host-data': 'str',
|
||||||
|
+ '*vcek-disabled': 'bool' } }
|
||||||
|
+
|
||||||
|
##
|
||||||
|
# @ThreadContextProperties:
|
||||||
|
#
|
||||||
|
@@ -1007,6 +1063,7 @@
|
||||||
|
{ 'name': 'secret_keyring',
|
||||||
|
'if': 'CONFIG_SECRET_KEYRING' },
|
||||||
|
'sev-guest',
|
||||||
|
+ 'sev-snp-guest',
|
||||||
|
'thread-context',
|
||||||
|
's390-pv-guest',
|
||||||
|
'throttle-group',
|
||||||
|
@@ -1077,6 +1134,7 @@
|
||||||
|
'secret_keyring': { 'type': 'SecretKeyringProperties',
|
||||||
|
'if': 'CONFIG_SECRET_KEYRING' },
|
||||||
|
'sev-guest': 'SevGuestProperties',
|
||||||
|
+ 'sev-snp-guest': 'SevSnpGuestProperties',
|
||||||
|
'thread-context': 'ThreadContextProperties',
|
||||||
|
'throttle-group': 'ThrottleGroupProperties',
|
||||||
|
'tls-creds-anon': 'TlsCredsAnonProperties',
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 28a018ed83..a81b3228d4 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -42,6 +42,7 @@
|
||||||
|
|
||||||
|
OBJECT_DECLARE_TYPE(SevCommonState, SevCommonStateClass, SEV_COMMON)
|
||||||
|
OBJECT_DECLARE_TYPE(SevGuestState, SevCommonStateClass, SEV_GUEST)
|
||||||
|
+OBJECT_DECLARE_TYPE(SevSnpGuestState, SevCommonStateClass, SEV_SNP_GUEST)
|
||||||
|
|
||||||
|
struct SevCommonState {
|
||||||
|
X86ConfidentialGuest parent_obj;
|
||||||
|
@@ -96,8 +97,22 @@ struct SevGuestState {
|
||||||
|
bool legacy_vm_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
+struct SevSnpGuestState {
|
||||||
|
+ SevCommonState parent_obj;
|
||||||
|
+
|
||||||
|
+ /* configuration parameters */
|
||||||
|
+ char *guest_visible_workarounds;
|
||||||
|
+ char *id_block;
|
||||||
|
+ char *id_auth;
|
||||||
|
+ char *host_data;
|
||||||
|
+
|
||||||
|
+ struct kvm_sev_snp_launch_start kvm_start_conf;
|
||||||
|
+ struct kvm_sev_snp_launch_finish kvm_finish_conf;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
|
||||||
|
#define DEFAULT_SEV_DEVICE "/dev/sev"
|
||||||
|
+#define DEFAULT_SEV_SNP_POLICY 0x30000
|
||||||
|
|
||||||
|
#define SEV_INFO_BLOCK_GUID "00f771de-1a7e-4fcb-890e-68c77e2fb44e"
|
||||||
|
typedef struct __attribute__((__packed__)) SevInfoBlock {
|
||||||
|
@@ -1500,11 +1515,249 @@ static const TypeInfo sev_guest_info = {
|
||||||
|
.class_init = sev_guest_class_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_get_policy(Object *obj, Visitor *v, const char *name,
|
||||||
|
+ void *opaque, Error **errp)
|
||||||
|
+{
|
||||||
|
+ visit_type_uint64(v, name,
|
||||||
|
+ (uint64_t *)&SEV_SNP_GUEST(obj)->kvm_start_conf.policy,
|
||||||
|
+ errp);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_policy(Object *obj, Visitor *v, const char *name,
|
||||||
|
+ void *opaque, Error **errp)
|
||||||
|
+{
|
||||||
|
+ visit_type_uint64(v, name,
|
||||||
|
+ (uint64_t *)&SEV_SNP_GUEST(obj)->kvm_start_conf.policy,
|
||||||
|
+ errp);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_guest_visible_workarounds(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ return g_strdup(SEV_SNP_GUEST(obj)->guest_visible_workarounds);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_guest_visible_workarounds(Object *obj, const char *value,
|
||||||
|
+ Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_start *start = &sev_snp_guest->kvm_start_conf;
|
||||||
|
+ g_autofree guchar *blob;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->guest_visible_workarounds);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->guest_visible_workarounds = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ blob = qbase64_decode(sev_snp_guest->guest_visible_workarounds,
|
||||||
|
+ -1, &len, errp);
|
||||||
|
+ if (!blob) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len != sizeof(start->gosvw)) {
|
||||||
|
+ error_setg(errp, "parameter length of %lu exceeds max of %lu",
|
||||||
|
+ len, sizeof(start->gosvw));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(start->gosvw, blob, len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_id_block(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return g_strdup(sev_snp_guest->id_block);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_id_block(Object *obj, const char *value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->id_block);
|
||||||
|
+ g_free((guchar *)finish->id_block_uaddr);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->id_block = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ finish->id_block_uaddr =
|
||||||
|
+ (uint64_t)qbase64_decode(sev_snp_guest->id_block, -1, &len, errp);
|
||||||
|
+
|
||||||
|
+ if (!finish->id_block_uaddr) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len != KVM_SEV_SNP_ID_BLOCK_SIZE) {
|
||||||
|
+ error_setg(errp, "parameter length of %lu not equal to %u",
|
||||||
|
+ len, KVM_SEV_SNP_ID_BLOCK_SIZE);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ finish->id_block_en = (len) ? 1 : 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_id_auth(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return g_strdup(sev_snp_guest->id_auth);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_id_auth(Object *obj, const char *value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->id_auth);
|
||||||
|
+ g_free((guchar *)finish->id_auth_uaddr);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->id_auth = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ finish->id_auth_uaddr =
|
||||||
|
+ (uint64_t)qbase64_decode(sev_snp_guest->id_auth, -1, &len, errp);
|
||||||
|
+
|
||||||
|
+ if (!finish->id_auth_uaddr) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len > KVM_SEV_SNP_ID_AUTH_SIZE) {
|
||||||
|
+ error_setg(errp, "parameter length:ID_AUTH %lu exceeds max of %u",
|
||||||
|
+ len, KVM_SEV_SNP_ID_AUTH_SIZE);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+sev_snp_guest_get_author_key_enabled(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return !!sev_snp_guest->kvm_finish_conf.auth_key_en;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_author_key_enabled(Object *obj, bool value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ sev_snp_guest->kvm_finish_conf.auth_key_en = value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static bool
|
||||||
|
+sev_snp_guest_get_vcek_disabled(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return !!sev_snp_guest->kvm_finish_conf.vcek_disabled;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_vcek_disabled(Object *obj, bool value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ sev_snp_guest->kvm_finish_conf.vcek_disabled = value;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static char *
|
||||||
|
+sev_snp_guest_get_host_data(Object *obj, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ return g_strdup(sev_snp_guest->host_data);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_set_host_data(Object *obj, const char *value, Error **errp)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+ struct kvm_sev_snp_launch_finish *finish = &sev_snp_guest->kvm_finish_conf;
|
||||||
|
+ g_autofree guchar *blob;
|
||||||
|
+ gsize len;
|
||||||
|
+
|
||||||
|
+ g_free(sev_snp_guest->host_data);
|
||||||
|
+
|
||||||
|
+ /* store the base64 str so we don't need to re-encode in getter */
|
||||||
|
+ sev_snp_guest->host_data = g_strdup(value);
|
||||||
|
+
|
||||||
|
+ blob = qbase64_decode(sev_snp_guest->host_data, -1, &len, errp);
|
||||||
|
+
|
||||||
|
+ if (!blob) {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (len != sizeof(finish->host_data)) {
|
||||||
|
+ error_setg(errp, "parameter length of %lu not equal to %lu",
|
||||||
|
+ len, sizeof(finish->host_data));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ memcpy(finish->host_data, blob, len);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
+{
|
||||||
|
+ object_class_property_add(oc, "policy", "uint64",
|
||||||
|
+ sev_snp_guest_get_policy,
|
||||||
|
+ sev_snp_guest_set_policy, NULL, NULL);
|
||||||
|
+ object_class_property_add_str(oc, "guest-visible-workarounds",
|
||||||
|
+ sev_snp_guest_get_guest_visible_workarounds,
|
||||||
|
+ sev_snp_guest_set_guest_visible_workarounds);
|
||||||
|
+ object_class_property_add_str(oc, "id-block",
|
||||||
|
+ sev_snp_guest_get_id_block,
|
||||||
|
+ sev_snp_guest_set_id_block);
|
||||||
|
+ object_class_property_add_str(oc, "id-auth",
|
||||||
|
+ sev_snp_guest_get_id_auth,
|
||||||
|
+ sev_snp_guest_set_id_auth);
|
||||||
|
+ object_class_property_add_bool(oc, "author-key-enabled",
|
||||||
|
+ sev_snp_guest_get_author_key_enabled,
|
||||||
|
+ sev_snp_guest_set_author_key_enabled);
|
||||||
|
+ object_class_property_add_bool(oc, "vcek-required",
|
||||||
|
+ sev_snp_guest_get_vcek_disabled,
|
||||||
|
+ sev_snp_guest_set_vcek_disabled);
|
||||||
|
+ object_class_property_add_str(oc, "host-data",
|
||||||
|
+ sev_snp_guest_get_host_data,
|
||||||
|
+ sev_snp_guest_set_host_data);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+sev_snp_guest_instance_init(Object *obj)
|
||||||
|
+{
|
||||||
|
+ SevSnpGuestState *sev_snp_guest = SEV_SNP_GUEST(obj);
|
||||||
|
+
|
||||||
|
+ /* default init/start/finish params for kvm */
|
||||||
|
+ sev_snp_guest->kvm_start_conf.policy = DEFAULT_SEV_SNP_POLICY;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* guest info specific to sev-snp */
|
||||||
|
+static const TypeInfo sev_snp_guest_info = {
|
||||||
|
+ .parent = TYPE_SEV_COMMON,
|
||||||
|
+ .name = TYPE_SEV_SNP_GUEST,
|
||||||
|
+ .instance_size = sizeof(SevSnpGuestState),
|
||||||
|
+ .class_init = sev_snp_guest_class_init,
|
||||||
|
+ .instance_init = sev_snp_guest_instance_init,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
sev_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&sev_common_info);
|
||||||
|
type_register_static(&sev_guest_info);
|
||||||
|
+ type_register_static(&sev_snp_guest_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(sev_register_types);
|
||||||
|
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||||
|
index 668374eef3..bedc667eeb 100644
|
||||||
|
--- a/target/i386/sev.h
|
||||||
|
+++ b/target/i386/sev.h
|
||||||
|
@@ -22,6 +22,7 @@
|
||||||
|
|
||||||
|
#define TYPE_SEV_COMMON "sev-common"
|
||||||
|
#define TYPE_SEV_GUEST "sev-guest"
|
||||||
|
+#define TYPE_SEV_SNP_GUEST "sev-snp-guest"
|
||||||
|
|
||||||
|
#define SEV_POLICY_NODBG 0x1
|
||||||
|
#define SEV_POLICY_NOKS 0x2
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,85 @@
|
|||||||
|
From be37914ae54c8aebc218cf41b37bc0ea1563daae Mon Sep 17 00:00:00 2001
|
||||||
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
Date: Fri, 31 May 2024 12:51:44 +0200
|
||||||
|
Subject: [PATCH 074/100] i386/sev: Invoke launch_updata_data() for SEV class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [74/91] f1b588a9ffecd6944a78186d88a6be3849698710 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Add launch_update_data() in SevCommonStateClass and
|
||||||
|
invoke as sev_launch_update_data() for SEV object.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-26-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 9861405a8f845133b7984322c2df0c43a45553c3)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 11 ++++++++---
|
||||||
|
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 7b5c4b4874..8834cf9441 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -74,6 +74,7 @@ struct SevCommonStateClass {
|
||||||
|
/* public */
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
+ int (*launch_update_data)(SevCommonState *sev_common, hwaddr gpa, uint8_t *ptr, uint64_t len);
|
||||||
|
int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp);
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -929,7 +930,7 @@ out:
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
-sev_launch_update_data(SevGuestState *sev_guest, uint8_t *addr, uint64_t len)
|
||||||
|
+sev_launch_update_data(SevCommonState *sev_common, hwaddr gpa, uint8_t *addr, uint64_t len)
|
||||||
|
{
|
||||||
|
int ret, fw_error;
|
||||||
|
struct kvm_sev_launch_update_data update;
|
||||||
|
@@ -941,7 +942,7 @@ sev_launch_update_data(SevGuestState *sev_guest, uint8_t *addr, uint64_t len)
|
||||||
|
update.uaddr = (uintptr_t)addr;
|
||||||
|
update.len = len;
|
||||||
|
trace_kvm_sev_launch_update_data(addr, len);
|
||||||
|
- ret = sev_ioctl(SEV_COMMON(sev_guest)->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
|
||||||
|
+ ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_LAUNCH_UPDATE_DATA,
|
||||||
|
&update, &fw_error);
|
||||||
|
if (ret) {
|
||||||
|
error_report("%s: LAUNCH_UPDATE ret=%d fw_error=%d '%s'",
|
||||||
|
@@ -1487,6 +1488,7 @@ int
|
||||||
|
sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
|
||||||
|
if (!sev_common) {
|
||||||
|
return 0;
|
||||||
|
@@ -1494,7 +1496,9 @@ sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
|
||||||
|
/* if SEV is in update state then encrypt the data else do nothing */
|
||||||
|
if (sev_check_state(sev_common, SEV_STATE_LAUNCH_UPDATE)) {
|
||||||
|
- int ret = sev_launch_update_data(SEV_GUEST(sev_common), ptr, len);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = klass->launch_update_data(sev_common, gpa, ptr, len);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_setg(errp, "SEV: Failed to encrypt pflash rom");
|
||||||
|
return ret;
|
||||||
|
@@ -1968,6 +1972,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
klass->launch_finish = sev_launch_finish;
|
||||||
|
+ klass->launch_update_data = sev_launch_update_data;
|
||||||
|
klass->kvm_init = sev_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_kvm_type;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
From 32899eb4fa5143b795b107de4857adce2cf1d434 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:38 -0500
|
||||||
|
Subject: [PATCH 075/100] i386/sev: Invoke launch_updata_data() for SNP class
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [75/91] 3520af5847f8dddb6d7fe7ad5feb308230f387b9 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Invoke as sev_snp_launch_update_data() for SNP object.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-27-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 0765d136eba400ad1cb7cae18438bb10eace64dc)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 10 ++++++++++
|
||||||
|
1 file changed, 10 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 8834cf9441..eaf5fc6c6b 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1091,6 +1091,15 @@ snp_launch_update_data(uint64_t gpa, void *hva,
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+sev_snp_launch_update_data(SevCommonState *sev_common, hwaddr gpa,
|
||||||
|
+ uint8_t *ptr, uint64_t len)
|
||||||
|
+{
|
||||||
|
+ int ret = snp_launch_update_data(gpa, ptr, len,
|
||||||
|
+ KVM_SEV_SNP_PAGE_TYPE_NORMAL);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int
|
||||||
|
sev_snp_cpuid_info_fill(SnpCpuidInfo *snp_cpuid_info,
|
||||||
|
const KvmCpuidInfo *kvm_cpuid_info)
|
||||||
|
@@ -2216,6 +2225,7 @@ sev_snp_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
|
||||||
|
klass->launch_start = sev_snp_launch_start;
|
||||||
|
klass->launch_finish = sev_snp_launch_finish;
|
||||||
|
+ klass->launch_update_data = sev_snp_launch_update_data;
|
||||||
|
klass->kvm_init = sev_snp_kvm_init;
|
||||||
|
x86_klass->kvm_type = sev_snp_kvm_type;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,47 @@
|
|||||||
|
From fa6076291eb45255bc2fe523399d7d0647fc5570 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Fri, 7 Jun 2024 13:36:10 -0500
|
||||||
|
Subject: [PATCH 085/100] i386/sev: Move SEV_COMMON null check before
|
||||||
|
dereferencing
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [85/91] e8d2bfd077766a5e7777b9337d0e77146f883224 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
Fixes Coverity CID 1546886.
|
||||||
|
|
||||||
|
Fixes: 9861405a8f ("i386/sev: Invoke launch_updata_data() for SEV class")
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240607183611.1111100-3-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit 48779faef3c8e2fe70bd8285bffa731bd76dc844)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index 7c9df621de..f18432f58e 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -1529,11 +1529,12 @@ int
|
||||||
|
sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs);
|
||||||
|
- SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
+ SevCommonStateClass *klass;
|
||||||
|
|
||||||
|
if (!sev_common) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
+ klass = SEV_COMMON_GET_CLASS(sev_common);
|
||||||
|
|
||||||
|
/* if SEV is in update state then encrypt the data else do nothing */
|
||||||
|
if (sev_check_state(sev_common, SEV_STATE_LAUNCH_UPDATE)) {
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
@ -0,0 +1,88 @@
|
|||||||
|
From 4d96ca893126d4c17c9fe03c76973b1d4a414f21 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Date: Thu, 30 May 2024 06:16:18 -0500
|
||||||
|
Subject: [PATCH 058/100] i386/sev: Move sev_launch_finish to separate class
|
||||||
|
method
|
||||||
|
|
||||||
|
RH-Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
RH-MergeRequest: 245: SEV-SNP support
|
||||||
|
RH-Jira: RHEL-39544
|
||||||
|
RH-Acked-by: Thomas Huth <thuth@redhat.com>
|
||||||
|
RH-Acked-by: Bandan Das <bdas@redhat.com>
|
||||||
|
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
||||||
|
RH-Commit: [58/91] 7865710d320a6df7038ef7016d350aa9cdcea326 (bonzini/rhel-qemu-kvm)
|
||||||
|
|
||||||
|
When sev-snp-guest objects are introduced there will be a number of
|
||||||
|
differences in how the launch finish is handled compared to the existing
|
||||||
|
sev-guest object. Move sev_launch_finish() to a class method to make it
|
||||||
|
easier to implement SNP-specific launch update functionality later.
|
||||||
|
|
||||||
|
Signed-off-by: Pankaj Gupta <pankaj.gupta@amd.com>
|
||||||
|
Message-ID: <20240530111643.1091816-7-pankaj.gupta@amd.com>
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
(cherry picked from commit bce615a14aec07cab0488e5a242f6a91e641efcb)
|
||||||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
---
|
||||||
|
target/i386/sev.c | 11 +++++++----
|
||||||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||||
|
index b2aa0d6f99..28a018ed83 100644
|
||||||
|
--- a/target/i386/sev.c
|
||||||
|
+++ b/target/i386/sev.c
|
||||||
|
@@ -71,6 +71,7 @@ struct SevCommonStateClass {
|
||||||
|
|
||||||
|
/* public */
|
||||||
|
int (*launch_start)(SevCommonState *sev_common);
|
||||||
|
+ void (*launch_finish)(SevCommonState *sev_common);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -801,12 +802,12 @@ static Notifier sev_machine_done_notify = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
-sev_launch_finish(SevGuestState *sev_guest)
|
||||||
|
+sev_launch_finish(SevCommonState *sev_common)
|
||||||
|
{
|
||||||
|
int ret, error;
|
||||||
|
|
||||||
|
trace_kvm_sev_launch_finish();
|
||||||
|
- ret = sev_ioctl(SEV_COMMON(sev_guest)->sev_fd, KVM_SEV_LAUNCH_FINISH, 0,
|
||||||
|
+ ret = sev_ioctl(sev_common->sev_fd, KVM_SEV_LAUNCH_FINISH, 0,
|
||||||
|
&error);
|
||||||
|
if (ret) {
|
||||||
|
error_report("%s: LAUNCH_FINISH ret=%d fw_error=%d '%s'",
|
||||||
|
@@ -814,7 +815,7 @@ sev_launch_finish(SevGuestState *sev_guest)
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
- sev_set_guest_state(SEV_COMMON(sev_guest), SEV_STATE_RUNNING);
|
||||||
|
+ sev_set_guest_state(sev_common, SEV_STATE_RUNNING);
|
||||||
|
|
||||||
|
/* add migration blocker */
|
||||||
|
error_setg(&sev_mig_blocker,
|
||||||
|
@@ -826,10 +827,11 @@ static void
|
||||||
|
sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||||
|
{
|
||||||
|
SevCommonState *sev_common = opaque;
|
||||||
|
+ SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(opaque);
|
||||||
|
|
||||||
|
if (running) {
|
||||||
|
if (!sev_check_state(sev_common, SEV_STATE_RUNNING)) {
|
||||||
|
- sev_launch_finish(SEV_GUEST(sev_common));
|
||||||
|
+ klass->launch_finish(sev_common);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1457,6 +1459,7 @@ sev_guest_class_init(ObjectClass *oc, void *data)
|
||||||
|
SevCommonStateClass *klass = SEV_COMMON_CLASS(oc);
|
||||||
|
|
||||||
|
klass->launch_start = sev_launch_start;
|
||||||
|
+ klass->launch_finish = sev_launch_finish;
|
||||||
|
|
||||||
|
object_class_property_add_str(oc, "dh-cert-file",
|
||||||
|
sev_guest_get_dh_cert_file,
|
||||||
|
--
|
||||||
|
2.39.3
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue