-
Notifications
You must be signed in to change notification settings - Fork 7.8k
drivers: vhost: Add Xen-MMIO VIRTIO backend #91605
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
9a620d7
ecc4750
2bb5f42
710d11d
754452c
0ef7694
834a8a3
071ee76
8ed4fd1
af226c7
9376df3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
/* | ||
* Copyright 2025 TOKITA Hiroshi | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/sys/util.h> | ||
#include <zephyr/xen/dmop.h> | ||
#include <zephyr/arch/arm64/hypercall.h> | ||
|
||
int dmop_create_ioreq_server(domid_t domid, uint8_t handle_bufioreq, ioservid_t *id) | ||
{ | ||
struct xen_dm_op_buf bufs[1] = {0}; | ||
struct xen_dm_op dm_op = {0}; | ||
int err; | ||
|
||
dm_op.op = XEN_DMOP_create_ioreq_server; | ||
dm_op.u.create_ioreq_server.handle_bufioreq = handle_bufioreq; | ||
|
||
set_xen_guest_handle(bufs[0].h, &dm_op); | ||
bufs[0].size = sizeof(struct xen_dm_op); | ||
|
||
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs); | ||
if (err) { | ||
return err; | ||
} | ||
|
||
*id = dm_op.u.create_ioreq_server.id; | ||
|
||
return 0; | ||
} | ||
|
||
int dmop_destroy_ioreq_server(domid_t domid, ioservid_t id) | ||
{ | ||
struct xen_dm_op_buf bufs[1] = {0}; | ||
struct xen_dm_op dm_op = {0}; | ||
int err; | ||
|
||
dm_op.op = XEN_DMOP_destroy_ioreq_server; | ||
dm_op.u.destroy_ioreq_server.id = id; | ||
|
||
set_xen_guest_handle(bufs[0].h, &dm_op); | ||
bufs[0].size = sizeof(struct xen_dm_op); | ||
|
||
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs); | ||
if (err) { | ||
return err; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int dmop_map_io_range_to_ioreq_server(domid_t domid, ioservid_t id, uint32_t type, uint64_t start, | ||
uint64_t end) | ||
{ | ||
struct xen_dm_op_buf bufs[1] = {0}; | ||
struct xen_dm_op dm_op = {0}; | ||
int err; | ||
|
||
dm_op.op = XEN_DMOP_map_io_range_to_ioreq_server; | ||
dm_op.u.map_io_range_to_ioreq_server.id = id; | ||
dm_op.u.map_io_range_to_ioreq_server.type = type; | ||
dm_op.u.map_io_range_to_ioreq_server.start = start; | ||
dm_op.u.map_io_range_to_ioreq_server.end = end; | ||
|
||
set_xen_guest_handle(bufs[0].h, &dm_op); | ||
bufs[0].size = sizeof(struct xen_dm_op); | ||
|
||
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs); | ||
if (err < 0) { | ||
return err; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int dmop_unmap_io_range_from_ioreq_server(domid_t domid, ioservid_t id, uint32_t type, | ||
uint64_t start, uint64_t end) | ||
{ | ||
struct xen_dm_op_buf bufs[1] = {0}; | ||
struct xen_dm_op dm_op = {0}; | ||
int err; | ||
|
||
dm_op.op = XEN_DMOP_unmap_io_range_from_ioreq_server; | ||
dm_op.u.unmap_io_range_from_ioreq_server.id = id; | ||
dm_op.u.unmap_io_range_from_ioreq_server.type = type; | ||
dm_op.u.unmap_io_range_from_ioreq_server.start = start; | ||
dm_op.u.unmap_io_range_from_ioreq_server.end = end; | ||
|
||
set_xen_guest_handle(bufs[0].h, &dm_op); | ||
bufs[0].size = sizeof(struct xen_dm_op); | ||
|
||
err = HYPERVISOR_dm_op(domid, ARRAY_SIZE(bufs), bufs); | ||
if (err < 0) { | ||
return err; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int dmop_set_ioreq_server_state(domid_t domid, ioservid_t id, uint8_t enabled) | ||
{ | ||
struct xen_dm_op_buf bufs[1] = {0}; | ||
struct xen_dm_op dm_op = {0}; | ||
int err; | ||
|
||
dm_op.op = XEN_DMOP_set_ioreq_server_state; | ||
dm_op.u.set_ioreq_server_state.id = id; | ||
dm_op.u.set_ioreq_server_state.enabled = enabled; | ||
|
||
set_xen_guest_handle(bufs[0].h, &dm_op); | ||
bufs[0].size = sizeof(struct xen_dm_op); | ||
|
||
err = HYPERVISOR_dm_op(domid, 1, bufs); | ||
if (err) { | ||
return err; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int dmop_nr_vcpus(domid_t domid) | ||
{ | ||
struct xen_dm_op_buf bufs[1] = {0}; | ||
struct xen_dm_op dm_op = {0}; | ||
int err; | ||
|
||
dm_op.op = XEN_DMOP_nr_vcpus; | ||
|
||
set_xen_guest_handle(bufs[0].h, &dm_op); | ||
bufs[0].size = sizeof(struct xen_dm_op); | ||
|
||
err = HYPERVISOR_dm_op(domid, 1, bufs); | ||
if (err < 0) { | ||
return err; | ||
} | ||
|
||
return dm_op.u.nr_vcpus.vcpus; | ||
} | ||
|
||
int dmop_set_irq_level(domid_t domid, uint32_t irq, uint8_t level) | ||
{ | ||
struct xen_dm_op_buf bufs[1] = {0}; | ||
struct xen_dm_op dm_op = {0}; | ||
int err; | ||
|
||
dm_op.op = XEN_DMOP_set_irq_level; | ||
dm_op.u.set_irq_level.irq = irq; | ||
dm_op.u.set_irq_level.level = level; | ||
|
||
set_xen_guest_handle(bufs[0].h, &dm_op); | ||
bufs[0].size = sizeof(struct xen_dm_op); | ||
|
||
err = HYPERVISOR_dm_op(domid, 1, bufs); | ||
|
||
return err; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright (c) 2025 TOKITA Hiroshi | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <zephyr/arch/arm64/hypercall.h> | ||
#include <zephyr/xen/sched.h> | ||
|
||
int sched_poll(evtchn_port_t *ports, unsigned int nr_ports, uint64_t timeout) | ||
{ | ||
struct sched_poll poll = { | ||
.ports.p = ports, | ||
.nr_ports = 1, | ||
.timeout = timeout, | ||
}; | ||
|
||
return HYPERVISOR_sched_op(SCHEDOP_poll, &poll); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright (c) 2025 TOKITA Hiroshi | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef ZEPHYR_XEN_DMOP_H_ | ||
#define ZEPHYR_XEN_DMOP_H_ | ||
|
||
#include <xen/public/hvm/dm_op.h> | ||
|
||
/** | ||
* @brief Create an I/O request server in the given Xen domain. | ||
* | ||
* This function issues the XEN_DMOP_create_ioreq_server hypercall to create | ||
* a server that handles I/O requests on behalf of the guest domain. | ||
* | ||
* @param domid Xen domain identifier where the server is created. | ||
* @param handle_bufioreq Flag indicating whether buffered I/O requests should be handled. | ||
* Set to non-zero to enable buffered handling. | ||
* @param id Output pointer to receive the newly created server ID. | ||
* | ||
* @return 0 on success, or a negative errno code on failure. | ||
*/ | ||
int dmop_create_ioreq_server(domid_t domid, uint8_t handle_bufioreq, ioservid_t *id); | ||
|
||
int dmop_destroy_ioreq_server(domid_t domid, ioservid_t id); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for this one(as for |
||
|
||
/** | ||
* @brief Map a specified I/O address range to an existing I/O request server. | ||
* | ||
* This function issues the XEN_DMOP_map_io_range_to_ioreq_server hypercall to grant | ||
* access to the given I/O address range for the specified server. | ||
* | ||
* @param domid Xen domain identifier where the mapping is applied. | ||
* @param id I/O request server ID returned by dmop_create_ioreq_server(). | ||
* @param type Type identifier for the I/O range (e.g., MMIO, port I/O). | ||
* @param start Start physical address of the I/O range. | ||
* @param end End physical address (inclusive) of the I/O range. | ||
* | ||
* @return 0 on success, or a negative errno code on failure. | ||
*/ | ||
int dmop_map_io_range_to_ioreq_server(domid_t domid, ioservid_t id, uint32_t type, uint64_t start, | ||
uint64_t end); | ||
|
||
int dmop_unmap_io_range_from_ioreq_server(domid_t domid, ioservid_t id, uint32_t type, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one has missing documentation comment. I understand that this and previous are opposite to each other, but when docs will be generated it will look strange. |
||
uint64_t start, uint64_t end); | ||
|
||
/** | ||
* @brief Enable or disable an existing I/O request server. | ||
* | ||
* This function issues the XEN_DMOP_set_ioreq_server_state hypercall to change | ||
* the operational state of the specified I/O request server. | ||
* | ||
* @param domid Xen domain identifier. | ||
* @param id I/O request server ID to modify. | ||
* @param enabled Non-zero to enable the server, zero to disable it. | ||
* | ||
* @return 0 on success, or a negative errno code on failure. | ||
*/ | ||
int dmop_set_ioreq_server_state(domid_t domid, ioservid_t id, uint8_t enabled); | ||
|
||
/** | ||
* @brief Query the number of virtual CPUs in a Xen domain. | ||
* | ||
* This function issues the XEN_DMOP_nr_vcpus hypercall to retrieve | ||
* the current vCPU count for the specified domain. | ||
* | ||
* @param domid Xen domain identifier to query. | ||
* | ||
* @return The number of vCPUs on success, or a negative errno code on failure. | ||
*/ | ||
int dmop_nr_vcpus(domid_t domid); | ||
|
||
/** | ||
* @brief Set the interrupt level for a specific IRQ in a Xen domain. | ||
* | ||
* This function issues the XEN_DMOP_set_irq_level hypercall to adjust | ||
* the signal level (assert or deassert) for the given IRQ line. | ||
* | ||
* @param domid Xen domain identifier. | ||
* @param irq IRQ number whose level is to be set. | ||
* @param level Non-zero to assert (raise) the IRQ, zero to deassert (lower) it. | ||
* | ||
* @return 0 on success, or a negative errno code on failure. | ||
*/ | ||
int dmop_set_irq_level(domid_t domid, uint32_t irq, uint8_t level); | ||
|
||
#endif /* ZEPHYR_XEN_DMOP_H_ */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/* | ||
* Copyright (c) 2025 TOKITA Hiroshi | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef ZEPHYR_XEN_SCHED_H_ | ||
#define ZEPHYR_XEN_SCHED_H_ | ||
|
||
#include <xen/public/sched.h> | ||
|
||
/** | ||
* @brief Poll one or more Xen event channels for activity. | ||
* | ||
* Issues the SCHEDOP_poll hypercall to wait for events on the specified ports. | ||
* | ||
* @param ports Array of event channel ports to poll. | ||
* @param nr_ports Number of ports in the array. | ||
* @param timeout Timeout in microseconds to wait for an event. | ||
* @return 0 if an event occurred, -EAGAIN on timeout, or negative errno on error. | ||
*/ | ||
int sched_poll(evtchn_port_t *ports, unsigned int nr_ports, uint64_t timeout); | ||
|
||
#endif /* ZEPHYR_XEN_SCHED_H_ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall comment for commit
drivers: xen: add more hypercall wrapper
:I strongly suggest you to split this commit into 3 separate commits and add more description regarding how it will be used in further development. Also, I believe that
sched.c
anddmop.c
should be guarded with separate CONFIG to have a possibility to disable it.