[PATCH 00/10] xtensa: Enable qemu-xtensa board

Hi all,
This series enabled qemu-xtensa board.
For dc232b CPU it needs to be built with toolchain[1].
This is a side product of me investigating architectures physical address != virtual address in U-Boot. Now we can get it covered under CI and regular tests.
VirtIO devices are not working as expected, due to U-Boot's assumption on VA == PA everywhere, I'm going to get this fixed later.
My Xtensa knowledge is pretty limited, Xtensa people please feel free to point out if I got anything wrong.
Thanks [1]: https://github.com/foss-xtensa/toolchain/releases/download/2020.07/x86_64-20...
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- Jiaxun Yang (10): xtensa: Move dram_init to xtfpga board file xtensa: Correct define of _end symbol xtensa: Implement phys virt conversion for PTP_MMU xtensa: Define PLATFORM_ELFFLAGS xtensa: Bring in semihosting headers and config options drivers: serial: Add xtensa semihosting driver drivers: cpu: Add xtensa CPU driver dts/upsteam: Add Makefile for xtensa board: emulation: New board qemu-xtensa doc: New documentation for qemu-xtensa
arch/xtensa/Kconfig | 32 +++++++ arch/xtensa/config.mk | 3 + arch/xtensa/cpu/cpu.c | 5 - arch/xtensa/cpu/u-boot.lds | 2 + arch/xtensa/include/asm/addrspace.h | 2 + arch/xtensa/include/asm/io.h | 32 +++++++ arch/xtensa/include/asm/ldscript.h | 1 - arch/xtensa/include/asm/platform/simcall-gdbio.h | 34 +++++++ arch/xtensa/include/asm/platform/simcall-iss.h | 73 ++++++++++++++ arch/xtensa/include/asm/platform/simcall.h | 110 +++++++++++++++++++++ board/cadence/xtfpga/xtfpga.c | 5 + board/emulation/qemu-xtensa/Kconfig | 41 ++++++++ board/emulation/qemu-xtensa/MAINTAINERS | 7 ++ board/emulation/qemu-xtensa/Makefile | 5 + board/emulation/qemu-xtensa/qemu-xtensa.c | 60 ++++++++++++ configs/qemu-xtensa-dc232b_defconfig | 32 +++++++ doc/board/emulation/index.rst | 1 + doc/board/emulation/qemu-xtensa.rst | 33 +++++++ drivers/cpu/Kconfig | 6 ++ drivers/cpu/Makefile | 1 + drivers/cpu/xtensa_cpu.c | 117 +++++++++++++++++++++++ drivers/serial/Kconfig | 18 +++- drivers/serial/Makefile | 1 + drivers/serial/serial_xtensa_semihosting.c | 79 +++++++++++++++ dts/upstream/src/xtensa/Makefile | 14 +++ include/configs/qemu-xtensa.h | 34 +++++++ 26 files changed, 741 insertions(+), 7 deletions(-) --- base-commit: 3be9f399e911cfc437a37ac826441f1d96da1c9b change-id: 20240519-qemu-xtensa-5fb95bb474e9
Best regards,

This is a board level stuff.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/xtensa/cpu/cpu.c | 5 ----- board/cadence/xtfpga/xtfpga.c | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/xtensa/cpu/cpu.c b/arch/xtensa/cpu/cpu.c index abcd8f7984fa..d2266812229c 100644 --- a/arch/xtensa/cpu/cpu.c +++ b/arch/xtensa/cpu/cpu.c @@ -48,8 +48,3 @@ int arch_cpu_init(void) gd->ram_size = CFG_SYS_SDRAM_SIZE; return 0; } - -int dram_init(void) -{ - return 0; -} diff --git a/board/cadence/xtfpga/xtfpga.c b/board/cadence/xtfpga/xtfpga.c index 5110fed31194..6b92fe31c0e0 100644 --- a/board/cadence/xtfpga/xtfpga.c +++ b/board/cadence/xtfpga/xtfpga.c @@ -66,6 +66,11 @@ unsigned long get_board_sys_clk(void) #endif }
+int dram_init(void) +{ + return 0; +} + int board_postclk_init(void) { gd->cpu_clk = get_board_sys_clk();

So U-Boot is using _end symbol to detect location of devicetree appended at the end of the ROM.
It needs to be calculated based on end of .data load address, as in our lds .current address is address in RAM.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/xtensa/cpu/u-boot.lds | 2 ++ arch/xtensa/include/asm/ldscript.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/xtensa/cpu/u-boot.lds b/arch/xtensa/cpu/u-boot.lds index 84ba32c04444..72e4b9a706e5 100644 --- a/arch/xtensa/cpu/u-boot.lds +++ b/arch/xtensa/cpu/u-boot.lds @@ -82,6 +82,8 @@ SECTIONS
__reloc_end = .; __init_end = .; + /* Calculation to get end address in ROM */ + _end = LOADADDR(.data) + (_data_end - _data_start);
SECTION_bss(__init_end (OVERLAY),)
diff --git a/arch/xtensa/include/asm/ldscript.h b/arch/xtensa/include/asm/ldscript.h index 78a0b230bdaa..bcf0fd5a7443 100644 --- a/arch/xtensa/include/asm/ldscript.h +++ b/arch/xtensa/include/asm/ldscript.h @@ -165,7 +165,6 @@ . = ALIGN(8); \ _bss_end = ABSOLUTE(.); \ __bss_end = ABSOLUTE(.); \ - _end = ALIGN(0x8); \ PROVIDE(end = ALIGN(0x8)); \ _stack_sentry = ALIGN(0x8); \ }

For PTP_MMU our physical address is not directly mapped into virtual address space, we need to access physical memory from those fixed map segments.
Implement phys_to_virt and virt_to_phys hook to reflect this setting.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/xtensa/include/asm/addrspace.h | 2 ++ arch/xtensa/include/asm/io.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
diff --git a/arch/xtensa/include/asm/addrspace.h b/arch/xtensa/include/asm/addrspace.h index 920b5fd26b20..c8bed8834b55 100644 --- a/arch/xtensa/include/asm/addrspace.h +++ b/arch/xtensa/include/asm/addrspace.h @@ -7,6 +7,8 @@ #ifndef _XTENSA_ADDRSPACE_H #define _XTENSA_ADDRSPACE_H
+#include <config.h> + #include <asm/arch/core.h>
/* diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h index 87ad9faa2995..ab2438b829ac 100644 --- a/arch/xtensa/include/asm/io.h +++ b/arch/xtensa/include/asm/io.h @@ -12,6 +12,8 @@ #include <linux/types.h> #include <asm/byteorder.h>
+#include <asm/addrspace.h> + /* * swap functions to change byte order from little-endian to big-endian and * vice versa. @@ -127,6 +129,36 @@ static inline void sync(void) { }
+#if XCHAL_HAVE_PTP_MMU +static inline void *phys_to_virt(phys_addr_t paddr) +{ + if (paddr >= CFG_SYS_IO_BASE) + return (void *)(unsigned long)paddr; + + if (paddr < CFG_MAX_MEM_MAPPED) + return (void *)(unsigned long)MEMADDR(paddr); + + return NULL; +} + +#define phys_to_virt phys_to_virt + +static inline phys_addr_t virt_to_phys(void *vaddr) +{ + unsigned long addr = (unsigned long)vaddr; + + if (addr >= CFG_SYS_IO_BASE) + return addr; + + if (addr >= CFG_SYS_SDRAM_BASE && addr < MEMADDR(CFG_MAX_MEM_MAPPED)) + return PHYSADDR(addr); + + return 0; +} + +#define virt_to_phys virt_to_phys +#endif /* XCHAL_HAVE_PTP_MMU */ + #include <asm-generic/io.h>
#endif /* _XTENSA_IO_H */

u-boot.elf target requiures it to work.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/xtensa/config.mk | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk index b0809999e403..3ec936272f25 100644 --- a/arch/xtensa/config.mk +++ b/arch/xtensa/config.mk @@ -7,3 +7,6 @@ PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \ -ffunction-sections -fdata-sections
LDFLAGS_FINAL += --gc-sections + +PLATFORM_ELFFLAGS += -B xtensa -O elf32-xtensa-le +

