summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2002-05-12 05:54:21 +0000
committermarcel <marcel@FreeBSD.org>2002-05-12 05:54:21 +0000
commit49d0eba5f2e4c8bc62afa196db9dc683dd92018e (patch)
tree60e30ee3008b26ae2fe106aea4d4197176e7a65c /sys
parente7bbea38d981582adb68f002d1abf784b0ea7047 (diff)
downloadFreeBSD-src-49d0eba5f2e4c8bc62afa196db9dc683dd92018e.zip
FreeBSD-src-49d0eba5f2e4c8bc62afa196db9dc683dd92018e.tar.gz
o Rename ia64_count_aps to ia64_count_cpus and reimplement the
function to return the total number of CPUs and not the highest CPU id. o Define mp_maxid based on the minimum of the actual number of CPUs in the system and MAXCPU. o In cpu_mp_add, when the CPU id of the CPU we're trying to add is larger than mp_maxid, don't add the CPU. Formerly this was based on MAXCPU. Don't count CPUs when we add them. We already know how many CPUs exist. o Replace MAXCPU with mp_maxid when used in loops that iterate over the id space. This avoids a couple of useless iterations. o In cpu_mp_unleash, use the number of CPUs to determine if we need to launch the CPUs. o Remove mp_hardware as it's not used anymore. o Move the IPI vector array from mp_machdep.c to sal.c. We use the array as a centralized place to collect vector assignments. Note that we still assign vectors to SMP specific IPIs in non-SMP configurations. Rename the array from mp_ipi_vector to ipi_vector. o Add IPI_MCA_RENDEZ and IPI_MCA_CMCV. These are used by MCA. Note that IPI_MCA_CMCV is not SMP specific. o Initialize the ipi_vector array so that we place the IPIs in sensible priority classes. The classes are relative to where the AP wake-up vector is located to guarantee that it's the highest priority (external) interrupt. Class assignment is as follows: class IPI notes x AP wake-up (normally x=15) x-1 MCA rendezvous x-2 AST, Rendezvous, stop x-3 CMCV, test
Diffstat (limited to 'sys')
-rw-r--r--sys/ia64/acpica/madt.c35
-rw-r--r--sys/ia64/ia64/interrupt.c8
-rw-r--r--sys/ia64/ia64/mp_machdep.c45
-rw-r--r--sys/ia64/ia64/sal.c70
-rw-r--r--sys/ia64/include/cpu.h2
-rw-r--r--sys/ia64/include/smp.h21
6 files changed, 125 insertions, 56 deletions
diff --git a/sys/ia64/acpica/madt.c b/sys/ia64/acpica/madt.c
index 0734f3e..0ddd374 100644
--- a/sys/ia64/acpica/madt.c
+++ b/sys/ia64/acpica/madt.c
@@ -134,30 +134,39 @@ parse_platform_interrupt(PLATFORM_INTERRUPT_SOURCE *source)
static int
parse_madt(APIC_TABLE *madt, int countcpus)
{
- char *p, *end;
- int maxid = 0;
+ char *end, *p;
+ int cpus;
+
+ end = (char *)madt + madt->Header.Length;
/*
* MADT header is followed by a number of variable length
* structures.
*/
- end = (char *) madt + madt->Header.Length;
- for (p = (char *) (madt + 1); p < end; ) {
- APIC_HEADER *head = (APIC_HEADER *) p;
- if (countcpus) {
+ if (countcpus) {
+ cpus = 0;
+
+ for (p = (char *)(madt + 1); p < end; ) {
+ APIC_HEADER *head = (APIC_HEADER *)p;
+
if (head->Type == APIC_LOCAL_SAPIC) {
LOCAL_SAPIC *sapic = (LOCAL_SAPIC *) head;
if (sapic->ProcessorEnabled)
- if (sapic->ProcessorId > maxid)
- maxid = sapic->ProcessorId;
+ cpus++;
}
p = p + head->Length;
- continue;
}
+ return (cpus);
+ }
+
+ for (p = (char *)(madt + 1); p < end; ) {
+ APIC_HEADER *head = (APIC_HEADER *)p;
+
if (bootverbose)
printf("\t");
+
switch (head->Type) {
case APIC_PROC:
if (bootverbose)
@@ -220,7 +229,7 @@ parse_madt(APIC_TABLE *madt, int countcpus)
p = p + head->Length;
}
- return (maxid);
+ return (0);
}
static int
@@ -262,11 +271,11 @@ ia64_probe_sapics(void)
}
/*
- * Return the maximum cpuid used by any cpu in the system. This will
- * return zero for systems with only one cpu.
+ * Count the number of local SAPIC entries in the APIC table. Every enabled
+ * entry corresponds to a processor.
*/
int
-ia64_count_aps(void)
+ia64_count_cpus(void)
{
return (parse_table(1));
}
diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c
index a7483a5..ec26586 100644
--- a/sys/ia64/ia64/interrupt.c
+++ b/sys/ia64/ia64/interrupt.c
@@ -122,12 +122,12 @@ interrupt(u_int64_t vector, struct trapframe *framep)
statclock((struct clockframe *)framep);
critical_exit();
#ifdef SMP
- } else if (vector == mp_ipi_vector[IPI_AST]) {
+ } else if (vector == ipi_vector[IPI_AST]) {
CTR1(KTR_SMP, "IPI_AST, cpuid=%d", PCPU_GET(cpuid));
- } else if (vector == mp_ipi_vector[IPI_RENDEZVOUS]) {
+ } else if (vector == ipi_vector[IPI_RENDEZVOUS]) {
CTR1(KTR_SMP, "IPI_RENDEZVOUS, cpuid=%d", PCPU_GET(cpuid));
smp_rendezvous_action();
- } else if (vector == mp_ipi_vector[IPI_STOP]) {
+ } else if (vector == ipi_vector[IPI_STOP]) {
u_int32_t mybit = PCPU_GET(cpumask);
CTR1(KTR_SMP, "IPI_STOP, cpuid=%d", PCPU_GET(cpuid));
@@ -142,7 +142,7 @@ interrupt(u_int64_t vector, struct trapframe *framep)
cpustop_restartfunc = NULL;
(*f)();
}
- } else if (vector == mp_ipi_vector[IPI_TEST]) {
+ } else if (vector == ipi_vector[IPI_TEST]) {
CTR1(KTR_SMP, "IPI_TEST, cpuid=%d", PCPU_GET(cpuid));
mp_ipi_test++;
#endif
diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c
index ff5b4ae..cc7e181 100644
--- a/sys/ia64/ia64/mp_machdep.c
+++ b/sys/ia64/ia64/mp_machdep.c
@@ -63,8 +63,6 @@ extern vm_offset_t vhpt_base, vhpt_size;
#define LID_SAPIC_SET(id,eid) (((id & 0xff) << 8 | (eid & 0xff)) << 16);
#define LID_SAPIC_MASK 0xffff0000UL
-int mp_hardware = 0;
-int mp_ipi_vector[IPI_COUNT];
int mp_ipi_test = 0;
/* Variables used by os_boot_rendez */
@@ -124,15 +122,26 @@ int
cpu_mp_probe()
{
/*
- * We've already discovered any APs when they're present.
- * Just return the result here.
+ * Count the number of processors in the system by walking the ACPI
+ * tables. Note that we record the actual number of processors, even
+ * if this is larger than MAXCPU. We only activate MAXCPU processors.
*/
- if (mp_hardware) {
- mp_maxid = ia64_count_aps();
- return (mp_maxid > 0);
- } else {
- return (0);
- }
+ mp_ncpus = ia64_count_cpus();
+
+ /*
+ * Set the largest cpuid we're going to use. This is necessary for
+ * VM initialization.
+ */
+ mp_maxid = min(mp_ncpus, MAXCPU) - 1;
+
+ /*
+ * If there's only 1 processor, or we don't have a wake-up vector,
+ * we're not going to enable SMP. Note that no wake-up vector can
+ * also mean that the wake-up mechanism is not supported. In this
+ * case we can have multiple processors, but we simply can't wake
+ * them up...
+ */
+ return (mp_ncpus > 1 && ipi_vector[IPI_AP_WAKEUP] != 0);
}
void
@@ -141,14 +150,9 @@ cpu_mp_add(uint acpiid, uint apicid, uint apiceid)
struct pcpu *pc;
u_int64_t lid;
- /* Count all CPUs, even the ones we cannot use */
- mp_ncpus++;
-
/* Ignore any processor numbers outside our range */
- if (acpiid >= MAXCPU) {
- printf("SMP: cpu%d skipped; increase MAXCPU\n", acpiid);
+ if (acpiid > mp_maxid)
return;
- }
KASSERT((all_cpus & (1UL << acpiid)) == 0,
("%s: cpu%d already in CPU map", __func__, acpiid));
@@ -176,7 +180,7 @@ cpu_mp_announce()
struct pcpu *pc;
int i;
- for (i = 0; i < MAXCPU; i++) {
+ for (i = 0; i <= mp_maxid; i++) {
pc = pcpu_find(i);
if (pc != NULL) {
printf("cpu%d: SAPIC Id=%x, SAPIC Eid=%x", i,
@@ -247,7 +251,7 @@ cpu_mp_unleash(void *dummy)
struct pcpu *pc;
int cpus;
- if (!mp_hardware)
+ if (mp_ncpus <= 1)
return;
if (mp_ipi_test != 1)
@@ -340,8 +344,9 @@ ipi_send(u_int64_t lid, int ipi)
pipi = ia64_memory_address(PAL_PIB_DEFAULT_ADDR |
((lid & LID_SAPIC_MASK) >> 12));
- vector = (u_int64_t)(mp_ipi_vector[ipi] & 0xff);
- CTR3(KTR_SMP, "ipi_send(%p, %ld), cpuid=%d", pipi, vector, PCPU_GET(cpuid));
+ vector = (u_int64_t)(ipi_vector[ipi] & 0xff);
+ CTR3(KTR_SMP, "ipi_send(%p, %ld), cpuid=%d", pipi, vector,
+ PCPU_GET(cpuid));
*pipi = vector;
ia64_mf_a();
}
diff --git a/sys/ia64/ia64/sal.c b/sys/ia64/ia64/sal.c
index ee15042..db3a094 100644
--- a/sys/ia64/ia64/sal.c
+++ b/sys/ia64/ia64/sal.c
@@ -36,6 +36,13 @@
#include <machine/sal.h>
#include <machine/smp.h>
+/*
+ * IPIs are used more genericly than only
+ * for inter-processor interrupts. Don't
+ * make it a SMP specific thing...
+ */
+int ipi_vector[IPI_COUNT];
+
static struct ia64_fdesc sal_fdesc;
static sal_entry_t fake_sal;
@@ -54,6 +61,21 @@ fake_sal(u_int64_t a1, u_int64_t a2, u_int64_t a3, u_int64_t a4,
return res;
}
+static void
+setup_ipi_vectors(int ceil)
+{
+ int ipi;
+
+ ipi_vector[IPI_MCA_RENDEZ] = ceil - 0x10;
+ ipi_vector[IPI_MCA_CMCV] = ceil - 0x30;
+ ipi_vector[IPI_TEST] = ceil - 0x30 + 1;
+
+ ipi = IPI_AST; /* First generic IPI. */
+ ceil -= 0x20; /* First vector in group. */
+ while (ipi < IPI_COUNT)
+ ipi_vector[ipi++] = ceil++;
+}
+
void
ia64_sal_init(struct sal_system_table *saltab)
{
@@ -90,30 +112,60 @@ ia64_sal_init(struct sal_system_table *saltab)
struct sal_ap_wakeup_descriptor *dp;
#ifdef SMP
struct ia64_sal_result result;
- int ipi;
#endif
dp = (struct sal_ap_wakeup_descriptor*)p;
- KASSERT(dp->sale_mechanism == 0,
- ("Unsupported AP wake-up mechanism"));
+ if (dp->sale_mechanism != 0) {
+ printf("SAL: unsupported AP wake-up mechanism "
+ "(%d)\n", dp->sale_mechanism);
+ break;
+ }
+
+ if (dp->sale_vector < 0x10 || dp->sale_vector > 0xff) {
+ printf("SAL: invalid AP wake-up vector "
+ "(0x%lx)\n", dp->sale_vector);
+ break;
+ }
+
+ /*
+ * SAL documents that the wake-up vector should be
+ * high (close to 255). The MCA rendezvous vector
+ * should be less than the wake-up vector, but still
+ * "high". We use the following priority assignment:
+ * Wake-up: priority of the sale_vector
+ * Rendezvous: priority-1
+ * Generic IPIs: priority-2
+ * Special IPIs: priority-3
+ * Consequently, the wake-up priority should be at
+ * least 4 (ie vector >= 0x40).
+ */
+ if (dp->sale_vector < 0x40) {
+ printf("SAL: AP wake-up vector too low "
+ "(0x%lx)\n", dp->sale_vector);
+ break;
+ }
+
if (bootverbose)
- printf("SMP: AP wake-up vector: 0x%lx\n",
+ printf("SAL: AP wake-up vector: 0x%x\n",
dp->sale_vector);
-#ifdef SMP
- for (ipi = 0; ipi < IPI_COUNT; ipi++)
- mp_ipi_vector[ipi] = dp->sale_vector + ipi;
+ ipi_vector[IPI_AP_WAKEUP] = dp->sale_vector;
+ setup_ipi_vectors(dp->sale_vector & 0xf0);
+
+#ifdef SMP
result = ia64_sal_entry(SAL_SET_VECTORS,
SAL_OS_BOOT_RENDEZ,
ia64_tpa(FDESC_FUNC(os_boot_rendez)),
ia64_tpa(FDESC_GP(os_boot_rendez)),
0, 0, 0, 0);
-
- mp_hardware = 1;
#endif
+
break;
}
}
p += sizes[*p];
}
+
+ if (ipi_vector[IPI_AP_WAKEUP] == 0)
+ setup_ipi_vectors(0xf0);
}
diff --git a/sys/ia64/include/cpu.h b/sys/ia64/include/cpu.h
index c97450d..5169f37 100644
--- a/sys/ia64/include/cpu.h
+++ b/sys/ia64/include/cpu.h
@@ -136,7 +136,7 @@ void fork_trampoline(void); /* MAGIC */
void syscall(int, u_int64_t *, struct trapframe *);
void trap(int vector, int imm, struct trapframe *framep);
void ia64_probe_sapics(void);
-int ia64_count_aps(void);
+int ia64_count_cpus(void);
void map_pal_code(void);
void cpu_mp_add(uint, uint, uint);
diff --git a/sys/ia64/include/smp.h b/sys/ia64/include/smp.h
index ba6677f..e985fc0 100644
--- a/sys/ia64/include/smp.h
+++ b/sys/ia64/include/smp.h
@@ -10,20 +10,23 @@
* 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. We base the other vectors on that. Keep IPI_AP_WAKEUP at
- * index 0.
+ * index 0 and IPI_MCA_RENDEZ at index 1. See sal.c for details.
*/
-#define IPI_AP_WAKEUP 0 /* ia64 specific */
-#define IPI_AST 1
-#define IPI_RENDEZVOUS 2
-#define IPI_STOP 3
-#define IPI_TEST 4 /* ia64 specific */
+/* Architecture specific IPIs. */
+#define IPI_AP_WAKEUP 0
+#define IPI_MCA_RENDEZ 1
+#define IPI_MCA_CMCV 2
+#define IPI_TEST 3
+/* Machine independent IPIs. */
+#define IPI_AST 4
+#define IPI_RENDEZVOUS 5
+#define IPI_STOP 6
-#define IPI_COUNT 5
+#define IPI_COUNT 7
#ifndef LOCORE
-extern int mp_hardware;
-extern int mp_ipi_vector[];
+extern int ipi_vector[];
void ipi_all(int ipi);
void ipi_all_but_self(int ipi);
OpenPOWER on IntegriCloud