Skip to content

Commit

Permalink
Merge branch 'bugfix/fix_onebyte_watchpoint_setting_v5.1' into 'relea…
Browse files Browse the repository at this point in the history
…se/v5.1'

fix(riscv): supports 1 byte and larger than 64byte range watchpoint setting (v5.1)

See merge request espressif/esp-idf!27215
  • Loading branch information
jack0c committed Nov 20, 2023
2 parents ea081e0 + 6b14ca5 commit 5719d88
Show file tree
Hide file tree
Showing 18 changed files with 106 additions and 75 deletions.
16 changes: 12 additions & 4 deletions 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
*/
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 9 additions & 3 deletions 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
*/
Expand Down Expand Up @@ -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
*/
Expand Down
8 changes: 3 additions & 5 deletions components/riscv/include/riscv/csr.h
Expand Up @@ -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*/

Expand All @@ -152,9 +148,11 @@ 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)


/* RISC-V CSR macros
Expand Down
83 changes: 51 additions & 32 deletions 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
*/
Expand Down Expand Up @@ -132,49 +132,68 @@ 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(tcontrol, TCONTROL_MPTE | TCONTROL_MTE);
RV_WRITE_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(tcontrol, TCONTROL_MPTE | TCONTROL_MTE);
RV_WRITE_CSR(tdata1, TDATA1_USER |
TDATA1_MACHINE |
((size == 1) ? TDATA1_MATCH_EXACT : TDATA1_MATCH_NAPOT) |
(on_read ? TDATA1_LOAD : 0) |
(on_write ? TDATA1_STORE : 0));
/* From RISC-V Debug Specification:
* 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)
*
* 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
*/
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)
{
RV_WRITE_CSR(tselect, bp_num);
RV_CLEAR_CSR(CSR_TCONTROL, TCONTROL_MTE);
RV_CLEAR_CSR(CSR_TDATA1, TDATA1_USER | TDATA1_MACHINE | TDATA1_EXECUTE);
/* tdata1 is a WARL(write any read legal) register
* We can just write 0 to it
*/
RV_WRITE_CSR(tdata1, 0);
}

FORCE_INLINE_ATTR void rv_utils_set_watchpoint(int wp_num,
uint32_t wp_addr,
size_t size,
bool on_read,
bool on_write)
FORCE_INLINE_ATTR void rv_utils_clear_watchpoint(int wp_num)
{
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);
/* riscv have the same registers for breakpoints and watchpoints */
rv_utils_clear_breakpoint(wp_num);
}

FORCE_INLINE_ATTR void rv_utils_clear_watchpoint(int wp_num)
FORCE_INLINE_ATTR bool rv_utils_is_trigger_fired(int id)
{
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);
RV_WRITE_CSR(tselect, id);
return (RV_READ_CSR(tdata1) >> TDATA1_HIT_S) & 1;
}

// ---------------------- Debugger -------------------------
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32/include/soc/Kconfig.soc_caps.in
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions 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
*/
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32c2/include/soc/Kconfig.soc_caps.in
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions 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
*/
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32c3/include/soc/Kconfig.soc_caps.in
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions 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
*/
Expand Down Expand Up @@ -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. */
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32c6/include/soc/Kconfig.soc_caps.in
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions components/soc/esp32c6/include/soc/soc_caps.h
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32h2/include/soc/Kconfig.soc_caps.in
Expand Up @@ -335,7 +335,7 @@ config SOC_CPU_WATCHPOINTS_NUM
int
default 4

config SOC_CPU_WATCHPOINT_SIZE
config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE
hex
default 0x80000000

Expand Down
6 changes: 3 additions & 3 deletions components/soc/esp32h2/include/soc/soc_caps.h
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32s2/include/soc/Kconfig.soc_caps.in
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions components/soc/esp32s2/include/soc/soc_caps.h
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion components/soc/esp32s3/include/soc/Kconfig.soc_caps.in
Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions components/soc/esp32s3/include/soc/soc_caps.h
Expand Up @@ -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. */
Expand Down

0 comments on commit 5719d88

Please sign in to comment.