diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-11-03 15:16:47 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2003-11-03 15:16:47 +0000 |
commit | 01b9634a9623af6695ece257d8cbe9296e906571 (patch) | |
tree | d53b2dea48e0aaa01d5dec0296bc0c1052337836 | |
parent | 98fd1a41ef7f38c12a47178b42c68332ed9eff55 (diff) | |
download | xen-01b9634a9623af6695ece257d8cbe9296e906571.tar.gz xen-01b9634a9623af6695ece257d8cbe9296e906571.tar.bz2 xen-01b9634a9623af6695ece257d8cbe9296e906571.zip |
bitkeeper revision 1.552 (3fa6715f0LpnznAkmX17sTFtzPmomQ)
Many files:
Clean up domain building interface ready for suspend/resume.
-rw-r--r-- | tools/internal/dom0_defs.h | 2 | ||||
-rw-r--r-- | tools/internal/xi_build.c | 167 | ||||
-rw-r--r-- | tools/internal/xi_list.c | 11 | ||||
-rw-r--r-- | xen/arch/i386/mm.c | 62 | ||||
-rw-r--r-- | xen/arch/i386/traps.c | 27 | ||||
-rw-r--r-- | xen/common/debug.c | 2 | ||||
-rw-r--r-- | xen/common/dom0_ops.c | 46 | ||||
-rw-r--r-- | xen/common/domain.c | 77 | ||||
-rw-r--r-- | xen/common/schedule.c | 7 | ||||
-rw-r--r-- | xen/include/asm-i386/processor.h | 7 | ||||
-rw-r--r-- | xen/include/hypervisor-ifs/dom0_ops.h | 10 | ||||
-rw-r--r-- | xen/include/xeno/sched.h | 14 | ||||
-rw-r--r-- | xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h | 5 |
13 files changed, 277 insertions, 160 deletions
diff --git a/tools/internal/dom0_defs.h b/tools/internal/dom0_defs.h index bea8981bee..13162534d2 100644 --- a/tools/internal/dom0_defs.h +++ b/tools/internal/dom0_defs.h @@ -98,7 +98,7 @@ static inline int do_dom0_op(dom0_op_t *op) if ( do_xen_hypercall(&hypercall) < 0 ) { - if ( errno == EINVAL ) + if ( errno == EACCES ) fprintf(stderr, "Dom0 operation failed -- need to" " rebuild the user-space tool set?\n"); goto out2; diff --git a/tools/internal/xi_build.c b/tools/internal/xi_build.c index f18f994124..1fb3be2748 100644 --- a/tools/internal/xi_build.c +++ b/tools/internal/xi_build.c @@ -68,7 +68,7 @@ static int send_pgupdates(mmu_update_t *updates, int nr_updates) /* Read the kernel header, extracting the image size and load address. */ static int read_kernel_header(int fd, long dom_size, - unsigned long * load_addr, size_t * ksize) + unsigned long * load_addr, size_t * ksize) { char signature[8]; char status[1024]; @@ -77,7 +77,7 @@ static int read_kernel_header(int fd, long dom_size, if ( fstat(fd, &stat) < 0 ) { PERROR("Cannot stat the kernel image"); - return -1; + return -1; } /* Double the kernel image size to account for dynamic memory usage etc. */ @@ -86,7 +86,7 @@ static int read_kernel_header(int fd, long dom_size, sprintf(status, "Kernel image size %ld larger than requested " "domain size %ld\n Terminated.\n", stat.st_size, dom_size); ERROR(status); - return -1; + return -1; } read(fd, signature, SIG_LEN); @@ -94,7 +94,7 @@ static int read_kernel_header(int fd, long dom_size, { ERROR("Kernel image does not contain required signature.\n" "Terminating.\n"); - return -1; + return -1; } /* Read the load address which immediately follows the Xeno signature. */ @@ -147,7 +147,7 @@ static int copy_to_domain_page(unsigned long dst_pfn, void *src_page) static int setup_guestos( int dom, int kernel_fd, int initrd_fd, unsigned long tot_pages, unsigned long virt_load_addr, size_t ksize, - dom0_builddomain_t *builddomain) + dom0_builddomain_t *builddomain, int argc, char **argv, int args_start) { l1_pgentry_t *vl1tab = NULL, *vl1e = NULL; l2_pgentry_t *vl2tab = NULL, *vl2e = NULL; @@ -158,6 +158,9 @@ static int setup_guestos( unsigned long l1tab = 0; unsigned long num_pgt_updates = 0; unsigned long count, pt_start, i, j; + unsigned long initrd_addr = 0, initrd_len = 0; + start_info_t *start_info; + int cmd_len; memset(builddomain, 0, sizeof(*builddomain)); @@ -169,14 +172,14 @@ static int setup_guestos( pgt_update_arr = pgt_updates; if ( (pgt_update_arr == NULL) || (page_array == NULL) ) { - PERROR("Could not allocate memory"); - goto error_out; + PERROR("Could not allocate memory"); + goto error_out; } if ( get_pfn_list(dom, page_array, tot_pages) != tot_pages ) { - PERROR("Could not get the page frame list"); - goto error_out; + PERROR("Could not get the page frame list"); + goto error_out; } /* Load the guest OS image. */ @@ -196,15 +199,15 @@ static int setup_guestos( /* Load the initial ramdisk image. */ if ( initrd_fd >= 0 ) { - struct stat stat; - unsigned long isize; + struct stat stat; + unsigned long isize; - if ( fstat(initrd_fd, &stat) < 0 ) + if ( fstat(initrd_fd, &stat) < 0 ) { PERROR("Could not stat the initrd image"); goto error_out; - } - isize = stat.st_size; + } + isize = stat.st_size; if ( ((isize + ksize) * 2) > (tot_pages << PAGE_SHIFT) ) { ERROR("Kernel + initrd too big to safely fit in domain memory"); @@ -212,8 +215,8 @@ static int setup_guestos( } /* 'i' is 'ksize' rounded up to a page boundary. */ - builddomain->virt_mod_addr = virt_load_addr + i; - builddomain->virt_mod_len = isize; + initrd_addr = virt_load_addr + i; + initrd_len = isize; for ( j = 0; j < isize; j += PAGE_SIZE, i += PAGE_SIZE ) { @@ -246,7 +249,7 @@ static int setup_guestos( */ l2tab = page_array[alloc_index] << PAGE_SHIFT; alloc_index--; - builddomain->l2_pgt_addr = l2tab; + builddomain->ctxt.pt_base = l2tab; /* * Pin down l2tab addr as page dir page - causes hypervisor to provide @@ -271,7 +274,7 @@ static int setup_guestos( goto error_out; memset(vl1tab, 0, PAGE_SIZE); alloc_index--; - + vl1e = vl1tab + l1_table_offset(virt_load_addr + (count << PAGE_SHIFT)); @@ -295,21 +298,40 @@ static int setup_guestos( { pgt_updates->ptr = (unsigned long)vl1e; pgt_updates->val = - ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW; + ((page_array[count] << PAGE_SHIFT) | L1_PROT) & ~_PAGE_RW; pgt_updates++; num_pgt_updates++; vl1e++; } pgt_updates->ptr = - (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; + (page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; pgt_updates->val = count; pgt_updates++; num_pgt_updates++; } builddomain->virt_startinfo_addr = - virt_load_addr + ((alloc_index-1)<<PAGE_SHIFT); + virt_load_addr + ((alloc_index-1) << PAGE_SHIFT); + + start_info = map_pfn(page_array[alloc_index-1]); + memset(start_info, 0, sizeof(*start_info)); + start_info->pt_base = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT); + start_info->mod_start = initrd_addr; + start_info->mod_len = initrd_len; + cmd_len = 0; + for ( i = args_start; i < argc; i++ ) + { + if ( cmd_len + strlen(argv[i]) > MAX_CMD_LEN - 1 ) + { + ERROR("Size of image boot params too big!\n"); + break; + } + strcat(start_info->cmd_line, argv[i]); + strcat(start_info->cmd_line, " "); + cmd_len += strlen(argv[i] + 1); + } + unmap_pfn(start_info); /* Send the page update requests down to the hypervisor. */ if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 ) @@ -321,9 +343,9 @@ static int setup_guestos( error_out: if ( page_array == NULL ) - free(page_array); + free(page_array); if ( pgt_update_arr == NULL ) - free(pgt_update_arr); + free(pgt_update_arr); return -1; } @@ -338,12 +360,11 @@ int main(int argc, char **argv) unsigned long load_addr; long tot_pages; int kernel_fd, initrd_fd = -1; - int count; - int cmd_len; int args_start = 4; char initrd_name[1024]; int domain_id; - int rc; + int rc, i; + full_execution_context_t *ctxt; if ( argv[0] != NULL ) argv0 = argv[0]; @@ -365,62 +386,98 @@ int main(int argc, char **argv) if ( (tot_pages = get_tot_pages(domain_id)) < 0 ) { PERROR("Could not find total pages for domain"); - return 1; + return 1; } kernel_fd = open(argv[2], O_RDONLY); if ( kernel_fd < 0 ) { PERROR("Could not open kernel image"); - return 1; + return 1; } rc = read_kernel_header(kernel_fd, - tot_pages << (PAGE_SHIFT - 10), - &load_addr, &ksize); + tot_pages << (PAGE_SHIFT - 10), + &load_addr, &ksize); if ( rc < 0 ) - return 1; + return 1; if( (argc > args_start) && (strncmp("initrd=", argv[args_start], 7) == 0) ) { - strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) ); - initrd_name[sizeof(initrd_name)-1] = 0; - printf("initrd present, name = %s\n", initrd_name ); - args_start++; + strncpy( initrd_name, argv[args_start]+7, sizeof(initrd_name) ); + initrd_name[sizeof(initrd_name)-1] = 0; + printf("initrd present, name = %s\n", initrd_name ); + args_start++; - initrd_fd = open(initrd_name, O_RDONLY); - if ( initrd_fd < 0 ) + initrd_fd = open(initrd_name, O_RDONLY); + if ( initrd_fd < 0 ) { PERROR("Could not open the initial ramdisk image"); - return 1; - } + return 1; + } } if ( setup_guestos(domain_id, kernel_fd, initrd_fd, tot_pages, - load_addr, ksize, &launch_op.u.builddomain) < 0 ) + load_addr, ksize, &launch_op.u.builddomain, + argc, argv, args_start) < 0 ) return 1; if ( initrd_fd >= 0 ) - close(initrd_fd); + close(initrd_fd); close(kernel_fd); - launch_op.u.builddomain.domain = domain_id; - launch_op.u.builddomain.virt_load_addr = load_addr; - launch_op.u.builddomain.num_vifs = atoi(argv[3]); - launch_op.u.builddomain.cmd_line[0] = '\0'; - cmd_len = 0; - for ( count = args_start; count < argc; count++ ) + ctxt = &launch_op.u.builddomain.ctxt; + + /* + * Initial register values: + * DS,ES,FS,GS = FLAT_RING1_DS + * CS:EIP = FLAT_RING1_CS:start_pc + * SS:ESP = FLAT_RING1_DS:start_stack + * ESI = start_info + * [EAX,EBX,ECX,EDX,EDI,EBP are zero] + * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1) + */ + ctxt->i386_ctxt.ds = FLAT_RING1_DS; + ctxt->i386_ctxt.es = FLAT_RING1_DS; + ctxt->i386_ctxt.fs = FLAT_RING1_DS; + ctxt->i386_ctxt.gs = FLAT_RING1_DS; + ctxt->i386_ctxt.ss = FLAT_RING1_DS; + ctxt->i386_ctxt.cs = FLAT_RING1_CS; + ctxt->i386_ctxt.eip = load_addr; + ctxt->i386_ctxt.esp = launch_op.u.builddomain.virt_startinfo_addr; + ctxt->i386_ctxt.esi = launch_op.u.builddomain.virt_startinfo_addr; + ctxt->i386_ctxt.eflags = (1<<9) | (1<<2); + + /* FPU is set up to default initial state. */ + memset(ctxt->i387_ctxt, 0, sizeof(ctxt->i387_ctxt)); + + /* Virtual IDT is empty at start-of-day. */ + for ( i = 0; i < 256; i++ ) { - if ( cmd_len + strlen(argv[count]) > MAX_CMD_LEN - 1 ) - { - ERROR("Size of image boot params too big!\n"); - break; - } - strcat(launch_op.u.builddomain.cmd_line, argv[count]); - strcat(launch_op.u.builddomain.cmd_line, " "); - cmd_len += strlen(argv[count] + 1); + ctxt->trap_ctxt[i].vector = i; + ctxt->trap_ctxt[i].cs = FLAT_RING1_CS; } + ctxt->fast_trap_idx = 0; + + /* No LDT. */ + ctxt->ldt_ents = 0; + + /* Use the default Xen-provided GDT. */ + ctxt->gdt_ents = 0; + + /* Ring 1 stack is the initial stack. */ + ctxt->ring1_ss = FLAT_RING1_DS; + ctxt->ring1_esp = launch_op.u.builddomain.virt_startinfo_addr; + + /* No debugging. */ + memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg)); + + /* Domain time counts from zero. */ + ctxt->domain_time = 0; + + launch_op.u.builddomain.domain = domain_id; + launch_op.u.builddomain.num_vifs = atoi(argv[3]); launch_op.cmd = DOM0_BUILDDOMAIN; rc = do_dom0_op(&launch_op); diff --git a/tools/internal/xi_list.c b/tools/internal/xi_list.c index 73df092b1d..562d5c302a 100644 --- a/tools/internal/xi_list.c +++ b/tools/internal/xi_list.c @@ -30,12 +30,11 @@ static char *statestr(int state) { switch ( state ) { - case 0: return "RUNNING"; - case 1: return "INTERRUPTIBLE"; - case 2: return "UNINTERRUPTIBLE"; - case 4: return "WAIT"; - case 8: return "SUSPENDED"; - case 16: return "DYING"; + case 0: return "RUNNING"; + case 1: return "INTERRUPTIBLE"; + case 2: return "UNINTERRUPTIBLE"; + case 4: return "STOPPED"; + case 8: return "DYING"; default: return "UNKNOWN"; } return NULL; diff --git a/xen/arch/i386/mm.c b/xen/arch/i386/mm.c index cac87b6ef2..419f4cb1b3 100644 --- a/xen/arch/i386/mm.c +++ b/xen/arch/i386/mm.c @@ -207,21 +207,18 @@ int check_descriptor(unsigned long a, unsigned long b) } -long do_set_gdt(unsigned long *frame_list, unsigned int entries) +long set_gdt(struct task_struct *p, + unsigned long *frames, + unsigned int entries) { /* NB. There are 512 8-byte entries per GDT page. */ unsigned int i, j, nr_pages = (entries + 511) / 512; - unsigned long frames[16], pfn, *gdt_page, flags; + unsigned long pfn, *gdt_page, flags; long ret = -EINVAL; struct pfn_info *page; + struct desc_struct *vgdt; - if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) - return -EINVAL; - - if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) ) - return -EFAULT; - - spin_lock_irqsave(¤t->page_lock, flags); + spin_lock_irqsave(&p->page_lock, flags); /* Check the new GDT. */ for ( i = 0; i < nr_pages; i++ ) @@ -230,7 +227,7 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries) goto out; page = frame_table + frames[i]; - if ( (page->flags & PG_domain_mask) != current->domain ) + if ( (page->flags & PG_domain_mask) != p->domain ) goto out; if ( (page->flags & PG_type_mask) != PGT_gdt_page ) @@ -250,12 +247,12 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries) /* Tear down the old GDT. */ for ( i = 0; i < 16; i++ ) { - pfn = l1_pgentry_to_pagenr(current->mm.perdomain_pt[i]); - current->mm.perdomain_pt[i] = mk_l1_pgentry(0); + pfn = l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]); + p->mm.perdomain_pt[i] = mk_l1_pgentry(0); if ( pfn == 0 ) continue; page = frame_table + pfn; ASSERT((page->flags & PG_type_mask) == PGT_gdt_page); - ASSERT((page->flags & PG_domain_mask) == current->domain); + ASSERT((page->flags & PG_domain_mask) == p->domain); ASSERT((page->type_count != 0) && (page->tot_count != 0)); put_page_type(page); put_page_tot(page); @@ -264,7 +261,7 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries) /* Install the new GDT. */ for ( i = 0; i < nr_pages; i++ ) { - current->mm.perdomain_pt[i] = + p->mm.perdomain_pt[i] = mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR); page = frame_table + frames[i]; @@ -274,21 +271,42 @@ long do_set_gdt(unsigned long *frame_list, unsigned int entries) get_page_tot(page); } - local_flush_tlb(); - /* Copy reserved GDT entries to the new GDT. */ - memcpy((struct desc_struct *)GDT_VIRT_START + FIRST_RESERVED_GDT_ENTRY, + vgdt = map_domain_mem(frames[i] << PAGE_SHIFT); + memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, gdt_table + FIRST_RESERVED_GDT_ENTRY, NR_RESERVED_GDT_ENTRIES*8); - - SET_GDT_ADDRESS(current, GDT_VIRT_START); - SET_GDT_ENTRIES(current, (entries*8)-1); - __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt)); + unmap_domain_mem(vgdt); + + SET_GDT_ADDRESS(p, GDT_VIRT_START); + SET_GDT_ENTRIES(p, (entries*8)-1); ret = 0; /* success */ out: - spin_unlock_irqrestore(¤t->page_lock, flags); + spin_unlock_irqrestore(&p->page_lock, flags); + return ret; +} + + +long do_set_gdt(unsigned long *frame_list, unsigned int entries) +{ + unsigned int nr_pages = (entries + 511) / 512; + unsigned long frames[16]; + long ret; + + if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) + return -EINVAL; + + if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) ) + return -EFAULT; + + if ( (ret = set_gdt(current, frames, entries)) == 0 ) + { + local_flush_tlb(); + __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt)); + } + return ret; } diff --git a/xen/arch/i386/traps.c b/xen/arch/i386/traps.c index 33bc451d03..9065aacd03 100644 --- a/xen/arch/i386/traps.c +++ b/xen/arch/i386/traps.c @@ -692,15 +692,16 @@ long do_set_callbacks(unsigned long event_selector, } -long do_set_fast_trap(int idx) +long set_fast_trap(struct task_struct *p, int idx) { trap_info_t *ti; /* Index 0 is special: it disables fast traps. */ if ( idx == 0 ) { - CLEAR_FAST_TRAP(¤t->thread); - SET_DEFAULT_FAST_TRAP(¤t->thread); + if ( p == current ) + CLEAR_FAST_TRAP(&p->thread); + SET_DEFAULT_FAST_TRAP(&p->thread); return 0; } @@ -712,7 +713,7 @@ long do_set_fast_trap(int idx) if ( (idx != 0x80) && ((idx < 0x20) || (idx > 0x2f)) ) return -1; - ti = current->thread.traps + idx; + ti = p->thread.traps + idx; /* * We can't virtualise interrupt gates, as there's no way to get @@ -721,19 +722,27 @@ long do_set_fast_trap(int idx) if ( TI_GET_IF(ti) ) return -1; - CLEAR_FAST_TRAP(¤t->thread); + if ( p == current ) + CLEAR_FAST_TRAP(&p->thread); - current->thread.fast_trap_idx = idx; - current->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff); - current->thread.fast_trap_desc.b = + p->thread.fast_trap_idx = idx; + p->thread.fast_trap_desc.a = (ti->cs << 16) | (ti->address & 0xffff); + p->thread.fast_trap_desc.b = (ti->address & 0xffff0000) | 0x8f00 | (TI_GET_DPL(ti)&3)<<13; - SET_FAST_TRAP(¤t->thread); + if ( p == current ) + SET_FAST_TRAP(&p->thread); return 0; } +long do_set_fast_trap(int idx) +{ + return set_fast_trap(current, idx); +} + + long do_fpu_taskswitch(void) { current->flags |= PF_GUEST_STTS; diff --git a/xen/common/debug.c b/xen/common/debug.c index c20c5b21b5..1d701e869b 100644 --- a/xen/common/debug.c +++ b/xen/common/debug.c @@ -61,7 +61,7 @@ void pdb_do_debug (dom0_op_t *op) if (p != NULL) { - if (p->state != TASK_SUSPENDED) + if (p->state != TASK_STOPPED) { cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP); hyp_event_notify(cpu_mask); diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 17dbf1d4de..b798c70022 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -93,7 +93,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) return -EFAULT; if ( op.interface_version != DOM0_INTERFACE_VERSION ) - return -EINVAL; + return -EACCES; switch ( op.cmd ) { @@ -249,6 +249,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) { struct task_struct *p = &idle0_task; u_long flags; + int i; read_lock_irqsave (&tasklist_lock, flags); @@ -271,11 +272,46 @@ long do_dom0_op(dom0_op_t *u_dom0_op) op.u.getdomaininfo.mcu_advance = p->mcu_advance; op.u.getdomaininfo.tot_pages = p->tot_pages; op.u.getdomaininfo.cpu_time = p->cpu_time; - memcpy(&op.u.getdomaininfo.ctxt, - &p->shared_info->execution_context, - sizeof(execution_context_t)); + if ( p->state == TASK_STOPPED ) + { + rmb(); /* Ensure that we see saved register state. */ + memcpy(&op.u.getdomaininfo.ctxt.i386_ctxt, + &p->shared_info->execution_context, + sizeof(p->shared_info->execution_context)); + memcpy(&op.u.getdomaininfo.ctxt.i387_ctxt, + &p->thread.i387, + sizeof(p->thread.i387)); + memcpy(&op.u.getdomaininfo.ctxt.trap_ctxt, + p->thread.traps, + sizeof(p->thread.traps)); + if ( (p->thread.fast_trap_desc.a == 0) && + (p->thread.fast_trap_desc.b == 0) ) + op.u.getdomaininfo.ctxt.fast_trap_idx = 0; + else + op.u.getdomaininfo.ctxt.fast_trap_idx = + p->thread.fast_trap_idx; + op.u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base; + op.u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents; + op.u.getdomaininfo.ctxt.gdt_ents = 0; + if ( GET_GDT_ADDRESS(p) == GDT_VIRT_START ) + { + for ( i = 0; i < 16; i++ ) + op.u.getdomaininfo.ctxt.gdt_frames[i] = + l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]); + op.u.getdomaininfo.ctxt.gdt_ents = + (GET_GDT_ENTRIES(p) + 1) >> 3; + } + op.u.getdomaininfo.ctxt.ring1_ss = p->thread.ss1; + op.u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1; + op.u.getdomaininfo.ctxt.pt_base = + pagetable_val(p->mm.pagetable); + memcpy(op.u.getdomaininfo.ctxt.debugreg, + p->thread.debugreg, + sizeof(p->thread.debugreg)); + op.u.getdomaininfo.ctxt.domain_time = + p->shared_info->domain_time; + } } - read_unlock_irqrestore(&tasklist_lock, flags); copy_to_user(u_dom0_op, &op, sizeof(op)); } diff --git a/xen/common/domain.c b/xen/common/domain.c index 5005cc9f47..d8963c0e71 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -18,6 +18,8 @@ #include <xeno/console.h> #include <xeno/vbd.h> +#include <asm/i387.h> + /* * NB. No ring-3 access in initial guestOS pagetables. Note that we allow * ring-3 privileges in the page directories, so that the guestOS may later @@ -186,7 +188,7 @@ long kill_other_domain(unsigned int dom, int force) p = find_domain_by_id(dom); if ( p == NULL ) return -ESRCH; - if ( p->state == TASK_SUSPENDED ) + if ( p->state == TASK_STOPPED ) { __kill_domain(p); } @@ -207,7 +209,12 @@ long kill_other_domain(unsigned int dom, int force) void stop_domain(void) { - set_current_state(TASK_SUSPENDED); + memcpy(¤t->shared_info->execution_context, + get_execution_context(), + sizeof(execution_context_t)); + unlazy_fpu(current); + wmb(); /* All CPUs must see saved info in state TASK_STOPPED. */ + set_current_state(TASK_STOPPED); clear_bit(_HYP_EVENT_STOP, ¤t->hyp_events); __enter_scheduler(); } @@ -220,7 +227,7 @@ long stop_other_domain(unsigned int dom) p = find_domain_by_id (dom); if ( p == NULL) return -ESRCH; - if ( p->state != TASK_SUSPENDED ) + if ( p->state != TASK_STOPPED ) { cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP); hyp_event_notify(cpu_mask); @@ -328,25 +335,10 @@ void release_task(struct task_struct *p) /* final_setup_guestos is used for final setup and launching of domains other * than domain 0. ie. the domains that are being built by the userspace dom0 * domain builder. - * - * Initial load map: - * start_address: - * OS image - * .... - * stack_start: - * start_info: - * <one page> - * page tables: - * <enough pages> - * end_address: - * shared_info: - * <one page> */ - int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) { start_info_t * virt_startinfo_addr; - unsigned long virt_stack_addr; unsigned long phys_l2tab; net_ring_t *shared_rings; net_vif_t *net_vif; @@ -355,19 +347,43 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) if ( (p->flags & PF_CONSTRUCTED) ) return -EINVAL; + memcpy(&p->shared_info->execution_context, + &builddomain->ctxt.i386_ctxt, + sizeof(p->shared_info->execution_context)); + memcpy(&p->thread.i387, + &builddomain->ctxt.i387_ctxt, + sizeof(p->thread.i387)); + memcpy(p->thread.traps, + &builddomain->ctxt.trap_ctxt, + sizeof(p->thread.traps)); + SET_DEFAULT_FAST_TRAP(&p->thread); + (void)set_fast_trap(p, builddomain->ctxt.fast_trap_idx); + p->mm.ldt_base = builddomain->ctxt.ldt_base; + p->mm.ldt_ents = builddomain->ctxt.ldt_ents; + SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES); + SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS); + if ( builddomain->ctxt.gdt_ents != 0 ) + (void)set_gdt(p, + builddomain->ctxt.gdt_frames, + builddomain->ctxt.gdt_ents); + p->thread.ss1 = builddomain->ctxt.ring1_ss; + p->thread.esp1 = builddomain->ctxt.ring1_esp; + memcpy(p->thread.debugreg, + builddomain->ctxt.debugreg, + sizeof(p->thread.debugreg)); + /* NB. Page base must already be pinned! */ - phys_l2tab = builddomain->l2_pgt_addr; + phys_l2tab = builddomain->ctxt.pt_base; p->mm.pagetable = mk_pagetable(phys_l2tab); get_page_type(&frame_table[phys_l2tab>>PAGE_SHIFT]); get_page_tot(&frame_table[phys_l2tab>>PAGE_SHIFT]); /* set up the shared info structure */ update_dom_time(p->shared_info); - p->shared_info->domain_time = 0; + p->shared_info->domain_time = builddomain->ctxt.domain_time; /* we pass start info struct to guest os as function parameter on stack */ virt_startinfo_addr = (start_info_t *)builddomain->virt_startinfo_addr; - virt_stack_addr = (unsigned long)virt_startinfo_addr; /* we need to populate start_info struct within the context of the * new domain. thus, temporarely install its pagetables. @@ -376,17 +392,8 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) __asm__ __volatile__ ( "mov %%eax,%%cr3" : : "a" (pagetable_val(p->mm.pagetable))); - memset(virt_startinfo_addr, 0, sizeof(*virt_startinfo_addr)); virt_startinfo_addr->nr_pages = p->tot_pages; - virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info); - virt_startinfo_addr->pt_base = builddomain->virt_load_addr + - ((p->tot_pages - 1) << PAGE_SHIFT); - - /* module size and length */ - - virt_startinfo_addr->mod_start = builddomain->virt_mod_addr; - virt_startinfo_addr->mod_len = builddomain->virt_mod_len; - + virt_startinfo_addr->shared_info = virt_to_phys(p->shared_info); virt_startinfo_addr->dom_id = p->domain; virt_startinfo_addr->flags = IS_PRIV(p) ? SIF_PRIVILEGED : 0; @@ -409,9 +416,6 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) /* Add block io interface */ virt_startinfo_addr->blk_ring = virt_to_phys(p->blk_ring_base); - /* Copy the command line */ - strcpy(virt_startinfo_addr->cmd_line, builddomain->cmd_line); - /* Reinstate the caller's page tables. */ __asm__ __volatile__ ( "mov %%eax,%%cr3" : : "a" (pagetable_val(current->mm.pagetable))); @@ -419,11 +423,6 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain) p->flags |= PF_CONSTRUCTED; - new_thread(p, - (unsigned long)builddomain->virt_load_addr, - (unsigned long)virt_stack_addr, - (unsigned long)virt_startinfo_addr); - return 0; } diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 2825e71efb..d56bf00412 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -116,7 +116,7 @@ static void __calc_evt(struct task_struct *p) */ void sched_add_domain(struct task_struct *p) { - p->state = TASK_SUSPENDED; + p->state = TASK_STOPPED; p->mcu_advance = MCU_ADVANCE; if ( p->domain == IDLE_DOMAIN_ID ) @@ -379,11 +379,10 @@ asmlinkage void __enter_scheduler(void) break; } case TASK_UNINTERRUPTIBLE: - case TASK_WAIT: case TASK_DYING: - case TASK_SUSPENDED: + case TASK_STOPPED: default: - /* done if not running. Else, continue */ + /* Done if not running. Else continue. */ goto deschedule_done; case TASK_RUNNING:; } diff --git a/xen/include/asm-i386/processor.h b/xen/include/asm-i386/processor.h index 3f3c8c4ba1..4022ef5fde 100644 --- a/xen/include/asm-i386/processor.h +++ b/xen/include/asm-i386/processor.h @@ -14,6 +14,7 @@ #include <xeno/config.h> #include <hypervisor-ifs/hypervisor-if.h> +struct task_struct; /* * Default implementation of macro that returns current @@ -381,6 +382,8 @@ extern struct desc_struct *idt_tables[]; (memcpy(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \ &((_p)->fast_trap_desc), 8)) +long set_fast_trap(struct task_struct *p, int idx); + #define INIT_THREAD { \ 0, 0, \ { [0 ... 7] = 0 }, /* debugging registers */ \ @@ -430,7 +433,9 @@ struct mm_struct { #define GET_GDT_ENTRIES(_p) ((*(u16 *)((_p)->mm.gdt + 0))) #define GET_GDT_ADDRESS(_p) ((*(u32 *)((_p)->mm.gdt + 2))) -struct task_struct; +long set_gdt(struct task_struct *p, + unsigned long *frames, + unsigned int entries); /* Free all resources held by a thread. */ extern void release_thread(struct task_struct *); diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h index ff07461f8b..cd18764106 100644 --- a/xen/include/hypervisor-ifs/dom0_ops.h +++ b/xen/include/hypervisor-ifs/dom0_ops.h @@ -17,7 +17,7 @@ * This makes sure that old versions of dom0 tools will stop working in a * well-defined way (rather than crashing the machine, for instance). */ -#define DOM0_INTERFACE_VERSION 0xAAAA0001 +#define DOM0_INTERFACE_VERSION 0xAAAA0002 /* @@ -35,6 +35,7 @@ typedef struct full_execution_context_st unsigned long ring1_ss, ring1_esp; /* Virtual TSS (only SS1/ESP1) */ unsigned long pt_base; /* CR3 (pagetable base) */ unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */ + u64 domain_time; /* Domain virtual time */ } full_execution_context_t; #define MAX_CMD_LEN 256 @@ -88,13 +89,8 @@ typedef struct dom0_builddomain_st { /* IN variables. */ unsigned int domain; - unsigned long l2_pgt_addr; - unsigned long virt_load_addr; unsigned long virt_startinfo_addr; - unsigned int num_vifs; - char cmd_line[MAX_CMD_LEN]; - unsigned long virt_mod_addr; - unsigned long virt_mod_len; + unsigned int num_vifs; full_execution_context_t ctxt; } dom0_builddomain_t; diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h index 8265726fd8..6775071a31 100644 --- a/xen/include/xeno/sched.h +++ b/xen/include/xeno/sched.h @@ -146,20 +146,18 @@ struct task_struct * or expiring timer * TASK_UNINTERRUPTIBLE: Domain is blocked but may not be woken up by an * arbitrary event or timer. - * TASK_WAIT: Domains CPU allocation expired. - * TASK_SUSPENDED: Domain is suspended (startofday or pervasive debugger) + * TASK_STOPPED: Domain is sopped. * TASK_DYING: Domain is about to cross over to the land of the dead. * * If you update these then please update the mapping to text names in * xi_list. */ -#define TASK_RUNNING 0 -#define TASK_INTERRUPTIBLE 1 -#define TASK_UNINTERRUPTIBLE 2 -#define TASK_WAIT 4 -#define TASK_SUSPENDED 8 -#define TASK_DYING 16 +#define TASK_RUNNING 0 +#define TASK_INTERRUPTIBLE 1 +#define TASK_UNINTERRUPTIBLE 2 +#define TASK_STOPPED 4 +#define TASK_DYING 8 #include <asm/uaccess.h> /* for KERNEL_DS */ diff --git a/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h b/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h index fedd5d9455..d1ded5214a 100644 --- a/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h +++ b/xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h @@ -11,6 +11,7 @@ #include <linux/types.h> #include <asm/hypervisor-ifs/hypervisor-if.h> +#include <asm/hypervisor-ifs/dom0_ops.h> #include <asm/ptrace.h> #include <asm/page.h> @@ -262,10 +263,10 @@ static inline int HYPERVISOR_exit(void) return ret; } -static inline int HYPERVISOR_dom0_op(void *dom0_op) +static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op) { int ret; - op->interface_version = DOM0_INTERFACE_VERSION; + dom0_op->interface_version = DOM0_INTERFACE_VERSION; __asm__ __volatile__ ( TRAP_INSTR : "=a" (ret) : "0" (__HYPERVISOR_dom0_op), |