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