[PATCH v2 0/6] LoongArch: Fix perf hardware breakpoints

Tiezhu Yang posted 6 patches 2 weeks, 3 days ago
There is a newer version of this series
arch/loongarch/include/asm/hw_breakpoint.h |  4 +-
arch/loongarch/include/asm/loongarch.h     |  7 +++-
arch/loongarch/kernel/hw_breakpoint.c      | 43 ++++++++++++++++------
arch/loongarch/kernel/traps.c              | 12 +++---
4 files changed, 46 insertions(+), 20 deletions(-)
[PATCH v2 0/6] LoongArch: Fix perf hardware breakpoints
Posted by Tiezhu Yang 2 weeks, 3 days ago
v2: Use single variable "need_sigtrap" to send SIGTRAP in do_watch().

This series addresses severe functional degradations in standard
perf_event usage, including initialization failures and one-shot
triggering limitations.

All fixes have been verified with user-space reproducers on real
hardware and align with the LoongArch Reference Manual.

Here is a user-space reproducer demonstrating that standard perf
hardware breakpoints can now reliably monitor 10,000 hits without
a single event leakage or subsystem lockup.

(1) Test program (perf-hw-breakpoint.c):

  #include <stdint.h>
  #include <stdio.h>
  #include <sys/ioctl.h>
  #include <sys/syscall.h>
  #include <unistd.h>
  #include <linux/hw_breakpoint.h>
  #include <linux/perf_event.h>

  #ifndef noinline
  #define noinline __attribute__((noinline))
  #endif

  static noinline void test_function(const uint8_t *data)
  {
	asm volatile("" :: "r"(data[0]) : "memory");
  }

  int main(void)
  {
	int fd, ret, i;
	size_t count;
	uint8_t data[] = "TEST DATA";
	struct perf_event_attr attr = {0};

	attr.type = PERF_TYPE_BREAKPOINT;
	attr.size = sizeof(struct perf_event_attr);
	attr.bp_type = HW_BREAKPOINT_RW;
	attr.bp_addr = (uintptr_t)data;
	attr.bp_len  = HW_BREAKPOINT_LEN_1;
	attr.exclude_kernel = 1;
	attr.exclude_hv = 1;
	attr.disabled = 1;

	fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
	ioctl(fd, PERF_EVENT_IOC_RESET, 0);
	ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);

	for (i = 0; i < 10000; i++)
		test_function(data);

	ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
	read(fd, &count, sizeof(size_t));

	printf("perf count = %zu\n", count);

	close(fd);
	return 0;
  }

(2) Test steps:

  $ gcc perf-hw-breakpoint.c -o perf-hw-breakpoint
  $ ./perf-hw-breakpoint

(3) Test results:

Without this series:

  perf count = 0

With this series:

  perf count = 10000

Tiezhu Yang (6):
  LoongArch: Fix bitmask corruption in update_bp_registers()
  LoongArch: Remove redundant call in update_bp_registers()
  LoongArch: Fix architectural naming typo for CSR_FWPS_SKIP
  LoongArch: Only send SIGTRAP signal if necessary in do_watch()
  LoongArch: Fix perf hardware breakpoint failure via installation
  LoongArch: Fix one-shot limitation for perf hardware breakpoints

 arch/loongarch/include/asm/hw_breakpoint.h |  4 +-
 arch/loongarch/include/asm/loongarch.h     |  7 +++-
 arch/loongarch/kernel/hw_breakpoint.c      | 43 ++++++++++++++++------
 arch/loongarch/kernel/traps.c              | 12 +++---
 4 files changed, 46 insertions(+), 20 deletions(-)

-- 
2.42.0
Re: [PATCH v2 0/6] LoongArch: Fix perf hardware breakpoints
Posted by WANG Rui 1 week, 2 days ago
Hi Tiezhu,

On Tue, Sep 8, 2026 at 3:58 PM Tiezhu Yang <yangtiezhu@loongson.cn> wrote:
>
> v2: Use single variable "need_sigtrap" to send SIGTRAP in do_watch().
>
> This series addresses severe functional degradations in standard
> perf_event usage, including initialization failures and one-shot
> triggering limitations.
>
> All fixes have been verified with user-space reproducers on real
> hardware and align with the LoongArch Reference Manual.
>
> Here is a user-space reproducer demonstrating that standard perf
> hardware breakpoints can now reliably monitor 10,000 hits without
> a single event leakage or subsystem lockup.
>
> (1) Test program (perf-hw-breakpoint.c):
>
>   #include <stdint.h>
>   #include <stdio.h>
>   #include <sys/ioctl.h>
>   #include <sys/syscall.h>
>   #include <unistd.h>
>   #include <linux/hw_breakpoint.h>
>   #include <linux/perf_event.h>
>
>   #ifndef noinline
>   #define noinline __attribute__((noinline))
>   #endif
>
>   static noinline void test_function(const uint8_t *data)
>   {
>         asm volatile("" :: "r"(data[0]) : "memory");
>   }
>
>   int main(void)
>   {
>         int fd, ret, i;
>         size_t count;
>         uint8_t data[] = "TEST DATA";
>         struct perf_event_attr attr = {0};
>
>         attr.type = PERF_TYPE_BREAKPOINT;
>         attr.size = sizeof(struct perf_event_attr);
>         attr.bp_type = HW_BREAKPOINT_RW;
>         attr.bp_addr = (uintptr_t)data;
>         attr.bp_len  = HW_BREAKPOINT_LEN_1;
>         attr.exclude_kernel = 1;
>         attr.exclude_hv = 1;
>         attr.disabled = 1;
>
>         fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
>         ioctl(fd, PERF_EVENT_IOC_RESET, 0);
>         ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
>
>         for (i = 0; i < 10000; i++)
>                 test_function(data);
>
>         ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
>         read(fd, &count, sizeof(size_t));
>
>         printf("perf count = %zu\n", count);
>
>         close(fd);
>         return 0;
>   }
>
> (2) Test steps:
>
>   $ gcc perf-hw-breakpoint.c -o perf-hw-breakpoint
>   $ ./perf-hw-breakpoint
>
> (3) Test results:
>
> Without this series:
>
>   perf count = 0
>
> With this series:
>
>   perf count = 10000
>
> Tiezhu Yang (6):
>   LoongArch: Fix bitmask corruption in update_bp_registers()
>   LoongArch: Remove redundant call in update_bp_registers()
>   LoongArch: Fix architectural naming typo for CSR_FWPS_SKIP
>   LoongArch: Only send SIGTRAP signal if necessary in do_watch()
>   LoongArch: Fix perf hardware breakpoint failure via installation
>   LoongArch: Fix one-shot limitation for perf hardware breakpoints

Thanks! Without these patches, perf-event tests always fail; with
them, they fail intermittently.

Reproduce with:
1. git clone https://github.com/jimblandy/perf-event && cd perf-event
2. cargo test -r # or --test breakpoint

Best,
Rui

>
>  arch/loongarch/include/asm/hw_breakpoint.h |  4 +-
>  arch/loongarch/include/asm/loongarch.h     |  7 +++-
>  arch/loongarch/kernel/hw_breakpoint.c      | 43 ++++++++++++++++------
>  arch/loongarch/kernel/traps.c              | 12 +++---
>  4 files changed, 46 insertions(+), 20 deletions(-)
>
> --
> 2.42.0
>
>