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 18 enum 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 SNP_POLICY_SMT (1ULL << 16) 29 #define SNP_POLICY_RSVD_MBO (1ULL << 17) 30 #define SNP_POLICY_DBG (1ULL << 19) 31 32 #define GHCB_MSR_TERM_REQ 0x100 33 34 static inline bool is_sev_snp_vm(struct kvm_vm *vm) 35 { 36 return vm->type == KVM_X86_SNP_VM; 37 } 38 39 static inline bool is_sev_es_vm(struct kvm_vm *vm) 40 { 41 return is_sev_snp_vm(vm) || vm->type == KVM_X86_SEV_ES_VM; 42 } 43 44 static inline bool is_sev_vm(struct kvm_vm *vm) 45 { 46 return is_sev_es_vm(vm) || vm->type == KVM_X86_SEV_VM; 47 } 48 49 void sev_vm_launch(struct kvm_vm *vm, uint32_t policy); 50 void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement); 51 void sev_vm_launch_finish(struct kvm_vm *vm); 52 void snp_vm_launch_start(struct kvm_vm *vm, uint64_t policy); 53 void snp_vm_launch_update(struct kvm_vm *vm); 54 void snp_vm_launch_finish(struct kvm_vm *vm); 55 56 struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code, 57 struct kvm_vcpu **cpu); 58 void vm_sev_launch(struct kvm_vm *vm, uint64_t policy, uint8_t *measurement); 59 60 kvm_static_assert(SEV_RET_SUCCESS == 0); 61 62 /* 63 * A SEV-SNP VM requires the policy reserved bit to always be set. 64 * The SMT policy bit is also required to be set based on SMT being 65 * available and active on the system. 66 */ 67 static inline u64 snp_default_policy(void) 68 { 69 return SNP_POLICY_RSVD_MBO | (is_smt_on() ? SNP_POLICY_SMT : 0); 70 } 71 72 /* 73 * The KVM_MEMORY_ENCRYPT_OP uAPI is utter garbage and takes an "unsigned long" 74 * instead of a proper struct. The size of the parameter is embedded in the 75 * ioctl number, i.e. is ABI and thus immutable. Hack around the mess by 76 * creating an overlay to pass in an "unsigned long" without a cast (casting 77 * will make the compiler unhappy due to dereferencing an aliased pointer). 78 */ 79 #define __vm_sev_ioctl(vm, cmd, arg) \ 80 ({ \ 81 int r; \ 82 \ 83 union { \ 84 struct kvm_sev_cmd c; \ 85 unsigned long raw; \ 86 } sev_cmd = { .c = { \ 87 .id = (cmd), \ 88 .data = (uint64_t)(arg), \ 89 .sev_fd = (vm)->arch.sev_fd, \ 90 } }; \ 91 \ 92 r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &sev_cmd.raw); \ 93 r ?: sev_cmd.c.error; \ 94 }) 95 96 #define vm_sev_ioctl(vm, cmd, arg) \ 97 ({ \ 98 int ret = __vm_sev_ioctl(vm, cmd, arg); \ 99 \ 100 __TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd, ret, vm); \ 101 }) 102 103 void sev_vm_init(struct kvm_vm *vm); 104 void sev_es_vm_init(struct kvm_vm *vm); 105 void snp_vm_init(struct kvm_vm *vm); 106 107 static inline void vmgexit(void) 108 { 109 __asm__ __volatile__("rep; vmmcall"); 110 } 111 112 static inline void sev_register_encrypted_memory(struct kvm_vm *vm, 113 struct userspace_mem_region *region) 114 { 115 struct kvm_enc_region range = { 116 .addr = region->region.userspace_addr, 117 .size = region->region.memory_size, 118 }; 119 120 vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range); 121 } 122 123 static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa, 124 uint64_t size) 125 { 126 struct kvm_sev_launch_update_data update_data = { 127 .uaddr = (unsigned long)addr_gpa2hva(vm, gpa), 128 .len = size, 129 }; 130 131 vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data); 132 } 133 134 static inline void snp_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa, 135 uint64_t hva, uint64_t size, uint8_t type) 136 { 137 struct kvm_sev_snp_launch_update update_data = { 138 .uaddr = hva, 139 .gfn_start = gpa >> PAGE_SHIFT, 140 .len = size, 141 .type = type, 142 }; 143 144 vm_sev_ioctl(vm, KVM_SEV_SNP_LAUNCH_UPDATE, &update_data); 145 } 146 147 #endif /* SELFTEST_KVM_SEV_H */ 148