ia64/xen-unstable

view xen/arch/ia64/domain.c @ 4309:3f1da48d663a

bitkeeper revision 1.1236.25.35 (42434291-xqRgr7TV4lWMs8BiZpDpQ)

Merge http://djm@sportsman//home/djm/xeno-unstable-ia64.bk
into djmnc4000.(none):/home/djm/src/xen/xeno-unstable-ia64.bk
author djm@djmnc4000.(none)
date Thu Mar 24 16:30:14 2005 +0000 (2005-03-24)
parents 267e5b0b3880 ef494fea7144
children de1a42be018c
line source
1 /*
2 * Copyright (C) 1995 Linus Torvalds
3 *
4 * Pentium III FXSR, SSE support
5 * Gareth Hughes <gareth@valinux.com>, May 2000
6 */
8 #include <xen/config.h>
9 #include <xen/lib.h>
10 #include <xen/errno.h>
11 #include <xen/sched.h>
12 #include <xen/smp.h>
13 #include <xen/delay.h>
14 #include <xen/softirq.h>
15 #include <xen/mm.h>
16 #include <asm/ptrace.h>
17 #include <asm/system.h>
18 #include <asm/io.h>
19 #include <asm/processor.h>
20 #include <asm/desc.h>
21 //#include <asm/mpspec.h>
22 #include <xen/irq.h>
23 #include <xen/event.h>
24 //#include <xen/shadow.h>
25 #include <xen/console.h>
27 #include <xen/elf.h>
28 //#include <asm/page.h>
29 #include <asm/pgalloc.h>
30 #include <asm/dma.h> /* for MAX_DMA_ADDRESS */
32 #include <asm/asm-offsets.h> /* for IA64_THREAD_INFO_SIZE */
34 #include <asm/vcpu.h> /* for function declarations */
36 #define CONFIG_DOMAIN0_CONTIGUOUS
37 unsigned long dom0_start = -1L;
38 unsigned long dom0_size = 512*1024*1024; //FIXME: Should be configurable
39 //FIXME: alignment should be 256MB, lest Linux use a 256MB page size
40 unsigned long dom0_align = 64*1024*1024;
42 // initialized by arch/ia64/setup.c:find_initrd()
43 unsigned long initrd_start = 0, initrd_end = 0;
45 #define IS_XEN_ADDRESS(d,a) ((a >= d->xen_vastart) && (a <= d->xen_vaend))
47 extern int loadelfimage(char *);
48 extern int readelfimage_base_and_size(char *, unsigned long,
49 unsigned long *, unsigned long *, unsigned long *);
51 unsigned long map_domain_page0(struct domain *);
52 extern unsigned long dom_fw_setup(struct domain *, char *, int);
54 /* this belongs in include/asm, but there doesn't seem to be a suitable place */
55 void free_perdomain_pt(struct domain *d)
56 {
57 dummy();
58 //free_page((unsigned long)d->mm.perdomain_pt);
59 }
61 int hlt_counter;
63 void disable_hlt(void)
64 {
65 hlt_counter++;
66 }
68 void enable_hlt(void)
69 {
70 hlt_counter--;
71 }
73 static void default_idle(void)
74 {
75 if ( hlt_counter == 0 )
76 {
77 local_irq_disable();
78 if ( !softirq_pending(smp_processor_id()) )
79 safe_halt();
80 //else
81 local_irq_enable();
82 }
83 }
85 void continue_cpu_idle_loop(void)
86 {
87 int cpu = smp_processor_id();
88 for ( ; ; )
89 {
90 #ifdef IA64
91 // __IRQ_STAT(cpu, idle_timestamp) = jiffies
92 #else
93 irq_stat[cpu].idle_timestamp = jiffies;
94 #endif
95 while ( !softirq_pending(cpu) )
96 default_idle();
97 do_softirq();
98 }
99 }
101 void startup_cpu_idle_loop(void)
102 {
103 /* Just some sanity to ensure that the scheduler is set up okay. */
104 ASSERT(current->domain == IDLE_DOMAIN_ID);
105 domain_unpause_by_systemcontroller(current->domain);
106 __enter_scheduler();
108 /*
109 * Declares CPU setup done to the boot processor.
110 * Therefore memory barrier to ensure state is visible.
111 */
112 smp_mb();
113 init_idle();
114 #if 0
115 //do we have to ensure the idle task has a shared page so that, for example,
116 //region registers can be loaded from it. Apparently not...
117 idle0_task.shared_info = (void *)alloc_xenheap_page();
118 memset(idle0_task.shared_info, 0, PAGE_SIZE);
119 /* pin mapping */
120 // FIXME: Does this belong here? Or do only at domain switch time?
121 {
122 /* WARNING: following must be inlined to avoid nested fault */
123 unsigned long psr = ia64_clear_ic();
124 ia64_itr(0x2, IA64_TR_SHARED_INFO, SHAREDINFO_ADDR,
125 pte_val(pfn_pte(ia64_tpa(idle0_task.shared_info) >> PAGE_SHIFT, PAGE_KERNEL)),
126 PAGE_SHIFT);
127 ia64_set_psr(psr);
128 ia64_srlz_i();
129 }
130 #endif
132 continue_cpu_idle_loop();
133 }
135 struct domain *arch_alloc_domain_struct(void)
136 {
137 return xmalloc(struct domain);
138 }
140 void arch_free_domain_struct(struct domain *d)
141 {
142 xfree(d);
143 }
145 struct exec_domain *arch_alloc_exec_domain_struct(void)
146 {
147 /* Per-vp stack is used here. So we need keep exec_domain
148 * same page as per-vp stack */
149 return alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER);
150 }
152 void arch_free_exec_domain_struct(struct exec_domain *ed)
153 {
154 free_xenheap_pages(ed, KERNEL_STACK_SIZE_ORDER);
155 }
157 void arch_do_createdomain(struct exec_domain *ed)
158 {
159 struct domain *d = ed->domain;
161 d->shared_info = (void *)alloc_xenheap_page();
162 ed->vcpu_info = (void *)alloc_xenheap_page();
163 if (!ed->vcpu_info) {
164 printk("ERROR/HALTING: CAN'T ALLOC PAGE\n");
165 while (1);
166 }
167 memset(ed->vcpu_info, 0, PAGE_SIZE);
168 /* pin mapping */
169 // FIXME: Does this belong here? Or do only at domain switch time?
170 #if 0
171 // this is now done in ia64_new_rr7
172 {
173 /* WARNING: following must be inlined to avoid nested fault */
174 unsigned long psr = ia64_clear_ic();
175 ia64_itr(0x2, IA64_TR_SHARED_INFO, SHAREDINFO_ADDR,
176 pte_val(pfn_pte(ia64_tpa(d->shared_info) >> PAGE_SHIFT, PAGE_KERNEL)),
177 PAGE_SHIFT);
178 ia64_set_psr(psr);
179 ia64_srlz_i();
180 }
181 #endif
182 d->max_pages = (128*1024*1024)/PAGE_SIZE; // 128MB default // FIXME
183 if ((d->metaphysical_rid = allocate_metaphysical_rid()) == -1UL)
184 BUG();
185 ed->vcpu_info->arch.metaphysical_mode = 1;
186 #define DOMAIN_RID_BITS_DEFAULT 18
187 if (!allocate_rid_range(d,DOMAIN_RID_BITS_DEFAULT)) // FIXME
188 BUG();
189 // the following will eventually need to be negotiated dynamically
190 d->xen_vastart = 0xfffc000000000000;
191 d->xen_vaend = 0xfffe000000000000;
192 d->shared_info_va = 0xfffd000000000000;
193 d->breakimm = 0x1000;
194 // stay on kernel stack because may get interrupts!
195 // ia64_ret_from_clone (which b0 gets in new_thread) switches
196 // to user stack
197 ed->thread.on_ustack = 0;
198 }
200 void arch_do_boot_vcpu(struct exec_domain *p)
201 {
202 return;
203 }
205 int arch_set_info_guest(struct exec_domain *p, full_execution_context_t *c)
206 {
207 dummy();
208 return 1;
209 }
211 int arch_final_setup_guest(struct exec_domain *p, full_execution_context_t *c)
212 {
213 dummy();
214 return 1;
215 }
217 void domain_relinquish_memory(struct domain *d)
218 {
219 dummy();
220 }
222 // heavily leveraged from linux/arch/ia64/kernel/process.c:copy_thread()
223 // and linux/arch/ia64/kernel/process.c:kernel_thread()
224 void new_thread(struct exec_domain *ed,
225 unsigned long start_pc,
226 unsigned long start_stack,
227 unsigned long start_info)
228 {
229 struct domain *d = ed->domain;
230 struct switch_stack *sw;
231 struct pt_regs *regs;
232 unsigned long new_rbs;
233 struct ia64_boot_param *bp;
234 extern char ia64_ret_from_clone;
235 extern char saved_command_line[];
237 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
238 if (d == dom0) start_pc += dom0_start;
239 #endif
240 regs = (struct pt_regs *) ((unsigned long) ed + IA64_STK_OFFSET) - 1;
241 sw = (struct switch_stack *) regs - 1;
242 new_rbs = (unsigned long) ed + IA64_RBS_OFFSET;
243 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
244 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN
245 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS);
246 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2
247 regs->cr_iip = start_pc;
248 regs->ar_rsc = 0xf; /* eager mode, privilege level 1 */
249 regs->ar_rnat = 0;
250 regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT;
251 regs->loadrs = 0;
252 //regs->r8 = current->mm->dumpable; /* set "don't zap registers" flag */
253 //regs->r8 = 0x01234567890abcdef; // FIXME: temp marker
254 //regs->r12 = ((unsigned long) regs - 16); /* 16 byte scratch */
255 regs->cr_ifs = 1UL << 63;
256 regs->pr = 0;
257 sw->pr = 0;
258 regs->ar_pfs = 0;
259 sw->caller_unat = 0;
260 sw->ar_pfs = 0;
261 sw->ar_bspstore = new_rbs;
262 //regs->r13 = (unsigned long) ed;
263 printf("new_thread: ed=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n",
264 ed,regs,sw,new_rbs,IA64_STK_OFFSET,&regs->r8);
265 sw->b0 = (unsigned long) &ia64_ret_from_clone;
266 ed->thread.ksp = (unsigned long) sw - 16;
267 //ed->thread_info->flags = 0;
268 printk("new_thread, about to call init_all_rr\n");
269 init_all_rr(ed);
270 // set up boot parameters (and fake firmware)
271 printk("new_thread, about to call dom_fw_setup\n");
272 regs->r28 = dom_fw_setup(d,saved_command_line,256L); //FIXME
273 printk("new_thread, done with dom_fw_setup\n");
274 // don't forget to set this!
275 ed->vcpu_info->arch.banknum = 1;
276 }
278 static struct page * map_new_domain0_page(unsigned long mpaddr)
279 {
280 if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
281 printk("map_new_domain0_page: bad domain0 mpaddr %p!\n",mpaddr);
282 printk("map_new_domain0_page: start=%p,end=%p!\n",dom0_start,dom0_start+dom0_size);
283 while(1);
284 }
285 return pfn_to_page((mpaddr >> PAGE_SHIFT));
286 }
288 /* allocate new page for domain and map it to the specified metaphysical addr */
289 struct page * map_new_domain_page(struct domain *d, unsigned long mpaddr)
290 {
291 struct mm_struct *mm = d->arch.mm;
292 struct page *p = (struct page *)0;
293 pgd_t *pgd;
294 pmd_t *pmd;
295 pte_t *pte;
296 extern unsigned long vhpt_paddr, vhpt_pend;
298 if (!mm->pgd) {
299 printk("map_new_domain_page: domain pgd must exist!\n");
300 return(p);
301 }
302 pgd = pgd_offset(mm,mpaddr);
303 if (pgd_none(*pgd))
304 pgd_populate(mm, pgd, pmd_alloc_one(mm,mpaddr));
306 pmd = pmd_offset(pgd, mpaddr);
307 if (pmd_none(*pmd))
308 pmd_populate(mm, pmd, pte_alloc_one(mm,mpaddr));
310 pte = pte_offset_map(pmd, mpaddr);
311 if (pte_none(*pte)) {
312 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
313 if (d == dom0) p = map_new_domain0_page(mpaddr);
314 else
315 #endif
316 p = alloc_domheap_page(d);
317 if (unlikely(!p)) {
318 printf("map_new_domain_page: Can't alloc!!!! Aaaargh!\n");
319 return(p);
320 }
321 if (unlikely(page_to_phys(p) > vhpt_paddr && page_to_phys(p) < vhpt_pend)) {
322 printf("map_new_domain_page: reassigned vhpt page %p!!\n",page_to_phys(p));
323 }
324 set_pte(pte, pfn_pte(page_to_phys(p) >> PAGE_SHIFT,
325 __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX)));
326 }
327 else printk("map_new_domain_page: page %p already mapped!\n",p);
328 return p;
329 }
331 void mpafoo(unsigned long mpaddr)
332 {
333 extern unsigned long privop_trace;
334 if (mpaddr == 0x3800)
335 privop_trace = 1;
336 }
338 unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
339 {
340 struct mm_struct *mm = d->arch.mm;
341 pgd_t *pgd = pgd_offset(mm, mpaddr);
342 pmd_t *pmd;
343 pte_t *pte;
345 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
346 if (d == dom0) {
347 if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
348 //printk("lookup_domain_mpa: bad dom0 mpaddr %p!\n",mpaddr);
349 //printk("lookup_domain_mpa: start=%p,end=%p!\n",dom0_start,dom0_start+dom0_size);
350 mpafoo(mpaddr);
351 }
352 pte_t pteval = pfn_pte(mpaddr >> PAGE_SHIFT,
353 __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX));
354 pte = &pteval;
355 return *(unsigned long *)pte;
356 }
357 #endif
358 tryagain:
359 if (pgd_present(*pgd)) {
360 pmd = pmd_offset(pgd,mpaddr);
361 if (pmd_present(*pmd)) {
362 pte = pte_offset_map(pmd,mpaddr);
363 if (pte_present(*pte)) {
364 //printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte));
365 return *(unsigned long *)pte;
366 }
367 }
368 }
369 /* if lookup fails and mpaddr is "legal", "create" the page */
370 if ((mpaddr >> PAGE_SHIFT) < d->max_pages) {
371 // FIXME: should zero out pages for security reasons
372 if (map_new_domain_page(d,mpaddr)) goto tryagain;
373 }
374 printk("lookup_domain_mpa: bad mpa %p (> %p\n",
375 mpaddr,d->max_pages<<PAGE_SHIFT);
376 mpafoo(mpaddr);
377 return 0;
378 }
380 // FIXME: ONLY USE FOR DOMAIN PAGE_SIZE == PAGE_SIZE
381 unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
382 {
383 unsigned long pte = lookup_domain_mpa(d,mpaddr);
384 unsigned long imva;
386 pte &= _PAGE_PPN_MASK;
387 imva = __va(pte);
388 imva |= mpaddr & ~PAGE_MASK;
389 return(imva);
390 }
392 // remove following line if not privifying in memory
393 //#define HAVE_PRIVIFY_MEMORY
394 #ifndef HAVE_PRIVIFY_MEMORY
395 #define privify_memory(x,y) do {} while(0)
396 #endif
398 // see arch/x86/xxx/domain_build.c
399 int elf_sanity_check(Elf_Ehdr *ehdr)
400 {
401 return (IS_ELF(*ehdr));
402 }
404 static void copy_memory(void *dst, void *src, int size)
405 {
406 int remain;
408 if (IS_XEN_ADDRESS(dom0,src)) {
409 memcpy(dst,src,size);
410 }
411 else {
412 printf("About to call __copy_from_user(%p,%p,%d)\n",
413 dst,src,size);
414 while (remain = __copy_from_user(dst,src,size)) {
415 printf("incomplete user copy, %d remain of %d\n",
416 remain,size);
417 dst += size - remain; src += size - remain;
418 size -= remain;
419 }
420 }
421 }
423 void loaddomainelfimage(struct domain *d, unsigned long image_start)
424 {
425 char *elfbase = image_start;
426 //Elf_Ehdr *ehdr = (Elf_Ehdr *)image_start;
427 Elf_Ehdr ehdr;
428 Elf_Phdr phdr;
429 int h, filesz, memsz, paddr;
430 unsigned long elfaddr, dom_mpaddr, dom_imva;
431 struct page *p;
433 copy_memory(&ehdr,image_start,sizeof(Elf_Ehdr));
434 for ( h = 0; h < ehdr.e_phnum; h++ ) {
435 copy_memory(&phdr,elfbase + ehdr.e_phoff + (h*ehdr.e_phentsize),
436 sizeof(Elf_Phdr));
437 //if ( !is_loadable_phdr(phdr) )
438 if ((phdr.p_type != PT_LOAD)) {
439 continue;
440 }
441 filesz = phdr.p_filesz; memsz = phdr.p_memsz;
442 elfaddr = elfbase + phdr.p_offset;
443 dom_mpaddr = phdr.p_paddr;
444 //printf("p_offset: %x, size=%x\n",elfaddr,filesz);
445 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
446 if (d == dom0) {
447 if (dom_mpaddr+memsz>dom0_size || dom_mpaddr+filesz>dom0_size) {
448 printf("Domain0 doesn't fit in allocated space!\n");
449 while(1);
450 }
451 dom_imva = __va(dom_mpaddr + dom0_start);
452 copy_memory(dom_imva,elfaddr,filesz);
453 if (memsz > filesz) memset(dom_imva+filesz,0,memsz-filesz);
454 //FIXME: This test for code seems to find a lot more than objdump -x does
455 if (phdr.p_flags & PF_X) privify_memory(dom_imva,filesz);
456 }
457 else
458 #endif
459 while (memsz > 0) {
460 p = map_new_domain_page(d,dom_mpaddr);
461 if (unlikely(!p)) BUG();
462 dom_imva = __va(page_to_phys(p));
463 if (filesz > 0) {
464 if (filesz >= PAGE_SIZE)
465 copy_memory(dom_imva,elfaddr,PAGE_SIZE);
466 else { // copy partial page, zero the rest of page
467 copy_memory(dom_imva,elfaddr,filesz);
468 memset(dom_imva+filesz,0,PAGE_SIZE-filesz);
469 }
470 //FIXME: This test for code seems to find a lot more than objdump -x does
471 if (phdr.p_flags & PF_X)
472 privify_memory(dom_imva,PAGE_SIZE);
473 }
474 else if (memsz > 0) // always zero out entire page
475 memset(dom_imva,0,PAGE_SIZE);
476 memsz -= PAGE_SIZE; filesz -= PAGE_SIZE;
477 elfaddr += PAGE_SIZE; dom_mpaddr += PAGE_SIZE;
478 }
479 }
480 }
482 int
483 parsedomainelfimage(char *elfbase, unsigned long elfsize, unsigned long *entry)
484 {
485 Elf_Ehdr ehdr;
487 copy_memory(&ehdr,elfbase,sizeof(Elf_Ehdr));
489 if ( !elf_sanity_check(&ehdr) ) {
490 printk("ELF sanity check failed.\n");
491 return -EINVAL;
492 }
494 if ( (ehdr.e_phoff + (ehdr.e_phnum * ehdr.e_phentsize)) > elfsize )
495 {
496 printk("ELF program headers extend beyond end of image.\n");
497 return -EINVAL;
498 }
500 if ( (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) > elfsize )
501 {
502 printk("ELF section headers extend beyond end of image.\n");
503 return -EINVAL;
504 }
506 /* Find the section-header strings table. */
507 if ( ehdr.e_shstrndx == SHN_UNDEF )
508 {
509 printk("ELF image has no section-header strings table (shstrtab).\n");
510 return -EINVAL;
511 }
513 *entry = ehdr.e_entry;
515 return 0;
516 }
519 void alloc_dom0(void)
520 {
521 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
522 if (platform_is_hp_ski()) {
523 dom0_size = 128*1024*1024; //FIXME: Should be configurable
524 }
525 printf("alloc_dom0: starting (initializing %d MB...)\n",dom0_size/(1024*1024));
527 /* FIXME: The first trunk (say 256M) should always be assigned to
528 * Dom0, since Dom0's physical == machine address for DMA purpose.
529 * Some old version linux, like 2.4, assumes physical memory existing
530 * in 2nd 64M space.
531 */
532 dom0_start = alloc_boot_pages(dom0_size,dom0_align);
533 if (!dom0_start) {
534 printf("construct_dom0: can't allocate contiguous memory size=%p\n",
535 dom0_size);
536 while(1);
537 }
538 printf("alloc_dom0: dom0_start=%p\n",dom0_start);
539 #else
540 dom0_start = 0;
541 #endif
543 }
545 int construct_dom0(struct domain *d,
546 unsigned long image_start, unsigned long image_len,
547 unsigned long initrd_start, unsigned long initrd_len,
548 char *cmdline)
549 {
550 char *dst;
551 int i, rc;
552 unsigned long pfn, mfn;
553 unsigned long nr_pt_pages;
554 unsigned long count;
555 //l2_pgentry_t *l2tab, *l2start;
556 //l1_pgentry_t *l1tab = NULL, *l1start = NULL;
557 struct pfn_info *page = NULL;
558 start_info_t *si;
559 struct exec_domain *ed = d->exec_domain[0];
561 struct domain_setup_info dsi;
562 unsigned long p_start;
563 unsigned long pkern_start;
564 unsigned long pkern_entry;
565 unsigned long pkern_end;
567 extern void physdev_init_dom0(struct domain *);
569 //printf("construct_dom0: starting\n");
570 /* Sanity! */
571 #ifndef CLONE_DOMAIN0
572 if ( d != dom0 )
573 BUG();
574 if ( test_bit(DF_CONSTRUCTED, &d->d_flags) )
575 BUG();
576 #endif
578 memset(&dsi, 0, sizeof(struct domain_setup_info));
580 printk("*** LOADING DOMAIN 0 ***\n");
582 d->max_pages = dom0_size/PAGE_SIZE;
583 image_start = __va(ia64_boot_param->initrd_start);
584 image_len = ia64_boot_param->initrd_size;
585 //printk("image_start=%lx, image_len=%lx\n",image_start,image_len);
586 //printk("First word of image: %lx\n",*(unsigned long *)image_start);
588 //printf("construct_dom0: about to call parseelfimage\n");
589 rc = parseelfimage(image_start, image_len, &dsi);
590 if ( rc != 0 )
591 return rc;
593 p_start = dsi.v_start;
594 pkern_start = dsi.v_kernstart;
595 pkern_end = dsi.v_kernend;
596 pkern_entry = dsi.v_kernentry;
598 //printk("p_start=%lx, pkern_start=%lx, pkern_end=%lx, pkern_entry=%lx\n",p_start,pkern_start,pkern_end,pkern_entry);
600 if ( (p_start & (PAGE_SIZE-1)) != 0 )
601 {
602 printk("Initial guest OS must load to a page boundary.\n");
603 return -EINVAL;
604 }
606 printk("METAPHYSICAL MEMORY ARRANGEMENT:\n"
607 " Kernel image: %lx->%lx\n"
608 " Entry address: %lx\n"
609 " Init. ramdisk: (NOT IMPLEMENTED YET)\n",
610 pkern_start, pkern_end, pkern_entry);
612 if ( (pkern_end - pkern_start) > (d->max_pages * PAGE_SIZE) )
613 {
614 printk("Initial guest OS requires too much space\n"
615 "(%luMB is greater than %luMB limit)\n",
616 (pkern_end-pkern_start)>>20, (d->max_pages<<PAGE_SHIFT)>>20);
617 return -ENOMEM;
618 }
620 // if high 3 bits of pkern start are non-zero, error
622 // if pkern end is after end of metaphysical memory, error
623 // (we should be able to deal with this... later)
626 //
628 #if 0
629 strcpy(d->name,"Domain0");
630 #endif
632 // prepare domain0 pagetable (maps METAphysical to physical)
633 // following is roughly mm_init() in linux/kernel/fork.c
634 d->arch.mm = xmalloc(struct mm_struct);
635 if (unlikely(!d->arch.mm)) {
636 printk("Can't allocate mm_struct for domain0\n");
637 return -ENOMEM;
638 }
639 memset(d->arch.mm, 0, sizeof(*d->arch.mm));
640 d->arch.mm->pgd = pgd_alloc(d->arch.mm);
641 if (unlikely(!d->arch.mm->pgd)) {
642 printk("Can't allocate pgd for domain0\n");
643 return -ENOMEM;
644 }
647 /* Mask all upcalls... */
648 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
649 d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
651 /* Copy the OS image. */
652 //(void)loadelfimage(image_start);
653 loaddomainelfimage(d,image_start);
655 /* Copy the initial ramdisk. */
656 //if ( initrd_len != 0 )
657 // memcpy((void *)vinitrd_start, initrd_start, initrd_len);
659 #if 0
660 /* Set up start info area. */
661 //si = (start_info_t *)vstartinfo_start;
662 memset(si, 0, PAGE_SIZE);
663 si->nr_pages = d->tot_pages;
664 si->shared_info = virt_to_phys(d->shared_info);
665 si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
666 //si->pt_base = vpt_start;
667 //si->nr_pt_frames = nr_pt_pages;
668 //si->mfn_list = vphysmap_start;
670 if ( initrd_len != 0 )
671 {
672 //si->mod_start = vinitrd_start;
673 si->mod_len = initrd_len;
674 printk("Initrd len 0x%lx, start at 0x%08lx\n",
675 si->mod_len, si->mod_start);
676 }
678 dst = si->cmd_line;
679 if ( cmdline != NULL )
680 {
681 for ( i = 0; i < 255; i++ )
682 {
683 if ( cmdline[i] == '\0' )
684 break;
685 *dst++ = cmdline[i];
686 }
687 }
688 *dst = '\0';
690 zap_low_mappings(); /* Do the same for the idle page tables. */
691 #endif
693 /* Give up the VGA console if DOM0 is configured to grab it. */
694 #ifdef IA64
695 if (cmdline != NULL)
696 #endif
697 console_endboot(strstr(cmdline, "tty0") != NULL);
699 /* DOM0 gets access to everything. */
700 #ifdef CLONE_DOMAIN0
701 if (d == dom0)
702 #endif
703 physdev_init_dom0(d);
705 set_bit(DF_CONSTRUCTED, &d->d_flags);
707 new_thread(ed, pkern_entry, 0, 0);
708 // FIXME: Hack for keyboard input
709 #ifdef CLONE_DOMAIN0
710 if (d == dom0)
711 #endif
712 serial_input_init();
713 if (d == dom0) {
714 ed->vcpu_info->arch.delivery_mask[0] = -1L;
715 ed->vcpu_info->arch.delivery_mask[1] = -1L;
716 ed->vcpu_info->arch.delivery_mask[2] = -1L;
717 ed->vcpu_info->arch.delivery_mask[3] = -1L;
718 }
719 else __set_bit(0x30,ed->vcpu_info->arch.delivery_mask);
721 return 0;
722 }
724 // FIXME: When dom0 can construct domains, this goes away (or is rewritten)
725 int construct_domN(struct domain *d,
726 unsigned long image_start, unsigned long image_len,
727 unsigned long initrd_start, unsigned long initrd_len,
728 char *cmdline)
729 {
730 int i, rc;
731 struct exec_domain *ed = d->exec_domain[0];
732 unsigned long pkern_entry;
734 if ( test_bit(DF_CONSTRUCTED, &d->d_flags) ) BUG();
736 printk("*** LOADING DOMAIN %d ***\n",d->id);
738 d->max_pages = dom0_size/PAGE_SIZE; // FIXME: use dom0 size
739 // FIXME: use domain0 command line
740 rc = parsedomainelfimage(image_start, image_len, &pkern_entry);
741 printk("parsedomainelfimage returns %d\n",rc);
742 if ( rc != 0 ) return rc;
744 d->arch.mm = xmalloc(struct mm_struct);
745 if (unlikely(!d->arch.mm)) {
746 printk("Can't allocate mm_struct for domain %d\n",d->id);
747 return -ENOMEM;
748 }
749 memset(d->arch.mm, 0, sizeof(*d->arch.mm));
750 d->arch.mm->pgd = pgd_alloc(d->arch.mm);
751 if (unlikely(!d->arch.mm->pgd)) {
752 printk("Can't allocate pgd for domain %d\n",d->id);
753 return -ENOMEM;
754 }
757 /* Mask all upcalls... */
758 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
759 d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
761 /* Copy the OS image. */
762 printk("calling loaddomainelfimage\n");
763 loaddomainelfimage(d,image_start);
764 printk("loaddomainelfimage returns\n");
766 set_bit(DF_CONSTRUCTED, &d->d_flags);
768 printk("calling new_thread\n");
769 new_thread(ed, pkern_entry, 0, 0);
770 printk("new_thread returns\n");
771 __set_bit(0x30,ed->vcpu_info->arch.delivery_mask);
773 return 0;
774 }
776 // FIXME: When dom0 can construct domains, this goes away (or is rewritten)
777 int launch_domainN(unsigned long start, unsigned long len,
778 unsigned long initrd_start, unsigned long initrd_len,
779 char *cmdline)
780 {
781 static int next = 100; // FIXME
783 struct domain *d = do_createdomain(next,0);
784 if (!d) {
785 printf("launch_domainN: couldn't create\n");
786 return 1;
787 }
788 if (construct_domN(d, start, len, 0, 0, 0)) {
789 printf("launch_domainN: couldn't construct(id=%d,%lx,%lx)\n",
790 d->id,start,len);
791 return 2;
792 }
793 domain_unpause_by_systemcontroller(d);
794 }
796 void machine_restart(char * __unused)
797 {
798 if (platform_is_hp_ski()) dummy();
799 printf("machine_restart called: spinning....\n");
800 while(1);
801 }
803 void machine_halt(void)
804 {
805 if (platform_is_hp_ski()) dummy();
806 printf("machine_halt called: spinning....\n");
807 while(1);
808 }
810 void dummy(void)
811 {
812 if (platform_is_hp_ski()) asm("break 0;;");
813 printf("dummy called: spinning....\n");
814 while(1);
815 }
818 #if 0
819 void switch_to(struct exec_domain *prev, struct exec_domain *next)
820 {
821 struct exec_domain *last;
823 __switch_to(prev,next,last);
824 //set_current(next);
825 }
826 #endif
828 void domain_pend_keyboard_interrupt(int irq)
829 {
830 vcpu_pend_interrupt(dom0->exec_domain[0],irq);
831 }