public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
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


  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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal