ia64: Move MCA information retrieval to a per-CPU kthread

Once AP's are launched, their MCA state information is stored and later obtainable using a sysctl. Since the size of the MCA state information is unknown, it will be malloc'ed as needed. However, when 'ia64_ap_startup' runs, it's not yet safe to call malloc and this may cause 'panic: blockable sleep lock (sleep mutex) 8192 @ /usr/src/sys/vm/uma_core.c'. This commit avoids this issue by scheduling a separate kthread to obtain this information, which immediately terminates afterwards.
This commit is contained in:
rink 2009-05-27 18:12:27 +00:00
parent 095c1f19b6
commit 1843497c73

View File

@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ktr.h>
#include <sys/proc.h>
#include <sys/bus.h>
#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@ -89,6 +90,28 @@ cpu_topo(void)
return smp_topo_none();
}
static void
ia64_store_mca_state(void* arg)
{
unsigned int ncpu = (unsigned int)(uintptr_t)arg;
struct thread* td;
/* ia64_mca_save_state() is CPU-sensitive, so bind ourself to our target CPU */
td = curthread;
thread_lock(td);
sched_bind(td, ncpu);
thread_unlock(td);
/*
* Get and save the CPU specific MCA records. Should we get the
* MCA state for each processor, or just the CMC state?
*/
ia64_mca_save_state(SAL_INFO_MCA);
ia64_mca_save_state(SAL_INFO_CMC);
kproc_exit(0);
}
void
ia64_ap_startup(void)
{
@ -118,13 +141,6 @@ ia64_ap_startup(void)
KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
PCPU_SET(curthread, PCPU_GET(idlethread));
/*
* Get and save the CPU specific MCA records. Should we get the
* MCA state for each processor, or just the CMC state?
*/
ia64_mca_save_state(SAL_INFO_MCA);
ia64_mca_save_state(SAL_INFO_CMC);
atomic_add_int(&ap_awake, 1);
while (!smp_started)
cpu_spinwait();
@ -285,8 +301,10 @@ cpu_mp_unleash(void *dummy)
smp_cpus = 0;
SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
cpus++;
if (pc->pc_awake)
if (pc->pc_awake) {
kproc_create(ia64_store_mca_state, (void*)((uintptr_t)pc->pc_cpuid), NULL, 0, 0, "mca %u", pc->pc_cpuid);
smp_cpus++;
}
}
ap_awake = 1;