This is an automated email from Gerrit.

"Nguyen Huy Hoang <[email protected]>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9396

-- gerrit

commit 17723a3c6e128cad160806b1d9aa7d9077f6f132
Author: hhoang308 <[email protected]>
Date:   Wed Jan 21 23:53:20 2026 +0700

    target/rtt: support 64-bit targets by using dynamic offsets
    
    The current RTT implementation hardcodes the channel structure size to
    24 bytes and uses fixed offsets for control block members. This conforms
    to the ILP32 (32-bit) layout but fails on LP64 (64-bit) targets such as
    RISC-V 64-bit or AArch64.
    
    On 64-bit targets:
    - Pointers are 8 bytes, increasing the channel struct size to 32 bytes.
    - Member offsets are shifted due to alignment.
    - Critically, the 'read_pos' offset moves from 0x10 (32-bit) to 0x18
      (64-bit).
    
    The existing code writes to offset 0x10 to update the read position. On
    a 64-bit target, offset 0x10 corresponds to 'SizeOfBuffer'. This
    overwrites the buffer size with the read position value, causing memory
    corruption and immediate firmware crashes (boot loops).
    
    This patch introduces a dynamic parameter structure that selects the
    correct offsets and sizes at runtime based on 'target->address_bits'.
    It has been verified on a RISC-V 64-bit target running Zephyr RTOS.
    
    Change-Id: If839cb531042f4e6f135743462be932ac881ab4c
    Signed-off-by: hhoang308 <[email protected]>

diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h
index d84fdb40b3..2f44450f2a 100644
--- a/src/rtt/rtt.h
+++ b/src/rtt/rtt.h
@@ -21,8 +21,11 @@
 /* Control block size in bytes. */
 #define RTT_CB_SIZE            (RTT_CB_MAX_ID_LENGTH + 2 * sizeof(uint32_t))
 
-/* Channel structure size in bytes. */
-#define RTT_CHANNEL_SIZE       24
+/* Channel structure size in bytes (32-bit architecture). */
+#define RTT_CHANNEL_SIZE_32    24
+
+/* Channel structure size in bytes (64-bit architecture). */
+#define RTT_CHANNEL_SIZE_64    32
 
 /* Minimal channel buffer size in bytes. */
 #define RTT_CHANNEL_BUFFER_MIN_SIZE    2
diff --git a/src/target/rtt.c b/src/target/rtt.c
index a8ab24a60b..d1115a6407 100644
--- a/src/target/rtt.c
+++ b/src/target/rtt.c
@@ -18,32 +18,69 @@
 
 #include "target.h"
 
+/** Offsets for RTT control block parameters. */
+struct rtt_control_params {
+    uint32_t channel_size;
+    uint32_t buffer_addr_offset;
+    uint32_t size_offset;
+    uint32_t write_pos_offset;
+    uint32_t read_pos_offset;
+    uint32_t flags_offset;
+};
+
+/** Offsets for 32-bit architecture. */
+static const struct rtt_control_params rtt_params_32 = {
+    .channel_size    = RTT_CHANNEL_SIZE_32,
+    .buffer_addr_offset = 4,
+    .size_offset        = 8,
+    .write_pos_offset   = 12,
+    .read_pos_offset    = 16,
+    .flags_offset       = 20
+};
+
+/** Offsets for 64-bit architecture. */
+static const struct rtt_control_params rtt_params_64 = {
+    .channel_size    = RTT_CHANNEL_SIZE_64,
+    .buffer_addr_offset = 8,
+    .size_offset        = 16,
+    .write_pos_offset   = 20,
+    .read_pos_offset    = 24,
+    .flags_offset       = 28
+};
+
+static const struct rtt_control_params *get_rtt_params(struct target *target)
+{
+    if (target_address_bits(target) == 64)
+        return &rtt_params_64;
+    return &rtt_params_32;
+}
+
 static int read_rtt_channel(struct target *target,
                const struct rtt_control *ctrl, unsigned int channel_index,
                enum rtt_channel_type type, struct rtt_channel *channel)
 {
        int ret;
-       uint8_t buf[RTT_CHANNEL_SIZE];
+       uint8_t buf[RTT_CHANNEL_SIZE_64];
        target_addr_t address;
+       const struct rtt_control_params *params = get_rtt_params(target);
 
-       address = ctrl->address + RTT_CB_SIZE + (channel_index * 
RTT_CHANNEL_SIZE);
+       address = ctrl->address + RTT_CB_SIZE + (channel_index * 
params->channel_size);
 
        if (type == RTT_CHANNEL_TYPE_DOWN)
-               address += ctrl->num_up_channels * RTT_CHANNEL_SIZE;
+               address += ctrl->num_up_channels * params->channel_size;
 
-       ret = target_read_buffer(target, address, RTT_CHANNEL_SIZE, buf);
+       ret = target_read_buffer(target, address, params->channel_size, buf);
 
        if (ret != ERROR_OK)
                return ret;
 
        channel->address = address;
        channel->name_addr = target_buffer_get_u32(target, buf + 0);
-       channel->buffer_addr = target_buffer_get_u32(target, buf + 4);
-       channel->size = target_buffer_get_u32(target, buf + 8);
-       channel->write_pos = target_buffer_get_u32(target, buf + 12);
-       channel->read_pos = target_buffer_get_u32(target, buf + 16);
-       channel->flags = target_buffer_get_u32(target, buf + 20);
-
+       channel->buffer_addr = target_buffer_get_u32(target, buf + 
params->buffer_addr_offset);
+       channel->size = target_buffer_get_u32(target, buf + 
params->size_offset);
+       channel->write_pos = target_buffer_get_u32(target, buf + 
params->write_pos_offset);
+       channel->read_pos = target_buffer_get_u32(target, buf + 
params->read_pos_offset);
+       channel->flags = target_buffer_get_u32(target, buf + 
params->flags_offset);
        return ERROR_OK;
 }
 
@@ -93,6 +130,7 @@ static int write_to_channel(struct target *target,
 {
        int ret;
        uint32_t len;
+       const struct rtt_control_params *params = get_rtt_params(target);
 
        if (!*length)
                return ERROR_OK;
@@ -157,7 +195,7 @@ static int write_to_channel(struct target *target,
                        return ret;
        }
 
-       ret = target_write_u32(target, channel->address + 12,
+       ret = target_write_u32(target, channel->address + 
params->write_pos_offset,
                (channel->write_pos + len) % channel->size);
 
        if (ret != ERROR_OK)
@@ -314,6 +352,7 @@ static int read_from_channel(struct target *target,
 {
        int ret;
        uint32_t len;
+       const struct rtt_control_params *params = get_rtt_params(target);
 
        if (!*length)
                return ERROR_OK;
@@ -349,7 +388,7 @@ static int read_from_channel(struct target *target,
        }
 
        if (len > 0) {
-               ret = target_write_u32(target, channel->address + 16,
+               ret = target_write_u32(target, channel->address + 
params->read_pos_offset,
                        (channel->read_pos + len) % channel->size);
 
                if (ret != ERROR_OK)

-- 

Reply via email to