From a5091276e466b4b9f6d1fb10d0f500082cab303e Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Wed, 19 Apr 2023 20:18:11 +0800 Subject: [PATCH 1/5] riscv: fix & refactor triggers add/delete --- components/riscv/include/riscv/csr.h | 1 + components/riscv/include/riscv/rv_utils.h | 83 ++++++++++++++--------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/components/riscv/include/riscv/csr.h b/components/riscv/include/riscv/csr.h index e5762c9e7e..052633c8d2 100644 --- a/components/riscv/include/riscv/csr.h +++ b/components/riscv/include/riscv/csr.h @@ -155,6 +155,7 @@ extern "C" { #define TDATA1_MATCH (1<<7) #define TDATA1_MATCH_V (0xF) /*R/W,Address match type :0 : Exact byte match 1 : NAPOT range match */ #define TDATA1_MATCH_S (7) +#define TDATA1_HIT_S (20) /* RISC-V CSR macros diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index 44f4b07e0c..521d810b3d 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -132,49 +132,66 @@ FORCE_INLINE_ATTR void rv_utils_set_breakpoint(int bp_num, uint32_t bp_addr) /* The code bellow sets breakpoint which will trigger `Breakpoint` exception * instead transfering control to debugger. */ RV_WRITE_CSR(tselect, bp_num); - RV_SET_CSR(CSR_TCONTROL, TCONTROL_MTE); - RV_SET_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE | TDATA1_EXECUTE); + RV_WRITE_CSR(CSR_TCONTROL, TCONTROL_MTE); + RV_WRITE_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE | TDATA1_EXECUTE); RV_WRITE_CSR(tdata2, bp_addr); } +FORCE_INLINE_ATTR void rv_utils_set_watchpoint(int wp_num, + uint32_t wp_addr, + size_t size, + bool on_read, + bool on_write) +{ + RV_WRITE_CSR(tselect, wp_num); + RV_WRITE_CSR(CSR_TCONTROL, TCONTROL_MPTE | TCONTROL_MTE); + RV_WRITE_CSR(CSR_TDATA1, TDATA1_USER | + TDATA1_MACHINE | + TDATA1_MATCH | + (on_read ? TDATA1_LOAD : 0) | + (on_write ? TDATA1_STORE : 0)); + /* From RISC-V Debug Specification: + * NAPOT (Naturally Aligned Power-Of-Two): + * Matches when the top M bits of any compare value match the top M bits of tdata2. + * M is XLEN − 1 minus the index of the least-significant bit containing 0 in tdata2. + * + * Note: Expectng that size is number power of 2 + * + * Examples for understanding how to calculate NAPOT: + * + * nnnn...nnnn0 2-byte NAPOT range + * nnnn...nnn01 4-byte NAPOT range + * nnnn...nn011 8-byte NAPOT range + * nnnn...n0111 16-byte NAPOT range + * nnnn...01111 32-byte NAPOT range + * * where n are bits from original address + */ + const uint32_t half_size = size >> 1; + uint32_t napot = wp_addr; + napot &= ~half_size; /* set the least-significant bit with zero */ + napot |= half_size - 1; /* fill all bits with ones after least-significant bit */ + RV_WRITE_CSR(tdata2, napot); +} + FORCE_INLINE_ATTR void rv_utils_clear_breakpoint(int bp_num) { RV_WRITE_CSR(tselect, bp_num); - RV_CLEAR_CSR(CSR_TCONTROL, TCONTROL_MTE); - RV_CLEAR_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE | TDATA1_EXECUTE); -} - -FORCE_INLINE_ATTR void rv_utils_set_watchpoint(int wp_num, - uint32_t wp_addr, - size_t size, - bool on_read, - bool on_write) -{ - RV_WRITE_CSR(tselect, wp_num); - RV_SET_CSR(CSR_TCONTROL, TCONTROL_MPTE | TCONTROL_MTE); - RV_SET_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE); - RV_SET_CSR_FIELD(CSR_TDATA1, (long unsigned int) TDATA1_MATCH, 1); - - // add 0 in napot encoding - uint32_t addr_napot; - addr_napot = ((uint32_t) wp_addr) | ((size >> 1) - 1); - if (on_read) { - RV_SET_CSR(CSR_TDATA1, TDATA1_LOAD); - } - if (on_write) { - RV_SET_CSR(CSR_TDATA1, TDATA1_STORE); - } - RV_WRITE_CSR(tdata2, addr_napot); + /* tdata1 is a WARL(write any read legal) register + * We can just write 0 to it + */ + RV_WRITE_CSR(CSR_TDATA1, 0); } FORCE_INLINE_ATTR void rv_utils_clear_watchpoint(int wp_num) { - RV_WRITE_CSR(tselect, wp_num); - RV_CLEAR_CSR(CSR_TCONTROL, TCONTROL_MTE); - RV_CLEAR_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE); - RV_CLEAR_CSR_FIELD(CSR_TDATA1, (long unsigned int) TDATA1_MATCH); - RV_CLEAR_CSR(CSR_TDATA1, TDATA1_MACHINE); - RV_CLEAR_CSR(CSR_TDATA1, TDATA1_LOAD | TDATA1_STORE | TDATA1_EXECUTE); + /* riscv have the same registers for breakpoints and watchpoints */ + rv_utils_clear_breakpoint(wp_num); +} + +FORCE_INLINE_ATTR bool rv_utils_is_trigger_fired(int id) +{ + RV_WRITE_CSR(tselect, id); + return (RV_READ_CSR(tdata1) >> TDATA1_HIT_S) & 1; } // ---------------------- Debugger ------------------------- From b6b8b0bd1f100fce46da14941ceae7d34951d76d Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Wed, 19 Apr 2023 20:19:40 +0800 Subject: [PATCH 2/5] riscv: fix trigger add from trap handlers --- components/riscv/include/riscv/rv_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index 521d810b3d..707c6ae7a9 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -132,7 +132,7 @@ FORCE_INLINE_ATTR void rv_utils_set_breakpoint(int bp_num, uint32_t bp_addr) /* The code bellow sets breakpoint which will trigger `Breakpoint` exception * instead transfering control to debugger. */ RV_WRITE_CSR(tselect, bp_num); - RV_WRITE_CSR(CSR_TCONTROL, TCONTROL_MTE); + RV_WRITE_CSR(CSR_TCONTROL, TCONTROL_MPTE | TCONTROL_MTE); RV_WRITE_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE | TDATA1_EXECUTE); RV_WRITE_CSR(tdata2, bp_addr); } From ff3ca9300a4d4cc6c500cd39607891fe963da7ab Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Thu, 20 Apr 2023 01:37:44 +0800 Subject: [PATCH 3/5] riscv: remove outdated macros --- components/riscv/include/riscv/csr.h | 4 ---- components/riscv/include/riscv/rv_utils.h | 10 +++++----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/components/riscv/include/riscv/csr.h b/components/riscv/include/riscv/csr.h index 052633c8d2..ebbda1d2fe 100644 --- a/components/riscv/include/riscv/csr.h +++ b/components/riscv/include/riscv/csr.h @@ -140,10 +140,6 @@ extern "C" { Trigger Module register fields (Debug specification) ********************************************************/ -/* tcontrol CSRs not recognized by toolchain currently */ -#define CSR_TCONTROL 0x7a5 -#define CSR_TDATA1 0x7a1 - #define TCONTROL_MTE (1<<3) /*R/W, Current M mode trigger enable bit*/ #define TCONTROL_MPTE (1<<7) /*R/W, Previous M mode trigger enable bit*/ diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index 707c6ae7a9..2b0a9a95a1 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -132,8 +132,8 @@ FORCE_INLINE_ATTR void rv_utils_set_breakpoint(int bp_num, uint32_t bp_addr) /* The code bellow sets breakpoint which will trigger `Breakpoint` exception * instead transfering control to debugger. */ RV_WRITE_CSR(tselect, bp_num); - RV_WRITE_CSR(CSR_TCONTROL, TCONTROL_MPTE | TCONTROL_MTE); - RV_WRITE_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE | TDATA1_EXECUTE); + RV_WRITE_CSR(tcontrol, TCONTROL_MPTE | TCONTROL_MTE); + RV_WRITE_CSR(tdata1, TDATA1_USER | TDATA1_MACHINE | TDATA1_EXECUTE); RV_WRITE_CSR(tdata2, bp_addr); } @@ -144,8 +144,8 @@ FORCE_INLINE_ATTR void rv_utils_set_watchpoint(int wp_num, bool on_write) { RV_WRITE_CSR(tselect, wp_num); - RV_WRITE_CSR(CSR_TCONTROL, TCONTROL_MPTE | TCONTROL_MTE); - RV_WRITE_CSR(CSR_TDATA1, TDATA1_USER | + RV_WRITE_CSR(tcontrol, TCONTROL_MPTE | TCONTROL_MTE); + RV_WRITE_CSR(tdata1, TDATA1_USER | TDATA1_MACHINE | TDATA1_MATCH | (on_read ? TDATA1_LOAD : 0) | @@ -179,7 +179,7 @@ FORCE_INLINE_ATTR void rv_utils_clear_breakpoint(int bp_num) /* tdata1 is a WARL(write any read legal) register * We can just write 0 to it */ - RV_WRITE_CSR(CSR_TDATA1, 0); + RV_WRITE_CSR(tdata1, 0); } FORCE_INLINE_ATTR void rv_utils_clear_watchpoint(int wp_num) From eb45eec5dbc7a93d41284ea1064b02b70ad96bfe Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Thu, 16 Nov 2023 10:26:29 +0800 Subject: [PATCH 4/5] change(soc): rename SOC_CPU_WATCHPOINT_SIZE to SOC_CPU_WATCHPOINT_MAX_REGION_SIZE --- components/soc/esp32/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32/include/soc/soc_caps.h | 8 ++++---- components/soc/esp32c2/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32c2/include/soc/soc_caps.h | 8 ++++---- components/soc/esp32c3/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32c3/include/soc/soc_caps.h | 8 ++++---- components/soc/esp32c6/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32c6/include/soc/soc_caps.h | 6 +++--- components/soc/esp32h2/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32h2/include/soc/soc_caps.h | 6 +++--- components/soc/esp32s2/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32s2/include/soc/soc_caps.h | 6 +++--- components/soc/esp32s3/include/soc/Kconfig.soc_caps.in | 2 +- components/soc/esp32s3/include/soc/soc_caps.h | 6 +++--- 14 files changed, 31 insertions(+), 31 deletions(-) diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index a9eba100f3..a2c5772ee6 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -255,7 +255,7 @@ config SOC_CPU_WATCHPOINTS_NUM int default 2 -config SOC_CPU_WATCHPOINT_SIZE +config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE int default 64 diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 9e5ace4640..001ed9f471 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -146,9 +146,9 @@ #define SOC_CPU_INTR_NUM 32 #define SOC_CPU_HAS_FPU 1 -#define SOC_CPU_BREAKPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINT_SIZE 64 // bytes +#define SOC_CPU_BREAKPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 // bytes /*-------------------------- DAC CAPS ----------------------------------------*/ #define SOC_DAC_CHAN_NUM 2 diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index 3fbd0ffb7e..fb5fc3781d 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -195,7 +195,7 @@ config SOC_CPU_WATCHPOINTS_NUM int default 2 -config SOC_CPU_WATCHPOINT_SIZE +config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE hex default 0x80000000 diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index 8752196a22..94e4a0a779 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -92,9 +92,9 @@ #define SOC_CPU_INTR_NUM 32 #define SOC_CPU_HAS_FLEXIBLE_INTC 1 -#define SOC_CPU_BREAKPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINT_SIZE 0x80000000 // bytes +#define SOC_CPU_BREAKPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x80000000 // bytes #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index a0dbdb144e..62642a88c9 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -283,7 +283,7 @@ config SOC_CPU_WATCHPOINTS_NUM int default 8 -config SOC_CPU_WATCHPOINT_SIZE +config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE hex default 0x80000000 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index c60f688b7c..519b022cb8 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -124,9 +124,9 @@ #define SOC_CPU_INTR_NUM 32 #define SOC_CPU_HAS_FLEXIBLE_INTC 1 -#define SOC_CPU_BREAKPOINTS_NUM 8 -#define SOC_CPU_WATCHPOINTS_NUM 8 -#define SOC_CPU_WATCHPOINT_SIZE 0x80000000 // bytes +#define SOC_CPU_BREAKPOINTS_NUM 8 +#define SOC_CPU_WATCHPOINTS_NUM 8 +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x80000000 // bytes /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ /** The maximum length of a Digital Signature in bits. */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 3bd19bcd5a..356eb7ac3c 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -339,7 +339,7 @@ config SOC_CPU_WATCHPOINTS_NUM int default 4 -config SOC_CPU_WATCHPOINT_SIZE +config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE hex default 0x80000000 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 5081a69a4c..283f07ff09 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -138,9 +138,9 @@ #define SOC_CPU_HAS_FLEXIBLE_INTC 1 #define SOC_INT_PLIC_SUPPORTED 1 //riscv platform-level interrupt controller -#define SOC_CPU_BREAKPOINTS_NUM 4 -#define SOC_CPU_WATCHPOINTS_NUM 4 -#define SOC_CPU_WATCHPOINT_SIZE 0x80000000 // bytes +#define SOC_CPU_BREAKPOINTS_NUM 4 +#define SOC_CPU_WATCHPOINTS_NUM 4 +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x80000000 // bytes #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index cc4654abc6..dfaafd809c 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -327,7 +327,7 @@ config SOC_CPU_WATCHPOINTS_NUM int default 4 -config SOC_CPU_WATCHPOINT_SIZE +config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE hex default 0x80000000 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 2b3b27ac2c..9107c6df52 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -136,9 +136,9 @@ #define SOC_CPU_HAS_FLEXIBLE_INTC 1 #define SOC_INT_PLIC_SUPPORTED 1 //riscv platform-level interrupt controller -#define SOC_CPU_BREAKPOINTS_NUM 4 -#define SOC_CPU_WATCHPOINTS_NUM 4 -#define SOC_CPU_WATCHPOINT_SIZE 0x80000000 // bytes +#define SOC_CPU_BREAKPOINTS_NUM 4 +#define SOC_CPU_WATCHPOINTS_NUM 4 +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x80000000 // bytes #define SOC_CPU_HAS_PMA 1 #define SOC_CPU_IDRAM_SPLIT_USING_PMP 1 diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 3857f0efac..d39fdbe123 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -295,7 +295,7 @@ config SOC_CPU_WATCHPOINTS_NUM int default 2 -config SOC_CPU_WATCHPOINT_SIZE +config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE int default 64 diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 00db84c258..7331ca2b7e 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -133,9 +133,9 @@ #define SOC_CPU_CORES_NUM (1U) #define SOC_CPU_INTR_NUM 32 -#define SOC_CPU_BREAKPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINT_SIZE 64 // bytes +#define SOC_CPU_BREAKPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 // bytes /*-------------------------- DAC CAPS ----------------------------------------*/ #define SOC_DAC_CHAN_NUM 2 diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index b572636fb6..30cc237866 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -339,7 +339,7 @@ config SOC_CPU_WATCHPOINTS_NUM int default 2 -config SOC_CPU_WATCHPOINT_SIZE +config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE int default 64 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 746e915698..b79d604a9d 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -127,9 +127,9 @@ #define SOC_CPU_INTR_NUM 32 #define SOC_CPU_HAS_FPU 1 -#define SOC_CPU_BREAKPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINT_SIZE 64 // bytes +#define SOC_CPU_BREAKPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINTS_NUM 2 +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 // bytes /*-------------------------- DIGITAL SIGNATURE CAPS ----------------------------------------*/ /** The maximum length of a Digital Signature in bits. */ From 6b14ca55d58bca3bada67362d3026dd70355bf4e Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Wed, 15 Nov 2023 14:00:09 +0800 Subject: [PATCH 5/5] fix(riscv): supports 1 byte and larger than 64byte range watchpoint setting --- components/esp_hw_support/cpu.c | 16 ++++++++++---- components/esp_hw_support/include/esp_cpu.h | 12 ++++++++--- components/riscv/include/riscv/csr.h | 3 ++- components/riscv/include/riscv/rv_utils.h | 24 +++++++++++---------- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/components/esp_hw_support/cpu.c b/components/esp_hw_support/cpu.c index b9bb784513..81ab19e4a3 100644 --- a/components/esp_hw_support/cpu.c +++ b/components/esp_hw_support/cpu.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -346,11 +346,19 @@ esp_err_t esp_cpu_set_watchpoint(int wp_num, const void *wp_addr, size_t size, e { /* Todo: - - Check that wp_num is in range - Check if the wp_num is already in use */ - // Check if size is 2^n, where n is in [0...6] - if (size < 1 || size > 64 || (size & (size - 1)) != 0) { + if (wp_num < 0 || wp_num >= SOC_CPU_WATCHPOINTS_NUM) { + return ESP_ERR_INVALID_ARG; + } + + // Check that the watched region's start address is naturally aligned to the size of the region + if ((uint32_t)wp_addr % size) { + return ESP_ERR_INVALID_ARG; + } + + // Check if size is 2^n, and size is in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE] + if (size < 1 || size > SOC_CPU_WATCHPOINT_MAX_REGION_SIZE || (size & (size - 1)) != 0) { return ESP_ERR_INVALID_ARG; } bool on_read = (trigger == ESP_CPU_WATCHPOINT_LOAD || trigger == ESP_CPU_WATCHPOINT_ACCESS); diff --git a/components/esp_hw_support/include/esp_cpu.h b/components/esp_hw_support/include/esp_cpu.h index 1d62ebcad6..ae976093e9 100644 --- a/components/esp_hw_support/include/esp_cpu.h +++ b/components/esp_hw_support/include/esp_cpu.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -468,9 +468,15 @@ esp_err_t esp_cpu_clear_breakpoint(int bp_num); * the CPU accesses (according to the trigger type) on a certain memory range. * * @note Overwrites previously set watchpoint with same watchpoint number. + * On RISC-V chips, this API uses method0(Exact matching) and method1(NAPOT matching) according to the + * riscv-debug-spec-0.13 specification for address matching. + * If the watch region size is 1byte, it uses exact matching (method 0). + * If the watch region size is larger than 1byte, it uses NAPOT matching (method 1). This mode requires + * the watching region start address to be aligned to the watching region size. + * * @param wp_num Hardware watchpoint number [0..SOC_CPU_WATCHPOINTS_NUM - 1] - * @param wp_addr Watchpoint's base address - * @param size Size of the region to watch. Must be one of 2^n, with n in [0..6]. + * @param wp_addr Watchpoint's base address, must be naturally aligned to the size of the region + * @param size Size of the region to watch. Must be one of 2^n and in the range of [1 ... SOC_CPU_WATCHPOINT_MAX_REGION_SIZE] * @param trigger Trigger type * @return ESP_ERR_INVALID_ARG on invalid arg, ESP_OK otherwise */ diff --git a/components/riscv/include/riscv/csr.h b/components/riscv/include/riscv/csr.h index ebbda1d2fe..17e1f723e3 100644 --- a/components/riscv/include/riscv/csr.h +++ b/components/riscv/include/riscv/csr.h @@ -148,7 +148,8 @@ extern "C" { #define TDATA1_EXECUTE (1<<2) /*R/W,Fire trigger on instruction fetch address match*/ #define TDATA1_USER (1<<3) /*R/W,allow trigger to be fired in user mode*/ #define TDATA1_MACHINE (1<<6) /*R/W,Allow trigger to be fired while hart is executing in machine mode*/ -#define TDATA1_MATCH (1<<7) +#define TDATA1_MATCH_EXACT (0) +#define TDATA1_MATCH_NAPOT (1<<7) #define TDATA1_MATCH_V (0xF) /*R/W,Address match type :0 : Exact byte match 1 : NAPOT range match */ #define TDATA1_MATCH_S (7) #define TDATA1_HIT_S (20) diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index 2b0a9a95a1..b545edb137 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -147,30 +147,32 @@ FORCE_INLINE_ATTR void rv_utils_set_watchpoint(int wp_num, RV_WRITE_CSR(tcontrol, TCONTROL_MPTE | TCONTROL_MTE); RV_WRITE_CSR(tdata1, TDATA1_USER | TDATA1_MACHINE | - TDATA1_MATCH | + ((size == 1) ? TDATA1_MATCH_EXACT : TDATA1_MATCH_NAPOT) | (on_read ? TDATA1_LOAD : 0) | (on_write ? TDATA1_STORE : 0)); /* From RISC-V Debug Specification: - * NAPOT (Naturally Aligned Power-Of-Two): + * tdata1(mcontrol) match = 0 : Exact byte match + * + * tdata1(mcontrol) match = 1 : NAPOT (Naturally Aligned Power-Of-Two): * Matches when the top M bits of any compare value match the top M bits of tdata2. * M is XLEN − 1 minus the index of the least-significant bit containing 0 in tdata2. + * Note: Expecting that size is number power of 2 (numbers should be in the range of 1 ~ 31) * - * Note: Expectng that size is number power of 2 - * - * Examples for understanding how to calculate NAPOT: + * Examples for understanding how to calculate match pattern to tdata2: * + * nnnn...nnnnn 1-byte Exact byte match * nnnn...nnnn0 2-byte NAPOT range * nnnn...nnn01 4-byte NAPOT range * nnnn...nn011 8-byte NAPOT range * nnnn...n0111 16-byte NAPOT range * nnnn...01111 32-byte NAPOT range + * ... + * n011...11111 2^31 byte NAPOT range * * where n are bits from original address */ - const uint32_t half_size = size >> 1; - uint32_t napot = wp_addr; - napot &= ~half_size; /* set the least-significant bit with zero */ - napot |= half_size - 1; /* fill all bits with ones after least-significant bit */ - RV_WRITE_CSR(tdata2, napot); + uint32_t match_pattern = (wp_addr & ~(size-1)) | ((size-1) >> 1); + + RV_WRITE_CSR(tdata2, match_pattern); } FORCE_INLINE_ATTR void rv_utils_clear_breakpoint(int bp_num)