Skip to content

Commit 3581527

Browse files
firscityfabiobaltieri
authored andcommitted
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 <[email protected]>
1 parent 0c69913 commit 3581527

File tree

6 files changed

+361
-7
lines changed

6 files changed

+361
-7
lines changed

arch/arm64/core/xen/hypercall.S

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
/* SPDX-License-Identifier: Apache-2.0 */
12
/*
2-
* Copyright (c) 2021 EPAM Systems
3-
*
4-
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright (c) 2021-2023 EPAM Systems
54
*/
65

76
#include <zephyr/toolchain.h>
@@ -24,3 +23,7 @@ HYPERCALL(sched_op);
2423
HYPERCALL(event_channel_op);
2524
HYPERCALL(hvm_op);
2625
HYPERCALL(memory_op);
26+
27+
#ifdef CONFIG_XEN_DOM0
28+
HYPERCALL(domctl);
29+
#endif

drivers/xen/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# SPDX-License-Identifier: Apache-2.0
2-
# Copyright (c) 2021-2022 EPAM Systems
2+
# Copyright (c) 2021-2023 EPAM Systems
33

44
zephyr_sources(hvm.c)
55
zephyr_sources(events.c)
66
zephyr_sources_ifdef(CONFIG_XEN_GRANT_TABLE gnttab.c)
7+
8+
add_subdirectory_ifdef(CONFIG_XEN_DOM0 dom0)

drivers/xen/dom0/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright (c) 2023 EPAM Systems
3+
4+
zephyr_sources(domctl.c)

