- Adjust some whitespace to reduce diffs with the i386 version.
- Rename the per-CPU variable 'cpuno' to 'cpuid'. This was done so that there is one consistent name across all architectures for a logical CPU id. - Remove all traces of IRQ forwarding. - Add globaldata_register() hook called by globaldata_init() to register globaldata structures in the cpuid_to_globaldata array. - Catch up to P_FOO -> PS_FOO. - Bring across some fixes for forwarded_statclock() from the i386 version to handle ithreads and idleproc properly. - Rename addugd_intr_forwarded() to addupc_intr_forwarded() so that it is the same name on all architectures. - Set flags in p_sflag instead of calling psignal() from forward_hardclock(). - Proc locking. - When we handle an IPI, turn off its bit in the mask of IPI's we are currently handling so that an IPI doesn't send a CPU into an infinite loop.
This commit is contained in:
parent
a1ce5e9db8
commit
277ef6eaf3
@ -55,32 +55,27 @@
|
||||
#define CHECKSTATE_SYS 1
|
||||
#define CHECKSTATE_INTR 2
|
||||
|
||||
volatile u_int stopped_cpus;
|
||||
volatile u_int started_cpus;
|
||||
volatile u_int checkstate_probed_cpus;
|
||||
volatile u_int checkstate_need_ast;
|
||||
volatile u_int checkstate_pending_ast;
|
||||
struct proc* checkstate_curproc[MAXCPU];
|
||||
int checkstate_cpustate[MAXCPU];
|
||||
u_long checkstate_pc[MAXCPU];
|
||||
volatile u_int resched_cpus;
|
||||
volatile u_int stopped_cpus;
|
||||
volatile u_int started_cpus;
|
||||
volatile u_int checkstate_probed_cpus;
|
||||
volatile u_int checkstate_need_ast;
|
||||
volatile u_int checkstate_pending_ast;
|
||||
struct proc* checkstate_curproc[MAXCPU];
|
||||
int checkstate_cpustate[MAXCPU];
|
||||
u_long checkstate_pc[MAXCPU];
|
||||
volatile u_int resched_cpus;
|
||||
void (*cpustop_restartfunc) __P((void));
|
||||
int mp_ncpus;
|
||||
int mp_ncpus;
|
||||
|
||||
int smp_started;
|
||||
int boot_cpu_id;
|
||||
u_int32_t all_cpus;
|
||||
int smp_started;
|
||||
int boot_cpu_id;
|
||||
u_int32_t all_cpus;
|
||||
|
||||
static struct globaldata *cpuno_to_globaldata[MAXCPU];
|
||||
static struct globaldata *cpuid_to_globaldata[MAXCPU];
|
||||
|
||||
int smp_active = 0; /* are the APs allowed to run? */
|
||||
SYSCTL_INT(_machdep, OID_AUTO, smp_active, CTLFLAG_RW, &smp_active, 0, "");
|
||||
|
||||
/* Is forwarding of a interrupt to the CPU holding the ISR lock enabled ? */
|
||||
int forward_irq_enabled = 1;
|
||||
SYSCTL_INT(_machdep, OID_AUTO, forward_irq_enabled, CTLFLAG_RW,
|
||||
&forward_irq_enabled, 0, "");
|
||||
|
||||
/* Enable forwarding of a signal to a process running on a different CPU */
|
||||
static int forward_signal_enabled = 1;
|
||||
SYSCTL_INT(_machdep, OID_AUTO, forward_signal_enabled, CTLFLAG_RW,
|
||||
@ -96,10 +91,10 @@ SYSCTL_INT(_machdep, OID_AUTO, forward_roundrobin_enabled, CTLFLAG_RW,
|
||||
* Return 1 on failure.
|
||||
*/
|
||||
static int
|
||||
smp_send_secondary_command(const char *command, int cpuno)
|
||||
smp_send_secondary_command(const char *command, int cpuid)
|
||||
{
|
||||
u_int64_t mask = 1L << cpuno;
|
||||
struct pcs *cpu = LOCATE_PCS(hwrpb, cpuno);
|
||||
u_int64_t mask = 1L << cpuid;
|
||||
struct pcs *cpu = LOCATE_PCS(hwrpb, cpuid);
|
||||
int i, len;
|
||||
|
||||
/*
|
||||
@ -176,8 +171,8 @@ smp_init_secondary(void)
|
||||
* Add to mask.
|
||||
*/
|
||||
smp_started = 1;
|
||||
if (PCPU_GET(cpuno) + 1 > mp_ncpus)
|
||||
mp_ncpus = PCPU_GET(cpuno) + 1;
|
||||
if (PCPU_GET(cpuid) + 1 > mp_ncpus)
|
||||
mp_ncpus = PCPU_GET(cpuid) + 1;
|
||||
spl0();
|
||||
smp_ipi_all(0);
|
||||
|
||||
@ -187,9 +182,9 @@ smp_init_secondary(void)
|
||||
extern void smp_init_secondary_glue(void);
|
||||
|
||||
static int
|
||||
smp_start_secondary(int cpuno)
|
||||
smp_start_secondary(int cpuid)
|
||||
{
|
||||
struct pcs *cpu = LOCATE_PCS(hwrpb, cpuno);
|
||||
struct pcs *cpu = LOCATE_PCS(hwrpb, cpuid);
|
||||
struct pcs *bootcpu = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id);
|
||||
struct alpha_pcb *pcb = (struct alpha_pcb *) cpu->pcs_hwpcb;
|
||||
struct globaldata *globaldata;
|
||||
@ -197,11 +192,11 @@ smp_start_secondary(int cpuno)
|
||||
size_t sz;
|
||||
|
||||
if ((cpu->pcs_flags & PCS_PV) == 0) {
|
||||
printf("smp_start_secondary: cpu %d PALcode invalid\n", cpuno);
|
||||
printf("smp_start_secondary: cpu %d PALcode invalid\n", cpuid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("smp_start_secondary: starting cpu %d\n", cpuno);
|
||||
printf("smp_start_secondary: starting cpu %d\n", cpuid);
|
||||
|
||||
sz = round_page(UPAGES * PAGE_SIZE);
|
||||
globaldata = malloc(sz, M_TEMP, M_NOWAIT);
|
||||
@ -210,7 +205,7 @@ smp_start_secondary(int cpuno)
|
||||
return 0;
|
||||
}
|
||||
|
||||
globaldata_init(globaldata, cpuno, sz);
|
||||
globaldata_init(globaldata, cpuid, sz);
|
||||
|
||||
/*
|
||||
* Copy the idle pcb and setup the address to start executing.
|
||||
@ -239,7 +234,7 @@ smp_start_secondary(int cpuno)
|
||||
/*
|
||||
* Fire it up and hope for the best.
|
||||
*/
|
||||
if (!smp_send_secondary_command("START\r\n", cpuno)) {
|
||||
if (!smp_send_secondary_command("START\r\n", cpuid)) {
|
||||
printf("smp_init_secondary: can't send START command\n");
|
||||
free(globaldata, M_TEMP);
|
||||
return 0;
|
||||
@ -262,34 +257,24 @@ smp_start_secondary(int cpuno)
|
||||
* It worked (I think).
|
||||
*/
|
||||
/* if (bootverbose) */
|
||||
printf("smp_init_secondary: cpu %d started\n", cpuno);
|
||||
printf("smp_init_secondary: cpu %d started\n", cpuid);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise a struct globaldata.
|
||||
* Register a struct globaldata.
|
||||
*/
|
||||
void
|
||||
globaldata_init(struct globaldata *globaldata, int cpuno, size_t sz)
|
||||
globaldata_register(struct globaldata *globaldata)
|
||||
{
|
||||
bzero(globaldata, sz);
|
||||
globaldata->gd_idlepcbphys = vtophys((vm_offset_t) &globaldata->gd_idlepcb);
|
||||
globaldata->gd_idlepcb.apcb_ksp = (u_int64_t)
|
||||
((caddr_t) globaldata + sz - sizeof(struct trapframe));
|
||||
globaldata->gd_idlepcb.apcb_ptbr = proc0.p_addr->u_pcb.pcb_hw.apcb_ptbr;
|
||||
globaldata->gd_cpuno = cpuno;
|
||||
globaldata->gd_other_cpus = all_cpus & ~(1 << cpuno);
|
||||
globaldata->gd_next_asn = 0;
|
||||
globaldata->gd_current_asngen = 1;
|
||||
globaldata->gd_cpuid = cpuno;
|
||||
cpuno_to_globaldata[cpuno] = globaldata;
|
||||
cpuid_to_globaldata[globaldata->cpuid] = globaldata;
|
||||
}
|
||||
|
||||
struct globaldata *
|
||||
globaldata_find(int cpuno)
|
||||
globaldata_find(int cpuid)
|
||||
{
|
||||
return cpuno_to_globaldata[cpuno];
|
||||
return cpuid_to_globaldata[cpuid];
|
||||
}
|
||||
|
||||
/* Implementation of simplelocks */
|
||||
@ -384,18 +369,18 @@ void
|
||||
mp_start()
|
||||
{
|
||||
int i;
|
||||
int cpuno = PCPU_GET(cpuno);
|
||||
int cpuid = PCPU_GET(cpuid);
|
||||
|
||||
init_locks();
|
||||
|
||||
if (cpuno + 1 > mp_ncpus)
|
||||
mp_ncpus = cpuno + 1;
|
||||
if (cpuid + 1 > mp_ncpus)
|
||||
mp_ncpus = cpuid + 1;
|
||||
|
||||
all_cpus = 1<<cpuno;
|
||||
all_cpus = 1<<cpuid;
|
||||
for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
|
||||
struct pcs *pcsp;
|
||||
|
||||
if (i == cpuno)
|
||||
if (i == cpuid)
|
||||
continue;
|
||||
pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off +
|
||||
(i * hwrpb->rpb_pcs_size));
|
||||
@ -404,12 +389,12 @@ mp_start()
|
||||
break; /* only one for now */
|
||||
}
|
||||
}
|
||||
PCPU_SET(other_cpus, all_cpus & ~(1<<cpuno));
|
||||
PCPU_SET(other_cpus, all_cpus & ~(1<<cpuid));
|
||||
|
||||
for (i = 0; i < hwrpb->rpb_pcs_cnt; i++) {
|
||||
struct pcs *pcsp;
|
||||
|
||||
if (i == cpuno)
|
||||
if (i == cpuid)
|
||||
continue;
|
||||
pcsp = (struct pcs *)((char *)hwrpb + hwrpb->rpb_pcs_off +
|
||||
(i * hwrpb->rpb_pcs_size));
|
||||
@ -436,7 +421,7 @@ smp_invltlb()
|
||||
(u_quad_t)((prof)->pr_scale)) >> 16) & ~1)
|
||||
|
||||
static void
|
||||
addugd_intr_forwarded(struct proc *p, int id, int *astmap)
|
||||
addupc_intr_forwarded(struct proc *p, int id, int *astmap)
|
||||
{
|
||||
int i;
|
||||
struct uprof *prof;
|
||||
@ -446,10 +431,10 @@ addugd_intr_forwarded(struct proc *p, int id, int *astmap)
|
||||
prof = &p->p_stats->p_prof;
|
||||
if (pc >= prof->pr_off &&
|
||||
(i = GD_TO_INDEX(pc, prof)) < prof->pr_size) {
|
||||
if ((p->p_flag & P_OWEUPC) == 0) {
|
||||
if ((p->p_sflag & PS_OWEUPC) == 0) {
|
||||
prof->pr_addr = pc;
|
||||
prof->pr_ticks = 1;
|
||||
p->p_flag |= P_OWEUPC;
|
||||
p->p_sflag |= PS_OWEUPC;
|
||||
}
|
||||
*astmap |= (1 << id);
|
||||
}
|
||||
@ -472,10 +457,16 @@ forwarded_statclock(int id, int pscnt, int *astmap)
|
||||
p = checkstate_curproc[id];
|
||||
cpustate = checkstate_cpustate[id];
|
||||
|
||||
/* XXX */
|
||||
if (p->p_ithd)
|
||||
cpustate = CHECKSTATE_INTR;
|
||||
else if (p == cpuid_to_globaldata[id]->gd_idleproc)
|
||||
cpustate = CHECKSTATE_SYS;
|
||||
|
||||
switch (cpustate) {
|
||||
case CHECKSTATE_USER:
|
||||
if (p->p_flag & P_PROFIL)
|
||||
addugd_intr_forwarded(p, id, astmap);
|
||||
if (p->p_sflag & PS_PROFIL)
|
||||
addupc_intr_forwarded(p, id, astmap);
|
||||
if (pscnt > 1)
|
||||
return;
|
||||
p->p_uticks++;
|
||||
@ -487,7 +478,7 @@ forwarded_statclock(int id, int pscnt, int *astmap)
|
||||
case CHECKSTATE_SYS:
|
||||
#ifdef GPROF
|
||||
/*
|
||||
* Kernel statistics are just like addugd_intr, only easier.
|
||||
* Kernel statistics are just like addupc_intr, only easier.
|
||||
*/
|
||||
g = &_gmonparam;
|
||||
if (g->state == GMON_PROF_ON) {
|
||||
@ -501,18 +492,17 @@ forwarded_statclock(int id, int pscnt, int *astmap)
|
||||
if (pscnt > 1)
|
||||
return;
|
||||
|
||||
if (!p)
|
||||
p->p_sticks++;
|
||||
if (p == cpuid_to_globaldata[id]->gd_idleproc)
|
||||
cp_time[CP_IDLE]++;
|
||||
else {
|
||||
p->p_sticks++;
|
||||
else
|
||||
cp_time[CP_SYS]++;
|
||||
}
|
||||
break;
|
||||
case CHECKSTATE_INTR:
|
||||
default:
|
||||
#ifdef GPROF
|
||||
/*
|
||||
* Kernel statistics are just like addugd_intr, only easier.
|
||||
* Kernel statistics are just like addupc_intr, only easier.
|
||||
*/
|
||||
g = &_gmonparam;
|
||||
if (g->state == GMON_PROF_ON) {
|
||||
@ -525,25 +515,24 @@ forwarded_statclock(int id, int pscnt, int *astmap)
|
||||
#endif
|
||||
if (pscnt > 1)
|
||||
return;
|
||||
if (p)
|
||||
p->p_iticks++;
|
||||
KASSERT(p != NULL, ("NULL process in interrupt state"));
|
||||
p->p_iticks++;
|
||||
cp_time[CP_INTR]++;
|
||||
}
|
||||
if (p != NULL) {
|
||||
schedclock(p);
|
||||
|
||||
schedclock(p);
|
||||
|
||||
/* Update resource usage integrals and maximums. */
|
||||
if ((pstats = p->p_stats) != NULL &&
|
||||
(ru = &pstats->p_ru) != NULL &&
|
||||
(vm = p->p_vmspace) != NULL) {
|
||||
ru->ru_ixrss += pgtok(vm->vm_tsize);
|
||||
ru->ru_idrss += pgtok(vm->vm_dsize);
|
||||
ru->ru_isrss += pgtok(vm->vm_ssize);
|
||||
rss = pgtok(vmspace_resident_count(vm));
|
||||
if (ru->ru_maxrss < rss)
|
||||
ru->ru_maxrss = rss;
|
||||
}
|
||||
}
|
||||
/* Update resource usage integrals and maximums. */
|
||||
if ((pstats = p->p_stats) != NULL &&
|
||||
(ru = &pstats->p_ru) != NULL &&
|
||||
(vm = p->p_vmspace) != NULL) {
|
||||
ru->ru_ixrss += pgtok(vm->vm_tsize);
|
||||
ru->ru_idrss += pgtok(vm->vm_dsize);
|
||||
ru->ru_isrss += pgtok(vm->vm_ssize);
|
||||
rss = pgtok(vmspace_resident_count(vm));
|
||||
if (ru->ru_maxrss < rss)
|
||||
ru->ru_maxrss = rss;
|
||||
}
|
||||
}
|
||||
|
||||
#define BETTER_CLOCK_DIAGNOSTIC
|
||||
@ -686,12 +675,12 @@ forward_hardclock(int pscnt)
|
||||
if (checkstate_cpustate[id] == CHECKSTATE_USER &&
|
||||
timevalisset(&pstats->p_timer[ITIMER_VIRTUAL].it_value) &&
|
||||
itimerdecr(&pstats->p_timer[ITIMER_VIRTUAL], tick) == 0) {
|
||||
psignal(p, SIGVTALRM);
|
||||
p->p_sflag |= PS_ALRMPEND;
|
||||
map |= (1 << id);
|
||||
}
|
||||
if (timevalisset(&pstats->p_timer[ITIMER_PROF].it_value) &&
|
||||
itimerdecr(&pstats->p_timer[ITIMER_PROF], tick) == 0) {
|
||||
psignal(p, SIGPROF);
|
||||
p->p_sflag |= PS_PROFPEND;
|
||||
map |= (1 << id);
|
||||
}
|
||||
}
|
||||
@ -741,10 +730,14 @@ forward_signal(struct proc *p)
|
||||
return;
|
||||
if (!forward_signal_enabled)
|
||||
return;
|
||||
mtx_enter(&sched_lock, MTX_SPIN);
|
||||
while (1) {
|
||||
if (p->p_stat != SRUN)
|
||||
if (p->p_stat != SRUN) {
|
||||
mtx_exit(&sched_lock, MTX_SPIN);
|
||||
return;
|
||||
}
|
||||
id = p->p_oncpu;
|
||||
mtx_exit(&sched_lock, MTX_SPIN);
|
||||
if (id == 0xff)
|
||||
return;
|
||||
map = (1<<id);
|
||||
@ -762,8 +755,11 @@ forward_signal(struct proc *p)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (id == p->p_oncpu)
|
||||
mtx_enter(&sched_lock, MTX_SPIN);
|
||||
if (id == p->p_oncpu) {
|
||||
mtx_exit(&sched_lock, MTX_SPIN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -957,15 +953,15 @@ smp_ipi_selected(u_int32_t cpus, u_int64_t ipi)
|
||||
CTR2(KTR_SMP, "smp_ipi_selected: cpus: %x ipi: %lx", cpus, ipi);
|
||||
alpha_mb();
|
||||
while (cpus) {
|
||||
int cpuno = ffs(cpus) - 1;
|
||||
cpus &= ~(1 << cpuno);
|
||||
int cpuid = ffs(cpus) - 1;
|
||||
cpus &= ~(1 << cpuid);
|
||||
|
||||
globaldata = cpuno_to_globaldata[cpuno];
|
||||
globaldata = cpuid_to_globaldata[cpuid];
|
||||
if (globaldata) {
|
||||
atomic_set_64(&globaldata->gd_pending_ipis, ipi);
|
||||
alpha_mb();
|
||||
CTR1(KTR_SMP, "calling alpha_pal_wripir(%d)", cpuno);
|
||||
alpha_pal_wripir(cpuno);
|
||||
CTR1(KTR_SMP, "calling alpha_pal_wripir(%d)", cpuid);
|
||||
alpha_pal_wripir(cpuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -994,7 +990,7 @@ smp_ipi_all_but_self(u_int64_t ipi)
|
||||
void
|
||||
smp_ipi_self(u_int64_t ipi)
|
||||
{
|
||||
smp_ipi_selected(1 << PCPU_GET(cpuno), ipi);
|
||||
smp_ipi_selected(1 << PCPU_GET(cpuid), ipi);
|
||||
}
|
||||
|
||||
static u_int64_t
|
||||
@ -1024,7 +1020,9 @@ smp_handle_ipi(struct trapframe *frame)
|
||||
{
|
||||
u_int64_t ipis = atomic_readandclear(PCPU_PTR(pending_ipis));
|
||||
u_int64_t ipi;
|
||||
int cpuno = PCPU_GET(cpuno);
|
||||
int cpumask;
|
||||
|
||||
cpumask = 1 << PCPU_GET(cpuid);
|
||||
|
||||
CTR1(KTR_SMP, "smp_handle_ipi(), ipis=%lx", ipis);
|
||||
while (ipis) {
|
||||
@ -1032,6 +1030,7 @@ smp_handle_ipi(struct trapframe *frame)
|
||||
* Find the lowest set bit.
|
||||
*/
|
||||
ipi = ipis & ~(ipis - 1);
|
||||
ipis &= ~ipi;
|
||||
switch (ipi) {
|
||||
case IPI_INVLTLB:
|
||||
break;
|
||||
@ -1043,8 +1042,8 @@ smp_handle_ipi(struct trapframe *frame)
|
||||
|
||||
case IPI_AST:
|
||||
CTR0(KTR_SMP, "IPI_AST");
|
||||
atomic_clear_int(&checkstate_need_ast, 1<<cpuno);
|
||||
atomic_set_int(&checkstate_pending_ast, 1<<cpuno);
|
||||
atomic_clear_int(&checkstate_need_ast, cpumask);
|
||||
atomic_set_int(&checkstate_pending_ast, cpumask);
|
||||
if (frame->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE)
|
||||
ast(frame); /* XXX */
|
||||
break;
|
||||
@ -1052,22 +1051,22 @@ smp_handle_ipi(struct trapframe *frame)
|
||||
case IPI_CHECKSTATE:
|
||||
CTR0(KTR_SMP, "IPI_CHECKSTATE");
|
||||
if (frame->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE)
|
||||
checkstate_cpustate[cpuno] = CHECKSTATE_USER;
|
||||
checkstate_cpustate[cpuid] = CHECKSTATE_USER;
|
||||
else if (curproc->p_intr_nesting_level == 1)
|
||||
checkstate_cpustate[cpuno] = CHECKSTATE_SYS;
|
||||
checkstate_cpustate[cpuid] = CHECKSTATE_SYS;
|
||||
else
|
||||
checkstate_cpustate[cpuno] = CHECKSTATE_INTR;
|
||||
checkstate_curproc[cpuno] = PCPU_GET(curproc);
|
||||
atomic_set_int(&checkstate_probed_cpus, 1<<cpuno);
|
||||
checkstate_cpustate[cpuid] = CHECKSTATE_INTR;
|
||||
checkstate_curproc[cpuid] = PCPU_GET(curproc);
|
||||
atomic_set_int(&checkstate_probed_cpus, cpumask);
|
||||
break;
|
||||
|
||||
case IPI_STOP:
|
||||
CTR0(KTR_SMP, "IPI_STOP");
|
||||
atomic_set_int(&stopped_cpus, 1<<cpuno);
|
||||
while ((started_cpus & (1<<cpuno)) == 0)
|
||||
atomic_set_int(&stopped_cpus, cpumask);
|
||||
while ((started_cpus & cpumask) == 0)
|
||||
alpha_mb();
|
||||
atomic_clear_int(&started_cpus, 1<<cpuno);
|
||||
atomic_clear_int(&stopped_cpus, 1<<cpuno);
|
||||
atomic_clear_int(&started_cpus, cpumask);
|
||||
atomic_clear_int(&stopped_cpus, cpumask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1075,7 +1074,7 @@ smp_handle_ipi(struct trapframe *frame)
|
||||
/*
|
||||
* Drop console messages on the floor.
|
||||
*/
|
||||
if (PCPU_GET(cpuno) == hwrpb->rpb_primary_cpu_id
|
||||
if (PCPU_GET(cpuid) == hwrpb->rpb_primary_cpu_id
|
||||
&& hwrpb->rpb_txrdy != 0) {
|
||||
hwrpb->rpb_txrdy = 0;
|
||||
alpha_mb();
|
||||
|
Loading…
x
Reference in New Issue
Block a user