ia64/xen-unstable

changeset 9206:d4a2af362e5e

Make xc_linux_build() load the initrd page-by-page rather
than all in one go, to conserve memory. This always has been
the behaviour, but it was changed by a changeset earlier today.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Thu Mar 09 15:16:35 2006 +0100 (2006-03-09)
parents a1fcee3b2abe
children 80bc37d5a32f
files tools/libxc/xc_hvm_build.c tools/libxc/xc_linux_build.c
line diff
     1.1 --- a/tools/libxc/xc_hvm_build.c	Thu Mar 09 14:35:36 2006 +0100
     1.2 +++ b/tools/libxc/xc_hvm_build.c	Thu Mar 09 15:16:35 2006 +0100
     1.3 @@ -641,7 +641,7 @@ int xc_hvm_build_mem(int xc_handle,
     1.4      if ( (image_buffer == NULL) || (image_size == 0) )
     1.5      {
     1.6          ERROR("kernel image buffer not present");
     1.7 -        return -EINVAL;
     1.8 +        return -1;
     1.9      }
    1.10  
    1.11      img = xc_inflate_buffer(image_buffer, image_size, &img_len);
     2.1 --- a/tools/libxc/xc_linux_build.c	Thu Mar 09 14:35:36 2006 +0100
     2.2 +++ b/tools/libxc/xc_linux_build.c	Thu Mar 09 15:16:35 2006 +0100
     2.3 @@ -46,6 +46,15 @@
     2.4  #define probe_aout9(image,image_size,load_funcs) 1
     2.5  #endif
     2.6  
     2.7 +struct initrd_info {
     2.8 +    enum { INITRD_none, INITRD_file, INITRD_mem } type;
     2.9 +    unsigned long len;
    2.10 +    union {
    2.11 +        gzFile file_handle;
    2.12 +        char *mem_addr;
    2.13 +    } u;
    2.14 +};
    2.15 +
    2.16  static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
    2.17      [XENFEAT_writable_page_tables]       = "writable_page_tables",
    2.18      [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
    2.19 @@ -132,6 +141,42 @@ static int probeimageformat(const char *
    2.20      return 0;
    2.21  }
    2.22  
    2.23 +int load_initrd(int xc_handle, domid_t dom,
    2.24 +                struct initrd_info *initrd,
    2.25 +                unsigned long physbase,
    2.26 +                unsigned long *phys_to_mach)
    2.27 +{
    2.28 +    char page[PAGE_SIZE];
    2.29 +    unsigned long pfn_start, pfn, nr_pages;
    2.30 +
    2.31 +    if ( initrd->type == INITRD_none )
    2.32 +        return 0;
    2.33 +
    2.34 +    pfn_start = physbase >> PAGE_SHIFT;
    2.35 +    nr_pages  = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
    2.36 +
    2.37 +    for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ )
    2.38 +    {
    2.39 +        if ( initrd->type == INITRD_mem )
    2.40 +        {
    2.41 +            xc_copy_to_domain_page(
    2.42 +                xc_handle, dom, phys_to_mach[pfn],
    2.43 +                &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]);
    2.44 +        }
    2.45 +        else
    2.46 +        {
    2.47 +            if ( gzread(initrd->u.file_handle, page, PAGE_SIZE) == -1 )
    2.48 +            {
    2.49 +                PERROR("Error reading initrd image, could not");
    2.50 +                return -EINVAL;
    2.51 +            }
    2.52 +            xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn], page);
    2.53 +        }
    2.54 +    }
    2.55 +
    2.56 +    return 0;
    2.57 +}
    2.58 +
    2.59  #define alloc_pt(ltab, vltab, pltab)                                    \
    2.60  do {                                                                    \
    2.61      pltab = ppt_alloc++;                                                \
    2.62 @@ -407,7 +452,7 @@ extern unsigned long xc_ia64_fpsr_defaul
    2.63  static int setup_guest(int xc_handle,
    2.64                         uint32_t dom,
    2.65                         const char *image, unsigned long image_size,
    2.66 -                       const char *initrd, unsigned long initrd_len,
    2.67 +                       struct initrd_info *initrd,
    2.68                         unsigned long nr_pages,
    2.69                         unsigned long *pvsi, unsigned long *pvke,
    2.70                         unsigned long *pvss, vcpu_guest_context_t *ctxt,
    2.71 @@ -441,7 +486,7 @@ static int setup_guest(int xc_handle,
    2.72  
    2.73      dsi.v_start      = round_pgdown(dsi.v_start);
    2.74      vinitrd_start    = round_pgup(dsi.v_end);
    2.75 -    vinitrd_end      = vinitrd_start + initrd_len;
    2.76 +    vinitrd_end      = vinitrd_start + initrd->len;
    2.77      v_end            = round_pgup(vinitrd_end);
    2.78  
    2.79      start_page = dsi.v_start >> PAGE_SHIFT;
    2.80 @@ -452,7 +497,8 @@ static int setup_guest(int xc_handle,
    2.81          goto error_out;
    2.82      }
    2.83  
    2.84 -    if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array, start_page, pgnr) != pgnr )
    2.85 +    if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array,
    2.86 +                              start_page, pgnr) != pgnr )
    2.87      {
    2.88          PERROR("Could not get the page frame list");
    2.89          goto error_out;
    2.90 @@ -472,17 +518,9 @@ static int setup_guest(int xc_handle,
    2.91      (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
    2.92                             &dsi);
    2.93  
    2.94 -    /* Load the initial ramdisk image, if present */
    2.95 -    if ( initrd_len != 0 )
    2.96 -    {
    2.97 -        /* Pages are not contiguous, so do the copy one page at a time */
    2.98 -        for ( i = (vinitrd_start - dsi.v_start), offset = 0; 
    2.99 -              i < (vinitrd_end - dsi.v_start);
   2.100 -              i += PAGE_SIZE, offset += PAGE_SIZE )
   2.101 -            xc_copy_to_domain_page(xc_handle, dom,
   2.102 -                                   page_array[i>>PAGE_SHIFT],
   2.103 -                                   &initrd[offset]);
   2.104 -    }
   2.105 +    if ( load_initrd(xc_handle, dom, initrd,
   2.106 +                     vinitrd_start - dsi.v_start, page_array) )
   2.107 +        goto error_out;
   2.108  
   2.109      *pvke = dsi.v_kernentry;
   2.110  
   2.111 @@ -513,10 +551,10 @@ static int setup_guest(int xc_handle,
   2.112      start_info->console_mfn   = nr_pages - 1;
   2.113      start_info->console_evtchn = console_evtchn;
   2.114      start_info->nr_pages       = nr_pages; // FIXME?: nr_pages - 2 ????
   2.115 -    if ( initrd_len != 0 )
   2.116 +    if ( initrd->len != 0 )
   2.117      {
   2.118          ctxt->initrd.start    = vinitrd_start;
   2.119 -        ctxt->initrd.size     = initrd_len;
   2.120 +        ctxt->initrd.size     = initrd->len;
   2.121      }
   2.122      else
   2.123      {
   2.124 @@ -541,7 +579,7 @@ static int setup_guest(int xc_handle,
   2.125  static int setup_guest(int xc_handle,
   2.126                         uint32_t dom,
   2.127                         const char *image, unsigned long image_size,
   2.128 -                       const char *initrd, unsigned long initrd_len,
   2.129 +                       struct initrd_info *initrd,
   2.130                         unsigned long nr_pages,
   2.131                         unsigned long *pvsi, unsigned long *pvke,
   2.132                         unsigned long *pvss, vcpu_guest_context_t *ctxt,
   2.133 @@ -610,7 +648,7 @@ static int setup_guest(int xc_handle,
   2.134       * which we solve by exhaustive search.
   2.135       */
   2.136      vinitrd_start    = round_pgup(dsi.v_end);
   2.137 -    vinitrd_end      = vinitrd_start + initrd_len;
   2.138 +    vinitrd_end      = vinitrd_start + initrd->len;
   2.139      vphysmap_start   = round_pgup(vinitrd_end);
   2.140      vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
   2.141      vstartinfo_start = round_pgup(vphysmap_end);
   2.142 @@ -731,20 +769,12 @@ static int setup_guest(int xc_handle,
   2.143          }
   2.144      }
   2.145  
   2.146 -    shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, required_features);
   2.147 +    shadow_mode_enabled = test_feature_bit(
   2.148 +        XENFEAT_auto_translated_physmap, required_features);
   2.149  
   2.150 -    /* Load the initial ramdisk image, if present. */
   2.151 -    if ( initrd_len != 0 )
   2.152 -    {
   2.153 -        int offset;
   2.154 -        /* Pages are not contiguous, so do the inflation a page at a time. */
   2.155 -        for ( i = (vinitrd_start - dsi.v_start), offset = 0;
   2.156 -              i < (vinitrd_end - dsi.v_start);
   2.157 -              i += PAGE_SIZE, offset += PAGE_SIZE )
   2.158 -            xc_copy_to_domain_page(xc_handle, dom,
   2.159 -                                   page_array[i>>PAGE_SHIFT],
   2.160 -                                   &initrd[offset]);
   2.161 -    }
   2.162 +    if ( load_initrd(xc_handle, dom, initrd,
   2.163 +                     vinitrd_start - dsi.v_start, page_array) )
   2.164 +        goto error_out;
   2.165  
   2.166      /* setup page tables */
   2.167  #if defined(__i386__)
   2.168 @@ -901,10 +931,10 @@ static int setup_guest(int xc_handle,
   2.169      start_info->store_evtchn = store_evtchn;
   2.170      start_info->console_mfn   = guest_console_mfn;
   2.171      start_info->console_evtchn = console_evtchn;
   2.172 -    if ( initrd_len != 0 )
   2.173 +    if ( initrd->len != 0 )
   2.174      {
   2.175          start_info->mod_start    = vinitrd_start;
   2.176 -        start_info->mod_len      = initrd_len;
   2.177 +        start_info->mod_len      = initrd->len;
   2.178      }
   2.179      if ( cmdline != NULL )
   2.180      { 
   2.181 @@ -961,8 +991,7 @@ static int xc_linux_build_internal(int x
   2.182                                     uint32_t domid,
   2.183                                     char *image,
   2.184                                     unsigned long image_size,
   2.185 -                                   char *initrd,
   2.186 -                                   unsigned long initrd_len,
   2.187 +                                   struct initrd_info *initrd,
   2.188                                     const char *cmdline,
   2.189                                     const char *features,
   2.190                                     unsigned long flags,
   2.191 @@ -1016,7 +1045,7 @@ static int xc_linux_build_internal(int x
   2.192      memset(ctxt, 0, sizeof(*ctxt));
   2.193  
   2.194      if ( setup_guest(xc_handle, domid, image, image_size, 
   2.195 -                     initrd, initrd_len,
   2.196 +                     initrd,
   2.197                       nr_pages, 
   2.198                       &vstartinfo_start, &vkern_entry,
   2.199                       &vstack_start, ctxt, cmdline,
   2.200 @@ -1132,14 +1161,15 @@ int xc_linux_build_mem(int xc_handle,
   2.201                         unsigned long *console_mfn)
   2.202  {
   2.203      int            sts;
   2.204 -    char          *img_buf, *ram_buf;
   2.205 -    unsigned long  img_len, ram_len;
   2.206 +    char          *img_buf;
   2.207 +    unsigned long  img_len;
   2.208 +    struct initrd_info initrd_info = { .type = INITRD_none };
   2.209  
   2.210      /* A kernel buffer is required */
   2.211      if ( (image_buffer == NULL) || (image_size == 0) )
   2.212      {
   2.213          ERROR("kernel image buffer not present");
   2.214 -        return EINVAL;
   2.215 +        return -1;
   2.216      }
   2.217  
   2.218      /* If it's gzipped, inflate it;  otherwise, use as is */
   2.219 @@ -1149,28 +1179,25 @@ int xc_linux_build_mem(int xc_handle,
   2.220      if ( img_buf == NULL )
   2.221      {
   2.222          ERROR("unable to inflate kernel image buffer");
   2.223 -        return EFAULT;
   2.224 +        return -1;
   2.225      }
   2.226  
   2.227      /* RAM disks are optional; if we get one, inflate it */
   2.228      if ( initrd != NULL )
   2.229      {
   2.230 -        ram_buf = xc_inflate_buffer(initrd, initrd_len, &ram_len);
   2.231 -        if ( ram_buf == NULL )
   2.232 +        initrd_info.type = INITRD_mem;
   2.233 +        initrd_info.u.mem_addr = xc_inflate_buffer(
   2.234 +            initrd, initrd_len, &initrd_info.len);
   2.235 +        if ( initrd_info.u.mem_addr == NULL )
   2.236          {
   2.237              ERROR("unable to inflate ram disk buffer");
   2.238              sts = -1;
   2.239              goto out;
   2.240          }
   2.241      }
   2.242 -    else
   2.243 -    {
   2.244 -        ram_buf = (char *)initrd;
   2.245 -        ram_len = initrd_len;
   2.246 -    }
   2.247  
   2.248      sts = xc_linux_build_internal(xc_handle, domid, img_buf, img_len,
   2.249 -                                  ram_buf, ram_len, cmdline, features, flags,
   2.250 +                                  &initrd_info, cmdline, features, flags,
   2.251                                    store_evtchn, store_mfn,
   2.252                                    console_evtchn, console_mfn);
   2.253  
   2.254 @@ -1180,8 +1207,9 @@ int xc_linux_build_mem(int xc_handle,
   2.255      /* Don't unnecessarily annoy/surprise/confound the caller */
   2.256      if ( (img_buf != NULL) && (img_buf != image_buffer) )
   2.257          free(img_buf);
   2.258 -    if ( (ram_buf != NULL) && (ram_buf != initrd) )
   2.259 -        free(ram_buf);
   2.260 +    if ( (initrd_info.u.mem_addr != NULL) &&
   2.261 +         (initrd_info.u.mem_addr != initrd) )
   2.262 +        free(initrd_info.u.mem_addr);
   2.263  
   2.264      return sts;
   2.265  }
   2.266 @@ -1198,28 +1226,44 @@ int xc_linux_build(int xc_handle,
   2.267                     unsigned int console_evtchn,
   2.268                     unsigned long *console_mfn)
   2.269  {
   2.270 -    char *image, *ram = NULL;
   2.271 -    unsigned long image_size, ram_size = 0;
   2.272 -    int  sts;
   2.273 +    char *image = NULL;
   2.274 +    unsigned long image_size;
   2.275 +    struct initrd_info initrd_info = { .type = INITRD_none };
   2.276 +    int fd = -1, sts = -1;
   2.277  
   2.278      if ( (image_name == NULL) ||
   2.279           ((image = xc_read_image(image_name, &image_size)) == NULL ))
   2.280          return -1;
   2.281  
   2.282 -    if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) &&
   2.283 -         ((ram = xc_read_image(initrd_name, &ram_size)) == NULL) )
   2.284 +    if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) )
   2.285      {
   2.286 -        free(image);
   2.287 -        return -1;
   2.288 +        initrd_info.type = INITRD_file;
   2.289 +
   2.290 +        if ( (fd = open(initrd_name, O_RDONLY)) < 0 )
   2.291 +        {
   2.292 +            PERROR("Could not open the initial ramdisk image");
   2.293 +            goto error_out;
   2.294 +        }
   2.295 +
   2.296 +        initrd_info.len = xc_get_filesz(fd);
   2.297 +        if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL )
   2.298 +        {
   2.299 +            PERROR("Could not allocate decompression state for initrd");
   2.300 +            goto error_out;
   2.301 +        }
   2.302      }
   2.303  
   2.304      sts = xc_linux_build_internal(xc_handle, domid, image, image_size,
   2.305 -                                  ram, ram_size, cmdline, features, flags,
   2.306 +                                  &initrd_info, cmdline, features, flags,
   2.307                                    store_evtchn, store_mfn,
   2.308                                    console_evtchn, console_mfn);
   2.309  
   2.310 + error_out:
   2.311      free(image);
   2.312 -    free(ram);
   2.313 +    if ( fd >= 0 )
   2.314 +        close(fd);
   2.315 +    if ( initrd_info.u.file_handle )
   2.316 +        gzclose(initrd_info.u.file_handle);
   2.317  
   2.318      return sts;
   2.319  }