1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Helpers used for SEV guests 4 * 5 */ 6#ifndef SELFTEST_KVM_SEV_H 7#define SELFTEST_KVM_SEV_H 8 9#include <stdint.h> 10#include <stdbool.h> 11 12#include "linux/psp-sev.h" 13 14#include "kvm_util.h" 15#include "svm_util.h" 16#include "processor.h" 17 18enum sev_guest_state { 19 SEV_GUEST_STATE_UNINITIALIZED = 0, 20 SEV_GUEST_STATE_LAUNCH_UPDATE, 21 SEV_GUEST_STATE_LAUNCH_SECRET, 22 SEV_GUEST_STATE_RUNNING, 23}; 24 25#define SEV_POLICY_NO_DBG (1UL << 0) 26#define SEV_POLICY_ES (1UL << 2) 27 28#define GHCB_MSR_TERM_REQ 0x100 29 30void sev_vm_launch(struct kvm_vm *vm, uint32_t policy); 31void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement); 32void sev_vm_launch_finish(struct kvm_vm *vm); 33 34struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t policy, void *guest_code, 35 struct kvm_vcpu **cpu); 36 37kvm_static_assert(SEV_RET_SUCCESS == 0); 38 39/* 40 * The KVM_MEMORY_ENCRYPT_OP uAPI is utter garbage and takes an "unsigned long" 41 * instead of a proper struct. The size of the parameter is embedded in the 42 * ioctl number, i.e. is ABI and thus immutable. Hack around the mess by 43 * creating an overlay to pass in an "unsigned long" without a cast (casting 44 * will make the compiler unhappy due to dereferencing an aliased pointer). 45 */ 46#define __vm_sev_ioctl(vm, cmd, arg) \ 47({ \ 48 int r; \ 49 \ 50 union { \ 51 struct kvm_sev_cmd c; \ 52 unsigned long raw; \ 53 } sev_cmd = { .c = { \ 54 .id = (cmd), \ 55 .data = (uint64_t)(arg), \ 56 .sev_fd = (vm)->arch.sev_fd, \ 57 } }; \ 58 \ 59 r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &sev_cmd.raw); \ 60 r ?: sev_cmd.c.error; \ 61}) 62 63#define vm_sev_ioctl(vm, cmd, arg) \ 64({ \ 65 int ret = __vm_sev_ioctl(vm, cmd, arg); \ 66 \ 67 __TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \ 68}) 69 70static inline void sev_vm_init(struct kvm_vm *vm) 71{ 72 vm->arch.sev_fd = open_sev_dev_path_or_exit(); 73 74 vm_sev_ioctl(vm, KVM_SEV_INIT, NULL); 75} 76 77 78static inline void sev_es_vm_init(struct kvm_vm *vm) 79{ 80 vm->arch.sev_fd = open_sev_dev_path_or_exit(); 81 82 vm_sev_ioctl(vm, KVM_SEV_ES_INIT, NULL); 83} 84 85static inline void sev_register_encrypted_memory(struct kvm_vm *vm, 86 struct userspace_mem_region *region) 87{ 88 struct kvm_enc_region range = { 89 .addr = region->region.userspace_addr, 90 .size = region->region.memory_size, 91 }; 92 93 vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range); 94} 95 96static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa, 97 uint64_t size) 98{ 99 struct kvm_sev_launch_update_data update_data = { 100 .uaddr = (unsigned long)addr_gpa2hva(vm, gpa), 101 .len = size, 102 }; 103 104 vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data); 105} 106 107#endif /* SELFTEST_KVM_SEV_H */ 108