semihosting: add armv7m semihosting support
authorSpencer Oliver <ntfreak@users.sourceforge.net>
Fri, 26 Feb 2010 23:30:30 +0000 (23:30 +0000)
committerSpencer Oliver <ntfreak@users.sourceforge.net>
Sun, 28 Feb 2010 22:48:44 +0000 (22:48 +0000)
do_semihosting and arm_semihosting now check the core type and
use the generic arm structure.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
src/target/arm_semihosting.c
src/target/armv7m.c
src/target/cortex_m3.c

index 24a4de57cea48652638673da452913a05a148b0d..2f50a4a6591a2e6c8d55214a63752eec10e3f415 100644 (file)
@@ -39,6 +39,9 @@
 
 #include "arm.h"
 #include "armv4_5.h"
 
 #include "arm.h"
 #include "armv4_5.h"
+#include "arm7_9_common.h"
+#include "armv7m.h"
+#include "cortex_m3.h"
 #include "register.h"
 #include "arm_semihosting.h"
 #include <helper/binarybuffer.h>
 #include "register.h"
 #include "arm_semihosting.h"
 #include <helper/binarybuffer.h>
@@ -62,14 +65,19 @@ static int open_modeflags[12] = {
 
 static int do_semihosting(struct target *target)
 {
 
 static int do_semihosting(struct target *target)
 {
-       struct arm *armv4_5 = target_to_arm(target);
-       uint32_t r0 = buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32);
-       uint32_t r1 = buf_get_u32(armv4_5->core_cache->reg_list[1].value, 0, 32);
-       uint32_t lr = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, ARM_MODE_SVC, 14).value, 0, 32);
-       uint32_t spsr = buf_get_u32(armv4_5->spsr->value, 0, 32);;
+       struct arm *arm = target_to_arm(target);
+       uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
+       uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32);
+       uint32_t lr, spsr;
        uint8_t params[16];
        int retval, result;
 
        uint8_t params[16];
        int retval, result;
 
+       if (is_arm7_9(target_to_arm7_9(target)))
+       {
+               lr = buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache, ARM_MODE_SVC, 14).value, 0, 32);
+               spsr = buf_get_u32(arm->spsr->value, 0, 32);;
+       }
+
        /*
         * TODO: lots of security issues are not considered yet, such as:
         * - no validation on target provided file descriptors
        /*
         * TODO: lots of security issues are not considered yet, such as:
         * - no validation on target provided file descriptors
@@ -105,10 +113,10 @@ static int do_semihosting(struct target *target)
                                         * written file */
                                        result = open((char *)fn, open_modeflags[m], 0644);
                                }
                                         * written file */
                                        result = open((char *)fn, open_modeflags[m], 0644);
                                }
-                               armv4_5->semihosting_errno =  errno;
+                               arm->semihosting_errno =  errno;
                        } else {
                                result = -1;
                        } else {
                                result = -1;
-                               armv4_5->semihosting_errno = EINVAL;
+                               arm->semihosting_errno = EINVAL;
                        }
                }
                break;
                        }
                }
                break;
@@ -120,7 +128,7 @@ static int do_semihosting(struct target *target)
                else {
                        int fd = target_buffer_get_u32(target, params+0);
                        result = close(fd);
                else {
                        int fd = target_buffer_get_u32(target, params+0);
                        result = close(fd);
-                       armv4_5->semihosting_errno = errno;
+                       arm->semihosting_errno = errno;
                }
                break;
 
                }
                break;
 
