Hi, it seems the XScale vector table handling code in OpenOCD is only partially implemented: the code to use user-provided vectors is there, but there is no way to set these variables, and also no code that syncs the cached vectors with the RAM contents.
The attached patch adds a "xscale vector_table" command that allows to set the values that are written in the mini-IC (plus documentation updates that describe why this is needed). Using the correct values, I can now start and debug a Linux kernel on my IXP425 board from openocd - this would before crash after "uncompressing kernel", because the cached exception vectors were completely off. This is only tested on big-endian IXP42x, but even if it does not work on other CPUs, it should not break any existing functionality. cu Michael
Index: src/target/xscale.c =================================================================== --- src/target/xscale.c (revision 2606) +++ src/target/xscale.c (working copy) @@ -5,6 +5,9 @@ * Copyright (C) 2007,2008 Ãyvind Harboe * * oyvind.har...@zylin.com * * * + * Copyright (C) 2009 Michael Schwingen * + * mich...@schwingen.org * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -3384,6 +3387,65 @@ } +int xscale_handle_vector_table_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc) +{ + target_t *target = get_current_target(cmd_ctx); + armv4_5_common_t *armv4_5; + xscale_common_t *xscale; + int err = 0; + + if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK) + { + return ERROR_OK; + } + + if (argc == 0) /* print current settings */ + { + int idx; + + command_print(cmd_ctx, "active user-set static vectors:"); + for (idx = 1; idx < 8; idx++) + if (xscale->static_low_vectors_set & (1 << idx)) + command_print(cmd_ctx, "low %d: 0x%x", idx, xscale->static_low_vectors[idx]); + for (idx = 1; idx < 8; idx++) + if (xscale->static_high_vectors_set & (1 << idx)) + command_print(cmd_ctx, "high %d: 0x%x", idx, xscale->static_high_vectors[idx]); + return ERROR_OK; + } + + if (argc != 3) + err = 1; + else + { + int idx; + uint32_t vec; + idx = strtoul(args[1], NULL, 0); + vec = strtoul(args[2], NULL, 0); + + if (idx < 1 || idx >= 8) + err = 1; + + if (!err && strcmp(args[0], "low") == 0) + { + xscale->static_low_vectors_set |= (1<<idx); + xscale->static_low_vectors[idx] = vec; + } + else if (!err && (strcmp(args[0], "high") == 0)) + { + xscale->static_high_vectors_set |= (1<<idx); + xscale->static_high_vectors[idx] = vec; + } + else + err = 1; + } + + if (err) + command_print(cmd_ctx, "usage: xscale vector_table <high|low> <index> <code>"); + + return ERROR_OK; +} + + int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { target_t *target = get_current_target(cmd_ctx); @@ -3692,6 +3754,7 @@ register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache"); register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_vector_catch_command, COMMAND_EXEC, "<mask> of vectors that should be catched"); + register_command(cmd_ctx, xscale_cmd, "vector_table", xscale_handle_vector_table_command, COMMAND_EXEC, "<high|low> <index> <code> set static code for exception handler entry"); register_command(cmd_ctx, xscale_cmd, "trace_buffer", xscale_handle_trace_buffer_command, COMMAND_EXEC, "<enable | disable> ['fill' [n]|'wrap']"); Index: doc/openocd.texi =================================================================== --- doc/openocd.texi (revision 2606) +++ doc/openocd.texi (working copy) @@ -4877,6 +4877,52 @@ @subsection XScale specific commands @cindex XScale +Some notes about the debug implementation on the XScale CPUs: + +The XScale CPU provides a special debug-only mini-instruction cache +(mini-IC) in which exception vectors and target-resident debug handler +code are placed by OpenOCD. In order to get access to the CPU, OpenOCD +must point vector 0 (the reset vector) to the entry of the debug +handler. However, this means that the complete first cacheline in the +mini-IC is marked valid, which makes the CPU fetch all exception +handlers from the mini-IC, ignoring the code in RAM. + +OpenOCD currently does not sync the mini-IC entries with the RAM +contents (which would fail anyway while the target is running), so +the user must provide appropriate values using the @code{xscale +vector_table} command. + +It is recommended to place a pc-relative indirect branch in the vector +table, and put the branch destination somewhere in memory. Doing so +makes sure the code in the vector table stays constant regardless of +code layout in memory: +...@example +_vectors: + ldr pc,[pc,#0x100-8] + ldr pc,[pc,#0x100-8] + ldr pc,[pc,#0x100-8] + ldr pc,[pc,#0x100-8] + ldr pc,[pc,#0x100-8] + ldr pc,[pc,#0x100-8] + ldr pc,[pc,#0x100-8] + ldr pc,[pc,#0x100-8] + .org 0x100 + .long real_reset_vector + .long real_ui_handler + .long real_swi_handler + .long real_pf_abort + .long real_data_abort + .long 0 /* unused */ + .long real_irq_handler + .long real_fiq_handler +...@end example + +The debug handler must be placed somewhere in the address space using +the @code{xscale debug_handler} command. The allowed locations for the +debug handler are either (0x800 - 0x1fef800) or (0xfe000800 - +0xfffff800). The default value is 0xfe000800. + + These commands are available to XScale based CPUs, which are implementations of the ARMv5TE architecture. @@ -4938,6 +4984,33 @@ If the optional parameter is provided, first set the bitmask to that value. @end deffn +The mask bits correspond with bit 16..23 in the DCSR: +...@example +0x01 Trap Reset +0x02 Trap Undefined Instructions +0x04 Trap Software Interrupt +0x08 Trap Prefetch Abort +0x10 Trap Data Abort +0x20 reserved +0x40 Trap IRQ +0x80 Trap FIQ +...@end example + + +...@anchor{xscale vector_table} +...@deffn Command {xscale vector_table} [<low|high> <index> <value>] +...@cindex vector_table + +Set an entry in the mini-IC vector table. There are two tables: one for +low vectors (at 0x00000000), and one for high vectors (0xFFFF0000), each +holding the 8 exception vectors. @var{index} can be 1-7, because vector 0 +points to the debug handler entry and can not be overwritten. +...@var{value} holds the 32-bit opcode that is placed in the mini-IC. + +Without arguments, the current settings are displayed. + +...@end deffn + @section ARMv6 Architecture @cindex ARMv6
_______________________________________________ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development