[PATCH] arm64: hw_breakpoint: warn on invalid breakpoint length

Osama Abdelkader posted 1 patch 1 day, 5 hours ago
There is a newer version of this series
arch/arm64/kernel/hw_breakpoint.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
[PATCH] arm64: hw_breakpoint: warn on invalid breakpoint length
Posted by Osama Abdelkader 1 day, 5 hours ago
Some tools (e.g. perf) incorrectly assume that breakpoints should be
sizeof(long), but this is wrong for AArch64 where breakpoints must be
4 bytes. Add a warning when we silently fix up the parameter so tool
developers can get notified.

This addresses the FIXME comment by adding diagnostic output rather
than breaking existing tools by returning -EINVAL.

Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
---
 arch/arm64/kernel/hw_breakpoint.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
index ab76b36dce82..4d31842e5d91 100644
--- a/arch/arm64/kernel/hw_breakpoint.c
+++ b/arch/arm64/kernel/hw_breakpoint.c
@@ -475,11 +475,13 @@ static int arch_build_bp_info(struct perf_event *bp,
 				return -EINVAL;
 		} else if (hw->ctrl.len != ARM_BREAKPOINT_LEN_4) {
 			/*
-			 * FIXME: Some tools (I'm looking at you perf) assume
-			 *	  that breakpoints should be sizeof(long). This
-			 *	  is nonsense. For now, we fix up the parameter
-			 *	  but we should probably return -EINVAL instead.
+			 * Some tools (e.g. perf) incorrectly assume that
+			 * breakpoints should be sizeof(long). This is wrong
+			 * for AArch64 where breakpoints must be 4 bytes.
+			 * Warn the user and fix up the parameter.
 			 */
+			pr_warn_once("hw_breakpoint: invalid AArch64 breakpoint length %d,
+				fixing to 4 bytes\n", hw->ctrl.len);
 			hw->ctrl.len = ARM_BREAKPOINT_LEN_4;
 		}
 	}
-- 
2.43.0
Re: [PATCH] arm64: hw_breakpoint: warn on invalid breakpoint length
Posted by kernel test robot 16 hours ago
Hi Osama,

