ia64/xen-unstable

changeset 16921:ed8ab1a36b09

x86-64: use 1GB pages in 1:1 mapping if available

At once adjust the 2/4Mb page handling slightly in a few places (to
match the newly added code):
- when re-creating a large page mapping after finding that all small
page mappings in the respective area are using identical flags and
suitable MFNs, the virtual address was already incremented pas the
area to be dealt with, which needs to be accounted for in the
invocation of flush_area() in that path
- don't or-in/and-out _PAGE_PSE on non-present pages
- when comparing flags, try minimse the number of l1f_to_lNf()/
lNf_to_l1f() instances used
- instead of skipping a single page when encountering a big page
mapping equalling to what a small page mapping would establish, skip
to the next larger page boundary

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Jan 28 10:17:05 2008 +0000 (2008-01-28)
parents 1fbab289fed1
children ed2ca78286a8
files xen/arch/x86/mm.c xen/arch/x86/setup.c xen/arch/x86/x86_64/mm.c xen/arch/x86/x86_64/traps.c xen/include/asm-x86/page.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Mon Jan 28 09:33:57 2008 +0000
     1.2 +++ b/xen/arch/x86/mm.c	Mon Jan 28 10:17:05 2008 +0000
     1.3 @@ -3684,8 +3684,9 @@ void free_xen_pagetable(void *v)
     1.4  {
     1.5      extern int early_boot;
     1.6  
     1.7 -    BUG_ON(early_boot);
     1.8 -    
     1.9 +    if ( early_boot )
    1.10 +        return;
    1.11 +
    1.12      if ( is_xen_heap_page(virt_to_page(v)) )
    1.13          free_xenheap_page(v);
    1.14      else
    1.15 @@ -3693,8 +3694,8 @@ void free_xen_pagetable(void *v)
    1.16  }
    1.17  
    1.18  /* Convert to from superpage-mapping flags for map_pages_to_xen(). */
    1.19 -#define l1f_to_l2f(f) ((f) | _PAGE_PSE)
    1.20 -#define l2f_to_l1f(f) ((f) & ~_PAGE_PSE)
    1.21 +#define l1f_to_lNf(f) (((f) & _PAGE_PRESENT) ? ((f) |  _PAGE_PSE) : (f))
    1.22 +#define lNf_to_l1f(f) (((f) & _PAGE_PRESENT) ? ((f) & ~_PAGE_PSE) : (f))
    1.23  
    1.24  /*
    1.25   * map_pages_to_xen() can be called with interrupts disabled:
    1.26 @@ -3720,6 +3721,127 @@ int map_pages_to_xen(
    1.27  
    1.28      while ( nr_mfns != 0 )
    1.29      {
    1.30 +#ifdef __x86_64__
    1.31 +        l3_pgentry_t *pl3e = virt_to_xen_l3e(virt);
    1.32 +        l3_pgentry_t ol3e = *pl3e;
    1.33 +
    1.34 +        if ( cpu_has_page1gb &&
    1.35 +             !(((virt >> PAGE_SHIFT) | mfn) &
    1.36 +               ((1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)) - 1)) &&
    1.37 +             nr_mfns >= (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)) &&
    1.38 +             !(flags & (_PAGE_PAT | MAP_SMALL_PAGES)) )
    1.39 +        {
    1.40 +            /* 1GB-page mapping. */
    1.41 +            l3e_write_atomic(pl3e, l3e_from_pfn(mfn, l1f_to_lNf(flags)));
    1.42 +
    1.43 +            if ( (l3e_get_flags(ol3e) & _PAGE_PRESENT) )
    1.44 +            {
    1.45 +                unsigned int flush_flags =
    1.46 +                    FLUSH_TLB | FLUSH_ORDER(2 * PAGETABLE_ORDER);
    1.47 +
    1.48 +                if ( l3e_get_flags(ol3e) & _PAGE_PSE )
    1.49 +                {
    1.50 +                    if ( l3e_get_flags(ol3e) & _PAGE_GLOBAL )
    1.51 +                        flush_flags |= FLUSH_TLB_GLOBAL;
    1.52 +                    if ( (l1f_to_lNf(l3e_get_flags(ol3e)) ^ flags) &
    1.53 +                         PAGE_CACHE_ATTRS )
    1.54 +                        flush_flags |= FLUSH_CACHE;
    1.55 +                    flush_area(virt, flush_flags);
    1.56 +                }
    1.57 +                else
    1.58 +                {
    1.59 +                    pl2e = l3e_to_l2e(ol3e);
    1.60 +                    for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
    1.61 +                    {
    1.62 +                        ol2e = pl2e[i];
    1.63 +                        if ( !(l2e_get_flags(ol2e) & _PAGE_PRESENT) )
    1.64 +                            continue;
    1.65 +                        if ( l2e_get_flags(ol2e) & _PAGE_PSE )
    1.66 +                        {
    1.67 +                            if ( l2e_get_flags(ol2e) & _PAGE_GLOBAL )
    1.68 +                                flush_flags |= FLUSH_TLB_GLOBAL;
    1.69 +                            if ( (lNf_to_l1f(l2e_get_flags(ol2e)) ^ flags) &
    1.70 +                                 PAGE_CACHE_ATTRS )
    1.71 +                                flush_flags |= FLUSH_CACHE;
    1.72 +                        }
    1.73 +                        else
    1.74 +                        {
    1.75 +                            unsigned int j;
    1.76 +
    1.77 +                            pl1e = l2e_to_l1e(ol2e);
    1.78 +                            for ( j = 0; j < L1_PAGETABLE_ENTRIES; j++ )
    1.79 +                            {
    1.80 +                                ol1e = pl1e[j];
    1.81 +                                if ( l1e_get_flags(ol1e) & _PAGE_GLOBAL )
    1.82 +                                    flush_flags |= FLUSH_TLB_GLOBAL;
    1.83 +                                if ( (l1e_get_flags(ol1e) ^ flags) &
    1.84 +                                     PAGE_CACHE_ATTRS )
    1.85 +                                    flush_flags |= FLUSH_CACHE;
    1.86 +                            }
    1.87 +                        }
    1.88 +                    }
    1.89 +                    flush_area(virt, flush_flags);
    1.90 +                    for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
    1.91 +                    {
    1.92 +                        ol2e = pl2e[i];
    1.93 +                        if ( (l2e_get_flags(ol2e) & _PAGE_PRESENT) &&
    1.94 +                             !(l2e_get_flags(ol2e) & _PAGE_PSE) )
    1.95 +                            free_xen_pagetable(l2e_to_l1e(ol2e));
    1.96 +                    }
    1.97 +                    free_xen_pagetable(pl2e);
    1.98 +                }
    1.99 +            }
   1.100 +
   1.101 +            virt    += 1UL << L3_PAGETABLE_SHIFT;
   1.102 +            mfn     += 1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT);
   1.103 +            nr_mfns -= 1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT);
   1.104 +            continue;
   1.105 +        }
   1.106 +
   1.107 +        if ( (l3e_get_flags(ol3e) & _PAGE_PRESENT) &&
   1.108 +             (l3e_get_flags(ol3e) & _PAGE_PSE) )
   1.109 +        {
   1.110 +            unsigned int flush_flags =
   1.111 +                FLUSH_TLB | FLUSH_ORDER(2 * PAGETABLE_ORDER);
   1.112 +
   1.113 +            /* Skip this PTE if there is no change. */
   1.114 +            if ( ((l3e_get_pfn(ol3e) & ~(L2_PAGETABLE_ENTRIES *
   1.115 +                                         L1_PAGETABLE_ENTRIES - 1)) +
   1.116 +                  (l2_table_offset(virt) << PAGETABLE_ORDER) +
   1.117 +                  l1_table_offset(virt) == mfn) &&
   1.118 +                 ((lNf_to_l1f(l3e_get_flags(ol3e)) ^ flags) &
   1.119 +                  ~(_PAGE_ACCESSED|_PAGE_DIRTY)) == 0 )
   1.120 +            {
   1.121 +                /* We can skip to end of L3 superpage if we got a match. */
   1.122 +                i = (1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)) -
   1.123 +                    (mfn & ((1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)) - 1));
   1.124 +                if ( i > nr_mfns )
   1.125 +                    i = nr_mfns;
   1.126 +                virt    += i << PAGE_SHIFT;
   1.127 +                mfn     += i;
   1.128 +                nr_mfns -= i;
   1.129 +                continue;
   1.130 +            }
   1.131 +
   1.132 +            pl2e = alloc_xen_pagetable();
   1.133 +            if ( pl2e == NULL )
   1.134 +                return -ENOMEM;
   1.135 +
   1.136 +            for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
   1.137 +                l2e_write(pl2e + i,
   1.138 +                          l2e_from_pfn(l3e_get_pfn(ol3e) +
   1.139 +                                       (i << PAGETABLE_ORDER),
   1.140 +                                       l3e_get_flags(ol3e)));
   1.141 +
   1.142 +            if ( l3e_get_flags(ol3e) & _PAGE_GLOBAL )
   1.143 +                flush_flags |= FLUSH_TLB_GLOBAL;
   1.144 +
   1.145 +            l3e_write_atomic(pl3e, l3e_from_pfn(virt_to_mfn(pl2e),
   1.146 +                                                __PAGE_HYPERVISOR));
   1.147 +            flush_area(virt, flush_flags);
   1.148 +        }
   1.149 +#endif
   1.150 +
   1.151          pl2e = virt_to_xen_l2e(virt);
   1.152  
   1.153          if ( ((((virt>>PAGE_SHIFT) | mfn) & ((1<<PAGETABLE_ORDER)-1)) == 0) &&
   1.154 @@ -3728,7 +3850,7 @@ int map_pages_to_xen(
   1.155          {
   1.156              /* Super-page mapping. */
   1.157              ol2e = *pl2e;
   1.158 -            l2e_write_atomic(pl2e, l2e_from_pfn(mfn, l1f_to_l2f(flags)));
   1.159 +            l2e_write_atomic(pl2e, l2e_from_pfn(mfn, l1f_to_lNf(flags)));
   1.160  
   1.161              if ( (l2e_get_flags(ol2e) & _PAGE_PRESENT) )
   1.162              {
   1.163 @@ -3739,8 +3861,8 @@ int map_pages_to_xen(
   1.164                  {
   1.165                      if ( l2e_get_flags(ol2e) & _PAGE_GLOBAL )
   1.166                          flush_flags |= FLUSH_TLB_GLOBAL;
   1.167 -                    if ( (l2e_get_flags(ol2e) ^ l1f_to_l2f(flags)) &
   1.168 -                         l1f_to_l2f(PAGE_CACHE_ATTRS) )
   1.169 +                    if ( (lNf_to_l1f(l2e_get_flags(ol2e)) ^ flags) &
   1.170 +                         PAGE_CACHE_ATTRS )
   1.171                          flush_flags |= FLUSH_CACHE;
   1.172                      flush_area(virt, flush_flags);
   1.173                  }
   1.174 @@ -3784,13 +3906,18 @@ int map_pages_to_xen(
   1.175                  /* Skip this PTE if there is no change. */
   1.176                  if ( (((l2e_get_pfn(*pl2e) & ~(L1_PAGETABLE_ENTRIES - 1)) +
   1.177                         l1_table_offset(virt)) == mfn) &&
   1.178 -                     (((l2f_to_l1f(l2e_get_flags(*pl2e)) ^ flags) &
   1.179 +                     (((lNf_to_l1f(l2e_get_flags(*pl2e)) ^ flags) &
   1.180                         ~(_PAGE_ACCESSED|_PAGE_DIRTY)) == 0) )
   1.181                  {
   1.182 -                    virt    += 1UL << L1_PAGETABLE_SHIFT;
   1.183 -                    mfn     += 1UL;
   1.184 -                    nr_mfns -= 1UL;
   1.185 -                    continue;
   1.186 +                    /* We can skip to end of L2 superpage if we got a match. */
   1.187 +                    i = (1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT)) -
   1.188 +                        (mfn & ((1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT)) - 1));
   1.189 +                    if ( i > nr_mfns )
   1.190 +                        i = nr_mfns;
   1.191 +                    virt    += i << L1_PAGETABLE_SHIFT;
   1.192 +                    mfn     += i;
   1.193 +                    nr_mfns -= i;
   1.194 +                    goto check_l3;
   1.195                  }
   1.196  
   1.197                  pl1e = alloc_xen_pagetable();
   1.198 @@ -3800,7 +3927,7 @@ int map_pages_to_xen(
   1.199                  for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
   1.200                      l1e_write(&pl1e[i],
   1.201                                l1e_from_pfn(l2e_get_pfn(*pl2e) + i,
   1.202 -                                           l2f_to_l1f(l2e_get_flags(*pl2e))));
   1.203 +                                           lNf_to_l1f(l2e_get_flags(*pl2e))));
   1.204  
   1.205                  if ( l2e_get_flags(*pl2e) & _PAGE_GLOBAL )
   1.206                      flush_flags |= FLUSH_TLB_GLOBAL;
   1.207 @@ -3843,13 +3970,45 @@ int map_pages_to_xen(
   1.208                  {
   1.209                      ol2e = *pl2e;
   1.210                      l2e_write_atomic(pl2e, l2e_from_pfn(base_mfn,
   1.211 -                                                        l1f_to_l2f(flags)));
   1.212 -                    flush_area(virt, (FLUSH_TLB_GLOBAL |
   1.213 -                                      FLUSH_ORDER(PAGETABLE_ORDER)));
   1.214 +                                                        l1f_to_lNf(flags)));
   1.215 +                    flush_area(virt - PAGE_SIZE,
   1.216 +                               FLUSH_TLB_GLOBAL |
   1.217 +                               FLUSH_ORDER(PAGETABLE_ORDER));
   1.218                      free_xen_pagetable(l2e_to_l1e(ol2e));
   1.219                  }
   1.220              }
   1.221          }
   1.222 +
   1.223 + check_l3: ;
   1.224 +#ifdef __x86_64__
   1.225 +        if ( cpu_has_page1gb &&
   1.226 +             (flags == PAGE_HYPERVISOR) &&
   1.227 +             ((nr_mfns == 0) ||
   1.228 +              !(((virt >> PAGE_SHIFT) | mfn) &
   1.229 +                ((1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT)) - 1))) )
   1.230 +        {
   1.231 +            unsigned long base_mfn;
   1.232 +
   1.233 +            ol3e = *pl3e;
   1.234 +            pl2e = l3e_to_l2e(ol3e);
   1.235 +            base_mfn = l2e_get_pfn(*pl2e) & ~(L2_PAGETABLE_ENTRIES *
   1.236 +                                              L1_PAGETABLE_ENTRIES - 1);
   1.237 +            for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++, pl2e++ )
   1.238 +                if ( (l2e_get_pfn(*pl2e) !=
   1.239 +                      (base_mfn + (i << PAGETABLE_ORDER))) ||
   1.240 +                     (l2e_get_flags(*pl2e) != l1f_to_lNf(flags)) )
   1.241 +                    break;
   1.242 +            if ( i == L2_PAGETABLE_ENTRIES )
   1.243 +            {
   1.244 +                l3e_write_atomic(pl3e, l3e_from_pfn(base_mfn,
   1.245 +                                                    l1f_to_lNf(flags)));
   1.246 +                flush_area(virt - PAGE_SIZE,
   1.247 +                           FLUSH_TLB_GLOBAL |
   1.248 +                           FLUSH_ORDER(2*PAGETABLE_ORDER));
   1.249 +                free_xen_pagetable(l3e_to_l2e(ol3e));
   1.250 +            }
   1.251 +        }
   1.252 +#endif
   1.253      }
   1.254  
   1.255      return 0;
   1.256 @@ -3867,6 +4026,40 @@ void destroy_xen_mappings(unsigned long 
   1.257  
   1.258      while ( v < e )
   1.259      {
   1.260 +#ifdef __x86_64__
   1.261 +        l3_pgentry_t *pl3e = virt_to_xen_l3e(v);
   1.262 +
   1.263 +        if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
   1.264 +        {
   1.265 +            v += 1UL << L3_PAGETABLE_SHIFT;
   1.266 +            v &= ~((1UL << L3_PAGETABLE_SHIFT) - 1);
   1.267 +            continue;
   1.268 +        }
   1.269 +
   1.270 +        if ( l3e_get_flags(*pl3e) & _PAGE_PSE )
   1.271 +        {
   1.272 +            if ( l2_table_offset(v) == 0 &&
   1.273 +                 l1_table_offset(v) == 0 &&
   1.274 +                 ((e - v) >= (1UL << L3_PAGETABLE_SHIFT)) )
   1.275 +            {
   1.276 +                /* PAGE1GB: whole superpage is destroyed. */
   1.277 +                l3e_write_atomic(pl3e, l3e_empty());
   1.278 +                v += 1UL << L3_PAGETABLE_SHIFT;
   1.279 +                continue;
   1.280 +            }
   1.281 +
   1.282 +            /* PAGE1GB: shatter the superpage and fall through. */
   1.283 +            pl2e = alloc_xen_pagetable();
   1.284 +            for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
   1.285 +                l2e_write(pl2e + i,
   1.286 +                          l2e_from_pfn(l3e_get_pfn(*pl3e) +
   1.287 +                                       (i << PAGETABLE_ORDER),
   1.288 +                                       l3e_get_flags(*pl3e)));
   1.289 +            l3e_write_atomic(pl3e, l3e_from_pfn(virt_to_mfn(pl2e),
   1.290 +                                                __PAGE_HYPERVISOR));
   1.291 +        }
   1.292 +#endif
   1.293 +
   1.294          pl2e = virt_to_xen_l2e(v);
   1.295  
   1.296          if ( !(l2e_get_flags(*pl2e) & _PAGE_PRESENT) )
   1.297 @@ -3919,6 +4112,23 @@ void destroy_xen_mappings(unsigned long 
   1.298                  free_xen_pagetable(pl1e);
   1.299              }
   1.300          }
   1.301 +
   1.302 +#ifdef __x86_64__
   1.303 +        /* If we are done with the L3E, check if it is now empty. */
   1.304 +        if ( (v != e) && (l2_table_offset(v) + l1_table_offset(v) != 0) )
   1.305 +            continue;
   1.306 +        pl2e = l3e_to_l2e(*pl3e);
   1.307 +        for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
   1.308 +            if ( l2e_get_intpte(pl2e[i]) != 0 )
   1.309 +                break;
   1.310 +        if ( i == L2_PAGETABLE_ENTRIES )
   1.311 +        {
   1.312 +            /* Empty: zap the L3E and free the L2 page. */
   1.313 +            l3e_write_atomic(pl3e, l3e_empty());
   1.314 +            flush_area(NULL, FLUSH_TLB_GLOBAL); /* flush before free */
   1.315 +            free_xen_pagetable(pl2e);
   1.316 +        }
   1.317 +#endif
   1.318      }
   1.319  
   1.320      flush_area(NULL, FLUSH_TLB_GLOBAL);
     2.1 --- a/xen/arch/x86/setup.c	Mon Jan 28 09:33:57 2008 +0000
     2.2 +++ b/xen/arch/x86/setup.c	Mon Jan 28 10:17:05 2008 +0000
     2.3 @@ -674,8 +674,9 @@ void __init __start_xen(unsigned long mb
     2.4                  pl3e = l4e_to_l3e(*pl4e);
     2.5                  for ( j = 0; j < L3_PAGETABLE_ENTRIES; j++, pl3e++ )
     2.6                  {
     2.7 -                    /* Not present or already relocated? */
     2.8 +                    /* Not present, 1GB mapping, or already relocated? */
     2.9                      if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) ||
    2.10 +                         (l3e_get_flags(*pl3e) & _PAGE_PSE) ||
    2.11                           (l3e_get_pfn(*pl3e) > 0x1000) )
    2.12                          continue;
    2.13                      *pl3e = l3e_from_intpte(l3e_get_intpte(*pl3e) +
     3.1 --- a/xen/arch/x86/x86_64/mm.c	Mon Jan 28 09:33:57 2008 +0000
     3.2 +++ b/xen/arch/x86/x86_64/mm.c	Mon Jan 28 10:17:05 2008 +0000
     3.3 @@ -69,30 +69,35 @@ void *alloc_xen_pagetable(void)
     3.4      return mfn_to_virt(mfn);
     3.5  }
     3.6  
     3.7 -l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
     3.8 +l3_pgentry_t *virt_to_xen_l3e(unsigned long v)
     3.9  {
    3.10      l4_pgentry_t *pl4e;
    3.11 -    l3_pgentry_t *pl3e;
    3.12 -    l2_pgentry_t *pl2e;
    3.13  
    3.14      pl4e = &idle_pg_table[l4_table_offset(v)];
    3.15      if ( !(l4e_get_flags(*pl4e) & _PAGE_PRESENT) )
    3.16      {
    3.17 -        pl3e = alloc_xen_pagetable();
    3.18 +        l3_pgentry_t *pl3e = alloc_xen_pagetable();
    3.19          clear_page(pl3e);
    3.20          l4e_write(pl4e, l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR));
    3.21      }
    3.22      
    3.23 -    pl3e = l4e_to_l3e(*pl4e) + l3_table_offset(v);
    3.24 +    return l4e_to_l3e(*pl4e) + l3_table_offset(v);
    3.25 +}
    3.26 +
    3.27 +l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
    3.28 +{
    3.29 +    l3_pgentry_t *pl3e;
    3.30 +
    3.31 +    pl3e = virt_to_xen_l3e(v);
    3.32      if ( !(l3e_get_flags(*pl3e) & _PAGE_PRESENT) )
    3.33      {
    3.34 -        pl2e = alloc_xen_pagetable();
    3.35 +        l2_pgentry_t *pl2e = alloc_xen_pagetable();
    3.36          clear_page(pl2e);
    3.37          l3e_write(pl3e, l3e_from_paddr(__pa(pl2e), __PAGE_HYPERVISOR));
    3.38      }
    3.39 -    
    3.40 -    pl2e = l3e_to_l2e(*pl3e) + l2_table_offset(v);
    3.41 -    return pl2e;
    3.42 +
    3.43 +    BUG_ON(l3e_get_flags(*pl3e) & _PAGE_PSE);
    3.44 +    return l3e_to_l2e(*pl3e) + l2_table_offset(v);
    3.45  }
    3.46  
    3.47  void __init paging_init(void)
     4.1 --- a/xen/arch/x86/x86_64/traps.c	Mon Jan 28 09:33:57 2008 +0000
     4.2 +++ b/xen/arch/x86/x86_64/traps.c	Mon Jan 28 10:17:05 2008 +0000
     4.3 @@ -146,9 +146,11 @@ void show_page_walk(unsigned long addr)
     4.4      l3e = l3t[l3_table_offset(addr)];
     4.5      mfn = l3e_get_pfn(l3e);
     4.6      pfn = mfn_valid(mfn) ? get_gpfn_from_mfn(mfn) : INVALID_M2P_ENTRY;
     4.7 -    printk(" L3[0x%03lx] = %"PRIpte" %016lx\n",
     4.8 -           l3_table_offset(addr), l3e_get_intpte(l3e), pfn);
     4.9 -    if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
    4.10 +    printk(" L3[0x%03lx] = %"PRIpte" %016lx%s\n",
    4.11 +           l3_table_offset(addr), l3e_get_intpte(l3e), pfn,
    4.12 +           (l3e_get_flags(l3e) & _PAGE_PSE) ? " (PSE)" : "");
    4.13 +    if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ||
    4.14 +         (l3e_get_flags(l3e) & _PAGE_PSE) )
    4.15          return;
    4.16  
    4.17      l2t = mfn_to_virt(mfn);
     5.1 --- a/xen/include/asm-x86/page.h	Mon Jan 28 09:33:57 2008 +0000
     5.2 +++ b/xen/include/asm-x86/page.h	Mon Jan 28 10:17:05 2008 +0000
     5.3 @@ -350,6 +350,9 @@ static inline int get_order_from_pages(u
     5.4  void *alloc_xen_pagetable(void);
     5.5  void free_xen_pagetable(void *v);
     5.6  l2_pgentry_t *virt_to_xen_l2e(unsigned long v);
     5.7 +#ifdef __x86_64__
     5.8 +l3_pgentry_t *virt_to_xen_l3e(unsigned long v);
     5.9 +#endif
    5.10  
    5.11  /* Map machine page range in Xen virtual address space. */
    5.12  #define MAP_SMALL_PAGES _PAGE_AVAIL0 /* don't use superpages for the mapping */