xref: /linux/tools/testing/selftests/kvm/include/x86/sev.h (revision e78f70bad29c5ae1e1076698b690b15794e9b81e)
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