diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-01-23 17:42:36 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2013-01-23 17:42:36 -0500 |
| commit | 13cea1069f65c120c8b5d44ea09903aad41ad715 (patch) | |
| tree | 745315397702b63bd023974c7ebf439dec6ccce4 | |
| parent | 7d1f9aeff1ee4a20b1aeb377dd0f579fe9647619 (diff) | |
| parent | 9a6eb310eaa5336b89a27a0bbb78da4bba35f6f1 (diff) | |
Merge branch 'for-rmk/hw-breakpoint' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into devel-stable
| -rw-r--r-- | arch/arm/include/asm/cti.h | 10 | ||||
| -rw-r--r-- | arch/arm/include/asm/hardware/coresight.h | 6 | ||||
| -rw-r--r-- | arch/arm/include/asm/hw_breakpoint.h | 3 | ||||
| -rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 61 |
4 files changed, 62 insertions, 18 deletions
diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h index f2e5cad3f306..2381199acb7d 100644 --- a/arch/arm/include/asm/cti.h +++ b/arch/arm/include/asm/cti.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define __ASMARM_CTI_H | 2 | #define __ASMARM_CTI_H |
| 3 | 3 | ||
| 4 | #include <asm/io.h> | 4 | #include <asm/io.h> |
| 5 | #include <asm/hardware/coresight.h> | ||
| 5 | 6 | ||
| 6 | /* The registers' definition is from section 3.2 of | 7 | /* The registers' definition is from section 3.2 of |
| 7 | * Embedded Cross Trigger Revision: r0p0 | 8 | * Embedded Cross Trigger Revision: r0p0 |
| @@ -35,11 +36,6 @@ | |||
| 35 | #define LOCKACCESS 0xFB0 | 36 | #define LOCKACCESS 0xFB0 |
| 36 | #define LOCKSTATUS 0xFB4 | 37 | #define LOCKSTATUS 0xFB4 |
| 37 | 38 | ||
| 38 | /* write this value to LOCKACCESS will unlock the module, and | ||
| 39 | * other value will lock the module | ||
| 40 | */ | ||
| 41 | #define LOCKCODE 0xC5ACCE55 | ||
| 42 | |||
| 43 | /** | 39 | /** |
| 44 | * struct cti - cross trigger interface struct | 40 | * struct cti - cross trigger interface struct |
| 45 | * @base: mapped virtual address for the cti base | 41 | * @base: mapped virtual address for the cti base |
| @@ -146,7 +142,7 @@ static inline void cti_irq_ack(struct cti *cti) | |||
| 146 | */ | 142 | */ |
| 147 | static inline void cti_unlock(struct cti *cti) | 143 | static inline void cti_unlock(struct cti *cti) |
| 148 | { | 144 | { |
| 149 | __raw_writel(LOCKCODE, cti->base + LOCKACCESS); | 145 | __raw_writel(CS_LAR_KEY, cti->base + LOCKACCESS); |
| 150 | } | 146 | } |
| 151 | 147 | ||
| 152 | /** | 148 | /** |
| @@ -158,6 +154,6 @@ static inline void cti_unlock(struct cti *cti) | |||
| 158 | */ | 154 | */ |
| 159 | static inline void cti_lock(struct cti *cti) | 155 | static inline void cti_lock(struct cti *cti) |
| 160 | { | 156 | { |
| 161 | __raw_writel(~LOCKCODE, cti->base + LOCKACCESS); | 157 | __raw_writel(~CS_LAR_KEY, cti->base + LOCKACCESS); |
| 162 | } | 158 | } |
| 163 | #endif | 159 | #endif |
diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h index 7ecd793b8f5a..0cf7a6b842ff 100644 --- a/arch/arm/include/asm/hardware/coresight.h +++ b/arch/arm/include/asm/hardware/coresight.h | |||
| @@ -36,7 +36,7 @@ | |||
| 36 | /* CoreSight Component Registers */ | 36 | /* CoreSight Component Registers */ |
| 37 | #define CSCR_CLASS 0xff4 | 37 | #define CSCR_CLASS 0xff4 |
| 38 | 38 | ||
| 39 | #define UNLOCK_MAGIC 0xc5acce55 | 39 | #define CS_LAR_KEY 0xc5acce55 |
| 40 | 40 | ||
| 41 | /* ETM control register, "ETM Architecture", 3.3.1 */ | 41 | /* ETM control register, "ETM Architecture", 3.3.1 */ |
| 42 | #define ETMR_CTRL 0 | 42 | #define ETMR_CTRL 0 |
| @@ -147,11 +147,11 @@ | |||
| 147 | 147 | ||
| 148 | #define etm_lock(t) do { etm_writel((t), 0, CSMR_LOCKACCESS); } while (0) | 148 | #define etm_lock(t) do { etm_writel((t), 0, CSMR_LOCKACCESS); } while (0) |
| 149 | #define etm_unlock(t) \ | 149 | #define etm_unlock(t) \ |
| 150 | do { etm_writel((t), UNLOCK_MAGIC, CSMR_LOCKACCESS); } while (0) | 150 | do { etm_writel((t), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0) |
| 151 | 151 | ||
| 152 | #define etb_lock(t) do { etb_writel((t), 0, CSMR_LOCKACCESS); } while (0) | 152 | #define etb_lock(t) do { etb_writel((t), 0, CSMR_LOCKACCESS); } while (0) |
| 153 | #define etb_unlock(t) \ | 153 | #define etb_unlock(t) \ |
| 154 | do { etb_writel((t), UNLOCK_MAGIC, CSMR_LOCKACCESS); } while (0) | 154 | do { etb_writel((t), CS_LAR_KEY, CSMR_LOCKACCESS); } while (0) |
| 155 | 155 | ||
| 156 | #endif /* __ASM_HARDWARE_CORESIGHT_H */ | 156 | #endif /* __ASM_HARDWARE_CORESIGHT_H */ |
| 157 | 157 | ||
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h index 01169dd723f1..eef55ea9ef00 100644 --- a/arch/arm/include/asm/hw_breakpoint.h +++ b/arch/arm/include/asm/hw_breakpoint.h | |||
| @@ -85,6 +85,9 @@ static inline void decode_ctrl_reg(u32 reg, | |||
| 85 | #define ARM_DSCR_HDBGEN (1 << 14) | 85 | #define ARM_DSCR_HDBGEN (1 << 14) |
| 86 | #define ARM_DSCR_MDBGEN (1 << 15) | 86 | #define ARM_DSCR_MDBGEN (1 << 15) |
| 87 | 87 | ||
| 88 | /* OSLSR os lock model bits */ | ||
| 89 | #define ARM_OSLSR_OSLM0 (1 << 0) | ||
| 90 | |||
| 88 | /* opcode2 numbers for the co-processor instructions. */ | 91 | /* opcode2 numbers for the co-processor instructions. */ |
| 89 | #define ARM_OP2_BVR 4 | 92 | #define ARM_OP2_BVR 4 |
| 90 | #define ARM_OP2_BCR 5 | 93 | #define ARM_OP2_BCR 5 |
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 5ff2e77782b1..5eae53e7a2e1 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/perf_event.h> | 28 | #include <linux/perf_event.h> |
| 29 | #include <linux/hw_breakpoint.h> | 29 | #include <linux/hw_breakpoint.h> |
| 30 | #include <linux/smp.h> | 30 | #include <linux/smp.h> |
| 31 | #include <linux/cpu_pm.h> | ||
| 31 | 32 | ||
| 32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
| 33 | #include <asm/cputype.h> | 34 | #include <asm/cputype.h> |
| @@ -35,6 +36,7 @@ | |||
| 35 | #include <asm/hw_breakpoint.h> | 36 | #include <asm/hw_breakpoint.h> |
| 36 | #include <asm/kdebug.h> | 37 | #include <asm/kdebug.h> |
| 37 | #include <asm/traps.h> | 38 | #include <asm/traps.h> |
| 39 | #include <asm/hardware/coresight.h> | ||
| 38 | 40 | ||
| 39 | /* Breakpoint currently in use for each BRP. */ | 41 | /* Breakpoint currently in use for each BRP. */ |
| 40 | static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); | 42 | static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]); |
| @@ -49,6 +51,9 @@ static int core_num_wrps; | |||
| 49 | /* Debug architecture version. */ | 51 | /* Debug architecture version. */ |
| 50 | static u8 debug_arch; | 52 | static u8 debug_arch; |
| 51 | 53 | ||
| 54 | /* Does debug architecture support OS Save and Restore? */ | ||
| 55 | static bool has_ossr; | ||
| 56 | |||
| 52 | /* Maximum supported watchpoint length. */ | 57 | /* Maximum supported watchpoint length. */ |
| 53 | static u8 max_watchpoint_len; | 58 | static u8 max_watchpoint_len; |
| 54 | 59 | ||
| @@ -903,6 +908,23 @@ static struct undef_hook debug_reg_hook = { | |||
| 903 | .fn = debug_reg_trap, | 908 | .fn = debug_reg_trap, |
| 904 | }; | 909 | }; |
| 905 | 910 | ||
| 911 | /* Does this core support OS Save and Restore? */ | ||
| 912 | static bool core_has_os_save_restore(void) | ||
| 913 | { | ||
| 914 | u32 oslsr; | ||
| 915 | |||
| 916 | switch (get_debug_arch()) { | ||
| 917 | case ARM_DEBUG_ARCH_V7_1: | ||
| 918 | return true; | ||
| 919 | case ARM_DEBUG_ARCH_V7_ECP14: | ||
| 920 | ARM_DBG_READ(c1, c1, 4, oslsr); | ||
| 921 | if (oslsr & ARM_OSLSR_OSLM0) | ||
| 922 | return true; | ||
| 923 | default: | ||
| 924 | return false; | ||
| 925 | } | ||
| 926 | } | ||
| 927 | |||
| 906 | static void reset_ctrl_regs(void *unused) | 928 | static void reset_ctrl_regs(void *unused) |
| 907 | { | 929 | { |
| 908 | int i, raw_num_brps, err = 0, cpu = smp_processor_id(); | 930 | int i, raw_num_brps, err = 0, cpu = smp_processor_id(); |
| @@ -930,11 +952,7 @@ static void reset_ctrl_regs(void *unused) | |||
| 930 | if ((val & 0x1) == 0) | 952 | if ((val & 0x1) == 0) |
| 931 | err = -EPERM; | 953 | err = -EPERM; |
| 932 | 954 | ||
| 933 | /* | 955 | if (!has_ossr) |
| 934 | * Check whether we implement OS save and restore. | ||
| 935 | */ | ||
| 936 | ARM_DBG_READ(c1, c1, 4, val); | ||
| 937 | if ((val & 0x9) == 0) | ||
| 938 | goto clear_vcr; | 956 | goto clear_vcr; |
| 939 | break; | 957 | break; |
| 940 | case ARM_DEBUG_ARCH_V7_1: | 958 | case ARM_DEBUG_ARCH_V7_1: |
| @@ -955,9 +973,9 @@ static void reset_ctrl_regs(void *unused) | |||
| 955 | 973 | ||
| 956 | /* | 974 | /* |
| 957 | * Unconditionally clear the OS lock by writing a value | 975 | * Unconditionally clear the OS lock by writing a value |
| 958 | * other than 0xC5ACCE55 to the access register. | 976 | * other than CS_LAR_KEY to the access register. |
| 959 | */ | 977 | */ |
| 960 | ARM_DBG_WRITE(c1, c0, 4, 0); | 978 | ARM_DBG_WRITE(c1, c0, 4, ~CS_LAR_KEY); |
| 961 | isb(); | 979 | isb(); |
| 962 | 980 | ||
| 963 | /* | 981 | /* |
| @@ -1015,6 +1033,30 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = { | |||
| 1015 | .notifier_call = dbg_reset_notify, | 1033 | .notifier_call = dbg_reset_notify, |
| 1016 | }; | 1034 | }; |
| 1017 | 1035 | ||
| 1036 | #ifdef CONFIG_CPU_PM | ||
| 1037 | static int dbg_cpu_pm_notify(struct notifier_block *self, unsigned long action, | ||
| 1038 | void *v) | ||
| 1039 | { | ||
| 1040 | if (action == CPU_PM_EXIT) | ||
| 1041 | reset_ctrl_regs(NULL); | ||
| 1042 | |||
| 1043 | return NOTIFY_OK; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static struct notifier_block __cpuinitdata dbg_cpu_pm_nb = { | ||
| 1047 | .notifier_call = dbg_cpu_pm_notify, | ||
| 1048 | }; | ||
| 1049 | |||
| 1050 | static void __init pm_init(void) | ||
| 1051 | { | ||
| 1052 | cpu_pm_register_notifier(&dbg_cpu_pm_nb); | ||
| 1053 | } | ||
| 1054 | #else | ||
| 1055 | static inline void pm_init(void) | ||
| 1056 | { | ||
| 1057 | } | ||
| 1058 | #endif | ||
| 1059 | |||
| 1018 | static int __init arch_hw_breakpoint_init(void) | 1060 | static int __init arch_hw_breakpoint_init(void) |
| 1019 | { | 1061 | { |
| 1020 | debug_arch = get_debug_arch(); | 1062 | debug_arch = get_debug_arch(); |
| @@ -1024,6 +1066,8 @@ static int __init arch_hw_breakpoint_init(void) | |||
| 1024 | return 0; | 1066 | return 0; |
| 1025 | } | 1067 | } |
| 1026 | 1068 | ||
| 1069 | has_ossr = core_has_os_save_restore(); | ||
| 1070 | |||
| 1027 | /* Determine how many BRPs/WRPs are available. */ | 1071 | /* Determine how many BRPs/WRPs are available. */ |
| 1028 | core_num_brps = get_num_brps(); | 1072 | core_num_brps = get_num_brps(); |
| 1029 | core_num_wrps = get_num_wrps(); | 1073 | core_num_wrps = get_num_wrps(); |
| @@ -1062,8 +1106,9 @@ static int __init arch_hw_breakpoint_init(void) | |||
| 1062 | hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, | 1106 | hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, |
| 1063 | TRAP_HWBKPT, "breakpoint debug exception"); | 1107 | TRAP_HWBKPT, "breakpoint debug exception"); |
| 1064 | 1108 | ||
| 1065 | /* Register hotplug notifier. */ | 1109 | /* Register hotplug and PM notifiers. */ |
| 1066 | register_cpu_notifier(&dbg_reset_nb); | 1110 | register_cpu_notifier(&dbg_reset_nb); |
| 1111 | pm_init(); | ||
| 1067 | return 0; | 1112 | return 0; |
| 1068 | } | 1113 | } |
| 1069 | arch_initcall(arch_hw_breakpoint_init); | 1114 | arch_initcall(arch_hw_breakpoint_init); |
