diff mbox

[U-Boot,1/8] xtensa: add support for the xtensa processor architecture [1/2]

Message ID 1467992526-13417-2-git-send-email-jcmvbkbc@gmail.com
State Changes Requested
Delegated to: Tom Rini
Headers show

Commit Message

Max Filippov July 8, 2016, 3:41 p.m. UTC
From: Chris Zankel <chris@zankel.net>

The Xtensa processor architecture is a configurable, extensible,
and synthesizable 32-bit RISC processor core provided by Cadence.

This is the first part of the basic architecture port with changes to
common files. The 'arch/xtensa' directory, and boards and additional
drivers will be in separate commits.

Signed-off-by: Chris Zankel <chris@zankel.net>
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
 MAINTAINERS                 |   5 +++
 MAKEALL                     |   6 +++
 Makefile                    |  10 ++++-
 cmd/bdinfo.c                |  22 ++++++++++
 common/board_f.c            |   7 ++--
 common/image.c              |   1 +
 doc/README.xtensa           | 100 ++++++++++++++++++++++++++++++++++++++++++++
 examples/standalone/stubs.c |  47 +++++++++++++++++++++
 include/image.h             |   1 +
 include/linux/stat.h        |   4 +-
 10 files changed, 197 insertions(+), 6 deletions(-)
 create mode 100644 doc/README.xtensa

Comments

Simon Glass July 12, 2016, 9:56 p.m. UTC | #1
Hi Max,

On 8 July 2016 at 09:41, Max Filippov <jcmvbkbc@gmail.com> wrote:
> From: Chris Zankel <chris@zankel.net>
>
> The Xtensa processor architecture is a configurable, extensible,
> and synthesizable 32-bit RISC processor core provided by Cadence.
>
> This is the first part of the basic architecture port with changes to
> common files. The 'arch/xtensa' directory, and boards and additional
> drivers will be in separate commits.
>
> Signed-off-by: Chris Zankel <chris@zankel.net>
> Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> ---
>  MAINTAINERS                 |   5 +++
>  MAKEALL                     |   6 +++
>  Makefile                    |  10 ++++-
>  cmd/bdinfo.c                |  22 ++++++++++
>  common/board_f.c            |   7 ++--
>  common/image.c              |   1 +
>  doc/README.xtensa           | 100 ++++++++++++++++++++++++++++++++++++++++++++
>  examples/standalone/stubs.c |  47 +++++++++++++++++++++
>  include/image.h             |   1 +
>  include/linux/stat.h        |   4 +-
>  10 files changed, 197 insertions(+), 6 deletions(-)
>  create mode 100644 doc/README.xtensa

Reviewed-by: Simon Glass <sjg@chromium.org>

nits below

>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1db8243..24afa88 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -453,6 +453,11 @@ S: Maintained
>  T:     git git://git.denx.de/u-boot-x86.git
>  F:     arch/x86/
>
> +XTENSA
> +M:     Max Filippov <jcmvbkbc@gmail.com>
> +S:     Maintained
> +F:     arch/xtensa/
> +
>  THE REST
>  M:     Tom Rini <trini@konsulko.com>
>  L:     u-boot@lists.denx.de
> diff --git a/MAKEALL b/MAKEALL
> index 7e42f10..e669aa9 100755
> --- a/MAKEALL
> +++ b/MAKEALL

This is deprecated and will be removed soon, so you don't need to
update it. See buildman.