@@ -159,7 +167,7 @@ static int do_semihosting(struct target *target)
                        uint8_t *buf = malloc(l);
                        if (!buf) {
                                result = -1;
                        uint8_t *buf = malloc(l);
                        if (!buf) {
                                result = -1;
-                               armv4_5->semihosting_errno = ENOMEM;
+                               arm->semihosting_errno = ENOMEM;
                        } else {
                                retval = target_read_buffer(target, a, l, buf);
                                if (retval != ERROR_OK) {
                        } else {
                                retval = target_read_buffer(target, a, l, buf);
                                if (retval != ERROR_OK) {
@@ -167,7 +175,7 @@ static int do_semihosting(struct target *target)
                                        return retval;
                                }
                                result = write(fd, buf, l);
                                        return retval;
                                }
                                result = write(fd, buf, l);
-                               armv4_5->semihosting_errno = errno;
+                               arm->semihosting_errno = errno;
                                if (result >= 0)
                                        result = l - result;
                                free(buf);
                                if (result >= 0)
                                        result = l - result;
                                free(buf);
@@ -186,10 +194,10 @@ static int do_semihosting(struct target *target)
                        uint8_t *buf = malloc(l);
                        if (!buf) {
                                result = -1;
                        uint8_t *buf = malloc(l);
                        if (!buf) {
                                result = -1;
-                               armv4_5->semihosting_errno = ENOMEM;
+                               arm->semihosting_errno = ENOMEM;
                        } else {
                                result = read(fd, buf, l);
                        } else {
                                result = read(fd, buf, l);
-                               armv4_5->semihosting_errno = errno;
+                               arm->semihosting_errno = errno;
                                if (result >= 0) {
                                        retval = target_write_buffer(target, a, result, buf);
                                        if (retval != ERROR_OK) {
                                if (result >= 0) {
                                        retval = target_write_buffer(target, a, result, buf);
                                        if (retval != ERROR_OK) {
@@ -229,7 +237,7 @@ static int do_semihosting(struct target *target)
                        int fd = target_buffer_get_u32(target, params+0);
                        off_t pos = target_buffer_get_u32(target, params+4);
                        result = lseek(fd, pos, SEEK_SET);
                        int fd = target_buffer_get_u32(target, params+0);
                        off_t pos = target_buffer_get_u32(target, params+4);
                        result = lseek(fd, pos, SEEK_SET);
-                       armv4_5->semihosting_errno = errno;
+                       arm->semihosting_errno = errno;
                        if (result == pos)
                                result = 0;
                }
                        if (result == pos)
                                result = 0;
                }
@@ -244,7 +252,7 @@ static int do_semihosting(struct target *target)
                        struct stat buf;
                        result = fstat(fd, &buf);
                        if (result == -1) {
                        struct stat buf;
                        result = fstat(fd, &buf);
                        if (result == -1) {
-                               armv4_5->semihosting_errno = errno;
+                               arm->semihosting_errno = errno;
                                result = -1;
                                break;
                        }
                                result = -1;
                                break;
                        }
@@ -266,10 +274,10 @@ static int do_semihosting(struct target *target)
                                        return retval;
                                fn[l] = 0;
                                result = remove((char *)fn);
                                        return retval;
                                fn[l] = 0;
                                result = remove((char *)fn);
-                               armv4_5->semihosting_errno =  errno;
+                               arm->semihosting_errno =  errno;
                        } else {
                                result = -1;
                        } else {
                                result = -1;
-                               armv4_5->semihosting_errno = EINVAL;
+                               arm->semihosting_errno = EINVAL;
                        }
                }
                break;
                        }
                }
                break;
@@ -294,10 +302,10 @@ static int do_semihosting(struct target *target)
                                fn1[l1] = 0;
                                fn2[l2] = 0;
                                result = rename((char *)fn1, (char *)fn2);
                                fn1[l1] = 0;
                                fn2[l2] = 0;
                                result = rename((char *)fn1, (char *)fn2);
-                               armv4_5->semihosting_errno =  errno;
+                               arm->semihosting_errno =  errno;
                        } else {
                                result = -1;
                        } else {
                                result = -1;
-                               armv4_5->semihosting_errno = EINVAL;
+                               arm->semihosting_errno = EINVAL;
                        }
                }
                break;
                        }
                }
                break;
@@ -307,7 +315,7 @@ static int do_semihosting(struct target *target)
                break;
 
        case 0x13:      /* SYS_ERRNO */
                break;
 
        case 0x13:      /* SYS_ERRNO */
-               result = armv4_5->semihosting_errno;
+               result = arm->semihosting_errno;
                break;
 
        case 0x15:      /* SYS_GET_CMDLINE */
                break;
 
        case 0x15:      /* SYS_GET_CMDLINE */
@@ -383,25 +391,37 @@ static int do_semihosting(struct target *target)
                fprintf(stderr, "semihosting: unsupported call %#x\n",
                                (unsigned) r0);
                result = -1;
                fprintf(stderr, "semihosting: unsupported call %#x\n",
                                (unsigned) r0);
                result = -1;
-               armv4_5->semihosting_errno = ENOTSUP;
+               arm->semihosting_errno = ENOTSUP;
        }
 
        /* resume execution to the original mode */
 
        }
 
        /* resume execution to the original mode */
 
