[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IA64] rewrite priv_handle_op()



# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID b8711fcb1e9563b6b5af9981bfd724e3efa99cee
# Parent  25483d9b55d4307d125f4135b609a6387f247ba8
[IA64] rewrite priv_handle_op()

introduce vcpu_get_domain_bundle() and replace __get_domain_handle call
in priv_handle_op with it.
priv_handle_op() uses __get_domain_handle to domain's bundle.
it directly access guest ip with guest virtual address which may results
in data tlb miss which cause some trobles.
This patch also cleans up vcpu_translate().

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
 xen/arch/ia64/xen/privop.c  |   15 +---
 xen/arch/ia64/xen/vcpu.c    |  162 +++++++++++++++++++++++++++++++++++++-------
 xen/include/asm-ia64/vcpu.h |    3 
 3 files changed, 145 insertions(+), 35 deletions(-)

diff -r 25483d9b55d4 -r b8711fcb1e95 xen/arch/ia64/xen/privop.c
--- a/xen/arch/ia64/xen/privop.c        Wed May 31 16:07:47 2006 -0600
+++ b/xen/arch/ia64/xen/privop.c        Sat Jun 03 11:16:34 2006 -0600
@@ -615,16 +615,11 @@ priv_handle_op(VCPU *vcpu, REGS *regs, i
        int x6;
        
        // make a local copy of the bundle containing the privop
-#if 1
-       bundle = __get_domain_bundle(iip);
-       if (!bundle.i64[0] && !bundle.i64[1])
-#else
-       if (__copy_from_user(&bundle,iip,sizeof(bundle)))
-#endif
-       {
-//printf("*** priv_handle_op: privop bundle at 0x%lx not mapped, 
retrying\n",iip);
-               return vcpu_force_data_miss(vcpu,regs->cr_iip);
-       }
+       if (!vcpu_get_domain_bundle(vcpu, regs, iip, &bundle)) {
+               //return vcpu_force_data_miss(vcpu, regs->cr_iip);
+               return vcpu_force_inst_miss(vcpu, regs->cr_iip);
+       }
+
 #if 0
        if (iip==0xa000000100001820) {
                static int firstpagefault = 1;
diff -r 25483d9b55d4 -r b8711fcb1e95 xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c  Wed May 31 16:07:47 2006 -0600
+++ b/xen/arch/ia64/xen/vcpu.c  Sat Jun 03 11:16:34 2006 -0600
@@ -17,6 +17,7 @@
 #include <asm/vmx_vcpu.h>
 #include <asm/vhpt.h>
 #include <asm/tlbflush.h>
+#include <asm/privop.h>
 #include <xen/event.h>
 #include <asm/vmx_phy_mode.h>
 
@@ -29,6 +30,7 @@ extern void setfpreg (unsigned long regn
 
 extern void panic_domain(struct pt_regs *, const char *, ...);
 extern unsigned long translate_domain_mpaddr(unsigned long);
+extern IA64_BUNDLE __get_domain_bundle(UINT64);
 
 typedef        union {
        struct ia64_psr ia64_psr;
@@ -1184,14 +1186,25 @@ Privileged operation emulation routines
 Privileged operation emulation routines
 **************************************************************************/
 
+static void
+vcpu_force_tlb_miss(VCPU* vcpu, UINT64 ifa)
+{
+       PSCB(vcpu, ifa) = ifa;
+       PSCB(vcpu, itir) = vcpu_get_itir_on_fault(vcpu, ifa);
+       vcpu_thash(current, ifa, &PSCB(current, iha));
+}
+
+IA64FAULT vcpu_force_inst_miss(VCPU *vcpu, UINT64 ifa)
+{
+       vcpu_force_tlb_miss(vcpu, ifa);
+       return (vcpu_get_rr_ve(vcpu, ifa)? IA64_INST_TLB_VECTOR: 
IA64_ALT_INST_TLB_VECTOR);
+}
+
 IA64FAULT vcpu_force_data_miss(VCPU *vcpu, UINT64 ifa)
 {
-       PSCB(vcpu,ifa) = ifa;
-       PSCB(vcpu,itir) = vcpu_get_itir_on_fault(vcpu,ifa);
-       vcpu_thash(current, ifa, &PSCB(current,iha));
-       return (vcpu_get_rr_ve(vcpu,ifa) ? IA64_DATA_TLB_VECTOR : 
IA64_ALT_DATA_TLB_VECTOR);
-}
-
+       vcpu_force_tlb_miss(vcpu, ifa);
+       return (vcpu_get_rr_ve(vcpu, ifa)? IA64_DATA_TLB_VECTOR: 
IA64_ALT_DATA_TLB_VECTOR);
+}
 
 IA64FAULT vcpu_rfi(VCPU *vcpu)
 {
@@ -1303,12 +1316,117 @@ static inline int vcpu_match_tr_entry(TR
        return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid);
 }
 
+static TR_ENTRY*
+vcpu_tr_lookup(VCPU* vcpu, unsigned long va, UINT64 rid, BOOLEAN is_data)
+{
+       unsigned int* regions;
+       TR_ENTRY *trp;
+       int tr_max;
+       int i;
+
+       if (is_data) {
+               // data
+               regions = &vcpu->arch.dtr_regions;
+               trp = vcpu->arch.dtrs;
+               tr_max = sizeof(vcpu->arch.dtrs)/sizeof(vcpu->arch.dtrs[0]);
+       } else {
+               // instruction
+               regions = &vcpu->arch.itr_regions;
+               trp = vcpu->arch.itrs;
+               tr_max = sizeof(vcpu->arch.itrs)/sizeof(vcpu->arch.itrs[0]);
+       }
+
+       if (!vcpu_quick_region_check(*regions, va)) {
+               return NULL;
+       }
+       for (i = 0; i < tr_max; i++, trp++) {
+               if (vcpu_match_tr_entry(trp, va, rid)) {
+                       return trp;
+               }
+       }
+       return NULL;
+}
+
+// return value
+// 0: failure
+// 1: success
+int
+vcpu_get_domain_bundle(VCPU* vcpu, REGS* regs, UINT64 gip, IA64_BUNDLE* bundle)
+{
+       UINT64 gpip;// guest pseudo phyiscal ip
+
+#if 0
+       // Currently xen doesn't track psr.it bits.
+       // it assumes always psr.it = 1.
+       if (!(VCPU(vcpu, vpsr) & IA64_PSR_IT)) {
+               gpip = gip;
+       } else
+#endif
+       {
+               unsigned long region = REGION_NUMBER(gip);
+               unsigned long rr = PSCB(vcpu, rrs)[region];
+               unsigned long rid = rr & RR_RID_MASK;
+               BOOLEAN swap_rr0;
+               TR_ENTRY* trp;
+
+               // vcpu->arch.{i, d}tlb are volatile,
+               // copy its value to the variable, tr, before use.
+               TR_ENTRY tr;
+
+               trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
+               if (trp != NULL) {
+                       tr = *trp;
+                       goto found;
+               }
+               // When it failed to get a bundle, itlb miss is reflected.
+               // Last itc.i value is cached to PSCBX(vcpu, itlb).
+               tr = PSCBX(vcpu, itlb);
+               if (vcpu_match_tr_entry(&tr, gip, rid)) {
+                       //DPRINTK("%s gip 0x%lx gpip 0x%lx\n", __func__, gip, 
gpip);
+                       goto found;
+               }
+               trp = vcpu_tr_lookup(vcpu, gip, rid, 1);
+               if (trp != NULL) {
+                       tr = *trp;
+                       goto found;
+               }
+#if 0
+               tr = PSCBX(vcpu, dtlb);
+               if (vcpu_match_tr_entry(&tr, gip, rid)) {
+                       goto found;
+               }
+#endif
+
+               // try to access gip with guest virtual address
+               // This may cause tlb miss. see vcpu_translate(). Be careful!
+               swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
+               if (swap_rr0) {
+                       set_one_rr(0x0, PSCB(vcpu, rrs[0]));
+               }
+               *bundle = __get_domain_bundle(gip);
+               if (swap_rr0) {
+                       set_metaphysical_rr0();
+               }
+               if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
+                       DPRINTK("%s gip 0x%lx\n", __func__, gip);
+                       return 0;
+               }
+               return 1;
+        
+       found:
+               gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
+                       (gip & ((1 << tr.ps) - 1));
+       }
+
+       *bundle = *((IA64_BUNDLE*)__va(__gpa_to_mpa(vcpu->domain, gpip)));
+       return 1;
+}
+
 IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 
*pteval, UINT64 *itir, UINT64 *iha)
 {
        unsigned long region = address >> 61;
        unsigned long pta, rid, rr;
        union pte_flags pte;
-       int i;
        TR_ENTRY *trp;
 
        if (PSCB(vcpu,metaphysical_mode) && !(!is_data && region)) {
@@ -1349,28 +1467,22 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UIN
        rr = PSCB(vcpu,rrs)[region];
        rid = rr & RR_RID_MASK;
        if (is_data) {
-               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->pte.val;
-                                       *itir = trp->itir;
-                                       tr_translate_count++;
-                                       return IA64_NO_FAULT;
-                               }
-                       }
+               trp = vcpu_tr_lookup(vcpu, address, rid, 1);
+               if (trp != NULL) {
+                       *pteval = trp->pte.val;
+                       *itir = trp->itir;
+                       tr_translate_count++;
+                       return IA64_NO_FAULT;
                }
        }
        // FIXME?: check itr's for data accesses too, else bad things happen?
        /* else */ {
-               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->pte.val;
-                                       *itir = trp->itir;
-                                       tr_translate_count++;
-                                       return IA64_NO_FAULT;
-                               }
-                       }
+               trp = vcpu_tr_lookup(vcpu, address, rid, 0);
+               if (trp != NULL) {
+                       *pteval = trp->pte.val;
+                       *itir = trp->itir;
+                       tr_translate_count++;
+                       return IA64_NO_FAULT;
                }
        }
 
