ia64/xen-unstable

changeset 18871:e239a47180fb

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@valinux.co.jp>
author Isaku Yamahata <yamahata@valinux.co.jp>
date Wed Dec 10 15:39:46 2008 +0900 (2008-12-10)
parents dd7ac569579a
children 3acca92b9597
files xen/arch/ia64/xen/faults.c xen/arch/ia64/xen/vcpu.c
line diff
     1.1 --- a/xen/arch/ia64/xen/faults.c	Wed Dec 10 15:39:44 2008 +0900
     1.2 +++ b/xen/arch/ia64/xen/faults.c	Wed Dec 10 15:39:46 2008 +0900
     1.3 @@ -318,6 +318,7 @@ handle_fpu_swa(int fp_fault, struct pt_r
     1.4  	IA64_BUNDLE bundle;
     1.5  	unsigned long fault_ip;
     1.6  	fpswa_ret_t ret;
     1.7 +	unsigned long rc;
     1.8  
     1.9  	fault_ip = regs->cr_iip;
    1.10  	/*
    1.11 @@ -329,15 +330,18 @@ handle_fpu_swa(int fp_fault, struct pt_r
    1.12  		fault_ip -= 16;
    1.13  
    1.14  	if (VMX_DOMAIN(current)) {
    1.15 -		if (IA64_RETRY == __vmx_get_domain_bundle(fault_ip, &bundle))
    1.16 -			return IA64_RETRY;
    1.17 -	} else
    1.18 -		bundle = __get_domain_bundle(fault_ip);
    1.19 -
    1.20 -	if (!bundle.i64[0] && !bundle.i64[1]) {
    1.21 -		printk("%s: floating-point bundle at 0x%lx not mapped\n",
    1.22 -		       __FUNCTION__, fault_ip);
    1.23 -		return -1;
    1.24 +		rc = __vmx_get_domain_bundle(fault_ip, &bundle);
    1.25 +	} else {
    1.26 +		rc = 0;
    1.27 +		if (vcpu_get_domain_bundle(current, regs, fault_ip,
    1.28 +					   &bundle) == 0)
    1.29 +			rc = IA64_RETRY;
    1.30 +	}
    1.31 +	if (rc == IA64_RETRY) {
    1.32 +		gdprintk(XENLOG_DEBUG,
    1.33 +			 "%s(%s): floating-point bundle at 0x%lx not mapped\n",
    1.34 +			 __FUNCTION__, fp_fault ? "fault" : "trap", fault_ip);
    1.35 +		return IA64_RETRY;
    1.36  	}
    1.37  
    1.38  	ret = fp_emulate(fp_fault, &bundle, &regs->cr_ipsr, &regs->ar_fpsr,
    1.39 @@ -689,8 +693,10 @@ ia64_handle_reflection(unsigned long ifa
    1.40  		if (!status)
    1.41  			return;
    1.42  		// fetch code fail
    1.43 -		if (IA64_RETRY == status)
    1.44 +		if (IA64_RETRY == status) {
    1.45 +			vcpu_decrement_iip(v);
    1.46  			return;
    1.47 +		}
    1.48  		printk("ia64_handle_reflection: handling FP trap\n");
    1.49  		vector = IA64_FP_TRAP_VECTOR;
    1.50  		break;
     2.1 --- a/xen/arch/ia64/xen/vcpu.c	Wed Dec 10 15:39:44 2008 +0900
     2.2 +++ b/xen/arch/ia64/xen/vcpu.c	Wed Dec 10 15:39:46 2008 +0900
     2.3 @@ -1355,6 +1355,26 @@ vcpu_get_domain_bundle(VCPU * vcpu, REGS
     2.4  		// copy its value to the variable, tr, before use.
     2.5  		TR_ENTRY tr;
     2.6  
     2.7 +		// fast path:
     2.8 +		// try to access gip with guest virtual address directly.
     2.9 +		// This may cause tlb miss. see vcpu_translate(). Be careful!
    2.10 +		swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
    2.11 +		if (swap_rr0) {
    2.12 +			set_virtual_rr0();
    2.13 +		}
    2.14 +		*bundle = __get_domain_bundle(gip);
    2.15 +		if (swap_rr0) {
    2.16 +			set_metaphysical_rr0();
    2.17 +		}
    2.18 +		
    2.19 +		if (!bundle->i64[0] && !bundle->i64[1]) {
    2.20 +			dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
    2.21 +		} else {
    2.22 +			// Okay, mDTC successed
    2.23 +			return 1;
    2.24 +		}
    2.25 +		// mDTC failed, so try vTLB.
    2.26 +
    2.27  		trp = vcpu_tr_lookup(vcpu, gip, rid, 0);
    2.28  		if (trp != NULL) {
    2.29  			tr = *trp;
    2.30 @@ -1374,28 +1394,13 @@ vcpu_get_domain_bundle(VCPU * vcpu, REGS
    2.31  			tr = *trp;
    2.32  			goto found;
    2.33  		}
    2.34 -#if 0
    2.35  		tr = PSCBX(vcpu, dtlb);
    2.36  		if (vcpu_match_tr_entry(&tr, gip, rid)) {
    2.37  			goto found;
    2.38  		}
    2.39 -#endif
    2.40  
    2.41 -		// try to access gip with guest virtual address
    2.42 -		// This may cause tlb miss. see vcpu_translate(). Be careful!
    2.43 -		swap_rr0 = (!region && PSCB(vcpu, metaphysical_mode));
    2.44 -		if (swap_rr0) {
    2.45 -			set_virtual_rr0();
    2.46 -		}
    2.47 -		*bundle = __get_domain_bundle(gip);
    2.48 -		if (swap_rr0) {
    2.49 -			set_metaphysical_rr0();
    2.50 -		}
    2.51 -		if (bundle->i64[0] == 0 && bundle->i64[1] == 0) {
    2.52 -			dprintk(XENLOG_INFO, "%s gip 0x%lx\n", __func__, gip);
    2.53 -			return 0;
    2.54 -		}
    2.55 -		return 1;
    2.56 +		// mDTC and vTLB failed. so reflect tlb miss into the guest.
    2.57 +		return 0;
    2.58  
    2.59  	found:
    2.60  		gpip = ((tr.pte.ppn >> (tr.ps - 12)) << tr.ps) |