diff options
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/entry.S | 30 | ||||
-rw-r--r-- | arch/ia64/kernel/iosapic.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/irq_ia64.c | 27 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 8 | ||||
-rw-r--r-- | arch/ia64/kernel/relocate_kernel.S | 11 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/sigframe.h | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/signal.c | 71 | ||||
-rw-r--r-- | arch/ia64/kernel/smp.c | 68 | ||||
-rw-r--r-- | arch/ia64/kernel/traps.c | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/unwind.c | 9 |
11 files changed, 132 insertions, 104 deletions
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 |
1200 | END(notify_resume_user) | 1200 | END(notify_resume_user) |
1201 | 1201 | ||
1202 | GLOBAL_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 | ||
1226 | END(sys_rt_sigsuspend) | ||
1227 | |||
1228 | ENTRY(sys_rt_sigreturn) | 1202 | ENTRY(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 | */ |
1015 | void __init | 1015 | void __devinit |
1016 | iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, | 1016 | iosapic_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 |
262 | extern irqreturn_t handle_IPI (int irq, void *dev_id); | ||
263 | 271 | ||
264 | static irqreturn_t dummy_handler (int irq, void *dev_id) | 272 | static irqreturn_t dummy_handler (int irq, void *dev_id) |
265 | { | 273 | { |
266 | BUG(); | 274 | BUG(); |
267 | } | 275 | } |
276 | extern irqreturn_t handle_IPI (int irq, void *dev_id); | ||
268 | 277 | ||
269 | static struct irqaction ipi_irqaction = { | 278 | static 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 | |||
290 | static struct irqaction tlb_irqaction = { | ||
291 | .handler = dummy_handler, | ||
292 | .flags = SA_INTERRUPT, | ||
293 | .name = "tlb_flush" | ||
294 | }; | ||
295 | |||
280 | #endif | 296 | #endif |
281 | 297 | ||
282 | void | 298 | void |
@@ -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 | ||
157 | void | 157 | void |
158 | do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | 158 | do_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 | ||
177 | static int pal_halt = 1; | 177 | static 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 | } |
261 | EXPORT_SYMBOL_GPL(cpu_idle_wait); | 263 | EXPORT_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) | |||
94 | 4: | 94 | 4: |
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 | ||
789 | void | 789 | void __init |
790 | setup_per_cpu_areas (void) | 790 | setup_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 | ||
25 | extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); | 25 | extern 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 | ||
43 | long | ||
44 | ia64_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(¤t->sighand->siglock); | ||
61 | { | ||
62 | oldset = current->blocked; | ||
63 | current->blocked = set; | ||
64 | recalc_sigpending(); | ||
65 | } | ||
66 | spin_unlock_irq(¤t->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 | |||
84 | asmlinkage long | 43 | asmlinkage long |
85 | sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, | 44 | sys_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 | */ |
480 | long | 439 | void |
481 | ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | 440 | ia64_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 = ¤t->saved_sigmask; | ||
459 | else | ||
498 | oldset = ¤t->blocked; | 460 | oldset = ¤t->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, ¤t->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 | */ | ||
57 | static struct local_tlb_flush_counts { | ||
58 | unsigned int count; | ||
59 | } __attribute__((__aligned__(32))) local_tlb_flush_counts[NR_CPUS]; | ||
60 | |||
61 | static 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 | */ | ||
266 | static void | ||
267 | smp_send_local_flush_tlb (int cpu) | ||
268 | { | ||
269 | platform_send_ipi(cpu, IA64_IPI_LOCAL_TLB_FLUSH, IA64_IPI_DM_INT, 0); | ||
270 | } | ||
271 | |||
272 | void | ||
273 | smp_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 | |||
288 | void | ||
289 | smp_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 | |||
251 | void | 319 | void |
252 | smp_flush_tlb_all (void) | 320 | smp_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); | |||
1943 | int | 1944 | int |
1944 | unw_unwind_to_user (struct unw_frame_info *info) | 1945 | unw_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); |