root/usr/src/uts/intel/sys/viona_io.h
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2013 Pluribus Networks Inc.
 * Copyright 2018 Joyent, Inc.
 * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
 * Copyright 2025 Oxide Computer Company
 */

#ifndef _VIONA_IO_H_
#define _VIONA_IO_H_

#include <sys/sysmacros.h>

#define VNA_IOC                         (('V' << 16)|('C' << 8))
#define VNA_IOC_CREATE                  (VNA_IOC | 0x01)
#define VNA_IOC_DELETE                  (VNA_IOC | 0x02)
#define VNA_IOC_VERSION                 (VNA_IOC | 0x03)
#define VNA_IOC_DEFAULT_PARAMS          (VNA_IOC | 0x04)

#define VNA_IOC_RING_INIT               (VNA_IOC | 0x10)
#define VNA_IOC_RING_RESET              (VNA_IOC | 0x11)
#define VNA_IOC_RING_KICK               (VNA_IOC | 0x12)
#define VNA_IOC_RING_SET_MSI            (VNA_IOC | 0x13)
#define VNA_IOC_RING_INTR_CLR           (VNA_IOC | 0x14)
#define VNA_IOC_RING_SET_STATE          (VNA_IOC | 0x15)
#define VNA_IOC_RING_GET_STATE          (VNA_IOC | 0x16)
#define VNA_IOC_RING_PAUSE              (VNA_IOC | 0x17)
#define VNA_IOC_RING_INIT_MODERN        (VNA_IOC | 0x18)

#define VNA_IOC_INTR_POLL               (VNA_IOC | 0x20)
#define VNA_IOC_SET_FEATURES            (VNA_IOC | 0x21)
#define VNA_IOC_GET_FEATURES            (VNA_IOC | 0x22)
#define VNA_IOC_SET_NOTIFY_IOP          (VNA_IOC | 0x23)
#define VNA_IOC_SET_PROMISC             (VNA_IOC | 0x24)
#define VNA_IOC_GET_PARAMS              (VNA_IOC | 0x25)
#define VNA_IOC_SET_PARAMS              (VNA_IOC | 0x26)
#define VNA_IOC_GET_MTU                 (VNA_IOC | 0x27)
#define VNA_IOC_SET_MTU                 (VNA_IOC | 0x28)
#define VNA_IOC_SET_NOTIFY_MMIO         (VNA_IOC | 0x29)
#define VNA_IOC_INTR_POLL_MQ            (VNA_IOC | 0x2a)

/*
 * While the VirtIO specification allows for up to 0x8000 queue pairs, we
 * impose a lower limit in Viona.
 */
#define VIONA_MIN_QPAIR                 1
#define VIONA_MAX_QPAIR                 0x100
#define VNA_IOC_GET_PAIRS               (VNA_IOC | 0x30)
#define VNA_IOC_SET_PAIRS               (VNA_IOC | 0x31)
#define VNA_IOC_GET_USEPAIRS            (VNA_IOC | 0x32)
#define VNA_IOC_SET_USEPAIRS            (VNA_IOC | 0x33)

/*
 * Viona Interface Version
 *
 * Like bhyve, viona exposes Private interfaces which are nonetheless consumed
 * by out-of-gate consumers.  While those consumers assume all risk of breakage
 * incurred by subsequent changes, it would be nice to equip them to potentially
 * detect (and handle) those modifications.
 *
 * There are no established criteria for the magnitude of change which requires
 * this version to be incremented, and maintenance of it is considered a
 * best-effort activity.  Nothing is to be inferred about the magnitude of a
 * change when the version is modified.  It follows no rules like semver.
 *
 */
#define VIONA_CURRENT_INTERFACE_VERSION 6

typedef struct vioc_create {
        datalink_id_t   c_linkid;
        int             c_vmfd;
} vioc_create_t;

typedef struct vioc_ring_init {
        uint16_t        ri_index;
        uint16_t        ri_qsize;
        uint64_t        ri_qaddr;
} vioc_ring_init_t;

typedef struct vioc_ring_init_modern {
        uint16_t        rim_index;
        uint16_t        rim_qsize;
        uint64_t        rim_qaddr_desc;
        uint64_t        rim_qaddr_avail;
        uint64_t        rim_qaddr_used;
} vioc_ring_init_modern_t;

typedef struct vioc_ring_state {
        uint16_t        vrs_index;
        uint16_t        vrs_avail_idx;
        uint16_t        vrs_used_idx;
        uint16_t        vrs_qsize;
        uint64_t        vrs_qaddr_desc;
        uint64_t        vrs_qaddr_avail;
        uint64_t        vrs_qaddr_used;
} vioc_ring_state_t;

typedef struct vioc_ring_msi {
        uint16_t        rm_index;
        uint64_t        rm_addr;
        uint64_t        rm_msg;
} vioc_ring_msi_t;

typedef enum {
        VIONA_PROMISC_NONE = 0,
        VIONA_PROMISC_MULTI,
        VIONA_PROMISC_ALL,
        VIONA_PROMISC_MAX,
} viona_promisc_t;

/*
 * The older VNA_IOC_INTR_POLL API, superseded by VNA_IOC_INTR_POLL_MQ, only
 * polls interrupt status for the first queue pair (two rings).
 */
typedef struct vioc_intr_poll {
        uint32_t        vip_status[2];
} vioc_intr_poll_t;

#define VIONA_INTR_WORD_BITS    32
#define VIONA_INTR_WORDS        \
        howmany(VIONA_MAX_QPAIR * 2, VIONA_INTR_WORD_BITS)
#define VIONA_INTR_WORD(q)      ((q) / VIONA_INTR_WORD_BITS)
#define VIONA_INTR_BIT(q)       (1u << ((q) % VIONA_INTR_WORD_BITS))
#define VIONA_INTR_SET(vipm, q) \
        (vipm)->vipm_status[VIONA_INTR_WORD(q)] |= VIONA_INTR_BIT(q)
#define VIONA_INTR_TEST(vipm, q) \
        (((vipm)->vipm_status[VIONA_INTR_WORD(q)] & VIONA_INTR_BIT(q)) != 0)
typedef struct vioc_intr_poll_mq {
        uint16_t        vipm_nrings;
        uint32_t        vipm_status[VIONA_INTR_WORDS];
} vioc_intr_poll_mq_t;

typedef struct vioc_notify_mmio {
        uint64_t        vim_address;
        uint32_t        vim_size;
} vioc_notify_mmio_t;

/*
 * Viona Parameter Interfaces
 *
 * A viona link can have various configuration parameters set upon it.  This is
 * done using packed nvlists in order to communicate those parameters to/from
 * the device driver.
 *
 *
 * Currently supported parameters are:
 * - tx_copy_data (boolean): During packet transmission, should viona copy all
 *   of the packet data, rather than "loaning" those regions of guest memory
 *   (other than the packet headers) in the mblk.
 * - tx_header_pad (uint16): How many bytes (if any) should be left as empty
 *   padding on transmitted packets?  These could be used by subsequent
 *   encapsulation mechanisms in the network stack without the need to
 *   reallocate space for the then-longer header.
 *
 */

/* Maximum size for parameter (or error) packed nvlist buffers */
#define VIONA_MAX_PARAM_NVLIST_SZ       4096

typedef struct vioc_get_params {
        void    *vgp_param;
        size_t  vgp_param_sz;
} vioc_get_params_t;

typedef struct vioc_set_params {
        void    *vsp_param;
        size_t  vsp_param_sz;
        void    *vsp_error;
        size_t  vsp_error_sz;
} vioc_set_params_t;

#endif  /* _VIONA_IO_H_ */