| // SPDX-License-Identifier: GPL-2.0-only | |
| #include <linux/kvm_host.h> | |
| #include "lapic.h" | |
| #include "mmu.h" | |
| #include "regs.h" | |
| #include "x86.h" | |
| unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu) | |
| { | |
| /* Can't read the RIP when guest state is protected, just return 0 */ | |
| if (vcpu->arch.guest_state_protected) | |
| return 0; | |
| if (is_64_bit_mode(vcpu)) | |
| return kvm_rip_read(vcpu); | |
| return (u32)(kvm_get_segment_base(vcpu, VCPU_SREG_CS) + | |
| kvm_rip_read(vcpu)); | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_linear_rip); | |
| bool kvm_is_linear_rip(struct kvm_vcpu *vcpu, unsigned long linear_rip) | |
| { | |
| return kvm_get_linear_rip(vcpu) == linear_rip; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_is_linear_rip); | |
| unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu) | |
| { | |
| unsigned long rflags; | |
| rflags = kvm_x86_call(get_rflags)(vcpu); | |
| if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) | |
| rflags &= ~X86_EFLAGS_TF; | |
| return rflags; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_rflags); | |
| void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) | |
| { | |
| if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP && | |
| kvm_is_linear_rip(vcpu, vcpu->arch.singlestep_rip)) | |
| rflags |= X86_EFLAGS_TF; | |
| kvm_x86_call(set_rflags)(vcpu, rflags); | |
| } | |
| void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags) | |
| { | |
| __kvm_set_rflags(vcpu, rflags); | |
| kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_rflags); | |
| static void __get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |
| { | |
| if (vcpu->arch.emulate_regs_need_sync_to_vcpu) { | |
| /* | |
| * We are here if userspace calls get_regs() in the middle of | |
| * instruction emulation. Registers state needs to be copied | |
| * back from emulation context to vcpu. Userspace shouldn't do | |
| * that usually, but some bad designed PV devices (vmware | |
| * backdoor interface) need this to work | |
| */ | |
| emulator_writeback_register_cache(vcpu->arch.emulate_ctxt); | |
| vcpu->arch.emulate_regs_need_sync_to_vcpu = false; | |
| } | |
| regs->rax = kvm_rax_read_raw(vcpu); | |
| regs->rbx = kvm_rbx_read_raw(vcpu); | |
| regs->rcx = kvm_rcx_read_raw(vcpu); | |
| regs->rdx = kvm_rdx_read_raw(vcpu); | |
| regs->rsi = kvm_rsi_read_raw(vcpu); | |
| regs->rdi = kvm_rdi_read_raw(vcpu); | |
| regs->rsp = kvm_rsp_read(vcpu); | |
| regs->rbp = kvm_rbp_read_raw(vcpu); | |
| #ifdef CONFIG_X86_64 | |
| regs->r8 = kvm_r8_read_raw(vcpu); | |
| regs->r9 = kvm_r9_read_raw(vcpu); | |
| regs->r10 = kvm_r10_read_raw(vcpu); | |
| regs->r11 = kvm_r11_read_raw(vcpu); | |
| regs->r12 = kvm_r12_read_raw(vcpu); | |
| regs->r13 = kvm_r13_read_raw(vcpu); | |
| regs->r14 = kvm_r14_read_raw(vcpu); | |
| regs->r15 = kvm_r15_read_raw(vcpu); | |
| #endif | |
| regs->rip = kvm_rip_read(vcpu); | |
| regs->rflags = kvm_get_rflags(vcpu); | |
| } | |
| int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |
| { | |
| if (vcpu->kvm->arch.has_protected_state && | |
| vcpu->arch.guest_state_protected) | |
| return -EINVAL; | |
| vcpu_load(vcpu); | |
| __get_regs(vcpu, regs); | |
| vcpu_put(vcpu); | |
| return 0; | |
| } | |
| static void __set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |
| { | |
| vcpu->arch.emulate_regs_need_sync_from_vcpu = true; | |
| vcpu->arch.emulate_regs_need_sync_to_vcpu = false; | |
| kvm_rax_write_raw(vcpu, regs->rax); | |
| kvm_rbx_write_raw(vcpu, regs->rbx); | |
| kvm_rcx_write_raw(vcpu, regs->rcx); | |
| kvm_rdx_write_raw(vcpu, regs->rdx); | |
| kvm_rsi_write_raw(vcpu, regs->rsi); | |
| kvm_rdi_write_raw(vcpu, regs->rdi); | |
| kvm_rsp_write(vcpu, regs->rsp); | |
| kvm_rbp_write_raw(vcpu, regs->rbp); | |
| #ifdef CONFIG_X86_64 | |
| kvm_r8_write_raw(vcpu, regs->r8); | |
| kvm_r9_write_raw(vcpu, regs->r9); | |
| kvm_r10_write_raw(vcpu, regs->r10); | |
| kvm_r11_write_raw(vcpu, regs->r11); | |
| kvm_r12_write_raw(vcpu, regs->r12); | |
| kvm_r13_write_raw(vcpu, regs->r13); | |
| kvm_r14_write_raw(vcpu, regs->r14); | |
| kvm_r15_write_raw(vcpu, regs->r15); | |
| #endif | |
| kvm_rip_write(vcpu, regs->rip); | |
| kvm_set_rflags(vcpu, regs->rflags | X86_EFLAGS_FIXED); | |
| vcpu->arch.exception.pending = false; | |
| vcpu->arch.exception_vmexit.pending = false; | |
| kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| } | |
| int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |
| { | |
| if (vcpu->kvm->arch.has_protected_state && | |
| vcpu->arch.guest_state_protected) | |
| return -EINVAL; | |
| vcpu_load(vcpu); | |
| __set_regs(vcpu, regs); | |
| vcpu_put(vcpu); | |
| return 0; | |
| } | |
| static inline u64 pdptr_rsvd_bits(struct kvm_vcpu *vcpu) | |
| { | |
| return vcpu->arch.reserved_gpa_bits | rsvd_bits(5, 8) | rsvd_bits(1, 2); | |
| } | |
| /* | |
| * Load the pae pdptrs. Return 1 if they are all valid, 0 otherwise. | |
| */ | |
| int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3) | |
| { | |
| struct kvm_pagewalk *w = &vcpu->arch.gva_walk; | |
| gfn_t pdpt_gfn = cr3 >> PAGE_SHIFT; | |
| gpa_t real_gpa; | |
| int i; | |
| int ret; | |
| u64 pdpte[ARRAY_SIZE(vcpu->arch.pdptrs)]; | |
| /* | |
| * If the MMU is nested, CR3 holds an L2 GPA and needs to be translated | |
| * to an L1 GPA. | |
| */ | |
| real_gpa = kvm_translate_gpa(vcpu, w, gfn_to_gpa(pdpt_gfn), | |
| PFERR_USER_MASK | PFERR_WRITE_MASK | | |
| PFERR_GUEST_PAGE_MASK, NULL, 0); | |
| if (real_gpa == INVALID_GPA) | |
| return 0; | |
| /* Note the offset, PDPTRs are 32 byte aligned when using PAE paging. */ | |
| ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(real_gpa), pdpte, | |
| cr3 & GENMASK(11, 5), sizeof(pdpte)); | |
| if (ret < 0) | |
| return 0; | |
| for (i = 0; i < ARRAY_SIZE(pdpte); ++i) { | |
| if ((pdpte[i] & PT_PRESENT_MASK) && | |
| (pdpte[i] & pdptr_rsvd_bits(vcpu))) { | |
| return 0; | |
| } | |
| } | |
| /* | |
| * Marking VCPU_REG_PDPTR dirty doesn't work for !tdp_enabled. | |
| * Shadow page roots need to be reconstructed instead. | |
| */ | |
| if (!tdp_enabled && memcmp(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs))) | |
| kvm_mmu_free_roots(vcpu->kvm, &vcpu->arch.root_mmu, | |
| KVM_MMU_ROOT_CURRENT); | |
| memcpy(vcpu->arch.pdptrs, pdpte, sizeof(vcpu->arch.pdptrs)); | |
| kvm_register_mark_dirty(vcpu, VCPU_REG_PDPTR); | |
| kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu); | |
| vcpu->arch.pdptrs_from_userspace = false; | |
| return 1; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(load_pdptrs); | |
| static bool kvm_is_valid_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |
| { | |
| #ifdef CONFIG_X86_64 | |
| if (cr0 & 0xffffffff00000000UL) | |
| return false; | |
| #endif | |
| if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD)) | |
| return false; | |
| if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE)) | |
| return false; | |
| return kvm_x86_call(is_valid_cr0)(vcpu, cr0); | |
| } | |
| void kvm_post_set_cr0(struct kvm_vcpu *vcpu, unsigned long old_cr0, unsigned long cr0) | |
| { | |
| /* | |
| * CR0.WP is incorporated into the MMU role, but only for non-nested, | |
| * indirect shadow MMUs. If paging is disabled, no updates are needed | |
| * as there are no permission bits to emulate. If TDP is enabled, the | |
| * MMU's metadata needs to be updated, e.g. so that emulating guest | |
| * translations does the right thing, but there's no need to unload the | |
| * root as CR0.WP doesn't affect SPTEs. | |
| */ | |
| if ((cr0 ^ old_cr0) == X86_CR0_WP) { | |
| if (!(cr0 & X86_CR0_PG)) | |
| return; | |
| if (tdp_enabled) { | |
| kvm_init_mmu(vcpu); | |
| return; | |
| } | |
| } | |
| if ((cr0 ^ old_cr0) & X86_CR0_PG) { | |
| /* | |
| * Clearing CR0.PG is defined to flush the TLB from the guest's | |
| * perspective. | |
| */ | |
| if (!(cr0 & X86_CR0_PG)) | |
| kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); | |
| /* | |
| * Check for async #PF completion events when enabling paging, | |
| * as the vCPU may have previously encountered async #PFs (it's | |
| * entirely legal for the guest to toggle paging on/off without | |
| * waiting for the async #PF queue to drain). | |
| */ | |
| else if (kvm_pv_async_pf_enabled(vcpu)) | |
| kvm_make_request(KVM_REQ_APF_READY, vcpu); | |
| } | |
| if ((cr0 ^ old_cr0) & KVM_MMU_CR0_ROLE_BITS) | |
| kvm_mmu_reset_context(vcpu); | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_post_set_cr0); | |
| int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | |
| { | |
| unsigned long old_cr0 = kvm_read_cr0(vcpu); | |
| if (!kvm_is_valid_cr0(vcpu, cr0)) | |
| return 1; | |
| cr0 |= X86_CR0_ET; | |
| /* Write to CR0 reserved bits are ignored, even on Intel. */ | |
| cr0 &= ~CR0_RESERVED_BITS; | |
| #ifdef CONFIG_X86_64 | |
| if ((vcpu->arch.efer & EFER_LME) && !is_paging(vcpu) && | |
| (cr0 & X86_CR0_PG)) { | |
| int cs_db, cs_l; | |
| if (!is_pae(vcpu)) | |
| return 1; | |
| kvm_x86_call(get_cs_db_l_bits)(vcpu, &cs_db, &cs_l); | |
| if (cs_l) | |
| return 1; | |
| } | |
| #endif | |
| if (!(vcpu->arch.efer & EFER_LME) && (cr0 & X86_CR0_PG) && | |
| is_pae(vcpu) && ((cr0 ^ old_cr0) & X86_CR0_PDPTR_BITS) && | |
| !load_pdptrs(vcpu, kvm_read_cr3(vcpu))) | |
| return 1; | |
| if (!(cr0 & X86_CR0_PG) && | |
| (is_64_bit_mode(vcpu) || kvm_is_cr4_bit_set(vcpu, X86_CR4_PCIDE))) | |
| return 1; | |
| if (!(cr0 & X86_CR0_WP) && kvm_is_cr4_bit_set(vcpu, X86_CR4_CET)) | |
| return 1; | |
| kvm_x86_call(set_cr0)(vcpu, cr0); | |
| kvm_post_set_cr0(vcpu, old_cr0, cr0); | |
| return 0; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr0); | |
| void kvm_lmsw(struct kvm_vcpu *vcpu, unsigned long msw) | |
| { | |
| (void)kvm_set_cr0(vcpu, kvm_read_cr0_bits(vcpu, ~0x0eul) | (msw & 0x0f)); | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_lmsw); | |
| int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | |
| { | |
| bool skip_tlb_flush = false; | |
| unsigned long pcid = 0; | |
| #ifdef CONFIG_X86_64 | |
| if (kvm_is_cr4_bit_set(vcpu, X86_CR4_PCIDE)) { | |
| skip_tlb_flush = cr3 & X86_CR3_PCID_NOFLUSH; | |
| cr3 &= ~X86_CR3_PCID_NOFLUSH; | |
| pcid = cr3 & X86_CR3_PCID_MASK; | |
| } | |
| #endif | |
| /* PDPTRs are always reloaded for PAE paging. */ | |
| if (cr3 == kvm_read_cr3(vcpu) && !is_pae_paging(vcpu)) | |
| goto handle_tlb_flush; | |
| /* | |
| * Do not condition the GPA check on long mode, this helper is used to | |
| * stuff CR3, e.g. for RSM emulation, and there is no guarantee that | |
| * the current vCPU mode is accurate. | |
| */ | |
| if (!kvm_vcpu_is_legal_cr3(vcpu, cr3)) | |
| return 1; | |
| if (is_pae_paging(vcpu) && !load_pdptrs(vcpu, cr3)) | |
| return 1; | |
| if (cr3 != kvm_read_cr3(vcpu)) | |
| kvm_mmu_new_pgd(vcpu, cr3); | |
| vcpu->arch.cr3 = cr3; | |
| kvm_register_mark_dirty(vcpu, VCPU_REG_CR3); | |
| /* Do not call post_set_cr3, we do not get here for confidential guests. */ | |
| handle_tlb_flush: | |
| /* | |
| * A load of CR3 that flushes the TLB flushes only the current PCID, | |
| * even if PCID is disabled, in which case PCID=0 is flushed. It's a | |
| * moot point in the end because _disabling_ PCID will flush all PCIDs, | |
| * and it's impossible to use a non-zero PCID when PCID is disabled, | |
| * i.e. only PCID=0 can be relevant. | |
| */ | |
| if (!skip_tlb_flush) | |
| kvm_invalidate_pcid(vcpu, pcid); | |
| return 0; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr3); | |
| static bool kvm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |
| { | |
| return __kvm_is_valid_cr4(vcpu, cr4) && | |
| kvm_x86_call(is_valid_cr4)(vcpu, cr4); | |
| } | |
| void kvm_post_set_cr4(struct kvm_vcpu *vcpu, unsigned long old_cr4, unsigned long cr4) | |
| { | |
| if ((cr4 ^ old_cr4) & KVM_MMU_CR4_ROLE_BITS) | |
| kvm_mmu_reset_context(vcpu); | |
| /* | |
| * If CR4.PCIDE is changed 0 -> 1, there is no need to flush the TLB | |
| * according to the SDM; however, stale prev_roots could be reused | |
| * incorrectly in the future after a MOV to CR3 with NOFLUSH=1, so we | |
| * free them all. This is *not* a superset of KVM_REQ_TLB_FLUSH_GUEST | |
| * or KVM_REQ_TLB_FLUSH_CURRENT, because the hardware TLB is not flushed, | |
| * so fall through. | |
| */ | |
| if (!tdp_enabled && | |
| (cr4 & X86_CR4_PCIDE) && !(old_cr4 & X86_CR4_PCIDE)) | |
| kvm_mmu_unload(vcpu); | |
| /* | |
| * The TLB has to be flushed for all PCIDs if any of the following | |
| * (architecturally required) changes happen: | |
| * - CR4.PCIDE is changed from 1 to 0 | |
| * - CR4.PGE is toggled | |
| * | |
| * This is a superset of KVM_REQ_TLB_FLUSH_CURRENT. | |
| */ | |
| if (((cr4 ^ old_cr4) & X86_CR4_PGE) || | |
| (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE))) | |
| kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); | |
| /* | |
| * The TLB has to be flushed for the current PCID if any of the | |
| * following (architecturally required) changes happen: | |
| * - CR4.SMEP is changed from 0 to 1 | |
| * - CR4.PAE is toggled | |
| */ | |
| else if (((cr4 ^ old_cr4) & X86_CR4_PAE) || | |
| ((cr4 & X86_CR4_SMEP) && !(old_cr4 & X86_CR4_SMEP))) | |
| kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu); | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_post_set_cr4); | |
| int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) | |
| { | |
| unsigned long old_cr4 = kvm_read_cr4(vcpu); | |
| if (!kvm_is_valid_cr4(vcpu, cr4)) | |
| return 1; | |
| if (is_long_mode(vcpu)) { | |
| if (!(cr4 & X86_CR4_PAE)) | |
| return 1; | |
| if ((cr4 ^ old_cr4) & X86_CR4_LA57) | |
| return 1; | |
| } else if (is_paging(vcpu) && (cr4 & X86_CR4_PAE) | |
| && ((cr4 ^ old_cr4) & X86_CR4_PDPTR_BITS) | |
| && !load_pdptrs(vcpu, kvm_read_cr3(vcpu))) | |
| return 1; | |
| if ((cr4 & X86_CR4_PCIDE) && !(old_cr4 & X86_CR4_PCIDE)) { | |
| /* PCID can not be enabled when cr3[11:0]!=000H or EFER.LMA=0 */ | |
| if ((kvm_read_cr3(vcpu) & X86_CR3_PCID_MASK) || !is_long_mode(vcpu)) | |
| return 1; | |
| } | |
| if ((cr4 & X86_CR4_CET) && !kvm_is_cr0_bit_set(vcpu, X86_CR0_WP)) | |
| return 1; | |
| kvm_x86_call(set_cr4)(vcpu, cr4); | |
| kvm_post_set_cr4(vcpu, old_cr4, cr4); | |
| return 0; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr4); | |
| static bool kvm_is_valid_cr8(unsigned long cr8) | |
| { | |
| return !(cr8 & CR8_RESERVED_BITS); | |
| } | |
| int kvm_set_cr8(struct kvm_vcpu *vcpu, unsigned long cr8) | |
| { | |
| if (!kvm_is_valid_cr8(cr8)) | |
| return 1; | |
| if (lapic_in_kernel(vcpu)) | |
| kvm_lapic_set_tpr(vcpu, cr8); | |
| else | |
| vcpu->arch.cr8 = cr8; | |
| return 0; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_cr8); | |
| unsigned long kvm_get_cr8(struct kvm_vcpu *vcpu) | |
| { | |
| if (lapic_in_kernel(vcpu)) | |
| return kvm_lapic_get_cr8(vcpu); | |
| else | |
| return vcpu->arch.cr8; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_cr8); | |
| static void __get_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |
| { | |
| struct desc_ptr dt; | |
| if (vcpu->arch.guest_state_protected) | |
| goto skip_protected_regs; | |
| kvm_handle_exception_payload_quirk(vcpu); | |
| kvm_get_segment(vcpu, &sregs->cs, VCPU_SREG_CS); | |
| kvm_get_segment(vcpu, &sregs->ds, VCPU_SREG_DS); | |
| kvm_get_segment(vcpu, &sregs->es, VCPU_SREG_ES); | |
| kvm_get_segment(vcpu, &sregs->fs, VCPU_SREG_FS); | |
| kvm_get_segment(vcpu, &sregs->gs, VCPU_SREG_GS); | |
| kvm_get_segment(vcpu, &sregs->ss, VCPU_SREG_SS); | |
| kvm_get_segment(vcpu, &sregs->tr, VCPU_SREG_TR); | |
| kvm_get_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); | |
| kvm_x86_call(get_idt)(vcpu, &dt); | |
| sregs->idt.limit = dt.size; | |
| sregs->idt.base = dt.address; | |
| kvm_x86_call(get_gdt)(vcpu, &dt); | |
| sregs->gdt.limit = dt.size; | |
| sregs->gdt.base = dt.address; | |
| sregs->cr2 = vcpu->arch.cr2; | |
| sregs->cr3 = kvm_read_cr3(vcpu); | |
| skip_protected_regs: | |
| sregs->cr0 = kvm_read_cr0(vcpu); | |
| sregs->cr4 = kvm_read_cr4(vcpu); | |
| sregs->cr8 = kvm_get_cr8(vcpu); | |
| sregs->efer = vcpu->arch.efer; | |
| sregs->apic_base = vcpu->arch.apic_base; | |
| } | |
| static void __get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |
| { | |
| __get_sregs_common(vcpu, sregs); | |
| if (vcpu->arch.guest_state_protected) | |
| return; | |
| if (vcpu->arch.interrupt.injected && !vcpu->arch.interrupt.soft) | |
| set_bit(vcpu->arch.interrupt.nr, | |
| (unsigned long *)sregs->interrupt_bitmap); | |
| } | |
| int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |
| struct kvm_sregs *sregs) | |
| { | |
| if (vcpu->kvm->arch.has_protected_state && | |
| vcpu->arch.guest_state_protected) | |
| return -EINVAL; | |
| vcpu_load(vcpu); | |
| __get_sregs(vcpu, sregs); | |
| vcpu_put(vcpu); | |
| return 0; | |
| } | |
| void kvm_vcpu_ioctl_x86_get_sregs2(struct kvm_vcpu *vcpu, | |
| struct kvm_sregs2 *sregs2) | |
| { | |
| int i; | |
| __get_sregs_common(vcpu, (struct kvm_sregs *)sregs2); | |
| if (vcpu->arch.guest_state_protected) | |
| return; | |
| if (is_pae_paging(vcpu)) { | |
| kvm_vcpu_srcu_read_lock(vcpu); | |
| for (i = 0 ; i < 4 ; i++) | |
| sregs2->pdptrs[i] = kvm_pdptr_read(vcpu, i); | |
| sregs2->flags |= KVM_SREGS2_FLAGS_PDPTRS_VALID; | |
| kvm_vcpu_srcu_read_unlock(vcpu); | |
| } | |
| } | |
| static bool kvm_is_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |
| { | |
| if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG)) { | |
| /* | |
| * When EFER.LME and CR0.PG are set, the processor is in | |
| * 64-bit mode (though maybe in a 32-bit code segment). | |
| * CR4.PAE and EFER.LMA must be set. | |
| */ | |
| if (!(sregs->cr4 & X86_CR4_PAE) || !(sregs->efer & EFER_LMA)) | |
| return false; | |
| if (!kvm_vcpu_is_legal_cr3(vcpu, sregs->cr3)) | |
| return false; | |
| } else { | |
| /* | |
| * Not in 64-bit mode: EFER.LMA is clear and the code | |
| * segment cannot be 64-bit. | |
| */ | |
| if (sregs->efer & EFER_LMA || sregs->cs.l) | |
| return false; | |
| } | |
| return kvm_is_valid_cr4(vcpu, sregs->cr4) && | |
| kvm_is_valid_cr0(vcpu, sregs->cr0) && | |
| kvm_is_valid_cr8(sregs->cr8) && | |
| kvm_valid_efer(vcpu, sregs->efer); | |
| } | |
| static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs, | |
| int *mmu_reset_needed, bool update_pdptrs) | |
| { | |
| int idx; | |
| struct desc_ptr dt; | |
| if (!kvm_is_valid_sregs(vcpu, sregs)) | |
| return -EINVAL; | |
| if (kvm_apic_set_base(vcpu, sregs->apic_base, true)) | |
| return -EINVAL; | |
| if (vcpu->arch.guest_state_protected) | |
| return 0; | |
| dt.size = sregs->idt.limit; | |
| dt.address = sregs->idt.base; | |
| kvm_x86_call(set_idt)(vcpu, &dt); | |
| dt.size = sregs->gdt.limit; | |
| dt.address = sregs->gdt.base; | |
| kvm_x86_call(set_gdt)(vcpu, &dt); | |
| vcpu->arch.cr2 = sregs->cr2; | |
| *mmu_reset_needed |= kvm_read_cr3(vcpu) != sregs->cr3; | |
| vcpu->arch.cr3 = sregs->cr3; | |
| kvm_register_mark_dirty(vcpu, VCPU_REG_CR3); | |
| kvm_x86_call(post_set_cr3)(vcpu, sregs->cr3); | |
| *mmu_reset_needed |= vcpu->arch.efer != sregs->efer; | |
| kvm_x86_call(set_efer)(vcpu, sregs->efer); | |
| *mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0; | |
| kvm_x86_call(set_cr0)(vcpu, sregs->cr0); | |
| *mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; | |
| kvm_x86_call(set_cr4)(vcpu, sregs->cr4); | |
| if (update_pdptrs) { | |
| idx = srcu_read_lock(&vcpu->kvm->srcu); | |
| if (is_pae_paging(vcpu)) { | |
| load_pdptrs(vcpu, kvm_read_cr3(vcpu)); | |
| *mmu_reset_needed = 1; | |
| } | |
| srcu_read_unlock(&vcpu->kvm->srcu, idx); | |
| } | |
| kvm_set_segment(vcpu, &sregs->cs, VCPU_SREG_CS); | |
| kvm_set_segment(vcpu, &sregs->ds, VCPU_SREG_DS); | |
| kvm_set_segment(vcpu, &sregs->es, VCPU_SREG_ES); | |
| kvm_set_segment(vcpu, &sregs->fs, VCPU_SREG_FS); | |
| kvm_set_segment(vcpu, &sregs->gs, VCPU_SREG_GS); | |
| kvm_set_segment(vcpu, &sregs->ss, VCPU_SREG_SS); | |
| kvm_set_segment(vcpu, &sregs->tr, VCPU_SREG_TR); | |
| kvm_set_segment(vcpu, &sregs->ldt, VCPU_SREG_LDTR); | |
| kvm_set_cr8(vcpu, sregs->cr8); | |
| /* Older userspace won't unhalt the vcpu on reset. */ | |
| if (kvm_vcpu_is_bsp(vcpu) && kvm_rip_read(vcpu) == 0xfff0 && | |
| sregs->cs.selector == 0xf000 && sregs->cs.base == 0xffff0000 && | |
| !is_protmode(vcpu)) | |
| kvm_set_mp_state(vcpu, KVM_MP_STATE_RUNNABLE); | |
| return 0; | |
| } | |
| static int __set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |
| { | |
| int pending_vec, max_bits; | |
| int mmu_reset_needed = 0; | |
| int ret = __set_sregs_common(vcpu, sregs, &mmu_reset_needed, true); | |
| if (ret) | |
| return ret; | |
| if (mmu_reset_needed) { | |
| kvm_mmu_reset_context(vcpu); | |
| kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); | |
| } | |
| max_bits = KVM_NR_INTERRUPTS; | |
| pending_vec = find_first_bit( | |
| (const unsigned long *)sregs->interrupt_bitmap, max_bits); | |
| if (pending_vec < max_bits) { | |
| kvm_queue_interrupt(vcpu, pending_vec, false); | |
| pr_debug("Set back pending irq %d\n", pending_vec); | |
| kvm_make_request(KVM_REQ_EVENT, vcpu); | |
| } | |
| return 0; | |
| } | |
| int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |
| struct kvm_sregs *sregs) | |
| { | |
| int ret; | |
| if (vcpu->kvm->arch.has_protected_state && | |
| vcpu->arch.guest_state_protected) | |
| return -EINVAL; | |
| vcpu_load(vcpu); | |
| ret = __set_sregs(vcpu, sregs); | |
| vcpu_put(vcpu); | |
| return ret; | |
| } | |
| int kvm_vcpu_ioctl_x86_set_sregs2(struct kvm_vcpu *vcpu, | |
| struct kvm_sregs2 *sregs2) | |
| { | |
| int mmu_reset_needed = 0; | |
| bool valid_pdptrs = sregs2->flags & KVM_SREGS2_FLAGS_PDPTRS_VALID; | |
| bool pae = (sregs2->cr0 & X86_CR0_PG) && (sregs2->cr4 & X86_CR4_PAE) && | |
| !(sregs2->efer & EFER_LMA); | |
| int i, ret; | |
| if (sregs2->flags & ~KVM_SREGS2_FLAGS_PDPTRS_VALID) | |
| return -EINVAL; | |
| if (valid_pdptrs && (!pae || vcpu->arch.guest_state_protected)) | |
| return -EINVAL; | |
| ret = __set_sregs_common(vcpu, (struct kvm_sregs *)sregs2, | |
| &mmu_reset_needed, !valid_pdptrs); | |
| if (ret) | |
| return ret; | |
| if (valid_pdptrs) { | |
| for (i = 0; i < 4 ; i++) | |
| kvm_pdptr_write(vcpu, i, sregs2->pdptrs[i]); | |
| kvm_register_mark_dirty(vcpu, VCPU_REG_PDPTR); | |
| mmu_reset_needed = 1; | |
| vcpu->arch.pdptrs_from_userspace = true; | |
| } | |
| if (mmu_reset_needed) { | |
| kvm_mmu_reset_context(vcpu); | |
| kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); | |
| } | |
| return 0; | |
| } | |
| void kvm_run_sync_regs_to_user(struct kvm_vcpu *vcpu) | |
| { | |
| BUILD_BUG_ON(sizeof(struct kvm_sync_regs) > SYNC_REGS_SIZE_BYTES); | |
| if (vcpu->run->kvm_valid_regs & KVM_SYNC_X86_REGS) | |
| __get_regs(vcpu, &vcpu->run->s.regs.regs); | |
| if (vcpu->run->kvm_valid_regs & KVM_SYNC_X86_SREGS) | |
| __get_sregs(vcpu, &vcpu->run->s.regs.sregs); | |
| } | |
| int kvm_run_sync_regs_from_user(struct kvm_vcpu *vcpu) | |
| { | |
| if (vcpu->run->kvm_dirty_regs & KVM_SYNC_X86_REGS) { | |
| __set_regs(vcpu, &vcpu->run->s.regs.regs); | |
| vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_REGS; | |
| } | |
| if (vcpu->run->kvm_dirty_regs & KVM_SYNC_X86_SREGS) { | |
| struct kvm_sregs sregs = vcpu->run->s.regs.sregs; | |
| if (__set_sregs(vcpu, &sregs)) | |
| return -EINVAL; | |
| vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_SREGS; | |
| } | |
| return 0; | |
| } | |
| void kvm_update_dr0123(struct kvm_vcpu *vcpu) | |
| { | |
| int i; | |
| if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) { | |
| for (i = 0; i < KVM_NR_DB_REGS; i++) | |
| vcpu->arch.eff_db[i] = vcpu->arch.db[i]; | |
| } | |
| } | |
| void kvm_update_dr7(struct kvm_vcpu *vcpu) | |
| { | |
| unsigned long dr7; | |
| if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) | |
| dr7 = vcpu->arch.guest_debug_dr7; | |
| else | |
| dr7 = vcpu->arch.dr7; | |
| kvm_x86_call(set_dr7)(vcpu, dr7); | |
| vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_BP_ENABLED; | |
| if (dr7 & DR7_BP_EN_MASK) | |
| vcpu->arch.switch_db_regs |= KVM_DEBUGREG_BP_ENABLED; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_update_dr7); | |
| unsigned long kvm_get_dr6_fixed_1(struct kvm_vcpu *vcpu) | |
| { | |
| unsigned long fixed = DR6_ACTIVE_LOW & ~DR6_VOLATILE; | |
| if (!guest_cpu_cap_has(vcpu, X86_FEATURE_RTM)) | |
| fixed |= DR6_RTM; | |
| if (!guest_cpu_cap_has(vcpu, X86_FEATURE_BUS_LOCK_DETECT)) | |
| fixed |= DR6_BUS_LOCK; | |
| return fixed; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_dr6_fixed_1); | |
| int kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) | |
| { | |
| size_t size = ARRAY_SIZE(vcpu->arch.db); | |
| switch (dr) { | |
| case 0 ... 3: | |
| vcpu->arch.db[array_index_nospec(dr, size)] = val; | |
| if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) | |
| vcpu->arch.eff_db[dr] = val; | |
| break; | |
| case 4: | |
| case 6: | |
| if (!kvm_dr6_valid(val)) | |
| return 1; /* #GP */ | |
| vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_get_dr6_fixed_1(vcpu); | |
| break; | |
| case 5: | |
| default: /* 7 */ | |
| if (!kvm_dr7_valid(val)) | |
| return 1; /* #GP */ | |
| vcpu->arch.dr7 = (val & DR7_VOLATILE) | DR7_FIXED_1; | |
| kvm_update_dr7(vcpu); | |
| break; | |
| } | |
| return 0; | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_set_dr); | |
| unsigned long kvm_get_dr(struct kvm_vcpu *vcpu, int dr) | |
| { | |
| size_t size = ARRAY_SIZE(vcpu->arch.db); | |
| switch (dr) { | |
| case 0 ... 3: | |
| return vcpu->arch.db[array_index_nospec(dr, size)]; | |
| case 4: | |
| case 6: | |
| return vcpu->arch.dr6; | |
| case 5: | |
| default: /* 7 */ | |
| return vcpu->arch.dr7; | |
| } | |
| } | |
| EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_dr); | |
| int kvm_vcpu_ioctl_x86_get_debugregs(struct kvm_vcpu *vcpu, | |
| struct kvm_debugregs *dbgregs) | |
| { | |
| unsigned int i; | |
| if (vcpu->kvm->arch.has_protected_state && | |
| vcpu->arch.guest_state_protected) | |
| return -EINVAL; | |
| kvm_handle_exception_payload_quirk(vcpu); | |
| memset(dbgregs, 0, sizeof(*dbgregs)); | |
| BUILD_BUG_ON(ARRAY_SIZE(vcpu->arch.db) != ARRAY_SIZE(dbgregs->db)); | |
| for (i = 0; i < ARRAY_SIZE(vcpu->arch.db); i++) | |
| dbgregs->db[i] = vcpu->arch.db[i]; | |
| dbgregs->dr6 = vcpu->arch.dr6; | |
| dbgregs->dr7 = vcpu->arch.dr7; | |
| return 0; | |
| } | |
| int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu, | |
| struct kvm_debugregs *dbgregs) | |
| { | |
| unsigned int i; | |
| if (vcpu->kvm->arch.has_protected_state && | |
| vcpu->arch.guest_state_protected) | |
| return -EINVAL; | |
| if (dbgregs->flags) | |
| return -EINVAL; | |
| if (!kvm_dr6_valid(dbgregs->dr6)) | |
| return -EINVAL; | |
| if (!kvm_dr7_valid(dbgregs->dr7)) | |
| return -EINVAL; | |
| for (i = 0; i < ARRAY_SIZE(vcpu->arch.db); i++) | |
| vcpu->arch.db[i] = dbgregs->db[i]; | |
| kvm_update_dr0123(vcpu); | |
| vcpu->arch.dr6 = dbgregs->dr6; | |
| vcpu->arch.dr7 = dbgregs->dr7; | |
| kvm_update_dr7(vcpu); | |
| return 0; | |
| } |