- 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)
This commit is contained in:
jhb 2003-11-21 22:23:26 +00:00
parent e90ec154d7
commit bbe7d290ea
8 changed files with 106 additions and 46 deletions

View File

@ -64,6 +64,7 @@ static struct mtx ap_boot_mtx;
u_int boot_cpu_id; u_int boot_cpu_id;
static void release_aps(void *dummy); static void release_aps(void *dummy);
static int smp_cpu_enabled(struct pcs *pcsp);
extern void smp_init_secondary_glue(void); extern void smp_init_secondary_glue(void);
static int smp_send_secondary_command(const char *command, int cpuid); static int smp_send_secondary_command(const char *command, int cpuid);
static int smp_start_secondary(int cpuid); static int smp_start_secondary(int cpuid);
@ -301,10 +302,50 @@ smp_start_secondary(int cpuid)
/* Other stuff */ /* 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 int
cpu_mp_probe(void) cpu_mp_probe(void)
{ {
struct pcs *pcsp;
int i, cpus; int i, cpus;
/* XXX: Need to check for valid platforms here. */ /* XXX: Need to check for valid platforms here. */
@ -315,33 +356,16 @@ cpu_mp_probe(void)
all_cpus = 1 << boot_cpu_id; all_cpus = 1 << boot_cpu_id;
mp_ncpus = 1; mp_ncpus = 1;
mp_maxid = 0;
/* Make sure we have at least one secondary CPU. */ /* Make sure we have at least one secondary CPU. */
cpus = 0; cpus = 0;
for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) { for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
if (i == PCPU_GET(cpuid)) if (i == PCPU_GET(cpuid))
continue; continue;
pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + if (!smp_cpu_enabled(LOCATE_PCS(hwrpb, i)))
(i * hwrpb->rpb_pcs_size));
if ((pcsp->pcs_flags & PCS_PP) == 0) {
continue; continue;
} if (i > MAXCPU)
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; continue;
}
if ((pcsp->pcs_flags & PCS_PV) == 0) {
continue;
}
if (i > MAXCPU) {
continue;
}
mp_maxid = i;
cpus++; cpus++;
} }
return (cpus); return (cpus);
@ -359,8 +383,7 @@ cpu_mp_start(void)
if (i == boot_cpu_id) if (i == boot_cpu_id)
continue; continue;
pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off + pcsp = LOCATE_PCS(hwrpb, i);
(i * hwrpb->rpb_pcs_size));
if ((pcsp->pcs_flags & PCS_PP) == 0) if ((pcsp->pcs_flags & PCS_PP) == 0)
continue; continue;
if ((pcsp->pcs_flags & PCS_PA) == 0) { if ((pcsp->pcs_flags & PCS_PA) == 0) {

View File

@ -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 int
cpu_mp_probe(void) cpu_mp_probe(void)
{ {
@ -202,8 +222,6 @@ cpu_mp_probe(void)
* the variables to represent a system with a single CPU * the variables to represent a system with a single CPU
* with an id of 0. * with an id of 0.
*/ */
KASSERT(mp_maxid == 0,
("%s: mp_ncpus is zero, but mp_maxid is not", __func__));
mp_ncpus = 1; mp_ncpus = 1;
return (0); return (0);
} }
@ -219,9 +237,6 @@ cpu_mp_probe(void)
} }
/* At least two CPUs were found. */ /* 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); return (1);
} }

View File

@ -248,14 +248,19 @@ cpu_add(u_int apic_id, char boot_cpu)
cpu_info[apic_id].cpu_bsp = 1; cpu_info[apic_id].cpu_bsp = 1;
} }
mp_ncpus++; mp_ncpus++;
if (apic_id > mp_maxid)
mp_maxid = apic_id;
if (bootverbose) if (bootverbose)
printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" : printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" :
"AP"); "AP");
} }
void
cpu_mp_setmaxid(void)
{
mp_maxid = MAXCPU;
}
int int
cpu_mp_probe(void) cpu_mp_probe(void)
{ {
@ -271,8 +276,6 @@ cpu_mp_probe(void)
* the variables to represent a system with a single CPU * the variables to represent a system with a single CPU
* with an id of 0. * with an id of 0.
*/ */
KASSERT(mp_maxid == 0,
("%s: mp_ncpus is zero, but mp_maxid is not", __func__));
mp_ncpus = 1; mp_ncpus = 1;
return (0); return (0);
} }
@ -283,14 +286,10 @@ cpu_mp_probe(void)
* One CPU was found, so this must be a UP system with * One CPU was found, so this must be a UP system with
* an I/O APIC. * an I/O APIC.
*/ */
mp_maxid = 0;
return (0); return (0);
} }
/* At least two CPUs were found. */ /* 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); return (1);
} }

View File

@ -132,9 +132,10 @@ ia64_ap_startup(void)
/* NOTREACHED */ /* NOTREACHED */
} }
int void
cpu_mp_probe() cpu_mp_setmaxid(void)
{ {
/* /*
* Count the number of processors in the system by walking the ACPI * Count the number of processors in the system by walking the ACPI
* tables. Note that we record the actual number of processors, even * tables. Note that we record the actual number of processors, even
@ -147,6 +148,11 @@ cpu_mp_probe()
* VM initialization. * VM initialization.
*/ */
mp_maxid = min(mp_ncpus, MAXCPU) - 1; 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, * If there's only 1 processor, or we don't have a wake-up vector,

View File

@ -92,17 +92,16 @@ static void (*smp_rv_teardown_func)(void *arg);
static void *smp_rv_func_arg; static void *smp_rv_func_arg;
static volatile int smp_rv_waiters[2]; static volatile int smp_rv_waiters[2];
static struct mtx smp_rv_mtx; 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 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. * Call the MD SMP initialization code.
@ -112,8 +111,9 @@ mp_start(void *dummy)
{ {
/* Probe for MP hardware. */ /* Probe for MP hardware. */
if (mp_probe_status == 0 || smp_disabled != 0) { if (smp_disabled != 0 || cpu_mp_probe() == 0) {
mp_ncpus = 1; mp_ncpus = 1;
all_cpus = PCPU_GET(cpumask);
return; return;
} }

View File

@ -47,6 +47,11 @@
int boot_cpu_id; int boot_cpu_id;
void
cpu_mp_setmaxid(void)
{
}
int int
cpu_mp_probe(void) cpu_mp_probe(void)
{ {

View File

@ -140,8 +140,8 @@ mp_tramp_alloc(void)
/* /*
* Probe for other cpus. * Probe for other cpus.
*/ */
int void
cpu_mp_probe(void) cpu_mp_setmaxid(void)
{ {
phandle_t child; phandle_t child;
phandle_t root; phandle_t root;
@ -160,7 +160,13 @@ cpu_mp_probe(void)
cpus++; cpus++;
} }
mp_maxid = cpus; mp_maxid = cpus;
return (cpus > 1); }
int
cpu_mp_probe(void)
{
return (mp_maxid > 1);
} }
static void static void

View File

@ -74,11 +74,17 @@ extern u_int mp_maxid;
* executed and a simple message will be output to the console. Finally, * executed and a simple message will be output to the console. Finally,
* cpu_mp_announce() will be called so that machine dependent messages about * cpu_mp_announce() will be called so that machine dependent messages about
* the MP support may be output to the console if desired. * 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; struct thread;
void cpu_mp_announce(void); void cpu_mp_announce(void);
int cpu_mp_probe(void); int cpu_mp_probe(void);
void cpu_mp_setmaxid(void);
void cpu_mp_start(void); void cpu_mp_start(void);
void forward_signal(struct thread *); void forward_signal(struct thread *);