13 #include <linux/sched.h>
16 #include <asm/cacheflush.h>
17 #include <asm/switch_to.h>
18 #include <asm/tlbflush.h>
19 #include <asm/timer.h>
20 #include <asm/oplib.h>
27 #define IRQ_CROSS_CALL 15
29 static volatile int smp_processors_ready;
30 static int smp_highest_cpu;
32 static inline unsigned long sun4d_swap(
volatile unsigned long *
ptr,
unsigned long val)
34 __asm__ __volatile__(
"swap [%1], %0\n\t" :
35 "=&r" (val),
"=&r" (ptr) :
36 "0" (val),
"1" (ptr));
40 static void smp4d_ipi_init(
void);
42 static unsigned char cpu_leds[32];
47 __asm__ __volatile__ (
"stba %0, [%1] %2" : :
48 "r" ((cpu_leds[cpuid] << 4) | cpu_leds[cpuid+1]),
59 cpu_leds[
cpuid] = 0x6;
63 cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
65 local_ops->cache_all();
68 notify_cpu_starting(cpuid);
76 register_percpu_ce(cpuid);
80 local_ops->cache_all();
85 local_ops->cache_all();
95 __asm__ __volatile__(
"ld [%0], %%g6\n\t"
99 cpu_leds[
cpuid] = 0x9;
106 local_ops->cache_all();
107 local_ops->tlb_all();
115 cc_set_imsk(cc_get_imsk() & ~0x4000);
116 spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
129 local_ops->cache_all();
134 unsigned long *
entry = &sun4d_cpu_startup;
151 local_ops->cache_all();
158 for (timeout = 0; timeout < 10000; timeout++) {
169 local_ops->cache_all();
186 local_ops->cache_all();
189 smp_processors_ready = 1;
190 sun4d_distribute_irqs();
203 static void __init smp4d_ipi_init(
void)
239 #define IGEN_MESSAGE(bcast, devid, sid, levels) \
240 (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
242 static void sun4d_send_ipi(
int cpu,
int level)
244 cc_set_igen(
IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
247 static void sun4d_ipi_single(
int cpu)
255 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
258 static void sun4d_ipi_mask_one(
int cpu)
266 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
269 static void sun4d_ipi_resched(
int cpu)
277 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
280 static struct smp_funcall {
298 if (smp_processors_ready) {
299 register int high = smp_highest_cpu;
309 register smpfunc_t
f asm(
"i0") = func;
310 register unsigned long a1 asm(
"i1") = arg1;
311 register unsigned long a2 asm(
"i2") = arg2;
312 register unsigned long a3 asm(
"i3") = arg3;
313 register unsigned long a4 asm(
"i4") = arg4;
314 register unsigned long a5 asm(
"i5") = 0;
318 "std %2, [%6 + 8]\n\t"
319 "std %4, [%6 + 16]\n\t" : :
320 "r"(
f),
"r"(
a1),
"r"(
a2),
"r"(
a3),
"r"(
a4),
"r"(
a5),
321 "r" (&ccall_info.func));
330 for (i = 0; i <=
high; i++) {
332 ccall_info.processors_in[
i] = 0;
333 ccall_info.processors_out[
i] = 0;
346 while (!ccall_info.processors_in[i])
348 }
while (++i <= high);
354 while (!ccall_info.processors_out[i])
356 }
while (++i <= high);
359 spin_unlock_irqrestore(&cross_call_lock, flags);
368 ccall_info.processors_in[
i] = 1;
369 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
370 ccall_info.arg4, ccall_info.arg5);
371 ccall_info.processors_out[
i] = 1;
378 struct clock_event_device *
ce;
380 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
382 old_regs = set_irq_regs(regs);
383 bw_get_prof_limit(cpu);
384 bw_clear_intr_mask(0, 1);
387 if (!(cpu_tick[cpu] & 15)) {
388 if (cpu_tick[cpu] == 0x60)
390 cpu_leds[
cpu] = led_mask[cpu_tick[
cpu] >> 4];
394 ce = &
per_cpu(sparc32_clockevent, cpu);
397 ce->event_handler(ce);
400 set_irq_regs(old_regs);
404 .cross_call = sun4d_cross_call,
405 .resched = sun4d_ipi_resched,
406 .single = sun4d_ipi_single,
407 .mask_one = sun4d_ipi_mask_one,
415 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
419 for (i = 0; i <
NR_CPUS; i++) {
420 ccall_info.processors_in[
i] = 1;
421 ccall_info.processors_out[
i] = 1;