debuggers.hg

annotate xen/common/domain.c @ 3658:0ef6e8e6e85d

bitkeeper revision 1.1159.212.71 (4200f0afX_JumfbEHQex6TdFENULMQ)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
author iap10@labyrinth.cl.cam.ac.uk
date Wed Feb 02 15:24:31 2005 +0000 (2005-02-02)
parents ba0bfd97ed0f beb0887c54bc
children bbe8541361dd 61899d6ae2eb 523e995bcc57
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 }