2 * linux/arch/alpha/kernel/smp.c
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().
9 * This is helpful for DCPI.
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>
19 #include <linux/threads.h>
20 #include <linux/smp.h>
21 #include <linux/smp_lock.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>
31 #include <asm/hwrpb.h>
32 #include <asm/ptrace.h>
33 #include <asm/atomic.h>
37 #include <asm/pgtable.h>
38 #include <asm/pgalloc.h>
39 #include <asm/mmu_context.h>
40 #include <asm/tlbflush.h>
48 #define DBGS(args) printk args
53 /* A collection of per-processor data. */
54 struct cpuinfo_alpha cpu_data
[NR_CPUS
];
56 /* A collection of single bit ipi messages. */
58 unsigned long bits ____cacheline_aligned
;
59 } ipi_data
[NR_CPUS
] __cacheline_aligned
;
61 enum ipi_message_type
{
67 /* Set to a secondary's cpuid when it comes online. */
68 static int smp_secondary_alive __initdata
= 0;
70 /* Which cpus ids came online. */
71 cpumask_t cpu_present_mask
;
72 cpumask_t cpu_online_map
;
74 EXPORT_SYMBOL(cpu_online_map
);
76 /* cpus reported in the hwrpb */
77 static unsigned long hwrpb_cpu_present_mask __initdata
= 0;
79 int smp_num_probed
; /* Internal processor count */
80 int smp_num_cpus
= 1; /* Number that came online. */
82 extern void calibrate_delay(void);
87 * Called by both boot and secondaries to move global data into
88 * per-processor storage.
90 static inline void __init
91 smp_store_cpu_info(int cpuid
)
93 cpu_data
[cpuid
].loops_per_jiffy
= loops_per_jiffy
;
94 cpu_data
[cpuid
].last_asn
= ASN_FIRST_VERSION
;
95 cpu_data
[cpuid
].need_new_asn
= 0;
96 cpu_data
[cpuid
].asn_lock
= 0;
100 * Ideally sets up per-cpu profiling hooks. Doesn't do much now...
102 static inline void __init
103 smp_setup_percpu_timer(int cpuid
)
105 cpu_data
[cpuid
].prof_counter
= 1;
106 cpu_data
[cpuid
].prof_multiplier
= 1;
110 wait_boot_cpu_to_stop(int cpuid
)
112 unsigned long stop
= jiffies
+ 10*HZ
;
114 while (time_before(jiffies
, stop
)) {
115 if (!smp_secondary_alive
)
120 printk("wait_boot_cpu_to_stop: FAILED on CPU %d, hanging now\n", cpuid
);
126 * Where secondaries begin a life of C.
131 int cpuid
= hard_smp_processor_id();
133 if (cpu_test_and_set(cpuid
, cpu_online_map
)) {
134 printk("??, cpu 0x%x already present??\n", cpuid
);
138 /* Turn on machine checks. */
141 /* Set trap vectors. */
144 /* Set interrupt vector. */
147 /* Get our local ticker going. */
148 smp_setup_percpu_timer(cpuid
);
150 /* Call platform-specific callin, if specified */
151 if (alpha_mv
.smp_callin
) alpha_mv
.smp_callin();
153 /* All kernel threads share the same mm context. */
154 atomic_inc(&init_mm
.mm_count
);
155 current
->active_mm
= &init_mm
;
157 /* Must have completely accurate bogos. */
160 /* Wait boot CPU to stop with irq enabled before running
162 wait_boot_cpu_to_stop(cpuid
);
166 smp_store_cpu_info(cpuid
);
167 /* Allow master to continue only after we written loops_per_jiffy. */
169 smp_secondary_alive
= 1;
171 DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n",
172 cpuid
, current
, current
->active_mm
));
178 /* Wait until hwrpb->txrdy is clear for cpu. Return -1 on timeout. */
180 wait_for_txrdy (unsigned long cpumask
)
182 unsigned long timeout
;
184 if (!(hwrpb
->txrdy
& cpumask
))
187 timeout
= jiffies
+ 10*HZ
;
188 while (time_before(jiffies
, timeout
)) {
189 if (!(hwrpb
->txrdy
& cpumask
))
199 * Send a message to a secondary's console. "START" is one such
200 * interesting message. ;-)
203 send_secondary_console_msg(char *str
, int cpuid
)
205 struct percpu_struct
*cpu
;
206 register char *cp1
, *cp2
;
207 unsigned long cpumask
;
210 cpu
= (struct percpu_struct
*)
212 + hwrpb
->processor_offset
213 + cpuid
* hwrpb
->processor_size
);
215 cpumask
= (1UL << cpuid
);
216 if (wait_for_txrdy(cpumask
))
221 *(unsigned int *)&cpu
->ipc_buffer
[0] = len
;
222 cp1
= (char *) &cpu
->ipc_buffer
[1];
223 memcpy(cp1
, cp2
, len
);
225 /* atomic test and set */
227 set_bit(cpuid
, &hwrpb
->rxrdy
);
229 if (wait_for_txrdy(cpumask
))
234 printk("Processor %x not ready\n", cpuid
);
238 * A secondary console wants to send a message. Receive it.
241 recv_secondary_console_msg(void)
244 unsigned long txrdy
= hwrpb
->txrdy
;
245 char *cp1
, *cp2
, buf
[80];
246 struct percpu_struct
*cpu
;
248 DBGS(("recv_secondary_console_msg: TXRDY 0x%lx.\n", txrdy
));
250 mycpu
= hard_smp_processor_id();
252 for (i
= 0; i
< NR_CPUS
; i
++) {
253 if (!(txrdy
& (1UL << i
)))
256 DBGS(("recv_secondary_console_msg: "
257 "TXRDY contains CPU %d.\n", i
));
259 cpu
= (struct percpu_struct
*)
261 + hwrpb
->processor_offset
262 + i
* hwrpb
->processor_size
);
264 DBGS(("recv_secondary_console_msg: on %d from %d"
265 " HALT_REASON 0x%lx FLAGS 0x%lx\n",
266 mycpu
, i
, cpu
->halt_reason
, cpu
->flags
));
268 cnt
= cpu
->ipc_buffer
[0] >> 32;
269 if (cnt
<= 0 || cnt
>= 80)
270 strcpy(buf
, "<<< BOGUS MSG >>>");
272 cp1
= (char *) &cpu
->ipc_buffer
[11];
276 while ((cp2
= strchr(cp2
, '\r')) != 0) {
283 DBGS((KERN_INFO
"recv_secondary_console_msg: on %d "
284 "message is '%s'\n", mycpu
, buf
));
291 * Convince the console to have a secondary cpu begin execution.
294 secondary_cpu_start(int cpuid
, struct task_struct
*idle
)
296 struct percpu_struct
*cpu
;
297 struct pcb_struct
*hwpcb
, *ipcb
;
298 unsigned long timeout
;
300 cpu
= (struct percpu_struct
*)
302 + hwrpb
->processor_offset
303 + cpuid
* hwrpb
->processor_size
);
304 hwpcb
= (struct pcb_struct
*) cpu
->hwpcb
;
305 ipcb
= &idle
->thread_info
->pcb
;
307 /* Initialize the CPU's HWPCB to something just good enough for
308 us to get started. Immediately after starting, we'll swpctx
309 to the target idle task's pcb. Reuse the stack in the mean
310 time. Precalculate the target PCBB. */
311 hwpcb
->ksp
= (unsigned long)ipcb
+ sizeof(union thread_union
) - 16;
313 hwpcb
->ptbr
= ipcb
->ptbr
;
316 hwpcb
->unique
= virt_to_phys(ipcb
);
317 hwpcb
->flags
= ipcb
->flags
;
318 hwpcb
->res1
= hwpcb
->res2
= 0;
321 DBGS(("KSP 0x%lx PTBR 0x%lx VPTBR 0x%lx UNIQUE 0x%lx\n",
322 hwpcb
->ksp
, hwpcb
->ptbr
, hwrpb
->vptb
, hwpcb
->unique
));
324 DBGS(("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
325 cpuid
, idle
->state
, ipcb
->flags
));
327 /* Setup HWRPB fields that SRM uses to activate secondary CPU */
328 hwrpb
->CPU_restart
= __smp_callin
;
329 hwrpb
->CPU_restart_data
= (unsigned long) __smp_callin
;
331 /* Recalculate and update the HWRPB checksum */
332 hwrpb_update_checksum(hwrpb
);
335 * Send a "start" command to the specified processor.
338 /* SRM III 3.4.1.3 */
339 cpu
->flags
|= 0x22; /* turn on Context Valid and Restart Capable */
340 cpu
->flags
&= ~1; /* turn off Bootstrap In Progress */
343 send_secondary_console_msg("START\r\n", cpuid
);
345 /* Wait 10 seconds for an ACK from the console. */
346 timeout
= jiffies
+ 10*HZ
;
347 while (time_before(jiffies
, timeout
)) {
353 printk(KERN_ERR
"SMP: Processor %d failed to start.\n", cpuid
);
357 DBGS(("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid
));
362 * Bring one cpu online.
365 smp_boot_one_cpu(int cpuid
)
367 struct task_struct
*idle
;
368 unsigned long timeout
;
370 /* Cook up an idler for this guy. Note that the address we
371 give to kernel_thread is irrelevant -- it's going to start
372 where HWRPB.CPU_restart says to start. But this gets all
373 the other task-y sort of data structures set up like we
374 wish. We can't use kernel_thread since we must avoid
375 rescheduling the child. */
376 idle
= fork_idle(cpuid
);
378 panic("failed fork for CPU %d", cpuid
);
380 DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n",
381 cpuid
, idle
->state
, idle
->flags
));
383 /* Signal the secondary to wait a moment. */
384 smp_secondary_alive
= -1;
386 /* Whirrr, whirrr, whirrrrrrrrr... */
387 if (secondary_cpu_start(cpuid
, idle
))
390 /* Notify the secondary CPU it can run calibrate_delay. */
392 smp_secondary_alive
= 0;
394 /* We've been acked by the console; wait one second for
395 the task to start up for real. */
396 timeout
= jiffies
+ 1*HZ
;
397 while (time_before(jiffies
, timeout
)) {
398 if (smp_secondary_alive
== 1)
404 /* We failed to boot the CPU. */
406 printk(KERN_ERR
"SMP: Processor %d is stuck.\n", cpuid
);
410 /* Another "Red Snapper". */
415 * Called from setup_arch. Detect an SMP system and which processors
421 struct percpu_struct
*cpubase
, *cpu
;
424 if (boot_cpuid
!= 0) {
425 printk(KERN_WARNING
"SMP: Booting off cpu %d instead of 0?\n",
429 if (hwrpb
->nr_processors
> 1) {
432 DBGS(("setup_smp: nr_processors %ld\n",
433 hwrpb
->nr_processors
));
435 cpubase
= (struct percpu_struct
*)
436 ((char*)hwrpb
+ hwrpb
->processor_offset
);
437 boot_cpu_palrev
= cpubase
->pal_revision
;
439 for (i
= 0; i
< hwrpb
->nr_processors
; i
++) {
440 cpu
= (struct percpu_struct
*)
441 ((char *)cpubase
+ i
*hwrpb
->processor_size
);
442 if ((cpu
->flags
& 0x1cc) == 0x1cc) {
444 /* Assume here that "whami" == index */
445 hwrpb_cpu_present_mask
|= (1UL << i
);
446 cpu
->pal_revision
= boot_cpu_palrev
;
449 DBGS(("setup_smp: CPU %d: flags 0x%lx type 0x%lx\n",
450 i
, cpu
->flags
, cpu
->type
));
451 DBGS(("setup_smp: CPU %d: PAL rev 0x%lx\n",
452 i
, cpu
->pal_revision
));
456 hwrpb_cpu_present_mask
= (1UL << boot_cpuid
);
458 cpu_present_mask
= cpumask_of_cpu(boot_cpuid
);
460 printk(KERN_INFO
"SMP: %d CPUs probed -- cpu_present_mask = %lx\n",
461 smp_num_probed
, hwrpb_cpu_present_mask
);
465 * Called by smp_init prepare the secondaries
468 smp_prepare_cpus(unsigned int max_cpus
)
472 /* Take care of some initial bookkeeping. */
473 memset(ipi_data
, 0, sizeof(ipi_data
));
475 current_thread_info()->cpu
= boot_cpuid
;
477 smp_store_cpu_info(boot_cpuid
);
478 smp_setup_percpu_timer(boot_cpuid
);
480 /* Nothing to do on a UP box, or when told not to. */
481 if (smp_num_probed
== 1 || max_cpus
== 0) {
482 cpu_present_mask
= cpumask_of_cpu(boot_cpuid
);
483 printk(KERN_INFO
"SMP mode deactivated.\n");
487 printk(KERN_INFO
"SMP starting up secondaries.\n");
490 for (i
= 0; (i
< NR_CPUS
) && (cpu_count
< max_cpus
); i
++) {
494 if (((hwrpb_cpu_present_mask
>> i
) & 1) == 0)
497 cpu_set(i
, cpu_possible_map
);
501 smp_num_cpus
= cpu_count
;
505 smp_prepare_boot_cpu(void)
508 * Mark the boot cpu (current cpu) as both present and online
510 cpu_set(smp_processor_id(), cpu_present_mask
);
511 cpu_set(smp_processor_id(), cpu_online_map
);
515 __cpu_up(unsigned int cpu
)
517 smp_boot_one_cpu(cpu
);
519 return cpu_online(cpu
) ? 0 : -ENOSYS
;
523 smp_cpus_done(unsigned int max_cpus
)
526 unsigned long bogosum
= 0;
528 for(cpu
= 0; cpu
< NR_CPUS
; cpu
++)
530 bogosum
+= cpu_data
[cpu
].loops_per_jiffy
;
532 printk(KERN_INFO
"SMP: Total of %d processors activated "
533 "(%lu.%02lu BogoMIPS).\n",
535 (bogosum
+ 2500) / (500000/HZ
),
536 ((bogosum
+ 2500) / (5000/HZ
)) % 100);
541 smp_percpu_timer_interrupt(struct pt_regs
*regs
)
543 int cpu
= smp_processor_id();
544 unsigned long user
= user_mode(regs
);
545 struct cpuinfo_alpha
*data
= &cpu_data
[cpu
];
547 /* Record kernel PC. */
548 profile_tick(CPU_PROFILING
, regs
);
550 if (!--data
->prof_counter
) {
551 /* We need to make like a normal interrupt -- otherwise
552 timer interrupts ignore the global interrupt lock,
553 which would be a Bad Thing. */
556 update_process_times(user
);
558 data
->prof_counter
= data
->prof_multiplier
;
565 setup_profiling_timer(unsigned int multiplier
)
572 send_ipi_message(cpumask_t to_whom
, enum ipi_message_type operation
)
577 for_each_cpu_mask(i
, to_whom
)
578 set_bit(operation
, &ipi_data
[i
].bits
);
581 for_each_cpu_mask(i
, to_whom
)
585 /* Structure and data for smp_call_function. This is designed to
586 minimize static memory requirements. Plus it looks cleaner. */
588 struct smp_call_struct
{
589 void (*func
) (void *info
);
592 atomic_t unstarted_count
;
593 atomic_t unfinished_count
;
596 static struct smp_call_struct
*smp_call_function_data
;
598 /* Atomicly drop data into a shared pointer. The pointer is free if
599 it is initially locked. If retry, spin until free. */
602 pointer_lock (void *lock
, void *data
, int retry
)
608 /* Compare and swap with zero. */
616 : "=&r"(old
), "=m"(*(void **)lock
), "=&r"(tmp
)
625 while (*(void **)lock
)
631 handle_ipi(struct pt_regs
*regs
)
633 int this_cpu
= smp_processor_id();
634 unsigned long *pending_ipis
= &ipi_data
[this_cpu
].bits
;
638 DBGS(("handle_ipi: on CPU %d ops 0x%lx PC 0x%lx\n",
639 this_cpu
, *pending_ipis
, regs
->pc
));
642 mb(); /* Order interrupt and bit testing. */
643 while ((ops
= xchg(pending_ipis
, 0)) != 0) {
644 mb(); /* Order bit clearing and data access. */
650 which
= __ffs(which
);
654 /* Reschedule callback. Everything to be done
655 is done by the interrupt return path. */
660 struct smp_call_struct
*data
;
661 void (*func
)(void *info
);
665 data
= smp_call_function_data
;
670 /* Notify the sending CPU that the data has been
671 received, and execution is about to begin. */
673 atomic_dec (&data
->unstarted_count
);
675 /* At this point the structure may be gone unless
679 /* Notify the sending CPU that the task is done. */
681 if (wait
) atomic_dec (&data
->unfinished_count
);
689 printk(KERN_CRIT
"Unknown IPI on CPU %d: %lu\n",
695 mb(); /* Order data access and bit testing. */
698 cpu_data
[this_cpu
].ipi_count
++;
701 recv_secondary_console_msg();
705 smp_send_reschedule(int cpu
)
708 if (cpu
== hard_smp_processor_id())
710 "smp_send_reschedule: Sending IPI to self.\n");
712 send_ipi_message(cpumask_of_cpu(cpu
), IPI_RESCHEDULE
);
718 cpumask_t to_whom
= cpu_possible_map
;
719 cpu_clear(smp_processor_id(), to_whom
);
721 if (hard_smp_processor_id() != boot_cpu_id
)
722 printk(KERN_WARNING
"smp_send_stop: Not on boot cpu.\n");
724 send_ipi_message(to_whom
, IPI_CPU_STOP
);
728 * Run a function on all other CPUs.
729 * <func> The function to run. This must be fast and non-blocking.
730 * <info> An arbitrary pointer to pass to the function.
731 * <retry> If true, keep retrying until ready.
732 * <wait> If true, wait until function has completed on other CPUs.
733 * [RETURNS] 0 on success, else a negative status code.
735 * Does not return until remote CPUs are nearly ready to execute <func>
736 * or are or have executed.
737 * You must not call this function with disabled interrupts or from a
738 * hardware interrupt handler or from a bottom half handler.
742 smp_call_function_on_cpu (void (*func
) (void *info
), void *info
, int retry
,
743 int wait
, cpumask_t to_whom
)
745 struct smp_call_struct data
;
746 unsigned long timeout
;
747 int num_cpus_to_call
;
749 /* Can deadlock when called with interrupts disabled */
750 WARN_ON(irqs_disabled());
756 cpu_clear(smp_processor_id(), to_whom
);
757 num_cpus_to_call
= cpus_weight(to_whom
);
759 atomic_set(&data
.unstarted_count
, num_cpus_to_call
);
760 atomic_set(&data
.unfinished_count
, num_cpus_to_call
);
762 /* Acquire the smp_call_function_data mutex. */
763 if (pointer_lock(&smp_call_function_data
, &data
, retry
))
766 /* Send a message to the requested CPUs. */
767 send_ipi_message(to_whom
, IPI_CALL_FUNC
);
769 /* Wait for a minimal response. */
770 timeout
= jiffies
+ HZ
;
771 while (atomic_read (&data
.unstarted_count
) > 0
772 && time_before (jiffies
, timeout
))
775 /* If there's no response yet, log a message but allow a longer
776 * timeout period -- if we get a response this time, log
777 * a message saying when we got it..
779 if (atomic_read(&data
.unstarted_count
) > 0) {
780 long start_time
= jiffies
;
781 printk(KERN_ERR
"%s: initial timeout -- trying long wait\n",
783 timeout
= jiffies
+ 30 * HZ
;
784 while (atomic_read(&data
.unstarted_count
) > 0
785 && time_before(jiffies
, timeout
))
787 if (atomic_read(&data
.unstarted_count
) <= 0) {
788 long delta
= jiffies
- start_time
;
790 "%s: response %ld.%ld seconds into long wait\n",
791 __FUNCTION__
, delta
/ HZ
,
792 (100 * (delta
- ((delta
/ HZ
) * HZ
))) / HZ
);
796 /* We either got one or timed out -- clear the lock. */
798 smp_call_function_data
= NULL
;
801 * If after both the initial and long timeout periods we still don't
802 * have a response, something is very wrong...
804 BUG_ON(atomic_read (&data
.unstarted_count
) > 0);
806 /* Wait for a complete response, if needed. */
808 while (atomic_read (&data
.unfinished_count
) > 0)
816 smp_call_function (void (*func
) (void *info
), void *info
, int retry
, int wait
)
818 return smp_call_function_on_cpu (func
, info
, retry
, wait
,
823 ipi_imb(void *ignored
)
831 /* Must wait other processors to flush their icache before continue. */
832 if (on_each_cpu(ipi_imb
, NULL
, 1, 1))
833 printk(KERN_CRIT
"smp_imb: timed out\n");
837 ipi_flush_tlb_all(void *ignored
)
845 /* Although we don't have any data to pass, we do want to
846 synchronize with the other processors. */
847 if (on_each_cpu(ipi_flush_tlb_all
, NULL
, 1, 1)) {
848 printk(KERN_CRIT
"flush_tlb_all: timed out\n");
852 #define asn_locked() (cpu_data[smp_processor_id()].asn_lock)
855 ipi_flush_tlb_mm(void *x
)
857 struct mm_struct
*mm
= (struct mm_struct
*) x
;
858 if (mm
== current
->active_mm
&& !asn_locked())
859 flush_tlb_current(mm
);
865 flush_tlb_mm(struct mm_struct
*mm
)
869 if (mm
== current
->active_mm
) {
870 flush_tlb_current(mm
);
871 if (atomic_read(&mm
->mm_users
) <= 1) {
872 int cpu
, this_cpu
= smp_processor_id();
873 for (cpu
= 0; cpu
< NR_CPUS
; cpu
++) {
874 if (!cpu_online(cpu
) || cpu
== this_cpu
)
876 if (mm
->context
[cpu
])
877 mm
->context
[cpu
] = 0;
884 if (smp_call_function(ipi_flush_tlb_mm
, mm
, 1, 1)) {
885 printk(KERN_CRIT
"flush_tlb_mm: timed out\n");
891 struct flush_tlb_page_struct
{
892 struct vm_area_struct
*vma
;
893 struct mm_struct
*mm
;
898 ipi_flush_tlb_page(void *x
)
900 struct flush_tlb_page_struct
*data
= (struct flush_tlb_page_struct
*)x
;
901 struct mm_struct
* mm
= data
->mm
;
903 if (mm
== current
->active_mm
&& !asn_locked())
904 flush_tlb_current_page(mm
, data
->vma
, data
->addr
);
910 flush_tlb_page(struct vm_area_struct
*vma
, unsigned long addr
)
912 struct flush_tlb_page_struct data
;
913 struct mm_struct
*mm
= vma
->vm_mm
;
917 if (mm
== current
->active_mm
) {
918 flush_tlb_current_page(mm
, vma
, addr
);
919 if (atomic_read(&mm
->mm_users
) <= 1) {
920 int cpu
, this_cpu
= smp_processor_id();
921 for (cpu
= 0; cpu
< NR_CPUS
; cpu
++) {
922 if (!cpu_online(cpu
) || cpu
== this_cpu
)
924 if (mm
->context
[cpu
])
925 mm
->context
[cpu
] = 0;
936 if (smp_call_function(ipi_flush_tlb_page
, &data
, 1, 1)) {
937 printk(KERN_CRIT
"flush_tlb_page: timed out\n");
944 flush_tlb_range(struct vm_area_struct
*vma
, unsigned long start
, unsigned long end
)
946 /* On the Alpha we always flush the whole user tlb. */
947 flush_tlb_mm(vma
->vm_mm
);
951 ipi_flush_icache_page(void *x
)
953 struct mm_struct
*mm
= (struct mm_struct
*) x
;
954 if (mm
== current
->active_mm
&& !asn_locked())
955 __load_new_mm_context(mm
);
961 flush_icache_user_range(struct vm_area_struct
*vma
, struct page
*page
,
962 unsigned long addr
, int len
)
964 struct mm_struct
*mm
= vma
->vm_mm
;
966 if ((vma
->vm_flags
& VM_EXEC
) == 0)
971 if (mm
== current
->active_mm
) {
972 __load_new_mm_context(mm
);
973 if (atomic_read(&mm
->mm_users
) <= 1) {
974 int cpu
, this_cpu
= smp_processor_id();
975 for (cpu
= 0; cpu
< NR_CPUS
; cpu
++) {
976 if (!cpu_online(cpu
) || cpu
== this_cpu
)
978 if (mm
->context
[cpu
])
979 mm
->context
[cpu
] = 0;
986 if (smp_call_function(ipi_flush_icache_page
, mm
, 1, 1)) {
987 printk(KERN_CRIT
"flush_icache_page: timed out\n");
993 #ifdef CONFIG_DEBUG_SPINLOCK
995 _raw_spin_unlock(spinlock_t
* lock
)
1001 lock
->previous
= NULL
;
1003 lock
->base_file
= "none";
1008 debug_spin_lock(spinlock_t
* lock
, const char *base_file
, int line_no
)
1012 void *inline_pc
= __builtin_return_address(0);
1013 unsigned long started
= jiffies
;
1015 int cpu
= smp_processor_id();
1020 /* Use sub-sections to put the actual loop at the end
1021 of this object file's text section so as to perfect
1022 branch prediction. */
1023 __asm__
__volatile__(
1038 : "=r" (tmp
), "=m" (lock
->lock
), "=r" (stuck
)
1039 : "1" (lock
->lock
), "2" (stuck
) : "memory");
1043 "%s:%d spinlock stuck in %s at %p(%d)"
1044 " owner %s at %p(%d) %s:%d\n",
1046 current
->comm
, inline_pc
, cpu
,
1047 lock
->task
->comm
, lock
->previous
,
1048 lock
->on_cpu
, lock
->base_file
, lock
->line_no
);
1054 /* Exiting. Got the lock. */
1056 lock
->previous
= inline_pc
;
1057 lock
->task
= current
;
1058 lock
->base_file
= base_file
;
1059 lock
->line_no
= line_no
;
1063 "%s:%d spinlock grabbed in %s at %p(%d) %ld ticks\n",
1064 base_file
, line_no
, current
->comm
, inline_pc
,
1065 cpu
, jiffies
- started
);
1070 debug_spin_trylock(spinlock_t
* lock
, const char *base_file
, int line_no
)
1073 if ((ret
= !test_and_set_bit(0, lock
))) {
1074 lock
->on_cpu
= smp_processor_id();
1075 lock
->previous
= __builtin_return_address(0);
1076 lock
->task
= current
;
1078 lock
->base_file
= base_file
;
1079 lock
->line_no
= line_no
;
1083 #endif /* CONFIG_DEBUG_SPINLOCK */
1085 #ifdef CONFIG_DEBUG_RWLOCK
1086 void _raw_write_lock(rwlock_t
* lock
)
1089 int stuck_lock
, stuck_reader
;
1090 void *inline_pc
= __builtin_return_address(0);
1095 stuck_reader
= 1<<30;
1097 __asm__
__volatile__(
1106 "6: blt %3,4b # debug\n"
1107 " subl %3,1,%3 # debug\n"
1110 "8: blt %4,4b # debug\n"
1111 " subl %4,1,%4 # debug\n"
1116 : "=m" (*(volatile int *)lock
), "=&r" (regx
), "=&r" (regy
),
1117 "=&r" (stuck_lock
), "=&r" (stuck_reader
)
1118 : "0" (*(volatile int *)lock
), "3" (stuck_lock
), "4" (stuck_reader
) : "memory");
1120 if (stuck_lock
< 0) {
1121 printk(KERN_WARNING
"write_lock stuck at %p\n", inline_pc
);
1124 if (stuck_reader
< 0) {
1125 printk(KERN_WARNING
"write_lock stuck on readers at %p\n",
1131 void _raw_read_lock(rwlock_t
* lock
)
1135 void *inline_pc
= __builtin_return_address(0);
1141 __asm__
__volatile__(
1150 " blt %2,4b # debug\n"
1151 " subl %2,1,%2 # debug\n"
1155 : "=m" (*(volatile int *)lock
), "=&r" (regx
), "=&r" (stuck_lock
)
1156 : "0" (*(volatile int *)lock
), "2" (stuck_lock
) : "memory");
1158 if (stuck_lock
< 0) {
1159 printk(KERN_WARNING
"read_lock stuck at %p\n", inline_pc
);
1163 #endif /* CONFIG_DEBUG_RWLOCK */