This commit adds support of Xen Enlighten page and initial support for Xen event channels. It is needed for future Xen PV drivers implementation. Now enlighten page is mapped to the prepared memory area on PRE_KERNEL_1 stage. In case of success event channel logic gets inited and can be used ASAP after Zephyr start. Current implementation allows to use only pre-defined event channels (PV console/XenBus) and works only in single CPU mode (without VCPUOP_register_vcpu_info). Event channel allocation will be implemented in future versions. Signed-off-by: Dmytro Firsov <dmytro_firsov@epam.com>
71 lines
1.8 KiB
C
71 lines
1.8 KiB
C
/*
|
|
* Copyright (c) 2021 EPAM Systems
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <arch/arm64/hypercall.h>
|
|
#include <xen/events.h>
|
|
#include <xen/generic.h>
|
|
#include <xen/public/xen.h>
|
|
#include <xen/public/memory.h>
|
|
|
|
#include <device.h>
|
|
#include <init.h>
|
|
#include <kernel.h>
|
|
#include <kernel/thread.h>
|
|
#include <logging/log.h>
|
|
|
|
LOG_MODULE_REGISTER(xen_enlighten);
|
|
|
|
/*
|
|
* During Xen Enlighten initialization we need to have allocated memory page,
|
|
* where hypervisor shared_info will be mapped. k_aligned_alloc() is not
|
|
* available on PRE_KERNEL_1 stage, so we will use statically allocated buffer,
|
|
* which will be casted to 'struct shared_info'. It is needed to initialize Xen
|
|
* event channels as soon as possible after start.
|
|
*/
|
|
static uint8_t shared_info_buf[XEN_PAGE_SIZE] __aligned(XEN_PAGE_SIZE);
|
|
|
|
/* Remains NULL until mapping will be finished by Xen */
|
|
shared_info_t *HYPERVISOR_shared_info;
|
|
|
|
static int xen_map_shared_info(const shared_info_t *shared_page)
|
|
{
|
|
struct xen_add_to_physmap xatp;
|
|
|
|
xatp.domid = DOMID_SELF;
|
|
xatp.idx = 0;
|
|
xatp.space = XENMAPSPACE_shared_info;
|
|
xatp.gpfn = (((xen_pfn_t) shared_page) >> XEN_PAGE_SHIFT);
|
|
|
|
return HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
|
|
}
|
|
|
|
static int xen_enlighten_init(const struct device *dev)
|
|
{
|
|
ARG_UNUSED(dev);
|
|
int ret = 0;
|
|
shared_info_t *info = (shared_info_t *) shared_info_buf;
|
|
|
|
ret = xen_map_shared_info(info);
|
|
if (ret) {
|
|
LOG_ERR("%s: failed to map for Xen shared page, ret = %d\n",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
/* Set value for globally visible pointer */
|
|
HYPERVISOR_shared_info = info;
|
|
|
|
ret = xen_events_init();
|
|
if (ret) {
|
|
LOG_ERR("%s: failed init Xen event channels, ret = %d\n",
|
|
__func__, ret);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SYS_INIT(xen_enlighten_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|