kvm.c (12881B)
1#define _GNU_SOURCE 2 3#include "test/kvm.h" 4#include "test/util.h" 5#include "cachepc/uapi.h" 6 7#include <linux/psp-sev.h> 8#include <linux/kvm.h> 9#include <sys/syscall.h> 10#include <sys/ioctl.h> 11#include <sys/user.h> 12#include <sys/wait.h> 13#include <sys/ioctl.h> 14#include <sys/mman.h> 15#include <sys/stat.h> 16#include <sys/types.h> 17#include <unistd.h> 18#include <signal.h> 19#include <dirent.h> 20#include <assert.h> 21#include <errno.h> 22#include <err.h> 23#include <fcntl.h> 24#include <sched.h> 25#include <string.h> 26#include <stdbool.h> 27#include <stdint.h> 28#include <stdio.h> 29#include <stdlib.h> 30 31int kvm_dev = -1; 32int sev_dev = -1; 33const char *vmtype = NULL; 34 35const char *sev_fwerr_strs[] = { 36 [0x00] = "Success", 37 [0x01] = "Platform state is invalid", 38 [0x02] = "Guest state is invalid", 39 [0x03] = "Platform configuration is invalid", 40 [0x04] = "Buffer too small", 41 [0x05] = "Platform is already owned", 42 [0x06] = "Certificate is invalid", 43 [0x07] = "Request not allowed by policy", 44 [0x08] = "Guest is inactive", 45 [0x09] = "Invalid address", 46 [0x0A] = "Bad signature", 47 [0x0B] = "Bad measurement", 48 [0x0C] = "Asid is already owned", 49 [0x0D] = "Invalid ASID", 50 [0x0E] = "WBINVD is required", 51 [0x0F] = "DF_FLUSH is required", 52 [0x10] = "Guest handle is invalid", 53 [0x11] = "Invalid command", 54 [0x12] = "Guest is active", 55 [0x13] = "Hardware error", 56 [0x14] = "Hardware unsafe", 57 [0x15] = "Feature not supported", 58 [0x16] = "Invalid parameter", 59 [0x17] = "Out of resources", 60 [0x18] = "Integrity checks failed", 61 [0x19] = "RMP page size is incorrect", 62 [0x1A] = "RMP page state is incorrect", 63}; 64 65const char *sev_gstate_strs[] = { 66 "UNINIT", 67 "LUPDATE", 68 "LSECRET", 69 "RUNNING", 70 "SUPDATE", 71 "RUPDATE", 72 "SEND" 73}; 74 75const char * 76sev_fwerr_str(int code) 77{ 78 if (code < 0 || code >= ARRLEN(sev_fwerr_strs)) 79 return "Unknown error"; 80 81 return sev_fwerr_strs[code]; 82} 83 84const char * 85sev_gstate_str(int code) 86{ 87 if (code < 0 || code >= ARRLEN(sev_gstate_strs)) 88 return "Unknown gstate"; 89 90 return sev_gstate_strs[code]; 91} 92 93int 94sev_ioctl(int vmfd, int cmd, void *data, int *error) 95{ 96 struct kvm_sev_cmd input; 97 int ret; 98 99 memset(&input, 0, sizeof(input)); 100 input.id = cmd; 101 input.sev_fd = sev_dev; 102 input.data = (uintptr_t) data; 103 104 if (vmfd == MAIN_VMFD) { 105 ret = ioctl(kvm_dev, KVM_CPC_MEMORY_ENCRYPT_OP, &input); 106 if (error) *error = input.error; 107 } else { 108 ret = ioctl(vmfd, KVM_MEMORY_ENCRYPT_OP, &input); 109 if (error) *error = input.error; 110 } 111 112 return ret; 113} 114 115void 116sev_get_measure(int vmfd) 117{ 118 struct kvm_sev_launch_measure msrmt; 119 int ret, fwerr; 120 uint8_t *data; 121 122 memset(&msrmt, 0, sizeof(msrmt)); 123 ret = sev_ioctl(vmfd, KVM_SEV_LAUNCH_MEASURE, &msrmt, &fwerr); 124 if (ret == -1 && fwerr != SEV_RET_INVALID_LEN) 125 errx(1, "KVM_SEV_LAUNCH_MEASURE: (%s) %s", 126 strerror(errno), sev_fwerr_str(fwerr)); 127 128 data = malloc(msrmt.len); 129 msrmt.uaddr = (uintptr_t) data; 130 131 ret = sev_ioctl(vmfd, KVM_SEV_LAUNCH_MEASURE, &msrmt, &fwerr); 132 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_MEASURE: (%s) %s", 133 strerror(errno), sev_fwerr_str(fwerr)); 134 135 free(data); 136} 137 138uint8_t 139sev_guest_state(int vmfd, uint32_t handle) 140{ 141 struct kvm_sev_guest_status status; 142 int ret, fwerr; 143 144 status.handle = handle; 145 ret = sev_ioctl(vmfd, KVM_SEV_GUEST_STATUS, &status, &fwerr); 146 if (ret == -1) errx(1, "KVM_SEV_GUEST_STATUS: (%s) %s", 147 strerror(errno), sev_fwerr_str(fwerr)); 148 149 return status.state; 150} 151 152void 153guest_init(struct guest *guest, const char *filename) 154{ 155 FILE *f; 156 157 f = fopen(filename, "r"); 158 if (!f) err(1, "fopen"); 159 160 fseek(f, 0, SEEK_END); 161 guest->code_size = ftell(f); 162 fseek(f, 0, SEEK_SET); 163 164 guest->code = malloc(guest->code_size); 165 if (!guest->code) err(1, "malloc"); 166 167 if (!fread(guest->code, guest->code_size, 1, f)) 168 errx(1, "read guest"); 169 170 guest->mem_size = 0; 171 172 fclose(f); 173} 174 175void 176guest_deinit(struct guest *guest) 177{ 178 free(guest->code); 179} 180 181void 182kvm_create_vm(struct kvm *kvm) 183{ 184 kvm->vmfd = ioctl(kvm_dev, KVM_CREATE_VM, 0); 185 if (kvm->vmfd < 0) err(1, "KVM_CREATE_VM"); 186} 187 188void 189kvm_init_memory(struct kvm *kvm, size_t mem_size, void *code, size_t code_size) 190{ 191 struct kvm_userspace_memory_region region; 192 int ret; 193 194 kvm->memsize = mem_size; 195 kvm->mem = mmap(NULL, kvm->memsize, PROT_READ | PROT_WRITE, 196 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 197 if (!kvm->mem) err(1, "mmap kvm->mem"); 198 /* nop slide oob to detect errors quickly */ 199 memset(kvm->mem, 0x90, kvm->memsize); 200 assert(code_size <= kvm->memsize); 201 memcpy(kvm->mem, code, code_size); 202 203 memset(®ion, 0, sizeof(region)); 204 region.slot = 0; 205 region.memory_size = kvm->memsize; 206 region.guest_phys_addr = 0x0000; 207 region.userspace_addr = (uintptr_t) kvm->mem; 208 ret = ioctl(kvm->vmfd, KVM_SET_USER_MEMORY_REGION, ®ion); 209 if (ret == -1) err(1, "KVM_SET_USER_MEMORY_REGION"); 210} 211 212void 213kvm_create_vcpu(struct kvm *kvm) 214{ 215 int ret; 216 217 kvm->vcpufd = ioctl(kvm->vmfd, KVM_CREATE_VCPU, 0); 218 if (kvm->vcpufd < 0) err(1, "KVM_CREATE_VCPU"); 219 220 ret = ioctl(kvm_dev, KVM_GET_VCPU_MMAP_SIZE, NULL); 221 if (ret == -1) err(1, "KVM_GET_VCPU_MMAP_SIZE"); 222 if (ret < sizeof(struct kvm_run)) 223 errx(1, "KVM_GET_VCPU_MMAP_SIZE too small"); 224 kvm->runsize = ret; 225 kvm->run = mmap(NULL, kvm->runsize, PROT_READ | PROT_WRITE, 226 MAP_SHARED, kvm->vcpufd, 0); 227 if (!kvm->run) err(1, "mmap kvm->run"); 228} 229 230void 231kvm_init_regs(struct kvm *kvm) 232{ 233 struct kvm_regs regs; 234 struct kvm_sregs sregs; 235 int ret; 236 237 /* Initialize segment regs */ 238 memset(&sregs, 0, sizeof(sregs)); 239 ret = ioctl(kvm->vcpufd, KVM_GET_SREGS, &sregs); 240 if (ret == -1) err(1, "KVM_GET_SREGS"); 241 sregs.cs.base = 0; 242 sregs.cs.selector = 0; 243 ret = ioctl(kvm->vcpufd, KVM_SET_SREGS, &sregs); 244 if (ret == -1) err(1, "KVM_SET_SREGS"); 245 246 /* Initialize rest of registers */ 247 memset(®s, 0, sizeof(regs)); 248 regs.rip = 0; 249 regs.rsp = kvm->memsize - 8; 250 regs.rbp = kvm->memsize - 8; 251 ret = ioctl(kvm->vcpufd, KVM_SET_REGS, ®s); 252 if (ret == -1) err(1, "KVM_SET_REGS"); 253} 254 255void 256kvm_init(struct kvm *kvm, struct guest *guest) 257{ 258 kvm_create_vm(kvm); 259 260 kvm_init_memory(kvm, guest->mem_size, guest->code, guest->code_size); 261 262 kvm_create_vcpu(kvm); 263 264 kvm_init_regs(kvm); 265} 266 267void 268sev_kvm_init(struct kvm *kvm, struct guest *guest) 269{ 270 struct kvm_sev_launch_update_data update; 271 struct kvm_sev_launch_start start; 272 int ret, fwerr; 273 274 kvm_create_vm(kvm); 275 276 kvm_init_memory(kvm, guest->mem_size, guest->code, guest->code_size); 277 278 /* Enable SEV for vm */ 279 ret = sev_ioctl(kvm->vmfd, KVM_SEV_INIT, NULL, &fwerr); 280 if (ret == -1) errx(1, "KVM_SEV_INIT: (%s) %s", 281 strerror(errno), sev_fwerr_str(fwerr)); 282 283 kvm_create_vcpu(kvm); 284 285 kvm_init_regs(kvm); 286 287 /* Generate encryption keys and set policy */ 288 memset(&start, 0, sizeof(start)); 289 start.handle = 0; 290 start.policy = 0; 291 ret = sev_ioctl(kvm->vmfd, KVM_SEV_LAUNCH_START, &start, &fwerr); 292 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_START: (%s) %s", 293 strerror(errno), sev_fwerr_str(fwerr)); 294 295 /* Prepare the vm memory (by encrypting it) */ 296 memset(&update, 0, sizeof(update)); 297 update.uaddr = (uintptr_t) kvm->mem; 298 update.len = kvm->memsize; 299 ret = sev_ioctl(kvm->vmfd, KVM_SEV_LAUNCH_UPDATE_DATA, &update, &fwerr); 300 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_UPDATE_DATA: (%s) %s", 301 strerror(errno), sev_fwerr_str(fwerr)); 302 303 /* Collect a measurement (necessary) */ 304 sev_get_measure(kvm->vmfd); 305 306 /* Finalize launch process */ 307 ret = sev_ioctl(kvm->vmfd, KVM_SEV_LAUNCH_FINISH, 0, &fwerr); 308 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_FINISH: (%s) %s", 309 strerror(errno), sev_fwerr_str(fwerr)); 310 311 ret = sev_guest_state(kvm->vmfd, start.handle); 312 if (ret != GSTATE_RUNNING) 313 errx(1, "Bad guest state: %s", sev_gstate_str(fwerr)); 314} 315 316void 317sev_es_kvm_init(struct kvm *kvm, struct guest *guest) 318{ 319 struct kvm_sev_launch_update_data update; 320 struct kvm_sev_launch_start start; 321 int ret, fwerr; 322 323 kvm_create_vm(kvm); 324 325 kvm_init_memory(kvm, guest->mem_size, guest->code, guest->code_size); 326 327 /* Enable SEV for vm */ 328 ret = sev_ioctl(kvm->vmfd, KVM_SEV_ES_INIT, NULL, &fwerr); 329 if (ret == -1) errx(1, "KVM_SEV_ES_INIT: (%s) %s", 330 strerror(errno), sev_fwerr_str(fwerr)); 331 332 kvm_create_vcpu(kvm); 333 334 kvm_init_regs(kvm); 335 336 /* Generate encryption keys and set policy */ 337 memset(&start, 0, sizeof(start)); 338 start.handle = 0; 339 start.policy = 1 << 2; /* require SEV-ES */ 340 ret = sev_ioctl(kvm->vmfd, KVM_SEV_LAUNCH_START, &start, &fwerr); 341 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_START: (%s) %s", 342 strerror(errno), sev_fwerr_str(fwerr)); 343 344 /* Prepare the vm memory (by encrypting it) */ 345 memset(&update, 0, sizeof(update)); 346 update.uaddr = (uintptr_t) kvm->mem; 347 update.len = kvm->memsize; 348 ret = sev_ioctl(kvm->vmfd, KVM_SEV_LAUNCH_UPDATE_DATA, &update, &fwerr); 349 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_UPDATE_DATA: (%s) %s", 350 strerror(errno), sev_fwerr_str(fwerr)); 351 352 /* Prepare the vm save area */ 353 ret = sev_ioctl(kvm->vmfd, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL, &fwerr); 354 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_UPDATE_VMSA: (%s) %s", 355 strerror(errno), sev_fwerr_str(fwerr)); 356 357 /* Collect a measurement (necessary) */ 358 sev_get_measure(kvm->vmfd); 359 360 /* Finalize launch process */ 361 ret = sev_ioctl(kvm->vmfd, KVM_SEV_LAUNCH_FINISH, 0, &fwerr); 362 if (ret == -1) errx(1, "KVM_SEV_LAUNCH_FINISH: (%s) %s", 363 strerror(errno), sev_fwerr_str(fwerr)); 364 365 ret = sev_guest_state(kvm->vmfd, start.handle); 366 if (ret != GSTATE_RUNNING) 367 errx(1, "Bad guest state: %s", sev_gstate_str(fwerr)); 368} 369 370void 371sev_snp_kvm_init(struct kvm *kvm, struct guest *guest) 372{ 373 struct kvm_sev_snp_launch_update update; 374 struct kvm_sev_snp_launch_start start; 375 struct kvm_sev_snp_launch_finish finish; 376 struct kvm_enc_region enc_region; 377 struct kvm_snp_init init; 378 int ret, fwerr; 379 380 kvm_create_vm(kvm); 381 382 kvm_init_memory(kvm, guest->mem_size, guest->code, guest->code_size); 383 384 /* Enable SEV for vm */ 385 memset(&init, 0, sizeof(init)); 386 ret = sev_ioctl(kvm->vmfd, KVM_SEV_SNP_INIT, &init, &fwerr); 387 if (ret == -1) errx(1, "KVM_SEV_SNP_INIT: (%s) %s", 388 strerror(errno), sev_fwerr_str(fwerr)); 389 390 /* Register memory region */ 391 memset(&enc_region, 0, sizeof(enc_region)); 392 enc_region.addr = (uintptr_t) kvm->mem; 393 enc_region.size = kvm->memsize; 394 ret = ioctl(kvm->vmfd, KVM_MEMORY_ENCRYPT_REG_REGION, &enc_region); 395 if (ret == -1) err(1, "KVM_MEMORY_ENCRYPT_REG_REGION"); 396 397 kvm_create_vcpu(kvm); 398 399 kvm_init_regs(kvm); 400 401 /* Generate encryption keys and set policy */ 402 memset(&start, 0, sizeof(start)); 403 start.policy = 1 << 17; /* must be set */ 404 start.policy |= 1 << 19; /* allow debug */ 405 start.policy |= 1 << 16; /* allow simultaneous multi-threading */ 406 ret = sev_ioctl(kvm->vmfd, KVM_SEV_SNP_LAUNCH_START, &start, &fwerr); 407 if (ret == -1) errx(1, "KVM_SEV_SNP_LAUNCH_START: (%s) %s", 408 strerror(errno), sev_fwerr_str(fwerr)); 409 410 /* Prepare the vm memory */ 411 memset(&update, 0, sizeof(update)); 412 update.uaddr = (uintptr_t) kvm->mem; 413 update.len = kvm->memsize; 414 update.start_gfn = 0; 415 update.page_type = KVM_SEV_SNP_PAGE_TYPE_NORMAL; 416 ret = sev_ioctl(kvm->vmfd, KVM_SEV_SNP_LAUNCH_UPDATE, &update, &fwerr); 417 if (ret == -1) errx(1, "KVM_SEV_SNP_LAUNCH_UPDATE: (%s) %s", 418 strerror(errno), sev_fwerr_str(fwerr)); 419 420 /* Finalize launch process */ 421 memset(&finish, 0, sizeof(finish)); 422 ret = sev_ioctl(kvm->vmfd, KVM_SEV_SNP_LAUNCH_FINISH, &finish, &fwerr); 423 if (ret == -1) errx(1, "KVM_SEV_SNP_LAUNCH_FINISH: (%s) %s", 424 strerror(errno), sev_fwerr_str(fwerr)); 425} 426 427void 428kvm_deinit(struct kvm *kvm) 429{ 430 close(kvm->vmfd); 431 close(kvm->vcpufd); 432 munmap(kvm->mem, kvm->memsize); 433 munmap(kvm->run, kvm->runsize); 434} 435 436uint64_t 437vm_get_rip(void) 438{ 439 struct cpc_sev_cmd cmd; 440 int ret, fwerr; 441 442 cmd.id = SEV_CPC_GET_RIP; 443 ret = sev_ioctl(MAIN_VMFD, KVM_SEV_CACHEPC, &cmd, &fwerr); 444 if (ret == -1) errx(1, "KVM_SEV_CACHEPC: (%s) %s", 445 strerror(errno), sev_fwerr_str(fwerr)); 446 447 return cmd.data; 448} 449 450void 451parse_vmtype(int argc, const char **argv) 452{ 453 vmtype = "kvm"; 454 if (argc > 1) vmtype = argv[1]; 455 if (strcmp(vmtype, "kvm") && strcmp(vmtype, "sev") 456 && strcmp(vmtype, "sev-es") 457 && strcmp(vmtype, "sev-snp")) 458 errx(1, "invalid vm mode: %s", vmtype); 459} 460 461void 462vm_init(struct kvm *kvm, struct guest *guest) 463{ 464 if (!guest->mem_size) 465 guest->mem_size = L1_SIZE * 2; 466 467 if (!strcmp(vmtype, "kvm")) { 468 kvm_init(kvm, guest); 469 } else if (!strcmp(vmtype, "sev")) { 470 sev_kvm_init(kvm, guest); 471 } else if (!strcmp(vmtype, "sev-es")) { 472 sev_es_kvm_init(kvm, guest); 473 } else if (!strcmp(vmtype, "sev-snp")) { 474 sev_snp_kvm_init(kvm, guest); 475 } else { 476 errx(1, "invalid version"); 477 } 478} 479 480void 481vm_deinit(struct kvm *kvm) 482{ 483 kvm_deinit(kvm); 484} 485 486void 487kvm_setup_init(void) 488{ 489 int ret; 490 491 kvm_dev = open("/dev/kvm", O_RDWR | O_CLOEXEC); 492 if (kvm_dev < 0) err(1, "open /dev/kvm"); 493 494 sev_dev = open("/dev/sev", O_RDWR | O_CLOEXEC); 495 if (sev_dev < 0) err(1, "open /dev/sev"); 496 497 /* ensure we have the stable version of the api */ 498 ret = ioctl(kvm_dev, KVM_GET_API_VERSION, NULL); 499 if (ret == -1) err(1, "KVM_GET_API_VERSION"); 500 if (ret != 12) errx(1, "KVM_GET_API_VERSION %d, expected 12", ret); 501 502} 503 504void 505kvm_setup_deinit(void) 506{ 507 close(kvm_dev); 508 kvm_dev = -1; 509 510 close(sev_dev); 511 sev_dev = -1; 512}