aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/entry.S4
-rw-r--r--arch/ia64/kernel/mca.c4
-rw-r--r--arch/ia64/kernel/minstate.h3
-rw-r--r--arch/ia64/kernel/perfmon.c175
-rw-r--r--arch/ia64/kernel/ptrace.c20
-rw-r--r--arch/ia64/kernel/smpboot.c2
-rw-r--r--arch/ia64/kernel/sys_ia64.c7
7 files changed, 183 insertions, 32 deletions
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 81c45d447394..d99316c9be28 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1182,7 +1182,7 @@ ENTRY(notify_resume_user)
1182 ;; 1182 ;;
1183(pNonSys) mov out2=0 // out2==0 => not a syscall 1183(pNonSys) mov out2=0 // out2==0 => not a syscall
1184 .fframe 16 1184 .fframe 16
1185 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) 1185 .spillsp ar.unat, 16
1186 st8 [sp]=r9,-16 // allocate space for ar.unat and save it 1186 st8 [sp]=r9,-16 // allocate space for ar.unat and save it
1187 st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch 1187 st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch
1188 .body 1188 .body
@@ -1208,7 +1208,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend)
1208 adds out2=8,sp // out2=&sigscratch->ar_pfs 1208 adds out2=8,sp // out2=&sigscratch->ar_pfs
1209 ;; 1209 ;;
1210 .fframe 16 1210 .fframe 16
1211 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) 1211 .spillsp ar.unat, 16
1212 st8 [sp]=r9,-16 // allocate space for ar.unat and save it 1212 st8 [sp]=r9,-16 // allocate space for ar.unat and save it
1213 st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch 1213 st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
1214 .body 1214 .body
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 4d6c7b8f667b..2c75741dcc66 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -1390,8 +1390,7 @@ ia64_mca_init(void)
1390 register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); 1390 register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
1391 1391
1392#ifdef CONFIG_ACPI 1392#ifdef CONFIG_ACPI
1393 /* Setup the CPEI/P vector and handler */ 1393 /* Setup the CPEI/P handler */
1394 cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
1395 register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); 1394 register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
1396#endif 1395#endif
1397 1396
@@ -1436,6 +1435,7 @@ ia64_mca_late_init(void)
1436 1435
1437#ifdef CONFIG_ACPI 1436#ifdef CONFIG_ACPI
1438 /* Setup the CPEI/P vector and handler */ 1437 /* Setup the CPEI/P vector and handler */
1438 cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
1439 init_timer(&cpe_poll_timer); 1439 init_timer(&cpe_poll_timer);
1440 cpe_poll_timer.function = ia64_mca_cpe_poll; 1440 cpe_poll_timer.function = ia64_mca_cpe_poll;
1441 1441
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index 1dbc7b2497c9..f6d8a010d99b 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -41,7 +41,7 @@
41(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \ 41(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \
42(pKStk) ld8 r3 = [r3];; \ 42(pKStk) ld8 r3 = [r3];; \
43(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \ 43(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \
44(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \ 44(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
45(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \ 45(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
46(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \ 46(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \
47 ;; \ 47 ;; \
@@ -50,7 +50,6 @@
50(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \ 50(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
51(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \ 51(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \
52 ;; \ 52 ;; \
53(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
54(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \ 53(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
55 ;; \ 54 ;; \
56(pUStk) mov r18=ar.bsp; \ 55(pUStk) mov r18=ar.bsp; \
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 71c101601e3e..6407bff6bfd7 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -11,7 +11,7 @@
11 * Version Perfmon-2.x is a rewrite of perfmon-1.x 11 * Version Perfmon-2.x is a rewrite of perfmon-1.x
12 * by Stephane Eranian, Hewlett Packard Co. 12 * by Stephane Eranian, Hewlett Packard Co.
13 * 13 *
14 * Copyright (C) 1999-2003, 2005 Hewlett Packard Co 14 * Copyright (C) 1999-2005 Hewlett Packard Co
15 * Stephane Eranian <eranian@hpl.hp.com> 15 * Stephane Eranian <eranian@hpl.hp.com>
16 * David Mosberger-Tang <davidm@hpl.hp.com> 16 * David Mosberger-Tang <davidm@hpl.hp.com>
17 * 17 *
@@ -497,6 +497,9 @@ typedef struct {
497static pfm_stats_t pfm_stats[NR_CPUS]; 497static pfm_stats_t pfm_stats[NR_CPUS];
498static pfm_session_t pfm_sessions; /* global sessions information */ 498static pfm_session_t pfm_sessions; /* global sessions information */
499 499
500static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED;
501static pfm_intr_handler_desc_t *pfm_alt_intr_handler;
502
500static struct proc_dir_entry *perfmon_dir; 503static struct proc_dir_entry *perfmon_dir;
501static pfm_uuid_t pfm_null_uuid = {0,}; 504static pfm_uuid_t pfm_null_uuid = {0,};
502 505
@@ -606,6 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info);
606DEFINE_PER_CPU(struct task_struct *, pmu_owner); 609DEFINE_PER_CPU(struct task_struct *, pmu_owner);
607DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); 610DEFINE_PER_CPU(pfm_context_t *, pmu_ctx);
608DEFINE_PER_CPU(unsigned long, pmu_activation_number); 611DEFINE_PER_CPU(unsigned long, pmu_activation_number);
612EXPORT_PER_CPU_SYMBOL_GPL(pfm_syst_info);
609 613
610 614
611/* forward declaration */ 615/* forward declaration */
@@ -1325,7 +1329,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
1325error_conflict: 1329error_conflict:
1326 DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n", 1330 DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n",
1327 pfm_sessions.pfs_sys_session[cpu]->pid, 1331 pfm_sessions.pfs_sys_session[cpu]->pid,
1328 smp_processor_id())); 1332 cpu));
1329abort: 1333abort:
1330 UNLOCK_PFS(flags); 1334 UNLOCK_PFS(flags);
1331 1335
@@ -5555,26 +5559,32 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
5555 int ret; 5559 int ret;
5556 5560
5557 this_cpu = get_cpu(); 5561 this_cpu = get_cpu();
5558 min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min; 5562 if (likely(!pfm_alt_intr_handler)) {
5559 max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max; 5563 min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
5564 max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
5560 5565
5561 start_cycles = ia64_get_itc(); 5566 start_cycles = ia64_get_itc();
5562 5567
5563 ret = pfm_do_interrupt_handler(irq, arg, regs); 5568 ret = pfm_do_interrupt_handler(irq, arg, regs);
5564 5569
5565 total_cycles = ia64_get_itc(); 5570 total_cycles = ia64_get_itc();
5566 5571
5567 /* 5572 /*
5568 * don't measure spurious interrupts 5573 * don't measure spurious interrupts
5569 */ 5574 */
5570 if (likely(ret == 0)) { 5575 if (likely(ret == 0)) {
5571 total_cycles -= start_cycles; 5576 total_cycles -= start_cycles;
5572 5577
5573 if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles; 5578 if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
5574 if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles; 5579 if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
5575 5580
5576 pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles; 5581 pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
5582 }
5583 }
5584 else {
5585 (*pfm_alt_intr_handler->handler)(irq, arg, regs);
5577 } 5586 }
5587
5578 put_cpu_no_resched(); 5588 put_cpu_no_resched();
5579 return IRQ_HANDLED; 5589 return IRQ_HANDLED;
5580} 5590}
@@ -6425,6 +6435,141 @@ static struct irqaction perfmon_irqaction = {
6425 .name = "perfmon" 6435 .name = "perfmon"
6426}; 6436};
6427 6437
6438static void
6439pfm_alt_save_pmu_state(void *data)
6440{
6441 struct pt_regs *regs;
6442
6443 regs = ia64_task_regs(current);
6444
6445 DPRINT(("called\n"));
6446
6447 /*
6448 * should not be necessary but
6449 * let's take not risk
6450 */
6451 pfm_clear_psr_up();
6452 pfm_clear_psr_pp();
6453 ia64_psr(regs)->pp = 0;
6454
6455 /*
6456 * This call is required
6457 * May cause a spurious interrupt on some processors
6458 */
6459 pfm_freeze_pmu();
6460
6461 ia64_srlz_d();
6462}
6463
6464void
6465pfm_alt_restore_pmu_state(void *data)
6466{
6467 struct pt_regs *regs;
6468
6469 regs = ia64_task_regs(current);
6470
6471 DPRINT(("called\n"));
6472
6473 /*
6474 * put PMU back in state expected
6475 * by perfmon
6476 */
6477 pfm_clear_psr_up();
6478 pfm_clear_psr_pp();
6479 ia64_psr(regs)->pp = 0;
6480
6481 /*
6482 * perfmon runs with PMU unfrozen at all times
6483 */
6484 pfm_unfreeze_pmu();
6485
6486 ia64_srlz_d();
6487}
6488
6489int
6490pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
6491{
6492 int ret, i;
6493 int reserve_cpu;
6494
6495 /* some sanity checks */
6496 if (hdl == NULL || hdl->handler == NULL) return -EINVAL;
6497
6498 /* do the easy test first */
6499 if (pfm_alt_intr_handler) return -EBUSY;
6500
6501 /* one at a time in the install or remove, just fail the others */
6502 if (!spin_trylock(&pfm_alt_install_check)) {
6503 return -EBUSY;
6504 }
6505
6506 /* reserve our session */
6507 for_each_online_cpu(reserve_cpu) {
6508 ret = pfm_reserve_session(NULL, 1, reserve_cpu);
6509 if (ret) goto cleanup_reserve;
6510 }
6511
6512 /* save the current system wide pmu states */
6513 ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 0, 1);
6514 if (ret) {
6515 DPRINT(("on_each_cpu() failed: %d\n", ret));
6516 goto cleanup_reserve;
6517 }
6518
6519 /* officially change to the alternate interrupt handler */
6520 pfm_alt_intr_handler = hdl;
6521
6522 spin_unlock(&pfm_alt_install_check);
6523
6524 return 0;
6525
6526cleanup_reserve:
6527 for_each_online_cpu(i) {
6528 /* don't unreserve more than we reserved */
6529 if (i >= reserve_cpu) break;
6530
6531 pfm_unreserve_session(NULL, 1, i);
6532 }
6533
6534 spin_unlock(&pfm_alt_install_check);
6535
6536 return ret;
6537}
6538EXPORT_SYMBOL_GPL(pfm_install_alt_pmu_interrupt);
6539
6540int
6541pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
6542{
6543 int i;
6544 int ret;
6545
6546 if (hdl == NULL) return -EINVAL;
6547
6548 /* cannot remove someone else's handler! */
6549 if (pfm_alt_intr_handler != hdl) return -EINVAL;
6550
6551 /* one at a time in the install or remove, just fail the others */
6552 if (!spin_trylock(&pfm_alt_install_check)) {
6553 return -EBUSY;
6554 }
6555
6556 pfm_alt_intr_handler = NULL;
6557
6558 ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 0, 1);
6559 if (ret) {
6560 DPRINT(("on_each_cpu() failed: %d\n", ret));
6561 }
6562
6563 for_each_online_cpu(i) {
6564 pfm_unreserve_session(NULL, 1, i);
6565 }
6566
6567 spin_unlock(&pfm_alt_install_check);
6568
6569 return 0;
6570}
6571EXPORT_SYMBOL_GPL(pfm_remove_alt_pmu_interrupt);
6572
6428/* 6573/*
6429 * perfmon initialization routine, called from the initcall() table 6574 * perfmon initialization routine, called from the initcall() table
6430 */ 6575 */
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 907464ee7273..08c8a5eb25ab 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -692,16 +692,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt,
692 unsigned long cfm) 692 unsigned long cfm)
693{ 693{
694 struct unw_frame_info info, prev_info; 694 struct unw_frame_info info, prev_info;
695 unsigned long ip, pr; 695 unsigned long ip, sp, pr;
696 696
697 unw_init_from_blocked_task(&info, child); 697 unw_init_from_blocked_task(&info, child);
698 while (1) { 698 while (1) {
699 prev_info = info; 699 prev_info = info;
700 if (unw_unwind(&info) < 0) 700 if (unw_unwind(&info) < 0)
701 return; 701 return;
702 if (unw_get_rp(&info, &ip) < 0) 702
703 unw_get_sp(&info, &sp);
704 if ((long)((unsigned long)child + IA64_STK_OFFSET - sp)
705 < IA64_PT_REGS_SIZE) {
706 dprintk("ptrace.%s: ran off the top of the kernel "
707 "stack\n", __FUNCTION__);
708 return;
709 }
710 if (unw_get_pr (&prev_info, &pr) < 0) {
711 unw_get_rp(&prev_info, &ip);
712 dprintk("ptrace.%s: failed to read "
713 "predicate register (ip=0x%lx)\n",
714 __FUNCTION__, ip);
703 return; 715 return;
704 if (ip < FIXADDR_USER_END) 716 }
717 if (unw_is_intr_frame(&info)
718 && (pr & (1UL << PRED_USER_STACK)))
705 break; 719 break;
706 } 720 }
707 721
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 0d5ee57c9865..3865f088ffa2 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -624,7 +624,7 @@ static struct {
624 __u16 thread_id; 624 __u16 thread_id;
625 __u16 proc_fixed_addr; 625 __u16 proc_fixed_addr;
626 __u8 valid; 626 __u8 valid;
627}mt_info[NR_CPUS] __devinit; 627} mt_info[NR_CPUS] __devinitdata;
628 628
629#ifdef CONFIG_HOTPLUG_CPU 629#ifdef CONFIG_HOTPLUG_CPU
630static inline void 630static inline void
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index a8cf6d8a509c..770fab37928e 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -182,13 +182,6 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un
182 } 182 }
183 } 183 }
184 184
185 /*
186 * A zero mmap always succeeds in Linux, independent of whether or not the
187 * remaining arguments are valid.
188 */
189 if (len == 0)
190 goto out;
191
192 /* Careful about overflows.. */ 185 /* Careful about overflows.. */
193 len = PAGE_ALIGN(len); 186 len = PAGE_ALIGN(len);
194 if (!len || len > TASK_SIZE) { 187 if (!len || len > TASK_SIZE) {