Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4508

kernel-2.6.18-194.11.1.el5.src.rpm

From: Chris Lalancette <clalance@redhat.com>
Date: Fri, 13 Mar 2009 09:55:10 +0100
Subject: [xen] improve handle_fpu_swa
Message-id: 49BA1F6E.1070600@redhat.com
O-Subject: [RHEL5.4 PATCH 1/3]: Improve handle_fpu_swa
Bugzilla: 477098
RH-Acked-by: Don Dutile <ddutile@redhat.com>

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().

xen-unstable c/s 18980

Fixes BZ 477098

diff --git a/arch/ia64/xen/faults.c b/arch/ia64/xen/faults.c
index a127c9f..2737c3a 100644
--- a/arch/ia64/xen/faults.c
+++ b/arch/ia64/xen/faults.c
@@ -344,6 +344,7 @@ handle_fpu_swa(int fp_fault, struct pt_regs *regs, unsigned long isr)
 	IA64_BUNDLE bundle;
 	unsigned long fault_ip;
 	fpswa_ret_t ret;
+	unsigned long rc;
 
 	fault_ip = regs->cr_iip;
 	/*
@@ -355,15 +356,18 @@ handle_fpu_swa(int fp_fault, struct pt_regs *regs, unsigned long isr)
 		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, &regs->cr_ipsr, &regs->ar_fpsr,
@@ -698,8 +702,10 @@ ia64_handle_reflection(unsigned long ifa, struct pt_regs *regs,
 		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/arch/ia64/xen/vcpu.c b/arch/ia64/xen/vcpu.c
index 4394bc9..b7fdc2d 100644
--- a/arch/ia64/xen/vcpu.c
+++ b/arch/ia64/xen/vcpu.c
@@ -1512,6 +1512,26 @@ vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
 		// 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;
@@ -1531,28 +1551,13 @@ vcpu_get_domain_bundle(VCPU * vcpu, REGS * regs, u64 gip,
 			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) |