xref: /linux/arch/alpha/kernel/smp.c (revision 367b8112fe2ea5c39a7bb4d263dcdd9b612fae18)
1 /*
2  *	linux/arch/alpha/kernel/smp.c
3  *
4  *      2001-07-09 Phil Ezolt (Phillip.Ezolt@compaq.com)
5  *            Renamed modified smp_call_function to smp_call_function_on_cpu()
6  *            Created an function that conforms to the old calling convention
7  *            of smp_call_function().
8  *
9  *            This is helpful for DCPI.
10  *
11  */
12 
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/kernel_stat.h>
16 #include <linux/module.h>
17 #include <linux/sched.h>
18 #include <linux/mm.h>
19 #include <linux/err.h>
20 #include <linux/threads.h>
21 #include <linux/smp.h>
22 #include <linux/interrupt.h>
23 #include <linux/init.h>
24 #include <linux/delay.h>
25 #include <linux/spinlock.h>
26 #include <linux/irq.h>
27 #include <linux/cache.h>
28 #include <linux/profile.h>
29 #include <linux/bitops.h>
30 #include <linux/cpu.h>
31 
32 #include <asm/hwrpb.h>
33 #include <asm/ptrace.h>
34 #include <asm/atomic.h>
35 
36 #include <asm/io.h>
37 #include <asm/irq.h>
38 #include <asm/pgtable.h>
39 #include <asm/pgalloc.h>
40 #include <asm/mmu_context.h>
41 #include <asm/tlbflush.h>
42 
43 #include "proto.h"
44 #include "irq_impl.h"
45 
46 
47 #define DEBUG_SMP 0
48 #if DEBUG_SMP
49 #define DBGS(args)	printk args
50 #else
51 #define DBGS(args)
52 #endif
53 
54 /* A collection of per-processor data.  */
55 struct cpuinfo_alpha cpu_data[NR_CPUS];
56 EXPORT_SYMBOL(cpu_data);
57 
58 /* A collection of single bit ipi messages.  */
59 static struct {
60 	unsigned long bits ____cacheline_aligned;
61 } ipi_data[NR_CPUS] __cacheline_aligned;
62 
63 enum ipi_message_type {
64 	IPI_RESCHEDULE,
65 	IPI_CALL_FUNC,
66 	IPI_CALL_FUNC_SINGLE,
67 	IPI_CPU_STOP,
68 };
69 
70 /* Set to a secondary's cpuid when it comes online.  */
71 static int smp_secondary_alive __devinitdata = 0;
72 
73 /* Which cpus ids came online.  */
74 cpumask_t cpu_online_map;
75 
76 EXPORT_SYMBOL(cpu_online_map);
77 
78 int smp_num_probed;		/* Internal processor count */
79 int smp_num_cpus = 1;		/* Number that came online.  */
80 EXPORT_SYMBOL(smp_num_cpus);
81 
82 /*
83  * Called by both boot and secondaries to move global data into
84  *  per-processor storage.
85  */
86 static inline void __init
87 smp_store_cpu_info(int cpuid)
88 {
89 	cpu_data[cpuid].loops_per_jiffy = loops_per_jiffy;
90 	cpu_data[cpuid].last_asn = ASN_FIRST_VERSION;
91 	cpu_data[cpuid].need_new_asn = 0;
92 	cpu_data[cpuid].asn_lock = 0;
93 }
94 
95 /*
96  * Ideally sets up per-cpu profiling hooks.  Doesn't do much now...
97  */
98 static inline void __init
99 smp_setup_percpu_timer(int cpuid)
100 {
101 	cpu_data[cpuid].prof_counter = 1;
102 	cpu_data[cpuid].prof_multiplier = 1;
103 }
104 
105 static void __init
106 wait_boot_cpu_to_stop(int cpuid)
107 {
108 	unsigned long stop = jiffies + 10*HZ;
109 
110 	while (time_before(jiffies, stop)) {
111 	        if (!smp_secondary_alive)
112 			return;
113 		barrier();
114 	}
115 
116 	printk("wait_boot_cpu_to_stop: FAILED on CPU %d, hanging now\n", cpuid);
117 	for (;;)
118 		barrier();
119 }
120 
121 /*
122  * Where secondaries begin a life of C.
123  */
124 void __init
125 smp_callin(void)
126 {
127 	int cpuid = hard_smp_processor_id();
128 
129 	if (cpu_test_and_set(cpuid, cpu_online_map)) {
130 		printk("??, cpu 0x%x already present??\n", cpuid);
131 		BUG();
132 	}
133 
134 	/* Turn on machine checks.  */
135 	wrmces(7);
136 
137 	/* Set trap vectors.  */
138 	trap_init();
139 
140 	/* Set interrupt vector.  */
141 	wrent(entInt, 0);
142 
143 	/* Get our local ticker going. */
144 	smp_setup_percpu_timer(cpuid);
145 
146 	/* Call platform-specific callin, if specified */
147 	if (alpha_mv.smp_callin) alpha_mv.smp_callin();
148 
149 	/* All kernel threads share the same mm context.  */
150 	atomic_inc(&init_mm.mm_count);
151 	current->active_mm = &init_mm;
152 
153 	/* inform the notifiers about the new cpu */
154 	notify_cpu_starting(cpuid);
155 
156 	/* Must have completely accurate bogos.  */
157 	local_irq_enable();
158 
159 	/* Wait boot CPU to stop with irq enabled before running
160 	   calibrate_delay. */
161 	wait_boot_cpu_to_stop(cpuid);
162 	mb();
163 	calibrate_delay();
164 
165 	smp_store_cpu_info(cpuid);
166 	/* Allow master to continue only after we written loops_per_jiffy.  */
167 	wmb();
168 	smp_secondary_alive = 1;
169 
170 	DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n",
171 	      cpuid, current, current->active_mm));
172 
173 	/* Do nothing.  */
174 	cpu_idle();
175 }
176 
177 /* Wait until hwrpb->txrdy is clear for cpu.  Return -1 on timeout.  */
178 static int __devinit
179 wait_for_txrdy (unsigned long cpumask)
180 {
181 	unsigned long timeout;
182 
183 	if (!(hwrpb->txrdy & cpumask))
184 		return 0;
185 
186 	timeout = jiffies + 10*HZ;
187 	while (time_before(jiffies, timeout)) {
188 		if (!(hwrpb->txrdy & cpumask))
189 			return 0;
190 		udelay(10);
191 		barrier();
192 	}
193 
194 	return -1;
195 }
196 
197 /*
198  * Send a message to a secondary's console.  "START" is one such
199  * interesting message.  ;-)
200  */
201 static void __init
202 send_secondary_console_msg(char *str, int cpuid)
203 {
204 	struct percpu_struct *cpu;
205 	register char *cp1, *cp2;
206 	unsigned long cpumask;
207 	size_t len;
208 
209 	cpu = (struct percpu_struct *)
210 		((char*)hwrpb
211 		 + hwrpb->processor_offset
212 		 + cpuid * hwrpb->processor_size);
213 
214 	cpumask = (1UL << cpuid);
215 	if (wait_for_txrdy(cpumask))
216 		goto timeout;
217 
218 	cp2 = str;
219 	len = strlen(cp2);
220 	*(unsigned int *)&cpu->ipc_buffer[0] = len;
221 	cp1 = (char *) &cpu->ipc_buffer[1];
222 	memcpy(cp1, cp2, len);
223 
224 	/* atomic test and set */
225 	wmb();
226 	set_bit(cpuid, &hwrpb->rxrdy);
227 
228 	if (wait_for_txrdy(cpumask))
229 		goto timeout;
230 	return;
231 
232  timeout:
233 	printk("Processor %x not ready\n", cpuid);
234 }
235 
236 /*
237  * A secondary console wants to send a message.  Receive it.
238  */
239 static void
240 recv_secondary_console_msg(void)
241 {
242 	int mycpu, i, cnt;
243 	unsigned long txrdy = hwrpb->txrdy;
244 	char *cp1, *cp2, buf[80];
245 	struct percpu_struct *cpu;
246 
247 	DBGS(("recv_secondary_console_msg: TXRDY 0x%lx.\n", txrdy));
248 
249 	mycpu = hard_smp_processor_id();
250 
251 	for (i = 0; i < NR_CPUS; i++) {
252 		if (!(txrdy & (1UL << i)))
253 			continue;
254 
255 		DBGS(("recv_secondary_console_msg: "
256 		      "TXRDY contains CPU %d.\n", i));
257 
258 		cpu = (struct percpu_struct *)
259 		  ((char*)hwrpb
260 		   + hwrpb->processor_offset
261 		   + i * hwrpb->processor_size);
262 
263  		DBGS(("recv_secondary_console_msg: on %d from %d"
264 		      " HALT_REASON 0x%lx FLAGS 0x%lx\n",
265 		      mycpu, i, cpu->halt_reason, cpu->flags));
266 
267 		cnt = cpu->ipc_buffer[0] >> 32;
268 		if (cnt <= 0 || cnt >= 80)
269 			strcpy(buf, "<<< BOGUS MSG >>>");
270 		else {
271 			cp1 = (char *) &cpu->ipc_buffer[11];
272 			cp2 = buf;
273 			strcpy(cp2, cp1);
274 
275 			while ((cp2 = strchr(cp2, '\r')) != 0) {
276 				*cp2 = ' ';
277 				if (cp2[1] == '\n')
278 					cp2[1] = ' ';
279 			}
280 		}
281 
282 		DBGS((KERN_INFO "recv_secondary_console_msg: on %d "
283 		      "message is '%s'\n", mycpu, buf));
284 	}
285 
286 	hwrpb->txrdy = 0;
287 }
288 
289 /*
290  * Convince the console to have a secondary cpu begin execution.
291  */
292 static int __init
293 secondary_cpu_start(int cpuid, struct task_struct *idle)
294 {
295 	struct percpu_struct *cpu;
296 	struct pcb_struct *hwpcb, *ipcb;
297 	unsigned long timeout;
298 
299 	cpu = (struct percpu_struct *)
300 		((char*)hwrpb
301 		 + hwrpb->processor_offset
302 		 + cpuid * hwrpb->processor_size);
303 	hwpcb = (struct pcb_struct *) cpu->hwpcb;
304 	ipcb = &task_thread_info(idle)->pcb;
305 
306 	/* Initialize the CPU's HWPCB to something just good enough for
307 	   us to get started.  Immediately after starting, we'll swpctx
308 	   to the target idle task's pcb.  Reuse the stack in the mean
309 	   time.  Precalculate the target PCBB.  */
310 	hwpcb->ksp = (unsigned long)ipcb + sizeof(union thread_union) - 16;
311 	hwpcb->usp = 0;
312 	hwpcb->ptbr = ipcb->ptbr;
313 	hwpcb->pcc = 0;
314 	hwpcb->asn = 0;
315 	hwpcb->unique = virt_to_phys(ipcb);
316 	hwpcb->flags = ipcb->flags;
317 	hwpcb->res1 = hwpcb->res2 = 0;
318 
319 #if 0
320 	DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
321 	      hwpcb->ksp, hwpcb->ptbr, hwrpb->vptb, hwpcb->unique));
322 #endif
323 	DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
324 	      cpuid, idle->state, ipcb->flags));
325 
326 	/* Setup HWRPB fields that SRM uses to activate secondary CPU */
327 	hwrpb->CPU_restart = __smp_callin;
328 	hwrpb->CPU_restart_data = (unsigned long) __smp_callin;
329 
330 	/* Recalculate and update the HWRPB checksum */
331 	hwrpb_update_checksum(hwrpb);
332 
333 	/*
334 	 * Send a "start" command to the specified processor.
335 	 */
336 
337 	/* SRM III 3.4.1.3 */
338 	cpu->flags |= 0x22;	/* turn on Context Valid and Restart Capable */
339 	cpu->flags &= ~1;	/* turn off Bootstrap In Progress */
340 	wmb();
341 
342 	send_secondary_console_msg("START\r\n", cpuid);
343 
344 	/* Wait 10 seconds for an ACK from the console.  */
345 	timeout = jiffies + 10*HZ;
346 	while (time_before(jiffies, timeout)) {
347 		if (cpu->flags & 1)
348 			goto started;
349 		udelay(10);
350 		barrier();
351 	}
352 	printk(KERN_ERR "SMP: Processor %d failed to start.\n", cpuid);
353 	return -1;
354 
355  started:
356 	DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid));
357 	return 0;
358 }
359 
360 /*
361  * Bring one cpu online.
362  */
363 static int __cpuinit
364 smp_boot_one_cpu(int cpuid)
365 {
366 	struct task_struct *idle;
367 	unsigned long timeout;
368 
369 	/* Cook up an idler for this guy.  Note that the address we
370 	   give to kernel_thread is irrelevant -- it's going to start
371 	   where HWRPB.CPU_restart says to start.  But this gets all
372 	   the other task-y sort of data structures set up like we
373 	   wish.  We can't use kernel_thread since we must avoid
374 	   rescheduling the child.  */
375 	idle = fork_idle(cpuid);
376 	if (IS_ERR(idle))
377 		panic("failed fork for CPU %d", cpuid);
378 
379 	DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
380 	      cpuid, idle->state, idle->flags));
381 
382 	/* Signal the secondary to wait a moment.  */
383 	smp_secondary_alive = -1;
384 
385 	/* Whirrr, whirrr, whirrrrrrrrr... */
386 	if (secondary_cpu_start(cpuid, idle))
387 		return -1;
388 
389 	/* Notify the secondary CPU it can run calibrate_delay.  */
390 	mb();
391 	smp_secondary_alive = 0;
392 
393 	/* We've been acked by the console; wait one second for
394 	   the task to start up for real.  */
395 	timeout = jiffies + 1*HZ;
396 	while (time_before(jiffies, timeout)) {
397 		if (smp_secondary_alive == 1)
398 			goto alive;
399 		udelay(10);
400 		barrier();
401 	}
402 
403 	/* We failed to boot the CPU.  */
404 
405 	printk(KERN_ERR "SMP: Processor %d is stuck.\n", cpuid);
406 	return -1;
407 
408  alive:
409 	/* Another "Red Snapper". */
410 	return 0;
411 }
412 
413 /*
414  * Called from setup_arch.  Detect an SMP system and which processors
415  * are present.
416  */
417 void __init
418 setup_smp(void)
419 {
420 	struct percpu_struct *cpubase, *cpu;
421 	unsigned long i;
422 
423 	if (boot_cpuid != 0) {
424 		printk(KERN_WARNING "SMP: Booting off cpu %d instead of 0?\n",
425 		       boot_cpuid);
426 	}
427 
428 	if (hwrpb->nr_processors > 1) {
429 		int boot_cpu_palrev;
430 
431 		DBGS(("setup_smp: nr_processors %ld\n",
432 		      hwrpb->nr_processors));
433 
434 		cpubase = (struct percpu_struct *)
435 			((char*)hwrpb + hwrpb->processor_offset);
436 		boot_cpu_palrev = cpubase->pal_revision;
437 
438 		for (i = 0; i < hwrpb->nr_processors; i++) {
439 			cpu = (struct percpu_struct *)
440 				((char *)cpubase + i*hwrpb->processor_size);
441 			if ((cpu->flags & 0x1cc) == 0x1cc) {
442 				smp_num_probed++;
443 				cpu_set(i, cpu_present_map);
444 				cpu->pal_revision = boot_cpu_palrev;
445 			}
446 
447 			DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n",
448 			      i, cpu->flags, cpu->type));
449 			DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n",
450 			      i, cpu->pal_revision));
451 		}
452 	} else {
453 		smp_num_probed = 1;
454 	}
455 
456 	printk(KERN_INFO "SMP: %d CPUs probed -- cpu_present_map = %lx\n",
457 	       smp_num_probed, cpu_present_map.bits[0]);
458 }
459 
460 /*
461  * Called by smp_init prepare the secondaries
462  */
463 void __init
464 smp_prepare_cpus(unsigned int max_cpus)
465 {
466 	/* Take care of some initial bookkeeping.  */
467 	memset(ipi_data, 0, sizeof(ipi_data));
468 
469 	current_thread_info()->cpu = boot_cpuid;
470 
471 	smp_store_cpu_info(boot_cpuid);
472 	smp_setup_percpu_timer(boot_cpuid);
473 
474 	/* Nothing to do on a UP box, or when told not to.  */
475 	if (smp_num_probed == 1 || max_cpus == 0) {
476 		cpu_present_map = cpumask_of_cpu(boot_cpuid);
477 		printk(KERN_INFO "SMP mode deactivated.\n");
478 		return;
479 	}
480 
481 	printk(KERN_INFO "SMP starting up secondaries.\n");
482 
483 	smp_num_cpus = smp_num_probed;
484 }
485 
486 void __devinit
487 smp_prepare_boot_cpu(void)
488 {
489 }
490 
491 int __cpuinit
492 __cpu_up(unsigned int cpu)
493 {
494 	smp_boot_one_cpu(cpu);
495 
496 	return cpu_online(cpu) ? 0 : -ENOSYS;
497 }
498 
499 void __init
500 smp_cpus_done(unsigned int max_cpus)
501 {
502 	int cpu;
503 	unsigned long bogosum = 0;
504 
505 	for(cpu = 0; cpu < NR_CPUS; cpu++)
506 		if (cpu_online(cpu))
507 			bogosum += cpu_data[cpu].loops_per_jiffy;
508 
509 	printk(KERN_INFO "SMP: Total of %d processors activated "
510 	       "(%lu.%02lu BogoMIPS).\n",
511 	       num_online_cpus(),
512 	       (bogosum + 2500) / (500000/HZ),
513 	       ((bogosum + 2500) / (5000/HZ)) % 100);
514 }
515 
516 
517 void
518 smp_percpu_timer_interrupt(struct pt_regs *regs)
519 {
520 	struct pt_regs *old_regs;
521 	int cpu = smp_processor_id();
522 	unsigned long user = user_mode(regs);
523 	struct cpuinfo_alpha *data = &cpu_data[cpu];
524 
525 	old_regs = set_irq_regs(regs);
526 
527 	/* Record kernel PC.  */
528 	profile_tick(CPU_PROFILING);
529 
530 	if (!--data->prof_counter) {
531 		/* We need to make like a normal interrupt -- otherwise
532 		   timer interrupts ignore the global interrupt lock,
533 		   which would be a Bad Thing.  */
534 		irq_enter();
535 
536 		update_process_times(user);
537 
538 		data->prof_counter = data->prof_multiplier;
539 
540 		irq_exit();
541 	}
542 	set_irq_regs(old_regs);
543 }
544 
545 int
546 setup_profiling_timer(unsigned int multiplier)
547 {
548 	return -EINVAL;
549 }
550 
551 
552 static void
553 send_ipi_message(cpumask_t to_whom, enum ipi_message_type operation)
554 {
555 	int i;
556 
557 	mb();
558 	for_each_cpu_mask(i, to_whom)
559 		set_bit(operation, &ipi_data[i].bits);
560 
561 	mb();
562 	for_each_cpu_mask(i, to_whom)
563 		wripir(i);
564 }
565 
566 void
567 handle_ipi(struct pt_regs *regs)
568 {
569 	int this_cpu = smp_processor_id();
570 	unsigned long *pending_ipis = &ipi_data[this_cpu].bits;
571 	unsigned long ops;
572 
573 #if 0
574 	DBGS(("handle_ipi: on CPU %d ops 0x%lx PC 0x%lx\n",
575 	      this_cpu, *pending_ipis, regs->pc));
576 #endif
577 
578 	mb();	/* Order interrupt and bit testing. */
579 	while ((ops = xchg(pending_ipis, 0)) != 0) {
580 	  mb();	/* Order bit clearing and data access. */
581 	  do {
582 		unsigned long which;
583 
584 		which = ops & -ops;
585 		ops &= ~which;
586 		which = __ffs(which);
587 
588 		switch (which) {
589 		case IPI_RESCHEDULE:
590 			/* Reschedule callback.  Everything to be done
591 			   is done by the interrupt return path.  */
592 			break;
593 
594 		case IPI_CALL_FUNC:
595 			generic_smp_call_function_interrupt();
596 			break;
597 
598 		case IPI_CALL_FUNC_SINGLE:
599 			generic_smp_call_function_single_interrupt();
600 			break;
601 
602 		case IPI_CPU_STOP:
603 			halt();
604 
605 		default:
606 			printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n",
607 			       this_cpu, which);
608 			break;
609 		}
610 	  } while (ops);
611 
612 	  mb();	/* Order data access and bit testing. */
613 	}
614 
615 	cpu_data[this_cpu].ipi_count++;
616 
617 	if (hwrpb->txrdy)
618 		recv_secondary_console_msg();
619 }
620 
621 void
622 smp_send_reschedule(int cpu)
623 {
624 #ifdef DEBUG_IPI_MSG
625 	if (cpu == hard_smp_processor_id())
626 		printk(KERN_WARNING
627 		       "smp_send_reschedule: Sending IPI to self.\n");
628 #endif
629 	send_ipi_message(cpumask_of_cpu(cpu), IPI_RESCHEDULE);
630 }
631 
632 void
633 smp_send_stop(void)
634 {
635 	cpumask_t to_whom = cpu_possible_map;
636 	cpu_clear(smp_processor_id(), to_whom);
637 #ifdef DEBUG_IPI_MSG
638 	if (hard_smp_processor_id() != boot_cpu_id)
639 		printk(KERN_WARNING "smp_send_stop: Not on boot cpu.\n");
640 #endif
641 	send_ipi_message(to_whom, IPI_CPU_STOP);
642 }
643 
644 void arch_send_call_function_ipi(cpumask_t mask)
645 {
646 	send_ipi_message(mask, IPI_CALL_FUNC);
647 }
648 
649 void arch_send_call_function_single_ipi(int cpu)
650 {
651 	send_ipi_message(cpumask_of_cpu(cpu), IPI_CALL_FUNC_SINGLE);
652 }
653 
654 static void
655 ipi_imb(void *ignored)
656 {
657 	imb();
658 }
659 
660 void
661 smp_imb(void)
662 {
663 	/* Must wait other processors to flush their icache before continue. */
664 	if (on_each_cpu(ipi_imb, NULL, 1))
665 		printk(KERN_CRIT "smp_imb: timed out\n");
666 }
667 EXPORT_SYMBOL(smp_imb);
668 
669 static void
670 ipi_flush_tlb_all(void *ignored)
671 {
672 	tbia();
673 }
674 
675 void
676 flush_tlb_all(void)
677 {
678 	/* Although we don't have any data to pass, we do want to
679 	   synchronize with the other processors.  */
680 	if (on_each_cpu(ipi_flush_tlb_all, NULL, 1)) {
681 		printk(KERN_CRIT "flush_tlb_all: timed out\n");
682 	}
683 }
684 
685 #define asn_locked() (cpu_data[smp_processor_id()].asn_lock)
686 
687 static void
688 ipi_flush_tlb_mm(void *x)
689 {
690 	struct mm_struct *mm = (struct mm_struct *) x;
691 	if (mm == current->active_mm && !asn_locked())
692 		flush_tlb_current(mm);
693 	else
694 		flush_tlb_other(mm);
695 }
696 
697 void
698 flush_tlb_mm(struct mm_struct *mm)
699 {
700 	preempt_disable();
701 
702 	if (mm == current->active_mm) {
703 		flush_tlb_current(mm);
704 		if (atomic_read(&mm->mm_users) <= 1) {
705 			int cpu, this_cpu = smp_processor_id();
706 			for (cpu = 0; cpu < NR_CPUS; cpu++) {
707 				if (!cpu_online(cpu) || cpu == this_cpu)
708 					continue;
709 				if (mm->context[cpu])
710 					mm->context[cpu] = 0;
711 			}
712 			preempt_enable();
713 			return;
714 		}
715 	}
716 
717 	if (smp_call_function(ipi_flush_tlb_mm, mm, 1)) {
718 		printk(KERN_CRIT "flush_tlb_mm: timed out\n");
719 	}
720 
721 	preempt_enable();
722 }
723 EXPORT_SYMBOL(flush_tlb_mm);
724 
725 struct flush_tlb_page_struct {
726 	struct vm_area_struct *vma;
727 	struct mm_struct *mm;
728 	unsigned long addr;
729 };
730 
731 static void
732 ipi_flush_tlb_page(void *x)
733 {
734 	struct flush_tlb_page_struct *data = (struct flush_tlb_page_struct *)x;
735 	struct mm_struct * mm = data->mm;
736 
737 	if (mm == current->active_mm && !asn_locked())
738 		flush_tlb_current_page(mm, data->vma, data->addr);
739 	else
740 		flush_tlb_other(mm);
741 }
742 
743 void
744 flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
745 {
746 	struct flush_tlb_page_struct data;
747 	struct mm_struct *mm = vma->vm_mm;
748 
749 	preempt_disable();
750 
751 	if (mm == current->active_mm) {
752 		flush_tlb_current_page(mm, vma, addr);
753 		if (atomic_read(&mm->mm_users) <= 1) {
754 			int cpu, this_cpu = smp_processor_id();
755 			for (cpu = 0; cpu < NR_CPUS; cpu++) {
756 				if (!cpu_online(cpu) || cpu == this_cpu)
757 					continue;
758 				if (mm->context[cpu])
759 					mm->context[cpu] = 0;
760 			}
761 			preempt_enable();
762 			return;
763 		}
764 	}
765 
766 	data.vma = vma;
767 	data.mm = mm;
768 	data.addr = addr;
769 
770 	if (smp_call_function(ipi_flush_tlb_page, &data, 1)) {
771 		printk(KERN_CRIT "flush_tlb_page: timed out\n");
772 	}
773 
774 	preempt_enable();
775 }
776 EXPORT_SYMBOL(flush_tlb_page);
777 
778 void
779 flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
780 {
781 	/* On the Alpha we always flush the whole user tlb.  */
782 	flush_tlb_mm(vma->vm_mm);
783 }
784 EXPORT_SYMBOL(flush_tlb_range);
785 
786 static void
787 ipi_flush_icache_page(void *x)
788 {
789 	struct mm_struct *mm = (struct mm_struct *) x;
790 	if (mm == current->active_mm && !asn_locked())
791 		__load_new_mm_context(mm);
792 	else
793 		flush_tlb_other(mm);
794 }
795 
796 void
797 flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
798 			unsigned long addr, int len)
799 {
800 	struct mm_struct *mm = vma->vm_mm;
801 
802 	if ((vma->vm_flags & VM_EXEC) == 0)
803 		return;
804 
805 	preempt_disable();
806 
807 	if (mm == current->active_mm) {
808 		__load_new_mm_context(mm);
809 		if (atomic_read(&mm->mm_users) <= 1) {
810 			int cpu, this_cpu = smp_processor_id();
811 			for (cpu = 0; cpu < NR_CPUS; cpu++) {
812 				if (!cpu_online(cpu) || cpu == this_cpu)
813 					continue;
814 				if (mm->context[cpu])
815 					mm->context[cpu] = 0;
816 			}
817 			preempt_enable();
818 			return;
819 		}
820 	}
821 
822 	if (smp_call_function(ipi_flush_icache_page, mm, 1)) {
823 		printk(KERN_CRIT "flush_icache_page: timed out\n");
824 	}
825 
826 	preempt_enable();
827 }
828