
Subject: [PATCH 03/17] board: Introduce xenguest_arm64 board
From: Andrii Anisov andrii_anisov@epam.com
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.
This patch needs to be in the last, otherwise it might break git bisect.
[1] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fxenbit s.xen.org%2F&data=02%7C01%7Cpeng.fan%40nxp.com%7C61151b8230 c94f145ce408d81ddc04ee%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0% 7C0%7C637292178110014498&sdata=pgJ6Qf1iDW%2FjNWTcGBWFVYY SrG0MX%2FiTzbfzbyqkxsY%3D&reserved=0 [2] https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwiki.xe nproject.org%2F&data=02%7C01%7Cpeng.fan%40nxp.com%7C61151b8 230c94f145ce408d81ddc04ee%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C 0%7C0%7C637292178110014498&sdata=x0gKBoJvFRQdX7YatAhgF%2Fc ovJ4kdrmbl2iUiXvCqww%3D&reserved=0
Signed-off-by: Andrii Anisov andrii_anisov@epam.com Signed-off-by: Oleksandr Andrushchenko oleksandr_andrushchenko@epam.com Signed-off-by: Anastasiia Lukianenko anastasiia_lukianenko@epam.com
arch/arm/Kconfig | 7 + arch/arm/cpu/armv8/Makefile | 1 + arch/arm/cpu/armv8/xen/Makefile | 6 + arch/arm/cpu/armv8/xen/hypercall.S | 78 +++++++++++ arch/arm/cpu/armv8/xen/lowlevel_init.S | 34 +++++ arch/arm/include/asm/xen.h | 8 ++ arch/arm/include/asm/xen/hypercall.h | 45 +++++++ board/xen/xenguest_arm64/Kconfig | 12 ++ board/xen/xenguest_arm64/Makefile | 5 + board/xen/xenguest_arm64/xenguest_arm64.c | 153 ++++++++++++++++++++++ configs/xenguest_arm64_defconfig | 56 ++++++++ include/configs/xenguest_arm64.h | 45 +++++++ 12 files changed, 450 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/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 e9ad716aaa..c469863967 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1717,6 +1717,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 @@ -1920,6 +1926,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 2e48df0eb9..dd6c354d19 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_S32V234) += s32v234/ obj-$(CONFIG_TARGET_HIKEY) += hisilicon/ obj-$(CONFIG_ARMV8_PSCI) += psci.o obj-$(CONFIG_ARCH_SUNXI) += lowlevel_init.o +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..9596e336b5 --- /dev/null +++ b/arch/arm/cpu/armv8/xen/hypercall.S @@ -0,0 +1,78 @@ +/************************************************************
+********
- hypercall.S
- Xen hypercall wrappers
- Stefano Stabellini stefano.stabellini@eu.citrix.com, 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 <xen/interface/xen.h>
+#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..25ed438e20 --- /dev/null +++ b/arch/arm/cpu/armv8/xen/lowlevel_init.S @@ -0,0 +1,34 @@ +/*
- SPDX-License-Identifier: GPL-2.0+
- (C) 2017 NXP
- (C) 2020 EPAM Systems Inc.
- */
+#include <config.h>
+.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..fb7f03e19c --- /dev/null +++ b/arch/arm/include/asm/xen.h @@ -0,0 +1,8 @@ +/*
- 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..26644ce886 --- /dev/null +++ b/arch/arm/include/asm/xen/hypercall.h @@ -0,0 +1,45 @@ +/************************************************************
+********
- hypercall.h
- Linux-specific hypervisor handling.
- Stefano Stabellini stefano.stabellini@eu.citrix.com, 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.
- */
+#ifndef _ASM_ARM_XEN_HYPERCALL_H +#define _ASM_ARM_XEN_HYPERCALL_H
+#include <xen/interface/xen.h>
+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/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..9e099f388f --- /dev/null +++ b/board/xen/xenguest_arm64/xenguest_arm64.c @@ -0,0 +1,153 @@ +/*
- SPDX-License-Identifier: GPL-2.0+
- (C) 2013
- David Feng fenghua@phytium.com.cn
- Sharma Bhupesh bhupesh.sharma@freescale.com
- (C) 2020 EPAM Systems Inc
- */
+#include <common.h> +#include <cpu_func.h> +#include <dm.h> +#include <errno.h> +#include <malloc.h>
+#include <asm/io.h> +#include <asm/armv8/mmu.h> +#include <asm/xen.h> +#include <asm/xen/hypercall.h>
+#include <linux/compiler.h>
+DECLARE_GLOBAL_DATA_PTR;
+int board_init(void) +{
- return 0;
+}
+/*
- Use fdt provided by Xen: according to
+https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww .k +ernel.org%2Fdoc%2FDocumentation%2Farm64%2Fbooting.txt&data=0 2%7C01% +7Cpeng.fan%40nxp.com%7C61151b8230c94f145ce408d81ddc04ee%7C686 ea1d3bc2b4 +c6fa92cd99c5c301635%7C0%7C0%7C637292178110014498&sdata=3t i9j4nAzNSw +xsmZs8rONDmPLNbGx89HYBsezkgD%2FVI%3D&reserved=0
- 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, bd_t *bd) {
- return 0;
+}
+int ft_board_setup(void *blob, bd_t *bd) {
- return 0;
+}
+int board_early_init_f(void) +{
- return 0;
+}
Drop the upper three functions if not needed.
+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..2a8caf8647 --- /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
10s?
Regards, Peng.
+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 is not set +# 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..467dabf1e5 --- /dev/null +++ b/include/configs/xenguest_arm64.h @@ -0,0 +1,45 @@ +/*
- SPDX-License-Identifier: GPL-2.0+
- (C) Copyright 2020 EPAM Systemc Inc.
- */
+#ifndef __XENGUEST_ARM64_H +#define __XENGUEST_ARM64_H
+#ifndef __ASSEMBLY__ +#include <linux/types.h> +#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 */
2.17.1