diff -r 8e1cd36ea002 xen/arch/ia64/xen/dom_fw.c --- a/xen/arch/ia64/xen/dom_fw.c Wed Apr 19 04:47:59 2006 +++ b/xen/arch/ia64/xen/dom_fw.c Wed Apr 19 07:07:44 2006 @@ -93,9 +93,24 @@ /* the following heavily leveraged from linux/arch/ia64/hp/sim/fw-emu.c */ -#define NUM_EFI_SYS_TABLES 6 -# define NUM_MEM_DESCS 5 - +/* 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, @@ -154,7 +169,18 @@ printf("NON-PRIV DOMAIN CALLED SAL_PCI_CONFIG_WRITE\n"); break; case SAL_SET_VECTORS: - printf("*** CALLED SAL_SET_VECTORS. IGNORED...\n"); + if (in1 == SAL_VECTOR_OS_BOOT_RENDEZ) { + if (in4 != 0 || in5 != 0 || in6 != 0 || in7 != 0) { + /* Sanity check: cs_length1 must be 0, + second vector is reserved. */ + status = -2; + } + else + set_os_boot_rendez (current->domain, in2, in3); + } + else + printf("*** CALLED SAL_SET_VECTORS %lu. IGNORED...\n", + in1); break; case SAL_GET_STATE_INFO: /* No more info. */ @@ -617,6 +643,9 @@ return; } +#define NUM_EFI_SYS_TABLES 6 +#define NUM_MEM_DESCS 5 + static struct ia64_boot_param * dom_fw_init (struct domain *d, const char *args, int arglen, char *fw_mem, int fw_mem_size) { @@ -624,8 +653,10 @@ efi_runtime_services_t *efi_runtime; efi_config_table_t *efi_tables; struct ia64_sal_systab *sal_systab; + struct ia64_sal_desc_entry_point *sal_ed; + struct ia64_sal_desc_ap_wakeup *sal_wakeup; + struct ia64_sal_desc_platform_feature *sal_feature; efi_memory_desc_t *efi_memmap, *md; - struct ia64_sal_desc_entry_point *sal_ed; struct ia64_boot_param *bp; unsigned long *pfn; unsigned char checksum = 0; @@ -661,6 +692,8 @@ efi_tables = (void *) cp; cp += NUM_EFI_SYS_TABLES * sizeof(*efi_tables); sal_systab = (void *) cp; cp += sizeof(*sal_systab); sal_ed = (void *) cp; cp += sizeof(*sal_ed); + sal_wakeup = (void *) cp; cp += sizeof(*sal_wakeup); + sal_feature = (void *) cp; cp += sizeof(*sal_feature); efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap); bp = (void *) cp; cp += sizeof(*bp); pfn = (void *) cp; cp += NFUNCPTRS * 2 * sizeof(pfn); @@ -778,7 +811,7 @@ sal_systab->size = sizeof(*sal_systab); sal_systab->sal_rev_minor = 1; sal_systab->sal_rev_major = 0; - sal_systab->entry_count = 1; + sal_systab->entry_count = 3; strcpy((char *)sal_systab->oem_id, "Xen/ia64"); strcpy((char *)sal_systab->product_id, "Xen/ia64"); @@ -790,6 +823,15 @@ sal_ed->sal_proc = FW_HYPERCALL_SAL_CALL_PADDR + start_mpaddr; dom_fw_hypercall_patch (d, sal_ed->sal_proc, FW_HYPERCALL_SAL_CALL, 1); sal_ed->gp = 0; // will be ignored + + /* Fill an AP wakeup descriptor. */ + sal_wakeup->type = SAL_DESC_AP_WAKEUP; + sal_wakeup->mechanism = IA64_SAL_AP_EXTERNAL_INT; + sal_wakeup->vector = XEN_SAL_BOOT_RENDEZ_VEC; + + /* Fill a platform feature. ITC are (almost!) synchronized. . */ + sal_feature->type = SAL_DESC_PLATFORM_FEATURE; + sal_feature->feature_mask = IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT; for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp) checksum += *cp; diff -r 8e1cd36ea002 xen/arch/ia64/xen/hypercall.c --- a/xen/arch/ia64/xen/hypercall.c Wed Apr 19 04:47:59 2006 +++ b/xen/arch/ia64/xen/hypercall.c Wed Apr 19 07:07:44 2006 @@ -123,6 +123,65 @@ } +static void +fw_hypercall_ipi (struct pt_regs *regs) +{ + int cpu = regs->r8; + int vector = regs->r9; + struct vcpu *targ; + + if (0 && vector == 254) + printf ("send_ipi from %d to %d vector=%d\n", + current->vcpu_id, cpu, vector); + + if (cpu > MAX_VIRT_CPUS) + return; + + targ = current->domain->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; + + 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; + + /* Copy from vcpu 0. */ + c.vcpu.evtchn_vector = + current->domain->vcpu[0]->vcpu_info->arch.evtchn_vector; + if (arch_set_info_guest (targ, &c) != 0) { + printf ("arch_boot_vcpu: failure\n"); + return; + } + 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); + } + else + printf ("arch_boot_vcpu: huu, already awaken!"); + } + else { + int running = test_bit(_VCPUF_running, + &targ->vcpu_flags); + + vcpu_pend_interrupt(targ, vector); + vcpu_unblock(targ); + if (running) + smp_send_event_check_cpu(targ->processor); + } + return; +} + static int fw_hypercall (struct pt_regs *regs) { @@ -223,6 +282,9 @@ // FIXME: need fixes in efi.h from 2.6.9 regs->r8 = EFI_UNSUPPORTED; break; + case FW_HYPERCALL_IPI: + fw_hypercall_ipi (regs); + break; default: printf("unknown ia64 fw hypercall %lx\n", regs->r2); regs->r8 = do_ni_hypercall(); diff -r 8e1cd36ea002 xen/include/asm-ia64/dom_fw.h --- a/xen/include/asm-ia64/dom_fw.h Wed Apr 19 04:47:59 2006 +++ b/xen/include/asm-ia64/dom_fw.h Wed Apr 19 07:07:44 2006 @@ -126,8 +126,13 @@ */ #define FW_HYPERCALL_FIRST_ARCH 0x300UL +#define FW_HYPERCALL_IPI 0x380UL + /* Xen/ia64 user hypercalls. Only used for debugging. */ #define FW_HYPERCALL_FIRST_USER 0xff00UL + +/* Interrupt vector used for os boot rendez vous. */ +#define XEN_SAL_BOOT_RENDEZ_VEC 0xF3 extern struct ia64_pal_retval xen_pal_emulator(UINT64, u64, u64, u64); extern struct sal_ret_values sal_emulator (long index, unsigned long in1, unsigned long in2, unsigned long in3, unsigned long in4, unsigned long in5, unsigned long in6, unsigned long in7);