Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 564f7dfd authored by Stefano Stabellini's avatar Stefano Stabellini Committed by Juergen Gross
Browse files

xen: import new ring macros in ring.h



Sync the ring.h file with upstream Xen, to introduce the new ring macros.
They will be used by the Xen transport for 9pfs.

CC: konrad.wilk@oracle.com
CC: boris.ostrovsky@oracle.com
CC: jgross@suse.com
CC: groug@kaod.org

Signed-off-by: default avatarStefano Stabellini <stefano@aporeto.com>
Acked-by: default avatarJuergen Gross <jgross@suse.com>
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
parent ab1570a4
Loading
Loading
Loading
Loading
+143 −0
Original line number Diff line number Diff line
@@ -283,4 +283,147 @@ struct __name##_back_ring { \
    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);			\
} while (0)


/*
 * DEFINE_XEN_FLEX_RING_AND_INTF defines two monodirectional rings and
 * functions to check if there is data on the ring, and to read and
 * write to them.
 *
 * DEFINE_XEN_FLEX_RING is similar to DEFINE_XEN_FLEX_RING_AND_INTF, but
 * does not define the indexes page. As different protocols can have
 * extensions to the basic format, this macro allow them to define their
 * own struct.
 *
 * XEN_FLEX_RING_SIZE
 *   Convenience macro to calculate the size of one of the two rings
 *   from the overall order.
 *
 * $NAME_mask
 *   Function to apply the size mask to an index, to reduce the index
 *   within the range [0-size].
 *
 * $NAME_read_packet
 *   Function to read data from the ring. The amount of data to read is
 *   specified by the "size" argument.
 *
 * $NAME_write_packet
 *   Function to write data to the ring. The amount of data to write is
 *   specified by the "size" argument.
 *
 * $NAME_get_ring_ptr
 *   Convenience function that returns a pointer to read/write to the
 *   ring at the right location.
 *
 * $NAME_data_intf
 *   Indexes page, shared between frontend and backend. It also
 *   contains the array of grant refs.
 *
 * $NAME_queued
 *   Function to calculate how many bytes are currently on the ring,
 *   ready to be read. It can also be used to calculate how much free
 *   space is currently on the ring (XEN_FLEX_RING_SIZE() -
 *   $NAME_queued()).
 */

#ifndef XEN_PAGE_SHIFT
/* The PAGE_SIZE for ring protocols and hypercall interfaces is always
 * 4K, regardless of the architecture, and page granularity chosen by
 * operating systems.
 */
#define XEN_PAGE_SHIFT 12
#endif
#define XEN_FLEX_RING_SIZE(order)                                             \
    (1UL << ((order) + XEN_PAGE_SHIFT - 1))

#define DEFINE_XEN_FLEX_RING(name)                                            \
static inline RING_IDX name##_mask(RING_IDX idx, RING_IDX ring_size)          \
{                                                                             \
    return idx & (ring_size - 1);                                             \
}                                                                             \
                                                                              \
static inline unsigned char *name##_get_ring_ptr(unsigned char *buf,          \
                                                 RING_IDX idx,                \
                                                 RING_IDX ring_size)          \
{                                                                             \
    return buf + name##_mask(idx, ring_size);                                 \
}                                                                             \
                                                                              \
static inline void name##_read_packet(void *opaque,                           \
                                      const unsigned char *buf,               \
                                      size_t size,                            \
                                      RING_IDX masked_prod,                   \
                                      RING_IDX *masked_cons,                  \
                                      RING_IDX ring_size)                     \
{                                                                             \
    if (*masked_cons < masked_prod ||                                         \
        size <= ring_size - *masked_cons) {                                   \
        memcpy(opaque, buf + *masked_cons, size);                             \
    } else {                                                                  \
        memcpy(opaque, buf + *masked_cons, ring_size - *masked_cons);         \
        memcpy((unsigned char *)opaque + ring_size - *masked_cons, buf,       \
               size - (ring_size - *masked_cons));                            \
    }                                                                         \
    *masked_cons = name##_mask(*masked_cons + size, ring_size);               \
}                                                                             \
                                                                              \
static inline void name##_write_packet(unsigned char *buf,                    \
                                       const void *opaque,                    \
                                       size_t size,                           \
                                       RING_IDX *masked_prod,                 \
                                       RING_IDX masked_cons,                  \
                                       RING_IDX ring_size)                    \
{                                                                             \
    if (*masked_prod < masked_cons ||                                         \
        size <= ring_size - *masked_prod) {                                   \
        memcpy(buf + *masked_prod, opaque, size);                             \
    } else {                                                                  \
        memcpy(buf + *masked_prod, opaque, ring_size - *masked_prod);         \
        memcpy(buf, (unsigned char *)opaque + (ring_size - *masked_prod),     \
               size - (ring_size - *masked_prod));                            \
    }                                                                         \
    *masked_prod = name##_mask(*masked_prod + size, ring_size);               \
}                                                                             \
                                                                              \
static inline RING_IDX name##_queued(RING_IDX prod,                           \
                                     RING_IDX cons,                           \
                                     RING_IDX ring_size)                      \
{                                                                             \
    RING_IDX size;                                                            \
                                                                              \
    if (prod == cons)                                                         \
        return 0;                                                             \
                                                                              \
    prod = name##_mask(prod, ring_size);                                      \
    cons = name##_mask(cons, ring_size);                                      \
                                                                              \
    if (prod == cons)                                                         \
        return ring_size;                                                     \
                                                                              \
    if (prod > cons)                                                          \
        size = prod - cons;                                                   \
    else                                                                      \
        size = ring_size - (cons - prod);                                     \
    return size;                                                              \
}                                                                             \
                                                                              \
struct name##_data {                                                          \
    unsigned char *in; /* half of the allocation */                           \
    unsigned char *out; /* half of the allocation */                          \
}

#define DEFINE_XEN_FLEX_RING_AND_INTF(name)                                   \
struct name##_data_intf {                                                     \
    RING_IDX in_cons, in_prod;                                                \
                                                                              \
    uint8_t pad1[56];                                                         \
                                                                              \
    RING_IDX out_cons, out_prod;                                              \
                                                                              \
    uint8_t pad2[56];                                                         \
                                                                              \
    RING_IDX ring_order;                                                      \
    grant_ref_t ref[];                                                        \
};                                                                            \
DEFINE_XEN_FLEX_RING(name)

#endif /* __XEN_PUBLIC_IO_RING_H__ */