On Sun, May 19, 2024 at 1:53 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
u-boot.elf target requiures it to work.
Typo.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/xtensa/config.mk | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk index b0809999e403..3ec936272f25 100644 --- a/arch/xtensa/config.mk +++ b/arch/xtensa/config.mk @@ -7,3 +7,6 @@ PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \ -ffunction-sections -fdata-sections
LDFLAGS_FINAL += --gc-sections
+PLATFORM_ELFFLAGS += -B xtensa -O elf32-xtensa-le
This fixes endianness as little for the whole architecture, but xtensa cores may be either little or big endian.

在2024年5月20日五月 下午4:18,Max Filippov写道:
On Sun, May 19, 2024 at 1:53 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
u-boot.elf target requiures it to work.
Typo.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/xtensa/config.mk | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk index b0809999e403..3ec936272f25 100644 --- a/arch/xtensa/config.mk +++ b/arch/xtensa/config.mk @@ -7,3 +7,6 @@ PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \ -ffunction-sections -fdata-sections
LDFLAGS_FINAL += --gc-sections
+PLATFORM_ELFFLAGS += -B xtensa -O elf32-xtensa-le
This fixes endianness as little for the whole architecture, but xtensa cores may be either little or big endian.
Hi Max,
Thanks for reviewing, I can just add a branch with ifdef CONFIG_SYS_BIG_EDNIAN if you wish, but I think all CPUs U-Boot support are little endian only?
I have an ongoing series[1] fixing endian selection options, please let me know if U-Boot do work with big endian Xtensa.
Thanks.
[1]: https://patchwork.ozlabs.org/project/uboot/patch/20240519-aarch64-be-v1-11-7...
-- Thanks. -- Max

