File: /usr/src/linux/arch/sparc/kernel/sun4d_smp.c

1     /* sun4d_smp.c: Sparc SS1000/SC2000 SMP support.
2      *
3      * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
4      *
5      * Based on sun4m's smp.c, which is:
6      * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
7      */
8     
9     #include <asm/head.h>
10     
11     #include <linux/kernel.h>
12     #include <linux/sched.h>
13     #include <linux/threads.h>
14     #include <linux/smp.h>
15     #include <linux/smp_lock.h>
16     #include <linux/interrupt.h>
17     #include <linux/kernel_stat.h>
18     #include <linux/init.h>
19     #include <linux/spinlock.h>
20     #include <linux/mm.h>
21     
22     #include <asm/ptrace.h>
23     #include <asm/atomic.h>
24     
25     #include <asm/delay.h>
26     #include <asm/irq.h>
27     #include <asm/page.h>
28     #include <asm/pgalloc.h>
29     #include <asm/pgtable.h>
30     #include <asm/oplib.h>
31     #include <asm/hardirq.h>
32     #include <asm/softirq.h>
33     #include <asm/sbus.h>
34     #include <asm/sbi.h>
35     
36     #define __KERNEL_SYSCALLS__
37     #include <linux/unistd.h>
38     
39     #define IRQ_CROSS_CALL		15
40     
41     extern ctxd_t *srmmu_ctx_table_phys;
42     extern int linux_num_cpus;
43     
44     extern void calibrate_delay(void);
45     
46     extern struct task_struct *current_set[NR_CPUS];
47     extern volatile int smp_processors_ready;
48     extern unsigned long cpu_present_map;
49     extern int smp_num_cpus;
50     static int smp_highest_cpu = 0;
51     extern int smp_threads_ready;
52     extern unsigned char mid_xlate[NR_CPUS];
53     extern volatile unsigned long cpu_callin_map[NR_CPUS];
54     extern unsigned long smp_proc_in_lock[NR_CPUS];
55     extern struct cpuinfo_sparc cpu_data[NR_CPUS];
56     extern unsigned long cpu_offset[NR_CPUS];
57     extern unsigned char boot_cpu_id;
58     extern int smp_activated;
59     extern volatile int __cpu_number_map[NR_CPUS];
60     extern volatile int __cpu_logical_map[NR_CPUS];
61     extern volatile unsigned long ipi_count;
62     extern volatile int smp_process_available;
63     extern volatile int smp_commenced;
64     extern int __smp4d_processor_id(void);
65     
66     extern unsigned long totalram_pages;
67     
68     /* #define SMP_DEBUG */
69     
70     #ifdef SMP_DEBUG
71     #define SMP_PRINTK(x)	printk x
72     #else
73     #define SMP_PRINTK(x)
74     #endif
75     
76     static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val)
77     {
78     	__asm__ __volatile__("swap [%1], %0\n\t" :
79     			     "=&r" (val), "=&r" (ptr) :
80     			     "0" (val), "1" (ptr));
81     	return val;
82     }
83     
84     static void smp_setup_percpu_timer(void);
85     extern void cpu_probe(void);
86     extern void sun4d_distribute_irqs(void);
87     
88     void __init smp4d_callin(void)
89     {
90     	int cpuid = hard_smp4d_processor_id();
91     	extern spinlock_t sun4d_imsk_lock;
92     	unsigned long flags;
93     	
94     	/* Show we are alive */
95     	cpu_leds[cpuid] = 0x6;
96     	show_leds(cpuid);
97     
98     	/* Enable level15 interrupt, disable level14 interrupt for now */
99     	cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
100     
101     	local_flush_cache_all();
102     	local_flush_tlb_all();
103     
104     	/*
105     	 * Unblock the master CPU _only_ when the scheduler state
106     	 * of all secondary CPUs will be up-to-date, so after
107     	 * the SMP initialization the master will be just allowed
108     	 * to call the scheduler code.
109     	 */
110     	init_idle();
111     
112     	/* Get our local ticker going. */
113     	smp_setup_percpu_timer();
114     
115     	calibrate_delay();
116     	smp_store_cpu_info(cpuid);
117     	local_flush_cache_all();
118     	local_flush_tlb_all();
119     
120     	/* Allow master to continue. */
121     	swap((unsigned long *)&cpu_callin_map[cpuid], 1);
122     	local_flush_cache_all();
123     	local_flush_tlb_all();
124     	
125     	cpu_probe();
126     
127     	while((unsigned long)current_set[cpuid] < PAGE_OFFSET)
128     		barrier();
129     		
130     	while(current_set[cpuid]->processor != cpuid)
131     		barrier();
132     		
133     	/* Fix idle thread fields. */
134     	__asm__ __volatile__("ld [%0], %%g6\n\t"
135     			     "sta %%g6, [%%g0] %1\n\t"
136     			     : : "r" (&current_set[cpuid]), "i" (ASI_M_VIKING_TMP2)
137     			     : "memory" /* paranoid */);
138     
139     	cpu_leds[cpuid] = 0x9;
140     	show_leds(cpuid);
141     	
142     	/* Attach to the address space of init_task. */
143     	atomic_inc(&init_mm.mm_count);
144     	current->active_mm = &init_mm;
145     
146     	local_flush_cache_all();
147     	local_flush_tlb_all();
148     	
149     	__sti();	/* We don't allow PIL 14 yet */
150     	
151     	while(!smp_commenced)
152     		barrier();
153     
154     	spin_lock_irqsave(&sun4d_imsk_lock, flags);
155     	cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */
156     	spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
157     }
158     
159     extern int cpu_idle(void *unused);
160     extern void init_IRQ(void);
161     extern void cpu_panic(void);
162     extern int start_secondary(void *unused);
163     
164     /*
165      *	Cycle through the processors asking the PROM to start each one.
166      */
167      
168     extern struct prom_cpuinfo linux_cpus[NR_CPUS];
169     extern struct linux_prom_registers smp_penguin_ctable;
170     extern unsigned long trapbase_cpu1[];
171     extern unsigned long trapbase_cpu2[];
172     extern unsigned long trapbase_cpu3[];
173     
174     void __init smp4d_boot_cpus(void)
175     {
176     	int cpucount = 0;
177     	int i = 0;
178     
179     	printk("Entering SMP Mode...\n");
180     	
181     	for (i = 0; i < NR_CPUS; i++)
182     		cpu_offset[i] = (char *)&cpu_data[i] - (char *)&cpu_data;
183     		
184     	if (boot_cpu_id)
185     		current_set[0] = NULL;
186     
187     	__sti();
188     	cpu_present_map = 0;
189     	for(i=0; i < linux_num_cpus; i++)
190     		cpu_present_map |= (1<<linux_cpus[i].mid);
191     	SMP_PRINTK(("cpu_present_map %08lx\n", cpu_present_map));
192     	for(i=0; i < NR_CPUS; i++)
193     		__cpu_number_map[i] = -1;
194     	for(i=0; i < NR_CPUS; i++)
195     		__cpu_logical_map[i] = -1;
196     	for(i=0; i < NR_CPUS; i++)
197     		mid_xlate[i] = i;
198     	__cpu_number_map[boot_cpu_id] = 0;
199     	__cpu_logical_map[0] = boot_cpu_id;
200     	current->processor = boot_cpu_id;
201     	smp_store_cpu_info(boot_cpu_id);
202     	smp_setup_percpu_timer();
203     	init_idle();
204     	local_flush_cache_all();
205     	if(linux_num_cpus == 1)
206     		return;  /* Not an MP box. */
207     	SMP_PRINTK(("Iterating over CPUs\n"));
208     	for(i = 0; i < NR_CPUS; i++) {
209     		if(i == boot_cpu_id)
210     			continue;
211     
212     		if(cpu_present_map & (1 << i)) {
213     			extern unsigned long sun4d_cpu_startup;
214     			unsigned long *entry = &sun4d_cpu_startup;
215     			struct task_struct *p;
216     			int timeout;
217     			int no;
218     
219     			/* Cook up an idler for this guy. */
220     			kernel_thread(start_secondary, NULL, CLONE_PID);
221     
222     			cpucount++;
223     
224     			p = init_task.prev_task;
225     			init_tasks[i] = p;
226     
227     			p->processor = i;
228     			p->has_cpu = 1; /* we schedule the first task manually */
229     
230     			current_set[i] = p;
231     
232     			del_from_runqueue(p);
233     			unhash_process(p);
234     
235     			for (no = 0; no < linux_num_cpus; no++)
236     				if (linux_cpus[no].mid == i)
237     					break;
238     
239     			/*
240     			 * Initialize the contexts table
241     			 * Since the call to prom_startcpu() trashes the structure,
242     			 * we need to re-initialize it for each cpu
243     			 */
244     			smp_penguin_ctable.which_io = 0;
245     			smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
246     			smp_penguin_ctable.reg_size = 0;
247     
248     			/* whirrr, whirrr, whirrrrrrrrr... */
249     			SMP_PRINTK(("Starting CPU %d at %p task %d node %08x\n", i, entry, cpucount, linux_cpus[no].prom_node));
250     			local_flush_cache_all();
251     			prom_startcpu(linux_cpus[no].prom_node,
252     				      &smp_penguin_ctable, 0, (char *)entry);
253     				      
254     			SMP_PRINTK(("prom_startcpu returned :)\n"));
255     
256     			/* wheee... it's going... */
257     			for(timeout = 0; timeout < 10000; timeout++) {
258     				if(cpu_callin_map[i])
259     					break;
260     				udelay(200);
261     			}
262     			
263     			if(cpu_callin_map[i]) {
264     				/* Another "Red Snapper". */
265     				__cpu_number_map[i] = cpucount;
266     				__cpu_logical_map[cpucount] = i;
267     			} else {
268     				cpucount--;
269     				printk("Processor %d is stuck.\n", i);
270     			}
271     		}
272     		if(!(cpu_callin_map[i])) {
273     			cpu_present_map &= ~(1 << i);
274     			__cpu_number_map[i] = -1;
275     		}
276     	}
277     	local_flush_cache_all();
278     	if(cpucount == 0) {
279     		printk("Error: only one Processor found.\n");
280     		cpu_present_map = (1 << hard_smp4d_processor_id());
281     	} else {
282     		unsigned long bogosum = 0;
283     		
284     		for(i = 0; i < NR_CPUS; i++) {
285     			if(cpu_present_map & (1 << i)) {
286     				bogosum += cpu_data[i].udelay_val;
287     				smp_highest_cpu = i;
288     			}
289     		}
290     		SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100));
291     		printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
292     		       cpucount + 1,
293     		       bogosum/(500000/HZ),
294     		       (bogosum/(5000/HZ))%100);
295     		smp_activated = 1;
296     		smp_num_cpus = cpucount + 1;
297     	}
298     
299     	/* Free unneeded trap tables */
300     	ClearPageReserved(virt_to_page(trapbase_cpu1));
301     	set_page_count(virt_to_page(trapbase_cpu1), 1);
302     	free_page((unsigned long)trapbase_cpu1);
303     	totalram_pages++;
304     	num_physpages++;
305     
306     	ClearPageReserved(virt_to_page(trapbase_cpu2));
307     	set_page_count(virt_to_page(trapbase_cpu2), 1);
308     	free_page((unsigned long)trapbase_cpu2);
309     	totalram_pages++;
310     	num_physpages++;
311     
312     	ClearPageReserved(virt_to_page(trapbase_cpu3));
313     	set_page_count(virt_to_page(trapbase_cpu3), 1);
314     	free_page((unsigned long)trapbase_cpu3);
315     	totalram_pages++;
316     	num_physpages++;
317     
318     	/* Ok, they are spinning and ready to go. */
319     	smp_processors_ready = 1;
320     	sun4d_distribute_irqs();
321     }
322     
323     static struct smp_funcall {
324     	smpfunc_t func;
325     	unsigned long arg1;
326     	unsigned long arg2;
327     	unsigned long arg3;
328     	unsigned long arg4;
329     	unsigned long arg5;
330     	unsigned char processors_in[NR_CPUS];  /* Set when ipi entered. */
331     	unsigned char processors_out[NR_CPUS]; /* Set when ipi exited. */
332     } ccall_info __attribute__((aligned(8)));
333     
334     static spinlock_t cross_call_lock = SPIN_LOCK_UNLOCKED;
335     
336     /* Cross calls must be serialized, at least currently. */
337     void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
338     		    unsigned long arg3, unsigned long arg4, unsigned long arg5)
339     {
340     	if(smp_processors_ready) {
341     		register int high = smp_highest_cpu;
342     		unsigned long flags;
343     
344     		spin_lock_irqsave(&cross_call_lock, flags);
345     
346     		{
347     			/* If you make changes here, make sure gcc generates proper code... */
348     			smpfunc_t f asm("i0") = func;
349     			unsigned long a1 asm("i1") = arg1;
350     			unsigned long a2 asm("i2") = arg2;
351     			unsigned long a3 asm("i3") = arg3;
352     			unsigned long a4 asm("i4") = arg4;
353     			unsigned long a5 asm("i5") = arg5;
354     					
355     			__asm__ __volatile__("
356     				std %0, [%6]
357     				std %2, [%6 + 8]
358     				std %4, [%6 + 16]" : : 
359     				"r"(f), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5),
360     				"r" (&ccall_info.func));
361     		}
362     
363     		/* Init receive/complete mapping, plus fire the IPI's off. */
364     		{
365     			register unsigned long mask;
366     			register int i;
367     
368     			mask = (cpu_present_map & ~(1 << hard_smp4d_processor_id()));
369     			for(i = 0; i <= high; i++) {
370     				if(mask & (1 << i)) {
371     					ccall_info.processors_in[i] = 0;
372     					ccall_info.processors_out[i] = 0;
373     					sun4d_send_ipi(i, IRQ_CROSS_CALL);
374     				}
375     			}
376     		}
377     
378     		{
379     			register int i;
380     
381     			i = 0;
382     			do {
383     				while(!ccall_info.processors_in[i])
384     					barrier();
385     			} while(++i <= high);
386     
387     			i = 0;
388     			do {
389     				while(!ccall_info.processors_out[i])
390     					barrier();
391     			} while(++i <= high);
392     		}
393     
394     		spin_unlock_irqrestore(&cross_call_lock, flags);
395     	}
396     }
397     
398     /* Running cross calls. */
399     void smp4d_cross_call_irq(void)
400     {
401     	int i = hard_smp4d_processor_id();
402     
403     	ccall_info.processors_in[i] = 1;
404     	ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
405     			ccall_info.arg4, ccall_info.arg5);
406     	ccall_info.processors_out[i] = 1;
407     }
408     
409     static int smp4d_stop_cpu_sender;
410     
411     static void smp4d_stop_cpu(void)
412     {
413     	int me = hard_smp4d_processor_id();
414     	
415     	if (me != smp4d_stop_cpu_sender)
416     		while(1) barrier();
417     }
418     
419     /* Cross calls, in order to work efficiently and atomically do all
420      * the message passing work themselves, only stopcpu and reschedule
421      * messages come through here.
422      */
423     void smp4d_message_pass(int target, int msg, unsigned long data, int wait)
424     {
425     	int me = hard_smp4d_processor_id();
426     
427     	SMP_PRINTK(("smp4d_message_pass %d %d %08lx %d\n", target, msg, data, wait));
428     	if (msg == MSG_STOP_CPU && target == MSG_ALL_BUT_SELF) {
429     		unsigned long flags;
430     		static spinlock_t stop_cpu_lock = SPIN_LOCK_UNLOCKED;
431     		spin_lock_irqsave(&stop_cpu_lock, flags);
432     		smp4d_stop_cpu_sender = me;
433     		smp4d_cross_call((smpfunc_t)smp4d_stop_cpu, 0, 0, 0, 0, 0);
434     		spin_unlock_irqrestore(&stop_cpu_lock, flags);
435     	}
436     	printk("Yeeee, trying to send SMP msg(%d) to %d on cpu %d\n", msg, target, me);
437     	panic("Bogon SMP message pass.");
438     }
439     
440     extern unsigned int prof_multiplier[NR_CPUS];
441     extern unsigned int prof_counter[NR_CPUS];
442     
443     extern void sparc_do_profile(unsigned long pc, unsigned long o7);
444     
445     void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
446     {
447     	int cpu = hard_smp4d_processor_id();
448     	static int cpu_tick[NR_CPUS];
449     	static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
450     
451     	bw_get_prof_limit(cpu);	
452     	bw_clear_intr_mask(0, 1);	/* INTR_TABLE[0] & 1 is Profile IRQ */
453     
454     	cpu_tick[cpu]++;
455     	if (!(cpu_tick[cpu] & 15)) {
456     		if (cpu_tick[cpu] == 0x60)
457     			cpu_tick[cpu] = 0;
458     		cpu_leds[cpu] = led_mask[cpu_tick[cpu] >> 4];
459     		show_leds(cpu);
460     	}
461     
462     	if(!user_mode(regs))
463     		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
464     
465     	if(!--prof_counter[cpu]) {
466     		int user = user_mode(regs);
467     
468     		irq_enter(cpu, 0);
469     		update_process_times(user);
470     		irq_exit(cpu, 0);
471     
472     		prof_counter[cpu] = prof_multiplier[cpu];
473     	}
474     }
475     
476     extern unsigned int lvl14_resolution;
477     
478     static void __init smp_setup_percpu_timer(void)
479     {
480     	int cpu = hard_smp4d_processor_id();
481     
482     	prof_counter[cpu] = prof_multiplier[cpu] = 1;
483     	load_profile_irq(cpu, lvl14_resolution);
484     }
485     
486     void __init smp4d_blackbox_id(unsigned *addr)
487     {
488     	int rd = *addr & 0x3e000000;
489     	
490     	addr[0] = 0xc0800800 | rd;		/* lda [%g0] ASI_M_VIKING_TMP1, reg */
491     	addr[1] = 0x01000000;    		/* nop */
492     	addr[2] = 0x01000000;    		/* nop */
493     }
494     
495     void __init smp4d_blackbox_current(unsigned *addr)
496     {
497     	/* We have a nice Linux current register :) */
498     	int rd = addr[1] & 0x3e000000;
499     	
500     	addr[0] = 0x10800006;			/* b .+24 */
501     	addr[1] = 0xc0800820 | rd;		/* lda [%g0] ASI_M_VIKING_TMP2, reg */
502     }
503     
504     void __init sun4d_init_smp(void)
505     {
506     	int i;
507     	extern unsigned int patchme_store_new_current[];
508     	extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[];
509     
510     	/* Store current into Linux current register :) */
511     	__asm__ __volatile__("sta %%g6, [%%g0] %0" : : "i"(ASI_M_VIKING_TMP2));
512     	
513     	/* Patch switch_to */
514     	patchme_store_new_current[0] = (patchme_store_new_current[0] & 0x3e000000) | 0xc0a00820;
515     	
516     	/* Patch ipi15 trap table */
517     	t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
518     	
519     	/* And set btfixup... */
520     	BTFIXUPSET_BLACKBOX(smp_processor_id, smp4d_blackbox_id);
521     	BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
522     	BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
523     	BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM);
524     	BTFIXUPSET_CALL(__smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
525     	
526     	for (i = 0; i < NR_CPUS; i++) {
527     		ccall_info.processors_in[i] = 1;
528     		ccall_info.processors_out[i] = 1;
529     	}
530     }
531