diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/powerpc/include/asm/pgtable.h | 6 | ||||
| -rw-r--r-- | arch/powerpc/kernel/Makefile | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 19 | ||||
| -rw-r--r-- | arch/powerpc/kernel/perf_callchain.c | 527 | ||||
| -rw-r--r-- | arch/powerpc/mm/slb.c | 37 | ||||
| -rw-r--r-- | arch/powerpc/mm/stab.c | 11 | ||||
| -rw-r--r-- | arch/x86/include/asm/perf_counter.h | 10 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 329 |
9 files changed, 921 insertions, 22 deletions
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index eb17da781128..2a5da069714e 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h | |||
| @@ -104,8 +104,8 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
| 104 | else | 104 | else |
| 105 | pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte)); | 105 | pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte)); |
| 106 | 106 | ||
| 107 | #elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) && defined(CONFIG_SMP) | 107 | #elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) |
| 108 | /* Second case is 32-bit with 64-bit PTE in SMP mode. In this case, we | 108 | /* Second case is 32-bit with 64-bit PTE. In this case, we |
| 109 | * can just store as long as we do the two halves in the right order | 109 | * can just store as long as we do the two halves in the right order |
| 110 | * with a barrier in between. This is possible because we take care, | 110 | * with a barrier in between. This is possible because we take care, |
| 111 | * in the hash code, to pre-invalidate if the PTE was already hashed, | 111 | * in the hash code, to pre-invalidate if the PTE was already hashed, |
| @@ -140,7 +140,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
| 140 | 140 | ||
| 141 | #else | 141 | #else |
| 142 | /* Anything else just stores the PTE normally. That covers all 64-bit | 142 | /* Anything else just stores the PTE normally. That covers all 64-bit |
| 143 | * cases, and 32-bit non-hash with 64-bit PTEs in UP mode | 143 | * cases, and 32-bit non-hash with 32-bit PTEs. |
| 144 | */ | 144 | */ |
| 145 | *ptep = pte; | 145 | *ptep = pte; |
| 146 | #endif | 146 | #endif |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b73396b93905..9619285f64e8 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -97,7 +97,7 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o | |||
| 97 | 97 | ||
| 98 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 98 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
| 99 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 99 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
| 100 | obj-$(CONFIG_PPC_PERF_CTRS) += perf_counter.o | 100 | obj-$(CONFIG_PPC_PERF_CTRS) += perf_counter.o perf_callchain.o |
| 101 | obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ | 101 | obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ |
| 102 | power5+-pmu.o power6-pmu.o power7-pmu.o | 102 | power5+-pmu.o power6-pmu.o power7-pmu.o |
| 103 | obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o | 103 | obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 561b64652311..197b15646eeb 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -67,6 +67,8 @@ int main(void) | |||
| 67 | DEFINE(MMCONTEXTID, offsetof(struct mm_struct, context.id)); | 67 | DEFINE(MMCONTEXTID, offsetof(struct mm_struct, context.id)); |
| 68 | #ifdef CONFIG_PPC64 | 68 | #ifdef CONFIG_PPC64 |
| 69 | DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); | 69 | DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); |
| 70 | DEFINE(SIGSEGV, SIGSEGV); | ||
| 71 | DEFINE(NMI_MASK, NMI_MASK); | ||
| 70 | #else | 72 | #else |
| 71 | DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); | 73 | DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); |
| 72 | #endif /* CONFIG_PPC64 */ | 74 | #endif /* CONFIG_PPC64 */ |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index eb898112e577..8ac85e08ffae 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -729,6 +729,11 @@ BEGIN_FTR_SECTION | |||
| 729 | bne- do_ste_alloc /* If so handle it */ | 729 | bne- do_ste_alloc /* If so handle it */ |
| 730 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | 730 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) |
| 731 | 731 | ||
| 732 | clrrdi r11,r1,THREAD_SHIFT | ||
| 733 | lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ | ||
| 734 | andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ | ||
| 735 | bne 77f /* then don't call hash_page now */ | ||
| 736 | |||
| 732 | /* | 737 | /* |
| 733 | * On iSeries, we soft-disable interrupts here, then | 738 | * On iSeries, we soft-disable interrupts here, then |
| 734 | * hard-enable interrupts so that the hash_page code can spin on | 739 | * hard-enable interrupts so that the hash_page code can spin on |
| @@ -833,6 +838,20 @@ handle_page_fault: | |||
| 833 | bl .low_hash_fault | 838 | bl .low_hash_fault |
| 834 | b .ret_from_except | 839 | b .ret_from_except |
| 835 | 840 | ||
| 841 | /* | ||
| 842 | * We come here as a result of a DSI at a point where we don't want | ||
| 843 | * to call hash_page, such as when we are accessing memory (possibly | ||
| 844 | * user memory) inside a PMU interrupt that occurred while interrupts | ||
| 845 | * were soft-disabled. We want to invoke the exception handler for | ||
| 846 | * the access, or panic if there isn't a handler. | ||
| 847 | */ | ||
| 848 | 77: bl .save_nvgprs | ||
| 849 | mr r4,r3 | ||
| 850 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 851 | li r5,SIGSEGV | ||
| 852 | bl .bad_page_fault | ||
| 853 | b .ret_from_except | ||
| 854 | |||
| 836 | /* here we have a segment miss */ | 855 | /* here we have a segment miss */ |
| 837 | do_ste_alloc: | 856 | do_ste_alloc: |
| 838 | bl .ste_allocate /* try to insert stab entry */ | 857 | bl .ste_allocate /* try to insert stab entry */ |
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c new file mode 100644 index 000000000000..f74b62c67511 --- /dev/null +++ b/arch/powerpc/kernel/perf_callchain.c | |||
| @@ -0,0 +1,527 @@ | |||
| 1 | /* | ||
| 2 | * Performance counter callchain support - powerpc architecture code | ||
| 3 | * | ||
| 4 | * Copyright © 2009 Paul Mackerras, IBM Corporation. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/sched.h> | ||
| 13 | #include <linux/perf_counter.h> | ||
| 14 | #include <linux/percpu.h> | ||
| 15 | #include <linux/uaccess.h> | ||
| 16 | #include <linux/mm.h> | ||
| 17 | #include <asm/ptrace.h> | ||
| 18 | #include <asm/pgtable.h> | ||
| 19 | #include <asm/sigcontext.h> | ||
| 20 | #include <asm/ucontext.h> | ||
| 21 | #include <asm/vdso.h> | ||
| 22 | #ifdef CONFIG_PPC64 | ||
| 23 | #include "ppc32.h" | ||
| 24 | #endif | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Store another value in a callchain_entry. | ||
| 28 | */ | ||
| 29 | static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip) | ||
| 30 | { | ||
| 31 | unsigned int nr = entry->nr; | ||
| 32 | |||
| 33 | if (nr < PERF_MAX_STACK_DEPTH) { | ||
| 34 | entry->ip[nr] = ip; | ||
| 35 | entry->nr = nr + 1; | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | /* | ||
| 40 | * Is sp valid as the address of the next kernel stack frame after prev_sp? | ||
| 41 | * The next frame may be in a different stack area but should not go | ||
| 42 | * back down in the same stack area. | ||
| 43 | */ | ||
| 44 | static int valid_next_sp(unsigned long sp, unsigned long prev_sp) | ||
| 45 | { | ||
| 46 | if (sp & 0xf) | ||
| 47 | return 0; /* must be 16-byte aligned */ | ||
| 48 | if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) | ||
| 49 | return 0; | ||
| 50 | if (sp >= prev_sp + STACK_FRAME_OVERHEAD) | ||
| 51 | return 1; | ||
| 52 | /* | ||
| 53 | * sp could decrease when we jump off an interrupt stack | ||
| 54 | * back to the regular process stack. | ||
| 55 | */ | ||
| 56 | if ((sp & ~(THREAD_SIZE - 1)) != (prev_sp & ~(THREAD_SIZE - 1))) | ||
| 57 | return 1; | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static void perf_callchain_kernel(struct pt_regs *regs, | ||
| 62 | struct perf_callchain_entry *entry) | ||
| 63 | { | ||
| 64 | unsigned long sp, next_sp; | ||
| 65 | unsigned long next_ip; | ||
| 66 | unsigned long lr; | ||
| 67 | long level = 0; | ||
| 68 | unsigned long *fp; | ||
| 69 | |||
| 70 | lr = regs->link; | ||
| 71 | sp = regs->gpr[1]; | ||
| 72 | callchain_store(entry, PERF_CONTEXT_KERNEL); | ||
| 73 | callchain_store(entry, regs->nip); | ||
| 74 | |||
| 75 | if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) | ||
| 76 | return; | ||
| 77 | |||
| 78 | for (;;) { | ||
| 79 | fp = (unsigned long *) sp; | ||
| 80 | next_sp = fp[0]; | ||
| 81 | |||
| 82 | if (next_sp == sp + STACK_INT_FRAME_SIZE && | ||
| 83 | fp[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) { | ||
| 84 | /* | ||
| 85 | * This looks like an interrupt frame for an | ||
| 86 | * interrupt that occurred in the kernel | ||
| 87 | */ | ||
| 88 | regs = (struct pt_regs *)(sp + STACK_FRAME_OVERHEAD); | ||
| 89 | next_ip = regs->nip; | ||
| 90 | lr = regs->link; | ||
| 91 | level = 0; | ||
| 92 | callchain_store(entry, PERF_CONTEXT_KERNEL); | ||
| 93 | |||
| 94 | } else { | ||
| 95 | if (level == 0) | ||
| 96 | next_ip = lr; | ||
| 97 | else | ||
| 98 | next_ip = fp[STACK_FRAME_LR_SAVE]; | ||
| 99 | |||
| 100 | /* | ||
| 101 | * We can't tell which of the first two addresses | ||
| 102 | * we get are valid, but we can filter out the | ||
| 103 | * obviously bogus ones here. We replace them | ||
| 104 | * with 0 rather than removing them entirely so | ||
| 105 | * that userspace can tell which is which. | ||
| 106 | */ | ||
| 107 | if ((level == 1 && next_ip == lr) || | ||
| 108 | (level <= 1 && !kernel_text_address(next_ip))) | ||
| 109 | next_ip = 0; | ||
| 110 | |||
| 111 | ++level; | ||
| 112 | } | ||
| 113 | |||
| 114 | callchain_store(entry, next_ip); | ||
| 115 | if (!valid_next_sp(next_sp, sp)) | ||
| 116 | return; | ||
| 117 | sp = next_sp; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | #ifdef CONFIG_PPC64 | ||
| 122 | |||
| 123 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 124 | #define is_huge_psize(pagesize) (HPAGE_SHIFT && mmu_huge_psizes[pagesize]) | ||
| 125 | #else | ||
| 126 | #define is_huge_psize(pagesize) 0 | ||
| 127 | #endif | ||
| 128 | |||
| 129 | /* | ||
| 130 | * On 64-bit we don't want to invoke hash_page on user addresses from | ||
| 131 | * interrupt context, so if the access faults, we read the page tables | ||
| 132 | * to find which page (if any) is mapped and access it directly. | ||
| 133 | */ | ||
| 134 | static int read_user_stack_slow(void __user *ptr, void *ret, int nb) | ||
| 135 | { | ||
| 136 | pgd_t *pgdir; | ||
| 137 | pte_t *ptep, pte; | ||
| 138 | int pagesize; | ||
| 139 | unsigned long addr = (unsigned long) ptr; | ||
| 140 | unsigned long offset; | ||
| 141 | unsigned long pfn; | ||
| 142 | void *kaddr; | ||
| 143 | |||
| 144 | pgdir = current->mm->pgd; | ||
| 145 | if (!pgdir) | ||
| 146 | return -EFAULT; | ||
| 147 | |||
| 148 | pagesize = get_slice_psize(current->mm, addr); | ||
| 149 | |||
| 150 | /* align address to page boundary */ | ||
| 151 | offset = addr & ((1ul << mmu_psize_defs[pagesize].shift) - 1); | ||
| 152 | addr -= offset; | ||
| 153 | |||
| 154 | if (is_huge_psize(pagesize)) | ||
| 155 | ptep = huge_pte_offset(current->mm, addr); | ||
| 156 | else | ||
| 157 | ptep = find_linux_pte(pgdir, addr); | ||
| 158 | |||
| 159 | if (ptep == NULL) | ||
| 160 | return -EFAULT; | ||
| 161 | pte = *ptep; | ||
| 162 | if (!pte_present(pte) || !(pte_val(pte) & _PAGE_USER)) | ||
| 163 | return -EFAULT; | ||
| 164 | pfn = pte_pfn(pte); | ||
| 165 | if (!page_is_ram(pfn)) | ||
| 166 | return -EFAULT; | ||
| 167 | |||
| 168 | /* no highmem to worry about here */ | ||
| 169 | kaddr = pfn_to_kaddr(pfn); | ||
| 170 | memcpy(ret, kaddr + offset, nb); | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret) | ||
| 175 | { | ||
| 176 | if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned long) || | ||
| 177 | ((unsigned long)ptr & 7)) | ||
| 178 | return -EFAULT; | ||
| 179 | |||
| 180 | if (!__get_user_inatomic(*ret, ptr)) | ||
| 181 | return 0; | ||
| 182 | |||
| 183 | return read_user_stack_slow(ptr, ret, 8); | ||
| 184 | } | ||
| 185 | |||
| 186 | static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) | ||
| 187 | { | ||
| 188 | if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || | ||
| 189 | ((unsigned long)ptr & 3)) | ||
| 190 | return -EFAULT; | ||
| 191 | |||
| 192 | if (!__get_user_inatomic(*ret, ptr)) | ||
| 193 | return 0; | ||
| 194 | |||
| 195 | return read_user_stack_slow(ptr, ret, 4); | ||
| 196 | } | ||
| 197 | |||
| 198 | static inline int valid_user_sp(unsigned long sp, int is_64) | ||
| 199 | { | ||
| 200 | if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x100000000UL) - 32) | ||
| 201 | return 0; | ||
| 202 | return 1; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* | ||
| 206 | * 64-bit user processes use the same stack frame for RT and non-RT signals. | ||
| 207 | */ | ||
| 208 | struct signal_frame_64 { | ||
| 209 | char dummy[__SIGNAL_FRAMESIZE]; | ||
| 210 | struct ucontext uc; | ||
| 211 | unsigned long unused[2]; | ||
| 212 | unsigned int tramp[6]; | ||
| 213 | struct siginfo *pinfo; | ||
| 214 | void *puc; | ||
| 215 | struct siginfo info; | ||
| 216 | char abigap[288]; | ||
| 217 | }; | ||
| 218 | |||
| 219 | static int is_sigreturn_64_address(unsigned long nip, unsigned long fp) | ||
| 220 | { | ||
| 221 | if (nip == fp + offsetof(struct signal_frame_64, tramp)) | ||
| 222 | return 1; | ||
| 223 | if (vdso64_rt_sigtramp && current->mm->context.vdso_base && | ||
| 224 | nip == current->mm->context.vdso_base + vdso64_rt_sigtramp) | ||
| 225 | return 1; | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Do some sanity checking on the signal frame pointed to by sp. | ||
| 231 | * We check the pinfo and puc pointers in the frame. | ||
| 232 | */ | ||
| 233 | static int sane_signal_64_frame(unsigned long sp) | ||
| 234 | { | ||
| 235 | struct signal_frame_64 __user *sf; | ||
| 236 | unsigned long pinfo, puc; | ||
| 237 | |||
| 238 | sf = (struct signal_frame_64 __user *) sp; | ||
| 239 | if (read_user_stack_64((unsigned long __user *) &sf->pinfo, &pinfo) || | ||
| 240 | read_user_stack_64((unsigned long __user *) &sf->puc, &puc)) | ||
| 241 | return 0; | ||
| 242 | return pinfo == (unsigned long) &sf->info && | ||
| 243 | puc == (unsigned long) &sf->uc; | ||
| 244 | } | ||
| 245 | |||
| 246 | static void perf_callchain_user_64(struct pt_regs *regs, | ||
| 247 | struct perf_callchain_entry *entry) | ||
| 248 | { | ||
| 249 | unsigned long sp, next_sp; | ||
| 250 | unsigned long next_ip; | ||
| 251 | unsigned long lr; | ||
| 252 | long level = 0; | ||
| 253 | struct signal_frame_64 __user *sigframe; | ||
| 254 | unsigned long __user *fp, *uregs; | ||
| 255 | |||
| 256 | next_ip = regs->nip; | ||
| 257 | lr = regs->link; | ||
| 258 | sp = regs->gpr[1]; | ||
| 259 | callchain_store(entry, PERF_CONTEXT_USER); | ||
| 260 | callchain_store(entry, next_ip); | ||
| 261 | |||
| 262 | for (;;) { | ||
| 263 | fp = (unsigned long __user *) sp; | ||
| 264 | if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp)) | ||
| 265 | return; | ||
| 266 | if (level > 0 && read_user_stack_64(&fp[2], &next_ip)) | ||
| 267 | return; | ||
| 268 | |||
| 269 | /* | ||
| 270 | * Note: the next_sp - sp >= signal frame size check | ||
| 271 | * is true when next_sp < sp, which can happen when | ||
| 272 | * transitioning from an alternate signal stack to the | ||
| 273 | * normal stack. | ||
| 274 | */ | ||
| 275 | if (next_sp - sp >= sizeof(struct signal_frame_64) && | ||
| 276 | (is_sigreturn_64_address(next_ip, sp) || | ||
| 277 | (level <= 1 && is_sigreturn_64_address(lr, sp))) && | ||
| 278 | sane_signal_64_frame(sp)) { | ||
| 279 | /* | ||
| 280 | * This looks like an signal frame | ||
| 281 | */ | ||
| 282 | sigframe = (struct signal_frame_64 __user *) sp; | ||
| 283 | uregs = sigframe->uc.uc_mcontext.gp_regs; | ||
| 284 | if (read_user_stack_64(&uregs[PT_NIP], &next_ip) || | ||
| 285 | read_user_stack_64(&uregs[PT_LNK], &lr) || | ||
| 286 | read_user_stack_64(&uregs[PT_R1], &sp)) | ||
| 287 | return; | ||
| 288 | level = 0; | ||
| 289 | callchain_store(entry, PERF_CONTEXT_USER); | ||
| 290 | callchain_store(entry, next_ip); | ||
| 291 | continue; | ||
| 292 | } | ||
| 293 | |||
| 294 | if (level == 0) | ||
| 295 | next_ip = lr; | ||
| 296 | callchain_store(entry, next_ip); | ||
| 297 | ++level; | ||
| 298 | sp = next_sp; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | static inline int current_is_64bit(void) | ||
| 303 | { | ||
| 304 | /* | ||
| 305 | * We can't use test_thread_flag() here because we may be on an | ||
| 306 | * interrupt stack, and the thread flags don't get copied over | ||
| 307 | * from the thread_info on the main stack to the interrupt stack. | ||
| 308 | */ | ||
| 309 | return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT); | ||
| 310 | } | ||
| 311 | |||
| 312 | #else /* CONFIG_PPC64 */ | ||
| 313 | /* | ||
| 314 | * On 32-bit we just access the address and let hash_page create a | ||
| 315 | * HPTE if necessary, so there is no need to fall back to reading | ||
| 316 | * the page tables. Since this is called at interrupt level, | ||
| 317 | * do_page_fault() won't treat a DSI as a page fault. | ||
| 318 | */ | ||
| 319 | static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) | ||
| 320 | { | ||
| 321 | if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) || | ||
| 322 | ((unsigned long)ptr & 3)) | ||
| 323 | return -EFAULT; | ||
| 324 | |||
| 325 | return __get_user_inatomic(*ret, ptr); | ||
| 326 | } | ||
| 327 | |||
| 328 | static inline void perf_callchain_user_64(struct pt_regs *regs, | ||
| 329 | struct perf_callchain_entry *entry) | ||
| 330 | { | ||
| 331 | } | ||
| 332 | |||
| 333 | static inline int current_is_64bit(void) | ||
| 334 | { | ||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static inline int valid_user_sp(unsigned long sp, int is_64) | ||
| 339 | { | ||
| 340 | if (!sp || (sp & 7) || sp > TASK_SIZE - 32) | ||
| 341 | return 0; | ||
| 342 | return 1; | ||
| 343 | } | ||
| 344 | |||
| 345 | #define __SIGNAL_FRAMESIZE32 __SIGNAL_FRAMESIZE | ||
| 346 | #define sigcontext32 sigcontext | ||
| 347 | #define mcontext32 mcontext | ||
| 348 | #define ucontext32 ucontext | ||
| 349 | #define compat_siginfo_t struct siginfo | ||
| 350 | |||
| 351 | #endif /* CONFIG_PPC64 */ | ||
| 352 | |||
| 353 | /* | ||
| 354 | * Layout for non-RT signal frames | ||
| 355 | */ | ||
| 356 | struct signal_frame_32 { | ||
| 357 | char dummy[__SIGNAL_FRAMESIZE32]; | ||
| 358 | struct sigcontext32 sctx; | ||
| 359 | struct mcontext32 mctx; | ||
| 360 | int abigap[56]; | ||
| 361 | }; | ||
| 362 | |||
| 363 | /* | ||
| 364 | * Layout for RT signal frames | ||
| 365 | */ | ||
| 366 | struct rt_signal_frame_32 { | ||
| 367 | char dummy[__SIGNAL_FRAMESIZE32 + 16]; | ||
| 368 | compat_siginfo_t info; | ||
| 369 | struct ucontext32 uc; | ||
| 370 | int abigap[56]; | ||
| 371 | }; | ||
| 372 | |||
| 373 | static int is_sigreturn_32_address(unsigned int nip, unsigned int fp) | ||
| 374 | { | ||
| 375 | if (nip == fp + offsetof(struct signal_frame_32, mctx.mc_pad)) | ||
| 376 | return 1; | ||
| 377 | if (vdso32_sigtramp && current->mm->context.vdso_base && | ||
| 378 | nip == current->mm->context.vdso_base + vdso32_sigtramp) | ||
| 379 | return 1; | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static int is_rt_sigreturn_32_address(unsigned int nip, unsigned int fp) | ||
| 384 | { | ||
| 385 | if (nip == fp + offsetof(struct rt_signal_frame_32, | ||
| 386 | uc.uc_mcontext.mc_pad)) | ||
| 387 | return 1; | ||
| 388 | if (vdso32_rt_sigtramp && current->mm->context.vdso_base && | ||
| 389 | nip == current->mm->context.vdso_base + vdso32_rt_sigtramp) | ||
| 390 | return 1; | ||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int sane_signal_32_frame(unsigned int sp) | ||
| 395 | { | ||
| 396 | struct signal_frame_32 __user *sf; | ||
| 397 | unsigned int regs; | ||
| 398 | |||
| 399 | sf = (struct signal_frame_32 __user *) (unsigned long) sp; | ||
| 400 | if (read_user_stack_32((unsigned int __user *) &sf->sctx.regs, ®s)) | ||
| 401 | return 0; | ||
| 402 | return regs == (unsigned long) &sf->mctx; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int sane_rt_signal_32_frame(unsigned int sp) | ||
| 406 | { | ||
| 407 | struct rt_signal_frame_32 __user *sf; | ||
| 408 | unsigned int regs; | ||
| 409 | |||
| 410 | sf = (struct rt_signal_frame_32 __user *) (unsigned long) sp; | ||
| 411 | if (read_user_stack_32((unsigned int __user *) &sf->uc.uc_regs, ®s)) | ||
| 412 | return 0; | ||
| 413 | return regs == (unsigned long) &sf->uc.uc_mcontext; | ||
| 414 | } | ||
| 415 | |||
| 416 | static unsigned int __user *signal_frame_32_regs(unsigned int sp, | ||
| 417 | unsigned int next_sp, unsigned int next_ip) | ||
| 418 | { | ||
| 419 | struct mcontext32 __user *mctx = NULL; | ||
| 420 | struct signal_frame_32 __user *sf; | ||
| 421 | struct rt_signal_frame_32 __user *rt_sf; | ||
| 422 | |||
| 423 | /* | ||
| 424 | * Note: the next_sp - sp >= signal frame size check | ||
| 425 | * is true when next_sp < sp, for example, when | ||
| 426 | * transitioning from an alternate signal stack to the | ||
| 427 | * normal stack. | ||
| 428 | */ | ||
| 429 | if (next_sp - sp >= sizeof(struct signal_frame_32) && | ||
| 430 | is_sigreturn_32_address(next_ip, sp) && | ||
| 431 | sane_signal_32_frame(sp)) { | ||
| 432 | sf = (struct signal_frame_32 __user *) (unsigned long) sp; | ||
| 433 | mctx = &sf->mctx; | ||
| 434 | } | ||
| 435 | |||
| 436 | if (!mctx && next_sp - sp >= sizeof(struct rt_signal_frame_32) && | ||
| 437 | is_rt_sigreturn_32_address(next_ip, sp) && | ||
| 438 | sane_rt_signal_32_frame(sp)) { | ||
| 439 | rt_sf = (struct rt_signal_frame_32 __user *) (unsigned long) sp; | ||
| 440 | mctx = &rt_sf->uc.uc_mcontext; | ||
| 441 | } | ||
| 442 | |||
| 443 | if (!mctx) | ||
| 444 | return NULL; | ||
| 445 | return mctx->mc_gregs; | ||
| 446 | } | ||
| 447 | |||
| 448 | static void perf_callchain_user_32(struct pt_regs *regs, | ||
| 449 | struct perf_callchain_entry *entry) | ||
| 450 | { | ||
| 451 | unsigned int sp, next_sp; | ||
| 452 | unsigned int next_ip; | ||
| 453 | unsigned int lr; | ||
| 454 | long level = 0; | ||
| 455 | unsigned int __user *fp, *uregs; | ||
| 456 | |||
| 457 | next_ip = regs->nip; | ||
| 458 | lr = regs->link; | ||
| 459 | sp = regs->gpr[1]; | ||
| 460 | callchain_store(entry, PERF_CONTEXT_USER); | ||
| 461 | callchain_store(entry, next_ip); | ||
| 462 | |||
| 463 | while (entry->nr < PERF_MAX_STACK_DEPTH) { | ||
| 464 | fp = (unsigned int __user *) (unsigned long) sp; | ||
| 465 | if (!valid_user_sp(sp, 0) || read_user_stack_32(fp, &next_sp)) | ||
| 466 | return; | ||
| 467 | if (level > 0 && read_user_stack_32(&fp[1], &next_ip)) | ||
| 468 | return; | ||
| 469 | |||
| 470 | uregs = signal_frame_32_regs(sp, next_sp, next_ip); | ||
| 471 | if (!uregs && level <= 1) | ||
| 472 | uregs = signal_frame_32_regs(sp, next_sp, lr); | ||
| 473 | if (uregs) { | ||
| 474 | /* | ||
| 475 | * This looks like an signal frame, so restart | ||
| 476 | * the stack trace with the values in it. | ||
| 477 | */ | ||
| 478 | if (read_user_stack_32(&uregs[PT_NIP], &next_ip) || | ||
| 479 | read_user_stack_32(&uregs[PT_LNK], &lr) || | ||
| 480 | read_user_stack_32(&uregs[PT_R1], &sp)) | ||
| 481 | return; | ||
| 482 | level = 0; | ||
| 483 | callchain_store(entry, PERF_CONTEXT_USER); | ||
| 484 | callchain_store(entry, next_ip); | ||
| 485 | continue; | ||
| 486 | } | ||
| 487 | |||
| 488 | if (level == 0) | ||
| 489 | next_ip = lr; | ||
| 490 | callchain_store(entry, next_ip); | ||
| 491 | ++level; | ||
| 492 | sp = next_sp; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | /* | ||
| 497 | * Since we can't get PMU interrupts inside a PMU interrupt handler, | ||
| 498 | * we don't need separate irq and nmi entries here. | ||
| 499 | */ | ||
| 500 | static DEFINE_PER_CPU(struct perf_callchain_entry, callchain); | ||
| 501 | |||
| 502 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | ||
| 503 | { | ||
| 504 | struct perf_callchain_entry *entry = &__get_cpu_var(callchain); | ||
| 505 | |||
| 506 | entry->nr = 0; | ||
| 507 | |||
| 508 | if (current->pid == 0) /* idle task? */ | ||
| 509 | return entry; | ||
| 510 | |||
| 511 | if (!user_mode(regs)) { | ||
| 512 | perf_callchain_kernel(regs, entry); | ||
| 513 | if (current->mm) | ||
| 514 | regs = task_pt_regs(current); | ||
| 515 | else | ||
| 516 | regs = NULL; | ||
| 517 | } | ||
| 518 | |||
| 519 | if (regs) { | ||
| 520 | if (current_is_64bit()) | ||
| 521 | perf_callchain_user_64(regs, entry); | ||
| 522 | else | ||
| 523 | perf_callchain_user_32(regs, entry); | ||
| 524 | } | ||
| 525 | |||
| 526 | return entry; | ||
| 527 | } | ||
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 5b7038f248b6..a685652effeb 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c | |||
| @@ -92,15 +92,13 @@ static inline void create_shadowed_slbe(unsigned long ea, int ssize, | |||
| 92 | : "memory" ); | 92 | : "memory" ); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | void slb_flush_and_rebolt(void) | 95 | static void __slb_flush_and_rebolt(void) |
| 96 | { | 96 | { |
| 97 | /* If you change this make sure you change SLB_NUM_BOLTED | 97 | /* If you change this make sure you change SLB_NUM_BOLTED |
| 98 | * appropriately too. */ | 98 | * appropriately too. */ |
| 99 | unsigned long linear_llp, vmalloc_llp, lflags, vflags; | 99 | unsigned long linear_llp, vmalloc_llp, lflags, vflags; |
| 100 | unsigned long ksp_esid_data, ksp_vsid_data; | 100 | unsigned long ksp_esid_data, ksp_vsid_data; |
| 101 | 101 | ||
| 102 | WARN_ON(!irqs_disabled()); | ||
| 103 | |||
| 104 | linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; | 102 | linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; |
| 105 | vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; | 103 | vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; |
| 106 | lflags = SLB_VSID_KERNEL | linear_llp; | 104 | lflags = SLB_VSID_KERNEL | linear_llp; |
| @@ -117,12 +115,6 @@ void slb_flush_and_rebolt(void) | |||
| 117 | ksp_vsid_data = get_slb_shadow()->save_area[2].vsid; | 115 | ksp_vsid_data = get_slb_shadow()->save_area[2].vsid; |
| 118 | } | 116 | } |
| 119 | 117 | ||
| 120 | /* | ||
| 121 | * We can't take a PMU exception in the following code, so hard | ||
| 122 | * disable interrupts. | ||
| 123 | */ | ||
| 124 | hard_irq_disable(); | ||
| 125 | |||
| 126 | /* We need to do this all in asm, so we're sure we don't touch | 118 | /* We need to do this all in asm, so we're sure we don't touch |
| 127 | * the stack between the slbia and rebolting it. */ | 119 | * the stack between the slbia and rebolting it. */ |
| 128 | asm volatile("isync\n" | 120 | asm volatile("isync\n" |
| @@ -139,6 +131,21 @@ void slb_flush_and_rebolt(void) | |||
| 139 | : "memory"); | 131 | : "memory"); |
| 140 | } | 132 | } |
| 141 | 133 | ||
| 134 | void slb_flush_and_rebolt(void) | ||
| 135 | { | ||
| 136 | |||
| 137 | WARN_ON(!irqs_disabled()); | ||
| 138 | |||
| 139 | /* | ||
| 140 | * We can't take a PMU exception in the following code, so hard | ||
| 141 | * disable interrupts. | ||
| 142 | */ | ||
| 143 | hard_irq_disable(); | ||
| 144 | |||
| 145 | __slb_flush_and_rebolt(); | ||
| 146 | get_paca()->slb_cache_ptr = 0; | ||
| 147 | } | ||
| 148 | |||
| 142 | void slb_vmalloc_update(void) | 149 | void slb_vmalloc_update(void) |
| 143 | { | 150 | { |
| 144 | unsigned long vflags; | 151 | unsigned long vflags; |
| @@ -180,12 +187,20 @@ static inline int esids_match(unsigned long addr1, unsigned long addr2) | |||
| 180 | /* Flush all user entries from the segment table of the current processor. */ | 187 | /* Flush all user entries from the segment table of the current processor. */ |
| 181 | void switch_slb(struct task_struct *tsk, struct mm_struct *mm) | 188 | void switch_slb(struct task_struct *tsk, struct mm_struct *mm) |
| 182 | { | 189 | { |
| 183 | unsigned long offset = get_paca()->slb_cache_ptr; | 190 | unsigned long offset; |
| 184 | unsigned long slbie_data = 0; | 191 | unsigned long slbie_data = 0; |
| 185 | unsigned long pc = KSTK_EIP(tsk); | 192 | unsigned long pc = KSTK_EIP(tsk); |
| 186 | unsigned long stack = KSTK_ESP(tsk); | 193 | unsigned long stack = KSTK_ESP(tsk); |
| 187 | unsigned long unmapped_base; | 194 | unsigned long unmapped_base; |
| 188 | 195 | ||
| 196 | /* | ||
| 197 | * We need interrupts hard-disabled here, not just soft-disabled, | ||
| 198 | * so that a PMU interrupt can't occur, which might try to access | ||
| 199 | * user memory (to get a stack trace) and possible cause an SLB miss | ||
| 200 | * which would update the slb_cache/slb_cache_ptr fields in the PACA. | ||
| 201 | */ | ||
| 202 | hard_irq_disable(); | ||
| 203 | offset = get_paca()->slb_cache_ptr; | ||
| 189 | if (!cpu_has_feature(CPU_FTR_NO_SLBIE_B) && | 204 | if (!cpu_has_feature(CPU_FTR_NO_SLBIE_B) && |
| 190 | offset <= SLB_CACHE_ENTRIES) { | 205 | offset <= SLB_CACHE_ENTRIES) { |
| 191 | int i; | 206 | int i; |
| @@ -200,7 +215,7 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm) | |||
| 200 | } | 215 | } |
| 201 | asm volatile("isync" : : : "memory"); | 216 | asm volatile("isync" : : : "memory"); |
| 202 | } else { | 217 | } else { |
| 203 | slb_flush_and_rebolt(); | 218 | __slb_flush_and_rebolt(); |
| 204 | } | 219 | } |
| 205 | 220 | ||
| 206 | /* Workaround POWER5 < DD2.1 issue */ | 221 | /* Workaround POWER5 < DD2.1 issue */ |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 98cd1dc2ae75..ab5fb48b3e90 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
| @@ -164,7 +164,7 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) | |||
| 164 | { | 164 | { |
| 165 | struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr; | 165 | struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr; |
| 166 | struct stab_entry *ste; | 166 | struct stab_entry *ste; |
| 167 | unsigned long offset = __get_cpu_var(stab_cache_ptr); | 167 | unsigned long offset; |
| 168 | unsigned long pc = KSTK_EIP(tsk); | 168 | unsigned long pc = KSTK_EIP(tsk); |
| 169 | unsigned long stack = KSTK_ESP(tsk); | 169 | unsigned long stack = KSTK_ESP(tsk); |
| 170 | unsigned long unmapped_base; | 170 | unsigned long unmapped_base; |
| @@ -172,6 +172,15 @@ void switch_stab(struct task_struct *tsk, struct mm_struct *mm) | |||
| 172 | /* Force previous translations to complete. DRENG */ | 172 | /* Force previous translations to complete. DRENG */ |
| 173 | asm volatile("isync" : : : "memory"); | 173 | asm volatile("isync" : : : "memory"); |
| 174 | 174 | ||
| 175 | /* | ||
| 176 | * We need interrupts hard-disabled here, not just soft-disabled, | ||
| 177 | * so that a PMU interrupt can't occur, which might try to access | ||
| 178 | * user memory (to get a stack trace) and possible cause an STAB miss | ||
| 179 | * which would update the stab_cache/stab_cache_ptr per-cpu variables. | ||
| 180 | */ | ||
| 181 | hard_irq_disable(); | ||
| 182 | |||
| 183 | offset = __get_cpu_var(stab_cache_ptr); | ||
| 175 | if (offset <= NR_STAB_CACHE_ENTRIES) { | 184 | if (offset <= NR_STAB_CACHE_ENTRIES) { |
| 176 | int i; | 185 | int i; |
| 177 | 186 | ||
diff --git a/arch/x86/include/asm/perf_counter.h b/arch/x86/include/asm/perf_counter.h index fa64e401589d..e7b7c938ae27 100644 --- a/arch/x86/include/asm/perf_counter.h +++ b/arch/x86/include/asm/perf_counter.h | |||
| @@ -84,6 +84,16 @@ union cpuid10_edx { | |||
| 84 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b | 84 | #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b |
| 85 | #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) | 85 | #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) |
| 86 | 86 | ||
| 87 | /* | ||
| 88 | * We model BTS tracing as another fixed-mode PMC. | ||
| 89 | * | ||
| 90 | * We choose a value in the middle of the fixed counter range, since lower | ||
| 91 | * values are used by actual fixed counters and higher values are used | ||
| 92 | * to indicate other overflow conditions in the PERF_GLOBAL_STATUS msr. | ||
| 93 | */ | ||
| 94 | #define X86_PMC_IDX_FIXED_BTS (X86_PMC_IDX_FIXED + 16) | ||
| 95 | |||
| 96 | |||
| 87 | #ifdef CONFIG_PERF_COUNTERS | 97 | #ifdef CONFIG_PERF_COUNTERS |
| 88 | extern void init_hw_perf_counters(void); | 98 | extern void init_hw_perf_counters(void); |
| 89 | extern void perf_counters_lapic_init(void); | 99 | extern void perf_counters_lapic_init(void); |
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 900332b800f8..f9cd0849bd42 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * Copyright (C) 2009 Jaswinder Singh Rajput | 6 | * Copyright (C) 2009 Jaswinder Singh Rajput |
| 7 | * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter | 7 | * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter |
| 8 | * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> | 8 | * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> |
| 9 | * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com> | ||
| 9 | * | 10 | * |
| 10 | * For licencing details see kernel-base/COPYING | 11 | * For licencing details see kernel-base/COPYING |
| 11 | */ | 12 | */ |
| @@ -20,6 +21,7 @@ | |||
| 20 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
| 21 | #include <linux/uaccess.h> | 22 | #include <linux/uaccess.h> |
| 22 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
| 24 | #include <linux/cpu.h> | ||
| 23 | 25 | ||
| 24 | #include <asm/apic.h> | 26 | #include <asm/apic.h> |
| 25 | #include <asm/stacktrace.h> | 27 | #include <asm/stacktrace.h> |
| @@ -27,12 +29,52 @@ | |||
| 27 | 29 | ||
| 28 | static u64 perf_counter_mask __read_mostly; | 30 | static u64 perf_counter_mask __read_mostly; |
| 29 | 31 | ||
| 32 | /* The maximal number of PEBS counters: */ | ||
| 33 | #define MAX_PEBS_COUNTERS 4 | ||
| 34 | |||
| 35 | /* The size of a BTS record in bytes: */ | ||
| 36 | #define BTS_RECORD_SIZE 24 | ||
| 37 | |||
| 38 | /* The size of a per-cpu BTS buffer in bytes: */ | ||
| 39 | #define BTS_BUFFER_SIZE (BTS_RECORD_SIZE * 1024) | ||
| 40 | |||
| 41 | /* The BTS overflow threshold in bytes from the end of the buffer: */ | ||
| 42 | #define BTS_OVFL_TH (BTS_RECORD_SIZE * 64) | ||
| 43 | |||
| 44 | |||
| 45 | /* | ||
| 46 | * Bits in the debugctlmsr controlling branch tracing. | ||
| 47 | */ | ||
| 48 | #define X86_DEBUGCTL_TR (1 << 6) | ||
| 49 | #define X86_DEBUGCTL_BTS (1 << 7) | ||
| 50 | #define X86_DEBUGCTL_BTINT (1 << 8) | ||
| 51 | #define X86_DEBUGCTL_BTS_OFF_OS (1 << 9) | ||
| 52 | #define X86_DEBUGCTL_BTS_OFF_USR (1 << 10) | ||
| 53 | |||
| 54 | /* | ||
| 55 | * A debug store configuration. | ||
| 56 | * | ||
| 57 | * We only support architectures that use 64bit fields. | ||
| 58 | */ | ||
| 59 | struct debug_store { | ||
| 60 | u64 bts_buffer_base; | ||
| 61 | u64 bts_index; | ||
| 62 | u64 bts_absolute_maximum; | ||
| 63 | u64 bts_interrupt_threshold; | ||
| 64 | u64 pebs_buffer_base; | ||
| 65 | u64 pebs_index; | ||
| 66 | u64 pebs_absolute_maximum; | ||
| 67 | u64 pebs_interrupt_threshold; | ||
| 68 | u64 pebs_counter_reset[MAX_PEBS_COUNTERS]; | ||
| 69 | }; | ||
| 70 | |||
| 30 | struct cpu_hw_counters { | 71 | struct cpu_hw_counters { |
| 31 | struct perf_counter *counters[X86_PMC_IDX_MAX]; | 72 | struct perf_counter *counters[X86_PMC_IDX_MAX]; |
| 32 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 73 | unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
| 33 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; | 74 | unsigned long active_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)]; |
| 34 | unsigned long interrupts; | 75 | unsigned long interrupts; |
| 35 | int enabled; | 76 | int enabled; |
| 77 | struct debug_store *ds; | ||
| 36 | }; | 78 | }; |
| 37 | 79 | ||
| 38 | /* | 80 | /* |
| @@ -58,6 +100,8 @@ struct x86_pmu { | |||
| 58 | int apic; | 100 | int apic; |
| 59 | u64 max_period; | 101 | u64 max_period; |
| 60 | u64 intel_ctrl; | 102 | u64 intel_ctrl; |
| 103 | void (*enable_bts)(u64 config); | ||
| 104 | void (*disable_bts)(void); | ||
| 61 | }; | 105 | }; |
| 62 | 106 | ||
| 63 | static struct x86_pmu x86_pmu __read_mostly; | 107 | static struct x86_pmu x86_pmu __read_mostly; |
| @@ -577,6 +621,9 @@ x86_perf_counter_update(struct perf_counter *counter, | |||
| 577 | u64 prev_raw_count, new_raw_count; | 621 | u64 prev_raw_count, new_raw_count; |
| 578 | s64 delta; | 622 | s64 delta; |
| 579 | 623 | ||
| 624 | if (idx == X86_PMC_IDX_FIXED_BTS) | ||
| 625 | return 0; | ||
| 626 | |||
| 580 | /* | 627 | /* |
| 581 | * Careful: an NMI might modify the previous counter value. | 628 | * Careful: an NMI might modify the previous counter value. |
| 582 | * | 629 | * |
| @@ -666,10 +713,110 @@ static void release_pmc_hardware(void) | |||
| 666 | #endif | 713 | #endif |
| 667 | } | 714 | } |
| 668 | 715 | ||
| 716 | static inline bool bts_available(void) | ||
| 717 | { | ||
| 718 | return x86_pmu.enable_bts != NULL; | ||
| 719 | } | ||
| 720 | |||
| 721 | static inline void init_debug_store_on_cpu(int cpu) | ||
| 722 | { | ||
| 723 | struct debug_store *ds = per_cpu(cpu_hw_counters, cpu).ds; | ||
| 724 | |||
| 725 | if (!ds) | ||
| 726 | return; | ||
| 727 | |||
| 728 | wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, | ||
| 729 | (u32)((u64)(unsigned long)ds), | ||
| 730 | (u32)((u64)(unsigned long)ds >> 32)); | ||
| 731 | } | ||
| 732 | |||
| 733 | static inline void fini_debug_store_on_cpu(int cpu) | ||
| 734 | { | ||
| 735 | if (!per_cpu(cpu_hw_counters, cpu).ds) | ||
| 736 | return; | ||
| 737 | |||
| 738 | wrmsr_on_cpu(cpu, MSR_IA32_DS_AREA, 0, 0); | ||
| 739 | } | ||
| 740 | |||
| 741 | static void release_bts_hardware(void) | ||
| 742 | { | ||
| 743 | int cpu; | ||
| 744 | |||
| 745 | if (!bts_available()) | ||
| 746 | return; | ||
| 747 | |||
| 748 | get_online_cpus(); | ||
| 749 | |||
| 750 | for_each_online_cpu(cpu) | ||
| 751 | fini_debug_store_on_cpu(cpu); | ||
| 752 | |||
| 753 | for_each_possible_cpu(cpu) { | ||
| 754 | struct debug_store *ds = per_cpu(cpu_hw_counters, cpu).ds; | ||
| 755 | |||
| 756 | if (!ds) | ||
| 757 | continue; | ||
| 758 | |||
| 759 | per_cpu(cpu_hw_counters, cpu).ds = NULL; | ||
| 760 | |||
| 761 | kfree((void *)(unsigned long)ds->bts_buffer_base); | ||
| 762 | kfree(ds); | ||
| 763 | } | ||
| 764 | |||
| 765 | put_online_cpus(); | ||
| 766 | } | ||
| 767 | |||
| 768 | static int reserve_bts_hardware(void) | ||
| 769 | { | ||
| 770 | int cpu, err = 0; | ||
| 771 | |||
| 772 | if (!bts_available()) | ||
| 773 | return 0; | ||
| 774 | |||
| 775 | get_online_cpus(); | ||
| 776 | |||
| 777 | for_each_possible_cpu(cpu) { | ||
| 778 | struct debug_store *ds; | ||
| 779 | void *buffer; | ||
| 780 | |||
| 781 | err = -ENOMEM; | ||
| 782 | buffer = kzalloc(BTS_BUFFER_SIZE, GFP_KERNEL); | ||
| 783 | if (unlikely(!buffer)) | ||
| 784 | break; | ||
| 785 | |||
| 786 | ds = kzalloc(sizeof(*ds), GFP_KERNEL); | ||
| 787 | if (unlikely(!ds)) { | ||
| 788 | kfree(buffer); | ||
| 789 | break; | ||
| 790 | } | ||
| 791 | |||
| 792 | ds->bts_buffer_base = (u64)(unsigned long)buffer; | ||
| 793 | ds->bts_index = ds->bts_buffer_base; | ||
| 794 | ds->bts_absolute_maximum = | ||
| 795 | ds->bts_buffer_base + BTS_BUFFER_SIZE; | ||
| 796 | ds->bts_interrupt_threshold = | ||
| 797 | ds->bts_absolute_maximum - BTS_OVFL_TH; | ||
| 798 | |||
| 799 | per_cpu(cpu_hw_counters, cpu).ds = ds; | ||
| 800 | err = 0; | ||
| 801 | } | ||
| 802 | |||
| 803 | if (err) | ||
| 804 | release_bts_hardware(); | ||
| 805 | else { | ||
| 806 | for_each_online_cpu(cpu) | ||
| 807 | init_debug_store_on_cpu(cpu); | ||
| 808 | } | ||
| 809 | |||
| 810 | put_online_cpus(); | ||
| 811 | |||
| 812 | return err; | ||
| 813 | } | ||
| 814 | |||
| 669 | static void hw_perf_counter_destroy(struct perf_counter *counter) | 815 | static void hw_perf_counter_destroy(struct perf_counter *counter) |
| 670 | { | 816 | { |
| 671 | if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) { | 817 | if (atomic_dec_and_mutex_lock(&active_counters, &pmc_reserve_mutex)) { |
| 672 | release_pmc_hardware(); | 818 | release_pmc_hardware(); |
| 819 | release_bts_hardware(); | ||
| 673 | mutex_unlock(&pmc_reserve_mutex); | 820 | mutex_unlock(&pmc_reserve_mutex); |
| 674 | } | 821 | } |
| 675 | } | 822 | } |
| @@ -712,6 +859,42 @@ set_ext_hw_attr(struct hw_perf_counter *hwc, struct perf_counter_attr *attr) | |||
| 712 | return 0; | 859 | return 0; |
| 713 | } | 860 | } |
| 714 | 861 | ||
| 862 | static void intel_pmu_enable_bts(u64 config) | ||
| 863 | { | ||
| 864 | unsigned long debugctlmsr; | ||
| 865 | |||
| 866 | debugctlmsr = get_debugctlmsr(); | ||
| 867 | |||
| 868 | debugctlmsr |= X86_DEBUGCTL_TR; | ||
| 869 | debugctlmsr |= X86_DEBUGCTL_BTS; | ||
| 870 | debugctlmsr |= X86_DEBUGCTL_BTINT; | ||
| 871 | |||
| 872 | if (!(config & ARCH_PERFMON_EVENTSEL_OS)) | ||
| 873 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_OS; | ||
| 874 | |||
| 875 | if (!(config & ARCH_PERFMON_EVENTSEL_USR)) | ||
| 876 | debugctlmsr |= X86_DEBUGCTL_BTS_OFF_USR; | ||
| 877 | |||
| 878 | update_debugctlmsr(debugctlmsr); | ||
| 879 | } | ||
| 880 | |||
| 881 | static void intel_pmu_disable_bts(void) | ||
| 882 | { | ||
| 883 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
| 884 | unsigned long debugctlmsr; | ||
| 885 | |||
| 886 | if (!cpuc->ds) | ||
| 887 | return; | ||
| 888 | |||
| 889 | debugctlmsr = get_debugctlmsr(); | ||
| 890 | |||
| 891 | debugctlmsr &= | ||
| 892 | ~(X86_DEBUGCTL_TR | X86_DEBUGCTL_BTS | X86_DEBUGCTL_BTINT | | ||
| 893 | X86_DEBUGCTL_BTS_OFF_OS | X86_DEBUGCTL_BTS_OFF_USR); | ||
| 894 | |||
| 895 | update_debugctlmsr(debugctlmsr); | ||
| 896 | } | ||
| 897 | |||
| 715 | /* | 898 | /* |
| 716 | * Setup the hardware configuration for a given attr_type | 899 | * Setup the hardware configuration for a given attr_type |
| 717 | */ | 900 | */ |
| @@ -728,9 +911,13 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
| 728 | err = 0; | 911 | err = 0; |
| 729 | if (!atomic_inc_not_zero(&active_counters)) { | 912 | if (!atomic_inc_not_zero(&active_counters)) { |
| 730 | mutex_lock(&pmc_reserve_mutex); | 913 | mutex_lock(&pmc_reserve_mutex); |
| 731 | if (atomic_read(&active_counters) == 0 && !reserve_pmc_hardware()) | 914 | if (atomic_read(&active_counters) == 0) { |
| 732 | err = -EBUSY; | 915 | if (!reserve_pmc_hardware()) |
| 733 | else | 916 | err = -EBUSY; |
| 917 | else | ||
| 918 | err = reserve_bts_hardware(); | ||
| 919 | } | ||
| 920 | if (!err) | ||
| 734 | atomic_inc(&active_counters); | 921 | atomic_inc(&active_counters); |
| 735 | mutex_unlock(&pmc_reserve_mutex); | 922 | mutex_unlock(&pmc_reserve_mutex); |
| 736 | } | 923 | } |
| @@ -793,6 +980,20 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
| 793 | if (config == -1LL) | 980 | if (config == -1LL) |
| 794 | return -EINVAL; | 981 | return -EINVAL; |
| 795 | 982 | ||
| 983 | /* | ||
| 984 | * Branch tracing: | ||
| 985 | */ | ||
| 986 | if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && | ||
| 987 | (hwc->sample_period == 1)) { | ||
| 988 | /* BTS is not supported by this architecture. */ | ||
| 989 | if (!bts_available()) | ||
| 990 | return -EOPNOTSUPP; | ||
| 991 | |||
| 992 | /* BTS is currently only allowed for user-mode. */ | ||
| 993 | if (hwc->config & ARCH_PERFMON_EVENTSEL_OS) | ||
| 994 | return -EOPNOTSUPP; | ||
| 995 | } | ||
| 996 | |||
| 796 | hwc->config |= config; | 997 | hwc->config |= config; |
| 797 | 998 | ||
| 798 | return 0; | 999 | return 0; |
| @@ -817,7 +1018,18 @@ static void p6_pmu_disable_all(void) | |||
| 817 | 1018 | ||
| 818 | static void intel_pmu_disable_all(void) | 1019 | static void intel_pmu_disable_all(void) |
| 819 | { | 1020 | { |
| 1021 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
| 1022 | |||
| 1023 | if (!cpuc->enabled) | ||
| 1024 | return; | ||
| 1025 | |||
| 1026 | cpuc->enabled = 0; | ||
| 1027 | barrier(); | ||
| 1028 | |||
| 820 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); | 1029 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0); |
| 1030 | |||
| 1031 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) | ||
| 1032 | intel_pmu_disable_bts(); | ||
| 821 | } | 1033 | } |
| 822 | 1034 | ||
| 823 | static void amd_pmu_disable_all(void) | 1035 | static void amd_pmu_disable_all(void) |
| @@ -875,7 +1087,25 @@ static void p6_pmu_enable_all(void) | |||
| 875 | 1087 | ||
| 876 | static void intel_pmu_enable_all(void) | 1088 | static void intel_pmu_enable_all(void) |
| 877 | { | 1089 | { |
| 1090 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | ||
| 1091 | |||
| 1092 | if (cpuc->enabled) | ||
| 1093 | return; | ||
| 1094 | |||
| 1095 | cpuc->enabled = 1; | ||
| 1096 | barrier(); | ||
| 1097 | |||
| 878 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | 1098 | wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); |
| 1099 | |||
| 1100 | if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) { | ||
| 1101 | struct perf_counter *counter = | ||
| 1102 | cpuc->counters[X86_PMC_IDX_FIXED_BTS]; | ||
| 1103 | |||
| 1104 | if (WARN_ON_ONCE(!counter)) | ||
| 1105 | return; | ||
| 1106 | |||
| 1107 | intel_pmu_enable_bts(counter->hw.config); | ||
| 1108 | } | ||
| 879 | } | 1109 | } |
| 880 | 1110 | ||
| 881 | static void amd_pmu_enable_all(void) | 1111 | static void amd_pmu_enable_all(void) |
| @@ -962,6 +1192,11 @@ p6_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) | |||
| 962 | static inline void | 1192 | static inline void |
| 963 | intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) | 1193 | intel_pmu_disable_counter(struct hw_perf_counter *hwc, int idx) |
| 964 | { | 1194 | { |
| 1195 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
| 1196 | intel_pmu_disable_bts(); | ||
| 1197 | return; | ||
| 1198 | } | ||
| 1199 | |||
| 965 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 1200 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
| 966 | intel_pmu_disable_fixed(hwc, idx); | 1201 | intel_pmu_disable_fixed(hwc, idx); |
| 967 | return; | 1202 | return; |
| @@ -990,6 +1225,9 @@ x86_perf_counter_set_period(struct perf_counter *counter, | |||
| 990 | s64 period = hwc->sample_period; | 1225 | s64 period = hwc->sample_period; |
| 991 | int err, ret = 0; | 1226 | int err, ret = 0; |
| 992 | 1227 | ||
| 1228 | if (idx == X86_PMC_IDX_FIXED_BTS) | ||
| 1229 | return 0; | ||
| 1230 | |||
| 993 | /* | 1231 | /* |
| 994 | * If we are way outside a reasoable range then just skip forward: | 1232 | * If we are way outside a reasoable range then just skip forward: |
| 995 | */ | 1233 | */ |
| @@ -1072,6 +1310,14 @@ static void p6_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | |||
| 1072 | 1310 | ||
| 1073 | static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) | 1311 | static void intel_pmu_enable_counter(struct hw_perf_counter *hwc, int idx) |
| 1074 | { | 1312 | { |
| 1313 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
| 1314 | if (!__get_cpu_var(cpu_hw_counters).enabled) | ||
| 1315 | return; | ||
| 1316 | |||
| 1317 | intel_pmu_enable_bts(hwc->config); | ||
| 1318 | return; | ||
| 1319 | } | ||
| 1320 | |||
| 1075 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { | 1321 | if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { |
| 1076 | intel_pmu_enable_fixed(hwc, idx); | 1322 | intel_pmu_enable_fixed(hwc, idx); |
| 1077 | return; | 1323 | return; |
| @@ -1093,11 +1339,16 @@ fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc) | |||
| 1093 | { | 1339 | { |
| 1094 | unsigned int event; | 1340 | unsigned int event; |
| 1095 | 1341 | ||
| 1342 | event = hwc->config & ARCH_PERFMON_EVENT_MASK; | ||
| 1343 | |||
| 1344 | if (unlikely((event == | ||
| 1345 | x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS)) && | ||
| 1346 | (hwc->sample_period == 1))) | ||
| 1347 | return X86_PMC_IDX_FIXED_BTS; | ||
| 1348 | |||
| 1096 | if (!x86_pmu.num_counters_fixed) | 1349 | if (!x86_pmu.num_counters_fixed) |
| 1097 | return -1; | 1350 | return -1; |
| 1098 | 1351 | ||
| 1099 | event = hwc->config & ARCH_PERFMON_EVENT_MASK; | ||
| 1100 | |||
| 1101 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) | 1352 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) |
| 1102 | return X86_PMC_IDX_FIXED_INSTRUCTIONS; | 1353 | return X86_PMC_IDX_FIXED_INSTRUCTIONS; |
| 1103 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) | 1354 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_CPU_CYCLES))) |
| @@ -1118,7 +1369,15 @@ static int x86_pmu_enable(struct perf_counter *counter) | |||
| 1118 | int idx; | 1369 | int idx; |
| 1119 | 1370 | ||
| 1120 | idx = fixed_mode_idx(counter, hwc); | 1371 | idx = fixed_mode_idx(counter, hwc); |
| 1121 | if (idx >= 0) { | 1372 | if (idx == X86_PMC_IDX_FIXED_BTS) { |
| 1373 | /* BTS is already occupied. */ | ||
| 1374 | if (test_and_set_bit(idx, cpuc->used_mask)) | ||
| 1375 | return -EAGAIN; | ||
| 1376 | |||
| 1377 | hwc->config_base = 0; | ||
| 1378 | hwc->counter_base = 0; | ||
| 1379 | hwc->idx = idx; | ||
| 1380 | } else if (idx >= 0) { | ||
| 1122 | /* | 1381 | /* |
| 1123 | * Try to get the fixed counter, if that is already taken | 1382 | * Try to get the fixed counter, if that is already taken |
| 1124 | * then try to get a generic counter: | 1383 | * then try to get a generic counter: |
| @@ -1229,6 +1488,44 @@ void perf_counter_print_debug(void) | |||
| 1229 | local_irq_restore(flags); | 1488 | local_irq_restore(flags); |
| 1230 | } | 1489 | } |
| 1231 | 1490 | ||
| 1491 | static void intel_pmu_drain_bts_buffer(struct cpu_hw_counters *cpuc, | ||
| 1492 | struct perf_sample_data *data) | ||
| 1493 | { | ||
| 1494 | struct debug_store *ds = cpuc->ds; | ||
| 1495 | struct bts_record { | ||
| 1496 | u64 from; | ||
| 1497 | u64 to; | ||
| 1498 | u64 flags; | ||
| 1499 | }; | ||
| 1500 | struct perf_counter *counter = cpuc->counters[X86_PMC_IDX_FIXED_BTS]; | ||
| 1501 | unsigned long orig_ip = data->regs->ip; | ||
| 1502 | struct bts_record *at, *top; | ||
| 1503 | |||
| 1504 | if (!counter) | ||
| 1505 | return; | ||
| 1506 | |||
| 1507 | if (!ds) | ||
| 1508 | return; | ||
| 1509 | |||
| 1510 | at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; | ||
| 1511 | top = (struct bts_record *)(unsigned long)ds->bts_index; | ||
| 1512 | |||
| 1513 | ds->bts_index = ds->bts_buffer_base; | ||
| 1514 | |||
| 1515 | for (; at < top; at++) { | ||
| 1516 | data->regs->ip = at->from; | ||
| 1517 | data->addr = at->to; | ||
| 1518 | |||
| 1519 | perf_counter_output(counter, 1, data); | ||
| 1520 | } | ||
| 1521 | |||
| 1522 | data->regs->ip = orig_ip; | ||
| 1523 | data->addr = 0; | ||
| 1524 | |||
| 1525 | /* There's new data available. */ | ||
| 1526 | counter->pending_kill = POLL_IN; | ||
| 1527 | } | ||
| 1528 | |||
| 1232 | static void x86_pmu_disable(struct perf_counter *counter) | 1529 | static void x86_pmu_disable(struct perf_counter *counter) |
| 1233 | { | 1530 | { |
| 1234 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); | 1531 | struct cpu_hw_counters *cpuc = &__get_cpu_var(cpu_hw_counters); |
| @@ -1253,6 +1550,15 @@ static void x86_pmu_disable(struct perf_counter *counter) | |||
| 1253 | * that we are disabling: | 1550 | * that we are disabling: |
| 1254 | */ | 1551 | */ |
| 1255 | x86_perf_counter_update(counter, hwc, idx); | 1552 | x86_perf_counter_update(counter, hwc, idx); |
| 1553 | |||
| 1554 | /* Drain the remaining BTS records. */ | ||
| 1555 | if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { | ||
| 1556 | struct perf_sample_data data; | ||
| 1557 | struct pt_regs regs; | ||
| 1558 | |||
| 1559 | data.regs = ®s; | ||
| 1560 | intel_pmu_drain_bts_buffer(cpuc, &data); | ||
| 1561 | } | ||
| 1256 | cpuc->counters[idx] = NULL; | 1562 | cpuc->counters[idx] = NULL; |
| 1257 | clear_bit(idx, cpuc->used_mask); | 1563 | clear_bit(idx, cpuc->used_mask); |
| 1258 | 1564 | ||
| @@ -1280,6 +1586,7 @@ static int intel_pmu_save_and_restart(struct perf_counter *counter) | |||
| 1280 | 1586 | ||
| 1281 | static void intel_pmu_reset(void) | 1587 | static void intel_pmu_reset(void) |
| 1282 | { | 1588 | { |
| 1589 | struct debug_store *ds = __get_cpu_var(cpu_hw_counters).ds; | ||
| 1283 | unsigned long flags; | 1590 | unsigned long flags; |
| 1284 | int idx; | 1591 | int idx; |
| 1285 | 1592 | ||
| @@ -1297,6 +1604,8 @@ static void intel_pmu_reset(void) | |||
| 1297 | for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) { | 1604 | for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++) { |
| 1298 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); | 1605 | checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull); |
| 1299 | } | 1606 | } |
| 1607 | if (ds) | ||
| 1608 | ds->bts_index = ds->bts_buffer_base; | ||
| 1300 | 1609 | ||
| 1301 | local_irq_restore(flags); | 1610 | local_irq_restore(flags); |
| 1302 | } | 1611 | } |
| @@ -1362,6 +1671,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs) | |||
| 1362 | cpuc = &__get_cpu_var(cpu_hw_counters); | 1671 | cpuc = &__get_cpu_var(cpu_hw_counters); |
| 1363 | 1672 | ||
| 1364 | perf_disable(); | 1673 | perf_disable(); |
| 1674 | intel_pmu_drain_bts_buffer(cpuc, &data); | ||
| 1365 | status = intel_pmu_get_status(); | 1675 | status = intel_pmu_get_status(); |
| 1366 | if (!status) { | 1676 | if (!status) { |
| 1367 | perf_enable(); | 1677 | perf_enable(); |
| @@ -1571,6 +1881,8 @@ static struct x86_pmu intel_pmu = { | |||
| 1571 | * the generic counter period: | 1881 | * the generic counter period: |
| 1572 | */ | 1882 | */ |
| 1573 | .max_period = (1ULL << 31) - 1, | 1883 | .max_period = (1ULL << 31) - 1, |
| 1884 | .enable_bts = intel_pmu_enable_bts, | ||
| 1885 | .disable_bts = intel_pmu_disable_bts, | ||
| 1574 | }; | 1886 | }; |
| 1575 | 1887 | ||
| 1576 | static struct x86_pmu amd_pmu = { | 1888 | static struct x86_pmu amd_pmu = { |
| @@ -1962,3 +2274,8 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
| 1962 | 2274 | ||
| 1963 | return entry; | 2275 | return entry; |
| 1964 | } | 2276 | } |
| 2277 | |||
| 2278 | void hw_perf_counter_setup_online(int cpu) | ||
| 2279 | { | ||
| 2280 | init_debug_store_on_cpu(cpu); | ||
| 2281 | } | ||
