Skip to content

Commit 571f5b9

Browse files
soburinashif
authored andcommitted
drivers: xen: add DMOP hypercall wrappers
Add wrappers for following XEN_DMOP_* hypercalls. These enables Xen device model control path: dm_op provides operations to create/manage the ioreq server so guest MMIO accesses are trapped and handled by the hypervisor. These are guarded by CONFIG_XEN_DMOP. - dmop - dmop_create_ioreq_server XEN_DMOP_create_ioreq_server - dmop_map_io_range_to_ioreq_server XEN_DMOP_map_io_range_to_ioreq_server - dmop_set_ioreq_server_state XEN_DMOP_set_ioreq_server_state - dmop_nr_vcpus XEN_DMOP_nr_vcpus - dmop_set_irq_level: XEN_DMOP_set_irq_level Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
1 parent 909373f commit 571f5b9

File tree

9 files changed

+930
-0
lines changed

9 files changed

+930
-0
lines changed

arch/arm64/core/xen/hypercall.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ HYPERCALL(sched_op);
2323
HYPERCALL(event_channel_op);
2424
HYPERCALL(hvm_op);
2525
HYPERCALL(memory_op);
26+
HYPERCALL(dm_op);
2627

2728
#ifdef CONFIG_XEN_DOM0
2829
HYPERCALL(domctl);

drivers/xen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ zephyr_sources(hvm.c)
55
zephyr_sources(events.c)
66
zephyr_sources_ifdef(CONFIG_XEN_GRANT_TABLE gnttab.c)
77
zephyr_sources(memory.c)
8+
zephyr_sources_ifdef(CONFIG_XEN_DMOP dmop.c)
89

910
add_subdirectory_ifdef(CONFIG_XEN_DOM0 dom0)

drivers/xen/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ if XEN
55

66
menu "Xen drivers"
77

8+
config XEN_DMOP
9+
bool "Xen dmop hypercall wrappers"
10+
help
11+
Enable lightweight wrappers for Xen dm_op hypercalls used by
12+
Xen device backends. Disable to drop dmop.c from the build.
13+
814
config XEN_GRANT_TABLE
915
bool "Xen grant table driver"
1016
depends on HEAP_MEM_POOL_SIZE > 0

