162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2009, 2010 ARM Limited
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Author: Will Deacon <will.deacon@arm.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/*
1062306a36Sopenharmony_ci * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
1162306a36Sopenharmony_ci * using the CPU's debug registers.
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci#define pr_fmt(fmt) "hw-breakpoint: " fmt
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/errno.h>
1662306a36Sopenharmony_ci#include <linux/hardirq.h>
1762306a36Sopenharmony_ci#include <linux/perf_event.h>
1862306a36Sopenharmony_ci#include <linux/hw_breakpoint.h>
1962306a36Sopenharmony_ci#include <linux/smp.h>
2062306a36Sopenharmony_ci#include <linux/cpu_pm.h>
2162306a36Sopenharmony_ci#include <linux/coresight.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <asm/cacheflush.h>
2462306a36Sopenharmony_ci#include <asm/cputype.h>
2562306a36Sopenharmony_ci#include <asm/current.h>
2662306a36Sopenharmony_ci#include <asm/hw_breakpoint.h>
2762306a36Sopenharmony_ci#include <asm/traps.h>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/* Breakpoint currently in use for each BRP. */
3062306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/* Watchpoint currently in use for each WRP. */
3362306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* Number of BRP/WRP registers on this CPU. */
3662306a36Sopenharmony_cistatic int core_num_brps __ro_after_init;
3762306a36Sopenharmony_cistatic int core_num_wrps __ro_after_init;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/* Debug architecture version. */
4062306a36Sopenharmony_cistatic u8 debug_arch __ro_after_init;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* Does debug architecture support OS Save and Restore? */
4362306a36Sopenharmony_cistatic bool has_ossr __ro_after_init;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/* Maximum supported watchpoint length. */
4662306a36Sopenharmony_cistatic u8 max_watchpoint_len __ro_after_init;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define READ_WB_REG_CASE(OP2, M, VAL)			\
4962306a36Sopenharmony_ci	case ((OP2 << 4) + M):				\
5062306a36Sopenharmony_ci		ARM_DBG_READ(c0, c ## M, OP2, VAL);	\
5162306a36Sopenharmony_ci		break
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#define WRITE_WB_REG_CASE(OP2, M, VAL)			\
5462306a36Sopenharmony_ci	case ((OP2 << 4) + M):				\
5562306a36Sopenharmony_ci		ARM_DBG_WRITE(c0, c ## M, OP2, VAL);	\
5662306a36Sopenharmony_ci		break
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci#define GEN_READ_WB_REG_CASES(OP2, VAL)		\
5962306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 0, VAL);		\
6062306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 1, VAL);		\
6162306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 2, VAL);		\
6262306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 3, VAL);		\
6362306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 4, VAL);		\
6462306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 5, VAL);		\
6562306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 6, VAL);		\
6662306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 7, VAL);		\
6762306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 8, VAL);		\
6862306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 9, VAL);		\
6962306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 10, VAL);		\
7062306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 11, VAL);		\
7162306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 12, VAL);		\
7262306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 13, VAL);		\
7362306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 14, VAL);		\
7462306a36Sopenharmony_ci	READ_WB_REG_CASE(OP2, 15, VAL)
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define GEN_WRITE_WB_REG_CASES(OP2, VAL)	\
7762306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 0, VAL);		\
7862306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 1, VAL);		\
7962306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 2, VAL);		\
8062306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 3, VAL);		\
8162306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 4, VAL);		\
8262306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 5, VAL);		\
8362306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 6, VAL);		\
8462306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 7, VAL);		\
8562306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 8, VAL);		\
8662306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 9, VAL);		\
8762306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 10, VAL);	\
8862306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 11, VAL);	\
8962306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 12, VAL);	\
9062306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 13, VAL);	\
9162306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 14, VAL);	\
9262306a36Sopenharmony_ci	WRITE_WB_REG_CASE(OP2, 15, VAL)
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic u32 read_wb_reg(int n)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	u32 val = 0;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	switch (n) {
9962306a36Sopenharmony_ci	GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val);
10062306a36Sopenharmony_ci	GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val);
10162306a36Sopenharmony_ci	GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val);
10262306a36Sopenharmony_ci	GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val);
10362306a36Sopenharmony_ci	default:
10462306a36Sopenharmony_ci		pr_warn("attempt to read from unknown breakpoint register %d\n",
10562306a36Sopenharmony_ci			n);
10662306a36Sopenharmony_ci	}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	return val;
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic void write_wb_reg(int n, u32 val)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	switch (n) {
11462306a36Sopenharmony_ci	GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val);
11562306a36Sopenharmony_ci	GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val);
11662306a36Sopenharmony_ci	GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val);
11762306a36Sopenharmony_ci	GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val);
11862306a36Sopenharmony_ci	default:
11962306a36Sopenharmony_ci		pr_warn("attempt to write to unknown breakpoint register %d\n",
12062306a36Sopenharmony_ci			n);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci	isb();
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/* Determine debug architecture. */
12662306a36Sopenharmony_cistatic u8 get_debug_arch(void)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	u32 didr;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	/* Do we implement the extended CPUID interface? */
13162306a36Sopenharmony_ci	if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
13262306a36Sopenharmony_ci		pr_warn_once("CPUID feature registers not supported. "
13362306a36Sopenharmony_ci			     "Assuming v6 debug is present.\n");
13462306a36Sopenharmony_ci		return ARM_DEBUG_ARCH_V6;
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	ARM_DBG_READ(c0, c0, 0, didr);
13862306a36Sopenharmony_ci	return (didr >> 16) & 0xf;
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ciu8 arch_get_debug_arch(void)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	return debug_arch;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic int debug_arch_supported(void)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	u8 arch = get_debug_arch();
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	/* We don't support the memory-mapped interface. */
15162306a36Sopenharmony_ci	return (arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14) ||
15262306a36Sopenharmony_ci		arch >= ARM_DEBUG_ARCH_V7_1;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci/* Can we determine the watchpoint access type from the fsr? */
15662306a36Sopenharmony_cistatic int debug_exception_updates_fsr(void)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	return get_debug_arch() >= ARM_DEBUG_ARCH_V8;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/* Determine number of WRP registers available. */
16262306a36Sopenharmony_cistatic int get_num_wrp_resources(void)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	u32 didr;
16562306a36Sopenharmony_ci	ARM_DBG_READ(c0, c0, 0, didr);
16662306a36Sopenharmony_ci	return ((didr >> 28) & 0xf) + 1;
16762306a36Sopenharmony_ci}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci/* Determine number of BRP registers available. */
17062306a36Sopenharmony_cistatic int get_num_brp_resources(void)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	u32 didr;
17362306a36Sopenharmony_ci	ARM_DBG_READ(c0, c0, 0, didr);
17462306a36Sopenharmony_ci	return ((didr >> 24) & 0xf) + 1;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci/* Does this core support mismatch breakpoints? */
17862306a36Sopenharmony_cistatic int core_has_mismatch_brps(void)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	return (get_debug_arch() >= ARM_DEBUG_ARCH_V7_ECP14 &&
18162306a36Sopenharmony_ci		get_num_brp_resources() > 1);
18262306a36Sopenharmony_ci}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci/* Determine number of usable WRPs available. */
18562306a36Sopenharmony_cistatic int get_num_wrps(void)
18662306a36Sopenharmony_ci{
18762306a36Sopenharmony_ci	/*
18862306a36Sopenharmony_ci	 * On debug architectures prior to 7.1, when a watchpoint fires, the
18962306a36Sopenharmony_ci	 * only way to work out which watchpoint it was is by disassembling
19062306a36Sopenharmony_ci	 * the faulting instruction and working out the address of the memory
19162306a36Sopenharmony_ci	 * access.
19262306a36Sopenharmony_ci	 *
19362306a36Sopenharmony_ci	 * Furthermore, we can only do this if the watchpoint was precise
19462306a36Sopenharmony_ci	 * since imprecise watchpoints prevent us from calculating register
19562306a36Sopenharmony_ci	 * based addresses.
19662306a36Sopenharmony_ci	 *
19762306a36Sopenharmony_ci	 * Providing we have more than 1 breakpoint register, we only report
19862306a36Sopenharmony_ci	 * a single watchpoint register for the time being. This way, we always
19962306a36Sopenharmony_ci	 * know which watchpoint fired. In the future we can either add a
20062306a36Sopenharmony_ci	 * disassembler and address generation emulator, or we can insert a
20162306a36Sopenharmony_ci	 * check to see if the DFAR is set on watchpoint exception entry
20262306a36Sopenharmony_ci	 * [the ARM ARM states that the DFAR is UNKNOWN, but experience shows
20362306a36Sopenharmony_ci	 * that it is set on some implementations].
20462306a36Sopenharmony_ci	 */
20562306a36Sopenharmony_ci	if (get_debug_arch() < ARM_DEBUG_ARCH_V7_1)
20662306a36Sopenharmony_ci		return 1;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	return get_num_wrp_resources();
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci/* Determine number of usable BRPs available. */
21262306a36Sopenharmony_cistatic int get_num_brps(void)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	int brps = get_num_brp_resources();
21562306a36Sopenharmony_ci	return core_has_mismatch_brps() ? brps - 1 : brps;
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/*
21962306a36Sopenharmony_ci * In order to access the breakpoint/watchpoint control registers,
22062306a36Sopenharmony_ci * we must be running in debug monitor mode. Unfortunately, we can
22162306a36Sopenharmony_ci * be put into halting debug mode at any time by an external debugger
22262306a36Sopenharmony_ci * but there is nothing we can do to prevent that.
22362306a36Sopenharmony_ci */
22462306a36Sopenharmony_cistatic int monitor_mode_enabled(void)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	u32 dscr;
22762306a36Sopenharmony_ci	ARM_DBG_READ(c0, c1, 0, dscr);
22862306a36Sopenharmony_ci	return !!(dscr & ARM_DSCR_MDBGEN);
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic int enable_monitor_mode(void)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	u32 dscr;
23462306a36Sopenharmony_ci	ARM_DBG_READ(c0, c1, 0, dscr);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	/* If monitor mode is already enabled, just return. */
23762306a36Sopenharmony_ci	if (dscr & ARM_DSCR_MDBGEN)
23862306a36Sopenharmony_ci		goto out;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	/* Write to the corresponding DSCR. */
24162306a36Sopenharmony_ci	switch (get_debug_arch()) {
24262306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V6:
24362306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V6_1:
24462306a36Sopenharmony_ci		ARM_DBG_WRITE(c0, c1, 0, (dscr | ARM_DSCR_MDBGEN));
24562306a36Sopenharmony_ci		break;
24662306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V7_ECP14:
24762306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V7_1:
24862306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V8:
24962306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V8_1:
25062306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V8_2:
25162306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V8_4:
25262306a36Sopenharmony_ci		ARM_DBG_WRITE(c0, c2, 2, (dscr | ARM_DSCR_MDBGEN));
25362306a36Sopenharmony_ci		isb();
25462306a36Sopenharmony_ci		break;
25562306a36Sopenharmony_ci	default:
25662306a36Sopenharmony_ci		return -ENODEV;
25762306a36Sopenharmony_ci	}
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	/* Check that the write made it through. */
26062306a36Sopenharmony_ci	ARM_DBG_READ(c0, c1, 0, dscr);
26162306a36Sopenharmony_ci	if (!(dscr & ARM_DSCR_MDBGEN)) {
26262306a36Sopenharmony_ci		pr_warn_once("Failed to enable monitor mode on CPU %d.\n",
26362306a36Sopenharmony_ci				smp_processor_id());
26462306a36Sopenharmony_ci		return -EPERM;
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ciout:
26862306a36Sopenharmony_ci	return 0;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ciint hw_breakpoint_slots(int type)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	if (!debug_arch_supported())
27462306a36Sopenharmony_ci		return 0;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/*
27762306a36Sopenharmony_ci	 * We can be called early, so don't rely on
27862306a36Sopenharmony_ci	 * our static variables being initialised.
27962306a36Sopenharmony_ci	 */
28062306a36Sopenharmony_ci	switch (type) {
28162306a36Sopenharmony_ci	case TYPE_INST:
28262306a36Sopenharmony_ci		return get_num_brps();
28362306a36Sopenharmony_ci	case TYPE_DATA:
28462306a36Sopenharmony_ci		return get_num_wrps();
28562306a36Sopenharmony_ci	default:
28662306a36Sopenharmony_ci		pr_warn("unknown slot type: %d\n", type);
28762306a36Sopenharmony_ci		return 0;
28862306a36Sopenharmony_ci	}
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci/*
29262306a36Sopenharmony_ci * Check if 8-bit byte-address select is available.
29362306a36Sopenharmony_ci * This clobbers WRP 0.
29462306a36Sopenharmony_ci */
29562306a36Sopenharmony_cistatic u8 get_max_wp_len(void)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	u32 ctrl_reg;
29862306a36Sopenharmony_ci	struct arch_hw_breakpoint_ctrl ctrl;
29962306a36Sopenharmony_ci	u8 size = 4;
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
30262306a36Sopenharmony_ci		goto out;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	memset(&ctrl, 0, sizeof(ctrl));
30562306a36Sopenharmony_ci	ctrl.len = ARM_BREAKPOINT_LEN_8;
30662306a36Sopenharmony_ci	ctrl_reg = encode_ctrl_reg(ctrl);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	write_wb_reg(ARM_BASE_WVR, 0);
30962306a36Sopenharmony_ci	write_wb_reg(ARM_BASE_WCR, ctrl_reg);
31062306a36Sopenharmony_ci	if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg)
31162306a36Sopenharmony_ci		size = 8;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ciout:
31462306a36Sopenharmony_ci	return size;
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ciu8 arch_get_max_wp_len(void)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	return max_watchpoint_len;
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci/*
32362306a36Sopenharmony_ci * Install a perf counter breakpoint.
32462306a36Sopenharmony_ci */
32562306a36Sopenharmony_ciint arch_install_hw_breakpoint(struct perf_event *bp)
32662306a36Sopenharmony_ci{
32762306a36Sopenharmony_ci	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
32862306a36Sopenharmony_ci	struct perf_event **slot, **slots;
32962306a36Sopenharmony_ci	int i, max_slots, ctrl_base, val_base;
33062306a36Sopenharmony_ci	u32 addr, ctrl;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	addr = info->address;
33362306a36Sopenharmony_ci	ctrl = encode_ctrl_reg(info->ctrl) | 0x1;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
33662306a36Sopenharmony_ci		/* Breakpoint */
33762306a36Sopenharmony_ci		ctrl_base = ARM_BASE_BCR;
33862306a36Sopenharmony_ci		val_base = ARM_BASE_BVR;
33962306a36Sopenharmony_ci		slots = this_cpu_ptr(bp_on_reg);
34062306a36Sopenharmony_ci		max_slots = core_num_brps;
34162306a36Sopenharmony_ci	} else {
34262306a36Sopenharmony_ci		/* Watchpoint */
34362306a36Sopenharmony_ci		ctrl_base = ARM_BASE_WCR;
34462306a36Sopenharmony_ci		val_base = ARM_BASE_WVR;
34562306a36Sopenharmony_ci		slots = this_cpu_ptr(wp_on_reg);
34662306a36Sopenharmony_ci		max_slots = core_num_wrps;
34762306a36Sopenharmony_ci	}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	for (i = 0; i < max_slots; ++i) {
35062306a36Sopenharmony_ci		slot = &slots[i];
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci		if (!*slot) {
35362306a36Sopenharmony_ci			*slot = bp;
35462306a36Sopenharmony_ci			break;
35562306a36Sopenharmony_ci		}
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	if (i == max_slots) {
35962306a36Sopenharmony_ci		pr_warn("Can't find any breakpoint slot\n");
36062306a36Sopenharmony_ci		return -EBUSY;
36162306a36Sopenharmony_ci	}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	/* Override the breakpoint data with the step data. */
36462306a36Sopenharmony_ci	if (info->step_ctrl.enabled) {
36562306a36Sopenharmony_ci		addr = info->trigger & ~0x3;
36662306a36Sopenharmony_ci		ctrl = encode_ctrl_reg(info->step_ctrl);
36762306a36Sopenharmony_ci		if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE) {
36862306a36Sopenharmony_ci			i = 0;
36962306a36Sopenharmony_ci			ctrl_base = ARM_BASE_BCR + core_num_brps;
37062306a36Sopenharmony_ci			val_base = ARM_BASE_BVR + core_num_brps;
37162306a36Sopenharmony_ci		}
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	/* Setup the address register. */
37562306a36Sopenharmony_ci	write_wb_reg(val_base + i, addr);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	/* Setup the control register. */
37862306a36Sopenharmony_ci	write_wb_reg(ctrl_base + i, ctrl);
37962306a36Sopenharmony_ci	return 0;
38062306a36Sopenharmony_ci}
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_civoid arch_uninstall_hw_breakpoint(struct perf_event *bp)
38362306a36Sopenharmony_ci{
38462306a36Sopenharmony_ci	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
38562306a36Sopenharmony_ci	struct perf_event **slot, **slots;
38662306a36Sopenharmony_ci	int i, max_slots, base;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
38962306a36Sopenharmony_ci		/* Breakpoint */
39062306a36Sopenharmony_ci		base = ARM_BASE_BCR;
39162306a36Sopenharmony_ci		slots = this_cpu_ptr(bp_on_reg);
39262306a36Sopenharmony_ci		max_slots = core_num_brps;
39362306a36Sopenharmony_ci	} else {
39462306a36Sopenharmony_ci		/* Watchpoint */
39562306a36Sopenharmony_ci		base = ARM_BASE_WCR;
39662306a36Sopenharmony_ci		slots = this_cpu_ptr(wp_on_reg);
39762306a36Sopenharmony_ci		max_slots = core_num_wrps;
39862306a36Sopenharmony_ci	}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	/* Remove the breakpoint. */
40162306a36Sopenharmony_ci	for (i = 0; i < max_slots; ++i) {
40262306a36Sopenharmony_ci		slot = &slots[i];
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci		if (*slot == bp) {
40562306a36Sopenharmony_ci			*slot = NULL;
40662306a36Sopenharmony_ci			break;
40762306a36Sopenharmony_ci		}
40862306a36Sopenharmony_ci	}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	if (i == max_slots) {
41162306a36Sopenharmony_ci		pr_warn("Can't find any breakpoint slot\n");
41262306a36Sopenharmony_ci		return;
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci	/* Ensure that we disable the mismatch breakpoint. */
41662306a36Sopenharmony_ci	if (info->ctrl.type != ARM_BREAKPOINT_EXECUTE &&
41762306a36Sopenharmony_ci	    info->step_ctrl.enabled) {
41862306a36Sopenharmony_ci		i = 0;
41962306a36Sopenharmony_ci		base = ARM_BASE_BCR + core_num_brps;
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	/* Reset the control register. */
42362306a36Sopenharmony_ci	write_wb_reg(base + i, 0);
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic int get_hbp_len(u8 hbp_len)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	unsigned int len_in_bytes = 0;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	switch (hbp_len) {
43162306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_1:
43262306a36Sopenharmony_ci		len_in_bytes = 1;
43362306a36Sopenharmony_ci		break;
43462306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_2:
43562306a36Sopenharmony_ci		len_in_bytes = 2;
43662306a36Sopenharmony_ci		break;
43762306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_4:
43862306a36Sopenharmony_ci		len_in_bytes = 4;
43962306a36Sopenharmony_ci		break;
44062306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_8:
44162306a36Sopenharmony_ci		len_in_bytes = 8;
44262306a36Sopenharmony_ci		break;
44362306a36Sopenharmony_ci	}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	return len_in_bytes;
44662306a36Sopenharmony_ci}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci/*
44962306a36Sopenharmony_ci * Check whether bp virtual address is in kernel space.
45062306a36Sopenharmony_ci */
45162306a36Sopenharmony_ciint arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw)
45262306a36Sopenharmony_ci{
45362306a36Sopenharmony_ci	unsigned int len;
45462306a36Sopenharmony_ci	unsigned long va;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	va = hw->address;
45762306a36Sopenharmony_ci	len = get_hbp_len(hw->ctrl.len);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci/*
46362306a36Sopenharmony_ci * Extract generic type and length encodings from an arch_hw_breakpoint_ctrl.
46462306a36Sopenharmony_ci * Hopefully this will disappear when ptrace can bypass the conversion
46562306a36Sopenharmony_ci * to generic breakpoint descriptions.
46662306a36Sopenharmony_ci */
46762306a36Sopenharmony_ciint arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
46862306a36Sopenharmony_ci			   int *gen_len, int *gen_type)
46962306a36Sopenharmony_ci{
47062306a36Sopenharmony_ci	/* Type */
47162306a36Sopenharmony_ci	switch (ctrl.type) {
47262306a36Sopenharmony_ci	case ARM_BREAKPOINT_EXECUTE:
47362306a36Sopenharmony_ci		*gen_type = HW_BREAKPOINT_X;
47462306a36Sopenharmony_ci		break;
47562306a36Sopenharmony_ci	case ARM_BREAKPOINT_LOAD:
47662306a36Sopenharmony_ci		*gen_type = HW_BREAKPOINT_R;
47762306a36Sopenharmony_ci		break;
47862306a36Sopenharmony_ci	case ARM_BREAKPOINT_STORE:
47962306a36Sopenharmony_ci		*gen_type = HW_BREAKPOINT_W;
48062306a36Sopenharmony_ci		break;
48162306a36Sopenharmony_ci	case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE:
48262306a36Sopenharmony_ci		*gen_type = HW_BREAKPOINT_RW;
48362306a36Sopenharmony_ci		break;
48462306a36Sopenharmony_ci	default:
48562306a36Sopenharmony_ci		return -EINVAL;
48662306a36Sopenharmony_ci	}
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	/* Len */
48962306a36Sopenharmony_ci	switch (ctrl.len) {
49062306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_1:
49162306a36Sopenharmony_ci		*gen_len = HW_BREAKPOINT_LEN_1;
49262306a36Sopenharmony_ci		break;
49362306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_2:
49462306a36Sopenharmony_ci		*gen_len = HW_BREAKPOINT_LEN_2;
49562306a36Sopenharmony_ci		break;
49662306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_4:
49762306a36Sopenharmony_ci		*gen_len = HW_BREAKPOINT_LEN_4;
49862306a36Sopenharmony_ci		break;
49962306a36Sopenharmony_ci	case ARM_BREAKPOINT_LEN_8:
50062306a36Sopenharmony_ci		*gen_len = HW_BREAKPOINT_LEN_8;
50162306a36Sopenharmony_ci		break;
50262306a36Sopenharmony_ci	default:
50362306a36Sopenharmony_ci		return -EINVAL;
50462306a36Sopenharmony_ci	}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	return 0;
50762306a36Sopenharmony_ci}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci/*
51062306a36Sopenharmony_ci * Construct an arch_hw_breakpoint from a perf_event.
51162306a36Sopenharmony_ci */
51262306a36Sopenharmony_cistatic int arch_build_bp_info(struct perf_event *bp,
51362306a36Sopenharmony_ci			      const struct perf_event_attr *attr,
51462306a36Sopenharmony_ci			      struct arch_hw_breakpoint *hw)
51562306a36Sopenharmony_ci{
51662306a36Sopenharmony_ci	/* Type */
51762306a36Sopenharmony_ci	switch (attr->bp_type) {
51862306a36Sopenharmony_ci	case HW_BREAKPOINT_X:
51962306a36Sopenharmony_ci		hw->ctrl.type = ARM_BREAKPOINT_EXECUTE;
52062306a36Sopenharmony_ci		break;
52162306a36Sopenharmony_ci	case HW_BREAKPOINT_R:
52262306a36Sopenharmony_ci		hw->ctrl.type = ARM_BREAKPOINT_LOAD;
52362306a36Sopenharmony_ci		break;
52462306a36Sopenharmony_ci	case HW_BREAKPOINT_W:
52562306a36Sopenharmony_ci		hw->ctrl.type = ARM_BREAKPOINT_STORE;
52662306a36Sopenharmony_ci		break;
52762306a36Sopenharmony_ci	case HW_BREAKPOINT_RW:
52862306a36Sopenharmony_ci		hw->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
52962306a36Sopenharmony_ci		break;
53062306a36Sopenharmony_ci	default:
53162306a36Sopenharmony_ci		return -EINVAL;
53262306a36Sopenharmony_ci	}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	/* Len */
53562306a36Sopenharmony_ci	switch (attr->bp_len) {
53662306a36Sopenharmony_ci	case HW_BREAKPOINT_LEN_1:
53762306a36Sopenharmony_ci		hw->ctrl.len = ARM_BREAKPOINT_LEN_1;
53862306a36Sopenharmony_ci		break;
53962306a36Sopenharmony_ci	case HW_BREAKPOINT_LEN_2:
54062306a36Sopenharmony_ci		hw->ctrl.len = ARM_BREAKPOINT_LEN_2;
54162306a36Sopenharmony_ci		break;
54262306a36Sopenharmony_ci	case HW_BREAKPOINT_LEN_4:
54362306a36Sopenharmony_ci		hw->ctrl.len = ARM_BREAKPOINT_LEN_4;
54462306a36Sopenharmony_ci		break;
54562306a36Sopenharmony_ci	case HW_BREAKPOINT_LEN_8:
54662306a36Sopenharmony_ci		hw->ctrl.len = ARM_BREAKPOINT_LEN_8;
54762306a36Sopenharmony_ci		if ((hw->ctrl.type != ARM_BREAKPOINT_EXECUTE)
54862306a36Sopenharmony_ci			&& max_watchpoint_len >= 8)
54962306a36Sopenharmony_ci			break;
55062306a36Sopenharmony_ci		fallthrough;
55162306a36Sopenharmony_ci	default:
55262306a36Sopenharmony_ci		return -EINVAL;
55362306a36Sopenharmony_ci	}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	/*
55662306a36Sopenharmony_ci	 * Breakpoints must be of length 2 (thumb) or 4 (ARM) bytes.
55762306a36Sopenharmony_ci	 * Watchpoints can be of length 1, 2, 4 or 8 bytes if supported
55862306a36Sopenharmony_ci	 * by the hardware and must be aligned to the appropriate number of
55962306a36Sopenharmony_ci	 * bytes.
56062306a36Sopenharmony_ci	 */
56162306a36Sopenharmony_ci	if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE &&
56262306a36Sopenharmony_ci	    hw->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
56362306a36Sopenharmony_ci	    hw->ctrl.len != ARM_BREAKPOINT_LEN_4)
56462306a36Sopenharmony_ci		return -EINVAL;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	/* Address */
56762306a36Sopenharmony_ci	hw->address = attr->bp_addr;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	/* Privilege */
57062306a36Sopenharmony_ci	hw->ctrl.privilege = ARM_BREAKPOINT_USER;
57162306a36Sopenharmony_ci	if (arch_check_bp_in_kernelspace(hw))
57262306a36Sopenharmony_ci		hw->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	/* Enabled? */
57562306a36Sopenharmony_ci	hw->ctrl.enabled = !attr->disabled;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	/* Mismatch */
57862306a36Sopenharmony_ci	hw->ctrl.mismatch = 0;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	return 0;
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci/*
58462306a36Sopenharmony_ci * Validate the arch-specific HW Breakpoint register settings.
58562306a36Sopenharmony_ci */
58662306a36Sopenharmony_ciint hw_breakpoint_arch_parse(struct perf_event *bp,
58762306a36Sopenharmony_ci			     const struct perf_event_attr *attr,
58862306a36Sopenharmony_ci			     struct arch_hw_breakpoint *hw)
58962306a36Sopenharmony_ci{
59062306a36Sopenharmony_ci	int ret = 0;
59162306a36Sopenharmony_ci	u32 offset, alignment_mask = 0x3;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	/* Ensure that we are in monitor debug mode. */
59462306a36Sopenharmony_ci	if (!monitor_mode_enabled())
59562306a36Sopenharmony_ci		return -ENODEV;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	/* Build the arch_hw_breakpoint. */
59862306a36Sopenharmony_ci	ret = arch_build_bp_info(bp, attr, hw);
59962306a36Sopenharmony_ci	if (ret)
60062306a36Sopenharmony_ci		goto out;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	/* Check address alignment. */
60362306a36Sopenharmony_ci	if (hw->ctrl.len == ARM_BREAKPOINT_LEN_8)
60462306a36Sopenharmony_ci		alignment_mask = 0x7;
60562306a36Sopenharmony_ci	offset = hw->address & alignment_mask;
60662306a36Sopenharmony_ci	switch (offset) {
60762306a36Sopenharmony_ci	case 0:
60862306a36Sopenharmony_ci		/* Aligned */
60962306a36Sopenharmony_ci		break;
61062306a36Sopenharmony_ci	case 1:
61162306a36Sopenharmony_ci	case 2:
61262306a36Sopenharmony_ci		/* Allow halfword watchpoints and breakpoints. */
61362306a36Sopenharmony_ci		if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2)
61462306a36Sopenharmony_ci			break;
61562306a36Sopenharmony_ci		fallthrough;
61662306a36Sopenharmony_ci	case 3:
61762306a36Sopenharmony_ci		/* Allow single byte watchpoint. */
61862306a36Sopenharmony_ci		if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1)
61962306a36Sopenharmony_ci			break;
62062306a36Sopenharmony_ci		fallthrough;
62162306a36Sopenharmony_ci	default:
62262306a36Sopenharmony_ci		ret = -EINVAL;
62362306a36Sopenharmony_ci		goto out;
62462306a36Sopenharmony_ci	}
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	hw->address &= ~alignment_mask;
62762306a36Sopenharmony_ci	hw->ctrl.len <<= offset;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	if (uses_default_overflow_handler(bp)) {
63062306a36Sopenharmony_ci		/*
63162306a36Sopenharmony_ci		 * Mismatch breakpoints are required for single-stepping
63262306a36Sopenharmony_ci		 * breakpoints.
63362306a36Sopenharmony_ci		 */
63462306a36Sopenharmony_ci		if (!core_has_mismatch_brps())
63562306a36Sopenharmony_ci			return -EINVAL;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci		/* We don't allow mismatch breakpoints in kernel space. */
63862306a36Sopenharmony_ci		if (arch_check_bp_in_kernelspace(hw))
63962306a36Sopenharmony_ci			return -EPERM;
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci		/*
64262306a36Sopenharmony_ci		 * Per-cpu breakpoints are not supported by our stepping
64362306a36Sopenharmony_ci		 * mechanism.
64462306a36Sopenharmony_ci		 */
64562306a36Sopenharmony_ci		if (!bp->hw.target)
64662306a36Sopenharmony_ci			return -EINVAL;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci		/*
64962306a36Sopenharmony_ci		 * We only support specific access types if the fsr
65062306a36Sopenharmony_ci		 * reports them.
65162306a36Sopenharmony_ci		 */
65262306a36Sopenharmony_ci		if (!debug_exception_updates_fsr() &&
65362306a36Sopenharmony_ci		    (hw->ctrl.type == ARM_BREAKPOINT_LOAD ||
65462306a36Sopenharmony_ci		     hw->ctrl.type == ARM_BREAKPOINT_STORE))
65562306a36Sopenharmony_ci			return -EINVAL;
65662306a36Sopenharmony_ci	}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ciout:
65962306a36Sopenharmony_ci	return ret;
66062306a36Sopenharmony_ci}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci/*
66362306a36Sopenharmony_ci * Enable/disable single-stepping over the breakpoint bp at address addr.
66462306a36Sopenharmony_ci */
66562306a36Sopenharmony_cistatic void enable_single_step(struct perf_event *bp, u32 addr)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	struct arch_hw_breakpoint *info = counter_arch_bp(bp);
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	arch_uninstall_hw_breakpoint(bp);
67062306a36Sopenharmony_ci	info->step_ctrl.mismatch  = 1;
67162306a36Sopenharmony_ci	info->step_ctrl.len	  = ARM_BREAKPOINT_LEN_4;
67262306a36Sopenharmony_ci	info->step_ctrl.type	  = ARM_BREAKPOINT_EXECUTE;
67362306a36Sopenharmony_ci	info->step_ctrl.privilege = info->ctrl.privilege;
67462306a36Sopenharmony_ci	info->step_ctrl.enabled	  = 1;
67562306a36Sopenharmony_ci	info->trigger		  = addr;
67662306a36Sopenharmony_ci	arch_install_hw_breakpoint(bp);
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_cistatic void disable_single_step(struct perf_event *bp)
68062306a36Sopenharmony_ci{
68162306a36Sopenharmony_ci	arch_uninstall_hw_breakpoint(bp);
68262306a36Sopenharmony_ci	counter_arch_bp(bp)->step_ctrl.enabled = 0;
68362306a36Sopenharmony_ci	arch_install_hw_breakpoint(bp);
68462306a36Sopenharmony_ci}
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci/*
68762306a36Sopenharmony_ci * Arm32 hardware does not always report a watchpoint hit address that matches
68862306a36Sopenharmony_ci * one of the watchpoints set. It can also report an address "near" the
68962306a36Sopenharmony_ci * watchpoint if a single instruction access both watched and unwatched
69062306a36Sopenharmony_ci * addresses. There is no straight-forward way, short of disassembling the
69162306a36Sopenharmony_ci * offending instruction, to map that address back to the watchpoint. This
69262306a36Sopenharmony_ci * function computes the distance of the memory access from the watchpoint as a
69362306a36Sopenharmony_ci * heuristic for the likelyhood that a given access triggered the watchpoint.
69462306a36Sopenharmony_ci *
69562306a36Sopenharmony_ci * See this same function in the arm64 platform code, which has the same
69662306a36Sopenharmony_ci * problem.
69762306a36Sopenharmony_ci *
69862306a36Sopenharmony_ci * The function returns the distance of the address from the bytes watched by
69962306a36Sopenharmony_ci * the watchpoint. In case of an exact match, it returns 0.
70062306a36Sopenharmony_ci */
70162306a36Sopenharmony_cistatic u32 get_distance_from_watchpoint(unsigned long addr, u32 val,
70262306a36Sopenharmony_ci					struct arch_hw_breakpoint_ctrl *ctrl)
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	u32 wp_low, wp_high;
70562306a36Sopenharmony_ci	u32 lens, lene;
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci	lens = __ffs(ctrl->len);
70862306a36Sopenharmony_ci	lene = __fls(ctrl->len);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	wp_low = val + lens;
71162306a36Sopenharmony_ci	wp_high = val + lene;
71262306a36Sopenharmony_ci	if (addr < wp_low)
71362306a36Sopenharmony_ci		return wp_low - addr;
71462306a36Sopenharmony_ci	else if (addr > wp_high)
71562306a36Sopenharmony_ci		return addr - wp_high;
71662306a36Sopenharmony_ci	else
71762306a36Sopenharmony_ci		return 0;
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_cistatic int watchpoint_fault_on_uaccess(struct pt_regs *regs,
72162306a36Sopenharmony_ci				       struct arch_hw_breakpoint *info)
72262306a36Sopenharmony_ci{
72362306a36Sopenharmony_ci	return !user_mode(regs) && info->ctrl.privilege == ARM_BREAKPOINT_USER;
72462306a36Sopenharmony_ci}
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_cistatic void watchpoint_handler(unsigned long addr, unsigned int fsr,
72762306a36Sopenharmony_ci			       struct pt_regs *regs)
72862306a36Sopenharmony_ci{
72962306a36Sopenharmony_ci	int i, access, closest_match = 0;
73062306a36Sopenharmony_ci	u32 min_dist = -1, dist;
73162306a36Sopenharmony_ci	u32 val, ctrl_reg;
73262306a36Sopenharmony_ci	struct perf_event *wp, **slots;
73362306a36Sopenharmony_ci	struct arch_hw_breakpoint *info;
73462306a36Sopenharmony_ci	struct arch_hw_breakpoint_ctrl ctrl;
73562306a36Sopenharmony_ci
73662306a36Sopenharmony_ci	slots = this_cpu_ptr(wp_on_reg);
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	/*
73962306a36Sopenharmony_ci	 * Find all watchpoints that match the reported address. If no exact
74062306a36Sopenharmony_ci	 * match is found. Attribute the hit to the closest watchpoint.
74162306a36Sopenharmony_ci	 */
74262306a36Sopenharmony_ci	rcu_read_lock();
74362306a36Sopenharmony_ci	for (i = 0; i < core_num_wrps; ++i) {
74462306a36Sopenharmony_ci		wp = slots[i];
74562306a36Sopenharmony_ci		if (wp == NULL)
74662306a36Sopenharmony_ci			continue;
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci		/*
74962306a36Sopenharmony_ci		 * The DFAR is an unknown value on debug architectures prior
75062306a36Sopenharmony_ci		 * to 7.1. Since we only allow a single watchpoint on these
75162306a36Sopenharmony_ci		 * older CPUs, we can set the trigger to the lowest possible
75262306a36Sopenharmony_ci		 * faulting address.
75362306a36Sopenharmony_ci		 */
75462306a36Sopenharmony_ci		if (debug_arch < ARM_DEBUG_ARCH_V7_1) {
75562306a36Sopenharmony_ci			BUG_ON(i > 0);
75662306a36Sopenharmony_ci			info = counter_arch_bp(wp);
75762306a36Sopenharmony_ci			info->trigger = wp->attr.bp_addr;
75862306a36Sopenharmony_ci		} else {
75962306a36Sopenharmony_ci			/* Check that the access type matches. */
76062306a36Sopenharmony_ci			if (debug_exception_updates_fsr()) {
76162306a36Sopenharmony_ci				access = (fsr & ARM_FSR_ACCESS_MASK) ?
76262306a36Sopenharmony_ci					  HW_BREAKPOINT_W : HW_BREAKPOINT_R;
76362306a36Sopenharmony_ci				if (!(access & hw_breakpoint_type(wp)))
76462306a36Sopenharmony_ci					continue;
76562306a36Sopenharmony_ci			}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci			val = read_wb_reg(ARM_BASE_WVR + i);
76862306a36Sopenharmony_ci			ctrl_reg = read_wb_reg(ARM_BASE_WCR + i);
76962306a36Sopenharmony_ci			decode_ctrl_reg(ctrl_reg, &ctrl);
77062306a36Sopenharmony_ci			dist = get_distance_from_watchpoint(addr, val, &ctrl);
77162306a36Sopenharmony_ci			if (dist < min_dist) {
77262306a36Sopenharmony_ci				min_dist = dist;
77362306a36Sopenharmony_ci				closest_match = i;
77462306a36Sopenharmony_ci			}
77562306a36Sopenharmony_ci			/* Is this an exact match? */
77662306a36Sopenharmony_ci			if (dist != 0)
77762306a36Sopenharmony_ci				continue;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci			/* We have a winner. */
78062306a36Sopenharmony_ci			info = counter_arch_bp(wp);
78162306a36Sopenharmony_ci			info->trigger = addr;
78262306a36Sopenharmony_ci		}
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci		/*
78762306a36Sopenharmony_ci		 * If we triggered a user watchpoint from a uaccess routine,
78862306a36Sopenharmony_ci		 * then handle the stepping ourselves since userspace really
78962306a36Sopenharmony_ci		 * can't help us with this.
79062306a36Sopenharmony_ci		 */
79162306a36Sopenharmony_ci		if (watchpoint_fault_on_uaccess(regs, info))
79262306a36Sopenharmony_ci			goto step;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci		perf_bp_event(wp, regs);
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci		/*
79762306a36Sopenharmony_ci		 * Defer stepping to the overflow handler if one is installed.
79862306a36Sopenharmony_ci		 * Otherwise, insert a temporary mismatch breakpoint so that
79962306a36Sopenharmony_ci		 * we can single-step over the watchpoint trigger.
80062306a36Sopenharmony_ci		 */
80162306a36Sopenharmony_ci		if (!uses_default_overflow_handler(wp))
80262306a36Sopenharmony_ci			continue;
80362306a36Sopenharmony_cistep:
80462306a36Sopenharmony_ci		enable_single_step(wp, instruction_pointer(regs));
80562306a36Sopenharmony_ci	}
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	if (min_dist > 0 && min_dist != -1) {
80862306a36Sopenharmony_ci		/* No exact match found. */
80962306a36Sopenharmony_ci		wp = slots[closest_match];
81062306a36Sopenharmony_ci		info = counter_arch_bp(wp);
81162306a36Sopenharmony_ci		info->trigger = addr;
81262306a36Sopenharmony_ci		pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
81362306a36Sopenharmony_ci		perf_bp_event(wp, regs);
81462306a36Sopenharmony_ci		if (uses_default_overflow_handler(wp))
81562306a36Sopenharmony_ci			enable_single_step(wp, instruction_pointer(regs));
81662306a36Sopenharmony_ci	}
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	rcu_read_unlock();
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_cistatic void watchpoint_single_step_handler(unsigned long pc)
82262306a36Sopenharmony_ci{
82362306a36Sopenharmony_ci	int i;
82462306a36Sopenharmony_ci	struct perf_event *wp, **slots;
82562306a36Sopenharmony_ci	struct arch_hw_breakpoint *info;
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci	slots = this_cpu_ptr(wp_on_reg);
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci	for (i = 0; i < core_num_wrps; ++i) {
83062306a36Sopenharmony_ci		rcu_read_lock();
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci		wp = slots[i];
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci		if (wp == NULL)
83562306a36Sopenharmony_ci			goto unlock;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci		info = counter_arch_bp(wp);
83862306a36Sopenharmony_ci		if (!info->step_ctrl.enabled)
83962306a36Sopenharmony_ci			goto unlock;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci		/*
84262306a36Sopenharmony_ci		 * Restore the original watchpoint if we've completed the
84362306a36Sopenharmony_ci		 * single-step.
84462306a36Sopenharmony_ci		 */
84562306a36Sopenharmony_ci		if (info->trigger != pc)
84662306a36Sopenharmony_ci			disable_single_step(wp);
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ciunlock:
84962306a36Sopenharmony_ci		rcu_read_unlock();
85062306a36Sopenharmony_ci	}
85162306a36Sopenharmony_ci}
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_cistatic void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
85462306a36Sopenharmony_ci{
85562306a36Sopenharmony_ci	int i;
85662306a36Sopenharmony_ci	u32 ctrl_reg, val, addr;
85762306a36Sopenharmony_ci	struct perf_event *bp, **slots;
85862306a36Sopenharmony_ci	struct arch_hw_breakpoint *info;
85962306a36Sopenharmony_ci	struct arch_hw_breakpoint_ctrl ctrl;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	slots = this_cpu_ptr(bp_on_reg);
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_ci	/* The exception entry code places the amended lr in the PC. */
86462306a36Sopenharmony_ci	addr = regs->ARM_pc;
86562306a36Sopenharmony_ci
86662306a36Sopenharmony_ci	/* Check the currently installed breakpoints first. */
86762306a36Sopenharmony_ci	for (i = 0; i < core_num_brps; ++i) {
86862306a36Sopenharmony_ci		rcu_read_lock();
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci		bp = slots[i];
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci		if (bp == NULL)
87362306a36Sopenharmony_ci			goto unlock;
87462306a36Sopenharmony_ci
87562306a36Sopenharmony_ci		info = counter_arch_bp(bp);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci		/* Check if the breakpoint value matches. */
87862306a36Sopenharmony_ci		val = read_wb_reg(ARM_BASE_BVR + i);
87962306a36Sopenharmony_ci		if (val != (addr & ~0x3))
88062306a36Sopenharmony_ci			goto mismatch;
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci		/* Possible match, check the byte address select to confirm. */
88362306a36Sopenharmony_ci		ctrl_reg = read_wb_reg(ARM_BASE_BCR + i);
88462306a36Sopenharmony_ci		decode_ctrl_reg(ctrl_reg, &ctrl);
88562306a36Sopenharmony_ci		if ((1 << (addr & 0x3)) & ctrl.len) {
88662306a36Sopenharmony_ci			info->trigger = addr;
88762306a36Sopenharmony_ci			pr_debug("breakpoint fired: address = 0x%x\n", addr);
88862306a36Sopenharmony_ci			perf_bp_event(bp, regs);
88962306a36Sopenharmony_ci			if (uses_default_overflow_handler(bp))
89062306a36Sopenharmony_ci				enable_single_step(bp, addr);
89162306a36Sopenharmony_ci			goto unlock;
89262306a36Sopenharmony_ci		}
89362306a36Sopenharmony_ci
89462306a36Sopenharmony_cimismatch:
89562306a36Sopenharmony_ci		/* If we're stepping a breakpoint, it can now be restored. */
89662306a36Sopenharmony_ci		if (info->step_ctrl.enabled)
89762306a36Sopenharmony_ci			disable_single_step(bp);
89862306a36Sopenharmony_ciunlock:
89962306a36Sopenharmony_ci		rcu_read_unlock();
90062306a36Sopenharmony_ci	}
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	/* Handle any pending watchpoint single-step breakpoints. */
90362306a36Sopenharmony_ci	watchpoint_single_step_handler(addr);
90462306a36Sopenharmony_ci}
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci/*
90762306a36Sopenharmony_ci * Called from either the Data Abort Handler [watchpoint] or the
90862306a36Sopenharmony_ci * Prefetch Abort Handler [breakpoint] with interrupts disabled.
90962306a36Sopenharmony_ci */
91062306a36Sopenharmony_cistatic int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
91162306a36Sopenharmony_ci				 struct pt_regs *regs)
91262306a36Sopenharmony_ci{
91362306a36Sopenharmony_ci	int ret = 0;
91462306a36Sopenharmony_ci	u32 dscr;
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_ci	preempt_disable();
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	if (interrupts_enabled(regs))
91962306a36Sopenharmony_ci		local_irq_enable();
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci	/* We only handle watchpoints and hardware breakpoints. */
92262306a36Sopenharmony_ci	ARM_DBG_READ(c0, c1, 0, dscr);
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	/* Perform perf callbacks. */
92562306a36Sopenharmony_ci	switch (ARM_DSCR_MOE(dscr)) {
92662306a36Sopenharmony_ci	case ARM_ENTRY_BREAKPOINT:
92762306a36Sopenharmony_ci		breakpoint_handler(addr, regs);
92862306a36Sopenharmony_ci		break;
92962306a36Sopenharmony_ci	case ARM_ENTRY_ASYNC_WATCHPOINT:
93062306a36Sopenharmony_ci		WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n");
93162306a36Sopenharmony_ci		fallthrough;
93262306a36Sopenharmony_ci	case ARM_ENTRY_SYNC_WATCHPOINT:
93362306a36Sopenharmony_ci		watchpoint_handler(addr, fsr, regs);
93462306a36Sopenharmony_ci		break;
93562306a36Sopenharmony_ci	default:
93662306a36Sopenharmony_ci		ret = 1; /* Unhandled fault. */
93762306a36Sopenharmony_ci	}
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	preempt_enable();
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	return ret;
94262306a36Sopenharmony_ci}
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci#ifdef CONFIG_ARM_ERRATA_764319
94562306a36Sopenharmony_cistatic int oslsr_fault;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_cistatic int debug_oslsr_trap(struct pt_regs *regs, unsigned int instr)
94862306a36Sopenharmony_ci{
94962306a36Sopenharmony_ci	oslsr_fault = 1;
95062306a36Sopenharmony_ci	instruction_pointer(regs) += 4;
95162306a36Sopenharmony_ci	return 0;
95262306a36Sopenharmony_ci}
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_cistatic struct undef_hook debug_oslsr_hook = {
95562306a36Sopenharmony_ci	.instr_mask  = 0xffffffff,
95662306a36Sopenharmony_ci	.instr_val = 0xee115e91,
95762306a36Sopenharmony_ci	.fn = debug_oslsr_trap,
95862306a36Sopenharmony_ci};
95962306a36Sopenharmony_ci#endif
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci/*
96262306a36Sopenharmony_ci * One-time initialisation.
96362306a36Sopenharmony_ci */
96462306a36Sopenharmony_cistatic cpumask_t debug_err_mask;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_cistatic int debug_reg_trap(struct pt_regs *regs, unsigned int instr)
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	int cpu = smp_processor_id();
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	pr_warn("Debug register access (0x%x) caused undefined instruction on CPU %d\n",
97162306a36Sopenharmony_ci		instr, cpu);
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	/* Set the error flag for this CPU and skip the faulting instruction. */
97462306a36Sopenharmony_ci	cpumask_set_cpu(cpu, &debug_err_mask);
97562306a36Sopenharmony_ci	instruction_pointer(regs) += 4;
97662306a36Sopenharmony_ci	return 0;
97762306a36Sopenharmony_ci}
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_cistatic struct undef_hook debug_reg_hook = {
98062306a36Sopenharmony_ci	.instr_mask	= 0x0fe80f10,
98162306a36Sopenharmony_ci	.instr_val	= 0x0e000e10,
98262306a36Sopenharmony_ci	.fn		= debug_reg_trap,
98362306a36Sopenharmony_ci};
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci/* Does this core support OS Save and Restore? */
98662306a36Sopenharmony_cistatic bool core_has_os_save_restore(void)
98762306a36Sopenharmony_ci{
98862306a36Sopenharmony_ci	u32 oslsr;
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	switch (get_debug_arch()) {
99162306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V7_1:
99262306a36Sopenharmony_ci		return true;
99362306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V7_ECP14:
99462306a36Sopenharmony_ci#ifdef CONFIG_ARM_ERRATA_764319
99562306a36Sopenharmony_ci		oslsr_fault = 0;
99662306a36Sopenharmony_ci		register_undef_hook(&debug_oslsr_hook);
99762306a36Sopenharmony_ci		ARM_DBG_READ(c1, c1, 4, oslsr);
99862306a36Sopenharmony_ci		unregister_undef_hook(&debug_oslsr_hook);
99962306a36Sopenharmony_ci		if (oslsr_fault)
100062306a36Sopenharmony_ci			return false;
100162306a36Sopenharmony_ci#else
100262306a36Sopenharmony_ci		ARM_DBG_READ(c1, c1, 4, oslsr);
100362306a36Sopenharmony_ci#endif
100462306a36Sopenharmony_ci		if (oslsr & ARM_OSLSR_OSLM0)
100562306a36Sopenharmony_ci			return true;
100662306a36Sopenharmony_ci		fallthrough;
100762306a36Sopenharmony_ci	default:
100862306a36Sopenharmony_ci		return false;
100962306a36Sopenharmony_ci	}
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_cistatic void reset_ctrl_regs(unsigned int cpu)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	int i, raw_num_brps, err = 0;
101562306a36Sopenharmony_ci	u32 val;
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci	/*
101862306a36Sopenharmony_ci	 * v7 debug contains save and restore registers so that debug state
101962306a36Sopenharmony_ci	 * can be maintained across low-power modes without leaving the debug
102062306a36Sopenharmony_ci	 * logic powered up. It is IMPLEMENTATION DEFINED whether we can access
102162306a36Sopenharmony_ci	 * the debug registers out of reset, so we must unlock the OS Lock
102262306a36Sopenharmony_ci	 * Access Register to avoid taking undefined instruction exceptions
102362306a36Sopenharmony_ci	 * later on.
102462306a36Sopenharmony_ci	 */
102562306a36Sopenharmony_ci	switch (debug_arch) {
102662306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V6:
102762306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V6_1:
102862306a36Sopenharmony_ci		/* ARMv6 cores clear the registers out of reset. */
102962306a36Sopenharmony_ci		goto out_mdbgen;
103062306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V7_ECP14:
103162306a36Sopenharmony_ci		/*
103262306a36Sopenharmony_ci		 * Ensure sticky power-down is clear (i.e. debug logic is
103362306a36Sopenharmony_ci		 * powered up).
103462306a36Sopenharmony_ci		 */
103562306a36Sopenharmony_ci		ARM_DBG_READ(c1, c5, 4, val);
103662306a36Sopenharmony_ci		if ((val & 0x1) == 0)
103762306a36Sopenharmony_ci			err = -EPERM;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci		if (!has_ossr)
104062306a36Sopenharmony_ci			goto clear_vcr;
104162306a36Sopenharmony_ci		break;
104262306a36Sopenharmony_ci	case ARM_DEBUG_ARCH_V7_1:
104362306a36Sopenharmony_ci		/*
104462306a36Sopenharmony_ci		 * Ensure the OS double lock is clear.
104562306a36Sopenharmony_ci		 */
104662306a36Sopenharmony_ci		ARM_DBG_READ(c1, c3, 4, val);
104762306a36Sopenharmony_ci		if ((val & 0x1) == 1)
104862306a36Sopenharmony_ci			err = -EPERM;
104962306a36Sopenharmony_ci		break;
105062306a36Sopenharmony_ci	}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	if (err) {
105362306a36Sopenharmony_ci		pr_warn_once("CPU %d debug is powered down!\n", cpu);
105462306a36Sopenharmony_ci		cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
105562306a36Sopenharmony_ci		return;
105662306a36Sopenharmony_ci	}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	/*
105962306a36Sopenharmony_ci	 * Unconditionally clear the OS lock by writing a value
106062306a36Sopenharmony_ci	 * other than CS_LAR_KEY to the access register.
106162306a36Sopenharmony_ci	 */
106262306a36Sopenharmony_ci	ARM_DBG_WRITE(c1, c0, 4, ~CORESIGHT_UNLOCK);
106362306a36Sopenharmony_ci	isb();
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	/*
106662306a36Sopenharmony_ci	 * Clear any configured vector-catch events before
106762306a36Sopenharmony_ci	 * enabling monitor mode.
106862306a36Sopenharmony_ci	 */
106962306a36Sopenharmony_ciclear_vcr:
107062306a36Sopenharmony_ci	ARM_DBG_WRITE(c0, c7, 0, 0);
107162306a36Sopenharmony_ci	isb();
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
107462306a36Sopenharmony_ci		pr_warn_once("CPU %d failed to disable vector catch\n", cpu);
107562306a36Sopenharmony_ci		return;
107662306a36Sopenharmony_ci	}
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	/*
107962306a36Sopenharmony_ci	 * The control/value register pairs are UNKNOWN out of reset so
108062306a36Sopenharmony_ci	 * clear them to avoid spurious debug events.
108162306a36Sopenharmony_ci	 */
108262306a36Sopenharmony_ci	raw_num_brps = get_num_brp_resources();
108362306a36Sopenharmony_ci	for (i = 0; i < raw_num_brps; ++i) {
108462306a36Sopenharmony_ci		write_wb_reg(ARM_BASE_BCR + i, 0UL);
108562306a36Sopenharmony_ci		write_wb_reg(ARM_BASE_BVR + i, 0UL);
108662306a36Sopenharmony_ci	}
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	for (i = 0; i < core_num_wrps; ++i) {
108962306a36Sopenharmony_ci		write_wb_reg(ARM_BASE_WCR + i, 0UL);
109062306a36Sopenharmony_ci		write_wb_reg(ARM_BASE_WVR + i, 0UL);
109162306a36Sopenharmony_ci	}
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
109462306a36Sopenharmony_ci		pr_warn_once("CPU %d failed to clear debug register pairs\n", cpu);
109562306a36Sopenharmony_ci		return;
109662306a36Sopenharmony_ci	}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci	/*
109962306a36Sopenharmony_ci	 * Have a crack at enabling monitor mode. We don't actually need
110062306a36Sopenharmony_ci	 * it yet, but reporting an error early is useful if it fails.
110162306a36Sopenharmony_ci	 */
110262306a36Sopenharmony_ciout_mdbgen:
110362306a36Sopenharmony_ci	if (enable_monitor_mode())
110462306a36Sopenharmony_ci		cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
110562306a36Sopenharmony_ci}
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_cistatic int dbg_reset_online(unsigned int cpu)
110862306a36Sopenharmony_ci{
110962306a36Sopenharmony_ci	local_irq_disable();
111062306a36Sopenharmony_ci	reset_ctrl_regs(cpu);
111162306a36Sopenharmony_ci	local_irq_enable();
111262306a36Sopenharmony_ci	return 0;
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci#ifdef CONFIG_CPU_PM
111662306a36Sopenharmony_cistatic int dbg_cpu_pm_notify(struct notifier_block *self, unsigned long action,
111762306a36Sopenharmony_ci			     void *v)
111862306a36Sopenharmony_ci{
111962306a36Sopenharmony_ci	if (action == CPU_PM_EXIT)
112062306a36Sopenharmony_ci		reset_ctrl_regs(smp_processor_id());
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci	return NOTIFY_OK;
112362306a36Sopenharmony_ci}
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_cistatic struct notifier_block dbg_cpu_pm_nb = {
112662306a36Sopenharmony_ci	.notifier_call = dbg_cpu_pm_notify,
112762306a36Sopenharmony_ci};
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_cistatic void __init pm_init(void)
113062306a36Sopenharmony_ci{
113162306a36Sopenharmony_ci	cpu_pm_register_notifier(&dbg_cpu_pm_nb);
113262306a36Sopenharmony_ci}
113362306a36Sopenharmony_ci#else
113462306a36Sopenharmony_cistatic inline void pm_init(void)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci}
113762306a36Sopenharmony_ci#endif
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_cistatic int __init arch_hw_breakpoint_init(void)
114062306a36Sopenharmony_ci{
114162306a36Sopenharmony_ci	int ret;
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	debug_arch = get_debug_arch();
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	if (!debug_arch_supported()) {
114662306a36Sopenharmony_ci		pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
114762306a36Sopenharmony_ci		return 0;
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	/*
115162306a36Sopenharmony_ci	 * Scorpion CPUs (at least those in APQ8060) seem to set DBGPRSR.SPD
115262306a36Sopenharmony_ci	 * whenever a WFI is issued, even if the core is not powered down, in
115362306a36Sopenharmony_ci	 * violation of the architecture.  When DBGPRSR.SPD is set, accesses to
115462306a36Sopenharmony_ci	 * breakpoint and watchpoint registers are treated as undefined, so
115562306a36Sopenharmony_ci	 * this results in boot time and runtime failures when these are
115662306a36Sopenharmony_ci	 * accessed and we unexpectedly take a trap.
115762306a36Sopenharmony_ci	 *
115862306a36Sopenharmony_ci	 * It's not clear if/how this can be worked around, so we blacklist
115962306a36Sopenharmony_ci	 * Scorpion CPUs to avoid these issues.
116062306a36Sopenharmony_ci	*/
116162306a36Sopenharmony_ci	if (read_cpuid_part() == ARM_CPU_PART_SCORPION) {
116262306a36Sopenharmony_ci		pr_info("Scorpion CPU detected. Hardware breakpoints and watchpoints disabled\n");
116362306a36Sopenharmony_ci		return 0;
116462306a36Sopenharmony_ci	}
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	has_ossr = core_has_os_save_restore();
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	/* Determine how many BRPs/WRPs are available. */
116962306a36Sopenharmony_ci	core_num_brps = get_num_brps();
117062306a36Sopenharmony_ci	core_num_wrps = get_num_wrps();
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	/*
117362306a36Sopenharmony_ci	 * We need to tread carefully here because DBGSWENABLE may be
117462306a36Sopenharmony_ci	 * driven low on this core and there isn't an architected way to
117562306a36Sopenharmony_ci	 * determine that.
117662306a36Sopenharmony_ci	 */
117762306a36Sopenharmony_ci	cpus_read_lock();
117862306a36Sopenharmony_ci	register_undef_hook(&debug_reg_hook);
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	/*
118162306a36Sopenharmony_ci	 * Register CPU notifier which resets the breakpoint resources. We
118262306a36Sopenharmony_ci	 * assume that a halting debugger will leave the world in a nice state
118362306a36Sopenharmony_ci	 * for us.
118462306a36Sopenharmony_ci	 */
118562306a36Sopenharmony_ci	ret = cpuhp_setup_state_cpuslocked(CPUHP_AP_ONLINE_DYN,
118662306a36Sopenharmony_ci					   "arm/hw_breakpoint:online",
118762306a36Sopenharmony_ci					   dbg_reset_online, NULL);
118862306a36Sopenharmony_ci	unregister_undef_hook(&debug_reg_hook);
118962306a36Sopenharmony_ci	if (WARN_ON(ret < 0) || !cpumask_empty(&debug_err_mask)) {
119062306a36Sopenharmony_ci		core_num_brps = 0;
119162306a36Sopenharmony_ci		core_num_wrps = 0;
119262306a36Sopenharmony_ci		if (ret > 0)
119362306a36Sopenharmony_ci			cpuhp_remove_state_nocalls_cpuslocked(ret);
119462306a36Sopenharmony_ci		cpus_read_unlock();
119562306a36Sopenharmony_ci		return 0;
119662306a36Sopenharmony_ci	}
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	pr_info("found %d " "%s" "breakpoint and %d watchpoint registers.\n",
119962306a36Sopenharmony_ci		core_num_brps, core_has_mismatch_brps() ? "(+1 reserved) " :
120062306a36Sopenharmony_ci		"", core_num_wrps);
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	/* Work out the maximum supported watchpoint length. */
120362306a36Sopenharmony_ci	max_watchpoint_len = get_max_wp_len();
120462306a36Sopenharmony_ci	pr_info("maximum watchpoint size is %u bytes.\n",
120562306a36Sopenharmony_ci			max_watchpoint_len);
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci	/* Register debug fault handler. */
120862306a36Sopenharmony_ci	hook_fault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
120962306a36Sopenharmony_ci			TRAP_HWBKPT, "watchpoint debug exception");
121062306a36Sopenharmony_ci	hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
121162306a36Sopenharmony_ci			TRAP_HWBKPT, "breakpoint debug exception");
121262306a36Sopenharmony_ci	cpus_read_unlock();
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	/* Register PM notifiers. */
121562306a36Sopenharmony_ci	pm_init();
121662306a36Sopenharmony_ci	return 0;
121762306a36Sopenharmony_ci}
121862306a36Sopenharmony_ciarch_initcall(arch_hw_breakpoint_init);
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_civoid hw_breakpoint_pmu_read(struct perf_event *bp)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci}
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci/*
122562306a36Sopenharmony_ci * Dummy function to register with die_notifier.
122662306a36Sopenharmony_ci */
122762306a36Sopenharmony_ciint hw_breakpoint_exceptions_notify(struct notifier_block *unused,
122862306a36Sopenharmony_ci					unsigned long val, void *data)
122962306a36Sopenharmony_ci{
123062306a36Sopenharmony_ci	return NOTIFY_DONE;
123162306a36Sopenharmony_ci}
1232