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
sev_register_encrypted_memory(struct kvm_vm * vm,struct userspace_mem_region * region)74 static inline void sev_register_encrypted_memory(struct kvm_vm *vm,
75 struct userspace_mem_region *region)
76 {
77 struct kvm_enc_region range = {
78 .addr = region->region.userspace_addr,
79 .size = region->region.memory_size,
80 };
81
82 vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);
83 }
84
sev_launch_update_data(struct kvm_vm * vm,vm_paddr_t gpa,uint64_t size)85 static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,
86 uint64_t size)
87 {
88 struct kvm_sev_launch_update_data update_data = {
89 .uaddr = (unsigned long)addr_gpa2hva(vm, gpa),
90 .len = size,
91 };
92
93 vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_DATA, &update_data);
94 }
95
96 #endif /* SELFTEST_KVM_SEV_H */
97