12f5bb3feSSean Christopherson // SPDX-License-Identifier: GPL-2.0-only 22f5bb3feSSean Christopherson #include <linux/kvm_host.h> 32f5bb3feSSean Christopherson 42f5bb3feSSean Christopherson #include "lapic.h" 52f5bb3feSSean Christopherson #include "mmu.h" 62f5bb3feSSean Christopherson #include "regs.h" 72f5bb3feSSean Christopherson #include "x86.h" 82f5bb3feSSean Christopherson 92f5bb3feSSean Christopherson unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu) 102f5bb3feSSean Christopherson { 112f5bb3feSSean Christopherson /* Can't read the RIP when guest state is protected, just return 0 */ 122f5bb3feSSean Christopherson if (vcpu->arch.guest_state_protected) 132f5bb3feSSean Christopherson return 0; 142f5bb3feSSean Christopherson 152f5bb3feSSean Christopherson if (is_64_bit_mode(vcpu)) 162f5bb3feSSean Christopherson return kvm_rip_read(vcpu); 172f5bb3feSSean Christopherson return (u32)(kvm_get_segment_base(vcpu, VCPU_SREG_CS) + 182f5bb3feSSean Christopherson kvm_rip_read(vcpu)); 192f5bb3feSSean Christopherson } 202f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_linear_rip); 212f5bb3feSSean Christopherson 222f5bb3feSSean Christopherson bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip) 232f5bb3feSSean Christopherson { 242f5bb3feSSean Christopherson return kvm_get_linear_rip(vcpu) == linear_rip; 252f5bb3feSSean Christopherson } 262f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_is_linear_rip); 272f5bb3feSSean Christopherson 282f5bb3feSSean Christopherson unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu) 292f5bb3feSSean Christopherson { 302f5bb3feSSean Christopherson unsigned long rflags; 312f5bb3feSSean Christopherson 322f5bb3feSSean Christopherson rflags = kvm_x86_call(get_rflags)(vcpu); 332f5bb3feSSean Christopherson if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) 342f5bb3feSSean Christopherson rflags &= ~X86_EFLAGS_TF; 352f5bb3feSSean Christopherson return rflags; 362f5bb3feSSean Christopherson } 372f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_rflags); 382f5bb3feSSean Christopherson 392f5bb3feSSean Christopherson void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) 402f5bb3feSSean Christopherson { 412f5bb3feSSean Christopherson if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP && 422f5bb3feSSean Christopherson kvm_is_linear_rip(vcpu, vcpu->arch.singlestep_rip)) 432f5bb3feSSean Christopherson rflags |= X86_EFLAGS_TF; 442f5bb3feSSean Christopherson kvm_x86_call(set_rflags)(vcpu, rflags); 452f5bb3feSSean Christopherson } 462f5bb3feSSean Christopherson 472f5bb3feSSean Christopherson void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) 482f5bb3feSSean Christopherson { 492f5bb3feSSean Christopherson __kvm_set_rflags(vcpu, rflags); 502f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_EVENT, vcpu); 512f5bb3feSSean Christopherson } 522f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_rflags); 532f5bb3feSSean Christopherson 542f5bb3feSSean Christopherson static void __get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 552f5bb3feSSean Christopherson { 562f5bb3feSSean Christopherson if (vcpu->arch.emulate_regs_need_sync_to_vcpu) { 572f5bb3feSSean Christopherson /* 582f5bb3feSSean Christopherson * We are here if userspace calls get_regs() in the middle of 592f5bb3feSSean Christopherson * instruction emulation. Registers state needs to be copied 602f5bb3feSSean Christopherson * back from emulation context to vcpu. Userspace shouldn't do 612f5bb3feSSean Christopherson * that usually, but some bad designed PV devices (vmware 622f5bb3feSSean Christopherson * backdoor interface) need this to work 632f5bb3feSSean Christopherson */ 642f5bb3feSSean Christopherson emulator_writeback_register_cache(vcpu->arch.emulate_ctxt); 652f5bb3feSSean Christopherson vcpu->arch.emulate_regs_need_sync_to_vcpu = false; 662f5bb3feSSean Christopherson } 672f5bb3feSSean Christopherson regs->rax = kvm_rax_read_raw(vcpu); 682f5bb3feSSean Christopherson regs->rbx = kvm_rbx_read_raw(vcpu); 692f5bb3feSSean Christopherson regs->rcx = kvm_rcx_read_raw(vcpu); 702f5bb3feSSean Christopherson regs->rdx = kvm_rdx_read_raw(vcpu); 712f5bb3feSSean Christopherson regs->rsi = kvm_rsi_read_raw(vcpu); 722f5bb3feSSean Christopherson regs->rdi = kvm_rdi_read_raw(vcpu); 732f5bb3feSSean Christopherson regs->rsp = kvm_rsp_read(vcpu); 742f5bb3feSSean Christopherson regs->rbp = kvm_rbp_read_raw(vcpu); 752f5bb3feSSean Christopherson #ifdef CONFIG_X86_64 762f5bb3feSSean Christopherson regs->r8 = kvm_r8_read_raw(vcpu); 772f5bb3feSSean Christopherson regs->r9 = kvm_r9_read_raw(vcpu); 782f5bb3feSSean Christopherson regs->r10 = kvm_r10_read_raw(vcpu); 792f5bb3feSSean Christopherson regs->r11 = kvm_r11_read_raw(vcpu); 802f5bb3feSSean Christopherson regs->r12 = kvm_r12_read_raw(vcpu); 812f5bb3feSSean Christopherson regs->r13 = kvm_r13_read_raw(vcpu); 822f5bb3feSSean Christopherson regs->r14 = kvm_r14_read_raw(vcpu); 832f5bb3feSSean Christopherson regs->r15 = kvm_r15_read_raw(vcpu); 842f5bb3feSSean Christopherson #endif 852f5bb3feSSean Christopherson 862f5bb3feSSean Christopherson regs->rip = kvm_rip_read(vcpu); 872f5bb3feSSean Christopherson regs->rflags = kvm_get_rflags(vcpu); 882f5bb3feSSean Christopherson } 892f5bb3feSSean Christopherson 902f5bb3feSSean Christopherson int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 912f5bb3feSSean Christopherson { 922f5bb3feSSean Christopherson if (vcpu->kvm->arch.has_protected_state && 932f5bb3feSSean Christopherson vcpu->arch.guest_state_protected) 942f5bb3feSSean Christopherson return -EINVAL; 952f5bb3feSSean Christopherson 962f5bb3feSSean Christopherson vcpu_load(vcpu); 972f5bb3feSSean Christopherson __get_regs(vcpu, regs); 982f5bb3feSSean Christopherson vcpu_put(vcpu); 992f5bb3feSSean Christopherson return 0; 1002f5bb3feSSean Christopherson } 1012f5bb3feSSean Christopherson 1022f5bb3feSSean Christopherson static void __set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 1032f5bb3feSSean Christopherson { 1042f5bb3feSSean Christopherson vcpu->arch.emulate_regs_need_sync_from_vcpu = true; 1052f5bb3feSSean Christopherson vcpu->arch.emulate_regs_need_sync_to_vcpu = false; 1062f5bb3feSSean Christopherson 1072f5bb3feSSean Christopherson kvm_rax_write_raw(vcpu, regs->rax); 1082f5bb3feSSean Christopherson kvm_rbx_write_raw(vcpu, regs->rbx); 1092f5bb3feSSean Christopherson kvm_rcx_write_raw(vcpu, regs->rcx); 1102f5bb3feSSean Christopherson kvm_rdx_write_raw(vcpu, regs->rdx); 1112f5bb3feSSean Christopherson kvm_rsi_write_raw(vcpu, regs->rsi); 1122f5bb3feSSean Christopherson kvm_rdi_write_raw(vcpu, regs->rdi); 1132f5bb3feSSean Christopherson kvm_rsp_write(vcpu, regs->rsp); 1142f5bb3feSSean Christopherson kvm_rbp_write_raw(vcpu, regs->rbp); 1152f5bb3feSSean Christopherson #ifdef CONFIG_X86_64 1162f5bb3feSSean Christopherson kvm_r8_write_raw(vcpu, regs->r8); 1172f5bb3feSSean Christopherson kvm_r9_write_raw(vcpu, regs->r9); 1182f5bb3feSSean Christopherson kvm_r10_write_raw(vcpu, regs->r10); 1192f5bb3feSSean Christopherson kvm_r11_write_raw(vcpu, regs->r11); 1202f5bb3feSSean Christopherson kvm_r12_write_raw(vcpu, regs->r12); 1212f5bb3feSSean Christopherson kvm_r13_write_raw(vcpu, regs->r13); 1222f5bb3feSSean Christopherson kvm_r14_write_raw(vcpu, regs->r14); 1232f5bb3feSSean Christopherson kvm_r15_write_raw(vcpu, regs->r15); 1242f5bb3feSSean Christopherson #endif 1252f5bb3feSSean Christopherson 1262f5bb3feSSean Christopherson kvm_rip_write(vcpu, regs->rip); 1272f5bb3feSSean Christopherson kvm_set_rflags(vcpu, regs->rflags | X86_EFLAGS_FIXED); 1282f5bb3feSSean Christopherson 1292f5bb3feSSean Christopherson vcpu->arch.exception.pending = false; 1302f5bb3feSSean Christopherson vcpu->arch.exception_vmexit.pending = false; 1312f5bb3feSSean Christopherson 1322f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_EVENT, vcpu); 1332f5bb3feSSean Christopherson } 1342f5bb3feSSean Christopherson 1352f5bb3feSSean Christopherson int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 1362f5bb3feSSean Christopherson { 1372f5bb3feSSean Christopherson if (vcpu->kvm->arch.has_protected_state && 1382f5bb3feSSean Christopherson vcpu->arch.guest_state_protected) 1392f5bb3feSSean Christopherson return -EINVAL; 1402f5bb3feSSean Christopherson 1412f5bb3feSSean Christopherson vcpu_load(vcpu); 1422f5bb3feSSean Christopherson __set_regs(vcpu, regs); 1432f5bb3feSSean Christopherson vcpu_put(vcpu); 1442f5bb3feSSean Christopherson return 0; 1452f5bb3feSSean Christopherson } 1462f5bb3feSSean Christopherson 1472f5bb3feSSean Christopherson static inline u64 pdptr_rsvd_bits(struct kvm_vcpu *vcpu) 1482f5bb3feSSean Christopherson { 1492f5bb3feSSean Christopherson return vcpu->arch.reserved_gpa_bits | rsvd_bits(5, 8) | rsvd_bits(1, 2); 1502f5bb3feSSean Christopherson } 1512f5bb3feSSean Christopherson 1522f5bb3feSSean Christopherson /* 1532f5bb3feSSean Christopherson * Load the pae pdptrs. Return 1 if they are all valid, 0 otherwise. 1542f5bb3feSSean Christopherson */ 1552f5bb3feSSean Christopherson int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3) 1562f5bb3feSSean Christopherson { 157148fe965SPaolo Bonzini struct kvm_pagewalk *w = &vcpu->arch.gva_walk; 1582f5bb3feSSean Christopherson gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT; 1592f5bb3feSSean Christopherson gpa_t real_gpa; 1602f5bb3feSSean Christopherson int i; 1612f5bb3feSSean Christopherson int ret; 1622f5bb3feSSean Christopherson u64 pdpte[ARRAY_SIZE(vcpu->arch.pdptrs)]; 1632f5bb3feSSean Christopherson 1642f5bb3feSSean Christopherson /* 1652f5bb3feSSean Christopherson * If the MMU is nested, CR3 holds an L2 GPA and needs to be translated 1662f5bb3feSSean Christopherson * to an L1 GPA. 1672f5bb3feSSean Christopherson */ 168d42e93eeSPaolo Bonzini real_gpa = kvm_translate_gpa(vcpu, w, gfn_to_gpa(pdpt_gfn), 1692f5bb3feSSean Christopherson PFERR_USER_MASK | PFERR_WRITE_MASK | 1702f5bb3feSSean Christopherson PFERR_GUEST_PAGE_MASK, NULL, 0); 1712f5bb3feSSean Christopherson if (real_gpa == INVALID_GPA) 1722f5bb3feSSean Christopherson return 0; 1732f5bb3feSSean Christopherson 1742f5bb3feSSean Christopherson /* Note the offset, PDPTRs are 32 byte aligned when using PAE paging. */ 1752f5bb3feSSean Christopherson ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(real_gpa), pdpte, 1762f5bb3feSSean Christopherson cr3 & GENMASK(11, 5), sizeof(pdpte)); 1772f5bb3feSSean Christopherson if (ret < 0) 1782f5bb3feSSean Christopherson return 0; 1792f5bb3feSSean Christopherson 1802f5bb3feSSean Christopherson for (i = 0; i < ARRAY_SIZE(pdpte); ++i) { 1812f5bb3feSSean Christopherson if ((pdpte[i] & PT_PRESENT_MASK) && 1822f5bb3feSSean Christopherson (pdpte[i] & pdptr_rsvd_bits(vcpu))) { 1832f5bb3feSSean Christopherson return 0; 1842f5bb3feSSean Christopherson } 1852f5bb3feSSean Christopherson } 1862f5bb3feSSean Christopherson 1872f5bb3feSSean Christopherson /* 1882f5bb3feSSean Christopherson * Marking VCPU_REG_PDPTR dirty doesn't work for !tdp_enabled. 1892f5bb3feSSean Christopherson * Shadow page roots need to be reconstructed instead. 1902f5bb3feSSean Christopherson */ 1912f5bb3feSSean Christopherson if (!tdp_enabled && memcmp(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs))) 192d42e93eeSPaolo Bonzini kvm_mmu_free_roots(vcpu->kvm, &vcpu->arch.root_mmu, 193d42e93eeSPaolo Bonzini KVM_MMU_ROOT_CURRENT); 1942f5bb3feSSean Christopherson 1952f5bb3feSSean Christopherson memcpy(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs)); 1962f5bb3feSSean Christopherson kvm_register_mark_dirty(vcpu, VCPU_REG_PDPTR); 1972f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu); 1982f5bb3feSSean Christopherson vcpu->arch.pdptrs_from_userspace = false; 1992f5bb3feSSean Christopherson 2002f5bb3feSSean Christopherson return 1; 2012f5bb3feSSean Christopherson } 2022f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(load_pdptrs); 2032f5bb3feSSean Christopherson 2042f5bb3feSSean Christopherson static bool kvm_is_valid_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) 2052f5bb3feSSean Christopherson { 2062f5bb3feSSean Christopherson #ifdef CONFIG_X86_64 2072f5bb3feSSean Christopherson if (cr0 & 0xffffffff00000000UL) 2082f5bb3feSSean Christopherson return false; 2092f5bb3feSSean Christopherson #endif 2102f5bb3feSSean Christopherson 2112f5bb3feSSean Christopherson if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) 2122f5bb3feSSean Christopherson return false; 2132f5bb3feSSean Christopherson 2142f5bb3feSSean Christopherson if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) 2152f5bb3feSSean Christopherson return false; 2162f5bb3feSSean Christopherson 2172f5bb3feSSean Christopherson return kvm_x86_call(is_valid_cr0)(vcpu, cr0); 2182f5bb3feSSean Christopherson } 2192f5bb3feSSean Christopherson 2202f5bb3feSSean Christopherson void kvm_post_set_cr0(struct kvm_vcpu *vcpu, unsigned long old_cr0, unsigned long cr0) 2212f5bb3feSSean Christopherson { 2222f5bb3feSSean Christopherson /* 2232f5bb3feSSean Christopherson * CR0.WP is incorporated into the MMU role, but only for non-nested, 2242f5bb3feSSean Christopherson * indirect shadow MMUs. If paging is disabled, no updates are needed 2252f5bb3feSSean Christopherson * as there are no permission bits to emulate. If TDP is enabled, the 2262f5bb3feSSean Christopherson * MMU's metadata needs to be updated, e.g. so that emulating guest 2272f5bb3feSSean Christopherson * translations does the right thing, but there's no need to unload the 2282f5bb3feSSean Christopherson * root as CR0.WP doesn't affect SPTEs. 2292f5bb3feSSean Christopherson */ 2302f5bb3feSSean Christopherson if ((cr0 ^ old_cr0) == X86_CR0_WP) { 2312f5bb3feSSean Christopherson if (!(cr0 & X86_CR0_PG)) 2322f5bb3feSSean Christopherson return; 2332f5bb3feSSean Christopherson 2342f5bb3feSSean Christopherson if (tdp_enabled) { 2352f5bb3feSSean Christopherson kvm_init_mmu(vcpu); 2362f5bb3feSSean Christopherson return; 2372f5bb3feSSean Christopherson } 2382f5bb3feSSean Christopherson } 2392f5bb3feSSean Christopherson 2402f5bb3feSSean Christopherson if ((cr0 ^ old_cr0) & X86_CR0_PG) { 2412f5bb3feSSean Christopherson /* 2422f5bb3feSSean Christopherson * Clearing CR0.PG is defined to flush the TLB from the guest's 2432f5bb3feSSean Christopherson * perspective. 2442f5bb3feSSean Christopherson */ 2452f5bb3feSSean Christopherson if (!(cr0 & X86_CR0_PG)) 2462f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); 2472f5bb3feSSean Christopherson /* 2482f5bb3feSSean Christopherson * Check for async #PF completion events when enabling paging, 2492f5bb3feSSean Christopherson * as the vCPU may have previously encountered async #PFs (it's 2502f5bb3feSSean Christopherson * entirely legal for the guest to toggle paging on/off without 2512f5bb3feSSean Christopherson * waiting for the async #PF queue to drain). 2522f5bb3feSSean Christopherson */ 2532f5bb3feSSean Christopherson else if (kvm_pv_async_pf_enabled(vcpu)) 2542f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_APF_READY, vcpu); 2552f5bb3feSSean Christopherson } 2562f5bb3feSSean Christopherson 2572f5bb3feSSean Christopherson if ((cr0 ^ old_cr0) & KVM_MMU_CR0_ROLE_BITS) 2582f5bb3feSSean Christopherson kvm_mmu_reset_context(vcpu); 2592f5bb3feSSean Christopherson } 2602f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_post_set_cr0); 2612f5bb3feSSean Christopherson 2622f5bb3feSSean Christopherson int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) 2632f5bb3feSSean Christopherson { 2642f5bb3feSSean Christopherson unsigned long old_cr0 = kvm_read_cr0(vcpu); 2652f5bb3feSSean Christopherson 2662f5bb3feSSean Christopherson if (!kvm_is_valid_cr0(vcpu, cr0)) 2672f5bb3feSSean Christopherson return 1; 2682f5bb3feSSean Christopherson 2692f5bb3feSSean Christopherson cr0 |= X86_CR0_ET; 2702f5bb3feSSean Christopherson 2712f5bb3feSSean Christopherson /* Write to CR0 reserved bits are ignored, even on Intel. */ 2722f5bb3feSSean Christopherson cr0 &= ~CR0_RESERVED_BITS; 2732f5bb3feSSean Christopherson 2742f5bb3feSSean Christopherson #ifdef CONFIG_X86_64 2752f5bb3feSSean Christopherson if ((vcpu->arch.efer & EFER_LME) && !is_paging(vcpu) && 2762f5bb3feSSean Christopherson (cr0 & X86_CR0_PG)) { 2772f5bb3feSSean Christopherson int cs_db, cs_l; 2782f5bb3feSSean Christopherson 2792f5bb3feSSean Christopherson if (!is_pae(vcpu)) 2802f5bb3feSSean Christopherson return 1; 2812f5bb3feSSean Christopherson kvm_x86_call(get_cs_db_l_bits)(vcpu, &cs_db, &cs_l); 2822f5bb3feSSean Christopherson if (cs_l) 2832f5bb3feSSean Christopherson return 1; 2842f5bb3feSSean Christopherson } 2852f5bb3feSSean Christopherson #endif 2862f5bb3feSSean Christopherson if (!(vcpu->arch.efer & EFER_LME) && (cr0 & X86_CR0_PG) && 2872f5bb3feSSean Christopherson is_pae(vcpu) && ((cr0 ^ old_cr0) & X86_CR0_PDPTR_BITS) && 2882f5bb3feSSean Christopherson !load_pdptrs(vcpu, kvm_read_cr3(vcpu))) 2892f5bb3feSSean Christopherson return 1; 2902f5bb3feSSean Christopherson 2912f5bb3feSSean Christopherson if (!(cr0 & X86_CR0_PG) && 2922f5bb3feSSean Christopherson (is_64_bit_mode(vcpu) || kvm_is_cr4_bit_set(vcpu, X86_CR4_PCIDE))) 2932f5bb3feSSean Christopherson return 1; 2942f5bb3feSSean Christopherson 2952f5bb3feSSean Christopherson if (!(cr0 & X86_CR0_WP) && kvm_is_cr4_bit_set(vcpu, X86_CR4_CET)) 2962f5bb3feSSean Christopherson return 1; 2972f5bb3feSSean Christopherson 2982f5bb3feSSean Christopherson kvm_x86_call(set_cr0)(vcpu, cr0); 2992f5bb3feSSean Christopherson 3002f5bb3feSSean Christopherson kvm_post_set_cr0(vcpu, old_cr0, cr0); 3012f5bb3feSSean Christopherson 3022f5bb3feSSean Christopherson return 0; 3032f5bb3feSSean Christopherson } 3042f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr0); 3052f5bb3feSSean Christopherson 3062f5bb3feSSean Christopherson void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw) 3072f5bb3feSSean Christopherson { 3082f5bb3feSSean Christopherson (void)kvm_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~0x0eul) | (msw & 0x0f)); 3092f5bb3feSSean Christopherson } 3102f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_lmsw); 3112f5bb3feSSean Christopherson 3122f5bb3feSSean Christopherson int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) 3132f5bb3feSSean Christopherson { 3142f5bb3feSSean Christopherson bool skip_tlb_flush = false; 3152f5bb3feSSean Christopherson unsigned long pcid = 0; 3162f5bb3feSSean Christopherson #ifdef CONFIG_X86_64 3172f5bb3feSSean Christopherson if (kvm_is_cr4_bit_set(vcpu, X86_CR4_PCIDE)) { 3182f5bb3feSSean Christopherson skip_tlb_flush = cr3 & X86_CR3_PCID_NOFLUSH; 3192f5bb3feSSean Christopherson cr3 &= ~X86_CR3_PCID_NOFLUSH; 3202f5bb3feSSean Christopherson pcid = cr3 & X86_CR3_PCID_MASK; 3212f5bb3feSSean Christopherson } 3222f5bb3feSSean Christopherson #endif 3232f5bb3feSSean Christopherson 3242f5bb3feSSean Christopherson /* PDPTRs are always reloaded for PAE paging. */ 3252f5bb3feSSean Christopherson if (cr3 == kvm_read_cr3(vcpu) && !is_pae_paging(vcpu)) 3262f5bb3feSSean Christopherson goto handle_tlb_flush; 3272f5bb3feSSean Christopherson 3282f5bb3feSSean Christopherson /* 3292f5bb3feSSean Christopherson * Do not condition the GPA check on long mode, this helper is used to 3302f5bb3feSSean Christopherson * stuff CR3, e.g. for RSM emulation, and there is no guarantee that 3312f5bb3feSSean Christopherson * the current vCPU mode is accurate. 3322f5bb3feSSean Christopherson */ 3332f5bb3feSSean Christopherson if (!kvm_vcpu_is_legal_cr3(vcpu, cr3)) 3342f5bb3feSSean Christopherson return 1; 3352f5bb3feSSean Christopherson 3362f5bb3feSSean Christopherson if (is_pae_paging(vcpu) && !load_pdptrs(vcpu, cr3)) 3372f5bb3feSSean Christopherson return 1; 3382f5bb3feSSean Christopherson 3392f5bb3feSSean Christopherson if (cr3 != kvm_read_cr3(vcpu)) 3402f5bb3feSSean Christopherson kvm_mmu_new_pgd(vcpu, cr3); 3412f5bb3feSSean Christopherson 3422f5bb3feSSean Christopherson vcpu->arch.cr3 = cr3; 3432f5bb3feSSean Christopherson kvm_register_mark_dirty(vcpu, VCPU_REG_CR3); 3442f5bb3feSSean Christopherson /* Do not call post_set_cr3, we do not get here for confidential guests. */ 3452f5bb3feSSean Christopherson 3462f5bb3feSSean Christopherson handle_tlb_flush: 3472f5bb3feSSean Christopherson /* 3482f5bb3feSSean Christopherson * A load of CR3 that flushes the TLB flushes only the current PCID, 3492f5bb3feSSean Christopherson * even if PCID is disabled, in which case PCID=0 is flushed. It's a 3502f5bb3feSSean Christopherson * moot point in the end because _disabling_ PCID will flush all PCIDs, 3512f5bb3feSSean Christopherson * and it's impossible to use a non-zero PCID when PCID is disabled, 3522f5bb3feSSean Christopherson * i.e. only PCID=0 can be relevant. 3532f5bb3feSSean Christopherson */ 3542f5bb3feSSean Christopherson if (!skip_tlb_flush) 3552f5bb3feSSean Christopherson kvm_invalidate_pcid(vcpu, pcid); 3562f5bb3feSSean Christopherson 3572f5bb3feSSean Christopherson return 0; 3582f5bb3feSSean Christopherson } 3592f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr3); 3602f5bb3feSSean Christopherson 3612f5bb3feSSean Christopherson static bool kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) 3622f5bb3feSSean Christopherson { 3632f5bb3feSSean Christopherson return __kvm_is_valid_cr4(vcpu, cr4) && 3642f5bb3feSSean Christopherson kvm_x86_call(is_valid_cr4)(vcpu, cr4); 3652f5bb3feSSean Christopherson } 3662f5bb3feSSean Christopherson 3672f5bb3feSSean Christopherson void kvm_post_set_cr4(struct kvm_vcpu *vcpu, unsigned long old_cr4, unsigned long cr4) 3682f5bb3feSSean Christopherson { 3692f5bb3feSSean Christopherson if ((cr4 ^ old_cr4) & KVM_MMU_CR4_ROLE_BITS) 3702f5bb3feSSean Christopherson kvm_mmu_reset_context(vcpu); 3712f5bb3feSSean Christopherson 3722f5bb3feSSean Christopherson /* 3732f5bb3feSSean Christopherson * If CR4.PCIDE is changed 0 -> 1, there is no need to flush the TLB 3742f5bb3feSSean Christopherson * according to the SDM; however, stale prev_roots could be reused 3752f5bb3feSSean Christopherson * incorrectly in the future after a MOV to CR3 with NOFLUSH=1, so we 3762f5bb3feSSean Christopherson * free them all. This is *not* a superset of KVM_REQ_TLB_FLUSH_GUEST 3772f5bb3feSSean Christopherson * or KVM_REQ_TLB_FLUSH_CURRENT, because the hardware TLB is not flushed, 3782f5bb3feSSean Christopherson * so fall through. 3792f5bb3feSSean Christopherson */ 3802f5bb3feSSean Christopherson if (!tdp_enabled && 3812f5bb3feSSean Christopherson (cr4 & X86_CR4_PCIDE) && !(old_cr4 & X86_CR4_PCIDE)) 3822f5bb3feSSean Christopherson kvm_mmu_unload(vcpu); 3832f5bb3feSSean Christopherson 3842f5bb3feSSean Christopherson /* 3852f5bb3feSSean Christopherson * The TLB has to be flushed for all PCIDs if any of the following 3862f5bb3feSSean Christopherson * (architecturally required) changes happen: 3872f5bb3feSSean Christopherson * - CR4.PCIDE is changed from 1 to 0 3882f5bb3feSSean Christopherson * - CR4.PGE is toggled 3892f5bb3feSSean Christopherson * 3902f5bb3feSSean Christopherson * This is a superset of KVM_REQ_TLB_FLUSH_CURRENT. 3912f5bb3feSSean Christopherson */ 3922f5bb3feSSean Christopherson if (((cr4 ^ old_cr4) & X86_CR4_PGE) || 3932f5bb3feSSean Christopherson (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE))) 3942f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); 3952f5bb3feSSean Christopherson 3962f5bb3feSSean Christopherson /* 3972f5bb3feSSean Christopherson * The TLB has to be flushed for the current PCID if any of the 3982f5bb3feSSean Christopherson * following (architecturally required) changes happen: 3992f5bb3feSSean Christopherson * - CR4.SMEP is changed from 0 to 1 4002f5bb3feSSean Christopherson * - CR4.PAE is toggled 4012f5bb3feSSean Christopherson */ 4022f5bb3feSSean Christopherson else if (((cr4 ^ old_cr4) & X86_CR4_PAE) || 4032f5bb3feSSean Christopherson ((cr4 & X86_CR4_SMEP) && !(old_cr4 & X86_CR4_SMEP))) 4042f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); 4052f5bb3feSSean Christopherson 4062f5bb3feSSean Christopherson } 4072f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_post_set_cr4); 4082f5bb3feSSean Christopherson 4092f5bb3feSSean Christopherson int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) 4102f5bb3feSSean Christopherson { 4112f5bb3feSSean Christopherson unsigned long old_cr4 = kvm_read_cr4(vcpu); 4122f5bb3feSSean Christopherson 4132f5bb3feSSean Christopherson if (!kvm_is_valid_cr4(vcpu, cr4)) 4142f5bb3feSSean Christopherson return 1; 4152f5bb3feSSean Christopherson 4162f5bb3feSSean Christopherson if (is_long_mode(vcpu)) { 4172f5bb3feSSean Christopherson if (!(cr4 & X86_CR4_PAE)) 4182f5bb3feSSean Christopherson return 1; 4192f5bb3feSSean Christopherson if ((cr4 ^ old_cr4) & X86_CR4_LA57) 4202f5bb3feSSean Christopherson return 1; 4212f5bb3feSSean Christopherson } else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE) 4222f5bb3feSSean Christopherson && ((cr4 ^ old_cr4) & X86_CR4_PDPTR_BITS) 4232f5bb3feSSean Christopherson && !load_pdptrs(vcpu, kvm_read_cr3(vcpu))) 4242f5bb3feSSean Christopherson return 1; 4252f5bb3feSSean Christopherson 4262f5bb3feSSean Christopherson if ((cr4 & X86_CR4_PCIDE) && !(old_cr4 & X86_CR4_PCIDE)) { 4272f5bb3feSSean Christopherson /* PCID can not be enabled when cr3[11:0]!=000H or EFER.LMA=0 */ 4282f5bb3feSSean Christopherson if ((kvm_read_cr3(vcpu) & X86_CR3_PCID_MASK) || !is_long_mode(vcpu)) 4292f5bb3feSSean Christopherson return 1; 4302f5bb3feSSean Christopherson } 4312f5bb3feSSean Christopherson 4322f5bb3feSSean Christopherson if ((cr4 & X86_CR4_CET) && !kvm_is_cr0_bit_set(vcpu, X86_CR0_WP)) 4332f5bb3feSSean Christopherson return 1; 4342f5bb3feSSean Christopherson 4352f5bb3feSSean Christopherson kvm_x86_call(set_cr4)(vcpu, cr4); 4362f5bb3feSSean Christopherson 4372f5bb3feSSean Christopherson kvm_post_set_cr4(vcpu, old_cr4, cr4); 4382f5bb3feSSean Christopherson 4392f5bb3feSSean Christopherson return 0; 4402f5bb3feSSean Christopherson } 4412f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr4); 4422f5bb3feSSean Christopherson 4432f5bb3feSSean Christopherson int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) 4442f5bb3feSSean Christopherson { 4452f5bb3feSSean Christopherson if (cr8 & CR8_RESERVED_BITS) 4462f5bb3feSSean Christopherson return 1; 4472f5bb3feSSean Christopherson if (lapic_in_kernel(vcpu)) 4482f5bb3feSSean Christopherson kvm_lapic_set_tpr(vcpu, cr8); 4492f5bb3feSSean Christopherson else 4502f5bb3feSSean Christopherson vcpu->arch.cr8 = cr8; 4512f5bb3feSSean Christopherson return 0; 4522f5bb3feSSean Christopherson } 4532f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr8); 4542f5bb3feSSean Christopherson 4552f5bb3feSSean Christopherson unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu) 4562f5bb3feSSean Christopherson { 4572f5bb3feSSean Christopherson if (lapic_in_kernel(vcpu)) 4582f5bb3feSSean Christopherson return kvm_lapic_get_cr8(vcpu); 4592f5bb3feSSean Christopherson else 4602f5bb3feSSean Christopherson return vcpu->arch.cr8; 4612f5bb3feSSean Christopherson } 4622f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_cr8); 4632f5bb3feSSean Christopherson 4642f5bb3feSSean Christopherson static void __get_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) 4652f5bb3feSSean Christopherson { 4662f5bb3feSSean Christopherson struct desc_ptr dt; 4672f5bb3feSSean Christopherson 4682f5bb3feSSean Christopherson if (vcpu->arch.guest_state_protected) 4692f5bb3feSSean Christopherson goto skip_protected_regs; 4702f5bb3feSSean Christopherson 4712f5bb3feSSean Christopherson kvm_handle_exception_payload_quirk(vcpu); 4722f5bb3feSSean Christopherson 4732f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->cs, VCPU_SREG_CS); 4742f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->ds, VCPU_SREG_DS); 4752f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->es, VCPU_SREG_ES); 4762f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->fs, VCPU_SREG_FS); 4772f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->gs, VCPU_SREG_GS); 4782f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->ss, VCPU_SREG_SS); 4792f5bb3feSSean Christopherson 4802f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->tr, VCPU_SREG_TR); 4812f5bb3feSSean Christopherson kvm_get_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); 4822f5bb3feSSean Christopherson 4832f5bb3feSSean Christopherson kvm_x86_call(get_idt)(vcpu, &dt); 4842f5bb3feSSean Christopherson sregs->idt.limit = dt.size; 4852f5bb3feSSean Christopherson sregs->idt.base = dt.address; 4862f5bb3feSSean Christopherson kvm_x86_call(get_gdt)(vcpu, &dt); 4872f5bb3feSSean Christopherson sregs->gdt.limit = dt.size; 4882f5bb3feSSean Christopherson sregs->gdt.base = dt.address; 4892f5bb3feSSean Christopherson 4902f5bb3feSSean Christopherson sregs->cr2 = vcpu->arch.cr2; 4912f5bb3feSSean Christopherson sregs->cr3 = kvm_read_cr3(vcpu); 4922f5bb3feSSean Christopherson 4932f5bb3feSSean Christopherson skip_protected_regs: 4942f5bb3feSSean Christopherson sregs->cr0 = kvm_read_cr0(vcpu); 4952f5bb3feSSean Christopherson sregs->cr4 = kvm_read_cr4(vcpu); 4962f5bb3feSSean Christopherson sregs->cr8 = kvm_get_cr8(vcpu); 4972f5bb3feSSean Christopherson sregs->efer = vcpu->arch.efer; 4982f5bb3feSSean Christopherson sregs->apic_base = vcpu->arch.apic_base; 4992f5bb3feSSean Christopherson } 5002f5bb3feSSean Christopherson 5012f5bb3feSSean Christopherson static void __get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) 5022f5bb3feSSean Christopherson { 5032f5bb3feSSean Christopherson __get_sregs_common(vcpu, sregs); 5042f5bb3feSSean Christopherson 5052f5bb3feSSean Christopherson if (vcpu->arch.guest_state_protected) 5062f5bb3feSSean Christopherson return; 5072f5bb3feSSean Christopherson 5082f5bb3feSSean Christopherson if (vcpu->arch.interrupt.injected && !vcpu->arch.interrupt.soft) 5092f5bb3feSSean Christopherson set_bit(vcpu->arch.interrupt.nr, 5102f5bb3feSSean Christopherson (unsigned long *)sregs->interrupt_bitmap); 5112f5bb3feSSean Christopherson } 5122f5bb3feSSean Christopherson 5132f5bb3feSSean Christopherson int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, 5142f5bb3feSSean Christopherson struct kvm_sregs *sregs) 5152f5bb3feSSean Christopherson { 5162f5bb3feSSean Christopherson if (vcpu->kvm->arch.has_protected_state && 5172f5bb3feSSean Christopherson vcpu->arch.guest_state_protected) 5182f5bb3feSSean Christopherson return -EINVAL; 5192f5bb3feSSean Christopherson 5202f5bb3feSSean Christopherson vcpu_load(vcpu); 5212f5bb3feSSean Christopherson __get_sregs(vcpu, sregs); 5222f5bb3feSSean Christopherson vcpu_put(vcpu); 5232f5bb3feSSean Christopherson return 0; 5242f5bb3feSSean Christopherson } 5252f5bb3feSSean Christopherson 5262f5bb3feSSean Christopherson void kvm_vcpu_ioctl_x86_get_sregs2(struct kvm_vcpu *vcpu, 5272f5bb3feSSean Christopherson struct kvm_sregs2 *sregs2) 5282f5bb3feSSean Christopherson { 5292f5bb3feSSean Christopherson int i; 5302f5bb3feSSean Christopherson 5312f5bb3feSSean Christopherson __get_sregs_common(vcpu, (struct kvm_sregs *)sregs2); 5322f5bb3feSSean Christopherson 5332f5bb3feSSean Christopherson if (vcpu->arch.guest_state_protected) 5342f5bb3feSSean Christopherson return; 5352f5bb3feSSean Christopherson 5362f5bb3feSSean Christopherson if (is_pae_paging(vcpu)) { 5372f5bb3feSSean Christopherson kvm_vcpu_srcu_read_lock(vcpu); 5382f5bb3feSSean Christopherson for (i = 0 ; i < 4 ; i++) 5392f5bb3feSSean Christopherson sregs2->pdptrs[i] = kvm_pdptr_read(vcpu, i); 5402f5bb3feSSean Christopherson sregs2->flags |= KVM_SREGS2_FLAGS_PDPTRS_VALID; 5412f5bb3feSSean Christopherson kvm_vcpu_srcu_read_unlock(vcpu); 5422f5bb3feSSean Christopherson } 5432f5bb3feSSean Christopherson } 5442f5bb3feSSean Christopherson 5452f5bb3feSSean Christopherson static bool kvm_is_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) 5462f5bb3feSSean Christopherson { 5472f5bb3feSSean Christopherson if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG)) { 5482f5bb3feSSean Christopherson /* 5492f5bb3feSSean Christopherson * When EFER.LME and CR0.PG are set, the processor is in 5502f5bb3feSSean Christopherson * 64-bit mode (though maybe in a 32-bit code segment). 5512f5bb3feSSean Christopherson * CR4.PAE and EFER.LMA must be set. 5522f5bb3feSSean Christopherson */ 5532f5bb3feSSean Christopherson if (!(sregs->cr4 & X86_CR4_PAE) || !(sregs->efer & EFER_LMA)) 5542f5bb3feSSean Christopherson return false; 5552f5bb3feSSean Christopherson if (!kvm_vcpu_is_legal_cr3(vcpu, sregs->cr3)) 5562f5bb3feSSean Christopherson return false; 5572f5bb3feSSean Christopherson } else { 5582f5bb3feSSean Christopherson /* 5592f5bb3feSSean Christopherson * Not in 64-bit mode: EFER.LMA is clear and the code 5602f5bb3feSSean Christopherson * segment cannot be 64-bit. 5612f5bb3feSSean Christopherson */ 5622f5bb3feSSean Christopherson if (sregs->efer & EFER_LMA || sregs->cs.l) 5632f5bb3feSSean Christopherson return false; 5642f5bb3feSSean Christopherson } 5652f5bb3feSSean Christopherson 5662f5bb3feSSean Christopherson return kvm_is_valid_cr4(vcpu, sregs->cr4) && 567*184bd464SYosry Ahmed kvm_is_valid_cr0(vcpu, sregs->cr0) && 568*184bd464SYosry Ahmed kvm_valid_efer(vcpu, sregs->efer); 5692f5bb3feSSean Christopherson } 5702f5bb3feSSean Christopherson 5712f5bb3feSSean Christopherson static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs, 5722f5bb3feSSean Christopherson int *mmu_reset_needed, bool update_pdptrs) 5732f5bb3feSSean Christopherson { 5742f5bb3feSSean Christopherson int idx; 5752f5bb3feSSean Christopherson struct desc_ptr dt; 5762f5bb3feSSean Christopherson 5772f5bb3feSSean Christopherson if (!kvm_is_valid_sregs(vcpu, sregs)) 5782f5bb3feSSean Christopherson return -EINVAL; 5792f5bb3feSSean Christopherson 5802f5bb3feSSean Christopherson if (kvm_apic_set_base(vcpu, sregs->apic_base, true)) 5812f5bb3feSSean Christopherson return -EINVAL; 5822f5bb3feSSean Christopherson 5832f5bb3feSSean Christopherson if (vcpu->arch.guest_state_protected) 5842f5bb3feSSean Christopherson return 0; 5852f5bb3feSSean Christopherson 5862f5bb3feSSean Christopherson dt.size = sregs->idt.limit; 5872f5bb3feSSean Christopherson dt.address = sregs->idt.base; 5882f5bb3feSSean Christopherson kvm_x86_call(set_idt)(vcpu, &dt); 5892f5bb3feSSean Christopherson dt.size = sregs->gdt.limit; 5902f5bb3feSSean Christopherson dt.address = sregs->gdt.base; 5912f5bb3feSSean Christopherson kvm_x86_call(set_gdt)(vcpu, &dt); 5922f5bb3feSSean Christopherson 5932f5bb3feSSean Christopherson vcpu->arch.cr2 = sregs->cr2; 5942f5bb3feSSean Christopherson *mmu_reset_needed |= kvm_read_cr3(vcpu) != sregs->cr3; 5952f5bb3feSSean Christopherson vcpu->arch.cr3 = sregs->cr3; 5962f5bb3feSSean Christopherson kvm_register_mark_dirty(vcpu, VCPU_REG_CR3); 5972f5bb3feSSean Christopherson kvm_x86_call(post_set_cr3)(vcpu, sregs->cr3); 5982f5bb3feSSean Christopherson 5992f5bb3feSSean Christopherson *mmu_reset_needed |= vcpu->arch.efer != sregs->efer; 6002f5bb3feSSean Christopherson kvm_x86_call(set_efer)(vcpu, sregs->efer); 6012f5bb3feSSean Christopherson 6022f5bb3feSSean Christopherson *mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0; 6032f5bb3feSSean Christopherson kvm_x86_call(set_cr0)(vcpu, sregs->cr0); 6042f5bb3feSSean Christopherson 6052f5bb3feSSean Christopherson *mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; 6062f5bb3feSSean Christopherson kvm_x86_call(set_cr4)(vcpu, sregs->cr4); 6072f5bb3feSSean Christopherson 6082f5bb3feSSean Christopherson if (update_pdptrs) { 6092f5bb3feSSean Christopherson idx = srcu_read_lock(&vcpu->kvm->srcu); 6102f5bb3feSSean Christopherson if (is_pae_paging(vcpu)) { 6112f5bb3feSSean Christopherson load_pdptrs(vcpu, kvm_read_cr3(vcpu)); 6122f5bb3feSSean Christopherson *mmu_reset_needed = 1; 6132f5bb3feSSean Christopherson } 6142f5bb3feSSean Christopherson srcu_read_unlock(&vcpu->kvm->srcu, idx); 6152f5bb3feSSean Christopherson } 6162f5bb3feSSean Christopherson 6172f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS); 6182f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->ds, VCPU_SREG_DS); 6192f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->es, VCPU_SREG_ES); 6202f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->fs, VCPU_SREG_FS); 6212f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->gs, VCPU_SREG_GS); 6222f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->ss, VCPU_SREG_SS); 6232f5bb3feSSean Christopherson 6242f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->tr, VCPU_SREG_TR); 6252f5bb3feSSean Christopherson kvm_set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); 6262f5bb3feSSean Christopherson 6272f5bb3feSSean Christopherson kvm_set_cr8(vcpu, sregs->cr8); 6282f5bb3feSSean Christopherson 6292f5bb3feSSean Christopherson /* Older userspace won't unhalt the vcpu on reset. */ 6302f5bb3feSSean Christopherson if (kvm_vcpu_is_bsp(vcpu) && kvm_rip_read(vcpu) == 0xfff0 && 6312f5bb3feSSean Christopherson sregs->cs.selector == 0xf000 && sregs->cs.base == 0xffff0000 && 6322f5bb3feSSean Christopherson !is_protmode(vcpu)) 6332f5bb3feSSean Christopherson kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); 6342f5bb3feSSean Christopherson 6352f5bb3feSSean Christopherson return 0; 6362f5bb3feSSean Christopherson } 6372f5bb3feSSean Christopherson 6382f5bb3feSSean Christopherson static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) 6392f5bb3feSSean Christopherson { 6402f5bb3feSSean Christopherson int pending_vec, max_bits; 6412f5bb3feSSean Christopherson int mmu_reset_needed = 0; 6422f5bb3feSSean Christopherson int ret = __set_sregs_common(vcpu, sregs, &mmu_reset_needed, true); 6432f5bb3feSSean Christopherson 6442f5bb3feSSean Christopherson if (ret) 6452f5bb3feSSean Christopherson return ret; 6462f5bb3feSSean Christopherson 6472f5bb3feSSean Christopherson if (mmu_reset_needed) { 6482f5bb3feSSean Christopherson kvm_mmu_reset_context(vcpu); 6492f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); 6502f5bb3feSSean Christopherson } 6512f5bb3feSSean Christopherson 6522f5bb3feSSean Christopherson max_bits = KVM_NR_INTERRUPTS; 6532f5bb3feSSean Christopherson pending_vec = find_first_bit( 6542f5bb3feSSean Christopherson (const unsigned long *)sregs->interrupt_bitmap, max_bits); 6552f5bb3feSSean Christopherson 6562f5bb3feSSean Christopherson if (pending_vec < max_bits) { 6572f5bb3feSSean Christopherson kvm_queue_interrupt(vcpu, pending_vec, false); 6582f5bb3feSSean Christopherson pr_debug("Set back pending irq %d\n", pending_vec); 6592f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_EVENT, vcpu); 6602f5bb3feSSean Christopherson } 6612f5bb3feSSean Christopherson return 0; 6622f5bb3feSSean Christopherson } 6632f5bb3feSSean Christopherson 6642f5bb3feSSean Christopherson int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, 6652f5bb3feSSean Christopherson struct kvm_sregs *sregs) 6662f5bb3feSSean Christopherson { 6672f5bb3feSSean Christopherson int ret; 6682f5bb3feSSean Christopherson 6692f5bb3feSSean Christopherson if (vcpu->kvm->arch.has_protected_state && 6702f5bb3feSSean Christopherson vcpu->arch.guest_state_protected) 6712f5bb3feSSean Christopherson return -EINVAL; 6722f5bb3feSSean Christopherson 6732f5bb3feSSean Christopherson vcpu_load(vcpu); 6742f5bb3feSSean Christopherson ret = __set_sregs(vcpu, sregs); 6752f5bb3feSSean Christopherson vcpu_put(vcpu); 6762f5bb3feSSean Christopherson return ret; 6772f5bb3feSSean Christopherson } 6782f5bb3feSSean Christopherson 6792f5bb3feSSean Christopherson int kvm_vcpu_ioctl_x86_set_sregs2(struct kvm_vcpu *vcpu, 6802f5bb3feSSean Christopherson struct kvm_sregs2 *sregs2) 6812f5bb3feSSean Christopherson { 6822f5bb3feSSean Christopherson int mmu_reset_needed = 0; 6832f5bb3feSSean Christopherson bool valid_pdptrs = sregs2->flags & KVM_SREGS2_FLAGS_PDPTRS_VALID; 6842f5bb3feSSean Christopherson bool pae = (sregs2->cr0 & X86_CR0_PG) && (sregs2->cr4 & X86_CR4_PAE) && 6852f5bb3feSSean Christopherson !(sregs2->efer & EFER_LMA); 6862f5bb3feSSean Christopherson int i, ret; 6872f5bb3feSSean Christopherson 6882f5bb3feSSean Christopherson if (sregs2->flags & ~KVM_SREGS2_FLAGS_PDPTRS_VALID) 6892f5bb3feSSean Christopherson return -EINVAL; 6902f5bb3feSSean Christopherson 6912f5bb3feSSean Christopherson if (valid_pdptrs && (!pae || vcpu->arch.guest_state_protected)) 6922f5bb3feSSean Christopherson return -EINVAL; 6932f5bb3feSSean Christopherson 6942f5bb3feSSean Christopherson ret = __set_sregs_common(vcpu, (struct kvm_sregs *)sregs2, 6952f5bb3feSSean Christopherson &mmu_reset_needed, !valid_pdptrs); 6962f5bb3feSSean Christopherson if (ret) 6972f5bb3feSSean Christopherson return ret; 6982f5bb3feSSean Christopherson 6992f5bb3feSSean Christopherson if (valid_pdptrs) { 7002f5bb3feSSean Christopherson for (i = 0; i < 4 ; i++) 7012f5bb3feSSean Christopherson kvm_pdptr_write(vcpu, i, sregs2->pdptrs[i]); 7022f5bb3feSSean Christopherson 7032f5bb3feSSean Christopherson kvm_register_mark_dirty(vcpu, VCPU_REG_PDPTR); 7042f5bb3feSSean Christopherson mmu_reset_needed = 1; 7052f5bb3feSSean Christopherson vcpu->arch.pdptrs_from_userspace = true; 7062f5bb3feSSean Christopherson } 7072f5bb3feSSean Christopherson if (mmu_reset_needed) { 7082f5bb3feSSean Christopherson kvm_mmu_reset_context(vcpu); 7092f5bb3feSSean Christopherson kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); 7102f5bb3feSSean Christopherson } 7112f5bb3feSSean Christopherson return 0; 7122f5bb3feSSean Christopherson } 7132f5bb3feSSean Christopherson 7142f5bb3feSSean Christopherson void kvm_run_sync_regs_to_user(struct kvm_vcpu *vcpu) 7152f5bb3feSSean Christopherson { 7162f5bb3feSSean Christopherson BUILD_BUG_ON(sizeof(struct kvm_sync_regs) > SYNC_REGS_SIZE_BYTES); 7172f5bb3feSSean Christopherson 7182f5bb3feSSean Christopherson if (vcpu->run->kvm_valid_regs & KVM_SYNC_X86_REGS) 7192f5bb3feSSean Christopherson __get_regs(vcpu, &vcpu->run->s.regs.regs); 7202f5bb3feSSean Christopherson 7212f5bb3feSSean Christopherson if (vcpu->run->kvm_valid_regs & KVM_SYNC_X86_SREGS) 7222f5bb3feSSean Christopherson __get_sregs(vcpu, &vcpu->run->s.regs.sregs); 7232f5bb3feSSean Christopherson } 7242f5bb3feSSean Christopherson 7252f5bb3feSSean Christopherson int kvm_run_sync_regs_from_user(struct kvm_vcpu *vcpu) 7262f5bb3feSSean Christopherson { 7272f5bb3feSSean Christopherson if (vcpu->run->kvm_dirty_regs & KVM_SYNC_X86_REGS) { 7282f5bb3feSSean Christopherson __set_regs(vcpu, &vcpu->run->s.regs.regs); 7292f5bb3feSSean Christopherson vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_REGS; 7302f5bb3feSSean Christopherson } 7312f5bb3feSSean Christopherson 7322f5bb3feSSean Christopherson if (vcpu->run->kvm_dirty_regs & KVM_SYNC_X86_SREGS) { 7332f5bb3feSSean Christopherson struct kvm_sregs sregs = vcpu->run->s.regs.sregs; 7342f5bb3feSSean Christopherson 7352f5bb3feSSean Christopherson if (__set_sregs(vcpu, &sregs)) 7362f5bb3feSSean Christopherson return -EINVAL; 7372f5bb3feSSean Christopherson 7382f5bb3feSSean Christopherson vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_SREGS; 7392f5bb3feSSean Christopherson } 7402f5bb3feSSean Christopherson 7412f5bb3feSSean Christopherson return 0; 7422f5bb3feSSean Christopherson } 7432f5bb3feSSean Christopherson 7442f5bb3feSSean Christopherson void kvm_update_dr0123(struct kvm_vcpu *vcpu) 7452f5bb3feSSean Christopherson { 7462f5bb3feSSean Christopherson int i; 7472f5bb3feSSean Christopherson 7482f5bb3feSSean Christopherson if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { 7492f5bb3feSSean Christopherson for (i = 0; i < KVM_NR_DB_REGS; i++) 7502f5bb3feSSean Christopherson vcpu->arch.eff_db[i] = vcpu->arch.db[i]; 7512f5bb3feSSean Christopherson } 7522f5bb3feSSean Christopherson } 7532f5bb3feSSean Christopherson 7542f5bb3feSSean Christopherson void kvm_update_dr7(struct kvm_vcpu *vcpu) 7552f5bb3feSSean Christopherson { 7562f5bb3feSSean Christopherson unsigned long dr7; 7572f5bb3feSSean Christopherson 7582f5bb3feSSean Christopherson if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) 7592f5bb3feSSean Christopherson dr7 = vcpu->arch.guest_debug_dr7; 7602f5bb3feSSean Christopherson else 7612f5bb3feSSean Christopherson dr7 = vcpu->arch.dr7; 7622f5bb3feSSean Christopherson kvm_x86_call(set_dr7)(vcpu, dr7); 7632f5bb3feSSean Christopherson vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_BP_ENABLED; 7642f5bb3feSSean Christopherson if (dr7 & DR7_BP_EN_MASK) 7652f5bb3feSSean Christopherson vcpu->arch.switch_db_regs |= KVM_DEBUGREG_BP_ENABLED; 7662f5bb3feSSean Christopherson } 7672f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_update_dr7); 7682f5bb3feSSean Christopherson 7692f5bb3feSSean Christopherson static u64 kvm_dr6_fixed(struct kvm_vcpu *vcpu) 7702f5bb3feSSean Christopherson { 7712f5bb3feSSean Christopherson u64 fixed = DR6_FIXED_1; 7722f5bb3feSSean Christopherson 7732f5bb3feSSean Christopherson if (!guest_cpu_cap_has(vcpu, X86_FEATURE_RTM)) 7742f5bb3feSSean Christopherson fixed |= DR6_RTM; 7752f5bb3feSSean Christopherson 7762f5bb3feSSean Christopherson if (!guest_cpu_cap_has(vcpu, X86_FEATURE_BUS_LOCK_DETECT)) 7772f5bb3feSSean Christopherson fixed |= DR6_BUS_LOCK; 7782f5bb3feSSean Christopherson return fixed; 7792f5bb3feSSean Christopherson } 7802f5bb3feSSean Christopherson 7812f5bb3feSSean Christopherson int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) 7822f5bb3feSSean Christopherson { 7832f5bb3feSSean Christopherson size_t size = ARRAY_SIZE(vcpu->arch.db); 7842f5bb3feSSean Christopherson 7852f5bb3feSSean Christopherson switch (dr) { 7862f5bb3feSSean Christopherson case 0 ... 3: 7872f5bb3feSSean Christopherson vcpu->arch.db[array_index_nospec(dr, size)] = val; 7882f5bb3feSSean Christopherson if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) 7892f5bb3feSSean Christopherson vcpu->arch.eff_db[dr] = val; 7902f5bb3feSSean Christopherson break; 7912f5bb3feSSean Christopherson case 4: 7922f5bb3feSSean Christopherson case 6: 7932f5bb3feSSean Christopherson if (!kvm_dr6_valid(val)) 7942f5bb3feSSean Christopherson return 1; /* #GP */ 7952f5bb3feSSean Christopherson vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_dr6_fixed(vcpu); 7962f5bb3feSSean Christopherson break; 7972f5bb3feSSean Christopherson case 5: 7982f5bb3feSSean Christopherson default: /* 7 */ 7992f5bb3feSSean Christopherson if (!kvm_dr7_valid(val)) 8002f5bb3feSSean Christopherson return 1; /* #GP */ 8012f5bb3feSSean Christopherson vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1; 8022f5bb3feSSean Christopherson kvm_update_dr7(vcpu); 8032f5bb3feSSean Christopherson break; 8042f5bb3feSSean Christopherson } 8052f5bb3feSSean Christopherson 8062f5bb3feSSean Christopherson return 0; 8072f5bb3feSSean Christopherson } 8082f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_dr); 8092f5bb3feSSean Christopherson 8102f5bb3feSSean Christopherson unsigned long kvm_get_dr(struct kvm_vcpu *vcpu, int dr) 8112f5bb3feSSean Christopherson { 8122f5bb3feSSean Christopherson size_t size = ARRAY_SIZE(vcpu->arch.db); 8132f5bb3feSSean Christopherson 8142f5bb3feSSean Christopherson switch (dr) { 8152f5bb3feSSean Christopherson case 0 ... 3: 8162f5bb3feSSean Christopherson return vcpu->arch.db[array_index_nospec(dr, size)]; 8172f5bb3feSSean Christopherson case 4: 8182f5bb3feSSean Christopherson case 6: 8192f5bb3feSSean Christopherson return vcpu->arch.dr6; 8202f5bb3feSSean Christopherson case 5: 8212f5bb3feSSean Christopherson default: /* 7 */ 8222f5bb3feSSean Christopherson return vcpu->arch.dr7; 8232f5bb3feSSean Christopherson } 8242f5bb3feSSean Christopherson } 8252f5bb3feSSean Christopherson EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_dr); 8262f5bb3feSSean Christopherson 8272f5bb3feSSean Christopherson int kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu, 8282f5bb3feSSean Christopherson struct kvm_debugregs *dbgregs) 8292f5bb3feSSean Christopherson { 8302f5bb3feSSean Christopherson unsigned int i; 8312f5bb3feSSean Christopherson 8322f5bb3feSSean Christopherson if (vcpu->kvm->arch.has_protected_state && 8332f5bb3feSSean Christopherson vcpu->arch.guest_state_protected) 8342f5bb3feSSean Christopherson return -EINVAL; 8352f5bb3feSSean Christopherson 8362f5bb3feSSean Christopherson kvm_handle_exception_payload_quirk(vcpu); 8372f5bb3feSSean Christopherson 8382f5bb3feSSean Christopherson memset(dbgregs, 0, sizeof(*dbgregs)); 8392f5bb3feSSean Christopherson 8402f5bb3feSSean Christopherson BUILD_BUG_ON(ARRAY_SIZE(vcpu->arch.db) != ARRAY_SIZE(dbgregs->db)); 8412f5bb3feSSean Christopherson for (i = 0; i < ARRAY_SIZE(vcpu->arch.db); i++) 8422f5bb3feSSean Christopherson dbgregs->db[i] = vcpu->arch.db[i]; 8432f5bb3feSSean Christopherson 8442f5bb3feSSean Christopherson dbgregs->dr6 = vcpu->arch.dr6; 8452f5bb3feSSean Christopherson dbgregs->dr7 = vcpu->arch.dr7; 8462f5bb3feSSean Christopherson return 0; 8472f5bb3feSSean Christopherson } 8482f5bb3feSSean Christopherson 8492f5bb3feSSean Christopherson int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, 8502f5bb3feSSean Christopherson struct kvm_debugregs *dbgregs) 8512f5bb3feSSean Christopherson { 8522f5bb3feSSean Christopherson unsigned int i; 8532f5bb3feSSean Christopherson 8542f5bb3feSSean Christopherson if (vcpu->kvm->arch.has_protected_state && 8552f5bb3feSSean Christopherson vcpu->arch.guest_state_protected) 8562f5bb3feSSean Christopherson return -EINVAL; 8572f5bb3feSSean Christopherson 8582f5bb3feSSean Christopherson if (dbgregs->flags) 8592f5bb3feSSean Christopherson return -EINVAL; 8602f5bb3feSSean Christopherson 8612f5bb3feSSean Christopherson if (!kvm_dr6_valid(dbgregs->dr6)) 8622f5bb3feSSean Christopherson return -EINVAL; 8632f5bb3feSSean Christopherson if (!kvm_dr7_valid(dbgregs->dr7)) 8642f5bb3feSSean Christopherson return -EINVAL; 8652f5bb3feSSean Christopherson 8662f5bb3feSSean Christopherson for (i = 0; i < ARRAY_SIZE(vcpu->arch.db); i++) 8672f5bb3feSSean Christopherson vcpu->arch.db[i] = dbgregs->db[i]; 8682f5bb3feSSean Christopherson 8692f5bb3feSSean Christopherson kvm_update_dr0123(vcpu); 8702f5bb3feSSean Christopherson vcpu->arch.dr6 = dbgregs->dr6; 8712f5bb3feSSean Christopherson vcpu->arch.dr7 = dbgregs->dr7; 8722f5bb3feSSean Christopherson kvm_update_dr7(vcpu); 8732f5bb3feSSean Christopherson 8742f5bb3feSSean Christopherson return 0; 8752f5bb3feSSean Christopherson } 876