aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-11-03 15:16:47 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2003-11-03 15:16:47 +0000
commit01b9634a9623af6695ece257d8cbe9296e906571 (patch)
treed53b2dea48e0aaa01d5dec0296bc0c1052337836
parent98fd1a41ef7f38c12a47178b42c68332ed9eff55 (diff)
downloadxen-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.h2
-rw-r--r--tools/internal/xi_build.c167
-rw-r--r--tools/internal/xi_list.c11
-rw-r--r--xen/arch/i386/mm.c62
-rw-r--r--xen/arch/i386/traps.c27
-rw-r--r--xen/common/debug.c2
-rw-r--r--xen/common/dom0_ops.c46
-rw-r--r--xen/common/domain.c77
-rw-r--r--xen/common/schedule.c7
-rw-r--r--xen/include/asm-i386/processor.h7
-rw-r--r--xen/include/hypervisor-ifs/dom0_ops.h10
-rw-r--r--xen/include/xeno/sched.h14
-rw-r--r--xenolinux-2.4.22-sparse/include/asm-xeno/hypervisor.h5
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(&current->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(&current->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(&current->thread);
- SET_DEFAULT_FAST_TRAP(&current->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(&current->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(&current->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(&current->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, &current->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),