drivers/xen/dmop.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* Copyright 2025 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/sys/util.h>
8+
#include <zephyr/xen/dmop.h>
9+
#include <zephyr/arch/arm64/hypercall.h>
10+
11+
int dmop_create_ioreq_server(domid_t domid, uint8_t handle_bufioreq, ioservid_t *id)
12+
{
13+
struct xen_dm_op_buf bufs[1] = {0};
14+
struct xen_dm_op dm_op = {0};
15+
int err;
16+
17+
dm_op.op = XEN_DMOP_create_ioreq_server;
18+
dm_op.u.create_ioreq_server.handle_bufioreq = handle_bufioreq;
19+
20+
set_xen_guest_handle(bufs[0].h, &dm_op);
21+
bufs[0].size = sizeof(struct xen_dm_op);
22+
23+
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs);
24+
if (err) {
25+
return err;
26+
}
27+
28+
*id = dm_op.u.create_ioreq_server.id;
29+
30+
return 0;
31+
}
32+
33+
int dmop_destroy_ioreq_server(domid_t domid, ioservid_t id)
34+
{
35+
struct xen_dm_op_buf bufs[1] = {0};
36+
struct xen_dm_op dm_op = {0};
37+
int err;
38+
39+
dm_op.op = XEN_DMOP_destroy_ioreq_server;
40+
dm_op.u.destroy_ioreq_server.id = id;
41+
42+
set_xen_guest_handle(bufs[0].h, &dm_op);
43+
bufs[0].size = sizeof(struct xen_dm_op);
44+
45+
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs);
46+
if (err) {
47+
return err;
48+
}
49+
50+
return 0;
51+
}
52+
53+
int dmop_map_io_range_to_ioreq_server(domid_t domid, ioservid_t id, uint32_t type, uint64_t start,
54+
uint64_t end)
55+
{
56+
struct xen_dm_op_buf bufs[1] = {0};
57+
struct xen_dm_op dm_op = {0};
58+
int err;
59+
60+
dm_op.op = XEN_DMOP_map_io_range_to_ioreq_server;
61+
dm_op.u.map_io_range_to_ioreq_server.id = id;
62+
dm_op.u.map_io_range_to_ioreq_server.type = type;
63+
dm_op.u.map_io_range_to_ioreq_server.start = start;
64+
dm_op.u.map_io_range_to_ioreq_server.end = end;
65+
66+
set_xen_guest_handle(bufs[0].h, &dm_op);
67+
bufs[0].size = sizeof(struct xen_dm_op);
68+
69+
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs);
70+
if (err < 0) {
71+
return err;
72+
}
73+
74+
return 0;
75+
}
76+
77+
int dmop_unmap_io_range_from_ioreq_server(domid_t domid, ioservid_t id, uint32_t type,
78+
uint64_t start, uint64_t end)
79+
{
80+
struct xen_dm_op_buf bufs[1] = {0};
81+
struct xen_dm_op dm_op = {0};
82+
int err;
83+
84+
dm_op.op = XEN_DMOP_unmap_io_range_from_ioreq_server;
85+
dm_op.u.unmap_io_range_from_ioreq_server.id = id;
86+
dm_op.u.unmap_io_range_from_ioreq_server.type = type;
87+
dm_op.u.unmap_io_range_from_ioreq_server.start = start;
88+
dm_op.u.unmap_io_range_from_ioreq_server.end = end;
89+
90+
set_xen_guest_handle(bufs[0].h, &dm_op);
91+
bufs[0].size = sizeof(struct xen_dm_op);
92+
93+
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs);
94+
if (err < 0) {
95+
return err;
96+
}
97+
98+
return 0;
99+
}
100+
101+
int dmop_set_ioreq_server_state(domid_t domid, ioservid_t id, uint8_t enabled)
102+
{
103+
struct xen_dm_op_buf bufs[1] = {0};
104+
struct xen_dm_op dm_op = {0};
105+
int err;
106+
107+
dm_op.op = XEN_DMOP_set_ioreq_server_state;
108+
dm_op.u.set_ioreq_server_state.id = id;
109+
dm_op.u.set_ioreq_server_state.enabled = enabled;
110+
111+
set_xen_guest_handle(bufs[0].h, &dm_op);
112+
bufs[0].size = sizeof(struct xen_dm_op);
113+
114+
err = HYPERVISOR_dm_op(domid, 1, bufs);
115+
if (err) {
116+
return err;
117+
}
118+
119+
return 0;
120+
}
121+
122+
int dmop_nr_vcpus(domid_t domid)
123+
{
124+
struct xen_dm_op_buf bufs[1] = {0};
125+
struct xen_dm_op dm_op = {0};
126+
int err;
127+
128+
dm_op.op = XEN_DMOP_nr_vcpus;
129+
130+
set_xen_guest_handle(bufs[0].h, &dm_op);
131+
bufs[0].size = sizeof(struct xen_dm_op);
132+
133+
err = HYPERVISOR_dm_op(domid, 1, bufs);
134+
if (err < 0) {
135+
return err;
136+
}
137+
138+
return dm_op.u.nr_vcpus.vcpus;
139+
}
140+
141+
int dmop_set_irq_level(domid_t domid, uint32_t irq, uint8_t level)
142+
{
143+
struct xen_dm_op_buf bufs[1] = {0};
144+
struct xen_dm_op dm_op = {0};
145+
int err;
146+
147+
dm_op.op = XEN_DMOP_set_irq_level;
148+
dm_op.u.set_irq_level.irq = irq;
149+
dm_op.u.set_irq_level.level = level;
150+
151+
set_xen_guest_handle(bufs[0].h, &dm_op);
152+
bufs[0].size = sizeof(struct xen_dm_op);
153+
154+
err = HYPERVISOR_dm_op(domid, 1, bufs);
155+
156+
return err;
157+
}

include/zephyr/arch/arm64/hypercall.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@
66
#ifndef ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_
77
#define ZEPHYR_INCLUDE_ARCH_ARM64_HYPERCALL_H_
88

9+
#include <zephyr/xen/dmop.h>
10+
911
/* defined in hypercall.S by HYPERCALL(hypercall) */
1012
int HYPERVISOR_console_io(int op, int cnt, char *str);
1113
int HYPERVISOR_sched_op(int op, void *param);
1214
int HYPERVISOR_event_channel_op(int op, void *param);
1315
int HYPERVISOR_hvm_op(int op, void *param);
1416
int HYPERVISOR_memory_op(int op, void *param);
1517
int HYPERVISOR_grant_table_op(int op, void *uop, unsigned int count);
18+
int HYPERVISOR_dm_op(domid_t domid, unsigned int nr_bufs, struct xen_dm_op_buf *bufs);
1619

1720
#ifdef CONFIG_XEN_DOM0
1821
int HYPERVISOR_domctl(void *param);

