Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/kvm/include/x86/sev.h
50058 views
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 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
34
static inline bool is_sev_snp_vm(struct kvm_vm *vm)
35
{
36
return vm->type == KVM_X86_SNP_VM;
37
}
38
39
static 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
44
static 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
49
void sev_vm_launch(struct kvm_vm *vm, uint32_t policy);
50
void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement);
51
void sev_vm_launch_finish(struct kvm_vm *vm);
52
void snp_vm_launch_start(struct kvm_vm *vm, uint64_t policy);
53
void snp_vm_launch_update(struct kvm_vm *vm);
54
void snp_vm_launch_finish(struct kvm_vm *vm);
55
56
struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t type, void *guest_code,
57
struct kvm_vcpu **cpu);
58
void vm_sev_launch(struct kvm_vm *vm, uint64_t policy, uint8_t *measurement);
59
60
kvm_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
*/
67
static 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 = (uint64_t)(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
103
void sev_vm_init(struct kvm_vm *vm);
104
void sev_es_vm_init(struct kvm_vm *vm);
105
void snp_vm_init(struct kvm_vm *vm);
106
107
static inline void vmgexit(void)
108
{
109
__asm__ __volatile__("rep; vmmcall");
110
}
111
112
static 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
123
static inline void sev_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,
124
uint64_t 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
134
static inline void snp_launch_update_data(struct kvm_vm *vm, vm_paddr_t gpa,
135
uint64_t hva, uint64_t size, uint8_t 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 */
148
149