📄 vmx_fault.c
字号:
/* case of using GSI as callback irq */ viosapic_set_irq(d, callback_irq, 1); viosapic_set_irq(d, callback_irq, 0); } } } rmb(); if (xchg(&v->arch.irq_new_pending, 0)) { v->arch.irq_new_condition = 0; vmx_check_pending_irq(v); } else if (v->arch.irq_new_condition) { v->arch.irq_new_condition = 0; vhpi_detection(v); }}static int vmx_handle_lds(REGS* regs){ regs->cr_ipsr |= IA64_PSR_ED; return IA64_FAULT;}static inline int unimpl_phys_addr (u64 paddr){ return (pa_clear_uc(paddr) >> MAX_PHYS_ADDR_BITS) != 0;}/* We came here because the H/W VHPT walker failed to find an entry */IA64FAULTvmx_hpw_miss(u64 vadr, u64 vec, REGS* regs){ IA64_PSR vpsr; int type; u64 vhpt_adr, gppa, pteval, rr, itir; ISR misr; PTA vpta; thash_data_t *data; VCPU *v = current; vpsr.val = VCPU(v, vpsr); misr.val = VMX(v,cr_isr); if (vec == 1 || vec == 3) type = ISIDE_TLB; else if (vec == 2 || vec == 4) type = DSIDE_TLB; else panic_domain(regs, "wrong vec:%lx\n", vec); /* Physical mode. */ if (type == ISIDE_TLB) { if (!vpsr.it) { if (unlikely(unimpl_phys_addr(vadr))) { unimpl_iaddr_trap(v, vadr); return IA64_FAULT; } physical_tlb_miss(v, vadr, type); return IA64_FAULT; } } else { /* DTLB miss. */ if (!misr.rs) { if (!vpsr.dt) { u64 pte; if (misr.sp) /* Refer to SDM Vol2 Table 4-11,4-12 */ return vmx_handle_lds(regs); if (unlikely(unimpl_phys_addr(vadr))) { unimpl_daddr(v); return IA64_FAULT; } pte = lookup_domain_mpa(v->domain, pa_clear_uc(vadr), NULL); if (v->domain != dom0 && (pte & _PAGE_IO)) { emulate_io_inst(v, pa_clear_uc(vadr), 4, (pte & _PFN_MASK) >> PAGE_SHIFT); return IA64_FAULT; } physical_tlb_miss(v, vadr, type); return IA64_FAULT; } } else { /* RSE fault. */ if (!vpsr.rt) { if (unlikely(unimpl_phys_addr(vadr))) { unimpl_daddr(v); return IA64_FAULT; } physical_tlb_miss(v, vadr, type); return IA64_FAULT; } } } try_again: /* Search in VTLB. */ data = vtlb_lookup(v, vadr, type); if (data != 0) { /* Found. */ if (v->domain != dom0 && type == DSIDE_TLB) { u64 pte; if (misr.sp) { /* Refer to SDM Vol2 Table 4-10,4-12 */ if ((data->ma == VA_MATTR_UC) || (data->ma == VA_MATTR_UCE)) return vmx_handle_lds(regs); } gppa = thash_translate(data, vadr); pte = lookup_domain_mpa(v->domain, gppa, NULL); if (pte & _PAGE_IO) { if (misr.sp) panic_domain(NULL, "ld.s on I/O page not with UC attr." " pte=0x%lx\n", data->page_flags); if (data->pl >= ((regs->cr_ipsr >> IA64_PSR_CPL0_BIT) & 3)) emulate_io_inst(v, gppa, data->ma, (pte & _PFN_MASK) >> PAGE_SHIFT); else { vcpu_set_isr(v, misr.val); data_access_rights(v, vadr); } return IA64_FAULT; } } thash_vhpt_insert(v, data->page_flags, data->itir, vadr, type); return IA64_NO_FAULT; } if (type == DSIDE_TLB) { struct opt_feature* optf = &(v->domain->arch.opt_feature); if (misr.sp) return vmx_handle_lds(regs); vcpu_get_rr(v, vadr, &rr); itir = rr & (RR_RID_MASK | RR_PS_MASK); if (!vhpt_enabled(v, vadr, misr.rs ? RSE_REF : DATA_REF)) { /* windows use region 4 and 5 for identity mapping */ if ((optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG4_FLG) && REGION_NUMBER(vadr) == 4 && !(regs->cr_ipsr & IA64_PSR_CPL) && REGION_OFFSET(vadr) <= _PAGE_PPN_MASK) { pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) | optf->im_reg4.pgprot; if (thash_purge_and_insert(v, pteval, itir, vadr, type)) goto try_again; return IA64_NO_FAULT; } if ((optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG5_FLG) && REGION_NUMBER(vadr) == 5 && !(regs->cr_ipsr & IA64_PSR_CPL) && REGION_OFFSET(vadr) <= _PAGE_PPN_MASK) { pteval = PAGEALIGN(REGION_OFFSET(vadr), itir_ps(itir)) | optf->im_reg5.pgprot; if (thash_purge_and_insert(v, pteval, itir, vadr, type)) goto try_again; return IA64_NO_FAULT; } if (vpsr.ic) { vcpu_set_isr(v, misr.val); alt_dtlb(v, vadr); } else { nested_dtlb(v); } return IA64_FAULT; } vpta.val = vmx_vcpu_get_pta(v); if (vpta.vf) { /* Long format is not yet supported. */ goto inject_dtlb_fault; } /* avoid recursively walking (short format) VHPT */ if (!(optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG4_FLG) && !(optf->mask & XEN_IA64_OPTF_IDENT_MAP_REG5_FLG) && (((vadr ^ vpta.val) << 3) >> (vpta.size + 3)) == 0) { goto inject_dtlb_fault; } vhpt_adr = vmx_vcpu_thash(v, vadr); if (!guest_vhpt_lookup(vhpt_adr, &pteval)) { /* VHPT successfully read. */ if (!(pteval & _PAGE_P)) { goto inject_dtlb_fault; } else if ((pteval & _PAGE_MA_MASK) != _PAGE_MA_ST) { thash_purge_and_insert(v, pteval, itir, vadr, DSIDE_TLB); return IA64_NO_FAULT; } goto inject_dtlb_fault; } else { /* Can't read VHPT. */ if (vpsr.ic) { vcpu_set_isr(v, misr.val); dvhpt_fault(v, vadr); return IA64_FAULT; } else { nested_dtlb(v); return IA64_FAULT; } } } else if (type == ISIDE_TLB) { if (!vpsr.ic) misr.ni = 1; /* Don't bother with PHY_D mode (will require rr0+rr4 switches, and certainly used only within nested TLB handler (hence TR mapped and ic=0). */ if (!vpsr.dt) goto inject_itlb_fault; if (!vhpt_enabled(v, vadr, INST_REF)) { vcpu_set_isr(v, misr.val); alt_itlb(v, vadr); return IA64_FAULT; } vpta.val = vmx_vcpu_get_pta(v); if (vpta.vf) { /* Long format is not yet supported. */ goto inject_itlb_fault; } vhpt_adr = vmx_vcpu_thash(v, vadr); if (!guest_vhpt_lookup(vhpt_adr, &pteval)) { /* VHPT successfully read. */ if (pteval & _PAGE_P) { if ((pteval & _PAGE_MA_MASK) == _PAGE_MA_ST) { goto inject_itlb_fault; } vcpu_get_rr(v, vadr, &rr); itir = rr & (RR_RID_MASK | RR_PS_MASK); thash_purge_and_insert(v, pteval, itir, vadr, ISIDE_TLB); return IA64_NO_FAULT; } else { vcpu_set_isr(v, misr.val); inst_page_not_present(v, vadr); return IA64_FAULT; } } else { vcpu_set_isr(v, misr.val); ivhpt_fault(v, vadr); return IA64_FAULT; } } return IA64_NO_FAULT; inject_dtlb_fault: if (vpsr.ic) { vcpu_set_isr(v, misr.val); dtlb_fault(v, vadr); } else nested_dtlb(v); return IA64_FAULT; inject_itlb_fault: vcpu_set_isr(v, misr.val); itlb_fault(v, vadr); return IA64_FAULT;}voidvmx_ia64_shadow_fault(u64 ifa, u64 isr, u64 mpa, REGS *regs){ struct vcpu *v = current; struct domain *d = v->domain; u64 gpfn, pte; thash_data_t *data; if (!shadow_mode_enabled(d)) goto inject_dirty_bit; gpfn = get_gpfn_from_mfn(mpa >> PAGE_SHIFT); data = vhpt_lookup(ifa); if (data) { pte = data->page_flags; // BUG_ON((pte ^ mpa) & (_PAGE_PPN_MASK & PAGE_MASK)); if (!(pte & _PAGE_VIRT_D)) goto inject_dirty_bit; data->page_flags = pte | _PAGE_D; } else { data = vtlb_lookup(v, ifa, DSIDE_TLB); if (data) { if (!(data->page_flags & _PAGE_VIRT_D)) goto inject_dirty_bit; } pte = 0; } /* Set the dirty bit in the bitmap. */ shadow_mark_page_dirty(d, gpfn); /* Retry */ atomic64_inc(&d->arch.shadow_fault_count); ia64_ptcl(ifa, PAGE_SHIFT << 2); return;inject_dirty_bit: /* Reflect. no need to purge. */ VCPU(v, isr) = isr; set_ifa_itir_iha (v, ifa, 1, 1, 1); inject_guest_interruption(v, IA64_DIRTY_BIT_VECTOR); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -