diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-11-19 06:23:08 -0500 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-11-19 06:23:08 -0500 |
| commit | c71d4aa7e98f30d4011b44b168263abc72f676bd (patch) | |
| tree | 3daa760c738a6e90f8af4b9ff163e608f10884e4 | |
| parent | 667832da846b5748e6c7b3139bbe015c7ea189f7 (diff) | |
| parent | f600b9fcd2bcb8ee0adb235f54ccdd93c729c442 (diff) | |
Merge branch '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 | 20 | ||||
| -rw-r--r-- | arch/arm/include/asm/hw_breakpoint.h | 8 | ||||
| -rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 154 |
3 files changed, 91 insertions, 91 deletions
diff --git a/arch/arm/include/asm/cti.h b/arch/arm/include/asm/cti.h index a0ada3ea435..f2e5cad3f30 100644 --- a/arch/arm/include/asm/cti.h +++ b/arch/arm/include/asm/cti.h | |||
| @@ -146,15 +146,7 @@ static inline void cti_irq_ack(struct cti *cti) | |||
| 146 | */ | 146 | */ |
| 147 | static inline void cti_unlock(struct cti *cti) | 147 | static inline void cti_unlock(struct cti *cti) |
| 148 | { | 148 | { |
| 149 | void __iomem *base = cti->base; | 149 | __raw_writel(LOCKCODE, cti->base + LOCKACCESS); |
| 150 | unsigned long val; | ||
| 151 | |||
| 152 | val = __raw_readl(base + LOCKSTATUS); | ||
| 153 | |||
| 154 | if (val & 1) { | ||
| 155 | val = LOCKCODE; | ||
| 156 | __raw_writel(val, base + LOCKACCESS); | ||
| 157 | } | ||
| 158 | } | 150 | } |
| 159 | 151 | ||
| 160 | /** | 152 | /** |
| @@ -166,14 +158,6 @@ static inline void cti_unlock(struct cti *cti) | |||
| 166 | */ | 158 | */ |
| 167 | static inline void cti_lock(struct cti *cti) | 159 | static inline void cti_lock(struct cti *cti) |
| 168 | { | 160 | { |
| 169 | void __iomem *base = cti->base; | 161 | __raw_writel(~LOCKCODE, cti->base + LOCKACCESS); |
| 170 | unsigned long val; | ||
| 171 | |||
| 172 | val = __raw_readl(base + LOCKSTATUS); | ||
| 173 | |||
| 174 | if (!(val & 1)) { | ||
| 175 | val = ~LOCKCODE; | ||
| 176 | __raw_writel(val, base + LOCKACCESS); | ||
| 177 | } | ||
| 178 | } | 162 | } |
| 179 | #endif | 163 | #endif |
diff --git a/arch/arm/include/asm/hw_breakpoint.h b/arch/arm/include/asm/hw_breakpoint.h index c190bc992f0..01169dd723f 100644 --- a/arch/arm/include/asm/hw_breakpoint.h +++ b/arch/arm/include/asm/hw_breakpoint.h | |||
| @@ -98,12 +98,12 @@ static inline void decode_ctrl_reg(u32 reg, | |||
| 98 | #define ARM_BASE_WCR 112 | 98 | #define ARM_BASE_WCR 112 |
| 99 | 99 | ||
| 100 | /* Accessor macros for the debug registers. */ | 100 | /* Accessor macros for the debug registers. */ |
| 101 | #define ARM_DBG_READ(M, OP2, VAL) do {\ | 101 | #define ARM_DBG_READ(N, M, OP2, VAL) do {\ |
| 102 | asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\ | 102 | asm volatile("mrc p14, 0, %0, " #N "," #M ", " #OP2 : "=r" (VAL));\ |
| 103 | } while (0) | 103 | } while (0) |
| 104 | 104 | ||
| 105 | #define ARM_DBG_WRITE(M, OP2, VAL) do {\ | 105 | #define ARM_DBG_WRITE(N, M, OP2, VAL) do {\ |
| 106 | asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\ | 106 | asm volatile("mcr p14, 0, %0, " #N "," #M ", " #OP2 : : "r" (VAL));\ |
| 107 | } while (0) | 107 | } while (0) |
| 108 | 108 | ||
| 109 | struct notifier_block; | 109 | struct notifier_block; |
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 281bf330124..5ff2e77782b 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c | |||
| @@ -52,14 +52,14 @@ static u8 debug_arch; | |||
| 52 | /* Maximum supported watchpoint length. */ | 52 | /* Maximum supported watchpoint length. */ |
| 53 | static u8 max_watchpoint_len; | 53 | static u8 max_watchpoint_len; |
| 54 | 54 | ||
| 55 | #define READ_WB_REG_CASE(OP2, M, VAL) \ | 55 | #define READ_WB_REG_CASE(OP2, M, VAL) \ |
| 56 | case ((OP2 << 4) + M): \ | 56 | case ((OP2 << 4) + M): \ |
| 57 | ARM_DBG_READ(c ## M, OP2, VAL); \ | 57 | ARM_DBG_READ(c0, c ## M, OP2, VAL); \ |
| 58 | break | 58 | break |
| 59 | 59 | ||
| 60 | #define WRITE_WB_REG_CASE(OP2, M, VAL) \ | 60 | #define WRITE_WB_REG_CASE(OP2, M, VAL) \ |
| 61 | case ((OP2 << 4) + M): \ | 61 | case ((OP2 << 4) + M): \ |
| 62 | ARM_DBG_WRITE(c ## M, OP2, VAL);\ | 62 | ARM_DBG_WRITE(c0, c ## M, OP2, VAL); \ |
| 63 | break | 63 | break |
| 64 | 64 | ||
| 65 | #define GEN_READ_WB_REG_CASES(OP2, VAL) \ | 65 | #define GEN_READ_WB_REG_CASES(OP2, VAL) \ |
| @@ -136,12 +136,12 @@ static u8 get_debug_arch(void) | |||
| 136 | 136 | ||
| 137 | /* Do we implement the extended CPUID interface? */ | 137 | /* Do we implement the extended CPUID interface? */ |
| 138 | if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { | 138 | if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { |
| 139 | pr_warning("CPUID feature registers not supported. " | 139 | pr_warn_once("CPUID feature registers not supported. " |
| 140 | "Assuming v6 debug is present.\n"); | 140 | "Assuming v6 debug is present.\n"); |
| 141 | return ARM_DEBUG_ARCH_V6; | 141 | return ARM_DEBUG_ARCH_V6; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | ARM_DBG_READ(c0, 0, didr); | 144 | ARM_DBG_READ(c0, c0, 0, didr); |
| 145 | return (didr >> 16) & 0xf; | 145 | return (didr >> 16) & 0xf; |
| 146 | } | 146 | } |
| 147 | 147 | ||
| @@ -169,7 +169,7 @@ static int debug_exception_updates_fsr(void) | |||
| 169 | static int get_num_wrp_resources(void) | 169 | static int get_num_wrp_resources(void) |
| 170 | { | 170 | { |
| 171 | u32 didr; | 171 | u32 didr; |
| 172 | ARM_DBG_READ(c0, 0, didr); | 172 | ARM_DBG_READ(c0, c0, 0, didr); |
| 173 | return ((didr >> 28) & 0xf) + 1; | 173 | return ((didr >> 28) & 0xf) + 1; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| @@ -177,7 +177,7 @@ static int get_num_wrp_resources(void) | |||
| 177 | static int get_num_brp_resources(void) | 177 | static int get_num_brp_resources(void) |
| 178 | { | 178 | { |
| 179 | u32 didr; | 179 | u32 didr; |
| 180 | ARM_DBG_READ(c0, 0, didr); | 180 | ARM_DBG_READ(c0, c0, 0, didr); |
| 181 | return ((didr >> 24) & 0xf) + 1; | 181 | return ((didr >> 24) & 0xf) + 1; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| @@ -228,19 +228,17 @@ static int get_num_brps(void) | |||
| 228 | * be put into halting debug mode at any time by an external debugger | 228 | * be put into halting debug mode at any time by an external debugger |
| 229 | * but there is nothing we can do to prevent that. | 229 | * but there is nothing we can do to prevent that. |
| 230 | */ | 230 | */ |
| 231 | static int enable_monitor_mode(void) | 231 | static int monitor_mode_enabled(void) |
| 232 | { | 232 | { |
| 233 | u32 dscr; | 233 | u32 dscr; |
| 234 | int ret = 0; | 234 | ARM_DBG_READ(c0, c1, 0, dscr); |
| 235 | 235 | return !!(dscr & ARM_DSCR_MDBGEN); | |
| 236 | ARM_DBG_READ(c1, 0, dscr); | 236 | } |
| 237 | 237 | ||
| 238 | /* Ensure that halting mode is disabled. */ | 238 | static int enable_monitor_mode(void) |
| 239 | if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, | 239 | { |
| 240 | "halting debug mode enabled. Unable to access hardware resources.\n")) { | 240 | u32 dscr; |
| 241 | ret = -EPERM; | 241 | ARM_DBG_READ(c0, c1, 0, dscr); |
| 242 | goto out; | ||
| 243 | } | ||
| 244 | 242 | ||
| 245 | /* If monitor mode is already enabled, just return. */ | 243 | /* If monitor mode is already enabled, just return. */ |
| 246 | if (dscr & ARM_DSCR_MDBGEN) | 244 | if (dscr & ARM_DSCR_MDBGEN) |
| @@ -250,24 +248,27 @@ static int enable_monitor_mode(void) | |||
| 250 | switch (get_debug_arch()) { | 248 | switch (get_debug_arch()) { |
| 251 | case ARM_DEBUG_ARCH_V6: | 249 | case ARM_DEBUG_ARCH_V6: |
| 252 | case ARM_DEBUG_ARCH_V6_1: | 250 | case ARM_DEBUG_ARCH_V6_1: |
| 253 | ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN)); | 251 | ARM_DBG_WRITE(c0, c1, 0, (dscr | ARM_DSCR_MDBGEN)); |
| 254 | break; | 252 | break; |
| 255 | case ARM_DEBUG_ARCH_V7_ECP14: | 253 | case ARM_DEBUG_ARCH_V7_ECP14: |
| 256 | case ARM_DEBUG_ARCH_V7_1: | 254 | case ARM_DEBUG_ARCH_V7_1: |
| 257 | ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN)); | 255 | ARM_DBG_WRITE(c0, c2, 2, (dscr | ARM_DSCR_MDBGEN)); |
| 256 | isb(); | ||
| 258 | break; | 257 | break; |
| 259 | default: | 258 | default: |
| 260 | ret = -ENODEV; | 259 | return -ENODEV; |
| 261 | goto out; | ||
| 262 | } | 260 | } |
| 263 | 261 | ||
| 264 | /* Check that the write made it through. */ | 262 | /* Check that the write made it through. */ |
| 265 | ARM_DBG_READ(c1, 0, dscr); | 263 | ARM_DBG_READ(c0, c1, 0, dscr); |
| 266 | if (!(dscr & ARM_DSCR_MDBGEN)) | 264 | if (!(dscr & ARM_DSCR_MDBGEN)) { |
| 267 | ret = -EPERM; | 265 | pr_warn_once("Failed to enable monitor mode on CPU %d.\n", |
| 266 | smp_processor_id()); | ||
| 267 | return -EPERM; | ||
| 268 | } | ||
| 268 | 269 | ||
| 269 | out: | 270 | out: |
| 270 | return ret; | 271 | return 0; |
| 271 | } | 272 | } |
| 272 | 273 | ||
| 273 | int hw_breakpoint_slots(int type) | 274 | int hw_breakpoint_slots(int type) |
| @@ -328,14 +329,9 @@ int arch_install_hw_breakpoint(struct perf_event *bp) | |||
| 328 | { | 329 | { |
| 329 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); | 330 | struct arch_hw_breakpoint *info = counter_arch_bp(bp); |
| 330 | struct perf_event **slot, **slots; | 331 | struct perf_event **slot, **slots; |
| 331 | int i, max_slots, ctrl_base, val_base, ret = 0; | 332 | int i, max_slots, ctrl_base, val_base; |
| 332 | u32 addr, ctrl; | 333 | u32 addr, ctrl; |
| 333 | 334 | ||
| 334 | /* Ensure that we are in monitor mode and halting mode is disabled. */ | ||
| 335 | ret = enable_monitor_mode(); | ||
| 336 | if (ret) | ||
| 337 | goto out; | ||
| 338 | |||
| 339 | addr = info->address; | 335 | addr = info->address; |
| 340 | ctrl = encode_ctrl_reg(info->ctrl) | 0x1; | 336 | ctrl = encode_ctrl_reg(info->ctrl) | 0x1; |
| 341 | 337 | ||
| @@ -362,9 +358,9 @@ int arch_install_hw_breakpoint(struct perf_event *bp) | |||
| 362 | } | 358 | } |
| 363 | } | 359 | } |
| 364 | 360 | ||
| 365 | if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) { | 361 | if (i == max_slots) { |
| 366 | ret = -EBUSY; | 362 | pr_warning("Can't find any breakpoint slot\n"); |
| 367 | goto out; | 363 | return -EBUSY; |
| 368 | } | 364 | } |
| 369 | 365 | ||
| 370 | /* Override the breakpoint data with the step data. */ | 366 | /* Override the breakpoint data with the step data. */ |
| @@ -383,9 +379,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp) | |||
| 383 | 379 | ||
| 384 | /* Setup the control register. */ | 380 | /* Setup the control register. */ |
| 385 | write_wb_reg(ctrl_base + i, ctrl); | 381 | write_wb_reg(ctrl_base + i, ctrl); |
| 386 | 382 | return 0; | |
| 387 | out: | ||
| 388 | return ret; | ||
| 389 | } | 383 | } |
| 390 | 384 | ||
| 391 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) | 385 | void arch_uninstall_hw_breakpoint(struct perf_event *bp) |
| @@ -416,8 +410,10 @@ void arch_uninstall_hw_breakpoint(struct perf_event *bp) | |||
| 416 | } | 410 | } |
| 417 | } | 411 | } |
| 418 | 412 | ||
| 419 | if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) | 413 | if (i == max_slots) { |
| 414 | pr_warning("Can't find any breakpoint slot\n"); | ||
| 420 | return; | 415 | return; |
| 416 | } | ||
| 421 | 417 | ||
| 422 | /* Ensure that we disable the mismatch breakpoint. */ | 418 | /* Ensure that we disable the mismatch breakpoint. */ |
| 423 | if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE && | 419 | if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE && |
| @@ -596,6 +592,10 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
| 596 | int ret = 0; | 592 | int ret = 0; |
| 597 | u32 offset, alignment_mask = 0x3; | 593 | u32 offset, alignment_mask = 0x3; |
| 598 | 594 | ||
| 595 | /* Ensure that we are in monitor debug mode. */ | ||
| 596 | if (!monitor_mode_enabled()) | ||
| 597 | return -ENODEV; | ||
| 598 | |||
| 599 | /* Build the arch_hw_breakpoint. */ | 599 | /* Build the arch_hw_breakpoint. */ |
| 600 | ret = arch_build_bp_info(bp); | 600 | ret = arch_build_bp_info(bp); |
| 601 | if (ret) | 601 | if (ret) |
| @@ -858,7 +858,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, | |||
| 858 | local_irq_enable(); | 858 | local_irq_enable(); |
| 859 | 859 | ||
| 860 | /* We only handle watchpoints and hardware breakpoints. */ | 860 | /* We only handle watchpoints and hardware breakpoints. */ |
| 861 | ARM_DBG_READ(c1, 0, dscr); | 861 | ARM_DBG_READ(c0, c1, 0, dscr); |
| 862 | 862 | ||
| 863 | /* Perform perf callbacks. */ | 863 | /* Perform perf callbacks. */ |
| 864 | switch (ARM_DSCR_MOE(dscr)) { | 864 | switch (ARM_DSCR_MOE(dscr)) { |
| @@ -906,7 +906,7 @@ static struct undef_hook debug_reg_hook = { | |||
| 906 | static void reset_ctrl_regs(void *unused) | 906 | static void reset_ctrl_regs(void *unused) |
| 907 | { | 907 | { |
| 908 | int i, raw_num_brps, err = 0, cpu = smp_processor_id(); | 908 | int i, raw_num_brps, err = 0, cpu = smp_processor_id(); |
| 909 | u32 dbg_power; | 909 | u32 val; |
| 910 | 910 | ||
| 911 | /* | 911 | /* |
| 912 | * v7 debug contains save and restore registers so that debug state | 912 | * v7 debug contains save and restore registers so that debug state |
| @@ -919,23 +919,30 @@ static void reset_ctrl_regs(void *unused) | |||
| 919 | switch (debug_arch) { | 919 | switch (debug_arch) { |
| 920 | case ARM_DEBUG_ARCH_V6: | 920 | case ARM_DEBUG_ARCH_V6: |
| 921 | case ARM_DEBUG_ARCH_V6_1: | 921 | case ARM_DEBUG_ARCH_V6_1: |
| 922 | /* ARMv6 cores just need to reset the registers. */ | 922 | /* ARMv6 cores clear the registers out of reset. */ |
| 923 | goto reset_regs; | 923 | goto out_mdbgen; |
| 924 | case ARM_DEBUG_ARCH_V7_ECP14: | 924 | case ARM_DEBUG_ARCH_V7_ECP14: |
| 925 | /* | 925 | /* |
| 926 | * Ensure sticky power-down is clear (i.e. debug logic is | 926 | * Ensure sticky power-down is clear (i.e. debug logic is |
| 927 | * powered up). | 927 | * powered up). |
| 928 | */ | 928 | */ |
| 929 | asm volatile("mrc p14, 0, %0, c1, c5, 4" : "=r" (dbg_power)); | 929 | ARM_DBG_READ(c1, c5, 4, val); |
| 930 | if ((dbg_power & 0x1) == 0) | 930 | if ((val & 0x1) == 0) |
| 931 | err = -EPERM; | 931 | err = -EPERM; |
| 932 | |||
| 933 | /* | ||
| 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; | ||
| 932 | break; | 939 | break; |
| 933 | case ARM_DEBUG_ARCH_V7_1: | 940 | case ARM_DEBUG_ARCH_V7_1: |
| 934 | /* | 941 | /* |
| 935 | * Ensure the OS double lock is clear. | 942 | * Ensure the OS double lock is clear. |
| 936 | */ | 943 | */ |
| 937 | asm volatile("mrc p14, 0, %0, c1, c3, 4" : "=r" (dbg_power)); | 944 | ARM_DBG_READ(c1, c3, 4, val); |
| 938 | if ((dbg_power & 0x1) == 1) | 945 | if ((val & 0x1) == 1) |
| 939 | err = -EPERM; | 946 | err = -EPERM; |
| 940 | break; | 947 | break; |
| 941 | } | 948 | } |
| @@ -947,24 +954,29 @@ static void reset_ctrl_regs(void *unused) | |||
| 947 | } | 954 | } |
| 948 | 955 | ||
| 949 | /* | 956 | /* |
| 950 | * Unconditionally clear the lock by writing a value | 957 | * Unconditionally clear the OS lock by writing a value |
| 951 | * other than 0xC5ACCE55 to the access register. | 958 | * other than 0xC5ACCE55 to the access register. |
| 952 | */ | 959 | */ |
| 953 | asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0)); | 960 | ARM_DBG_WRITE(c1, c0, 4, 0); |
| 954 | isb(); | 961 | isb(); |
| 955 | 962 | ||
| 956 | /* | 963 | /* |
| 957 | * Clear any configured vector-catch events before | 964 | * Clear any configured vector-catch events before |
| 958 | * enabling monitor mode. | 965 | * enabling monitor mode. |
| 959 | */ | 966 | */ |
| 960 | asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0)); | 967 | clear_vcr: |
| 968 | ARM_DBG_WRITE(c0, c7, 0, 0); | ||
| 961 | isb(); | 969 | isb(); |
| 962 | 970 | ||
| 963 | reset_regs: | 971 | if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) { |
| 964 | if (enable_monitor_mode()) | 972 | pr_warning("CPU %d failed to disable vector catch\n", cpu); |
| 965 | return; | 973 | return; |
| 974 | } | ||
| 966 | 975 | ||
| 967 | /* We must also reset any reserved registers. */ | 976 | /* |
| 977 | * The control/value register pairs are UNKNOWN out of reset so | ||
| 978 | * clear them to avoid spurious debug events. | ||
| 979 | */ | ||
| 968 | raw_num_brps = get_num_brp_resources(); | 980 | raw_num_brps = get_num_brp_resources(); |
| 969 | for (i = 0; i < raw_num_brps; ++i) { | 981 | for (i = 0; i < raw_num_brps; ++i) { |
| 970 | write_wb_reg(ARM_BASE_BCR + i, 0UL); | 982 | write_wb_reg(ARM_BASE_BCR + i, 0UL); |
| @@ -975,6 +987,19 @@ reset_regs: | |||
| 975 | write_wb_reg(ARM_BASE_WCR + i, 0UL); | 987 | write_wb_reg(ARM_BASE_WCR + i, 0UL); |
| 976 | write_wb_reg(ARM_BASE_WVR + i, 0UL); | 988 | write_wb_reg(ARM_BASE_WVR + i, 0UL); |
| 977 | } | 989 | } |
| 990 | |||
| 991 | if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) { | ||
| 992 | pr_warning("CPU %d failed to clear debug register pairs\n", cpu); | ||
| 993 | return; | ||
| 994 | } | ||
| 995 | |||
| 996 | /* | ||
| 997 | * Have a crack at enabling monitor mode. We don't actually need | ||
| 998 | * it yet, but reporting an error early is useful if it fails. | ||
| 999 | */ | ||
| 1000 | out_mdbgen: | ||
| 1001 | if (enable_monitor_mode()) | ||
| 1002 | cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu)); | ||
| 978 | } | 1003 | } |
| 979 | 1004 | ||
| 980 | static int __cpuinit dbg_reset_notify(struct notifier_block *self, | 1005 | static int __cpuinit dbg_reset_notify(struct notifier_block *self, |
| @@ -992,8 +1017,6 @@ static struct notifier_block __cpuinitdata dbg_reset_nb = { | |||
| 992 | 1017 | ||
| 993 | static int __init arch_hw_breakpoint_init(void) | 1018 | static int __init arch_hw_breakpoint_init(void) |
| 994 | { | 1019 | { |
| 995 | u32 dscr; | ||
| 996 | |||
| 997 | debug_arch = get_debug_arch(); | 1020 | debug_arch = get_debug_arch(); |
| 998 | 1021 | ||
| 999 | if (!debug_arch_supported()) { | 1022 | if (!debug_arch_supported()) { |
| @@ -1028,17 +1051,10 @@ static int __init arch_hw_breakpoint_init(void) | |||
| 1028 | core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " : | 1051 | core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " : |
| 1029 | "", core_num_wrps); | 1052 | "", core_num_wrps); |
| 1030 | 1053 | ||
| 1031 | ARM_DBG_READ(c1, 0, dscr); | 1054 | /* Work out the maximum supported watchpoint length. */ |
| 1032 | if (dscr & ARM_DSCR_HDBGEN) { | 1055 | max_watchpoint_len = get_max_wp_len(); |
| 1033 | max_watchpoint_len = 4; | 1056 | pr_info("maximum watchpoint size is %u bytes.\n", |
| 1034 | pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n", | 1057 | max_watchpoint_len); |
| 1035 | max_watchpoint_len); | ||
| 1036 | } else { | ||
| 1037 | /* Work out the maximum supported watchpoint length. */ | ||
| 1038 | max_watchpoint_len = get_max_wp_len(); | ||
| 1039 | pr_info("maximum watchpoint size is %u bytes.\n", | ||
| 1040 | max_watchpoint_len); | ||
| 1041 | } | ||
| 1042 | 1058 | ||
| 1043 | /* Register debug fault handler. */ | 1059 | /* Register debug fault handler. */ |
| 1044 | hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, | 1060 | hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP, |
