From 770a8eef3e27a5dc16e286cafa1a58e9201c9721 Mon Sep 17 00:00:00 2001 From: Andrii Anisov Date: Thu, 6 Aug 2020 12:42:47 +0300 Subject: [PATCH] board: Introduce xenguest_arm64 board Introduce a minimal Xen guest board running as a virtual machine under Xen Project's hypervisor [1], [2]. Part of the code is ported from Xen mini-os and also uses work initially done by different authors from NXP: please see relevant files for their copyrights. [1] https://xenbits.xen.org [2] https://wiki.xenproject.org/ Signed-off-by: Andrii Anisov Signed-off-by: Oleksandr Andrushchenko Signed-off-by: Anastasiia Lukianenko --- arch/arm/Kconfig | 7 + arch/arm/cpu/armv8/Makefile | 1 + arch/arm/cpu/armv8/xen/Makefile | 6 + arch/arm/cpu/armv8/xen/hypercall.S | 79 +++++++++++ arch/arm/cpu/armv8/xen/lowlevel_init.S | 33 +++++ arch/arm/include/asm/xen.h | 7 + arch/arm/include/asm/xen/hypercall.h | 22 ++++ board/xen/xenguest_arm64/Kconfig | 12 ++ board/xen/xenguest_arm64/MAINTAINERS | 7 + board/xen/xenguest_arm64/Makefile | 5 + board/xen/xenguest_arm64/xenguest_arm64.c | 152 ++++++++++++++++++++++ configs/xenguest_arm64_defconfig | 56 ++++++++ include/configs/xenguest_arm64.h | 44 +++++++ 13 files changed, 431 insertions(+) create mode 100644 arch/arm/cpu/armv8/xen/Makefile create mode 100644 arch/arm/cpu/armv8/xen/hypercall.S create mode 100644 arch/arm/cpu/armv8/xen/lowlevel_init.S create mode 100644 arch/arm/include/asm/xen.h create mode 100644 arch/arm/include/asm/xen/hypercall.h create mode 100644 board/xen/xenguest_arm64/Kconfig create mode 100644 board/xen/xenguest_arm64/MAINTAINERS create mode 100644 board/xen/xenguest_arm64/Makefile create mode 100644 board/xen/xenguest_arm64/xenguest_arm64.c create mode 100644 configs/xenguest_arm64_defconfig create mode 100644 include/configs/xenguest_arm64.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6b8a32c38d..bee626f05c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1749,6 +1749,12 @@ config TARGET_PRESIDIO_ASIC bool "Support Cortina Presidio ASIC Platform" select ARM64 +config TARGET_XENGUEST_ARM64 + bool "Xen guest ARM64" + select ARM64 + select XEN + select OF_CONTROL + select LINUX_KERNEL_IMAGE_HEADER endchoice config ARCH_SUPPORT_TFABOOT @@ -1955,6 +1961,7 @@ source "board/xilinx/Kconfig" source "board/xilinx/zynq/Kconfig" source "board/xilinx/zynqmp/Kconfig" source "board/phytium/durian/Kconfig" +source "board/xen/xenguest_arm64/Kconfig" source "arch/arm/Kconfig.debug" diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile index 7e33a183d5..93d26f9856 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -40,3 +40,4 @@ obj-$(CONFIG_TARGET_HIKEY) += hisilicon/ obj-$(CONFIG_ARMV8_PSCI) += psci.o obj-$(CONFIG_ARCH_SUNXI) += lowlevel_init.o obj-$(CONFIG_TARGET_BCMNS3) += bcmns3/ +obj-$(CONFIG_XEN) += xen/ diff --git a/arch/arm/cpu/armv8/xen/Makefile b/arch/arm/cpu/armv8/xen/Makefile new file mode 100644 index 0000000000..e3b4ae2bd4 --- /dev/null +++ b/arch/arm/cpu/armv8/xen/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) 2018 NXP +# (C) 2020 EPAM Systems Inc. + +obj-y += lowlevel_init.o hypercall.o diff --git a/arch/arm/cpu/armv8/xen/hypercall.S b/arch/arm/cpu/armv8/xen/hypercall.S new file mode 100644 index 0000000000..731256b34e --- /dev/null +++ b/arch/arm/cpu/armv8/xen/hypercall.S @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * hypercall.S + * + * Xen hypercall wrappers + * + * Stefano Stabellini , Citrix, 2012 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +/* + * The Xen hypercall calling convention is very similar to the procedure + * call standard for the ARM 64-bit architecture: the first parameter is + * passed in x0, the second in x1, the third in x2, the fourth in x3 and + * the fifth in x4. + * + * The hypercall number is passed in x16. + * + * The return value is in x0. + * + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM + * hypercall tag. + * + * Parameter structs passed to hypercalls are laid out according to + * the ARM 64-bit EABI standard. + */ + +#include + +#define XEN_HYPERCALL_TAG 0xEA1 + +#define HYPERCALL_SIMPLE(hypercall) \ +.globl HYPERVISOR_##hypercall; \ +.align 4,0x90; \ +HYPERVISOR_##hypercall: \ + mov x16, #__HYPERVISOR_##hypercall; \ + hvc XEN_HYPERCALL_TAG; \ + ret; \ + +#define HYPERCALL0 HYPERCALL_SIMPLE +#define HYPERCALL1 HYPERCALL_SIMPLE +#define HYPERCALL2 HYPERCALL_SIMPLE +#define HYPERCALL3 HYPERCALL_SIMPLE +#define HYPERCALL4 HYPERCALL_SIMPLE +#define HYPERCALL5 HYPERCALL_SIMPLE + + .text + +HYPERCALL2(xen_version); +HYPERCALL3(console_io); +HYPERCALL3(grant_table_op); +HYPERCALL2(sched_op); +HYPERCALL2(event_channel_op); +HYPERCALL2(hvm_op); +HYPERCALL2(memory_op); + diff --git a/arch/arm/cpu/armv8/xen/lowlevel_init.S b/arch/arm/cpu/armv8/xen/lowlevel_init.S new file mode 100644 index 0000000000..760e32ed76 --- /dev/null +++ b/arch/arm/cpu/armv8/xen/lowlevel_init.S @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * (C) 2017 NXP + * (C) 2020 EPAM Systems Inc. + */ + +#include + +.align 8 +.global rom_pointer +rom_pointer: + .space 32 + +/* + * Routine: save_boot_params (called after reset from start.S) + */ + +.global save_boot_params +save_boot_params: + /* The firmware provided ATAG/FDT address can be found in r2/x0 */ + adr x1, rom_pointer + stp x0, x2, [x1], #16 + stp x3, x4, [x1], #16 + + /* Returns */ + b save_boot_params_ret + +.global restore_boot_params +restore_boot_params: + adr x1, rom_pointer + ldp x0, x2, [x1], #16 + ldp x3, x4, [x1], #16 + ret diff --git a/arch/arm/include/asm/xen.h b/arch/arm/include/asm/xen.h new file mode 100644 index 0000000000..8e2ee3d64e --- /dev/null +++ b/arch/arm/include/asm/xen.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * (C) 2020 EPAM Systems Inc. + */ + +extern unsigned long rom_pointer[]; + diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h new file mode 100644 index 0000000000..a4fd077079 --- /dev/null +++ b/arch/arm/include/asm/xen/hypercall.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * hypercall.h + * + * Linux-specific hypervisor handling. + * + * Stefano Stabellini , Citrix, 2012 + */ + +#ifndef _ASM_ARM_XEN_HYPERCALL_H +#define _ASM_ARM_XEN_HYPERCALL_H + +#include + +int HYPERVISOR_xen_version(int cmd, void *arg); +int HYPERVISOR_console_io(int cmd, int count, char *str); +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); +int HYPERVISOR_sched_op(int cmd, void *arg); +int HYPERVISOR_event_channel_op(int cmd, void *arg); +unsigned long HYPERVISOR_hvm_op(int op, void *arg); +int HYPERVISOR_memory_op(unsigned int cmd, void *arg); +#endif /* _ASM_ARM_XEN_HYPERCALL_H */ diff --git a/board/xen/xenguest_arm64/Kconfig b/board/xen/xenguest_arm64/Kconfig new file mode 100644 index 0000000000..cc131ed5b9 --- /dev/null +++ b/board/xen/xenguest_arm64/Kconfig @@ -0,0 +1,12 @@ +if TARGET_XENGUEST_ARM64 + +config SYS_BOARD + default "xenguest_arm64" + +config SYS_VENDOR + default "xen" + +config SYS_CONFIG_NAME + default "xenguest_arm64" + +endif diff --git a/board/xen/xenguest_arm64/MAINTAINERS b/board/xen/xenguest_arm64/MAINTAINERS new file mode 100644 index 0000000000..787e9e0d0e --- /dev/null +++ b/board/xen/xenguest_arm64/MAINTAINERS @@ -0,0 +1,7 @@ +XEN GUEST FOR ARM64 +M: Andrii Anisov +S: Maintained +F: board/xen/xenguest_arm64/ +F: doc/board/xen/ +F: include/configs/xenguest_arm64.h +F: configs/xenguest_arm64_defconfig diff --git a/board/xen/xenguest_arm64/Makefile b/board/xen/xenguest_arm64/Makefile new file mode 100644 index 0000000000..1cf87a728f --- /dev/null +++ b/board/xen/xenguest_arm64/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2020 EPAM Systems Inc. + +obj-y := xenguest_arm64.o diff --git a/board/xen/xenguest_arm64/xenguest_arm64.c b/board/xen/xenguest_arm64/xenguest_arm64.c new file mode 100644 index 0000000000..1d1e229085 --- /dev/null +++ b/board/xen/xenguest_arm64/xenguest_arm64.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) 2013 + * David Feng + * Sharma Bhupesh + * + * (C) 2020 EPAM Systems Inc + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + return 0; +} + +/* + * Use fdt provided by Xen: according to + * https://www.kernel.org/doc/Documentation/arm64/booting.txt + * x0 is the physical address of the device tree blob (dtb) in system RAM. + * This is stored in rom_pointer during low level init. + */ +void *board_fdt_blob_setup(void) +{ + if (fdt_magic(rom_pointer[0]) != FDT_MAGIC) + return NULL; + return (void *)rom_pointer[0]; +} + +#define MAX_MEM_MAP_REGIONS 5 +static struct mm_region xen_mem_map[MAX_MEM_MAP_REGIONS]; +struct mm_region *mem_map = xen_mem_map; + +static int get_next_memory_node(const void *blob, int mem) +{ + do { + mem = fdt_node_offset_by_prop_value(blob, mem, + "device_type", "memory", 7); + } while (!fdtdec_get_is_enabled(blob, mem)); + + return mem; +} + +static int setup_mem_map(void) +{ + int i, ret, mem, reg = 0; + struct fdt_resource res; + const void *blob = gd->fdt_blob; + + mem = get_next_memory_node(blob, -1); + if (mem < 0) { + printf("%s: Missing /memory node\n", __func__); + return -EINVAL; + } + + for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) { + ret = fdt_get_resource(blob, mem, "reg", reg++, &res); + if (ret == -FDT_ERR_NOTFOUND) { + reg = 0; + mem = get_next_memory_node(blob, mem); + if (mem == -FDT_ERR_NOTFOUND) + break; + + ret = fdt_get_resource(blob, mem, "reg", reg++, &res); + if (ret == -FDT_ERR_NOTFOUND) + break; + } + if (ret != 0) { + printf("No reg property for memory node\n"); + return -EINVAL; + } + + xen_mem_map[i].virt = (phys_addr_t)res.start; + xen_mem_map[i].phys = (phys_addr_t)res.start; + xen_mem_map[i].size = (phys_size_t)(res.end - res.start + 1); + xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE); + } + return 0; +} + +void enable_caches(void) +{ + /* Re-setup the memory map as BSS gets cleared after relocation. */ + setup_mem_map(); + icache_enable(); + dcache_enable(); +} + +/* Read memory settings from the Xen provided device tree. */ +int dram_init(void) +{ + int ret; + + ret = fdtdec_setup_mem_size_base(); + if (ret < 0) + return ret; + /* Setup memory map, so MMU page table size can be estimated. */ + return setup_mem_map(); +} + +int dram_init_banksize(void) +{ + return fdtdec_setup_memory_banksize(); +} + +/* + * Board specific reset that is system reset. + */ +void reset_cpu(ulong addr) +{ +} + +int ft_system_setup(void *blob, struct bd_info *bd) +{ + return 0; +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + return 0; +} + +int board_early_init_f(void) +{ + return 0; +} + +int print_cpuinfo(void) +{ + printf("Xen virtual CPU\n"); + return 0; +} + +__weak struct serial_device *default_serial_console(void) +{ + return NULL; +} + diff --git a/configs/xenguest_arm64_defconfig b/configs/xenguest_arm64_defconfig new file mode 100644 index 0000000000..f730799fc9 --- /dev/null +++ b/configs/xenguest_arm64_defconfig @@ -0,0 +1,56 @@ +CONFIG_ARM=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_SYS_TEXT_BASE=0x40080000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_IDENT_STRING=" xenguest" +CONFIG_TARGET_XENGUEST_ARM64=y +CONFIG_BOOTDELAY=10 + +CONFIG_SYS_PROMPT="xenguest# " + +CONFIG_CMD_NET=n +CONFIG_CMD_BDI=n +CONFIG_CMD_BOOTD=n +CONFIG_CMD_BOOTEFI=n +CONFIG_CMD_BOOTEFI_HELLO_COMPILE=n +CONFIG_CMD_ELF=n +CONFIG_CMD_GO=n +CONFIG_CMD_RUN=n +CONFIG_CMD_IMI=n +CONFIG_CMD_IMLS=n +CONFIG_CMD_XIMG=n +CONFIG_CMD_EXPORTENV=n +CONFIG_CMD_IMPORTENV=n +CONFIG_CMD_EDITENV=n +CONFIG_CMD_ENV_EXISTS=n +CONFIG_CMD_MEMORY=y +CONFIG_CMD_CRC32=n +CONFIG_CMD_DM=n +CONFIG_CMD_LOADB=n +CONFIG_CMD_LOADS=n +CONFIG_CMD_FLASH=n +CONFIG_CMD_GPT=n +CONFIG_CMD_FPGA=n +CONFIG_CMD_ECHO=n +CONFIG_CMD_ITEST=n +CONFIG_CMD_SOURCE=n +CONFIG_CMD_SETEXPR=n +CONFIG_CMD_MISC=n +CONFIG_CMD_UNZIP=n +CONFIG_CMD_LZMADEC=n +CONFIG_CMD_SAVEENV=n +CONFIG_CMD_UMS=n + +#CONFIG_USB=n +# CONFIG_ISO_PARTITION is not set + +#CONFIG_EFI_PARTITION=y +# CONFIG_EFI_LOADER is not set + +CONFIG_DM=y +# CONFIG_MMC is not set +# CONFIG_DM_SERIAL is not set +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set + +CONFIG_OF_BOARD=y +CONFIG_OF_LIBFDT=y diff --git a/include/configs/xenguest_arm64.h b/include/configs/xenguest_arm64.h new file mode 100644 index 0000000000..d8958cfe75 --- /dev/null +++ b/include/configs/xenguest_arm64.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0+ + * + * (C) Copyright 2020 EPAM Systemc Inc. + */ +#ifndef __XENGUEST_ARM64_H +#define __XENGUEST_ARM64_H + +#ifndef __ASSEMBLY__ +#include +#endif + +#define CONFIG_BOARD_EARLY_INIT_F + +#define CONFIG_EXTRA_ENV_SETTINGS + +#undef CONFIG_NR_DRAM_BANKS +#undef CONFIG_SYS_SDRAM_BASE + +#define CONFIG_NR_DRAM_BANKS 1 + +/* + * This can be any arbitrary address as we are using PIE, but + * please note, that CONFIG_SYS_TEXT_BASE must match the below. + */ +#define CONFIG_SYS_LOAD_ADDR 0x40000000 +#define CONFIG_LNX_KRNL_IMG_TEXT_OFFSET_BASE CONFIG_SYS_LOAD_ADDR + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (32 * 1024 * 1024) + +/* Monitor Command Prompt */ +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " +#define CONFIG_SYS_CBSIZE 1024 +#define CONFIG_SYS_MAXARGS 64 +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) + +#define CONFIG_OF_SYSTEM_SETUP + +#define CONFIG_CMDLINE_TAG 1 +#define CONFIG_INITRD_TAG 1 + +#endif /* __XENGUEST_ARM64_H */