> @@ -497,6 +497,12 @@ LIST_nds32="$(targets_by_arch nds32)"
>
>  LIST_arc="$(targets_by_arch arc)"
>
> +#########################################################################
> +## Xtensa Systems
> +#########################################################################
> +
> +LIST_xtensa="$(targets_by_arch xtensa)"
> +
>  #-----------------------------------------------------------------------
>
>  get_target_location() {
> diff --git a/Makefile b/Makefile
> index 09a18e1..083af95 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -556,6 +556,14 @@ else
>  include/config/auto.conf: ;
>  endif # $(dot-config)
>
> +#
> +# Xtensa linker script cannot be preprocessed with -ansi because of
> +# preprocessor operations on strings that don't make C identifiers.
> +#
> +ifeq ($(CONFIG_XTENSA),)
> +LDPPFLAGS      += -ansi
> +endif
> +
>  ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
>  KBUILD_CFLAGS  += -Os
>  else
> @@ -1310,7 +1318,7 @@ $(timestamp_h): $(srctree)/Makefile FORCE
>
>  # ---------------------------------------------------------------------------
>  quiet_cmd_cpp_lds = LDS     $@
> -cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
> +cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
>                 -D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<
>
>  u-boot.lds: $(LDSCRIPT) prepare FORCE
> diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
> index 1c4bed9..076b950 100644
> --- a/cmd/bdinfo.c
> +++ b/cmd/bdinfo.c
> @@ -563,6 +563,28 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
>         return 0;
>  }
>
> +#elif defined(CONFIG_XTENSA)
> +
> +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> +       bd_t *bd = gd->bd;
> +
> +       print_num("boot_params",        (ulong)bd->bi_boot_params);
> +       print_num("memstart",           (ulong)bd->bi_memstart);
> +       print_lnum("memsize",           (u64)bd->bi_memsize);
> +       print_num("flashstart",         (ulong)bd->bi_flashstart);
> +       print_num("flashsize",          (ulong)bd->bi_flashsize);
> +       print_num("flashoffset",        (ulong)bd->bi_flashoffset);
> +
> +#if defined(CONFIG_CMD_NET)
> +       print_eth(0);
> +       printf("ip_addr     = %s\n", getenv("ipaddr"));
> +#endif
> +       printf("baudrate    = %d bps\n", gd->baudrate);

It would be great if you could put this in a common function so that
other archs can call it. There is a lot of duplication in this file.

