Implement a C program that extracts AMD SEV hardware information such
as reduced-phys-bios and cbitpos from CPUID at boot time, looks if
SEV, SEV-ES & SEV-SNP are enabled, and outputs these details as JSON
to /run/qemu-server/host-hw-capabilities.json

This programm can also be used to read and save other hardware
information at boot time.

Signed-off-by: Markus Frank <m.fr...@proxmox.com>
Co-authored-by: Thomas Lamprecht <t.lampre...@proxmox.com>
Tested-by: Filip Schauer <f.scha...@proxmox.com>
---
changes v11:
* removed systemd service

 Makefile                                      |  1 +
 query-machine-capabilities/Makefile           | 18 +++++
 .../query-machine-capabilities.c              | 79 +++++++++++++++++++
 3 files changed, 98 insertions(+)
 create mode 100644 query-machine-capabilities/Makefile
 create mode 100644 query-machine-capabilities/query-machine-capabilities.c

diff --git a/Makefile b/Makefile
index 133468d..ed67fe0 100644
--- a/Makefile
+++ b/Makefile
@@ -65,6 +65,7 @@ install: $(PKGSOURCES)
        install -m 0644 -D bootsplash.jpg $(DESTDIR)/usr/share/$(PACKAGE)
        $(MAKE) -C PVE install
        $(MAKE) -C qmeventd install
+       $(MAKE) -C query-machine-capabilities install
        $(MAKE) -C qemu-configs install
        $(MAKE) -C vm-network-scripts install
        install -m 0755 qm $(DESTDIR)$(SBINDIR)
diff --git a/query-machine-capabilities/Makefile 
b/query-machine-capabilities/Makefile
new file mode 100644
index 0000000..469c69f
--- /dev/null
+++ b/query-machine-capabilities/Makefile
@@ -0,0 +1,18 @@
+DESTDIR=
+PREFIX=/usr
+BINDIR=${PREFIX}/libexec/qemu-server
+
+CC ?= gcc
+CFLAGS += -O2 -fanalyzer -Werror -Wall -Wextra -Wpedantic -Wtype-limits 
-Wl,-z,relro -std=gnu11
+
+query-machine-capabilities: query-machine-capabilities.c
+       $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)
+
+.PHONY: install
+install: query-machine-capabilities
+       install -d ${DESTDIR}/${BINDIR}
+       install -m 0755 query-machine-capabilities ${DESTDIR}${BINDIR}
+
+.PHONY: clean
+clean:
+       rm -f query-machine-capabilities
diff --git a/query-machine-capabilities/query-machine-capabilities.c 
b/query-machine-capabilities/query-machine-capabilities.c
new file mode 100644
index 0000000..7640e38
--- /dev/null
+++ b/query-machine-capabilities/query-machine-capabilities.c
@@ -0,0 +1,79 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+
+int main() {
+    uint32_t eax, ebx, ecx, edx;
+
+    // query Encrypted Memory Capabilities, see:
+    // 
https://en.wikipedia.org/wiki/CPUID#EAX=8000001Fh:_Encrypted_Memory_Capabilities
+    uint32_t query_function = 0x8000001F;
+    asm volatile("cpuid"
+        : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
+        : "0"(query_function)
+    );
+
+    bool sev_support = (eax & (1<<1)) != 0;
+    bool sev_es_support = (eax & (1<<3)) != 0;
+    bool sev_snp_support = (eax & (1<<4)) != 0;
+
+    uint8_t cbitpos = ebx & 0x3f;
+    uint8_t reduced_phys_bits = (ebx >> 6) & 0x3f;
+
+    const char *path = "/run/qemu-server/";
+    // Check that the directory exists and create it if it does not.
+    struct stat statbuf;
+    int ret = stat(path, &statbuf);
+    if (ret == 0) {
+       if (!S_ISDIR(statbuf.st_mode)) {
+           printf("Path %s is not a directory.\n", path);
+           return 1;
+       }
+    } else if (errno == ENOENT) {
+       if (mkdir(path, 0755) != 0) {
+           printf("Error creating directory %s: %s\n", path, strerror(errno));
+           return 1;
+       }
+    } else {
+       printf("Error checking path %s: %s\n", path, strerror(errno));
+       return 1;
+    }
+
+    FILE *file;
+    const char *filename = "/run/qemu-server/host-hw-capabilities.json";
+    file = fopen(filename, "w");
+    if (file == NULL) {
+       perror("Error opening file");
+       return 1;
+    }
+
+    ret = fprintf(file,
+       "{"
+       " \"amd-sev\": {"
+       " \"cbitpos\": %u,"
+       " \"reduced-phys-bits\": %u,"
+       " \"sev-support\": %s,"
+       " \"sev-support-es\": %s,"
+       " \"sev-support-snp\": %s"
+       " }"
+       " }\n",
+       cbitpos,
+       reduced_phys_bits,
+       sev_support ? "true" : "false",
+       sev_es_support ? "true" : "false",
+       sev_snp_support ? "true" : "false"
+    );
+    if (ret == -1) {
+       printf("Error writing to file %s: %s\n", path, strerror(errno));
+    }
+
+    ret = fclose(file);
+    if (ret == -1) {
+       printf("Error closing file %s: %s\n", path, strerror(errno));
+    }
+
+    return 0;
+}
-- 
2.39.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to