diff -r 25483d9b55d4 -r b8711fcb1e95 xen/include/asm-ia64/vcpu.h
--- a/xen/include/asm-ia64/vcpu.h       Wed May 31 16:07:47 2006 -0600
+++ b/xen/include/asm-ia64/vcpu.h       Sat Jun 03 11:16:34 2006 -0600
@@ -151,9 +151,12 @@ extern IA64FAULT vcpu_ptc_ga(VCPU *vcpu,
 extern IA64FAULT vcpu_ptc_ga(VCPU *vcpu, UINT64 vadr, UINT64 addr_range);
 extern IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr, UINT64 addr_range);
 extern IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr, UINT64 addr_range);
+union U_IA64_BUNDLE;
+extern int vcpu_get_domain_bundle(VCPU *vcpu, REGS *regs, UINT64 gip, union 
U_IA64_BUNDLE *bundle);
 extern IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data,
                                UINT64 *pteval, UINT64 *itir, UINT64 *iha);
 extern IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr);
+extern IA64FAULT vcpu_force_inst_miss(VCPU *vcpu, UINT64 ifa);
 extern IA64FAULT vcpu_force_data_miss(VCPU *vcpu, UINT64 ifa);
 extern IA64FAULT vcpu_fc(VCPU *vcpu, UINT64 vadr);
 /* misc */

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.