debuggers.hg

view xen/common/domain.c @ 637:f33864f401d8

bitkeeper revision 1.331.1.1 (3f0d5ce2ty7t1xKoi_XfrqGCd6L9mg)

Clean up segments when the domain dies.
author sos22@labyrinth.cl.cam.ac.uk
date Thu Jul 10 12:32:34 2003 +0000 (2003-07-10)
parents f18ad5c14d58
children 75e23848b238
line source
1 #include <xeno/config.h>
2 #include <xeno/init.h>
3 #include <xeno/lib.h>
4 #include <xeno/errno.h>
5 #include <xeno/sched.h>
6 #include <xeno/mm.h>
7 #include <xeno/skbuff.h>
8 #include <xeno/interrupt.h>
9 #include <xeno/delay.h>
10 #include <xeno/event.h>
11 #include <xeno/time.h>
12 #include <hypervisor-ifs/dom0_ops.h>
13 #include <asm/io.h>
14 #include <asm/domain_page.h>
15 #include <asm/flushtlb.h>
16 #include <asm/msr.h>
17 #include <xeno/blkdev.h>
18 #include <xeno/console.h>
19 #include <hypervisor-ifs/block.h>
20 #include <xeno/physdisk.h>
22 /*
23 * NB. No ring-3 access in initial guestOS pagetables. Note that we allow
24 * ring-3 privileges in the page directories, so that the guestOS may later
25 * decide to share a 4MB region with applications.
26 */
27 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
28 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
30 /* Both these structures are protected by the tasklist_lock. */
31 rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED;
32 struct task_struct *task_hash[TASK_HASH_SIZE];
34 /*
35 * create a new domain
36 */
37 struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu)
38 {
39 int retval, i;
40 struct task_struct *p = NULL;
41 unsigned long flags;
43 retval = -ENOMEM;
44 p = alloc_task_struct();
45 if ( p == NULL ) return NULL;
46 memset(p, 0, sizeof(*p));
48 atomic_set(&p->refcnt, 1);
50 p->domain = dom_id;
51 p->processor = cpu;
53 sprintf(p->name, "Domain-%d", dom_id);
55 spin_lock_init(&p->blk_ring_lock);
56 spin_lock_init(&p->page_lock);
57 spin_lock_init(&p->physdev_lock);
59 p->shared_info = (void *)get_free_page(GFP_KERNEL);
60 memset(p->shared_info, 0, PAGE_SIZE);
61 SHARE_PFN_WITH_DOMAIN(virt_to_page(p->shared_info), dom_id);
63 p->mm.perdomain_pt = (l1_pgentry_t *)get_free_page(GFP_KERNEL);
64 memset(p->mm.perdomain_pt, 0, PAGE_SIZE);
66 init_blkdev_info(p);
68 INIT_LIST_HEAD(&p->physdisk_aces);
70 SET_GDT_ENTRIES(p, DEFAULT_GDT_ENTRIES);
71 SET_GDT_ADDRESS(p, DEFAULT_GDT_ADDRESS);
73 p->addr_limit = USER_DS;
74 p->active_mm = &p->mm;
76 /*
77 * We're basically forcing default RPLs to 1, so that our "what privilege
78 * level are we returning to?" logic works.
79 */
80 p->failsafe_selector = FLAT_RING1_CS;
81 p->event_selector = FLAT_RING1_CS;
82 p->thread.ss1 = FLAT_RING1_DS;
83 for ( i = 0; i < 256; i++ ) p->thread.traps[i].cs = FLAT_RING1_CS;
85 sched_add_domain(p);
87 INIT_LIST_HEAD(&p->pg_head);
88 p->max_pages = p->tot_pages = 0;
89 write_lock_irqsave(&tasklist_lock, flags);
90 SET_LINKS(p);
91 p->next_hash = task_hash[TASK_HASH(dom_id)];
92 task_hash[TASK_HASH(dom_id)] = p;
93 write_unlock_irqrestore(&tasklist_lock, flags);
95 return(p);
96 }
99 struct task_struct *find_domain_by_id(unsigned int dom)
100 {
101 struct task_struct *p;
102 unsigned long flags;
104 read_lock_irqsave(&tasklist_lock, flags);
105 p = task_hash[TASK_HASH(dom)];
106 while ( p != NULL )
107 {
108 if ( p->domain == dom )
109 {
110 get_task_struct(p);
111 break;
112 }
113 p = p->next_hash;
114 }
115 read_unlock_irqrestore(&tasklist_lock, flags);
117 return p;
118 }
121 void kill_domain_with_errmsg(const char *err)
122 {
123 printk("DOM%d FATAL ERROR: %s\n",
124 current->domain, err);
125 kill_domain();
126 }
129 void __kill_domain(struct task_struct *p)
130 {
131 int i;
133 if ( p->domain == 0 )
134 {
135 extern void machine_restart(char *);
136 printk("Domain 0 killed: rebooting machine!\n");
137 machine_restart(0);
138 }
140 printk("Killing domain %d\n", p->domain);
142 sched_rem_domain(p);
144 unlink_blkdev_info(p);
146 for ( i = 0; i < XEN_MAX_SEGMENTS; i++ )
147 xen_segment_delete(p, i);
149 for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
150 unlink_net_vif(p->net_vif_list[i]);
152 if ( p == current )
153 {
154 schedule();
155 BUG(); /* never get here */
156 }
157 else
158 {
159 put_task_struct(p);
160 }
161 }
164 void kill_domain(void)
165 {
166 __kill_domain(current);
167 }
170 long kill_other_domain(unsigned int dom, int force)
171 {
172 struct task_struct *p;
173 unsigned long cpu_mask = 0;
175 p = find_domain_by_id(dom);
176 if ( p == NULL ) return -ESRCH;
178 if ( p->state == TASK_SUSPENDED )
179 {
180 __kill_domain(p);
181 }
182 else if ( force )
183 {
184 cpu_mask = mark_hyp_event(p, _HYP_EVENT_DIE);
185 hyp_event_notify(cpu_mask);
186 }
187 else
188 {
189 cpu_mask = mark_guest_event(p, _EVENT_DIE);
190 guest_event_notify(cpu_mask);
191 }
193 put_task_struct(p);
194 return 0;
195 }
197 void stop_domain(void)
198 {
199 current -> state = TASK_SUSPENDED;
200 clear_bit(_HYP_EVENT_STOP, &(current->hyp_events));
201 schedule ();
202 }
204 long stop_other_domain(unsigned int dom)
205 {
206 unsigned long cpu_mask;
207 struct task_struct *p;
209 p = find_domain_by_id (dom);
210 if ( p == NULL) return -ESRCH;
212 if ( p->state != TASK_SUSPENDED )
213 {
214 cpu_mask = mark_hyp_event(p, _HYP_EVENT_STOP);
215 hyp_event_notify(cpu_mask);
216 }
218 put_task_struct(p);
219 return 0;
220 }
222 unsigned int alloc_new_dom_mem(struct task_struct *p, unsigned int kbytes)
223 {
224 struct list_head *temp;
225 struct pfn_info *pf;
226 unsigned int alloc_pfns;
227 unsigned int req_pages;
228 unsigned long flags;
230 /* how many pages do we need to alloc? */
231 req_pages = kbytes >> (PAGE_SHIFT - 10);
233 spin_lock_irqsave(&free_list_lock, flags);
235 /* is there enough mem to serve the request? */
236 if ( (req_pages + (SLACK_DOMAIN_MEM_KILOBYTES >> (PAGE_SHIFT-10))) >
237 free_pfns )
238 {
239 spin_unlock_irqrestore(&free_list_lock, flags);
240 return -1;
241 }
243 /* allocate pages and build a thread through frame_table */
244 temp = free_list.next;
245 for ( alloc_pfns = 0; alloc_pfns < req_pages; alloc_pfns++ )
246 {
247 pf = list_entry(temp, struct pfn_info, list);
248 pf->flags = p->domain;
249 pf->type_count = pf->tot_count = 0;
250 temp = temp->next;
251 list_del(&pf->list);
252 list_add_tail(&pf->list, &p->pg_head);
253 free_pfns--;
254 ASSERT(free_pfns != 0);
255 }
257 spin_unlock_irqrestore(&free_list_lock, flags);
259 p->tot_pages = req_pages;
261 /* TEMPORARY: max_pages should be explicitly specified. */
262 p->max_pages = p->tot_pages;
264 return 0;
265 }
268 void free_all_dom_mem(struct task_struct *p)
269 {
270 struct list_head *ent;
271 unsigned long flags;
273 spin_lock_irqsave(&free_list_lock, flags);
274 while ( (ent = p->pg_head.next) != &p->pg_head )
275 {
276 struct pfn_info *pf = list_entry(ent, struct pfn_info, list);
277 pf->type_count = pf->tot_count = pf->flags = 0;
278 ASSERT(ent->next->prev == ent);
279 ASSERT(ent->prev->next == ent);
280 list_del(ent);
281 list_add(ent, &free_list);
282 free_pfns++;
283 }
284 spin_unlock_irqrestore(&free_list_lock, flags);
286 p->tot_pages = 0;
287 }
290 /* Release resources belonging to task @p. */
291 void release_task(struct task_struct *p)
292 {
293 struct task_struct **pp;
294 unsigned long flags;
296 ASSERT(p->state == TASK_DYING);
297 ASSERT(!p->has_cpu);
299 printk("Releasing task %d\n", p->domain);
301 write_lock_irqsave(&tasklist_lock, flags);
302 REMOVE_LINKS(p);
303 pp = &task_hash[TASK_HASH(p->domain)];
304 while ( *pp != p ) *pp = (*pp)->next_hash;
305 *pp = p->next_hash;
306 write_unlock_irqrestore(&tasklist_lock, flags);
308 /*
309 * This frees up blkdev rings. Totally safe since blkdev ref counting
310 * actually uses the task_struct refcnt.
311 */
312 destroy_blkdev_info(p);
314 /* Free up the physdisk access control info */
315 destroy_physdisk_aces(p);
317 /* Free all memory associated with this domain. */
318 free_page((unsigned long)p->mm.perdomain_pt);
319 UNSHARE_PFN(virt_to_page(p->shared_info));
320 free_page((unsigned long)p->shared_info);
321 free_all_dom_mem(p);
322 free_pages((unsigned long)p, 1);
323 }
326 /* final_setup_guestos is used for final setup and launching of domains other
327 * than domain 0. ie. the domains that are being built by the userspace dom0
328 * domain builder.
329 *
330 * Initial load map:
331 * start_address:
332 * OS image
333 * ....
334 * stack_start:
335 * start_info:
336 * <one page>
337 * page tables:
338 * <enough pages>
339 * end_address:
340 * shared_info:
341 * <one page>
342 */
344 int final_setup_guestos(struct task_struct * p, dom_meminfo_t * meminfo)
345 {
346 l2_pgentry_t * l2tab;
347 l1_pgentry_t * l1tab;
348 start_info_t * virt_startinfo_addr;
349 unsigned long virt_stack_addr;
350 unsigned long phys_l2tab;
351 net_ring_t *shared_rings;
352 net_vif_t *net_vif;
353 int i;
355 if ( (p->flags & PF_CONSTRUCTED) )
356 return -EINVAL;
358 /* High entries in page table must contain hypervisor
359 * mem mappings - set them up.
360 */
361 phys_l2tab = meminfo->l2_pgt_addr;
362 l2tab = map_domain_mem(phys_l2tab);
363 memcpy(l2tab + DOMAIN_ENTRIES_PER_L2_PAGETABLE,
364 ((l2_pgentry_t *)idle_pg_table[p->processor]) +
365 DOMAIN_ENTRIES_PER_L2_PAGETABLE,
366 (ENTRIES_PER_L2_PAGETABLE - DOMAIN_ENTRIES_PER_L2_PAGETABLE)
367 * sizeof(l2_pgentry_t));
368 l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
369 mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR);
370 p->mm.pagetable = mk_pagetable(phys_l2tab);
371 unmap_domain_mem(l2tab);
373 /* map in the shared info structure */
374 phys_l2tab = pagetable_val(p->mm.pagetable);
375 l2tab = map_domain_mem(phys_l2tab);
376 l2tab += l2_table_offset(meminfo->virt_shinfo_addr);
377 l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
378 l1tab += l1_table_offset(meminfo->virt_shinfo_addr);
379 *l1tab = mk_l1_pgentry(__pa(p->shared_info) | L1_PROT);
380 unmap_domain_mem((void *)((unsigned long)l2tab & PAGE_MASK));
381 unmap_domain_mem((void *)((unsigned long)l1tab & PAGE_MASK));
383 /* set up the shared info structure */
384 update_dom_time(p->shared_info);
385 p->shared_info->cpu_freq = cpu_freq;
386 p->shared_info->domain_time = 0;
388 /* we pass start info struct to guest os as function parameter on stack */
389 virt_startinfo_addr = (start_info_t *)meminfo->virt_startinfo_addr;
390 virt_stack_addr = (unsigned long)virt_startinfo_addr;
392 /* we need to populate start_info struct within the context of the
393 * new domain. thus, temporarely install its pagetables.
394 */
395 __cli();
396 __asm__ __volatile__ (
397 "mov %%eax,%%cr3" : : "a" (pagetable_val(p->mm.pagetable)));
399 memset(virt_startinfo_addr, 0, sizeof(*virt_startinfo_addr));
400 virt_startinfo_addr->nr_pages = p->tot_pages;
401 virt_startinfo_addr->shared_info = (shared_info_t *)meminfo->virt_shinfo_addr;
402 virt_startinfo_addr->pt_base = meminfo->virt_load_addr +
403 ((p->tot_pages - 1) << PAGE_SHIFT);
405 /* module size and length */
407 virt_startinfo_addr->mod_start = meminfo->virt_mod_addr;
408 virt_startinfo_addr->mod_len = meminfo->virt_mod_len;
410 virt_startinfo_addr->dom_id = p->domain;
411 virt_startinfo_addr->flags = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
413 /* Add virtual network interfaces and point to them in startinfo. */
414 while (meminfo->num_vifs-- > 0) {
415 net_vif = create_net_vif(p->domain);
416 shared_rings = net_vif->shared_rings;
417 if (!shared_rings) panic("no network ring!\n");
418 }
420 for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
421 {
422 if ( p->net_vif_list[i] == NULL ) continue;
423 virt_startinfo_addr->net_rings[i] =
424 virt_to_phys(p->net_vif_list[i]->shared_rings);
425 memcpy(virt_startinfo_addr->net_vmac[i],
426 p->net_vif_list[i]->vmac, ETH_ALEN);
427 }
429 /* Add block io interface */
430 virt_startinfo_addr->blk_ring = virt_to_phys(p->blk_ring_base);
432 /* Copy the command line */
433 strcpy(virt_startinfo_addr->cmd_line, meminfo->cmd_line);
435 /* Reinstate the caller's page tables. */
436 __asm__ __volatile__ (
437 "mov %%eax,%%cr3" : : "a" (pagetable_val(current->mm.pagetable)));
438 __sti();
440 p->flags |= PF_CONSTRUCTED;
442 new_thread(p,
443 (unsigned long)meminfo->virt_load_addr,
444 (unsigned long)virt_stack_addr,
445 (unsigned long)virt_startinfo_addr);
447 return 0;
448 }
450 static unsigned long alloc_page_from_domain(unsigned long * cur_addr,
451 unsigned long * index)
452 {
453 unsigned long ret = *cur_addr;
454 struct list_head *ent = frame_table[ret >> PAGE_SHIFT].list.prev;
455 *cur_addr = list_entry(ent, struct pfn_info, list) - frame_table;
456 *cur_addr <<= PAGE_SHIFT;
457 (*index)--;
458 return ret;
459 }
461 /* setup_guestos is used for building dom0 solely. other domains are built in
462 * userspace dom0 and final setup is being done by final_setup_guestos.
463 */
464 int setup_guestos(struct task_struct *p, dom0_newdomain_t *params,
465 char *phy_data_start, unsigned long data_len,
466 char *cmdline, unsigned long initrd_len)
467 {
468 struct list_head *list_ent;
469 char *src, *vsrc, *dst, *data_start;
470 int i, dom = p->domain;
471 unsigned long phys_l1tab, phys_l2tab;
472 unsigned long cur_address, alloc_address;
473 unsigned long virt_load_address, virt_stack_address, virt_shinfo_address;
474 start_info_t *virt_startinfo_address;
475 unsigned long count;
476 unsigned long alloc_index;
477 l2_pgentry_t *l2tab, *l2start;
478 l1_pgentry_t *l1tab = NULL, *l1start = NULL;
479 struct pfn_info *page = NULL;
480 net_ring_t *shared_rings;
481 net_vif_t *net_vif;
483 /* Sanity! */
484 if ( p->domain != 0 ) BUG();
485 if ( (p->flags & PF_CONSTRUCTED) ) BUG();
487 /*
488 * This is all a bit grim. We've moved the modules to the "safe" physical
489 * memory region above MAP_DIRECTMAP_ADDRESS (48MB). Later in this
490 * routeine, we're going to copy it down into the region that's actually
491 * been allocated to domain 0. This is highly likely to be overlapping, so
492 * we use a forward copy.
493 *
494 * MAP_DIRECTMAP_ADDRESS should be safe. The worst case is a machine with
495 * 4GB and lots of network/disk cards that allocate loads of buffers.
496 * We'll have to revist this if we ever support PAE (64GB).
497 */
499 data_start = map_domain_mem((unsigned long)phy_data_start);
501 if ( strncmp(data_start, "XenoGues", 8) )
502 {
503 printk("DOM%d: Invalid guest OS image\n", dom);
504 return -1;
505 }
507 virt_load_address = *(unsigned long *)(data_start + 8);
508 if ( (virt_load_address & (PAGE_SIZE-1)) )
509 {
510 printk("DOM%d: Guest OS load address not page-aligned (%08lx)\n",
511 dom, virt_load_address);
512 return -1;
513 }
515 if ( alloc_new_dom_mem(p, params->memory_kb) ) return -ENOMEM;
516 alloc_address = list_entry(p->pg_head.prev, struct pfn_info, list) -
517 frame_table;
518 alloc_address <<= PAGE_SHIFT;
519 alloc_index = p->tot_pages;
521 if ( data_len > (params->memory_kb << 9) )
522 {
523 printk("DOM%d: Guest OS image is too large\n"
524 " (%luMB is greater than %uMB limit for a\n"
525 " %uMB address space)\n",
526 dom, data_len>>20,
527 (params->memory_kb)>>11,
528 (params->memory_kb)>>10);
529 free_all_dom_mem(p);
530 return -1;
531 }
533 printk("DOM%d: Guest OS virtual load address is %08lx\n", dom,
534 virt_load_address);
536 /*
537 * WARNING: The new domain must have its 'processor' field
538 * filled in by now !!
539 */
540 phys_l2tab = alloc_page_from_domain(&alloc_address, &alloc_index);
541 l2start = l2tab = map_domain_mem(phys_l2tab);
542 memcpy(l2tab, idle_pg_table[p->processor], PAGE_SIZE);
543 l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
544 mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR);
545 memset(l2tab, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE*sizeof(l2_pgentry_t));
546 p->mm.pagetable = mk_pagetable(phys_l2tab);
548 /*
549 * NB. The upper limit on this loop does one extra page. This is to make
550 * sure a pte exists when we want to map the shared_info struct.
551 */
553 l2tab += l2_table_offset(virt_load_address);
554 cur_address = list_entry(p->pg_head.next, struct pfn_info, list) -
555 frame_table;
556 cur_address <<= PAGE_SHIFT;
557 for ( count = 0; count < p->tot_pages + 1; count++ )
558 {
559 if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) )
560 {
561 if ( l1tab != NULL ) unmap_domain_mem(l1start);
562 phys_l1tab = alloc_page_from_domain(&alloc_address, &alloc_index);
563 *l2tab++ = mk_l2_pgentry(phys_l1tab|L2_PROT);
564 l1start = l1tab = map_domain_mem(phys_l1tab);
565 clear_page(l1tab);
566 l1tab += l1_table_offset(
567 virt_load_address + (count << PAGE_SHIFT));
568 }
569 *l1tab++ = mk_l1_pgentry(cur_address|L1_PROT);
571 if ( count < p->tot_pages )
572 {
573 page = frame_table + (cur_address >> PAGE_SHIFT);
574 page->flags = dom | PGT_writeable_page | PG_need_flush;
575 page->type_count = page->tot_count = 1;
576 /* Set up the MPT entry. */
577 machine_to_phys_mapping[cur_address >> PAGE_SHIFT] = count;
578 }
580 list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
581 cur_address = list_entry(list_ent, struct pfn_info, list) -
582 frame_table;
583 cur_address <<= PAGE_SHIFT;
584 }
585 unmap_domain_mem(l1start);
587 /* pages that are part of page tables must be read only */
588 cur_address = list_entry(p->pg_head.next, struct pfn_info, list) -
589 frame_table;
590 cur_address <<= PAGE_SHIFT;
591 for ( count = 0; count < alloc_index; count++ )
592 {
593 list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
594 cur_address = list_entry(list_ent, struct pfn_info, list) -
595 frame_table;
596 cur_address <<= PAGE_SHIFT;
597 }
599 l2tab = l2start + l2_table_offset(virt_load_address +
600 (alloc_index << PAGE_SHIFT));
601 l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
602 l1tab += l1_table_offset(virt_load_address + (alloc_index << PAGE_SHIFT));
603 l2tab++;
604 for ( count = alloc_index; count < p->tot_pages; count++ )
605 {
606 *l1tab++ = mk_l1_pgentry(l1_pgentry_val(*l1tab) & ~_PAGE_RW);
607 if( !((unsigned long)l1tab & (PAGE_SIZE - 1)) )
608 {
609 unmap_domain_mem(l1start);
610 l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
611 l2tab++;
612 }
613 page = frame_table + (cur_address >> PAGE_SHIFT);
614 page->flags = dom | PGT_l1_page_table;
615 page->tot_count++;
617 list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
618 cur_address = list_entry(list_ent, struct pfn_info, list) -
619 frame_table;
620 cur_address <<= PAGE_SHIFT;
621 }
622 page->type_count |= REFCNT_PIN_BIT;
623 page->tot_count |= REFCNT_PIN_BIT;
624 page->flags = dom | PGT_l2_page_table;
625 unmap_domain_mem(l1start);
627 /* Map in the the shared info structure. */
628 virt_shinfo_address = virt_load_address + (p->tot_pages << PAGE_SHIFT);
629 l2tab = l2start + l2_table_offset(virt_shinfo_address);
630 l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
631 l1tab += l1_table_offset(virt_shinfo_address);
632 *l1tab = mk_l1_pgentry(__pa(p->shared_info)|L1_PROT);
633 unmap_domain_mem(l1start);
635 /* Set up shared info area. */
636 update_dom_time(p->shared_info);
637 p->shared_info->cpu_freq = cpu_freq;
638 p->shared_info->domain_time = 0;
640 virt_startinfo_address = (start_info_t *)
641 (virt_load_address + ((alloc_index - 1) << PAGE_SHIFT));
642 virt_stack_address = (unsigned long)virt_startinfo_address;
644 unmap_domain_mem(l2start);
646 /* Install the new page tables. */
647 __cli();
648 __write_cr3_counted(pagetable_val(p->mm.pagetable));
650 /* Copy the guest OS image. */
651 src = (char *)(phy_data_start + 12);
652 vsrc = (char *)(data_start + 12); /* data_start invalid after first page*/
653 dst = (char *)virt_load_address;
654 while ( src < (phy_data_start+data_len) )
655 {
656 *dst++ = *vsrc++;
657 src++;
658 if ( (((unsigned long)src) & (PAGE_SIZE-1)) == 0 )
659 {
660 unmap_domain_mem( vsrc-1 );
661 vsrc = map_domain_mem( (unsigned long)src );
662 }
663 }
664 unmap_domain_mem( vsrc );
666 /* Set up start info area. */
667 memset(virt_startinfo_address, 0, sizeof(*virt_startinfo_address));
668 virt_startinfo_address->nr_pages = p->tot_pages;
669 virt_startinfo_address->shared_info =
670 (shared_info_t *)virt_shinfo_address;
671 virt_startinfo_address->pt_base = virt_load_address +
672 ((p->tot_pages - 1) << PAGE_SHIFT);
674 virt_startinfo_address->dom_id = p->domain;
675 virt_startinfo_address->flags = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
676 // guest os can have console if:
677 // 1) its privileged (need iopl right now)
678 // 2) its the owner of the console (and therefore will get kbd/mouse events)
679 // 3) xen hasnt tried to touch the console (see console.h)
680 virt_startinfo_address->flags |= (IS_PRIV(p) && CONSOLE_ISOWNER(p) && opt_console == 0) ? SIF_CONSOLE : 0;
682 if ( initrd_len )
683 {
684 virt_startinfo_address->mod_start = (unsigned long)dst-initrd_len;
685 virt_startinfo_address->mod_len = initrd_len;
686 printk("Initrd len 0x%lx, start at 0x%08lx\n",
687 virt_startinfo_address->mod_len,
688 virt_startinfo_address->mod_start);
689 }
691 /* Add virtual network interfaces and point to them in startinfo. */
692 while (params->num_vifs-- > 0) {
693 net_vif = create_net_vif(dom);
694 shared_rings = net_vif->shared_rings;
695 if (!shared_rings) panic("no network ring!\n");
696 }
698 for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
699 {
700 if ( p->net_vif_list[i] == NULL ) continue;
701 virt_startinfo_address->net_rings[i] =
702 virt_to_phys(p->net_vif_list[i]->shared_rings);
703 memcpy(virt_startinfo_address->net_vmac[i],
704 p->net_vif_list[i]->vmac, ETH_ALEN);
705 }
707 /* Add block io interface */
708 virt_startinfo_address->blk_ring = virt_to_phys(p->blk_ring_base);
710 dst = virt_startinfo_address->cmd_line;
711 if ( cmdline != NULL )
712 {
713 for ( i = 0; i < 255; i++ )
714 {
715 if ( cmdline[i] == '\0' ) break;
716 *dst++ = cmdline[i];
717 }
718 }
719 *dst = '\0';
721 /* Reinstate the caller's page tables. */
722 __write_cr3_counted(pagetable_val(current->mm.pagetable));
723 __sti();
725 p->flags |= PF_CONSTRUCTED;
727 new_thread(p,
728 (unsigned long)virt_load_address,
729 (unsigned long)virt_stack_address,
730 (unsigned long)virt_startinfo_address);
732 return 0;
733 }
736 void __init domain_init(void)
737 {
738 printk("Initialising domains\n");
739 }