direct-io.hg

changeset 14353:b01d4f415f5f

x86: PAE linear page tables.

While full linear page table support makes little sense (and would be
more complicated to implement), partial linear page table support is
almost identical to that in non-PAE, and is used (at least) by NetWare.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author kfraser@localhost.localdomain
date Mon Mar 12 14:47:00 2007 +0000 (2007-03-12)
parents 6d2328b353c8
children a4ca6a264fee
files xen/arch/x86/domain.c xen/arch/x86/mm.c
line diff
     1.1 --- a/xen/arch/x86/domain.c	Mon Mar 12 14:11:43 2007 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Mon Mar 12 14:47:00 2007 +0000
     1.3 @@ -1386,7 +1386,8 @@ int hypercall_xlat_continuation(unsigned
     1.4  }
     1.5  #endif
     1.6  
     1.7 -static void relinquish_memory(struct domain *d, struct list_head *list)
     1.8 +static void relinquish_memory(struct domain *d, struct list_head *list,
     1.9 +                              unsigned long type)
    1.10  {
    1.11      struct list_head *ent;
    1.12      struct page_info  *page;
    1.13 @@ -1415,23 +1416,24 @@ static void relinquish_memory(struct dom
    1.14              put_page(page);
    1.15  
    1.16          /*
    1.17 -         * Forcibly invalidate base page tables at this point to break circular
    1.18 -         * 'linear page table' references. This is okay because MMU structures
    1.19 -         * are not shared across domains and this domain is now dead. Thus base
    1.20 -         * tables are not in use so a non-zero count means circular reference.
    1.21 +         * Forcibly invalidate top-most, still valid page tables at this point
    1.22 +         * to break circular 'linear page table' references. This is okay
    1.23 +         * because MMU structures are not shared across domains and this domain
    1.24 +         * is now dead. Thus top-most valid tables are not in use so a non-zero
    1.25 +         * count means circular reference.
    1.26           */
    1.27          y = page->u.inuse.type_info;
    1.28          for ( ; ; )
    1.29          {
    1.30              x = y;
    1.31              if ( likely((x & (PGT_type_mask|PGT_validated)) !=
    1.32 -                        (PGT_base_page_table|PGT_validated)) )
    1.33 +                        (type|PGT_validated)) )
    1.34                  break;
    1.35  
    1.36              y = cmpxchg(&page->u.inuse.type_info, x, x & ~PGT_validated);
    1.37              if ( likely(y == x) )
    1.38              {
    1.39 -                free_page_type(page, PGT_base_page_table);
    1.40 +                free_page_type(page, type);
    1.41                  break;
    1.42              }
    1.43          }
    1.44 @@ -1529,8 +1531,16 @@ void domain_relinquish_resources(struct 
    1.45          destroy_gdt(v);
    1.46  
    1.47      /* Relinquish every page of memory. */
    1.48 -    relinquish_memory(d, &d->xenpage_list);
    1.49 -    relinquish_memory(d, &d->page_list);
    1.50 +#if CONFIG_PAGING_LEVELS >= 4
    1.51 +    relinquish_memory(d, &d->xenpage_list, PGT_l4_page_table);
    1.52 +    relinquish_memory(d, &d->page_list, PGT_l4_page_table);
    1.53 +#endif
    1.54 +#if CONFIG_PAGING_LEVELS >= 3
    1.55 +    relinquish_memory(d, &d->xenpage_list, PGT_l3_page_table);
    1.56 +    relinquish_memory(d, &d->page_list, PGT_l3_page_table);
    1.57 +#endif
    1.58 +    relinquish_memory(d, &d->xenpage_list, PGT_l2_page_table);
    1.59 +    relinquish_memory(d, &d->page_list, PGT_l2_page_table);
    1.60  
    1.61      /* Free page used by xen oprofile buffer */
    1.62      free_xenoprof_pages(d);
     2.1 --- a/xen/arch/x86/mm.c	Mon Mar 12 14:11:43 2007 +0000
     2.2 +++ b/xen/arch/x86/mm.c	Mon Mar 12 14:47:00 2007 +0000
     2.3 @@ -517,7 +517,6 @@ static int get_page_and_type_from_pagenr
     2.4      return 1;
     2.5  }
     2.6  
     2.7 -#ifndef CONFIG_X86_PAE /* We do not support guest linear mappings on PAE. */
     2.8  /*
     2.9   * We allow root tables to map each other (a.k.a. linear page tables). It
    2.10   * needs some special care with reference counts and access permissions:
    2.11 @@ -530,48 +529,54 @@ static int get_page_and_type_from_pagenr
    2.12   *     frame if it is mapped by a different root table. This is sufficient and
    2.13   *     also necessary to allow validation of a root table mapping itself.
    2.14   */
    2.15 -static int 
    2.16 -get_linear_pagetable(
    2.17 -    root_pgentry_t re, unsigned long re_pfn, struct domain *d)
    2.18 -{
    2.19 -    unsigned long x, y;
    2.20 -    struct page_info *page;
    2.21 -    unsigned long pfn;
    2.22 -
    2.23 -    if ( (root_get_flags(re) & _PAGE_RW) )
    2.24 -    {
    2.25 -        MEM_LOG("Attempt to create linear p.t. with write perms");
    2.26 -        return 0;
    2.27 -    }
    2.28 -
    2.29 -    if ( (pfn = root_get_pfn(re)) != re_pfn )
    2.30 -    {
    2.31 -        /* Make sure the mapped frame belongs to the correct domain. */
    2.32 -        if ( unlikely(!get_page_from_pagenr(pfn, d)) )
    2.33 -            return 0;
    2.34 -
    2.35 -        /*
    2.36 -         * Make sure that the mapped frame is an already-validated L2 table. 
    2.37 -         * If so, atomically increment the count (checking for overflow).
    2.38 -         */
    2.39 -        page = mfn_to_page(pfn);
    2.40 -        y = page->u.inuse.type_info;
    2.41 -        do {
    2.42 -            x = y;
    2.43 -            if ( unlikely((x & PGT_count_mask) == PGT_count_mask) ||
    2.44 -                 unlikely((x & (PGT_type_mask|PGT_validated)) != 
    2.45 -                          (PGT_root_page_table|PGT_validated)) )
    2.46 -            {
    2.47 -                put_page(page);
    2.48 -                return 0;
    2.49 -            }
    2.50 -        }
    2.51 -        while ( (y = cmpxchg(&page->u.inuse.type_info, x, x + 1)) != x );
    2.52 -    }
    2.53 -
    2.54 -    return 1;
    2.55 +#define define_get_linear_pagetable(name1, name2)                           \
    2.56 +static int                                                                  \
    2.57 +get_##name1##_linear_pagetable(                                             \
    2.58 +    name1##_pgentry_t pde, unsigned long pde_pfn, struct domain *d)         \
    2.59 +{                                                                           \
    2.60 +    unsigned long x, y;                                                     \
    2.61 +    struct page_info *page;                                                 \
    2.62 +    unsigned long pfn;                                                      \
    2.63 +                                                                            \
    2.64 +    if ( (name2##_get_flags(pde) & _PAGE_RW) )                              \
    2.65 +    {                                                                       \
    2.66 +        MEM_LOG("Attempt to create linear p.t. with write perms");          \
    2.67 +        return 0;                                                           \
    2.68 +    }                                                                       \
    2.69 +                                                                            \
    2.70 +    if ( (pfn = name2##_get_pfn(pde)) != pde_pfn )                          \
    2.71 +    {                                                                       \
    2.72 +        /* Make sure the mapped frame belongs to the correct domain. */     \
    2.73 +        if ( unlikely(!get_page_from_pagenr(pfn, d)) )                      \
    2.74 +            return 0;                                                       \
    2.75 +                                                                            \
    2.76 +        /*                                                                  \
    2.77 +         * Ensure that the mapped frame is an already-validated page table. \
    2.78 +         * If so, atomically increment the count (checking for overflow).   \
    2.79 +         */                                                                 \
    2.80 +        page = mfn_to_page(pfn);                                            \
    2.81 +        y = page->u.inuse.type_info;                                        \
    2.82 +        do {                                                                \
    2.83 +            x = y;                                                          \
    2.84 +            if ( unlikely((x & PGT_count_mask) == PGT_count_mask) ||        \
    2.85 +                 unlikely((x & (PGT_type_mask|PGT_validated)) !=            \
    2.86 +                          (PGT_##name1##_page_table|PGT_validated)) )       \
    2.87 +            {                                                               \
    2.88 +                put_page(page);                                             \
    2.89 +                return 0;                                                   \
    2.90 +            }                                                               \
    2.91 +        }                                                                   \
    2.92 +        while ( (y = cmpxchg(&page->u.inuse.type_info, x, x + 1)) != x );   \
    2.93 +    }                                                                       \
    2.94 +                                                                            \
    2.95 +    return 1;                                                               \
    2.96  }
    2.97 -#endif /* !CONFIG_X86_PAE */
    2.98 +#if !defined(CONFIG_X86_PAE)
    2.99 +define_get_linear_pagetable(root,root)
   2.100 +#endif
   2.101 +#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
   2.102 +define_get_linear_pagetable(l2,l2e)
   2.103 +#endif
   2.104  
   2.105  int
   2.106  get_page_from_l1e(
   2.107 @@ -649,10 +654,15 @@ get_page_from_l2e(
   2.108      }
   2.109  
   2.110      rc = get_page_and_type_from_pagenr(l2e_get_pfn(l2e), PGT_l1_page_table, d);
   2.111 +    if ( unlikely(!rc) )
   2.112 +    {
   2.113  #if CONFIG_PAGING_LEVELS == 2
   2.114 -    if ( unlikely(!rc) )
   2.115 -        rc = get_linear_pagetable(l2e, pfn, d);
   2.116 +        rc = get_root_linear_pagetable(l2e, pfn, d);
   2.117 +#else
   2.118 +        rc = get_l2_linear_pagetable(l2e, pfn, d);
   2.119  #endif
   2.120 +    }
   2.121 +
   2.122      return rc;
   2.123  }
   2.124  
   2.125 @@ -697,7 +707,7 @@ get_page_from_l4e(
   2.126      rc = get_page_and_type_from_pagenr(l4e_get_pfn(l4e), PGT_l3_page_table, d);
   2.127  
   2.128      if ( unlikely(!rc) )
   2.129 -        rc = get_linear_pagetable(l4e, pfn, d);
   2.130 +        rc = get_root_linear_pagetable(l4e, pfn, d);
   2.131  
   2.132      return rc;
   2.133  }