Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 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
34static inline bool is_sev_snp_vm(struct kvm_vm *vm)
35{
36 return vm->type == KVM_X86_SNP_VM;
37}
38
39static 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
44static 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
49void sev_vm_launch(struct kvm_vm *vm, u32 policy);
50void sev_vm_launch_measure(struct kvm_vm *vm, u8 *measurement);
51void sev_vm_launch_finish(struct kvm_vm *vm);
52void snp_vm_launch_start(struct kvm_vm *vm, u64 policy);
53void snp_vm_launch_update(struct kvm_vm *vm);
54void snp_vm_launch_finish(struct kvm_vm *vm);
55
56struct kvm_vm *vm_sev_create_with_one_vcpu(u32 type, void *guest_code,
57 struct kvm_vcpu **cpu);
58void vm_sev_launch(struct kvm_vm *vm, u64 policy, u8 *measurement);
59
60kvm_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 */
67static 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 = (u64)(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
103void sev_vm_init(struct kvm_vm *vm);
104void sev_es_vm_init(struct kvm_vm *vm);
105void snp_vm_init(struct kvm_vm *vm);
106
107static inline void vmgexit(void)
108{
109 __asm__ __volatile__("rep; vmmcall");
110}
111
112static 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
123static inline void sev_launch_update_data(struct kvm_vm *vm, gpa_t gpa,
124 u64 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
134static inline void snp_launch_update_data(struct kvm_vm *vm, gpa_t gpa,
135 u64 hva, u64 size, u8 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 */