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

Reply via email to