xen: implement Xen domain control interface
Add Xen domctl API implementation for Zephyr as control domain. Previously Zephyr OS was used as unprivileged Xen domain (Domain-U), but it also can be used as lightweight Xen control domain (Domain-0). To implement such fuctionality additional Xen interfaces are needed. One of them is Xen domain controls (domctls) - it allows to create, configure and manage Xen domains. Also, used it as a possibility to update files copyright and licenses identifiers in touched files. Signed-off-by: Dmytro Firsov <dmytro_firsov@epam.com>
This commit is contained in:
parent
0c69913eae
commit
3581527b53
|
@ -1,7 +1,6 @@
|
||||||
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021 EPAM Systems
|
* Copyright (c) 2021-2023 EPAM Systems
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <zephyr/toolchain.h>
|
#include <zephyr/toolchain.h>
|
||||||
|
@ -24,3 +23,7 @@ HYPERCALL(sched_op);
|
||||||
HYPERCALL(event_channel_op);
|
HYPERCALL(event_channel_op);
|
||||||
HYPERCALL(hvm_op);
|
HYPERCALL(hvm_op);
|
||||||
HYPERCALL(memory_op);
|
HYPERCALL(memory_op);
|
||||||
|
|
||||||
|
#ifdef CONFIG_XEN_DOM0
|
||||||
|
HYPERCALL(domctl);
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
# Copyright (c) 2021-2022 EPAM Systems
|
# Copyright (c) 2021-2023 EPAM Systems
|
||||||
|
|
||||||
zephyr_sources(hvm.c)
|
zephyr_sources(hvm.c)
|
||||||
zephyr_sources(events.c)
|
zephyr_sources(events.c)
|
||||||
zephyr_sources_ifdef(CONFIG_XEN_GRANT_TABLE gnttab.c)
|
zephyr_sources_ifdef(CONFIG_XEN_GRANT_TABLE gnttab.c)
|
||||||
|
|
||||||
|
add_subdirectory_ifdef(CONFIG_XEN_DOM0 dom0)
|
||||||
|
|
4
drivers/xen/dom0/CMakeLists.txt
Normal file
4
drivers/xen/dom0/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# Copyright (c) 2023 EPAM Systems
|
||||||
|
|
||||||
|
zephyr_sources(domctl.c)
|
305
drivers/xen/dom0/domctl.c
Normal file
305
drivers/xen/dom0/domctl.c
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 EPAM Systems
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <zephyr/arch/arm64/hypercall.h>
|
||||||
|
#include <zephyr/xen/dom0/domctl.h>
|
||||||
|
#include <zephyr/xen/generic.h>
|
||||||
|
#include <zephyr/xen/public/domctl.h>
|
||||||
|
#include <zephyr/xen/public/xen.h>
|
||||||
|
|
||||||
|
#include <zephyr/init.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int do_domctl(xen_domctl_t *domctl)
|
||||||
|
{
|
||||||
|
domctl->interface_version = XEN_DOMCTL_INTERFACE_VERSION;
|
||||||
|
return HYPERVISOR_domctl(domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_scheduler_op(int domid, struct xen_domctl_scheduler_op *sched_op)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_scheduler_op,
|
||||||
|
.domain = domid,
|
||||||
|
.u.scheduler_op = *sched_op,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_pausedomain(int domid)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_pausedomain,
|
||||||
|
.domain = domid,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_unpausedomain(int domid)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_unpausedomain,
|
||||||
|
.domain = domid,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_resumedomain(int domid)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_resumedomain,
|
||||||
|
.domain = domid,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_getvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_getvcpucontext,
|
||||||
|
.domain = domid,
|
||||||
|
.u.vcpucontext.vcpu = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_setvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_setvcpucontext,
|
||||||
|
.domain = domid,
|
||||||
|
.u.vcpucontext.vcpu = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_getdomaininfo(int domid, xen_domctl_getdomaininfo_t *dom_info)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_getdomaininfo,
|
||||||
|
.domain = domid,
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = do_domctl(&domctl);
|
||||||
|
if (rc) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(dom_info, &domctl.u.getdomaininfo, sizeof(*dom_info));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_get_paging_mempool_size(int domid, uint64_t *size_mb)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_get_paging_mempool_size,
|
||||||
|
.domain = domid,
|
||||||
|
};
|
||||||
|
|
||||||
|
rc = do_domctl(&domctl);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
*size_mb = domctl.u.paging_mempool.size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_set_paging_mempool_size(int domid, uint64_t size_mb)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_set_paging_mempool_size,
|
||||||
|
.domain = domid,
|
||||||
|
.u.paging_mempool.size = size_mb,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_max_mem(int domid, uint64_t max_memkb)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_max_mem,
|
||||||
|
.domain = domid,
|
||||||
|
.u.max_mem.max_memkb = max_memkb,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_set_address_size(int domid, int addr_size)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.domain = domid,
|
||||||
|
.cmd = XEN_DOMCTL_set_address_size,
|
||||||
|
.u.address_size.size = addr_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_iomem_permission(int domid, uint64_t first_mfn,
|
||||||
|
uint64_t nr_mfns, uint8_t allow_access)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.domain = domid,
|
||||||
|
.cmd = XEN_DOMCTL_iomem_permission,
|
||||||
|
.u.iomem_permission.first_mfn = first_mfn,
|
||||||
|
.u.iomem_permission.nr_mfns = nr_mfns,
|
||||||
|
.u.iomem_permission.allow_access = allow_access,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_memory_mapping(int domid, uint64_t first_gfn, uint64_t first_mfn,
|
||||||
|
uint64_t nr_mfns, uint32_t add_mapping)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint64_t curr, nr_max, done;
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.domain = domid,
|
||||||
|
.cmd = XEN_DOMCTL_memory_mapping,
|
||||||
|
.u.memory_mapping.add_mapping = add_mapping,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!nr_mfns) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* nr_mfns can be big and we need to handle this here */
|
||||||
|
done = 0;
|
||||||
|
nr_max = nr_mfns;
|
||||||
|
do {
|
||||||
|
domctl.u.memory_mapping.first_gfn = first_gfn + done;
|
||||||
|
domctl.u.memory_mapping.first_mfn = first_mfn + done;
|
||||||
|
|
||||||
|
curr = MIN(nr_mfns - done, nr_max);
|
||||||
|
domctl.u.memory_mapping.nr_mfns = curr;
|
||||||
|
|
||||||
|
ret = do_domctl(&domctl);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == -E2BIG) {
|
||||||
|
/* Check if we not reach min amount */
|
||||||
|
if (nr_max <= 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrease amount twice and try again */
|
||||||
|
nr_max = nr_max >> 1;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
done += curr;
|
||||||
|
} while (done < nr_mfns);
|
||||||
|
|
||||||
|
/* We may come here when get E2BIG and reach 1 at nr_max */
|
||||||
|
if (!done) {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_assign_dt_device(int domid, char *dtdev_path)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.domain = domid,
|
||||||
|
.cmd = XEN_DOMCTL_assign_device,
|
||||||
|
.u.assign_device.flags = 0,
|
||||||
|
.u.assign_device.dev = XEN_DOMCTL_DEV_DT,
|
||||||
|
.u.assign_device.u.dt.size = strlen(dtdev_path),
|
||||||
|
};
|
||||||
|
|
||||||
|
set_xen_guest_handle(domctl.u.assign_device.u.dt.path, dtdev_path);
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_bind_pt_irq(int domid, uint32_t machine_irq, uint8_t irq_type,
|
||||||
|
uint8_t bus, uint8_t device, uint8_t intx, uint8_t isa_irq,
|
||||||
|
uint16_t spi)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.domain = domid,
|
||||||
|
.cmd = XEN_DOMCTL_bind_pt_irq,
|
||||||
|
};
|
||||||
|
struct xen_domctl_bind_pt_irq *bind = &(domctl.u.bind_pt_irq);
|
||||||
|
|
||||||
|
switch (irq_type) {
|
||||||
|
case PT_IRQ_TYPE_SPI:
|
||||||
|
bind->irq_type = irq_type;
|
||||||
|
bind->machine_irq = machine_irq;
|
||||||
|
bind->u.spi.spi = spi;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* TODO: implement other types */
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_max_vcpus(int domid, int max_vcpus)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_max_vcpus,
|
||||||
|
.domain = domid,
|
||||||
|
.u.max_vcpus.max = max_vcpus,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_createdomain(int domid, struct xen_domctl_createdomain *config)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_createdomain,
|
||||||
|
.domain = domid,
|
||||||
|
.u.createdomain = *config,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_destroydomain(int domid)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_destroydomain,
|
||||||
|
.domain = domid,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xen_domctl_cacheflush(int domid, struct xen_domctl_cacheflush *cacheflush)
|
||||||
|
{
|
||||||
|
xen_domctl_t domctl = {
|
||||||
|
.cmd = XEN_DOMCTL_cacheflush,
|
||||||
|
.domain = domid,
|
||||||
|
.u.cacheflush = *cacheflush,
|
||||||
|
};
|
||||||
|
|
||||||
|
return do_domctl(&domctl);
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 EPAM Systems
|
* Copyright (c) 2021-2023 EPAM Systems
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_
|
#ifndef ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_
|
||||||
|
@ -15,4 +14,8 @@ int HYPERVISOR_hvm_op(int op, void *param);
|
||||||
int HYPERVISOR_memory_op(int op, void *param);
|
int HYPERVISOR_memory_op(int op, void *param);
|
||||||
int HYPERVISOR_grant_table_op(int op, void *uop, unsigned int count);
|
int HYPERVISOR_grant_table_op(int op, void *uop, unsigned int count);
|
||||||
|
|
||||||
|
#ifdef CONFIG_XEN_DOM0
|
||||||
|
int HYPERVISOR_domctl(void *param);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_ */
|
#endif /* ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_ */
|
||||||
|
|
37
include/zephyr/xen/dom0/domctl.h
Normal file
37
include/zephyr/xen/dom0/domctl.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/* SPDX-License-Identifier: Apache-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 EPAM Systems
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef __XEN_DOM0_DOMCTL_H__
|
||||||
|
#define __XEN_DOM0_DOMCTL_H__
|
||||||
|
|
||||||
|
#include <zephyr/xen/generic.h>
|
||||||
|
#include <zephyr/xen/public/domctl.h>
|
||||||
|
#include <zephyr/xen/public/xen.h>
|
||||||
|
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
int xen_domctl_scheduler_op(int domid, struct xen_domctl_scheduler_op *sched_op);
|
||||||
|
int xen_domctl_pausedomain(int domid);
|
||||||
|
int xen_domctl_unpausedomain(int domid);
|
||||||
|
int xen_domctl_resumedomain(int domid);
|
||||||
|
int xen_domctl_getvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt);
|
||||||
|
int xen_domctl_setvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt);
|
||||||
|
int xen_domctl_getdomaininfo(int domid, xen_domctl_getdomaininfo_t *dom_info);
|
||||||
|
int xen_domctl_set_paging_mempool_size(int domid, uint64_t size_mb);
|
||||||
|
int xen_domctl_max_mem(int domid, uint64_t max_memkb);
|
||||||
|
int xen_domctl_set_address_size(int domid, int addr_size);
|
||||||
|
int xen_domctl_iomem_permission(int domid, uint64_t first_mfn,
|
||||||
|
uint64_t nr_mfns, uint8_t allow_access);
|
||||||
|
int xen_domctl_memory_mapping(int domid, uint64_t first_gfn, uint64_t first_mfn,
|
||||||
|
uint64_t nr_mfns, uint32_t add_mapping);
|
||||||
|
int xen_domctl_assign_dt_device(int domid, char *dtdev_path);
|
||||||
|
int xen_domctl_bind_pt_irq(int domid, uint32_t machine_irq, uint8_t irq_type, uint8_t bus,
|
||||||
|
uint8_t device, uint8_t intx, uint8_t isa_irq, uint16_t spi);
|
||||||
|
int xen_domctl_max_vcpus(int domid, int max_vcpus);
|
||||||
|
int xen_domctl_createdomain(int domid, struct xen_domctl_createdomain *config);
|
||||||
|
int xen_domctl_cacheflush(int domid, struct xen_domctl_cacheflush *cacheflush);
|
||||||
|
int xen_domctl_destroydomain(int domid);
|
||||||
|
|
||||||
|
#endif /* __XEN_DOM0_DOMCTL_H__ */
|
Loading…
Reference in a new issue