-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathvmx.h
More file actions
249 lines (208 loc) · 5.31 KB
/
vmx.h
File metadata and controls
249 lines (208 loc) · 5.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*
* SPDX-License-Identifier: GPL-2.0 OR MIT
* Copyright (c) 2026 Ant Group Corporation.
*
* vmx.h - header file for SlimVM VMX driver.
*/
#ifndef __VMX_H_
#define __VMX_H_
#include <linux/types.h>
#include <asm/vmx.h>
#include <asm/signal.h>
#include <linux/kvm_types.h>
#include <linux/version.h>
#include "instance.h"
#include "vmcs.h"
#define ENTER_UESTMODE_FLAGS \
(_TIF_NOTIFY_RESUME | \
_TIF_SIGPENDING | \
_TIF_NEED_RESCHED)
DECLARE_PER_CPU(struct vmx_vcpu *, local_vcpu);
struct vmx_capability {
u64 pin_based;
u64 secondary;
u32 ept;
u32 vpid;
int has_load_efer:1;
};
extern struct vmx_capability vmx_capability;
enum vmx_reg {
VCPU_REGS_RAX = 0,
VCPU_REGS_RCX = 1,
VCPU_REGS_RDX = 2,
VCPU_REGS_RBX = 3,
VCPU_REGS_RSP = 4,
VCPU_REGS_RBP = 5,
VCPU_REGS_RSI = 6,
VCPU_REGS_RDI = 7,
#ifdef CONFIG_X86_64
VCPU_REGS_R8 = 8,
VCPU_REGS_R9 = 9,
VCPU_REGS_R10 = 10,
VCPU_REGS_R11 = 11,
VCPU_REGS_R12 = 12,
VCPU_REGS_R13 = 13,
VCPU_REGS_R14 = 14,
VCPU_REGS_R15 = 15,
#endif
VCPU_REGS_RIP,
NR_VCPU_REGS
};
enum {
VCPU_SREG_ES,
VCPU_SREG_CS,
VCPU_SREG_SS,
VCPU_SREG_DS,
VCPU_SREG_FS,
VCPU_SREG_GS,
VCPU_SREG_TR,
VCPU_SREG_LDTR,
};
enum {
OUTSIDE_ROOT_MODE,
IN_ROOT_MODE,
OUTSIDE_GUEST_MODE,
IN_GUEST_MODE,
EXITING_GUEST_MODE,
};
struct msr_entry {
u32 index;
u32 reserved;
u64 data;
};
struct vmx_vcpu {
struct list_head list;
int cpu;
int vpid;
int launched;
unsigned long requests;
#ifdef CONFIG_PREEMPT_NOTIFIERS
struct preempt_notifier preempt_notifier;
#endif
bool guest_msrs_loaded;
bool guest_xcr0_loaded;
bool scheded;
bool debug_mode;
u8 mode;
u8 fail;
u64 exit_reason;
u64 host_rsp;
u64 regs[NR_VCPU_REGS];
u64 cr2;
s64 status;
u64 xcr0;
u64 flags;
int shutdown;
int save_nmsrs;
int nmsrs;
struct {
unsigned long cr3;
unsigned long cr4;
u16 fs_sel, gs_sel, ldt_sel;
u16 ds_sel, es_sel;
int gs_ldt_reload_needed;
int fs_reload_needed;
} host_state;
struct msr_autoload {
struct vmx_msr_entry guest;
struct vmx_msr_entry host;
} msr_autoload;
struct vmcs *vmcs;
void *syscall_table;
void *idt_base;
struct msr_entry *host_msrs;
struct msr_entry *guest_msrs;
struct {
int sys_call_mask;
int kernel_gs_base;
int feature_enable;
int lstar;
int efer;
int star;
} msr_index;
struct instance *instance;
int vcpu_no;
sigset_t sigset;
bool sigset_active;
bool bounce_pending;
bool nmi_pending;
int vmexit_num;
int vmcall_total;
};
/*
* Copied from KVM.
* Architecture-independent vcpu->requests bit members
* Bits 4-7 are reserved for more arch-independent bits.
*/
#define VMX_REQ_TLB_FLUSH 0
#define VMX_REQ_MMU_RELOAD 1
#define VMX_REQ_PENDING_TIMER 2
#define VMX_REQ_UNHALT 3
/* x86-specific vcpu->requests bit members */
#define VMX_REQ_NMI 17
extern __init int vmx_init(void);
extern void vmx_exit(void);
extern void vmx_cleanup(void);
extern int vmx_launch(struct vmx_vcpu *vcpu, struct slimvm_config *conf);
extern struct vmx_vcpu *vmx_create_vcpu(struct slimvm_config *conf, struct instance *instp);
extern void vmx_destroy_vcpu(struct vmx_vcpu *vcpu);
extern void vmx_shutdown_all_vcpus(struct instance *instp);
extern void vmx_sync_all_vcpus(struct instance *instp);
extern void vcpu_inject_nmi(struct instance *instp, int vcpu_no);
extern int vmx_do_ept_violation(struct instance *instp, unsigned long gpa,
unsigned long gva, int fault_flags);
extern int vmx_do_ept_misconfig(struct instance *instp,
unsigned long gpa, unsigned long **epte);
extern u64 construct_eptp(unsigned long root_hpa);
extern void vmx_ept_sync_individual_addr(struct instance *instp, gpa_t gpa);
extern void vmx_get_cpu(struct vmx_vcpu *vcpu);
extern void vmx_put_cpu(struct vmx_vcpu *vcpu);
extern void vmx_set_vcpu_mode(struct vmx_vcpu *vcpu, u8 mode);
extern bool vmx_check_vcpu_mode(struct vmx_vcpu *vcpu, u8 mode);
extern void make_pt_regs(struct vmx_vcpu *vcpu, struct pt_regs *regs, int sysnr);
extern void (*fn_do_nmi)(struct pt_regs *);
extern inline bool cpu_has_secondary_exec_ctrls(void);
extern inline bool cpu_has_vmx_invvpid_single(void);
extern inline bool cpu_has_vmx_invept_individual_addr(void);
extern inline bool cpu_has_vmx_invept_context(void);
extern inline bool cpu_has_vmx_invept_global(void);
extern inline bool cpu_has_vmx_ept_ad_bits(void);
static inline bool vmx_check_request(int req, struct vmx_vcpu *vcpu)
{
if (test_bit(req, &vcpu->requests)) {
clear_bit(req, &vcpu->requests);
/*
* Ensure the rest of the request is visible to vmx_check_request's
* caller. Paired with the smp_wmb in vmx_make_request.
*/
smp_mb__after_atomic();
return true;
}
return false;
}
static inline void vmx_make_request(int req, struct vmx_vcpu *vcpu)
{
/*
* Ensure the rest of the request is published to kvm_check_request's
* caller. Paired with the smp_mb__after_atomic in kvm_check_request.
*/
smp_wmb();
set_bit(req, &vcpu->requests);
}
static inline int vmx_vcpu_exiting_guest_mode(struct vmx_vcpu *vcpu)
{
return cmpxchg(&vcpu->mode, IN_GUEST_MODE, EXITING_GUEST_MODE);
}
static inline int vmx_interrupt_allowed(void)
{
return (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) &&
!(vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) &
(GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS));
}
static inline unsigned long read_msr(unsigned long msr)
{
unsigned long value;
rdmsrl(msr, value);
return value;
}
#endif /* __VMX_H_ */