ia64/xen-unstable

changeset 12856:1d83974d08b1

[XEN] Add new safe pte update macros and use as necessary when
updating active pagetables.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu Dec 07 14:57:14 2006 +0000 (2006-12-07)
parents 93314655b16f
children ec9259920f85
files xen/arch/x86/mm.c xen/arch/x86/mm/shadow/multi.c xen/arch/x86/x86_32/domain_page.c xen/arch/x86/x86_32/mm.c xen/arch/x86/x86_64/mm.c xen/include/asm-x86/page.h xen/include/asm-x86/x86_32/page-2level.h xen/include/asm-x86/x86_32/page-3level.h xen/include/asm-x86/x86_64/page.h
line diff
     1.1 --- a/xen/arch/x86/mm.c	Thu Dec 07 14:40:13 2006 +0000
     1.2 +++ b/xen/arch/x86/mm.c	Thu Dec 07 14:57:14 2006 +0000
     1.3 @@ -335,7 +335,7 @@ void make_cr3(struct vcpu *v, unsigned l
     1.4      cache->high_mfn   = mfn;
     1.5  
     1.6      /* Map the guest L3 table and copy to the chosen low-memory cache. */
     1.7 -    *(fix_pae_highmem_pl1e - cpu) = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
     1.8 +    l1e_write(fix_pae_highmem_pl1e-cpu, l1e_from_pfn(mfn, __PAGE_HYPERVISOR));
     1.9      /* First check the previous high mapping can't be in the TLB. 
    1.10       * (i.e. have we loaded CR3 since we last did this?) */
    1.11      if ( unlikely(this_cpu(make_cr3_timestamp) == this_cpu(tlbflush_time)) )
    1.12 @@ -343,7 +343,7 @@ void make_cr3(struct vcpu *v, unsigned l
    1.13      highmem_l3tab = (l3_pgentry_t *)fix_to_virt(FIX_PAE_HIGHMEM_0 + cpu);
    1.14      lowmem_l3tab  = cache->table[cache->inuse_idx];
    1.15      memcpy(lowmem_l3tab, highmem_l3tab, sizeof(cache->table[0]));
    1.16 -    *(fix_pae_highmem_pl1e - cpu) = l1e_empty();
    1.17 +    l1e_write(fix_pae_highmem_pl1e-cpu, l1e_empty());
    1.18      this_cpu(make_cr3_timestamp) = this_cpu(tlbflush_time);
    1.19  
    1.20      v->arch.cr3 = __pa(lowmem_l3tab);
    1.21 @@ -380,7 +380,7 @@ void invalidate_shadow_ldt(struct vcpu *
    1.22      {
    1.23          pfn = l1e_get_pfn(v->arch.perdomain_ptes[i]);
    1.24          if ( pfn == 0 ) continue;
    1.25 -        v->arch.perdomain_ptes[i] = l1e_empty();
    1.26 +        l1e_write(&v->arch.perdomain_ptes[i], l1e_empty());
    1.27          page = mfn_to_page(pfn);
    1.28          ASSERT_PAGE_IS_TYPE(page, PGT_ldt_page);
    1.29          ASSERT_PAGE_IS_DOMAIN(page, v->domain);
    1.30 @@ -449,7 +449,7 @@ int map_ldt_shadow_page(unsigned int off
    1.31  
    1.32      nl1e = l1e_from_pfn(mfn, l1e_get_flags(l1e) | _PAGE_RW);
    1.33  
    1.34 -    v->arch.perdomain_ptes[off + 16] = nl1e;
    1.35 +    l1e_write(&v->arch.perdomain_ptes[off + 16], nl1e);
    1.36      v->arch.shadow_ldt_mapcnt++;
    1.37  
    1.38      return 1;
    1.39 @@ -851,7 +851,7 @@ static int alloc_l1_table(struct page_in
    1.40  static int create_pae_xen_mappings(l3_pgentry_t *pl3e)
    1.41  {
    1.42      struct page_info *page;
    1.43 -    l2_pgentry_t    *pl2e;
    1.44 +    l2_pgentry_t    *pl2e, l2e;
    1.45      l3_pgentry_t     l3e3;
    1.46      int              i;
    1.47  
    1.48 @@ -892,15 +892,19 @@ static int create_pae_xen_mappings(l3_pg
    1.49             &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT],
    1.50             L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
    1.51      for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
    1.52 -        pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
    1.53 -            l2e_from_page(
    1.54 -                virt_to_page(page_get_owner(page)->arch.mm_perdomain_pt) + i,
    1.55 -                __PAGE_HYPERVISOR);
    1.56 +    {
    1.57 +        l2e = l2e_from_page(
    1.58 +            virt_to_page(page_get_owner(page)->arch.mm_perdomain_pt) + i,
    1.59 +            __PAGE_HYPERVISOR);
    1.60 +        l2e_write(&pl2e[l2_table_offset(PERDOMAIN_VIRT_START) + i], l2e);
    1.61 +    }
    1.62      for ( i = 0; i < (LINEARPT_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ )
    1.63 -        pl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i] =
    1.64 -            (l3e_get_flags(pl3e[i]) & _PAGE_PRESENT) ?
    1.65 -            l2e_from_pfn(l3e_get_pfn(pl3e[i]), __PAGE_HYPERVISOR) :
    1.66 -        l2e_empty();
    1.67 +    {
    1.68 +        l2e = l2e_empty();
    1.69 +        if ( l3e_get_flags(pl3e[i]) & _PAGE_PRESENT )
    1.70 +            l2e = l2e_from_pfn(l3e_get_pfn(pl3e[i]), __PAGE_HYPERVISOR);
    1.71 +        l2e_write(&pl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i], l2e);
    1.72 +    }
    1.73      unmap_domain_page(pl2e);
    1.74  
    1.75      return 1;
    1.76 @@ -2760,7 +2764,7 @@ void destroy_gdt(struct vcpu *v)
    1.77      {
    1.78          if ( (pfn = l1e_get_pfn(v->arch.perdomain_ptes[i])) != 0 )
    1.79              put_page_and_type(mfn_to_page(pfn));
    1.80 -        v->arch.perdomain_ptes[i] = l1e_empty();
    1.81 +        l1e_write(&v->arch.perdomain_ptes[i], l1e_empty());
    1.82          v->arch.guest_context.gdt_frames[i] = 0;
    1.83      }
    1.84  }
    1.85 @@ -2794,8 +2798,8 @@ long set_gdt(struct vcpu *v,
    1.86      for ( i = 0; i < nr_pages; i++ )
    1.87      {
    1.88          v->arch.guest_context.gdt_frames[i] = frames[i];
    1.89 -        v->arch.perdomain_ptes[i] =
    1.90 -            l1e_from_pfn(frames[i], __PAGE_HYPERVISOR);
    1.91 +        l1e_write(&v->arch.perdomain_ptes[i],
    1.92 +                  l1e_from_pfn(frames[i], __PAGE_HYPERVISOR));
    1.93      }
    1.94  
    1.95      return 0;
    1.96 @@ -3298,8 +3302,8 @@ int map_pages_to_xen(
    1.97               !map_small_pages )
    1.98          {
    1.99              /* Super-page mapping. */
   1.100 -            ol2e  = *pl2e;
   1.101 -            *pl2e = l2e_from_pfn(mfn, flags|_PAGE_PSE);
   1.102 +            ol2e = *pl2e;
   1.103 +            l2e_write(pl2e, l2e_from_pfn(mfn, flags|_PAGE_PSE));
   1.104  
   1.105              if ( (l2e_get_flags(ol2e) & _PAGE_PRESENT) )
   1.106              {
   1.107 @@ -3319,22 +3323,24 @@ int map_pages_to_xen(
   1.108              {
   1.109                  pl1e = page_to_virt(alloc_xen_pagetable());
   1.110                  clear_page(pl1e);
   1.111 -                *pl2e = l2e_from_page(virt_to_page(pl1e), __PAGE_HYPERVISOR);
   1.112 +                l2e_write(pl2e, l2e_from_page(virt_to_page(pl1e),
   1.113 +                                              __PAGE_HYPERVISOR));
   1.114              }
   1.115              else if ( l2e_get_flags(*pl2e) & _PAGE_PSE )
   1.116              {
   1.117                  pl1e = page_to_virt(alloc_xen_pagetable());
   1.118                  for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
   1.119 -                    pl1e[i] = l1e_from_pfn(
   1.120 -                        l2e_get_pfn(*pl2e) + i,
   1.121 -                        l2e_get_flags(*pl2e) & ~_PAGE_PSE);
   1.122 -                *pl2e = l2e_from_page(virt_to_page(pl1e), __PAGE_HYPERVISOR);
   1.123 +                    l1e_write(&pl1e[i],
   1.124 +                              l1e_from_pfn(l2e_get_pfn(*pl2e) + i,
   1.125 +                                           l2e_get_flags(*pl2e) & ~_PAGE_PSE));
   1.126 +                l2e_write(pl2e, l2e_from_page(virt_to_page(pl1e),
   1.127 +                                              __PAGE_HYPERVISOR));
   1.128                  local_flush_tlb_pge();
   1.129              }
   1.130  
   1.131              pl1e  = l2e_to_l1e(*pl2e) + l1_table_offset(virt);
   1.132              ol1e  = *pl1e;
   1.133 -            *pl1e = l1e_from_pfn(mfn, flags);
   1.134 +            l1e_write(pl1e, l1e_from_pfn(mfn, flags));
   1.135              if ( (l1e_get_flags(ol1e) & _PAGE_PRESENT) )
   1.136                  local_flush_tlb_one(virt);
   1.137  
     2.1 --- a/xen/arch/x86/mm/shadow/multi.c	Thu Dec 07 14:40:13 2006 +0000
     2.2 +++ b/xen/arch/x86/mm/shadow/multi.c	Thu Dec 07 14:57:14 2006 +0000
     2.3 @@ -851,7 +851,9 @@ static inline void safe_write_entry(void
     2.4       * then writing the high word before the low word. */
     2.5      BUILD_BUG_ON(sizeof (shadow_l1e_t) != 2 * sizeof (unsigned long));
     2.6      d[0] = 0;
     2.7 +    wmb();
     2.8      d[1] = s[1];
     2.9 +    wmb();
    2.10      d[0] = s[0];
    2.11  #else
    2.12      /* In 32-bit and 64-bit, sizeof(pte) == sizeof(ulong) == 1 word,
     3.1 --- a/xen/arch/x86/x86_32/domain_page.c	Thu Dec 07 14:40:13 2006 +0000
     3.2 +++ b/xen/arch/x86/x86_32/domain_page.c	Thu Dec 07 14:57:14 2006 +0000
     3.3 @@ -107,7 +107,7 @@ void *map_domain_page(unsigned long mfn)
     3.4  
     3.5      spin_unlock(&cache->lock);
     3.6  
     3.7 -    cache->l1tab[idx] = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
     3.8 +    l1e_write(&cache->l1tab[idx], l1e_from_pfn(mfn, __PAGE_HYPERVISOR));
     3.9  
    3.10   out:
    3.11      va = MAPCACHE_VIRT_START + (idx << PAGE_SHIFT);
    3.12 @@ -147,7 +147,7 @@ void unmap_domain_page(void *va)
    3.13          {
    3.14              /* /First/, zap the PTE. */
    3.15              ASSERT(l1e_get_pfn(cache->l1tab[hashent->idx]) == hashent->mfn);
    3.16 -            cache->l1tab[hashent->idx] = l1e_empty();
    3.17 +            l1e_write(&cache->l1tab[hashent->idx], l1e_empty());
    3.18              /* /Second/, mark as garbage. */
    3.19              set_bit(hashent->idx, cache->garbage);
    3.20          }
    3.21 @@ -159,7 +159,7 @@ void unmap_domain_page(void *va)
    3.22      else
    3.23      {
    3.24          /* /First/, zap the PTE. */
    3.25 -        cache->l1tab[idx] = l1e_empty();
    3.26 +        l1e_write(&cache->l1tab[idx], l1e_empty());
    3.27          /* /Second/, mark as garbage. */
    3.28          set_bit(idx, cache->garbage);
    3.29      }
    3.30 @@ -229,7 +229,7 @@ void *map_domain_page_global(unsigned lo
    3.31  
    3.32      pl2e = virt_to_xen_l2e(va);
    3.33      pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(va);
    3.34 -    *pl1e = l1e_from_pfn(mfn, __PAGE_HYPERVISOR);
    3.35 +    l1e_write(pl1e, l1e_from_pfn(mfn, __PAGE_HYPERVISOR));
    3.36  
    3.37      return (void *)va;
    3.38  }
    3.39 @@ -246,7 +246,7 @@ void unmap_domain_page_global(void *va)
    3.40      /* /First/, we zap the PTE. */
    3.41      pl2e = virt_to_xen_l2e(__va);
    3.42      pl1e = l2e_to_l1e(*pl2e) + l1_table_offset(__va);
    3.43 -    *pl1e = l1e_empty();
    3.44 +    l1e_write(pl1e, l1e_empty());
    3.45  
    3.46      /* /Second/, we add to the garbage map. */
    3.47      idx = (__va - IOREMAP_VIRT_START) >> PAGE_SHIFT;
     4.1 --- a/xen/arch/x86/x86_32/mm.c	Thu Dec 07 14:40:13 2006 +0000
     4.2 +++ b/xen/arch/x86/x86_32/mm.c	Thu Dec 07 14:57:14 2006 +0000
     4.3 @@ -99,11 +99,12 @@ void __init paging_init(void)
     4.4      {
     4.5          if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL )
     4.6              panic("Not enough memory to bootstrap Xen.\n");
     4.7 -        idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i] =
     4.8 -            l2e_from_page(pg, PAGE_HYPERVISOR | _PAGE_PSE);
     4.9 +        l2e_write(&idle_pg_table_l2[l2_linear_offset(RDWR_MPT_VIRT_START) + i],
    4.10 +                  l2e_from_page(pg, PAGE_HYPERVISOR | _PAGE_PSE));
    4.11          /* NB. Cannot be GLOBAL as shadow_mode_translate reuses this area. */
    4.12 -        idle_pg_table_l2[l2_linear_offset(RO_MPT_VIRT_START) + i] =
    4.13 -            l2e_from_page(pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW);
    4.14 +        l2e_write(&idle_pg_table_l2[l2_linear_offset(RO_MPT_VIRT_START) + i],
    4.15 +                  l2e_from_page(
    4.16 +                      pg, (__PAGE_HYPERVISOR | _PAGE_PSE) & ~_PAGE_RW));
    4.17      }
    4.18  
    4.19      /* Fill with an obvious debug pattern. */
    4.20 @@ -115,8 +116,8 @@ void __init paging_init(void)
    4.21      {
    4.22          ioremap_pt = alloc_xenheap_page();
    4.23          clear_page(ioremap_pt);
    4.24 -        idle_pg_table_l2[l2_linear_offset(IOREMAP_VIRT_START) + i] =
    4.25 -            l2e_from_page(virt_to_page(ioremap_pt), __PAGE_HYPERVISOR);
    4.26 +        l2e_write(&idle_pg_table_l2[l2_linear_offset(IOREMAP_VIRT_START) + i],
    4.27 +                  l2e_from_page(virt_to_page(ioremap_pt), __PAGE_HYPERVISOR));
    4.28      }
    4.29  }
    4.30  
    4.31 @@ -125,10 +126,10 @@ void __init setup_idle_pagetable(void)
    4.32      int i;
    4.33  
    4.34      for ( i = 0; i < PDPT_L2_ENTRIES; i++ )
    4.35 -        idle_pg_table_l2[l2_linear_offset(PERDOMAIN_VIRT_START) + i] =
    4.36 -            l2e_from_page(virt_to_page(idle_vcpu[0]->domain->
    4.37 -                                       arch.mm_perdomain_pt) + i,
    4.38 -                          __PAGE_HYPERVISOR);
    4.39 +        l2e_write(&idle_pg_table_l2[l2_linear_offset(PERDOMAIN_VIRT_START)+i],
    4.40 +                  l2e_from_page(virt_to_page(idle_vcpu[0]->domain->
    4.41 +                                             arch.mm_perdomain_pt) + i,
    4.42 +                                __PAGE_HYPERVISOR));
    4.43  }
    4.44  
    4.45  void __init zap_low_mappings(l2_pgentry_t *base)
    4.46 @@ -136,14 +137,16 @@ void __init zap_low_mappings(l2_pgentry_
    4.47      int i;
    4.48      u32 addr;
    4.49  
    4.50 -    for (i = 0; ; i++) {
    4.51 -        addr = (i << L2_PAGETABLE_SHIFT);
    4.52 -        if (addr >= HYPERVISOR_VIRT_START)
    4.53 +    for ( i = 0; ; i++ )
    4.54 +    {
    4.55 +        addr = i << L2_PAGETABLE_SHIFT;
    4.56 +        if ( addr >= HYPERVISOR_VIRT_START )
    4.57              break;
    4.58 -        if (l2e_get_paddr(base[i]) != addr)
    4.59 +        if ( l2e_get_paddr(base[i]) != addr )
    4.60              continue;
    4.61 -        base[i] = l2e_empty();
    4.62 +        l2e_write(&base[i], l2e_empty());
    4.63      }
    4.64 +
    4.65      flush_tlb_all_pge();
    4.66  }
    4.67  
     5.1 --- a/xen/arch/x86/x86_64/mm.c	Thu Dec 07 14:40:13 2006 +0000
     5.2 +++ b/xen/arch/x86/x86_64/mm.c	Thu Dec 07 14:57:14 2006 +0000
     5.3 @@ -59,7 +59,7 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned l
     5.4      {
     5.5          pl3e = page_to_virt(alloc_xen_pagetable());
     5.6          clear_page(pl3e);
     5.7 -        *pl4e = l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR);
     5.8 +        l4e_write(pl4e, l4e_from_paddr(__pa(pl3e), __PAGE_HYPERVISOR));
     5.9      }
    5.10      
    5.11      pl3e = l4e_to_l3e(*pl4e) + l3_table_offset(v);
    5.12 @@ -67,7 +67,7 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned l
    5.13      {
    5.14          pl2e = page_to_virt(alloc_xen_pagetable());
    5.15          clear_page(pl2e);
    5.16 -        *pl3e = l3e_from_paddr(__pa(pl2e), __PAGE_HYPERVISOR);
    5.17 +        l3e_write(pl3e, l3e_from_paddr(__pa(pl2e), __PAGE_HYPERVISOR));
    5.18      }
    5.19      
    5.20      pl2e = l3e_to_l2e(*pl3e) + l2_table_offset(v);
    5.21 @@ -85,8 +85,8 @@ void __init paging_init(void)
    5.22      if ( (l2_pg = alloc_domheap_page(NULL)) == NULL )
    5.23          goto nomem;
    5.24      l3_ro_mpt = clear_page(page_to_virt(l2_pg));
    5.25 -    idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)] =
    5.26 -        l4e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER);
    5.27 +    l4e_write(&idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)],
    5.28 +              l4e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER));
    5.29  
    5.30      /*
    5.31       * Allocate and map the machine-to-phys table.
    5.32 @@ -111,18 +111,19 @@ void __init paging_init(void)
    5.33                  goto nomem;
    5.34              va = RO_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT);
    5.35              l2_ro_mpt = clear_page(page_to_virt(l2_pg));
    5.36 -            l3_ro_mpt[l3_table_offset(va)] =
    5.37 -                l3e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER);
    5.38 +            l3e_write(&l3_ro_mpt[l3_table_offset(va)],
    5.39 +                      l3e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER));
    5.40              l2_ro_mpt += l2_table_offset(va);
    5.41          }
    5.42          /* NB. Cannot be GLOBAL as shadow_mode_translate reuses this area. */
    5.43 -        *l2_ro_mpt++ = l2e_from_page(
    5.44 -            l1_pg, /*_PAGE_GLOBAL|*/_PAGE_PSE|_PAGE_USER|_PAGE_PRESENT);
    5.45 +        l2e_write(l2_ro_mpt, l2e_from_page(
    5.46 +            l1_pg, /*_PAGE_GLOBAL|*/_PAGE_PSE|_PAGE_USER|_PAGE_PRESENT));
    5.47 +        l2_ro_mpt++;
    5.48      }
    5.49  
    5.50      /* Set up linear page table mapping. */
    5.51 -    idle_pg_table[l4_table_offset(LINEAR_PT_VIRT_START)] =
    5.52 -        l4e_from_paddr(__pa(idle_pg_table), __PAGE_HYPERVISOR);
    5.53 +    l4e_write(&idle_pg_table[l4_table_offset(LINEAR_PT_VIRT_START)],
    5.54 +              l4e_from_paddr(__pa(idle_pg_table), __PAGE_HYPERVISOR));
    5.55      return;
    5.56  
    5.57   nomem:
    5.58 @@ -132,15 +133,15 @@ void __init paging_init(void)
    5.59  void __init setup_idle_pagetable(void)
    5.60  {
    5.61      /* Install per-domain mappings for idle domain. */
    5.62 -    idle_pg_table[l4_table_offset(PERDOMAIN_VIRT_START)] =
    5.63 -        l4e_from_page(
    5.64 -            virt_to_page(idle_vcpu[0]->domain->arch.mm_perdomain_l3),
    5.65 -            __PAGE_HYPERVISOR);
    5.66 +    l4e_write(&idle_pg_table[l4_table_offset(PERDOMAIN_VIRT_START)],
    5.67 +              l4e_from_page(
    5.68 +                  virt_to_page(idle_vcpu[0]->domain->arch.mm_perdomain_l3),
    5.69 +                  __PAGE_HYPERVISOR));
    5.70  }
    5.71  
    5.72  void __init zap_low_mappings(void)
    5.73  {
    5.74 -    idle_pg_table[0] = l4e_empty();
    5.75 +    l4e_write(&idle_pg_table[0], l4e_empty());
    5.76      flush_tlb_all_pge();
    5.77  }
    5.78  
     6.1 --- a/xen/include/asm-x86/page.h	Thu Dec 07 14:40:13 2006 +0000
     6.2 +++ b/xen/include/asm-x86/page.h	Thu Dec 07 14:57:14 2006 +0000
     6.3 @@ -33,9 +33,18 @@
     6.4  
     6.5  /* Write a pte atomically to memory. */
     6.6  #define l1e_write_atomic(l1ep, l1e) pte_write_atomic(l1ep, l1e_get_intpte(l1e))
     6.7 -#define l2e_write_atomic(l2ep, l2e) pte_write_atomic(l2ep, l1e_get_intpte(l2e))
     6.8 -#define l3e_write_atomic(l3ep, l3e) pte_write_atomic(l3ep, l1e_get_intpte(l3e))
     6.9 -#define l4e_write_atomic(l4ep, l4e) pte_write_atomic(l4ep, l1e_get_intpte(l4e))
    6.10 +#define l2e_write_atomic(l2ep, l2e) pte_write_atomic(l2ep, l2e_get_intpte(l2e))
    6.11 +#define l3e_write_atomic(l3ep, l3e) pte_write_atomic(l3ep, l3e_get_intpte(l3e))
    6.12 +#define l4e_write_atomic(l4ep, l4e) pte_write_atomic(l4ep, l4e_get_intpte(l4e))
    6.13 +
    6.14 +/*
    6.15 + * Write a pte safely but non-atomically to memory.
    6.16 + * The PTE may become temporarily not-present during the update.
    6.17 + */
    6.18 +#define l1e_write(l1ep, l1e) pte_write(l1ep, l1e_get_intpte(l1e))
    6.19 +#define l2e_write(l2ep, l2e) pte_write(l2ep, l2e_get_intpte(l2e))
    6.20 +#define l3e_write(l3ep, l3e) pte_write(l3ep, l3e_get_intpte(l3e))
    6.21 +#define l4e_write(l4ep, l4e) pte_write(l4ep, l4e_get_intpte(l4e))
    6.22  
    6.23  /* Get direct integer representation of a pte's contents (intpte_t). */
    6.24  #define l1e_get_intpte(x)          ((x).l1)
     7.1 --- a/xen/include/asm-x86/x86_32/page-2level.h	Thu Dec 07 14:40:13 2006 +0000
     7.2 +++ b/xen/include/asm-x86/x86_32/page-2level.h	Thu Dec 07 14:57:14 2006 +0000
     7.3 @@ -29,7 +29,8 @@ typedef l2_pgentry_t root_pgentry_t;
     7.4  #endif /* !__ASSEMBLY__ */
     7.5  
     7.6  #define pte_read_atomic(ptep)       (*(intpte_t *)(ptep))
     7.7 -#define pte_write_atomic(ptep, pte) (*(intpte_t *)(ptep)) = (pte))
     7.8 +#define pte_write_atomic(ptep, pte) ((*(intpte_t *)(ptep)) = (pte))
     7.9 +#define pte_write(ptep, pte)        ((*(intpte_t *)(ptep)) = (pte))
    7.10  
    7.11  /* root table */
    7.12  #define root_get_pfn              l2e_get_pfn
     8.1 --- a/xen/include/asm-x86/x86_32/page-3level.h	Thu Dec 07 14:40:13 2006 +0000
     8.2 +++ b/xen/include/asm-x86/x86_32/page-3level.h	Thu Dec 07 14:57:14 2006 +0000
     8.3 @@ -48,6 +48,13 @@ typedef l3_pgentry_t root_pgentry_t;
     8.4      while ( (__npte = cmpxchg((intpte_t *)(ptep), __pte, (pte))) != __pte ) \
     8.5          __pte = __npte;                                                     \
     8.6  } while ( 0 )
     8.7 +#define pte_write(ptep, pte) do {               \
     8.8 +    *((u32 *)(ptep)+0) = 0;                     \
     8.9 +    wmb();                                      \
    8.10 +    *((u32 *)(ptep)+1) = (pte) >> 32;           \
    8.11 +    wmb();                                      \
    8.12 +    *((u32 *)(ptep)+0) = (pte) >>  0;           \
    8.13 +} while ( 0 )
    8.14  
    8.15  /* root table */
    8.16  #define root_get_pfn              l3e_get_pfn
     9.1 --- a/xen/include/asm-x86/x86_64/page.h	Thu Dec 07 14:40:13 2006 +0000
     9.2 +++ b/xen/include/asm-x86/x86_64/page.h	Thu Dec 07 14:57:14 2006 +0000
     9.3 @@ -44,7 +44,8 @@ typedef l4_pgentry_t root_pgentry_t;
     9.4  #endif /* !__ASSEMBLY__ */
     9.5  
     9.6  #define pte_read_atomic(ptep)       (*(intpte_t *)(ptep))
     9.7 -#define pte_write_atomic(ptep, pte) (*(intpte_t *)(ptep)) = (pte))
     9.8 +#define pte_write_atomic(ptep, pte) ((*(intpte_t *)(ptep)) = (pte))
     9.9 +#define pte_write(ptep, pte)        ((*(intpte_t *)(ptep)) = (pte))
    9.10  
    9.11  /* Given a virtual address, get an entry offset into a linear page table. */
    9.12  #define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> L1_PAGETABLE_SHIFT)