drivers/xen/dom0/domctl.c

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
/* SPDX-License-Identifier: Apache-2.0 */
2+
/*
3+
* Copyright (c) 2023 EPAM Systems
4+
*
5+
*/
6+
7+
#include <zephyr/arch/arm64/hypercall.h>
8+
#include <zephyr/xen/dom0/domctl.h>
9+
#include <zephyr/xen/generic.h>
10+
#include <zephyr/xen/public/domctl.h>
11+
#include <zephyr/xen/public/xen.h>
12+
13+
#include <zephyr/init.h>
14+
#include <zephyr/kernel.h>
15+
#include <string.h>
16+
17+
static int do_domctl(xen_domctl_t *domctl)
18+
{
19+
domctl->interface_version = XEN_DOMCTL_INTERFACE_VERSION;
20+
return HYPERVISOR_domctl(domctl);
21+
}
22+
23+
int xen_domctl_scheduler_op(int domid, struct xen_domctl_scheduler_op *sched_op)
24+
{
25+
xen_domctl_t domctl = {
26+
.cmd = XEN_DOMCTL_scheduler_op,
27+
.domain = domid,
28+
.u.scheduler_op = *sched_op,
29+
};
30+
31+
return do_domctl(&domctl);
32+
}
33+
34+
int xen_domctl_pausedomain(int domid)
35+
{
36+
xen_domctl_t domctl = {
37+
.cmd = XEN_DOMCTL_pausedomain,
38+
.domain = domid,
39+
};
40+
41+
return do_domctl(&domctl);
42+
}
43+
44+
int xen_domctl_unpausedomain(int domid)
45+
{
46+
xen_domctl_t domctl = {
47+
.cmd = XEN_DOMCTL_unpausedomain,
48+
.domain = domid,
49+
};
50+
51+
return do_domctl(&domctl);
52+
}
53+
54+
int xen_domctl_resumedomain(int domid)
55+
{
56+
xen_domctl_t domctl = {
57+
.cmd = XEN_DOMCTL_resumedomain,
58+
.domain = domid,
59+
};
60+
61+
return do_domctl(&domctl);
62+
}
63+
64+
int xen_domctl_getvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt)
65+
{
66+
xen_domctl_t domctl = {
67+
.cmd = XEN_DOMCTL_getvcpucontext,
68+
.domain = domid,
69+
.u.vcpucontext.vcpu = 0,
70+
};
71+
72+
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
73+
74+
return do_domctl(&domctl);
75+
}
76+
77+
int xen_domctl_setvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt)
78+
{
79+
xen_domctl_t domctl = {
80+
.cmd = XEN_DOMCTL_setvcpucontext,
81+
.domain = domid,
82+
.u.vcpucontext.vcpu = 0,
83+
};
84+
85+
set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt);
86+
87+
return do_domctl(&domctl);
88+
}
89+
90+
int xen_domctl_getdomaininfo(int domid, xen_domctl_getdomaininfo_t *dom_info)
91+
{
92+
int rc;
93+
xen_domctl_t domctl = {
94+
.cmd = XEN_DOMCTL_getdomaininfo,
95+
.domain = domid,
96+
};
97+
98+
rc = do_domctl(&domctl);
99+
if (rc) {
100+
return rc;
101+
}
102+
103+
memcpy(dom_info, &domctl.u.getdomaininfo, sizeof(*dom_info));
104+
105+
return 0;
106+
}
107+
108+
int xen_domctl_get_paging_mempool_size(int domid, uint64_t *size_mb)
109+
{
110+
int rc;
111+
xen_domctl_t domctl = {
112+
.cmd = XEN_DOMCTL_get_paging_mempool_size,
113+
.domain = domid,
114+
};
115+
116+
rc = do_domctl(&domctl);
117+
if (rc)
118+
return rc;
119+
120+
*size_mb = domctl.u.paging_mempool.size;
121+
122+
return 0;
123+
}
124+
125+
int xen_domctl_set_paging_mempool_size(int domid, uint64_t size_mb)
126+
{
127+
xen_domctl_t domctl = {
128+
.cmd = XEN_DOMCTL_set_paging_mempool_size,
129+
.domain = domid,
130+
.u.paging_mempool.size = size_mb,
131+
};
132+
133+
return do_domctl(&domctl);
134+
}
135+
136+
int xen_domctl_max_mem(int domid, uint64_t max_memkb)
137+
{
138+
xen_domctl_t domctl = {
139+
.cmd = XEN_DOMCTL_max_mem,
140+
.domain = domid,
141+
.u.max_mem.max_memkb = max_memkb,
142+
};
143+
144+
return do_domctl(&domctl);
145+
}
146+
147+
int xen_domctl_set_address_size(int domid, int addr_size)
148+
{
149+
xen_domctl_t domctl = {
150+
.domain = domid,
151+
.cmd = XEN_DOMCTL_set_address_size,
152+
.u.address_size.size = addr_size,
153+
};
154+
155+
return do_domctl(&domctl);
156+
}
157+
158+
int xen_domctl_iomem_permission(int domid, uint64_t first_mfn,
159+
uint64_t nr_mfns, uint8_t allow_access)
160+
{
161+
xen_domctl_t domctl = {
162+
.domain = domid,
163+
.cmd = XEN_DOMCTL_iomem_permission,
164+
.u.iomem_permission.first_mfn = first_mfn,
165+
.u.iomem_permission.nr_mfns = nr_mfns,
166+
.u.iomem_permission.allow_access = allow_access,
167+
};
168+
169+
return do_domctl(&domctl);
170+
}
171+
172+
int xen_domctl_memory_mapping(int domid, uint64_t first_gfn, uint64_t first_mfn,
173+
uint64_t nr_mfns, uint32_t add_mapping)
174+
{
175+
int ret;
176+
uint64_t curr, nr_max, done;
177+
xen_domctl_t domctl = {
178+
.domain = domid,
179+
.cmd = XEN_DOMCTL_memory_mapping,
180+
.u.memory_mapping.add_mapping = add_mapping,
181+
};
182+
183+
if (!nr_mfns) {
184+
return 0;
185+
}
186+
187+
/* nr_mfns can be big and we need to handle this here */
188+
done = 0;
189+
nr_max = nr_mfns;
190+
do {
191+
domctl.u.memory_mapping.first_gfn = first_gfn + done;
192+
domctl.u.memory_mapping.first_mfn = first_mfn + done;
193+
194+
curr = MIN(nr_mfns - done, nr_max);
195+
domctl.u.memory_mapping.nr_mfns = curr;
196+
197+
ret = do_domctl(&domctl);
198+
if (ret < 0) {
199+
if (ret == -E2BIG) {
200+
/* Check if we not reach min amount */
201+
if (nr_max <= 1) {
202+
break;
203+
}
204+
205+
/* Decrease amount twice and try again */
206+
nr_max = nr_max >> 1;
207+
continue;
208+
} else {
209+
break;
210+
}
211+
}
212+
213+
done += curr;
214+
} while (done < nr_mfns);
215+
216+
/* We may come here when get E2BIG and reach 1 at nr_max */
217+
if (!done) {
218+
ret = -1;
219+
}
220+
221+
return ret;
222+
}
223+
224+
int xen_domctl_assign_dt_device(int domid, char *dtdev_path)
225+
{
226+
xen_domctl_t domctl = {
227+
.domain = domid,
228+
.cmd = XEN_DOMCTL_assign_device,
229+
.u.assign_device.flags = 0,
230+
.u.assign_device.dev = XEN_DOMCTL_DEV_DT,
231+
.u.assign_device.u.dt.size = strlen(dtdev_path),
232+
};
233+
234+
set_xen_guest_handle(domctl.u.assign_device.u.dt.path, dtdev_path);
235+
236+
return do_domctl(&domctl);
237+
238+
}
239+
240+
int xen_domctl_bind_pt_irq(int domid, uint32_t machine_irq, uint8_t irq_type,
241+
uint8_t bus, uint8_t device, uint8_t intx, uint8_t isa_irq,
242+
uint16_t spi)
243+
{
244+
xen_domctl_t domctl = {
245+
.domain = domid,
246+
.cmd = XEN_DOMCTL_bind_pt_irq,
247+
};
248+
struct xen_domctl_bind_pt_irq *bind = &(domctl.u.bind_pt_irq);
249+
250+
switch (irq_type) {
251+
case PT_IRQ_TYPE_SPI:
252+
bind->irq_type = irq_type;
253+
bind->machine_irq = machine_irq;
254+
bind->u.spi.spi = spi;
255+
break;
256+
default:
257+
/* TODO: implement other types */
258+
return -ENOTSUP;
259+
}
260+
261+
return do_domctl(&domctl);
262+
}
263+
264+
int xen_domctl_max_vcpus(int domid, int max_vcpus)
265+
{
266+
xen_domctl_t domctl = {
267+
.cmd = XEN_DOMCTL_max_vcpus,
268+
.domain = domid,
269+
.u.max_vcpus.max = max_vcpus,
270+
};
271+
272+
return do_domctl(&domctl);
273+
}
274+
275+
int xen_domctl_createdomain(int domid, struct xen_domctl_createdomain *config)
276+
{
277+
xen_domctl_t domctl = {
278+
.cmd = XEN_DOMCTL_createdomain,
279+
.domain = domid,
280+
.u.createdomain = *config,
281+
};
282+
283+
return do_domctl(&domctl);
284+
}
285+
286+
int xen_domctl_destroydomain(int domid)
287+
{
288+
xen_domctl_t domctl = {
289+
.cmd = XEN_DOMCTL_destroydomain,
290+
.domain = domid,
291+
};
292+
293+
return do_domctl(&domctl);
294+
}
295+
296+
int xen_domctl_cacheflush(int domid, struct xen_domctl_cacheflush *cacheflush)
297+
{
298+
xen_domctl_t domctl = {
299+
.cmd = XEN_DOMCTL_cacheflush,
300+
.domain = domid,
301+
.u.cacheflush = *cacheflush,
302+
};
303+
304+
return do_domctl(&domctl);
305+
}

