diff options
author | Jaroslav Kysela <perex@hera.kernel.org> | 2005-06-21 10:39:41 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@hera.kernel.org> | 2005-06-21 10:39:41 -0400 |
commit | fae6ec69c84d71b1d5bda9ede1a262c1681684aa (patch) | |
tree | eb4aff9a5c2b7d04ce09a3717bb1dd4a79fe7595 /arch/ia64 | |
parent | bbc0274e9bb2e3f1d724d445a2bd32566b9b66f7 (diff) | |
parent | 1d345dac1f30af1cd9f3a1faa12f9f18f17f236e (diff) |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/ia32/sys_ia32.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/ia64/kernel/fsys.S | 4 | ||||
-rw-r--r-- | arch/ia64/kernel/mca.c | 8 | ||||
-rw-r--r-- | arch/ia64/kernel/minstate.h | 3 | ||||
-rw-r--r-- | arch/ia64/kernel/module.c | 10 | ||||
-rw-r--r-- | arch/ia64/kernel/perfmon.c | 175 | ||||
-rw-r--r-- | arch/ia64/kernel/ptrace.c | 26 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/ia64/kernel/smpboot.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/sys_ia64.c | 7 | ||||
-rw-r--r-- | arch/ia64/kernel/traps.c | 29 | ||||
-rw-r--r-- | arch/ia64/mm/init.c | 19 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/setup.c | 6 | ||||
-rw-r--r-- | arch/ia64/sn/kernel/tiocx.c | 25 |
15 files changed, 262 insertions, 61 deletions
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 247a21c64aea..c1e20d65dd6c 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c | |||
@@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents, | |||
2427 | { | 2427 | { |
2428 | struct epoll_event *events64 = NULL; | 2428 | struct epoll_event *events64 = NULL; |
2429 | mm_segment_t old_fs = get_fs(); | 2429 | mm_segment_t old_fs = get_fs(); |
2430 | int error, numevents, size; | 2430 | int numevents, size; |
2431 | int evt_idx; | 2431 | int evt_idx; |
2432 | int do_free_pages = 0; | 2432 | int do_free_pages = 0; |
2433 | 2433 | ||
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/fsys.S b/arch/ia64/kernel/fsys.S index 4f3cdef75797..962b6c4e32b5 100644 --- a/arch/ia64/kernel/fsys.S +++ b/arch/ia64/kernel/fsys.S | |||
@@ -460,9 +460,9 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set | |||
460 | ;; | 460 | ;; |
461 | 461 | ||
462 | st8 [r2]=r14 // update current->blocked with new mask | 462 | st8 [r2]=r14 // update current->blocked with new mask |
463 | cmpxchg4.acq r14=[r9],r18,ar.ccv // current->thread_info->flags <- r18 | 463 | cmpxchg4.acq r8=[r9],r18,ar.ccv // current->thread_info->flags <- r18 |
464 | ;; | 464 | ;; |
465 | cmp.ne p6,p0=r17,r14 // update failed? | 465 | cmp.ne p6,p0=r17,r8 // update failed? |
466 | (p6) br.cond.spnt.few 1b // yes -> retry | 466 | (p6) br.cond.spnt.few 1b // yes -> retry |
467 | 467 | ||
468 | #ifdef CONFIG_SMP | 468 | #ifdef CONFIG_SMP |
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 4d6c7b8f667b..736e328b5e61 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c | |||
@@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) | |||
1103 | return IRQ_HANDLED; | 1103 | return IRQ_HANDLED; |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | #endif /* CONFIG_ACPI */ | ||
1107 | |||
1108 | /* | 1106 | /* |
1109 | * ia64_mca_cpe_poll | 1107 | * ia64_mca_cpe_poll |
1110 | * | 1108 | * |
@@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy) | |||
1122 | platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); | 1120 | platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0); |
1123 | } | 1121 | } |
1124 | 1122 | ||
1123 | #endif /* CONFIG_ACPI */ | ||
1124 | |||
1125 | /* | 1125 | /* |
1126 | * C portion of the OS INIT handler | 1126 | * C portion of the OS INIT handler |
1127 | * | 1127 | * |
@@ -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/module.c b/arch/ia64/kernel/module.c index febc091c2f02..f1aca7cffd12 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c | |||
@@ -825,14 +825,16 @@ apply_relocate_add (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symind | |||
825 | * XXX Should have an arch-hook for running this after final section | 825 | * XXX Should have an arch-hook for running this after final section |
826 | * addresses have been selected... | 826 | * addresses have been selected... |
827 | */ | 827 | */ |
828 | /* See if gp can cover the entire core module: */ | 828 | uint64_t gp; |
829 | uint64_t gp = (uint64_t) mod->module_core + MAX_LTOFF / 2; | 829 | if (mod->core_size > MAX_LTOFF) |
830 | if (mod->core_size >= MAX_LTOFF) | ||
831 | /* | 830 | /* |
832 | * This takes advantage of fact that SHF_ARCH_SMALL gets allocated | 831 | * This takes advantage of fact that SHF_ARCH_SMALL gets allocated |
833 | * at the end of the module. | 832 | * at the end of the module. |
834 | */ | 833 | */ |
835 | gp = (uint64_t) mod->module_core + mod->core_size - MAX_LTOFF / 2; | 834 | gp = mod->core_size - MAX_LTOFF / 2; |
835 | else | ||
836 | gp = mod->core_size / 2; | ||
837 | gp = (uint64_t) mod->module_core + ((gp + 7) & -8); | ||
836 | mod->arch.gp = gp; | 838 | mod->arch.gp = gp; |
837 | DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp); | 839 | DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp); |
838 | } | 840 | } |
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 { | |||
497 | static pfm_stats_t pfm_stats[NR_CPUS]; | 497 | static pfm_stats_t pfm_stats[NR_CPUS]; |
498 | static pfm_session_t pfm_sessions; /* global sessions information */ | 498 | static pfm_session_t pfm_sessions; /* global sessions information */ |
499 | 499 | ||
500 | static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED; | ||
501 | static pfm_intr_handler_desc_t *pfm_alt_intr_handler; | ||
502 | |||
500 | static struct proc_dir_entry *perfmon_dir; | 503 | static struct proc_dir_entry *perfmon_dir; |
501 | static pfm_uuid_t pfm_null_uuid = {0,}; | 504 | static pfm_uuid_t pfm_null_uuid = {0,}; |
502 | 505 | ||
@@ -606,6 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info); | |||
606 | DEFINE_PER_CPU(struct task_struct *, pmu_owner); | 609 | DEFINE_PER_CPU(struct task_struct *, pmu_owner); |
607 | DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); | 610 | DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); |
608 | DEFINE_PER_CPU(unsigned long, pmu_activation_number); | 611 | DEFINE_PER_CPU(unsigned long, pmu_activation_number); |
612 | EXPORT_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) | |||
1325 | error_conflict: | 1329 | error_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)); |
1329 | abort: | 1333 | abort: |
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 | ||
6438 | static void | ||
6439 | pfm_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 | |||
6464 | void | ||
6465 | pfm_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 | |||
6489 | int | ||
6490 | pfm_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 | |||
6526 | cleanup_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 | } | ||
6538 | EXPORT_SYMBOL_GPL(pfm_install_alt_pmu_interrupt); | ||
6539 | |||
6540 | int | ||
6541 | pfm_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 | } | ||
6571 | EXPORT_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..575a8f657b31 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c | |||
@@ -635,11 +635,17 @@ ia64_flush_fph (struct task_struct *task) | |||
635 | { | 635 | { |
636 | struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); | 636 | struct ia64_psr *psr = ia64_psr(ia64_task_regs(task)); |
637 | 637 | ||
638 | /* | ||
639 | * Prevent migrating this task while | ||
640 | * we're fiddling with the FPU state | ||
641 | */ | ||
642 | preempt_disable(); | ||
638 | if (ia64_is_local_fpu_owner(task) && psr->mfh) { | 643 | if (ia64_is_local_fpu_owner(task) && psr->mfh) { |
639 | psr->mfh = 0; | 644 | psr->mfh = 0; |
640 | task->thread.flags |= IA64_THREAD_FPH_VALID; | 645 | task->thread.flags |= IA64_THREAD_FPH_VALID; |
641 | ia64_save_fpu(&task->thread.fph[0]); | 646 | ia64_save_fpu(&task->thread.fph[0]); |
642 | } | 647 | } |
648 | preempt_enable(); | ||
643 | } | 649 | } |
644 | 650 | ||
645 | /* | 651 | /* |
@@ -692,16 +698,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt, | |||
692 | unsigned long cfm) | 698 | unsigned long cfm) |
693 | { | 699 | { |
694 | struct unw_frame_info info, prev_info; | 700 | struct unw_frame_info info, prev_info; |
695 | unsigned long ip, pr; | 701 | unsigned long ip, sp, pr; |
696 | 702 | ||
697 | unw_init_from_blocked_task(&info, child); | 703 | unw_init_from_blocked_task(&info, child); |
698 | while (1) { | 704 | while (1) { |
699 | prev_info = info; | 705 | prev_info = info; |
700 | if (unw_unwind(&info) < 0) | 706 | if (unw_unwind(&info) < 0) |
701 | return; | 707 | return; |
702 | if (unw_get_rp(&info, &ip) < 0) | 708 | |
709 | unw_get_sp(&info, &sp); | ||
710 | if ((long)((unsigned long)child + IA64_STK_OFFSET - sp) | ||
711 | < IA64_PT_REGS_SIZE) { | ||
712 | dprintk("ptrace.%s: ran off the top of the kernel " | ||
713 | "stack\n", __FUNCTION__); | ||
714 | return; | ||
715 | } | ||
716 | if (unw_get_pr (&prev_info, &pr) < 0) { | ||
717 | unw_get_rp(&prev_info, &ip); | ||
718 | dprintk("ptrace.%s: failed to read " | ||
719 | "predicate register (ip=0x%lx)\n", | ||
720 | __FUNCTION__, ip); | ||
703 | return; | 721 | return; |
704 | if (ip < FIXADDR_USER_END) | 722 | } |
723 | if (unw_is_intr_frame(&info) | ||
724 | && (pr & (1UL << PRED_USER_STACK))) | ||
705 | break; | 725 | break; |
706 | } | 726 | } |
707 | 727 | ||
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index b7e6b4cb374b..d14692e0920a 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c | |||
@@ -720,7 +720,8 @@ cpu_init (void) | |||
720 | ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page))); | 720 | ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page))); |
721 | 721 | ||
722 | /* | 722 | /* |
723 | * Initialize default control register to defer all speculative faults. The | 723 | * Initialize default control register to defer speculative faults except |
724 | * for those arising from TLB misses, which are not deferred. The | ||
724 | * kernel MUST NOT depend on a particular setting of these bits (in other words, | 725 | * kernel MUST NOT depend on a particular setting of these bits (in other words, |
725 | * the kernel must have recovery code for all speculative accesses). Turn on | 726 | * the kernel must have recovery code for all speculative accesses). Turn on |
726 | * dcr.lc as per recommendation by the architecture team. Most IA-32 apps | 727 | * dcr.lc as per recommendation by the architecture team. Most IA-32 apps |
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 |
630 | static inline void | 630 | static 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) { |
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c index e82ad78081b3..1861173bd4f6 100644 --- a/arch/ia64/kernel/traps.c +++ b/arch/ia64/kernel/traps.c | |||
@@ -111,6 +111,24 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs) | |||
111 | siginfo_t siginfo; | 111 | siginfo_t siginfo; |
112 | int sig, code; | 112 | int sig, code; |
113 | 113 | ||
114 | /* break.b always sets cr.iim to 0, which causes problems for | ||
115 | * debuggers. Get the real break number from the original instruction, | ||
116 | * but only for kernel code. User space break.b is left alone, to | ||
117 | * preserve the existing behaviour. All break codings have the same | ||
118 | * format, so there is no need to check the slot type. | ||
119 | */ | ||
120 | if (break_num == 0 && !user_mode(regs)) { | ||
121 | struct ia64_psr *ipsr = ia64_psr(regs); | ||
122 | unsigned long *bundle = (unsigned long *)regs->cr_iip; | ||
123 | unsigned long slot; | ||
124 | switch (ipsr->ri) { | ||
125 | case 0: slot = (bundle[0] >> 5); break; | ||
126 | case 1: slot = (bundle[0] >> 46) | (bundle[1] << 18); break; | ||
127 | default: slot = (bundle[1] >> 23); break; | ||
128 | } | ||
129 | break_num = ((slot >> 36 & 1) << 20) | (slot >> 6 & 0xfffff); | ||
130 | } | ||
131 | |||
114 | /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ | 132 | /* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */ |
115 | siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); | 133 | siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri); |
116 | siginfo.si_imm = break_num; | 134 | siginfo.si_imm = break_num; |
@@ -202,13 +220,21 @@ disabled_fph_fault (struct pt_regs *regs) | |||
202 | 220 | ||
203 | /* first, grant user-level access to fph partition: */ | 221 | /* first, grant user-level access to fph partition: */ |
204 | psr->dfh = 0; | 222 | psr->dfh = 0; |
223 | |||
224 | /* | ||
225 | * Make sure that no other task gets in on this processor | ||
226 | * while we're claiming the FPU | ||
227 | */ | ||
228 | preempt_disable(); | ||
205 | #ifndef CONFIG_SMP | 229 | #ifndef CONFIG_SMP |
206 | { | 230 | { |
207 | struct task_struct *fpu_owner | 231 | struct task_struct *fpu_owner |
208 | = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER); | 232 | = (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER); |
209 | 233 | ||
210 | if (ia64_is_local_fpu_owner(current)) | 234 | if (ia64_is_local_fpu_owner(current)) { |
235 | preempt_enable_no_resched(); | ||
211 | return; | 236 | return; |
237 | } | ||
212 | 238 | ||
213 | if (fpu_owner) | 239 | if (fpu_owner) |
214 | ia64_flush_fph(fpu_owner); | 240 | ia64_flush_fph(fpu_owner); |
@@ -226,6 +252,7 @@ disabled_fph_fault (struct pt_regs *regs) | |||
226 | */ | 252 | */ |
227 | psr->mfh = 1; | 253 | psr->mfh = 1; |
228 | } | 254 | } |
255 | preempt_enable_no_resched(); | ||
229 | } | 256 | } |
230 | 257 | ||
231 | static inline int | 258 | static inline int |
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 547785e3cba2..4eb2f52b87a1 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
@@ -305,8 +305,9 @@ setup_gate (void) | |||
305 | struct page *page; | 305 | struct page *page; |
306 | 306 | ||
307 | /* | 307 | /* |
308 | * Map the gate page twice: once read-only to export the ELF headers etc. and once | 308 | * Map the gate page twice: once read-only to export the ELF |
309 | * execute-only page to enable privilege-promotion via "epc": | 309 | * headers etc. and once execute-only page to enable |
310 | * privilege-promotion via "epc": | ||
310 | */ | 311 | */ |
311 | page = virt_to_page(ia64_imva(__start_gate_section)); | 312 | page = virt_to_page(ia64_imva(__start_gate_section)); |
312 | put_kernel_page(page, GATE_ADDR, PAGE_READONLY); | 313 | put_kernel_page(page, GATE_ADDR, PAGE_READONLY); |
@@ -315,6 +316,20 @@ setup_gate (void) | |||
315 | put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE); | 316 | put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE); |
316 | #else | 317 | #else |
317 | put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE); | 318 | put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE); |
319 | /* Fill in the holes (if any) with read-only zero pages: */ | ||
320 | { | ||
321 | unsigned long addr; | ||
322 | |||
323 | for (addr = GATE_ADDR + PAGE_SIZE; | ||
324 | addr < GATE_ADDR + PERCPU_PAGE_SIZE; | ||
325 | addr += PAGE_SIZE) | ||
326 | { | ||
327 | put_kernel_page(ZERO_PAGE(0), addr, | ||
328 | PAGE_READONLY); | ||
329 | put_kernel_page(ZERO_PAGE(0), addr + PERCPU_PAGE_SIZE, | ||
330 | PAGE_READONLY); | ||
331 | } | ||
332 | } | ||
318 | #endif | 333 | #endif |
319 | ia64_patch_gate(); | 334 | ia64_patch_gate(); |
320 | } | 335 | } |
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 4fb44984afe6..44bfc7f318cb 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c | |||
@@ -222,7 +222,7 @@ void __init early_sn_setup(void) | |||
222 | 222 | ||
223 | extern int platform_intr_list[]; | 223 | extern int platform_intr_list[]; |
224 | extern nasid_t master_nasid; | 224 | extern nasid_t master_nasid; |
225 | static int shub_1_1_found __initdata; | 225 | static int __initdata shub_1_1_found = 0; |
226 | 226 | ||
227 | /* | 227 | /* |
228 | * sn_check_for_wars | 228 | * sn_check_for_wars |
@@ -251,7 +251,7 @@ static void __init sn_check_for_wars(void) | |||
251 | } else { | 251 | } else { |
252 | for_each_online_node(cnode) { | 252 | for_each_online_node(cnode) { |
253 | if (is_shub_1_1(cnodeid_to_nasid(cnode))) | 253 | if (is_shub_1_1(cnodeid_to_nasid(cnode))) |
254 | sn_hub_info->shub_1_1_found = 1; | 254 | shub_1_1_found = 1; |
255 | } | 255 | } |
256 | } | 256 | } |
257 | } | 257 | } |
@@ -271,6 +271,8 @@ void __init sn_setup(char **cmdline_p) | |||
271 | int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); | 271 | int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); |
272 | extern void sn_cpu_init(void); | 272 | extern void sn_cpu_init(void); |
273 | 273 | ||
274 | ia64_sn_plat_set_error_handling_features(); | ||
275 | |||
274 | /* | 276 | /* |
275 | * If the generic code has enabled vga console support - lets | 277 | * If the generic code has enabled vga console support - lets |
276 | * get rid of it again. This is a kludge for the fact that ACPI | 278 | * get rid of it again. This is a kludge for the fact that ACPI |
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index ab9b5f35c2a7..a087b274847e 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c | |||
@@ -432,7 +432,7 @@ static int tiocx_reload(struct cx_dev *cx_dev) | |||
432 | return cx_device_reload(cx_dev); | 432 | return cx_device_reload(cx_dev); |
433 | } | 433 | } |
434 | 434 | ||
435 | static ssize_t show_cxdev_control(struct device *dev, char *buf) | 435 | static ssize_t show_cxdev_control(struct device *dev, struct device_attribute *attr, char *buf) |
436 | { | 436 | { |
437 | struct cx_dev *cx_dev = to_cx_dev(dev); | 437 | struct cx_dev *cx_dev = to_cx_dev(dev); |
438 | 438 | ||
@@ -442,7 +442,7 @@ static ssize_t show_cxdev_control(struct device *dev, char *buf) | |||
442 | tiocx_btchar_get(cx_dev->cx_id.nasid)); | 442 | tiocx_btchar_get(cx_dev->cx_id.nasid)); |
443 | } | 443 | } |
444 | 444 | ||
445 | static ssize_t store_cxdev_control(struct device *dev, const char *buf, | 445 | static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf, |
446 | size_t count) | 446 | size_t count) |
447 | { | 447 | { |
448 | int n; | 448 | int n; |
@@ -518,25 +518,22 @@ static int __init tiocx_init(void) | |||
518 | return 0; | 518 | return 0; |
519 | } | 519 | } |
520 | 520 | ||
521 | static void __exit tiocx_exit(void) | 521 | static int cx_remove_device(struct device * dev, void * data) |
522 | { | 522 | { |
523 | struct device *dev; | 523 | struct cx_dev *cx_dev = to_cx_dev(dev); |
524 | struct device *tdev; | 524 | device_remove_file(dev, &dev_attr_cxdev_control); |
525 | cx_device_unregister(cx_dev); | ||
526 | return 0; | ||
527 | } | ||
525 | 528 | ||
529 | static void __exit tiocx_exit(void) | ||
530 | { | ||
526 | DBG("tiocx_exit\n"); | 531 | DBG("tiocx_exit\n"); |
527 | 532 | ||
528 | /* | 533 | /* |
529 | * Unregister devices. | 534 | * Unregister devices. |
530 | */ | 535 | */ |
531 | list_for_each_entry_safe(dev, tdev, &tiocx_bus_type.devices.list, | 536 | bus_for_each_dev(&tiocx_bus_type, NULL, NULL, cx_remove_device); |
532 | bus_list) { | ||
533 | if (dev) { | ||
534 | struct cx_dev *cx_dev = to_cx_dev(dev); | ||
535 | device_remove_file(dev, &dev_attr_cxdev_control); | ||
536 | cx_device_unregister(cx_dev); | ||
537 | } | ||
538 | } | ||
539 | |||
540 | bus_unregister(&tiocx_bus_type); | 537 | bus_unregister(&tiocx_bus_type); |
541 | } | 538 | } |
542 | 539 | ||