* [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP
@ 2025-02-07 8:51 Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH pve-edk2-firmware 1/4] Update edk2 to edkstable202411 Philipp Giersfeld
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Philipp Giersfeld @ 2025-02-07 8:51 UTC (permalink / raw)
To: pve-devel
This patch series adds support for AMD SEV-SNP.
Where possible it maintains the existing support for AMD SEV(-ES).
Running SEV-SNP VMs requires a more recent version of edk2
and OVMF firmware image. Contrary to other setups, SEV-SNP does not support loading the firmware via pflash. Instead, the firmware image is loaded via the -bios option.
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pve-devel] [PATCH pve-edk2-firmware 1/4] Update edk2 to edkstable202411
2025-02-07 8:51 [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP Philipp Giersfeld
@ 2025-02-07 8:51 ` Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH pve-edk2-firmware 2/4] Add OVMF targets for AMD SEV-ES and SEV-SNP Philipp Giersfeld
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Philipp Giersfeld @ 2025-02-07 8:51 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Philipp Giersfeld <philipp.giersfeld@canarybit.eu>
---
debian/binary-check.remove | 4 ++--
debian/rules | 6 +++---
edk2 | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/debian/binary-check.remove b/debian/binary-check.remove
index 7651301..e5f352a 100644
--- a/debian/binary-check.remove
+++ b/debian/binary-check.remove
@@ -1,5 +1,5 @@
-ArmPkg/Library/GccLto/liblto-aarch64.a
-ArmPkg/Library/GccLto/liblto-arm.a
+BaseTools/Bin/GccLto/liblto-aarch64.a
+BaseTools/Bin/GccLto/liblto-arm.a
BaseTools/Source/Python/Eot/EfiCompressor.pyd
BaseTools/Source/Python/Eot/LzmaCompressor.pyd
IntelFsp2Pkg/FspSecCore/Vtf0/Bin/ResetVec.ia32.raw
diff --git a/debian/rules b/debian/rules
index 7f92c16..2e9365b 100755
--- a/debian/rules
+++ b/debian/rules
@@ -180,10 +180,10 @@ debian/oem-string-%: debian/PkKek-1-%.pem
--no-default \
-C `< debian/oem-string-snakeoil` -o $@
-ArmPkg/Library/GccLto/liblto-aarch64.a: ArmPkg/Library/GccLto/liblto-aarch64.s
+BaseTools/Bin/GccLto/liblto-aarch64.a: BaseTools/Bin/GccLto/liblto-aarch64.s
$($(EDK2_TOOLCHAIN)_AARCH64_PREFIX)gcc -c -fpic $< -o $@
-ArmPkg/Library/GccLto/liblto-arm.a: ArmPkg/Library/GccLto/liblto-arm.s
+BaseTools/Bin/GccLto/liblto-arm.a: BaseTools/Bin/GccLto/liblto-arm.s
$($(EDK2_TOOLCHAIN)_ARM_PREFIX)gcc -c -fpic $< -o $@
build-qemu-efi: debian/setup-build-stamp
@@ -202,7 +202,7 @@ build-qemu-efi: debian/setup-build-stamp
truncate -s 64M $(QEMU_EFI_BUILD_DIR)/FV/$(FW_NAME)_VARS.fd
build-qemu-efi-aarch64: $(AAVMF_BINARIES) $(AAVMF_IMAGES) $(AAVMF_PREENROLLED_VARS)
-$(AAVMF_BINARIES) $(AAVMF_IMAGES): ArmPkg/Library/GccLto/liblto-aarch64.a
+$(AAVMF_BINARIES) $(AAVMF_IMAGES): BaseTools/Bin/GccLto/liblto-aarch64.a
$(MAKE) -f debian/rules build-qemu-efi EDK2_ARCH_DIR=AArch64 EDK2_HOST_ARCH=AARCH64 FW_NAME=AAVMF
build-qemu-efi-riscv64: $(RISCV64_IMAGES)
diff --git a/edk2 b/edk2
index 819cfc6..0f3867f 160000
--- a/edk2
+++ b/edk2
@@ -1 +1 @@
-Subproject commit 819cfc6b42a68790a23509e4fcc58ceb70e1965e
+Subproject commit 0f3867fa6ef0553e26c42f7d71ff6bdb98429742
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pve-devel] [PATCH pve-edk2-firmware 2/4] Add OVMF targets for AMD SEV-ES and SEV-SNP
2025-02-07 8:51 [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH pve-edk2-firmware 1/4] Update edk2 to edkstable202411 Philipp Giersfeld
@ 2025-02-07 8:51 ` Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH qemu-server 3/4] config: add AMD SEV-SNP support Philipp Giersfeld
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Philipp Giersfeld @ 2025-02-07 8:51 UTC (permalink / raw)
To: pve-devel
AMD SEV-SNP boots with a single volatile firmware image OVMF.fd via the
-bios option.
Currently, an SEV-enabled VM will not boot with an OVMF
firmware that was compiled with `SECURE_BOOT_ENABLE` [1].
Furthermore, during testing, SEV-enabled amchines did not boot with
`SMM_REQUIRE`.
Therefore, introduce a new target build-ovmf-cvm that builds OVMF
firmware suitable for AMD SEV.
[1] https://github.com/tianocore/edk2/pull/6285
Signed-off-by: Philipp Giersfeld <philipp.giersfeld@canarybit.eu>
---
debian/pve-edk2-firmware-ovmf.install | 3 +++
debian/rules | 35 +++++++++++++++++++++++----
2 files changed, 33 insertions(+), 5 deletions(-)
diff --git a/debian/pve-edk2-firmware-ovmf.install b/debian/pve-edk2-firmware-ovmf.install
index f4c0602..a51846e 100644
--- a/debian/pve-edk2-firmware-ovmf.install
+++ b/debian/pve-edk2-firmware-ovmf.install
@@ -1,5 +1,8 @@
debian/ovmf-install/OVMF_CODE*.fd /usr/share/pve-edk2-firmware
debian/ovmf-install/OVMF_VARS*.fd /usr/share/pve-edk2-firmware
+debian/ovmf-cvm-install/OVMF_CVM_CODE*.fd /usr/share/pve-edk2-firmware
+debian/ovmf-cvm-install/OVMF_CVM_VARS*.fd /usr/share/pve-edk2-firmware
+debian/ovmf-cvm-install/OVMF_CVM_4M.fd /usr/share/pve-edk2-firmware
debian/ovmf32-install/OVMF32_CODE*.fd /usr/share/pve-edk2-firmware
debian/ovmf32-install/OVMF32_VARS*.fd /usr/share/pve-edk2-firmware
debian/PkKek-1-snakeoil.* /usr/share/pve-edk2-firmware
diff --git a/debian/rules b/debian/rules
index 2e9365b..3959500 100755
--- a/debian/rules
+++ b/debian/rules
@@ -28,22 +28,24 @@ PCD_FLAGS += --pcd PcdFirmwareReleaseDateString=L"$(PCD_RELEASE_DATE)\\0"
COMMON_FLAGS = -DNETWORK_HTTP_BOOT_ENABLE=TRUE
COMMON_FLAGS += -DNETWORK_IP6_ENABLE=TRUE
COMMON_FLAGS += -DNETWORK_TLS_ENABLE
-COMMON_FLAGS += -DSECURE_BOOT_ENABLE=TRUE
COMMON_FLAGS += -DPVSCSI_ENABLE=TRUE
COMMON_FLAGS += $(PCD_FLAGS)
OVMF_COMMON_FLAGS = $(COMMON_FLAGS)
OVMF_COMMON_FLAGS += -DTPM2_ENABLE=TRUE
-OVMF_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB
+OVMF_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB -DSECURE_BOOT_ENABLE=TRUE
OVMF_4M_SMM_FLAGS = $(OVMF_4M_FLAGS) -DSMM_REQUIRE=TRUE
-OVMF32_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB
+OVMF32_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB -DSECURE_BOOT_ENABLE=TRUE
OVMF32_4M_SMM_FLAGS = $(OVMF32_4M_FLAGS) -DSMM_REQUIRE=TRUE
+OVMF_CVM_4M_FLAGS = $(OVMF_COMMON_FLAGS) -DFD_SIZE_4MB
AAVMF_FLAGS = $(COMMON_FLAGS)
+AAVMF_FLAGS += -DSECURE_BOOT_ENABLE=TRUE
AAVMF_FLAGS += -DTPM2_ENABLE=TRUE
AAVMF_FLAGS += -DTPM2_CONFIG_ENABLE=TRUE
AAVMF_FLAGS += -DCAVIUM_ERRATUM_27456=TRUE
RISCV64_FLAGS = $(COMMON_FLAGS)
+RISCV64_FLAGS += -DSECURE_BOOT_ENABLE=TRUE
# Clear variables used internally by the edk2 build system
undefine WORKSPACE
@@ -56,7 +58,7 @@ undefine CONF_PATH
%:
dh $@
-override_dh_auto_build: build-qemu-efi-aarch64 build-ovmf build-ovmf32 build-qemu-efi-riscv64
+override_dh_auto_build: build-qemu-efi-aarch64 build-ovmf build-ovmf32 build-ovmf-cvm build-qemu-efi-riscv64
debian/setup-build-stamp:
cp -a debian/Logo.bmp MdeModulePkg/Logo/Logo.bmp
@@ -79,6 +81,12 @@ OVMF32_SHELL = $(OVMF32_BUILD_DIR)/IA32/Shell.efi
OVMF32_BINARIES = $(OVMF32_SHELL)
OVMF32_IMAGES := $(addprefix $(OVMF32_INSTALL_DIR)/,OVMF32_CODE_4M.secboot.fd OVMF32_VARS_4M.fd)
+OVMF_CVM_INSTALL_DIR = debian/ovmf-cvm-install
+OVMF_CVM_BUILD_DIR = Build/OvmfX64/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
+OVMF_CVM_SHELL = $(OVMF_CVM_BUILD_DIR)/X64/Shell.efi
+OVMF_CVM_BINARIES = $(OVMF_CVM_SHELL)
+OVMF_CVM_IMAGES := $(addprefix $(OVMF_CVM_INSTALL_DIR)/,OVMF_CVM_CODE_4M.fd OVMF_CVM_VARS_4M.fd)
+
QEMU_EFI_BUILD_DIR = Build/ArmVirtQemu-$(EDK2_HOST_ARCH)/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
AAVMF_BUILD_DIR = Build/ArmVirtQemu-AARCH64/$(BUILD_TYPE)_$(EDK2_TOOLCHAIN)
AAVMF_ENROLL = $(AAVMF_BUILD_DIR)/AARCH64/EnrollDefaultKeys.efi
@@ -106,6 +114,23 @@ $(OVMF32_BINARIES) $(OVMF32_IMAGES): debian/setup-build-stamp
cp $(OVMF32_BUILD_DIR)/FV/OVMF_VARS.fd \
$(OVMF32_INSTALL_DIR)/OVMF32_VARS_4M.fd
+build-ovmf-cvm: $(OVMF_CVM_BINARIES) $(OVMF_CVM_IMAGES)
+$(OVMF_CVM_BINARIES) $(OVMF_CVM_IMAGES): debian/setup-build-stamp
+ rm -rf $(OVMF_CVM_INSTALL_DIR)
+ mkdir $(OVMF_CVM_INSTALL_DIR)
+ set -e; . ./edksetup.sh; \
+ build -a X64 \
+ -t $(EDK2_TOOLCHAIN) \
+ -p OvmfPkg/OvmfPkgX64.dsc \
+ $(OVMF_CVM_4M_FLAGS) -b $(BUILD_TYPE)
+ #-b $(BUILD_TYPE)
+ cp $(OVMF_CVM_BUILD_DIR)/FV/OVMF_CODE.fd \
+ $(OVMF_CVM_INSTALL_DIR)/OVMF_CVM_CODE_4M.fd
+ cp $(OVMF_CVM_BUILD_DIR)/FV/OVMF_VARS.fd \
+ $(OVMF_CVM_INSTALL_DIR)/OVMF_CVM_VARS_4M.fd
+ cp $(OVMF_CVM_BUILD_DIR)/FV/OVMF.fd \
+ $(OVMF_CVM_INSTALL_DIR)/OVMF_CVM_4M.fd
+
build-ovmf: $(OVMF_BINARIES) $(OVMF_IMAGES) $(OVMF_PREENROLLED_VARS)
$(OVMF_BINARIES) $(OVMF_IMAGES): debian/setup-build-stamp
rm -rf $(OVMF_INSTALL_DIR)
@@ -250,4 +275,4 @@ get-orig-source:
edk2-$(DEB_VERSION_UPSTREAM)
rm -rf edk2.tmp edk2-$(DEB_VERSION_UPSTREAM)
-.PHONY: build-ovmf build-ovmf32 build-qemu-efi build-qemu-efi-aarch64 build-qemu-efi-riscv64
+.PHONY: build-ovmf build-ovmf32 build-ovmf-cvm build-qemu-efi build-qemu-efi-aarch64 build-qemu-efi-riscv64
\ No newline at end of file
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pve-devel] [PATCH qemu-server 3/4] config: add AMD SEV-SNP support.
2025-02-07 8:51 [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH pve-edk2-firmware 1/4] Update edk2 to edkstable202411 Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH pve-edk2-firmware 2/4] Add OVMF targets for AMD SEV-ES and SEV-SNP Philipp Giersfeld
@ 2025-02-07 8:51 ` Philipp Giersfeld
2025-02-07 10:55 ` Daniel Kral
2025-02-07 8:51 ` [pve-devel] [PATCH pve-manager 4/4] Add configuration options for AMD SEV-SNP Philipp Giersfeld
2025-02-13 15:08 ` [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] " Markus Frank
4 siblings, 1 reply; 8+ messages in thread
From: Philipp Giersfeld @ 2025-02-07 8:51 UTC (permalink / raw)
To: pve-devel
This patch is for enabling AMD SEV-SNP support.
Where applicable, it extends support for existing SEV(-ES) variables
to SEV-SNP.
The default policy value is identical to QEMU’s, and the therefore
required option has been added to configure SMT support.
The code was tested by running a VM without SEV, with SEV, SEV-ES,
SEV-SNP. Each configuration was tested with and without an EFI disk
attached. For SEV-enabled configurations it was also verified that the
kernel actually used the respective feature.
Signed-off-by: Philipp Giersfeld <philipp.giersfeld@canarybit.eu>
---
PVE/API2/Qemu.pm | 9 +++--
PVE/QemuServer.pm | 57 +++++++++++++++++++++++---------
PVE/QemuServer/CPUConfig.pm | 66 ++++++++++++++++++++++++++++---------
3 files changed, 99 insertions(+), 33 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 295260e7..35c76dc2 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -548,8 +548,13 @@ my sub create_disks : prototype($$$$$$$$$$$) {
my $volid;
if ($ds eq 'efidisk0') {
my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf);
- ($volid, $size) = PVE::QemuServer::create_efidisk(
- $storecfg, $storeid, $vmid, $fmt, $arch, $disk, $smm);
+ my $amd_sev_type = PVE::QemuServer::CPUConfig::get_amd_sev_type($conf);
+ if($amd_sev_type && $amd_sev_type eq 'snp') {
+ die "SEV-SNP only uses consolidated read-only firmware";
+ } else {
+ ($volid, $size) = PVE::QemuServer::create_efidisk(
+ $storecfg, $storeid, $vmid, $fmt, $arch, $disk, $smm, $amd_sev_type);
+ }
} elsif ($ds eq 'tpmstate0') {
# swtpm can only use raw volumes, and uses a fixed size
$size = PVE::Tools::convert_size(PVE::QemuServer::Drive::TPMSTATE_DISK_SIZE, 'b' => 'kb');
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 808c0e1c..e46b3434 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -52,7 +52,7 @@ use PVE::QemuConfig;
use PVE::QemuServer::Helpers qw(config_aware_timeout min_version kvm_user_version windows_version);
use PVE::QemuServer::Cloudinit;
use PVE::QemuServer::CGroup;
-use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object);
+use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object get_amd_sev_type);
use PVE::QemuServer::Drive qw(is_valid_drivename checked_volume_format drive_is_cloudinit drive_is_cdrom drive_is_read_only parse_drive print_drive);
use PVE::QemuServer::Machine;
use PVE::QemuServer::Memory qw(get_current_memory);
@@ -88,6 +88,13 @@ my $OVMF = {
"$EDK2_FW_BASE/OVMF_CODE_4M.secboot.fd",
"$EDK2_FW_BASE/OVMF_VARS_4M.ms.fd",
],
+ '4m-sev' => [
+ "$EDK2_FW_BASE/OVMF_CVM_CODE_4M.fd",
+ "$EDK2_FW_BASE/OVMF_CVM_VARS_4M.fd",
+ ],
+ '4m-snp' => [
+ "$EDK2_FW_BASE/OVMF_CVM_4M.fd",
+ ],
# FIXME: These are legacy 2MB-sized images that modern OVMF doesn't supports to build
# anymore. how can we deperacate this sanely without breaking existing instances, or using
# older backups and snapshot?
@@ -3172,19 +3179,28 @@ sub vga_conf_has_spice {
return $1 || 1;
}
-sub get_ovmf_files($$$) {
- my ($arch, $efidisk, $smm) = @_;
+sub get_ovmf_files($$$$) {
+ my ($arch, $efidisk, $smm, $amd_sev_type) = @_;
my $types = $OVMF->{$arch}
or die "no OVMF images known for architecture '$arch'\n";
my $type = 'default';
if ($arch eq 'x86_64') {
- if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
- $type = $smm ? "4m" : "4m-no-smm";
- $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
+ if ($amd_sev_type && $amd_sev_type eq 'snp') {
+ $type = "4m-snp";
+ my ($ovmf) = $types->{$type}->@*;
+ die "EFI base image '$ovmf' not found\n" if ! -f $ovmf;
+ return ($ovmf);
+ } elsif ($amd_sev_type) {
+ $type = "4m-sev";
} else {
- # TODO: log_warn about use of legacy images for x86_64 with Promxox VE 9
+ if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
+ $type = $smm ? "4m" : "4m-no-smm";
+ $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
+ } else {
+ # TODO: log_warn about use of legacy images for x86_64 with Promxox VE 9
+ }
}
}
@@ -3329,7 +3345,8 @@ my sub print_ovmf_drive_commandlines {
my $d = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
- my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35);
+ my $amd_sev_type = get_amd_sev_type($conf);
+ my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35, $amd_sev_type);
my $var_drive_str = "if=pflash,unit=1,id=drive-efidisk0";
if ($d) {
@@ -3526,10 +3543,17 @@ sub config_to_command {
die "OVMF (UEFI) BIOS is not supported on 32-bit CPU types\n"
if !$forcecpu && get_cpu_bitness($conf->{cpu}, $arch) == 32;
- my ($code_drive_str, $var_drive_str) =
- print_ovmf_drive_commandlines($conf, $storecfg, $vmid, $arch, $q35, $version_guard);
- push $cmd->@*, '-drive', $code_drive_str;
- push $cmd->@*, '-drive', $var_drive_str;
+ my $amd_sev_type = get_amd_sev_type($conf);
+ if ($amd_sev_type && $amd_sev_type eq 'snp') {
+ my $arch = PVE::QemuServer::Helpers::get_vm_arch($conf);
+ my $d = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
+ push $cmd->@*, '-bios', get_ovmf_files($arch, $d, undef, $amd_sev_type);
+ } else {
+ my ($code_drive_str, $var_drive_str) = print_ovmf_drive_commandlines(
+ $conf, $storecfg, $vmid, $arch, $q35, $version_guard);
+ push $cmd->@*, '-drive', $code_drive_str;
+ push $cmd->@*, '-drive', $var_drive_str;
+ }
}
if ($q35) { # tell QEMU to load q35 config early
@@ -8337,7 +8361,8 @@ sub get_efivars_size {
my $arch = PVE::QemuServer::Helpers::get_vm_arch($conf);
$efidisk //= $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf);
- my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm);
+ my $amd_sev_type = get_amd_sev_type($conf);
+ my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
return -s $ovmf_vars;
}
@@ -8361,10 +8386,10 @@ sub update_tpmstate_size {
$conf->{tpmstate0} = print_drive($disk);
}
-sub create_efidisk($$$$$$$) {
- my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm) = @_;
+sub create_efidisk($$$$$$$$) {
+ my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm, $amd_sev_type) = @_;
- my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm);
+ my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
my $vars_size_b = -s $ovmf_vars;
my $vars_size = PVE::Tools::convert_size($vars_size_b, 'b' => 'kb');
diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
index e65d8c26..dbc31462 100644
--- a/PVE/QemuServer/CPUConfig.pm
+++ b/PVE/QemuServer/CPUConfig.pm
@@ -18,6 +18,7 @@ get_cpu_options
get_cpu_bitness
is_native_arch
get_amd_sev_object
+get_amd_sev_type
);
# under certain race-conditions, this module might be loaded before pve-cluster
@@ -231,25 +232,32 @@ my $cpu_fmt = {
my $sev_fmt = {
type => {
description => "Enable standard SEV with type='std' or enable"
- ." experimental SEV-ES with the 'es' option.",
+ ." experimental SEV-ES with the 'es' option or enable "
+ ."experimental SEV-SNP with the 'snp option.",
type => 'string',
default_key => 1,
format_description => "sev-type",
- enum => ['std', 'es'],
+ enum => ['std', 'es', 'snp'],
maxLength => 3,
},
'no-debug' => {
- description => "Sets policy bit 0 to 1 to disallow debugging of guest",
+ description => "Sets policy bit to disallow debugging of guest",
type => 'boolean',
default => 0,
optional => 1,
},
'no-key-sharing' => {
- description => "Sets policy bit 1 to 1 to disallow key sharing with other guests",
+ description => "Sets policy bit to disallow key sharing with other guests",
type => 'boolean',
default => 0,
optional => 1,
},
+ 'allow-smt' => {
+ description => "Sets policy bit to allow SMT",
+ type => 'boolean',
+ default => 1,
+ optional => 1,
+ },
"kernel-hashes" => {
description => "Add kernel hashes to guest firmware for measured linux kernel launch",
type => 'boolean',
@@ -823,6 +831,16 @@ sub get_hw_capabilities {
}
return $hw_capabilities;
}
+sub get_amd_sev_type {
+ my ($conf) = @_;
+
+ if ($conf->{'amd-sev'}) {
+ return PVE::JSONSchema::parse_property_string($sev_fmt, $conf->{'amd-sev'})->{type};
+ }
+ else {
+ return undef;
+ }
+}
sub get_amd_sev_object {
my ($amd_sev, $bios) = @_;
@@ -836,22 +854,40 @@ sub get_amd_sev_object {
if ($amd_sev_conf->{type} eq 'es' && !$sev_hw_caps->{'sev-support-es'}) {
die "Your CPU does not support AMD SEV-ES.\n";
}
+ if ($amd_sev_conf->{type} eq 'snp' && !$sev_hw_caps->{'sev-support-snp'}) {
+ die "Your CPU does not support AMD SEV-SNP.\n";
+ }
if (!$bios || $bios ne 'ovmf') {
die "To use AMD SEV, you need to change the BIOS to OVMF.\n";
}
- my $sev_mem_object = 'sev-guest,id=sev0';
- $sev_mem_object .= ',cbitpos='.$sev_hw_caps->{cbitpos};
- $sev_mem_object .= ',reduced-phys-bits='.$sev_hw_caps->{'reduced-phys-bits'};
+ my $sev_mem_object = '';
+ my $policy;
+ if ($amd_sev_conf->{type} eq 'es' || $amd_sev_conf->{type} eq 'std') {
+ $sev_mem_object .= 'sev-guest,id=sev0';
+ $sev_mem_object .= ',cbitpos='.$sev_hw_caps->{cbitpos};
+ $sev_mem_object .= ',reduced-phys-bits='.$sev_hw_caps->{'reduced-phys-bits'};
+
+ # guest policy bit calculation as described here:
+ # https://documentation.suse.com/sles/15-SP5/html/SLES-amd-sev/article-amd-sev.html#table-guestpolicy
+ $policy = 0b0000;
+ $policy += 0b0001 if $amd_sev_conf->{'no-debug'};
+ $policy += 0b0010 if $amd_sev_conf->{'no-key-sharing'};
+ $policy += 0b0100 if $amd_sev_conf->{type} eq 'es';
+ # disable migration with bit 3 nosend to prevent amd-sev-migration-attack
+ $policy += 0b1000;
+ } elsif ($amd_sev_conf->{type} eq 'snp') {
+ $sev_mem_object .= 'sev-snp-guest,id=sev0';
+ $sev_mem_object .= ',cbitpos='.$sev_hw_caps->{cbitpos};
+ $sev_mem_object .= ',reduced-phys-bits='.$sev_hw_caps->{'reduced-phys-bits'};
+
+ # guest policy bit calculation as described here:
+ # https://libvirt.org/formatdomain.html#id121
+ $policy = 0x20000;
+ $policy += 0x80000 if $amd_sev_conf->{'no-debug'};
+ $policy += 0x10000 if $amd_sev_conf->{'allow-smt'};
+ }
- # guest policy bit calculation as described here:
- # https://documentation.suse.com/sles/15-SP5/html/SLES-amd-sev/article-amd-sev.html#table-guestpolicy
- my $policy = 0b0000;
- $policy += 0b0001 if $amd_sev_conf->{'no-debug'};
- $policy += 0b0010 if $amd_sev_conf->{'no-key-sharing'};
- $policy += 0b0100 if $amd_sev_conf->{type} eq 'es';
- # disable migration with bit 3 nosend to prevent amd-sev-migration-attack
- $policy += 0b1000;
$sev_mem_object .= ',policy='.sprintf("%#x", $policy);
$sev_mem_object .= ',kernel-hashes=on' if ($amd_sev_conf->{'kernel-hashes'});
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* [pve-devel] [PATCH pve-manager 4/4] Add configuration options for AMD SEV-SNP
2025-02-07 8:51 [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP Philipp Giersfeld
` (2 preceding siblings ...)
2025-02-07 8:51 ` [pve-devel] [PATCH qemu-server 3/4] config: add AMD SEV-SNP support Philipp Giersfeld
@ 2025-02-07 8:51 ` Philipp Giersfeld
2025-02-07 10:56 ` Daniel Kral
2025-02-13 15:08 ` [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] " Markus Frank
4 siblings, 1 reply; 8+ messages in thread
From: Philipp Giersfeld @ 2025-02-07 8:51 UTC (permalink / raw)
To: pve-devel
Expand input panel with AMD SEV-SNP selection, and relevant optional
parameters similar to existing options for AMD SEV(-ES).
Further, upon selecting AMD SEV-SNP, issue a warning that EFI disks are
not included when using SEV-SNP.
Signed-off-by: Philipp Giersfeld <philipp.giersfeld@canarybit.eu>
---
www/manager6/qemu/Options.js | 1 +
www/manager6/qemu/SevEdit.js | 40 ++++++++++++++++++++++++++++++------
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/www/manager6/qemu/Options.js b/www/manager6/qemu/Options.js
index cbe9e52b..49a921cd 100644
--- a/www/manager6/qemu/Options.js
+++ b/www/manager6/qemu/Options.js
@@ -346,6 +346,7 @@ Ext.define('PVE.qemu.Options', {
let amd_sev = PVE.Parser.parsePropertyString(value, "type");
if (amd_sev.type === 'std') return 'AMD SEV (' + value + ')';
if (amd_sev.type === 'es') return 'AMD SEV-ES (' + value + ')';
+ if (amd_sev.type === 'snp') return 'AMD SEV-SNP (' + value + ')';
return value;
},
},
diff --git a/www/manager6/qemu/SevEdit.js b/www/manager6/qemu/SevEdit.js
index a2080f2d..9605cf59 100644
--- a/www/manager6/qemu/SevEdit.js
+++ b/www/manager6/qemu/SevEdit.js
@@ -9,7 +9,8 @@ Ext.define('PVE.qemu.SevInputPanel', {
type: '__default__',
},
formulas: {
- sevEnabled: get => get('type') !== '__default__',
+ sevEnabled: get => get('type') === 'std' || get('type') === 'es',
+ snpEnabled: get => get('type') === 'snp',
},
},
@@ -21,10 +22,14 @@ Ext.define('PVE.qemu.SevInputPanel', {
if (!values.debug) {
values["no-debug"] = 1;
}
+ if (values.smt) {
+ values["allow-smt"] = 1;
+ }
if (!values["key-sharing"]) {
values["no-key-sharing"] = 1;
}
delete values.debug;
+ delete values.smt;
delete values["key-sharing"];
let ret = {};
ret['amd-sev'] = PVE.Parser.printPropertyString(values, 'type');
@@ -36,13 +41,16 @@ Ext.define('PVE.qemu.SevInputPanel', {
if (PVE.Parser.parseBoolean(values["no-debug"])) {
values.debug = 0;
}
+ if (PVE.Parser.parseBoolean(values["allow-smt"])) {
+ values.smt = 1;
+ }
if (PVE.Parser.parseBoolean(values["no-key-sharing"])) {
values["key-sharing"] = 0;
}
this.callParent(arguments);
},
- items: {
+ items: [{
xtype: 'proxmoxKVComboBox',
fieldLabel: gettext('AMD SEV Type'),
labelWidth: 150,
@@ -52,11 +60,20 @@ Ext.define('PVE.qemu.SevInputPanel', {
['__default__', Proxmox.Utils.defaultText + ' (' + Proxmox.Utils.disabledText + ')'],
['std', 'AMD SEV'],
['es', 'AMD SEV-ES (highly experimental)'],
+ ['snp', 'AMD SEV-SNP (highly experimental)'],
],
bind: {
value: '{type}',
},
},
+ {
+ xtype: 'displayfield',
+ userCls: 'pmx-hint',
+ value: gettext('WARNING: When using SEV-SNP no variable store is loaded as pflash.'),
+ bind: {
+ hidden: '{!snpEnabled}',
+ },
+ }],
advancedItems: [
{
@@ -66,8 +83,8 @@ Ext.define('PVE.qemu.SevInputPanel', {
name: 'debug',
value: 1,
bind: {
- hidden: '{!sevEnabled}',
- disabled: '{!sevEnabled}',
+ hidden: '{!sevEnabled && !snpEnabled}',
+ disabled: '{!sevEnabled && !snpEnabled}',
},
},
{
@@ -81,6 +98,17 @@ Ext.define('PVE.qemu.SevInputPanel', {
disabled: '{!sevEnabled}',
},
},
+ {
+ xtype: 'proxmoxcheckbox',
+ fieldLabel: gettext('Allow SMT'),
+ labelWidth: 150,
+ name: 'smt',
+ value: 1,
+ bind: {
+ hidden: '{!snpEnabled}',
+ disabled: '{!snpEnabled}',
+ },
+ },
{
xtype: 'proxmoxcheckbox',
fieldLabel: gettext('Enable Kernel Hashes'),
@@ -88,8 +116,8 @@ Ext.define('PVE.qemu.SevInputPanel', {
name: 'kernel-hashes',
deleteDefaultValue: false,
bind: {
- hidden: '{!sevEnabled}',
- disabled: '{!sevEnabled}',
+ hidden: '{!sevEnabled && !snpEnabled}',
+ disabled: '{!sevEnabled && !snpEnabled}',
},
},
],
--
2.39.5
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [pve-devel] [PATCH qemu-server 3/4] config: add AMD SEV-SNP support.
2025-02-07 8:51 ` [pve-devel] [PATCH qemu-server 3/4] config: add AMD SEV-SNP support Philipp Giersfeld
@ 2025-02-07 10:55 ` Daniel Kral
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Kral @ 2025-02-07 10:55 UTC (permalink / raw)
To: Proxmox VE development discussion, Philipp Giersfeld
Hi,
thanks for wanting to contribute and sending a patch for AMD SEV-SNP! We
really appreciate it!
Unfortunately I don't have the hardware to test this and neither have
enough knowledge about the specific details for this, but I added some
higher-level inlined comments as I wanted to take a closer look at this
anyway. Hope those help the process.
On another note, if you haven't already, please make sure that you have
a signed CLA sent to office@proxmox.com (see
https://pve.proxmox.com/wiki/Developer_Documentation for more information).
All else, I'd be happy to see this applied!
Daniel
On 2/7/25 09:51, Philipp Giersfeld wrote:
> This patch is for enabling AMD SEV-SNP support.
>
> Where applicable, it extends support for existing SEV(-ES) variables
> to SEV-SNP.
This could be more specific and tell which parameters are not applicable
to SEV-SNP anymore (i.e. no-key-sharing).
>
> The default policy value is identical to QEMU’s, and the therefore
> required option has been added to configure SMT support.
>
> The code was tested by running a VM without SEV, with SEV, SEV-ES,
> SEV-SNP. Each configuration was tested with and without an EFI disk
> attached. For SEV-enabled configurations it was also verified that the
> kernel actually used the respective feature.
>
> Signed-off-by: Philipp Giersfeld <philipp.giersfeld@canarybit.eu>
> ---
> PVE/API2/Qemu.pm | 9 +++--
> PVE/QemuServer.pm | 57 +++++++++++++++++++++++---------
> PVE/QemuServer/CPUConfig.pm | 66 ++++++++++++++++++++++++++++---------
> 3 files changed, 99 insertions(+), 33 deletions(-)
>
> diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
> index 295260e7..35c76dc2 100644
> --- a/PVE/API2/Qemu.pm
> +++ b/PVE/API2/Qemu.pm
> @@ -548,8 +548,13 @@ my sub create_disks : prototype($$$$$$$$$$$) {
> my $volid;
> if ($ds eq 'efidisk0') {
> my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf);
> - ($volid, $size) = PVE::QemuServer::create_efidisk(
> - $storecfg, $storeid, $vmid, $fmt, $arch, $disk, $smm);
> + my $amd_sev_type = PVE::QemuServer::CPUConfig::get_amd_sev_type($conf);
> + if($amd_sev_type && $amd_sev_type eq 'snp') {
> + die "SEV-SNP only uses consolidated read-only firmware";
it could be just my reader, but it seems like there are three tabs
instead of two tabs + 4 spaces to align it with my $smm.
also nit: this special case could be handled with a die post-if, i.e.
```
die "SEV-SNP only uses consolidated read-only firmware"
if $amd_sev_type && $amd_sev_type eq 'snp';
```
as there's plenty of indentation in this subroutine already.
> + } else {
> + ($volid, $size) = PVE::QemuServer::create_efidisk(
> + $storecfg, $storeid, $vmid, $fmt, $arch, $disk, $smm, $amd_sev_type);
> + }
> } elsif ($ds eq 'tpmstate0') {
> # swtpm can only use raw volumes, and uses a fixed size
> $size = PVE::Tools::convert_size(PVE::QemuServer::Drive::TPMSTATE_DISK_SIZE, 'b' => 'kb');
> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
> index 808c0e1c..e46b3434 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -52,7 +52,7 @@ use PVE::QemuConfig;
> use PVE::QemuServer::Helpers qw(config_aware_timeout min_version kvm_user_version windows_version);
> use PVE::QemuServer::Cloudinit;
> use PVE::QemuServer::CGroup;
> -use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object);
> +use PVE::QemuServer::CPUConfig qw(print_cpu_device get_cpu_options get_cpu_bitness is_native_arch get_amd_sev_object get_amd_sev_type);
> use PVE::QemuServer::Drive qw(is_valid_drivename checked_volume_format drive_is_cloudinit drive_is_cdrom drive_is_read_only parse_drive print_drive);
> use PVE::QemuServer::Machine;
> use PVE::QemuServer::Memory qw(get_current_memory);
> @@ -88,6 +88,13 @@ my $OVMF = {
> "$EDK2_FW_BASE/OVMF_CODE_4M.secboot.fd",
> "$EDK2_FW_BASE/OVMF_VARS_4M.ms.fd",
> ],
> + '4m-sev' => [
> + "$EDK2_FW_BASE/OVMF_CVM_CODE_4M.fd",
> + "$EDK2_FW_BASE/OVMF_CVM_VARS_4M.fd",
> + ],
> + '4m-snp' => [
> + "$EDK2_FW_BASE/OVMF_CVM_4M.fd",
> + ],
> # FIXME: These are legacy 2MB-sized images that modern OVMF doesn't supports to build
> # anymore. how can we deperacate this sanely without breaking existing instances, or using
> # older backups and snapshot?
> @@ -3172,19 +3179,28 @@ sub vga_conf_has_spice {
> return $1 || 1;
> }
>
> -sub get_ovmf_files($$$) {
> - my ($arch, $efidisk, $smm) = @_;
> +sub get_ovmf_files($$$$) {
> + my ($arch, $efidisk, $smm, $amd_sev_type) = @_;
>
> my $types = $OVMF->{$arch}
> or die "no OVMF images known for architecture '$arch'\n";
>
> my $type = 'default';
> if ($arch eq 'x86_64') {
> - if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
> - $type = $smm ? "4m" : "4m-no-smm";
> - $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
> + if ($amd_sev_type && $amd_sev_type eq 'snp') {
> + $type = "4m-snp";
> + my ($ovmf) = $types->{$type}->@*;
> + die "EFI base image '$ovmf' not found\n" if ! -f $ovmf;
> + return ($ovmf);
> + } elsif ($amd_sev_type) {
> + $type = "4m-sev";
> } else {
> - # TODO: log_warn about use of legacy images for x86_64 with Promxox VE 9
> + if (defined($efidisk->{efitype}) && $efidisk->{efitype} eq '4m') {
> + $type = $smm ? "4m" : "4m-no-smm";
> + $type .= '-ms' if $efidisk->{'pre-enrolled-keys'};
> + } else {
> + # TODO: log_warn about use of legacy images for x86_64 with Promxox VE 9
> + }
nit: this branch could also be folded into an elsif
> }
> }
>
> @@ -3329,7 +3345,8 @@ my sub print_ovmf_drive_commandlines {
>
> my $d = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
>
> - my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35);
> + my $amd_sev_type = get_amd_sev_type($conf);
> + my ($ovmf_code, $ovmf_vars) = get_ovmf_files($arch, $d, $q35, $amd_sev_type);
>
> my $var_drive_str = "if=pflash,unit=1,id=drive-efidisk0";
> if ($d) {
> @@ -3526,10 +3543,17 @@ sub config_to_command {
> die "OVMF (UEFI) BIOS is not supported on 32-bit CPU types\n"
> if !$forcecpu && get_cpu_bitness($conf->{cpu}, $arch) == 32;
>
> - my ($code_drive_str, $var_drive_str) =
> - print_ovmf_drive_commandlines($conf, $storecfg, $vmid, $arch, $q35, $version_guard);
> - push $cmd->@*, '-drive', $code_drive_str;
> - push $cmd->@*, '-drive', $var_drive_str;
> + my $amd_sev_type = get_amd_sev_type($conf);
> + if ($amd_sev_type && $amd_sev_type eq 'snp') {
> + my $arch = PVE::QemuServer::Helpers::get_vm_arch($conf);
> + my $d = $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
> + push $cmd->@*, '-bios', get_ovmf_files($arch, $d, undef, $amd_sev_type);
> + } else {
> + my ($code_drive_str, $var_drive_str) = print_ovmf_drive_commandlines(
> + $conf, $storecfg, $vmid, $arch, $q35, $version_guard);
> + push $cmd->@*, '-drive', $code_drive_str;
> + push $cmd->@*, '-drive', $var_drive_str;
> + }
> }
>
> if ($q35) { # tell QEMU to load q35 config early
> @@ -8337,7 +8361,8 @@ sub get_efivars_size {
> my $arch = PVE::QemuServer::Helpers::get_vm_arch($conf);
> $efidisk //= $conf->{efidisk0} ? parse_drive('efidisk0', $conf->{efidisk0}) : undef;
> my $smm = PVE::QemuServer::Machine::machine_type_is_q35($conf);
> - my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm);
> + my $amd_sev_type = get_amd_sev_type($conf);
> + my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
> return -s $ovmf_vars;
> }
>
> @@ -8361,10 +8386,10 @@ sub update_tpmstate_size {
> $conf->{tpmstate0} = print_drive($disk);
> }
>
> -sub create_efidisk($$$$$$$) {
> - my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm) = @_;
> +sub create_efidisk($$$$$$$$) {
> + my ($storecfg, $storeid, $vmid, $fmt, $arch, $efidisk, $smm, $amd_sev_type) = @_;
>
> - my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm);
> + my (undef, $ovmf_vars) = get_ovmf_files($arch, $efidisk, $smm, $amd_sev_type);
>
> my $vars_size_b = -s $ovmf_vars;
> my $vars_size = PVE::Tools::convert_size($vars_size_b, 'b' => 'kb');
> diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm
> index e65d8c26..dbc31462 100644
> --- a/PVE/QemuServer/CPUConfig.pm
> +++ b/PVE/QemuServer/CPUConfig.pm
> @@ -18,6 +18,7 @@ get_cpu_options
> get_cpu_bitness
> is_native_arch
> get_amd_sev_object
> +get_amd_sev_type
> );
>
> # under certain race-conditions, this module might be loaded before pve-cluster
> @@ -231,25 +232,32 @@ my $cpu_fmt = {
> my $sev_fmt = {
> type => {
> description => "Enable standard SEV with type='std' or enable"
> - ." experimental SEV-ES with the 'es' option.",
> + ." experimental SEV-ES with the 'es' option or enable "
> + ."experimental SEV-SNP with the 'snp option.",
`'snp'` instead of `'snp`
> type => 'string',
> default_key => 1,
> format_description => "sev-type",
> - enum => ['std', 'es'],
> + enum => ['std', 'es', 'snp'],
> maxLength => 3,
> },
> 'no-debug' => {
> - description => "Sets policy bit 0 to 1 to disallow debugging of guest",
> + description => "Sets policy bit to disallow debugging of guest",
> type => 'boolean',
> default => 0,
> optional => 1,
> },
> 'no-key-sharing' => {
> - description => "Sets policy bit 1 to 1 to disallow key sharing with other guests",
> + description => "Sets policy bit to disallow key sharing with other guests",
Good catch to also adapt these!
> type => 'boolean',
> default => 0,
> optional => 1,
> },
> + 'allow-smt' => {
> + description => "Sets policy bit to allow SMT",
This would certainly benefit for a clarification that SMT = Simultaneous
Multi Threading.
> + type => 'boolean',
> + default => 1,
> + optional => 1,
> + },
> "kernel-hashes" => {
> description => "Add kernel hashes to guest firmware for measured linux kernel launch",
> type => 'boolean',
> @@ -823,6 +831,16 @@ sub get_hw_capabilities {
> }
> return $hw_capabilities;
> }
> +sub get_amd_sev_type {
> + my ($conf) = @_;
> +
> + if ($conf->{'amd-sev'}) {
> + return PVE::JSONSchema::parse_property_string($sev_fmt, $conf->{'amd-sev'})->{type};
> + }
> + else {
> + return undef;
> + }
nit: could be a `return undef if !$conf->{'amd-sev'};`
> +}
>
> sub get_amd_sev_object {
> my ($amd_sev, $bios) = @_;
> @@ -836,22 +854,40 @@ sub get_amd_sev_object {
> if ($amd_sev_conf->{type} eq 'es' && !$sev_hw_caps->{'sev-support-es'}) {
> die "Your CPU does not support AMD SEV-ES.\n";
> }
> + if ($amd_sev_conf->{type} eq 'snp' && !$sev_hw_caps->{'sev-support-snp'}) {
> + die "Your CPU does not support AMD SEV-SNP.\n";
> + }
> if (!$bios || $bios ne 'ovmf') {
> die "To use AMD SEV, you need to change the BIOS to OVMF.\n";
> }
>
> - my $sev_mem_object = 'sev-guest,id=sev0';
> - $sev_mem_object .= ',cbitpos='.$sev_hw_caps->{cbitpos};
> - $sev_mem_object .= ',reduced-phys-bits='.$sev_hw_caps->{'reduced-phys-bits'};
> + my $sev_mem_object = '';
> + my $policy;
> + if ($amd_sev_conf->{type} eq 'es' || $amd_sev_conf->{type} eq 'std') {
> + $sev_mem_object .= 'sev-guest,id=sev0';
> + $sev_mem_object .= ',cbitpos='.$sev_hw_caps->{cbitpos};
> + $sev_mem_object .= ',reduced-phys-bits='.$sev_hw_caps->{'reduced-phys-bits'};
> +
> + # guest policy bit calculation as described here:
> + # https://documentation.suse.com/sles/15-SP5/html/SLES-amd-sev/article-amd-sev.html#table-guestpolicy
> + $policy = 0b0000;
> + $policy += 0b0001 if $amd_sev_conf->{'no-debug'};
> + $policy += 0b0010 if $amd_sev_conf->{'no-key-sharing'};
> + $policy += 0b0100 if $amd_sev_conf->{type} eq 'es';
> + # disable migration with bit 3 nosend to prevent amd-sev-migration-attack
> + $policy += 0b1000;
Since the AMD SEV-SNP code below uses hex numbers since they use the
higher number bits 15, 16 and 19, I think it would be more consistent to
convert the above binary numbers (in its own patch before this!) to either
1. hexadecimal numbers too,
2. or maybe even more readable: use shift operators for all of these, as
the official manuals specify them in bits. Also ORing those is more
standard for me than adding binary numbers, but that's just a nit, e.g.
```
$policy = 0;
$policy |= 1 << 0 if $amd_sev_conf->{'no-debug'};
$policy |= 1 << 1 if $amd_sev_conf->{'no-key-sharing'};
$policy |= 1 << 2 if $amd_sev_conf->{type} eq 'es';
# disable migration with bit 3 nosend to prevent amd-sev-migration-attack
$policy |= 1 << 3;
```
> + } elsif ($amd_sev_conf->{type} eq 'snp') {
> + $sev_mem_object .= 'sev-snp-guest,id=sev0';
> + $sev_mem_object .= ',cbitpos='.$sev_hw_caps->{cbitpos};
> + $sev_mem_object .= ',reduced-phys-bits='.$sev_hw_caps->{'reduced-phys-bits'};
> +
> + # guest policy bit calculation as described here:
> + # https://libvirt.org/formatdomain.html#id121
This should be https://libvirt.org/formatdomain.html#launch-security,
and nit: could also directly point to the official AMD specification at
https://www.amd.com/system/files/TechDocs/56860.pdf and then chapter 4.3
Guest Policy settings
> + $policy = 0x20000;
> + $policy += 0x80000 if $amd_sev_conf->{'no-debug'};
I think this is wrong, as the AMD SEV-SNP specification in 4.3 Guest
Policy states:
Bit 19 (Debug): 0 - Debugging is disallowed, 1 - Debugging is allowed
This is probably an oversight, since the AMD **SEV** spec states the
opposite for the debug bit 0.
> + $policy += 0x10000 if $amd_sev_conf->{'allow-smt'};
And if you consider the shift operation + ORing then the above becomes:
```
# Reserved bit must be one
$policy = 1 << 17;
$policy |= 1 << 16 if $amd_sev_conf->{'allow-smt'};
$policy |= 1 << 19 if !$amd_sev_conf->{'no-debug'};
```
> + }
>
> - # guest policy bit calculation as described here:
> - # https://documentation.suse.com/sles/15-SP5/html/SLES-amd-sev/article-amd-sev.html#table-guestpolicy
> - my $policy = 0b0000;
> - $policy += 0b0001 if $amd_sev_conf->{'no-debug'};
> - $policy += 0b0010 if $amd_sev_conf->{'no-key-sharing'};
> - $policy += 0b0100 if $amd_sev_conf->{type} eq 'es';
> - # disable migration with bit 3 nosend to prevent amd-sev-migration-attack
> - $policy += 0b1000;
>
> $sev_mem_object .= ',policy='.sprintf("%#x", $policy);
> $sev_mem_object .= ',kernel-hashes=on' if ($amd_sev_conf->{'kernel-hashes'});
With those comments fixed, consider this:
Reviewed-by: Daniel Kral <d.kral@proxmox.com>
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [pve-devel] [PATCH pve-manager 4/4] Add configuration options for AMD SEV-SNP
2025-02-07 8:51 ` [pve-devel] [PATCH pve-manager 4/4] Add configuration options for AMD SEV-SNP Philipp Giersfeld
@ 2025-02-07 10:56 ` Daniel Kral
0 siblings, 0 replies; 8+ messages in thread
From: Daniel Kral @ 2025-02-07 10:56 UTC (permalink / raw)
To: Proxmox VE development discussion, Philipp Giersfeld
On 2/7/25 09:51, Philipp Giersfeld wrote:
> Expand input panel with AMD SEV-SNP selection, and relevant optional
> parameters similar to existing options for AMD SEV(-ES).
>
> Further, upon selecting AMD SEV-SNP, issue a warning that EFI disks are
> not included when using SEV-SNP.
>
> Signed-off-by: Philipp Giersfeld <philipp.giersfeld@canarybit.eu>
> ---
> www/manager6/qemu/Options.js | 1 +
> www/manager6/qemu/SevEdit.js | 40 ++++++++++++++++++++++++++++++------
> 2 files changed, 35 insertions(+), 6 deletions(-)
>
> diff --git a/www/manager6/qemu/Options.js b/www/manager6/qemu/Options.js
> index cbe9e52b..49a921cd 100644
> --- a/www/manager6/qemu/Options.js
> +++ b/www/manager6/qemu/Options.js
> @@ -346,6 +346,7 @@ Ext.define('PVE.qemu.Options', {
> let amd_sev = PVE.Parser.parsePropertyString(value, "type");
> if (amd_sev.type === 'std') return 'AMD SEV (' + value + ')';
> if (amd_sev.type === 'es') return 'AMD SEV-ES (' + value + ')';
> + if (amd_sev.type === 'snp') return 'AMD SEV-SNP (' + value + ')';
> return value;
> },
> },
> diff --git a/www/manager6/qemu/SevEdit.js b/www/manager6/qemu/SevEdit.js
> index a2080f2d..9605cf59 100644
> --- a/www/manager6/qemu/SevEdit.js
> +++ b/www/manager6/qemu/SevEdit.js
> @@ -9,7 +9,8 @@ Ext.define('PVE.qemu.SevInputPanel', {
> type: '__default__',
> },
> formulas: {
> - sevEnabled: get => get('type') !== '__default__',
> + sevEnabled: get => get('type') === 'std' || get('type') === 'es',
Looks like most changes here and below use tabs instead of 4 spaces. See
[0] for more information on the indentation for our JavaScript projects.
Also relevant here: I think it'd be better to add all three SEV types to
`sevEnabled` here, so we do not need to modify any `!sevEnabled` to
`!sevEnabled && !snpEnabled` below.
The `snpEnabled` can stay as it is here, as it's relevant for the pflash
warning and the "Allow SMT" checkbox ofc.
> + snpEnabled: get => get('type') === 'snp',
> },
> },
>
> @@ -21,10 +22,14 @@ Ext.define('PVE.qemu.SevInputPanel', {
> if (!values.debug) {
> values["no-debug"] = 1;
> }
> + if (values.smt) {
> + values["allow-smt"] = 1;
> + }
> if (!values["key-sharing"]) {
> values["no-key-sharing"] = 1;
> }
> delete values.debug;
> + delete values.smt;
> delete values["key-sharing"];
> let ret = {};
> ret['amd-sev'] = PVE.Parser.printPropertyString(values, 'type');
> @@ -36,13 +41,16 @@ Ext.define('PVE.qemu.SevInputPanel', {
> if (PVE.Parser.parseBoolean(values["no-debug"])) {
> values.debug = 0;
> }
> + if (PVE.Parser.parseBoolean(values["allow-smt"])) {
> + values.smt = 1;
> + }
> if (PVE.Parser.parseBoolean(values["no-key-sharing"])) {
> values["key-sharing"] = 0;
> }
> this.callParent(arguments);
> },
>
> - items: {
> + items: [{
> xtype: 'proxmoxKVComboBox',
> fieldLabel: gettext('AMD SEV Type'),
> labelWidth: 150,
> @@ -52,11 +60,20 @@ Ext.define('PVE.qemu.SevInputPanel', {
> ['__default__', Proxmox.Utils.defaultText + ' (' + Proxmox.Utils.disabledText + ')'],
> ['std', 'AMD SEV'],
> ['es', 'AMD SEV-ES (highly experimental)'],
> + ['snp', 'AMD SEV-SNP (highly experimental)'],
> ],
> bind: {
> value: '{type}',
> },
> },
> + {
> + xtype: 'displayfield',
> + userCls: 'pmx-hint',
> + value: gettext('WARNING: When using SEV-SNP no variable store is loaded as pflash.'),
> + bind: {
> + hidden: '{!snpEnabled}',
> + },
> + }],
>
> advancedItems: [
> {
> @@ -66,8 +83,8 @@ Ext.define('PVE.qemu.SevInputPanel', {
> name: 'debug',
> value: 1,
> bind: {
> - hidden: '{!sevEnabled}',
> - disabled: '{!sevEnabled}',
> + hidden: '{!sevEnabled && !snpEnabled}',
> + disabled: '{!sevEnabled && !snpEnabled}',
> },
> },
> {
> @@ -81,6 +98,17 @@ Ext.define('PVE.qemu.SevInputPanel', {
> disabled: '{!sevEnabled}',
The "Allow Key-Sharing" option should be disabled AFAICS for SEV-SNP
being set, no?
> },
> },
> + {
> + xtype: 'proxmoxcheckbox',
> + fieldLabel: gettext('Allow SMT'),
> + labelWidth: 150,
> + name: 'smt',
> + value: 1,
> + bind: {
> + hidden: '{!snpEnabled}',
> + disabled: '{!snpEnabled}',
> + },
> + },
> {
> xtype: 'proxmoxcheckbox',
> fieldLabel: gettext('Enable Kernel Hashes'),
> @@ -88,8 +116,8 @@ Ext.define('PVE.qemu.SevInputPanel', {
> name: 'kernel-hashes',
> deleteDefaultValue: false,
> bind: {
> - hidden: '{!sevEnabled}',
> - disabled: '{!sevEnabled}',
> + hidden: '{!sevEnabled && !snpEnabled}',
> + disabled: '{!sevEnabled && !snpEnabled}',
> },
> },
> ],
[0] https://pve.proxmox.com/wiki/Javascript_Style_Guide#Indentation
With those comments fixed, consider this:
Reviewed-by: Daniel Kral <d.kral@proxmox.com>
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP
2025-02-07 8:51 [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP Philipp Giersfeld
` (3 preceding siblings ...)
2025-02-07 8:51 ` [pve-devel] [PATCH pve-manager 4/4] Add configuration options for AMD SEV-SNP Philipp Giersfeld
@ 2025-02-13 15:08 ` Markus Frank
4 siblings, 0 replies; 8+ messages in thread
From: Markus Frank @ 2025-02-13 15:08 UTC (permalink / raw)
To: Proxmox VE development discussion, Philipp Giersfeld
Thanks.
I have tested AMD SEV SNP and it works fine with your patch series.
Tested-by: Markus Frank <m.frank@proxmox.com>
One thing I noticed:
I would add a note in the WebUI that you need kernel >= 6.11 installed on the pve host to enable SEV-SNP as long as >=6.11 is not the default kernel.
On 2025-02-07 09:51, Philipp Giersfeld wrote:
> This patch series adds support for AMD SEV-SNP.
> Where possible it maintains the existing support for AMD SEV(-ES).
>
> Running SEV-SNP VMs requires a more recent version of edk2
> and OVMF firmware image. Contrary to other setups, SEV-SNP does not support loading the firmware via pflash. Instead, the firmware image is loaded via the -bios option.
>
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
>
>
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-02-13 15:09 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-07 8:51 [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] AMD SEV-SNP Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH pve-edk2-firmware 1/4] Update edk2 to edkstable202411 Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH pve-edk2-firmware 2/4] Add OVMF targets for AMD SEV-ES and SEV-SNP Philipp Giersfeld
2025-02-07 8:51 ` [pve-devel] [PATCH qemu-server 3/4] config: add AMD SEV-SNP support Philipp Giersfeld
2025-02-07 10:55 ` Daniel Kral
2025-02-07 8:51 ` [pve-devel] [PATCH pve-manager 4/4] Add configuration options for AMD SEV-SNP Philipp Giersfeld
2025-02-07 10:56 ` Daniel Kral
2025-02-13 15:08 ` [pve-devel] [PATCH edk2-firmware/qemu-server/manager 0/4] " Markus Frank
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal