direct-io.hg

changeset 881:e6d36e3e7847

bitkeeper revision 1.552 (3fa6715f0LpnznAkmX17sTFtzPmomQ)

Many files:
Clean up domain building interface ready for suspend/resume.
author kaf24@scramble.cl.cam.ac.uk
date Mon Nov 03 15:16:47 2003 +0000 (2003-11-03)
parents 0d9e340b7374
children bb30fa014b9d
files tools/internal/dom0_defs.h tools/internal/xi_build.c tools/internal/xi_list.c xen/arch/i386/mm.c xen/arch/i386/traps.c xen/common/debug.c xen/common/dom0_ops.c xen/common/domain.c xen/common/schedule.c xen/include/asm-i386/processor.h xen/include/hypervisor-ifs/dom0_ops.h xen/include/xeno/sched.h xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h
line diff
     1.1 --- a/tools/internal/dom0_defs.h	Mon Nov 03 11:19:13 2003 +0000
     1.2 +++ b/tools/internal/dom0_defs.h	Mon Nov 03 15:16:47 2003 +0000
     1.3 @@ -98,7 +98,7 @@ static inline int do_dom0_op(dom0_op_t *
     1.4  
     1.5      if ( do_xen_hypercall(&hypercall) < 0 )
     1.6      {
     1.7 -        if ( errno == EINVAL )
     1.8 +        if ( errno == EACCES )
     1.9              fprintf(stderr, "Dom0 operation failed -- need to"
    1.10                      " rebuild the user-space tool set?\n");
    1.11          goto out2;
     2.1 --- a/tools/internal/xi_build.c	Mon Nov 03 11:19:13 2003 +0000
     2.2 +++ b/tools/internal/xi_build.c	Mon Nov 03 15:16:47 2003 +0000
     2.3 @@ -68,7 +68,7 @@ static int send_pgupdates(mmu_update_t *
     2.4  
     2.5  /* Read the kernel header, extracting the image size and load address. */
     2.6  static int read_kernel_header(int fd, long dom_size, 
     2.7 -			      unsigned long * load_addr, size_t * ksize)
     2.8 +                              unsigned long * load_addr, size_t * ksize)
     2.9  {
    2.10      char signature[8];
    2.11      char status[1024];
    2.12 @@ -77,7 +77,7 @@ static int read_kernel_header(int fd, lo
    2.13      if ( fstat(fd, &stat) < 0 )
    2.14      {
    2.15          PERROR("Cannot stat the kernel image");
    2.16 -	return -1;
    2.17 +        return -1;
    2.18      }
    2.19  
    2.20      /* Double the kernel image size to account for dynamic memory usage etc. */
    2.21 @@ -86,7 +86,7 @@ static int read_kernel_header(int fd, lo
    2.22          sprintf(status, "Kernel image size %ld larger than requested "
    2.23                  "domain size %ld\n Terminated.\n", stat.st_size, dom_size);
    2.24          ERROR(status);
    2.25 -	return -1;
    2.26 +        return -1;
    2.27      }
    2.28      
    2.29      read(fd, signature, SIG_LEN);
    2.30 @@ -94,7 +94,7 @@ static int read_kernel_header(int fd, lo
    2.31      {
    2.32          ERROR("Kernel image does not contain required signature.\n"
    2.33                "Terminating.\n");
    2.34 -	return -1;
    2.35 +        return -1;
    2.36      }
    2.37  
    2.38      /* Read the load address which immediately follows the Xeno signature. */
    2.39 @@ -147,7 +147,7 @@ static int copy_to_domain_page(unsigned 
    2.40  static int setup_guestos(
    2.41      int dom, int kernel_fd, int initrd_fd, unsigned long tot_pages,
    2.42      unsigned long virt_load_addr, size_t ksize, 
    2.43 -    dom0_builddomain_t *builddomain)
    2.44 +    dom0_builddomain_t *builddomain, int argc, char **argv, int args_start)
    2.45  {
    2.46      l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
    2.47      l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
    2.48 @@ -158,6 +158,9 @@ static int setup_guestos(
    2.49      unsigned long l1tab = 0;
    2.50      unsigned long num_pgt_updates = 0;
    2.51      unsigned long count, pt_start, i, j;
    2.52 +    unsigned long initrd_addr = 0, initrd_len = 0;
    2.53 +    start_info_t *start_info;
    2.54 +    int cmd_len;
    2.55  
    2.56      memset(builddomain, 0, sizeof(*builddomain));
    2.57  
    2.58 @@ -169,14 +172,14 @@ static int setup_guestos(
    2.59      pgt_update_arr = pgt_updates;
    2.60      if ( (pgt_update_arr == NULL) || (page_array == NULL) )
    2.61      {
    2.62 -	PERROR("Could not allocate memory");
    2.63 -	goto error_out;
    2.64 +        PERROR("Could not allocate memory");
    2.65 +        goto error_out;
    2.66      }
    2.67  
    2.68      if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages )
    2.69      {
    2.70 -	PERROR("Could not get the page frame list");
    2.71 -	goto error_out;
    2.72 +        PERROR("Could not get the page frame list");
    2.73 +        goto error_out;
    2.74      }
    2.75  
    2.76      /* Load the guest OS image. */
    2.77 @@ -196,15 +199,15 @@ static int setup_guestos(
    2.78      /* Load the initial ramdisk image. */
    2.79      if ( initrd_fd >= 0 )
    2.80      {
    2.81 -	struct stat stat;
    2.82 -	unsigned long isize;
    2.83 +        struct stat stat;
    2.84 +        unsigned long isize;
    2.85  
    2.86 -	if ( fstat(initrd_fd, &stat) < 0 )
    2.87 +        if ( fstat(initrd_fd, &stat) < 0 )
    2.88          {
    2.89              PERROR("Could not stat the initrd image");
    2.90              goto error_out;
    2.91 -	}
    2.92 -	isize = stat.st_size;
    2.93 +        }
    2.94 +        isize = stat.st_size;
    2.95          if ( ((isize + ksize) * 2) > (tot_pages << PAGE_SHIFT) )
    2.96          {
    2.97              ERROR("Kernel + initrd too big to safely fit in domain memory");
    2.98 @@ -212,8 +215,8 @@ static int setup_guestos(
    2.99          }
   2.100  
   2.101          /* 'i' is 'ksize' rounded up to a page boundary. */
   2.102 -        builddomain->virt_mod_addr = virt_load_addr + i;
   2.103 -        builddomain->virt_mod_len  = isize;
   2.104 +        initrd_addr = virt_load_addr + i;
   2.105 +        initrd_len  = isize;
   2.106  
   2.107          for ( j = 0; j < isize; j += PAGE_SIZE, i += PAGE_SIZE )
   2.108          {
   2.109 @@ -246,7 +249,7 @@ static int setup_guestos(
   2.110       */
   2.111      l2tab = page_array[alloc_index] << PAGE_SHIFT;
   2.112      alloc_index--;
   2.113 -    builddomain->l2_pgt_addr = l2tab;
   2.114 +    builddomain->ctxt.pt_base = l2tab;
   2.115  
   2.116      /*
   2.117       * Pin down l2tab addr as page dir page - causes hypervisor to provide
   2.118 @@ -271,7 +274,7 @@ static int setup_guestos(
   2.119                  goto error_out;
   2.120              memset(vl1tab, 0, PAGE_SIZE);
   2.121              alloc_index--;
   2.122 -			
   2.123 +		
   2.124              vl1e = vl1tab + l1_table_offset(virt_load_addr + 
   2.125                                              (count << PAGE_SHIFT));
   2.126  
   2.127 @@ -295,21 +298,40 @@ static int setup_guestos(
   2.128          {
   2.129              pgt_updates->ptr = (unsigned long)vl1e;
   2.130              pgt_updates->val = 
   2.131 -		((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
   2.132 +                ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW;
   2.133              pgt_updates++;
   2.134              num_pgt_updates++;
   2.135              vl1e++;
   2.136          }
   2.137  
   2.138          pgt_updates->ptr = 
   2.139 -	    (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
   2.140 +            (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
   2.141          pgt_updates->val = count;
   2.142          pgt_updates++;
   2.143          num_pgt_updates++;
   2.144      }
   2.145  
   2.146      builddomain->virt_startinfo_addr =
   2.147 -        virt_load_addr + ((alloc_index-1)<<PAGE_SHIFT);
   2.148 +        virt_load_addr + ((alloc_index-1) << PAGE_SHIFT);
   2.149 +
   2.150 +    start_info = map_pfn(page_array[alloc_index-1]);
   2.151 +    memset(start_info, 0, sizeof(*start_info));
   2.152 +    start_info->pt_base     = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
   2.153 +    start_info->mod_start   = initrd_addr;
   2.154 +    start_info->mod_len     = initrd_len;
   2.155 +    cmd_len = 0;
   2.156 +    for ( i = args_start; i < argc; i++ )
   2.157 +    {
   2.158 +        if ( cmd_len + strlen(argv[i]) > MAX_CMD_LEN - 1 ) 
   2.159 +        {
   2.160 +            ERROR("Size of image boot params too big!\n");
   2.161 +            break;
   2.162 +        }
   2.163 +        strcat(start_info->cmd_line, argv[i]);
   2.164 +        strcat(start_info->cmd_line, " ");
   2.165 +        cmd_len += strlen(argv[i] + 1);
   2.166 +    }
   2.167 +    unmap_pfn(start_info);
   2.168  
   2.169      /* Send the page update requests down to the hypervisor. */
   2.170      if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
   2.171 @@ -321,9 +343,9 @@ static int setup_guestos(
   2.172  
   2.173   error_out:
   2.174      if ( page_array == NULL )
   2.175 -	free(page_array);
   2.176 +        free(page_array);
   2.177      if ( pgt_update_arr == NULL )
   2.178 -	free(pgt_update_arr);
   2.179 +        free(pgt_update_arr);
   2.180      return -1;
   2.181  }
   2.182  
   2.183 @@ -338,12 +360,11 @@ int main(int argc, char **argv)
   2.184      unsigned long load_addr;
   2.185      long tot_pages;
   2.186      int kernel_fd, initrd_fd = -1;
   2.187 -    int count;
   2.188 -    int cmd_len;
   2.189      int args_start = 4;
   2.190      char initrd_name[1024];
   2.191      int domain_id;
   2.192 -    int rc;
   2.193 +    int rc, i;
   2.194 +    full_execution_context_t *ctxt;
   2.195  
   2.196      if ( argv[0] != NULL ) 
   2.197          argv0 = argv[0];
   2.198 @@ -365,62 +386,98 @@ int main(int argc, char **argv)
   2.199      if ( (tot_pages = get_tot_pages(domain_id)) < 0 )
   2.200      {
   2.201          PERROR("Could not find total pages for domain");
   2.202 -	return 1;
   2.203 +        return 1;
   2.204      }
   2.205  
   2.206      kernel_fd = open(argv[2], O_RDONLY);
   2.207      if ( kernel_fd < 0 )
   2.208      {
   2.209          PERROR("Could not open kernel image");
   2.210 -	return 1;
   2.211 +        return 1;
   2.212      }
   2.213  
   2.214      rc = read_kernel_header(kernel_fd,
   2.215 -			    tot_pages << (PAGE_SHIFT - 10), 
   2.216 -			    &load_addr, &ksize);
   2.217 +                            tot_pages << (PAGE_SHIFT - 10), 
   2.218 +                            &load_addr, &ksize);
   2.219      if ( rc < 0 )
   2.220 -	return 1;
   2.221 +        return 1;
   2.222      
   2.223      if( (argc > args_start) && 
   2.224          (strncmp("initrd=", argv[args_start], 7) == 0) )
   2.225      {
   2.226 -	strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) );
   2.227 -	initrd_name[sizeof(initrd_name)-1] = 0;
   2.228 -	printf("initrd present, name = %s\n", initrd_name );
   2.229 -	args_start++;
   2.230 +        strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) );
   2.231 +        initrd_name[sizeof(initrd_name)-1] = 0;
   2.232 +        printf("initrd present, name = %s\n", initrd_name );
   2.233 +        args_start++;
   2.234          
   2.235 -	initrd_fd = open(initrd_name, O_RDONLY);
   2.236 -	if ( initrd_fd < 0 )
   2.237 +        initrd_fd = open(initrd_name, O_RDONLY);
   2.238 +        if ( initrd_fd < 0 )
   2.239          {
   2.240              PERROR("Could not open the initial ramdisk image");
   2.241 -	    return 1;
   2.242 -	}
   2.243 +            return 1;
   2.244 +        }
   2.245      }
   2.246  
   2.247      if ( setup_guestos(domain_id, kernel_fd, initrd_fd, tot_pages,
   2.248 -                       load_addr, ksize, &launch_op.u.builddomain) < 0 )
   2.249 +                       load_addr, ksize, &launch_op.u.builddomain,
   2.250 +                       argc, argv, args_start) < 0 )
   2.251          return 1;
   2.252  
   2.253      if ( initrd_fd >= 0 )
   2.254 -	close(initrd_fd);
   2.255 +        close(initrd_fd);
   2.256      close(kernel_fd);
   2.257  
   2.258 -    launch_op.u.builddomain.domain         = domain_id;
   2.259 -    launch_op.u.builddomain.virt_load_addr = load_addr;
   2.260 -    launch_op.u.builddomain.num_vifs       = atoi(argv[3]);
   2.261 -    launch_op.u.builddomain.cmd_line[0]    = '\0';
   2.262 -    cmd_len = 0;
   2.263 -    for ( count = args_start; count < argc; count++ )
   2.264 +    ctxt = &launch_op.u.builddomain.ctxt;
   2.265 +
   2.266 +    /*
   2.267 +     * Initial register values:
   2.268 +     *  DS,ES,FS,GS = FLAT_RING1_DS
   2.269 +     *       CS:EIP = FLAT_RING1_CS:start_pc
   2.270 +     *       SS:ESP = FLAT_RING1_DS:start_stack
   2.271 +     *          ESI = start_info
   2.272 +     *  [EAX,EBX,ECX,EDX,EDI,EBP are zero]
   2.273 +     *       EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
   2.274 +     */
   2.275 +    ctxt->i386_ctxt.ds = FLAT_RING1_DS;
   2.276 +    ctxt->i386_ctxt.es = FLAT_RING1_DS;
   2.277 +    ctxt->i386_ctxt.fs = FLAT_RING1_DS;
   2.278 +    ctxt->i386_ctxt.gs = FLAT_RING1_DS;
   2.279 +    ctxt->i386_ctxt.ss = FLAT_RING1_DS;
   2.280 +    ctxt->i386_ctxt.cs = FLAT_RING1_CS;
   2.281 +    ctxt->i386_ctxt.eip = load_addr;
   2.282 +    ctxt->i386_ctxt.esp = launch_op.u.builddomain.virt_startinfo_addr;
   2.283 +    ctxt->i386_ctxt.esi = launch_op.u.builddomain.virt_startinfo_addr;
   2.284 +    ctxt->i386_ctxt.eflags = (1<<9) | (1<<2);
   2.285 +
   2.286 +    /* FPU is set up to default initial state. */
   2.287 +    memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt));
   2.288 +
   2.289 +    /* Virtual IDT is empty at start-of-day. */
   2.290 +    for ( i = 0; i < 256; i++ )
   2.291      {
   2.292 -        if ( cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1 ) 
   2.293 -        {
   2.294 -            ERROR("Size of image boot params too big!\n");
   2.295 -            break;
   2.296 -        }
   2.297 -        strcat(launch_op.u.builddomain.cmd_line, argv[count]);
   2.298 -        strcat(launch_op.u.builddomain.cmd_line, " ");
   2.299 -        cmd_len += strlen(argv[count] + 1);
   2.300 +        ctxt->trap_ctxt[i].vector = i;
   2.301 +        ctxt->trap_ctxt[i].cs     = FLAT_RING1_CS;
   2.302      }
   2.303 +    ctxt->fast_trap_idx = 0;
   2.304 +
   2.305 +    /* No LDT. */
   2.306 +    ctxt->ldt_ents = 0;
   2.307 +    
   2.308 +    /* Use the default Xen-provided GDT. */
   2.309 +    ctxt->gdt_ents = 0;
   2.310 +
   2.311 +    /* Ring 1 stack is the initial stack. */
   2.312 +    ctxt->ring1_ss  = FLAT_RING1_DS;
   2.313 +    ctxt->ring1_esp = launch_op.u.builddomain.virt_startinfo_addr;
   2.314 +
   2.315 +    /* No debugging. */
   2.316 +    memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
   2.317 +
   2.318 +    /* Domain time counts from zero. */
   2.319 +    ctxt->domain_time = 0;
   2.320 +
   2.321 +    launch_op.u.builddomain.domain   = domain_id;
   2.322 +    launch_op.u.builddomain.num_vifs = atoi(argv[3]);
   2.323  
   2.324      launch_op.cmd = DOM0_BUILDDOMAIN;
   2.325      rc = do_dom0_op(&launch_op);
     3.1 --- a/tools/internal/xi_list.c	Mon Nov 03 11:19:13 2003 +0000
     3.2 +++ b/tools/internal/xi_list.c	Mon Nov 03 15:16:47 2003 +0000
     3.3 @@ -30,12 +30,11 @@ static char *statestr(int state)
     3.4  {
     3.5      switch ( state )
     3.6      {
     3.7 -    case  0: return "RUNNING";
     3.8 -    case  1: return "INTERRUPTIBLE";
     3.9 -    case  2: return "UNINTERRUPTIBLE";
    3.10 -    case  4: return "WAIT";
    3.11 -    case  8: return "SUSPENDED";
    3.12 -    case 16: return "DYING";
    3.13 +    case 0: return "RUNNING";
    3.14 +    case 1: return "INTERRUPTIBLE";
    3.15 +    case 2: return "UNINTERRUPTIBLE";
    3.16 +    case 4: return "STOPPED";
    3.17 +    case 8: return "DYING";
    3.18      default: return "UNKNOWN";
    3.19      }
    3.20      return NULL;
     4.1 --- a/xen/arch/i386/mm.c	Mon Nov 03 11:19:13 2003 +0000
     4.2 +++ b/xen/arch/i386/mm.c	Mon Nov 03 15:16:47 2003 +0000
     4.3 @@ -207,21 +207,18 @@ int check_descriptor(unsigned long a, un
     4.4  }
     4.5  
     4.6  
     4.7 -long do_set_gdt(unsigned long *frame_list, unsigned int entries)
     4.8 +long set_gdt(struct task_struct *p, 
     4.9 +             unsigned long *frames,
    4.10 +             unsigned int entries)
    4.11  {
    4.12      /* NB. There are 512 8-byte entries per GDT page. */
    4.13      unsigned int i, j, nr_pages = (entries + 511) / 512;
    4.14 -    unsigned long frames[16], pfn, *gdt_page, flags;
    4.15 +    unsigned long pfn, *gdt_page, flags;
    4.16      long ret = -EINVAL;
    4.17      struct pfn_info *page;
    4.18 -
    4.19 -    if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) 
    4.20 -        return -EINVAL;
    4.21 +    struct desc_struct *vgdt;
    4.22  
    4.23 -    if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
    4.24 -        return -EFAULT;
    4.25 -
    4.26 -    spin_lock_irqsave(&current->page_lock, flags);
    4.27 +    spin_lock_irqsave(&p->page_lock, flags);
    4.28  
    4.29      /* Check the new GDT. */
    4.30      for ( i = 0; i < nr_pages; i++ )
    4.31 @@ -230,7 +227,7 @@ long do_set_gdt(unsigned long *frame_lis
    4.32              goto out;
    4.33          
    4.34          page = frame_table + frames[i];
    4.35 -        if ( (page->flags & PG_domain_mask) != current->domain )
    4.36 +        if ( (page->flags & PG_domain_mask) != p->domain )
    4.37              goto out;
    4.38  
    4.39          if ( (page->flags & PG_type_mask) != PGT_gdt_page )
    4.40 @@ -250,12 +247,12 @@ long do_set_gdt(unsigned long *frame_lis
    4.41      /* Tear down the old GDT. */
    4.42      for ( i = 0; i < 16; i++ )
    4.43      {
    4.44 -        pfn = l1_pgentry_to_pagenr(current->mm.perdomain_pt[i]);
    4.45 -        current->mm.perdomain_pt[i] = mk_l1_pgentry(0);
    4.46 +        pfn = l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]);
    4.47 +        p->mm.perdomain_pt[i] = mk_l1_pgentry(0);
    4.48          if ( pfn == 0 ) continue;
    4.49          page = frame_table + pfn;
    4.50          ASSERT((page->flags & PG_type_mask) == PGT_gdt_page);
    4.51 -        ASSERT((page->flags & PG_domain_mask) == current->domain);
    4.52 +        ASSERT((page->flags & PG_domain_mask) == p->domain);
    4.53          ASSERT((page->type_count != 0) && (page->tot_count != 0));
    4.54          put_page_type(page);
    4.55          put_page_tot(page);
    4.56 @@ -264,7 +261,7 @@ long do_set_gdt(unsigned long *frame_lis
    4.57      /* Install the new GDT. */
    4.58      for ( i = 0; i < nr_pages; i++ )
    4.59      {
    4.60 -        current->mm.perdomain_pt[i] =
    4.61 +        p->mm.perdomain_pt[i] =
    4.62              mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
    4.63          
    4.64          page = frame_table + frames[i];
    4.65 @@ -274,21 +271,42 @@ long do_set_gdt(unsigned long *frame_lis
    4.66          get_page_tot(page);
    4.67      }
    4.68  
    4.69 -    local_flush_tlb();
    4.70 -
    4.71      /* Copy reserved GDT entries to the new GDT. */
    4.72 -    memcpy((struct desc_struct *)GDT_VIRT_START + FIRST_RESERVED_GDT_ENTRY, 
    4.73 +    vgdt = map_domain_mem(frames[i] << PAGE_SHIFT);
    4.74 +    memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, 
    4.75             gdt_table + FIRST_RESERVED_GDT_ENTRY, 
    4.76             NR_RESERVED_GDT_ENTRIES*8);
    4.77 -    
    4.78 -    SET_GDT_ADDRESS(current, GDT_VIRT_START);
    4.79 -    SET_GDT_ENTRIES(current, (entries*8)-1);
    4.80 -    __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt));
    4.81 +    unmap_domain_mem(vgdt);
    4.82 +
    4.83 +    SET_GDT_ADDRESS(p, GDT_VIRT_START);
    4.84 +    SET_GDT_ENTRIES(p, (entries*8)-1);
    4.85  
    4.86      ret = 0; /* success */
    4.87  
    4.88   out:
    4.89 -    spin_unlock_irqrestore(&current->page_lock, flags);
    4.90 +    spin_unlock_irqrestore(&p->page_lock, flags);
    4.91 +    return ret;
    4.92 +}
    4.93 +
    4.94 +
    4.95 +long do_set_gdt(unsigned long *frame_list, unsigned int entries)
    4.96 +{
    4.97 +    unsigned int nr_pages = (entries + 511) / 512;
    4.98 +    unsigned long frames[16];
    4.99 +    long ret;
   4.100 +
   4.101 +    if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) 
   4.102 +        return -EINVAL;
   4.103 +    
   4.104 +    if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
   4.105 +        return -EFAULT;
   4.106 +
   4.107 +    if ( (ret = set_gdt(current, frames, entries)) == 0 )
   4.108 +    {
   4.109 +        local_flush_tlb();
   4.110 +        __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt));
   4.111 +    }
   4.112 +
   4.113      return ret;
   4.114  }
   4.115  
     5.1 --- a/xen/arch/i386/traps.c	Mon Nov 03 11:19:13 2003 +0000
     5.2 +++ b/xen/arch/i386/traps.c	Mon Nov 03 15:16:47 2003 +0000
     5.3 @@ -692,15 +692,16 @@ long do_set_callbacks(unsigned long even
     5.4  }
     5.5  
     5.6  
     5.7 -long do_set_fast_trap(int idx)
     5.8 +long set_fast_trap(struct task_struct *p, int idx)
     5.9  {
    5.10      trap_info_t *ti;
    5.11  
    5.12      /* Index 0 is special: it disables fast traps. */
    5.13      if ( idx == 0 )
    5.14      {
    5.15 -        CLEAR_FAST_TRAP(&current->thread);
    5.16 -        SET_DEFAULT_FAST_TRAP(&current->thread);
    5.17 +        if ( p == current )
    5.18 +            CLEAR_FAST_TRAP(&p->thread);
    5.19 +        SET_DEFAULT_FAST_TRAP(&p->thread);
    5.20          return 0;
    5.21      }
    5.22  
    5.23 @@ -712,7 +713,7 @@ long do_set_fast_trap(int idx)
    5.24      if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) 
    5.25          return -1;
    5.26  
    5.27 -    ti = current->thread.traps + idx;
    5.28 +    ti = p->thread.traps + idx;
    5.29  
    5.30      /*
    5.31       * We can't virtualise interrupt gates, as there's no way to get
    5.32 @@ -721,19 +722,27 @@ long do_set_fast_trap(int idx)
    5.33      if ( TI_GET_IF(ti) )
    5.34          return -1;
    5.35  
    5.36 -    CLEAR_FAST_TRAP(&current->thread);
    5.37 +    if ( p == current )
    5.38 +        CLEAR_FAST_TRAP(&p->thread);
    5.39  
    5.40 -    current->thread.fast_trap_idx    = idx;
    5.41 -    current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
    5.42 -    current->thread.fast_trap_desc.b = 
    5.43 +    p->thread.fast_trap_idx    = idx;
    5.44 +    p->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff);
    5.45 +    p->thread.fast_trap_desc.b = 
    5.46          (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13;
    5.47  
    5.48 -    SET_FAST_TRAP(&current->thread);
    5.49 +    if ( p == current )
    5.50 +        SET_FAST_TRAP(&p->thread);
    5.51  
    5.52      return 0;
    5.53  }
    5.54  
    5.55  
    5.56 +long do_set_fast_trap(int idx)
    5.57 +{
    5.58 +    return set_fast_trap(current, idx);
    5.59 +}
    5.60 +
    5.61 +
    5.62  long do_fpu_taskswitch(void)
    5.63  {
    5.64      current->flags |= PF_GUEST_STTS;
     6.1 --- a/xen/common/debug.c	Mon Nov 03 11:19:13 2003 +0000
     6.2 +++ b/xen/common/debug.c	Mon Nov 03 15:16:47 2003 +0000
     6.3 @@ -61,7 +61,7 @@ void pdb_do_debug (dom0_op_t *op)
     6.4  
     6.5  	    if (p != NULL)
     6.6  	    {
     6.7 -	        if (p->state != TASK_SUSPENDED)
     6.8 +	        if (p->state != TASK_STOPPED)
     6.9  		{
    6.10  		    cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
    6.11  		    hyp_event_notify(cpu_mask);
     7.1 --- a/xen/common/dom0_ops.c	Mon Nov 03 11:19:13 2003 +0000
     7.2 +++ b/xen/common/dom0_ops.c	Mon Nov 03 15:16:47 2003 +0000
     7.3 @@ -93,7 +93,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     7.4          return -EFAULT;
     7.5  
     7.6      if ( op.interface_version != DOM0_INTERFACE_VERSION )
     7.7 -        return -EINVAL;
     7.8 +        return -EACCES;
     7.9  
    7.10      switch ( op.cmd )
    7.11      {
    7.12 @@ -249,6 +249,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    7.13      { 
    7.14          struct task_struct *p = &idle0_task;
    7.15          u_long flags;
    7.16 +        int i;
    7.17  
    7.18          read_lock_irqsave (&tasklist_lock, flags);
    7.19  
    7.20 @@ -271,11 +272,46 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
    7.21              op.u.getdomaininfo.mcu_advance = p->mcu_advance;
    7.22              op.u.getdomaininfo.tot_pages   = p->tot_pages;
    7.23              op.u.getdomaininfo.cpu_time    = p->cpu_time;
    7.24 -            memcpy(&op.u.getdomaininfo.ctxt, 
    7.25 -                   &p->shared_info->execution_context,
    7.26 -                   sizeof(execution_context_t));
    7.27 +            if ( p->state == TASK_STOPPED )
    7.28 +            {
    7.29 +                rmb(); /* Ensure that we see saved register state. */
    7.30 +                memcpy(&op.u.getdomaininfo.ctxt.i386_ctxt, 
    7.31 +                       &p->shared_info->execution_context,
    7.32 +                       sizeof(p->shared_info->execution_context));
    7.33 +                memcpy(&op.u.getdomaininfo.ctxt.i387_ctxt,
    7.34 +                       &p->thread.i387,
    7.35 +                       sizeof(p->thread.i387));
    7.36 +                memcpy(&op.u.getdomaininfo.ctxt.trap_ctxt,
    7.37 +                       p->thread.traps,
    7.38 +                       sizeof(p->thread.traps));
    7.39 +                if ( (p->thread.fast_trap_desc.a == 0) &&
    7.40 +                     (p->thread.fast_trap_desc.b == 0) )
    7.41 +                    op.u.getdomaininfo.ctxt.fast_trap_idx = 0;
    7.42 +                else
    7.43 +                    op.u.getdomaininfo.ctxt.fast_trap_idx = 
    7.44 +                        p->thread.fast_trap_idx;
    7.45 +                op.u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base;
    7.46 +                op.u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents;
    7.47 +                op.u.getdomaininfo.ctxt.gdt_ents = 0;
    7.48 +                if ( GET_GDT_ADDRESS(p) == GDT_VIRT_START )
    7.49 +                {
    7.50 +                    for ( i = 0; i < 16; i++ )
    7.51 +                        op.u.getdomaininfo.ctxt.gdt_frames[i] = 
    7.52 +                            l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]);
    7.53 +                    op.u.getdomaininfo.ctxt.gdt_ents = 
    7.54 +                        (GET_GDT_ENTRIES(p) + 1) >> 3;
    7.55 +                }
    7.56 +                op.u.getdomaininfo.ctxt.ring1_ss  = p->thread.ss1;
    7.57 +                op.u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1;
    7.58 +                op.u.getdomaininfo.ctxt.pt_base   = 
    7.59 +                    pagetable_val(p->mm.pagetable);
    7.60 +                memcpy(op.u.getdomaininfo.ctxt.debugreg, 
    7.61 +                       p->thread.debugreg, 
    7.62 +                       sizeof(p->thread.debugreg));
    7.63 +                op.u.getdomaininfo.ctxt.domain_time = 
    7.64 +                    p->shared_info->domain_time;
    7.65 +            }
    7.66          }
    7.67 -
    7.68          read_unlock_irqrestore(&tasklist_lock, flags);
    7.69          copy_to_user(u_dom0_op, &op, sizeof(op));
    7.70      }
     8.1 --- a/xen/common/domain.c	Mon Nov 03 11:19:13 2003 +0000
     8.2 +++ b/xen/common/domain.c	Mon Nov 03 15:16:47 2003 +0000
     8.3 @@ -18,6 +18,8 @@
     8.4  #include <xeno/console.h>
     8.5  #include <xeno/vbd.h>
     8.6  
     8.7 +#include <asm/i387.h>
     8.8 +
     8.9  /*
    8.10   * NB. No ring-3 access in initial guestOS pagetables. Note that we allow
    8.11   * ring-3 privileges in the page directories, so that the guestOS may later
    8.12 @@ -186,7 +188,7 @@ long kill_other_domain(unsigned int dom,
    8.13      p = find_domain_by_id(dom);
    8.14      if ( p == NULL ) return -ESRCH;
    8.15  
    8.16 -    if ( p->state == TASK_SUSPENDED )
    8.17 +    if ( p->state == TASK_STOPPED )
    8.18      {
    8.19          __kill_domain(p);
    8.20      }
    8.21 @@ -207,7 +209,12 @@ long kill_other_domain(unsigned int dom,
    8.22  
    8.23  void stop_domain(void)
    8.24  {
    8.25 -    set_current_state(TASK_SUSPENDED);
    8.26 +    memcpy(&current->shared_info->execution_context, 
    8.27 +           get_execution_context(), 
    8.28 +           sizeof(execution_context_t));
    8.29 +    unlazy_fpu(current);
    8.30 +    wmb(); /* All CPUs must see saved info in state TASK_STOPPED. */
    8.31 +    set_current_state(TASK_STOPPED);
    8.32      clear_bit(_HYP_EVENT_STOP, &current->hyp_events);
    8.33      __enter_scheduler();
    8.34  }
    8.35 @@ -220,7 +227,7 @@ long stop_other_domain(unsigned int dom)
    8.36      p = find_domain_by_id (dom);
    8.37      if ( p == NULL) return -ESRCH;
    8.38      
    8.39 -    if ( p->state != TASK_SUSPENDED )
    8.40 +    if ( p->state != TASK_STOPPED )
    8.41      {
    8.42          cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
    8.43          hyp_event_notify(cpu_mask);
    8.44 @@ -328,25 +335,10 @@ void release_task(struct task_struct *p)
    8.45  /* final_setup_guestos is used for final setup and launching of domains other
    8.46   * than domain 0. ie. the domains that are being built by the userspace dom0
    8.47   * domain builder.
    8.48 - *
    8.49 - * Initial load map:
    8.50 - *  start_address:
    8.51 - *     OS image
    8.52 - *      ....
    8.53 - *  stack_start:
    8.54 - *  start_info:
    8.55 - *      <one page>
    8.56 - *  page tables:
    8.57 - *      <enough pages>
    8.58 - *  end_address:
    8.59 - *  shared_info:
    8.60 - *      <one page>
    8.61   */
    8.62 -
    8.63  int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
    8.64  {
    8.65      start_info_t * virt_startinfo_addr;
    8.66 -    unsigned long virt_stack_addr;
    8.67      unsigned long phys_l2tab;
    8.68      net_ring_t *shared_rings;
    8.69      net_vif_t *net_vif;
    8.70 @@ -355,19 +347,43 @@ int final_setup_guestos(struct task_stru
    8.71      if ( (p->flags & PF_CONSTRUCTED) )
    8.72          return -EINVAL;
    8.73  
    8.74 +    memcpy(&p->shared_info->execution_context,
    8.75 +           &builddomain->ctxt.i386_ctxt,
    8.76 +           sizeof(p->shared_info->execution_context));
    8.77 +    memcpy(&p->thread.i387,
    8.78 +           &builddomain->ctxt.i387_ctxt,
    8.79 +           sizeof(p->thread.i387));
    8.80 +    memcpy(p->thread.traps,
    8.81 +           &builddomain->ctxt.trap_ctxt,
    8.82 +           sizeof(p->thread.traps));
    8.83 +    SET_DEFAULT_FAST_TRAP(&p->thread);
    8.84 +    (void)set_fast_trap(p, builddomain->ctxt.fast_trap_idx);
    8.85 +    p->mm.ldt_base = builddomain->ctxt.ldt_base;
    8.86 +    p->mm.ldt_ents = builddomain->ctxt.ldt_ents;
    8.87 +    SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
    8.88 +    SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
    8.89 +    if ( builddomain->ctxt.gdt_ents != 0 )
    8.90 +        (void)set_gdt(p,
    8.91 +                      builddomain->ctxt.gdt_frames,
    8.92 +                      builddomain->ctxt.gdt_ents);
    8.93 +    p->thread.ss1  = builddomain->ctxt.ring1_ss;
    8.94 +    p->thread.esp1 = builddomain->ctxt.ring1_esp;
    8.95 +    memcpy(p->thread.debugreg,
    8.96 +           builddomain->ctxt.debugreg,
    8.97 +           sizeof(p->thread.debugreg));
    8.98 +    
    8.99      /* NB. Page base must already be pinned! */
   8.100 -    phys_l2tab = builddomain->l2_pgt_addr;
   8.101 +    phys_l2tab = builddomain->ctxt.pt_base;
   8.102      p->mm.pagetable = mk_pagetable(phys_l2tab);
   8.103      get_page_type(&frame_table[phys_l2tab>>PAGE_SHIFT]);
   8.104      get_page_tot(&frame_table[phys_l2tab>>PAGE_SHIFT]);
   8.105  
   8.106      /* set up the shared info structure */
   8.107      update_dom_time(p->shared_info);
   8.108 -    p->shared_info->domain_time = 0;
   8.109 +    p->shared_info->domain_time = builddomain->ctxt.domain_time;
   8.110  
   8.111      /* we pass start info struct to guest os as function parameter on stack */
   8.112      virt_startinfo_addr = (start_info_t *)builddomain->virt_startinfo_addr;
   8.113 -    virt_stack_addr = (unsigned long)virt_startinfo_addr;       
   8.114  
   8.115      /* we need to populate start_info struct within the context of the
   8.116       * new domain. thus, temporarely install its pagetables.
   8.117 @@ -376,17 +392,8 @@ int final_setup_guestos(struct task_stru
   8.118      __asm__ __volatile__ ( 
   8.119          "mov %%eax,%%cr3" : : "a" (pagetable_val(p->mm.pagetable)));
   8.120  
   8.121 -    memset(virt_startinfo_addr, 0, sizeof(*virt_startinfo_addr));
   8.122      virt_startinfo_addr->nr_pages = p->tot_pages;
   8.123 -    virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info);
   8.124 -    virt_startinfo_addr->pt_base = builddomain->virt_load_addr + 
   8.125 -                    ((p->tot_pages - 1) << PAGE_SHIFT);
   8.126 -   
   8.127 -    /* module size and length */
   8.128 -
   8.129 -    virt_startinfo_addr->mod_start = builddomain->virt_mod_addr;
   8.130 -    virt_startinfo_addr->mod_len   = builddomain->virt_mod_len;
   8.131 -
   8.132 +    virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info);   
   8.133      virt_startinfo_addr->dom_id = p->domain;
   8.134      virt_startinfo_addr->flags  = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
   8.135  
   8.136 @@ -409,9 +416,6 @@ int final_setup_guestos(struct task_stru
   8.137      /* Add block io interface */
   8.138      virt_startinfo_addr->blk_ring = virt_to_phys(p->blk_ring_base);
   8.139  
   8.140 -    /* Copy the command line */
   8.141 -    strcpy(virt_startinfo_addr->cmd_line, builddomain->cmd_line);
   8.142 -
   8.143      /* Reinstate the caller's page tables. */
   8.144      __asm__ __volatile__ (
   8.145          "mov %%eax,%%cr3" : : "a" (pagetable_val(current->mm.pagetable)));    
   8.146 @@ -419,11 +423,6 @@ int final_setup_guestos(struct task_stru
   8.147  
   8.148      p->flags |= PF_CONSTRUCTED;
   8.149      
   8.150 -    new_thread(p, 
   8.151 -               (unsigned long)builddomain->virt_load_addr, 
   8.152 -               (unsigned long)virt_stack_addr, 
   8.153 -               (unsigned long)virt_startinfo_addr);
   8.154 -
   8.155      return 0;
   8.156  }
   8.157  
     9.1 --- a/xen/common/schedule.c	Mon Nov 03 11:19:13 2003 +0000
     9.2 +++ b/xen/common/schedule.c	Mon Nov 03 15:16:47 2003 +0000
     9.3 @@ -116,7 +116,7 @@ static void __calc_evt(struct task_struc
     9.4   */
     9.5  void sched_add_domain(struct task_struct *p) 
     9.6  {
     9.7 -    p->state       = TASK_SUSPENDED;
     9.8 +    p->state       = TASK_STOPPED;
     9.9      p->mcu_advance = MCU_ADVANCE;
    9.10  
    9.11      if ( p->domain == IDLE_DOMAIN_ID )
    9.12 @@ -379,11 +379,10 @@ asmlinkage void __enter_scheduler(void)
    9.13              break;
    9.14          }
    9.15      case TASK_UNINTERRUPTIBLE:
    9.16 -    case TASK_WAIT:
    9.17      case TASK_DYING:
    9.18 -    case TASK_SUSPENDED:
    9.19 +    case TASK_STOPPED:
    9.20      default:
    9.21 -        /* done if not running. Else, continue */
    9.22 +        /* Done if not running. Else continue. */
    9.23          goto deschedule_done;
    9.24      case TASK_RUNNING:;
    9.25      }
    10.1 --- a/xen/include/asm-i386/processor.h	Mon Nov 03 11:19:13 2003 +0000
    10.2 +++ b/xen/include/asm-i386/processor.h	Mon Nov 03 15:16:47 2003 +0000
    10.3 @@ -14,6 +14,7 @@
    10.4  #include <xeno/config.h>
    10.5  #include <hypervisor-ifs/hypervisor-if.h>
    10.6  
    10.7 +struct task_struct;
    10.8  
    10.9  /*
   10.10   * Default implementation of macro that returns current
   10.11 @@ -381,6 +382,8 @@ extern struct desc_struct *idt_tables[];
   10.12      (memcpy(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \
   10.13       &((_p)->fast_trap_desc), 8))
   10.14  
   10.15 +long set_fast_trap(struct task_struct *p, int idx);
   10.16 +
   10.17  #define INIT_THREAD  {						\
   10.18  	0, 0,		      					\
   10.19  	{ [0 ... 7] = 0 },	/* debugging registers */	\
   10.20 @@ -430,7 +433,9 @@ struct mm_struct {
   10.21  #define GET_GDT_ENTRIES(_p)     ((*(u16 *)((_p)->mm.gdt + 0)))
   10.22  #define GET_GDT_ADDRESS(_p)     ((*(u32 *)((_p)->mm.gdt + 2)))
   10.23  
   10.24 -struct task_struct;
   10.25 +long set_gdt(struct task_struct *p, 
   10.26 +             unsigned long *frames, 
   10.27 +             unsigned int entries);
   10.28  
   10.29  /* Free all resources held by a thread. */
   10.30  extern void release_thread(struct task_struct *);
    11.1 --- a/xen/include/hypervisor-ifs/dom0_ops.h	Mon Nov 03 11:19:13 2003 +0000
    11.2 +++ b/xen/include/hypervisor-ifs/dom0_ops.h	Mon Nov 03 15:16:47 2003 +0000
    11.3 @@ -17,7 +17,7 @@
    11.4   * This makes sure that old versions of dom0 tools will stop working in a
    11.5   * well-defined way (rather than crashing the machine, for instance).
    11.6   */
    11.7 -#define DOM0_INTERFACE_VERSION   0xAAAA0001
    11.8 +#define DOM0_INTERFACE_VERSION   0xAAAA0002
    11.9  
   11.10  
   11.11  /*
   11.12 @@ -35,6 +35,7 @@ typedef struct full_execution_context_st
   11.13      unsigned long ring1_ss, ring1_esp;      /* Virtual TSS (only SS1/ESP1)  */
   11.14      unsigned long pt_base;                  /* CR3 (pagetable base)         */
   11.15      unsigned long debugreg[8];              /* DB0-DB7 (debug registers)    */
   11.16 +    u64           domain_time;              /* Domain virtual time          */
   11.17  } full_execution_context_t;
   11.18  
   11.19  #define MAX_CMD_LEN       256
   11.20 @@ -88,13 +89,8 @@ typedef struct dom0_builddomain_st
   11.21  {
   11.22      /* IN variables. */
   11.23      unsigned int  domain;
   11.24 -    unsigned long l2_pgt_addr;
   11.25 -    unsigned long virt_load_addr;
   11.26      unsigned long virt_startinfo_addr;
   11.27 -    unsigned int num_vifs;
   11.28 -    char cmd_line[MAX_CMD_LEN];
   11.29 -    unsigned long virt_mod_addr;
   11.30 -    unsigned long virt_mod_len;
   11.31 +    unsigned int  num_vifs;
   11.32      full_execution_context_t ctxt;
   11.33  } dom0_builddomain_t;
   11.34  
    12.1 --- a/xen/include/xeno/sched.h	Mon Nov 03 11:19:13 2003 +0000
    12.2 +++ b/xen/include/xeno/sched.h	Mon Nov 03 15:16:47 2003 +0000
    12.3 @@ -146,20 +146,18 @@ struct task_struct
    12.4   *                       or expiring timer
    12.5   * TASK_UNINTERRUPTIBLE: Domain is blocked but may not be woken up by an
    12.6   *                       arbitrary event or timer.
    12.7 - * TASK_WAIT:            Domains CPU allocation expired.
    12.8 - * TASK_SUSPENDED:       Domain is suspended (startofday or pervasive debugger)
    12.9 + * TASK_STOPPED:         Domain is sopped.
   12.10   * TASK_DYING:           Domain is about to cross over to the land of the dead.
   12.11   *
   12.12   * If you update these then please update the mapping to text names in
   12.13   * xi_list.
   12.14   */
   12.15  
   12.16 -#define TASK_RUNNING            0
   12.17 -#define TASK_INTERRUPTIBLE      1
   12.18 -#define TASK_UNINTERRUPTIBLE    2
   12.19 -#define TASK_WAIT               4
   12.20 -#define TASK_SUSPENDED          8
   12.21 -#define TASK_DYING              16
   12.22 +#define TASK_RUNNING             0
   12.23 +#define TASK_INTERRUPTIBLE       1
   12.24 +#define TASK_UNINTERRUPTIBLE     2
   12.25 +#define TASK_STOPPED             4
   12.26 +#define TASK_DYING               8
   12.27  
   12.28  #include <asm/uaccess.h> /* for KERNEL_DS */
   12.29  
    13.1 --- a/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h	Mon Nov 03 11:19:13 2003 +0000
    13.2 +++ b/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h	Mon Nov 03 15:16:47 2003 +0000
    13.3 @@ -11,6 +11,7 @@
    13.4  
    13.5  #include <linux/types.h>
    13.6  #include <asm/hypervisor-ifs/hypervisor-if.h>
    13.7 +#include <asm/hypervisor-ifs/dom0_ops.h>
    13.8  #include <asm/ptrace.h>
    13.9  #include <asm/page.h>
   13.10  
   13.11 @@ -262,10 +263,10 @@ static inline int HYPERVISOR_exit(void)
   13.12      return ret;
   13.13  }
   13.14  
   13.15 -static inline int HYPERVISOR_dom0_op(void *dom0_op)
   13.16 +static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
   13.17  {
   13.18      int ret;
   13.19 -    op->interface_version = DOM0_INTERFACE_VERSION;
   13.20 +    dom0_op->interface_version = DOM0_INTERFACE_VERSION;
   13.21      __asm__ __volatile__ (
   13.22          TRAP_INSTR
   13.23          : "=a" (ret) : "0" (__HYPERVISOR_dom0_op),