direct-io.hg

changeset 7848:fe3a892b33b4

Many fixes for save/restore and related areas for PAE in particular. Now
should be able to save/restore successfully on machines with up to 16GB
and any size of guest.

Signed-off-by: Steven Hand <steven@xensource.com>
author smh22@firebug.cl.cam.ac.uk
date Wed Nov 16 17:45:03 2005 +0100 (2005-11-16)
parents 9b345321fd06
children c5a49efa11d6
files linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h tools/libxc/xc_linux_restore.c tools/libxc/xc_linux_save.c tools/libxc/xc_private.c tools/libxc/xg_private.h tools/libxc/xg_save_restore.h tools/python/xen/xend/XendCheckpoint.py xen/arch/x86/mm.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c	Wed Nov 16 15:50:36 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c	Wed Nov 16 17:45:03 2005 +0100
     1.3 @@ -136,21 +136,19 @@ int direct_kernel_remap_pfn_range(unsign
     1.4  }
     1.5  EXPORT_SYMBOL(direct_kernel_remap_pfn_range);
     1.6  
     1.7 -/* FIXME: This is horribly broken on PAE */ 
     1.8  static int lookup_pte_fn(
     1.9  	pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
    1.10  {
    1.11 -	unsigned long *ptep = (unsigned long *)data;
    1.12 +	uint64_t *ptep = (uint64_t *)data;
    1.13  	if (ptep)
    1.14 -		*ptep = (pfn_to_mfn(page_to_pfn(pte_page)) <<
    1.15 -			 PAGE_SHIFT) |
    1.16 -			((unsigned long)pte & ~PAGE_MASK);
    1.17 +		*ptep = ((uint64_t)pfn_to_mfn(page_to_pfn(pte_page)) <<
    1.18 +			 PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
    1.19  	return 0;
    1.20  }
    1.21  
    1.22  int create_lookup_pte_addr(struct mm_struct *mm, 
    1.23  			   unsigned long address,
    1.24 -			   unsigned long *ptep)
    1.25 +			   uint64_t *ptep)
    1.26  {
    1.27  	return generic_page_range(mm, address, PAGE_SIZE, lookup_pte_fn, ptep);
    1.28  }
     2.1 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c	Wed Nov 16 15:50:36 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c	Wed Nov 16 17:45:03 2005 +0100
     2.3 @@ -412,7 +412,7 @@ static void fast_flush_area(int idx, int
     2.4  	struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
     2.5  	unsigned int i, op = 0;
     2.6  	struct grant_handle_pair *handle;
     2.7 -	unsigned long ptep;
     2.8 +	uint64_t ptep;
     2.9  	int ret;
    2.10  
    2.11  	for ( i = 0; i < nr_pages; i++)
    2.12 @@ -427,9 +427,9 @@ static void fast_flush_area(int idx, int
    2.13  		op++;
    2.14  
    2.15  		if (create_lookup_pte_addr(
    2.16 -			blktap_vma->vm_mm,
    2.17 -			MMAP_VADDR(user_vstart, idx, i), 
    2.18 -			&ptep) !=0) {
    2.19 +			    blktap_vma->vm_mm,
    2.20 +			    MMAP_VADDR(user_vstart, idx, i), 
    2.21 +			    &ptep) !=0) {
    2.22  			DPRINTK("Couldn't get a pte addr!\n");
    2.23  			return;
    2.24  		}
    2.25 @@ -705,7 +705,7 @@ static void dispatch_rw_block_io(blkif_t
    2.26  
    2.27  		unsigned long uvaddr;
    2.28  		unsigned long kvaddr;
    2.29 -		unsigned long ptep;
    2.30 +		uint64_t ptep;
    2.31  
    2.32  		uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
    2.33  		kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
     3.1 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Wed Nov 16 15:50:36 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c	Wed Nov 16 17:45:03 2005 +0100
     3.3 @@ -152,7 +152,8 @@ static int privcmd_ioctl(struct inode *i
     3.4  		privcmd_mmapbatch_t m;
     3.5  		struct vm_area_struct *vma = NULL;
     3.6  		unsigned long *p, addr;
     3.7 -		unsigned long mfn, ptep;
     3.8 +		unsigned long mfn; 
     3.9 +		uint64_t ptep;
    3.10  		int i;
    3.11  
    3.12  		if (copy_from_user(&m, (void *)data, sizeof(m))) {
    3.13 @@ -217,15 +218,39 @@ static int privcmd_ioctl(struct inode *i
    3.14  #endif
    3.15  
    3.16  #ifndef __ia64__
    3.17 -	case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN: {
    3.18 -		unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
    3.19 -		pgd_t *pgd = pgd_offset_k(m2pv);
    3.20 -		pud_t *pud = pud_offset(pgd, m2pv);
    3.21 -		pmd_t *pmd = pmd_offset(pud, m2pv);
    3.22 -		unsigned long m2p_start_mfn =
    3.23 -			(*(unsigned long *)pmd) >> PAGE_SHIFT; 
    3.24 -		ret = put_user(m2p_start_mfn, (unsigned long *)data) ?
    3.25 -			-EFAULT: 0;
    3.26 +	case IOCTL_PRIVCMD_GET_MACH2PHYS_MFNS: {
    3.27 +
    3.28 +		pgd_t *pgd; 
    3.29 +		pud_t *pud; 
    3.30 +		pmd_t *pmd; 
    3.31 +		unsigned long m2pv, m2p_mfn; 	
    3.32 +		privcmd_m2pmfns_t m; 
    3.33 +		unsigned long *p; 
    3.34 +		int i; 
    3.35 +
    3.36 +		if (copy_from_user(&m, (void *)data, sizeof(m)))
    3.37 +			return -EFAULT;
    3.38 +
    3.39 +		m2pv = (unsigned long)machine_to_phys_mapping;
    3.40 +
    3.41 +		p = m.arr; 
    3.42 +
    3.43 +		for(i=0; i < m.num; i++) { 
    3.44 +
    3.45 +			pgd = pgd_offset_k(m2pv);
    3.46 +			pud = pud_offset(pgd, m2pv);
    3.47 +			pmd = pmd_offset(pud, m2pv);
    3.48 +			m2p_mfn = (*(uint64_t *)pmd >> PAGE_SHIFT)&0xFFFFFFFF;
    3.49 +			
    3.50 +			if (put_user(m2p_mfn, p + i))
    3.51 +				return -EFAULT;
    3.52 +
    3.53 +			m2pv += (1 << 21); 
    3.54 +		}
    3.55 +
    3.56 +		ret = 0; 
    3.57 +		break; 
    3.58 +
    3.59  	}
    3.60  	break;
    3.61  #endif
     4.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h	Wed Nov 16 15:50:36 2005 +0100
     4.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h	Wed Nov 16 17:45:03 2005 +0100
     4.3 @@ -450,11 +450,11 @@ void make_pages_writable(void *va, unsig
     4.4  #endif /* !CONFIG_DISCONTIGMEM */
     4.5  
     4.6  int direct_remap_pfn_range(struct vm_area_struct *vma,
     4.7 -                            unsigned long address, 
     4.8 -                            unsigned long mfn,
     4.9 -                            unsigned long size, 
    4.10 -                            pgprot_t prot,
    4.11 -                            domid_t  domid);
    4.12 +                           unsigned long address, 
    4.13 +                           unsigned long mfn,
    4.14 +                           unsigned long size, 
    4.15 +                           pgprot_t prot,
    4.16 +                           domid_t  domid);
    4.17  int direct_kernel_remap_pfn_range(unsigned long address, 
    4.18  				  unsigned long mfn,
    4.19  				  unsigned long size, 
    4.20 @@ -462,7 +462,7 @@ int direct_kernel_remap_pfn_range(unsign
    4.21  				  domid_t  domid);
    4.22  int create_lookup_pte_addr(struct mm_struct *mm,
    4.23                             unsigned long address,
    4.24 -                           unsigned long *ptep);
    4.25 +                           uint64_t *ptep);
    4.26  int touch_pte_range(struct mm_struct *mm,
    4.27                      unsigned long address,
    4.28                      unsigned long size);
     5.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h	Wed Nov 16 15:50:36 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h	Wed Nov 16 17:45:03 2005 +0100
     5.3 @@ -541,7 +541,7 @@ int direct_kernel_remap_pfn_range(unsign
     5.4  
     5.5  int create_lookup_pte_addr(struct mm_struct *mm,
     5.6                             unsigned long address,
     5.7 -                           unsigned long *ptep);
     5.8 +                           uint64_t *ptep);
     5.9  
    5.10  int touch_pte_range(struct mm_struct *mm,
    5.11                      unsigned long address,
     6.1 --- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h	Wed Nov 16 15:50:36 2005 +0100
     6.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h	Wed Nov 16 17:45:03 2005 +0100
     6.3 @@ -55,6 +55,11 @@ typedef struct privcmd_mmapbatch {
     6.4  	unsigned long *arr; /* array of mfns - top nibble set on err */
     6.5  } privcmd_mmapbatch_t; 
     6.6  
     6.7 +typedef struct privcmd_m2pmfns { 
     6.8 +	int num;    /* max number of mfns to return */
     6.9 +	unsigned long *arr; /* array of mfns */
    6.10 +} privcmd_m2pmfns_t; 
    6.11 +
    6.12  typedef struct privcmd_blkmsg
    6.13  {
    6.14  	unsigned long op;
    6.15 @@ -69,12 +74,11 @@ typedef struct privcmd_blkmsg
    6.16   */
    6.17  #define IOCTL_PRIVCMD_HYPERCALL					\
    6.18  	_IOC(_IOC_NONE, 'P', 0, sizeof(privcmd_hypercall_t))
    6.19 -
    6.20  #define IOCTL_PRIVCMD_MMAP					\
    6.21  	_IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
    6.22  #define IOCTL_PRIVCMD_MMAPBATCH					\
    6.23  	_IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
    6.24 -#define IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN			\
    6.25 +#define IOCTL_PRIVCMD_GET_MACH2PHYS_MFNS			\
    6.26  	_IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
    6.27  
    6.28  #endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
     7.1 --- a/tools/libxc/xc_linux_restore.c	Wed Nov 16 15:50:36 2005 +0100
     7.2 +++ b/tools/libxc/xc_linux_restore.c	Wed Nov 16 17:45:03 2005 +0100
     7.3 @@ -13,13 +13,13 @@
     7.4  #include "xg_save_restore.h"
     7.5  
     7.6  /* max mfn of the whole machine */
     7.7 -static uint32_t max_mfn; 
     7.8 +static unsigned long max_mfn; 
     7.9  
    7.10  /* virtual starting address of the hypervisor */
    7.11 -static uint32_t hvirt_start; 
    7.12 +static unsigned long hvirt_start; 
    7.13  
    7.14  /* #levels of page tables used by the currrent guest */
    7.15 -static uint32_t pt_levels; 
    7.16 +static unsigned int pt_levels; 
    7.17  
    7.18  /* total number of pages used by the current guest */
    7.19  static unsigned long max_pfn;
    7.20 @@ -50,7 +50,6 @@ read_exact(int fd, void *buf, size_t cou
    7.21      return (r == count) ? 1 : 0; 
    7.22  }
    7.23  
    7.24 -
    7.25  /*
    7.26  ** In the state file (or during transfer), all page-table pages are 
    7.27  ** converted into a 'canonical' form where references to actual mfns 
    7.28 @@ -60,23 +59,11 @@ read_exact(int fd, void *buf, size_t cou
    7.29  */
    7.30  int uncanonicalize_pagetable(unsigned long type, void *page) 
    7.31  { 
    7.32 -    int i, pte_last, xen_start, xen_end; 
    7.33 +    int i, pte_last; 
    7.34      unsigned long pfn; 
    7.35      uint64_t pte; 
    7.36  
    7.37 -    /* 
    7.38 -    ** We need to determine which entries in this page table hold
    7.39 -    ** reserved hypervisor mappings. This depends on the current
    7.40 -    ** page table type as well as the number of paging levels. 
    7.41 -    */
    7.42 -    xen_start = xen_end = pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8); 
    7.43 -    
    7.44 -    if (pt_levels == 2 && type == L2TAB)
    7.45 -        xen_start = (hvirt_start >> L2_PAGETABLE_SHIFT); 
    7.46 -
    7.47 -    if (pt_levels == 3 && type == L3TAB) 
    7.48 -        xen_start = L3_PAGETABLE_ENTRIES_PAE; 
    7.49 -
    7.50 +    pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8); 
    7.51  
    7.52      /* Now iterate through the page table, uncanonicalizing each PTE */
    7.53      for(i = 0; i < pte_last; i++) { 
    7.54 @@ -85,13 +72,10 @@ int uncanonicalize_pagetable(unsigned lo
    7.55              pte = ((uint32_t *)page)[i]; 
    7.56          else 
    7.57              pte = ((uint64_t *)page)[i]; 
    7.58 -        
    7.59 -        if(i >= xen_start && i < xen_end) 
    7.60 -            pte = 0; 
    7.61 -        
    7.62 +
    7.63          if(pte & _PAGE_PRESENT) { 
    7.64 -            
    7.65 -            pfn = pte >> PAGE_SHIFT; 
    7.66 +
    7.67 +            pfn = (pte >> PAGE_SHIFT) & 0xffffffff;
    7.68              
    7.69              if(pfn >= max_pfn) { 
    7.70                  ERR("Frame number in type %lu page table is out of range: "
    7.71 @@ -101,17 +85,16 @@ int uncanonicalize_pagetable(unsigned lo
    7.72              } 
    7.73              
    7.74              
    7.75 -            if(type == L1TAB) 
    7.76 -                pte &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PAT);
    7.77 -            else 
    7.78 -                pte &= (PAGE_SIZE - 1) & ~(_PAGE_GLOBAL | _PAGE_PSE);
    7.79 -            
    7.80 -            pte |= p2m[pfn] << PAGE_SHIFT;
    7.81 -            
    7.82 +            pte &= 0xffffff0000000fffULL;
    7.83 +            pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT;
    7.84 +
    7.85              if(pt_levels == 2) 
    7.86                  ((uint32_t *)page)[i] = (uint32_t)pte; 
    7.87              else 
    7.88                  ((uint64_t *)page)[i] = (uint64_t)pte; 
    7.89 +
    7.90 +        
    7.91 +
    7.92          }
    7.93      }
    7.94      
    7.95 @@ -143,6 +126,9 @@ int xc_linux_restore(int xc_handle, int 
    7.96      /* A table of MFNs to map in the current region */
    7.97      unsigned long *region_mfn = NULL;
    7.98  
    7.99 +    /* Types of the pfns in the current region */
   7.100 +    unsigned long region_pfn_type[MAX_BATCH_SIZE];
   7.101 +
   7.102      /* A temporary mapping, and a copy, of one frame of guest memory. */
   7.103      unsigned long *page = NULL;
   7.104  
   7.105 @@ -233,11 +219,13 @@ int xc_linux_restore(int xc_handle, int 
   7.106      
   7.107      if(xc_domain_memory_increase_reservation(
   7.108             xc_handle, dom, max_pfn, 0, 0, NULL) != 0) { 
   7.109 -        ERR("Failed to increase reservation by %lx KB\n", max_pfn); 
   7.110 +        ERR("Failed to increase reservation by %lx KB\n", PFN_TO_KB(max_pfn));
   7.111          errno = ENOMEM;
   7.112          goto out;
   7.113      }
   7.114  
   7.115 +    DPRINTF("Increased domain reservation by %lx KB\n", PFN_TO_KB(max_pfn)); 
   7.116 +
   7.117      /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
   7.118      if (xc_get_pfn_list(xc_handle, dom, p2m, max_pfn) != max_pfn) {
   7.119          ERR("Did not read correct number of frame numbers for new dom");
   7.120 @@ -249,6 +237,7 @@ int xc_linux_restore(int xc_handle, int 
   7.121          goto out;
   7.122      }
   7.123  
   7.124 +
   7.125      DPRINTF("Reloading memory pages:   0%%\n");
   7.126  
   7.127      /*
   7.128 @@ -261,7 +250,6 @@ int xc_linux_restore(int xc_handle, int 
   7.129      while (1) { 
   7.130  
   7.131          int j;
   7.132 -        unsigned long region_pfn_type[MAX_BATCH_SIZE];
   7.133  
   7.134          this_pc = (n * 100) / max_pfn;
   7.135          if ( (this_pc - prev_pc) >= 5 )
   7.136 @@ -322,7 +310,7 @@ int xc_linux_restore(int xc_handle, int 
   7.137              if (pagetype == XTAB) 
   7.138                  /* a bogus/unmapped page: skip it */
   7.139                  continue;
   7.140 -            
   7.141 +
   7.142              if (pfn > max_pfn) {
   7.143                  ERR("pfn out of range");
   7.144                  goto out;
   7.145 @@ -348,10 +336,20 @@ int xc_linux_restore(int xc_handle, int 
   7.146                  ** A page table page - need to 'uncanonicalize' it, i.e. 
   7.147                  ** replace all the references to pfns with the corresponding 
   7.148                  ** mfns for the new domain. 
   7.149 -                */ 
   7.150 -                if(!uncanonicalize_pagetable(pagetype, page))
   7.151 -                    goto out; 
   7.152 +                ** 
   7.153 +                ** On PAE we need to ensure that PGDs are in MFNs < 4G, and 
   7.154 +                ** so we may need to update the p2m after the main loop. 
   7.155 +                ** Hence we defer canonicalization of L1s until then. 
   7.156 +                */
   7.157 +                if(pt_levels != 3 || pagetype != L1TAB) { 
   7.158  
   7.159 +                    if(!uncanonicalize_pagetable(pagetype, page)) {
   7.160 +                        ERR("failed uncanonicalize pt!\n"); 
   7.161 +                        goto out; 
   7.162 +                    }
   7.163 +
   7.164 +                } 
   7.165 +                    
   7.166              } else if(pagetype != NOTAB) { 
   7.167  
   7.168                  ERR("Bogus page type %lx page table is out of range: "
   7.169 @@ -361,7 +359,6 @@ int xc_linux_restore(int xc_handle, int 
   7.170              } 
   7.171  
   7.172  
   7.173 -
   7.174              if (verify) {
   7.175  
   7.176                  int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE);
   7.177 @@ -386,9 +383,9 @@ int xc_linux_restore(int xc_handle, int 
   7.178              }
   7.179  
   7.180              if (xc_add_mmu_update(xc_handle, mmu, 
   7.181 -                                  (mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE,
   7.182 -                                  pfn)) {
   7.183 -                ERR("machpys mfn=%ld pfn=%ld", mfn, pfn);
   7.184 +                                  (((unsigned long long)mfn) << PAGE_SHIFT) 
   7.185 +                                  | MMU_MACHPHYS_UPDATE, pfn)) {
   7.186 +                ERR("failed machpys update mfn=%lx pfn=%lx", mfn, pfn);
   7.187                  goto out;
   7.188              }
   7.189          } /* end of 'batch' for loop */
   7.190 @@ -399,14 +396,39 @@ int xc_linux_restore(int xc_handle, int 
   7.191  
   7.192      DPRINTF("Received all pages\n");
   7.193  
   7.194 -    if (pt_levels == 3) {
   7.195 +    if(pt_levels == 3) { 
   7.196  
   7.197 -        /* Get all PGDs below 4GB. */
   7.198 +        /* 
   7.199 +        ** XXX SMH on PAE we need to ensure PGDs are in MFNs < 4G. This 
   7.200 +        ** is a little awkward and involves (a) finding all such PGDs and
   7.201 +        ** replacing them with 'lowmem' versions; (b) upating the p2m[] 
   7.202 +        ** with the new info; and (c) canonicalizing all the L1s using the
   7.203 +        ** (potentially updated) p2m[]. 
   7.204 +        ** 
   7.205 +        ** This is relatively slow (and currently involves two passes through
   7.206 +        ** the pfn_type[] array), but at least seems to be correct. May wish
   7.207 +        ** to consider more complex approaches to optimize this later. 
   7.208 +        */
   7.209 +
   7.210 +        int j, k; 
   7.211 +
   7.212 +        /* First pass: find all L3TABs current in > 4G mfns and get new mfns */
   7.213          for (i = 0; i < max_pfn; i++) {
   7.214              
   7.215              if (((pfn_type[i] & LTABTYPE_MASK)==L3TAB) && (p2m[i]>0xfffffUL)) {
   7.216  
   7.217                  unsigned long new_mfn; 
   7.218 +                uint64_t l3ptes[4]; 
   7.219 +                uint64_t *l3tab; 
   7.220 +
   7.221 +                l3tab = (uint64_t *)
   7.222 +                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, 
   7.223 +                                         PROT_READ, p2m[i]); 
   7.224 +
   7.225 +                for(j = 0; j < 4; j++) 
   7.226 +                    l3ptes[j] = l3tab[j]; 
   7.227 +                
   7.228 +                munmap(l3tab, PAGE_SIZE); 
   7.229  
   7.230                  if (!(new_mfn=xc_make_page_below_4G(xc_handle, dom, p2m[i]))) {
   7.231                      ERR("Couldn't get a page below 4GB :-(");
   7.232 @@ -414,15 +436,58 @@ int xc_linux_restore(int xc_handle, int 
   7.233                  }
   7.234                  
   7.235                  p2m[i] = new_mfn;
   7.236 -                if (xc_add_mmu_update(
   7.237 -                        xc_handle, mmu, 
   7.238 -                        (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, i)) {
   7.239 +                if (xc_add_mmu_update(xc_handle, mmu, 
   7.240 +                                      (((unsigned long long)new_mfn) 
   7.241 +                                       << PAGE_SHIFT) | 
   7.242 +                                      MMU_MACHPHYS_UPDATE, i)) {
   7.243                      ERR("Couldn't m2p on PAE root pgdir");
   7.244                      goto out;
   7.245                  }
   7.246 +                
   7.247 +                l3tab = (uint64_t *)
   7.248 +                    xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, 
   7.249 +                                         PROT_READ | PROT_WRITE, p2m[i]); 
   7.250 +                
   7.251 +                for(j = 0; j < 4; j++) 
   7.252 +                    l3tab[j] = l3ptes[j]; 
   7.253 +                
   7.254 +                munmap(l3tab, PAGE_SIZE); 
   7.255 +                
   7.256              }
   7.257          }
   7.258 -        
   7.259 +
   7.260 +        /* Second pass: find all L1TABs and uncanonicalize them */
   7.261 +        j = 0; 
   7.262 +
   7.263 +        for(i = 0; i < max_pfn; i++) { 
   7.264 +            
   7.265 +            if (((pfn_type[i] & LTABTYPE_MASK)==L1TAB)) { 
   7.266 +                region_mfn[j] = p2m[i]; 
   7.267 +                j++; 
   7.268 +            }
   7.269 +
   7.270 +            if(i == (max_pfn-1) || j == MAX_BATCH_SIZE) { 
   7.271 +
   7.272 +                if (!(region_base = xc_map_foreign_batch(
   7.273 +                          xc_handle, dom, PROT_READ | PROT_WRITE, 
   7.274 +                          region_mfn, j))) {  
   7.275 +                    ERR("map batch failed");
   7.276 +                    goto out;
   7.277 +                }
   7.278 +
   7.279 +                for(k = 0; k < j; k++) {
   7.280 +                    if(!uncanonicalize_pagetable(L1TAB, 
   7.281 +                                                 region_base + k*PAGE_SIZE)) {
   7.282 +                        ERR("failed uncanonicalize pt!\n"); 
   7.283 +                        goto out; 
   7.284 +                    } 
   7.285 +                }
   7.286 +                
   7.287 +                munmap(region_base, j*PAGE_SIZE); 
   7.288 +                j = 0; 
   7.289 +            }
   7.290 +        }
   7.291 +
   7.292      }
   7.293  
   7.294  
   7.295 @@ -431,6 +496,7 @@ int xc_linux_restore(int xc_handle, int 
   7.296          goto out;
   7.297      } 
   7.298  
   7.299 +
   7.300      /*
   7.301       * Pin page tables. Do this after writing to them as otherwise Xen
   7.302       * will barf when doing the type-checking.
   7.303 @@ -439,7 +505,7 @@ int xc_linux_restore(int xc_handle, int 
   7.304  
   7.305          if ( (pfn_type[i] & LPINTAB) == 0 )
   7.306              continue;
   7.307 -        
   7.308 +
   7.309          switch(pfn_type[i]) { 
   7.310  
   7.311          case (L1TAB|LPINTAB): 
   7.312 @@ -463,24 +529,17 @@ int xc_linux_restore(int xc_handle, int 
   7.313          }
   7.314  
   7.315          pin[nr_pins].arg1.mfn = p2m[i];
   7.316 +
   7.317 +        nr_pins ++; 
   7.318          
   7.319 -        if (++nr_pins == MAX_PIN_BATCH) {
   7.320 +        if (i == (max_pfn-1) || nr_pins == MAX_PIN_BATCH) {
   7.321              if (xc_mmuext_op(xc_handle, pin, nr_pins, dom) < 0) { 
   7.322                  ERR("Failed to pin batch of %d page tables", nr_pins); 
   7.323                  goto out;
   7.324              } 
   7.325 -            DPRINTF("successfully pinned batch of %d page tables", nr_pins); 
   7.326              nr_pins = 0;
   7.327          }
   7.328      }
   7.329 -    
   7.330 -    if (nr_pins != 0) { 
   7.331 -        if((rc = xc_mmuext_op(xc_handle, pin, nr_pins, dom)) < 0) { 
   7.332 -            ERR("Failed (2) to pin batch of %d page tables", nr_pins); 
   7.333 -            DPRINTF("rc is %d\n", rc); 
   7.334 -            goto out;
   7.335 -        }
   7.336 -    }
   7.337  
   7.338      DPRINTF("\b\b\b\b100%%\n");
   7.339      DPRINTF("Memory reloaded.\n");
   7.340 @@ -579,23 +638,20 @@ int xc_linux_restore(int xc_handle, int 
   7.341      pfn = ctxt.ctrlreg[3] >> PAGE_SHIFT;
   7.342  
   7.343      if (pfn >= max_pfn) {
   7.344 -        DPRINTF("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx\n",
   7.345 -                pfn, max_pfn, pfn_type[pfn]); 
   7.346 -        ERR("PT base is bad.");
   7.347 +        ERR("PT base is bad: pfn=%lu max_pfn=%lu type=%08lx",
   7.348 +            pfn, max_pfn, pfn_type[pfn]); 
   7.349          goto out;
   7.350      }
   7.351  
   7.352      if ((pt_levels == 2) && ((pfn_type[pfn]&LTABTYPE_MASK) != L2TAB)) { 
   7.353 -        DPRINTF("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n",
   7.354 -                pfn, max_pfn, pfn_type[pfn], (unsigned long)L2TAB);
   7.355 -        ERR("PT base is bad.");
   7.356 +        ERR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
   7.357 +            pfn, max_pfn, pfn_type[pfn], (unsigned long)L2TAB);
   7.358          goto out;
   7.359      }
   7.360  
   7.361      if ((pt_levels == 3) && ((pfn_type[pfn]&LTABTYPE_MASK) != L3TAB)) { 
   7.362 -        DPRINTF("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n",
   7.363 -                pfn, max_pfn, pfn_type[pfn], (unsigned long)L3TAB);
   7.364 -        ERR("PT base is bad.");
   7.365 +        ERR("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx",
   7.366 +            pfn, max_pfn, pfn_type[pfn], (unsigned long)L3TAB);
   7.367          goto out;
   7.368      }
   7.369      
     8.1 --- a/tools/libxc/xc_linux_save.c	Wed Nov 16 15:50:36 2005 +0100
     8.2 +++ b/tools/libxc/xc_linux_save.c	Wed Nov 16 17:45:03 2005 +0100
     8.3 @@ -27,13 +27,13 @@
     8.4  
     8.5  
     8.6  /* max mfn of the whole machine */
     8.7 -static uint32_t max_mfn; 
     8.8 +static unsigned long max_mfn; 
     8.9  
    8.10  /* virtual starting address of the hypervisor */
    8.11 -static uint32_t hvirt_start; 
    8.12 +static unsigned long hvirt_start; 
    8.13  
    8.14  /* #levels of page tables used by the currrent guest */
    8.15 -static uint32_t pt_levels; 
    8.16 +static unsigned int pt_levels; 
    8.17  
    8.18  /* total number of pages used by the current guest */
    8.19  static unsigned long max_pfn;
    8.20 @@ -500,6 +500,70 @@ void canonicalize_pagetable(unsigned lon
    8.21  
    8.22  
    8.23  
    8.24 +static unsigned long *xc_map_m2p(int xc_handle, 
    8.25 +                                 unsigned long max_mfn, 
    8.26 +                                 int prot) 
    8.27 +{ 
    8.28 +    privcmd_m2pmfns_t m2p_mfns; 
    8.29 +    privcmd_mmap_t ioctlx; 
    8.30 +    privcmd_mmap_entry_t *entries; 
    8.31 +    unsigned long m2p_chunks, m2p_size; 
    8.32 +    unsigned long *m2p; 
    8.33 +    int i, rc; 
    8.34 +
    8.35 +    m2p_size   = M2P_SIZE(max_mfn); 
    8.36 +    m2p_chunks = M2P_CHUNKS(max_mfn); 
    8.37 +
    8.38 +
    8.39 +    m2p_mfns.num = m2p_chunks; 
    8.40 +
    8.41 +    if(!(m2p_mfns.arr = malloc(m2p_chunks * sizeof(unsigned long)))) { 
    8.42 +        ERR("failed to allocate space for m2p mfns!\n"); 
    8.43 +        return NULL; 
    8.44 +    } 
    8.45 +
    8.46 +    if (ioctl(xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_MFNS, &m2p_mfns) < 0) {
    8.47 +        ERR("xc_get_m2p_mfns:"); 
    8.48 +        return NULL;
    8.49 +    }
    8.50 +
    8.51 +    if((m2p = mmap(NULL, m2p_size, prot, 
    8.52 +                   MAP_SHARED, xc_handle, 0)) == MAP_FAILED) {
    8.53 +        ERR("failed to mmap m2p"); 
    8.54 +        return NULL; 
    8.55 +    } 
    8.56 +    
    8.57 +
    8.58 +    if(!(entries = malloc(m2p_chunks * sizeof(privcmd_mmap_entry_t)))) { 
    8.59 +        ERR("failed to allocate space for mmap entries!\n"); 
    8.60 +        return NULL; 
    8.61 +    } 
    8.62 +
    8.63 +
    8.64 +    ioctlx.num   = m2p_chunks;
    8.65 +    ioctlx.dom   = DOMID_XEN; 
    8.66 +    ioctlx.entry = entries; 
    8.67 +    
    8.68 +    for(i=0; i < m2p_chunks; i++) { 
    8.69 +        
    8.70 +        entries[i].va = (unsigned long)(((void *)m2p) + (i * M2P_CHUNK_SIZE)); 
    8.71 +        entries[i].mfn = m2p_mfns.arr[i]; 
    8.72 +        entries[i].npages = M2P_CHUNK_SIZE >> PAGE_SHIFT;
    8.73 +
    8.74 +    }
    8.75 +
    8.76 +    if((rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx)) < 0) {
    8.77 +        ERR("ioctl_mmap failed (rc = %d)", rc); 
    8.78 +        return NULL; 
    8.79 +    }
    8.80 +        
    8.81 +    free(m2p_mfns.arr); 
    8.82 +    free(entries); 
    8.83 +
    8.84 +    return m2p; 
    8.85 +}
    8.86 +
    8.87 +
    8.88  
    8.89  int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, 
    8.90                    uint32_t max_factor, uint32_t flags)
    8.91 @@ -531,16 +595,12 @@ int xc_linux_save(int xc_handle, int io_
    8.92      /* A copy of the pfn-to-mfn table frame list. */
    8.93      unsigned long *p2m_frame_list = NULL;
    8.94  
    8.95 -    unsigned long m2p_start_mfn;
    8.96 -    
    8.97      /* Live mapping of shared info structure */
    8.98      shared_info_t *live_shinfo = NULL;
    8.99  
   8.100      /* base of the region in which domain memory is mapped */
   8.101      unsigned char *region_base = NULL;
   8.102  
   8.103 -
   8.104 -    
   8.105      /* power of 2 order of max_pfn */
   8.106      int order_nr; 
   8.107  
   8.108 @@ -564,9 +624,6 @@ int xc_linux_save(int xc_handle, int io_
   8.109      
   8.110      initialize_mbit_rate(); 
   8.111  
   8.112 -    DPRINTF("xc_linux_save start DOM%u live=%s\n", dom, live ? 
   8.113 -            "true" : "false"); 
   8.114 -
   8.115      if(!get_platform_info(xc_handle, dom, 
   8.116                            &max_mfn, &hvirt_start, &pt_levels)) {
   8.117          ERR("Unable to get platform info."); 
   8.118 @@ -647,11 +704,13 @@ int xc_linux_save(int xc_handle, int io_
   8.119      }
   8.120  
   8.121      /* Setup the mfn_to_pfn table mapping */
   8.122 -    m2p_start_mfn = xc_get_m2p_start_mfn(xc_handle);
   8.123 -    live_m2p      = xc_map_foreign_range(xc_handle, DOMID_XEN, M2P_SIZE, 
   8.124 -                                         PROT_READ, m2p_start_mfn);
   8.125 +    if(!(live_m2p = xc_map_m2p(xc_handle, max_mfn, PROT_READ))) { 
   8.126 +        ERR("Failed to map live M2P table"); 
   8.127 +        goto out; 
   8.128 +    } 
   8.129 +
   8.130      
   8.131 -    /* Get a local copy fo the live_P2M_frame_list */
   8.132 +    /* Get a local copy of the live_P2M_frame_list */
   8.133      if(!(p2m_frame_list = malloc(P2M_FL_SIZE))) { 
   8.134          ERR("Couldn't allocate p2m_frame_list array");
   8.135          goto out;
   8.136 @@ -662,6 +721,8 @@ int xc_linux_save(int xc_handle, int io_
   8.137      for (i = 0; i < max_pfn; i += ulpp) {
   8.138          if (!translate_mfn_to_pfn(&p2m_frame_list[i/ulpp])) { 
   8.139              ERR("Frame# in pfn-to-mfn frame list is not in pseudophys");
   8.140 +            ERR("entry %d: p2m_frame_list[%ld] is 0x%lx", i, i/ulpp, 
   8.141 +                p2m_frame_list[i/ulpp]); 
   8.142              goto out;
   8.143          }
   8.144      }
   8.145 @@ -693,11 +754,8 @@ int xc_linux_save(int xc_handle, int io_
   8.146          
   8.147      }
   8.148  
   8.149 -#if 0
   8.150 -    sent_last_iter = 0xFFFFFFFF; /* Pretend we sent a /lot/ last time */
   8.151 -#else
   8.152 -    sent_last_iter = 1 << 20; 
   8.153 -#endif
   8.154 +    /* pretend we sent all the pages last iteration */
   8.155 +    sent_last_iter = max_pfn; 
   8.156  
   8.157  
   8.158      /* calculate the power of 2 order of max_pfn, e.g.
   8.159 @@ -705,9 +763,6 @@ int xc_linux_save(int xc_handle, int io_
   8.160      for (i = max_pfn-1, order_nr = 0; i ; i >>= 1, order_nr++)
   8.161          continue;
   8.162  
   8.163 -#undef BITMAP_SIZE
   8.164 -#define BITMAP_SIZE ((1<<20)/8) 
   8.165 -
   8.166      /* Setup to_send / to_fix and to_skip bitmaps */
   8.167      to_send = malloc(BITMAP_SIZE); 
   8.168      to_fix  = calloc(1, BITMAP_SIZE); 
   8.169 @@ -922,10 +977,8 @@ int xc_linux_save(int xc_handle, int io_
   8.170  
   8.171  
   8.172                  /* write out pages in batch */
   8.173 -                if (pagetype == XTAB) {
   8.174 -                    DPRINTF("SKIP BOGUS page %i mfn %08lx\n", j, pfn_type[j]);
   8.175 +                if (pagetype == XTAB)
   8.176                      continue;
   8.177 -                }
   8.178  
   8.179                  pagetype &= LTABTYPE_MASK; 
   8.180                  
   8.181 @@ -950,11 +1003,11 @@ int xc_linux_save(int xc_handle, int io_
   8.182              } /* end of the write out for this batch */
   8.183              
   8.184              sent_this_iter += batch;
   8.185 -            
   8.186 +
   8.187 +            munmap(region_base, batch*PAGE_SIZE);
   8.188 +        
   8.189          } /* end of this while loop for this iteration */
   8.190          
   8.191 -        munmap(region_base, batch*PAGE_SIZE);
   8.192 -        
   8.193        skip: 
   8.194          
   8.195          total_sent += sent_this_iter;
   8.196 @@ -1027,13 +1080,9 @@ int xc_linux_save(int xc_handle, int io_
   8.197  
   8.198      DPRINTF("All memory is saved\n");
   8.199  
   8.200 -    /* Success! */
   8.201 -    rc = 0;
   8.202 -    
   8.203 -    /* ^^^^^^ XXX SMH: hmm.. not sure that's really success! */
   8.204 -    
   8.205      /* Zero terminate */
   8.206 -    if (!write_exact(io_fd, &rc, sizeof(int))) { 
   8.207 +    i = 0; 
   8.208 +    if (!write_exact(io_fd, &i, sizeof(int))) { 
   8.209          ERR("Error when writing to state file (6)");
   8.210          goto out;
   8.211      }
   8.212 @@ -1043,17 +1092,17 @@ int xc_linux_save(int xc_handle, int io_
   8.213          unsigned int i,j;
   8.214          unsigned long pfntab[1024]; 
   8.215  
   8.216 -        for ( i = 0, j = 0; i < max_pfn; i++ ) {
   8.217 -            if ( ! is_mapped(live_p2m[i]) )
   8.218 +        for (i = 0, j = 0; i < max_pfn; i++) {
   8.219 +            if (!is_mapped(live_p2m[i]))
   8.220                  j++;
   8.221          }
   8.222 -
   8.223 +        
   8.224          if(!write_exact(io_fd, &j, sizeof(unsigned int))) { 
   8.225              ERR("Error when writing to state file (6a)");
   8.226              goto out;
   8.227          }	
   8.228          
   8.229 -        for ( i = 0, j = 0; i < max_pfn; ) {
   8.230 +        for (i = 0, j = 0; i < max_pfn; ) {
   8.231  
   8.232              if (!is_mapped(live_p2m[i]))
   8.233                  pfntab[j++] = i;
   8.234 @@ -1097,7 +1146,10 @@ int xc_linux_save(int xc_handle, int io_
   8.235          ERR("Error when writing to state file (1)");
   8.236          goto out;
   8.237      }
   8.238 -    
   8.239 +
   8.240 +    /* Success! */
   8.241 +    rc = 0;
   8.242 +
   8.243   out:
   8.244  
   8.245      if (live_shinfo)
   8.246 @@ -1110,7 +1162,7 @@ int xc_linux_save(int xc_handle, int io_
   8.247          munmap(live_p2m, P2M_SIZE); 
   8.248  
   8.249      if(live_m2p) 
   8.250 -        munmap(live_m2p, M2P_SIZE); 
   8.251 +        munmap(live_m2p, M2P_SIZE(max_mfn)); 
   8.252  
   8.253      free(pfn_type);
   8.254      free(pfn_batch);
     9.1 --- a/tools/libxc/xc_private.c	Wed Nov 16 15:50:36 2005 +0100
     9.2 +++ b/tools/libxc/xc_private.c	Wed Nov 16 17:45:03 2005 +0100
     9.3 @@ -260,18 +260,6 @@ long long xc_domain_get_cpu_usage( int x
     9.4  }
     9.5  
     9.6  
     9.7 -unsigned long xc_get_m2p_start_mfn ( int xc_handle )
     9.8 -{
     9.9 -    unsigned long mfn;
    9.10 -
    9.11 -    if ( ioctl( xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN, &mfn ) < 0 )
    9.12 -    {
    9.13 -        perror("xc_get_m2p_start_mfn:");
    9.14 -        return 0;
    9.15 -    }
    9.16 -    return mfn;
    9.17 -}
    9.18 -
    9.19  int xc_get_pfn_list(int xc_handle,
    9.20                      uint32_t domid, 
    9.21                      unsigned long *pfn_buf, 
    10.1 --- a/tools/libxc/xg_private.h	Wed Nov 16 15:50:36 2005 +0100
    10.2 +++ b/tools/libxc/xg_private.h	Wed Nov 16 17:45:03 2005 +0100
    10.3 @@ -153,8 +153,6 @@ typedef struct mfn_mapper {
    10.4      
    10.5  } mfn_mapper_t;
    10.6  
    10.7 -unsigned long xc_get_m2p_start_mfn (int xc_handle);
    10.8 -
    10.9  int xc_copy_to_domain_page(int xc_handle, uint32_t domid,
   10.10                              unsigned long dst_pfn, void *src_page);
   10.11  
    11.1 --- a/tools/libxc/xg_save_restore.h	Wed Nov 16 15:50:36 2005 +0100
    11.2 +++ b/tools/libxc/xg_save_restore.h	Wed Nov 16 17:45:03 2005 +0100
    11.3 @@ -4,6 +4,8 @@
    11.4  ** Defintions and utilities for save / restore. 
    11.5  */
    11.6  
    11.7 +#include "xc_private.h"
    11.8 +
    11.9  #define DEBUG    1
   11.10  #define PROGRESS 0
   11.11  
   11.12 @@ -55,25 +57,24 @@ while (0)
   11.13  ** Returns 1 on success, 0 on failure. 
   11.14  */
   11.15  static int get_platform_info(int xc_handle, uint32_t dom, 
   11.16 -                             /* OUT */ uint32_t *max_mfn,  
   11.17 -                             /* OUT */ uint32_t *hvirt_start, 
   11.18 -                             /* OUT */ uint32_t *pt_levels)
   11.19 +                             /* OUT */ unsigned long *max_mfn,  
   11.20 +                             /* OUT */ unsigned long *hvirt_start, 
   11.21 +                             /* OUT */ unsigned int *pt_levels)
   11.22      
   11.23  { 
   11.24      xen_capabilities_info_t xen_caps = "";
   11.25      xen_platform_parameters_t xen_params;
   11.26 -    xc_physinfo_t physinfo;
   11.27      
   11.28 -    if (xc_physinfo(xc_handle, &physinfo) != 0) 
   11.29 -        return 0;
   11.30 -    
   11.31 +
   11.32      if (xc_version(xc_handle, XENVER_platform_parameters, &xen_params) != 0)
   11.33          return 0;
   11.34      
   11.35      if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0)
   11.36          return 0;
   11.37  
   11.38 -    *max_mfn =     physinfo.total_pages;
   11.39 +    if (xc_memory_op(xc_handle, XENMEM_maximum_ram_page, max_mfn) != 0)
   11.40 +        return 0; 
   11.41 +    
   11.42      *hvirt_start = xen_params.virt_start;
   11.43  
   11.44      if (strstr(xen_caps, "xen-3.0-x86_64"))
   11.45 @@ -95,13 +96,22 @@ static int get_platform_info(int xc_hand
   11.46  ** entry tell us whether or not the the PFN is currently mapped.
   11.47  */
   11.48  
   11.49 -#define PFN_TO_KB(_pfn) ((_pfn) * PAGE_SIZE / 1024)
   11.50 +#define PFN_TO_KB(_pfn) ((_pfn) << (PAGE_SHIFT - 10))
   11.51  #define ROUNDUP(_x,_w) (((unsigned long)(_x)+(1UL<<(_w))-1) & ~((1UL<<(_w))-1))
   11.52  
   11.53 -/* Size in bytes of the M2P and P2M (both rounded up to nearest PAGE_SIZE) */
   11.54 -#define M2P_SIZE ROUNDUP((max_mfn * sizeof(unsigned long)), PAGE_SHIFT) 
   11.55 -#define P2M_SIZE ROUNDUP((max_pfn * sizeof(unsigned long)), PAGE_SHIFT) 
   11.56  
   11.57 +/* 
   11.58 +** The M2P is made up of some number of 'chunks' of at least 2MB in size. 
   11.59 +** The below definitions and utility function(s) deal with mapping the M2P 
   11.60 +** regarldess of the underlying machine memory size or architecture. 
   11.61 +*/
   11.62 +#define M2P_SHIFT       L2_PAGETABLE_SHIFT_PAE 
   11.63 +#define M2P_CHUNK_SIZE  (1 << M2P_SHIFT) 
   11.64 +#define M2P_SIZE(_m)    ROUNDUP(((_m) * sizeof(unsigned long)), M2P_SHIFT) 
   11.65 +#define M2P_CHUNKS(_m)  (M2P_SIZE((_m)) >> M2P_SHIFT)
   11.66 +
   11.67 +/* Size in bytes of the P2M (rounded up to the nearest PAGE_SIZE bytes) */
   11.68 +#define P2M_SIZE        ROUNDUP((max_pfn * sizeof(unsigned long)), PAGE_SHIFT) 
   11.69  
   11.70  /* Number of unsigned longs in a page */
   11.71  #define ulpp            (PAGE_SIZE/sizeof(unsigned long))
    12.1 --- a/tools/python/xen/xend/XendCheckpoint.py	Wed Nov 16 15:50:36 2005 +0100
    12.2 +++ b/tools/python/xen/xend/XendCheckpoint.py	Wed Nov 16 17:45:03 2005 +0100
    12.3 @@ -129,7 +129,7 @@ def restore(xd, fd):
    12.4          l = read_exact(fd, sizeof_unsigned_long,
    12.5                         "not a valid guest state file: pfn count read")
    12.6          nr_pfns = unpack("=L", l)[0]   # XXX endianess
    12.7 -        if nr_pfns > 1024*1024:     # XXX
    12.8 +        if nr_pfns > 16*1024*1024:     # XXX 
    12.9              raise XendError(
   12.10                  "not a valid guest state file: pfn count out of range")
   12.11  
    13.1 --- a/xen/arch/x86/mm.c	Wed Nov 16 15:50:36 2005 +0100
    13.2 +++ b/xen/arch/x86/mm.c	Wed Nov 16 17:45:03 2005 +0100
    13.3 @@ -898,6 +898,7 @@ static int alloc_l3_table(struct pfn_inf
    13.4      return 1;
    13.5  
    13.6   fail:
    13.7 +    MEM_LOG("Failure in alloc_l3_table: entry %d", i);
    13.8      while ( i-- > 0 )
    13.9          if ( is_guest_l3_slot(i) )
   13.10              put_page_from_l3e(pl3e[i], pfn);
   13.11 @@ -948,6 +949,7 @@ static int alloc_l4_table(struct pfn_inf
   13.12      return 1;
   13.13  
   13.14   fail:
   13.15 +    MEM_LOG("Failure in alloc_l4_table: entry %d", i);
   13.16      while ( i-- > 0 )
   13.17          if ( is_guest_l4_slot(i) )
   13.18              put_page_from_l4e(pl4e[i], pfn);