summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/ia64/acpica/OsdEnvironment.c22
-rw-r--r--sys/ia64/acpica/madt.c166
-rw-r--r--sys/ia64/ia64/locore.S52
-rw-r--r--sys/ia64/ia64/locore.s52
-rw-r--r--sys/ia64/ia64/mp_machdep.c172
-rw-r--r--sys/ia64/ia64/sal.c23
-rw-r--r--sys/ia64/include/sal.h5
-rw-r--r--sys/ia64/include/smp.h32
8 files changed, 359 insertions, 165 deletions
diff --git a/sys/ia64/acpica/OsdEnvironment.c b/sys/ia64/acpica/OsdEnvironment.c
index 5da1d5c..897fc26 100644
--- a/sys/ia64/acpica/OsdEnvironment.c
+++ b/sys/ia64/acpica/OsdEnvironment.c
@@ -51,25 +51,15 @@ AcpiOsTerminate(void)
}
ACPI_STATUS
-AcpiOsGetRootPointer(
- UINT32 Flags,
- ACPI_PHYSICAL_ADDRESS *RsdpPhysicalAddress)
+AcpiOsGetRootPointer(UINT32 Flags, ACPI_PHYSICAL_ADDRESS *RsdpPhysicalAddress)
{
- RSDP_DESCRIPTOR *rsdp;
- XSDT_DESCRIPTOR *xsdt;
- if (ia64_efi_acpi20_table) {
+ if (ia64_efi_acpi20_table)
*RsdpPhysicalAddress = ia64_efi_acpi20_table;
- rsdp = (RSDP_DESCRIPTOR *)
- IA64_PHYS_TO_RR7(ia64_efi_acpi20_table);
- xsdt = (XSDT_DESCRIPTOR *)
- IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress);
- ia64_parse_xsdt(xsdt);
- return(AE_OK);
- } else if (ia64_efi_acpi_table) {
+ else if (ia64_efi_acpi_table)
*RsdpPhysicalAddress = ia64_efi_acpi_table;
- return(AE_OK);
- }
+ else
+ return(AE_NOT_FOUND);
- return(AE_NOT_FOUND);
+ return(AE_OK);
}
diff --git a/sys/ia64/acpica/madt.c b/sys/ia64/acpica/madt.c
index 325bf62..a3bc09d 100644
--- a/sys/ia64/acpica/madt.c
+++ b/sys/ia64/acpica/madt.c
@@ -28,96 +28,71 @@
#include "acpi.h"
+void cpu_mp_add(uint, uint, uint);
+struct sapic *sapic_create(int, int, u_int64_t);
+
#pragma pack(1)
-#define APIC_INTERRUPT_SOURCE_OVERRIDE 2
-#define APIC_NMI 3
-#define APIC_LOCAL_APIC_NMI 4
-#define APIC_LOCAL_APIC_OVERRIDE 5
-#define APIC_IO_SAPIC 6
-#define APIC_LOCAL_SAPIC 7
-#define APIC_PLATFORM_INTERRUPT 8
-
+#define APIC_INTERRUPT_SOURCE_OVERRIDE 2
+#define APIC_NMI 3
+#define APIC_LOCAL_APIC_NMI 4
+#define APIC_LOCAL_APIC_OVERRIDE 5
+#define APIC_IO_SAPIC 6
+#define APIC_LOCAL_SAPIC 7
+#define APIC_PLATFORM_INTERRUPT 8
-typedef struct /* Interrupt Source Override */
+typedef struct /* Interrupt Source Override */
{
- APIC_HEADER header;
- UINT8 Bus;
- UINT8 Source;
- UINT32 GlobalSystemInterrupt;
- UINT16 Flags;
+ APIC_HEADER header;
+ UINT8 Bus;
+ UINT8 Source;
+ UINT32 GlobalSystemInterrupt;
+ UINT16 Flags;
} INTERRUPT_SOURCE_OVERRIDE;
-typedef struct /* IO SAPIC */
+typedef struct /* IO SAPIC */
{
- APIC_HEADER header;
- UINT8 IoSapicId; /* I/O SAPIC ID */
- UINT8 Reserved; /* reserved - must be zero */
- UINT32 Vector; /* interrupt vector index where INTI
- * lines start */
- UINT64 IoSapicAddress; /* SAPIC's physical address */
-
+ APIC_HEADER header;
+ UINT8 IoSapicId; /* I/O SAPIC ID */
+ UINT8 Reserved; /* reserved - must be zero */
+ UINT32 Vector; /* interrupt base */
+ UINT64 IoSapicAddress; /* SAPIC's physical address */
} IO_SAPIC;
-
typedef struct /* LOCAL SAPIC */
{
- APIC_HEADER header;
- UINT16 ProcessorId; /* ACPI processor id */
- UINT16 ProcessorEnabled: 1; /* Processor is usable if set */
- UINT16 Reserved1 : 15;
- UINT8 LocalSapicId; /* processor's local SAPIC id */
- UINT8 LocalSapicEid; /* processor's local SAPIC eid */
-
+ APIC_HEADER header;
+ UINT8 ProcessorId; /* ACPI processor id */
+ UINT8 LocalSapicId; /* Processor local SAPIC id */
+ UINT8 LocalSapicEid; /* Processor local SAPIC eid */
+ UINT8 Reserved;
+ UINT32 Reserved1: 16;
+ UINT32 ProcessorEnabled: 1;
+ UINT32 Reserved2: 15;
} LOCAL_SAPIC;
-
typedef struct /* PLATFORM INTERRUPT SOURCE */
{
- APIC_HEADER header;
- UINT16 Polarity : 2; /* Polarity of input signal */
- UINT16 TriggerMode: 2; /* Trigger mode of input signal */
- UINT16 Reserved1 : 12;
- UINT8 InterruptType; /* 1-PMI, 2-INIT, 3-Error */
- UINT8 ProcessorId; /* Processor ID of destination */
- UINT8 ProcessorEid; /* Processor EID of destination */
- UINT8 IoSapicVector; /* Value for redirection table */
- UINT32 GlobalSystemInterrupt; /* Global System Interrupt */
- UINT32 Reserved2;
-
+ APIC_HEADER header;
+ UINT16 Polarity : 2; /* Polarity of input signal */
+ UINT16 TriggerMode: 2; /* Trigger mode of input signal */
+ UINT16 Reserved1 : 12;
+ UINT8 InterruptType; /* 1-PMI, 2-INIT, 3-Error */
+ UINT8 ProcessorId; /* Processor ID of destination */
+ UINT8 ProcessorEid; /* Processor EID of destination */
+ UINT8 IoSapicVector; /* Value for redirection table */
+ UINT32 GlobalSystemInterrupt; /* Global System Interrupt */
+ UINT32 Reserved2;
} PLATFORM_INTERRUPT_SOURCE;
-
#pragma pack()
static void
-parse_local_apic(PROCESSOR_APIC *apic)
-{
- if (bootverbose) {
- printf("\t\tProcessorId=0x%x, APIC Id=0x%x",
- apic->ProcessorApicId, apic->LocalApicId);
- if (!apic->ProcessorEnabled)
- printf(" (disabled)");
- printf("\n");
- }
-}
-
-static void
-parse_io_apic(IO_APIC *apic)
-{
- if (bootverbose)
- printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
- apic->IoApicId, apic->Vector, apic->IoApicAddress);
-}
-
-static void
parse_interrupt_override(INTERRUPT_SOURCE_OVERRIDE *override)
{
if (bootverbose)
- printf("\t\tBus=%d, Source=%d, Irq=0x%x\n",
- override->Bus,
- override->Source,
- override->GlobalSystemInterrupt);
+ printf("\t\tBus=%d, Source=%d, Irq=0x%x\n", override->Bus,
+ override->Source, override->GlobalSystemInterrupt);
}
static void
@@ -125,9 +100,7 @@ parse_io_sapic(IO_SAPIC *sapic)
{
if (bootverbose)
printf("\t\tId=0x%x, Vector=0x%x, Address=0x%lx\n",
- sapic->IoSapicId,
- sapic->Vector,
- sapic->IoSapicAddress);
+ sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress);
sapic_create(sapic->IoSapicId, sapic->Vector, sapic->IoSapicAddress);
}
@@ -142,6 +115,11 @@ parse_local_sapic(LOCAL_SAPIC *sapic)
printf(" (disabled)");
printf("\n");
}
+#ifdef SMP
+ if (sapic->ProcessorEnabled)
+ cpu_mp_add(sapic->ProcessorId, sapic->LocalSapicId,
+ sapic->LocalSapicEid);
+#endif
}
static void
@@ -149,13 +127,10 @@ parse_platform_interrupt(PLATFORM_INTERRUPT_SOURCE *source)
{
if (bootverbose)
printf("\t\tPolarity=%d, TriggerMode=%d, Id=0x%x, "
- "Eid=0x%x, Vector=0x%x, Irq=%d\n",
- source->Polarity,
- source->TriggerMode,
- source->ProcessorId,
- source->ProcessorEid,
- source->IoSapicVector,
- source->GlobalSystemInterrupt);
+ "Eid=0x%x, Vector=0x%x, Irq=%d\n", source->Polarity,
+ source->TriggerMode, source->ProcessorId,
+ source->ProcessorEid, source->IoSapicVector,
+ source->GlobalSystemInterrupt);
}
static void
@@ -177,13 +152,11 @@ parse_madt(APIC_TABLE *madt)
case APIC_PROC:
if (bootverbose)
printf("Local APIC entry\n");
- parse_local_apic((PROCESSOR_APIC *) head);
break;
case APIC_IO:
if (bootverbose)
printf("I/O APIC entry\n");
- parse_io_apic((IO_APIC *) head);
break;
case APIC_INTERRUPT_SOURCE_OVERRIDE:
@@ -203,6 +176,7 @@ parse_madt(APIC_TABLE *madt)
printf("Local APIC NMI entry\n");
break;
+
case APIC_LOCAL_APIC_OVERRIDE:
if (bootverbose)
printf("Local APIC override entry\n");
@@ -238,28 +212,32 @@ parse_madt(APIC_TABLE *madt)
}
void
-ia64_parse_xsdt(XSDT_DESCRIPTOR *xsdt)
+ia64_probe_sapics(void)
{
- int i, count;
+ ACPI_PHYSICAL_ADDRESS rsdp_phys;
+ RSDP_DESCRIPTOR *rsdp;
+ XSDT_DESCRIPTOR *xsdt;
ACPI_TABLE_HEADER *table;
+ int i, count;
- /*
- * First find the MADT.
- */
- count = (UINT64 *) ((char *) xsdt + xsdt->Header.Length)
- - &xsdt->TableOffsetEntry[0];
+ if (AcpiOsGetRootPointer(0, &rsdp_phys) != AE_OK)
+ return;
+
+ rsdp = (RSDP_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp_phys);
+ xsdt = (XSDT_DESCRIPTOR *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress);
+
+ count = (UINT64 *)((char *)xsdt + xsdt->Header.Length)
+ - xsdt->TableOffsetEntry;
for (i = 0; i < count; i++) {
table = (ACPI_TABLE_HEADER *)
IA64_PHYS_TO_RR7(xsdt->TableOffsetEntry[i]);
+
if (bootverbose)
- printf("Table '%c%c%c%c' at %p\n",
- table->Signature[0],
- table->Signature[1],
- table->Signature[2],
- table->Signature[3],
- table);
- if (!strncmp(table->Signature, APIC_SIG, 4)) {
+ printf("Table '%c%c%c%c' at %p\n", table->Signature[0],
+ table->Signature[1], table->Signature[2],
+ table->Signature[3], table);
+
+ if (!strncmp(table->Signature, APIC_SIG, 4))
parse_madt((APIC_TABLE *) table);
- }
}
}
diff --git a/sys/ia64/ia64/locore.S b/sys/ia64/ia64/locore.S
index ae5946b..278c276 100644
--- a/sys/ia64/ia64/locore.S
+++ b/sys/ia64/ia64/locore.S
@@ -54,6 +54,7 @@
#include <sys/cdefs.h>
#include <machine/asm.h>
+#include <machine/ia64_cpu.h>
#include <machine/fpu.h>
#include <sys/syscall.h>
#include <assym.s>
@@ -74,7 +75,6 @@ kstack: .space KSTACK_PAGES * PAGE_SIZE
* Not really a leaf but we can't return.
*/
ENTRY(__start, 1)
-
movl r8=ia64_vector_table // set up IVT early
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
;;
@@ -130,6 +130,56 @@ ENTRY(__start, 1)
END(__start)
+/*
+ * AP wake-up entry point. The handoff state is similar as for the BSP,
+ * as described on page 3-9 of the IPF SAL Specification. The difference
+ * lies in the contents of register b0. For APs this register holds the
+ * return address into the SAL rendezvous routine.
+ */
+ .align 32
+ENTRY(os_boot_rendez,0)
+1: mov r16 = ip
+ movl r17 = (IA64_PSR_AC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT|IA64_PSR_BN)
+ mov r18 = 7
+ ;;
+ add r16 = 2f-1b, r16
+ mov cr.ipsr = r17
+ ;;
+ dep r16 = r18, r16, 61, 3
+ ;;
+ mov cr.iip = r16
+ ;;
+ rfi
+
+ .align 32
+2: movl r16 = ia64_vector_table // set up IVT early
+ movl r17 = ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
+ ;;
+ mov cr.iva = r16
+ mov cr.pta = r17
+ ;;
+ srlz.i
+ ;;
+ srlz.d
+ movl gp = __gp
+ ;;
+ br.call.sptk.many rp = ia64_ap_get_stack
+ ;;
+ mov r9 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
+ ;;
+ add sp = r9, r8
+ mov ar.bspstore = r8
+ ;;
+ loadrs
+ ;;
+ mov ar.rsc = 3
+ ;;
+ alloc r16=ar.pfs,0,0,0,0
+ ;;
+ br.call.sptk.many rp=ia64_ap_startup
+ /* NOT REACHED */
+END(os_boot_rendez)
+
/**************************************************************************/
/*
diff --git a/sys/ia64/ia64/locore.s b/sys/ia64/ia64/locore.s
index ae5946b..278c276 100644
--- a/sys/ia64/ia64/locore.s
+++ b/sys/ia64/ia64/locore.s
@@ -54,6 +54,7 @@
#include <sys/cdefs.h>
#include <machine/asm.h>
+#include <machine/ia64_cpu.h>
#include <machine/fpu.h>
#include <sys/syscall.h>
#include <assym.s>
@@ -74,7 +75,6 @@ kstack: .space KSTACK_PAGES * PAGE_SIZE
* Not really a leaf but we can't return.
*/
ENTRY(__start, 1)
-
movl r8=ia64_vector_table // set up IVT early
movl r9=ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
;;
@@ -130,6 +130,56 @@ ENTRY(__start, 1)
END(__start)
+/*
+ * AP wake-up entry point. The handoff state is similar as for the BSP,
+ * as described on page 3-9 of the IPF SAL Specification. The difference
+ * lies in the contents of register b0. For APs this register holds the
+ * return address into the SAL rendezvous routine.
+ */
+ .align 32
+ENTRY(os_boot_rendez,0)
+1: mov r16 = ip
+ movl r17 = (IA64_PSR_AC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT|IA64_PSR_BN)
+ mov r18 = 7
+ ;;
+ add r16 = 2f-1b, r16
+ mov cr.ipsr = r17
+ ;;
+ dep r16 = r18, r16, 61, 3
+ ;;
+ mov cr.iip = r16
+ ;;
+ rfi
+
+ .align 32
+2: movl r16 = ia64_vector_table // set up IVT early
+ movl r17 = ia64_vhpt+(1<<8)+(15<<2)+1 // and VHPT
+ ;;
+ mov cr.iva = r16
+ mov cr.pta = r17
+ ;;
+ srlz.i
+ ;;
+ srlz.d
+ movl gp = __gp
+ ;;
+ br.call.sptk.many rp = ia64_ap_get_stack
+ ;;
+ mov r9 = KSTACK_PAGES*PAGE_SIZE-SIZEOF_PCB-SIZEOF_TRAPFRAME-16
+ ;;
+ add sp = r9, r8
+ mov ar.bspstore = r8
+ ;;
+ loadrs
+ ;;
+ mov ar.rsc = 3
+ ;;
+ alloc r16=ar.pfs,0,0,0,0
+ ;;
+ br.call.sptk.many rp=ia64_ap_startup
+ /* NOT REACHED */
+END(os_boot_rendez)
+
/**************************************************************************/
/*
diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c
index 251e52d..86898b7 100644
--- a/sys/ia64/ia64/mp_machdep.c
+++ b/sys/ia64/ia64/mp_machdep.c
@@ -46,77 +46,186 @@
#include <machine/pal.h>
#include <machine/pmap.h>
#include <machine/clock.h>
+#include <machine/sal.h>
-static void ipi_send(u_int64_t, u_int64_t);
+#define LID_SAPIC_ID(x) ((int)((x) >> 24) & 0xff)
+#define LID_SAPIC_EID(x) ((int)((x) >> 16) & 0xff)
-u_int64_t cpu_to_lid[MAXCPU];
-int ncpus;
+void ia64_probe_sapics(void);
+
+static MALLOC_DEFINE(M_SMP, "smp", "SMP structures");
+
+static void ipi_send(u_int64_t, int);
+static void cpu_mp_unleash(void *);
+
+struct mp_cpu {
+ TAILQ_ENTRY(mp_cpu) cpu_next;
+ u_int64_t cpu_lid; /* Local processor ID */
+ int32_t cpu_no; /* Sequential CPU number */
+ u_int32_t cpu_bsp:1; /* 1=BSP; 0=AP */
+ u_int32_t cpu_awake:1; /* 1=Awake; 0=sleeping */
+ void *cpu_stack;
+};
+
+int mp_hardware = 0;
+int mp_ipi_vector[IPI_COUNT];
+
+TAILQ_HEAD(, mp_cpu) ia64_cpus = TAILQ_HEAD_INITIALIZER(ia64_cpus);
+
+void *
+ia64_ap_get_stack(void)
+{
+ struct mp_cpu *cpu;
+ u_int64_t lid = ia64_get_lid() & 0xffff0000;
+
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ if (cpu->cpu_lid == lid)
+ return (cpu->cpu_stack);
+ }
+
+ /* XXX - Should never reach here */
+ return NULL;
+}
+
+void
+ia64_ap_startup(void)
+{
+ struct mp_cpu *cpu;
+ u_int64_t lid = ia64_get_lid() & 0xffff0000;
+
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ if (cpu->cpu_lid == lid) {
+ cpu->cpu_lid = ia64_get_lid();
+ cpu->cpu_awake = 1;
+ printf("SMP: CPU%d is awake!\n", cpu->cpu_no);
+ while (1)
+ ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0);
+ }
+ }
+}
int
cpu_mp_probe()
{
- all_cpus = 1; /* Needed for MB init code */
- return (0);
+ ia64_probe_sapics();
+ return (mp_hardware);
}
void
-cpu_mp_start()
+cpu_mp_add(uint acpiid, uint apicid, uint apiceid)
{
+ struct mp_cpu *cpu;
+ u_int64_t lid = ia64_get_lid() & 0xffff0000;
+
+ cpu = malloc(sizeof(*cpu), M_SMP, M_WAITOK|M_ZERO);
+ if (cpu == NULL)
+ return;
+
+ TAILQ_INSERT_TAIL(&ia64_cpus, cpu, cpu_next);
+ cpu->cpu_no = acpiid;
+ lid = ((apicid & 0xff) << 8 | (apiceid & 0xff)) << 16;
+ if (lid == (ia64_get_lid() & 0xffff0000L)) {
+ cpu->cpu_lid = ia64_get_lid();
+ cpu->cpu_bsp = 1;
+ cpu->cpu_awake = 1;
+ } else
+ cpu->cpu_lid = lid;
+ all_cpus |= (1 << acpiid);
+ mp_ncpus++;
}
void
cpu_mp_announce()
{
+ struct mp_cpu *cpu;
+
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ printf("cpu%d: SAPIC Id=%x, SAPIC Eid=%x (%s)\n", cpu->cpu_no,
+ LID_SAPIC_ID(cpu->cpu_lid), LID_SAPIC_EID(cpu->cpu_lid),
+ (cpu->cpu_bsp) ? "BSP" : "AP");
+ }
+}
+
+void
+cpu_mp_start()
+{
+ struct mp_cpu *cpu;
+
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ if (!cpu->cpu_bsp) {
+ cpu->cpu_stack = malloc(KSTACK_PAGES * PAGE_SIZE,
+ M_SMP, M_WAITOK);
+ if (bootverbose)
+ printf("SMP: waking up CPU%d\n", cpu->cpu_no);
+ ipi_send(cpu->cpu_lid, IPI_AP_WAKEUP);
+ }
+ }
+}
+
+static void
+cpu_mp_unleash(void *dummy)
+{
+ struct mp_cpu *cpu;
+ int awake = 0;
+
+ if (!mp_hardware)
+ return;
+
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ if (cpu->cpu_awake)
+ awake++;
+ }
+
+ printf("SMP: %d CPUs, %d awake\n", mp_ncpus, awake);
}
/*
* send an IPI to a set of cpus.
*/
void
-ipi_selected(u_int cpus, u_int64_t ipi)
+ipi_selected(u_int64_t cpus, int ipi)
{
- u_int mask;
- int cpu;
+ struct mp_cpu *cpu;
- for (mask = 1, cpu = 0; cpu < ncpus; mask <<= 1, cpu++) {
- if (cpus & mask)
- ipi_send(cpu_to_lid[cpu], ipi);
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ if (cpus & (1 << cpu->cpu_no))
+ ipi_send(cpu->cpu_lid, ipi);
}
}
/*
- * send an IPI INTerrupt containing 'vector' to all CPUs, including myself
+ * send an IPI to all CPUs, including myself.
*/
void
-ipi_all(u_int64_t ipi)
+ipi_all(int ipi)
{
- int cpu;
+ struct mp_cpu *cpu;
- for (cpu = 0; cpu < ncpus; cpu++)
- ipi_send(cpu_to_lid[cpu], ipi);
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ ipi_send(cpu->cpu_lid, ipi);
+ }
}
/*
- * send an IPI to all CPUs EXCEPT myself
+ * send an IPI to all CPUs EXCEPT myself.
*/
void
-ipi_all_but_self(u_int64_t ipi)
+ipi_all_but_self(int ipi)
{
- u_int64_t lid;
- int cpu;
+ struct mp_cpu *cpu;
+ u_int64_t lid = ia64_get_lid();
- for (cpu = 0; cpu < ncpus; cpu++) {
- lid = cpu_to_lid[cpu];
- if (lid != ia64_get_lid())
- ipi_send(lid, ipi);
+ TAILQ_FOREACH(cpu, &ia64_cpus, cpu_next) {
+ if (cpu->cpu_lid != lid)
+ ipi_send(cpu->cpu_lid, ipi);
}
}
/*
- * send an IPI to myself
+ * send an IPI to myself.
*/
void
-ipi_self(u_int64_t ipi)
+ipi_self(int ipi)
{
ipi_send(ia64_get_lid(), ipi);
@@ -128,12 +237,15 @@ ipi_self(u_int64_t ipi)
* fields are used here.
*/
static void
-ipi_send(u_int64_t lid, u_int64_t ipi)
+ipi_send(u_int64_t lid, int ipi)
{
volatile u_int64_t *pipi;
+ u_int64_t vector;
- CTR2(KTR_SMP, __func__ ": lid=%lx, ipi=%lx", lid, ipi);
pipi = ia64_memory_address(PAL_PIB_DEFAULT_ADDR |
((lid >> 12) & 0xFFFF0L));
- *pipi = ipi & 0xFF;
+ vector = (u_int64_t)(mp_ipi_vector[ipi] & 0xff);
+ *pipi = vector;
}
+
+SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
diff --git a/sys/ia64/ia64/sal.c b/sys/ia64/ia64/sal.c
index a1bb1ce..6118771 100644
--- a/sys/ia64/ia64/sal.c
+++ b/sys/ia64/ia64/sal.c
@@ -29,6 +29,9 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <machine/sal.h>
+#include <machine/smp.h>
+
+void os_boot_rendez(void);
struct ia64_fdesc {
u_int64_t func;
@@ -40,7 +43,6 @@ static sal_entry_t fake_sal;
extern u_int64_t ia64_pal_entry;
sal_entry_t *ia64_sal_entry = fake_sal;
-u_int64_t ia64_sal_wakeup;
static struct ia64_sal_result
fake_sal(u_int64_t a1, u_int64_t a2, u_int64_t a3, u_int64_t a4,
@@ -86,23 +88,28 @@ ia64_sal_init(struct sal_system_table *saltab)
ia64_sal_entry = (sal_entry_t *) &sal_fdesc;
break;
}
-#ifdef SMP
case 5: {
struct sal_ap_wakeup_descriptor *dp;
+ struct ia64_sal_result sal;
+ int ipi;
dp = (struct sal_ap_wakeup_descriptor*)p;
KASSERT(dp->sale_mechanism == 0,
("Unsupported AP wake-up mechanism"));
- ia64_sal_wakeup = dp->sale_vector;
if (bootverbose)
printf("SMP: AP wake-up vector: 0x%lx\n",
- ia64_sal_wakeup);
- /*
- * Register OS_BOOT_RENDEZ using SAL_SET_VECTORS
- */
+ dp->sale_vector);
+ for (ipi = 0; ipi < IPI_COUNT; ipi++)
+ mp_ipi_vector[ipi] = dp->sale_vector + ipi;
+
+ sal = ia64_sal_entry(SAL_SET_VECTORS,
+ SAL_OS_BOOT_RENDEZ,
+ ia64_tpa((vm_offset_t)os_boot_rendez), 0, 0,
+ 0, 0, 0);
+
+ mp_hardware = 1;
break;
}
-#endif
}
p += sizes[*p];
}
diff --git a/sys/ia64/include/sal.h b/sys/ia64/include/sal.h
index b9dd889..c4ee7bf 100644
--- a/sys/ia64/include/sal.h
+++ b/sys/ia64/include/sal.h
@@ -113,6 +113,11 @@ struct sal_ap_wakeup_descriptor {
#define SAL_FREQ_BASE 0x01000012
#define SAL_UPDATE_PAL 0x01000020
+/* SAL_SET_VECTORS event handler types */
+#define SAL_OS_MCA 0
+#define SAL_OS_INIT 1
+#define SAL_OS_BOOT_RENDEZ 2
+
struct ia64_sal_result {
int64_t sal_status;
u_int64_t sal_result[3];
diff --git a/sys/ia64/include/smp.h b/sys/ia64/include/smp.h
index ded849f..3f99e15 100644
--- a/sys/ia64/include/smp.h
+++ b/sys/ia64/include/smp.h
@@ -7,26 +7,28 @@
#ifdef _KERNEL
/*
- * Interprocessor interrupts for SMP.
+ * Interprocessor interrupts for SMP. The following values are indices
+ * into the IPI vector table. The SAL gives us the vector used for AP
+ * wake-up. Keep the IPI_AP_WAKEUP at index 0.
*/
-#define IPI_INVLTLB 0x0001
-#define IPI_RENDEZVOUS 0x0002
-#define IPI_AST 0x0004
-#define IPI_CHECKSTATE 0x0008
-#define IPI_STOP 0x0010
+#define IPI_AP_WAKEUP 0
+#define IPI_AST 1
+#define IPI_CHECKSTATE 2
+#define IPI_INVLTLB 3
+#define IPI_RENDEZVOUS 4
+#define IPI_STOP 5
+
+#define IPI_COUNT 6
#ifndef LOCORE
-/* global data in mp_machdep.c */
-extern volatile u_int checkstate_probed_cpus;
-extern volatile u_int checkstate_need_ast;
-extern volatile u_int resched_cpus;
+extern int mp_hardware;
+extern int mp_ipi_vector[];
-void ipi_all(u_int64_t ipi);
-void ipi_all_but_self(u_int64_t ipi);
-void ipi_selected(u_int cpus, u_int64_t ipi);
-void ipi_self(u_int64_t ipi);
-void smp_init_secondary(void);
+void ipi_all(int ipi);
+void ipi_all_but_self(int ipi);
+void ipi_selected(u_int64_t cpus, int ipi);
+void ipi_self(int ipi);
#endif /* !LOCORE */
#endif /* _KERNEL */
OpenPOWER on IntegriCloud