[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [IA64] ptc.ga for SMP-g
# HG changeset patch # User awilliam@xxxxxxxxxxx # Node ID b09e8f46c9f6c6daf59ba97542af05e4981d0579 # Parent bfc00c83f08318097446b3818c9de6f2ce286fb6 [IA64] ptc.ga for SMP-g Implementation of ptc.ga for SMP-g. Signed-off-by: Tristan Gingold <tristan.gingold@xxxxxxxx> diff -r bfc00c83f083 -r b09e8f46c9f6 xen/arch/ia64/vmx/vmmu.c --- a/xen/arch/ia64/vmx/vmmu.c Fri Apr 07 14:06:44 2006 -0600 +++ b/xen/arch/ia64/vmx/vmmu.c Mon Apr 10 14:51:38 2006 -0600 @@ -459,7 +459,7 @@ IA64FAULT vmx_vcpu_ptr_d(VCPU *vcpu,UINT va = PAGEALIGN(ifa, ps); index = vtr_find_overlap(vcpu, va, ps, DSIDE_TLB); if (index>=0) { - vcpu->arch.dtrs[index].p=0; + vcpu->arch.dtrs[index].pte.p=0; index = vtr_find_overlap(vcpu, va, ps, DSIDE_TLB); } hcb = vmx_vcpu_get_vtlb(vcpu); @@ -476,7 +476,7 @@ IA64FAULT vmx_vcpu_ptr_i(VCPU *vcpu,UINT va = PAGEALIGN(ifa, ps); index = vtr_find_overlap(vcpu, va, ps, ISIDE_TLB); if (index>=0) { - vcpu->arch.itrs[index].p=0; + vcpu->arch.itrs[index].pte.p=0; index = vtr_find_overlap(vcpu, va, ps, ISIDE_TLB); } hcb = vmx_vcpu_get_vtlb(vcpu); diff -r bfc00c83f083 -r b09e8f46c9f6 xen/arch/ia64/xen/process.c --- a/xen/arch/ia64/xen/process.c Fri Apr 07 14:06:44 2006 -0600 +++ b/xen/arch/ia64/xen/process.c Mon Apr 10 14:51:38 2006 -0600 @@ -287,12 +287,24 @@ void ia64_do_page_fault (unsigned long a return; } + again: fault = vcpu_translate(current,address,is_data,0,&pteval,&itir,&iha); - if (fault == IA64_NO_FAULT) { + if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) { pteval = translate_domain_pte(pteval,address,itir); vcpu_itc_no_srlz(current,is_data?2:1,address,pteval,-1UL,(itir>>2)&0x3f); + if (fault == IA64_USE_TLB && !current->arch.dtlb.pte.p) { + /* dtlb has been purged in-between. This dtlb was + matching. Undo the work. */ +#ifdef VHPT_GLOBAL + vhpt_flush_address (address, 1); +#endif + ia64_ptcl(address, 1<<2); + ia64_srlz_i(); + goto again; + } return; } + if (!user_mode (regs)) { /* The fault occurs inside Xen. */ if (!ia64_done_with_exception(regs)) { diff -r bfc00c83f083 -r b09e8f46c9f6 xen/arch/ia64/xen/vcpu.c --- a/xen/arch/ia64/xen/vcpu.c Fri Apr 07 14:06:44 2006 -0600 +++ b/xen/arch/ia64/xen/vcpu.c Mon Apr 10 14:51:38 2006 -0600 @@ -1253,17 +1253,23 @@ int warn_region0_address = 0; // FIXME l int warn_region0_address = 0; // FIXME later: tie to a boot parameter? // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key)) -static inline int vcpu_match_tr_entry(TR_ENTRY *trp, UINT64 ifa, UINT64 rid) -{ - return trp->p && trp->rid == rid +static inline int vcpu_match_tr_entry_no_p(TR_ENTRY *trp, UINT64 ifa, UINT64 rid) +{ + return trp->rid == rid && ifa >= trp->vadr && ifa <= (trp->vadr + (1L << trp->ps) - 1); } +static inline int vcpu_match_tr_entry(TR_ENTRY *trp, UINT64 ifa, UINT64 rid) +{ + return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid); +} + IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, BOOLEAN in_tpa, UINT64 *pteval, UINT64 *itir, UINT64 *iha) { unsigned long region = address >> 61; - unsigned long pta, pte, rid, rr; + unsigned long pta, rid, rr; + union pte_flags pte; int i; TR_ENTRY *trp; @@ -1283,6 +1289,7 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN */ printk("vcpu_translate: bad physical address: 0x%lx\n", address); + } else { *pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX; @@ -1307,7 +1314,7 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN if (vcpu_quick_region_check(vcpu->arch.dtr_regions,address)) { for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++) { if (vcpu_match_tr_entry(trp,address,rid)) { - *pteval = trp->page_flags; + *pteval = trp->pte.val; *itir = trp->itir; tr_translate_count++; return IA64_NO_FAULT; @@ -1320,7 +1327,7 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN if (vcpu_quick_region_check(vcpu->arch.itr_regions,address)) { for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++) { if (vcpu_match_tr_entry(trp,address,rid)) { - *pteval = trp->page_flags; + *pteval = trp->pte.val; *itir = trp->itir; tr_translate_count++; return IA64_NO_FAULT; @@ -1332,12 +1339,14 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN /* check 1-entry TLB */ // FIXME?: check dtlb for inst accesses too, else bad things happen? trp = &vcpu->arch.dtlb; - if (/* is_data && */ vcpu_match_tr_entry(trp,address,rid)) { - if (vcpu->domain==dom0 && !in_tpa) *pteval = trp->page_flags; + pte = trp->pte; + if (/* is_data && */ pte.p + && vcpu_match_tr_entry_no_p(trp,address,rid)) { + if (vcpu->domain==dom0 && !in_tpa) *pteval = pte.val; else *pteval = vcpu->arch.dtlb_pte; *itir = trp->itir; dtlb_translate_count++; - return IA64_NO_FAULT; + return IA64_USE_TLB; } /* check guest VHPT */ @@ -1358,7 +1367,8 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0) return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR); - if (__copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0) + if (!__access_ok (*iha) + || __copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0) // virtual VHPT walker "missed" in TLB return IA64_VHPT_FAULT; @@ -1367,12 +1377,12 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN * instead of inserting a not-present translation, this allows * vectoring directly to the miss handler. */ - if (!(pte & _PAGE_P)) + if (!pte.p) return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR); /* found mapping in guest VHPT! */ *itir = rr & RR_PS_MASK; - *pteval = pte; + *pteval = pte.val; vhpt_translate_count++; return IA64_NO_FAULT; } @@ -1383,7 +1393,7 @@ IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 va IA64FAULT fault; fault = vcpu_translate(vcpu, vadr, TRUE, TRUE, &pteval, &itir, &iha); - if (fault == IA64_NO_FAULT) + if (fault == IA64_NO_FAULT || fault == IA64_USE_TLB) { mask = itir_mask(itir); *padr = (pteval & _PAGE_PPN_MASK & mask) | (vadr & ~mask); @@ -1670,24 +1680,27 @@ IA64FAULT vcpu_set_pkr(VCPU *vcpu, UINT6 static inline void vcpu_purge_tr_entry(TR_ENTRY *trp) { - trp->p = 0; + trp->pte.val = 0; } static void vcpu_set_tr_entry(TR_ENTRY *trp, UINT64 pte, UINT64 itir, UINT64 ifa) { UINT64 ps; + union pte_flags new_pte; trp->itir = itir; trp->rid = VCPU(current,rrs[ifa>>61]) & RR_RID_MASK; - trp->p = 1; ps = trp->ps; - trp->page_flags = pte; - if (trp->pl < 2) trp->pl = 2; + new_pte.val = pte; + if (new_pte.pl < 2) new_pte.pl = 2; trp->vadr = ifa & ~0xfff; if (ps > 12) { // "ignore" relevant low-order bits - trp->ppn &= ~((1UL<<(ps-12))-1); + new_pte.ppn &= ~((1UL<<(ps-12))-1); trp->vadr &= ~((1UL<<ps)-1); } + + /* Atomic write. */ + trp->pte.val = new_pte.val; } IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte, @@ -1852,19 +1865,6 @@ IA64FAULT vcpu_ptc_g(VCPU *vcpu, UINT64 return IA64_ILLOP_FAULT; } -#if defined(CONFIG_XEN_SMP) && defined(VHPT_GLOBAL) -struct ptc_ga_args { - unsigned long vadr; - unsigned long addr_range; -}; - -static void ptc_ga_remote_func (void *varg) -{ - struct ptc_ga_args *args = (struct ptc_ga_args *)varg; - vhpt_flush_address (args->vadr, args->addr_range); -} -#endif - IA64FAULT vcpu_ptc_ga(VCPU *vcpu,UINT64 vadr,UINT64 addr_range) { // FIXME: validate not flushing Xen addresses @@ -1875,32 +1875,20 @@ IA64FAULT vcpu_ptc_ga(VCPU *vcpu,UINT64 #ifdef CONFIG_XEN_SMP struct domain *d = vcpu->domain; struct vcpu *v; - struct ptc_ga_args args; - - args.vadr = vadr; - args.addr_range = addr_range; - - /* This method is very conservative and should be optimized: - - maybe IPI calls can be avoided, - - a processor map can be built to avoid duplicate purge - - maybe ptc.ga can be replaced by ptc.l+invala. - Hopefully, it has no impact when UP. - */ + for_each_vcpu (d, v) { - if (v != vcpu) { - /* Purge tc entry. - Can we do this directly ? Well, this is just a - single atomic write. */ - vcpu_purge_tr_entry(&PSCBX(v,dtlb)); - vcpu_purge_tr_entry(&PSCBX(v,itlb)); + if (v == vcpu) + continue; + + /* Purge TC entries. + FIXME: clear only if match. */ + vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb)); + vcpu_purge_tr_entry(&PSCBX(vcpu,itlb)); + #ifdef VHPT_GLOBAL - /* Flush VHPT on remote processors. - FIXME: invalidate directly the entries? */ - smp_call_function_single - (v->processor, &ptc_ga_remote_func, - &args, 0, 1); -#endif - } + /* Invalidate VHPT entries. */ + vhpt_flush_address_remote (v->processor, vadr, addr_range); +#endif } #endif diff -r bfc00c83f083 -r b09e8f46c9f6 xen/arch/ia64/xen/vhpt.c --- a/xen/arch/ia64/xen/vhpt.c Fri Apr 07 14:06:44 2006 -0600 +++ b/xen/arch/ia64/xen/vhpt.c Mon Apr 10 14:51:38 2006 -0600 @@ -71,6 +71,20 @@ void vhpt_flush_address(unsigned long va //printf("vhpt_flush_address: blowing away valid tag for vadr=%p\n",vadr); //} vlfe->ti_tag |= INVALID_TI_TAG; + addr_range -= PAGE_SIZE; + vadr += PAGE_SIZE; + } +} + +void vhpt_flush_address_remote(int cpu, + unsigned long vadr, unsigned long addr_range) +{ + while ((long)addr_range > 0) { + /* Get the VHPT entry. */ + unsigned int off = ia64_thash(vadr) - VHPT_ADDR; + volatile struct vhpt_lf_entry *v; + v =__va(per_cpu(vhpt_paddr, cpu) + off); + v->ti_tag = INVALID_TI_TAG; addr_range -= PAGE_SIZE; vadr += PAGE_SIZE; } diff -r bfc00c83f083 -r b09e8f46c9f6 xen/include/asm-ia64/ia64_int.h --- a/xen/include/asm-ia64/ia64_int.h Fri Apr 07 14:06:44 2006 -0600 +++ b/xen/include/asm-ia64/ia64_int.h Mon Apr 10 14:51:38 2006 -0600 @@ -38,6 +38,7 @@ #define IA64_RFI_IN_PROGRESS 0x0002 #define IA64_RETRY 0x0003 #define IA64_FORCED_IFA 0x0004 +#define IA64_USE_TLB 0x0005 #define IA64_ILLOP_FAULT (IA64_GENEX_VECTOR | 0x00) #define IA64_PRIVOP_FAULT (IA64_GENEX_VECTOR | 0x10) #define IA64_PRIVREG_FAULT (IA64_GENEX_VECTOR | 0x20) diff -r bfc00c83f083 -r b09e8f46c9f6 xen/include/asm-ia64/tlb.h --- a/xen/include/asm-ia64/tlb.h Fri Apr 07 14:06:44 2006 -0600 +++ b/xen/include/asm-ia64/tlb.h Mon Apr 10 14:51:38 2006 -0600 @@ -4,23 +4,24 @@ #define NITRS 8 #define NDTRS 8 +union pte_flags { + struct { + unsigned long p : 1; // 0 + unsigned long : 1; // 1 + unsigned long ma : 3; // 2-4 + unsigned long a : 1; // 5 + unsigned long d : 1; // 6 + unsigned long pl : 2; // 7-8 + unsigned long ar : 3; // 9-11 + unsigned long ppn : 38; // 12-49 + unsigned long : 2; // 50-51 + unsigned long ed : 1; // 52 + }; + unsigned long val; +}; + typedef struct { - union { - struct { - unsigned long p : 1; // 0 - unsigned long : 1; // 1 - unsigned long ma : 3; // 2-4 - unsigned long a : 1; // 5 - unsigned long d : 1; // 6 - unsigned long pl : 2; // 7-8 - unsigned long ar : 3; // 9-11 - unsigned long ppn : 38; // 12-49 - unsigned long : 2; // 50-51 - unsigned long ed : 1; // 52 - }; - unsigned long page_flags; - }; - + volatile union pte_flags pte; union { struct { unsigned long : 2; // 0-1 diff -r bfc00c83f083 -r b09e8f46c9f6 xen/include/asm-ia64/vhpt.h --- a/xen/include/asm-ia64/vhpt.h Fri Apr 07 14:06:44 2006 -0600 +++ b/xen/include/asm-ia64/vhpt.h Mon Apr 10 14:51:38 2006 -0600 @@ -122,6 +122,8 @@ extern void zero_vhpt_stats(void); extern void zero_vhpt_stats(void); extern int dump_vhpt_stats(char *buf); extern void vhpt_flush_address(unsigned long vadr, unsigned long addr_range); +extern void vhpt_flush_address_remote(int cpu, unsigned long vadr, + unsigned long addr_range); extern void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte, unsigned long logps); extern void vhpt_insert (unsigned long vadr, unsigned long ptr, _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |