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 kvm_make_request(KVM_REQ_SMI, vcpu); 146 return 0; 147 } 148 149 static inline bool is_smm(struct kvm_vcpu *vcpu) 150 { 151 return vcpu->arch.hflags & HF_SMM_MASK; 152 } 153 154 void kvm_smm_changed(struct kvm_vcpu *vcpu, bool in_smm); 155 void enter_smm(struct kvm_vcpu *vcpu); 156 int emulator_leave_smm(struct x86_emulate_ctxt *ctxt); 157 void process_smi(struct kvm_vcpu *vcpu); 158 #else 159 static inline int kvm_inject_smi(struct kvm_vcpu *vcpu) { return -ENOTTY; } 160 static inline bool is_smm(struct kvm_vcpu *vcpu) { return false; } 161 162 /* 163 * emulator_leave_smm is used as a function pointer, so the 164 * stub is defined in x86.c. 165 */ 166 #endif 167 168 #endif 169