xref: /linux/tools/testing/selftests/kvm/include/x86/sev.h (revision f694f30e81c4ade358eb8c75273bac1a48f0cb8f)
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 GHCB_MSR_TERM_REQ	0x100
29 
30 void sev_vm_launch(struct kvm_vm *vm, uint32_t policy);
31 void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement);
32 void sev_vm_launch_finish(struct kvm_vm *vm);
33 
34 struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code,
35 					   struct kvm_vcpu **cpu);
36 void vm_sev_launch(struct kvm_vm *vm, uint32_t policy, uint8_t *measurement);
37 
38 kvm_static_assert(SEV_RET_SUCCESS == 0);
39 
40 /*
41  * The KVM_MEMORY_ENCRYPT_OP uAPI is utter garbage and takes an "unsigned long"
42  * instead of a proper struct.  The size of the parameter is embedded in the
43  * ioctl number, i.e. is ABI and thus immutable.  Hack around the mess by
44  * creating an overlay to pass in an "unsigned long" without a cast (casting
45  * will make the compiler unhappy due to dereferencing an aliased pointer).
46  */
47 #define __vm_sev_ioctl(vm, cmd, arg)					\
48 ({									\
49 	int r;								\
50 									\
51 	union {								\
52 		struct kvm_sev_cmd c;					\
53 		unsigned long raw;					\
54 	} sev_cmd = { .c = {						\
55 		.id = (cmd),						\
56 		.data = (uint64_t)(arg),				\
57 		.sev_fd = (vm)->arch.sev_fd,				\
58 	} };								\
59 									\
60 	r = __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_OP, &sev_cmd.raw);	\
61 	r ?: sev_cmd.c.error;						\
62 })
63 
64 #define vm_sev_ioctl(vm, cmd, arg)					\
65 ({									\
66 	int ret = __vm_sev_ioctl(vm, cmd, arg);				\
67 									\
68 	__TEST_ASSERT_VM_VCPU_IOCTL(!ret, #cmd,	ret, vm);		\
69 })
70 
71 void sev_vm_init(struct kvm_vm *vm);
72 void sev_es_vm_init(struct kvm_vm *vm);
73 
74 static inline void vmgexit(void)
75 {
76 	__asm__ __volatile__("rep; vmmcall");
77 }
78 
79 static inline void sev_register_encrypted_memory(struct kvm_vm *vm,
80 						 struct userspace_mem_region *region)
81 {
82 	struct kvm_enc_region range = {
83 		.addr = region->region.userspace_addr,
84 		.size = region->region.memory_size,
85 	};
86 
87 	vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
88 }
89 
90 static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,
91 					  uint64_t size)
92 {
93 	struct kvm_sev_launch_update_data update_data = {
94 		.uaddr = (unsigned long)addr_gpa2hva(vm, gpa),
95 		.len = size,
96 	};
97 
98 	vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data);
99 }
100 
101 #endif /* SELFTEST_KVM_SEV_H */
102