ia64/xen-unstable

changeset 6757:413c911e5780

Re-indent xc_linux_restore, and add code to force PAE
root pgdirs below 4GB on restore.

Signed-off-by: Ian Pratt <ian@xensource.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Sep 12 12:48:33 2005 +0000 (2005-09-12)
parents f752e0c873a6
children 7ae8090e5f67
files tools/libxc/xc_linux_restore.c
line diff
     1.1 --- a/tools/libxc/xc_linux_restore.c	Mon Sep 12 12:32:20 2005 +0000
     1.2 +++ b/tools/libxc/xc_linux_restore.c	Mon Sep 12 12:48:33 2005 +0000
     1.3 @@ -42,18 +42,18 @@ read_exact(int fd, void *buf, size_t cou
     1.4      unsigned char *b = buf;
     1.5  
     1.6      while (r < count) {
     1.7 -	s = read(fd, &b[r], count - r);
     1.8 -	if (s <= 0)
     1.9 -	    break;
    1.10 -	r += s;
    1.11 +        s = read(fd, &b[r], count - r);
    1.12 +        if (s <= 0)
    1.13 +            break;
    1.14 +        r += s;
    1.15      }
    1.16  
    1.17      return r;
    1.18  }
    1.19  
    1.20  int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
    1.21 -		     unsigned int store_evtchn, unsigned long *store_mfn,
    1.22 -		     unsigned int console_evtchn, unsigned long *console_mfn)
    1.23 +                     unsigned int store_evtchn, unsigned long *store_mfn,
    1.24 +                     unsigned int console_evtchn, unsigned long *console_mfn)
    1.25  {
    1.26      dom0_op_t op;
    1.27      int rc = 1, i, n, k;
    1.28 @@ -91,6 +91,8 @@ int xc_linux_restore(int xc_handle, int 
    1.29      /* A temporary mapping of the guest's start_info page. */
    1.30      start_info_t *start_info;
    1.31  
    1.32 +    int pt_levels = 2; /* XXX auto-detect this */
    1.33 +
    1.34      char *region_base;
    1.35  
    1.36      xc_mmu_t *mmu = NULL;
    1.37 @@ -112,8 +114,8 @@ int xc_linux_restore(int xc_handle, int 
    1.38      }
    1.39  
    1.40      if (read_exact(io_fd, pfn_to_mfn_frame_list, PAGE_SIZE) != PAGE_SIZE) {
    1.41 -	ERR("read pfn_to_mfn_frame_list failed");
    1.42 -	goto out;
    1.43 +        ERR("read pfn_to_mfn_frame_list failed");
    1.44 +        goto out;
    1.45      }
    1.46  
    1.47      /* We want zeroed memory so use calloc rather than malloc. */
    1.48 @@ -289,10 +291,10 @@ int xc_linux_restore(int xc_handle, int 
    1.49                          if ( xpfn >= nr_pfns )
    1.50                          {
    1.51                              ERR("Frame number in type %lu page "
    1.52 -                                       "table is out of range. i=%d k=%d "
    1.53 -                                       "pfn=0x%lx nr_pfns=%lu", 
    1.54 -                                       region_pfn_type[i]>>28, i, 
    1.55 -                                       k, xpfn, nr_pfns);
    1.56 +                                "table is out of range. i=%d k=%d "
    1.57 +                                "pfn=0x%lx nr_pfns=%lu", 
    1.58 +                                region_pfn_type[i]>>28, i, 
    1.59 +                                k, xpfn, nr_pfns);
    1.60                              goto out;
    1.61                          }
    1.62  
    1.63 @@ -317,10 +319,10 @@ int xc_linux_restore(int xc_handle, int 
    1.64                          if ( xpfn >= nr_pfns )
    1.65                          {
    1.66                              ERR("Frame number in type %lu page"
    1.67 -                                       " table is out of range. i=%d k=%d "
    1.68 -                                       "pfn=%lu nr_pfns=%lu",
    1.69 -                                       region_pfn_type[i]>>28, i, k, 
    1.70 -                                       xpfn, nr_pfns);
    1.71 +                                " table is out of range. i=%d k=%d "
    1.72 +                                "pfn=%lu nr_pfns=%lu",
    1.73 +                                region_pfn_type[i]>>28, i, k, 
    1.74 +                                xpfn, nr_pfns);
    1.75                              goto out;
    1.76                          }
    1.77  
    1.78 @@ -334,8 +336,8 @@ int xc_linux_restore(int xc_handle, int 
    1.79  
    1.80              default:
    1.81                  ERR("Bogus page type %lx page table is "
    1.82 -                           "out of range. i=%d nr_pfns=%lu", 
    1.83 -                           region_pfn_type[i], i, nr_pfns);
    1.84 +                    "out of range. i=%d nr_pfns=%lu", 
    1.85 +                    region_pfn_type[i], i, nr_pfns);
    1.86                  goto out;
    1.87  
    1.88              } /* end of page type switch statement */
    1.89 @@ -362,8 +364,8 @@ int xc_linux_restore(int xc_handle, int 
    1.90              }
    1.91  
    1.92              if ( xc_add_mmu_update(xc_handle, mmu,
    1.93 -				   (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE,
    1.94 -				   pfn) )
    1.95 +                                   (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE,
    1.96 +                                   pfn) )
    1.97              {
    1.98                  printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn);
    1.99                  goto out;
   1.100 @@ -377,6 +379,33 @@ int xc_linux_restore(int xc_handle, int 
   1.101  
   1.102      DPRINTF("Received all pages\n");
   1.103  
   1.104 +    if ( pt_levels == 3 )
   1.105 +    {
   1.106 +        /* Get all PGDs below 4GB. */
   1.107 +        for ( i = 0; i < nr_pfns; i++ )
   1.108 +        {
   1.109 +            if ( ((pfn_type[i] & LTABTYPE_MASK) == L3TAB) &&
   1.110 +                 (pfn_to_mfn_table[i] > 0xfffffUL) )
   1.111 +            {
   1.112 +                unsigned long new_mfn = xc_make_page_below_4G(
   1.113 +                    xc_handle, dom, pfn_to_mfn_table[i]);
   1.114 +                if ( new_mfn == 0 )
   1.115 +                {
   1.116 +                    fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
   1.117 +                    goto out;
   1.118 +                }
   1.119 +                pfn_to_mfn_table[i] = new_mfn;
   1.120 +                if ( xc_add_mmu_update(
   1.121 +                    xc_handle, mmu, (new_mfn << PAGE_SHIFT) |
   1.122 +                    MMU_MACHPHYS_UPDATE, i) )
   1.123 +                {
   1.124 +                    fprintf(stderr, "Couldn't m2p on PAE root pgdir\n");
   1.125 +                    goto out;
   1.126 +                }
   1.127 +            }
   1.128 +        }
   1.129 +    }
   1.130 +
   1.131      if ( xc_finish_mmu_updates(xc_handle, mmu) )
   1.132          goto out;
   1.133  
   1.134 @@ -410,57 +439,57 @@ int xc_linux_restore(int xc_handle, int 
   1.135  
   1.136      /* Get the list of PFNs that are not in the psuedo-phys map */
   1.137      {
   1.138 -	unsigned int count;
   1.139 +        unsigned int count;
   1.140          unsigned long *pfntab;
   1.141 -	int rc;
   1.142 -
   1.143 -	if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) )
   1.144 -	{
   1.145 -	    ERR("Error when reading pfn count");
   1.146 -	    goto out;
   1.147 -	}
   1.148 +        int rc;
   1.149  
   1.150 -	pfntab = malloc( sizeof(unsigned int) * count );
   1.151 -	if ( pfntab == NULL )
   1.152 -	{
   1.153 -	    ERR("Out of memory");
   1.154 -	    goto out;
   1.155 -	}
   1.156 +        if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) )
   1.157 +        {
   1.158 +            ERR("Error when reading pfn count");
   1.159 +            goto out;
   1.160 +        }
   1.161  
   1.162 -	if ( read_exact(io_fd, pfntab, sizeof(unsigned int)*count) !=
   1.163 +        pfntab = malloc( sizeof(unsigned int) * count );
   1.164 +        if ( pfntab == NULL )
   1.165 +        {
   1.166 +            ERR("Out of memory");
   1.167 +            goto out;
   1.168 +        }
   1.169 +
   1.170 +        if ( read_exact(io_fd, pfntab, sizeof(unsigned int)*count) !=
   1.171               sizeof(unsigned int)*count )
   1.172 -	{
   1.173 -	    ERR("Error when reading pfntab");
   1.174 -	    goto out;
   1.175 -	}
   1.176 +        {
   1.177 +            ERR("Error when reading pfntab");
   1.178 +            goto out;
   1.179 +        }
   1.180  
   1.181 -	for ( i = 0; i < count; i++ )
   1.182 -	{
   1.183 -	    unsigned long pfn = pfntab[i];
   1.184 -	    pfntab[i]=pfn_to_mfn_table[pfn];
   1.185 -	    pfn_to_mfn_table[pfn] = 0x80000001;  // not in pmap
   1.186 -	}
   1.187 +        for ( i = 0; i < count; i++ )
   1.188 +        {
   1.189 +            unsigned long pfn = pfntab[i];
   1.190 +            pfntab[i]=pfn_to_mfn_table[pfn];
   1.191 +            pfn_to_mfn_table[pfn] = 0x80000001;  // not in pmap
   1.192 +        }
   1.193  
   1.194 -	if ( count > 0 )
   1.195 -	{
   1.196 +        if ( count > 0 )
   1.197 +        {
   1.198              struct xen_memory_reservation reservation = {
   1.199                  .extent_start = pfntab,
   1.200                  .nr_extents   = count,
   1.201                  .extent_order = 0,
   1.202                  .domid        = dom
   1.203              };
   1.204 -	    if ( (rc = xc_memory_op(xc_handle,
   1.205 +            if ( (rc = xc_memory_op(xc_handle,
   1.206                                      XENMEM_decrease_reservation,
   1.207                                      &reservation)) != count )
   1.208 -	    {
   1.209 -		ERR("Could not decrease reservation : %d",rc);
   1.210 -		goto out;
   1.211 -	    }
   1.212 -	    else
   1.213 -	    {
   1.214 -		printf("Decreased reservation by %d pages\n", count);
   1.215 -	    }
   1.216 -	}	
   1.217 +            {
   1.218 +                ERR("Could not decrease reservation : %d",rc);
   1.219 +                goto out;
   1.220 +            }
   1.221 +            else
   1.222 +            {
   1.223 +                printf("Decreased reservation by %d pages\n", count);
   1.224 +            }
   1.225 +        } 
   1.226      }
   1.227  
   1.228      if ( read_exact(io_fd, &ctxt,            sizeof(ctxt)) != sizeof(ctxt) ||
   1.229 @@ -484,10 +513,10 @@ int xc_linux_restore(int xc_handle, int 
   1.230      start_info->shared_info = shared_info_frame << PAGE_SHIFT;
   1.231      start_info->flags       = 0;
   1.232      *store_mfn = start_info->store_mfn   =
   1.233 -	pfn_to_mfn_table[start_info->store_mfn];
   1.234 +        pfn_to_mfn_table[start_info->store_mfn];
   1.235      start_info->store_evtchn = store_evtchn;
   1.236      *console_mfn = start_info->console_mfn   =
   1.237 -	pfn_to_mfn_table[start_info->console_mfn];
   1.238 +        pfn_to_mfn_table[start_info->console_mfn];
   1.239      start_info->console_evtchn = console_evtchn;
   1.240      munmap(start_info, PAGE_SIZE);
   1.241  
   1.242 @@ -522,7 +551,7 @@ int xc_linux_restore(int xc_handle, int 
   1.243  
   1.244      /* clear any pending events and the selector */
   1.245      memset(&(shared_info->evtchn_pending[0]), 0,
   1.246 -	   sizeof (shared_info->evtchn_pending));
   1.247 +           sizeof (shared_info->evtchn_pending));
   1.248      for ( i = 0; i < MAX_VIRT_CPUS; i++ )
   1.249          shared_info->vcpu_data[i].evtchn_pending_sel = 0;
   1.250  
   1.251 @@ -548,7 +577,7 @@ int xc_linux_restore(int xc_handle, int 
   1.252      }
   1.253      
   1.254      if ( (live_pfn_to_mfn_table = 
   1.255 -	  xc_map_foreign_batch(xc_handle, dom, 
   1.256 +          xc_map_foreign_batch(xc_handle, dom, 
   1.257                                 PROT_WRITE,
   1.258                                 pfn_to_mfn_frame_list,
   1.259                                 (nr_pfns+1023)/1024 )) == 0 )