bitkeeper revision 1.553 (3fa68dcd5yXksUZ7k12Hq41k_eQIOw)

Many files:
  More cleanups for suspend/resume. STOP requests are now routed thru the guestos to allow preparation for pickling.
This commit is contained in:
kaf24@scramble.cl.cam.ac.uk committed 2003-11-03 17:18:05 +00:00
1 parent 01b9634a96
commit 0e1a07327c
15 files changed
+149 -108

No files matched your search

+36 -5
View File
@@ -147,7 +147,8 @@ 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, int argc, char **argv, int args_start)
dom0_builddomain_t *builddomain, int argc, char **argv, int args_start,
unsigned long shared_info_frame)
{
l1_pgentry_t *vl1tab = NULL, *vl1e = NULL;
l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
@@ -160,6 +161,7 @@ static int setup_guestos(
unsigned long count, pt_start, i, j;
unsigned long initrd_addr = 0, initrd_len = 0;
start_info_t *start_info;
shared_info_t *shared_info;
int cmd_len;
memset(builddomain, 0, sizeof(*builddomain));
@@ -319,6 +321,10 @@ static int setup_guestos(
start_info->pt_base = virt_load_addr + ((tot_pages-1) << PAGE_SHIFT);
start_info->mod_start = initrd_addr;
start_info->mod_len = initrd_len;
start_info->nr_pages = tot_pages;
start_info->shared_info = shared_info_frame << PAGE_SHIFT;
start_info->dom_id = dom;
start_info->flags = 0;
cmd_len = 0;
for ( i = args_start; i < argc; i++ )
{
@@ -333,6 +339,11 @@ static int setup_guestos(
}
unmap_pfn(start_info);
/* shared_info page starts its life empty. */
shared_info = map_pfn(shared_info_frame);
memset(shared_info, 0, PAGE_SIZE);
unmap_pfn(shared_info);
/* Send the page update requests down to the hypervisor. */
if ( send_pgupdates(pgt_update_arr, num_pgt_updates) < 0 )
goto error_out;
@@ -356,7 +367,7 @@ int main(int argc, char **argv)
* the 8-byte signature and 4-byte load address.
*/
size_t ksize;
dom0_op_t launch_op;
dom0_op_t launch_op, op;
unsigned long load_addr;
long tot_pages;
int kernel_fd, initrd_fd = -1;
@@ -418,9 +429,24 @@ int main(int argc, char **argv)
}
}
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = domain_id;
if ( (do_dom0_op(&op) < 0) || (op.u.getdomaininfo.domain != domain_id) )
{
PERROR("Could not get info on domain");
return 1;
}
if ( (op.u.getdomaininfo.state != DOMSTATE_STOPPED) ||
(op.u.getdomaininfo.ctxt.pt_base != 0) )
{
ERROR("Domain is already constructed");
return 1;
}
if ( setup_guestos(domain_id, kernel_fd, initrd_fd, tot_pages,
load_addr, ksize, &launch_op.u.builddomain,
argc, argv, args_start) < 0 )
argc, argv, args_start,
op.u.getdomaininfo.shared_info_frame) < 0 )
return 1;
if ( initrd_fd >= 0 )
@@ -429,6 +455,8 @@ int main(int argc, char **argv)
ctxt = &launch_op.u.builddomain.ctxt;
ctxt->flags = 0;
/*
* Initial register values:
* DS,ES,FS,GS = FLAT_RING1_DS
@@ -473,8 +501,11 @@ int main(int argc, char **argv)
/* No debugging. */
memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
/* Domain time counts from zero. */
ctxt->domain_time = 0;
/* No callback handlers. */
ctxt->event_callback_cs = FLAT_RING1_CS;
ctxt->event_callback_eip = 0;
ctxt->failsafe_callback_cs = FLAT_RING1_CS;
ctxt->failsafe_callback_eip = 0;
launch_op.u.builddomain.domain = domain_id;
launch_op.u.builddomain.num_vifs = atoi(argv[3]);
+3 -6
View File
@@ -30,12 +30,9 @@ static char *statestr(int state)
{
switch ( state )
{
case 0: return "RUNNING";
case 1: return "INTERRUPTIBLE";
case 2: return "UNINTERRUPTIBLE";
case 4: return "STOPPED";
case 8: return "DYING";
default: return "UNKNOWN";
case DOMSTATE_ACTIVE: return "ACTIVE";
case DOMSTATE_STOPPED: return "STOPPED";
default: return "UNKNOWN";
}
return NULL;
}
-21
View File
@@ -188,27 +188,6 @@ void machine_power_off(void)
machine_restart(0);
}
void exit_thread(void)
{
/* nothing to do ... */
}
void flush_thread(void)
{
struct task_struct *tsk = current;
memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
/*
* Forget coprocessor state..
*/
clear_fpu(tsk);
tsk->flags &= ~PF_DONEFPUINIT;
}
void release_thread(struct task_struct *dead_task)
{
}
void new_thread(struct task_struct *p,
unsigned long start_pc,
unsigned long start_stack,
+2 -2
View File
@@ -63,8 +63,8 @@ void pdb_do_debug (dom0_op_t *op)
{
if (p->state != TASK_STOPPED)
{
cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
hyp_event_notify(cpu_mask);
cpu_mask = mark_guest_event(p, _EVENT_STOP);
guest_event_notify(cpu_mask);
}
put_task_struct(p);
}
+14 -3
View File
@@ -267,17 +267,24 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
strcpy (op.u.getdomaininfo.name, p->name);
op.u.getdomaininfo.processor = p->processor;
op.u.getdomaininfo.has_cpu = p->has_cpu;
op.u.getdomaininfo.state = p->state;
op.u.getdomaininfo.state = DOMSTATE_ACTIVE;
if ( (p->state == TASK_STOPPED) || (p->state == TASK_DYING) )
op.u.getdomaininfo.state = DOMSTATE_STOPPED;
op.u.getdomaininfo.hyp_events = p->hyp_events;
op.u.getdomaininfo.mcu_advance = p->mcu_advance;
op.u.getdomaininfo.tot_pages = p->tot_pages;
op.u.getdomaininfo.cpu_time = p->cpu_time;
op.u.getdomaininfo.shared_info_frame =
__pa(p->shared_info) >> PAGE_SHIFT;
if ( p->state == TASK_STOPPED )
{
rmb(); /* Ensure that we see saved register state. */
op.u.getdomaininfo.ctxt.flags = 0;
memcpy(&op.u.getdomaininfo.ctxt.i386_ctxt,
&p->shared_info->execution_context,
sizeof(p->shared_info->execution_context));
if ( p->flags & PF_DONEFPUINIT )
op.u.getdomaininfo.ctxt.flags |= ECF_I387_VALID;
memcpy(&op.u.getdomaininfo.ctxt.i387_ctxt,
&p->thread.i387,
sizeof(p->thread.i387));
@@ -308,8 +315,12 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
memcpy(op.u.getdomaininfo.ctxt.debugreg,
p->thread.debugreg,
sizeof(p->thread.debugreg));
op.u.getdomaininfo.ctxt.domain_time =
p->shared_info->domain_time;
op.u.getdomaininfo.ctxt.event_callback_cs = p->event_selector;
op.u.getdomaininfo.ctxt.event_callback_eip = p->event_address;
op.u.getdomaininfo.ctxt.failsafe_callback_cs =
p->failsafe_selector;
op.u.getdomaininfo.ctxt.failsafe_callback_eip =
p->failsafe_address;
}
}
read_unlock_irqrestore(&tasklist_lock, flags);
+37 -35
View File
@@ -32,12 +32,9 @@
rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED;
struct task_struct *task_hash[TASK_HASH_SIZE];
/*
* create a new domain
*/
struct task_struct *do_createdomain(unsigned int dom_id, unsigned int cpu)
{
int retval, i;
int retval;
struct task_struct *p = NULL;
unsigned long flags;
@@ -68,20 +65,8 @@ struct task_struct *do_createdomain(unsigned int dom_id, unsigned int cpu)
INIT_LIST_HEAD(&p->physdisk_aces);
SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
p->addr_limit = USER_DS;
/*
* We're basically forcing default RPLs to 1, so that our "what privilege
* level are we returning to?" logic works.
*/
p->failsafe_selector = FLAT_RING1_CS;
p->event_selector = FLAT_RING1_CS;
p->thread.ss1 = FLAT_RING1_DS;
for ( i = 0; i < 256; i++ ) p->thread.traps[i].cs = FLAT_RING1_CS;
sched_add_domain(p);
INIT_LIST_HEAD(&p->pg_head);
@@ -139,9 +124,11 @@ void __kill_domain(struct task_struct *p)
machine_restart(0);
}
printk("Killing domain %d\n", p->domain);
/* Only allow the domain to be destroyed once. */
if ( !sched_rem_domain(p) )
return;
sched_rem_domain(p);
printk("Killing domain %d\n", p->domain);
unlink_blkdev_info(p);
@@ -215,7 +202,6 @@ void stop_domain(void)
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();
}
@@ -229,8 +215,8 @@ long stop_other_domain(unsigned int dom)
if ( p->state != TASK_STOPPED )
{
cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
hyp_event_notify(cpu_mask);
cpu_mask = mark_guest_event(p, _EVENT_STOP);
guest_event_notify(cpu_mask);
}
put_task_struct(p);
@@ -332,13 +318,14 @@ void release_task(struct task_struct *p)
}
/* final_setup_guestos is used for final setup and launching of domains other
/*
* 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.
*/
int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
{
start_info_t * virt_startinfo_addr;
start_info_t *virt_startinfo_addr;
unsigned long phys_l2tab;
net_ring_t *shared_rings;
net_vif_t *net_vif;
@@ -346,7 +333,10 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
if ( (p->flags & PF_CONSTRUCTED) )
return -EINVAL;
p->flags &= ~PF_DONEFPUINIT;
if ( builddomain->ctxt.flags & ECF_I387_VALID )
p->flags |= PF_DONEFPUINIT;
memcpy(&p->shared_info->execution_context,
&builddomain->ctxt.i386_ctxt,
sizeof(p->shared_info->execution_context));
@@ -371,6 +361,10 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
memcpy(p->thread.debugreg,
builddomain->ctxt.debugreg,
sizeof(p->thread.debugreg));
p->event_selector = builddomain->ctxt.event_callback_cs;
p->event_address = builddomain->ctxt.event_callback_eip;
p->failsafe_selector = builddomain->ctxt.failsafe_callback_cs;
p->failsafe_address = builddomain->ctxt.failsafe_callback_eip;
/* NB. Page base must already be pinned! */
phys_l2tab = builddomain->ctxt.pt_base;
@@ -378,25 +372,19 @@ int final_setup_guestos(struct task_struct *p, dom0_builddomain_t *builddomain)
get_page_type(&frame_table[phys_l2tab>>PAGE_SHIFT]);
get_page_tot(&frame_table[phys_l2tab>>PAGE_SHIFT]);
/* set up the shared info structure */
/* Set up the shared info structure. */
update_dom_time(p->shared_info);
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;
/* we need to populate start_info struct within the context of the
* new domain. thus, temporarely install its pagetables.
/*
* We need to populate start_info struct within the context of the new
* domain. Thus temporarely install its pagetables.
*/
__cli();
__asm__ __volatile__ (
"mov %%eax,%%cr3" : : "a" (pagetable_val(p->mm.pagetable)));
virt_startinfo_addr->nr_pages = p->tot_pages;
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;
/* Add virtual network interfaces and point to them in startinfo. */
while (builddomain->num_vifs-- > 0) {
net_vif = create_net_vif(p->domain);
@@ -437,7 +425,8 @@ static unsigned long alloc_page_from_domain(unsigned long * cur_addr,
return ret;
}
/* setup_guestos is used for building dom0 solely. other domains are built in
/*
* setup_guestos is used for building dom0 solely. other domains are built in
* userspace dom0 and final setup is being done by final_setup_guestos.
*/
int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
@@ -513,6 +502,19 @@ int setup_guestos(struct task_struct *p, dom0_createdomain_t *params,
printk("DOM%d: Guest OS virtual load address is %08lx\n", dom,
virt_load_address);
SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
/*
* We're basically forcing default RPLs to 1, so that our "what privilege
* level are we returning to?" logic works.
*/
p->failsafe_selector = FLAT_RING1_CS;
p->event_selector = FLAT_RING1_CS;
p->thread.ss1 = FLAT_RING1_DS;
for ( i = 0; i < 256; i++ )
p->thread.traps[i].cs = FLAT_RING1_CS;
/*
* WARNING: The new domain must have its 'processor' field
* filled in by now !!
-1
View File
@@ -18,7 +18,6 @@ static hyp_event_callback_fn_t event_call_fn[] =
{
__enter_scheduler,
kill_domain,
stop_domain
};
/* Handle outstanding events for the currently-executing domain. */
+12 -3
View File
@@ -24,7 +24,6 @@
#include <xeno/timer.h>
#include <xeno/perfc.h>
#undef SCHEDULER_TRACE
#ifdef SCHEDULER_TRACE
#define TRC(_x) _x
@@ -138,9 +137,13 @@ void sched_add_domain(struct task_struct *p)
}
}
void sched_rem_domain(struct task_struct *p)
int sched_rem_domain(struct task_struct *p)
{
p->state = TASK_DYING;
int x, y = p->state;
do {
if ( (x = y) == TASK_DYING ) return 0;
} while ( (y = cmpxchg(&p->state, x, TASK_DYING)) != x );
return 1;
}
@@ -227,6 +230,12 @@ long do_sched_op(unsigned long op)
break;
}
case SCHEDOP_stop:
{
stop_domain();
break;
}
default:
ret = -ENOSYS;
}
-15
View File
@@ -437,21 +437,6 @@ 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 *);
/*
* create a kernel thread without removing it from tasklists
*/
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
/* Copy and release all segment info associated with a VM */
extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
extern void release_segments(struct mm_struct * mm);
unsigned long get_wchan(struct task_struct *p);
#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
struct microcode {
unsigned int hdrver;
unsigned int rev;
-7
View File
@@ -63,9 +63,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz
* indicated by comparing RETURN with OLD.
*/
#ifdef CONFIG_X86_CMPXCHG
#define __HAVE_ARCH_CMPXCHG 1
static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
unsigned long new, int size)
{
@@ -97,10 +94,6 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
(unsigned long)(n),sizeof(*(ptr))))
#else
/* Compiling for a 386 proper. Is it worth implementing via cli/sti? */
#endif
/*
* Force strict CPU ordering.
* And yes, this is required on UP too when we're talking
+10 -2
View File
@@ -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 0xAAAA0002
#define DOM0_INTERFACE_VERSION 0xAAAA0003
/*
@@ -26,6 +26,8 @@
*/
typedef struct full_execution_context_st
{
#define ECF_I387_VALID (1<<0)
unsigned long flags;
execution_context_t i386_ctxt; /* User-level CPU registers */
char i387_ctxt[256]; /* User-level FPU registers */
trap_info_t trap_ctxt[256]; /* Virtual IDT */
@@ -35,7 +37,10 @@ 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 */
unsigned long event_callback_cs; /* CS:EIP of event callback */
unsigned long event_callback_eip;
unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
unsigned long failsafe_callback_eip;
} full_execution_context_t;
#define MAX_CMD_LEN 256
@@ -121,11 +126,14 @@ typedef struct dom0_getdomaininfo_st
char name[MAX_DOMAIN_NAME];
int processor;
int has_cpu;
#define DOMSTATE_ACTIVE 0
#define DOMSTATE_STOPPED 1
int state;
int hyp_events;
unsigned long mcu_advance;
unsigned int tot_pages;
long long cpu_time;
unsigned long shared_info_frame; /* MFN of shared_info struct */
full_execution_context_t ctxt;
} dom0_getdomaininfo_t;
@@ -90,6 +90,7 @@
#define EVENT_DEBUG 0x08 /* Request guest to dump debug info (gross!) */
#define EVENT_NET 0x10 /* There are packets for transmission. */
#define EVENT_PS2 0x20 /* PS/2 keyboard or mouse event(s) */
#define EVENT_STOP 0x40 /* Prepare for stopping and possible pickling */
/* Bit offsets, as opposed to the above masks. */
#define _EVENT_BLKDEV 0
@@ -98,6 +99,7 @@
#define _EVENT_DEBUG 3
#define _EVENT_NET 4
#define _EVENT_PS2 5
#define _EVENT_STOP 6
/*
* Virtual addresses beyond this are not modifiable by guest OSes. The
@@ -156,6 +158,7 @@
*/
#define SCHEDOP_yield 0
#define SCHEDOP_exit 1
#define SCHEDOP_stop 2
+1 -7
View File
@@ -31,7 +31,6 @@ extern struct mm_struct init_mm;
#define _HYP_EVENT_NEED_RESCHED 0
#define _HYP_EVENT_DIE 1
#define _HYP_EVENT_STOP 2
#define PF_DONEFPUINIT 0x1 /* Has the FPU been initialised for this task? */
#define PF_USEDFPU 0x2 /* Has this task used the FPU since last save? */
@@ -148,9 +147,6 @@ struct task_struct
* arbitrary event or timer.
* 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
@@ -214,8 +210,6 @@ void new_thread(struct task_struct *p,
unsigned long start_pc,
unsigned long start_stack,
unsigned long start_info);
extern void flush_thread(void);
extern void exit_thread(void);
/* Linux puts these here for some reason! */
extern int request_irq(unsigned int,
@@ -235,7 +229,7 @@ extern unsigned long wait_init_idle;
void scheduler_init(void);
void schedulers_start(void);
void sched_add_domain(struct task_struct *p);
void sched_rem_domain(struct task_struct *p);
int sched_rem_domain(struct task_struct *p);
long sched_bvtctl(unsigned long ctx_allow);
long sched_adjdom(int dom, unsigned long mcu_adv, unsigned long warp,
unsigned long warpl, unsigned long warpu);
@@ -50,7 +50,7 @@
* Point at the empty zero page to start with. We map the real shared_info
* page as soon as fixmap is up and running.
*/
shared_info_t *HYPERVISOR_shared_info = empty_zero_page;
shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
unsigned long *phys_to_machine_mapping;
@@ -1048,3 +1048,22 @@ static int __init setup_death_event(void)
}
__initcall(setup_death_event);
/******************************************************************************
* Stop/pickle callback handling.
*/
static void time_to_stop(int irq, void *unused, struct pt_regs *regs)
{
HYPERVISOR_stop();
}
static int __init setup_stop_event(void)
{
(void)request_irq(_EVENT_STOP, time_to_stop, 0, "stop", NULL);
return 0;
}
__initcall(setup_stop_event);
@@ -263,6 +263,17 @@ static inline int HYPERVISOR_exit(void)
return ret;
}
static inline int HYPERVISOR_stop(void)
{
int ret;
__asm__ __volatile__ (
TRAP_INSTR
: "=a" (ret) : "0" (__HYPERVISOR_sched_op),
"b" (SCHEDOP_stop) );
return ret;
}
static inline int HYPERVISOR_dom0_op(dom0_op_t *dom0_op)
{
int ret;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.