5
0
mirror of git://git.proxmox.com/git/qemu-server.git synced 2025-01-21 18:03:56 +03:00
qemu-server/query-machine-capabilities/query-machine-capabilities.c
Thomas Lamprecht 390e77d438 query-machine-capabilities: use macro for output paths and error helpers
This moves all error output to stderr while at it and fixes some bad
references to wrong paths in some error messages.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
2024-11-17 19:12:04 +01:00

97 lines
2.6 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#define OUTPUT_DIR "/run/qemu-server"
#define OUTPUT_FILENAME "host-hw-capabilities.json"
#define OUTPUT_PATH OUTPUT_DIR "/" OUTPUT_FILENAME
typedef struct {
bool sev_support;
bool sev_es_support;
bool sev_snp_support;
uint8_t cbitpos;
uint8_t reduced_phys_bits;
} cpu_caps_t;
void query_cpu_capabilities(cpu_caps_t *res) {
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)
);
res->sev_support = (eax & (1<<1)) != 0;
res->sev_es_support = (eax & (1<<3)) != 0;
res->sev_snp_support = (eax & (1<<4)) != 0;
res->cbitpos = ebx & 0x3f;
res->reduced_phys_bits = (ebx >> 6) & 0x3f;
}
int main() {
cpu_caps_t caps;
query_cpu_capabilities(&caps);
// Check that the directory exists and create it if it does not.
struct stat statbuf;
int ret = stat(OUTPUT_DIR, &statbuf);
if (ret == 0) {
if (!S_ISDIR(statbuf.st_mode)) {
eprintf("Path '" OUTPUT_DIR "' already exists but is not a directory.\n");
return 1;
}
} else if (errno == ENOENT) {
if (mkdir(OUTPUT_DIR, 0755) != 0) {
eprintf("Error creating directory '" OUTPUT_DIR "': %s\n", strerror(errno));
return 1;
}
} else {
eprintf("Error checking path '" OUTPUT_DIR "': %s\n", strerror(errno));
return 1;
}
FILE *file = fopen(OUTPUT_PATH, "w");
if (file == NULL) {
eprintf("Error opening to file '" OUTPUT_PATH "': %s\n", strerror(errno));
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",
caps.cbitpos,
caps.reduced_phys_bits,
caps.sev_support ? "true" : "false",
caps.sev_es_support ? "true" : "false",
caps.sev_snp_support ? "true" : "false"
);
if (ret < 0) {
eprintf("Error writing to file '" OUTPUT_PATH "': %s\n", strerror(errno));
}
ret = fclose(file);
if (ret != 0) {
eprintf("Error closing file '" OUTPUT_PATH "': %s\n", strerror(errno));
}
return 0;
}