> +
> +       return 0;
> +}
> +
>  #else
>   #error "a case for this architecture does not exist!"
>  #endif
> diff --git a/common/board_f.c b/common/board_f.c
> index d405b5b..5c4f9fb 100644
> --- a/common/board_f.c
> +++ b/common/board_f.c
> @@ -270,7 +270,8 @@ static int setup_mon_len(void)
>         gd->mon_len = (ulong)&__bss_end - (ulong)_start;
>  #elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
>         gd->mon_len = (ulong)&_end - (ulong)_init;
> -#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2)
> +#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2) || \
> +       defined(CONFIG_XTENSA)
>         gd->mon_len = CONFIG_SYS_MONITOR_LEN;
>  #elif defined(CONFIG_NDS32)
>         gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start);
> @@ -961,7 +962,7 @@ static init_fnc_t init_sequence_f[] = {
>          *  - board info struct
>          */
>         setup_dest_addr,
> -#if defined(CONFIG_BLACKFIN)
> +#if defined(CONFIG_BLACKFIN) || defined(CONFIG_XTENSA)
>         /* Blackfin u-boot monitor should be on top of the ram */
>         reserve_uboot,
>  #endif
> @@ -993,7 +994,7 @@ static init_fnc_t init_sequence_f[] = {
>  # endif
>  #endif /* CONFIG_DM_VIDEO */
>         reserve_trace,
> -#if !defined(CONFIG_BLACKFIN)
> +#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_XTENSA)
>         reserve_uboot,
>  #endif
>  #ifndef CONFIG_SPL_BUILD
> diff --git a/common/image.c b/common/image.c
> index 0be09e5..7d25e10 100644
> --- a/common/image.c
> +++ b/common/image.c
> @@ -93,6 +93,7 @@ static const table_entry_t uimage_arch[] = {
>         {       IH_ARCH_ARM64,          "arm64",        "AArch64",      },
>         {       IH_ARCH_ARC,            "arc",          "ARC",          },
>         {       IH_ARCH_X86_64,         "x86_64",       "AMD x86_64",   },
> +       {       IH_ARCH_XTENSA,         "xtensa",       "Xtensa",       },
>         {       -1,                     "",             "",             },
>  };
>
> diff --git a/doc/README.xtensa b/doc/README.xtensa
> new file mode 100644
> index 0000000..a461714
> --- /dev/null
> +++ b/doc/README.xtensa
> @@ -0,0 +1,100 @@
> +U-Boot for the Xtensa Architecture
> +==================================
> +
> +Xtensa Architecture and Diamond Cores
> +-------------------------------------
> +
> +Xtensa is a configurable processor architecture from Tensilica, Inc.
> +Diamond Cores are pre-configured instances available for license and
> +SoC cores in the same manner as ARM, MIPS, etc.
> +
> +Xtensa licensees create their own Xtensa cores with selected features
> +and custom instructions, registers and co-processors. The custom core
> +is configured with Tensilica tools and built with Tensilica's Xtensa
> +Processor Generator.
> +
> +There are an effectively infinite number of CPUs in the Xtensa
> +architecture family. It is, however, not feasible to support individual
> +Xtensa CPUs in U-Boot. Therefore, there is only a single 'xtensa' CPU
> +in the cpu tree of U-Boot.
> +
> +In the same manner as the Linux port to Xtensa, U-Boot adapts to an
> +individual Xtensa core configuration using a set of macros provided with
> +the particular core. This is part of what is known as the hardware
> +abstraction layer (HAL). For the purpose of U-Boot, the HAL consists only
> +of a few header files. These provide CPP macros that customize sources,
> +Makefiles, and the linker script.
> +
> +
> +Adding support for an additional processor configuration
> +--------------------------------------------------------
> +
> +The header files for one particular processor configuration are inside
> +a variant specific directory located in the arch/xtensa/include/asm

variant-specific

> +directory. The name of that directory starts with 'arch-' followed by
> +the name for the processor configuration, for example, arch-dc233c for
> +the Diamond DC233 processor.
> +
> +    core.h     Definitions for the core itself.
> +
> +The following files are part of the overlay but not used by U-Boot.
> +
> +    tie.h      Co-processors and custom extensions defined
> +               in the Tensilica Instruction Extension (TIE)
> +               language.
> +    tie-asm.h  Assembly macros to access custom-defined registers
> +               and states.
> +
> +
> +Global Data Pointer, Exported Function Stubs, and the ABI
> +---------------------------------------------------------
> +
> +To support standalone applications launched with the "go" command,
> +U-Boot provides a jump table of entrypoints to exported functions
> +(grep for EXPORT_FUNC). The implementation for Xtensa depends on
> +which ABI (or function calling convention) is used.
> +
> +Windowed ABI presents unique difficulties with the approach based on
> +keeping global data pointer in dedicated register. Because the register
> +window rotates during a call, there is no register that is constantly
> +available for the gd pointer. Therefore, a global variable is used in
> +the same manner as i386.

Or you could make gd a simple global variable. It you keep it in the
data section that should work.

> Another difficulty arises from the requirement
> +to have an 'entry' at the beginning of a function, which rotates the
> +register file and reserves a stack frame. This is an integral part of
> +the windowed ABI implemented in hardware. It makes using a jump table
> +to an arbitrary (separately compiled) function a bit tricky. Use of a
> +simple wrapper is also very tedious due to the need to move all
> +possible register arguments and adjust the stack to handle arguments
> +that cannot be passed in registers. The most efficient approach is to
> +have the jump table perform the 'entry' so as to pretend it's the start
> +of the real function. This requires decoding the target function's
> +'entry' instruction to determine the stack frame size, and adjusting
> +the stack pointer accordingly, then jumping into the target function
> +just after the 'entry'. Decoding depends on the processor's endianness
> +so uses the HAL. The implementation (12 instructions) is in
> +examples/stubs.c.
> +
> +
> +Access to Invalid Memory Addresses
> +----------------------------------
> +
> +U-Boot does not check if memory addresses given as arguments to commands
> +such as "md" are valid. The expectation appears to be that if the user
> +requests to look at invalid memory he should expect to see garbage, and
> +writes to invalid memory should be ignored.
> +
> +On many processors, and indeed many Xtensa configurations, this is
> +acceptable. However on some configurations (particularly those with an
> +MMU such as would be used with Linux) an exception is generated for an
> +invalid memory access, which results in a hang if not handled.
> +
> +U-Boot for Xtensa provides a special memory exception handler to prevent
> +hanging. The memory exception handler simply skips over the offending
> +instruction. It is called for all memory exception causes that might
> +be triggered by bad user input. While this is simplistic, it's better
> +than hanging in most cases, while keeping U-Boot small and simple.

Wouldn't it be better to print an exception message? See for example
ARM's do_prefetch_abort().

[snip]

Regards,
Simon
Max Filippov July 14, 2016, 9:55 p.m. UTC | #2
Hi Simon,

On Tue, Jul 12, 2016 at 03:56:01PM -0600, Simon Glass wrote:
> On 8 July 2016 at 09:41, Max Filippov <jcmvbkbc@gmail.com> wrote:
> > From: Chris Zankel <chris@zankel.net>
> >
> > The Xtensa processor architecture is a configurable, extensible,
> > and synthesizable 32-bit RISC processor core provided by Cadence.
> >
> > This is the first part of the basic architecture port with changes to
> > common files. The 'arch/xtensa' directory, and boards and additional
> > drivers will be in separate commits.
> >
> > Signed-off-by: Chris Zankel <chris@zankel.net>
> > Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
> > ---
> >  MAINTAINERS                 |   5 +++
> >  MAKEALL                     |   6 +++
> >  Makefile                    |  10 ++++-
> >  cmd/bdinfo.c                |  22 ++++++++++
> >  common/board_f.c            |   7 ++--
> >  common/image.c              |   1 +
> >  doc/README.xtensa           | 100 ++++++++++++++++++++++++++++++++++++++++++++
> >  examples/standalone/stubs.c |  47 +++++++++++++++++++++
> >  include/image.h             |   1 +
> >  include/linux/stat.h        |   4 +-
> >  10 files changed, 197 insertions(+), 6 deletions(-)
> >  create mode 100644 doc/README.xtensa
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>

Thanks for the review.

[...]

> > diff --git a/MAKEALL b/MAKEALL
> > index 7e42f10..e669aa9 100755
> > --- a/MAKEALL
> > +++ b/MAKEALL
> 
> This is deprecated and will be removed soon, so you don't need to
> update it. See buildman.

Ok.

[...]

> > diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
> > index 1c4bed9..076b950 100644
> > --- a/cmd/bdinfo.c
> > +++ b/cmd/bdinfo.c
> > @@ -563,6 +563,28 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> >         return 0;
> >  }
> >
> > +#elif defined(CONFIG_XTENSA)
> > +
> > +int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> > +{
> > +       bd_t *bd = gd->bd;
> > +
> > +       print_num("boot_params",        (ulong)bd->bi_boot_params);
> > +       print_num("memstart",           (ulong)bd->bi_memstart);
> > +       print_lnum("memsize",           (u64)bd->bi_memsize);
> > +       print_num("flashstart",         (ulong)bd->bi_flashstart);
> > +       print_num("flashsize",          (ulong)bd->bi_flashsize);
> > +       print_num("flashoffset",        (ulong)bd->bi_flashoffset);
> > +
> > +#if defined(CONFIG_CMD_NET)
> > +       print_eth(0);
> > +       printf("ip_addr     = %s\n", getenv("ipaddr"));
> > +#endif
> > +       printf("baudrate    = %d bps\n", gd->baudrate);
> 
> It would be great if you could put this in a common function so that
> other archs can call it. There is a lot of duplication in this file.

Ok, let me look at that.

[...]

> > diff --git a/doc/README.xtensa b/doc/README.xtensa
> > new file mode 100644
> > index 0000000..a461714
> > --- /dev/null
> > +++ b/doc/README.xtensa

[...]

> > +The header files for one particular processor configuration are inside
> > +a variant specific directory located in the arch/xtensa/include/asm
> 
> variant-specific

Ok.

[...]

> > +Windowed ABI presents unique difficulties with the approach based on
> > +keeping global data pointer in dedicated register. Because the register
> > +window rotates during a call, there is no register that is constantly
> > +available for the gd pointer. Therefore, a global variable is used in
> > +the same manner as i386.
> 
> Or you could make gd a simple global variable. It you keep it in the
> data section that should work.

gd is a simple global variable on xtensa, I haven't actually checked
what 'in the same manner as i386' means now. Will fix wording.

[...]

> > +U-Boot for Xtensa provides a special memory exception handler to prevent
> > +hanging. The memory exception handler simply skips over the offending
> > +instruction. It is called for all memory exception causes that might
> > +be triggered by bad user input. While this is simplistic, it's better
> > +than hanging in most cases, while keeping U-Boot small and simple.
> 
> Wouldn't it be better to print an exception message? See for example
> ARM's do_prefetch_abort().

I see that on ARM such errors result in panic and reset. Sure I can do
that if that's the preferred way of dealing with such errors.
diff mbox

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 1db8243..24afa88 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -453,6 +453,11 @@  S:	Maintained
 T:	git git://git.denx.de/u-boot-x86.git
 F:	arch/x86/
 
+XTENSA
+M:	Max Filippov <jcmvbkbc@gmail.com>
+S:	Maintained
+F:	arch/xtensa/
+
 THE REST
 M:	Tom Rini <trini@konsulko.com>
 L:	u-boot@lists.denx.de
diff --git a/MAKEALL b/MAKEALL
index 7e42f10..e669aa9 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -497,6 +497,12 @@  LIST_nds32="$(targets_by_arch nds32)"
 
 LIST_arc="$(targets_by_arch arc)"
 
+#########################################################################
+## Xtensa Systems
+#########################################################################
+
+LIST_xtensa="$(targets_by_arch xtensa)"
+
 #-----------------------------------------------------------------------
 
 get_target_location() {
diff --git a/Makefile b/Makefile
index 09a18e1..083af95 100644
--- a/Makefile
+++ b/Makefile
@@ -556,6 +556,14 @@  else
 include/config/auto.conf: ;
 endif # $(dot-config)
 
+#
+# Xtensa linker script cannot be preprocessed with -ansi because of
+# preprocessor operations on strings that don't make C identifiers.
+#
+ifeq ($(CONFIG_XTENSA),)
+LDPPFLAGS	+= -ansi
+endif
+
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 KBUILD_CFLAGS	+= -Os
 else
@@ -1310,7 +1318,7 @@  $(timestamp_h): $(srctree)/Makefile FORCE
 
 # ---------------------------------------------------------------------------
 quiet_cmd_cpp_lds = LDS     $@
-cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) -ansi \
+cmd_cpp_lds = $(CPP) -Wp,-MD,$(depfile) $(cpp_flags) $(LDPPFLAGS) \
 		-D__ASSEMBLY__ -x assembler-with-cpp -P -o $@ $<
 
 u-boot.lds: $(LDSCRIPT) prepare FORCE
diff --git a/cmd/bdinfo.c b/cmd/bdinfo.c
index 1c4bed9..076b950 100644
--- a/cmd/bdinfo.c
+++ b/cmd/bdinfo.c
@@ -563,6 +563,28 @@  int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	return 0;
 }
 
+#elif defined(CONFIG_XTENSA)
+
+int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	bd_t *bd = gd->bd;
+
+	print_num("boot_params",	(ulong)bd->bi_boot_params);
+	print_num("memstart",		(ulong)bd->bi_memstart);
+	print_lnum("memsize",		(u64)bd->bi_memsize);
+	print_num("flashstart",		(ulong)bd->bi_flashstart);
+	print_num("flashsize",		(ulong)bd->bi_flashsize);
+	print_num("flashoffset",	(ulong)bd->bi_flashoffset);
+
+#if defined(CONFIG_CMD_NET)
+	print_eth(0);
+	printf("ip_addr     = %s\n", getenv("ipaddr"));
+#endif
+	printf("baudrate    = %d bps\n", gd->baudrate);
+
+	return 0;
+}
+
 #else
  #error "a case for this architecture does not exist!"
 #endif
