debuggers.hg

view xen/arch/ia64/domain.c @ 4619:5b9e241131fb

bitkeeper revision 1.1329 (42661815u5WPq8d5f4_axi2xWheybA)

Merge firebug.cl.cam.ac.uk:/local/scratch/kaf24/xen-unstable.bk
into firebug.cl.cam.ac.uk:/local/scratch/kaf24/xeno-unstable-ia64.bk
author kaf24@firebug.cl.cam.ac.uk
date Wed Apr 20 08:51:33 2005 +0000 (2005-04-20)
parents 927255a97d41 58efb3448933
children 38a02ee9a9c8 65b28c74cec2
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;
41 #ifdef DOMU_BUILD_STAGING
42 unsigned long domU_staging_size = 32*1024*1024; //FIXME: Should be configurable
43 unsigned long domU_staging_start;
44 unsigned long domU_staging_align = 64*1024;
45 unsigned long *domU_staging_area;
46 #endif
48 // initialized by arch/ia64/setup.c:find_initrd()
49 unsigned long initrd_start = 0, initrd_end = 0;
51 #define IS_XEN_ADDRESS(d,a) ((a >= d->xen_vastart) && (a <= d->xen_vaend))
53 //extern int loadelfimage(char *);
54 extern int readelfimage_base_and_size(char *, unsigned long,
55 unsigned long *, unsigned long *, unsigned long *);
57 unsigned long map_domain_page0(struct domain *);
58 extern unsigned long dom_fw_setup(struct domain *, char *, int);
60 /* this belongs in include/asm, but there doesn't seem to be a suitable place */
61 void free_perdomain_pt(struct domain *d)
62 {
63 dummy();
64 //free_page((unsigned long)d->mm.perdomain_pt);
65 }
67 int hlt_counter;
69 void disable_hlt(void)
70 {
71 hlt_counter++;
72 }
74 void enable_hlt(void)
75 {
76 hlt_counter--;
77 }
79 static void default_idle(void)
80 {
81 if ( hlt_counter == 0 )
82 {
83 local_irq_disable();
84 if ( !softirq_pending(smp_processor_id()) )
85 safe_halt();
86 //else
87 local_irq_enable();
88 }
89 }
91 void continue_cpu_idle_loop(void)
92 {
93 int cpu = smp_processor_id();
94 for ( ; ; )
95 {
96 #ifdef IA64
97 // __IRQ_STAT(cpu, idle_timestamp) = jiffies
98 #else
99 irq_stat[cpu].idle_timestamp = jiffies;
100 #endif
101 while ( !softirq_pending(cpu) )
102 default_idle();
103 do_softirq();
104 }
105 }
107 void startup_cpu_idle_loop(void)
108 {
109 /* Just some sanity to ensure that the scheduler is set up okay. */
110 ASSERT(current->domain == IDLE_DOMAIN_ID);
111 domain_unpause_by_systemcontroller(current->domain);
112 raise_softirq(SCHEDULE_SOFTIRQ);
113 do_softirq();
115 /*
116 * Declares CPU setup done to the boot processor.
117 * Therefore memory barrier to ensure state is visible.
118 */
119 smp_mb();
120 init_idle();
121 #if 0
122 //do we have to ensure the idle task has a shared page so that, for example,
123 //region registers can be loaded from it. Apparently not...
124 idle0_task.shared_info = (void *)alloc_xenheap_page();
125 memset(idle0_task.shared_info, 0, PAGE_SIZE);
126 /* pin mapping */
127 // FIXME: Does this belong here? Or do only at domain switch time?
128 {
129 /* WARNING: following must be inlined to avoid nested fault */
130 unsigned long psr = ia64_clear_ic();
131 ia64_itr(0x2, IA64_TR_SHARED_INFO, SHAREDINFO_ADDR,
132 pte_val(pfn_pte(ia64_tpa(idle0_task.shared_info) >> PAGE_SHIFT, PAGE_KERNEL)),
133 PAGE_SHIFT);
134 ia64_set_psr(psr);
135 ia64_srlz_i();
136 }
137 #endif
139 continue_cpu_idle_loop();
140 }
142 struct exec_domain *arch_alloc_exec_domain_struct(void)
143 {
144 /* Per-vp stack is used here. So we need keep exec_domain
145 * same page as per-vp stack */
146 return alloc_xenheap_pages(KERNEL_STACK_SIZE_ORDER);
147 }
149 void arch_free_exec_domain_struct(struct exec_domain *ed)
150 {
151 free_xenheap_pages(ed, KERNEL_STACK_SIZE_ORDER);
152 }
154 void arch_do_createdomain(struct exec_domain *ed)
155 {
156 struct domain *d = ed->domain;
158 d->shared_info = (void *)alloc_xenheap_page();
159 ed->vcpu_info = (void *)alloc_xenheap_page();
160 if (!ed->vcpu_info) {
161 printk("ERROR/HALTING: CAN'T ALLOC PAGE\n");
162 while (1);
163 }
164 memset(ed->vcpu_info, 0, PAGE_SIZE);
165 /* pin mapping */
166 // FIXME: Does this belong here? Or do only at domain switch time?
167 #if 0
168 // this is now done in ia64_new_rr7
169 {
170 /* WARNING: following must be inlined to avoid nested fault */
171 unsigned long psr = ia64_clear_ic();
172 ia64_itr(0x2, IA64_TR_SHARED_INFO, SHAREDINFO_ADDR,
173 pte_val(pfn_pte(ia64_tpa(d->shared_info) >> PAGE_SHIFT, PAGE_KERNEL)),
174 PAGE_SHIFT);
175 ia64_set_psr(psr);
176 ia64_srlz_i();
177 }
178 #endif
179 d->max_pages = (128*1024*1024)/PAGE_SIZE; // 128MB default // FIXME
180 if ((d->metaphysical_rid = allocate_metaphysical_rid()) == -1UL)
181 BUG();
182 ed->vcpu_info->arch.metaphysical_mode = 1;
183 #define DOMAIN_RID_BITS_DEFAULT 18
184 if (!allocate_rid_range(d,DOMAIN_RID_BITS_DEFAULT)) // FIXME
185 BUG();
186 // the following will eventually need to be negotiated dynamically
187 d->xen_vastart = 0xf000000000000000;
188 d->xen_vaend = 0xf300000000000000;
189 d->shared_info_va = 0xf100000000000000;
190 d->breakimm = 0x1000;
191 // stay on kernel stack because may get interrupts!
192 // ia64_ret_from_clone (which b0 gets in new_thread) switches
193 // to user stack
194 ed->thread.on_ustack = 0;
195 }
197 void arch_do_boot_vcpu(struct exec_domain *p)
198 {
199 return;
200 }
202 int arch_set_info_guest(struct exec_domain *p, full_execution_context_t *c)
203 {
204 dummy();
205 return 1;
206 }
208 int arch_final_setup_guest(struct exec_domain *p, full_execution_context_t *c)
209 {
210 dummy();
211 return 1;
212 }
214 void domain_relinquish_resources(struct domain *d)
215 {
216 dummy();
217 }
219 // heavily leveraged from linux/arch/ia64/kernel/process.c:copy_thread()
220 // and linux/arch/ia64/kernel/process.c:kernel_thread()
221 void new_thread(struct exec_domain *ed,
222 unsigned long start_pc,
223 unsigned long start_stack,
224 unsigned long start_info)
225 {
226 struct domain *d = ed->domain;
227 struct switch_stack *sw;
228 struct pt_regs *regs;
229 unsigned long new_rbs;
230 struct ia64_boot_param *bp;
231 extern char ia64_ret_from_clone;
232 extern char saved_command_line[];
234 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
235 if (d == dom0) start_pc += dom0_start;
236 #endif
237 regs = (struct pt_regs *) ((unsigned long) ed + IA64_STK_OFFSET) - 1;
238 sw = (struct switch_stack *) regs - 1;
239 memset(sw,0,sizeof(struct switch_stack)+sizeof(struct pt_regs));
240 new_rbs = (unsigned long) ed + IA64_RBS_OFFSET;
241 regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR)
242 | IA64_PSR_BITS_TO_SET | IA64_PSR_BN
243 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS);
244 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2
245 regs->cr_iip = start_pc;
246 regs->ar_rsc = 0; /* lazy mode */
247 regs->ar_rnat = 0;
248 regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT;
249 regs->loadrs = 0;
250 //regs->r8 = current->mm->dumpable; /* set "don't zap registers" flag */
251 //regs->r8 = 0x01234567890abcdef; // FIXME: temp marker
252 //regs->r12 = ((unsigned long) regs - 16); /* 16 byte scratch */
253 regs->cr_ifs = 1UL << 63;
254 regs->pr = 0;
255 sw->pr = 0;
256 regs->ar_pfs = 0;
257 sw->caller_unat = 0;
258 sw->ar_pfs = 0;
259 sw->ar_bspstore = new_rbs;
260 //regs->r13 = (unsigned long) ed;
261 printf("new_thread: ed=%p, start_pc=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n",
262 ed,start_pc,regs,sw,new_rbs,IA64_STK_OFFSET,&regs->r8);
263 sw->b0 = (unsigned long) &ia64_ret_from_clone;
264 ed->thread.ksp = (unsigned long) sw - 16;
265 //ed->thread_info->flags = 0;
266 printk("new_thread, about to call init_all_rr\n");
267 init_all_rr(ed);
268 // set up boot parameters (and fake firmware)
269 printk("new_thread, about to call dom_fw_setup\n");
270 regs->r28 = dom_fw_setup(d,saved_command_line,256L); //FIXME
271 printk("new_thread, done with dom_fw_setup\n");
272 // don't forget to set this!
273 ed->vcpu_info->arch.banknum = 1;
274 }
276 static struct page * map_new_domain0_page(unsigned long mpaddr)
277 {
278 if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
279 printk("map_new_domain0_page: bad domain0 mpaddr %p!\n",mpaddr);
280 printk("map_new_domain0_page: start=%p,end=%p!\n",dom0_start,dom0_start+dom0_size);
281 while(1);
282 }
283 return pfn_to_page((mpaddr >> PAGE_SHIFT));
284 }
286 /* allocate new page for domain and map it to the specified metaphysical addr */
287 struct page * map_new_domain_page(struct domain *d, unsigned long mpaddr)
288 {
289 struct mm_struct *mm = d->arch.mm;
290 struct page *p = (struct page *)0;
291 pgd_t *pgd;
292 pud_t *pud;
293 pmd_t *pmd;
294 pte_t *pte;
295 extern unsigned long vhpt_paddr, vhpt_pend;
297 if (!mm->pgd) {
298 printk("map_new_domain_page: domain pgd must exist!\n");
299 return(p);
300 }
301 pgd = pgd_offset(mm,mpaddr);
302 if (pgd_none(*pgd))
303 pgd_populate(mm, pgd, pud_alloc_one(mm,mpaddr));
305 pud = pud_offset(pgd, mpaddr);
306 if (pud_none(*pud))
307 pud_populate(mm, pud, pmd_alloc_one(mm,mpaddr));
309 pmd = pmd_offset(pud, mpaddr);
310 if (pmd_none(*pmd))
311 pmd_populate_kernel(mm, pmd, pte_alloc_one_kernel(mm,mpaddr));
312 // pmd_populate(mm, pmd, pte_alloc_one(mm,mpaddr));
314 pte = pte_offset_map(pmd, mpaddr);
315 if (pte_none(*pte)) {
316 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
317 if (d == dom0) p = map_new_domain0_page(mpaddr);
318 else
319 #endif
320 p = alloc_domheap_page(d);
321 if (unlikely(!p)) {
322 printf("map_new_domain_page: Can't alloc!!!! Aaaargh!\n");
323 return(p);
324 }
325 if (unlikely(page_to_phys(p) > vhpt_paddr && page_to_phys(p) < vhpt_pend)) {
326 printf("map_new_domain_page: reassigned vhpt page %p!!\n",page_to_phys(p));
327 }
328 set_pte(pte, pfn_pte(page_to_phys(p) >> PAGE_SHIFT,
329 __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX)));
330 }
331 else printk("map_new_domain_page: page %p already mapped!\n",p);
332 return p;
333 }
335 void mpafoo(unsigned long mpaddr)
336 {
337 extern unsigned long privop_trace;
338 if (mpaddr == 0x3800)
339 privop_trace = 1;
340 }
342 unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
343 {
344 struct mm_struct *mm = d->arch.mm;
345 pgd_t *pgd = pgd_offset(mm, mpaddr);
346 pud_t *pud;
347 pmd_t *pmd;
348 pte_t *pte;
350 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
351 if (d == dom0) {
352 if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
353 //printk("lookup_domain_mpa: bad dom0 mpaddr %p!\n",mpaddr);
354 //printk("lookup_domain_mpa: start=%p,end=%p!\n",dom0_start,dom0_start+dom0_size);
355 mpafoo(mpaddr);
356 }
357 pte_t pteval = pfn_pte(mpaddr >> PAGE_SHIFT,
358 __pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX));
359 pte = &pteval;
360 return *(unsigned long *)pte;
361 }
362 #endif
363 tryagain:
364 if (pgd_present(*pgd)) {
365 pud = pud_offset(pgd,mpaddr);
366 if (pud_present(*pud)) {
367 pmd = pmd_offset(pud,mpaddr);
368 if (pmd_present(*pmd)) {
369 pte = pte_offset_map(pmd,mpaddr);
370 if (pte_present(*pte)) {
371 //printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte));
372 return *(unsigned long *)pte;
373 }
374 }
375 }
376 }
377 /* if lookup fails and mpaddr is "legal", "create" the page */
378 if ((mpaddr >> PAGE_SHIFT) < d->max_pages) {
379 // FIXME: should zero out pages for security reasons
380 if (map_new_domain_page(d,mpaddr)) goto tryagain;
381 }
382 printk("lookup_domain_mpa: bad mpa %p (> %p\n",
383 mpaddr,d->max_pages<<PAGE_SHIFT);
384 mpafoo(mpaddr);
385 return 0;
386 }
388 // FIXME: ONLY USE FOR DOMAIN PAGE_SIZE == PAGE_SIZE
389 unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
390 {
391 unsigned long pte = lookup_domain_mpa(d,mpaddr);
392 unsigned long imva;
394 pte &= _PAGE_PPN_MASK;
395 imva = __va(pte);
396 imva |= mpaddr & ~PAGE_MASK;
397 return(imva);
398 }
400 // remove following line if not privifying in memory
401 //#define HAVE_PRIVIFY_MEMORY
402 #ifndef HAVE_PRIVIFY_MEMORY
403 #define privify_memory(x,y) do {} while(0)
404 #endif
406 // see arch/x86/xxx/domain_build.c
407 int elf_sanity_check(Elf_Ehdr *ehdr)
408 {
409 return (IS_ELF(*ehdr));
410 }
412 static void copy_memory(void *dst, void *src, int size)
413 {
414 int remain;
416 if (IS_XEN_ADDRESS(dom0,src)) {
417 memcpy(dst,src,size);
418 }
419 else {
420 printf("About to call __copy_from_user(%p,%p,%d)\n",
421 dst,src,size);
422 while (remain = __copy_from_user(dst,src,size)) {
423 printf("incomplete user copy, %d remain of %d\n",
424 remain,size);
425 dst += size - remain; src += size - remain;
426 size -= remain;
427 }
428 }
429 }
431 void loaddomainelfimage(struct domain *d, unsigned long image_start)
432 {
433 char *elfbase = image_start;
434 //Elf_Ehdr *ehdr = (Elf_Ehdr *)image_start;
435 Elf_Ehdr ehdr;
436 Elf_Phdr phdr;
437 int h, filesz, memsz, paddr;
438 unsigned long elfaddr, dom_mpaddr, dom_imva;
439 struct page *p;
440 unsigned long pteval;
442 copy_memory(&ehdr,image_start,sizeof(Elf_Ehdr));
443 for ( h = 0; h < ehdr.e_phnum; h++ ) {
444 copy_memory(&phdr,elfbase + ehdr.e_phoff + (h*ehdr.e_phentsize),
445 sizeof(Elf_Phdr));
446 //if ( !is_loadable_phdr(phdr) )
447 if ((phdr.p_type != PT_LOAD)) {
448 continue;
449 }
450 filesz = phdr.p_filesz; memsz = phdr.p_memsz;
451 elfaddr = elfbase + phdr.p_offset;
452 dom_mpaddr = phdr.p_paddr;
453 //printf("p_offset: %x, size=%x\n",elfaddr,filesz);
454 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
455 if (d == dom0) {
456 if (dom_mpaddr+memsz>dom0_size || dom_mpaddr+filesz>dom0_size) {
457 printf("Domain0 doesn't fit in allocated space!\n");
458 while(1);
459 }
460 dom_imva = __va(dom_mpaddr + dom0_start);
461 copy_memory(dom_imva,elfaddr,filesz);
462 if (memsz > filesz) memset(dom_imva+filesz,0,memsz-filesz);
463 //FIXME: This test for code seems to find a lot more than objdump -x does
464 if (phdr.p_flags & PF_X) privify_memory(dom_imva,filesz);
465 }
466 else
467 #endif
468 while (memsz > 0) {
469 #ifdef DOMU_AUTO_RESTART
470 pteval = lookup_domain_mpa(d,dom_mpaddr);
471 if (pteval) dom_imva = __va(pteval & _PFN_MASK);
472 else { printf("loaddomainelfimage: BAD!\n"); while(1); }
473 #else
474 p = map_new_domain_page(d,dom_mpaddr);
475 if (unlikely(!p)) BUG();
476 dom_imva = __va(page_to_phys(p));
477 #endif
478 if (filesz > 0) {
479 if (filesz >= PAGE_SIZE)
480 copy_memory(dom_imva,elfaddr,PAGE_SIZE);
481 else { // copy partial page, zero the rest of page
482 copy_memory(dom_imva,elfaddr,filesz);
483 memset(dom_imva+filesz,0,PAGE_SIZE-filesz);
484 }
485 //FIXME: This test for code seems to find a lot more than objdump -x does
486 if (phdr.p_flags & PF_X)
487 privify_memory(dom_imva,PAGE_SIZE);
488 }
489 else if (memsz > 0) // always zero out entire page
490 memset(dom_imva,0,PAGE_SIZE);
491 memsz -= PAGE_SIZE; filesz -= PAGE_SIZE;
492 elfaddr += PAGE_SIZE; dom_mpaddr += PAGE_SIZE;
493 }
494 }
495 }
497 int
498 parsedomainelfimage(char *elfbase, unsigned long elfsize, unsigned long *entry)
499 {
500 Elf_Ehdr ehdr;
502 copy_memory(&ehdr,elfbase,sizeof(Elf_Ehdr));
504 if ( !elf_sanity_check(&ehdr) ) {
505 printk("ELF sanity check failed.\n");
506 return -EINVAL;
507 }
509 if ( (ehdr.e_phoff + (ehdr.e_phnum * ehdr.e_phentsize)) > elfsize )
510 {
511 printk("ELF program headers extend beyond end of image.\n");
512 return -EINVAL;
513 }
515 if ( (ehdr.e_shoff + (ehdr.e_shnum * ehdr.e_shentsize)) > elfsize )
516 {
517 printk("ELF section headers extend beyond end of image.\n");
518 return -EINVAL;
519 }
521 #if 0
522 /* Find the section-header strings table. */
523 if ( ehdr.e_shstrndx == SHN_UNDEF )
524 {
525 printk("ELF image has no section-header strings table (shstrtab).\n");
526 return -EINVAL;
527 }
528 #endif
530 *entry = ehdr.e_entry;
531 printf("parsedomainelfimage: entry point = %p\n",*entry);
533 return 0;
534 }
537 void alloc_dom0(void)
538 {
539 #ifdef CONFIG_DOMAIN0_CONTIGUOUS
540 if (platform_is_hp_ski()) {
541 dom0_size = 128*1024*1024; //FIXME: Should be configurable
542 }
543 printf("alloc_dom0: starting (initializing %d MB...)\n",dom0_size/(1024*1024));
545 /* FIXME: The first trunk (say 256M) should always be assigned to
546 * Dom0, since Dom0's physical == machine address for DMA purpose.
547 * Some old version linux, like 2.4, assumes physical memory existing
548 * in 2nd 64M space.
549 */
550 dom0_start = alloc_boot_pages(dom0_size,dom0_align);
551 if (!dom0_start) {
552 printf("construct_dom0: can't allocate contiguous memory size=%p\n",
553 dom0_size);
554 while(1);
555 }
556 printf("alloc_dom0: dom0_start=%p\n",dom0_start);
557 #else
558 dom0_start = 0;
559 #endif
561 }
563 #ifdef DOMU_BUILD_STAGING
564 void alloc_domU_staging(void)
565 {
566 domU_staging_size = 32*1024*1024; //FIXME: Should be configurable
567 printf("alloc_domU_staging: starting (initializing %d MB...)\n",domU_staging_size/(1024*1024));
568 domU_staging_start= alloc_boot_pages(domU_staging_size,domU_staging_align);
569 if (!domU_staging_size) {
570 printf("alloc_domU_staging: can't allocate, spinning...\n");
571 while(1);
572 }
573 else domU_staging_area = (unsigned long *)__va(domU_staging_start);
574 printf("alloc_domU_staging: domU_staging_area=%p\n",domU_staging_area);
576 }
578 unsigned long
579 domU_staging_read_8(unsigned long at)
580 {
581 // no way to return errors so just do it
582 return domU_staging_area[at>>3];
584 }
586 unsigned long
587 domU_staging_write_32(unsigned long at, unsigned long a, unsigned long b,
588 unsigned long c, unsigned long d)
589 {
590 if (at + 32 > domU_staging_size) return -1;
591 if (at & 0x1f) return -1;
592 at >>= 3;
593 domU_staging_area[at++] = a;
594 domU_staging_area[at++] = b;
595 domU_staging_area[at++] = c;
596 domU_staging_area[at] = d;
597 return 0;
599 }
600 #endif
602 int construct_dom0(struct domain *d,
603 unsigned long image_start, unsigned long image_len,
604 unsigned long initrd_start, unsigned long initrd_len,
605 char *cmdline)
606 {
607 char *dst;
608 int i, rc;
609 unsigned long pfn, mfn;
610 unsigned long nr_pt_pages;
611 unsigned long count;
612 //l2_pgentry_t *l2tab, *l2start;
613 //l1_pgentry_t *l1tab = NULL, *l1start = NULL;
614 struct pfn_info *page = NULL;
615 start_info_t *si;
616 struct exec_domain *ed = d->exec_domain[0];
618 struct domain_setup_info dsi;
619 unsigned long p_start;
620 unsigned long pkern_start;
621 unsigned long pkern_entry;
622 unsigned long pkern_end;
624 extern void physdev_init_dom0(struct domain *);
626 //printf("construct_dom0: starting\n");
627 /* Sanity! */
628 #ifndef CLONE_DOMAIN0
629 if ( d != dom0 )
630 BUG();
631 if ( test_bit(DF_CONSTRUCTED, &d->d_flags) )
632 BUG();
633 #endif
635 memset(&dsi, 0, sizeof(struct domain_setup_info));
637 printk("*** LOADING DOMAIN 0 ***\n");
639 d->max_pages = dom0_size/PAGE_SIZE;
640 image_start = __va(ia64_boot_param->initrd_start);
641 image_len = ia64_boot_param->initrd_size;
642 //printk("image_start=%lx, image_len=%lx\n",image_start,image_len);
643 //printk("First word of image: %lx\n",*(unsigned long *)image_start);
645 //printf("construct_dom0: about to call parseelfimage\n");
646 dsi.image_addr = (unsigned long)image_start;
647 dsi.image_len = image_len;
648 rc = parseelfimage(&dsi);
649 if ( rc != 0 )
650 return rc;
652 p_start = dsi.v_start;
653 pkern_start = dsi.v_kernstart;
654 pkern_end = dsi.v_kernend;
655 pkern_entry = dsi.v_kernentry;
657 //printk("p_start=%lx, pkern_start=%lx, pkern_end=%lx, pkern_entry=%lx\n",p_start,pkern_start,pkern_end,pkern_entry);
659 if ( (p_start & (PAGE_SIZE-1)) != 0 )
660 {
661 printk("Initial guest OS must load to a page boundary.\n");
662 return -EINVAL;
663 }
665 printk("METAPHYSICAL MEMORY ARRANGEMENT:\n"
666 " Kernel image: %lx->%lx\n"
667 " Entry address: %lx\n"
668 " Init. ramdisk: (NOT IMPLEMENTED YET)\n",
669 pkern_start, pkern_end, pkern_entry);
671 if ( (pkern_end - pkern_start) > (d->max_pages * PAGE_SIZE) )
672 {
673 printk("Initial guest OS requires too much space\n"
674 "(%luMB is greater than %luMB limit)\n",
675 (pkern_end-pkern_start)>>20, (d->max_pages<<PAGE_SHIFT)>>20);
676 return -ENOMEM;
677 }
679 // if high 3 bits of pkern start are non-zero, error
681 // if pkern end is after end of metaphysical memory, error
682 // (we should be able to deal with this... later)
685 //
687 #if 0
688 strcpy(d->name,"Domain0");
689 #endif
691 // prepare domain0 pagetable (maps METAphysical to physical)
692 // following is roughly mm_init() in linux/kernel/fork.c
693 d->arch.mm = xmalloc(struct mm_struct);
694 if (unlikely(!d->arch.mm)) {
695 printk("Can't allocate mm_struct for domain0\n");
696 return -ENOMEM;
697 }
698 memset(d->arch.mm, 0, sizeof(*d->arch.mm));
699 d->arch.mm->pgd = pgd_alloc(d->arch.mm);
700 if (unlikely(!d->arch.mm->pgd)) {
701 printk("Can't allocate pgd for domain0\n");
702 return -ENOMEM;
703 }
706 /* Mask all upcalls... */
707 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
708 d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
710 /* Copy the OS image. */
711 //(void)loadelfimage(image_start);
712 loaddomainelfimage(d,image_start);
714 /* Copy the initial ramdisk. */
715 //if ( initrd_len != 0 )
716 // memcpy((void *)vinitrd_start, initrd_start, initrd_len);
718 #if 0
719 /* Set up start info area. */
720 //si = (start_info_t *)vstartinfo_start;
721 memset(si, 0, PAGE_SIZE);
722 si->nr_pages = d->tot_pages;
723 si->shared_info = virt_to_phys(d->shared_info);
724 si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
725 //si->pt_base = vpt_start;
726 //si->nr_pt_frames = nr_pt_pages;
727 //si->mfn_list = vphysmap_start;
729 if ( initrd_len != 0 )
730 {
731 //si->mod_start = vinitrd_start;
732 si->mod_len = initrd_len;
733 printk("Initrd len 0x%lx, start at 0x%08lx\n",
734 si->mod_len, si->mod_start);
735 }
737 dst = si->cmd_line;
738 if ( cmdline != NULL )
739 {
740 for ( i = 0; i < 255; i++ )
741 {
742 if ( cmdline[i] == '\0' )
743 break;
744 *dst++ = cmdline[i];
745 }
746 }
747 *dst = '\0';
749 zap_low_mappings(); /* Do the same for the idle page tables. */
750 #endif
752 /* Give up the VGA console if DOM0 is configured to grab it. */
753 #ifdef IA64
754 if (cmdline != NULL)
755 #endif
756 console_endboot(strstr(cmdline, "tty0") != NULL);
758 /* DOM0 gets access to everything. */
759 #ifdef CLONE_DOMAIN0
760 if (d == dom0)
761 #endif
762 physdev_init_dom0(d);
764 set_bit(DF_CONSTRUCTED, &d->d_flags);
766 new_thread(ed, pkern_entry, 0, 0);
767 // FIXME: Hack for keyboard input
768 #ifdef CLONE_DOMAIN0
769 if (d == dom0)
770 #endif
771 serial_input_init();
772 if (d == dom0) {
773 ed->vcpu_info->arch.delivery_mask[0] = -1L;
774 ed->vcpu_info->arch.delivery_mask[1] = -1L;
775 ed->vcpu_info->arch.delivery_mask[2] = -1L;
776 ed->vcpu_info->arch.delivery_mask[3] = -1L;
777 }
778 else __set_bit(0x30,ed->vcpu_info->arch.delivery_mask);
780 return 0;
781 }
783 // FIXME: When dom0 can construct domains, this goes away (or is rewritten)
784 int construct_domU(struct domain *d,
785 unsigned long image_start, unsigned long image_len,
786 unsigned long initrd_start, unsigned long initrd_len,
787 char *cmdline)
788 {
789 int i, rc;
790 struct exec_domain *ed = d->exec_domain[0];
791 unsigned long pkern_entry;
793 #ifndef DOMU_AUTO_RESTART
794 if ( test_bit(DF_CONSTRUCTED, &d->d_flags) ) BUG();
795 #endif
797 printk("*** LOADING DOMAIN %d ***\n",d->id);
799 d->max_pages = dom0_size/PAGE_SIZE; // FIXME: use dom0 size
800 // FIXME: use domain0 command line
801 rc = parsedomainelfimage(image_start, image_len, &pkern_entry);
802 printk("parsedomainelfimage returns %d\n",rc);
803 if ( rc != 0 ) return rc;
805 d->arch.mm = xmalloc(struct mm_struct);
806 if (unlikely(!d->arch.mm)) {
807 printk("Can't allocate mm_struct for domain %d\n",d->id);
808 return -ENOMEM;
809 }
810 memset(d->arch.mm, 0, sizeof(*d->arch.mm));
811 d->arch.mm->pgd = pgd_alloc(d->arch.mm);
812 if (unlikely(!d->arch.mm->pgd)) {
813 printk("Can't allocate pgd for domain %d\n",d->id);
814 return -ENOMEM;
815 }
818 /* Mask all upcalls... */
819 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
820 d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
822 /* Copy the OS image. */
823 printk("calling loaddomainelfimage(%p,%p)\n",d,image_start);
824 loaddomainelfimage(d,image_start);
825 printk("loaddomainelfimage returns\n");
827 set_bit(DF_CONSTRUCTED, &d->d_flags);
829 printk("calling new_thread, entry=%p\n",pkern_entry);
830 #ifdef DOMU_AUTO_RESTART
831 ed->domain->arch.image_start = image_start;
832 ed->domain->arch.image_len = image_len;
833 ed->domain->arch.entry = pkern_entry;
834 #endif
835 new_thread(ed, pkern_entry, 0, 0);
836 printk("new_thread returns\n");
837 __set_bit(0x30,ed->vcpu_info->arch.delivery_mask);
839 return 0;
840 }
842 #ifdef DOMU_AUTO_RESTART
843 void reconstruct_domU(struct exec_domain *ed)
844 {
845 /* re-copy the OS image to reset data values to original */
846 printk("reconstruct_domU: restarting domain %d...\n",
847 ed->domain->id);
848 loaddomainelfimage(ed->domain,ed->domain->arch.image_start);
849 new_thread(ed, ed->domain->arch.entry, 0, 0);
850 }
851 #endif
853 // FIXME: When dom0 can construct domains, this goes away (or is rewritten)
854 int launch_domainU(unsigned long size)
855 {
856 #ifdef CLONE_DOMAIN0
857 static int next = CLONE_DOMAIN0+1;
858 #else
859 static int next = 1;
860 #endif
862 struct domain *d = do_createdomain(next,0);
863 if (!d) {
864 printf("launch_domainU: couldn't create\n");
865 return 1;
866 }
867 else next++;
868 if (construct_domU(d, (unsigned long)domU_staging_area, size,0,0,0)) {
869 printf("launch_domainU: couldn't construct(id=%d,%lx,%lx)\n",
870 d->id,domU_staging_area,size);
871 return 2;
872 }
873 domain_unpause_by_systemcontroller(d);
874 }
876 void machine_restart(char * __unused)
877 {
878 if (platform_is_hp_ski()) dummy();
879 printf("machine_restart called: spinning....\n");
880 while(1);
881 }
883 void machine_halt(void)
884 {
885 if (platform_is_hp_ski()) dummy();
886 printf("machine_halt called: spinning....\n");
887 while(1);
888 }
890 void dummy(void)
891 {
892 if (platform_is_hp_ski()) asm("break 0;;");
893 printf("dummy called: spinning....\n");
894 while(1);
895 }
898 #if 0
899 void switch_to(struct exec_domain *prev, struct exec_domain *next)
900 {
901 struct exec_domain *last;
903 __switch_to(prev,next,last);
904 //set_current(next);
905 }
906 #endif
908 void domain_pend_keyboard_interrupt(int irq)
909 {
910 vcpu_pend_interrupt(dom0->exec_domain[0],irq);
911 }
913 /////////////////////////////////
914 // added 01Apr2005, to accomodate change in xen/sched.h, not clear
915 // yet if this functionality is needed on ia64
916 #if 0
917 static void __synchronise_lazy_execstate(void *unused)
918 {
919 if ( percpu_ctxt[smp_processor_id()].curr_ed != current )
920 {
921 __context_switch();
922 load_LDT(current);
923 clear_segments();
924 }
925 }
926 #endif
928 void synchronise_lazy_execstate(unsigned long cpuset)
929 {
930 //smp_subset_call_function(__synchronise_lazy_execstate, NULL, 1, cpuset);
931 }
932 /////////////////////////////////