ia64/xen-unstable

changeset 9249:d14cb80574ee

Revert some of the bigger changes in c/s 9217 as these have been
causing problems for a few people:
1. HVM guests can now have page directories with unknown
back pointers (I think this is the cause of problems that
Jun Nakajima was seeing).
2. L1 pagetable pinning requests are no longer ignored (may
be the cause of problems Joe Bonasera was seeing).
3. The PGT_va_mutable flag has been reintroduced, but for
L1 pagetables only.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Mar 14 13:01:43 2006 +0100 (2006-03-14)
parents 36cf47cfea4e
children 7d8efd4f1ac7
files xen/arch/x86/mm.c xen/include/asm-x86/mm.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Mon Mar 13 15:06:58 2006 +0100
     1.2 +++ b/xen/arch/x86/mm.c	Tue Mar 14 13:01:43 2006 +0100
     1.3 @@ -778,6 +778,7 @@ static inline int l1_backptr(
     1.4  {
     1.5      unsigned long l2_backptr = l2_type & PGT_va_mask;
     1.6      ASSERT(l2_backptr != PGT_va_unknown);
     1.7 +    ASSERT(l2_backptr != PGT_va_mutable);
     1.8      *backptr = 
     1.9          ((l2_backptr >> PGT_va_shift) << L3_PAGETABLE_SHIFT) | 
    1.10          (offset_in_l2 << L2_PAGETABLE_SHIFT);
    1.11 @@ -792,6 +793,7 @@ static inline int l1_backptr(
    1.12  {
    1.13      unsigned long l2_backptr = l2_type & PGT_va_mask;
    1.14      ASSERT(l2_backptr != PGT_va_unknown);
    1.15 +    ASSERT(l2_backptr != PGT_va_mutable);
    1.16      *backptr = ((l2_backptr >> PGT_va_shift) << L3_PAGETABLE_SHIFT) | 
    1.17          (offset_in_l2 << L2_PAGETABLE_SHIFT);
    1.18      return 1;
    1.19 @@ -802,6 +804,7 @@ static inline int l2_backptr(
    1.20  {
    1.21      unsigned long l3_backptr = l3_type & PGT_va_mask;
    1.22      ASSERT(l3_backptr != PGT_va_unknown);
    1.23 +    ASSERT(l3_backptr != PGT_va_mutable);
    1.24      *backptr = ((l3_backptr >> PGT_va_shift) << L4_PAGETABLE_SHIFT) | 
    1.25          (offset_in_l3 << L3_PAGETABLE_SHIFT);
    1.26      return 1;
    1.27 @@ -1431,6 +1434,12 @@ void put_page_type(struct page_info *pag
    1.28                  nx &= ~PGT_validated;
    1.29              }
    1.30          }
    1.31 +        else if ( unlikely((nx & (PGT_pinned|PGT_type_mask|PGT_count_mask)) == 
    1.32 +                           (PGT_pinned|PGT_l1_page_table|1)) )
    1.33 +        {
    1.34 +            /* Page is now only pinned. Make the back pointer mutable again. */
    1.35 +            nx |= PGT_va_mutable;
    1.36 +        }
    1.37      }
    1.38      while ( unlikely((y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x) );
    1.39  }
    1.40 @@ -1513,16 +1522,24 @@ int get_page_type(struct page_info *page
    1.41                                  get_gpfn_from_mfn(page_to_mfn(page)));
    1.42                      return 0;
    1.43                  }
    1.44 +                else if ( (x & PGT_va_mask) == PGT_va_mutable )
    1.45 +                {
    1.46 +                    /* The va backpointer is mutable, hence we update it. */
    1.47 +                    nx &= ~PGT_va_mask;
    1.48 +                    nx |= type; /* we know the actual type is correct */
    1.49 +                }
    1.50                  else
    1.51                  {
    1.52                      ASSERT((type & PGT_va_mask) != (x & PGT_va_mask));
    1.53 +                    ASSERT((type & PGT_va_mask) != PGT_va_mutable);
    1.54  #ifdef CONFIG_X86_PAE
    1.55                      /* We use backptr as extra typing. Cannot be unknown. */
    1.56                      if ( (type & PGT_type_mask) == PGT_l2_page_table )
    1.57                          return 0;
    1.58  #endif
    1.59                      /* Fixme: add code to propagate va_unknown to subtables. */
    1.60 -                    if ( (type & PGT_type_mask) >= PGT_l2_page_table )
    1.61 +                    if ( ((type & PGT_type_mask) >= PGT_l2_page_table) &&
    1.62 +                         !shadow_mode_refcounts(page_get_owner(page)) )
    1.63                          return 0;
    1.64                      /* This table is possibly mapped at multiple locations. */
    1.65                      nx &= ~PGT_va_mask;
    1.66 @@ -1801,17 +1818,22 @@ int do_mmuext_op(
    1.67          switch ( op.cmd )
    1.68          {
    1.69          case MMUEXT_PIN_L1_TABLE:
    1.70 +            type = PGT_l1_page_table | PGT_va_mutable;
    1.71 +            goto pin_page;
    1.72 +
    1.73          case MMUEXT_PIN_L2_TABLE:
    1.74          case MMUEXT_PIN_L3_TABLE:
    1.75          case MMUEXT_PIN_L4_TABLE:
    1.76 +            /* Ignore pinning of subdirectories. */
    1.77              if ( (op.cmd - MMUEXT_PIN_L1_TABLE) != (CONFIG_PAGING_LEVELS - 1) )
    1.78                  break;
    1.79  
    1.80 -            if ( shadow_mode_refcounts(FOREIGNDOM) )
    1.81 -                break;
    1.82 -
    1.83              type = PGT_root_page_table;
    1.84  
    1.85 +        pin_page:
    1.86 +            if ( shadow_mode_refcounts(FOREIGNDOM) )
    1.87 +                break;
    1.88 +
    1.89              okay = get_page_and_type_from_pagenr(mfn, type, FOREIGNDOM);
    1.90              if ( unlikely(!okay) )
    1.91              {
    1.92 @@ -3350,7 +3372,7 @@ int ptwr_do_page_fault(struct domain *d,
    1.93      
    1.94      /* Get the L2 index at which this L1 p.t. is always mapped. */
    1.95      l2_idx = page->u.inuse.type_info & PGT_va_mask;
    1.96 -    if ( unlikely(l2_idx == PGT_va_unknown) )
    1.97 +    if ( unlikely(l2_idx >= PGT_va_unknown) )
    1.98          goto emulate; /* Urk! This L1 is mapped in multiple L2 slots! */
    1.99      l2_idx >>= PGT_va_shift;
   1.100  
     2.1 --- a/xen/include/asm-x86/mm.h	Mon Mar 13 15:06:58 2006 +0100
     2.2 +++ b/xen/include/asm-x86/mm.h	Tue Mar 14 13:01:43 2006 +0100
     2.3 @@ -81,14 +81,18 @@ struct page_info
     2.4   /* The 11 most significant bits of virt address if this is a page table. */
     2.5  #define PGT_va_shift        16
     2.6  #define PGT_va_mask         (((1U<<11)-1)<<PGT_va_shift)
     2.7 + /* Is the back pointer still mutable (i.e. not fixed yet)? */
     2.8 +#define PGT_va_mutable      (((1U<<11)-1)<<PGT_va_shift)
     2.9   /* Is the back pointer unknown (e.g., p.t. is mapped at multiple VAs)? */
    2.10 -#define PGT_va_unknown      (((1U<<11)-1)<<PGT_va_shift)
    2.11 +#define PGT_va_unknown      (((1U<<11)-2)<<PGT_va_shift)
    2.12  #elif defined(__x86_64__)
    2.13   /* The 27 most significant bits of virt address if this is a page table. */
    2.14  #define PGT_va_shift        32
    2.15  #define PGT_va_mask         ((unsigned long)((1U<<28)-1)<<PGT_va_shift)
    2.16 + /* Is the back pointer still mutable (i.e. not fixed yet)? */
    2.17 +#define PGT_va_mutable      ((unsigned long)((1U<<28)-1)<<PGT_va_shift)
    2.18   /* Is the back pointer unknown (e.g., p.t. is mapped at multiple VAs)? */
    2.19 -#define PGT_va_unknown      ((unsigned long)((1U<<28)-1)<<PGT_va_shift)
    2.20 +#define PGT_va_unknown      ((unsigned long)((1U<<28)-2)<<PGT_va_shift)
    2.21  #endif
    2.22  
    2.23   /* 16-bit count of uses of this frame as its current type. */