debuggers.hg

view xen/common/domain.c @ 3515:d331c6994d28

bitkeeper revision 1.1159.223.12 (41f14d3cE4GADmEAEr6XE9nXX4dyGw)

Common-code cleanups. Moved arch-specific code out into arch/x86
and asm-x86.
author kaf24@scramble.cl.cam.ac.uk
date Fri Jan 21 18:43:08 2005 +0000 (2005-01-21)
parents 4b44501cd54c
children 46c14b1a4351 0a2fa97dfafc e674bd389503
line source
1 /******************************************************************************
2 * domain.c
3 *
4 * Generic domain-handling functions.
5 */
7 #include <xen/config.h>
8 #include <xen/init.h>
9 #include <xen/lib.h>
10 #include <xen/errno.h>
11 #include <xen/sched.h>
12 #include <xen/mm.h>
13 #include <xen/event.h>
14 #include <xen/time.h>
15 #include <xen/console.h>
16 #include <asm/shadow.h>
17 #include <public/dom0_ops.h>
18 #include <asm/domain_page.h>
20 /* Both these structures are protected by the domlist_lock. */
21 rwlock_t domlist_lock = RW_LOCK_UNLOCKED;
22 struct domain *domain_hash[DOMAIN_HASH_SIZE];
23 struct domain *domain_list;
25 struct domain *dom0;
27 struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
28 {
29 struct domain *d, **pd;
31 if ( (d = alloc_domain_struct()) == NULL )
32 return NULL;
34 atomic_set(&d->refcnt, 1);
35 atomic_set(&d->pausecnt, 0);
37 shadow_lock_init(d);
39 d->id = dom_id;
40 d->processor = cpu;
41 d->create_time = NOW();
43 memcpy(&d->thread, &idle0_task.thread, sizeof(d->thread));
45 spin_lock_init(&d->page_alloc_lock);
46 INIT_LIST_HEAD(&d->page_list);
47 INIT_LIST_HEAD(&d->xenpage_list);
49 /* Per-domain PCI-device list. */
50 spin_lock_init(&d->pcidev_lock);
51 INIT_LIST_HEAD(&d->pcidev_list);
53 if ( (d->id != IDLE_DOMAIN_ID) &&
54 ((init_event_channels(d) != 0) || (grant_table_create(d) != 0)) )
55 {
56 destroy_event_channels(d);
57 free_domain_struct(d);
58 return NULL;
59 }
61 arch_do_createdomain(d);
63 sched_add_domain(d);
65 if ( d->id != IDLE_DOMAIN_ID )
66 {
67 write_lock(&domlist_lock);
68 pd = &domain_list; /* NB. domain_list maintained in order of dom_id. */
69 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_list )
70 if ( (*pd)->id > d->id )
71 break;
72 d->next_list = *pd;
73 *pd = d;
74 d->next_hash = domain_hash[DOMAIN_HASH(dom_id)];
75 domain_hash[DOMAIN_HASH(dom_id)] = d;
76 write_unlock(&domlist_lock);
77 }
79 return d;
80 }
83 struct domain *find_domain_by_id(domid_t dom)
84 {
85 struct domain *d;
87 read_lock(&domlist_lock);
88 d = domain_hash[DOMAIN_HASH(dom)];
89 while ( d != NULL )
90 {
91 if ( d->id == dom )
92 {
93 if ( unlikely(!get_domain(d)) )
94 d = NULL;
95 break;
96 }
97 d = d->next_hash;
98 }
99 read_unlock(&domlist_lock);
101 return d;
102 }
105 /* Return the most recently created domain. */
106 struct domain *find_last_domain(void)
107 {
108 struct domain *d, *dlast;
110 read_lock(&domlist_lock);
111 dlast = domain_list;
112 d = dlast->next_list;
113 while ( d != NULL )
114 {
115 if ( d->create_time > dlast->create_time )
116 dlast = d;
117 d = d->next_list;
118 }
119 if ( !get_domain(dlast) )
120 dlast = NULL;
121 read_unlock(&domlist_lock);
123 return dlast;
124 }
127 void domain_kill(struct domain *d)
128 {
129 domain_pause(d);
130 if ( !test_and_set_bit(DF_DYING, &d->flags) )
131 {
132 sched_rem_domain(d);
133 domain_relinquish_memory(d);
134 put_domain(d);
135 }
136 }
139 void domain_crash(void)
140 {
141 if ( current->id == 0 )
142 BUG();
144 set_bit(DF_CRASHED, &current->flags);
146 send_guest_virq(dom0, VIRQ_DOM_EXC);
148 __enter_scheduler();
149 BUG();
150 }
152 void domain_shutdown(u8 reason)
153 {
154 if ( current->id == 0 )
155 {
156 extern void machine_restart(char *);
157 extern void machine_halt(void);
159 if ( reason == 0 )
160 {
161 printk("Domain 0 halted: halting machine.\n");
162 machine_halt();
163 }
164 else
165 {
166 printk("Domain 0 shutdown: rebooting machine.\n");
167 machine_restart(0);
168 }
169 }
171 current->shutdown_code = reason;
172 set_bit(DF_SHUTDOWN, &current->flags);
174 send_guest_virq(dom0, VIRQ_DOM_EXC);
176 __enter_scheduler();
177 }
179 unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes)
180 {
181 unsigned int alloc_pfns, nr_pages;
182 struct pfn_info *page;
184 nr_pages = (kbytes + ((PAGE_SIZE-1)>>10)) >> (PAGE_SHIFT - 10);
185 d->max_pages = nr_pages; /* this can now be controlled independently */
187 /* Grow the allocation if necessary. */
188 for ( alloc_pfns = d->tot_pages; alloc_pfns < nr_pages; alloc_pfns++ )
189 {
190 if ( unlikely((page = alloc_domheap_page(d)) == NULL) )
191 {
192 domain_relinquish_memory(d);
193 return -ENOMEM;
194 }
196 /* Initialise the machine-to-phys mapping for this page. */
197 set_machinetophys(page_to_pfn(page), alloc_pfns);
198 }
200 return 0;
201 }
204 /* Release resources belonging to task @p. */
205 void domain_destruct(struct domain *d)
206 {
207 struct domain **pd;
208 atomic_t old, new;
210 if ( !test_bit(DF_DYING, &d->flags) )
211 BUG();
213 /* May be already destructed, or get_domain() can race us. */
214 _atomic_set(old, 0);
215 _atomic_set(new, DOMAIN_DESTRUCTED);
216 old = atomic_compareandswap(old, new, &d->refcnt);
217 if ( _atomic_read(old) != 0 )
218 return;
220 /* Delete from task list and task hashtable. */
221 write_lock(&domlist_lock);
222 pd = &domain_list;
223 while ( *pd != d )
224 pd = &(*pd)->next_list;
225 *pd = d->next_list;
226 pd = &domain_hash[DOMAIN_HASH(d->id)];
227 while ( *pd != d )
228 pd = &(*pd)->next_hash;
229 *pd = d->next_hash;
230 write_unlock(&domlist_lock);
232 destroy_event_channels(d);
233 grant_table_destroy(d);
235 free_perdomain_pt(d);
236 free_xenheap_page((unsigned long)d->shared_info);
238 free_domain_struct(d);
239 }
242 /*
243 * final_setup_guestos is used for final setup and launching of domains other
244 * than domain 0. ie. the domains that are being built by the userspace dom0
245 * domain builder.
246 */
247 int final_setup_guestos(struct domain *p, dom0_builddomain_t *builddomain)
248 {
249 int rc = 0;
250 full_execution_context_t *c;
252 if ( (c = xmalloc(sizeof(*c))) == NULL )
253 return -ENOMEM;
255 if ( test_bit(DF_CONSTRUCTED, &p->flags) )
256 {
257 rc = -EINVAL;
258 goto out;
259 }
261 if ( copy_from_user(c, builddomain->ctxt, sizeof(*c)) )
262 {
263 rc = -EFAULT;
264 goto out;
265 }
267 if ( (rc = arch_final_setup_guestos(p,c)) != 0 )
268 goto out;
270 /* Set up the shared info structure. */
271 update_dom_time(p->shared_info);
273 set_bit(DF_CONSTRUCTED, &p->flags);
275 out:
276 if ( c != NULL )
277 xfree(c);
278 return rc;
279 }
281 long vm_assist(struct domain *p, unsigned int cmd, unsigned int type)
282 {
283 if ( type > MAX_VMASST_TYPE )
284 return -EINVAL;
286 switch ( cmd )
287 {
288 case VMASST_CMD_enable:
289 set_bit(type, &p->vm_assist);
290 if (vm_assist_info[type].enable)
291 (*vm_assist_info[type].enable)(p);
292 return 0;
293 case VMASST_CMD_disable:
294 clear_bit(type, &p->vm_assist);
295 if (vm_assist_info[type].disable)
296 (*vm_assist_info[type].disable)(p);
297 return 0;
298 }
300 return -ENOSYS;
301 }