diff --git a/CODEOWNERS b/CODEOWNERS index d8b28facda978..ca2a6d1c31a5d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -24,6 +24,7 @@ /arch/arm/core/aarch32/cortex_a_r/ @MaureenHelm @galak @ioannisg @bbolen @stephanosio /arch/arm64/ @carlocaione /arch/arm64/core/cortex_r/ @povergoing +/arch/arm64/core/xen/ @lorc @firscity /arch/common/ @ioannisg @andyross /soc/arc/snps_*/ @abrodkin @ruuddw @evgeniy-paltsev /soc/nios2/ @nashif @@ -60,7 +61,7 @@ /soc/arm64/qemu_cortex_a53/ @carlocaione /soc/arm64/bcm_vk/ @abhishek-brcm /soc/arm64/nxp_layerscape/ @JiafeiPan -/soc/arm64/xenvm/ @lorc +/soc/arm64/xenvm/ @lorc @firscity /soc/arm64/arm/ @povergoing /soc/arm64/arm/fvp_aemv8a/ @carlocaione /submanifests/* @mbolivar-nordic @@ -166,7 +167,7 @@ /boards/arm64/qemu_cortex_a53/ @carlocaione /boards/arm64/bcm958402m2_a72/ @abhishek-brcm /boards/arm64/nxp_ls1046ardb/ @JiafeiPan -/boards/arm64/xenvm/ @lorc +/boards/arm64/xenvm/ @lorc @firscity /boards/arm64/fvp_baser_aemv8r/ @povergoing /boards/arm64/fvp_base_revc_2xaemv8a/ @carlocaione /boards/arm64/intel_socfpga_agilex_socdk/ @siclim @ngboonkhai @@ -343,6 +344,8 @@ /drivers/serial/serial_test.c @str4t0m /drivers/serial/*esp32c3* @uLipe /drivers/serial/*esp32s2* @glaubermaroto +/drivers/serial/Kconfig.xen @lorc @firscity +/drivers/serial/uart_hvc_xen.c @lorc @firscity /drivers/disk/ @jfischer-no /drivers/disk/sdmmc_sdhc.h @JunYangNXP /drivers/disk/sdmmc_spi.c @JunYangNXP @@ -389,6 +392,7 @@ /drivers/wifi/eswifi/ @loicpoulain @nandojve /drivers/wifi/winc1500/ @kludentwo /drivers/virtualization/ @tbursztyka +/drivers/xen/ @lorc @firscity /dts/arc/ @abrodkin @ruuddw @iriszzw @evgeniy-paltsev /dts/arm/acsip/ @NorthernDean /dts/arm/atmel/sam4e* @nandojve diff --git a/arch/arm64/core/CMakeLists.txt b/arch/arm64/core/CMakeLists.txt index 84013f2b5b63a..1a0a5337bf8de 100644 --- a/arch/arm64/core/CMakeLists.txt +++ b/arch/arm64/core/CMakeLists.txt @@ -30,3 +30,5 @@ if ((CONFIG_MP_NUM_CPUS GREATER 1) OR (CONFIG_SMP)) endif () zephyr_cc_option_ifdef(CONFIG_USERSPACE -mno-outline-atomics) + +add_subdirectory_ifdef(CONFIG_SOC_XENVM xen) diff --git a/arch/arm64/core/xen/CMakeLists.txt b/arch/arm64/core/xen/CMakeLists.txt new file mode 100644 index 0000000000000..1009e655e69b8 --- /dev/null +++ b/arch/arm64/core/xen/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2021 EPAM Systems + +# Needed to separate definitions in common Xen headers +zephyr_compile_options($<$:-D__ASSEMBLY__>) + +# Xen interface version used in headers for correct definition +zephyr_compile_options(-D__XEN_INTERFACE_VERSION__=0x00040e00) + +zephyr_library_sources(hypercall.S) diff --git a/arch/arm64/core/xen/hypercall.S b/arch/arm64/core/xen/hypercall.S new file mode 100644 index 0000000000000..a9abdb003e0ba --- /dev/null +++ b/arch/arm64/core/xen/hypercall.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define HYPERCALL(hypercall) \ +GTEXT(HYPERVISOR_##hypercall); \ +SECTION_FUNC(TEXT, HYPERVISOR_##hypercall) \ + mov x16, #__HYPERVISOR_##hypercall; \ + hvc XEN_HYPERCALL_TAG; \ + ret; + +_ASM_FILE_PROLOGUE + +HYPERCALL(console_io); +HYPERCALL(grant_table_op); +HYPERCALL(sched_op); +HYPERCALL(event_channel_op); +HYPERCALL(hvm_op); +HYPERCALL(memory_op); diff --git a/boards/arm64/xenvm/doc/index.rst b/boards/arm64/xenvm/doc/index.rst index 5c9d190e04748..1809b5ba67329 100644 --- a/boards/arm64/xenvm/doc/index.rst +++ b/boards/arm64/xenvm/doc/index.rst @@ -20,8 +20,6 @@ It provides minimal set of devices: * ARM Generic timer * GICv2 -* SBSA (subset of PL011) UART controller - Hardware ******** @@ -35,8 +33,6 @@ The following hardware features are supported: +==============+=============+======================+ | GIC | virtualized | interrupt controller | +--------------+-------------+----------------------+ -| SBSA UART | emulated | serial port | -+--------------+-------------+----------------------+ | ARM TIMER | virtualized | system clock | +--------------+-------------+----------------------+ @@ -57,13 +53,6 @@ boot log: (XEN) [ 0.147541] Generic Timer IRQ: phys=30 hyp=26 virt=27 Freq: 8320 KHz -Serial Port ------------ - -This board configuration uses a single serial communication channel using SBSA -UART. This is a minimal UART implementation provided by Xen. Xen PV Console is -not supported at this moment. - Interrupt Controller -------------------- @@ -88,13 +77,17 @@ configuration would not boot on your hardware. In this case you need to update configuration by altering device tree and Kconfig options. This will be covered in detail in next section. -No Xen-specific features are supported at the moment. This includes: +Most of Xen-specific features are not supported at the moment. This includes: -* Xen Enlighten memory page +* Xen Enlighten memory page (under development) * XenBus -* Xen event channels +* Xen event channels (under development) * Xen grant tables -* Xen PV drivers (including PV console) +* Xen PV drivers + +Now only following features are supported: +* Xen PV console (UART-like driver with poll API, IRQ driven is under development) +* Xen early console_io interface (mainly for debug purposes) Building and Running ******************** @@ -118,7 +111,6 @@ create guest configuration file :code:`zephyr.conf`. There is example: memory=16 gic_version="v2" on_crash="preserve" - vuart="sbsa_uart" You need to upload both :code:`zephyr.bin` and :code:`zephyr.conf` to your Dom0 and then you can run Zephyr by issuing @@ -127,11 +119,17 @@ and then you can run Zephyr by issuing $ xl create zephyr.conf -Next you need to attach to SBSA virtual console: +Next you need to attach to PV console: + +.. code-block:: + + $ xl console zephyr + +Also this can be performed via single command: .. code-block:: - $ xl console -t vuart zephyr + $ xl create -c zephyr.conf You will see Zephyr output: diff --git a/boards/arm64/xenvm/xenvm.dts b/boards/arm64/xenvm/xenvm.dts index c2ebaff21a41e..08ed885287bd9 100644 --- a/boards/arm64/xenvm/xenvm.dts +++ b/boards/arm64/xenvm/xenvm.dts @@ -25,9 +25,8 @@ #size-cells = <0x02>; chosen { - zephyr,console = &sbsa; - zephyr,shell-uart = &sbsa; zephyr,sram = &ram; + zephyr,console = &xen_hvc; }; cpus { @@ -78,12 +77,8 @@ interrupt-parent = <&gic>; }; - sbsa: sbsa-pl011@22000000 { - compatible = "arm,sbsa-uart"; - reg = <0x00 0x22000000 0x00 0x1000>; - interrupts = ; - interrupt-parent = <&gic>; - current-speed = <0x1c200>; - label = "UART"; + xen_hvc: hvc { + compatible = "xen,uart_hvc"; + status = "okay"; }; }; diff --git a/boards/arm64/xenvm/xenvm_defconfig b/boards/arm64/xenvm/xenvm_defconfig index 25e402bfc34e0..e4605a110648d 100644 --- a/boards/arm64/xenvm/xenvm_defconfig +++ b/boards/arm64/xenvm/xenvm_defconfig @@ -14,7 +14,9 @@ CONFIG_MAX_XLAT_TABLES=10 CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -# Enable serial port -CONFIG_UART_PL011=y -CONFIG_UART_PL011_SBSA=y -CONFIG_UART_INTERRUPT_DRIVEN=n +# Enable PV hypervisor console +CONFIG_UART_XEN_HVC=y + +# Enable logging subsys +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 9837eb9f81db9..528d45b70c968 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -63,3 +63,4 @@ add_subdirectory_ifdef(CONFIG_BBRAM bbram) add_subdirectory_ifdef(CONFIG_FPGA fpga) add_subdirectory_ifdef(CONFIG_PINCTRL pinctrl) add_subdirectory_ifdef(CONFIG_MBOX mbox) +add_subdirectory_ifdef(CONFIG_BOARD_XENVM xen) diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index 5bfc1bf927a08..576492a1e049a 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -45,6 +45,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_RCAR uart_rcar.c) zephyr_library_sources_ifdef(CONFIG_UART_XEC uart_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_UART_NEORV32 uart_neorv32.c) zephyr_library_sources_ifdef(CONFIG_USART_GD32 usart_gd32.c) +zephyr_library_sources_ifdef(CONFIG_UART_XEN_HVC uart_hvc_xen.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 475c17f2e88c2..569b7ed2f25ac 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -171,4 +171,6 @@ source "drivers/serial/Kconfig.test" source "drivers/serial/Kconfig.neorv32" +source "drivers/serial/Kconfig.xen" + endif # SERIAL diff --git a/drivers/serial/Kconfig.xen b/drivers/serial/Kconfig.xen new file mode 100644 index 0000000000000..e95ddb7c4587e --- /dev/null +++ b/drivers/serial/Kconfig.xen @@ -0,0 +1,30 @@ +# Xen hypervisor console via UART setup +# +# Copyright (c) 2021 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 +# + +config UART_XEN_HVC + bool "Xen hypervisor console UART Driver" + select SERIAL_HAS_DRIVER + depends on BOARD_XENVM + default y + help + Enable Xen hypervisor console driver. + +config XEN_HVC_INIT_PRIORITY + int "Xen hypervisor console init priority" + depends on UART_XEN_HVC + default 55 + help + Set init priority for Xen HVC, should be inited before UART + console driver (HVC gets inited on PRE_KERNEL_1 stage). + +config XEN_EARLY_CONSOLEIO + bool "Early printk/stdout through console_io Xen interface" + depends on BOARD_XENVM + default n + help + Enable setting of console_io symbol hook for stdout and printk. + Log output will become available on PRE_KERNEL_1 stage. Requires + Xen, compiled with CONFIG_DEBUG flag. diff --git a/drivers/serial/uart_hvc_xen.c b/drivers/serial/uart_hvc_xen.c new file mode 100644 index 0000000000000..9b0004bc79260 --- /dev/null +++ b/drivers/serial/uart_hvc_xen.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(uart_hvc_xen); + +static struct hvc_xen_data hvc_data = {0}; + +static int read_from_ring(const struct device *dev, char *str, int len) +{ + int recv = 0; + struct hvc_xen_data *hvc_data = dev->data; + XENCONS_RING_IDX cons = hvc_data->intf->in_cons; + XENCONS_RING_IDX prod = hvc_data->intf->in_prod; + XENCONS_RING_IDX in_idx = 0; + + compiler_barrier(); + __ASSERT((prod - cons) <= sizeof(hvc_data->intf->in), + "Invalid input ring buffer"); + + while (cons != prod && recv < len) { + in_idx = MASK_XENCONS_IDX(cons, hvc_data->intf->in); + str[recv] = hvc_data->intf->in[in_idx]; + recv++; + cons++; + } + + compiler_barrier(); + hvc_data->intf->in_cons = cons; + + notify_evtchn(hvc_data->evtchn); + return recv; +} + +static int write_to_ring(const struct device *dev, const char *str, int len) +{ + int sent = 0; + struct hvc_xen_data *hvc_data = dev->data; + XENCONS_RING_IDX cons = hvc_data->intf->out_cons; + XENCONS_RING_IDX prod = hvc_data->intf->out_prod; + XENCONS_RING_IDX out_idx = 0; + + compiler_barrier(); + __ASSERT((prod - cons) <= sizeof(hvc_data->intf->out), + "Invalid output ring buffer"); + + while ((sent < len) && ((prod - cons) < sizeof(hvc_data->intf->out))) { + out_idx = MASK_XENCONS_IDX(prod, hvc_data->intf->out); + hvc_data->intf->out[out_idx] = str[sent]; + prod++; + sent++; + } + + compiler_barrier(); + hvc_data->intf->out_prod = prod; + + if (sent) { + notify_evtchn(hvc_data->evtchn); + } + + return sent; +} + +static int xen_hvc_poll_in(const struct device *dev, + unsigned char *c) +{ + int ret = 0; + char temp; + + ret = read_from_ring(dev, &temp, sizeof(temp)); + if (!ret) { + /* Char was not received */ + return -1; + } + + *c = temp; + return 0; +} + +static void xen_hvc_poll_out(const struct device *dev, + unsigned char c) +{ + /* Not a good solution (notifying HV every time), but needed for poll_out */ + (void) write_to_ring(dev, &c, sizeof(c)); +} + +static const struct uart_driver_api xen_hvc_api = { + .poll_in = xen_hvc_poll_in, + .poll_out = xen_hvc_poll_out, +}; + +int xen_console_init(const struct device *dev) +{ + int ret = 0; + uint64_t console_pfn = 0; + uintptr_t console_addr = 0; + struct hvc_xen_data *data = dev->data; + + data->dev = dev; + + ret = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &data->evtchn); + if (ret) { + LOG_ERR("%s: failed to get Xen console evtchn, ret = %d\n", + __func__, ret); + return ret; + } + + ret = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &console_pfn); + if (ret) { + LOG_ERR("%s: failed to get Xen console PFN, ret = %d\n", + __func__, ret); + return ret; + } + + console_addr = (uintptr_t) (console_pfn << XEN_PAGE_SHIFT); + device_map(DEVICE_MMIO_RAM_PTR(dev), console_addr, XEN_PAGE_SIZE, + K_MEM_CACHE_WB); + + data->intf = (struct xencons_interface *) DEVICE_MMIO_GET(dev); + + LOG_INF("Xen HVC inited successfully\n"); + + return 0; +} + +DEVICE_DT_DEFINE(DT_NODELABEL(xen_hvc), xen_console_init, NULL, &hvc_data, + NULL, PRE_KERNEL_1, CONFIG_XEN_HVC_INIT_PRIORITY, + &xen_hvc_api); + +#ifdef CONFIG_XEN_EARLY_CONSOLEIO +extern void __printk_hook_install(int (*fn)(int)); +extern void __stdout_hook_install(int (*fn)(int)); + +int xen_consoleio_putc(int c) +{ + char symbol = (char) c; + + HYPERVISOR_console_io(CONSOLEIO_write, sizeof(symbol), &symbol); + return c; +} + + + +int consoleio_hooks_set(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Will be replaced with poll_in/poll_out by uart_console.c later on boot */ + __stdout_hook_install(xen_consoleio_putc); + __printk_hook_install(xen_consoleio_putc); + + return 0; +} + +SYS_INIT(consoleio_hooks_set, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +#endif /* CONFIG_XEN_EARLY_CONSOLEIO */ diff --git a/drivers/xen/CMakeLists.txt b/drivers/xen/CMakeLists.txt new file mode 100644 index 0000000000000..2060ee25e157f --- /dev/null +++ b/drivers/xen/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2021 EPAM Systems + +zephyr_sources(hvm.c) +zephyr_sources(events.c) diff --git a/drivers/xen/events.c b/drivers/xen/events.c new file mode 100644 index 0000000000000..897a2b8962838 --- /dev/null +++ b/drivers/xen/events.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +void notify_evtchn(evtchn_port_t port) +{ + struct evtchn_send send; + + if (port >= EVTCHN_2L_NR_CHANNELS) { + printk("%s: trying to send notify for invalid evtchn #%u\n", + __func__, port); + return; + } + + send.port = port; + + HYPERVISOR_event_channel_op(EVTCHNOP_send, &send); +} diff --git a/drivers/xen/hvm.c b/drivers/xen/hvm.c new file mode 100644 index 0000000000000..80895a84ef909 --- /dev/null +++ b/drivers/xen/hvm.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include + +int hvm_set_parameter(int idx, uint64_t value) +{ + struct xen_hvm_param xhv; + + xhv.domid = DOMID_SELF; + xhv.index = idx; + xhv.value = value; + + return HYPERVISOR_hvm_op(HVMOP_set_param, &xhv); +} + +int hvm_get_parameter(int idx, uint64_t *value) +{ + int ret = 0; + struct xen_hvm_param xhv; + + xhv.domid = DOMID_SELF; + xhv.index = idx; + + ret = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv); + if (ret < 0) + return ret; + + *value = xhv.value; + return ret; +} diff --git a/include/arch/arm64/hypercall.h b/include/arch/arm64/hypercall.h new file mode 100644 index 0000000000000..6fefdff12b015 --- /dev/null +++ b/include/arch/arm64/hypercall.h @@ -0,0 +1,12 @@ +/* + * Copyright (c() 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* defined in hypercall.S by HYPERCALL(hypercall) */ +int HYPERVISOR_console_io(int op, int cnt, char *str); +int HYPERVISOR_sched_op(int op, void *param); +int HYPERVISOR_event_channel_op(int op, void *param); +int HYPERVISOR_hvm_op(int op, void *param); +int HYPERVISOR_memory_op(int op, void *param); diff --git a/include/xen/console.h b/include/xen/console.h new file mode 100644 index 0000000000000..2e617b04d1d2a --- /dev/null +++ b/include/xen/console.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __XEN_CONSOLE_H__ +#define __XEN_CONSOLE_H__ + +#include +#include +#include +#include + +struct hvc_xen_data { + DEVICE_MMIO_RAM; /* should be first */ + const struct device *dev; + struct xencons_interface *intf; + uint64_t evtchn; +}; + +int xen_console_init(const struct device *dev); + +#endif /* __XEN_CONSOLE_H__ */ diff --git a/include/xen/events.h b/include/xen/events.h new file mode 100644 index 0000000000000..eee0ff0e8fb8e --- /dev/null +++ b/include/xen/events.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __XEN_EVENTS_H__ +#define __XEN_EVENTS_H__ + +#include + +void notify_evtchn(evtchn_port_t port); + +#endif /* __XEN_EVENTS_H__ */ diff --git a/include/xen/generic.h b/include/xen/generic.h new file mode 100644 index 0000000000000..c1123a7327813 --- /dev/null +++ b/include/xen/generic.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __XEN_GENERIC_H__ +#define __XEN_GENERIC_H__ + +#include + +#define XEN_PAGE_SIZE 4096 +#define XEN_PAGE_SHIFT 12 + +#endif /* __XEN_GENERIC_H__ */ diff --git a/include/xen/hvm.h b/include/xen/hvm.h new file mode 100644 index 0000000000000..1bd770ba1dfb3 --- /dev/null +++ b/include/xen/hvm.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2021 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef __XEN_HVM_H__ +#define __XEN_HVM_H__ + +#include +#include + +#include + +int hvm_set_parameter(int idx, uint64_t value); +int hvm_get_parameter(int idx, uint64_t *value); + +#endif /* __XEN_HVM_H__ */ diff --git a/include/xen/public/arch-arm.h b/include/xen/public/arch-arm.h new file mode 100644 index 0000000000000..77771e2fa0fde --- /dev/null +++ b/include/xen/public/arch-arm.h @@ -0,0 +1,228 @@ +/* SPDX-License-Identifier: MIT */ + +/****************************************************************************** + * arch-arm.h + * + * Guest OS interface to ARM Xen. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright 2011 (C) Citrix Systems + */ + +#ifndef __XEN_PUBLIC_ARCH_ARM_H__ +#define __XEN_PUBLIC_ARCH_ARM_H__ + +#include + +/* + * `incontents 50 arm_abi Hypercall Calling Convention + * + * A hypercall is issued using the ARM HVC instruction. + * + * A hypercall can take up to 5 arguments. These are passed in + * registers, the first argument in x0/r0 (for arm64/arm32 guests + * respectively irrespective of whether the underlying hypervisor is + * 32- or 64-bit), the second argument in x1/r1, the third in x2/r2, + * the forth in x3/r3 and the fifth in x4/r4. + * + * The hypercall number is passed in r12 (arm) or x16 (arm64). In both + * cases the relevant ARM procedure calling convention specifies this + * is an inter-procedure-call scratch register (e.g. for use in linker + * stubs). This use does not conflict with use during a hypercall. + * + * The HVC ISS must contain a Xen specific TAG: XEN_HYPERCALL_TAG. + * + * The return value is in x0/r0. + * + * The hypercall will clobber x16/r12 and the argument registers used + * by that hypercall (except r0 which is the return value) i.e. in + * addition to x16/r12 a 2 argument hypercall will clobber x1/r1 and a + * 4 argument hypercall will clobber x1/r1, x2/r2 and x3/r3. + * + * Parameter structs passed to hypercalls are laid out according to + * the Procedure Call Standard for the ARM Architecture (AAPCS, AKA + * EABI) and Procedure Call Standard for the ARM 64-bit Architecture + * (AAPCS64). Where there is a conflict the 64-bit standard should be + * used regardless of guest type. Structures which are passed as + * hypercall arguments are always little endian. + * + * All memory which is shared with other entities in the system + * (including the hypervisor and other guests) must reside in memory + * which is mapped as Normal Inner Write-Back Outer Write-Back Inner-Shareable. + * This applies to: + * - hypercall arguments passed via a pointer to guest memory. + * - memory shared via the grant table mechanism (including PV I/O + * rings etc). + * - memory shared with the hypervisor (struct shared_info, struct + * vcpu_info, the grant table, etc). + * + * Any cache allocation hints are acceptable. + */ + +/* + * `incontents 55 arm_hcall Supported Hypercalls + * + * Xen on ARM makes extensive use of hardware facilities and therefore + * only a subset of the potential hypercalls are required. + * + * Since ARM uses second stage paging any machine/physical addresses + * passed to hypercalls are Guest Physical Addresses (Intermediate + * Physical Addresses) unless otherwise noted. + * + * The following hypercalls (and sub operations) are supported on the + * ARM platform. Other hypercalls should be considered + * unavailable/unsupported. + * + * HYPERVISOR_memory_op + * All generic sub-operations + * + * HYPERVISOR_domctl + * All generic sub-operations, with the exception of: + * * XEN_DOMCTL_irq_permission (not yet implemented) + * + * HYPERVISOR_sched_op + * All generic sub-operations, with the exception of: + * * SCHEDOP_block -- prefer wfi hardware instruction + * + * HYPERVISOR_console_io + * All generic sub-operations + * + * HYPERVISOR_xen_version + * All generic sub-operations + * + * HYPERVISOR_event_channel_op + * All generic sub-operations + * + * HYPERVISOR_physdev_op + * No sub-operations are currenty supported + * + * HYPERVISOR_sysctl + * All generic sub-operations, with the exception of: + * * XEN_SYSCTL_page_offline_op + * * XEN_SYSCTL_get_pmstat + * * XEN_SYSCTL_pm_op + * + * HYPERVISOR_hvm_op + * Exactly these sub-operations are supported: + * * HVMOP_set_param + * * HVMOP_get_param + * + * HYPERVISOR_grant_table_op + * All generic sub-operations + * + * HYPERVISOR_vcpu_op + * Exactly these sub-operations are supported: + * * VCPUOP_register_vcpu_info + * * VCPUOP_register_runstate_memory_area + * + * + * Other notes on the ARM ABI: + * + * - struct start_info is not exported to ARM guests. + * + * - struct shared_info is mapped by ARM guests using the + * HYPERVISOR_memory_op sub-op XENMEM_add_to_physmap, passing + * XENMAPSPACE_shared_info as space parameter. + * + * - All the per-cpu struct vcpu_info are mapped by ARM guests using the + * HYPERVISOR_vcpu_op sub-op VCPUOP_register_vcpu_info, including cpu0 + * struct vcpu_info. + * + * - The grant table is mapped using the HYPERVISOR_memory_op sub-op + * XENMEM_add_to_physmap, passing XENMAPSPACE_grant_table as space + * parameter. The memory range specified under the Xen compatible + * hypervisor node on device tree can be used as target gpfn for the + * mapping. + * + * - Xenstore is initialized by using the two hvm_params + * HVM_PARAM_STORE_PFN and HVM_PARAM_STORE_EVTCHN. They can be read + * with the HYPERVISOR_hvm_op sub-op HVMOP_get_param. + * + * - The paravirtualized console is initialized by using the two + * hvm_params HVM_PARAM_CONSOLE_PFN and HVM_PARAM_CONSOLE_EVTCHN. They + * can be read with the HYPERVISOR_hvm_op sub-op HVMOP_get_param. + * + * - Event channel notifications are delivered using the percpu GIC + * interrupt specified under the Xen compatible hypervisor node on + * device tree. + * + * - The device tree Xen compatible node is fully described under Linux + * at Documentation/devicetree/bindings/arm/xen.txt. + */ + +#define XEN_HYPERCALL_TAG 0XEA1 + +#define int64_aligned_t int64_t __aligned(8) +#define uint64_aligned_t uint64_t __aligned(8) + +#ifndef __ASSEMBLY__ +#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \ + typedef union { type *p; unsigned long q; } \ + __guest_handle_ ## name; \ + typedef union { type *p; uint64_aligned_t q; } \ + __guest_handle_64_ ## name + +/* + * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field + * in a struct in memory. On ARM is always 8 bytes sizes and 8 bytes + * aligned. + * XEN_GUEST_HANDLE_PARAM represents a guest pointer, when passed as an + * hypercall argument. It is 4 bytes on aarch32 and 8 bytes on aarch64. + */ +#define __DEFINE_XEN_GUEST_HANDLE(name, type) \ + ___DEFINE_XEN_GUEST_HANDLE(name, type); \ + ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type) +#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) +#define __XEN_GUEST_HANDLE(name) __guest_handle_64_ ## name +#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name) +#define XEN_GUEST_HANDLE_PARAM(name) __guest_handle_ ## name +#define set_xen_guest_handle_raw(hnd, val) \ + do { \ + __typeof__(&(hnd)) _sxghr_tmp = &(hnd); \ + _sxghr_tmp->q = 0; \ + _sxghr_tmp->p = val; \ + } while (0) +#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val) + +typedef uint64_t xen_pfn_t; +#define PRI_xen_pfn PRIx64 +#define PRIu_xen_pfn PRIu64 + +typedef uint64_t xen_ulong_t; +#define PRI_xen_ulong PRIx64 + +/* + * Maximum number of virtual CPUs in legacy multi-processor guests. + * Only one. All other VCPUS must use VCPUOP_register_vcpu_info. + */ +#define XEN_LEGACY_MAX_VCPUS 1 + +struct arch_vcpu_info { +}; +typedef struct arch_vcpu_info arch_vcpu_info_t; + +struct arch_shared_info { +}; +typedef struct arch_shared_info arch_shared_info_t; +typedef uint64_t xen_callback_t; + +#endif /* __ASSEMBLY__ */ + +#endif /* __XEN_PUBLIC_ARCH_ARM_H__ */ diff --git a/include/xen/public/event_channel.h b/include/xen/public/event_channel.h new file mode 100644 index 0000000000000..dba62545713f9 --- /dev/null +++ b/include/xen/public/event_channel.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: MIT */ + +/****************************************************************************** + * event_channel.h + * + * Event channels between domains. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright (c) 2003-2004, K A Fraser. + */ + +#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__ +#define __XEN_PUBLIC_EVENT_CHANNEL_H__ + +#include "xen.h" + +/* + * `incontents 150 evtchn Event Channels + * + * Event channels are the basic primitive provided by Xen for event + * notifications. An event is the Xen equivalent of a hardware + * interrupt. They essentially store one bit of information, the event + * of interest is signalled by transitioning this bit from 0 to 1. + * + * Notifications are received by a guest via an upcall from Xen, + * indicating when an event arrives (setting the bit). Further + * notifications are masked until the bit is cleared again (therefore, + * guests must check the value of the bit after re-enabling event + * delivery to ensure no missed notifications). + * + * Event notifications can be masked by setting a flag; this is + * equivalent to disabling interrupts and can be used to ensure + * atomicity of certain operations in the guest kernel. + * + * Event channels are represented by the evtchn_* fields in + * struct shared_info and struct vcpu_info. + */ + +#define EVTCHNOP_bind_interdomain 0 +#define EVTCHNOP_bind_virq 1 +#define EVTCHNOP_bind_pirq 2 +#define EVTCHNOP_close 3 +#define EVTCHNOP_send 4 +#define EVTCHNOP_status 5 +#define EVTCHNOP_alloc_unbound 6 +#define EVTCHNOP_bind_ipi 7 +#define EVTCHNOP_bind_vcpu 8 +#define EVTCHNOP_unmask 9 +#define EVTCHNOP_reset 10 +#define EVTCHNOP_init_control 11 +#define EVTCHNOP_expand_array 12 +#define EVTCHNOP_set_priority 13 +#ifdef __XEN__ +#define EVTCHNOP_reset_cont 14 +#endif + +typedef uint32_t evtchn_port_t; +DEFINE_XEN_GUEST_HANDLE(evtchn_port_t); + +/* + * EVTCHNOP_send: Send an event to the remote end of the channel whose local + * endpoint is . + */ +struct evtchn_send { + /* IN parameters. */ + evtchn_port_t port; +}; +typedef struct evtchn_send evtchn_send_t; + +#define EVTCHN_2L_NR_CHANNELS (sizeof(xen_ulong_t) * sizeof(xen_ulong_t) * 64) + +#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */ diff --git a/include/xen/public/hvm/hvm_op.h b/include/xen/public/hvm/hvm_op.h new file mode 100644 index 0000000000000..89a63dc1291ef --- /dev/null +++ b/include/xen/public/hvm/hvm_op.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: MIT */ + +/* + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright (c) 2007, Keir Fraser + */ + +#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__ +#define __XEN_PUBLIC_HVM_HVM_OP_H__ + +#include "../xen.h" + +/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */ +#define HVMOP_set_param 0 +#define HVMOP_get_param 1 +struct xen_hvm_param { + domid_t domid; /* IN */ + uint16_t pad; + uint32_t index; /* IN */ + uint64_t value; /* IN/OUT */ +}; +typedef struct xen_hvm_param xen_hvm_param_t; +DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t); + +#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */ diff --git a/include/xen/public/hvm/params.h b/include/xen/public/hvm/params.h new file mode 100644 index 0000000000000..1222b2ffdefda --- /dev/null +++ b/include/xen/public/hvm/params.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: MIT */ + +/* + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright (c) 2007, Keir Fraser + */ + +#ifndef __XEN_PUBLIC_HVM_PARAMS_H__ +#define __XEN_PUBLIC_HVM_PARAMS_H__ + +#include "hvm_op.h" + +/* + * These are not used by Xen. They are here for convenience of HVM-guest + * xenbus implementations. + */ +#define HVM_PARAM_STORE_PFN 1 +#define HVM_PARAM_STORE_EVTCHN 2 + +/* Console debug shared memory ring and event channel */ +#define HVM_PARAM_CONSOLE_PFN 17 +#define HVM_PARAM_CONSOLE_EVTCHN 18 + +#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */ diff --git a/include/xen/public/io/console.h b/include/xen/public/io/console.h new file mode 100644 index 0000000000000..5178bb086e86f --- /dev/null +++ b/include/xen/public/io/console.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: MIT */ + +/****************************************************************************** + * console.h + * + * Console I/O interface for Xen guest OSes. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright (c) 2005, Keir Fraser + */ + +#ifndef __XEN_PUBLIC_IO_CONSOLE_H__ +#define __XEN_PUBLIC_IO_CONSOLE_H__ + +typedef uint32_t XENCONS_RING_IDX; + +#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1)) + +struct xencons_interface { + char in[1024]; + char out[2048]; + XENCONS_RING_IDX in_cons, in_prod; + XENCONS_RING_IDX out_cons, out_prod; +}; + +#ifdef XEN_WANT_FLEX_CONSOLE_RING +#include "ring.h" +DEFINE_XEN_FLEX_RING(xencons); +#endif + +#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */ diff --git a/include/xen/public/memory.h b/include/xen/public/memory.h new file mode 100644 index 0000000000000..c2a463974903c --- /dev/null +++ b/include/xen/public/memory.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: MIT */ + +/****************************************************************************** + * memory.h + * + * Memory reservation and information. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright (c) 2005, Keir Fraser + */ + +#ifndef __XEN_PUBLIC_MEMORY_H__ +#define __XEN_PUBLIC_MEMORY_H__ + +#include "xen.h" + +#define XENMAPSPACE_shared_info 0 /* shared info page */ +#define XENMAPSPACE_grant_table 1 /* grant table page */ +#define XENMAPSPACE_gmfn 2 /* GMFN */ + +/* GMFN range, XENMEM_add_to_physmap only.*/ +#define XENMAPSPACE_gmfn_range 3 + +/* GMFN from another dom, XENMEM_add_to_physmap_batch only. */ +#define XENMAPSPACE_gmfn_foreign 4 + +/* + * Device mmio region ARM only; the region is mapped in Stage-2 using the + * Normal Memory Inner/Outer Write-Back Cacheable memory attribute. + */ +#define XENMAPSPACE_dev_mmio 5 + +/* + * Sets the GPFN at which a particular page appears in the specified guest's + * physical address space (translated guests only). + * arg == addr of xen_add_to_physmap_t. + */ +#define XENMEM_add_to_physmap 7 +struct xen_add_to_physmap { + /* Which domain to change the mapping for. */ + domid_t domid; + + /* Number of pages to go through for gmfn_range */ + uint16_t size; + + unsigned int space; /* => enum phys_map_space */ + +#define XENMAPIDX_grant_table_status 0x80000000 + + /* Index into space being mapped. */ + xen_ulong_t idx; + + /* GPFN in domid where the source mapping page should appear. */ + xen_pfn_t gpfn; +}; +typedef struct xen_add_to_physmap xen_add_to_physmap_t; +DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t); + +#endif /* __XEN_PUBLIC_MEMORY_H__ */ diff --git a/include/xen/public/sched.h b/include/xen/public/sched.h new file mode 100644 index 0000000000000..e9a29a172df18 --- /dev/null +++ b/include/xen/public/sched.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: MIT */ + +/****************************************************************************** + * sched.h + * + * Scheduler state interactions + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright (c) 2005, Keir Fraser + */ + +#ifndef __XEN_PUBLIC_SCHED_H__ +#define __XEN_PUBLIC_SCHED_H__ + +#include "event_channel.h" + +/* + * `incontents 150 sched Guest Scheduler Operations + * + * The SCHEDOP interface provides mechanisms for a guest to interact + * with the scheduler, including yield, blocking and shutting itself + * down. + */ + +/* + * The prototype for this hypercall is: + * ` long HYPERVISOR_sched_op(enum sched_op cmd, void *arg, ...) + * + * @cmd == SCHEDOP_??? (scheduler operation). + * @arg == Operation-specific extra argument(s), as described below. + * ... == Additional Operation-specific extra arguments, described below. + * + * Versions of Xen prior to 3.0.2 provided only the following legacy version + * of this hypercall, supporting only the commands yield, block and shutdown: + * long sched_op(int cmd, unsigned long arg) + * @cmd == SCHEDOP_??? (scheduler operation). + * @arg == 0 (SCHEDOP_yield and SCHEDOP_block) + * == SHUTDOWN_* code (SCHEDOP_shutdown) + * + * This legacy version is available to new guests as: + * ` long HYPERVISOR_sched_op_compat(enum sched_op cmd, unsigned long arg) + */ + +/* + * Voluntarily yield the CPU. + * @arg == NULL. + */ +#define SCHEDOP_yield 0 + +/* + * Block execution of this VCPU until an event is received for processing. + * If called with event upcalls masked, this operation will atomically + * reenable event delivery and check for pending events before blocking the + * VCPU. This avoids a "wakeup waiting" race. + * @arg == NULL. + */ +#define SCHEDOP_block 1 + +/* + * Halt execution of this domain (all VCPUs) and notify the system controller. + * @arg == pointer to sched_shutdown_t structure. + * + * If the sched_shutdown_t reason is SHUTDOWN_suspend then + * x86 PV guests must also set RDX (EDX for 32-bit guests) to the MFN + * of the guest's start info page. RDX/EDX is the third hypercall + * argument. + * + * In addition, which reason is SHUTDOWN_suspend this hypercall + * returns 1 if suspend was cancelled or the domain was merely + * checkpointed, and 0 if it is resuming in a new domain. + */ +#define SCHEDOP_shutdown 2 + +/* + * Poll a set of event-channel ports. Return when one or more are pending. An + * optional timeout may be specified. + * @arg == pointer to sched_poll_t structure. + */ +#define SCHEDOP_poll 3 + +/* + * Declare a shutdown for another domain. The main use of this function is + * in interpreting shutdown requests and reasons for fully-virtualized + * domains. A para-virtualized domain may use SCHEDOP_shutdown directly. + * @arg == pointer to sched_remote_shutdown_t structure. + */ +#define SCHEDOP_remote_shutdown 4 + +/* + * Latch a shutdown code, so that when the domain later shuts down it + * reports this code to the control tools. + * @arg == sched_shutdown_t, as for SCHEDOP_shutdown. + */ +#define SCHEDOP_shutdown_code 5 + +/* + * Setup, poke and destroy a domain watchdog timer. + * @arg == pointer to sched_watchdog_t structure. + * With id == 0, setup a domain watchdog timer to cause domain shutdown + * after timeout, returns watchdog id. + * With id != 0 and timeout == 0, destroy domain watchdog timer. + * With id != 0 and timeout != 0, poke watchdog timer and set new timeout. + */ +#define SCHEDOP_watchdog 6 + +/* + * Override the current vcpu affinity by pinning it to one physical cpu or + * undo this override restoring the previous affinity. + * @arg == pointer to sched_pin_override_t structure. + * + * A negative pcpu value will undo a previous pin override and restore the + * previous cpu affinity. + * This call is allowed for the hardware domain only and requires the cpu + * to be part of the domain's cpupool. + */ +#define SCHEDOP_pin_override 7 + +struct sched_shutdown { + unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */ +}; +typedef struct sched_shutdown sched_shutdown_t; +DEFINE_XEN_GUEST_HANDLE(sched_shutdown_t); + +struct sched_poll { + XEN_GUEST_HANDLE(evtchn_port_t) ports; + unsigned int nr_ports; + uint64_t timeout; +}; +typedef struct sched_poll sched_poll_t; +DEFINE_XEN_GUEST_HANDLE(sched_poll_t); + +struct sched_remote_shutdown { + domid_t domain_id; /* Remote domain ID */ + unsigned int reason; /* SHUTDOWN_* => enum sched_shutdown_reason */ +}; +typedef struct sched_remote_shutdown sched_remote_shutdown_t; +DEFINE_XEN_GUEST_HANDLE(sched_remote_shutdown_t); + +struct sched_watchdog { + uint32_t id; /* watchdog ID */ + uint32_t timeout; /* timeout */ +}; +typedef struct sched_watchdog sched_watchdog_t; +DEFINE_XEN_GUEST_HANDLE(sched_watchdog_t); + +struct sched_pin_override { + int32_t pcpu; +}; +typedef struct sched_pin_override sched_pin_override_t; +DEFINE_XEN_GUEST_HANDLE(sched_pin_override_t); + +/* + * Reason codes for SCHEDOP_shutdown. These may be interpreted by control + * software to determine the appropriate action. For the most part, Xen does + * not care about the shutdown code. + */ +/* Domain exited normally. Clean up and kill. */ +#define SHUTDOWN_poweroff 0 + +/* Clean up, kill, and then restart. */ +#define SHUTDOWN_reboot 1 + +/* Clean up, save suspend info, kill. */ +#define SHUTDOWN_suspend 2 + +/* Tell controller we've crashed. */ +#define SHUTDOWN_crash 3 + +/* Restart because watchdog time expired. */ +#define SHUTDOWN_watchdog 4 + +/* + * Domain asked to perform 'soft reset' for it. The expected behavior is to + * reset internal Xen state for the domain returning it to the point where it + * was created but leaving the domain's memory contents and vCPU contexts + * intact. This will allow the domain to start over and set up all Xen specific + * interfaces again. + */ +#define SHUTDOWN_soft_reset 5 + +/* Maximum valid shutdown reason. */ +#define SHUTDOWN_MAX 5 + +#endif /* __XEN_PUBLIC_SCHED_H__ */ diff --git a/include/xen/public/xen.h b/include/xen/public/xen.h new file mode 100644 index 0000000000000..359e1a2abea7f --- /dev/null +++ b/include/xen/public/xen.h @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: MIT */ + +/****************************************************************************** + * xen.h + * + * Guest OS interface to Xen. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (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. + * + * Copyright (c) 2004, K A Fraser + */ + +#ifndef __XEN_PUBLIC_XEN_H__ +#define __XEN_PUBLIC_XEN_H__ + +#if defined(CONFIG_ARM64) +#include "arch-arm.h" +#else +#error "Unsupported architecture" +#endif + +#ifndef __ASSEMBLY__ +/* Guest handles for primitive C types. */ +DEFINE_XEN_GUEST_HANDLE(char); +__DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); +DEFINE_XEN_GUEST_HANDLE(int); +__DEFINE_XEN_GUEST_HANDLE(uint, unsigned int); +#if __XEN_INTERFACE_VERSION__ < 0x00040300 +DEFINE_XEN_GUEST_HANDLE(long); +__DEFINE_XEN_GUEST_HANDLE(ulong, unsigned long); +#endif +DEFINE_XEN_GUEST_HANDLE(void); + +DEFINE_XEN_GUEST_HANDLE(uint64_t); +DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); +DEFINE_XEN_GUEST_HANDLE(xen_ulong_t); + +/* Define a variable length array (depends on compiler). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#define XEN_FLEX_ARRAY_DIM +#elif defined(__GNUC__) +#define XEN_FLEX_ARRAY_DIM 0 +#else +#define XEN_FLEX_ARRAY_DIM 1 /* variable size */ +#endif + +/* Turn a plain number into a C unsigned (long (long)) constant. */ +#define __xen_mk_uint(x) x ## U +#define __xen_mk_ulong(x) x ## UL +#ifndef __xen_mk_ullong +#define __xen_mk_ullong(x) x ## ULL +#endif +#define xen_mk_uint(x) __xen_mk_uint(x) +#define xen_mk_ulong(x) __xen_mk_ulong(x) +#define xen_mk_ullong(x) __xen_mk_ullong(x) + +#else + +/* In assembly code we cannot use C numeric constant suffixes. */ +#define xen_mk_uint(x) x +#define xen_mk_ulong(x) x +#define xen_mk_ullong(x) x + +#endif + +/* + * HYPERCALLS + */ + +/* `incontents 100 hcalls List of hypercalls + * ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*() + */ + +#define __HYPERVISOR_set_trap_table 0 +#define __HYPERVISOR_mmu_update 1 +#define __HYPERVISOR_set_gdt 2 +#define __HYPERVISOR_stack_switch 3 +#define __HYPERVISOR_set_callbacks 4 +#define __HYPERVISOR_fpu_taskswitch 5 + +/* compat since 0x00030101 */ +#define __HYPERVISOR_sched_op_compat 6 +#define __HYPERVISOR_platform_op 7 +#define __HYPERVISOR_set_debugreg 8 +#define __HYPERVISOR_get_debugreg 9 +#define __HYPERVISOR_update_descriptor 10 +#define __HYPERVISOR_memory_op 12 +#define __HYPERVISOR_multicall 13 +#define __HYPERVISOR_update_va_mapping 14 +#define __HYPERVISOR_set_timer_op 15 + +/* compat since 0x00030202 */ +#define __HYPERVISOR_event_channel_op_compat 16 +#define __HYPERVISOR_xen_version 17 +#define __HYPERVISOR_console_io 18 + +/* compat since 0x00030202 */ +#define __HYPERVISOR_physdev_op_compat 19 +#define __HYPERVISOR_grant_table_op 20 +#define __HYPERVISOR_vm_assist 21 +#define __HYPERVISOR_update_va_mapping_otherdomain 22 + +/* x86 only */ +#define __HYPERVISOR_iret 23 +#define __HYPERVISOR_vcpu_op 24 + +/* x86/64 only */ +#define __HYPERVISOR_set_segment_base 25 +#define __HYPERVISOR_mmuext_op 26 +#define __HYPERVISOR_xsm_op 27 +#define __HYPERVISOR_nmi_op 28 +#define __HYPERVISOR_sched_op 29 +#define __HYPERVISOR_callback_op 30 +#define __HYPERVISOR_xenoprof_op 31 +#define __HYPERVISOR_event_channel_op 32 +#define __HYPERVISOR_physdev_op 33 +#define __HYPERVISOR_hvm_op 34 +#define __HYPERVISOR_sysctl 35 +#define __HYPERVISOR_domctl 36 +#define __HYPERVISOR_kexec_op 37 +#define __HYPERVISOR_tmem_op 38 +#define __HYPERVISOR_argo_op 39 +#define __HYPERVISOR_xenpmu_op 40 +#define __HYPERVISOR_dm_op 41 +#define __HYPERVISOR_hypfs_op 42 + +/* + * ` int + * ` HYPERVISOR_console_io(unsigned int cmd, + * ` unsigned int count, + * ` char buffer[]); + * + * @cmd: Command (see below) + * @count: Size of the buffer to read/write + * @buffer: Pointer in the guest memory + * + * List of commands: + * + * * CONSOLEIO_write: Write the buffer to Xen console. + * For the hardware domain, all the characters in the buffer will + * be written. Characters will be printed directly to the console. + * For all the other domains, only the printable characters will be + * written. Characters may be buffered until a newline (i.e '\n') is + * found. + * @return 0 on success, otherwise return an error code. + * * CONSOLEIO_read: Attempts to read up to @count characters from Xen + * console. The maximum buffer size (i.e. @count) supported is 2GB. + * @return the number of characters read on success, otherwise return + * an error code. + */ +#define CONSOLEIO_write 0 +#define CONSOLEIO_read 1 + +/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */ +#define DOMID_FIRST_RESERVED xen_mk_uint(0x7FF0) + +/* DOMID_SELF is used in certain contexts to refer to oneself. */ +#define DOMID_SELF xen_mk_uint(0x7FF0) + +/* + * DOMID_IO is used to restrict page-table updates to mapping I/O memory. + * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO + * is useful to ensure that no mappings to the OS's own heap are accidentally + * installed. (e.g., in Linux this could cause havoc as reference counts + * aren't adjusted on the I/O-mapping code path). + * This only makes sense as HYPERVISOR_mmu_update()'s and + * HYPERVISOR_update_va_mapping_otherdomain()'s "foreigndom" argument. For + * HYPERVISOR_mmu_update() context it can be specified by any calling domain, + * otherwise it's only permitted if the caller is privileged. + */ +#define DOMID_IO xen_mk_uint(0x7FF1) + +/* + * DOMID_XEN is used to allow privileged domains to map restricted parts of + * Xen's heap space (e.g., the machine_to_phys table). + * This only makes sense as + * - HYPERVISOR_mmu_update()'s, HYPERVISOR_mmuext_op()'s, or + * HYPERVISOR_update_va_mapping_otherdomain()'s "foreigndom" argument, + * - with XENMAPSPACE_gmfn_foreign, + * and is only permitted if the caller is privileged. + */ +#define DOMID_XEN xen_mk_uint(0x7FF2) + +/* + * DOMID_COW is used as the owner of sharable pages. + */ +#define DOMID_COW xen_mk_uint(0x7FF3) + +/* DOMID_INVALID is used to identify pages with unknown owner. */ +#define DOMID_INVALID xen_mk_uint(0x7FF4) + +/* Idle domain. */ +#define DOMID_IDLE xen_mk_uint(0x7FFF) + +/* Mask for valid domain id values */ +#define DOMID_MASK xen_mk_uint(0x7FFF) + +#ifndef __ASSEMBLY__ + +typedef uint16_t domid_t; + +#if __XEN_INTERFACE_VERSION__ < 0x00040400 +/* + * Event channel endpoints per domain (when using the 2-level ABI): + * 1024 if a long is 32 bits; 4096 if a long is 64 bits. + */ +#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS +#endif + +struct vcpu_time_info { + /* + * Updates to the following values are preceded and followed by an + * increment of 'version'. The guest can therefore detect updates by + * looking for changes to 'version'. If the least-significant bit of + * the version number is set then an update is in progress and the + * guest must wait to read a consistent set of values. + * The correct way to interact with the version number is similar to + * Linux's seqlock: see the implementations of + * read_seqbegin/read_seqretry. + */ + uint32_t version; + uint32_t pad0; + uint64_t tsc_timestamp; /* TSC at last update of time vals. */ + uint64_t system_time; /* Time, in nanosecs, since boot.*/ + /* + * Current system time: + * system_time + + * ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32) + * CPU frequency (Hz): + * ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift + */ + uint32_t tsc_to_system_mul; + int8_t tsc_shift; +#if __XEN_INTERFACE_VERSION__ > 0x040600 + uint8_t flags; + uint8_t pad1[2]; +#else + int8_t pad1[3]; +#endif +}; /* 32 bytes */ +typedef struct vcpu_time_info vcpu_time_info_t; + +#define XEN_PVCLOCK_TSC_STABLE_BIT (1 << 0) +#define XEN_PVCLOCK_GUEST_STOPPED (1 << 1) + +struct vcpu_info { + /* + * 'evtchn_upcall_pending' is written non-zero by Xen to indicate + * a pending notification for a particular VCPU. It is then cleared + * by the guest OS /before/ checking for pending work, thus avoiding + * a set-and-check race. Note that the mask is only accessed by Xen + * on the CPU that is currently hosting the VCPU. This means that the + * pending and mask flags can be updated by the guest without special + * synchronisation (i.e., no need for the x86 LOCK prefix). + * This may seem suboptimal because if the pending flag is set by + * a different CPU then an IPI may be scheduled even when the mask + * is set. However, note: + * 1. The task of 'interrupt holdoff' is covered by the per-event- + * channel mask bits. A 'noisy' event that is continually being + * triggered can be masked at source at this very precise + * granularity. + * 2. The main purpose of the per-VCPU mask is therefore to restrict + * reentrant execution: whether for concurrency control, or to + * prevent unbounded stack usage. Whatever the purpose, we expect + * that the mask will be asserted only for short periods at a time, + * and so the likelihood of a 'spurious' IPI is suitably small. + * The mask is read before making an event upcall to the guest: a + * non-zero mask therefore guarantees that the VCPU will not receive + * an upcall activation. The mask is cleared when the VCPU requests + * to block: this avoids wakeup-waiting races. + */ + uint8_t evtchn_upcall_pending; +#ifdef XEN_HAVE_PV_UPCALL_MASK + uint8_t evtchn_upcall_mask; +#else /* XEN_HAVE_PV_UPCALL_MASK */ + uint8_t pad0; +#endif /* XEN_HAVE_PV_UPCALL_MASK */ + xen_ulong_t evtchn_pending_sel; + struct arch_vcpu_info arch; + vcpu_time_info_t time; +}; /* 64 bytes (x86) */ +#ifndef __XEN__ +typedef struct vcpu_info vcpu_info_t; +#endif + +/* + * `incontents 200 startofday_shared Start-of-day shared data structure + * Xen/kernel shared data -- pointer provided in start_info. + * + * This structure is defined to be both smaller than a page, and the + * only data on the shared page, but may vary in actual size even within + * compatible Xen versions; guests should not rely on the size + * of this structure remaining constant. + */ +struct shared_info { + struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS]; + + /* + * A domain can create "event channels" on which it can send and receive + * asynchronous event notifications. There are three classes of event that + * are delivered by this mechanism: + * 1. Bi-directional inter- and intra-domain connections. Domains must + * arrange out-of-band to set up a connection (usually by allocating + * an unbound 'listener' port and avertising that via a storage service + * such as xenstore). + * 2. Physical interrupts. A domain with suitable hardware-access + * privileges can bind an event-channel port to a physical interrupt + * source. + * 3. Virtual interrupts ('events'). A domain can bind an event-channel + * port to a virtual interrupt source, such as the virtual-timer + * device or the emergency console. + * + * Event channels are addressed by a "port index". Each channel is + * associated with two bits of information: + * 1. PENDING -- notifies the domain that there is a pending notification + * to be processed. This bit is cleared by the guest. + * 2. MASK -- if this bit is clear then a 0->1 transition of PENDING + * will cause an asynchronous upcall to be scheduled. This bit is only + * updated by the guest. It is read-only within Xen. If a channel + * becomes pending while the channel is masked then the 'edge' is lost + * (i.e., when the channel is unmasked, the guest must manually handle + * pending notifications as no upcall will be scheduled by Xen). + * + * To expedite scanning of pending notifications, any 0->1 pending + * transition on an unmasked channel causes a corresponding bit in a + * per-vcpu selector word to be set. Each bit in the selector covers a + * 'C long' in the PENDING bitfield array. + */ + xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8]; + xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8]; + + /* + * Wallclock time: updated by control software or RTC emulation. + * Guests should base their gettimeofday() syscall on this + * wallclock-base value. + * The values of wc_sec and wc_nsec are offsets from the Unix epoch + * adjusted by the domain's 'time offset' (in seconds) as set either + * by XEN_DOMCTL_settimeoffset, or adjusted via a guest write to the + * emulated RTC. + */ + uint32_t wc_version; /* Version counter: see vcpu_time_info_t. */ + uint32_t wc_sec; + uint32_t wc_nsec; +#if !defined(__i386__) + uint32_t wc_sec_hi; +# define xen_wc_sec_hi wc_sec_hi +#elif !defined(__XEN__) && !defined(__XEN_TOOLS__) +# define xen_wc_sec_hi arch.wc_sec_hi +#endif + + struct arch_shared_info arch; + +}; +#ifndef __XEN__ +typedef struct shared_info shared_info_t; +#endif + +#endif /* !__ASSEMBLY__ */ + +#endif /* __XEN_PUBLIC_XEN_H__ */ diff --git a/soc/arm64/xenvm/mmu_regions.c b/soc/arm64/xenvm/mmu_regions.c index c3818104c16d2..c4d3eee5d024c 100644 --- a/soc/arm64/xenvm/mmu_regions.c +++ b/soc/arm64/xenvm/mmu_regions.c @@ -18,11 +18,6 @@ static const struct arm_mmu_region mmu_regions[] = { DT_REG_ADDR_BY_IDX(DT_INST(0, arm_gic), 1), DT_REG_SIZE_BY_IDX(DT_INST(0, arm_gic), 1), MT_DEVICE_nGnRnE | MT_P_RW_U_RW | MT_NS), - - MMU_REGION_FLAT_ENTRY("UART", - DT_REG_ADDR(DT_INST(0, arm_sbsa_uart)), - DT_REG_SIZE(DT_INST(0, arm_sbsa_uart)), - MT_DEVICE_nGnRnE | MT_P_RW_U_RW | MT_NS), }; const struct arm_mmu_config mmu_config = {