mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
[IA64] SMP-guest
Final SMP-guest patch: add IPI and boot rendez-vous support. Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
This commit is contained in:
1 parent
bd546a62ac
commit
9cc9df7182
5 files changed
+126
-5
No files matched your search
@@ -265,6 +265,14 @@ ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
|
||||
unsigned long ipi_data;
|
||||
unsigned long phys_cpu_id;
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
if (running_on_xen) {
|
||||
extern void xen_send_ipi (int cpu, int vec);
|
||||
xen_send_ipi (cpu, vector);
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_XEN */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
phys_cpu_id = cpu_physical_id(cpu);
|
||||
#else
|
||||
|
||||
@@ -341,3 +341,13 @@ GLOBAL_ENTRY(xen_set_eflag)
|
||||
br.ret.sptk.many rp
|
||||
END(xen_set_eflag)
|
||||
#endif
|
||||
|
||||
GLOBAL_ENTRY(xen_send_ipi)
|
||||
mov r14=r32
|
||||
mov r15=r33
|
||||
mov r2=0x380
|
||||
break 0x1000
|
||||
;;
|
||||
br.ret.sptk.many rp
|
||||
;;
|
||||
END(xen_send_ipi)
|
||||
@@ -94,9 +94,24 @@ unsigned long dom_fw_setup(struct domain *d, const char *args, int arglen)
|
||||
|
||||
/* 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,
|
||||
@@ -155,7 +170,18 @@ sal_emulator (long index, unsigned long in1, unsigned long in2,
|
||||
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. */
|
||||
@@ -618,6 +644,9 @@ dom_fw_fake_acpi(struct domain *d, struct fake_acpi_tables *tables)
|
||||
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)
|
||||
{
|
||||
@@ -625,8 +654,9 @@ dom_fw_init (struct domain *d, const char *args, int arglen, char *fw_mem, int f
|
||||
efi_runtime_services_t *efi_runtime;
|
||||
efi_config_table_t *efi_tables;
|
||||
struct ia64_sal_systab *sal_systab;
|
||||
efi_memory_desc_t *efi_memmap, *md;
|
||||
struct ia64_sal_desc_entry_point *sal_ed;
|
||||
struct ia64_sal_desc_ap_wakeup *sal_wakeup;
|
||||
efi_memory_desc_t *efi_memmap, *md;
|
||||
struct ia64_boot_param *bp;
|
||||
unsigned long *pfn;
|
||||
unsigned char checksum = 0;
|
||||
@@ -662,6 +692,7 @@ dom_fw_init (struct domain *d, const char *args, int arglen, char *fw_mem, int f
|
||||
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);
|
||||
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);
|
||||
@@ -779,7 +810,7 @@ dom_fw_init (struct domain *d, const char *args, int arglen, char *fw_mem, int f
|
||||
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 = 2;
|
||||
|
||||
strcpy((char *)sal_systab->oem_id, "Xen/ia64");
|
||||
strcpy((char *)sal_systab->product_id, "Xen/ia64");
|
||||
@@ -792,6 +823,11 @@ dom_fw_init (struct domain *d, const char *args, int arglen, char *fw_mem, int f
|
||||
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;
|
||||
|
||||
for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp)
|
||||
checksum += *cp;
|
||||
|
||||
|
||||
@@ -132,6 +132,65 @@ xen_hypercall (struct pt_regs *regs)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
fw_hypercall_ipi (struct pt_regs *regs)
|
||||
{
|
||||
int cpu = regs->r14;
|
||||
int vector = regs->r15;
|
||||
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)
|
||||
{
|
||||
@@ -232,6 +291,9 @@ fw_hypercall (struct pt_regs *regs)
|
||||
// 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();
|
||||
|
||||
@@ -125,9 +125,14 @@ extern unsigned long dom_fw_setup(struct domain *, const char *, int);
|
||||
*/
|
||||
#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);
|
||||
extern struct ia64_pal_retval pal_emulator_static (unsigned long);
|
||||
|
||||