aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 16:38:45 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-09 16:38:45 -0400
commit38cb162b7585d837083b8365da1eb32687c5164c (patch)
treee4ae15715b23b320b1a92699fac767bc766c8f0b /arch/ia64
parentba7cc09c9c9e29a57045dc5bbf843ac1cfad3283 (diff)
parente180583b85f4a48bd55924712c88e5d8eb182e08 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6: [IA64] wire up pselect, ppoll [IA64] Add TIF_RESTORE_SIGMASK [IA64] unwind did not work for processes born with CLONE_STOPPED [IA64] Optional method to purge the TLB on SN systems [IA64] SPIN_LOCK_UNLOCKED macro cleanup in arch/ia64 [IA64-SN2][KJ] mmtimer.c-kzalloc [IA64] fix stack alignment for ia32 signal handlers [IA64] - Altix: hotplug after intr redirect can crash system [IA64] save and restore cpus_allowed in cpu_idle_wait [IA64] Removal of percpu TR cleanup in kexec code [IA64] Fix some section mismatch errors
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/ia32/ia32_entry.S39
-rw-r--r--arch/ia64/ia32/ia32_signal.c65
-rw-r--r--arch/ia64/kernel/entry.S30
-rw-r--r--arch/ia64/kernel/iosapic.c2
-rw-r--r--arch/ia64/kernel/irq_ia64.c27
-rw-r--r--arch/ia64/kernel/process.c8
-rw-r--r--arch/ia64/kernel/relocate_kernel.S11
-rw-r--r--arch/ia64/kernel/setup.c2
-rw-r--r--arch/ia64/kernel/sigframe.h2
-rw-r--r--arch/ia64/kernel/signal.c71
-rw-r--r--arch/ia64/kernel/smp.c68
-rw-r--r--arch/ia64/kernel/traps.c6
-rw-r--r--arch/ia64/kernel/unwind.c9
-rw-r--r--arch/ia64/mm/tlb.c6
-rw-r--r--arch/ia64/sn/kernel/irq.c58
-rw-r--r--arch/ia64/sn/kernel/sn2/sn2_smp.c65
16 files changed, 254 insertions, 215 deletions
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index 687e5fdc9683..99b665e2b1d5 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -52,43 +52,6 @@ ENTRY(ia32_clone)
52 br.ret.sptk.many rp 52 br.ret.sptk.many rp
53END(ia32_clone) 53END(ia32_clone)
54 54
55ENTRY(sys32_rt_sigsuspend)
56 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
57 alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
58 mov loc0=rp
59 mov out0=in0 // mask
60 mov out1=in1 // sigsetsize
61 mov out2=sp // out2 = &sigscratch
62 .fframe 16
63 adds sp=-16,sp // allocate dummy "sigscratch"
64 ;;
65 .body
66 br.call.sptk.many rp=ia32_rt_sigsuspend
671: .restore sp
68 adds sp=16,sp
69 mov rp=loc0
70 mov ar.pfs=loc1
71 br.ret.sptk.many rp
72END(sys32_rt_sigsuspend)
73
74ENTRY(sys32_sigsuspend)
75 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
76 alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs
77 mov loc0=rp
78 mov out0=in2 // mask (first two args are ignored)
79 ;;
80 mov out1=sp // out1 = &sigscratch
81 .fframe 16
82 adds sp=-16,sp // allocate dummy "sigscratch"
83 .body
84 br.call.sptk.many rp=ia32_sigsuspend
851: .restore sp
86 adds sp=16,sp
87 mov rp=loc0
88 mov ar.pfs=loc1
89 br.ret.sptk.many rp
90END(sys32_sigsuspend)
91
92GLOBAL_ENTRY(ia32_ret_from_clone) 55GLOBAL_ENTRY(ia32_ret_from_clone)
93 PT_REGS_UNWIND_INFO(0) 56 PT_REGS_UNWIND_INFO(0)
94{ /* 57{ /*
@@ -389,7 +352,7 @@ ia32_syscall_table:
389 data8 sys_rt_sigpending 352 data8 sys_rt_sigpending
390 data8 compat_sys_rt_sigtimedwait 353 data8 compat_sys_rt_sigtimedwait
391 data8 sys32_rt_sigqueueinfo 354 data8 sys32_rt_sigqueueinfo
392 data8 sys32_rt_sigsuspend 355 data8 compat_sys_rt_sigsuspend
393 data8 sys32_pread /* 180 */ 356 data8 sys32_pread /* 180 */
394 data8 sys32_pwrite 357 data8 sys32_pwrite
395 data8 sys_chown /* 16-bit version */ 358 data8 sys_chown /* 16-bit version */
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index 10510e585204..85e82f32e480 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -451,59 +451,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r
451 sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); 451 sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);
452} 452}
453 453
454long 454asmlinkage long
455__ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) 455sys32_sigsuspend (int history0, int history1, old_sigset_t mask)
456{ 456{
457 extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); 457 mask &= _BLOCKABLE;
458 sigset_t oldset, set;
459
460 scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */
461 memset(&set, 0, sizeof(set));
462
463 memcpy(&set.sig, &sset->sig, sigsetsize);
464
465 sigdelsetmask(&set, ~_BLOCKABLE);
466
467 spin_lock_irq(&current->sighand->siglock); 458 spin_lock_irq(&current->sighand->siglock);
468 { 459 current->saved_sigmask = current->blocked;
469 oldset = current->blocked; 460 siginitset(&current->blocked, mask);
470 current->blocked = set; 461 recalc_sigpending();
471 recalc_sigpending();
472 }
473 spin_unlock_irq(&current->sighand->siglock); 462 spin_unlock_irq(&current->sighand->siglock);
474 463
475 /* 464 current->state = TASK_INTERRUPTIBLE;
476 * The return below usually returns to the signal handler. We need to pre-set the 465 schedule();
477 * correct error code here to ensure that the right values get saved in sigcontext 466 set_thread_flag(TIF_RESTORE_SIGMASK);
478 * by ia64_do_signal. 467 return -ERESTARTNOHAND;
479 */
480 scr->pt.r8 = -EINTR;
481 while (1) {
482 current->state = TASK_INTERRUPTIBLE;
483 schedule();
484 if (ia64_do_signal(&oldset, scr, 1))
485 return -EINTR;
486 }
487}
488
489asmlinkage long
490ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr)
491{
492 compat_sigset_t set;
493
494 if (sigsetsize > sizeof(compat_sigset_t))
495 return -EINVAL;
496
497 if (copy_from_user(&set.sig, &uset->sig, sigsetsize))
498 return -EFAULT;
499
500 return __ia32_rt_sigsuspend(&set, sigsetsize, scr);
501}
502
503asmlinkage long
504ia32_sigsuspend (unsigned int mask, struct sigscratch *scr)
505{
506 return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr);
507} 468}
508 469
509asmlinkage long 470asmlinkage long
@@ -810,7 +771,11 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
810 } 771 }
811 /* Legacy stack switching not supported */ 772 /* Legacy stack switching not supported */
812 773
813 return (void __user *)((esp - frame_size) & -8ul); 774 esp -= frame_size;
775 /* Align the stack pointer according to the i386 ABI,
776 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
777 esp = ((esp + 4) & -16ul) - 4;
778 return (void __user *) esp;
814} 779}
815 780
816static int 781static int
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 55fd2d5471e1..b50bf208678e 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1199,32 +1199,6 @@ ENTRY(notify_resume_user)
1199 br.ret.sptk.many rp 1199 br.ret.sptk.many rp
1200END(notify_resume_user) 1200END(notify_resume_user)
1201 1201
1202GLOBAL_ENTRY(sys_rt_sigsuspend)
1203 .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8)
1204 alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart!
1205 mov r9=ar.unat
1206 mov loc0=rp // save return address
1207 mov out0=in0 // mask
1208 mov out1=in1 // sigsetsize
1209 adds out2=8,sp // out2=&sigscratch->ar_pfs
1210 ;;
1211 .fframe 16
1212 .spillsp ar.unat, 16
1213 st8 [sp]=r9,-16 // allocate space for ar.unat and save it
1214 st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
1215 .body
1216 br.call.sptk.many rp=ia64_rt_sigsuspend
1217.ret17: .restore sp
1218 adds sp=16,sp // pop scratch stack space
1219 ;;
1220 ld8 r9=[sp] // load new unat from sw->caller_unat
1221 mov rp=loc0
1222 ;;
1223 mov ar.unat=r9
1224 mov ar.pfs=loc1
1225 br.ret.sptk.many rp
1226END(sys_rt_sigsuspend)
1227
1228ENTRY(sys_rt_sigreturn) 1202ENTRY(sys_rt_sigreturn)
1229 PT_REGS_UNWIND_INFO(0) 1203 PT_REGS_UNWIND_INFO(0)
1230 /* 1204 /*
@@ -1598,8 +1572,8 @@ sys_call_table:
1598 data8 sys_readlinkat 1572 data8 sys_readlinkat
1599 data8 sys_fchmodat 1573 data8 sys_fchmodat
1600 data8 sys_faccessat 1574 data8 sys_faccessat
1601 data8 sys_ni_syscall // reserved for pselect 1575 data8 sys_pselect6
1602 data8 sys_ni_syscall // 1295 reserved for ppoll 1576 data8 sys_ppoll
1603 data8 sys_unshare 1577 data8 sys_unshare
1604 data8 sys_splice 1578 data8 sys_splice
1605 data8 sys_set_robust_list 1579 data8 sys_set_robust_list
diff --git a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
index 93d9ab14ba24..37f46527d233 100644
--- a/arch/ia64/kernel/iosapic.c
+++ b/arch/ia64/kernel/iosapic.c
@@ -1012,7 +1012,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi,
1012/* 1012/*
1013 * ACPI calls this when it finds an entry for a legacy ISA IRQ override. 1013 * ACPI calls this when it finds an entry for a legacy ISA IRQ override.
1014 */ 1014 */
1015void __init 1015void __devinit
1016iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, 1016iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
1017 unsigned long polarity, 1017 unsigned long polarity,
1018 unsigned long trigger) 1018 unsigned long trigger)
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
index 1c5044a80958..dce5341303de 100644
--- a/arch/ia64/kernel/irq_ia64.c
+++ b/arch/ia64/kernel/irq_ia64.c
@@ -38,6 +38,7 @@
38#include <asm/machvec.h> 38#include <asm/machvec.h>
39#include <asm/pgtable.h> 39#include <asm/pgtable.h>
40#include <asm/system.h> 40#include <asm/system.h>
41#include <asm/tlbflush.h>
41 42
42#ifdef CONFIG_PERFMON 43#ifdef CONFIG_PERFMON
43# include <asm/perfmon.h> 44# include <asm/perfmon.h>
@@ -126,8 +127,10 @@ void destroy_irq(unsigned int irq)
126 127
127#ifdef CONFIG_SMP 128#ifdef CONFIG_SMP
128# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) 129# define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE)
130# define IS_LOCAL_TLB_FLUSH(vec) (vec == IA64_IPI_LOCAL_TLB_FLUSH)
129#else 131#else
130# define IS_RESCHEDULE(vec) (0) 132# define IS_RESCHEDULE(vec) (0)
133# define IS_LOCAL_TLB_FLUSH(vec) (0)
131#endif 134#endif
132/* 135/*
133 * That's where the IVT branches when we get an external 136 * That's where the IVT branches when we get an external
@@ -179,8 +182,11 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
179 saved_tpr = ia64_getreg(_IA64_REG_CR_TPR); 182 saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
180 ia64_srlz_d(); 183 ia64_srlz_d();
181 while (vector != IA64_SPURIOUS_INT_VECTOR) { 184 while (vector != IA64_SPURIOUS_INT_VECTOR) {
182 if (unlikely(IS_RESCHEDULE(vector))) 185 if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
183 kstat_this_cpu.irqs[vector]++; 186 smp_local_flush_tlb();
187 kstat_this_cpu.irqs[vector]++;
188 } else if (unlikely(IS_RESCHEDULE(vector)))
189 kstat_this_cpu.irqs[vector]++;
184 else { 190 else {
185 ia64_setreg(_IA64_REG_CR_TPR, vector); 191 ia64_setreg(_IA64_REG_CR_TPR, vector);
186 ia64_srlz_d(); 192 ia64_srlz_d();
@@ -226,8 +232,11 @@ void ia64_process_pending_intr(void)
226 * Perform normal interrupt style processing 232 * Perform normal interrupt style processing
227 */ 233 */
228 while (vector != IA64_SPURIOUS_INT_VECTOR) { 234 while (vector != IA64_SPURIOUS_INT_VECTOR) {
229 if (unlikely(IS_RESCHEDULE(vector))) 235 if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
230 kstat_this_cpu.irqs[vector]++; 236 smp_local_flush_tlb();
237 kstat_this_cpu.irqs[vector]++;
238 } else if (unlikely(IS_RESCHEDULE(vector)))
239 kstat_this_cpu.irqs[vector]++;
231 else { 240 else {
232 struct pt_regs *old_regs = set_irq_regs(NULL); 241 struct pt_regs *old_regs = set_irq_regs(NULL);
233 242
@@ -259,12 +268,12 @@ void ia64_process_pending_intr(void)
259 268
260 269
261#ifdef CONFIG_SMP 270#ifdef CONFIG_SMP
262extern irqreturn_t handle_IPI (int irq, void *dev_id);
263 271
264static irqreturn_t dummy_handler (int irq, void *dev_id) 272static irqreturn_t dummy_handler (int irq, void *dev_id)
265{ 273{
266 BUG(); 274 BUG();
267} 275}
276extern irqreturn_t handle_IPI (int irq, void *dev_id);
268 277
269static struct irqaction ipi_irqaction = { 278static struct irqaction ipi_irqaction = {
270 .handler = handle_IPI, 279 .handler = handle_IPI,
@@ -277,6 +286,13 @@ static struct irqaction resched_irqaction = {
277 .flags = IRQF_DISABLED, 286 .flags = IRQF_DISABLED,
278 .name = "resched" 287 .name = "resched"
279}; 288};
289
290static struct irqaction tlb_irqaction = {
291 .handler = dummy_handler,
292 .flags = SA_INTERRUPT,
293 .name = "tlb_flush"
294};
295
280#endif 296#endif
281 297
282void 298void
@@ -302,6 +318,7 @@ init_IRQ (void)
302#ifdef CONFIG_SMP 318#ifdef CONFIG_SMP
303 register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction); 319 register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
304 register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction); 320 register_percpu_irq(IA64_IPI_RESCHEDULE, &resched_irqaction);
321 register_percpu_irq(IA64_IPI_LOCAL_TLB_FLUSH, &tlb_irqaction);
305#endif 322#endif
306#ifdef CONFIG_PERFMON 323#ifdef CONFIG_PERFMON
307 pfm_init_percpu(); 324 pfm_init_percpu();
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index 8bb571a8a738..d1c3ed9943e5 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -155,7 +155,7 @@ show_regs (struct pt_regs *regs)
155} 155}
156 156
157void 157void
158do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) 158do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall)
159{ 159{
160 if (fsys_mode(current, &scr->pt)) { 160 if (fsys_mode(current, &scr->pt)) {
161 /* defer signal-handling etc. until we return to privilege-level 0. */ 161 /* defer signal-handling etc. until we return to privilege-level 0. */
@@ -170,8 +170,8 @@ do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall
170#endif 170#endif
171 171
172 /* deal with pending signal delivery */ 172 /* deal with pending signal delivery */
173 if (test_thread_flag(TIF_SIGPENDING)) 173 if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK))
174 ia64_do_signal(oldset, scr, in_syscall); 174 ia64_do_signal(scr, in_syscall);
175} 175}
176 176
177static int pal_halt = 1; 177static int pal_halt = 1;
@@ -236,6 +236,7 @@ void cpu_idle_wait(void)
236{ 236{
237 unsigned int cpu, this_cpu = get_cpu(); 237 unsigned int cpu, this_cpu = get_cpu();
238 cpumask_t map; 238 cpumask_t map;
239 cpumask_t tmp = current->cpus_allowed;
239 240
240 set_cpus_allowed(current, cpumask_of_cpu(this_cpu)); 241 set_cpus_allowed(current, cpumask_of_cpu(this_cpu));
241 put_cpu(); 242 put_cpu();
@@ -257,6 +258,7 @@ void cpu_idle_wait(void)
257 } 258 }
258 cpus_and(map, map, cpu_online_map); 259 cpus_and(map, map, cpu_online_map);
259 } while (!cpus_empty(map)); 260 } while (!cpus_empty(map));
261 set_cpus_allowed(current, tmp);
260} 262}
261EXPORT_SYMBOL_GPL(cpu_idle_wait); 263EXPORT_SYMBOL_GPL(cpu_idle_wait);
262 264
diff --git a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S
index ae473e3f2a0d..903babd22d62 100644
--- a/arch/ia64/kernel/relocate_kernel.S
+++ b/arch/ia64/kernel/relocate_kernel.S
@@ -94,7 +94,7 @@ GLOBAL_ENTRY(relocate_new_kernel)
944: 944:
95 srlz.i 95 srlz.i
96 ;; 96 ;;
97 //purge TR entry for kernel text and data 97 // purge TR entry for kernel text and data
98 movl r16=KERNEL_START 98 movl r16=KERNEL_START
99 mov r18=KERNEL_TR_PAGE_SHIFT<<2 99 mov r18=KERNEL_TR_PAGE_SHIFT<<2
100 ;; 100 ;;
@@ -104,15 +104,6 @@ GLOBAL_ENTRY(relocate_new_kernel)
104 srlz.i 104 srlz.i
105 ;; 105 ;;
106 106
107 // purge TR entry for percpu data
108 movl r16=PERCPU_ADDR
109 mov r18=PERCPU_PAGE_SHIFT<<2
110 ;;
111 ptr.d r16,r18
112 ;;
113 srlz.d
114 ;;
115
116 // purge TR entry for pal code 107 // purge TR entry for pal code
117 mov r16=in3 108 mov r16=in3
118 mov r18=IA64_GRANULE_SHIFT<<2 109 mov r18=IA64_GRANULE_SHIFT<<2
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 6e19da122ae3..9df1efe7487d 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -786,7 +786,7 @@ identify_cpu (struct cpuinfo_ia64 *c)
786 c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1)); 786 c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1));
787} 787}
788 788
789void 789void __init
790setup_per_cpu_areas (void) 790setup_per_cpu_areas (void)
791{ 791{
792 /* start_kernel() requires this... */ 792 /* start_kernel() requires this... */
diff --git a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h
index 37b986cb86e0..9fd9a1933b3d 100644
--- a/arch/ia64/kernel/sigframe.h
+++ b/arch/ia64/kernel/sigframe.h
@@ -22,4 +22,4 @@ struct sigframe {
22 struct sigcontext sc; 22 struct sigcontext sc;
23}; 23};
24 24
25extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); 25extern void ia64_do_signal (struct sigscratch *, long);
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 0dcd56da6001..aeec8184e862 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -40,47 +40,6 @@
40# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) 40# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0])
41#endif 41#endif
42 42
43long
44ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr)
45{
46 sigset_t oldset, set;
47
48 /* XXX: Don't preclude handling different sized sigset_t's. */
49 if (sigsetsize != sizeof(sigset_t))
50 return -EINVAL;
51
52 if (!access_ok(VERIFY_READ, uset, sigsetsize))
53 return -EFAULT;
54
55 if (GET_SIGSET(&set, uset))
56 return -EFAULT;
57
58 sigdelsetmask(&set, ~_BLOCKABLE);
59
60 spin_lock_irq(&current->sighand->siglock);
61 {
62 oldset = current->blocked;
63 current->blocked = set;
64 recalc_sigpending();
65 }
66 spin_unlock_irq(&current->sighand->siglock);
67
68 /*
69 * The return below usually returns to the signal handler. We need to
70 * pre-set the correct error code here to ensure that the right values
71 * get saved in sigcontext by ia64_do_signal.
72 */
73 scr->pt.r8 = EINTR;
74 scr->pt.r10 = -1;
75
76 while (1) {
77 current->state = TASK_INTERRUPTIBLE;
78 schedule();
79 if (ia64_do_signal(&oldset, scr, 1))
80 return -EINTR;
81 }
82}
83
84asmlinkage long 43asmlinkage long
85sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, 44sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2,
86 long arg3, long arg4, long arg5, long arg6, long arg7, 45 long arg3, long arg4, long arg5, long arg6, long arg7,
@@ -477,10 +436,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
477 * Note that `init' is a special process: it doesn't get signals it doesn't want to 436 * Note that `init' is a special process: it doesn't get signals it doesn't want to
478 * handle. Thus you cannot kill init even with a SIGKILL even by mistake. 437 * handle. Thus you cannot kill init even with a SIGKILL even by mistake.
479 */ 438 */
480long 439void
481ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) 440ia64_do_signal (struct sigscratch *scr, long in_syscall)
482{ 441{
483 struct k_sigaction ka; 442 struct k_sigaction ka;
443 sigset_t *oldset;
484 siginfo_t info; 444 siginfo_t info;
485 long restart = in_syscall; 445 long restart = in_syscall;
486 long errno = scr->pt.r8; 446 long errno = scr->pt.r8;
@@ -492,9 +452,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
492 * doing anything if so. 452 * doing anything if so.
493 */ 453 */
494 if (!user_mode(&scr->pt)) 454 if (!user_mode(&scr->pt))
495 return 0; 455 return;
496 456
497 if (!oldset) 457 if (test_thread_flag(TIF_RESTORE_SIGMASK))
458 oldset = &current->saved_sigmask;
459 else
498 oldset = &current->blocked; 460 oldset = &current->blocked;
499 461
500 /* 462 /*
@@ -557,8 +519,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
557 * Whee! Actually deliver the signal. If the delivery failed, we need to 519 * Whee! Actually deliver the signal. If the delivery failed, we need to
558 * continue to iterate in this loop so we can deliver the SIGSEGV... 520 * continue to iterate in this loop so we can deliver the SIGSEGV...
559 */ 521 */
560 if (handle_signal(signr, &ka, &info, oldset, scr)) 522 if (handle_signal(signr, &ka, &info, oldset, scr)) {
561 return 1; 523 /* a signal was successfully delivered; the saved
524 * sigmask will have been stored in the signal frame,
525 * and will be restored by sigreturn, so we can simply
526 * clear the TIF_RESTORE_SIGMASK flag */
527 if (test_thread_flag(TIF_RESTORE_SIGMASK))
528 clear_thread_flag(TIF_RESTORE_SIGMASK);
529 return;
530 }
562 } 531 }
563 532
564 /* Did we come from a system call? */ 533 /* Did we come from a system call? */
@@ -584,5 +553,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
584 } 553 }
585 } 554 }
586 } 555 }
587 return 0; 556
557 /* if there's no signal to deliver, we just put the saved sigmask
558 * back */
559 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
560 clear_thread_flag(TIF_RESTORE_SIGMASK);
561 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
562 }
588} 563}
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 55ddd809b02d..221de3804560 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -50,6 +50,18 @@
50#include <asm/mca.h> 50#include <asm/mca.h>
51 51
52/* 52/*
53 * Note: alignment of 4 entries/cacheline was empirically determined
54 * to be a good tradeoff between hot cachelines & spreading the array
55 * across too many cacheline.
56 */
57static struct local_tlb_flush_counts {
58 unsigned int count;
59} __attribute__((__aligned__(32))) local_tlb_flush_counts[NR_CPUS];
60
61static DEFINE_PER_CPU(unsigned int, shadow_flush_counts[NR_CPUS]) ____cacheline_aligned;
62
63
64/*
53 * Structure and data for smp_call_function(). This is designed to minimise static memory 65 * Structure and data for smp_call_function(). This is designed to minimise static memory
54 * requirements. It also looks cleaner. 66 * requirements. It also looks cleaner.
55 */ 67 */
@@ -248,6 +260,62 @@ smp_send_reschedule (int cpu)
248 platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0); 260 platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
249} 261}
250 262
263/*
264 * Called with preeemption disabled.
265 */
266static void
267smp_send_local_flush_tlb (int cpu)
268{
269 platform_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0);
270}
271
272void
273smp_local_flush_tlb(void)
274{
275 /*
276 * Use atomic ops. Otherwise, the load/increment/store sequence from
277 * a "++" operation can have the line stolen between the load & store.
278 * The overhead of the atomic op in negligible in this case & offers
279 * significant benefit for the brief periods where lots of cpus
280 * are simultaneously flushing TLBs.
281 */
282 ia64_fetchadd(1, &local_tlb_flush_counts[smp_processor_id()].count, acq);
283 local_flush_tlb_all();
284}
285
286#define FLUSH_DELAY 5 /* Usec backoff to eliminate excessive cacheline bouncing */
287
288void
289smp_flush_tlb_cpumask(cpumask_t xcpumask)
290{
291 unsigned int *counts = __ia64_per_cpu_var(shadow_flush_counts);
292 cpumask_t cpumask = xcpumask;
293 int mycpu, cpu, flush_mycpu = 0;
294
295 preempt_disable();
296 mycpu = smp_processor_id();
297
298 for_each_cpu_mask(cpu, cpumask)
299 counts[cpu] = local_tlb_flush_counts[cpu].count;
300
301 mb();
302 for_each_cpu_mask(cpu, cpumask) {
303 if (cpu == mycpu)
304 flush_mycpu = 1;
305 else
306 smp_send_local_flush_tlb(cpu);
307 }
308
309 if (flush_mycpu)
310 smp_local_flush_tlb();
311
312 for_each_cpu_mask(cpu, cpumask)
313 while(counts[cpu] == local_tlb_flush_counts[cpu].count)
314 udelay(FLUSH_DELAY);
315
316 preempt_enable();
317}
318
251void 319void
252smp_flush_tlb_all (void) 320smp_flush_tlb_all (void)
253{ 321{
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index 5bfb8be02b70..b8e0d70bf989 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -43,9 +43,9 @@ die (const char *str, struct pt_regs *regs, long err)
43 u32 lock_owner; 43 u32 lock_owner;
44 int lock_owner_depth; 44 int lock_owner_depth;
45 } die = { 45 } die = {
46 .lock = SPIN_LOCK_UNLOCKED, 46 .lock = __SPIN_LOCK_UNLOCKED(die.lock),
47 .lock_owner = -1, 47 .lock_owner = -1,
48 .lock_owner_depth = 0 48 .lock_owner_depth = 0
49 }; 49 };
50 static int die_counter; 50 static int die_counter;
51 int cpu = get_cpu(); 51 int cpu = get_cpu();
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index 93d5a3b41f69..fe1426266b9b 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -60,6 +60,7 @@
60# define UNW_DEBUG_ON(n) unw_debug_level >= n 60# define UNW_DEBUG_ON(n) unw_debug_level >= n
61 /* Do not code a printk level, not all debug lines end in newline */ 61 /* Do not code a printk level, not all debug lines end in newline */
62# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__) 62# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__)
63# undef inline
63# define inline 64# define inline
64#else /* !UNW_DEBUG */ 65#else /* !UNW_DEBUG */
65# define UNW_DEBUG_ON(n) 0 66# define UNW_DEBUG_ON(n) 0
@@ -145,7 +146,7 @@ static struct {
145# endif 146# endif
146} unw = { 147} unw = {
147 .tables = &unw.kernel_table, 148 .tables = &unw.kernel_table,
148 .lock = SPIN_LOCK_UNLOCKED, 149 .lock = __SPIN_LOCK_UNLOCKED(unw.lock),
149 .save_order = { 150 .save_order = {
150 UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR, 151 UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
151 UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR 152 UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
@@ -1943,9 +1944,9 @@ EXPORT_SYMBOL(unw_unwind);
1943int 1944int
1944unw_unwind_to_user (struct unw_frame_info *info) 1945unw_unwind_to_user (struct unw_frame_info *info)
1945{ 1946{
1946 unsigned long ip, sp, pr = 0; 1947 unsigned long ip, sp, pr = info->pr;
1947 1948
1948 while (unw_unwind(info) >= 0) { 1949 do {
1949 unw_get_sp(info, &sp); 1950 unw_get_sp(info, &sp);
1950 if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp) 1951 if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
1951 < IA64_PT_REGS_SIZE) { 1952 < IA64_PT_REGS_SIZE) {
@@ -1963,7 +1964,7 @@ unw_unwind_to_user (struct unw_frame_info *info)
1963 __FUNCTION__, ip); 1964 __FUNCTION__, ip);
1964 return -1; 1965 return -1;
1965 } 1966 }
1966 } 1967 } while (unw_unwind(info) >= 0);
1967 unw_get_ip(info, &ip); 1968 unw_get_ip(info, &ip);
1968 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", 1969 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
1969 __FUNCTION__, ip); 1970 __FUNCTION__, ip);
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index ffad7624436c..fa4e6d4810f3 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -32,9 +32,9 @@ static struct {
32} purge; 32} purge;
33 33
34struct ia64_ctx ia64_ctx = { 34struct ia64_ctx ia64_ctx = {
35 .lock = SPIN_LOCK_UNLOCKED, 35 .lock = __SPIN_LOCK_UNLOCKED(ia64_ctx.lock),
36 .next = 1, 36 .next = 1,
37 .max_ctx = ~0U 37 .max_ctx = ~0U
38}; 38};
39 39
40DEFINE_PER_CPU(u8, ia64_need_tlb_flush); 40DEFINE_PER_CPU(u8, ia64_need_tlb_flush);
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 8d2a1bfbfe7c..7f6d2360a262 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -59,6 +59,22 @@ void sn_intr_free(nasid_t local_nasid, int local_widget,
59 (u64) sn_irq_info->irq_cookie, 0, 0); 59 (u64) sn_irq_info->irq_cookie, 0, 0);
60} 60}
61 61
62u64 sn_intr_redirect(nasid_t local_nasid, int local_widget,
63 struct sn_irq_info *sn_irq_info,
64 nasid_t req_nasid, int req_slice)
65{
66 struct ia64_sal_retval ret_stuff;
67 ret_stuff.status = 0;
68 ret_stuff.v0 = 0;
69
70 SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_INTERRUPT,
71 (u64) SAL_INTR_REDIRECT, (u64) local_nasid,
72 (u64) local_widget, __pa(sn_irq_info),
73 (u64) req_nasid, (u64) req_slice, 0);
74
75 return ret_stuff.status;
76}
77
62static unsigned int sn_startup_irq(unsigned int irq) 78static unsigned int sn_startup_irq(unsigned int irq)
63{ 79{
64 return 0; 80 return 0;
@@ -127,15 +143,8 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
127 struct sn_irq_info *new_irq_info; 143 struct sn_irq_info *new_irq_info;
128 struct sn_pcibus_provider *pci_provider; 144 struct sn_pcibus_provider *pci_provider;
129 145
130 new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); 146 bridge = (u64) sn_irq_info->irq_bridge;
131 if (new_irq_info == NULL)
132 return NULL;
133
134 memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
135
136 bridge = (u64) new_irq_info->irq_bridge;
137 if (!bridge) { 147 if (!bridge) {
138 kfree(new_irq_info);
139 return NULL; /* irq is not a device interrupt */ 148 return NULL; /* irq is not a device interrupt */
140 } 149 }
141 150
@@ -145,8 +154,25 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
145 local_widget = TIO_SWIN_WIDGETNUM(bridge); 154 local_widget = TIO_SWIN_WIDGETNUM(bridge);
146 else 155 else
147 local_widget = SWIN_WIDGETNUM(bridge); 156 local_widget = SWIN_WIDGETNUM(bridge);
148
149 vector = sn_irq_info->irq_irq; 157 vector = sn_irq_info->irq_irq;
158
159 /* Make use of SAL_INTR_REDIRECT if PROM supports it */
160 status = sn_intr_redirect(local_nasid, local_widget, sn_irq_info, nasid, slice);
161 if (!status) {
162 new_irq_info = sn_irq_info;
163 goto finish_up;
164 }
165
166 /*
167 * PROM does not support SAL_INTR_REDIRECT, or it failed.
168 * Revert to old method.
169 */
170 new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
171 if (new_irq_info == NULL)
172 return NULL;
173
174 memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info));
175
150 /* Free the old PROM new_irq_info structure */ 176 /* Free the old PROM new_irq_info structure */
151 sn_intr_free(local_nasid, local_widget, new_irq_info); 177 sn_intr_free(local_nasid, local_widget, new_irq_info);
152 unregister_intr_pda(new_irq_info); 178 unregister_intr_pda(new_irq_info);
@@ -162,11 +188,18 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
162 return NULL; 188 return NULL;
163 } 189 }
164 190
191 register_intr_pda(new_irq_info);
192 spin_lock(&sn_irq_info_lock);
193 list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
194 spin_unlock(&sn_irq_info_lock);
195 call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
196
197
198finish_up:
165 /* Update kernels new_irq_info with new target info */ 199 /* Update kernels new_irq_info with new target info */
166 cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid, 200 cpuid = nasid_slice_to_cpuid(new_irq_info->irq_nasid,
167 new_irq_info->irq_slice); 201 new_irq_info->irq_slice);
168 new_irq_info->irq_cpuid = cpuid; 202 new_irq_info->irq_cpuid = cpuid;
169 register_intr_pda(new_irq_info);
170 203
171 pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; 204 pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
172 205
@@ -178,11 +211,6 @@ struct sn_irq_info *sn_retarget_vector(struct sn_irq_info *sn_irq_info,
178 pci_provider && pci_provider->target_interrupt) 211 pci_provider && pci_provider->target_interrupt)
179 (pci_provider->target_interrupt)(new_irq_info); 212 (pci_provider->target_interrupt)(new_irq_info);
180 213
181 spin_lock(&sn_irq_info_lock);
182 list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
183 spin_unlock(&sn_irq_info_lock);
184 call_rcu(&sn_irq_info->rcu, sn_irq_info_free);
185
186#ifdef CONFIG_SMP 214#ifdef CONFIG_SMP
187 cpuphys = cpu_physical_id(cpuid); 215 cpuphys = cpu_physical_id(cpuid);
188 set_irq_affinity_info((vector & 0xff), cpuphys, 0); 216 set_irq_affinity_info((vector & 0xff), cpuphys, 0);
diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
index 601747b1e22a..5d318b579fb1 100644
--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
+++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
@@ -46,6 +46,9 @@ DECLARE_PER_CPU(struct ptc_stats, ptcstats);
46 46
47static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); 47static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock);
48 48
49/* 0 = old algorithm (no IPI flushes), 1 = ipi deadlock flush, 2 = ipi instead of SHUB ptc, >2 = always ipi */
50static int sn2_flush_opt = 0;
51
49extern unsigned long 52extern unsigned long
50sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, 53sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long,
51 volatile unsigned long *, unsigned long, 54 volatile unsigned long *, unsigned long,
@@ -76,6 +79,8 @@ struct ptc_stats {
76 unsigned long shub_itc_clocks; 79 unsigned long shub_itc_clocks;
77 unsigned long shub_itc_clocks_max; 80 unsigned long shub_itc_clocks_max;
78 unsigned long shub_ptc_flushes_not_my_mm; 81 unsigned long shub_ptc_flushes_not_my_mm;
82 unsigned long shub_ipi_flushes;
83 unsigned long shub_ipi_flushes_itc_clocks;
79}; 84};
80 85
81#define sn2_ptctest 0 86#define sn2_ptctest 0
@@ -121,6 +126,18 @@ void sn_tlb_migrate_finish(struct mm_struct *mm)
121 flush_tlb_mm(mm); 126 flush_tlb_mm(mm);
122} 127}
123 128
129static void
130sn2_ipi_flush_all_tlb(struct mm_struct *mm)
131{
132 unsigned long itc;
133
134 itc = ia64_get_itc();
135 smp_flush_tlb_cpumask(mm->cpu_vm_mask);
136 itc = ia64_get_itc() - itc;
137 __get_cpu_var(ptcstats).shub_ipi_flushes_itc_clocks += itc;
138 __get_cpu_var(ptcstats).shub_ipi_flushes++;
139}
140
124/** 141/**
125 * sn2_global_tlb_purge - globally purge translation cache of virtual address range 142 * sn2_global_tlb_purge - globally purge translation cache of virtual address range
126 * @mm: mm_struct containing virtual address range 143 * @mm: mm_struct containing virtual address range
@@ -154,7 +171,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
154 unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0; 171 unsigned long itc, itc2, flags, data0 = 0, data1 = 0, rr_value, old_rr = 0;
155 short nasids[MAX_NUMNODES], nix; 172 short nasids[MAX_NUMNODES], nix;
156 nodemask_t nodes_flushed; 173 nodemask_t nodes_flushed;
157 int active, max_active, deadlock; 174 int active, max_active, deadlock, flush_opt = sn2_flush_opt;
175
176 if (flush_opt > 2) {
177 sn2_ipi_flush_all_tlb(mm);
178 return;
179 }
158 180
159 nodes_clear(nodes_flushed); 181 nodes_clear(nodes_flushed);
160 i = 0; 182 i = 0;
@@ -189,6 +211,12 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
189 return; 211 return;
190 } 212 }
191 213
214 if (flush_opt == 2) {
215 sn2_ipi_flush_all_tlb(mm);
216 preempt_enable();
217 return;
218 }
219
192 itc = ia64_get_itc(); 220 itc = ia64_get_itc();
193 nix = 0; 221 nix = 0;
194 for_each_node_mask(cnode, nodes_flushed) 222 for_each_node_mask(cnode, nodes_flushed)
@@ -256,6 +284,8 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
256 } 284 }
257 if (active >= max_active || i == (nix - 1)) { 285 if (active >= max_active || i == (nix - 1)) {
258 if ((deadlock = wait_piowc())) { 286 if ((deadlock = wait_piowc())) {
287 if (flush_opt == 1)
288 goto done;
259 sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1); 289 sn2_ptc_deadlock_recovery(nasids, ibegin, i, mynasid, ptc0, data0, ptc1, data1);
260 if (reset_max_active_on_deadlock()) 290 if (reset_max_active_on_deadlock())
261 max_active = 1; 291 max_active = 1;
@@ -267,6 +297,7 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
267 start += (1UL << nbits); 297 start += (1UL << nbits);
268 } while (start < end); 298 } while (start < end);
269 299
300done:
270 itc2 = ia64_get_itc() - itc2; 301 itc2 = ia64_get_itc() - itc2;
271 __get_cpu_var(ptcstats).shub_itc_clocks += itc2; 302 __get_cpu_var(ptcstats).shub_itc_clocks += itc2;
272 if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) 303 if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max)
@@ -279,6 +310,11 @@ sn2_global_tlb_purge(struct mm_struct *mm, unsigned long start,
279 310
280 spin_unlock_irqrestore(PTC_LOCK(shub1), flags); 311 spin_unlock_irqrestore(PTC_LOCK(shub1), flags);
281 312
313 if (flush_opt == 1 && deadlock) {
314 __get_cpu_var(ptcstats).deadlocks++;
315 sn2_ipi_flush_all_tlb(mm);
316 }
317
282 preempt_enable(); 318 preempt_enable();
283} 319}
284 320
@@ -425,24 +461,42 @@ static int sn2_ptc_seq_show(struct seq_file *file, void *data)
425 461
426 if (!cpu) { 462 if (!cpu) {
427 seq_printf(file, 463 seq_printf(file,
428 "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2\n"); 464 "# cpu ptc_l newrid ptc_flushes nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max not_my_mm deadlock2 ipi_fluches ipi_nsec\n");
429 seq_printf(file, "# ptctest %d\n", sn2_ptctest); 465 seq_printf(file, "# ptctest %d, flushopt %d\n", sn2_ptctest, sn2_flush_opt);
430 } 466 }
431 467
432 if (cpu < NR_CPUS && cpu_online(cpu)) { 468 if (cpu < NR_CPUS && cpu_online(cpu)) {
433 stat = &per_cpu(ptcstats, cpu); 469 stat = &per_cpu(ptcstats, cpu);
434 seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, 470 seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l,
435 stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, 471 stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed,
436 stat->deadlocks, 472 stat->deadlocks,
437 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 473 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
438 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, 474 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec,
439 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec, 475 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec,
440 stat->shub_ptc_flushes_not_my_mm, 476 stat->shub_ptc_flushes_not_my_mm,
441 stat->deadlocks2); 477 stat->deadlocks2,
478 stat->shub_ipi_flushes,
479 1000 * stat->shub_ipi_flushes_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec);
442 } 480 }
443 return 0; 481 return 0;
444} 482}
445 483
484static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, size_t count, loff_t *data)
485{
486 int cpu;
487 char optstr[64];
488
489 if (copy_from_user(optstr, user, count))
490 return -EFAULT;
491 optstr[count - 1] = '\0';
492 sn2_flush_opt = simple_strtoul(optstr, NULL, 0);
493
494 for_each_online_cpu(cpu)
495 memset(&per_cpu(ptcstats, cpu), 0, sizeof(struct ptc_stats));
496
497 return count;
498}
499
446static struct seq_operations sn2_ptc_seq_ops = { 500static struct seq_operations sn2_ptc_seq_ops = {
447 .start = sn2_ptc_seq_start, 501 .start = sn2_ptc_seq_start,
448 .next = sn2_ptc_seq_next, 502 .next = sn2_ptc_seq_next,
@@ -458,6 +512,7 @@ static int sn2_ptc_proc_open(struct inode *inode, struct file *file)
458static const struct file_operations proc_sn2_ptc_operations = { 512static const struct file_operations proc_sn2_ptc_operations = {
459 .open = sn2_ptc_proc_open, 513 .open = sn2_ptc_proc_open,
460 .read = seq_read, 514 .read = seq_read,
515 .write = sn2_ptc_proc_write,
461 .llseek = seq_lseek, 516 .llseek = seq_lseek,
462 .release = seq_release, 517 .release = seq_release,
463}; 518};