On Mon, May 20, 2024 at 9:00 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk index b0809999e403..3ec936272f25 100644 --- a/arch/xtensa/config.mk +++ b/arch/xtensa/config.mk @@ -7,3 +7,6 @@ PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \ -ffunction-sections -fdata-sections
LDFLAGS_FINAL += --gc-sections
+PLATFORM_ELFFLAGS += -B xtensa -O elf32-xtensa-le
This fixes endianness as little for the whole architecture, but xtensa cores may be either little or big endian.
Thanks for reviewing, I can just add a branch with ifdef CONFIG_SYS_BIG_EDNIAN if you wish, but I think all CPUs U-Boot support are little endian only?
I have an ongoing series[1] fixing endian selection options, please let me know if U-Boot do work with big endian Xtensa.
I had an impression that there's nothing endian-specific in the xtensa port, so it should work for both little- and big-endian cores. Let me test whether it's true though (:

On Tue, May 21, 2024 at 12:12 AM Max Filippov jcmvbkbc@gmail.com wrote:
On Mon, May 20, 2024 at 9:00 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
diff --git a/arch/xtensa/config.mk b/arch/xtensa/config.mk index b0809999e403..3ec936272f25 100644 --- a/arch/xtensa/config.mk +++ b/arch/xtensa/config.mk @@ -7,3 +7,6 @@ PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \ -ffunction-sections -fdata-sections
LDFLAGS_FINAL += --gc-sections
+PLATFORM_ELFFLAGS += -B xtensa -O elf32-xtensa-le
This fixes endianness as little for the whole architecture, but xtensa cores may be either little or big endian.
Thanks for reviewing, I can just add a branch with ifdef CONFIG_SYS_BIG_EDNIAN if you wish, but I think all CPUs U-Boot support are little endian only?
I have an ongoing series[1] fixing endian selection options, please let me know if U-Boot do work with big endian Xtensa.
I had an impression that there's nothing endian-specific in the xtensa port, so it should work for both little- and big-endian cores. Let me test whether it's true though (:
Yep, I can confirm that. Importing big endian xtensa core files into the current u-boot (I tested this one: https://github.com/jcmvbkbc/xtensa-toolchain-build/blob/master/overlays/xten... matching cross-compiler is available here: https://github.com/foss-xtensa/toolchain/releases/download/2019.03/x86_64-20... ) and building it for xtfpga produces a working image.

They are all directly imported from Linux kernel.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/xtensa/Kconfig | 27 ++++++ arch/xtensa/include/asm/platform/simcall-gdbio.h | 34 +++++++ arch/xtensa/include/asm/platform/simcall-iss.h | 73 +++++++++++++++ arch/xtensa/include/asm/platform/simcall.h | 110 +++++++++++++++++++++++ 4 files changed, 244 insertions(+)
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 8f668cc67ed0..4afd56bca095 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -41,6 +41,33 @@ config SPL_SYS_DCACHE_OFF help Do not enable data cache in SPL.
+config XTENSA_SEMIHOSTING + bool "Support semihosting" + help + Enable Xtensa semihosting debugging support. + +choice + prompt "Semihosting interface" + default XTENSA_SIMCALL_ISS + depends on XTENSA_SEMIHOSTING + help + Choose semihosting interface that will be used for serial port, + block device and networking. + +config XTENSA_SIMCALL_ISS + bool "simcall" + help + Use simcall instruction. simcall is only available on simulators, + it does nothing on hardware. + +config XTENSA_SIMCALL_GDBIO + bool "GDBIO" + help + Use break instruction. It is available on real hardware when GDB + is attached to it via JTAG. + +endchoice + source "board/cadence/xtfpga/Kconfig"
endmenu diff --git a/arch/xtensa/include/asm/platform/simcall-gdbio.h b/arch/xtensa/include/asm/platform/simcall-gdbio.h new file mode 100644 index 000000000000..e642860e25a8 --- /dev/null +++ b/arch/xtensa/include/asm/platform/simcall-gdbio.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2021 Cadence Design Systems Inc. */ + +#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_GDBIO_H +#define _XTENSA_PLATFORM_ISS_SIMCALL_GDBIO_H + +/* + * System call like services offered by the GDBIO host. + */ + +#define SYS_open -2 +#define SYS_close -3 +#define SYS_read -4 +#define SYS_write -5 +#define SYS_lseek -6 + +static int errno; + +static inline int __simc(int a, int b, int c, int d) +{ + register int a1 asm("a2") = a; + register int b1 asm("a6") = b; + register int c1 asm("a3") = c; + register int d1 asm("a4") = d; + __asm__ __volatile__ ( + "break 1, 14\n" + : "+r"(a1), "+r"(c1) + : "r"(b1), "r"(d1) + : "memory"); + errno = c1; + return a1; +} + +#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_GDBIO_H */ diff --git a/arch/xtensa/include/asm/platform/simcall-iss.h b/arch/xtensa/include/asm/platform/simcall-iss.h new file mode 100644 index 000000000000..5a1e7a1f182e --- /dev/null +++ b/arch/xtensa/include/asm/platform/simcall-iss.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2021 Cadence Design Systems Inc. */ + +#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_ISS_H +#define _XTENSA_PLATFORM_ISS_SIMCALL_ISS_H + +/* + * System call like services offered by the simulator host. + */ + +#define SYS_nop 0 /* unused */ +#define SYS_exit 1 /*x*/ +#define SYS_fork 2 +#define SYS_read 3 /*x*/ +#define SYS_write 4 /*x*/ +#define SYS_open 5 /*x*/ +#define SYS_close 6 /*x*/ +#define SYS_rename 7 /*x 38 - waitpid */ +#define SYS_creat 8 /*x*/ +#define SYS_link 9 /*x (not implemented on WIN32) */ +#define SYS_unlink 10 /*x*/ +#define SYS_execv 11 /* n/a - execve */ +#define SYS_execve 12 /* 11 - chdir */ +#define SYS_pipe 13 /* 42 - time */ +#define SYS_stat 14 /* 106 - mknod */ +#define SYS_chmod 15 +#define SYS_chown 16 /* 202 - lchown */ +#define SYS_utime 17 /* 30 - break */ +#define SYS_wait 18 /* n/a - oldstat */ +#define SYS_lseek 19 /*x*/ +#define SYS_getpid 20 +#define SYS_isatty 21 /* n/a - mount */ +#define SYS_fstat 22 /* 108 - oldumount */ +#define SYS_time 23 /* 13 - setuid */ +#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */ +#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */ +#define SYS_socket 26 +#define SYS_sendto 27 +#define SYS_recvfrom 28 +#define SYS_select_one 29 /* not compatible select, one file descriptor at the time */ +#define SYS_bind 30 +#define SYS_ioctl 31 + +#define SYS_iss_argc 1000 /* returns value of argc */ +#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */ +#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */ + +/* + * SYS_select_one specifiers + */ + +#define XTISS_SELECT_ONE_READ 1 +#define XTISS_SELECT_ONE_WRITE 2 +#define XTISS_SELECT_ONE_EXCEPT 3 + +static int errno; + +static inline int __simc(int a, int b, int c, int d) +{ + register int a1 asm("a2") = a; + register int b1 asm("a3") = b; + register int c1 asm("a4") = c; + register int d1 asm("a5") = d; + __asm__ __volatile__ ( + "simcall\n" + : "+r"(a1), "+r"(b1) + : "r"(c1), "r"(d1) + : "memory"); + errno = b1; + return a1; +} + +#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_ISS_H */ diff --git a/arch/xtensa/include/asm/platform/simcall.h b/arch/xtensa/include/asm/platform/simcall.h new file mode 100644 index 000000000000..a1cb269e68f0 --- /dev/null +++ b/arch/xtensa/include/asm/platform/simcall.h @@ -0,0 +1,110 @@ +/* + * include/asm-xtensa/platform-iss/simcall.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2001 Tensilica Inc. + * Copyright (C) 2017 - 2021 Cadence Design Systems Inc. + */ + +#ifndef _XTENSA_PLATFORM_ISS_SIMCALL_H +#define _XTENSA_PLATFORM_ISS_SIMCALL_H + +#include <linux/bug.h> + +#ifdef CONFIG_XTENSA_SIMCALL_ISS +#include <asm/platform/simcall-iss.h> +#endif +#ifdef CONFIG_XTENSA_SIMCALL_GDBIO +#include <asm/platform/simcall-gdbio.h> +#endif + +static inline int simc_exit(int exit_code) +{ +#ifdef SYS_exit + return __simc(SYS_exit, exit_code, 0, 0); +#else + WARN_ONCE(1, "%s: not implemented\n", __func__); + return -1; +#endif +} + +static inline int simc_open(const char *file, int flags, int mode) +{ + return __simc(SYS_open, (int) file, flags, mode); +} + +static inline int simc_close(int fd) +{ + return __simc(SYS_close, fd, 0, 0); +} + +static inline int simc_ioctl(int fd, int request, void *arg) +{ +#ifdef SYS_ioctl + return __simc(SYS_ioctl, fd, request, (int) arg); +#else + WARN_ONCE(1, "%s: not implemented\n", __func__); + return -1; +#endif +} + +static inline int simc_read(int fd, void *buf, size_t count) +{ + return __simc(SYS_read, fd, (int) buf, count); +} + +static inline int simc_write(int fd, const void *buf, size_t count) +{ + return __simc(SYS_write, fd, (int) buf, count); +} + +static inline int simc_poll(int fd) +{ +#ifdef SYS_select_one + long timeval[2] = { 0, 0 }; + + return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&timeval); +#else + WARN_ONCE(1, "%s: not implemented\n", __func__); + return -1; +#endif +} + +static inline int simc_lseek(int fd, uint32_t off, int whence) +{ + return __simc(SYS_lseek, fd, off, whence); +} + +static inline int simc_argc(void) +{ +#ifdef SYS_iss_argc + return __simc(SYS_iss_argc, 0, 0, 0); +#else + WARN_ONCE(1, "%s: not implemented\n", __func__); + return 0; +#endif +} + +static inline int simc_argv_size(void) +{ +#ifdef SYS_iss_argv_size + return __simc(SYS_iss_argv_size, 0, 0, 0); +#else + WARN_ONCE(1, "%s: not implemented\n", __func__); + return 0; +#endif +} + +static inline void simc_argv(void *buf) +{ +#ifdef SYS_iss_set_argv + __simc(SYS_iss_set_argv, (int)buf, 0, 0); +#else + WARN_ONCE(1, "%s: not implemented\n", __func__); +#endif +} + +#endif /* _XTENSA_PLATFORM_ISS_SIMCALL_H */

On Sun, May 19, 2024 at 1:53 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
They are all directly imported from Linux kernel.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/xtensa/Kconfig | 27 ++++++ arch/xtensa/include/asm/platform/simcall-gdbio.h | 34 +++++++ arch/xtensa/include/asm/platform/simcall-iss.h | 73 +++++++++++++++ arch/xtensa/include/asm/platform/simcall.h | 110 +++++++++++++++++++++++ 4 files changed, 244 insertions(+)
Reviewed-by: Max Filippov jcmvbkbc@gmail.com

Add xtensa semihosting driver.
It can't use regular semihosting driver as Xtensa's has it's own semihosting ABI.
Note that semihosting supports puts in serial but I never managed to get it work, so it's putc only for now.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- drivers/serial/Kconfig | 18 ++++++- drivers/serial/Makefile | 1 + drivers/serial/serial_xtensa_semihosting.c | 79 ++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 1fe4607598eb..3a1e5a6f2877 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -501,6 +501,15 @@ config DEBUG_UART_MT7620 driver will be available until the real driver model serial is running.
+config DEBUG_UART_XTENSA_SEMIHOSTING + bool "Xtensa semihosting" + depends on XTENSA_SEMIHOSTING_SERIAL + help + Select this to enable the debug UART using the Xtensa semihosting driver. + This provides basic serial output from the console without needing to + start up driver model. The driver will be available until the real + driver model serial is running. + endchoice
config DEBUG_UART_BASE @@ -936,7 +945,6 @@ config SH_SCIF_CLK_FREQ config SEMIHOSTING_SERIAL bool "Semihosting UART support" depends on SEMIHOSTING && !SERIAL_RX_BUFFER - imply SERIAL_PUTS help Select this to enable a serial UART using semihosting. Special halt instructions will be issued which an external debugger (such as a @@ -1115,6 +1123,14 @@ config XEN_SERIAL If built without DM support, then requires Xen to be built with CONFIG_VERBOSE_DEBUG.
+config XTENSA_SEMIHOSTING_SERIAL + bool "Xtensa Semihosting UART support" + depends on DM_SERIAL + depends on XTENSA_SEMIHOSTING + imply SERIAL_PUTS + help + Select this to enable a serial UART using Xtensa semihosting. + choice prompt "Console port" default 8xx_CONS_SMC1 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index dbe598b74064..78810f98367c 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o obj-$(CONFIG_XEN_SERIAL) += serial_xen.o +obj-$(CONFIG_XTENSA_SEMIHOSTING_SERIAL) += serial_xtensa_semihosting.o obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o
ifndef CONFIG_SPL_BUILD diff --git a/drivers/serial/serial_xtensa_semihosting.c b/drivers/serial/serial_xtensa_semihosting.c new file mode 100644 index 000000000000..1bf3c18537e7 --- /dev/null +++ b/drivers/serial/serial_xtensa_semihosting.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#include <dm.h> +#include <malloc.h> +#include <serial.h> + +#include <asm/platform/simcall.h> + +/** + * struct simc_serial_priv - Semihosting serial private data + * @counter: Counter used to fake pending every other call + */ +struct simc_serial_priv { + unsigned int counter; +}; + +static int simc_serial_getc(struct udevice *dev) +{ + char ch = 0; + + simc_read(0, &ch, sizeof(ch)); + + return ch; +} + +static int simc_serial_putc(struct udevice *dev, const char ch) +{ + char str[2] = {0}; + + str[0] = ch; + simc_write(1, str, 1); + + return 0; +} + +static int simc_serial_pending(struct udevice *dev, bool input) +{ + struct simc_serial_priv *priv = dev_get_priv(dev); + + if (input) + return priv->counter++ & 1; + return false; +} + +static const struct dm_serial_ops simc_serial_ops = { + .putc = simc_serial_putc, + .getc = simc_serial_getc, + .pending = simc_serial_pending, +}; + +U_BOOT_DRIVER(simc_serial) = { + .name = "serial_xtensa_semihosting", + .id = UCLASS_SERIAL, + .priv_auto = sizeof(struct simc_serial_priv), + .ops = &simc_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRVINFO(simc_serial) = { + .name = "serial_xtensa_semihosting", +}; + +#if CONFIG_IS_ENABLED(DEBUG_UART_XTENSA_SEMIHOSTING) +#include <debug_uart.h> + +static inline void _debug_uart_init(void) +{ +} + +static inline void _debug_uart_putc(int c) +{ + simc_serial_putc(NULL, c); +} + +DEBUG_UART_FUNCS +#endif

On Sun, May 19, 2024 at 1:53 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Add xtensa semihosting driver.
It can't use regular semihosting driver as Xtensa's has it's own semihosting ABI.
Note that semihosting supports puts in serial but I never managed to get it work, so it's putc only for now.
I wonder, what were the issues that you experienced?
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
drivers/serial/Kconfig | 18 ++++++- drivers/serial/Makefile | 1 + drivers/serial/serial_xtensa_semihosting.c | 79 ++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 1fe4607598eb..3a1e5a6f2877 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -501,6 +501,15 @@ config DEBUG_UART_MT7620 driver will be available until the real driver model serial is running.
+config DEBUG_UART_XTENSA_SEMIHOSTING
bool "Xtensa semihosting"
depends on XTENSA_SEMIHOSTING_SERIAL
help
Select this to enable the debug UART using the Xtensa semihosting driver.
This provides basic serial output from the console without needing to
start up driver model. The driver will be available until the real
driver model serial is running.
endchoice
config DEBUG_UART_BASE @@ -936,7 +945,6 @@ config SH_SCIF_CLK_FREQ config SEMIHOSTING_SERIAL bool "Semihosting UART support" depends on SEMIHOSTING && !SERIAL_RX_BUFFER
imply SERIAL_PUTS help Select this to enable a serial UART using semihosting. Special halt instructions will be issued which an external debugger (such as a
@@ -1115,6 +1123,14 @@ config XEN_SERIAL If built without DM support, then requires Xen to be built with CONFIG_VERBOSE_DEBUG.
+config XTENSA_SEMIHOSTING_SERIAL
bool "Xtensa Semihosting UART support"
depends on DM_SERIAL
depends on XTENSA_SEMIHOSTING
imply SERIAL_PUTS
help
Select this to enable a serial UART using Xtensa semihosting.
choice prompt "Console port" default 8xx_CONS_SMC1 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index dbe598b74064..78810f98367c 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o obj-$(CONFIG_XEN_SERIAL) += serial_xen.o +obj-$(CONFIG_XTENSA_SEMIHOSTING_SERIAL) += serial_xtensa_semihosting.o obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o
ifndef CONFIG_SPL_BUILD diff --git a/drivers/serial/serial_xtensa_semihosting.c b/drivers/serial/serial_xtensa_semihosting.c new file mode 100644 index 000000000000..1bf3c18537e7 --- /dev/null +++ b/drivers/serial/serial_xtensa_semihosting.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com
- */
+#include <dm.h> +#include <malloc.h> +#include <serial.h>
+#include <asm/platform/simcall.h>
+/**
- struct simc_serial_priv - Semihosting serial private data
- @counter: Counter used to fake pending every other call
- */
+struct simc_serial_priv {
unsigned int counter;
+};
+static int simc_serial_getc(struct udevice *dev) +{
char ch = 0;
simc_read(0, &ch, sizeof(ch));
return ch;
+}
+static int simc_serial_putc(struct udevice *dev, const char ch) +{
char str[2] = {0};
Why does it need to be an array if only the first element is ever used?
str[0] = ch;
simc_write(1, str, 1);
return 0;
+}
+static int simc_serial_pending(struct udevice *dev, bool input) +{
struct simc_serial_priv *priv = dev_get_priv(dev);
if (input)
return priv->counter++ & 1;
This can result in blocking the whole CPU thread of the emulator when used with simcall-based semihosting and there's no input actually available. Not sure how it would behave with the gdbio. I think something like the following:
if (input) { int res = simc_poll(0); return res < 0 ? priv->counter++ & 1 : res; }
could be used here to avoid that.
return false;
+}
+static const struct dm_serial_ops simc_serial_ops = {
.putc = simc_serial_putc,
.getc = simc_serial_getc,
.pending = simc_serial_pending,
+};
+U_BOOT_DRIVER(simc_serial) = {
.name = "serial_xtensa_semihosting",
.id = UCLASS_SERIAL,
.priv_auto = sizeof(struct simc_serial_priv),
.ops = &simc_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
+};
+U_BOOT_DRVINFO(simc_serial) = {
.name = "serial_xtensa_semihosting",
+};
+#if CONFIG_IS_ENABLED(DEBUG_UART_XTENSA_SEMIHOSTING) +#include <debug_uart.h>
+static inline void _debug_uart_init(void) +{ +}
+static inline void _debug_uart_putc(int c) +{
simc_serial_putc(NULL, c);
+}
+DEBUG_UART_FUNCS +#endif
-- 2.43.0

在2024年5月21日五月 上午3:31,Max Filippov写道:
On Sun, May 19, 2024 at 1:53 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Add xtensa semihosting driver.
It can't use regular semihosting driver as Xtensa's has it's own semihosting ABI.
Note that semihosting supports puts in serial but I never managed to get it work, so it's putc only for now.
I wonder, what were the issues that you experienced?
Never mind, I got it work, it was an off-by-one error in length calculation.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
drivers/serial/Kconfig | 18 ++++++- drivers/serial/Makefile | 1 + drivers/serial/serial_xtensa_semihosting.c | 79 ++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 1fe4607598eb..3a1e5a6f2877 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -501,6 +501,15 @@ config DEBUG_UART_MT7620 driver will be available until the real driver model serial is running.
+config DEBUG_UART_XTENSA_SEMIHOSTING
bool "Xtensa semihosting"
depends on XTENSA_SEMIHOSTING_SERIAL
help
Select this to enable the debug UART using the Xtensa semihosting driver.
This provides basic serial output from the console without needing to
start up driver model. The driver will be available until the real
driver model serial is running.
endchoice
config DEBUG_UART_BASE @@ -936,7 +945,6 @@ config SH_SCIF_CLK_FREQ config SEMIHOSTING_SERIAL bool "Semihosting UART support" depends on SEMIHOSTING && !SERIAL_RX_BUFFER
imply SERIAL_PUTS help Select this to enable a serial UART using semihosting. Special halt instructions will be issued which an external debugger (such as a
@@ -1115,6 +1123,14 @@ config XEN_SERIAL If built without DM support, then requires Xen to be built with CONFIG_VERBOSE_DEBUG.
+config XTENSA_SEMIHOSTING_SERIAL
bool "Xtensa Semihosting UART support"
depends on DM_SERIAL
depends on XTENSA_SEMIHOSTING
imply SERIAL_PUTS
help
Select this to enable a serial UART using Xtensa semihosting.
choice prompt "Console port" default 8xx_CONS_SMC1 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index dbe598b74064..78810f98367c 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_MT7620_SERIAL) += serial_mt7620.o obj-$(CONFIG_HTIF_CONSOLE) += serial_htif.o obj-$(CONFIG_SIFIVE_SERIAL) += serial_sifive.o obj-$(CONFIG_XEN_SERIAL) += serial_xen.o +obj-$(CONFIG_XTENSA_SEMIHOSTING_SERIAL) += serial_xtensa_semihosting.o obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o
ifndef CONFIG_SPL_BUILD diff --git a/drivers/serial/serial_xtensa_semihosting.c b/drivers/serial/serial_xtensa_semihosting.c new file mode 100644 index 000000000000..1bf3c18537e7 --- /dev/null +++ b/drivers/serial/serial_xtensa_semihosting.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com
- */
+#include <dm.h> +#include <malloc.h> +#include <serial.h>
+#include <asm/platform/simcall.h>
+/**
- struct simc_serial_priv - Semihosting serial private data
- @counter: Counter used to fake pending every other call
- */
+struct simc_serial_priv {
unsigned int counter;
+};
+static int simc_serial_getc(struct udevice *dev) +{
char ch = 0;
simc_read(0, &ch, sizeof(ch));
return ch;
+}
+static int simc_serial_putc(struct udevice *dev, const char ch) +{
char str[2] = {0};
Why does it need to be an array if only the first element is ever used?
I want to ensure it's null terminated but it turns out to be unnecessay, will drop in next version.
str[0] = ch;
simc_write(1, str, 1);
return 0;
+}
+static int simc_serial_pending(struct udevice *dev, bool input) +{
struct simc_serial_priv *priv = dev_get_priv(dev);
if (input)
return priv->counter++ & 1;
This can result in blocking the whole CPU thread of the emulator when used with simcall-based semihosting and there's no input actually available. Not sure how it would behave with the gdbio. I think something like the following:
if (input) { int res = simc_poll(0); return res < 0 ? priv->counter++ & 1 : res; }
could be used here to avoid that.
That worked out, thanks.
return false;
+}
+static const struct dm_serial_ops simc_serial_ops = {
.putc = simc_serial_putc,
.getc = simc_serial_getc,
.pending = simc_serial_pending,
+};
+U_BOOT_DRIVER(simc_serial) = {
.name = "serial_xtensa_semihosting",
.id = UCLASS_SERIAL,
.priv_auto = sizeof(struct simc_serial_priv),
.ops = &simc_serial_ops,
.flags = DM_FLAG_PRE_RELOC,
+};
+U_BOOT_DRVINFO(simc_serial) = {
.name = "serial_xtensa_semihosting",
+};
+#if CONFIG_IS_ENABLED(DEBUG_UART_XTENSA_SEMIHOSTING) +#include <debug_uart.h>
+static inline void _debug_uart_init(void) +{ +}
+static inline void _debug_uart_putc(int c) +{
simc_serial_putc(NULL, c);
+}
+DEBUG_UART_FUNCS +#endif
-- 2.43.0
-- Thanks. -- Max

Implement various CPU related functions. I'm actually just using it to get cpu clock frequency.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- drivers/cpu/Kconfig | 6 +++ drivers/cpu/Makefile | 1 + drivers/cpu/xtensa_cpu.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+)
diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig index 1c3c810651ef..5c06cd9f60e8 100644 --- a/drivers/cpu/Kconfig +++ b/drivers/cpu/Kconfig @@ -33,3 +33,9 @@ config CPU_MICROBLAZE select XILINX_MICROBLAZE0_PVR help Support CPU cores for Microblaze architecture. + +config CPU_XTENSA + bool "Enable Xtensa CPU driver" + depends on CPU && XTENSA + help + Support CPU cores for Xtensa architecture. diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile index d4bbf6fa5e05..bc75d9b974e8 100644 --- a/drivers/cpu/Makefile +++ b/drivers/cpu/Makefile @@ -14,4 +14,5 @@ obj-$(CONFIG_CPU_IMX) += imx8_cpu.o obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o obj-$(CONFIG_CPU_MICROBLAZE) += microblaze_cpu.o +obj-$(CONFIG_CPU_XTENSA) += xtensa_cpu.o obj-$(CONFIG_SANDBOX) += cpu_sandbox.o diff --git a/drivers/cpu/xtensa_cpu.c b/drivers/cpu/xtensa_cpu.c new file mode 100644 index 000000000000..fbb561dd6128 --- /dev/null +++ b/drivers/cpu/xtensa_cpu.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#include <clk.h> +#include <cpu.h> +#include <dm.h> +#include <errno.h> +#include <linux/bitops.h> +#include <linux/err.h> + +#include <asm/arch/core.h> + +static int xtensa_cpu_get_desc(const struct udevice *dev, char *buf, int size) +{ + const char *cpu = XCHAL_CORE_ID; + + if (!cpu || size < (strlen(cpu) + 1)) + return -ENOSPC; + + strcpy(buf, cpu); + + return 0; +} + +static int xtensa_cpu_get_info(const struct udevice *dev, struct cpu_info *info) +{ + struct cpu_plat *plat = dev_get_parent_plat(dev); + + info->cpu_freq = plat->timebase_freq; + +#if XCHAL_HAVE_PTP_MMU + info->features |= BIT(CPU_FEAT_MMU); +#endif +#if XCHAL_ICACHE_SIZE || XCHAL_DCACHE_SIZE + info->features |= BIT(CPU_FEAT_L1_CACHE); +#endif + + return 0; +} + +static int xtensa_cpu_get_count(const struct udevice *dev) +{ + ofnode node; + int num = 0; + + ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { + const char *device_type; + + /* skip if hart is marked as not available in the device tree */ + if (!ofnode_is_enabled(node)) + continue; + + device_type = ofnode_read_string(node, "device_type"); + if (!device_type) + continue; + if (strcmp(device_type, "cpu") == 0) + num++; + } + + return num; +} + +static int xtensa_cpu_bind(struct udevice *dev) +{ + struct cpu_plat *plat = dev_get_parent_plat(dev); + + plat->cpu_id = dev_read_addr(dev); + + return 0; +} + +static int xtensa_cpu_probe(struct udevice *dev) +{ + int ret = 0; + struct clk clk; + struct cpu_plat *plat = dev_get_parent_plat(dev); + + asm volatile ("rsr %0, 176\n" + "rsr %1, 208\n" + : "=r"(plat->id[0]), "=r"(plat->id[1])); + + /* Get a clock if it exists */ + ret = clk_get_by_index(dev, 0, &clk); + if (!ret) { + ret = clk_enable(&clk); + if (ret && (ret != -ENOSYS || ret != -ENOTSUPP)) + return ret; + ret = clk_get_rate(&clk); + if (!IS_ERR_VALUE(ret)) + plat->timebase_freq = ret; + } + + return 0; +} + +static const struct cpu_ops xtensa_cpu_ops = { + .get_desc = xtensa_cpu_get_desc, + .get_info = xtensa_cpu_get_info, + .get_count = xtensa_cpu_get_count, +}; + +static const struct udevice_id xtensa_cpu_ids[] = { + { .compatible = "cdns,xtensa-cpu" }, + { } +}; + +U_BOOT_DRIVER(xtensa_cpu) = { + .name = "xtensa_cpu", + .id = UCLASS_CPU, + .of_match = xtensa_cpu_ids, + .bind = xtensa_cpu_bind, + .probe = xtensa_cpu_probe, + .ops = &xtensa_cpu_ops, + .flags = DM_FLAG_PRE_RELOC, +};

It is required to get it xtensa OF_UPSTREAM work.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- dts/upstream/src/xtensa/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/dts/upstream/src/xtensa/Makefile b/dts/upstream/src/xtensa/Makefile new file mode 100644 index 000000000000..2a81acb32bc3 --- /dev/null +++ b/dts/upstream/src/xtensa/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0+ + +include $(srctree)/scripts/Makefile.dts + +targets += $(dtb-y) + +# Add any required device tree compiler flags here +DTC_FLAGS += -a 0x8 + +PHONY += dtbs +dtbs: $(addprefix $(obj)/, $(dtb-y)) + @: + +clean-files := *.dtb *.dtbo */*.dtb */*.dtbo

On Mon, 20 May 2024 at 02:24, Jiaxun Yang jiaxun.yang@flygoat.com wrote:
It is required to get it xtensa OF_UPSTREAM work.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
dts/upstream/src/xtensa/Makefile | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Reviewed-by: Sumit Garg sumit.garg@linaro.org
-Sumit
diff --git a/dts/upstream/src/xtensa/Makefile b/dts/upstream/src/xtensa/Makefile new file mode 100644 index 000000000000..2a81acb32bc3 --- /dev/null +++ b/dts/upstream/src/xtensa/Makefile @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0+
+include $(srctree)/scripts/Makefile.dts
+targets += $(dtb-y)
+# Add any required device tree compiler flags here +DTC_FLAGS += -a 0x8
+PHONY += dtbs +dtbs: $(addprefix $(obj)/, $(dtb-y))
@:
+clean-files := *.dtb *.dtbo */*.dtb */*.dtbo
-- 2.43.0

Introduce the new board, define every bits.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- arch/xtensa/Kconfig | 5 +++ board/emulation/qemu-xtensa/Kconfig | 41 +++++++++++++++++++++ board/emulation/qemu-xtensa/MAINTAINERS | 7 ++++ board/emulation/qemu-xtensa/Makefile | 5 +++ board/emulation/qemu-xtensa/qemu-xtensa.c | 60 +++++++++++++++++++++++++++++++ configs/qemu-xtensa-dc232b_defconfig | 32 +++++++++++++++++ include/configs/qemu-xtensa.h | 34 ++++++++++++++++++ 7 files changed, 184 insertions(+)
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 4afd56bca095..70eebb4bd22f 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -15,6 +15,10 @@ config TARGET_XTFPGA bool "Support XTFPGA" select BOARD_POSTCLK_INIT
+config TARGET_QEMU_XTENSA + bool "Support QEMU Xtensa Virt Board" + select BOARD_LATE_INIT + endchoice
config SYS_ICACHE_OFF @@ -69,5 +73,6 @@ config XTENSA_SIMCALL_GDBIO endchoice
source "board/cadence/xtfpga/Kconfig" +source "board/emulation/qemu-xtensa/Kconfig"
endmenu diff --git a/board/emulation/qemu-xtensa/Kconfig b/board/emulation/qemu-xtensa/Kconfig new file mode 100644 index 000000000000..df9142af0875 --- /dev/null +++ b/board/emulation/qemu-xtensa/Kconfig @@ -0,0 +1,41 @@ +if TARGET_QEMU_XTENSA + +config SYS_BOARD + default "qemu-xtensa" + +config SYS_VENDOR + default "emulation" + +config SYS_CONFIG_NAME + default "qemu-xtensa" + +config TEXT_BASE + default 0xfe000000 + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + select BOARD_EARLY_INIT_F + select DM + select CPU + select CPU_XTENSA + select CLK + select DM_SERIAL + select XTENSA_SEMIHOSTING + select XTENSA_SEMIHOSTING_SERIAL + imply BLK + imply VIRTIO + imply VIRTIO_PCI + imply VIRTIO_NET + imply VIRTIO_BLK + imply E1000 + imply PCI + imply PCI_INIT_R + imply NVME_PCI + imply PCIE_ECAM_GENERIC + imply SCSI + imply REMAKE_ELF + select OF_CONTROL + select OF_UPSTREAM + imply CMD_DM + +endif diff --git a/board/emulation/qemu-xtensa/MAINTAINERS b/board/emulation/qemu-xtensa/MAINTAINERS new file mode 100644 index 000000000000..851ef596f611 --- /dev/null +++ b/board/emulation/qemu-xtensa/MAINTAINERS @@ -0,0 +1,7 @@ +QEMU XTENSA 'VIRT' BOARD +M: Jiaxun Yang jiaxun.yang@flygoat.com +S: Maintained +F: board/emulation/qemu-xtensa/ +F: board/emulation/common/ +F: include/configs/qemu-riscv.h +F: configs/qemu-xtensa-dc232b_defconfig diff --git a/board/emulation/qemu-xtensa/Makefile b/board/emulation/qemu-xtensa/Makefile new file mode 100644 index 000000000000..0f33a65f6c6b --- /dev/null +++ b/board/emulation/qemu-xtensa/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2024, Jiaxun Yang jiaxun.yang@flygoat.com + +obj-y += qemu-xtensa.o diff --git a/board/emulation/qemu-xtensa/qemu-xtensa.c b/board/emulation/qemu-xtensa/qemu-xtensa.c new file mode 100644 index 000000000000..0ca83341c25c --- /dev/null +++ b/board/emulation/qemu-xtensa/qemu-xtensa.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng bmeng.cn@gmail.com + */ + +#include <dm.h> +#include <cpu.h> +#include <log.h> +#include <init.h> +#include <usb.h> +#include <virtio_types.h> +#include <virtio.h> + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + return 0; +} + +unsigned long get_board_sys_clk(void) +{ + return gd->cpu_clk ? gd->cpu_clk : 40000000; +} + +int dram_init(void) +{ + return fdtdec_setup_mem_size_base(); +} + +int board_early_init_f(void) +{ + struct cpu_plat *cpu_plat; + struct udevice *cpu = cpu_get_current_dev(); + + if (!cpu) + return -ENODEV; + + cpu_plat = dev_get_parent_plat(cpu); + if (!cpu_plat) + return -ENODEV; + + gd->cpu_clk = cpu_plat->timebase_freq; + return 0; +} + +int board_late_init(void) +{ + /* start usb so that usb keyboard can be used as input device */ + if (CONFIG_IS_ENABLED(USB_KEYBOARD)) + usb_init(); + + /* + * Make sure virtio bus is enumerated so that peripherals + * on the virtio bus can be discovered by their drivers + */ + virtio_init(); + + return 0; +} diff --git a/configs/qemu-xtensa-dc232b_defconfig b/configs/qemu-xtensa-dc232b_defconfig new file mode 100644 index 000000000000..12d5ca9399ae --- /dev/null +++ b/configs/qemu-xtensa-dc232b_defconfig @@ -0,0 +1,32 @@ +CONFIG_XTENSA=y +CONFIG_SYS_CPU="dc232b" +CONFIG_SYS_MALLOC_LEN=0x40000 +CONFIG_SYS_MALLOC_F_LEN=0x400 +CONFIG_ENV_SIZE=0x20000 +CONFIG_DEFAULT_DEVICE_TREE="virt" +CONFIG_SYS_MONITOR_LEN=262144 +CONFIG_SYS_LOAD_ADDR=0x02000000 +CONFIG_TARGET_QEMU_XTENSA=y +CONFIG_REMAKE_ELF=y +CONFIG_SYS_MONITOR_BASE=0xF6000000 +CONFIG_DYNAMIC_SYS_CLK_FREQ=y +CONFIG_SHOW_BOOT_PROGRESS=y +CONFIG_BOOTDELAY=10 +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Autobooting in %d seconds, press <SPACE> to stop\n" +CONFIG_AUTOBOOT_STOP_STR=" " +CONFIG_SYS_PBSIZE=1049 +CONFIG_SYS_MALLOC_BOOTPARAMS=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="U-Boot> " +CONFIG_CMD_ASKENV=y +CONFIG_CRC32_VERIFY=y +CONFIG_CMD_MX_CYCLIC=y +CONFIG_CMD_SAVES=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_CMD_DIAG=y +CONFIG_USE_BOOTFILE=y +CONFIG_BOOTFILE="uImage" +CONFIG_VERSION_VARIABLE=y +CONFIG_SYSRESET=y diff --git a/include/configs/qemu-xtensa.h b/include/configs/qemu-xtensa.h new file mode 100644 index 000000000000..56e1cd40e1a6 --- /dev/null +++ b/include/configs/qemu-xtensa.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2007-2013 Tensilica, Inc. + * Copyright (C) 2014 - 2016 Cadence Design Systems Inc. + * Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include <asm/arch/core.h> +#include <asm/addrspace.h> +#include <asm/config.h> + +#if XCHAL_HAVE_PTP_MMU +#define CFG_SYS_MEMORY_BASE \ + (XCHAL_VECBASE_RESET_VADDR - XCHAL_VECBASE_RESET_PADDR) +#define CFG_SYS_IO_BASE 0xf0000000 +#else +#define CFG_SYS_MEMORY_BASE 0x60000000 +#define CFG_SYS_IO_BASE 0x90000000 +#define CFG_MAX_MEM_MAPPED 0x10000000 +#endif + +#define CFG_SYS_SDRAM_SIZE 0x80000000 +#define CFG_SYS_SDRAM_BASE MEMADDR(0x00000000) + +#if defined(CFG_MAX_MEM_MAPPED) && \ + CFG_MAX_MEM_MAPPED < CFG_SYS_SDRAM_SIZE +#define XTENSA_SYS_TEXT_ADDR \ + (MEMADDR(CFG_MAX_MEM_MAPPED) - CONFIG_SYS_MONITOR_LEN) +#endif + +#endif /* __CONFIG_H */

On Sun, May 19, 2024 at 1:54 PM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
Introduce the new board, define every bits.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
arch/xtensa/Kconfig | 5 +++ board/emulation/qemu-xtensa/Kconfig | 41 +++++++++++++++++++++ board/emulation/qemu-xtensa/MAINTAINERS | 7 ++++ board/emulation/qemu-xtensa/Makefile | 5 +++ board/emulation/qemu-xtensa/qemu-xtensa.c | 60 +++++++++++++++++++++++++++++++ configs/qemu-xtensa-dc232b_defconfig | 32 +++++++++++++++++ include/configs/qemu-xtensa.h | 34 ++++++++++++++++++ 7 files changed, 184 insertions(+)
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 4afd56bca095..70eebb4bd22f 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -15,6 +15,10 @@ config TARGET_XTFPGA bool "Support XTFPGA" select BOARD_POSTCLK_INIT
+config TARGET_QEMU_XTENSA
bool "Support QEMU Xtensa Virt Board"
select BOARD_LATE_INIT
endchoice
config SYS_ICACHE_OFF @@ -69,5 +73,6 @@ config XTENSA_SIMCALL_GDBIO endchoice
source "board/cadence/xtfpga/Kconfig" +source "board/emulation/qemu-xtensa/Kconfig"
endmenu diff --git a/board/emulation/qemu-xtensa/Kconfig b/board/emulation/qemu-xtensa/Kconfig new file mode 100644 index 000000000000..df9142af0875 --- /dev/null +++ b/board/emulation/qemu-xtensa/Kconfig @@ -0,0 +1,41 @@ +if TARGET_QEMU_XTENSA
+config SYS_BOARD
default "qemu-xtensa"
+config SYS_VENDOR
default "emulation"
+config SYS_CONFIG_NAME
default "qemu-xtensa"
+config TEXT_BASE
default 0xfe000000
+config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select BOARD_EARLY_INIT_F
select DM
select CPU
select CPU_XTENSA
select CLK
select DM_SERIAL
select XTENSA_SEMIHOSTING
select XTENSA_SEMIHOSTING_SERIAL
imply BLK
imply VIRTIO
imply VIRTIO_PCI
imply VIRTIO_NET
imply VIRTIO_BLK
imply E1000
imply PCI
imply PCI_INIT_R
imply NVME_PCI
imply PCIE_ECAM_GENERIC
imply SCSI
imply REMAKE_ELF
select OF_CONTROL
select OF_UPSTREAM
imply CMD_DM
+endif diff --git a/board/emulation/qemu-xtensa/MAINTAINERS b/board/emulation/qemu-xtensa/MAINTAINERS new file mode 100644 index 000000000000..851ef596f611 --- /dev/null +++ b/board/emulation/qemu-xtensa/MAINTAINERS @@ -0,0 +1,7 @@ +QEMU XTENSA 'VIRT' BOARD +M: Jiaxun Yang jiaxun.yang@flygoat.com +S: Maintained +F: board/emulation/qemu-xtensa/ +F: board/emulation/common/ +F: include/configs/qemu-riscv.h
This must be qemu-xtensa.h, right?
+F: configs/qemu-xtensa-dc232b_defconfig diff --git a/board/emulation/qemu-xtensa/Makefile b/board/emulation/qemu-xtensa/Makefile new file mode 100644 index 000000000000..0f33a65f6c6b --- /dev/null +++ b/board/emulation/qemu-xtensa/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2024, Jiaxun Yang jiaxun.yang@flygoat.com
+obj-y += qemu-xtensa.o diff --git a/board/emulation/qemu-xtensa/qemu-xtensa.c b/board/emulation/qemu-xtensa/qemu-xtensa.c new file mode 100644 index 000000000000..0ca83341c25c --- /dev/null +++ b/board/emulation/qemu-xtensa/qemu-xtensa.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0+ +/*
- Copyright (C) 2018, Bin Meng bmeng.cn@gmail.com
- */
+#include <dm.h> +#include <cpu.h> +#include <log.h> +#include <init.h> +#include <usb.h> +#include <virtio_types.h> +#include <virtio.h>
+DECLARE_GLOBAL_DATA_PTR;
+int board_init(void) +{
return 0;
+}
+unsigned long get_board_sys_clk(void) +{
return gd->cpu_clk ? gd->cpu_clk : 40000000;
+}
+int dram_init(void) +{
return fdtdec_setup_mem_size_base();
+}
+int board_early_init_f(void) +{
struct cpu_plat *cpu_plat;
struct udevice *cpu = cpu_get_current_dev();
if (!cpu)
return -ENODEV;
cpu_plat = dev_get_parent_plat(cpu);
if (!cpu_plat)
return -ENODEV;
gd->cpu_clk = cpu_plat->timebase_freq;
return 0;
+}
+int board_late_init(void) +{
/* start usb so that usb keyboard can be used as input device */
if (CONFIG_IS_ENABLED(USB_KEYBOARD))
usb_init();
/*
* Make sure virtio bus is enumerated so that peripherals
* on the virtio bus can be discovered by their drivers
*/
virtio_init();
return 0;
+} diff --git a/configs/qemu-xtensa-dc232b_defconfig b/configs/qemu-xtensa-dc232b_defconfig new file mode 100644 index 000000000000..12d5ca9399ae --- /dev/null +++ b/configs/qemu-xtensa-dc232b_defconfig @@ -0,0 +1,32 @@ +CONFIG_XTENSA=y +CONFIG_SYS_CPU="dc232b" +CONFIG_SYS_MALLOC_LEN=0x40000 +CONFIG_SYS_MALLOC_F_LEN=0x400 +CONFIG_ENV_SIZE=0x20000 +CONFIG_DEFAULT_DEVICE_TREE="virt" +CONFIG_SYS_MONITOR_LEN=262144 +CONFIG_SYS_LOAD_ADDR=0x02000000 +CONFIG_TARGET_QEMU_XTENSA=y +CONFIG_REMAKE_ELF=y +CONFIG_SYS_MONITOR_BASE=0xF6000000 +CONFIG_DYNAMIC_SYS_CLK_FREQ=y +CONFIG_SHOW_BOOT_PROGRESS=y +CONFIG_BOOTDELAY=10 +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Autobooting in %d seconds, press <SPACE> to stop\n" +CONFIG_AUTOBOOT_STOP_STR=" " +CONFIG_SYS_PBSIZE=1049 +CONFIG_SYS_MALLOC_BOOTPARAMS=y +CONFIG_HUSH_PARSER=y +CONFIG_SYS_PROMPT="U-Boot> " +CONFIG_CMD_ASKENV=y +CONFIG_CRC32_VERIFY=y +CONFIG_CMD_MX_CYCLIC=y +CONFIG_CMD_SAVES=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_CMD_DIAG=y +CONFIG_USE_BOOTFILE=y +CONFIG_BOOTFILE="uImage" +CONFIG_VERSION_VARIABLE=y +CONFIG_SYSRESET=y diff --git a/include/configs/qemu-xtensa.h b/include/configs/qemu-xtensa.h new file mode 100644 index 000000000000..56e1cd40e1a6 --- /dev/null +++ b/include/configs/qemu-xtensa.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/*
- Copyright (C) 2007-2013 Tensilica, Inc.
- Copyright (C) 2014 - 2016 Cadence Design Systems Inc.
- Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com
- */
+#ifndef __CONFIG_H +#define __CONFIG_H
+#include <asm/arch/core.h> +#include <asm/addrspace.h> +#include <asm/config.h>
+#if XCHAL_HAVE_PTP_MMU +#define CFG_SYS_MEMORY_BASE \
(XCHAL_VECBASE_RESET_VADDR - XCHAL_VECBASE_RESET_PADDR)
+#define CFG_SYS_IO_BASE 0xf0000000 +#else +#define CFG_SYS_MEMORY_BASE 0x60000000 +#define CFG_SYS_IO_BASE 0x90000000 +#define CFG_MAX_MEM_MAPPED 0x10000000 +#endif
+#define CFG_SYS_SDRAM_SIZE 0x80000000
+#define CFG_SYS_SDRAM_BASE MEMADDR(0x00000000)
I'm not sure what CFG_SYS_IO_BASE means for the virt machine, but it looks like in the noMMU case SDRAM is going to overlap the IO range with the above base addresses and sizes. And from QEMU monitor I see the following address space distribution in the virt machine with a noMMU core:
address-space: memory 0000000000000000-ffffffffffffffff (prio 0, i/o): system 000000003ffe0000-000000003fffffff (prio 0, ram): xtensa.dataram0 0000000040000000-000000004001ffff (prio 0, ram): xtensa.instram0 0000000050000000-0000000053ffffff (prio 0, ram): xtensa.sysrom0 0000000060000000-00000000dfffffff (prio 0, ram): xtensa.sysram0 00000000f0000000-00000000f000ffff (prio 0, i/o): alias pcie-pio @gpex_ioport_window 0000000000000000-000000000000ffff 00000000f0100000-00000000f3ffffff (prio 0, i/o): alias pcie-ecam @pcie-mmcfg-mmio 0000000000000000-0000000003efffff 00000000f4000000-00000000fbffffff (prio 0, i/o): alias pcie-mmio @gpex_mmio_window 00000000f4000000-00000000fbffffff
i.e. there's no IO at the address 0x90000000.

在2024年5月21日五月 上午8:35,Max Filippov写道: [...]
+++ b/board/emulation/qemu-xtensa/MAINTAINERS @@ -0,0 +1,7 @@ +QEMU XTENSA 'VIRT' BOARD +M: Jiaxun Yang jiaxun.yang@flygoat.com +S: Maintained +F: board/emulation/qemu-xtensa/ +F: board/emulation/common/ +F: include/configs/qemu-riscv.h
This must be qemu-xtensa.h, right?
Ah yes :-)
Do you mind me to give you a M: entry? I'm pretty dumb to Xtensa stuff so it deserves an M from people know Xtensa better.
[...]
I'm not sure what CFG_SYS_IO_BASE means for the virt machine, but it looks like in the noMMU case SDRAM is going to overlap the IO range with the above base addresses and sizes. And from QEMU monitor I see the following address space distribution in the virt machine with a noMMU core:
So CFG_SYS_IO_BASE means physical address left for I/O with 1:1 mapping from virtual address. for PTP MMU I handled it in:
[PATCH 03/10] xtensa: Implement phys virt conversion for PTP_MMU
Can you confirm if noMMU core is doing the same on VA-PA mapping?
If so, that patch needs to be expanded to include noMMU as well.
Thanks - Jiaxun
address-space: memory 0000000000000000-ffffffffffffffff (prio 0, i/o): system 000000003ffe0000-000000003fffffff (prio 0, ram): xtensa.dataram0 0000000040000000-000000004001ffff (prio 0, ram): xtensa.instram0 0000000050000000-0000000053ffffff (prio 0, ram): xtensa.sysrom0 0000000060000000-00000000dfffffff (prio 0, ram): xtensa.sysram0 00000000f0000000-00000000f000ffff (prio 0, i/o): alias pcie-pio @gpex_ioport_window 0000000000000000-000000000000ffff 00000000f0100000-00000000f3ffffff (prio 0, i/o): alias pcie-ecam @pcie-mmcfg-mmio 0000000000000000-0000000003efffff 00000000f4000000-00000000fbffffff (prio 0, i/o): alias pcie-mmio @gpex_mmio_window 00000000f4000000-00000000fbffffff
i.e. there's no IO at the address 0x90000000.
-- Thanks. -- Max

On Tue, May 21, 2024 at 1:20 AM Jiaxun Yang jiaxun.yang@flygoat.com wrote:
在2024年5月21日五月 上午8:35,Max Filippov写道:
+++ b/board/emulation/qemu-xtensa/MAINTAINERS @@ -0,0 +1,7 @@ +QEMU XTENSA 'VIRT' BOARD +M: Jiaxun Yang jiaxun.yang@flygoat.com +S: Maintained +F: board/emulation/qemu-xtensa/ +F: board/emulation/common/ +F: include/configs/qemu-riscv.h
This must be qemu-xtensa.h, right?
Ah yes :-)
Do you mind me to give you a M: entry?
Sure you can add me as a co-maintainer for this board.
I'm not sure what CFG_SYS_IO_BASE means for the virt machine, but it looks like in the noMMU case SDRAM is going to overlap the IO range with the above base addresses and sizes. And from QEMU monitor I see the following address space distribution in the virt machine with a noMMU core:
So CFG_SYS_IO_BASE means physical address left for I/O with 1:1 mapping from virtual address. for PTP MMU I handled it in:
[PATCH 03/10] xtensa: Implement phys virt conversion for PTP_MMU
Can you confirm if noMMU core is doing the same on VA-PA mapping?
So far all xtensa cores except those that have MMUv2 (like dc232b) come out of reset with identity mapping between virtual and physical addresses.

Introduce the board and provide instructions on how to get it work.
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com --- doc/board/emulation/index.rst | 1 + doc/board/emulation/qemu-xtensa.rst | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+)
diff --git a/doc/board/emulation/index.rst b/doc/board/emulation/index.rst index d3d6b8f3d86b..98a0b26ad245 100644 --- a/doc/board/emulation/index.rst +++ b/doc/board/emulation/index.rst @@ -14,3 +14,4 @@ Emulation qemu-ppce500 qemu-riscv qemu-x86 + qemu-xtensa diff --git a/doc/board/emulation/qemu-xtensa.rst b/doc/board/emulation/qemu-xtensa.rst new file mode 100644 index 000000000000..fdab6d7c439d --- /dev/null +++ b/doc/board/emulation/qemu-xtensa.rst @@ -0,0 +1,33 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright (C) 2024 Jiaxun Yang jiaxun.yang@flygoat.com + +QEMU Xtensa +=========== + +QEMU for Xtensa supports a special 'virt' machine designed for emulation and +virtualization purposes. This document describes how to run U-Boot under it. + +The QEMU virt machine models a generic Xtensa virtual machine with PCI Bus +and Xtensa ISS simcall semihosting support. It supports many different Xtensa +CPU configuration. Currently, only dc232b variant is tested against U-Boot. + +Building U-Boot +--------------- +Set the CROSS_COMPILE environment variable as usual, and run: + + make qemu-xtensa-dc232b_defconfig + make + +Note that Xtensa's toolchain is bounded to CPU configuration, you must use +the toolchain built for exactly the same CPU configuration as you selected +in U-Boot. + +Running U-Boot +-------------- +The minimal QEMU command line to get U-Boot up and running is: + + qemu-system-xtensa -nographic -machine virt -cpu dc232b -semihosting -kernel ./u-boot.elf + +You many change cpu option to match your U-Boot CPU type configuration. +semihosting option is mandatory because this is the only way to interact +with U-Boot in command line.
participants (3)
-
Jiaxun Yang
-
Max Filippov
-
Sumit Garg