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 Bonzinistatic 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 Bonzinistatic 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 Bonzinistatic inline int kvm_inject_smi(struct kvm_vcpu *vcpu) { return -ENOTTY; } is_smm(struct kvm_vcpu * vcpu)1604b8e1b32SPaolo Bonzinistatic 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