kernel test robot noticed the following build errors:

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on arm-perf/for-next/perf linus/master v6.18 next-20251212]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Osama-Abdelkader/arm64-hw_breakpoint-warn-on-invalid-breakpoint-length/20251213-045501
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20251212205230.84606-1-osama.abdelkader%40gmail.com
patch subject: [PATCH] arm64: hw_breakpoint: warn on invalid breakpoint length
config: arm64-allmodconfig (https://download.01.org/0day-ci/archive/20251213/202512131730.89TvJc2D-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251213/202512131730.89TvJc2D-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512131730.89TvJc2D-lkp@intel.com/

All errors (new ones prefixed by >>):

   arch/arm64/kernel/hw_breakpoint.c:483:17: warning: missing terminating '"' character [-Winvalid-pp-token]
     483 |                         pr_warn_once("hw_breakpoint: invalid AArch64 breakpoint length %d,
         |                                      ^
   arch/arm64/kernel/hw_breakpoint.c:484:24: warning: missing terminating '"' character [-Winvalid-pp-token]
     484 |                                 fixing to 4 bytes\n", hw->ctrl.len);
         |                                                    ^
>> arch/arm64/kernel/hw_breakpoint.c:483:4: error: unterminated function-like macro invocation
     483 |                         pr_warn_once("hw_breakpoint: invalid AArch64 breakpoint length %d,
         |                         ^
   include/linux/printk.h:669:9: note: macro 'pr_warn_once' defined here
     669 | #define pr_warn_once(fmt, ...)                                  \
         |         ^
>> arch/arm64/kernel/hw_breakpoint.c:1014:2: error: expected '}'
    1014 | }
         |  ^
   arch/arm64/kernel/hw_breakpoint.c:476:52: note: to match this '{'
     476 |                 } else if (hw->ctrl.len != ARM_BREAKPOINT_LEN_4) {
         |                                                                  ^
>> arch/arm64/kernel/hw_breakpoint.c:1014:2: error: expected '}'
    1014 | }
         |  ^
   arch/arm64/kernel/hw_breakpoint.c:471:47: note: to match this '{'
     471 |         if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
         |                                                      ^
>> arch/arm64/kernel/hw_breakpoint.c:1014:2: error: expected '}'
    1014 | }
         |  ^
   arch/arm64/kernel/hw_breakpoint.c:417:1: note: to match this '{'
     417 | {
         | ^
   2 warnings and 4 errors generated.


vim +483 arch/arm64/kernel/hw_breakpoint.c

   410	
   411	/*
   412	 * Construct an arch_hw_breakpoint from a perf_event.
   413	 */
   414	static int arch_build_bp_info(struct perf_event *bp,
   415				      const struct perf_event_attr *attr,
   416				      struct arch_hw_breakpoint *hw)
   417	{
   418		/* Type */
   419		switch (attr->bp_type) {
   420		case HW_BREAKPOINT_X:
   421			hw->ctrl.type = ARM_BREAKPOINT_EXECUTE;
   422			break;
   423		case HW_BREAKPOINT_R:
   424			hw->ctrl.type = ARM_BREAKPOINT_LOAD;
   425			break;
   426		case HW_BREAKPOINT_W:
   427			hw->ctrl.type = ARM_BREAKPOINT_STORE;
   428			break;
   429		case HW_BREAKPOINT_RW:
   430			hw->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
   431			break;
   432		default:
   433			return -EINVAL;
   434		}
   435	
   436		/* Len */
   437		switch (attr->bp_len) {
   438		case HW_BREAKPOINT_LEN_1:
   439			hw->ctrl.len = ARM_BREAKPOINT_LEN_1;
   440			break;
   441		case HW_BREAKPOINT_LEN_2:
   442			hw->ctrl.len = ARM_BREAKPOINT_LEN_2;
   443			break;
   444		case HW_BREAKPOINT_LEN_3:
   445			hw->ctrl.len = ARM_BREAKPOINT_LEN_3;
   446			break;
   447		case HW_BREAKPOINT_LEN_4:
   448			hw->ctrl.len = ARM_BREAKPOINT_LEN_4;
   449			break;
   450		case HW_BREAKPOINT_LEN_5:
   451			hw->ctrl.len = ARM_BREAKPOINT_LEN_5;
   452			break;
   453		case HW_BREAKPOINT_LEN_6:
   454			hw->ctrl.len = ARM_BREAKPOINT_LEN_6;
   455			break;
   456		case HW_BREAKPOINT_LEN_7:
   457			hw->ctrl.len = ARM_BREAKPOINT_LEN_7;
   458			break;
   459		case HW_BREAKPOINT_LEN_8:
   460			hw->ctrl.len = ARM_BREAKPOINT_LEN_8;
   461			break;
   462		default:
   463			return -EINVAL;
   464		}
   465	
   466		/*
   467		 * On AArch64, we only permit breakpoints of length 4, whereas
   468		 * AArch32 also requires breakpoints of length 2 for Thumb.
   469		 * Watchpoints can be of length 1, 2, 4 or 8 bytes.
   470		 */
   471		if (hw->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
   472			if (is_compat_bp(bp)) {
   473				if (hw->ctrl.len != ARM_BREAKPOINT_LEN_2 &&
   474				    hw->ctrl.len != ARM_BREAKPOINT_LEN_4)
   475					return -EINVAL;
   476			} else if (hw->ctrl.len != ARM_BREAKPOINT_LEN_4) {
   477				/*
   478				 * Some tools (e.g. perf) incorrectly assume that
   479				 * breakpoints should be sizeof(long). This is wrong
   480				 * for AArch64 where breakpoints must be 4 bytes.
   481				 * Warn the user and fix up the parameter.
   482				 */
 > 483				pr_warn_once("hw_breakpoint: invalid AArch64 breakpoint length %d,
 > 484					fixing to 4 bytes\n", hw->ctrl.len);
   485				hw->ctrl.len = ARM_BREAKPOINT_LEN_4;
   486			}
   487		}
   488	
   489		/* Address */
   490		hw->address = attr->bp_addr;
   491	
   492		/*
   493		 * Privilege
   494		 * Note that we disallow combined EL0/EL1 breakpoints because
   495		 * that would complicate the stepping code.
   496		 */
   497		if (arch_check_bp_in_kernelspace(hw))
   498			hw->ctrl.privilege = AARCH64_BREAKPOINT_EL1;
   499		else
   500			hw->ctrl.privilege = AARCH64_BREAKPOINT_EL0;
   501	
   502		/* Enabled? */
   503		hw->ctrl.enabled = !attr->disabled;
   504	
   505		return 0;
   506	}
   507	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki