// SPDX-License-Identifier: GPL-2.0 /* leon_smp.c: Sparc-Leon SMP support. * * based on sun4m_smp.c * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
*/
void leon_cpu_pre_online(void *arg)
{ int cpuid = hard_smp_processor_id();
/* Allow master to continue. The master will then give us the * go-ahead by setting the smp_commenced_mask and will wait without * timeouts until our setup is completed fully (signified by * our bit being set in the cpu_online_mask).
*/
do_swap(&cpu_callin_map[cpuid], 1);
void leon_configure_cache_smp(void)
{ unsignedlong cfg = sparc_leon3_get_dcachecfg(); int me = smp_processor_id();
if (ASI_LEON3_SYSCTRL_CFG_SSIZE(cfg) > 4) {
printk(KERN_INFO "Note: SMP with snooping only works on 4k cache, found %dk(0x%x) on cpu %d, disabling caches\n",
(unsignedint)ASI_LEON3_SYSCTRL_CFG_SSIZE(cfg),
(unsignedint)cfg, (unsignedint)me);
sparc_leon3_disable_cache();
} else { if (cfg & ASI_LEON3_SYSCTRL_CFG_SNOOPING) {
sparc_leon3_enable_snooping();
} else {
printk(KERN_INFO "Note: You have to enable snooping in the vhdl model cpu %d, disabling caches\n",
me);
sparc_leon3_disable_cache();
}
}
local_ops->cache_all();
local_ops->tlb_all();
}
staticvoid leon_smp_setbroadcast(unsignedint mask)
{ int broadcast =
((LEON3_BYPASS_LOAD_PA(&(leon3_irqctrl_regs->mpstatus)) >>
LEON3_IRQMPSTATUS_BROADCAST) & 1); if (!broadcast) {
prom_printf("######## !!!! The irqmp-ctrl must have broadcast enabled, smp wont work !!!!! ####### nr cpus: %d\n",
leon_smp_nrcpus()); if (leon_smp_nrcpus() > 1) {
BUG();
} else {
prom_printf("continue anyway\n"); return;
}
}
LEON_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mpbroadcast), mask);
}
int leon_smp_nrcpus(void)
{ int nrcpu =
((LEON3_BYPASS_LOAD_PA(&(leon3_irqctrl_regs->mpstatus)) >>
LEON3_IRQMPSTATUS_CPUNR) & 0xf) + 1; return nrcpu;
}
void __init leon_boot_cpus(void)
{ int nrcpu = leon_smp_nrcpus(); int me = smp_processor_id();
/* Setup IPI */
leon_ipi_init();
printk(KERN_INFO "%d:(%d:%d) cpus mpirq at 0x%x\n", (unsignedint)me,
(unsignedint)nrcpu, (unsignedint)NR_CPUS,
(unsignedint)&(leon3_irqctrl_regs->mpstatus));
int leon_boot_one_cpu(int i, struct task_struct *idle)
{ int timeout;
current_set[i] = task_thread_info(idle);
/* See trampoline.S:leon_smp_cpu_startup for details... * 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;
/* setup cpu list for irq rotation */
first = 0;
prev = &first; for (i = 0; i < NR_CPUS; i++) { if (cpu_online(i)) {
*prev = i;
prev = &cpu_data(i).next;
}
}
*prev = first;
local_ops->cache_all();
/* Free unneeded trap tables */ if (!cpu_present(1)) {
free_reserved_page(virt_to_page(&trapbase_cpu1[0]));
} if (!cpu_present(2)) {
free_reserved_page(virt_to_page(&trapbase_cpu2[0]));
} if (!cpu_present(3)) {
free_reserved_page(virt_to_page(&trapbase_cpu3[0]));
} /* Ok, they are spinning and ready to go. */
smp_processors_ready = 1;
}
struct leon_ipi_work { int single; int msk; int resched;
};
/* Initialize IPIs on the LEON, in order to save IRQ resources only one IRQ * is used for all three types of IPIs.
*/ staticvoid __init leon_ipi_init(void)
{ int cpu, len; struct leon_ipi_work *work; struct property *pp; struct device_node *rootnp; struct tt_entry *trap_table; unsignedlong flags;
/* Find IPI IRQ or stick with default value */
rootnp = of_find_node_by_path("/ambapp0"); if (rootnp) {
pp = of_find_property(rootnp, "ipi_num", &len); if (pp && (*(int *)pp->value))
leon_ipi_irq = *(int *)pp->value;
}
printk(KERN_INFO "leon: SMP IPIs at IRQ %d\n", leon_ipi_irq);
/* Adjust so that we jump directly to smpleon_ipi */
local_irq_save(flags);
trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_ipi_irq - 1)];
trap_table->inst_three += smpleon_ipi - real_irq_entry;
local_ops->cache_all();
local_irq_restore(flags);
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.