From: Christian Ludwig <christian_ludwig@genua.de>
To: <pve-devel@lists.proxmox.com>
Subject: [PATCH qemu-server 3/7] sev: Expose chip ID and reported TCB versions
Date: Thu, 24 Sep 2026 16:14:05 +0200 [thread overview]
Message-ID: <7c9b5440cca3c31c9a59aed5162ea4476155a27a.1790236014.git@genua.de> (raw)
In-Reply-To: <chipid.1790235905.git@genua.de>
[-- Attachment #1: Type: text/plain, Size: 5092 bytes --]
Collect the SEV chip unique ID and the SNP reported TCB version. These
identify the exact VCEK a remote attestation client needs to fetch from
AMD's KDS for a given host, and are exposed alongside the existing
capability flags.
Signed-off-by: Christian Ludwig <christian_ludwig@genua.de>
---
.../query-machine-capabilities.c | 81 ++++++++++++++++++-
1 file changed, 79 insertions(+), 2 deletions(-)
diff --git a/src/query-machine-capabilities/query-machine-capabilities.c b/src/query-machine-capabilities/query-machine-capabilities.c
index b7e06286..088b2683 100644
--- a/src/query-machine-capabilities/query-machine-capabilities.c
+++ b/src/query-machine-capabilities/query-machine-capabilities.c
@@ -6,7 +6,10 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
+#include <inttypes.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/psp-sev.h>
#ifdef __aarch64__
#include <sys/auxv.h>
@@ -28,6 +31,9 @@ typedef struct {
bool sev_support;
bool sev_es_support;
bool sev_snp_support;
+ uint8_t *sev_chip_id;
+ size_t sev_chip_id_len;
+ uint64_t sev_snp_reported_tcb_version;
uint8_t cbitpos;
uint8_t reduced_phys_bits;
@@ -123,7 +129,11 @@ int read_msr(uint32_t msr_index, uint64_t *value) {
void query_cpu_capabilities_sev(cpu_caps_amd_sev_t *res) {
#ifdef __x86_64__
+ int fd, ret;
uint32_t eax, ebx, ecx, edx;
+ struct sev_issue_cmd cmd;
+ struct sev_user_data_snp_status snp_status;
+ struct sev_user_data_get_id2 get_id;
struct {
const char *path;
bool *result;
@@ -170,6 +180,64 @@ void query_cpu_capabilities_sev(cpu_caps_amd_sev_t *res) {
res->cbitpos = ebx & 0x3f;
res->reduced_phys_bits = (ebx >> 6) & 0x3f;
+ /*
+ * Get ChipId and TCB_VERSION for an Attester.
+ * Only necessary for SEV-SNP.
+ */
+ if (!res->sev_snp_support)
+ return;
+
+ fd = open("/dev/sev", O_RDWR);
+ if (fd < 0)
+ return;
+
+ memset(&snp_status, 0, sizeof(snp_status));
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = SNP_PLATFORM_STATUS;
+ cmd.data = (uintptr_t)&snp_status;
+ ret = ioctl(fd, SEV_ISSUE_CMD, &cmd);
+ if (ret >= 0 && cmd.error == 0) {
+ res->sev_snp_reported_tcb_version = snp_status.reported_tcb_version;
+ } else if (cmd.error != 0) {
+ fprintf(stderr, "SEV firmware error: 0x%x\n", cmd.error);
+ }
+
+ /*
+ * Get ChipId. The ID length must not be assumed, so ask for it first by
+ * passing a zero-length buffer. That query is expected to fail with
+ * INVALID_LEN; the firmware reports the required length either way.
+ */
+ memset(&get_id, 0, sizeof(get_id));
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = SEV_GET_ID2;
+ cmd.data = (uintptr_t)&get_id;
+ ioctl(fd, SEV_ISSUE_CMD, &cmd);
+ if (get_id.length == 0)
+ goto skip_chip_id;
+
+ res->sev_chip_id = malloc(get_id.length);
+ if (res->sev_chip_id == NULL) {
+ perror("malloc");
+ goto skip_chip_id;
+ }
+ res->sev_chip_id_len = get_id.length;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.cmd = SEV_GET_ID2;
+ cmd.data = (uintptr_t)&get_id;
+ get_id.address = (uintptr_t)res->sev_chip_id;
+ get_id.length = res->sev_chip_id_len;
+ ret = ioctl(fd, SEV_ISSUE_CMD, &cmd);
+ if (ret < 0 || cmd.error != 0 || get_id.length != res->sev_chip_id_len) {
+ if (cmd.error != 0)
+ fprintf(stderr, "SEV firmware error: 0x%x\n", cmd.error);
+ free(res->sev_chip_id);
+ res->sev_chip_id = NULL;
+ res->sev_chip_id_len = 0;
+ goto skip_chip_id;
+ }
+skip_chip_id:
+ close(fd);
#else
memset(res, 0, sizeof(*res));
#endif
@@ -240,6 +308,11 @@ int main() {
if (strncmp(vendor, "AuthenticAMD", 12) == 0) {
cpu_caps_amd_sev_t caps_sev = { 0 };
query_cpu_capabilities_sev(&caps_sev);
+ char sev_chip_id[(caps_sev.sev_chip_id_len * 2) + 1];
+
+ memset(sev_chip_id, 0, (caps_sev.sev_chip_id_len * 2) + 1);
+ for (size_t i = 0; i < caps_sev.sev_chip_id_len; i++)
+ sprintf(&sev_chip_id[i*2], "%02x", caps_sev.sev_chip_id[i]);
ret = fprintf(file,
" \"amd-sev\": {"
@@ -247,13 +320,17 @@ int main() {
" \"reduced-phys-bits\": %u,"
" \"sev-support\": %s,"
" \"sev-support-es\": %s,"
- " \"sev-support-snp\": %s"
+ " \"sev-support-snp\": %s,"
+ " \"sev-chip-id\": \"0x%s\","
+ " \"sev-snp-tcb-version\": \"0x%016" PRIX64 "\""
" }",
caps_sev.cbitpos,
caps_sev.reduced_phys_bits,
caps_sev.sev_support ? "true" : "false",
caps_sev.sev_es_support ? "true" : "false",
- caps_sev.sev_snp_support ? "true" : "false"
+ caps_sev.sev_snp_support ? "true" : "false",
+ sev_chip_id,
+ caps_sev.sev_snp_reported_tcb_version
);
} else if (strncmp(vendor, "GenuineIntel", 12) == 0) {
cpu_caps_intel_tdx_t caps_tdx;
--
2.34.1
next prev parent reply other threads:[~2026-09-24 14:24 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 14:14 [PATCH 0/7] SEV: Expose chip ID and reported TCB versions Christian Ludwig
2026-09-24 14:14 ` [PATCH pve-common 1/7] procfs: read CPU model and stepping from cpuinfo Christian Ludwig
2026-09-24 14:14 ` [PATCH qemu-server 2/7] sev: Detect SEV- Christian Ludwig
2026-09-24 14:14 ` Christian Ludwig [this message]
2026-09-24 14:14 ` [PATCH qemu-server 4/7] api: add endpoint for SEV attestation data Christian Ludwig
2026-09-24 14:14 ` [PATCH pve-manager 5/7] api: register SEV capabilities endpoint Christian Ludwig
2026-09-24 14:14 ` [PATCH pve-docs 6/7] qm: Describe ASIDs for SEV Christian Ludwig
2026-09-24 14:14 ` [PATCH pve-docs 7/7] sev: Describe VCEK retieval Christian Ludwig
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=7c9b5440cca3c31c9a59aed5162ea4476155a27a.1790236014.git@genua.de \
--to=christian_ludwig@genua.de \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox