target/xtensa: add file-IO support 50/7550/5
authorIan Thompson <ianst@cadence.com>
Fri, 24 Mar 2023 00:30:53 +0000 (17:30 -0700)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 27 May 2023 06:43:59 +0000 (06:43 +0000)
- Manual integration of File-IO support from xt0.2 release
- Verified with applications linked using gdbio LSP
- No new clang static analysis warnings

Signed-off-by: Ian Thompson <ianst@cadence.com>
Change-Id: Iedc5f885b2548097ef4f11ae1a675b5944f5fdf0
Reviewed-on: https://review.openocd.org/c/openocd/+/7550
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/target/xtensa/Makefile.am
src/target/xtensa/xtensa.c
src/target/xtensa/xtensa_chip.c
src/target/xtensa/xtensa_fileio.c [new file with mode: 0644]
src/target/xtensa/xtensa_fileio.h [new file with mode: 0644]

index 94c7c4a85b7263aa01856312e6a0053bd62dc872..22504e78b2427522db4155c39f58784f942f07b3 100644 (file)
@@ -8,4 +8,6 @@ noinst_LTLIBRARIES += %D%/libxtensa.la
        %D%/xtensa_chip.h \
        %D%/xtensa_debug_module.c \
        %D%/xtensa_debug_module.h \
+       %D%/xtensa_fileio.c \
+       %D%/xtensa_fileio.h \
        %D%/xtensa_regs.h
index 5880637f411c751bdc6bb466ee5ff7c96ad4bf7d..431c36a2496aec024c2503b571770fede302701a 100644 (file)
@@ -1544,6 +1544,7 @@ int xtensa_prepare_resume(struct target *target,
                LOG_TARGET_WARNING(target, "target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
+       xtensa->halt_request = false;
 
        if (address && !current) {
                xtensa_reg_set(target, XT_REG_IDX_PC, address);
index c62992f625150a71eafcfb309ef38d10fbc8eaf8..668aa3acc71c06e89c3d09fecf6b300a692faf98 100644 (file)
@@ -15,6 +15,7 @@
 #include <target/arm_adi_v5.h>
 #include <rtos/rtos.h>
 #include "xtensa_chip.h"
+#include "xtensa_fileio.h"
 
 int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
        struct xtensa_debug_module_config *dm_cfg)
@@ -30,7 +31,10 @@ int xtensa_chip_init_arch_info(struct target *target, void *arch_info,
 
 int xtensa_chip_target_init(struct command_context *cmd_ctx, struct target *target)
 {
-       return xtensa_target_init(cmd_ctx, target);
+       int ret = xtensa_target_init(cmd_ctx, target);
+       if (ret != ERROR_OK)
+               return ret;
+       return xtensa_fileio_init(target);
 }
 
 int xtensa_chip_arch_state(struct target *target)
@@ -45,10 +49,12 @@ static int xtensa_chip_poll(struct target *target)
 
        if (old_state != TARGET_HALTED && target->state == TARGET_HALTED) {
                /*Call any event callbacks that are applicable */
-               if (old_state == TARGET_DEBUG_RUNNING)
+               if (old_state == TARGET_DEBUG_RUNNING) {
                        target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
-               else
+               } else {
+                       xtensa_fileio_detect_proc(target);
                        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+               }
        }
 
        return ret;
@@ -193,4 +199,7 @@ struct target_type xtensa_chip_target = {
        .gdb_query_custom = xtensa_gdb_query_custom,
 
        .commands = xtensa_command_handlers,
+
+       .get_gdb_fileio_info = xtensa_get_gdb_fileio_info,
+       .gdb_fileio_end = xtensa_gdb_fileio_end,
 };
diff --git a/src/target/xtensa/xtensa_fileio.c b/src/target/xtensa/xtensa_fileio.c
new file mode 100644 (file)
index 0000000..7628fbe
--- /dev/null
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ *   Xtensa Target File-I/O Support for OpenOCD                            *
+ *   Copyright (C) 2020-2023 Cadence Design Systems, Inc.                  *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xtensa_chip.h"
+#include "xtensa_fileio.h"
+#include "xtensa.h"
+
+#define XTENSA_SYSCALL(x)              XT_INS_BREAK(x, 1, 14)
+#define XTENSA_SYSCALL_SZ              3
+#define XTENSA_SYSCALL_LEN_MAX 255
+
+
+int xtensa_fileio_init(struct target *target)
+{
+       char *idmem = malloc(XTENSA_SYSCALL_LEN_MAX + 1);
+       target->fileio_info = malloc(sizeof(struct gdb_fileio_info));
+       if (!idmem || !target->fileio_info) {
+               LOG_TARGET_ERROR(target, "Out of memory!");
+               free(idmem);
+               free(target->fileio_info);
+               return ERROR_FAIL;
+       }
+       target->fileio_info->identifier = idmem;
+       return ERROR_OK;
+}
+
+/**
+ * Checks for and processes an Xtensa File-IO request.
+ *
+ * Return ERROR_OK if request was found and handled; or
+ * return ERROR_FAIL if no request was detected.
+ */
+int xtensa_fileio_detect_proc(struct target *target)
+{
+       struct xtensa *xtensa = target_to_xtensa(target);
+       int retval;
+
+       xtensa_reg_val_t dbg_cause = xtensa_cause_get(target);
+       if ((dbg_cause & (DEBUGCAUSE_BI | DEBUGCAUSE_BN)) == 0 || xtensa->halt_request)
+               return ERROR_FAIL;
+
+       uint8_t brk_insn_buf[sizeof(uint32_t)] = {0};
+       xtensa_reg_val_t pc = xtensa_reg_get(target, XT_REG_IDX_PC);
+       retval = target_read_memory(target,
+               pc,
+               XTENSA_SYSCALL_SZ,
+               1,
+               (uint8_t *)brk_insn_buf);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Failed to read break instruction!");
+               return ERROR_FAIL;
+       }
+       if (buf_get_u32(brk_insn_buf, 0, 32) != XTENSA_SYSCALL(xtensa))
+               return ERROR_FAIL;
+
+       LOG_TARGET_DEBUG(target, "File-I/O: syscall breakpoint found at 0x%x", pc);
+       xtensa->proc_syscall = true;
+       return ERROR_OK;
+}
+
+int xtensa_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info)
+{
+       /* fill syscall parameters to file-I/O info */
+       if (!fileio_info) {
+               LOG_ERROR("File-I/O data structure uninitialized");
+               return ERROR_FAIL;
+       }
+
+       struct xtensa *xtensa = target_to_xtensa(target);
+       if (!xtensa->proc_syscall)
+               return ERROR_FAIL;
+
+       xtensa_reg_val_t syscall = xtensa_reg_get(target, XTENSA_SYSCALL_OP_REG);
+       xtensa_reg_val_t arg0 = xtensa_reg_get(target, XT_REG_IDX_A6);
+       xtensa_reg_val_t arg1 = xtensa_reg_get(target, XT_REG_IDX_A3);
+       xtensa_reg_val_t arg2 = xtensa_reg_get(target, XT_REG_IDX_A4);
+       xtensa_reg_val_t arg3 = xtensa_reg_get(target, XT_REG_IDX_A5);
+       int retval = ERROR_OK;
+
+       LOG_TARGET_DEBUG(target, "File-I/O: syscall 0x%x 0x%x 0x%x 0x%x 0x%x",
+               syscall, arg0, arg1, arg2, arg3);
+
+       switch (syscall) {
+       case XTENSA_SYSCALL_OPEN:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "open");
+               fileio_info->param_1 = arg0;    // pathp
+               fileio_info->param_2 = arg3;    // len
+               fileio_info->param_3 = arg1;    // flags
+               fileio_info->param_4 = arg2;    // mode
+               break;
+       case XTENSA_SYSCALL_CLOSE:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "close");
+               fileio_info->param_1 = arg0;    // fd
+               break;
+       case XTENSA_SYSCALL_READ:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "read");
+               fileio_info->param_1 = arg0;    // fd
+               fileio_info->param_2 = arg1;    // bufp
+               fileio_info->param_3 = arg2;    // count
+               break;
+       case XTENSA_SYSCALL_WRITE:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "write");
+               fileio_info->param_1 = arg0;    // fd
+               fileio_info->param_2 = arg1;    // bufp
+               fileio_info->param_3 = arg2;    // count
+               break;
+       case XTENSA_SYSCALL_LSEEK:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "lseek");
+               fileio_info->param_1 = arg0;    // fd
+               fileio_info->param_2 = arg1;    // offset
+               fileio_info->param_3 = arg2;    // flags
+               break;
+       case XTENSA_SYSCALL_RENAME:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "rename");
+               fileio_info->param_1 = arg0;    // old pathp
+               fileio_info->param_2 = arg3;    // old len
+               fileio_info->param_3 = arg1;    // new pathp
+               fileio_info->param_4 = arg2;    // new len
+               break;
+       case XTENSA_SYSCALL_UNLINK:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "unlink");
+               fileio_info->param_1 = arg0;    // pathnamep
+               fileio_info->param_2 = arg1;    // len
+               break;
+       case XTENSA_SYSCALL_STAT:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "stat");
+               fileio_info->param_1 = arg0;    // pathnamep
+               fileio_info->param_2 = arg2;    // len
+               fileio_info->param_3 = arg1;    // bufp
+               break;
+       case XTENSA_SYSCALL_FSTAT:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "fstat");
+               fileio_info->param_1 = arg0;    // fd
+               fileio_info->param_2 = arg1;    // bufp
+               break;
+       case XTENSA_SYSCALL_GETTIMEOFDAY:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "gettimeofday");
+               fileio_info->param_1 = arg0;    // tvp
+               fileio_info->param_2 = arg1;    // tzp
+               break;
+       case XTENSA_SYSCALL_ISATTY:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "isatty");
+               fileio_info->param_1 = arg0;    // fd
+               break;
+       case XTENSA_SYSCALL_SYSTEM:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "system");
+               fileio_info->param_1 = arg0;    // cmdp
+               fileio_info->param_2 = arg1;    // len
+               break;
+       default:
+               snprintf(fileio_info->identifier, XTENSA_SYSCALL_LEN_MAX, "unknown");
+               LOG_TARGET_DEBUG(target, "File-I/O: syscall unknown (%d), pc=0x%08X",
+                       syscall, xtensa_reg_get(target, XT_REG_IDX_PC));
+               LOG_INFO("File-I/O: syscall unknown (%d), pc=0x%08X",
+                       syscall, xtensa_reg_get(target, XT_REG_IDX_PC));
+               retval = ERROR_FAIL;
+               break;
+       }
+
+       return retval;
+}
+
+int xtensa_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c)
+{
+       struct xtensa *xtensa = target_to_xtensa(target);
+       if (!xtensa->proc_syscall)
+               return ERROR_FAIL;
+
+       LOG_TARGET_DEBUG(target, "File-I/O: syscall return code: 0x%x, errno: 0x%x , ctrl_c: %s",
+               retcode, fileio_errno, ctrl_c ? "true" : "false");
+
+       /* If interrupt was requested before FIO completion (ERRNO==4), halt and repeat
+        * syscall. Otherwise, set File-I/O Ax and underlying ARx registers, increment PC.
+        * NOTE: sporadic cases of ((ERRNO==4) && !ctrl_c) were observed; most have ctrl_c.
+        */
+       if (fileio_errno != 4) {
+               xtensa_reg_set_deep_relgen(target, XTENSA_SYSCALL_RETVAL_REG, retcode);
+               xtensa_reg_set_deep_relgen(target, XTENSA_SYSCALL_ERRNO_REG, fileio_errno);
+
+               xtensa_reg_val_t pc = xtensa_reg_get(target, XT_REG_IDX_PC);
+               xtensa_reg_set(target, XT_REG_IDX_PC, pc + XTENSA_SYSCALL_SZ);
+       }
+
+       xtensa->proc_syscall = false;
+       xtensa->halt_request = true;
+       return ctrl_c ? ERROR_FAIL : ERROR_OK;
+}
diff --git a/src/target/xtensa/xtensa_fileio.h b/src/target/xtensa/xtensa_fileio.h
new file mode 100644 (file)
index 0000000..5e1af5f
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/***************************************************************************
+ *   Xtensa Target File-I/O Support for OpenOCD                            *
+ *   Copyright (C) 2020-2023 Cadence Design Systems, Inc.                  *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_XTENSA_FILEIO_H
+#define OPENOCD_TARGET_XTENSA_FILEIO_H
+
+#include <target/target.h>
+#include <helper/command.h>
+#include "xtensa.h"
+
+#define XTENSA_SYSCALL_OP_REG          XT_REG_IDX_A2
+#define XTENSA_SYSCALL_RETVAL_REG      XT_REG_IDX_A2
+#define XTENSA_SYSCALL_ERRNO_REG       XT_REG_IDX_A3
+
+#define XTENSA_SYSCALL_OPEN                    (-2)
+#define XTENSA_SYSCALL_CLOSE           (-3)
+#define XTENSA_SYSCALL_READ                    (-4)
+#define XTENSA_SYSCALL_WRITE           (-5)
+#define XTENSA_SYSCALL_LSEEK           (-6)
+#define XTENSA_SYSCALL_RENAME          (-7)
+#define XTENSA_SYSCALL_UNLINK          (-8)
+#define XTENSA_SYSCALL_STAT                    (-9)
+#define XTENSA_SYSCALL_FSTAT           (-10)
+#define XTENSA_SYSCALL_GETTIMEOFDAY    (-11)
+#define XTENSA_SYSCALL_ISATTY          (-12)
+#define XTENSA_SYSCALL_SYSTEM          (-13)
+
+int xtensa_fileio_init(struct target *target);
+int xtensa_fileio_detect_proc(struct target *target);
+int xtensa_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info);
+int xtensa_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c);
+
+#endif /* OPENOCD_TARGET_XTENSA_FILEIO_H */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)