ia64/xen-unstable

changeset 18701:007a5df1d45b

EPT: tidy exception handler to give more useful errors

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Oct 22 11:59:19 2008 +0100 (2008-10-22)
parents 96d8b7f40dc7
children 71c15dfaa12b
files xen/arch/x86/hvm/vmx/vmx.c
line diff
     1.1 --- a/xen/arch/x86/hvm/vmx/vmx.c	Wed Oct 22 11:58:20 2008 +0100
     1.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c	Wed Oct 22 11:59:19 2008 +0100
     1.3 @@ -1964,27 +1964,25 @@ static void ept_handle_violation(unsigne
     1.4  {
     1.5      unsigned long gla_validity = qualification & EPT_GLA_VALIDITY_MASK;
     1.6      struct domain *d = current->domain;
     1.7 -    unsigned long gfn = gpa >> PAGE_SHIFT;
     1.8 +    unsigned long gla, gfn = gpa >> PAGE_SHIFT;
     1.9      mfn_t mfn;
    1.10      p2m_type_t t;
    1.11  
    1.12 -    if ( unlikely(qualification & EPT_GAW_VIOLATION) )
    1.13 +    mfn = gfn_to_mfn(d, gfn, &t);
    1.14 +
    1.15 +    /* There are two legitimate reasons for taking an EPT violation. 
    1.16 +     * One is a guest access to MMIO space. */
    1.17 +    if ( gla_validity == EPT_GLA_VALIDITY_MATCH && p2m_is_mmio(t) )
    1.18      {
    1.19 -        gdprintk(XENLOG_ERR, "EPT violation: guest physical address %"PRIpaddr
    1.20 -                 " exceeded its width limit.\n", gpa);
    1.21 -        goto crash;
    1.22 +        handle_mmio();
    1.23 +        return;
    1.24      }
    1.25  
    1.26 -    if ( unlikely(gla_validity == EPT_GLA_VALIDITY_RSVD) ||
    1.27 -         unlikely(gla_validity == EPT_GLA_VALIDITY_PDPTR_LOAD) )
    1.28 -    {
    1.29 -        gdprintk(XENLOG_ERR, "EPT violation: reserved bit or "
    1.30 -                 "pdptr load violation.\n");
    1.31 -        goto crash;
    1.32 -    }
    1.33 -
    1.34 -    mfn = gfn_to_mfn(d, gfn, &t);
    1.35 -    if ( (t != p2m_ram_ro) && p2m_is_ram(t) && paging_mode_log_dirty(d) )
    1.36 +    /* The other is log-dirty mode, writing to a read-only page */
    1.37 +    if ( paging_mode_log_dirty(d)
    1.38 +         && (gla_validity == EPT_GLA_VALIDITY_MATCH
    1.39 +             || gla_validity == EPT_GLA_VALIDITY_GPT_WALK)
    1.40 +         && p2m_is_ram(t) && (t != p2m_ram_ro) )
    1.41      {
    1.42          paging_mark_dirty(d, mfn_x(mfn));
    1.43          p2m_change_type(d, gfn, p2m_ram_logdirty, p2m_ram_rw);
    1.44 @@ -1992,16 +1990,39 @@ static void ept_handle_violation(unsigne
    1.45          return;
    1.46      }
    1.47  
    1.48 -    /* This can only happen in log-dirty mode, writing back A/D bits. */
    1.49 -    if ( unlikely(gla_validity == EPT_GLA_VALIDITY_GPT_WALK) )
    1.50 -        goto crash;
    1.51 +    /* Everything else is an error. */
    1.52 +    gla = __vmread(GUEST_LINEAR_ADDRESS);
    1.53 +    gdprintk(XENLOG_ERR, "EPT violation %#lx (%c%c%c/%c%c%c), "
    1.54 +             "gpa %#"PRIpaddr", mfn %#lx, type %i.\n", 
    1.55 +             qualification, 
    1.56 +             (qualification & EPT_READ_VIOLATION) ? 'r' : '-',
    1.57 +             (qualification & EPT_WRITE_VIOLATION) ? 'w' : '-',
    1.58 +             (qualification & EPT_EXEC_VIOLATION) ? 'x' : '-',
    1.59 +             (qualification & EPT_EFFECTIVE_READ) ? 'r' : '-',
    1.60 +             (qualification & EPT_EFFECTIVE_WRITE) ? 'w' : '-',
    1.61 +             (qualification & EPT_EFFECTIVE_EXEC) ? 'x' : '-',
    1.62 +             gpa, mfn_x(mfn), t);
    1.63  
    1.64 -    ASSERT(gla_validity == EPT_GLA_VALIDITY_MATCH);
    1.65 -    handle_mmio();
    1.66 +    if ( qualification & EPT_GAW_VIOLATION )
    1.67 +        gdprintk(XENLOG_ERR, " --- GPA too wide (max %u bits)\n", 
    1.68 +                 9 * (unsigned) d->arch.hvm_domain.vmx.ept_control.gaw + 21);
    1.69  
    1.70 -    return;
    1.71 +    switch ( gla_validity )
    1.72 +    {
    1.73 +    case EPT_GLA_VALIDITY_PDPTR_LOAD:
    1.74 +        gdprintk(XENLOG_ERR, " --- PDPTR load failed\n"); 
    1.75 +        break;
    1.76 +    case EPT_GLA_VALIDITY_GPT_WALK:
    1.77 +        gdprintk(XENLOG_ERR, " --- guest PT walk to %#lx failed\n", gla);
    1.78 +        break;
    1.79 +    case EPT_GLA_VALIDITY_RSVD:
    1.80 +        gdprintk(XENLOG_ERR, " --- GLA_validity 2 (reserved)\n");
    1.81 +        break;
    1.82 +    case EPT_GLA_VALIDITY_MATCH:
    1.83 +        gdprintk(XENLOG_ERR, " --- guest access to %#lx failed\n", gla);
    1.84 +        break;
    1.85 +    }
    1.86  
    1.87 - crash:
    1.88      domain_crash(d);
    1.89  }
    1.90