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