On Thu, Feb 05, 2026 at 08:58:04PM +0100, Ruslan Ruslichenko wrote:
> From: Ruslan Ruslichenko <[email protected]>
>
> Introduce main execution loop for the Remote Port protocol.
> Creates a dedicated thread to manage the communication lifecycle.
> This includes logic to read packets and manage RX queue.
>
> Patch also implements handshake logic to verify protocol
> versions and negotiate capabilities with remote peer.
>
> Signed-off-by: Edgar E. Iglesias <[email protected]>
> Signed-off-by: Takahiro Nakata <[email protected]>
> Signed-off-by: Ruslan Ruslichenko <[email protected]>
> ---
> hw/core/remote-port.c | 190 ++++++++++++++++++++++++++++++++++
> include/hw/core/remote-port.h | 22 ++++
> 2 files changed, 212 insertions(+)
>
> diff --git a/hw/core/remote-port.c b/hw/core/remote-port.c
> index 5154c1bc2a..91b0682884 100644
> --- a/hw/core/remote-port.c
> +++ b/hw/core/remote-port.c
> @@ -52,6 +52,88 @@
> #define REMOTE_PORT_CLASS(klass) \
> OBJECT_CLASS_CHECK(RemotePortClass, (klass), TYPE_REMOTE_PORT)
>
> +static void rp_pkt_dump(const char *prefix, const char *buf, size_t len)
> +{
> + qemu_hexdump(stdout, prefix, buf, len);
> +}
> +
> +static void rp_fatal_error(RemotePort *s, const char *reason)
> +{
> + error_report("%s: %s", s->prefix, reason);
> + exit(EXIT_FAILURE);
> +}
> +
> +static ssize_t rp_recv(RemotePort *s, void *buf, size_t count)
> +{
> + ssize_t r;
> +
> + r = qemu_chr_fe_read_all(&s->chr, buf, count);
> + if (r <= 0) {
> + return r;
> + }
> + if (r != count) {
> + error_report("%s: Bad read, expected %zd but got %zd",
> + s->prefix, count, r);
> + rp_fatal_error(s, "Bad read");
> + }
> +
> + return r;
> +}
> +
> +ssize_t rp_write(RemotePort *s, const void *buf, size_t count)
> +{
> + ssize_t r;
> +
> + qemu_mutex_lock(&s->write_mutex);
> + r = qemu_chr_fe_write_all(&s->chr, buf, count);
> + qemu_mutex_unlock(&s->write_mutex);
> + assert(r == count);
> + if (r <= 0) {
> + error_report("%s: Disconnected r=%zd buf=%p count=%zd",
> + s->prefix, r, buf, count);
> + rp_fatal_error(s, "Bad write");
> + }
> + return r;
> +}
> +
> +static void rp_cmd_hello(RemotePort *s, struct rp_pkt *pkt)
> +{
> + s->peer.version = pkt->hello.version;
> + if (pkt->hello.version.major != RP_VERSION_MAJOR) {
> + error_report("remote-port version missmatch remote=%d.%d
> local=%d.%d",
> + pkt->hello.version.major, pkt->hello.version.minor,
> + RP_VERSION_MAJOR, RP_VERSION_MINOR);
> + rp_fatal_error(s, "Bad version");
> + }
> +
> + if (pkt->hello.caps.len) {
> + void *caps = (char *) pkt + pkt->hello.caps.offset;
> +
> + rp_process_caps(&s->peer, caps, pkt->hello.caps.len);
> + }
> +}
> +
> +static void rp_say_hello(RemotePort *s)
> +{
> + struct rp_pkt_hello pkt;
> + uint32_t caps[] = {
> + CAP_BUSACCESS_EXT_BASE,
> + CAP_BUSACCESS_EXT_BYTE_EN,
> + CAP_WIRE_POSTED_UPDATES,
> + CAP_ATS,
> + };
> + size_t len;
> +
> + len = rp_encode_hello_caps(s->current_id++, 0, &pkt, RP_VERSION_MAJOR,
> + RP_VERSION_MINOR,
> + caps, caps, sizeof caps / sizeof caps[0]);
> + rp_write(s, (void *) &pkt, len);
> +
> + if (sizeof caps) {
> + rp_write(s, caps, sizeof caps);
> + }
> +}
> +
> static char *rp_sanitize_prefix(RemotePort *s)
> {
> char *sanitized_name;
> @@ -105,6 +187,108 @@ static Chardev *rp_autocreate_chardev(RemotePort *s,
> char *name)
> return chr;
> }
>
> +static bool rp_pt_process_pkt(RemotePort *s, RemotePortDynPkt *dpkt)
> +{
> + struct rp_pkt *pkt = dpkt->pkt;
> +
> + D(qemu_log("%s: cmd=%x id=%d dev=%d\n", __func__, pkt->hdr.cmd,
> + pkt->hdr.id, pkt->hdr.dev));
This kind of thing feels better suited to being implement with
QEMU tracepoints.
> +
> + if (pkt->hdr.dev >= ARRAY_SIZE(s->devs)) {
> + /* FIXME: Respond with an error. */
> + return true;
> + }
> +
> + switch (pkt->hdr.cmd) {
> + case RP_CMD_hello:
> + rp_cmd_hello(s, pkt);
> + break;
> + case RP_CMD_read:
> + case RP_CMD_write:
> + case RP_CMD_interrupt:
> + case RP_CMD_ats_req:
> + case RP_CMD_ats_inv:
> + /* TBD */;
> + break;
> + default:
> + g_assert_not_reached();
> + break;
> + }
> + return false;
> +}
With regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|