-       /* return value in R0 */
-       buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, result);
-       armv4_5->core_cache->reg_list[0].dirty = 1;
-
-       /* LR --> PC */
-       buf_set_u32(armv4_5->pc->value, 0, 32, lr);
-       armv4_5->pc->dirty = 1;
-
-       /* saved PSR --> current PSR */
-       buf_set_u32(armv4_5->cpsr->value, 0, 32, spsr);
-       armv4_5->cpsr->dirty = 1;
-       armv4_5->core_mode = spsr & 0x1f;
-       if (spsr & 0x20)
-               armv4_5->core_state = ARM_STATE_THUMB;
+       if (is_arm7_9(target_to_arm7_9(target)))
+       {
+               /* return value in R0 */
+               buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result);
+               arm->core_cache->reg_list[0].dirty = 1;
+
+               /* LR --> PC */
+               buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, lr);
+               arm->core_cache->reg_list[15].dirty = 1;
+
+               /* saved PSR --> current PSR */
+               buf_set_u32(arm->cpsr->value, 0, 32, spsr);
+               arm->cpsr->dirty = 1;
+               arm->core_mode = spsr & 0x1f;
+               if (spsr & 0x20)
+                       arm->core_state = ARM_STATE_THUMB;
+       }
+       else
+       {
+               /* resume execution, this will be pc+2 to skip over the
+                * bkpt instruction */
+
+               /* return result in R0 */
+               buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result);
+               arm->core_cache->reg_list[0].dirty = 1;
+       }
 
        return target_resume(target, 1, 0, 0, 0);
 }
 
        return target_resume(target, 1, 0, 0, 0);
 }
@@ -425,60 +445,90 @@ int arm_semihosting(struct target *target, int *retval)
        uint32_t pc, lr, spsr;
        struct reg *r;
 
        uint32_t pc, lr, spsr;
        struct reg *r;
 
-       if (!arm->is_semihosting || arm->core_mode != ARM_MODE_SVC)
+       if (!arm->is_semihosting)
                return 0;
 
                return 0;
 
-       /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */
-       r = arm->pc;
-       pc = buf_get_u32(r->value, 0, 32);
-       if (pc != 0x00000008 && pc != 0xffff0008)
-               return 0;
+       if (is_arm7_9(target_to_arm7_9(target)))
+       {
+               if (arm->core_mode != ARM_MODE_SVC)
+                       return 0;
 
 
-       r = arm_reg_current(arm, 14);
-       lr = buf_get_u32(r->value, 0, 32);
+               /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */
+               r = arm->pc;
+               pc = buf_get_u32(r->value, 0, 32);
+               if (pc != 0x00000008 && pc != 0xffff0008)
+                       return 0;
 
 
-       /* Core-specific code should make sure SPSR is retrieved
-        * when the above checks pass...
-        */
-       if (!arm->spsr->valid) {
-               LOG_ERROR("SPSR not valid!");
-               *retval = ERROR_FAIL;
-               return 1;
-       }
+               r = arm_reg_current(arm, 14);
+               lr = buf_get_u32(r->value, 0, 32);
 
 
-       spsr = buf_get_u32(arm->spsr->value, 0, 32);
+               /* Core-specific code should make sure SPSR is retrieved
+                * when the above checks pass...
+                */
+               if (!arm->spsr->valid) {
+                       LOG_ERROR("SPSR not valid!");
+                       *retval = ERROR_FAIL;
+                       return 1;
+               }
 
 
-       /* check instruction that triggered this trap */
-       if (spsr & (1 << 5)) {
-               /* was in Thumb (or ThumbEE) mode */
-               uint8_t insn_buf[2];
-               uint16_t insn;
+               spsr = buf_get_u32(arm->spsr->value, 0, 32);
 
 
-               *retval = target_read_memory(target, lr-2, 2, 1, insn_buf);
-               if (*retval != ERROR_OK)
-                       return 1;
-               insn = target_buffer_get_u16(target, insn_buf);
+               /* check instruction that triggered this trap */
+               if (spsr & (1 << 5)) {
+                       /* was in Thumb (or ThumbEE) mode */
+                       uint8_t insn_buf[2];
+                       uint16_t insn;
+
+                       *retval = target_read_memory(target, lr-2, 2, 1, insn_buf);
+                       if (*retval != ERROR_OK)
+                               return 1;
+                       insn = target_buffer_get_u16(target, insn_buf);
 
 
-               /* SVC 0xab */
-               if (insn != 0xDFAB)
+                       /* SVC 0xab */
+                       if (insn != 0xDFAB)
+                               return 0;
+               } else if (spsr & (1 << 24)) {
+                       /* was in Jazelle mode */
+                       return 0;
+               } else {
+                       /* was in ARM mode */
+                       uint8_t insn_buf[4];
+                       uint32_t insn;
+
+                       *retval = target_read_memory(target, lr-4, 4, 1, insn_buf);
+                       if (*retval != ERROR_OK)
+                               return 1;
+                       insn = target_buffer_get_u32(target, insn_buf);
+
+                       /* SVC 0x123456 */
+                       if (insn != 0xEF123456)
+                               return 0;
+               }
+       }
+       else if (is_armv7m(target_to_armv7m(target)))
+       {
+               uint16_t insn;
+
+               if (target->debug_reason != DBG_REASON_BREAKPOINT)
                        return 0;
                        return 0;
-       } else if (spsr & (1 << 24)) {
-               /* was in Jazelle mode */
-               return 0;
-       } else {
-               /* was in ARM mode */
-               uint8_t insn_buf[4];
-               uint32_t insn;
 
 
-               *retval = target_read_memory(target, lr-4, 4, 1, insn_buf);
+               r = arm->pc;
+               pc = buf_get_u32(r->value, 0, 32);
+
+               pc &= ~1;
+               *retval = target_read_u16(target, pc, &insn);
                if (*retval != ERROR_OK)
                        return 1;
                if (*retval != ERROR_OK)
                        return 1;
-               insn = target_buffer_get_u32(target, insn_buf);
 
 
-               /* SVC 0x123456 */
-               if (insn != 0xEF123456)
+               /* bkpt 0xAB */
+               if (insn != 0xBEAB)
                        return 0;
        }
                        return 0;
        }
