debuggers.hg

view xen/common/domain.c @ 648:cda951fc1bef

bitkeeper revision 1.341 (3f1120a2WW6KGE81TArq_p654xy38Q)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into labyrinth.cl.cam.ac.uk:/auto/anfs/scratch/labyrinth/iap10/xeno-clone/xeno.bk
author iap10@labyrinth.cl.cam.ac.uk
date Sun Jul 13 09:04:34 2003 +0000 (2003-07-13)
parents 6879a4610638 9339f3942f4e
children 3c7d3bff01da
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 unsigned int num_vifs,
466 char *phy_data_start, unsigned long data_len,
467 char *cmdline, unsigned long initrd_len)
468 {
469 struct list_head *list_ent;
470 char *src, *vsrc, *dst, *data_start;
471 int i, dom = p->domain;
472 unsigned long phys_l1tab, phys_l2tab;
473 unsigned long cur_address, alloc_address;
474 unsigned long virt_load_address, virt_stack_address, virt_shinfo_address;
475 start_info_t *virt_startinfo_address;
476 unsigned long count;
477 unsigned long alloc_index;
478 l2_pgentry_t *l2tab, *l2start;
479 l1_pgentry_t *l1tab = NULL, *l1start = NULL;
480 struct pfn_info *page = NULL;
481 net_ring_t *shared_rings;
482 net_vif_t *net_vif;
484 /* Sanity! */
485 if ( p->domain != 0 ) BUG();
486 if ( (p->flags & PF_CONSTRUCTED) ) BUG();
488 /*
489 * This is all a bit grim. We've moved the modules to the "safe" physical
490 * memory region above MAP_DIRECTMAP_ADDRESS (48MB). Later in this
491 * routeine, we're going to copy it down into the region that's actually
492 * been allocated to domain 0. This is highly likely to be overlapping, so
493 * we use a forward copy.
494 *
495 * MAP_DIRECTMAP_ADDRESS should be safe. The worst case is a machine with
496 * 4GB and lots of network/disk cards that allocate loads of buffers.
497 * We'll have to revist this if we ever support PAE (64GB).
498 */
500 data_start = map_domain_mem((unsigned long)phy_data_start);
502 if ( strncmp(data_start, "XenoGues", 8) )
503 {
504 printk("DOM%d: Invalid guest OS image\n", dom);
505 return -1;
506 }
508 virt_load_address = *(unsigned long *)(data_start + 8);
509 if ( (virt_load_address & (PAGE_SIZE-1)) )
510 {
511 printk("DOM%d: Guest OS load address not page-aligned (%08lx)\n",
512 dom, virt_load_address);
513 return -1;
514 }
516 if ( alloc_new_dom_mem(p, params->memory_kb) ) return -ENOMEM;
517 alloc_address = list_entry(p->pg_head.prev, struct pfn_info, list) -
518 frame_table;
519 alloc_address <<= PAGE_SHIFT;
520 alloc_index = p->tot_pages;
522 if ( data_len > (params->memory_kb << 9) )
523 {
524 printk("DOM%d: Guest OS image is too large\n"
525 " (%luMB is greater than %uMB limit for a\n"
526 " %uMB address space)\n",
527 dom, data_len>>20,
528 (params->memory_kb)>>11,
529 (params->memory_kb)>>10);
530 free_all_dom_mem(p);
531 return -1;
532 }
534 printk("DOM%d: Guest OS virtual load address is %08lx\n", dom,
535 virt_load_address);
537 /*
538 * WARNING: The new domain must have its 'processor' field
539 * filled in by now !!
540 */
541 phys_l2tab = alloc_page_from_domain(&alloc_address, &alloc_index);
542 l2start = l2tab = map_domain_mem(phys_l2tab);
543 memcpy(l2tab, idle_pg_table[p->processor], PAGE_SIZE);
544 l2tab[PERDOMAIN_VIRT_START >> L2_PAGETABLE_SHIFT] =
545 mk_l2_pgentry(__pa(p->mm.perdomain_pt) | __PAGE_HYPERVISOR);
546 memset(l2tab, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE*sizeof(l2_pgentry_t));
547 p->mm.pagetable = mk_pagetable(phys_l2tab);
549 /*
550 * NB. The upper limit on this loop does one extra page. This is to make
551 * sure a pte exists when we want to map the shared_info struct.
552 */
554 l2tab += l2_table_offset(virt_load_address);
555 cur_address = list_entry(p->pg_head.next, struct pfn_info, list) -
556 frame_table;
557 cur_address <<= PAGE_SHIFT;
558 for ( count = 0; count < p->tot_pages + 1; count++ )
559 {
560 if ( !((unsigned long)l1tab & (PAGE_SIZE-1)) )
561 {
562 if ( l1tab != NULL ) unmap_domain_mem(l1start);
563 phys_l1tab = alloc_page_from_domain(&alloc_address, &alloc_index);
564 *l2tab++ = mk_l2_pgentry(phys_l1tab|L2_PROT);
565 l1start = l1tab = map_domain_mem(phys_l1tab);
566 clear_page(l1tab);
567 l1tab += l1_table_offset(
568 virt_load_address + (count << PAGE_SHIFT));
569 }
570 *l1tab++ = mk_l1_pgentry(cur_address|L1_PROT);
572 if ( count < p->tot_pages )
573 {
574 page = frame_table + (cur_address >> PAGE_SHIFT);
575 page->flags = dom | PGT_writeable_page | PG_need_flush;
576 page->type_count = page->tot_count = 1;
577 /* Set up the MPT entry. */
578 machine_to_phys_mapping[cur_address >> PAGE_SHIFT] = count;
579 }
581 list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
582 cur_address = list_entry(list_ent, struct pfn_info, list) -
583 frame_table;
584 cur_address <<= PAGE_SHIFT;
585 }
586 unmap_domain_mem(l1start);
588 /* pages that are part of page tables must be read only */
589 cur_address = list_entry(p->pg_head.next, struct pfn_info, list) -
590 frame_table;
591 cur_address <<= PAGE_SHIFT;
592 for ( count = 0; count < alloc_index; count++ )
593 {
594 list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
595 cur_address = list_entry(list_ent, struct pfn_info, list) -
596 frame_table;
597 cur_address <<= PAGE_SHIFT;
598 }
600 l2tab = l2start + l2_table_offset(virt_load_address +
601 (alloc_index << PAGE_SHIFT));
602 l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
603 l1tab += l1_table_offset(virt_load_address + (alloc_index << PAGE_SHIFT));
604 l2tab++;
605 for ( count = alloc_index; count < p->tot_pages; count++ )
606 {
607 *l1tab++ = mk_l1_pgentry(l1_pgentry_val(*l1tab) & ~_PAGE_RW);
608 if( !((unsigned long)l1tab & (PAGE_SIZE - 1)) )
609 {
610 unmap_domain_mem(l1start);
611 l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
612 l2tab++;
613 }
614 page = frame_table + (cur_address >> PAGE_SHIFT);
615 page->flags = dom | PGT_l1_page_table;
616 page->tot_count++;
618 list_ent = frame_table[cur_address >> PAGE_SHIFT].list.next;
619 cur_address = list_entry(list_ent, struct pfn_info, list) -
620 frame_table;
621 cur_address <<= PAGE_SHIFT;
622 }
623 page->type_count |= REFCNT_PIN_BIT;
624 page->tot_count |= REFCNT_PIN_BIT;
625 page->flags = dom | PGT_l2_page_table;
626 unmap_domain_mem(l1start);
628 /* Map in the the shared info structure. */
629 virt_shinfo_address = virt_load_address + (p->tot_pages << PAGE_SHIFT);
630 l2tab = l2start + l2_table_offset(virt_shinfo_address);
631 l1start = l1tab = map_domain_mem(l2_pgentry_to_phys(*l2tab));
632 l1tab += l1_table_offset(virt_shinfo_address);
633 *l1tab = mk_l1_pgentry(__pa(p->shared_info)|L1_PROT);
634 unmap_domain_mem(l1start);
636 /* Set up shared info area. */
637 update_dom_time(p->shared_info);
638 p->shared_info->cpu_freq = cpu_freq;
639 p->shared_info->domain_time = 0;
641 virt_startinfo_address = (start_info_t *)
642 (virt_load_address + ((alloc_index - 1) << PAGE_SHIFT));
643 virt_stack_address = (unsigned long)virt_startinfo_address;
645 unmap_domain_mem(l2start);
647 /* Install the new page tables. */
648 __cli();
649 __write_cr3_counted(pagetable_val(p->mm.pagetable));
651 /* Copy the guest OS image. */
652 src = (char *)(phy_data_start + 12);
653 vsrc = (char *)(data_start + 12); /* data_start invalid after first page*/
654 dst = (char *)virt_load_address;
655 while ( src < (phy_data_start+data_len) )
656 {
657 *dst++ = *vsrc++;
658 src++;
659 if ( (((unsigned long)src) & (PAGE_SIZE-1)) == 0 )
660 {
661 unmap_domain_mem( vsrc-1 );
662 vsrc = map_domain_mem( (unsigned long)src );
663 }
664 }
665 unmap_domain_mem( vsrc );
667 /* Set up start info area. */
668 memset(virt_startinfo_address, 0, sizeof(*virt_startinfo_address));
669 virt_startinfo_address->nr_pages = p->tot_pages;
670 virt_startinfo_address->shared_info =
671 (shared_info_t *)virt_shinfo_address;
672 virt_startinfo_address->pt_base = virt_load_address +
673 ((p->tot_pages - 1) << PAGE_SHIFT);
675 virt_startinfo_address->dom_id = p->domain;
676 virt_startinfo_address->flags = IS_PRIV(p) ? SIF_PRIVILEGED : 0;
677 // guest os can have console if:
678 // 1) its privileged (need iopl right now)
679 // 2) its the owner of the console (and therefore will get kbd/mouse events)
680 // 3) xen hasnt tried to touch the console (see console.h)
681 virt_startinfo_address->flags |= (IS_PRIV(p) && CONSOLE_ISOWNER(p) ) ? SIF_CONSOLE : 0;
683 if ( initrd_len )
684 {
685 virt_startinfo_address->mod_start = (unsigned long)dst-initrd_len;
686 virt_startinfo_address->mod_len = initrd_len;
687 printk("Initrd len 0x%lx, start at 0x%08lx\n",
688 virt_startinfo_address->mod_len,
689 virt_startinfo_address->mod_start);
690 }
692 /* Add virtual network interfaces and point to them in startinfo. */
693 while (num_vifs-- > 0) {
694 net_vif = create_net_vif(dom);
695 shared_rings = net_vif->shared_rings;
696 if (!shared_rings) panic("no network ring!\n");
697 }
699 for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
700 {
701 if ( p->net_vif_list[i] == NULL ) continue;
702 virt_startinfo_address->net_rings[i] =
703 virt_to_phys(p->net_vif_list[i]->shared_rings);
704 memcpy(virt_startinfo_address->net_vmac[i],
705 p->net_vif_list[i]->vmac, ETH_ALEN);
706 }
708 /* Add block io interface */
709 virt_startinfo_address->blk_ring = virt_to_phys(p->blk_ring_base);
711 dst = virt_startinfo_address->cmd_line;
712 if ( cmdline != NULL )
713 {
714 for ( i = 0; i < 255; i++ )
715 {
716 if ( cmdline[i] == '\0' ) break;
717 *dst++ = cmdline[i];
718 }
719 }
720 *dst = '\0';
722 /* If this guy's getting the console we'd better let go */
723 if ( virt_startinfo_address->flags & SIF_CONSOLE )
724 {
725 // should reset the console, but seems to work anyhow...
726 opt_console = 0;
727 }
730 /* Reinstate the caller's page tables. */
731 __write_cr3_counted(pagetable_val(current->mm.pagetable));
732 __sti();
734 p->flags |= PF_CONSTRUCTED;
736 new_thread(p,
737 (unsigned long)virt_load_address,
738 (unsigned long)virt_stack_address,
739 (unsigned long)virt_startinfo_address);
741 return 0;
742 }
745 void __init domain_init(void)
746 {
747 printk("Initialising domains\n");
748 }