Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kvm/smm.h
26424 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
#ifndef ASM_KVM_SMM_H
3
#define ASM_KVM_SMM_H
4
5
#include <linux/build_bug.h>
6
7
#ifdef CONFIG_KVM_SMM
8
9
10
/*
11
* 32 bit KVM's emulated SMM layout. Based on Intel P6 layout
12
* (https://www.sandpile.org/x86/smm.htm).
13
*/
14
15
struct kvm_smm_seg_state_32 {
16
u32 flags;
17
u32 limit;
18
u32 base;
19
} __packed;
20
21
struct kvm_smram_state_32 {
22
u32 reserved1[62];
23
u32 smbase;
24
u32 smm_revision;
25
u16 io_inst_restart;
26
u16 auto_hlt_restart;
27
u32 io_restart_rdi;
28
u32 io_restart_rcx;
29
u32 io_restart_rsi;
30
u32 io_restart_rip;
31
u32 cr4;
32
33
/* A20M#, CPL, shutdown and other reserved/undocumented fields */
34
u16 reserved2;
35
u8 int_shadow; /* KVM extension */
36
u8 reserved3[17];
37
38
struct kvm_smm_seg_state_32 ds;
39
struct kvm_smm_seg_state_32 fs;
40
struct kvm_smm_seg_state_32 gs;
41
struct kvm_smm_seg_state_32 idtr; /* IDTR has only base and limit */
42
struct kvm_smm_seg_state_32 tr;
43
u32 reserved;
44
struct kvm_smm_seg_state_32 gdtr; /* GDTR has only base and limit */
45
struct kvm_smm_seg_state_32 ldtr;
46
struct kvm_smm_seg_state_32 es;
47
struct kvm_smm_seg_state_32 cs;
48
struct kvm_smm_seg_state_32 ss;
49
50
u32 es_sel;
51
u32 cs_sel;
52
u32 ss_sel;
53
u32 ds_sel;
54
u32 fs_sel;
55
u32 gs_sel;
56
u32 ldtr_sel;
57
u32 tr_sel;
58
59
u32 dr7;
60
u32 dr6;
61
u32 gprs[8]; /* GPRS in the "natural" X86 order (EAX/ECX/EDX.../EDI) */
62
u32 eip;
63
u32 eflags;
64
u32 cr3;
65
u32 cr0;
66
} __packed;
67
68
69
/* 64 bit KVM's emulated SMM layout. Based on AMD64 layout */
70
71
struct kvm_smm_seg_state_64 {
72
u16 selector;
73
u16 attributes;
74
u32 limit;
75
u64 base;
76
};
77
78
struct kvm_smram_state_64 {
79
80
struct kvm_smm_seg_state_64 es;
81
struct kvm_smm_seg_state_64 cs;
82
struct kvm_smm_seg_state_64 ss;
83
struct kvm_smm_seg_state_64 ds;
84
struct kvm_smm_seg_state_64 fs;
85
struct kvm_smm_seg_state_64 gs;
86
struct kvm_smm_seg_state_64 gdtr; /* GDTR has only base and limit*/
87
struct kvm_smm_seg_state_64 ldtr;
88
struct kvm_smm_seg_state_64 idtr; /* IDTR has only base and limit*/
89
struct kvm_smm_seg_state_64 tr;
90
91
/* I/O restart and auto halt restart are not implemented by KVM */
92
u64 io_restart_rip;
93
u64 io_restart_rcx;
94
u64 io_restart_rsi;
95
u64 io_restart_rdi;
96
u32 io_restart_dword;
97
u32 reserved1;
98
u8 io_inst_restart;
99
u8 auto_hlt_restart;
100
u8 amd_nmi_mask; /* Documented in AMD BKDG as NMI mask, not used by KVM */
101
u8 int_shadow;
102
u32 reserved2;
103
104
u64 efer;
105
106
/*
107
* Two fields below are implemented on AMD only, to store
108
* SVM guest vmcb address if the #SMI was received while in the guest mode.
109
*/
110
u64 svm_guest_flag;
111
u64 svm_guest_vmcb_gpa;
112
u64 svm_guest_virtual_int; /* unknown purpose, not implemented */
113
114
u32 reserved3[3];
115
u32 smm_revison;
116
u32 smbase;
117
u32 reserved4[5];
118
119
/* ssp and svm_* fields below are not implemented by KVM */
120
u64 ssp;
121
u64 svm_guest_pat;
122
u64 svm_host_efer;
123
u64 svm_host_cr4;
124
u64 svm_host_cr3;
125
u64 svm_host_cr0;
126
127
u64 cr4;
128
u64 cr3;
129
u64 cr0;
130
u64 dr7;
131
u64 dr6;
132
u64 rflags;
133
u64 rip;
134
u64 gprs[16]; /* GPRS in a reversed "natural" X86 order (R15/R14/../RCX/RAX.) */
135
};
136
137
union kvm_smram {
138
struct kvm_smram_state_64 smram64;
139
struct kvm_smram_state_32 smram32;
140
u8 bytes[512];
141
};
142
143
static inline int kvm_inject_smi(struct kvm_vcpu *vcpu)
144
{
145
if (!kvm_x86_call(has_emulated_msr)(vcpu->kvm, MSR_IA32_SMBASE))
146
return -ENOTTY;
147
148
kvm_make_request(KVM_REQ_SMI, vcpu);
149
return 0;
150
}
151
152
static inline bool is_smm(struct kvm_vcpu *vcpu)
153
{
154
return vcpu->arch.hflags & HF_SMM_MASK;
155
}
156
157
void kvm_smm_changed(struct kvm_vcpu *vcpu, bool in_smm);
158
void enter_smm(struct kvm_vcpu *vcpu);
159
int emulator_leave_smm(struct x86_emulate_ctxt *ctxt);
160
void process_smi(struct kvm_vcpu *vcpu);
161
#else
162
static inline int kvm_inject_smi(struct kvm_vcpu *vcpu) { return -ENOTTY; }
163
static inline bool is_smm(struct kvm_vcpu *vcpu) { return false; }
164
165
/*
166
* emulator_leave_smm is used as a function pointer, so the
167
* stub is defined in x86.c.
168
*/
169
#endif
170
171
#endif
172
173