ia64/xen-unstable

changeset 3753:0d53bdb43b1c

bitkeeper revision 1.1159.1.559 (4209e312Ii3Tsz9q9NZb2CbM0b1BzA)

More x86_64 work. do_mmu_update and update_va_mapping are now done.
Still todo: 1. exception/interrupt callbacks to guest OS
2. OS ring 3 vs. application ring 3
3. writable pagetables and shadow pagetables
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Wed Feb 09 10:16:50 2005 +0000 (2005-02-09)
parents 0e59227addd8
children 2318bacbb21e be9bb69e54cf
files xen/arch/x86/Makefile xen/arch/x86/domain.c xen/arch/x86/mm.c xen/arch/x86/x86_64/domain_build.c xen/include/asm-x86/config.h xen/include/asm-x86/domain.h xen/include/asm-x86/page.h xen/include/asm-x86/x86_32/page.h xen/include/asm-x86/x86_64/page.h
line diff
     1.1 --- a/xen/arch/x86/Makefile	Wed Feb 09 02:59:54 2005 +0000
     1.2 +++ b/xen/arch/x86/Makefile	Wed Feb 09 10:16:50 2005 +0000
     1.3 @@ -8,10 +8,7 @@ OBJS += $(patsubst %.c,%.o,$(wildcard mt
     1.4  OBJS := $(subst $(TARGET_SUBARCH)/asm-offsets.o,,$(OBJS))
     1.5  
     1.6  ifneq ($(TARGET_SUBARCH),x86_32)
     1.7 -OBJS := $(subst vmx.o,,$(OBJS))
     1.8 -OBJS := $(subst vmx_io.o,,$(OBJS))
     1.9 -OBJS := $(subst vmx_platform.o,,$(OBJS))
    1.10 -OBJS := $(subst vmx_vmcs.o,,$(OBJS))
    1.11 +OBJS := $(patsubst vmx%.o,,$(OBJS))
    1.12  endif
    1.13  
    1.14  default: $(TARGET)
     2.1 --- a/xen/arch/x86/domain.c	Wed Feb 09 02:59:54 2005 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Wed Feb 09 10:16:50 2005 +0000
     2.3 @@ -233,6 +233,10 @@ void arch_free_exec_domain_struct(struct
     2.4  void free_perdomain_pt(struct domain *d)
     2.5  {
     2.6      free_xenheap_page((unsigned long)d->arch.mm_perdomain_pt);
     2.7 +#ifdef __x86_64__
     2.8 +    free_xenheap_page((unsigned long)d->arch.mm_perdomain_l2);
     2.9 +    free_xenheap_page((unsigned long)d->arch.mm_perdomain_l3);
    2.10 +#endif
    2.11  }
    2.12  
    2.13  static void continue_idle_task(struct exec_domain *ed)
    2.14 @@ -271,6 +275,17 @@ void arch_do_createdomain(struct exec_do
    2.15          machine_to_phys_mapping[virt_to_phys(d->arch.mm_perdomain_pt) >> 
    2.16                                 PAGE_SHIFT] = INVALID_P2M_ENTRY;
    2.17          ed->arch.perdomain_ptes = d->arch.mm_perdomain_pt;
    2.18 +
    2.19 +#ifdef __x86_64__
    2.20 +        d->arch.mm_perdomain_l2 = (l2_pgentry_t *)alloc_xenheap_page();
    2.21 +        memset(d->arch.mm_perdomain_l2, 0, PAGE_SIZE);
    2.22 +        d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)] = 
    2.23 +            mk_l2_pgentry(__pa(d->arch.mm_perdomain_pt) | __PAGE_HYPERVISOR);
    2.24 +        d->arch.mm_perdomain_l3 = (l3_pgentry_t *)alloc_xenheap_page();
    2.25 +        memset(d->arch.mm_perdomain_l3, 0, PAGE_SIZE);
    2.26 +        d->arch.mm_perdomain_l3[l3_table_offset(PERDOMAIN_VIRT_START)] = 
    2.27 +            mk_l3_pgentry(__pa(d->arch.mm_perdomain_l2) | __PAGE_HYPERVISOR);
    2.28 +#endif
    2.29      }
    2.30  }
    2.31  
    2.32 @@ -322,12 +337,12 @@ static void monitor_mk_pagetable(struct 
    2.33      ed->arch.monitor_table = mk_pagetable(mpfn << PAGE_SHIFT);
    2.34      d->arch.shadow_mode = SHM_full_32;
    2.35  
    2.36 -    mpl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
    2.37 +    mpl2e[l2_table_offset(PERDOMAIN_VIRT_START)] =
    2.38          mk_l2_pgentry((__pa(d->arch.mm_perdomain_pt) & PAGE_MASK) 
    2.39                        | __PAGE_HYPERVISOR);
    2.40  
    2.41 -    phys_table = (l2_pgentry_t *) map_domain_mem(pagetable_val(
    2.42 -                                        ed->arch.phys_table));
    2.43 +    phys_table = (l2_pgentry_t *)
    2.44 +        map_domain_mem(pagetable_val(ed->arch.phys_table));
    2.45      memcpy(d->arch.mm_perdomain_pt, phys_table,
    2.46             L1_PAGETABLE_ENTRIES * sizeof(l1_pgentry_t));
    2.47  
    2.48 @@ -345,7 +360,8 @@ static void monitor_rm_pagetable(struct 
    2.49  
    2.50      ASSERT( pagetable_val(ed->arch.monitor_table) );
    2.51      
    2.52 -    mpl2e = (l2_pgentry_t *) map_domain_mem(pagetable_val(ed->arch.monitor_table));
    2.53 +    mpl2e = (l2_pgentry_t *)
    2.54 +        map_domain_mem(pagetable_val(ed->arch.monitor_table));
    2.55      /*
    2.56       * First get the pfn for guest_pl2e_cache by looking at monitor_table
    2.57       */
    2.58 @@ -384,8 +400,10 @@ static int vmx_final_setup_guestos(struc
    2.59      memset(&ed->arch.arch_vmx, 0, sizeof (struct arch_vmx_struct));
    2.60  
    2.61      ed->arch.arch_vmx.vmcs = vmcs;
    2.62 -    error = construct_vmcs(&ed->arch.arch_vmx, context, full_context, VMCS_USE_HOST_ENV);
    2.63 -    if (error < 0) {
    2.64 +    error = construct_vmcs(
    2.65 +        &ed->arch.arch_vmx, context, full_context, VMCS_USE_HOST_ENV);
    2.66 +    if ( error < 0 )
    2.67 +    {
    2.68          printk("Failed to construct a new VMCS\n");
    2.69          goto out;
    2.70      }
     3.1 --- a/xen/arch/x86/mm.c	Wed Feb 09 02:59:54 2005 +0000
     3.2 +++ b/xen/arch/x86/mm.c	Wed Feb 09 10:16:50 2005 +0000
     3.3 @@ -281,8 +281,9 @@ int map_ldt_shadow_page(unsigned int off
     3.4                 &linear_pg_table[l1_linear_offset(ed->arch.ldt_base) + off]);
     3.5  
     3.6      if ( unlikely(!(l1e & _PAGE_PRESENT)) ||
     3.7 -         unlikely(!get_page_and_type(&frame_table[l1e >> PAGE_SHIFT], 
     3.8 -                                     d, PGT_ldt_page)) )
     3.9 +         unlikely(!get_page_and_type(
    3.10 +             &frame_table[l1_pgentry_to_pfn(mk_l1_pgentry(l1e))],
    3.11 +             d, PGT_ldt_page)) )
    3.12          return 0;
    3.13  
    3.14      ed->arch.perdomain_ptes[off + 16] = mk_l1_pgentry(l1e | _PAGE_RW);
    3.15 @@ -403,7 +404,7 @@ get_page_from_l1e(
    3.16  
    3.17      if ( unlikely(l1v & L1_DISALLOW_MASK) )
    3.18      {
    3.19 -        MEM_LOG("Bad L1 type settings %04lx", l1v & L1_DISALLOW_MASK);
    3.20 +        MEM_LOG("Bad L1 type settings %p", l1v & L1_DISALLOW_MASK);
    3.21          return 0;
    3.22      }
    3.23  
    3.24 @@ -442,7 +443,7 @@ get_page_from_l2e(
    3.25  
    3.26      if ( unlikely((l2_pgentry_val(l2e) & L2_DISALLOW_MASK)) )
    3.27      {
    3.28 -        MEM_LOG("Bad L2 page type settings %04lx",
    3.29 +        MEM_LOG("Bad L2 page type settings %p",
    3.30                  l2_pgentry_val(l2e) & L2_DISALLOW_MASK);
    3.31          return 0;
    3.32      }
    3.33 @@ -470,13 +471,13 @@ get_page_from_l3e(
    3.34  
    3.35      if ( unlikely((l3_pgentry_val(l3e) & L3_DISALLOW_MASK)) )
    3.36      {
    3.37 -        MEM_LOG("Bad L3 page type settings %04lx",
    3.38 +        MEM_LOG("Bad L3 page type settings %p",
    3.39                  l3_pgentry_val(l3e) & L3_DISALLOW_MASK);
    3.40          return 0;
    3.41      }
    3.42  
    3.43      return get_page_and_type_from_pagenr(
    3.44 -        l3_pgentry_to_pfn(l3e), PGT_l3_page_table, d);
    3.45 +        l3_pgentry_to_pfn(l3e), PGT_l2_page_table, d);
    3.46  }
    3.47  
    3.48  
    3.49 @@ -491,13 +492,13 @@ get_page_from_l4e(
    3.50  
    3.51      if ( unlikely((l4_pgentry_val(l4e) & L4_DISALLOW_MASK)) )
    3.52      {
    3.53 -        MEM_LOG("Bad L4 page type settings %04lx",
    3.54 +        MEM_LOG("Bad L4 page type settings %p",
    3.55                  l4_pgentry_val(l4e) & L4_DISALLOW_MASK);
    3.56          return 0;
    3.57      }
    3.58  
    3.59      rc = get_page_and_type_from_pagenr(
    3.60 -        l4_pgentry_to_pfn(l4e), PGT_l4_page_table, d);
    3.61 +        l4_pgentry_to_pfn(l4e), PGT_l3_page_table, d);
    3.62  
    3.63      if ( unlikely(!rc) )
    3.64          return get_linear_pagetable(l4e, pfn, d);
    3.65 @@ -560,7 +561,7 @@ static void put_page_from_l1e(l1_pgentry
    3.66  static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
    3.67  {
    3.68      if ( (l2_pgentry_val(l2e) & _PAGE_PRESENT) && 
    3.69 -         ((l2_pgentry_val(l2e) >> PAGE_SHIFT) != pfn) )
    3.70 +         (l2_pgentry_to_pfn(l2e) != pfn) )
    3.71          put_page_and_type(&frame_table[l2_pgentry_to_pfn(l2e)]);
    3.72  }
    3.73  
    3.74 @@ -570,7 +571,7 @@ static void put_page_from_l2e(l2_pgentry
    3.75  static void put_page_from_l3e(l3_pgentry_t l3e, unsigned long pfn)
    3.76  {
    3.77      if ( (l3_pgentry_val(l3e) & _PAGE_PRESENT) && 
    3.78 -         ((l3_pgentry_val(l3e) >> PAGE_SHIFT) != pfn) )
    3.79 +         (l3_pgentry_to_pfn(l3e) != pfn) )
    3.80          put_page_and_type(&frame_table[l3_pgentry_to_pfn(l3e)]);
    3.81  }
    3.82  
    3.83 @@ -578,7 +579,7 @@ static void put_page_from_l3e(l3_pgentry
    3.84  static void put_page_from_l4e(l4_pgentry_t l4e, unsigned long pfn)
    3.85  {
    3.86      if ( (l4_pgentry_val(l4e) & _PAGE_PRESENT) && 
    3.87 -         ((l4_pgentry_val(l4e) >> PAGE_SHIFT) != pfn) )
    3.88 +         (l4_pgentry_to_pfn(l4e) != pfn) )
    3.89          put_page_and_type(&frame_table[l4_pgentry_to_pfn(l4e)]);
    3.90  }
    3.91  
    3.92 @@ -595,7 +596,8 @@ static int alloc_l1_table(struct pfn_inf
    3.93      pl1e = map_domain_mem(pfn << PAGE_SHIFT);
    3.94  
    3.95      for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
    3.96 -        if ( unlikely(!get_page_from_l1e(pl1e[i], d)) )
    3.97 +        if ( is_guest_l1_slot(i) &&
    3.98 +             unlikely(!get_page_from_l1e(pl1e[i], d)) )
    3.99              goto fail;
   3.100  
   3.101      unmap_domain_mem(pl1e);
   3.102 @@ -603,7 +605,8 @@ static int alloc_l1_table(struct pfn_inf
   3.103  
   3.104   fail:
   3.105      while ( i-- > 0 )
   3.106 -        put_page_from_l1e(pl1e[i], d);
   3.107 +        if ( is_guest_l1_slot(i) )
   3.108 +            put_page_from_l1e(pl1e[i], d);
   3.109  
   3.110      unmap_domain_mem(pl1e);
   3.111      return 0;
   3.112 @@ -619,18 +622,19 @@ static int alloc_l2_table(struct pfn_inf
   3.113     
   3.114      pl2e = map_domain_mem(pfn << PAGE_SHIFT);
   3.115  
   3.116 -    for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
   3.117 -        if ( unlikely(!get_page_from_l2e(pl2e[i], pfn, d, i)) )
   3.118 +    for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
   3.119 +        if ( is_guest_l2_slot(i) &&
   3.120 +             unlikely(!get_page_from_l2e(pl2e[i], pfn, d, i)) )
   3.121              goto fail;
   3.122  
   3.123  #if defined(__i386__)
   3.124 -    /* Now we add our private high mappings. */
   3.125 -    memcpy(&pl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE], 
   3.126 -           &idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
   3.127 -           HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
   3.128 -    pl2e[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
   3.129 +    /* Xen private mappings. */
   3.130 +    memcpy(&pl2e[ROOT_PAGETABLE_FIRST_XEN_SLOT],
   3.131 +           &idle_pg_table[ROOT_PAGETABLE_FIRST_XEN_SLOT],
   3.132 +           ROOT_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t));
   3.133 +    pl2e[l2_table_offset(LINEAR_PT_VIRT_START)] =
   3.134          mk_l2_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
   3.135 -    pl2e[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
   3.136 +    pl2e[l2_table_offset(PERDOMAIN_VIRT_START)] =
   3.137          mk_l2_pgentry(__pa(page_get_owner(page)->arch.mm_perdomain_pt) | 
   3.138                        __PAGE_HYPERVISOR);
   3.139  #endif
   3.140 @@ -640,7 +644,8 @@ static int alloc_l2_table(struct pfn_inf
   3.141  
   3.142   fail:
   3.143      while ( i-- > 0 )
   3.144 -        put_page_from_l2e(pl2e[i], pfn);
   3.145 +        if ( is_guest_l2_slot(i) )
   3.146 +            put_page_from_l2e(pl2e[i], pfn);
   3.147  
   3.148      unmap_domain_mem(pl2e);
   3.149      return 0;
   3.150 @@ -657,14 +662,16 @@ static int alloc_l3_table(struct pfn_inf
   3.151      int            i;
   3.152  
   3.153      for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
   3.154 -        if ( unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) )
   3.155 +        if ( is_guest_l3_slot(i) &&
   3.156 +             unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) )
   3.157              goto fail;
   3.158  
   3.159      return 1;
   3.160  
   3.161   fail:
   3.162      while ( i-- > 0 )
   3.163 -        put_page_from_l3e(pl3e[i], pfn);
   3.164 +        if ( is_guest_l3_slot(i) )
   3.165 +            put_page_from_l3e(pl3e[i], pfn);
   3.166  
   3.167      return 0;
   3.168  }
   3.169 @@ -678,14 +685,26 @@ static int alloc_l4_table(struct pfn_inf
   3.170      int            i;
   3.171  
   3.172      for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
   3.173 -        if ( unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) )
   3.174 +        if ( is_guest_l4_slot(i) &&
   3.175 +             unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) )
   3.176              goto fail;
   3.177  
   3.178 +    /* Xen private mappings. */
   3.179 +    memcpy(&pl4e[ROOT_PAGETABLE_FIRST_XEN_SLOT],
   3.180 +           &idle_pg_table[ROOT_PAGETABLE_FIRST_XEN_SLOT],
   3.181 +           ROOT_PAGETABLE_XEN_SLOTS * sizeof(l4_pgentry_t));
   3.182 +    pl4e[l4_table_offset(LINEAR_PT_VIRT_START)] =
   3.183 +        mk_l4_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR);
   3.184 +    pl4e[l4_table_offset(PERDOMAIN_VIRT_START)] =
   3.185 +        mk_l4_pgentry(__pa(page_get_owner(page)->arch.mm_perdomain_l3) | 
   3.186 +                      __PAGE_HYPERVISOR);
   3.187 +
   3.188      return 1;
   3.189  
   3.190   fail:
   3.191      while ( i-- > 0 )
   3.192 -        put_page_from_l4e(pl4e[i], pfn);
   3.193 +        if ( is_guest_l4_slot(i) )
   3.194 +            put_page_from_l4e(pl4e[i], pfn);
   3.195  
   3.196      return 0;
   3.197  }
   3.198 @@ -703,7 +722,8 @@ static void free_l1_table(struct pfn_inf
   3.199      pl1e = map_domain_mem(pfn << PAGE_SHIFT);
   3.200  
   3.201      for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ )
   3.202 -        put_page_from_l1e(pl1e[i], d);
   3.203 +        if ( is_guest_l1_slot(i) )
   3.204 +            put_page_from_l1e(pl1e[i], d);
   3.205  
   3.206      unmap_domain_mem(pl1e);
   3.207  }
   3.208 @@ -717,8 +737,9 @@ static void free_l2_table(struct pfn_inf
   3.209  
   3.210      pl2e = map_domain_mem(pfn << PAGE_SHIFT);
   3.211  
   3.212 -    for ( i = 0; i < DOMAIN_ENTRIES_PER_L2_PAGETABLE; i++ )
   3.213 -        put_page_from_l2e(pl2e[i], pfn);
   3.214 +    for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ )
   3.215 +        if ( is_guest_l2_slot(i) )
   3.216 +            put_page_from_l2e(pl2e[i], pfn);
   3.217  
   3.218      unmap_domain_mem(pl2e);
   3.219  }
   3.220 @@ -733,7 +754,8 @@ static void free_l3_table(struct pfn_inf
   3.221      int           i;
   3.222  
   3.223      for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ )
   3.224 -        put_page_from_l3e(pl3e[i], pfn);
   3.225 +        if ( is_guest_l3_slot(i) )
   3.226 +            put_page_from_l3e(pl3e[i], pfn);
   3.227  }
   3.228  
   3.229  
   3.230 @@ -744,74 +766,13 @@ static void free_l4_table(struct pfn_inf
   3.231      int           i;
   3.232  
   3.233      for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ )
   3.234 -        put_page_from_l4e(pl4e[i], pfn);
   3.235 +        if ( is_guest_l4_slot(i) )
   3.236 +            put_page_from_l4e(pl4e[i], pfn);
   3.237  }
   3.238  
   3.239  #endif /* __x86_64__ */
   3.240  
   3.241  
   3.242 -static inline int update_l2e(l2_pgentry_t *pl2e, 
   3.243 -                             l2_pgentry_t  ol2e, 
   3.244 -                             l2_pgentry_t  nl2e)
   3.245 -{
   3.246 -    unsigned long o = cmpxchg((unsigned long *)pl2e, 
   3.247 -                              l2_pgentry_val(ol2e), 
   3.248 -                              l2_pgentry_val(nl2e));
   3.249 -    if ( o != l2_pgentry_val(ol2e) )
   3.250 -        MEM_LOG("Failed to update %p -> %p: saw %p\n",
   3.251 -                l2_pgentry_val(ol2e), l2_pgentry_val(nl2e), o);
   3.252 -    return (o == l2_pgentry_val(ol2e));
   3.253 -}
   3.254 -
   3.255 -
   3.256 -/* Update the L2 entry at pl2e to new value nl2e. pl2e is within frame pfn. */
   3.257 -static int mod_l2_entry(l2_pgentry_t *pl2e, 
   3.258 -                        l2_pgentry_t nl2e, 
   3.259 -                        unsigned long pfn)
   3.260 -{
   3.261 -    l2_pgentry_t ol2e;
   3.262 -    unsigned long _ol2e;
   3.263 -
   3.264 -    if ( unlikely((((unsigned long)pl2e & (PAGE_SIZE-1)) >> 2) >=
   3.265 -                  DOMAIN_ENTRIES_PER_L2_PAGETABLE) )
   3.266 -    {
   3.267 -        MEM_LOG("Illegal L2 update attempt in Xen-private area %p", pl2e);
   3.268 -        return 0;
   3.269 -    }
   3.270 -
   3.271 -    if ( unlikely(__get_user(_ol2e, (unsigned long *)pl2e) != 0) )
   3.272 -        return 0;
   3.273 -    ol2e = mk_l2_pgentry(_ol2e);
   3.274 -
   3.275 -    if ( l2_pgentry_val(nl2e) & _PAGE_PRESENT )
   3.276 -    {
   3.277 -        /* Differ in mapping (bits 12-31) or presence (bit 0)? */
   3.278 -        if ( ((l2_pgentry_val(ol2e) ^ l2_pgentry_val(nl2e)) & ~0xffe) == 0 )
   3.279 -            return update_l2e(pl2e, ol2e, nl2e);
   3.280 -
   3.281 -        if ( unlikely(!get_page_from_l2e(nl2e, pfn, current->domain,
   3.282 -                                        ((unsigned long)pl2e & 
   3.283 -                                         ~PAGE_MASK) >> 2)) )
   3.284 -            return 0;
   3.285 -
   3.286 -        if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) )
   3.287 -        {
   3.288 -            put_page_from_l2e(nl2e, pfn);
   3.289 -            return 0;
   3.290 -        }
   3.291 -        
   3.292 -        put_page_from_l2e(ol2e, pfn);
   3.293 -        return 1;
   3.294 -    }
   3.295 -
   3.296 -    if ( unlikely(!update_l2e(pl2e, ol2e, nl2e)) )
   3.297 -        return 0;
   3.298 -
   3.299 -    put_page_from_l2e(ol2e, pfn);
   3.300 -    return 1;
   3.301 -}
   3.302 -
   3.303 -
   3.304  static inline int update_l1e(l1_pgentry_t *pl1e, 
   3.305                               l1_pgentry_t  ol1e, 
   3.306                               l1_pgentry_t  nl1e)
   3.307 @@ -839,17 +800,21 @@ static int mod_l1_entry(l1_pgentry_t *pl
   3.308      struct domain *d = current->domain;
   3.309  
   3.310      if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) )
   3.311 -    {
   3.312 -        MEM_LOG("Bad get_user\n");
   3.313          return 0;
   3.314 -    }
   3.315 -    
   3.316      ol1e = mk_l1_pgentry(_ol1e);
   3.317  
   3.318      if ( l1_pgentry_val(nl1e) & _PAGE_PRESENT )
   3.319      {
   3.320 -        /* Same mapping (bits 12-31), r/w (bit 1), and presence (bit 0)? */
   3.321 -        if ( ((l1_pgentry_val(ol1e) ^ l1_pgentry_val(nl1e)) & ~0xffc) == 0 )
   3.322 +        if ( unlikely(l1_pgentry_val(nl1e) & L1_DISALLOW_MASK) )
   3.323 +        {
   3.324 +            MEM_LOG("Bad L1 type settings %p", 
   3.325 +                    l1_pgentry_val(nl1e) & L1_DISALLOW_MASK);
   3.326 +            return 0;
   3.327 +        }
   3.328 +
   3.329 +        /* Fast path for identical mapping, r/w and presence. */
   3.330 +        if ( ((l1_pgentry_val(ol1e) ^ l1_pgentry_val(nl1e)) & 
   3.331 +              ((PADDR_MASK & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT)) == 0 )
   3.332              return update_l1e(pl1e, ol1e, nl1e);
   3.333  
   3.334          if ( unlikely(!get_page_from_l1e(nl1e, FOREIGNDOM)) )
   3.335 @@ -873,6 +838,181 @@ static int mod_l1_entry(l1_pgentry_t *pl
   3.336  }
   3.337  
   3.338  
   3.339 +#define UPDATE_ENTRY(_t,_p,_o,_n) ({                                    \
   3.340 +    unsigned long __o = cmpxchg((unsigned long *)(_p),                  \
   3.341 +                                _t ## _pgentry_val(_o),                 \
   3.342 +                                _t ## _pgentry_val(_n));                \
   3.343 +    if ( __o != _t ## _pgentry_val(_o) )                                \
   3.344 +        MEM_LOG("Failed to update %p -> %p: saw %p\n",                  \
   3.345 +                _t ## _pgentry_val(_o), _t ## _pgentry_val(_n), __o);   \
   3.346 +    (__o == _t ## _pgentry_val(_o)); })
   3.347 +
   3.348 +
   3.349 +/* Update the L2 entry at pl2e to new value nl2e. pl2e is within frame pfn. */
   3.350 +static int mod_l2_entry(l2_pgentry_t *pl2e, 
   3.351 +                        l2_pgentry_t nl2e, 
   3.352 +                        unsigned long pfn)
   3.353 +{
   3.354 +    l2_pgentry_t ol2e;
   3.355 +    unsigned long _ol2e;
   3.356 +
   3.357 +    if ( unlikely(!is_guest_l2_slot(pgentry_ptr_to_slot(pl2e))) )
   3.358 +    {
   3.359 +        MEM_LOG("Illegal L2 update attempt in Xen-private area %p", pl2e);
   3.360 +        return 0;
   3.361 +    }
   3.362 +
   3.363 +    if ( unlikely(__get_user(_ol2e, (unsigned long *)pl2e) != 0) )
   3.364 +        return 0;
   3.365 +    ol2e = mk_l2_pgentry(_ol2e);
   3.366 +
   3.367 +    if ( l2_pgentry_val(nl2e) & _PAGE_PRESENT )
   3.368 +    {
   3.369 +        if ( unlikely(l2_pgentry_val(nl2e) & L2_DISALLOW_MASK) )
   3.370 +        {
   3.371 +            MEM_LOG("Bad L2 type settings %p", 
   3.372 +                    l2_pgentry_val(nl2e) & L2_DISALLOW_MASK);
   3.373 +            return 0;
   3.374 +        }
   3.375 +
   3.376 +        /* Fast path for identical mapping and presence. */
   3.377 +        if ( ((l2_pgentry_val(ol2e) ^ l2_pgentry_val(nl2e)) & 
   3.378 +              ((PADDR_MASK & PAGE_MASK) | _PAGE_PRESENT)) == 0 )
   3.379 +            return UPDATE_ENTRY(l2, pl2e, ol2e, nl2e);
   3.380 +
   3.381 +        if ( unlikely(!get_page_from_l2e(nl2e, pfn, current->domain,
   3.382 +                                        ((unsigned long)pl2e & 
   3.383 +                                         ~PAGE_MASK) >> 2)) )
   3.384 +            return 0;
   3.385 +
   3.386 +        if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e)) )
   3.387 +        {
   3.388 +            put_page_from_l2e(nl2e, pfn);
   3.389 +            return 0;
   3.390 +        }
   3.391 +        
   3.392 +        put_page_from_l2e(ol2e, pfn);
   3.393 +        return 1;
   3.394 +    }
   3.395 +
   3.396 +    if ( unlikely(!UPDATE_ENTRY(l2, pl2e, ol2e, nl2e)) )
   3.397 +        return 0;
   3.398 +
   3.399 +    put_page_from_l2e(ol2e, pfn);
   3.400 +    return 1;
   3.401 +}
   3.402 +
   3.403 +
   3.404 +#ifdef __x86_64__
   3.405 +
   3.406 +/* Update the L3 entry at pl3e to new value nl3e. pl3e is within frame pfn. */
   3.407 +static int mod_l3_entry(l3_pgentry_t *pl3e, 
   3.408 +                        l3_pgentry_t nl3e, 
   3.409 +                        unsigned long pfn)
   3.410 +{
   3.411 +    l3_pgentry_t ol3e;
   3.412 +    unsigned long _ol3e;
   3.413 +
   3.414 +    if ( unlikely(!is_guest_l3_slot(pgentry_ptr_to_slot(pl3e))) )
   3.415 +    {
   3.416 +        MEM_LOG("Illegal L3 update attempt in Xen-private area %p", pl3e);
   3.417 +        return 0;
   3.418 +    }
   3.419 +
   3.420 +    if ( unlikely(__get_user(_ol3e, (unsigned long *)pl3e) != 0) )
   3.421 +        return 0;
   3.422 +    ol3e = mk_l3_pgentry(_ol3e);
   3.423 +
   3.424 +    if ( l3_pgentry_val(nl3e) & _PAGE_PRESENT )
   3.425 +    {
   3.426 +        if ( unlikely(l3_pgentry_val(nl3e) & L3_DISALLOW_MASK) )
   3.427 +        {
   3.428 +            MEM_LOG("Bad L3 type settings %p", 
   3.429 +                    l3_pgentry_val(nl3e) & L3_DISALLOW_MASK);
   3.430 +            return 0;
   3.431 +        }
   3.432 +
   3.433 +        /* Fast path for identical mapping and presence. */
   3.434 +        if ( ((l3_pgentry_val(ol3e) ^ l3_pgentry_val(nl3e)) & 
   3.435 +              ((PADDR_MASK & PAGE_MASK) | _PAGE_PRESENT)) == 0 )
   3.436 +            return UPDATE_ENTRY(l3, pl3e, ol3e, nl3e);
   3.437 +
   3.438 +        if ( unlikely(!get_page_from_l3e(nl3e, pfn, current->domain)) )
   3.439 +            return 0;
   3.440 +
   3.441 +        if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e)) )
   3.442 +        {
   3.443 +            put_page_from_l3e(nl3e, pfn);
   3.444 +            return 0;
   3.445 +        }
   3.446 +        
   3.447 +        put_page_from_l3e(ol3e, pfn);
   3.448 +        return 1;
   3.449 +    }
   3.450 +
   3.451 +    if ( unlikely(!UPDATE_ENTRY(l3, pl3e, ol3e, nl3e)) )
   3.452 +        return 0;
   3.453 +
   3.454 +    put_page_from_l3e(ol3e, pfn);
   3.455 +    return 1;
   3.456 +}
   3.457 +
   3.458 +
   3.459 +/* Update the L4 entry at pl4e to new value nl4e. pl4e is within frame pfn. */
   3.460 +static int mod_l4_entry(l4_pgentry_t *pl4e, 
   3.461 +                        l4_pgentry_t nl4e, 
   3.462 +                        unsigned long pfn)
   3.463 +{
   3.464 +    l4_pgentry_t ol4e;
   3.465 +    unsigned long _ol4e;
   3.466 +
   3.467 +    if ( unlikely(!is_guest_l4_slot(pgentry_ptr_to_slot(pl4e))) )
   3.468 +    {
   3.469 +        MEM_LOG("Illegal L4 update attempt in Xen-private area %p", pl4e);
   3.470 +        return 0;
   3.471 +    }
   3.472 +
   3.473 +    if ( unlikely(__get_user(_ol4e, (unsigned long *)pl4e) != 0) )
   3.474 +        return 0;
   3.475 +    ol4e = mk_l4_pgentry(_ol4e);
   3.476 +
   3.477 +    if ( l4_pgentry_val(nl4e) & _PAGE_PRESENT )
   3.478 +    {
   3.479 +        if ( unlikely(l4_pgentry_val(nl4e) & L4_DISALLOW_MASK) )
   3.480 +        {
   3.481 +            MEM_LOG("Bad L4 type settings %p", 
   3.482 +                    l4_pgentry_val(nl4e) & L4_DISALLOW_MASK);
   3.483 +            return 0;
   3.484 +        }
   3.485 +
   3.486 +        /* Fast path for identical mapping and presence. */
   3.487 +        if ( ((l4_pgentry_val(ol4e) ^ l4_pgentry_val(nl4e)) & 
   3.488 +              ((PADDR_MASK & PAGE_MASK) | _PAGE_PRESENT)) == 0 )
   3.489 +            return UPDATE_ENTRY(l4, pl4e, ol4e, nl4e);
   3.490 +
   3.491 +        if ( unlikely(!get_page_from_l4e(nl4e, pfn, current->domain)) )
   3.492 +            return 0;
   3.493 +
   3.494 +        if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e)) )
   3.495 +        {
   3.496 +            put_page_from_l4e(nl4e, pfn);
   3.497 +            return 0;
   3.498 +        }
   3.499 +        
   3.500 +        put_page_from_l4e(ol4e, pfn);
   3.501 +        return 1;
   3.502 +    }
   3.503 +
   3.504 +    if ( unlikely(!UPDATE_ENTRY(l4, pl4e, ol4e, nl4e)) )
   3.505 +        return 0;
   3.506 +
   3.507 +    put_page_from_l4e(ol4e, pfn);
   3.508 +    return 1;
   3.509 +}
   3.510 +
   3.511 +#endif /* __x86_64__ */
   3.512 +
   3.513 +
   3.514  int alloc_page_type(struct pfn_info *page, unsigned int type)
   3.515  {
   3.516      switch ( type )
   3.517 @@ -1099,7 +1239,7 @@ int new_guest_cr3(unsigned long pfn)
   3.518      int okay, cpu = smp_processor_id();
   3.519      unsigned long old_base_pfn;
   3.520      
   3.521 -    okay = get_page_and_type_from_pagenr(pfn, PGT_l2_page_table, d);
   3.522 +    okay = get_page_and_type_from_pagenr(pfn, PGT_root_page_table, d);
   3.523      if ( likely(okay) )
   3.524      {
   3.525          invalidate_shadow_ldt(ed);
   3.526 @@ -1125,30 +1265,27 @@ int new_guest_cr3(unsigned long pfn)
   3.527  static int do_extended_command(unsigned long ptr, unsigned long val)
   3.528  {
   3.529      int okay = 1, cpu = smp_processor_id();
   3.530 -    unsigned int cmd = val & MMUEXT_CMD_MASK;
   3.531 +    unsigned int cmd = val & MMUEXT_CMD_MASK, type;
   3.532      unsigned long pfn = ptr >> PAGE_SHIFT;
   3.533      struct pfn_info *page = &frame_table[pfn];
   3.534      struct exec_domain *ed = current;
   3.535 -    struct domain *d = ed->domain, *nd, *e;
   3.536 -    u32 x, y;
   3.537 +    struct domain *d = ed->domain, *e;
   3.538 +    u32 x, y, _d, _nd;
   3.539      domid_t domid;
   3.540      grant_ref_t gntref;
   3.541  
   3.542      switch ( cmd )
   3.543      {
   3.544      case MMUEXT_PIN_L1_TABLE:
   3.545 -    case MMUEXT_PIN_L2_TABLE:
   3.546          /*
   3.547           * We insist that, if you pin an L1 page, it's the first thing that
   3.548           * you do to it. This is because we require the backptr to still be
   3.549           * mutable. This assumption seems safe.
   3.550           */
   3.551 -        okay = get_page_and_type_from_pagenr(
   3.552 -            pfn, 
   3.553 -            ((cmd==MMUEXT_PIN_L2_TABLE) ? 
   3.554 -             PGT_l2_page_table : (PGT_l1_page_table|PGT_va_mutable)),
   3.555 -            FOREIGNDOM);
   3.556 -
   3.557 +        type = PGT_l1_page_table | PGT_va_mutable;
   3.558 +
   3.559 +    pin_page:
   3.560 +        okay = get_page_and_type_from_pagenr(pfn, type, FOREIGNDOM);
   3.561          if ( unlikely(!okay) )
   3.562          {
   3.563              MEM_LOG("Error while pinning pfn %p", pfn);
   3.564 @@ -1166,6 +1303,20 @@ static int do_extended_command(unsigned 
   3.565  
   3.566          break;
   3.567  
   3.568 +    case MMUEXT_PIN_L2_TABLE:
   3.569 +        type = PGT_l2_page_table;
   3.570 +        goto pin_page;
   3.571 +
   3.572 +#ifdef __x86_64__
   3.573 +    case MMUEXT_PIN_L3_TABLE:
   3.574 +        type = PGT_l3_page_table;
   3.575 +        goto pin_page;
   3.576 +
   3.577 +    case MMUEXT_PIN_L4_TABLE:
   3.578 +        type = PGT_l4_page_table;
   3.579 +        goto pin_page;
   3.580 +#endif /* __x86_64__ */
   3.581 +
   3.582      case MMUEXT_UNPIN_TABLE:
   3.583          if ( unlikely(!(okay = get_page_from_pagenr(pfn, FOREIGNDOM))) )
   3.584          {
   3.585 @@ -1300,28 +1451,30 @@ static int do_extended_command(unsigned 
   3.586           * benign reference to the page (PGC_allocated). If that reference
   3.587           * disappears then the deallocation routine will safely spin.
   3.588           */
   3.589 -        nd = page_get_owner(page);
   3.590 -        y  = page->count_info;
   3.591 +        _d  = pickle_domptr(d);
   3.592 +        _nd = page->u.inuse._domain;
   3.593 +        y   = page->count_info;
   3.594          do {
   3.595              x = y;
   3.596              if ( unlikely((x & (PGC_count_mask|PGC_allocated)) != 
   3.597                            (1|PGC_allocated)) ||
   3.598 -                 unlikely(nd != d) )
   3.599 +                 unlikely(_nd != _d) )
   3.600              {
   3.601                  MEM_LOG("Bad page values %p: ed=%p(%u), sd=%p,"
   3.602                          " caf=%08x, taf=%08x\n", page_to_pfn(page),
   3.603 -                        d, d->id, nd, x, page->u.inuse.type_info);
   3.604 +                        d, d->id, unpickle_domptr(_nd), x, 
   3.605 +                        page->u.inuse.type_info);
   3.606                  spin_unlock(&d->page_alloc_lock);
   3.607                  put_domain(e);
   3.608                  return 0;
   3.609              }
   3.610              __asm__ __volatile__(
   3.611                  LOCK_PREFIX "cmpxchg8b %2"
   3.612 -                : "=d" (nd), "=a" (y),
   3.613 +                : "=d" (_nd), "=a" (y),
   3.614                  "=m" (*(volatile u64 *)(&page->count_info))
   3.615 -                : "0" (d), "1" (x), "c" (NULL), "b" (x) );
   3.616 +                : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
   3.617          } 
   3.618 -        while ( unlikely(nd != d) || unlikely(y != x) );
   3.619 +        while ( unlikely(_nd != _d) || unlikely(y != x) );
   3.620  
   3.621          /*
   3.622           * Unlink from 'd'. At least one reference remains (now anonymous), so
   3.623 @@ -1412,27 +1565,29 @@ static int do_extended_command(unsigned 
   3.624           * benign reference to the page (PGC_allocated). If that reference
   3.625           * disappears then the deallocation routine will safely spin.
   3.626           */
   3.627 -        nd = page_get_owner(page);
   3.628 -        y  = page->count_info;
   3.629 +        _d  = pickle_domptr(d);
   3.630 +        _nd = page->u.inuse._domain;
   3.631 +        y   = page->count_info;
   3.632          do {
   3.633              x = y;
   3.634              if ( unlikely((x & (PGC_count_mask|PGC_allocated)) != 
   3.635                            (1|PGC_allocated)) ||
   3.636 -                 unlikely(nd != d) )
   3.637 +                 unlikely(_nd != _d) )
   3.638              {
   3.639                  MEM_LOG("Bad page values %p: ed=%p(%u), sd=%p,"
   3.640                          " caf=%08x, taf=%08x\n", page_to_pfn(page),
   3.641 -                        d, d->id, nd, x, page->u.inuse.type_info);
   3.642 +                        d, d->id, unpickle_domptr(_nd), x,
   3.643 +                        page->u.inuse.type_info);
   3.644                  okay = 0;
   3.645                  goto reassign_fail;
   3.646              }
   3.647              __asm__ __volatile__(
   3.648                  LOCK_PREFIX "cmpxchg8b %3"
   3.649 -                : "=d" (nd), "=a" (y), "=c" (e),
   3.650 +                : "=d" (_nd), "=a" (y), "=c" (e),
   3.651                  "=m" (*(volatile u64 *)(&page->count_info))
   3.652 -                : "0" (d), "1" (x), "c" (e), "b" (x) );
   3.653 +                : "0" (_d), "1" (x), "c" (e), "b" (x) );
   3.654          } 
   3.655 -        while ( unlikely(nd != d) || unlikely(y != x) );
   3.656 +        while ( unlikely(_nd != _d) || unlikely(y != x) );
   3.657          
   3.658          /*
   3.659           * Unlink from 'd'. We transferred at least one reference to 'e', so
   3.660 @@ -1625,6 +1780,44 @@ int do_mmu_update(
   3.661                      put_page_type(page);
   3.662                  }
   3.663                  break;
   3.664 +#ifdef __x86_64__
   3.665 +            case PGT_l3_page_table:
   3.666 +                if ( likely(get_page_type(page, PGT_l3_page_table)) )
   3.667 +                {
   3.668 +                    okay = mod_l3_entry((l3_pgentry_t *)va, 
   3.669 +                                        mk_l3_pgentry(req.val),
   3.670 +                                        pfn); 
   3.671 +
   3.672 +                    if ( unlikely(shadow_mode(d)) && okay &&
   3.673 +                         (get_shadow_status(d, page-frame_table) & 
   3.674 +                          PSH_shadowed) )
   3.675 +                    {
   3.676 +                        /*XXXshadow_l3_normal_pt_update(req.ptr, req.val);*/
   3.677 +                        put_shadow_status(d);
   3.678 +                    }
   3.679 +
   3.680 +                    put_page_type(page);
   3.681 +                }
   3.682 +                break;
   3.683 +            case PGT_l4_page_table:
   3.684 +                if ( likely(get_page_type(page, PGT_l4_page_table)) )
   3.685 +                {
   3.686 +                    okay = mod_l4_entry((l4_pgentry_t *)va, 
   3.687 +                                        mk_l4_pgentry(req.val),
   3.688 +                                        pfn); 
   3.689 +
   3.690 +                    if ( unlikely(shadow_mode(d)) && okay &&
   3.691 +                         (get_shadow_status(d, page-frame_table) & 
   3.692 +                          PSH_shadowed) )
   3.693 +                    {
   3.694 +                        /*XXXshadow_l4_normal_pt_update(req.ptr, req.val);*/
   3.695 +                        put_shadow_status(d);
   3.696 +                    }
   3.697 +
   3.698 +                    put_page_type(page);
   3.699 +                }
   3.700 +                break;
   3.701 +#endif /* __x86_64__ */
   3.702              default:
   3.703                  if ( likely(get_page_type(page, PGT_writable_page)) )
   3.704                  {
   3.705 @@ -2019,7 +2212,7 @@ void ptwr_flush(const int which)
   3.706      struct domain *d = ed->domain;
   3.707  
   3.708      l1va = ptwr_info[cpu].ptinfo[which].l1va;
   3.709 -    ptep = (unsigned long *)&linear_pg_table[l1va>>PAGE_SHIFT];
   3.710 +    ptep = (unsigned long *)&linear_pg_table[l1_linear_offset(l1va)];
   3.711  
   3.712      /*
   3.713       * STEP 1. Write-protect the p.t. page so no more updates can occur.
   3.714 @@ -2042,8 +2235,8 @@ void ptwr_flush(const int which)
   3.715      {
   3.716          /* Write-protect the p.t. page in the shadow page table. */
   3.717          l1pte_propagate_from_guest(d, &pte, &spte);
   3.718 -        __put_user(
   3.719 -            spte, (unsigned long *)&shadow_linear_pg_table[l1va>>PAGE_SHIFT]);
   3.720 +        __put_user(spte, (unsigned long *)
   3.721 +                   &shadow_linear_pg_table[l1_linear_offset(l1va)]);
   3.722  
   3.723          /* Is the p.t. page itself shadowed? Map it into Xen space if so. */
   3.724          sstat = get_shadow_status(d, pte >> PAGE_SHIFT);
   3.725 @@ -2168,7 +2361,8 @@ int ptwr_do_page_fault(unsigned long add
   3.726       */
   3.727      if ( !(l2_pgentry_val(linear_l2_table[addr>>L2_PAGETABLE_SHIFT]) &
   3.728             _PAGE_PRESENT) ||
   3.729 -         __get_user(pte, (unsigned long *)&linear_pg_table[addr>>PAGE_SHIFT]) )
   3.730 +         __get_user(pte, (unsigned long *)
   3.731 +                    &linear_pg_table[l1_linear_offset(addr)]) )
   3.732      {
   3.733          return 0;
   3.734      }
     4.1 --- a/xen/arch/x86/x86_64/domain_build.c	Wed Feb 09 02:59:54 2005 +0000
     4.2 +++ b/xen/arch/x86/x86_64/domain_build.c	Wed Feb 09 10:16:50 2005 +0000
     4.3 @@ -238,7 +238,7 @@ int construct_dom0(struct domain *d,
     4.4      l4tab[l4_table_offset(LINEAR_PT_VIRT_START)] =
     4.5          mk_l4_pgentry(__pa(l4start) | __PAGE_HYPERVISOR);
     4.6      l4tab[l4_table_offset(PERDOMAIN_VIRT_START)] =
     4.7 -        mk_l4_pgentry(__pa(d->arch.mm_perdomain_pt) | __PAGE_HYPERVISOR);
     4.8 +        mk_l4_pgentry(__pa(d->arch.mm_perdomain_l3) | __PAGE_HYPERVISOR);
     4.9      ed->arch.pagetable = mk_pagetable(__pa(l4start));
    4.10  
    4.11      l4tab += l4_table_offset(dsi.v_start);
     5.1 --- a/xen/include/asm-x86/config.h	Wed Feb 09 02:59:54 2005 +0000
     5.2 +++ b/xen/include/asm-x86/config.h	Wed Feb 09 10:16:50 2005 +0000
     5.3 @@ -151,6 +151,11 @@ extern void __out_of_line_bug(int line) 
     5.4   */
     5.5  
     5.6  
     5.7 +#define ROOT_PAGETABLE_FIRST_XEN_SLOT 256
     5.8 +#define ROOT_PAGETABLE_LAST_XEN_SLOT  271
     5.9 +#define ROOT_PAGETABLE_XEN_SLOTS \
    5.10 +    (ROOT_PAGETABLE_LAST_XEN_SLOT - ROOT_PAGETABLE_FIRST_XEN_SLOT + 1)
    5.11 +
    5.12  /* Hypervisor reserves PML4 slots 256 to 271 inclusive. */
    5.13  #define HYPERVISOR_VIRT_START   (PML4_ADDR(256))
    5.14  #define HYPERVISOR_VIRT_END     (HYPERVISOR_VIRT_START + PML4_ENTRY_BYTES*16)
    5.15 @@ -210,6 +215,13 @@ extern void __out_of_line_bug(int line) 
    5.16  #define __HYPERVISOR_VIRT_START  0xFC000000
    5.17  #define HYPERVISOR_VIRT_START   (0xFC000000UL)
    5.18  
    5.19 +#define ROOT_PAGETABLE_FIRST_XEN_SLOT \
    5.20 +    (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT)
    5.21 +#define ROOT_PAGETABLE_LAST_XEN_SLOT  \
    5.22 +    (~0UL >> L2_PAGETABLE_SHIFT)
    5.23 +#define ROOT_PAGETABLE_XEN_SLOTS \
    5.24 +    (ROOT_PAGETABLE_LAST_XEN_SLOT - ROOT_PAGETABLE_FIRST_XEN_SLOT + 1)
    5.25 +
    5.26  /*
    5.27   * First 4MB are mapped read-only for all. It's for the machine->physical
    5.28   * mapping table (MPT table). The following are virtual addresses.
     6.1 --- a/xen/include/asm-x86/domain.h	Wed Feb 09 02:59:54 2005 +0000
     6.2 +++ b/xen/include/asm-x86/domain.h	Wed Feb 09 10:16:50 2005 +0000
     6.3 @@ -14,6 +14,10 @@ struct trap_bounce {
     6.4  struct arch_domain
     6.5  {
     6.6      l1_pgentry_t *mm_perdomain_pt;
     6.7 +#ifdef __x86_64__
     6.8 +    l2_pgentry_t *mm_perdomain_l2;
     6.9 +    l3_pgentry_t *mm_perdomain_l3;
    6.10 +#endif
    6.11  
    6.12      /* shadow mode status and controls */
    6.13      unsigned int shadow_mode;  /* flags to control shadow table operation */
     7.1 --- a/xen/include/asm-x86/page.h	Wed Feb 09 02:59:54 2005 +0000
     7.2 +++ b/xen/include/asm-x86/page.h	Wed Feb 09 10:16:50 2005 +0000
     7.3 @@ -9,6 +9,10 @@
     7.4  #include <asm/x86_64/page.h>
     7.5  #endif
     7.6  
     7.7 +/* Convert a pointer to a page-table entry into pagetable slot index. */
     7.8 +#define pgentry_ptr_to_slot(_p) \
     7.9 +    (((unsigned long)(_p) & ~PAGE_MASK) / sizeof(*(_p)))
    7.10 +
    7.11  /* Page-table type. */
    7.12  #ifndef __ASSEMBLY__
    7.13  typedef struct { unsigned long pt_lo; } pagetable_t;
     8.1 --- a/xen/include/asm-x86/x86_32/page.h	Wed Feb 09 02:59:54 2005 +0000
     8.2 +++ b/xen/include/asm-x86/x86_32/page.h	Wed Feb 09 10:16:50 2005 +0000
     8.3 @@ -59,6 +59,9 @@ typedef l2_pgentry_t root_pgentry_t;
     8.4  /* Given a virtual address, get an entry offset into a linear page table. */
     8.5  #define l1_linear_offset(_a) ((_a) >> PAGE_SHIFT)
     8.6  
     8.7 +#define is_guest_l1_slot(_s) (1)
     8.8 +#define is_guest_l2_slot(_s) ((_s) < ROOT_PAGETABLE_FIRST_XEN_SLOT)
     8.9 +
    8.10  #define PGT_root_page_table PGT_l2_page_table
    8.11  
    8.12  #define _PAGE_NX         0UL
     9.1 --- a/xen/include/asm-x86/x86_64/page.h	Wed Feb 09 02:59:54 2005 +0000
     9.2 +++ b/xen/include/asm-x86/x86_64/page.h	Wed Feb 09 10:16:50 2005 +0000
     9.3 @@ -82,6 +82,13 @@ typedef l4_pgentry_t root_pgentry_t;
     9.4  /* Given a virtual address, get an entry offset into a linear page table. */
     9.5  #define l1_linear_offset(_a) (((_a) & VADDR_MASK) >> PAGE_SHIFT)
     9.6  
     9.7 +#define is_guest_l1_slot(_s) (1)
     9.8 +#define is_guest_l2_slot(_s) (1)
     9.9 +#define is_guest_l3_slot(_s) (1)
    9.10 +#define is_guest_l4_slot(_s)                   \
    9.11 +    (((_s) < ROOT_PAGETABLE_FIRST_XEN_SLOT) || \
    9.12 +     ((_s) > ROOT_PAGETABLE_LAST_XEN_SLOT))
    9.13 +
    9.14  #define PGT_root_page_table PGT_l4_page_table
    9.15  
    9.16  #define _PAGE_NX         (cpu_has_nx ? (1UL<<63) : 0UL)