diff options
Diffstat (limited to 'xen/arch/ia64/domain.c')
-rw-r--r-- | xen/arch/ia64/domain.c | 226 |
1 files changed, 96 insertions, 130 deletions
diff --git a/xen/arch/ia64/domain.c b/xen/arch/ia64/domain.c index 869396ed06..40a38b2e07 100644 --- a/xen/arch/ia64/domain.c +++ b/xen/arch/ia64/domain.c @@ -76,7 +76,7 @@ extern unsigned long dom_fw_setup(struct domain *, char *, int); /* this belongs in include/asm, but there doesn't seem to be a suitable place */ void free_perdomain_pt(struct domain *d) { - dummy(); + printf("free_perdomain_pt: not implemented\n"); //free_page((unsigned long)d->mm.perdomain_pt); } @@ -166,27 +166,49 @@ void arch_free_vcpu_struct(struct vcpu *v) free_xenheap_pages(v, KERNEL_STACK_SIZE_ORDER); } +static void init_switch_stack(struct vcpu *v) +{ + struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; + struct switch_stack *sw = (struct switch_stack *) regs - 1; + extern void ia64_ret_from_clone; + + memset(sw, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); + sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET; + sw->b0 = (unsigned long) &ia64_ret_from_clone; + sw->ar_fpsr = FPSR_DEFAULT; + v->arch._thread.ksp = (unsigned long) sw - 16; + // stay on kernel stack because may get interrupts! + // ia64_ret_from_clone (which b0 gets in new_thread) switches + // to user stack + v->arch._thread.on_ustack = 0; + memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96); +} + #ifdef CONFIG_VTI void arch_do_createdomain(struct vcpu *v) { struct domain *d = v->domain; struct thread_info *ti = alloc_thread_info(v); - /* If domain is VMX domain, shared info area is created - * by domain and then domain notifies HV by specific hypercall. - * If domain is xenolinux, shared info area is created by - * HV. - * Since we have no idea about whether domain is VMX now, - * (dom0 when parse and domN when build), postpone possible - * allocation. - */ + /* Clear thread_info to clear some important fields, like preempt_count */ + memset(ti, 0, sizeof(struct thread_info)); + init_switch_stack(v); + + /* Shared info area is required to be allocated at domain + * creation, since control panel will write some I/O info + * between front end and back end to that area. However for + * vmx domain, our design is to let domain itself to allcoate + * shared info area, to keep machine page contiguous. So this + * page will be released later when domainN issues request + * after up. + */ + d->shared_info = (void *)alloc_xenheap_page(); /* FIXME: Because full virtual cpu info is placed in this area, * it's unlikely to put it into one shareinfo page. Later * need split vcpu context from vcpu_info and conforms to * normal xen convention. */ - d->shared_info = NULL; v->vcpu_info = (void *)alloc_xenheap_page(); if (!v->vcpu_info) { printk("ERROR/HALTING: CAN'T ALLOC PAGE\n"); @@ -194,9 +216,6 @@ void arch_do_createdomain(struct vcpu *v) } memset(v->vcpu_info, 0, PAGE_SIZE); - /* Clear thread_info to clear some important fields, like preempt_count */ - memset(ti, 0, sizeof(struct thread_info)); - /* Allocate per-domain vTLB and vhpt */ v->arch.vtlb = init_domain_tlb(v); @@ -211,38 +230,25 @@ void arch_do_createdomain(struct vcpu *v) d->xen_vastart = 0xf000000000000000; d->xen_vaend = 0xf300000000000000; d->arch.breakimm = 0x1000; - - // stay on kernel stack because may get interrupts! - // ia64_ret_from_clone (which b0 gets in new_thread) switches - // to user stack - v->arch._thread.on_ustack = 0; } #else // CONFIG_VTI void arch_do_createdomain(struct vcpu *v) { struct domain *d = v->domain; + struct thread_info *ti = alloc_thread_info(v); + + /* Clear thread_info to clear some important fields, like preempt_count */ + memset(ti, 0, sizeof(struct thread_info)); + init_switch_stack(v); d->shared_info = (void *)alloc_xenheap_page(); - v->vcpu_info = (void *)alloc_xenheap_page(); - if (!v->vcpu_info) { + if (!d->shared_info) { printk("ERROR/HALTING: CAN'T ALLOC PAGE\n"); while (1); } - memset(v->vcpu_info, 0, PAGE_SIZE); - /* pin mapping */ - // FIXME: Does this belong here? Or do only at domain switch time? -#if 0 - // this is now done in ia64_new_rr7 - { - /* WARNING: following must be inlined to avoid nested fault */ - unsigned long psr = ia64_clear_ic(); - ia64_itr(0x2, IA64_TR_SHARED_INFO, SHAREDINFO_ADDR, - pte_val(pfn_pte(ia64_tpa(d->shared_info) >> PAGE_SHIFT, PAGE_KERNEL)), - PAGE_SHIFT); - ia64_set_psr(psr); - ia64_srlz_i(); - } -#endif + memset(d->shared_info, 0, PAGE_SIZE); + v->vcpu_info = &(d->shared_info->vcpu_data[0]); + d->max_pages = (128*1024*1024)/PAGE_SIZE; // 128MB default // FIXME if ((d->arch.metaphysical_rr0 = allocate_metaphysical_rr0()) == -1UL) BUG(); @@ -258,33 +264,63 @@ void arch_do_createdomain(struct vcpu *v) d->shared_info_va = 0xf100000000000000; d->arch.breakimm = 0x1000; v->arch.breakimm = d->arch.breakimm; - // stay on kernel stack because may get interrupts! - // ia64_ret_from_clone (which b0 gets in new_thread) switches - // to user stack - v->arch._thread.on_ustack = 0; + + d->arch.mm = xmalloc(struct mm_struct); + if (unlikely(!d->arch.mm)) { + printk("Can't allocate mm_struct for domain %d\n",d->domain_id); + return -ENOMEM; + } + memset(d->arch.mm, 0, sizeof(*d->arch.mm)); + d->arch.mm->pgd = pgd_alloc(d->arch.mm); + if (unlikely(!d->arch.mm->pgd)) { + printk("Can't allocate pgd for domain %d\n",d->domain_id); + return -ENOMEM; + } } #endif // CONFIG_VTI -void arch_do_boot_vcpu(struct vcpu *v) +void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c) { - return; + struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; + + printf("arch_getdomaininfo_ctxt\n"); + c->regs = *regs; + c->vcpu = v->vcpu_info->arch; + c->shared = v->domain->shared_info->arch; } int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c) { - dummy(); - return 1; + struct pt_regs *regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; + + printf("arch_set_info_guest\n"); + *regs = c->regs; + regs->cr_ipsr = IA64_PSR_IT|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IC|IA64_PSR_I|IA64_PSR_DFH|IA64_PSR_BN|IA64_PSR_SP|IA64_PSR_DI; + regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; + regs->ar_rsc |= (2 << 2); /* force PL2/3 */ + + v->vcpu_info->arch = c->vcpu; + init_all_rr(v); + + // this should be in userspace + regs->r28 = dom_fw_setup(v->domain,"nomca nosmp xencons=ttyS console=ttyS0",256L); //FIXME + v->vcpu_info->arch.banknum = 1; + v->vcpu_info->arch.metaphysical_mode = 1; + + v->domain->shared_info->arch = c->shared; + return 0; } -int arch_final_setup_guest(struct vcpu *v, struct vcpu_guest_context *c) +void arch_do_boot_vcpu(struct vcpu *v) { - dummy(); - return 1; + printf("arch_do_boot_vcpu: not implemented\n"); + return; } void domain_relinquish_resources(struct domain *d) { - dummy(); + /* FIXME */ + printf("domain_relinquish_resources: not implemented\n"); } #ifdef CONFIG_VTI @@ -294,10 +330,8 @@ void new_thread(struct vcpu *v, unsigned long start_info) { struct domain *d = v->domain; - struct switch_stack *sw; struct xen_regs *regs; struct ia64_boot_param *bp; - extern char ia64_ret_from_clone; extern char saved_command_line[]; //char *dom0_cmdline = "BOOT_IMAGE=scsi0:\EFI\redhat\xenlinux nomca root=/dev/sdb1 ro"; @@ -305,11 +339,8 @@ void new_thread(struct vcpu *v, #ifdef CONFIG_DOMAIN0_CONTIGUOUS if (d == dom0) start_pc += dom0_start; #endif - regs = (struct xen_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; - sw = (struct switch_stack *) regs - 1; - /* Sanity Clear */ - memset(sw, 0, sizeof(struct xen_regs) + sizeof(struct switch_stack)); + regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; if (VMX_DOMAIN(v)) { /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */ regs->cr_ipsr = 0x501008826008; /* Need to be expanded as macro */ @@ -320,33 +351,23 @@ void new_thread(struct vcpu *v, regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2 } regs->cr_iip = start_pc; - regs->ar_rsc = 0x0; - regs->cr_ifs = 0x0; - regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT; - sw->ar_bspstore = (unsigned long)v + IA64_RBS_OFFSET; - printf("new_thread: v=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n", - v,regs,sw,sw->ar_bspstore,IA64_STK_OFFSET,®s->r8); - printf("iip:0x%lx,ipsr:0x%lx\n", regs->cr_iip, regs->cr_ipsr); - - sw->b0 = (unsigned long) &ia64_ret_from_clone; - v->arch._thread.ksp = (unsigned long) sw - 16; - printk("new_thread, about to call init_all_rr\n"); + regs->cr_ifs = 0; /* why? - matthewc */ + regs->ar_fpsr = FPSR_DEFAULT; if (VMX_DOMAIN(v)) { vmx_init_all_rr(v); } else init_all_rr(v); - // set up boot parameters (and fake firmware) - printk("new_thread, about to call dom_fw_setup\n"); - VMX_VPD(v,vgr[12]) = dom_fw_setup(d,saved_command_line,256L); //FIXME - printk("new_thread, done with dom_fw_setup\n"); if (VMX_DOMAIN(v)) { + VMX_VPD(v,vgr[12]) = dom_fw_setup(d,saved_command_line,256L); /* Virtual processor context setup */ VMX_VPD(v, vpsr) = IA64_PSR_BN; VPD_CR(v, dcr) = 0; } else { - // don't forget to set this! + regs->r28 = dom_fw_setup(d,saved_command_line,256L); v->vcpu_info->arch.banknum = 1; + v->vcpu_info->arch.metaphysical_mode = 1; + d->shared_info->arch.flags = (d == dom0) ? (SIF_INITDOMAIN|SIF_PRIVILEGED|SIF_BLK_BE_DOMAIN|SIF_NET_BE_DOMAIN|SIF_USB_BE_DOMAIN) : 0; } } #else // CONFIG_VTI @@ -359,54 +380,27 @@ void new_thread(struct vcpu *v, unsigned long start_info) { struct domain *d = v->domain; - struct switch_stack *sw; struct pt_regs *regs; - unsigned long new_rbs; struct ia64_boot_param *bp; - extern char ia64_ret_from_clone; extern char saved_command_line[]; #ifdef CONFIG_DOMAIN0_CONTIGUOUS if (d == dom0) start_pc += dom0_start; #endif + regs = (struct pt_regs *) ((unsigned long) v + IA64_STK_OFFSET) - 1; - sw = (struct switch_stack *) regs - 1; - memset(sw,0,sizeof(struct switch_stack)+sizeof(struct pt_regs)); - new_rbs = (unsigned long) v + IA64_RBS_OFFSET; regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BITS_TO_SET | IA64_PSR_BN & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS); regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2 regs->cr_iip = start_pc; - regs->ar_rsc = 0; /* lazy mode */ - regs->ar_rnat = 0; - regs->ar_fpsr = sw->ar_fpsr = FPSR_DEFAULT; - regs->loadrs = 0; - //regs->r8 = current->mm->dumpable; /* set "don't zap registers" flag */ - //regs->r8 = 0x01234567890abcdef; // FIXME: temp marker - //regs->r12 = ((unsigned long) regs - 16); /* 16 byte scratch */ regs->cr_ifs = 1UL << 63; - regs->pr = 0; - sw->pr = 0; - regs->ar_pfs = 0; - sw->caller_unat = 0; - sw->ar_pfs = 0; - sw->ar_bspstore = new_rbs; - //regs->r13 = (unsigned long) v; -printf("new_thread: v=%p, start_pc=%p, regs=%p, sw=%p, new_rbs=%p, IA64_STK_OFFSET=%p, &r8=%p\n", -v,start_pc,regs,sw,new_rbs,IA64_STK_OFFSET,®s->r8); - sw->b0 = (unsigned long) &ia64_ret_from_clone; - v->arch._thread.ksp = (unsigned long) sw - 16; - //v->thread_info->flags = 0; -printk("new_thread, about to call init_all_rr\n"); + regs->ar_fpsr = FPSR_DEFAULT; init_all_rr(v); - // set up boot parameters (and fake firmware) -printk("new_thread, about to call dom_fw_setup\n"); regs->r28 = dom_fw_setup(d,saved_command_line,256L); //FIXME -printk("new_thread, done with dom_fw_setup\n"); - // don't forget to set this! v->vcpu_info->arch.banknum = 1; - memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96); + v->vcpu_info->arch.metaphysical_mode = 1; + d->shared_info->arch.flags = (d == dom0) ? (SIF_INITDOMAIN|SIF_PRIVILEGED|SIF_BLK_BE_DOMAIN|SIF_NET_BE_DOMAIN|SIF_USB_BE_DOMAIN) : 0; } #endif // CONFIG_VTI @@ -1037,21 +1031,6 @@ int construct_dom0(struct domain *d, strcpy(d->name,"Domain0"); #endif - // prepare domain0 pagetable (maps METAphysical to physical) - // following is roughly mm_init() in linux/kernel/fork.c - d->arch.mm = xmalloc(struct mm_struct); - if (unlikely(!d->arch.mm)) { - printk("Can't allocate mm_struct for domain0\n"); - return -ENOMEM; - } - memset(d->arch.mm, 0, sizeof(*d->arch.mm)); - d->arch.mm->pgd = pgd_alloc(d->arch.mm); - if (unlikely(!d->arch.mm->pgd)) { - printk("Can't allocate pgd for domain0\n"); - return -ENOMEM; - } - - /* Mask all upcalls... */ for ( i = 0; i < MAX_VIRT_CPUS; i++ ) d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; @@ -1146,19 +1125,6 @@ int construct_domU(struct domain *d, printk("parsedomainelfimage returns %d\n",rc); if ( rc != 0 ) return rc; - d->arch.mm = xmalloc(struct mm_struct); - if (unlikely(!d->arch.mm)) { - printk("Can't allocate mm_struct for domain %d\n",d->domain_id); - return -ENOMEM; - } - memset(d->arch.mm, 0, sizeof(*d->arch.mm)); - d->arch.mm->pgd = pgd_alloc(d->arch.mm); - if (unlikely(!d->arch.mm->pgd)) { - printk("Can't allocate pgd for domain %d\n",d->domain_id); - return -ENOMEM; - } - - /* Mask all upcalls... */ for ( i = 0; i < MAX_VIRT_CPUS; i++ ) d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1; @@ -1231,10 +1197,10 @@ void machine_halt(void) while(1); } -void dummy(void) +void dummy_called(char *function) { if (platform_is_hp_ski()) asm("break 0;;"); - printf("dummy called: spinning....\n"); + printf("dummy called in %s: spinning....\n", function); while(1); } |