11 #include <linux/kernel.h>
12 #include <linux/sched.h>
29 #include <asm/cacheflush.h>
30 #include <asm/tlbflush.h>
32 #include <asm/ptrace.h>
34 #include <asm/irq_regs.h>
35 #include <asm/traps.h>
37 #include <asm/delay.h>
40 #include <asm/pgalloc.h>
41 #include <asm/pgtable.h>
42 #include <asm/oplib.h>
47 #include <asm/timer.h>
54 static int smp_processors_ready;
58 static void leon_ipi_init(
void);
63 static inline unsigned long do_swap(
volatile unsigned long *
ptr,
66 __asm__ __volatile__(
"swapa [%2] %3, %0\n\t" :
"=&r"(val)
76 local_ops->cache_all();
80 notify_cpu_starting(cpuid);
83 register_percpu_ce(cpuid);
88 local_ops->cache_all();
100 local_ops->cache_all();
101 local_ops->tlb_all();
126 unsigned long cfg = sparc_leon3_get_dcachecfg();
130 printk(
KERN_INFO "Note: SMP with snooping only works on 4k cache, found %dk(0x%x) on cpu %d, disabling caches\n",
132 (
unsigned int)cfg, (
unsigned int)me);
133 sparc_leon3_disable_cache();
136 sparc_leon3_enable_snooping();
138 printk(
KERN_INFO "Note: You have to enable snooping in the vhdl model cpu %d, disabling caches\n",
140 sparc_leon3_disable_cache();
144 local_ops->cache_all();
145 local_ops->tlb_all();
154 prom_printf(
"######## !!!! The irqmp-ctrl must have broadcast enabled, smp wont work !!!!! ####### nr cpus: %d\n",
190 (
unsigned int)nrcpu, (
unsigned int)
NR_CPUS,
193 leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, me);
194 leon_enable_irq_cpu(LEON3_IRQ_TICKER, me);
200 local_ops->cache_all();
222 local_ops->cache_all();
231 for (timeout = 0; timeout < 10000; timeout++) {
242 leon_enable_irq_cpu(LEON3_IRQ_CROSS_CALL, i);
243 leon_enable_irq_cpu(LEON3_IRQ_TICKER, i);
247 local_ops->cache_all();
260 for (i = 0; i <
NR_CPUS; i++) {
267 local_ops->cache_all();
273 free_page((
unsigned long)&trapbase_cpu1);
280 free_page((
unsigned long)&trapbase_cpu2);
287 free_page((
unsigned long)&trapbase_cpu3);
292 smp_processors_ready = 1;
311 static void __init leon_ipi_init(
void)
324 if (pp && (*(
int *)pp->
value))
332 trap_table->
inst_three += smpleon_ipi - real_irq_entry;
333 local_ops->cache_all();
342 static void leon_send_ipi(
int cpu,
int level)
349 static void leon_ipi_single(
int cpu)
360 static void leon_ipi_mask_one(
int cpu)
371 static void leon_ipi_resched(
int cpu)
400 static struct smp_funcall {
415 unsigned long arg2,
unsigned long arg3,
418 if (smp_processors_ready) {
426 register smpfunc_t
f asm(
"i0") = func;
427 register unsigned long a1 asm(
"i1") = arg1;
428 register unsigned long a2 asm(
"i2") = arg2;
429 register unsigned long a3 asm(
"i3") = arg3;
430 register unsigned long a4 asm(
"i4") = arg4;
431 register unsigned long a5 asm(
"i5") = 0;
433 __asm__ __volatile__(
"std %0, [%6]\n\t"
434 "std %2, [%6 + 8]\n\t"
435 "std %4, [%6 + 16]\n\t" : :
436 "r"(
f),
"r"(
a1),
"r"(
a2),
"r"(
a3),
438 "r"(&ccall_info.func));
446 cpumask_and(&mask, cpu_online_mask, &mask);
447 for (i = 0; i <=
high; i++) {
449 ccall_info.processors_in[
i] = 0;
450 ccall_info.processors_out[
i] = 0;
451 leon_send_ipi(i, LEON3_IRQ_CROSS_CALL);
465 while (!ccall_info.processors_in[i])
467 }
while (++i <= high);
474 while (!ccall_info.processors_out[i])
476 }
while (++i <= high);
479 spin_unlock_irqrestore(&cross_call_lock, flags);
488 ccall_info.processors_in[
i] = 1;
489 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
490 ccall_info.arg4, ccall_info.arg5);
491 ccall_info.processors_out[
i] = 1;
495 .cross_call = leon_cross_call,
496 .resched = leon_ipi_resched,
497 .single = leon_ipi_single,
498 .mask_one = leon_ipi_mask_one,
504 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_leon - linux_trap_ipi15_sun4m);