// SPDX-License-Identifier: GPL-2.0 /* Sparc SS1000/SC2000 SMP support. * * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * * Based on sun4m's smp.c, which is: * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
*/
void sun4d_cpu_pre_starting(void *arg)
{ int cpuid = hard_smp_processor_id();
/* Show we are alive */
cpu_leds[cpuid] = 0x6;
show_leds(cpuid);
/* Enable level15 interrupt, disable level14 interrupt for now */
cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
}
void sun4d_cpu_pre_online(void *arg)
{ unsignedlong flags; int cpuid;
cpuid = hard_smp_processor_id();
/* Unblock the master CPU _only_ when the scheduler state * of all secondary CPUs will be up-to-date, so after * the SMP initialization the master will be just allowed * to call the scheduler code.
*/
sun4d_swap((unsignedlong *)&cpu_callin_map[cpuid], 1);
local_ops->cache_all();
local_ops->tlb_all();
while ((unsignedlong)current_set[cpuid] < PAGE_OFFSET)
barrier();
while (current_set[cpuid]->cpu != cpuid)
barrier();
/* Attach to the address space of init_task. */
mmgrab(&init_mm);
current->active_mm = &init_mm;
local_ops->cache_all();
local_ops->tlb_all();
while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
barrier();
spin_lock_irqsave(&sun4d_imsk_lock, flags);
cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
}
/* * Cycle through the processors asking the PROM to start each one.
*/ void __init smp4d_boot_cpus(void)
{
smp4d_ipi_init(); if (boot_cpu_id)
current_set[0] = NULL;
local_ops->cache_all();
}
int smp4d_boot_one_cpu(int i, struct task_struct *idle)
{ unsignedlong *entry = &sun4d_cpu_startup; int timeout; int cpu_node;
cpu_find_by_instance(i, &cpu_node, NULL);
current_set[i] = task_thread_info(idle); /* * Initialize the contexts table * Since the call to prom_startcpu() trashes the structure, * we need to re-initialize it for each cpu
*/
smp_penguin_ctable.which_io = 0;
smp_penguin_ctable.phys_addr = (unsignedint) srmmu_ctx_table_phys;
smp_penguin_ctable.reg_size = 0;
/* whirrr, whirrr, whirrrrrrrrr... */
printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
local_ops->cache_all();
prom_startcpu(cpu_node,
&smp_penguin_ctable, 0, (char *)entry);
printk(KERN_INFO "prom_startcpu returned :)\n");
/* wheee... it's going... */ for (timeout = 0; timeout < 10000; timeout++) { if (cpu_callin_map[i]) break;
udelay(200);
}
if (!(cpu_callin_map[i])) {
printk(KERN_ERR "Processor %d is stuck.\n", i); return -ENODEV;
}
local_ops->cache_all(); return 0;
}
void __init smp4d_smp_done(void)
{ int i, first; int *prev;
/* setup cpu list for irq rotation */
first = 0;
prev = &first;
for_each_online_cpu(i) {
*prev = i;
prev = &cpu_data(i).next;
}
*prev = first;
local_ops->cache_all();
/* Ok, they are spinning and ready to go. */
smp_processors_ready = 1;
sun4d_distribute_irqs();
}
/* Memory structure giving interrupt handler information about IPI generated */ struct sun4d_ipi_work { int single; int msk; int resched;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.