From: Markus Frank <m.frank@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH qemu-server v6 2/3] config: QEMU AMD SEV enable
Date: Fri, 19 Apr 2024 12:59:29 +0200 [thread overview]
Message-ID: <20240419105930.896952-2-m.frank@proxmox.com> (raw)
In-Reply-To: <20240419105930.896952-1-m.frank@proxmox.com>
This patch is for enabling AMD SEV (Secure Encrypted
Virtualization) support in QEMU
VM-Config-Examples:
amd_sev: type=std,nodbg=1,noks=1
amd_sev: es,nodbg=1,kernel-hashes=1
Node-Config-Example (gets generated automatically):
amd_sev: cbitpos=47,reduced-phys-bios=1
kernel-hashes, reduced-phys-bios & cbitpos correspond to the varibles
with the same name in qemu.
kernel-hashes=1 adds kernel-hashes to enable measured linux kernel
launch since it is per default off for backward compatibility.
reduced-phys-bios and cbitpos are system specific and are read out by
a C program started by the amd-sev-support.service on boot and saved
to the /run/amd-sev-params file. This file is parsed and than used by
qemu-server to correctly start a AMD SEV VM.
type=std stands for standard sev to differentiate it from sev-es (es)
or sev-snp (snp) when support is upstream.
QEMU's sev-guest policy gets calculated with the parameters nodbg & noks
These parameters correspond to policy-bits 0 & 1.
If type is 'es' than policy-bit 2 gets set to 1 to activate SEV-ES.
Policy bit 3 (nosend) is always set to 1, because migration
features for sev are not upstream yet and are attackable.
SEV-ES is highly experimental since it could not be tested.
see coherent doc patch
Signed-off-by: Markus Frank <m.frank@proxmox.com>
---
v6:
* rebase on master
* removed unused $sev_node_fmt object
v5:
* parse /run/amd-sev-params for hardware parameters
* removed NodeConfig dependency
* only disallow live-migration and snapshots with vmstate
-> allow offline migration and snapshots without vmstate
v4:
* reduced lines of code
* added text that SEV-ES is experimental
PVE/API2/Qemu.pm | 10 ++++++
PVE/QemuMigrate.pm | 4 +++
PVE/QemuServer.pm | 83 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 97 insertions(+)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 2a349c8..2e8d654 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -4512,6 +4512,10 @@ __PACKAGE__->register_method({
push $local_resources->@*, "clipboard=vnc";
}
+ if ($res->{running} && $vmconf->{amd_sev}) {
+ push $local_resources->@*, "amd_sev";
+ }
+
# if vm is not running, return target nodes where local storage/mapped devices are available
# for offline migration
if (!$res->{running}) {
@@ -5192,6 +5196,12 @@ __PACKAGE__->register_method({
die "unable to use snapshot name 'pending' (reserved name)\n"
if lc($snapname) eq 'pending';
+ my $conf = PVE::QemuConfig->load_config($vmid);
+ if ($param->{vmstate} && $conf->{amd_sev}) {
+ die "Snapshots that include memory are not supported while memory"
+ ." is encrypted by AMD SEV.\n"
+ }
+
my $realcmd = sub {
PVE::Cluster::log_msg('info', $authuser, "snapshot VM $vmid: $snapname");
PVE::QemuConfig->snapshot_create($vmid, $snapname, $param->{vmstate},
diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
index 8d9b35a..7db18b2 100644
--- a/PVE/QemuMigrate.pm
+++ b/PVE/QemuMigrate.pm
@@ -260,6 +260,10 @@ sub prepare {
die "VMs with 'clipboard' set to 'vnc' are not live migratable!\n";
}
+ if ($running && $conf->{'amd_sev'}) {
+ die "VMs with AMD SEV are not live migratable!\n";
+ }
+
my $vollist = PVE::QemuServer::get_vm_volumes($conf);
my $storages = {};
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 28e630d..b6e2713 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -177,6 +177,40 @@ my $agent_fmt = {
},
};
+my $sev_fmt = {
+ type => {
+ description => "Enable standard SEV with type='std' or enable experimental SEV-ES"
+ ." with the 'es' option.",
+ type => 'string',
+ default_key => 1,
+ format_description => "qemu-sev-type",
+ enum => ['std', 'es'],
+ maxLength => 3,
+ },
+ nodbg => {
+ description => "Sets policy bit 0 to 1 to disallow debugging of guest",
+ type => 'boolean',
+ format_description => "qemu-sev-nodbg",
+ default => 0,
+ optional => 1,
+ },
+ noks => {
+ description => "Sets policy bit 1 to 1 to disallow key sharing with other guests",
+ type => 'boolean',
+ format_description => "qemu-sev-noks",
+ default => 0,
+ optional => 1,
+ },
+ "kernel-hashes" => {
+ description => "Add kernel hashes to guest firmware for measured linux kernel launch",
+ type => 'boolean',
+ format_description => "qemu-sev-kernel-hashes",
+ default => 0,
+ optional => 1,
+ },
+};
+PVE::JSONSchema::register_format('pve-qemu-sev-fmt', $sev_fmt);
+
my $vga_fmt = {
type => {
description => "Select the VGA type.",
@@ -358,6 +392,12 @@ my $confdesc = {
description => "Memory properties.",
format => $PVE::QemuServer::Memory::memory_fmt
},
+ amd_sev => {
+ description => "Secure Encrypted Virtualization (SEV) features by AMD CPUs",
+ optional => 1,
+ format => 'pve-qemu-sev-fmt',
+ type => 'string',
+ },
balloon => {
optional => 1,
type => 'integer',
@@ -4091,6 +4131,39 @@ sub config_to_command {
}
}
+ if ($conf->{amd_sev}) {
+ if ($conf->{bios} && $conf->{bios} ne 'ovmf') {
+ die "For using SEV you need to change your guest bios to ovmf.\n";
+ }
+
+ my $amd_sev_conf = parse_property_string($sev_fmt, $conf->{amd_sev});
+ my $sev_hw_params = get_sev_hw_parameters();
+
+ if (!$sev_hw_params->{sev}) {
+ die "Your CPU does not support AMD SEV!\n";
+ }
+ if ($amd_sev_conf->{type} eq 'es' && !$sev_hw_params->{'sev-es'}) {
+ die "Your CPU does not support AMD SEV-ES!\n";
+ }
+
+ my $sev_mem_object = 'sev-guest,id=sev0'
+ .',cbitpos='.$sev_hw_params->{cbitpos}
+ .',reduced-phys-bits='.$sev_hw_params->{'reduced-phys-bits'};
+
+ my $policy = 0b0;
+ $policy += 0b1 if ($amd_sev_conf->{nodbg});
+ $policy += 0b10 if ($amd_sev_conf->{noks});
+ $policy += 0b100 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'});
+
+ push @$devices, '-object' , $sev_mem_object;
+ push @$machineFlags, 'confidential-guest-support=sev0';
+ }
+
push @$cmd, @$devices;
push @$cmd, '-rtc', join(',', @$rtcFlags) if scalar(@$rtcFlags);
push @$cmd, '-machine', join(',', @$machineFlags) if scalar(@$machineFlags);
@@ -4134,6 +4207,16 @@ sub check_rng_source {
}
}
+sub get_sev_hw_parameters {
+ # Get reduced-phys-bits & cbitpos from /run/amd-sev-params
+ my $filename = '/run/amd-sev-params';
+ open my $fh, '<', $filename or die "Could not open '$filename' for reading: $!";
+ my $json_text = do { local $/; <$fh> };
+ close $fh;
+ my $sev_params = JSON->new->decode($json_text);
+ return $sev_params;
+}
+
sub spice_port {
my ($vmid) = @_;
--
2.39.2
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2024-04-19 10:59 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-19 10:59 [pve-devel] [PATCH qemu-server v6 1/3] add C program to get AMD SEV hardware parameters from CPUID Markus Frank
2024-04-19 10:59 ` Markus Frank [this message]
2024-04-19 10:59 ` [pve-devel] [PATCH docs v6 3/3] add AMD SEV documentation Markus Frank
2024-04-22 6:39 ` [pve-devel] [PATCH qemu-server v6 1/3] add C program to get AMD SEV hardware parameters from CPUID Thomas Lamprecht
2024-04-22 7:33 ` Thomas Lamprecht
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240419105930.896952-2-m.frank@proxmox.com \
--to=m.frank@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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