IA64: improve handle_fpu_swa()
It tries to get a bundle in guest.
Make it more robust using vmx_get_domain_bundle() instead of
__get_domain_bundle().
Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
diff --git a/xen/arch/ia64/xen/faults.c b/xen/arch/ia64/xen/faults.c
--- a/xen/arch/ia64/xen/faults.c
+++ b/xen/arch/ia64/xen/faults.c
@@ -318,6 +318,7 @@ handle_fpu_swa(int fp_fault, struct pt_r
IA64_BUNDLE bundle;
unsigned long fault_ip;
fpswa_ret_t ret;
+ unsigned long rc;
fault_ip = regs->cr_iip;
/*
@@ -329,15 +330,18 @@ handle_fpu_swa(int fp_fault, struct pt_r
fault_ip -= 16;
if (VMX_DOMAIN(current)) {
- if (IA64_RETRY == __vmx_get_domain_bundle(fault_ip, &bundle))
- return IA64_RETRY;
- } else
- bundle = __get_domain_bundle(fault_ip);
-
- if (!bundle.i64[0] && !bundle.i64[1]) {
- printk("%s: floating-point bundle at 0x%lx not mapped\n",
- __FUNCTION__, fault_ip);
- return -1;
+ rc = __vmx_get_domain_bundle(fault_ip, &bundle);
+ } else {
+ rc = 0;
+ if (vcpu_get_domain_bundle(current, regs, fault_ip,
+ &bundle) == 0)
+ rc = IA64_RETRY;
+ }
+ if (rc == IA64_RETRY) {
+ gdprintk(XENLOG_DEBUG,
+ "%s(%s): floating-point bundle at 0x%lx not mapped\n",
+ __FUNCTION__, fp_fault ? "fault" : "trap", fault_ip);
+ return IA64_RETRY;
}
ret = fp_emulate(fp_fault, &bundle, ®s->cr_ipsr, ®s->ar_fpsr,
@@ -689,8 +693,10 @@ ia64_handle_reflection(unsigned long ifa
if (!status)
return;
// fetch code fail
- if (IA64_RETRY == status)
+ if (IA64_RETRY == status) {
+ vcpu_decrement_iip(v);
return;
+ }
printk("ia64_handle_reflection: handling FP trap\n");
vector = IA64_FP_TRAP_VECTOR;
break;
diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c
--- a/xen/arch/ia64/xen/vcpu.c
+++ b/xen/arch/ia64/xen/vcpu.c
@@ -1355,6 +1355,26 @@ vcpu_get_domain_bundle(VCPU * vcpu, REGS
// copy its value to the variable, tr, before use.
TR_ENTRY tr;
+ // fast path:
+ // try to access gip with guest virtual address directly.
+ // This may cause tlb miss. see vcpu_translate(). Be careful!
+ swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
+ if (swap_rr0) {
+ set_virtual_rr0();
+ }
+ *bundle = __get_domain_bundle(gip);
+ if (swap_rr0) {
+ set_metaphysical_rr0();
+ }
+
+ if (!bundle->i64[0] && !bundle->i64[1]) {
+ dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
+ } else {
+ // Okay, mDTC successed
+ return 1;
+ }
+ // mDTC failed, so try vTLB.
+
trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
if (trp != NULL) {
tr = *trp;
@@ -1374,28 +1394,13 @@ vcpu_get_domain_bundle(VCPU * vcpu, REGS
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_virtual_rr0();
- }
- *bundle = __get_domain_bundle(gip);
- if (swap_rr0) {
- set_metaphysical_rr0();
- }
- if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
- dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
- return 0;
- }
- return 1;
+ // mDTC and vTLB failed. so reflect tlb miss into the guest.
+ return 0;
found:
gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |
fpswa.patch
Description: Text Data
_______________________________________________
Xen-ia64-devel mailing list
Xen-ia64-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ia64-devel
|