diff --git a/common/board_f.c b/common/board_f.c
index d405b5b..5c4f9fb 100644
--- a/common/board_f.c
+++ b/common/board_f.c
@@ -270,7 +270,8 @@  static int setup_mon_len(void)
 	gd->mon_len = (ulong)&__bss_end - (ulong)_start;
 #elif defined(CONFIG_SANDBOX) || defined(CONFIG_EFI_APP)
 	gd->mon_len = (ulong)&_end - (ulong)_init;
-#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2)
+#elif defined(CONFIG_BLACKFIN) || defined(CONFIG_NIOS2) || \
+	defined(CONFIG_XTENSA)
 	gd->mon_len = CONFIG_SYS_MONITOR_LEN;
 #elif defined(CONFIG_NDS32)
 	gd->mon_len = (ulong)(&__bss_end) - (ulong)(&_start);
@@ -961,7 +962,7 @@  static init_fnc_t init_sequence_f[] = {
 	 *  - board info struct
 	 */
 	setup_dest_addr,
-#if defined(CONFIG_BLACKFIN)
+#if defined(CONFIG_BLACKFIN) || defined(CONFIG_XTENSA)
 	/* Blackfin u-boot monitor should be on top of the ram */
 	reserve_uboot,
 #endif
@@ -993,7 +994,7 @@  static init_fnc_t init_sequence_f[] = {
 # endif
 #endif /* CONFIG_DM_VIDEO */
 	reserve_trace,
-#if !defined(CONFIG_BLACKFIN)
+#if !defined(CONFIG_BLACKFIN) && !defined(CONFIG_XTENSA)
 	reserve_uboot,
 #endif
 #ifndef CONFIG_SPL_BUILD
diff --git a/common/image.c b/common/image.c
index 0be09e5..7d25e10 100644
--- a/common/image.c
+++ b/common/image.c
@@ -93,6 +93,7 @@  static const table_entry_t uimage_arch[] = {
 	{	IH_ARCH_ARM64,		"arm64",	"AArch64",	},
 	{	IH_ARCH_ARC,		"arc",		"ARC",		},
 	{	IH_ARCH_X86_64,		"x86_64",	"AMD x86_64",	},
+	{	IH_ARCH_XTENSA,		"xtensa",	"Xtensa",	},
 	{	-1,			"",		"",		},
 };
 
diff --git a/doc/README.xtensa b/doc/README.xtensa
new file mode 100644
index 0000000..a461714
--- /dev/null
+++ b/doc/README.xtensa
@@ -0,0 +1,100 @@ 
+U-Boot for the Xtensa Architecture
+==================================
+
+Xtensa Architecture and Diamond Cores
+-------------------------------------
+
+Xtensa is a configurable processor architecture from Tensilica, Inc.
+Diamond Cores are pre-configured instances available for license and
+SoC cores in the same manner as ARM, MIPS, etc.
+
+Xtensa licensees create their own Xtensa cores with selected features
+and custom instructions, registers and co-processors. The custom core
+is configured with Tensilica tools and built with Tensilica's Xtensa
+Processor Generator.
+
+There are an effectively infinite number of CPUs in the Xtensa
+architecture family. It is, however, not feasible to support individual
+Xtensa CPUs in U-Boot. Therefore, there is only a single 'xtensa' CPU
+in the cpu tree of U-Boot.
+
+In the same manner as the Linux port to Xtensa, U-Boot adapts to an
+individual Xtensa core configuration using a set of macros provided with
+the particular core. This is part of what is known as the hardware
+abstraction layer (HAL). For the purpose of U-Boot, the HAL consists only
+of a few header files. These provide CPP macros that customize sources,
+Makefiles, and the linker script.
+
+
+Adding support for an additional processor configuration
+--------------------------------------------------------
+
+The header files for one particular processor configuration are inside
+a variant specific directory located in the arch/xtensa/include/asm
+directory. The name of that directory starts with 'arch-' followed by
+the name for the processor configuration, for example, arch-dc233c for
+the Diamond DC233 processor.
+
+    core.h	Definitions for the core itself.
+
+The following files are part of the overlay but not used by U-Boot.
+
+    tie.h	Co-processors and custom extensions defined
+		in the Tensilica Instruction Extension (TIE)
+		language.
+    tie-asm.h	Assembly macros to access custom-defined registers
+		and states.
+
+
+Global Data Pointer, Exported Function Stubs, and the ABI
+---------------------------------------------------------
+
+To support standalone applications launched with the "go" command,
+U-Boot provides a jump table of entrypoints to exported functions
+(grep for EXPORT_FUNC). The implementation for Xtensa depends on
+which ABI (or function calling convention) is used.
+
+Windowed ABI presents unique difficulties with the approach based on
+keeping global data pointer in dedicated register. Because the register
+window rotates during a call, there is no register that is constantly
+available for the gd pointer. Therefore, a global variable is used in
+the same manner as i386. Another difficulty arises from the requirement
+to have an 'entry' at the beginning of a function, which rotates the
+register file and reserves a stack frame. This is an integral part of
+the windowed ABI implemented in hardware. It makes using a jump table
+to an arbitrary (separately compiled) function a bit tricky. Use of a
+simple wrapper is also very tedious due to the need to move all
+possible register arguments and adjust the stack to handle arguments
+that cannot be passed in registers. The most efficient approach is to
+have the jump table perform the 'entry' so as to pretend it's the start
+of the real function. This requires decoding the target function's
+'entry' instruction to determine the stack frame size, and adjusting
+the stack pointer accordingly, then jumping into the target function
+just after the 'entry'. Decoding depends on the processor's endianness
+so uses the HAL. The implementation (12 instructions) is in
+examples/stubs.c.
+
+
+Access to Invalid Memory Addresses
+----------------------------------
+
+U-Boot does not check if memory addresses given as arguments to commands
+such as "md" are valid. The expectation appears to be that if the user
+requests to look at invalid memory he should expect to see garbage, and
+writes to invalid memory should be ignored.
+
+On many processors, and indeed many Xtensa configurations, this is
+acceptable. However on some configurations (particularly those with an
+MMU such as would be used with Linux) an exception is generated for an
+invalid memory access, which results in a hang if not handled.
+
+U-Boot for Xtensa provides a special memory exception handler to prevent
+hanging. The memory exception handler simply skips over the offending
+instruction. It is called for all memory exception causes that might
+be triggered by bad user input. While this is simplistic, it's better
+than hanging in most cases, while keeping U-Boot small and simple.
+
+
+------------------------------------------------------------------------------
+Chris Zankel
+Ross Morley
diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c
index 0d62067..a8b7e14 100644
--- a/examples/standalone/stubs.c
+++ b/examples/standalone/stubs.c
@@ -240,6 +240,53 @@  gd_t *global_data;
 "	ld	r10, [r10, %1]\n" \
 "	j	[r10]\n" \
 	: : "i"(offsetof(gd_t, jt)), "i"(FO(x)) : "r10");
+#elif defined(CONFIG_XTENSA)
+/*
+ * Global data ptr is in global_data, jump table ptr is in jt.
+ * Windowed ABI: Jump just past 'entry' in target and adjust stack frame
+ * (extract stack frame size from target 'entry' instruction).
+ */
+
+static void **jt;
+
+#if defined(__XTENSA_CALL0_ABI__)
+#define EXPORT_FUNC(f, a, x, ...)	\
+	asm volatile (			\
+"	.extern jt\n"			\
+"	.globl " #x "\n"		\
+"	.align 4\n"			\
+#x ":\n"				\
+"	l32i	a8, %0, 0\n"		\
+"	l32i	a8, a8, %1\n"		\
+"	jx	a8\n"			\
+	: : "r"(jt), "i" (FO(x)) : "a8");
+#elif defined(__XTENSA_WINDOWED_ABI__)
+#if XCHAL_HAVE_BE
+# define SFT "8"
+#else
+# define SFT "12"
+#endif
+#define EXPORT_FUNC(f, a, x, ...)	\
+	asm volatile (			\
+"	.extern jt\n"			\
+"	.globl " #x "\n"		\
+"	.align 4\n"			\
+#x ":\n"				\
+"	entry	sp, 16\n"		\
+"	l32i	a8, %0, 0\n"		\
+"	l32i	a8, a8, %1\n"		\
+"	l32i	a9, a8, 0\n"		\
+"	extui	a9, a9, " SFT ", 12\n"	\
+"	subx8	a9, a9, sp\n"		\
+"	movi	a10, 16\n"		\
+"	sub	a9, a10, a9\n"		\
+"	movsp	sp, a9\n"		\
+"	addi	a8, a8, 3\n"		\
+"	jx	a8\n"			\
+	: : "r"(jt), "i" (FO(x)) : "a8", "a9", "a10");
+#else
+#error Unsupported Xtensa ABI
+#endif
 #else
 /*"	addi	$sp, $sp, -24\n"	\
 "	br	$r16\n"			\*/
diff --git a/include/image.h b/include/image.h
index d788c26..bcf58a7 100644
--- a/include/image.h
+++ b/include/image.h
@@ -179,6 +179,7 @@  struct lmb;
 #define IH_ARCH_ARM64		22	/* ARM64	*/
 #define IH_ARCH_ARC		23	/* Synopsys DesignWare ARC */
 #define IH_ARCH_X86_64		24	/* AMD x86_64, Intel and Via */
+#define IH_ARCH_XTENSA		25	/* Xtensa	*/
 
 /*
  * Image Types
diff --git a/include/linux/stat.h b/include/linux/stat.h
index cef6369..1af0876 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -126,7 +126,7 @@  struct stat {
 
 #endif	/* __MIPS__ */
 
-#if defined(__AVR32__) || defined(__SH__)
+#if defined(__AVR32__) || defined(__SH__) || defined(__XTENSA__)
 
 struct stat {
 	unsigned long st_dev;
@@ -149,7 +149,7 @@  struct stat {
 	unsigned long  __unused5;
 };
 
-#endif /* __AVR32__ || __SH__ */
+#endif /* __AVR32__ || __SH__  || __XTENSA__ */
 
 #ifdef __cplusplus
 }