+       else
+       {
+               LOG_ERROR("Unsupported semi-hosting Target");
+               return 0;
+       }
 
        *retval = do_semihosting(target);
        return 1;
 
        *retval = do_semihosting(target);
        return 1;
index ec111760d5dd4e6f6914ebcd381b7005a5f68cbf..65e03bf6db724d4d997e41718ea332ce583090b5 100644 (file)
@@ -469,14 +469,15 @@ int armv7m_arch_state(struct target *target)
        sp = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
 
        LOG_USER("target halted due to %s, current mode: %s %s\n"
        sp = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
 
        LOG_USER("target halted due to %s, current mode: %s %s\n"
-               "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32,
+               "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s",
                debug_reason_name(target),
                armv7m_mode_strings[armv7m->core_mode],
                armv7m_exception_string(armv7m->exception_number),
                buf_get_u32(arm->cpsr->value, 0, 32),
                buf_get_u32(arm->pc->value, 0, 32),
                (ctrl & 0x02) ? 'p' : 'm',
                debug_reason_name(target),
                armv7m_mode_strings[armv7m->core_mode],
                armv7m_exception_string(armv7m->exception_number),
                buf_get_u32(arm->cpsr->value, 0, 32),
                buf_get_u32(arm->pc->value, 0, 32),
                (ctrl & 0x02) ? 'p' : 'm',
-               sp);
+               sp,
+               arm->is_semihosting ? ", semihosting" : "");
 
        return ERROR_OK;
 }
 
        return ERROR_OK;
 }
@@ -529,6 +530,12 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target)
        return cache;
 }
 
        return cache;
 }
 
+int armv7m_setup_semihosting(struct target *target, int enable)
+{
+       /* nothing todo for armv7m */
+       return ERROR_OK;
+}
+
 /** Sets up target as a generic ARMv7-M core */
 int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
 {
 /** Sets up target as a generic ARMv7-M core */
 int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
 {
@@ -538,6 +545,7 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
 
        arm->core_type = ARM_MODE_THREAD;
        arm->arch_info = armv7m;
 
        arm->core_type = ARM_MODE_THREAD;
        arm->arch_info = armv7m;
+       arm->setup_semihosting = armv7m_setup_semihosting;
 
        /* FIXME remove v7m-specific r/w core_reg functions;
         * use the generic ARM core support..
 
        /* FIXME remove v7m-specific r/w core_reg functions;
         * use the generic ARM core support..
index 0aa7ac13850dbab6531282b04ded737fd523fe52..aecf371842beb3cfd55c8a67c4041345d0ea9505 100644 (file)
@@ -38,7 +38,7 @@
 #include "arm_disassembler.h"
 #include "register.h"
 #include "arm_opcodes.h"
 #include "arm_disassembler.h"
 #include "register.h"
 #include "arm_opcodes.h"
-
+#include "arm_semihosting.h"
 
 /* NOTE:  most of this should work fine for the Cortex-M1 and
  * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
 
 /* NOTE:  most of this should work fine for the Cortex-M1 and
  * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
@@ -495,6 +495,9 @@ static int cortex_m3_poll(struct target *target)
                        if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
                                return retval;
 
                        if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
                                return retval;
 
+                       if (arm_semihosting(target, &retval) != 0)
+                               return retval;
+
                        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                }
                if (prev_target_state == TARGET_DEBUG_RUNNING)
                        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                }
                if (prev_target_state == TARGET_DEBUG_RUNNING)

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)