Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
perf tools: Makefile: Use gcc to determine ARCH
perf events, x86: Fix Intel Nehalem and Westmere last level cache event definitions
hw_breakpoints, powerpc: Fix CONFIG_HAVE_HW_BREAKPOINT off-case in ptrace_set_debugreg()
sh, hw_breakpoints: Fix racy access to ptrace breakpoints
arm, hw_breakpoints: Fix racy access to ptrace breakpoints
powerpc, hw_breakpoints: Fix racy access to ptrace breakpoints
x86, hw_breakpoints: Fix racy access to ptrace breakpoints
ptrace: Prepare to fix racy accesses on task breakpoints

+144 -54
+8
arch/arm/kernel/ptrace.c
··· 767 767 768 768 #ifdef CONFIG_HAVE_HW_BREAKPOINT 769 769 case PTRACE_GETHBPREGS: 770 + if (ptrace_get_breakpoints(child) < 0) 771 + return -ESRCH; 772 + 770 773 ret = ptrace_gethbpregs(child, addr, 771 774 (unsigned long __user *)data); 775 + ptrace_put_breakpoints(child); 772 776 break; 773 777 case PTRACE_SETHBPREGS: 778 + if (ptrace_get_breakpoints(child) < 0) 779 + return -ESRCH; 780 + 774 781 ret = ptrace_sethbpregs(child, addr, 775 782 (unsigned long __user *)data); 783 + ptrace_put_breakpoints(child); 776 784 break; 777 785 #endif 778 786
+11 -1
arch/powerpc/kernel/ptrace.c
··· 933 933 if (data && !(data & DABR_TRANSLATION)) 934 934 return -EIO; 935 935 #ifdef CONFIG_HAVE_HW_BREAKPOINT 936 + if (ptrace_get_breakpoints(task) < 0) 937 + return -ESRCH; 938 + 936 939 bp = thread->ptrace_bps[0]; 937 940 if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) { 938 941 if (bp) { 939 942 unregister_hw_breakpoint(bp); 940 943 thread->ptrace_bps[0] = NULL; 941 944 } 945 + ptrace_put_breakpoints(task); 942 946 return 0; 943 947 } 944 948 if (bp) { ··· 952 948 (DABR_DATA_WRITE | DABR_DATA_READ), 953 949 &attr.bp_type); 954 950 ret = modify_user_hw_breakpoint(bp, &attr); 955 - if (ret) 951 + if (ret) { 952 + ptrace_put_breakpoints(task); 956 953 return ret; 954 + } 957 955 thread->ptrace_bps[0] = bp; 956 + ptrace_put_breakpoints(task); 958 957 thread->dabr = data; 959 958 return 0; 960 959 } ··· 972 965 ptrace_triggered, task); 973 966 if (IS_ERR(bp)) { 974 967 thread->ptrace_bps[0] = NULL; 968 + ptrace_put_breakpoints(task); 975 969 return PTR_ERR(bp); 976 970 } 971 + 972 + ptrace_put_breakpoints(task); 977 973 978 974 #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 979 975
+4
arch/sh/kernel/ptrace_32.c
··· 117 117 118 118 set_tsk_thread_flag(child, TIF_SINGLESTEP); 119 119 120 + if (ptrace_get_breakpoints(child) < 0) 121 + return; 122 + 120 123 set_single_step(child, pc); 124 + ptrace_put_breakpoints(child); 121 125 } 122 126 123 127 void user_disable_single_step(struct task_struct *child)
+52 -35
arch/x86/kernel/cpu/perf_event_intel.c
··· 184 184 }, 185 185 }, 186 186 [ C(LL ) ] = { 187 - /* 188 - * TBD: Need Off-core Response Performance Monitoring support 189 - */ 190 187 [ C(OP_READ) ] = { 191 - /* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */ 188 + /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */ 192 189 [ C(RESULT_ACCESS) ] = 0x01b7, 193 - /* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */ 194 - [ C(RESULT_MISS) ] = 0x01bb, 190 + /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */ 191 + [ C(RESULT_MISS) ] = 0x01b7, 195 192 }, 196 193 [ C(OP_WRITE) ] = { 197 - /* OFFCORE_RESPONSE_0.ANY_RFO.LOCAL_CACHE */ 194 + /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */ 198 195 [ C(RESULT_ACCESS) ] = 0x01b7, 199 - /* OFFCORE_RESPONSE_1.ANY_RFO.ANY_LLC_MISS */ 200 - [ C(RESULT_MISS) ] = 0x01bb, 196 + /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */ 197 + [ C(RESULT_MISS) ] = 0x01b7, 201 198 }, 202 199 [ C(OP_PREFETCH) ] = { 203 - /* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */ 200 + /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */ 204 201 [ C(RESULT_ACCESS) ] = 0x01b7, 205 - /* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */ 206 - [ C(RESULT_MISS) ] = 0x01bb, 202 + /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */ 203 + [ C(RESULT_MISS) ] = 0x01b7, 207 204 }, 208 205 }, 209 206 [ C(DTLB) ] = { ··· 282 285 }, 283 286 [ C(LL ) ] = { 284 287 [ C(OP_READ) ] = { 285 - /* OFFCORE_RESPONSE_0.ANY_DATA.LOCAL_CACHE */ 288 + /* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */ 286 289 [ C(RESULT_ACCESS) ] = 0x01b7, 287 - /* OFFCORE_RESPONSE_1.ANY_DATA.ANY_LLC_MISS */ 288 - [ C(RESULT_MISS) ] = 0x01bb, 290 + /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */ 291 + [ C(RESULT_MISS) ] = 0x01b7, 289 292 }, 290 293 /* 291 294 * Use RFO, not WRITEBACK, because a write miss would typically occur 292 295 * on RFO. 293 296 */ 294 297 [ C(OP_WRITE) ] = { 295 - /* OFFCORE_RESPONSE_1.ANY_RFO.LOCAL_CACHE */ 296 - [ C(RESULT_ACCESS) ] = 0x01bb, 297 - /* OFFCORE_RESPONSE_0.ANY_RFO.ANY_LLC_MISS */ 298 + /* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */ 299 + [ C(RESULT_ACCESS) ] = 0x01b7, 300 + /* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */ 298 301 [ C(RESULT_MISS) ] = 0x01b7, 299 302 }, 300 303 [ C(OP_PREFETCH) ] = { 301 - /* OFFCORE_RESPONSE_0.PREFETCH.LOCAL_CACHE */ 304 + /* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */ 302 305 [ C(RESULT_ACCESS) ] = 0x01b7, 303 - /* OFFCORE_RESPONSE_1.PREFETCH.ANY_LLC_MISS */ 304 - [ C(RESULT_MISS) ] = 0x01bb, 306 + /* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */ 307 + [ C(RESULT_MISS) ] = 0x01b7, 305 308 }, 306 309 }, 307 310 [ C(DTLB) ] = { ··· 349 352 }; 350 353 351 354 /* 352 - * OFFCORE_RESPONSE MSR bits (subset), See IA32 SDM Vol 3 30.6.1.3 355 + * Nehalem/Westmere MSR_OFFCORE_RESPONSE bits; 356 + * See IA32 SDM Vol 3B 30.6.1.3 353 357 */ 354 358 355 - #define DMND_DATA_RD (1 << 0) 356 - #define DMND_RFO (1 << 1) 357 - #define DMND_WB (1 << 3) 358 - #define PF_DATA_RD (1 << 4) 359 - #define PF_DATA_RFO (1 << 5) 360 - #define RESP_UNCORE_HIT (1 << 8) 361 - #define RESP_MISS (0xf600) /* non uncore hit */ 359 + #define NHM_DMND_DATA_RD (1 << 0) 360 + #define NHM_DMND_RFO (1 << 1) 361 + #define NHM_DMND_IFETCH (1 << 2) 362 + #define NHM_DMND_WB (1 << 3) 363 + #define NHM_PF_DATA_RD (1 << 4) 364 + #define NHM_PF_DATA_RFO (1 << 5) 365 + #define NHM_PF_IFETCH (1 << 6) 366 + #define NHM_OFFCORE_OTHER (1 << 7) 367 + #define NHM_UNCORE_HIT (1 << 8) 368 + #define NHM_OTHER_CORE_HIT_SNP (1 << 9) 369 + #define NHM_OTHER_CORE_HITM (1 << 10) 370 + /* reserved */ 371 + #define NHM_REMOTE_CACHE_FWD (1 << 12) 372 + #define NHM_REMOTE_DRAM (1 << 13) 373 + #define NHM_LOCAL_DRAM (1 << 14) 374 + #define NHM_NON_DRAM (1 << 15) 375 + 376 + #define NHM_ALL_DRAM (NHM_REMOTE_DRAM|NHM_LOCAL_DRAM) 377 + 378 + #define NHM_DMND_READ (NHM_DMND_DATA_RD) 379 + #define NHM_DMND_WRITE (NHM_DMND_RFO|NHM_DMND_WB) 380 + #define NHM_DMND_PREFETCH (NHM_PF_DATA_RD|NHM_PF_DATA_RFO) 381 + 382 + #define NHM_L3_HIT (NHM_UNCORE_HIT|NHM_OTHER_CORE_HIT_SNP|NHM_OTHER_CORE_HITM) 383 + #define NHM_L3_MISS (NHM_NON_DRAM|NHM_ALL_DRAM|NHM_REMOTE_CACHE_FWD) 384 + #define NHM_L3_ACCESS (NHM_L3_HIT|NHM_L3_MISS) 362 385 363 386 static __initconst const u64 nehalem_hw_cache_extra_regs 364 387 [PERF_COUNT_HW_CACHE_MAX] ··· 387 370 { 388 371 [ C(LL ) ] = { 389 372 [ C(OP_READ) ] = { 390 - [ C(RESULT_ACCESS) ] = DMND_DATA_RD|RESP_UNCORE_HIT, 391 - [ C(RESULT_MISS) ] = DMND_DATA_RD|RESP_MISS, 373 + [ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_L3_ACCESS, 374 + [ C(RESULT_MISS) ] = NHM_DMND_READ|NHM_L3_MISS, 392 375 }, 393 376 [ C(OP_WRITE) ] = { 394 - [ C(RESULT_ACCESS) ] = DMND_RFO|DMND_WB|RESP_UNCORE_HIT, 395 - [ C(RESULT_MISS) ] = DMND_RFO|DMND_WB|RESP_MISS, 377 + [ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_L3_ACCESS, 378 + [ C(RESULT_MISS) ] = NHM_DMND_WRITE|NHM_L3_MISS, 396 379 }, 397 380 [ C(OP_PREFETCH) ] = { 398 - [ C(RESULT_ACCESS) ] = PF_DATA_RD|PF_DATA_RFO|RESP_UNCORE_HIT, 399 - [ C(RESULT_MISS) ] = PF_DATA_RD|PF_DATA_RFO|RESP_MISS, 381 + [ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS, 382 + [ C(RESULT_MISS) ] = NHM_DMND_PREFETCH|NHM_L3_MISS, 400 383 }, 401 384 } 402 385 };
+26 -10
arch/x86/kernel/ptrace.c
··· 608 608 unsigned len, type; 609 609 struct perf_event *bp; 610 610 611 + if (ptrace_get_breakpoints(tsk) < 0) 612 + return -ESRCH; 613 + 611 614 data &= ~DR_CONTROL_RESERVED; 612 615 old_dr7 = ptrace_get_dr7(thread->ptrace_bps); 613 616 restore: ··· 658 655 } 659 656 goto restore; 660 657 } 658 + 659 + ptrace_put_breakpoints(tsk); 660 + 661 661 return ((orig_ret < 0) ? orig_ret : rc); 662 662 } 663 663 ··· 674 668 675 669 if (n < HBP_NUM) { 676 670 struct perf_event *bp; 671 + 672 + if (ptrace_get_breakpoints(tsk) < 0) 673 + return -ESRCH; 674 + 677 675 bp = thread->ptrace_bps[n]; 678 676 if (!bp) 679 - return 0; 680 - val = bp->hw.info.address; 677 + val = 0; 678 + else 679 + val = bp->hw.info.address; 680 + 681 + ptrace_put_breakpoints(tsk); 681 682 } else if (n == 6) { 682 683 val = thread->debugreg6; 683 684 } else if (n == 7) { ··· 699 686 struct perf_event *bp; 700 687 struct thread_struct *t = &tsk->thread; 701 688 struct perf_event_attr attr; 689 + int err = 0; 690 + 691 + if (ptrace_get_breakpoints(tsk) < 0) 692 + return -ESRCH; 702 693 703 694 if (!t->ptrace_bps[nr]) { 704 695 ptrace_breakpoint_init(&attr); ··· 726 709 * writing for the user. And anyway this is the previous 727 710 * behaviour. 728 711 */ 729 - if (IS_ERR(bp)) 730 - return PTR_ERR(bp); 712 + if (IS_ERR(bp)) { 713 + err = PTR_ERR(bp); 714 + goto put; 715 + } 731 716 732 717 t->ptrace_bps[nr] = bp; 733 718 } else { 734 - int err; 735 - 736 719 bp = t->ptrace_bps[nr]; 737 720 738 721 attr = bp->attr; 739 722 attr.bp_addr = addr; 740 723 err = modify_user_hw_breakpoint(bp, &attr); 741 - if (err) 742 - return err; 743 724 } 744 725 745 - 746 - return 0; 726 + put: 727 + ptrace_put_breakpoints(tsk); 728 + return err; 747 729 } 748 730 749 731 /*
+12 -1
include/linux/ptrace.h
··· 189 189 child->ptrace = current->ptrace; 190 190 __ptrace_link(child, current->parent); 191 191 } 192 + 193 + #ifdef CONFIG_HAVE_HW_BREAKPOINT 194 + atomic_set(&child->ptrace_bp_refcnt, 1); 195 + #endif 192 196 } 193 197 194 198 /** ··· 354 350 unsigned long args[6], unsigned int maxargs, 355 351 unsigned long *sp, unsigned long *pc); 356 352 357 - #endif 353 + #ifdef CONFIG_HAVE_HW_BREAKPOINT 354 + extern int ptrace_get_breakpoints(struct task_struct *tsk); 355 + extern void ptrace_put_breakpoints(struct task_struct *tsk); 356 + #else 357 + static inline void ptrace_put_breakpoints(struct task_struct *tsk) { } 358 + #endif /* CONFIG_HAVE_HW_BREAKPOINT */ 359 + 360 + #endif /* __KERNEL */ 358 361 359 362 #endif
+3
include/linux/sched.h
··· 1537 1537 unsigned long memsw_nr_pages; /* uncharged mem+swap usage */ 1538 1538 } memcg_batch; 1539 1539 #endif 1540 + #ifdef CONFIG_HAVE_HW_BREAKPOINT 1541 + atomic_t ptrace_bp_refcnt; 1542 + #endif 1540 1543 }; 1541 1544 1542 1545 /* Future-safe accessor for struct task_struct's cpus_allowed. */
+1 -1
kernel/exit.c
··· 1016 1016 /* 1017 1017 * FIXME: do that only when needed, using sched_exit tracepoint 1018 1018 */ 1019 - flush_ptrace_hw_breakpoint(tsk); 1019 + ptrace_put_breakpoints(tsk); 1020 1020 1021 1021 exit_notify(tsk, group_dead); 1022 1022 #ifdef CONFIG_NUMA
+17
kernel/ptrace.c
··· 22 22 #include <linux/syscalls.h> 23 23 #include <linux/uaccess.h> 24 24 #include <linux/regset.h> 25 + #include <linux/hw_breakpoint.h> 25 26 26 27 27 28 /* ··· 880 879 return ret; 881 880 } 882 881 #endif /* CONFIG_COMPAT */ 882 + 883 + #ifdef CONFIG_HAVE_HW_BREAKPOINT 884 + int ptrace_get_breakpoints(struct task_struct *tsk) 885 + { 886 + if (atomic_inc_not_zero(&tsk->ptrace_bp_refcnt)) 887 + return 0; 888 + 889 + return -1; 890 + } 891 + 892 + void ptrace_put_breakpoints(struct task_struct *tsk) 893 + { 894 + if (atomic_dec_and_test(&tsk->ptrace_bp_refcnt)) 895 + flush_ptrace_hw_breakpoint(tsk); 896 + } 897 + #endif /* CONFIG_HAVE_HW_BREAKPOINT */
+10 -6
tools/perf/Makefile
··· 35 35 -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ 36 36 -e s/sh[234].*/sh/ ) 37 37 38 + CC = $(CROSS_COMPILE)gcc 39 + AR = $(CROSS_COMPILE)ar 40 + 38 41 # Additional ARCH settings for x86 39 42 ifeq ($(ARCH),i386) 40 43 ARCH := x86 41 44 endif 42 45 ifeq ($(ARCH),x86_64) 43 - RAW_ARCH := x86_64 44 - ARCH := x86 45 - ARCH_CFLAGS := -DARCH_X86_64 46 - ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S 46 + ARCH := x86 47 + IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) 48 + ifeq (${IS_X86_64}, 1) 49 + RAW_ARCH := x86_64 50 + ARCH_CFLAGS := -DARCH_X86_64 51 + ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S 52 + endif 47 53 endif 48 54 49 55 # ··· 125 119 126 120 export prefix bindir sharedir sysconfdir 127 121 128 - CC = $(CROSS_COMPILE)gcc 129 - AR = $(CROSS_COMPILE)ar 130 122 RM = rm -f 131 123 MKDIR = mkdir 132 124 FIND = find