include/zephyr/xen/dmop.h

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2025 TOKITA Hiroshi
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef ZEPHYR_XEN_DMOP_H_
8+
#define ZEPHYR_XEN_DMOP_H_
9+
10+
#include <zephyr/xen/public/hvm/dm_op.h>
11+
12+
/**
13+
* @brief Create an I/O request server in the given Xen domain.
14+
*
15+
* This function issues the XEN_DMOP_create_ioreq_server hypercall to create
16+
* a server that handles I/O requests on behalf of the guest domain.
17+
*
18+
* @param domid Xen domain identifier where the server is created.
19+
* @param handle_bufioreq Flag indicating whether buffered I/O requests should be handled.
20+
* Set to non-zero to enable buffered handling.
21+
* @param id Output pointer to receive the newly created server ID.
22+
*
23+
* @retval 0 On success
24+
* @retval -errno Negative errno code on failure.
25+
*/
26+
int dmop_create_ioreq_server(domid_t domid, uint8_t handle_bufioreq, ioservid_t *id);
27+
28+
/**
29+
* @brief Destroy a previously created I/O request server.
30+
*
31+
* Issues the XEN_DMOP_destroy_ioreq_server hypercall to tear down the
32+
* specified I/O request server.
33+
*
34+
* @param domid Xen domain identifier where the server exists.
35+
* @param id I/O request server ID returned by dmop_create_ioreq_server().
36+
*
37+
* @retval 0 On success
38+
* @retval -errno Negative errno code on failure.
39+
*/
40+
int dmop_destroy_ioreq_server(domid_t domid, ioservid_t id);
41+
42+
/**
43+
* @brief Map a specified I/O address range to an existing I/O request server.
44+
*
45+
* This function issues the XEN_DMOP_map_io_range_to_ioreq_server hypercall to grant
46+
* access to the given I/O address range for the specified server.
47+
*
48+
* @param domid Xen domain identifier where the mapping is applied.
49+
* @param id I/O request server ID returned by dmop_create_ioreq_server().
50+
* @param type Type identifier for the I/O range (e.g., MMIO, port I/O).
51+
* @param start Start physical address of the I/O range.
52+
* @param end End physical address (inclusive) of the I/O range.
53+
*
54+
* @retval 0 On success
55+
* @retval -errno Negative errno code on failure.
56+
*/
57+
int dmop_map_io_range_to_ioreq_server(domid_t domid, ioservid_t id, uint32_t type, uint64_t start,
58+
uint64_t end);
59+
60+
/**
61+
* @brief Unmap an I/O address range from an I/O request server.
62+
*
63+
* Issues the XEN_DMOP_unmap_io_range_from_ioreq_server hypercall to revoke
64+
* access to a previously mapped I/O address range.
65+
*
66+
* @param domid Xen domain identifier where the unmapping is applied.
67+
* @param id I/O request server ID returned by dmop_create_ioreq_server().
68+
* @param type Type identifier for the I/O range (e.g., MMIO, port I/O).
69+
* @param start Start physical address of the I/O range.
70+
* @param end End physical address (inclusive) of the I/O range.
71+
*
72+
* @retval 0 On success
73+
* @retval -errno Negative errno code on failure.
74+
*/
75+
int dmop_unmap_io_range_from_ioreq_server(domid_t domid, ioservid_t id, uint32_t type,
76+
uint64_t start, uint64_t end);
77+
78+
/**
79+
* @brief Enable or disable an existing I/O request server.
80+
*
81+
* This function issues the XEN_DMOP_set_ioreq_server_state hypercall to change
82+
* the operational state of the specified I/O request server.
83+
*
84+
* @param domid Xen domain identifier.
85+
* @param id I/O request server ID to modify.
86+
* @param enabled Non-zero to enable the server, zero to disable it.
87+
*
88+
* @retval 0 On success
89+
* @retval -errno Negative errno code on failure.
90+
*/
91+
int dmop_set_ioreq_server_state(domid_t domid, ioservid_t id, uint8_t enabled);
92+
93+
/**
94+
* @brief Query the number of virtual CPUs in a Xen domain.
95+
*
96+
* This function issues the XEN_DMOP_nr_vcpus hypercall to retrieve
97+
* the current vCPU count for the specified domain.
98+
*
99+
* @param domid Xen domain identifier to query.
100+
*
101+
* @retval num_vcpus The number of vCPUs on success.
102+
* @retval -errno Negative errno code on failure.
103+
*/
104+
int dmop_nr_vcpus(domid_t domid);
105+
106+
/**
107+
* @brief Set the interrupt level for a specific IRQ in a Xen domain.
108+
*
109+
* This function issues the XEN_DMOP_set_irq_level hypercall to adjust
110+
* the signal level (assert or deassert) for the given IRQ line.
111+
*
112+
* @param domid Xen domain identifier.
113+
* @param irq IRQ number whose level is to be set.
114+
* @param level Non-zero to assert (raise) the IRQ, zero to deassert (lower) it.
115+
*
116+
* @retval 0 On success
117+
* @retval -errno Negative errno code on failure.
118+
*/
119+
int dmop_set_irq_level(domid_t domid, uint32_t irq, uint8_t level);
120+
121+
#endif /* ZEPHYR_XEN_DMOP_H_ */

0 commit comments

Comments
 (0)