diff -r 45a3c14a5878 xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Wed May 17 07:19:24 2006 +++ b/xen/arch/ia64/xen/dom_fw.c Wed May 17 11:28:14 2006 @@ -17,6 +17,7 @@ #include #include #include +//#include #include #include @@ -113,25 +114,6 @@ /* the following heavily leveraged from linux/arch/ia64/hp/sim/fw-emu.c */ -/* Set IP and GR1 of not yet initialized vcpu. */ -static void -set_os_boot_rendez (struct domain *d, unsigned long pc, unsigned long gr1) -{ - struct vcpu *v; - int i; - - printf ("set_os_boot_rendez: %lx %lx\n", pc, gr1); - for (i = 1; i < MAX_VIRT_CPUS; i++) { - v = d->vcpu[i]; - if (v != NULL - && !test_bit(_VCPUF_initialised, &v->vcpu_flags)) { - struct pt_regs *regs = vcpu_regs (v); - regs->cr_iip = pc; - regs->r1 = gr1; - } - } -} - struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, @@ -195,8 +177,11 @@ second vector is reserved. */ status = -2; } - else - set_os_boot_rendez (current->domain, in2, in3); + else { + struct domain *d = current->domain; + d->arch.boot_rdv_ip = in2; + d->arch.boot_rdv_r1 = in3; + } } else printf("*** CALLED SAL_SET_VECTORS %lu. IGNORED...\n", @@ -951,6 +936,11 @@ dom_fw_hypercall_patch (d, sal_ed->sal_proc, FW_HYPERCALL_SAL_CALL, 1); sal_ed->gp = 0; // will be ignored + /* SAL return point. */ + d->arch.sal_return_addr = FW_HYPERCALL_SAL_RETURN_PADDR + start_mpaddr; + dom_fw_hypercall_patch (d, d->arch.sal_return_addr, + FW_HYPERCALL_SAL_RETURN, 0); + /* Fill an AP wakeup descriptor. */ sal_wakeup->type = SAL_DESC_AP_WAKEUP; sal_wakeup->mechanism = IA64_SAL_AP_EXTERNAL_INT; diff -r 45a3c14a5878 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Wed May 17 07:19:24 2006 +++ b/xen/arch/ia64/xen/domain.c Wed May 17 11:28:14 2006 @@ -69,6 +69,8 @@ unsigned long initrd_start = 0, initrd_end = 0; extern unsigned long running_on_sim; +extern char dom0_command_line[]; + #define IS_XEN_ADDRESS(d,a) ((a >= d->xen_vastart) && (a <= d->xen_vaend)) /* FIXME: where these declarations should be there ? */ @@ -210,8 +212,7 @@ 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 + // ia64_ret_from_clone switches to user stack v->arch._thread.on_ustack = 0; memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96); } @@ -246,6 +247,9 @@ if ((d->arch.mm.pgd = pgd_alloc(&d->arch.mm)) == NULL) goto fail_nomem; + d->shared_info->arch.flags = (d == dom0) ? + (SIF_INITDOMAIN|SIF_PRIVILEGED) : 0; + printf ("arch_domain_create: domain=%p\n", d); return 0; @@ -267,6 +271,7 @@ { struct pt_regs *regs = vcpu_regs (v); struct domain *d = v->domain; + unsigned long cmdline_addr; if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) return 0; @@ -284,6 +289,7 @@ build_physmap_table(d); *regs = c->regs; + cmdline_addr = 0; if (v == d->vcpu[0]) { /* Only for first vcpu. */ d->arch.sys_pgnr = c->sys_pgnr; @@ -292,11 +298,28 @@ d->arch.cmdline = c->cmdline; d->shared_info->arch = c->shared; + if (!VMX_DOMAIN(v)) { + const char *cmdline = d->arch.cmdline; + int len; + + if (*cmdline == 0) { +#define DEFAULT_CMDLINE "nomca nosmp xencons=tty0 console=tty0 root=/dev/hda1" + cmdline = DEFAULT_CMDLINE; + len = sizeof (DEFAULT_CMDLINE); + printf("domU command line defaulted to" + DEFAULT_CMDLINE "\n"); + } + else + len = IA64_COMMAND_LINE_SIZE; + cmdline_addr = dom_fw_setup (d, cmdline, len); + } + /* Cache synchronization seems to be done by the linux kernel during mmap/unmap operation. However be conservative. */ domain_cache_flush (d, 1); } - new_thread(v, regs->cr_iip, 0, 0); + vcpu_init_regs (v); + regs->r28 = cmdline_addr; if ( c->privregs && copy_from_user(v->arch.privregs, c->privregs, sizeof(mapped_regs_t))) { @@ -305,7 +328,6 @@ return -EFAULT; } - v->arch.domain_itm_last = -1L; /* Don't redo final setup */ set_bit(_VCPUF_initialised, &v->vcpu_flags); @@ -492,20 +514,9 @@ relinquish_memory(d, &d->page_list); } -// heavily leveraged from linux/arch/ia64/kernel/process.c:copy_thread() -// and linux/arch/ia64/kernel/process.c:kernel_thread() -void new_thread(struct vcpu *v, - unsigned long start_pc, - unsigned long start_stack, - unsigned long start_info) -{ - struct domain *d = v->domain; +void vcpu_init_regs (struct vcpu *v) +{ struct pt_regs *regs; - extern char dom0_command_line[]; - -#ifdef CONFIG_DOMAIN0_CONTIGUOUS - if (d == dom0 && v->vcpu_id == 0) start_pc += dom0_start; -#endif regs = vcpu_regs (v); if (VMX_DOMAIN(v)) { @@ -518,44 +529,16 @@ | IA64_PSR_RI | IA64_PSR_IS); regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; // domain runs at PL2 } - regs->cr_iip = start_pc; regs->cr_ifs = 1UL << 63; /* or clear? */ regs->ar_fpsr = FPSR_DEFAULT; if (VMX_DOMAIN(v)) { vmx_init_all_rr(v); - if (d == dom0) - regs->r28 = dom_fw_setup(d,dom0_command_line, - COMMAND_LINE_SIZE); /* Virtual processor context setup */ VCPU(v, vpsr) = IA64_PSR_BN; VCPU(v, dcr) = 0; } else { init_all_rr(v); - if (v->vcpu_id == 0) { - /* Build the firmware. */ - if (d == dom0) - regs->r28 = dom_fw_setup(d,dom0_command_line, - COMMAND_LINE_SIZE); - else { - const char *cmdline = d->arch.cmdline; - int len; - - if (*cmdline == 0) { -#define DEFAULT_CMDLINE "nomca nosmp xencons=tty0 console=tty0 root=/dev/hda1" - cmdline = DEFAULT_CMDLINE; - len = sizeof (DEFAULT_CMDLINE); - printf("domU command line defaulted to" - DEFAULT_CMDLINE "\n"); - } - else - len = IA64_COMMAND_LINE_SIZE; - - regs->r28 = dom_fw_setup (d, cmdline, len); - } - d->shared_info->arch.flags = (d == dom0) ? - (SIF_INITDOMAIN|SIF_PRIVILEGED) : 0; - } regs->ar_rsc |= (2 << 2); /* force PL2/3 */ VCPU(v, banknum) = 1; VCPU(v, metaphysical_mode) = 1; @@ -563,6 +546,8 @@ (uint64_t)SHAREDINFO_ADDR + INT_ENABLE_OFFSET(v); VCPU(v, itv) = (1 << 16); /* timer vector masked */ } + + v->arch.domain_itm_last = -1L; } // stolen from share_xen_page_with_guest() in xen/arch/x86/mm.c @@ -1560,6 +1545,7 @@ unsigned long pkern_end; unsigned long pinitrd_start = 0; unsigned long pstart_info; + unsigned long cmdline_addr; struct page_info *start_info_page; #ifdef VALIDATE_VT @@ -1733,7 +1719,16 @@ set_bit(_VCPUF_initialised, &v->vcpu_flags); - new_thread(v, pkern_entry, 0, 0); + cmdline_addr = dom_fw_setup(d, dom0_command_line, COMMAND_LINE_SIZE); + + vcpu_init_regs (v); + +#ifdef CONFIG_DOMAIN0_CONTIGUOUS + pkern_entry += dom0_start; +#endif + vcpu_regs (v)->cr_iip = pkern_entry; + vcpu_regs (v)->r28 = cmdline_addr; + physdev_init_dom0(d); // dom0 doesn't need build_physmap_table() diff -r 45a3c14a5878 xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Wed May 17 07:19:24 2006 +++ b/xen/arch/ia64/xen/hypercall.c Wed May 17 11:28:14 2006 @@ -128,6 +128,7 @@ int cpu = regs->r14; int vector = regs->r15; struct vcpu *targ; + struct domain *d = current->domain; if (0 && vector == 254) printf ("send_ipi from %d to %d vector=%d\n", @@ -136,32 +137,39 @@ if (cpu > MAX_VIRT_CPUS) return; - targ = current->domain->vcpu[cpu]; + targ = d->vcpu[cpu]; if (targ == NULL) return; - if (vector == XEN_SAL_BOOT_RENDEZ_VEC - && !test_bit(_VCPUF_initialised, &targ->vcpu_flags)) { - struct pt_regs *targ_regs = vcpu_regs (targ); - struct vcpu_guest_context c; + if (vector == XEN_SAL_BOOT_RENDEZ_VEC + && (!test_bit(_VCPUF_initialised, &targ->vcpu_flags) + || test_bit(_VCPUF_down, &targ->vcpu_flags))) { + if (!test_bit(_VCPUF_initialised, &targ->vcpu_flags)) { + struct vcpu_guest_context c; - printf ("arch_boot_vcpu: %p %p\n", - (void *)targ_regs->cr_iip, - (void *)targ_regs->r1); - memset (&c, 0, sizeof (c)); - /* Copy regs. */ - c.regs.cr_iip = targ_regs->cr_iip; - c.regs.r1 = targ_regs->r1; - - if (arch_set_info_guest (targ, &c) != 0) { - printf ("arch_boot_vcpu: failure\n"); - return; + memset (&c, 0, sizeof (c)); + +#if 0 + /* Copy from vcpu 0. */ + c.vcpu.evtchn_vector = current->domain->vcpu[0]-> + vcpu_info->arch.evtchn_vector; +#endif + if (arch_set_info_guest (targ, &c) != 0) { + printf ("arch_boot_vcpu: failure\n"); + return; + } } + + vcpu_init_regs (targ); + vcpu_regs (targ)->cr_iip = d->arch.boot_rdv_ip; + vcpu_regs (targ)->r1 = d->arch.boot_rdv_r1; + vcpu_regs (targ)->b0 = d->arch.sal_return_addr; + if (test_and_clear_bit(_VCPUF_down, &targ->vcpu_flags)) { vcpu_wake(targ); - printf ("arch_boot_vcpu: vcpu %d awaken %016lx!\n", - targ->vcpu_id, targ_regs->cr_iip); + printf ("arch_boot_vcpu: vcpu %d awaken\n", + targ->vcpu_id); } else printf ("arch_boot_vcpu: huu, already awaken!"); @@ -245,6 +253,11 @@ regs->r8 = x.r8; regs->r9 = x.r9; regs->r10 = x.r10; regs->r11 = x.r11; break; + case FW_HYPERCALL_SAL_RETURN: + printf ("Sal_return vcpu %d\n", v->vcpu_id); + if ( !test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) + vcpu_sleep_nosync(v); + break; case FW_HYPERCALL_EFI_CALL: efi_ret_value = efi_emulator (regs, &fault); if (fault != IA64_NO_FAULT) return fault; diff -r 45a3c14a5878 xen/arch/ia64/xen/privop.c --- a/xen/arch/ia64/xen/privop.c Wed May 17 07:19:24 2006 +++ b/xen/arch/ia64/xen/privop.c Wed May 17 11:28:14 2006 @@ -166,19 +166,19 @@ IA64FAULT priv_ptr_d(VCPU *vcpu, INST64 inst) { UINT64 vadr = vcpu_get_gr(vcpu,inst.M45.r3); - UINT64 addr_range; - - addr_range = 1 << ((vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2); - return vcpu_ptr_d(vcpu,vadr,addr_range); + UINT64 log_range; + + log_range = (vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2; + return vcpu_ptr_d(vcpu,vadr,log_range); } IA64FAULT priv_ptr_i(VCPU *vcpu, INST64 inst) { UINT64 vadr = vcpu_get_gr(vcpu,inst.M45.r3); - UINT64 addr_range; - - addr_range = 1 << ((vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2); - return vcpu_ptr_i(vcpu,vadr,addr_range); + UINT64 log_range; + + log_range = (vcpu_get_gr(vcpu,inst.M45.r2) & 0xfc) >> 2; + return vcpu_ptr_i(vcpu,vadr,log_range); } IA64FAULT priv_tpa(VCPU *vcpu, INST64 inst) diff -r 45a3c14a5878 xen/arch/ia64/xen/vcpu.c --- a/xen/arch/ia64/xen/vcpu.c Wed May 17 07:19:24 2006 +++ b/xen/arch/ia64/xen/vcpu.c Wed May 17 11:28:14 2006 @@ -1275,6 +1275,12 @@ int warn_region0_address = 0; // FIXME later: tie to a boot parameter? +/* Return TRUE iff [b1,e1] and [b2,e2] partially or fully overlaps. */ +static inline int range_overlap (u64 b1, u64 e1, u64 b2, u64 e2) +{ + return (b1 <= e2) && (e1 >= b2); +} + // FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key)) static inline int vcpu_match_tr_entry_no_p(TR_ENTRY *trp, UINT64 ifa, UINT64 rid) { @@ -1286,6 +1292,16 @@ static inline int vcpu_match_tr_entry(TR_ENTRY *trp, UINT64 ifa, UINT64 rid) { return trp->pte.p && vcpu_match_tr_entry_no_p(trp, ifa, rid); +} + +static inline int +vcpu_match_tr_entry_range(TR_ENTRY *trp, UINT64 rid, u64 b, u64 e) +{ + return trp->rid == rid + && trp->pte.p + && range_overlap (b, e, + trp->vadr, trp->vadr + (1L << trp->ps) - 1); + } IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pteval, UINT64 *itir, UINT64 *iha) @@ -1310,8 +1326,8 @@ * region=5,VMM need to handle this tlb miss as if * PSCB(vcpu,metaphysical_mode)=0 */ - printk("vcpu_translate: bad physical address: 0x%lx\n", - address); + printk("vcpu_translate: bad physical address: 0x%lx at %lx\n", + address, vcpu_regs (vcpu)->cr_iip); } else { *pteval = (address & _PAGE_PPN_MASK) | __DIRTY_BITS | @@ -1750,8 +1766,6 @@ VCPU translation cache access routines **************************************************************************/ -void foobar(void) { /*vcpu_verbose = 1;*/ } - void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64 mp_pte, UINT64 logps) { unsigned long psr; @@ -1889,16 +1903,59 @@ return IA64_NO_FAULT; } -IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 addr_range) -{ - printf("vcpu_ptr_d: Purging TLB is unsupported\n"); - // don't forget to recompute dtr_regions - return (IA64_ILLOP_FAULT); -} - -IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 addr_range) -{ - printf("vcpu_ptr_i: Purging TLB is unsupported\n"); - // don't forget to recompute itr_regions - return (IA64_ILLOP_FAULT); -} +IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 log_range) +{ + unsigned long region = vadr >> 61; + u64 addr_range = 1UL << log_range; + unsigned long rid, rr; + int i; + TR_ENTRY *trp; + + rr = PSCB(vcpu,rrs)[region]; + rid = rr & RR_RID_MASK; + + /* Purge TC */ + vcpu_purge_tr_entry(&PSCBX(vcpu,dtlb)); + + /* Purge tr and recompute dtr_regions. */ + vcpu->arch.dtr_regions = 0; + for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++) + if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range)) + vcpu_purge_tr_entry(trp); + else if (trp->pte.p) + vcpu_quick_region_set(vcpu->arch.dtr_regions, + trp->vadr); + + vcpu_flush_tlb_vhpt_range (vadr, log_range); + + return IA64_NO_FAULT; +} + +IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 log_range) +{ + unsigned long region = vadr >> 61; + u64 addr_range = 1UL << log_range; + unsigned long rid, rr; + int i; + TR_ENTRY *trp; + + rr = PSCB(vcpu,rrs)[region]; + rid = rr & RR_RID_MASK; + + /* Purge TC */ + vcpu_purge_tr_entry(&PSCBX(vcpu,itlb)); + + /* Purge tr and recompute itr_regions. */ + vcpu->arch.itr_regions = 0; + for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++) + if (vcpu_match_tr_entry_range (trp,rid, vadr, vadr+addr_range)) + vcpu_purge_tr_entry(trp); + else if (trp->pte.p) + vcpu_quick_region_set(vcpu->arch.itr_regions, + trp->vadr); + + + vcpu_flush_tlb_vhpt_range (vadr, log_range); + + return IA64_NO_FAULT; +} diff -r 45a3c14a5878 xen/include/asm-ia64/dom_fw.h --- a/xen/include/asm-ia64/dom_fw.h Wed May 17 07:19:24 2006 +++ b/xen/include/asm-ia64/dom_fw.h Wed May 17 11:28:14 2006 @@ -20,6 +20,11 @@ #define FW_HYPERCALL_BASE_PADDR HYPERCALL_START #define FW_HYPERCALL_END_PADDR HYPERCALL_END #define FW_HYPERCALL_PADDR(index) (FW_HYPERCALL_BASE_PADDR + (16UL * index)) + +/* Hypercalls number have a low part and a high part. + The high part is the class (xen/pal/sal/efi). */ +#define FW_HYPERCALL_NUM_MASK_HIGH ~0xffUL +#define FW_HYPERCALL_NUM_MASK_LOW 0xffUL /* * PAL can be called in physical or virtual mode simply by @@ -57,6 +62,11 @@ #define FW_HYPERCALL_SAL_CALL_PADDR FW_HYPERCALL_PADDR(FW_HYPERCALL_SAL_CALL_INDEX) #define FW_HYPERCALL_SAL_CALL 0x1100UL +/* SAL return point. */ +#define FW_HYPERCALL_SAL_RETURN_INDEX 0x84UL +#define FW_HYPERCALL_SAL_RETURN_PADDR FW_HYPERCALL_PADDR(FW_HYPERCALL_SAL_RETURN_INDEX) +#define FW_HYPERCALL_SAL_RETURN 0x1200UL + /* * EFI is accessed via the EFI system table, which contains: * - a header which contains version info @@ -81,7 +91,6 @@ */ /* these are indexes into the runtime services table */ -#define FW_HYPERCALL_EFI_BASE #define FW_HYPERCALL_EFI_GET_TIME_INDEX 0UL #define FW_HYPERCALL_EFI_SET_TIME_INDEX 1UL #define FW_HYPERCALL_EFI_GET_WAKEUP_TIME_INDEX 2UL @@ -134,9 +143,6 @@ /* Interrupt vector used for os boot rendez vous. */ #define XEN_SAL_BOOT_RENDEZ_VEC 0xF3 -#define FW_HYPERCALL_NUM_MASK_HIGH ~0xffUL -#define FW_HYPERCALL_NUM_MASK_LOW 0xffUL - #define EFI_MEMDESC_VERSION 1 extern struct ia64_pal_retval xen_pal_emulator(UINT64, u64, u64, u64); diff -r 45a3c14a5878 xen/include/asm-ia64/domain.h --- a/xen/include/asm-ia64/domain.h Wed May 17 07:19:24 2006 +++ b/xen/include/asm-ia64/domain.h Wed May 17 11:28:14 2006 @@ -52,6 +52,13 @@ unsigned long max_pfn; /* Max pfn including I/O holes */ struct virtual_platform_def vmx_platform; #define hvm_domain vmx_platform /* platform defs are not vmx specific */ + + /* OS boot rendez vous. */ + unsigned long boot_rdv_ip; + unsigned long boot_rdv_r1; + + /* SAL return point. */ + unsigned long sal_return_addr; u64 xen_vastart; u64 xen_vaend; diff -r 45a3c14a5878 xen/include/asm-ia64/vcpu.h --- a/xen/include/asm-ia64/vcpu.h Wed May 17 07:19:24 2006 +++ b/xen/include/asm-ia64/vcpu.h Wed May 17 11:28:14 2006 @@ -149,8 +149,8 @@ extern IA64FAULT vcpu_ptc_e(VCPU *vcpu, UINT64 vadr); extern IA64FAULT vcpu_ptc_g(VCPU *vcpu, UINT64 vadr, UINT64 addr_range); extern IA64FAULT vcpu_ptc_ga(VCPU *vcpu, UINT64 vadr, UINT64 addr_range); -extern IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr, UINT64 addr_range); -extern IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr, UINT64 addr_range); +extern IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr, UINT64 log_range); +extern IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr, UINT64 log_range); extern IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pteval, UINT64 *itir, UINT64 *iha); extern IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr); @@ -173,6 +173,9 @@ extern UINT64 vcpu_get_tmp(VCPU *, UINT64); extern void vcpu_set_tmp(VCPU *, UINT64, UINT64); +/* Initialize vcpu regs (but not cr_iip, r1, b0...) */ +extern void vcpu_init_regs (struct vcpu *v); + static inline UINT64 itir_ps(UINT64 itir) {