From bbe7d290eaefab02b2aae1d8556f86baf226f87c Mon Sep 17 00:00:00 2001 From: jhb Date: Fri, 21 Nov 2003 22:23:26 +0000 Subject: [PATCH] - Split cpu_mp_probe() into two parts. cpu_mp_setmaxid() is still called very early (SI_SUB_TUNABLES - 1) and is responsible for setting mp_maxid. cpu_mp_probe() is now called at SI_SUB_CPU and determines if SMP is actually present and sets mp_ncpus and all_cpus. Splitting these up allows an architecture to probe CPUs later than SI_SUB_TUNABLES by just setting mp_maxid to MAXCPU in cpu_mp_setmaxid(). This could allow the CPU probing code to live in a module, for example, since modules sysinit's in modules cannot be invoked prior to SI_SUB_KLD. This is needed to re-enable the ACPI module on i386. - For the alpha SMP probing code, use LOCATE_PCS() instead of duplicating its contents in a few places. Also, add a smp_cpu_enabled() function to avoid duplicating some code. There is room for further code reduction later since much of this code is also present in cpu_mp_start(). - All archs besides i386 still set mp_maxid to the same values they set it to before this change. i386 now sets mp_maxid to MAXCPU. Tested on: alpha, amd64, i386, ia64, sparc64 Approved by: re (scottl) --- sys/alpha/alpha/mp_machdep.c | 67 +++++++++++++++++++++----------- sys/amd64/amd64/mp_machdep.c | 25 +++++++++--- sys/i386/i386/mp_machdep.c | 15 ++++--- sys/ia64/ia64/mp_machdep.c | 10 ++++- sys/kern/subr_smp.c | 12 +++--- sys/powerpc/powerpc/mp_machdep.c | 5 +++ sys/sparc64/sparc64/mp_machdep.c | 12 ++++-- sys/sys/smp.h | 6 +++ 8 files changed, 106 insertions(+), 46 deletions(-) diff --git a/sys/alpha/alpha/mp_machdep.c b/sys/alpha/alpha/mp_machdep.c index 914410c4887..d3a646023a4 100644 --- a/sys/alpha/alpha/mp_machdep.c +++ b/sys/alpha/alpha/mp_machdep.c @@ -64,6 +64,7 @@ static struct mtx ap_boot_mtx; u_int boot_cpu_id; static void release_aps(void *dummy); +static int smp_cpu_enabled(struct pcs *pcsp); extern void smp_init_secondary_glue(void); static int smp_send_secondary_command(const char *command, int cpuid); static int smp_start_secondary(int cpuid); @@ -301,10 +302,50 @@ smp_start_secondary(int cpuid) /* Other stuff */ +static int +smp_cpu_enabled(struct pcs *pcsp) +{ + + /* Is this CPU present? */ + if ((pcsp->pcs_flags & PCS_PP) == 0) + return (0); + + /* Is this CPU available? */ + if ((pcsp->pcs_flags & PCS_PA) == 0) + /* + * The TurboLaser PCS_PA bit doesn't seem to be set + * correctly. + */ + if (hwrpb->rpb_type != ST_DEC_21000) + return (0); + + /* Is this CPU's PALcode valid? */ + if ((pcsp->pcs_flags & PCS_PV) == 0) + return (0); + + return (1); +} + +void +cpu_mp_setmaxid(void) +{ + int i; + + mp_maxid = 0; + for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { + if (i == PCPU_GET(cpuid)) + continue; + if (!smp_cpu_enabled(LOCATE_PCS(hwrpb, i))) + continue; + if (i > MAXCPU) + continue; + mp_maxid = i; + } +} + int cpu_mp_probe(void) { - struct pcs *pcsp; int i, cpus; /* XXX: Need to check for valid platforms here. */ @@ -315,33 +356,16 @@ cpu_mp_probe(void) all_cpus = 1 << boot_cpu_id; mp_ncpus = 1; - mp_maxid = 0; /* Make sure we have at least one secondary CPU. */ cpus = 0; for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { if (i == PCPU_GET(cpuid)) continue; - pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + - (i * hwrpb->rpb_pcs_size)); - if ((pcsp->pcs_flags & PCS_PP) == 0) { + if (!smp_cpu_enabled(LOCATE_PCS(hwrpb, i))) continue; - } - if ((pcsp->pcs_flags & PCS_PA) == 0) { - /* - * The TurboLaser PCS_PA bit doesn't seem to be set - * correctly. - */ - if (hwrpb->rpb_type != ST_DEC_21000) - continue; - } - if ((pcsp->pcs_flags & PCS_PV) == 0) { - continue; - } - if (i > MAXCPU) { + if (i > MAXCPU) continue; - } - mp_maxid = i; cpus++; } return (cpus); @@ -359,8 +383,7 @@ cpu_mp_start(void) if (i == boot_cpu_id) continue; - pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + - (i * hwrpb->rpb_pcs_size)); + pcsp = LOCATE_PCS(hwrpb, i); if ((pcsp->pcs_flags & PCS_PP) == 0) continue; if ((pcsp->pcs_flags & PCS_PA) == 0) { diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c index 3b46b3f04ec..0d4ddf8e553 100644 --- a/sys/amd64/amd64/mp_machdep.c +++ b/sys/amd64/amd64/mp_machdep.c @@ -187,6 +187,26 @@ cpu_add(u_int apic_id, char boot_cpu) } +void +cpu_mp_setmaxid(void) +{ + + /* + * mp_maxid should be already set by calls to cpu_add(). + * Just sanity check its value here. + */ + if (mp_ncpus == 0) + KASSERT(mp_maxid == 0, + ("%s: mp_ncpus is zero, but mp_maxid is not", __func__)); + else if (mp_ncpus == 1) + mp_maxid = 0; + else + KASSERT(mp_maxid >= mp_ncpus - 1, + ("%s: counters out of sync: max %d, count %d", __func__, + mp_maxid, mp_ncpus)); + +} + int cpu_mp_probe(void) { @@ -202,8 +222,6 @@ cpu_mp_probe(void) * the variables to represent a system with a single CPU * with an id of 0. */ - KASSERT(mp_maxid == 0, - ("%s: mp_ncpus is zero, but mp_maxid is not", __func__)); mp_ncpus = 1; return (0); } @@ -219,9 +237,6 @@ cpu_mp_probe(void) } /* At least two CPUs were found. */ - KASSERT(mp_maxid >= mp_ncpus - 1, - ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid, - mp_ncpus)); return (1); } diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index f58a94f5583..578eb22548d 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -248,14 +248,19 @@ cpu_add(u_int apic_id, char boot_cpu) cpu_info[apic_id].cpu_bsp = 1; } mp_ncpus++; - if (apic_id > mp_maxid) - mp_maxid = apic_id; if (bootverbose) printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" : "AP"); } +void +cpu_mp_setmaxid(void) +{ + + mp_maxid = MAXCPU; +} + int cpu_mp_probe(void) { @@ -271,8 +276,6 @@ cpu_mp_probe(void) * the variables to represent a system with a single CPU * with an id of 0. */ - KASSERT(mp_maxid == 0, - ("%s: mp_ncpus is zero, but mp_maxid is not", __func__)); mp_ncpus = 1; return (0); } @@ -283,14 +286,10 @@ cpu_mp_probe(void) * One CPU was found, so this must be a UP system with * an I/O APIC. */ - mp_maxid = 0; return (0); } /* At least two CPUs were found. */ - KASSERT(mp_maxid >= mp_ncpus - 1, - ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid, - mp_ncpus)); return (1); } diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index 69bead1ff13..b1e4749f9be 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -132,9 +132,10 @@ ia64_ap_startup(void) /* NOTREACHED */ } -int -cpu_mp_probe() +void +cpu_mp_setmaxid(void) { + /* * Count the number of processors in the system by walking the ACPI * tables. Note that we record the actual number of processors, even @@ -147,6 +148,11 @@ cpu_mp_probe() * VM initialization. */ mp_maxid = min(mp_ncpus, MAXCPU) - 1; +} + +int +cpu_mp_probe(void) +{ /* * If there's only 1 processor, or we don't have a wake-up vector, diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c index 5bb02896d23..b6fd97f737d 100644 --- a/sys/kern/subr_smp.c +++ b/sys/kern/subr_smp.c @@ -92,17 +92,16 @@ static void (*smp_rv_teardown_func)(void *arg); static void *smp_rv_func_arg; static volatile int smp_rv_waiters[2]; static struct mtx smp_rv_mtx; -static int mp_probe_status; /* - * Initialize MI SMP variables. + * Let the MD SMP code initialize mp_maxid very early if it can. */ static void -mp_probe(void *dummy) +mp_setmaxid(void *dummy) { - mp_probe_status = cpu_mp_probe(); + cpu_mp_setmaxid(); } -SYSINIT(cpu_mp_probe, SI_SUB_TUNABLES, SI_ORDER_FIRST, mp_probe, NULL) +SYSINIT(cpu_mp_setmaxid, SI_SUB_TUNABLES, SI_ORDER_FIRST, mp_setmaxid, NULL) /* * Call the MD SMP initialization code. @@ -112,8 +111,9 @@ mp_start(void *dummy) { /* Probe for MP hardware. */ - if (mp_probe_status == 0 || smp_disabled != 0) { + if (smp_disabled != 0 || cpu_mp_probe() == 0) { mp_ncpus = 1; + all_cpus = PCPU_GET(cpumask); return; } diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c index 685c3e00278..54af2323677 100644 --- a/sys/powerpc/powerpc/mp_machdep.c +++ b/sys/powerpc/powerpc/mp_machdep.c @@ -47,6 +47,11 @@ int boot_cpu_id; +void +cpu_mp_setmaxid(void) +{ +} + int cpu_mp_probe(void) { diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c index 967ac5a69ee..c26f6f75d64 100644 --- a/sys/sparc64/sparc64/mp_machdep.c +++ b/sys/sparc64/sparc64/mp_machdep.c @@ -140,8 +140,8 @@ mp_tramp_alloc(void) /* * Probe for other cpus. */ -int -cpu_mp_probe(void) +void +cpu_mp_setmaxid(void) { phandle_t child; phandle_t root; @@ -160,7 +160,13 @@ cpu_mp_probe(void) cpus++; } mp_maxid = cpus; - return (cpus > 1); +} + +int +cpu_mp_probe(void) +{ + + return (mp_maxid > 1); } static void diff --git a/sys/sys/smp.h b/sys/sys/smp.h index 277e879bd41..24ef3670b3e 100644 --- a/sys/sys/smp.h +++ b/sys/sys/smp.h @@ -74,11 +74,17 @@ extern u_int mp_maxid; * executed and a simple message will be output to the console. Finally, * cpu_mp_announce() will be called so that machine dependent messages about * the MP support may be output to the console if desired. + * + * The cpu_setmaxid() function is called very early during the boot process + * so that the MD code may set mp_maxid to provide an upper bound on CPU IDs + * that other subsystems may use. If a platform is not able to determine + * the exact maximum ID that early, then it may set mp_maxid to MAXCPU. */ struct thread; void cpu_mp_announce(void); int cpu_mp_probe(void); +void cpu_mp_setmaxid(void); void cpu_mp_start(void); void forward_signal(struct thread *); -- 2.45.2