xref: /openbmc/linux/arch/x86/kvm/smm.h (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1b0b42197SPaolo Bonzini /* SPDX-License-Identifier: GPL-2.0 */
2b0b42197SPaolo Bonzini #ifndef ASM_KVM_SMM_H
3b0b42197SPaolo Bonzini #define ASM_KVM_SMM_H
4b0b42197SPaolo Bonzini 
509779c16SMaxim Levitsky #include <linux/build_bug.h>
609779c16SMaxim Levitsky 
74b8e1b32SPaolo Bonzini #ifdef CONFIG_KVM_SMM
809779c16SMaxim Levitsky 
909779c16SMaxim Levitsky 
1009779c16SMaxim Levitsky /*
1109779c16SMaxim Levitsky  * 32 bit KVM's emulated SMM layout. Based on Intel P6 layout
1209779c16SMaxim Levitsky  * (https://www.sandpile.org/x86/smm.htm).
1309779c16SMaxim Levitsky  */
1409779c16SMaxim Levitsky 
1509779c16SMaxim Levitsky struct kvm_smm_seg_state_32 {
1609779c16SMaxim Levitsky 	u32 flags;
1709779c16SMaxim Levitsky 	u32 limit;
1809779c16SMaxim Levitsky 	u32 base;
1909779c16SMaxim Levitsky } __packed;
2009779c16SMaxim Levitsky 
2109779c16SMaxim Levitsky struct kvm_smram_state_32 {
2209779c16SMaxim Levitsky 	u32 reserved1[62];
2309779c16SMaxim Levitsky 	u32 smbase;
2409779c16SMaxim Levitsky 	u32 smm_revision;
2509779c16SMaxim Levitsky 	u16 io_inst_restart;
2609779c16SMaxim Levitsky 	u16 auto_hlt_restart;
2709779c16SMaxim Levitsky 	u32 io_restart_rdi;
2809779c16SMaxim Levitsky 	u32 io_restart_rcx;
2909779c16SMaxim Levitsky 	u32 io_restart_rsi;
3009779c16SMaxim Levitsky 	u32 io_restart_rip;
3109779c16SMaxim Levitsky 	u32 cr4;
3209779c16SMaxim Levitsky 
3309779c16SMaxim Levitsky 	/* A20M#, CPL, shutdown and other reserved/undocumented fields */
34*fb28875fSMaxim Levitsky 	u16 reserved2;
35*fb28875fSMaxim Levitsky 	u8 int_shadow; /* KVM extension */
36*fb28875fSMaxim Levitsky 	u8 reserved3[17];
3709779c16SMaxim Levitsky 
3809779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 ds;
3909779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 fs;
4009779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 gs;
4109779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 idtr; /* IDTR has only base and limit */
4209779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 tr;
4309779c16SMaxim Levitsky 	u32 reserved;
4409779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 gdtr; /* GDTR has only base and limit */
4509779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 ldtr;
4609779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 es;
4709779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 cs;
4809779c16SMaxim Levitsky 	struct kvm_smm_seg_state_32 ss;
4909779c16SMaxim Levitsky 
5009779c16SMaxim Levitsky 	u32 es_sel;
5109779c16SMaxim Levitsky 	u32 cs_sel;
5209779c16SMaxim Levitsky 	u32 ss_sel;
5309779c16SMaxim Levitsky 	u32 ds_sel;
5409779c16SMaxim Levitsky 	u32 fs_sel;
5509779c16SMaxim Levitsky 	u32 gs_sel;
5609779c16SMaxim Levitsky 	u32 ldtr_sel;
5709779c16SMaxim Levitsky 	u32 tr_sel;
5809779c16SMaxim Levitsky 
5909779c16SMaxim Levitsky 	u32 dr7;
6009779c16SMaxim Levitsky 	u32 dr6;
6109779c16SMaxim Levitsky 	u32 gprs[8]; /* GPRS in the "natural" X86 order (EAX/ECX/EDX.../EDI) */
6209779c16SMaxim Levitsky 	u32 eip;
6309779c16SMaxim Levitsky 	u32 eflags;
6409779c16SMaxim Levitsky 	u32 cr3;
6509779c16SMaxim Levitsky 	u32 cr0;
6609779c16SMaxim Levitsky } __packed;
6709779c16SMaxim Levitsky 
6809779c16SMaxim Levitsky 
6909779c16SMaxim Levitsky /* 64 bit KVM's emulated SMM layout. Based on AMD64 layout */
7009779c16SMaxim Levitsky 
7109779c16SMaxim Levitsky struct kvm_smm_seg_state_64 {
7209779c16SMaxim Levitsky 	u16 selector;
7309779c16SMaxim Levitsky 	u16 attributes;
7409779c16SMaxim Levitsky 	u32 limit;
7509779c16SMaxim Levitsky 	u64 base;
7609779c16SMaxim Levitsky };
7709779c16SMaxim Levitsky 
7809779c16SMaxim Levitsky struct kvm_smram_state_64 {
7909779c16SMaxim Levitsky 
8009779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 es;
8109779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 cs;
8209779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 ss;
8309779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 ds;
8409779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 fs;
8509779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 gs;
8609779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 gdtr; /* GDTR has only base and limit*/
8709779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 ldtr;
8809779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 idtr; /* IDTR has only base and limit*/
8909779c16SMaxim Levitsky 	struct kvm_smm_seg_state_64 tr;
9009779c16SMaxim Levitsky 
9109779c16SMaxim Levitsky 	/* I/O restart and auto halt restart are not implemented by KVM */
9209779c16SMaxim Levitsky 	u64 io_restart_rip;
9309779c16SMaxim Levitsky 	u64 io_restart_rcx;
9409779c16SMaxim Levitsky 	u64 io_restart_rsi;
9509779c16SMaxim Levitsky 	u64 io_restart_rdi;
9609779c16SMaxim Levitsky 	u32 io_restart_dword;
9709779c16SMaxim Levitsky 	u32 reserved1;
9809779c16SMaxim Levitsky 	u8 io_inst_restart;
9909779c16SMaxim Levitsky 	u8 auto_hlt_restart;
100*fb28875fSMaxim Levitsky 	u8 amd_nmi_mask; /* Documented in AMD BKDG as NMI mask, not used by KVM */
101*fb28875fSMaxim Levitsky 	u8 int_shadow;
102*fb28875fSMaxim Levitsky 	u32 reserved2;
10309779c16SMaxim Levitsky 
10409779c16SMaxim Levitsky 	u64 efer;
10509779c16SMaxim Levitsky 
10609779c16SMaxim Levitsky 	/*
10709779c16SMaxim Levitsky 	 * Two fields below are implemented on AMD only, to store
10809779c16SMaxim Levitsky 	 * SVM guest vmcb address if the #SMI was received while in the guest mode.
10909779c16SMaxim Levitsky 	 */
11009779c16SMaxim Levitsky 	u64 svm_guest_flag;
11109779c16SMaxim Levitsky 	u64 svm_guest_vmcb_gpa;
11209779c16SMaxim Levitsky 	u64 svm_guest_virtual_int; /* unknown purpose, not implemented */
11309779c16SMaxim Levitsky 
11409779c16SMaxim Levitsky 	u32 reserved3[3];
11509779c16SMaxim Levitsky 	u32 smm_revison;
11609779c16SMaxim Levitsky 	u32 smbase;
11709779c16SMaxim Levitsky 	u32 reserved4[5];
11809779c16SMaxim Levitsky 
11909779c16SMaxim Levitsky 	/* ssp and svm_* fields below are not implemented by KVM */
12009779c16SMaxim Levitsky 	u64 ssp;
12109779c16SMaxim Levitsky 	u64 svm_guest_pat;
12209779c16SMaxim Levitsky 	u64 svm_host_efer;
12309779c16SMaxim Levitsky 	u64 svm_host_cr4;
12409779c16SMaxim Levitsky 	u64 svm_host_cr3;
12509779c16SMaxim Levitsky 	u64 svm_host_cr0;
12609779c16SMaxim Levitsky 
12709779c16SMaxim Levitsky 	u64 cr4;
12809779c16SMaxim Levitsky 	u64 cr3;
12909779c16SMaxim Levitsky 	u64 cr0;
13009779c16SMaxim Levitsky 	u64 dr7;
13109779c16SMaxim Levitsky 	u64 dr6;
13209779c16SMaxim Levitsky 	u64 rflags;
13309779c16SMaxim Levitsky 	u64 rip;
13409779c16SMaxim Levitsky 	u64 gprs[16]; /* GPRS in a reversed "natural" X86 order (R15/R14/../RCX/RAX.) */
13509779c16SMaxim Levitsky };
13609779c16SMaxim Levitsky 
13709779c16SMaxim Levitsky union kvm_smram {
13809779c16SMaxim Levitsky 	struct kvm_smram_state_64 smram64;
13909779c16SMaxim Levitsky 	struct kvm_smram_state_32 smram32;
14009779c16SMaxim Levitsky 	u8 bytes[512];
14109779c16SMaxim Levitsky };
14209779c16SMaxim Levitsky 
kvm_inject_smi(struct kvm_vcpu * vcpu)143b0b42197SPaolo Bonzini static inline int kvm_inject_smi(struct kvm_vcpu *vcpu)
144b0b42197SPaolo Bonzini {
145b0b42197SPaolo Bonzini 	kvm_make_request(KVM_REQ_SMI, vcpu);
146b0b42197SPaolo Bonzini 	return 0;
147b0b42197SPaolo Bonzini }
148b0b42197SPaolo Bonzini 
is_smm(struct kvm_vcpu * vcpu)149b0b42197SPaolo Bonzini static inline bool is_smm(struct kvm_vcpu *vcpu)
150b0b42197SPaolo Bonzini {
151b0b42197SPaolo Bonzini 	return vcpu->arch.hflags & HF_SMM_MASK;
152b0b42197SPaolo Bonzini }
153b0b42197SPaolo Bonzini 
154b0b42197SPaolo Bonzini void kvm_smm_changed(struct kvm_vcpu *vcpu, bool in_smm);
155c53da4f3SPaolo Bonzini void enter_smm(struct kvm_vcpu *vcpu);
156f1554150SPaolo Bonzini int emulator_leave_smm(struct x86_emulate_ctxt *ctxt);
157b0b42197SPaolo Bonzini void process_smi(struct kvm_vcpu *vcpu);
1584b8e1b32SPaolo Bonzini #else
kvm_inject_smi(struct kvm_vcpu * vcpu)1594b8e1b32SPaolo Bonzini static inline int kvm_inject_smi(struct kvm_vcpu *vcpu) { return -ENOTTY; }
is_smm(struct kvm_vcpu * vcpu)1604b8e1b32SPaolo Bonzini static inline bool is_smm(struct kvm_vcpu *vcpu) { return false; }
1614b8e1b32SPaolo Bonzini 
1624b8e1b32SPaolo Bonzini /*
1634b8e1b32SPaolo Bonzini  * emulator_leave_smm is used as a function pointer, so the
1644b8e1b32SPaolo Bonzini  * stub is defined in x86.c.
1654b8e1b32SPaolo Bonzini  */
1664b8e1b32SPaolo Bonzini #endif
167b0b42197SPaolo Bonzini 
168b0b42197SPaolo Bonzini #endif
169