debuggers.hg
annotate xen/common/domain.c @ 3650:beb0887c54bc
bitkeeper revision 1.1159.238.1 (4200c8d8KsGlaM3w6o3y4GHhK1jKjg)
A typesafe allocator submitted by Rusty Russel with trivial renames by me.
Signed-off-by: Rusty Russel <rusty@rustcorp.com.au> (authored)
Signed-off-by: ian.pratt@cl.cam.ac.uk
A typesafe allocator submitted by Rusty Russel with trivial renames by me.
Signed-off-by: Rusty Russel <rusty@rustcorp.com.au> (authored)
Signed-off-by: ian.pratt@cl.cam.ac.uk
author | iap10@labyrinth.cl.cam.ac.uk |
---|---|
date | Wed Feb 02 12:34:32 2005 +0000 (2005-02-02) |
parents | ba0bfd97ed0f |
children | 0ef6e8e6e85d |
rev | line source |
---|---|
kaf24@1787 | 1 /****************************************************************************** |
kaf24@1787 | 2 * domain.c |
kaf24@1787 | 3 * |
kaf24@1787 | 4 * Generic domain-handling functions. |
kaf24@1787 | 5 */ |
kaf24@1488 | 6 |
kaf24@1248 | 7 #include <xen/config.h> |
kaf24@1248 | 8 #include <xen/init.h> |
kaf24@1248 | 9 #include <xen/lib.h> |
cl349@2964 | 10 #include <xen/sched.h> |
kaf24@1248 | 11 #include <xen/errno.h> |
kaf24@1248 | 12 #include <xen/sched.h> |
kaf24@1248 | 13 #include <xen/mm.h> |
kaf24@1248 | 14 #include <xen/event.h> |
kaf24@1248 | 15 #include <xen/time.h> |
kaf24@1544 | 16 #include <xen/console.h> |
kaf24@1787 | 17 #include <asm/shadow.h> |
kaf24@2827 | 18 #include <public/dom0_ops.h> |
gm281@1760 | 19 #include <asm/domain_page.h> |
kaf24@919 | 20 |
kaf24@2844 | 21 /* Both these structures are protected by the domlist_lock. */ |
kaf24@3113 | 22 rwlock_t domlist_lock = RW_LOCK_UNLOCKED; |
kaf24@2844 | 23 struct domain *domain_hash[DOMAIN_HASH_SIZE]; |
kaf24@2844 | 24 struct domain *domain_list; |
kaf24@420 | 25 |
kaf24@3376 | 26 struct domain *dom0; |
kaf24@3376 | 27 |
kaf24@2217 | 28 struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) |
iap10@274 | 29 { |
kaf24@1628 | 30 struct domain *d, **pd; |
cl349@2957 | 31 struct exec_domain *ed; |
iap10@274 | 32 |
kaf24@1628 | 33 if ( (d = alloc_domain_struct()) == NULL ) |
kaf24@1161 | 34 return NULL; |
iap10@274 | 35 |
cl349@2957 | 36 ed = d->exec_domain[0]; |
cl349@2957 | 37 |
kaf24@1628 | 38 atomic_set(&d->refcnt, 1); |
cl349@2957 | 39 atomic_set(&ed->pausecnt, 0); |
kaf24@276 | 40 |
cl349@2957 | 41 shadow_lock_init(ed); |
iap10@1414 | 42 |
kaf24@2748 | 43 d->id = dom_id; |
cl349@2957 | 44 ed->processor = cpu; |
kaf24@1628 | 45 d->create_time = NOW(); |
gm281@2007 | 46 |
cl349@2957 | 47 memcpy(&ed->thread, &idle0_exec_domain.thread, sizeof(ed->thread)); |
kaf24@1161 | 48 |
cl349@2982 | 49 spin_lock_init(&d->time_lock); |
cl349@2982 | 50 |
cl349@3036 | 51 spin_lock_init(&d->big_lock); |
kaf24@1161 | 52 |
kaf24@2336 | 53 spin_lock_init(&d->page_alloc_lock); |
kaf24@2336 | 54 INIT_LIST_HEAD(&d->page_list); |
kaf24@2360 | 55 INIT_LIST_HEAD(&d->xenpage_list); |
kaf24@2336 | 56 |
kaf24@2336 | 57 /* Per-domain PCI-device list. */ |
kaf24@2336 | 58 spin_lock_init(&d->pcidev_lock); |
kaf24@2336 | 59 INIT_LIST_HEAD(&d->pcidev_list); |
kaf24@3310 | 60 |
kaf24@3310 | 61 if ( (d->id != IDLE_DOMAIN_ID) && |
kaf24@3310 | 62 ((init_event_channels(d) != 0) || (grant_table_create(d) != 0)) ) |
kaf24@3310 | 63 { |
kaf24@3310 | 64 destroy_event_channels(d); |
kaf24@3310 | 65 free_domain_struct(d); |
kaf24@3310 | 66 return NULL; |
kaf24@3310 | 67 } |
kaf24@3310 | 68 |
cl349@3318 | 69 arch_do_createdomain(ed); |
kaf24@3310 | 70 |
cl349@3318 | 71 sched_add_domain(ed); |
kaf24@2336 | 72 |
kaf24@2748 | 73 if ( d->id != IDLE_DOMAIN_ID ) |
kaf24@1161 | 74 { |
kaf24@2844 | 75 write_lock(&domlist_lock); |
kaf24@2844 | 76 pd = &domain_list; /* NB. domain_list maintained in order of dom_id. */ |
kaf24@2844 | 77 for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_list ) |
kaf24@2748 | 78 if ( (*pd)->id > d->id ) |
kaf24@1161 | 79 break; |
kaf24@1628 | 80 d->next_list = *pd; |
kaf24@1628 | 81 *pd = d; |
kaf24@2844 | 82 d->next_hash = domain_hash[DOMAIN_HASH(dom_id)]; |
kaf24@2844 | 83 domain_hash[DOMAIN_HASH(dom_id)] = d; |
kaf24@2844 | 84 write_unlock(&domlist_lock); |
kaf24@1161 | 85 } |
iap10@274 | 86 |
kaf24@1628 | 87 return d; |
iap10@274 | 88 } |
iap10@274 | 89 |
kaf24@414 | 90 |
kaf24@1543 | 91 struct domain *find_domain_by_id(domid_t dom) |
iap10@274 | 92 { |
kaf24@1628 | 93 struct domain *d; |
iap10@274 | 94 |
kaf24@2844 | 95 read_lock(&domlist_lock); |
kaf24@2844 | 96 d = domain_hash[DOMAIN_HASH(dom)]; |
kaf24@1628 | 97 while ( d != NULL ) |
kaf24@420 | 98 { |
kaf24@2748 | 99 if ( d->id == dom ) |
kaf24@420 | 100 { |
kaf24@1628 | 101 if ( unlikely(!get_domain(d)) ) |
kaf24@1628 | 102 d = NULL; |
kaf24@420 | 103 break; |
iap10@274 | 104 } |
kaf24@1628 | 105 d = d->next_hash; |
kaf24@420 | 106 } |
kaf24@2844 | 107 read_unlock(&domlist_lock); |
iap10@274 | 108 |
kaf24@1628 | 109 return d; |
iap10@274 | 110 } |
iap10@274 | 111 |
iap10@274 | 112 |
kaf24@1628 | 113 /* Return the most recently created domain. */ |
kaf24@1543 | 114 struct domain *find_last_domain(void) |
ach61@1347 | 115 { |
kaf24@1628 | 116 struct domain *d, *dlast; |
ach61@1347 | 117 |
kaf24@2844 | 118 read_lock(&domlist_lock); |
kaf24@2844 | 119 dlast = domain_list; |
kaf24@1628 | 120 d = dlast->next_list; |
kaf24@1628 | 121 while ( d != NULL ) |
ach61@1347 | 122 { |
kaf24@1628 | 123 if ( d->create_time > dlast->create_time ) |
kaf24@1628 | 124 dlast = d; |
kaf24@1628 | 125 d = d->next_list; |
ach61@1347 | 126 } |
kaf24@1628 | 127 if ( !get_domain(dlast) ) |
kaf24@1628 | 128 dlast = NULL; |
kaf24@2844 | 129 read_unlock(&domlist_lock); |
ach61@1347 | 130 |
kaf24@1628 | 131 return dlast; |
ach61@1347 | 132 } |
ach61@1347 | 133 |
ach61@1347 | 134 |
kaf24@1543 | 135 void domain_kill(struct domain *d) |
iap10@274 | 136 { |
cl349@3152 | 137 struct exec_domain *ed; |
cl349@3152 | 138 |
kaf24@1543 | 139 domain_pause(d); |
cl349@2957 | 140 if ( !test_and_set_bit(DF_DYING, &d->d_flags) ) |
iap10@274 | 141 { |
cl349@3152 | 142 for_each_exec_domain(d, ed) |
cl349@3152 | 143 sched_rem_domain(ed); |
kaf24@1580 | 144 domain_relinquish_memory(d); |
kaf24@1543 | 145 put_domain(d); |
kaf24@414 | 146 } |
kaf24@414 | 147 } |
kaf24@414 | 148 |
kaf24@414 | 149 |
kaf24@1543 | 150 void domain_crash(void) |
kaf24@414 | 151 { |
cl349@2957 | 152 struct domain *d = current->domain; |
cl349@2957 | 153 |
cl349@2957 | 154 if ( d->id == 0 ) |
kaf24@2474 | 155 BUG(); |
cl349@2414 | 156 |
cl349@2957 | 157 set_bit(DF_CRASHED, &d->d_flags); |
kaf24@1544 | 158 |
cl349@2957 | 159 send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC); |
kaf24@1485 | 160 |
kaf24@1485 | 161 __enter_scheduler(); |
kaf24@1485 | 162 BUG(); |
kaf24@1485 | 163 } |
kaf24@1485 | 164 |
kaf24@1574 | 165 void domain_shutdown(u8 reason) |
kaf24@1485 | 166 { |
cl349@2957 | 167 struct domain *d = current->domain; |
cl349@2957 | 168 |
cl349@2957 | 169 if ( d->id == 0 ) |
kaf24@1488 | 170 { |
kaf24@1488 | 171 extern void machine_restart(char *); |
iap10@1819 | 172 extern void machine_halt(void); |
iap10@1819 | 173 |
iap10@1819 | 174 if ( reason == 0 ) |
iap10@1819 | 175 { |
kaf24@2788 | 176 printk("Domain 0 halted: halting machine.\n"); |
iap10@1819 | 177 machine_halt(); |
iap10@1819 | 178 } |
iap10@1819 | 179 else |
iap10@1819 | 180 { |
kaf24@2788 | 181 printk("Domain 0 shutdown: rebooting machine.\n"); |
iap10@1819 | 182 machine_restart(0); |
iap10@1819 | 183 } |
kaf24@1488 | 184 } |
kaf24@1488 | 185 |
cl349@2957 | 186 d->shutdown_code = reason; |
cl349@2957 | 187 set_bit(DF_SHUTDOWN, &d->d_flags); |
iap10@1449 | 188 |
cl349@2957 | 189 send_guest_virq(dom0->exec_domain[0], VIRQ_DOM_EXC); |
iap10@1449 | 190 |
kaf24@824 | 191 __enter_scheduler(); |
tlh20@461 | 192 } |
tlh20@461 | 193 |
kaf24@1580 | 194 unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes) |
kaf24@1048 | 195 { |
kaf24@1048 | 196 unsigned int alloc_pfns, nr_pages; |
iap10@1397 | 197 struct pfn_info *page; |
kaf24@1048 | 198 |
iap10@1357 | 199 nr_pages = (kbytes + ((PAGE_SIZE-1)>>10)) >> (PAGE_SHIFT - 10); |
kaf24@1580 | 200 d->max_pages = nr_pages; /* this can now be controlled independently */ |
iap10@274 | 201 |
kaf24@1580 | 202 /* Grow the allocation if necessary. */ |
kaf24@1580 | 203 for ( alloc_pfns = d->tot_pages; alloc_pfns < nr_pages; alloc_pfns++ ) |
kaf24@1048 | 204 { |
kaf24@1979 | 205 if ( unlikely((page = alloc_domheap_page(d)) == NULL) ) |
kaf24@1048 | 206 { |
kaf24@1580 | 207 domain_relinquish_memory(d); |
kaf24@1299 | 208 return -ENOMEM; |
kaf24@1048 | 209 } |
iap10@1397 | 210 |
kaf24@3515 | 211 /* Initialise the machine-to-phys mapping for this page. */ |
kaf24@3515 | 212 set_machinetophys(page_to_pfn(page), alloc_pfns); |
kaf24@1048 | 213 } |
kaf24@1048 | 214 |
iap10@274 | 215 return 0; |
iap10@274 | 216 } |
iap10@274 | 217 |
iap10@274 | 218 |
iap10@274 | 219 /* Release resources belonging to task @p. */ |
kaf24@1580 | 220 void domain_destruct(struct domain *d) |
iap10@274 | 221 { |
kaf24@1580 | 222 struct domain **pd; |
kaf24@2382 | 223 atomic_t old, new; |
kaf24@1543 | 224 |
cl349@2957 | 225 if ( !test_bit(DF_DYING, &d->d_flags) ) |
kaf24@1543 | 226 BUG(); |
kaf24@1543 | 227 |
kaf24@1543 | 228 /* May be already destructed, or get_domain() can race us. */ |
kaf24@2382 | 229 _atomic_set(old, 0); |
kaf24@2382 | 230 _atomic_set(new, DOMAIN_DESTRUCTED); |
kaf24@2382 | 231 old = atomic_compareandswap(old, new, &d->refcnt); |
kaf24@2382 | 232 if ( _atomic_read(old) != 0 ) |
kaf24@1543 | 233 return; |
kaf24@406 | 234 |
kaf24@1543 | 235 /* Delete from task list and task hashtable. */ |
kaf24@2844 | 236 write_lock(&domlist_lock); |
kaf24@2844 | 237 pd = &domain_list; |
kaf24@1580 | 238 while ( *pd != d ) |
kaf24@1580 | 239 pd = &(*pd)->next_list; |
kaf24@1580 | 240 *pd = d->next_list; |
kaf24@2844 | 241 pd = &domain_hash[DOMAIN_HASH(d->id)]; |
kaf24@1580 | 242 while ( *pd != d ) |
kaf24@1580 | 243 pd = &(*pd)->next_hash; |
kaf24@1580 | 244 *pd = d->next_hash; |
kaf24@2844 | 245 write_unlock(&domlist_lock); |
kaf24@1543 | 246 |
kaf24@1580 | 247 destroy_event_channels(d); |
kaf24@2360 | 248 grant_table_destroy(d); |
kaf24@1543 | 249 |
djm@1736 | 250 free_perdomain_pt(d); |
kaf24@1958 | 251 free_xenheap_page((unsigned long)d->shared_info); |
kaf24@865 | 252 |
kaf24@1580 | 253 free_domain_struct(d); |
iap10@274 | 254 } |
iap10@274 | 255 |
iap10@274 | 256 |
kaf24@920 | 257 /* |
kaf24@920 | 258 * final_setup_guestos is used for final setup and launching of domains other |
iap10@274 | 259 * than domain 0. ie. the domains that are being built by the userspace dom0 |
iap10@274 | 260 * domain builder. |
iap10@274 | 261 */ |
kaf24@1543 | 262 int final_setup_guestos(struct domain *p, dom0_builddomain_t *builddomain) |
iap10@274 | 263 { |
djm@1736 | 264 int rc = 0; |
iap10@1373 | 265 full_execution_context_t *c; |
iap10@1373 | 266 |
iap10@3650 | 267 if ( (c = xmalloc(full_execution_context_t)) == NULL ) |
kaf24@1464 | 268 return -ENOMEM; |
iap10@274 | 269 |
cl349@2957 | 270 if ( test_bit(DF_CONSTRUCTED, &p->d_flags) ) |
iap10@1373 | 271 { |
iap10@1373 | 272 rc = -EINVAL; |
kaf24@1464 | 273 goto out; |
iap10@1373 | 274 } |
iap10@1373 | 275 |
iap10@1373 | 276 if ( copy_from_user(c, builddomain->ctxt, sizeof(*c)) ) |
iap10@1373 | 277 { |
iap10@1373 | 278 rc = -EFAULT; |
iap10@1373 | 279 goto out; |
iap10@1373 | 280 } |
kaf24@920 | 281 |
cl349@2957 | 282 if ( (rc = arch_final_setup_guestos(p->exec_domain[0],c)) != 0 ) |
kaf24@2503 | 283 goto out; |
iap10@274 | 284 |
kaf24@920 | 285 /* Set up the shared info structure. */ |
cl349@2960 | 286 update_dom_time(p); |
iap10@274 | 287 |
cl349@2957 | 288 set_bit(DF_CONSTRUCTED, &p->d_flags); |
iap10@1373 | 289 |
kaf24@1464 | 290 out: |
kaf24@1787 | 291 if ( c != NULL ) |
kaf24@1958 | 292 xfree(c); |
iap10@1373 | 293 return rc; |
iap10@274 | 294 } |
cl349@2486 | 295 |
cl349@2964 | 296 /* |
cl349@2964 | 297 * final_setup_guestos is used for final setup and launching of domains other |
cl349@2964 | 298 * than domain 0. ie. the domains that are being built by the userspace dom0 |
cl349@2964 | 299 * domain builder. |
cl349@2964 | 300 */ |
cl349@2964 | 301 long do_boot_vcpu(unsigned long vcpu, full_execution_context_t *ctxt) |
cl349@2964 | 302 { |
cl349@2964 | 303 struct domain *d = current->domain; |
cl349@2964 | 304 struct exec_domain *ed; |
cl349@2964 | 305 int rc = 0; |
cl349@2964 | 306 full_execution_context_t *c; |
cl349@2964 | 307 |
mafetter@3546 | 308 if ( (vcpu >= MAX_VIRT_CPUS) || (d->exec_domain[vcpu] != NULL) ) |
mafetter@3546 | 309 return -EINVAL; |
cl349@2964 | 310 |
cl349@2964 | 311 if ( alloc_exec_domain_struct(d, vcpu) == NULL ) |
cl349@2964 | 312 return -ENOMEM; |
cl349@2964 | 313 |
iap10@3650 | 314 if ( (c = xmalloc(full_execution_context_t)) == NULL ) |
cl349@2964 | 315 { |
cl349@2964 | 316 rc = -ENOMEM; |
cl349@2964 | 317 goto out; |
cl349@2964 | 318 } |
cl349@2964 | 319 |
cl349@2964 | 320 if ( copy_from_user(c, ctxt, sizeof(*c)) ) |
cl349@2964 | 321 { |
cl349@2964 | 322 rc = -EFAULT; |
cl349@2964 | 323 goto out; |
cl349@2964 | 324 } |
cl349@2964 | 325 |
cl349@2964 | 326 ed = d->exec_domain[vcpu]; |
cl349@2964 | 327 |
cl349@2964 | 328 atomic_set(&ed->pausecnt, 0); |
cl349@2964 | 329 shadow_lock_init(ed); |
cl349@2964 | 330 |
cl349@2964 | 331 memcpy(&ed->thread, &idle0_exec_domain.thread, sizeof(ed->thread)); |
cl349@2964 | 332 |
cl349@2964 | 333 /* arch_do_createdomain */ |
cl349@3324 | 334 ed->thread.schedule_tail = d->exec_domain[0]->thread.schedule_tail; |
cl349@3036 | 335 ed->mm.perdomain_ptes = d->mm_perdomain_pt + (ed->eid << PDPT_VCPU_SHIFT); |
cl349@2964 | 336 |
cl349@2964 | 337 sched_add_domain(ed); |
cl349@2964 | 338 |
cl349@3152 | 339 if ( (rc = arch_final_setup_guestos(ed, c)) != 0 ) { |
cl349@3152 | 340 sched_rem_domain(ed); |
cl349@2964 | 341 goto out; |
cl349@3152 | 342 } |
cl349@2964 | 343 |
cl349@2964 | 344 /* Set up the shared info structure. */ |
cl349@2964 | 345 update_dom_time(d); |
cl349@2964 | 346 |
cl349@2964 | 347 /* domain_unpause_by_systemcontroller */ |
cl349@2964 | 348 if ( test_and_clear_bit(EDF_CTRLPAUSE, &ed->ed_flags) ) |
cl349@2964 | 349 domain_wake(ed); |
cl349@2964 | 350 |
cl349@2964 | 351 xfree(c); |
cl349@2964 | 352 return 0; |
cl349@2964 | 353 |
cl349@2964 | 354 out: |
cl349@2964 | 355 if ( c != NULL ) |
cl349@2964 | 356 xfree(c); |
kaf24@3517 | 357 arch_free_exec_domain_struct(d->exec_domain[vcpu]); |
cl349@2964 | 358 d->exec_domain[vcpu] = NULL; |
cl349@2964 | 359 return rc; |
cl349@2964 | 360 } |
cl349@2964 | 361 |
cl349@2486 | 362 long vm_assist(struct domain *p, unsigned int cmd, unsigned int type) |
cl349@2486 | 363 { |
cl349@2486 | 364 if ( type > MAX_VMASST_TYPE ) |
cl349@2486 | 365 return -EINVAL; |
cl349@2486 | 366 |
cl349@2486 | 367 switch ( cmd ) |
cl349@2486 | 368 { |
cl349@2486 | 369 case VMASST_CMD_enable: |
cl349@2486 | 370 set_bit(type, &p->vm_assist); |
cl349@2486 | 371 if (vm_assist_info[type].enable) |
cl349@2486 | 372 (*vm_assist_info[type].enable)(p); |
cl349@2486 | 373 return 0; |
cl349@2486 | 374 case VMASST_CMD_disable: |
cl349@2486 | 375 clear_bit(type, &p->vm_assist); |
cl349@2486 | 376 if (vm_assist_info[type].disable) |
cl349@2486 | 377 (*vm_assist_info[type].disable)(p); |
cl349@2486 | 378 return 0; |
cl349@2486 | 379 } |
cl349@2486 | 380 |
cl349@2486 | 381 return -ENOSYS; |
cl349@2486 | 382 } |