ia64/xen-unstable

changeset 14423:c07b1dc6dc6d

[IA64] fix access rights in VHPT when itr.ar!=dtr.ar

This is a workaround patch for Windows 2003 Server.
Windows (vcpu>=2) set itr[1].ar=3(RWX) but dtr[1].ar=2(RW).
It causes an impossible INST_ACCESS_RIGHTS interruption via VHPT
which is used for emulating TR.

Surprisingly, windows ordinarily accepts this interruption.
But windows sometimes crashes with the message 'PANIC_STACK_SWITCH'
owing to this interruption.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
author awilliam@xenbuild2.aw
date Tue Mar 20 09:32:24 2007 -0600 (2007-03-20)
parents 2dbee4f1ee63
children 0fadd0476e03
files xen/arch/ia64/vmx/vmx_process.c xen/arch/ia64/vmx/vtlb.c xen/include/asm-ia64/vmmu.h
line diff
     1.1 --- a/xen/arch/ia64/vmx/vmx_process.c	Tue Mar 20 09:24:02 2007 -0600
     1.2 +++ b/xen/arch/ia64/vmx/vmx_process.c	Tue Mar 20 09:32:24 2007 -0600
     1.3 @@ -92,6 +92,11 @@ void vmx_reflect_interruption(u64 ifa, u
     1.4  
     1.5      switch (vec) {
     1.6  
     1.7 +    case 22:	// IA64_INST_ACCESS_RIGHTS_VECTOR
     1.8 +        if (vhpt_access_rights_fixup(vcpu, ifa, 0))
     1.9 +            return;
    1.10 +        break;
    1.11 +
    1.12      case 25:	// IA64_DISABLED_FPREG_VECTOR
    1.13  
    1.14          if (FP_PSR(vcpu) & IA64_PSR_DFH) {
     2.1 --- a/xen/arch/ia64/vmx/vtlb.c	Tue Mar 20 09:24:02 2007 -0600
     2.2 +++ b/xen/arch/ia64/vmx/vtlb.c	Tue Mar 20 09:32:24 2007 -0600
     2.3 @@ -196,6 +196,37 @@ void thash_vhpt_insert(VCPU *v, u64 pte,
     2.4          ia64_srlz_i();
     2.5      }
     2.6  }
     2.7 +
     2.8 +int vhpt_access_rights_fixup(VCPU *v, u64 ifa, int is_data)
     2.9 +{
    2.10 +    thash_data_t *trp, *data;
    2.11 +    u64 ps, tag, mask;
    2.12 +
    2.13 +    trp = __vtr_lookup(v, ifa, is_data);
    2.14 +    if (trp) {
    2.15 +        ps = _REGION_PAGE_SIZE(ia64_get_rr(ifa));
    2.16 +        if (trp->ps < ps)
    2.17 +            return 0;
    2.18 +        ifa = PAGEALIGN(ifa, ps);
    2.19 +        data = (thash_data_t *)ia64_thash(ifa);
    2.20 +        tag = ia64_ttag(ifa);
    2.21 +        do {
    2.22 +            if (data->etag == tag) {
    2.23 +                mask = trp->page_flags & PAGE_FLAGS_AR_PL_MASK;
    2.24 +                if (mask != (data->page_flags & PAGE_FLAGS_AR_PL_MASK)) {
    2.25 +                    data->page_flags &= ~PAGE_FLAGS_AR_PL_MASK;
    2.26 +                    data->page_flags |= mask;
    2.27 +                    machine_tlb_purge(ifa, ps);
    2.28 +                    return 1;
    2.29 +                }
    2.30 +                return 0;
    2.31 +            }
    2.32 +            data = data->next;
    2.33 +        } while(data);
    2.34 +    }
    2.35 +    return 0;
    2.36 +}
    2.37 +
    2.38  /*
    2.39   *   vhpt lookup
    2.40   */
     3.1 --- a/xen/include/asm-ia64/vmmu.h	Tue Mar 20 09:24:02 2007 -0600
     3.2 +++ b/xen/include/asm-ia64/vmmu.h	Tue Mar 20 09:32:24 2007 -0600
     3.3 @@ -291,6 +291,7 @@ extern int thash_lock_tc(thash_cb_t *hcb
     3.4  
     3.5  #define   ITIR_RV_MASK      (((1UL<<32)-1)<<32 | 0x3)
     3.6  #define   PAGE_FLAGS_RV_MASK    (0x2 | (0x3UL<<50)|(((1UL<<11)-1)<<53))
     3.7 +#define   PAGE_FLAGS_AR_PL_MASK ((0x7UL<<9)|(0x3UL<<7))
     3.8  extern u64 machine_ttag(PTA pta, u64 va);
     3.9  extern u64 machine_thash(PTA pta, u64 va);
    3.10  extern void purge_machine_tc_by_domid(domid_t domid);
    3.11 @@ -309,6 +310,7 @@ extern u64 translate_phy_pte(struct vcpu
    3.12  extern void thash_vhpt_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa,
    3.13                                int type);
    3.14  extern u64 guest_vhpt_lookup(u64 iha, u64 *pte);
    3.15 +extern int vhpt_access_rights_fixup(struct vcpu *v, u64 ifa, int is_data);
    3.16  
    3.17  static inline void vmx_vcpu_set_tr (thash_data_t *trp, u64 pte, u64 itir, u64 va, u64 rid)
    3.18  {