include/zephyr/arch/arm64/hypercall.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
/* SPDX-License-Identifier: Apache-2.0 */
12
/*
2-
* Copyright (c) 2021-2022 EPAM Systems
3-
*
4-
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright (c) 2021-2023 EPAM Systems
54
*/
65

76
#ifndef ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_
@@ -15,4 +14,8 @@ int HYPERVISOR_hvm_op(int op, void *param);
1514
int HYPERVISOR_memory_op(int op, void *param);
1615
int HYPERVISOR_grant_table_op(int op, void *uop, unsigned int count);
1716

17+
#ifdef CONFIG_XEN_DOM0
18+
int HYPERVISOR_domctl(void *param);
19+
#endif
20+
1821
#endif /* ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_ */

include/zephyr/xen/dom0/domctl.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/* SPDX-License-Identifier: Apache-2.0 */
2+
/*
3+
* Copyright (c) 2023 EPAM Systems
4+
*
5+
*/
6+
#ifndef __XEN_DOM0_DOMCTL_H__
7+
#define __XEN_DOM0_DOMCTL_H__
8+
9+
#include <zephyr/xen/generic.h>
10+
#include <zephyr/xen/public/domctl.h>
11+
#include <zephyr/xen/public/xen.h>
12+
13+
#include <zephyr/kernel.h>
14+
15+
int xen_domctl_scheduler_op(int domid, struct xen_domctl_scheduler_op *sched_op);
16+
int xen_domctl_pausedomain(int domid);
17+
int xen_domctl_unpausedomain(int domid);
18+
int xen_domctl_resumedomain(int domid);
19+
int xen_domctl_getvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt);
20+
int xen_domctl_setvcpucontext(int domid, int vcpu, vcpu_guest_context_t *ctxt);
21+
int xen_domctl_getdomaininfo(int domid, xen_domctl_getdomaininfo_t *dom_info);
22+
int xen_domctl_set_paging_mempool_size(int domid, uint64_t size_mb);
23+
int xen_domctl_max_mem(int domid, uint64_t max_memkb);
24+
int xen_domctl_set_address_size(int domid, int addr_size);
25+
int xen_domctl_iomem_permission(int domid, uint64_t first_mfn,
26+
uint64_t nr_mfns, uint8_t allow_access);
27+
int xen_domctl_memory_mapping(int domid, uint64_t first_gfn, uint64_t first_mfn,
28+
uint64_t nr_mfns, uint32_t add_mapping);
29+
int xen_domctl_assign_dt_device(int domid, char *dtdev_path);
30+
int xen_domctl_bind_pt_irq(int domid, uint32_t machine_irq, uint8_t irq_type, uint8_t bus,
31+
uint8_t device, uint8_t intx, uint8_t isa_irq, uint16_t spi);
32+
int xen_domctl_max_vcpus(int domid, int max_vcpus);
33+
int xen_domctl_createdomain(int domid, struct xen_domctl_createdomain *config);
34+
int xen_domctl_cacheflush(int domid, struct xen_domctl_cacheflush *cacheflush);
35+
int xen_domctl_destroydomain(int domid);
36+
37+
#endif /* __XEN_DOM0_DOMCTL_H__ */

0 commit comments

Comments
 (0)