Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: x86: stubs for SMM support

This patch adds the interface between x86.c and the emulator: the
SMBASE register, a new emulator flag, the RSM instruction. It also
adds a new request bit that will be used by the KVM_SMI ioctl.

Reviewed-by: Radim Krčmář <rkrcmar@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

+81 -4
+4
arch/x86/include/asm/kvm_emulate.h
··· 193 193 int (*cpl)(struct x86_emulate_ctxt *ctxt); 194 194 int (*get_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong *dest); 195 195 int (*set_dr)(struct x86_emulate_ctxt *ctxt, int dr, ulong value); 196 + u64 (*get_smbase)(struct x86_emulate_ctxt *ctxt); 197 + void (*set_smbase)(struct x86_emulate_ctxt *ctxt, u64 smbase); 196 198 int (*set_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 data); 197 199 int (*get_msr)(struct x86_emulate_ctxt *ctxt, u32 msr_index, u64 *pdata); 198 200 int (*check_pmc)(struct x86_emulate_ctxt *ctxt, u32 pmc); ··· 266 264 267 265 /* These match some of the HF_* flags defined in kvm_host.h */ 268 266 #define X86EMUL_GUEST_MASK (1 << 5) /* VCPU is in guest-mode */ 267 + #define X86EMUL_SMM_MASK (1 << 6) 268 + #define X86EMUL_SMM_INSIDE_NMI_MASK (1 << 7) 269 269 270 270 struct x86_emulate_ctxt { 271 271 const struct x86_emulate_ops *ops;
+1
arch/x86/include/asm/kvm_host.h
··· 368 368 int32_t apic_arb_prio; 369 369 int mp_state; 370 370 u64 ia32_misc_enable_msr; 371 + u64 smbase; 371 372 bool tpr_access_reporting; 372 373 u64 ia32_xss; 373 374
+9 -1
arch/x86/kvm/emulate.c
··· 2259 2259 return rc; 2260 2260 } 2261 2261 2262 + static int em_rsm(struct x86_emulate_ctxt *ctxt) 2263 + { 2264 + if ((ctxt->emul_flags & X86EMUL_SMM_MASK) == 0) 2265 + return emulate_ud(ctxt); 2266 + 2267 + return X86EMUL_UNHANDLEABLE; 2268 + } 2269 + 2262 2270 static void 2263 2271 setup_syscalls_segments(struct x86_emulate_ctxt *ctxt, 2264 2272 struct desc_struct *cs, struct desc_struct *ss) ··· 4205 4197 F(DstMem | SrcReg | Src2CL | ModRM, em_shld), N, N, 4206 4198 /* 0xA8 - 0xAF */ 4207 4199 I(Stack | Src2GS, em_push_sreg), I(Stack | Src2GS, em_pop_sreg), 4208 - DI(ImplicitOps, rsm), 4200 + II(No64 | EmulateOnUD | ImplicitOps, em_rsm, rsm), 4209 4201 F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_bts), 4210 4202 F(DstMem | SrcReg | Src2ImmByte | ModRM, em_shrd), 4211 4203 F(DstMem | SrcReg | Src2CL | ModRM, em_shrd),
+3 -1
arch/x86/kvm/lapic.c
··· 808 808 break; 809 809 810 810 case APIC_DM_SMI: 811 - apic_debug("Ignoring guest SMI\n"); 811 + result = 1; 812 + kvm_make_request(KVM_REQ_SMI, vcpu); 813 + kvm_vcpu_kick(vcpu); 812 814 break; 813 815 814 816 case APIC_DM_NMI:
+1
arch/x86/kvm/svm.c
··· 3394 3394 [SVM_EXIT_MWAIT] = mwait_interception, 3395 3395 [SVM_EXIT_XSETBV] = xsetbv_interception, 3396 3396 [SVM_EXIT_NPF] = pf_interception, 3397 + [SVM_EXIT_RSM] = emulate_on_interception, 3397 3398 }; 3398 3399 3399 3400 static void dump_vmcb(struct kvm_vcpu *vcpu)
+62 -2
arch/x86/kvm/x86.c
··· 954 954 MSR_IA32_MISC_ENABLE, 955 955 MSR_IA32_MCG_STATUS, 956 956 MSR_IA32_MCG_CTL, 957 + MSR_IA32_SMBASE, 957 958 }; 958 959 959 960 static unsigned num_emulated_msrs; ··· 2283 2282 case MSR_IA32_MISC_ENABLE: 2284 2283 vcpu->arch.ia32_misc_enable_msr = data; 2285 2284 break; 2285 + case MSR_IA32_SMBASE: 2286 + if (!msr_info->host_initiated) 2287 + return 1; 2288 + vcpu->arch.smbase = data; 2289 + break; 2286 2290 case MSR_KVM_WALL_CLOCK_NEW: 2287 2291 case MSR_KVM_WALL_CLOCK: 2288 2292 vcpu->kvm->arch.wall_clock = data; ··· 2684 2678 break; 2685 2679 case MSR_IA32_MISC_ENABLE: 2686 2680 msr_info->data = vcpu->arch.ia32_misc_enable_msr; 2681 + break; 2682 + case MSR_IA32_SMBASE: 2683 + if (!msr_info->host_initiated) 2684 + return 1; 2685 + msr_info->data = vcpu->arch.smbase; 2687 2686 break; 2688 2687 case MSR_IA32_PERF_STATUS: 2689 2688 /* TSC increment by tick */ ··· 3114 3103 3115 3104 static int kvm_vcpu_ioctl_smi(struct kvm_vcpu *vcpu) 3116 3105 { 3106 + kvm_make_request(KVM_REQ_SMI, vcpu); 3107 + 3117 3108 return 0; 3118 3109 } 3119 3110 ··· 5142 5129 return kvm_set_msr(emul_to_vcpu(ctxt), &msr); 5143 5130 } 5144 5131 5132 + static u64 emulator_get_smbase(struct x86_emulate_ctxt *ctxt) 5133 + { 5134 + struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); 5135 + 5136 + return vcpu->arch.smbase; 5137 + } 5138 + 5139 + static void emulator_set_smbase(struct x86_emulate_ctxt *ctxt, u64 smbase) 5140 + { 5141 + struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); 5142 + 5143 + vcpu->arch.smbase = smbase; 5144 + } 5145 + 5145 5146 static int emulator_check_pmc(struct x86_emulate_ctxt *ctxt, 5146 5147 u32 pmc) 5147 5148 { ··· 5241 5214 .cpl = emulator_get_cpl, 5242 5215 .get_dr = emulator_get_dr, 5243 5216 .set_dr = emulator_set_dr, 5217 + .get_smbase = emulator_get_smbase, 5218 + .set_smbase = emulator_set_smbase, 5244 5219 .set_msr = emulator_set_msr, 5245 5220 .get_msr = emulator_get_msr, 5246 5221 .check_pmc = emulator_check_pmc, ··· 5305 5276 cs_db ? X86EMUL_MODE_PROT32 : 5306 5277 X86EMUL_MODE_PROT16; 5307 5278 BUILD_BUG_ON(HF_GUEST_MASK != X86EMUL_GUEST_MASK); 5279 + BUILD_BUG_ON(HF_SMM_MASK != X86EMUL_SMM_MASK); 5280 + BUILD_BUG_ON(HF_SMM_INSIDE_NMI_MASK != X86EMUL_SMM_INSIDE_NMI_MASK); 5308 5281 ctxt->emul_flags = vcpu->arch.hflags; 5309 5282 5310 5283 init_decode_cache(ctxt); ··· 5476 5445 static int complete_emulated_mmio(struct kvm_vcpu *vcpu); 5477 5446 static int complete_emulated_pio(struct kvm_vcpu *vcpu); 5478 5447 5479 - void kvm_set_hflags(struct kvm_vcpu *vcpu, unsigned emul_flags) 5448 + static void kvm_smm_changed(struct kvm_vcpu *vcpu) 5480 5449 { 5450 + if (!(vcpu->arch.hflags & HF_SMM_MASK)) { 5451 + if (unlikely(vcpu->arch.smi_pending)) { 5452 + kvm_make_request(KVM_REQ_SMI, vcpu); 5453 + vcpu->arch.smi_pending = 0; 5454 + } 5455 + } 5456 + } 5457 + 5458 + static void kvm_set_hflags(struct kvm_vcpu *vcpu, unsigned emul_flags) 5459 + { 5460 + unsigned changed = vcpu->arch.hflags ^ emul_flags; 5461 + 5481 5462 vcpu->arch.hflags = emul_flags; 5463 + 5464 + if (changed & HF_SMM_MASK) 5465 + kvm_smm_changed(vcpu); 5482 5466 } 5483 5467 5484 5468 static int kvm_vcpu_check_hw_bp(unsigned long addr, u32 type, u32 dr7, ··· 6387 6341 kvm_make_request(KVM_REQ_EVENT, vcpu); 6388 6342 } 6389 6343 6344 + static void process_smi(struct kvm_vcpu *vcpu) 6345 + { 6346 + if (is_smm(vcpu)) { 6347 + vcpu->arch.smi_pending = true; 6348 + return; 6349 + } 6350 + 6351 + printk_once(KERN_DEBUG "Ignoring guest SMI\n"); 6352 + } 6353 + 6390 6354 static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu) 6391 6355 { 6392 6356 u64 eoi_exit_bitmap[4]; ··· 6505 6449 } 6506 6450 if (kvm_check_request(KVM_REQ_STEAL_UPDATE, vcpu)) 6507 6451 record_steal_time(vcpu); 6452 + if (kvm_check_request(KVM_REQ_SMI, vcpu)) 6453 + process_smi(vcpu); 6508 6454 if (kvm_check_request(KVM_REQ_NMI, vcpu)) 6509 6455 process_nmi(vcpu); 6510 6456 if (kvm_check_request(KVM_REQ_PMU, vcpu)) ··· 7421 7363 kvm_async_pf_hash_reset(vcpu); 7422 7364 vcpu->arch.apf.halted = false; 7423 7365 7424 - if (!init_event) 7366 + if (!init_event) { 7425 7367 kvm_pmu_reset(vcpu); 7368 + vcpu->arch.smbase = 0x30000; 7369 + } 7426 7370 7427 7371 memset(vcpu->arch.regs, 0, sizeof(vcpu->arch.regs)); 7428 7372 vcpu->arch.regs_avail = ~0;
+1
include/linux/kvm_host.h
··· 134 134 #define KVM_REQ_ENABLE_IBS 23 135 135 #define KVM_REQ_DISABLE_IBS 24 136 136 #define KVM_REQ_APIC_PAGE_RELOAD 25 137 + #define KVM_REQ_SMI 26 137 138 138 139 #define KVM_USERSPACE_IRQ_SOURCE_ID 0 139 140 #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1