]> git.proxmox.com Git - pve-kernel.git/blame - patches/kernel/0010-KVM-x86-emulator-smm-add-structs-for-KVM-s-smram-lay.patch
update to Ubuntu-6.1.0-1.1
[pve-kernel.git] / patches / kernel / 0010-KVM-x86-emulator-smm-add-structs-for-KVM-s-smram-lay.patch
CommitLineData
f6df304f
TL
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Maxim Levitsky <mlevitsk@redhat.com>
83250735 3Date: Wed, 3 Aug 2022 18:50:05 +0300
f6df304f
TL
4Subject: [PATCH] KVM: x86: emulator/smm: add structs for KVM's smram layout
5
6Those structs will be used to read/write the smram state image.
7
8Also document the differences between KVM's SMRAM layout and SMRAM
9layout that is used by real Intel/AMD cpus.
10
11Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
12Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
13---
83250735
TL
14 arch/x86/kvm/emulate.c | 6 +
15 arch/x86/kvm/kvm_emulate.h | 218 +++++++++++++++++++++++++++++++++++++
16 arch/x86/kvm/x86.c | 1 +
17 3 files changed, 225 insertions(+)
f6df304f 18
83250735 19diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
12247ad0 20index 4f7f5117ec7a..470dd4453b01 100644
83250735
TL
21--- a/arch/x86/kvm/emulate.c
22+++ b/arch/x86/kvm/emulate.c
12247ad0 23@@ -5856,3 +5856,9 @@ bool emulator_can_use_gpa(struct x86_emulate_ctxt *ctxt)
83250735
TL
24
25 return true;
26 }
27+
28+void __init kvm_emulator_init(void)
29+{
30+ __check_smram32_offsets();
31+ __check_smram64_offsets();
32+}
f6df304f 33diff --git a/arch/x86/kvm/kvm_emulate.h b/arch/x86/kvm/kvm_emulate.h
12247ad0 34index 89246446d6aa..dd0ae61e44a1 100644
f6df304f
TL
35--- a/arch/x86/kvm/kvm_emulate.h
36+++ b/arch/x86/kvm/kvm_emulate.h
83250735
TL
37@@ -13,6 +13,7 @@
38 #define _ASM_X86_KVM_X86_EMULATE_H
39
40 #include <asm/desc_defs.h>
41+#include <linux/build_bug.h>
42 #include "fpu.h"
43
44 struct x86_emulate_ctxt;
12247ad0 45@@ -503,6 +504,223 @@ enum x86_intercept {
f6df304f
TL
46 nr_x86_intercepts
47 };
48
49+
83250735 50+/* 32 bit KVM's emulated SMM layout. Loosely based on Intel's layout */
f6df304f
TL
51+
52+struct kvm_smm_seg_state_32 {
53+ u32 flags;
54+ u32 limit;
55+ u32 base;
56+} __packed;
57+
58+struct kvm_smram_state_32 {
83250735
TL
59+ u32 reserved1[62];
60+ u32 smbase;
61+ u32 smm_revision;
62+ u32 reserved2[5];
63+ u32 cr4; /* CR4 is not present in Intel/AMD SMRAM image */
64+ u32 reserved3[5];
f6df304f
TL
65+
66+ /*
83250735
TL
67+ * Segment state is not present/documented in the Intel/AMD SMRAM image
68+ * Instead this area on Intel/AMD contains IO/HLT restart flags.
f6df304f 69+ */
83250735
TL
70+ struct kvm_smm_seg_state_32 ds;
71+ struct kvm_smm_seg_state_32 fs;
72+ struct kvm_smm_seg_state_32 gs;
73+ struct kvm_smm_seg_state_32 idtr; /* IDTR has only base and limit */
74+ struct kvm_smm_seg_state_32 tr;
75+ u32 reserved;
76+ struct kvm_smm_seg_state_32 gdtr; /* GDTR has only base and limit */
77+ struct kvm_smm_seg_state_32 ldtr;
78+ struct kvm_smm_seg_state_32 es;
79+ struct kvm_smm_seg_state_32 cs;
80+ struct kvm_smm_seg_state_32 ss;
81+
82+ u32 es_sel;
83+ u32 cs_sel;
84+ u32 ss_sel;
85+ u32 ds_sel;
86+ u32 fs_sel;
87+ u32 gs_sel;
88+ u32 ldtr_sel;
89+ u32 tr_sel;
90+
91+ u32 dr7;
92+ u32 dr6;
93+ u32 gprs[8]; /* GPRS in the "natural" X86 order (EAX/ECX/EDX.../EDI) */
94+ u32 eip;
95+ u32 eflags;
96+ u32 cr3;
97+ u32 cr0;
f6df304f
TL
98+} __packed;
99+
83250735
TL
100+
101+static inline void __check_smram32_offsets(void)
102+{
103+#define __CHECK_SMRAM32_OFFSET(field, offset) \
104+ ASSERT_STRUCT_OFFSET(struct kvm_smram_state_32, field, offset - 0xFE00)
105+
106+ __CHECK_SMRAM32_OFFSET(reserved1, 0xFE00);
107+ __CHECK_SMRAM32_OFFSET(smbase, 0xFEF8);
108+ __CHECK_SMRAM32_OFFSET(smm_revision, 0xFEFC);
109+ __CHECK_SMRAM32_OFFSET(reserved2, 0xFF00);
110+ __CHECK_SMRAM32_OFFSET(cr4, 0xFF14);
111+ __CHECK_SMRAM32_OFFSET(reserved3, 0xFF18);
112+ __CHECK_SMRAM32_OFFSET(ds, 0xFF2C);
113+ __CHECK_SMRAM32_OFFSET(fs, 0xFF38);
114+ __CHECK_SMRAM32_OFFSET(gs, 0xFF44);
115+ __CHECK_SMRAM32_OFFSET(idtr, 0xFF50);
116+ __CHECK_SMRAM32_OFFSET(tr, 0xFF5C);
117+ __CHECK_SMRAM32_OFFSET(gdtr, 0xFF6C);
118+ __CHECK_SMRAM32_OFFSET(ldtr, 0xFF78);
119+ __CHECK_SMRAM32_OFFSET(es, 0xFF84);
120+ __CHECK_SMRAM32_OFFSET(cs, 0xFF90);
121+ __CHECK_SMRAM32_OFFSET(ss, 0xFF9C);
122+ __CHECK_SMRAM32_OFFSET(es_sel, 0xFFA8);
123+ __CHECK_SMRAM32_OFFSET(cs_sel, 0xFFAC);
124+ __CHECK_SMRAM32_OFFSET(ss_sel, 0xFFB0);
125+ __CHECK_SMRAM32_OFFSET(ds_sel, 0xFFB4);
126+ __CHECK_SMRAM32_OFFSET(fs_sel, 0xFFB8);
127+ __CHECK_SMRAM32_OFFSET(gs_sel, 0xFFBC);
128+ __CHECK_SMRAM32_OFFSET(ldtr_sel, 0xFFC0);
129+ __CHECK_SMRAM32_OFFSET(tr_sel, 0xFFC4);
130+ __CHECK_SMRAM32_OFFSET(dr7, 0xFFC8);
131+ __CHECK_SMRAM32_OFFSET(dr6, 0xFFCC);
132+ __CHECK_SMRAM32_OFFSET(gprs, 0xFFD0);
133+ __CHECK_SMRAM32_OFFSET(eip, 0xFFF0);
134+ __CHECK_SMRAM32_OFFSET(eflags, 0xFFF4);
135+ __CHECK_SMRAM32_OFFSET(cr3, 0xFFF8);
136+ __CHECK_SMRAM32_OFFSET(cr0, 0xFFFC);
137+#undef __CHECK_SMRAM32_OFFSET
138+}
139+
140+
141+/* 64 bit KVM's emulated SMM layout. Based on AMD64 layout */
f6df304f
TL
142+
143+struct kvm_smm_seg_state_64 {
144+ u16 selector;
145+ u16 attributes;
146+ u32 limit;
147+ u64 base;
148+};
149+
150+struct kvm_smram_state_64 {
f6df304f 151+
83250735
TL
152+ struct kvm_smm_seg_state_64 es;
153+ struct kvm_smm_seg_state_64 cs;
154+ struct kvm_smm_seg_state_64 ss;
155+ struct kvm_smm_seg_state_64 ds;
156+ struct kvm_smm_seg_state_64 fs;
157+ struct kvm_smm_seg_state_64 gs;
158+ struct kvm_smm_seg_state_64 gdtr; /* GDTR has only base and limit*/
159+ struct kvm_smm_seg_state_64 ldtr;
160+ struct kvm_smm_seg_state_64 idtr; /* IDTR has only base and limit*/
161+ struct kvm_smm_seg_state_64 tr;
f6df304f
TL
162+
163+ /* I/O restart and auto halt restart are not implemented by KVM */
83250735
TL
164+ u64 io_restart_rip;
165+ u64 io_restart_rcx;
166+ u64 io_restart_rsi;
167+ u64 io_restart_rdi;
168+ u32 io_restart_dword;
169+ u32 reserved1;
170+ u8 io_inst_restart;
171+ u8 auto_hlt_restart;
172+ u8 reserved2[6];
173+
174+ u64 efer;
f6df304f
TL
175+
176+ /*
83250735
TL
177+ * Two fields below are implemented on AMD only, to store
178+ * SVM guest vmcb address if the #SMI was received while in the guest mode.
f6df304f 179+ */
83250735
TL
180+ u64 svm_guest_flag;
181+ u64 svm_guest_vmcb_gpa;
182+ u64 svm_guest_virtual_int; /* unknown purpose, not implemented */
f6df304f 183+
83250735
TL
184+ u32 reserved3[3];
185+ u32 smm_revison;
186+ u32 smbase;
187+ u32 reserved4[5];
f6df304f 188+
83250735
TL
189+ /* ssp and svm_* fields below are not implemented by KVM */
190+ u64 ssp;
191+ u64 svm_guest_pat;
192+ u64 svm_host_efer;
193+ u64 svm_host_cr4;
194+ u64 svm_host_cr3;
195+ u64 svm_host_cr0;
f6df304f 196+
83250735
TL
197+ u64 cr4;
198+ u64 cr3;
199+ u64 cr0;
200+ u64 dr7;
201+ u64 dr6;
202+ u64 rflags;
203+ u64 rip;
204+ u64 gprs[16]; /* GPRS in a reversed "natural" X86 order (R15/R14/../RCX/RAX.) */
205+};
f6df304f 206+
f6df304f 207+
83250735
TL
208+static inline void __check_smram64_offsets(void)
209+{
210+#define __CHECK_SMRAM64_OFFSET(field, offset) \
211+ ASSERT_STRUCT_OFFSET(struct kvm_smram_state_64, field, offset - 0xFE00)
f6df304f 212+
83250735
TL
213+ __CHECK_SMRAM64_OFFSET(es, 0xFE00);
214+ __CHECK_SMRAM64_OFFSET(cs, 0xFE10);
215+ __CHECK_SMRAM64_OFFSET(ss, 0xFE20);
216+ __CHECK_SMRAM64_OFFSET(ds, 0xFE30);
217+ __CHECK_SMRAM64_OFFSET(fs, 0xFE40);
218+ __CHECK_SMRAM64_OFFSET(gs, 0xFE50);
219+ __CHECK_SMRAM64_OFFSET(gdtr, 0xFE60);
220+ __CHECK_SMRAM64_OFFSET(ldtr, 0xFE70);
221+ __CHECK_SMRAM64_OFFSET(idtr, 0xFE80);
222+ __CHECK_SMRAM64_OFFSET(tr, 0xFE90);
223+ __CHECK_SMRAM64_OFFSET(io_restart_rip, 0xFEA0);
224+ __CHECK_SMRAM64_OFFSET(io_restart_rcx, 0xFEA8);
225+ __CHECK_SMRAM64_OFFSET(io_restart_rsi, 0xFEB0);
226+ __CHECK_SMRAM64_OFFSET(io_restart_rdi, 0xFEB8);
227+ __CHECK_SMRAM64_OFFSET(io_restart_dword, 0xFEC0);
228+ __CHECK_SMRAM64_OFFSET(reserved1, 0xFEC4);
229+ __CHECK_SMRAM64_OFFSET(io_inst_restart, 0xFEC8);
230+ __CHECK_SMRAM64_OFFSET(auto_hlt_restart, 0xFEC9);
231+ __CHECK_SMRAM64_OFFSET(reserved2, 0xFECA);
232+ __CHECK_SMRAM64_OFFSET(efer, 0xFED0);
233+ __CHECK_SMRAM64_OFFSET(svm_guest_flag, 0xFED8);
234+ __CHECK_SMRAM64_OFFSET(svm_guest_vmcb_gpa, 0xFEE0);
235+ __CHECK_SMRAM64_OFFSET(svm_guest_virtual_int, 0xFEE8);
236+ __CHECK_SMRAM64_OFFSET(reserved3, 0xFEF0);
237+ __CHECK_SMRAM64_OFFSET(smm_revison, 0xFEFC);
238+ __CHECK_SMRAM64_OFFSET(smbase, 0xFF00);
239+ __CHECK_SMRAM64_OFFSET(reserved4, 0xFF04);
240+ __CHECK_SMRAM64_OFFSET(ssp, 0xFF18);
241+ __CHECK_SMRAM64_OFFSET(svm_guest_pat, 0xFF20);
242+ __CHECK_SMRAM64_OFFSET(svm_host_efer, 0xFF28);
243+ __CHECK_SMRAM64_OFFSET(svm_host_cr4, 0xFF30);
244+ __CHECK_SMRAM64_OFFSET(svm_host_cr3, 0xFF38);
245+ __CHECK_SMRAM64_OFFSET(svm_host_cr0, 0xFF40);
246+ __CHECK_SMRAM64_OFFSET(cr4, 0xFF48);
247+ __CHECK_SMRAM64_OFFSET(cr3, 0xFF50);
248+ __CHECK_SMRAM64_OFFSET(cr0, 0xFF58);
249+ __CHECK_SMRAM64_OFFSET(dr7, 0xFF60);
250+ __CHECK_SMRAM64_OFFSET(dr6, 0xFF68);
251+ __CHECK_SMRAM64_OFFSET(rflags, 0xFF70);
252+ __CHECK_SMRAM64_OFFSET(rip, 0xFF78);
253+ __CHECK_SMRAM64_OFFSET(gprs, 0xFF80);
254+#undef __CHECK_SMRAM64_OFFSET
255+}
f6df304f 256+
83250735
TL
257+union kvm_smram {
258+ struct kvm_smram_state_64 smram64;
259+ struct kvm_smram_state_32 smram32;
260+ u8 bytes[512];
f6df304f
TL
261+};
262+
83250735
TL
263+void __init kvm_emulator_init(void);
264+
f6df304f
TL
265+
266 /* Host execution mode. */
267 #if defined(CONFIG_X86_32)
268 #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32
83250735 269diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
12247ad0 270index acca85b10545..20aec64e3521 100644
83250735
TL
271--- a/arch/x86/kvm/x86.c
272+++ b/arch/x86/kvm/x86.c
12247ad0 273@@ -13730,6 +13730,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_vmgexit_msr_protocol_exit);
83250735
TL
274 static int __init kvm_x86_init(void)
275 {
276 kvm_mmu_x86_module_init();
277+ kvm_emulator_init();
278 return 0;
279 }
280 module_init(kvm_x86_init);