On Wed, May 21, 2025 at 10:18 PM <dm...@proton.me> wrote:

> From: Christopher Clark <christopher.w.cl...@gmail.com>
>
> From: Christopher Clark <christopher.w.cl...@gmail.com>
>
> Simple test cases for the four Argo operations, register, unregister,
> sendv and notify exercised with a single test domain.
> Add infrastructure to access Argo: a 5-argument hypercall, number 39.
>
> Signed-off-by: Christopher Clark <christopher.cla...@baesystems.com>
> Signed-off-by: Denis Mukhin <dmuk...@ford.com>
>

Reviewed-by: Christopher Clark <christopher.w.cl...@gmail.com>
Tested-by: Christopher Clark <christopher.w.cl...@gmail.com>

Thanks for working to advance this - sorry for the slow response.

Christopher


> ---
> Original XTF argo test:
>
> https://github.com/dozylynx/meta-argo/blob/master/recipes-extended/xen/xtf/0001-Add-Argo-test.patch
> ---
>  docs/all-tests.dox      |   2 +
>  include/xen/argo.h      | 259 +++++++++++++++++++++++++++++
>  include/xtf/hypercall.h |   1 +
>  include/xtf/numbers.h   |   5 +
>  tests/argo/Makefile     |   9 +
>  tests/argo/main.c       | 353 ++++++++++++++++++++++++++++++++++++++++
>  6 files changed, 629 insertions(+)
>  create mode 100644 include/xen/argo.h
>  create mode 100644 tests/argo/Makefile
>  create mode 100644 tests/argo/main.c
>
> diff --git a/docs/all-tests.dox b/docs/all-tests.dox
> index 566762c..1a7b4b7 100644
> --- a/docs/all-tests.dox
> +++ b/docs/all-tests.dox
> @@ -178,6 +178,8 @@ states.
>
>  @section index-utility Utilities
>
> +@subpage test-argo - Argo functionality test
> +
>  @subpage test-cpuid - Print CPUID information.
>
>  @subpage test-fep - Test availability of HVM Forced Emulation Prefix.
> diff --git a/include/xen/argo.h b/include/xen/argo.h
> new file mode 100644
> index 0000000..5ae2def
> --- /dev/null
> +++ b/include/xen/argo.h
> @@ -0,0 +1,259 @@
>
> +/******************************************************************************
> + * Argo : Hypervisor-Mediated data eXchange
> + *
> + * Derived from v4v, the version 2 of v2v.
> + *
> + * Copyright (c) 2010, Citrix Systems
> + * Copyright (c) 2018-2019, BAE Systems
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining
> a copy
> + * of this software and associated documentation files (the "Software"),
> to
> + * deal in the Software without restriction, including without limitation
> the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense,
> and/or
> + * sell copies of the Software, and to permit persons to whom the
> Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be
> included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
> SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + */
> +
> +#ifndef __XEN_PUBLIC_ARGO_H__
> +#define __XEN_PUBLIC_ARGO_H__
> +
> +#define XEN_ARGO_DOMID_ANY       DOMID_INVALID
> +
> +/* The maximum size of an Argo ring is defined to be: 16MB (0x1000000
> bytes). */
> +#define XEN_ARGO_MAX_RING_SIZE  (0x1000000ULL)
> +
> +/* Fixed-width type for "argo port" number. Nothing to do with evtchns. */
> +typedef uint32_t xen_argo_port_t;
> +
> +/* gfn type: 64-bit fixed-width on all architectures */
> +typedef uint64_t xen_argo_gfn_t;
> +
> +/*
> + * XEN_ARGO_MAXIOV : maximum number of iovs accepted in a single sendv.
> + * Caution is required if this value is increased: this determines the
> size of
> + * an array of xen_argo_iov_t structs on the hypervisor stack, so could
> cause
> + * stack overflow if the value is too large.
> + * The Linux Argo driver never passes more than two iovs.
> +*/
> +#define XEN_ARGO_MAXIOV          8U
> +
> +typedef struct xen_argo_iov
> +{
> +    unsigned long iov_hnd;
> +    uint32_t iov_len;
> +    uint32_t pad;
> +} xen_argo_iov_t;
> +
> +typedef struct xen_argo_addr
> +{
> +    xen_argo_port_t aport;
> +    domid_t domain_id;
> +    uint16_t pad;
> +} xen_argo_addr_t;
> +
> +typedef struct xen_argo_send_addr
> +{
> +    struct xen_argo_addr src;
> +    struct xen_argo_addr dst;
> +} xen_argo_send_addr_t;
> +
> +typedef struct xen_argo_ring
> +{
> +    /* Guests should use atomic operations to access rx_ptr */
> +    uint32_t rx_ptr;
> +    /* Guests should use atomic operations to access tx_ptr */
> +    uint32_t tx_ptr;
> +    /*
> +     * Header space reserved for later use. Align the start of the ring
> to a
> +     * multiple of the message slot size.
> +     */
> +    uint8_t reserved[56];
> +    uint8_t ring[];
> +} xen_argo_ring_t;
> +
> +typedef struct xen_argo_register_ring
> +{
> +    xen_argo_port_t aport;
> +    domid_t partner_id;
> +    uint16_t pad;
> +    uint32_t len;
> +} xen_argo_register_ring_t;
> +
> +typedef struct xen_argo_unregister_ring
> +{
> +    xen_argo_port_t aport;
> +    domid_t partner_id;
> +    uint16_t pad;
> +} xen_argo_unregister_ring_t;
> +
> +/* Messages on the ring are padded to a multiple of this size. */
> +#define XEN_ARGO_MSG_SLOT_SIZE 0x10
> +
> +/*
> + * Notify flags
> + */
> +/* Ring exists */
> +#define XEN_ARGO_RING_EXISTS            (1U << 0)
> +/* Ring is shared, not unicast */
> +#define XEN_ARGO_RING_SHARED            (1U << 1)
> +/* Ring is empty */
> +#define XEN_ARGO_RING_EMPTY             (1U << 2)
> +/* Sufficient space to queue space_required bytes might exist */
> +#define XEN_ARGO_RING_SUFFICIENT        (1U << 3)
> +/* Insufficient ring size for space_required bytes */
> +#define XEN_ARGO_RING_EMSGSIZE          (1U << 4)
> +/* Too many domains waiting for available space signals for this ring */
> +#define XEN_ARGO_RING_EBUSY             (1U << 5)
> +
> +typedef struct xen_argo_ring_data_ent
> +{
> +    struct xen_argo_addr ring;
> +    uint16_t flags;
> +    uint16_t pad;
> +    uint32_t space_required;
> +    uint32_t max_message_size;
> +} xen_argo_ring_data_ent_t;
> +
> +typedef struct xen_argo_ring_data
> +{
> +    uint32_t nent;
> +    uint32_t pad;
> +
> +    /*
> +     * The Xen headers have:
> +     *   struct xen_argo_ring_data_ent data[];
> +     * here.  It's useful for the hypervisor side of the interface, but
> really
> +     * not for the client side.
> +     */
> +} xen_argo_ring_data_t;
> +
> +struct xen_argo_ring_message_header
> +{
> +    uint32_t len;
> +    struct xen_argo_addr source;
> +    uint32_t message_type;
> +    uint8_t data[];
> +};
> +
> +/*
> + * Hypercall operations
> + */
> +
> +/*
> + * XEN_ARGO_OP_register_ring
> + *
> + * Register a ring using the guest-supplied memory pages.
> + * Also used to reregister an existing ring (eg. after resume from
> hibernate).
> + *
> + * The first argument struct indicates the port number for the ring to
> register
> + * and the partner domain, if any, that is to be allowed to send to the
> ring.
> + * A wildcard (XEN_ARGO_DOMID_ANY) may be supplied instead of a partner
> domid,
> + * and if the hypervisor has wildcard sender rings enabled, this will
> allow
> + * any domain (XSM notwithstanding) to send to the ring.
> + *
> + * The second argument is an array of guest frame numbers and the third
> argument
> + * indicates the size of the array. This operation only supports 4K-sized
> pages.
> + *
> + * arg1: XEN_GUEST_HANDLE(xen_argo_register_ring_t)
> + * arg2: XEN_GUEST_HANDLE(xen_argo_gfn_t)
> + * arg3: unsigned long npages
> + * arg4: unsigned long flags (32-bit value)
> + */
> +#define XEN_ARGO_OP_register_ring     1
> +
> +/* Register op flags */
> +/*
> + * Fail exist:
> + * If set, reject attempts to (re)register an existing established ring.
> + * If clear, reregistration occurs if the ring exists, with the new ring
> + * taking the place of the old, preserving tx_ptr if it remains valid.
> + */
> +#define XEN_ARGO_REGISTER_FLAG_FAIL_EXIST  0x1
> +
> +#ifdef __XEN__
> +/* Mask for all defined flags. */
> +#define XEN_ARGO_REGISTER_FLAG_MASK XEN_ARGO_REGISTER_FLAG_FAIL_EXIST
> +#endif
> +
> +/*
> + * XEN_ARGO_OP_unregister_ring
> + *
> + * Unregister a previously-registered ring, ending communication.
> + *
> + * arg1: XEN_GUEST_HANDLE(xen_argo_unregister_ring_t)
> + * arg2: NULL
> + * arg3: 0 (ZERO)
> + * arg4: 0 (ZERO)
> + */
> +#define XEN_ARGO_OP_unregister_ring     2
> +
> +/*
> + * XEN_ARGO_OP_sendv
> + *
> + * Send a list of buffers contained in iovs.
> + *
> + * The send address struct specifies the source and destination addresses
> + * for the message being sent, which are used to find the destination
> ring:
> + * Xen first looks for a most-specific match with a registered ring with
> + *  (id.addr == dst) and (id.partner == sending_domain) ;
> + * if that fails, it then looks for a wildcard match (aka multicast
> receiver)
> + * where (id.addr == dst) and (id.partner == DOMID_ANY).
> + *
> + * For each iov entry, send iov_len bytes from iov_base to the
> destination ring.
> + * If insufficient space exists in the destination ring, it will return
> -EAGAIN
> + * and Xen will notify the caller when sufficient space becomes available.
> + *
> + * The message type is a 32-bit data field available to communicate
> message
> + * context data (eg. kernel-to-kernel, rather than application layer).
> + *
> + * arg1: XEN_GUEST_HANDLE(xen_argo_send_addr_t) source and dest addresses
> + * arg2: XEN_GUEST_HANDLE(xen_argo_iov_t) iovs
> + * arg3: unsigned long niov
> + * arg4: unsigned long message type (32-bit value)
> + */
> +#define XEN_ARGO_OP_sendv               3
> +
> +/*
> + * XEN_ARGO_OP_notify
> + *
> + * Asks Xen for information about other rings in the system.
> + *
> + * ent->ring is the xen_argo_addr_t of the ring you want information on.
> + * Uses the same ring matching rules as XEN_ARGO_OP_sendv.
> + *
> + * ent->space_required : if this field is not null then Xen will check
> + * that there is space in the destination ring for this many bytes of
> payload.
> + * If the ring is too small for the requested space_required, it will set
> the
> + * XEN_ARGO_RING_EMSGSIZE flag on return.
> + * If sufficient space is available, it will set XEN_ARGO_RING_SUFFICIENT
> + * and CANCEL any pending notification for that ent->ring; otherwise it
> + * will schedule a notification event and the flag will not be set.
> + *
> + * These flags are set by Xen when notify replies:
> + * XEN_ARGO_RING_EXISTS     ring exists
> + * XEN_ARGO_RING_SHARED     ring is registered for wildcard partner
> + * XEN_ARGO_RING_EMPTY      ring is empty
> + * XEN_ARGO_RING_SUFFICIENT sufficient space for space_required is there
> + * XEN_ARGO_RING_EMSGSIZE   space_required is too large for the ring size
> + * XEN_ARGO_RING_EBUSY      too many domains waiting for available space
> signals
> + *
> + * arg1: XEN_GUEST_HANDLE(xen_argo_ring_data_t) ring_data (may be NULL)
> + * arg2: NULL
> + * arg3: 0 (ZERO)
> + * arg4: 0 (ZERO)
> + */
> +#define XEN_ARGO_OP_notify              4
> +
> +#endif
> diff --git a/include/xtf/hypercall.h b/include/xtf/hypercall.h
> index 0d33807..17975ba 100644
> --- a/include/xtf/hypercall.h
> +++ b/include/xtf/hypercall.h
> @@ -33,6 +33,7 @@
>  extern uint8_t hypercall_page[PAGE_SIZE];
>
>  /* All Xen ABI for includers convenience .*/
> +#include <xen/argo.h>
>  #include <xen/callback.h>
>  #include <xen/elfnote.h>
>  #include <xen/errno.h>
> diff --git a/include/xtf/numbers.h b/include/xtf/numbers.h
> index f5c73b7..b0b2c1b 100644
> --- a/include/xtf/numbers.h
> +++ b/include/xtf/numbers.h
> @@ -52,6 +52,11 @@
>   */
>  #define _u(v) ((unsigned long)(v))
>
> +/**
> + * Round up a number to the next integer
> + */
> +#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
> +
>  #endif /* !__ASSEMBLY__ */
>  #endif /* XTF_NUMBERS_H */
>
> diff --git a/tests/argo/Makefile b/tests/argo/Makefile
> new file mode 100644
> index 0000000..c6b3113
> --- /dev/null
> +++ b/tests/argo/Makefile
> @@ -0,0 +1,9 @@
> +include $(ROOT)/build/common.mk
> +
> +NAME      := argo
> +CATEGORY  := in-development
> +TEST-ENVS := $(ALL_ENVIRONMENTS)
> +
> +obj-perenv += main.o
> +
> +include $(ROOT)/build/gen.mk
> diff --git a/tests/argo/main.c b/tests/argo/main.c
> new file mode 100644
> index 0000000..fa54aed
> --- /dev/null
> +++ b/tests/argo/main.c
> @@ -0,0 +1,353 @@
> +/**
> + * @file tests/argo/main.c
> + * @ref test-argo
> + *
> + * @page test-argo argo
> + *
> + * @todo Docs for test-argo
> + *
> + * @see tests/argo/main.c
> + */
> +#include <xtf.h>
> +
> +const char test_title[] = "Argo hypercall test";
> +
> +/*
> + * The current Linux Argo driver has a default ring size of 32 4k pages,
> + * so follow that for the test ring size.
> + */
> +static uint8_t ring_buffer[32 * PAGE_SIZE] __page_aligned_bss;
> +#define TEST_RING_NPAGES (sizeof(ring_buffer) / PAGE_SIZE)
> +
> +static int probe_for_argo(domid_t own_domid)
> +{
> +    /* Attempt an Argo call to register a ring with invalid arguments */
> +    xen_argo_register_ring_t reg = {
> +        .aport      = 1,
> +        .partner_id = own_domid,
> +        .len        = 1, /* A 1-byte ring is never allowed */
> +    };
> +    int rc = hypercall_argo_op(XEN_ARGO_OP_register_ring, &reg, NULL, 0,
> 0);
> +
> +    switch ( rc )
> +    {
> +    case -EINVAL: /* This is the response we are looking for */
> +        return 0;
> +
> +        /* All below here are test exit conditions */
> +    case -ENOSYS:
> +        xtf_skip("Skip: Argo support has not been enabled in this
> hypervisor\n");
> +        break;
> +    case -EOPNOTSUPP:
> +        xtf_skip("Skip: Argo is not enabled at runtime for this
> hypervisor\n");
> +        break;
> +    case -ENODEV:
> +        xtf_skip("Skip: Argo is not enabled for this domain\n");
> +        break;
> +
> +    case -EPERM:
> +        xtf_failure("Fail: ring registration by this domain is not
> permitted\n");
> +        break;
> +    case 0:
> +        xtf_failure("Fail: an invalid ring register op was not
> rejected\n");
> +        break;
> +    default:
> +        xtf_failure("Fail: unknown error %d for invalid ring
> registration\n", rc);
> +        break;
> +    }
> +
> +    return -1;
> +}
> +
> +/* notify: asks Xen for information about rings */
> +static int
> +test_notify_for_one_ring(domid_t query_domid, xen_argo_port_t query_port,
> +                         bool exists)
> +{
> +    struct {
> +        xen_argo_ring_data_t data;
> +        xen_argo_ring_data_ent_t ents[1];
> +    } notify = {
> +        .data = {
> +            .nent = ARRAY_SIZE(notify.ents),
> +        },
> +        .ents = {
> +            {
> +                .ring = {
> +                    .domain_id = query_domid,
> +                    .aport     = query_port,
> +                },
> +            },
> +        },
> +    };
> +    int rc = hypercall_argo_op(XEN_ARGO_OP_notify, &notify, NULL, 0, 0);
> +
> +    if ( rc )
> +    {
> +        xtf_failure("Fail: Unexpected error code %d in notify test\n",
> rc);
> +        return -1;
> +    }
> +
> +    if ( !exists )
> +    {
> +        /* No currently-defined flags should be set for a non-existent
> ring */
> +        if ( notify.ents[0].flags )
> +        {
> +            xtf_failure("Fail: Non-existent ring reported as existing\n");
> +            return -1;
> +        }
> +    }
> +    else
> +    {
> +        if ( !(notify.ents[0].flags & XEN_ARGO_RING_EXISTS) )
> +        {
> +            xtf_failure("Fail: Ring not reported as existing\n");
> +            return -1;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
> +/* See the Argo Linux device driver for similar use of these macros */
> +#define XEN_ARGO_ROUNDUP(x) roundup((x), XEN_ARGO_MSG_SLOT_SIZE)
> +#define ARGO_RING_OVERHEAD 80
> +#define TEST_RING_SIZE(npages)                                      \
> +    (XEN_ARGO_ROUNDUP((((PAGE_SIZE)*npages) - ARGO_RING_OVERHEAD)))
> +
> +static int
> +test_register_ring(domid_t own_domid, xen_argo_port_t aport)
> +{
> +    unsigned int i;
> +    xen_argo_register_ring_t reg = {
> +        .aport      = aport,
> +        .partner_id = own_domid,
> +        .len        = TEST_RING_SIZE(TEST_RING_NPAGES),
> +    };
> +    xen_argo_gfn_t gfns[TEST_RING_NPAGES];
> +
> +    for ( i = 0; i < TEST_RING_NPAGES; i++ )
> +        gfns[i] = virt_to_gfn(ring_buffer + (i * PAGE_SIZE));
> +
> +    int rc = hypercall_argo_op(XEN_ARGO_OP_register_ring, &reg, &gfns,
> +                               TEST_RING_NPAGES,
> XEN_ARGO_REGISTER_FLAG_FAIL_EXIST);
> +    switch ( rc )
> +    {
> +    case 0:
> +        return 0;
> +
> +    case -ENODEV:
> +        xtf_failure("Fail: Argo is not enabled for this domain\n");
> +        break;
> +    case -EFAULT:
> +        xtf_failure("Fail: Memory fault performing register ring test\n");
> +        break;
> +    default:
> +        xtf_failure("Fail: Unexpected error code %d in register ring
> test\n", rc);
> +        break;
> +    }
> +    return -1;
> +}
> +
> +static int
> +test_unregister_ring(domid_t partner_domid, xen_argo_port_t aport,
> +                     bool exists)
> +{
> +    xen_argo_register_ring_t unreg = {
> +        .aport      = aport,
> +        .partner_id = partner_domid,
> +    };
> +    int rc = hypercall_argo_op(XEN_ARGO_OP_unregister_ring, &unreg, NULL,
> 0, 0);
> +
> +    switch ( rc )
> +    {
> +    case 0:
> +        if ( exists )
> +            return 0;
> +        xtf_failure("Fail: unexpected success unregistering non-existent
> ring\n");
> +        return -1;
> +
> +    case -ENOENT:
> +        if ( !exists )
> +            return 0;
> +        xtf_failure("Fail: unexpected ring not found when unregistering
> \n");
> +        return -1;
> +
> +    default:
> +        xtf_failure("Fail: Unexpected error code %d in unregister ring
> test\n", rc);
> +        break;
> +    }
> +    return -1;
> +}
> +
> +static int
> +test_sendv(domid_t src_domid, xen_argo_port_t src_aport,
> +           domid_t dst_domid, xen_argo_port_t dst_aport,
> +           const char *msg_text, size_t msg_len, unsigned int msg_type)
> +{
> +    xen_argo_send_addr_t send_addr = {
> +        .src = {
> +            .domain_id = src_domid,
> +            .aport     = src_aport,
> +        },
> +        .dst = {
> +            .domain_id = dst_domid,
> +            .aport     = dst_aport,
> +        },
> +    };
> +    xen_argo_iov_t iovs[] = {
> +        {
> +            .iov_hnd = _u(msg_text),
> +            .iov_len = msg_len,
> +        },
> +    };
> +    int rc = hypercall_argo_op(XEN_ARGO_OP_sendv, &send_addr,
> +                               iovs, ARRAY_SIZE(iovs), msg_type);
> +
> +    if ( rc < 0 )
> +    {
> +        xtf_failure("Fail: Unexpected error code %d in sendv test\n", rc);
> +        return -1;
> +    }
> +
> +    if ( (size_t)rc != msg_len )
> +    {
> +        xtf_failure("Fail: Unexpected message size %d written in sendv
> test\n", rc);
> +        return -1;
> +    }
> +
> +    return 0;
> +}
> +
> +static int
> +inspect_ring_after_first_single_sendv(domid_t src_domid,
> +                                      xen_argo_port_t src_aport,
> +                                      const char *sent_msg,
> +                                      unsigned int sent_msg_len,
> +                                      unsigned int sent_msg_type)
> +{
> +    int rc = 0;
> +    xen_argo_ring_t *ringp = (xen_argo_ring_t *)ring_buffer;
> +    struct xen_argo_ring_message_header *msg_hdr;
> +    unsigned int sent_length;
> +
> +    if ( ringp->rx_ptr != 0 )
> +    {
> +        xtf_failure("Fail: receive pointer non-zero after sendv: %u\n",
> +                    ringp->rx_ptr);
> +        rc = -1;
> +    }
> +
> +    if ( ringp->tx_ptr != XEN_ARGO_ROUNDUP(
> +             sizeof(struct xen_argo_ring_message_header) + sent_msg_len) )
> +    {
> +        xtf_failure("Fail: transmit pointer incorrect after sendv: %u\n",
> +                    ringp->rx_ptr);
> +        rc = -1;
> +    }
> +
> +    msg_hdr = (struct xen_argo_ring_message_header *)&(ringp->ring);
> +
> +    if ( msg_hdr->source.domain_id != src_domid )
> +    {
> +        xtf_failure("Fail: source domain id incorrect: %u, expected %u\n",
> +                    msg_hdr->source.domain_id, src_domid);
> +        rc = -1;
> +    }
> +
> +    if ( msg_hdr->source.aport != src_aport )
> +    {
> +        xtf_failure("Fail: source domain port incorrect: %u, expected
> %u\n",
> +                    msg_hdr->source.domain_id, src_aport);
> +        rc = -1;
> +    }
> +
> +    if ( msg_hdr->source.pad != 0 )
> +    {
> +        xtf_failure("Fail: source padding incorrect: %u, expected zero\n",
> +                    msg_hdr->source.pad);
> +        rc = -1;
> +    }
> +
> +    if ( sent_msg_type != msg_hdr->message_type )
> +    {
> +        xtf_failure("Fail: message type incorrect: %u sent, %u
> received\n",
> +                    sent_msg_type, msg_hdr->message_type);
> +        rc = -1;
> +    }
> +
> +    sent_length = sent_msg_len + sizeof(struct
> xen_argo_ring_message_header);
> +    if ( sent_length != msg_hdr->len )
> +    {
> +        xtf_failure("Fail: received message length incorrect: "
> +                    "%u sent is %u with header added, %u received\n",
> +                    sent_msg_len, sent_length, msg_hdr->len);
> +        rc = -1;
> +    }
> +
> +    if ( strncmp((const char *)msg_hdr->data, sent_msg, sent_msg_len) )
> +    {
> +        xtf_failure("Fail: sent message got mangled\n");
> +        rc = -1;
> +    }
> +
> +    return rc;
> +}
> +
> +static void clear_test_ring(void)
> +{
> +    memset(ring_buffer, 0, sizeof(ring_buffer));
> +}
> +
> +void test_main(void)
> +{
> +    int own_domid;
> +    xen_argo_port_t test_aport = 1;
> +    const char simple_text[] = "a simple thing to send\n";
> +    const unsigned int msg_type = 0x12345678;
> +
> +    own_domid = xtf_get_domid();
> +    if ( own_domid < 0 )
> +        return xtf_error("Error: could not determine domid of the test
> domain\n");
> +
> +    /* First test validates for Argo availability to gate further testing
> */
> +    if ( probe_for_argo(own_domid) )
> +        return;
> +
> +    if ( test_notify_for_one_ring(own_domid, test_aport, false) ||
> +         test_unregister_ring(own_domid, test_aport, false) )
> +        return;
> +
> +    clear_test_ring();
> +
> +    if ( test_register_ring(own_domid, test_aport) ||
> +         test_notify_for_one_ring(own_domid, test_aport, true) ||
> +         test_unregister_ring(own_domid, test_aport, true) ||
> +         test_notify_for_one_ring(own_domid, test_aport, false) ||
> +         test_unregister_ring(own_domid, test_aport, false) )
> +        return;
> +
> +    clear_test_ring();
> +
> +    if ( test_register_ring(own_domid, test_aport) ||
> +         test_sendv(own_domid, test_aport, own_domid, test_aport,
> +                    simple_text, strlen(simple_text), msg_type) ||
> +         inspect_ring_after_first_single_sendv(
> +             own_domid, test_aport, simple_text, strlen(simple_text),
> msg_type) ||
> +         test_notify_for_one_ring(own_domid, test_aport, true) ||
> +         test_unregister_ring(own_domid, test_aport, true) ||
> +         test_unregister_ring(own_domid, test_aport, false) )
> +        return;
> +
> +    xtf_success(NULL);
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> --
> 2.34.1
>
>
>

Reply via email to