qemu/include/hw/remote-port-proto.h
<<
>>
Prefs
   1/*
   2 * QEMU remote port protocol parts.
   3 *
   4 * Copyright (c) 2013 Xilinx Inc
   5 * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11 * copies of the Software, and to permit persons to whom the Software is
  12 * furnished to do so, subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in
  15 * all copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23 * THE SOFTWARE.
  24 */
  25#ifndef REMOTE_PORT_PROTO_H__
  26#define REMOTE_PORT_PROTO_H__
  27
  28#include <stdbool.h>
  29#include <string.h>
  30
  31/*
  32 * Remote-Port (RP) is an inter-simulator protocol. It assumes a reliable
  33 * point to point communcation with the remote simulation environment.
  34 *
  35 * Setup
  36 * In the SETUP phase a mandatory HELLO packet is exchanged with optional
  37 * CFG packets following. HELLO packets are useful to ensure that both
  38 * sides are speaking the same protocol and using compatible versions.
  39 *
  40 * CFG packets are used to negotiate configuration options. At the moment
  41 * these remain unimplemented.
  42 *
  43 * Once the session is up, communication can start through various other
  44 * commands. The list can be found further down this document.
  45 * Commands are carried over RP packets. Every RP packet contains a header
  46 * with length, flags and an ID to track potential responses.
  47 * The header is followed by a packet specific payload. You'll find the
  48 * details of the various commands packet layouts here. Some commands can
  49 * carry data/blobs in their payload.
  50 */
  51
  52
  53#define RP_VERSION_MAJOR 4
  54#define RP_VERSION_MINOR 2
  55
  56#if defined(_WIN32) && defined(__MINGW32__)
  57/* mingw GCC has a bug with packed attributes.  */
  58#define PACKED __attribute__ ((gcc_struct, packed))
  59#else
  60#define PACKED __attribute__ ((packed))
  61#endif
  62
  63/* Could be auto generated.  */
  64enum rp_cmd {
  65    RP_CMD_nop         = 0,
  66    RP_CMD_hello       = 1,
  67    RP_CMD_cfg         = 2,
  68    RP_CMD_read        = 3,
  69    RP_CMD_write       = 4,
  70    RP_CMD_interrupt   = 5,
  71    RP_CMD_sync        = 6,
  72    RP_CMD_max         = 6
  73};
  74
  75enum {
  76    RP_OPT_quantum = 0,
  77};
  78
  79struct rp_cfg_state {
  80    uint64_t quantum;
  81};
  82
  83enum {
  84    RP_PKT_FLAGS_optional      = 1 << 0,
  85    RP_PKT_FLAGS_response      = 1 << 1,
  86};
  87
  88struct rp_pkt_hdr {
  89    uint32_t cmd;
  90    uint32_t len;
  91    uint32_t id;
  92    uint32_t flags;
  93    uint32_t dev;
  94} PACKED;
  95
  96struct rp_pkt_cfg {
  97    struct rp_pkt_hdr hdr;
  98    uint32_t opt;
  99    uint8_t set;
 100} PACKED;
 101
 102struct rp_version {
 103    uint16_t major;
 104    uint16_t minor;
 105} PACKED;
 106
 107struct rp_capabilities {
 108    /* Offset from start of packet.  */
 109    uint32_t offset;
 110    uint16_t len;
 111    uint16_t reserved0;
 112} PACKED;
 113
 114enum {
 115    CAP_BUSACCESS_EXT_BASE = 1,    /* New header layout. */
 116    CAP_BUSACCESS_EXT_BYTE_EN = 2, /* Support for Byte Enables.  */
 117};
 118
 119struct rp_pkt_hello {
 120    struct rp_pkt_hdr hdr;
 121    struct rp_version version;
 122    struct rp_capabilities caps;
 123} PACKED;
 124
 125
 126enum {
 127    RP_BUS_ATTR_EOP        =  (1 << 0),
 128    RP_BUS_ATTR_SECURE     =  (1 << 1),
 129    RP_BUS_ATTR_EXT_BASE   =  (1 << 2),
 130};
 131
 132struct rp_pkt_busaccess {
 133    struct rp_pkt_hdr hdr;
 134    uint64_t timestamp;
 135    uint64_t attributes;
 136    uint64_t addr;
 137
 138    /* Length in bytes.  */
 139    uint32_t len;
 140
 141    /* Width of each beat in bytes. Set to zero for unknown (let the remote
 142       side choose).  */
 143    uint32_t width;
 144
 145    /* Width of streaming, must be a multiple of width.
 146       addr should repeat itself around this width. Set to same as len
 147       for incremental (normal) accesses.  In bytes.  */
 148    uint32_t stream_width;
 149
 150    /* Implementation specific source or master-id.  */
 151    uint16_t master_id;
 152} PACKED;
 153
 154
 155/* This is the new extended busaccess packet layout.  */
 156struct rp_pkt_busaccess_ext_base {
 157    struct rp_pkt_hdr hdr;
 158    uint64_t timestamp;
 159    uint64_t attributes;
 160    uint64_t addr;
 161
 162    /* Length in bytes.  */
 163    uint32_t len;
 164
 165    /* Width of each beat in bytes. Set to zero for unknown (let the remote
 166       side choose).  */
 167    uint32_t width;
 168
 169    /* Width of streaming, must be a multiple of width.
 170       addr should repeat itself around this width. Set to same as len
 171       for incremental (normal) accesses.  In bytes.  */
 172    uint32_t stream_width;
 173
 174    /* Implementation specific source or master-id.  */
 175    uint16_t master_id;
 176    /* ---- End of 4.0 base busaccess. ---- */
 177
 178    uint16_t master_id_31_16;   /* MasterID bits [31:16].  */
 179    uint32_t master_id_63_32;   /* MasterID bits [63:32].  */
 180    /* ---------------------------------------------------
 181     * Since hdr is 5 x 32bit, we are now 64bit aligned.  */
 182
 183    uint32_t data_offset;       /* Offset to data from start of pkt.  */
 184    uint32_t next_offset;       /* Offset to next extension. 0 if none.  */
 185
 186    uint32_t byte_enable_offset;
 187    uint32_t byte_enable_len;
 188
 189    /* ---- End of CAP_BUSACCESS_EXT_BASE. ---- */
 190
 191    /* If new features are needed that may always occupy space
 192     * in the header, then add a new capability and extend the
 193     * this area with new fields.
 194     * Will help receivers find data_offset and next offset,
 195     * even those that don't know about extended fields.
 196     */
 197} PACKED;
 198
 199struct rp_pkt_interrupt {
 200    struct rp_pkt_hdr hdr;
 201    uint64_t timestamp;
 202    uint64_t vector;
 203    uint32_t line;
 204    uint8_t val;
 205} PACKED;
 206
 207struct rp_pkt_sync {
 208    struct rp_pkt_hdr hdr;
 209    uint64_t timestamp;
 210} PACKED;
 211
 212struct rp_pkt {
 213    union {
 214        struct rp_pkt_hdr hdr;
 215        struct rp_pkt_hello hello;
 216        struct rp_pkt_busaccess busaccess;
 217        struct rp_pkt_busaccess_ext_base busaccess_ext_base;
 218        struct rp_pkt_interrupt interrupt;
 219        struct rp_pkt_sync sync;
 220    };
 221};
 222
 223struct rp_peer_state {
 224    void *opaque;
 225
 226    struct rp_pkt pkt;
 227    bool hdr_used;
 228
 229    struct rp_version version;
 230
 231    struct {
 232        bool busaccess_ext_base;
 233        bool busaccess_ext_byte_en;
 234    } caps;
 235
 236    /* Used to normalize our clk.  */
 237    int64_t clk_base;
 238
 239    struct rp_cfg_state local_cfg;
 240    struct rp_cfg_state peer_cfg;
 241};
 242
 243const char *rp_cmd_to_string(enum rp_cmd cmd);
 244int rp_decode_hdr(struct rp_pkt *pkt);
 245int rp_decode_payload(struct rp_pkt *pkt);
 246
 247void rp_encode_hdr(struct rp_pkt_hdr *hdr,
 248                   uint32_t cmd, uint32_t id, uint32_t dev, uint32_t len,
 249                   uint32_t flags);
 250
 251/*
 252 * caps is a an array of supported capabilities by the implementor.
 253 * caps_out is the encoded (network byte order) version of the
 254 * same array. It should be sent to the peer after the hello packet.
 255 */
 256size_t rp_encode_hello_caps(uint32_t id, uint32_t dev, struct rp_pkt_hello *pkt,
 257                            uint16_t version_major, uint16_t version_minor,
 258                            uint32_t *caps, uint32_t *features_out,
 259                            uint32_t features_len);
 260
 261/* rp_encode_hello is deprecated in favor of hello_caps.  */
 262static inline size_t __attribute__ ((deprecated))
 263rp_encode_hello(uint32_t id, uint32_t dev, struct rp_pkt_hello *pkt,
 264                uint16_t version_major, uint16_t version_minor) {
 265    return rp_encode_hello_caps(id, dev, pkt, version_major, version_minor,
 266                                NULL, NULL, 0);
 267}
 268
 269static inline void *__attribute__ ((deprecated))
 270rp_busaccess_dataptr(struct rp_pkt_busaccess *pkt)
 271{
 272    /* Right after the packet.  */
 273    return pkt + 1;
 274}
 275
 276/*
 277 * rp_busaccess_rx_dataptr
 278 *
 279 * Predicts the dataptr for a packet to be transmitted.
 280 * This should only be used if you are trying to keep
 281 * the entire packet in a linear buffer.
 282 */
 283static inline unsigned char *
 284rp_busaccess_tx_dataptr(struct rp_peer_state *peer,
 285                        struct rp_pkt_busaccess_ext_base *pkt)
 286{
 287    unsigned char *p = (unsigned char *) pkt;
 288
 289    if (peer->caps.busaccess_ext_base) {
 290        /* We always put our data right after the header.  */
 291        return p + sizeof *pkt;
 292    } else {
 293        /* Right after the old packet layout.  */
 294        return p + sizeof(struct rp_pkt_busaccess);
 295    }
 296}
 297
 298/*
 299 * rp_busaccess_rx_dataptr
 300 *
 301 * Extracts the dataptr from a received packet.
 302 */
 303static inline unsigned char *
 304rp_busaccess_rx_dataptr(struct rp_peer_state *peer,
 305                        struct rp_pkt_busaccess_ext_base *pkt)
 306{
 307    unsigned char *p = (unsigned char *) pkt;
 308
 309    if (pkt->attributes & RP_BUS_ATTR_EXT_BASE) {
 310        return p + pkt->data_offset;
 311    } else {
 312        /* Right after the old packet layout.  */
 313        return p + sizeof(struct rp_pkt_busaccess);
 314    }
 315}
 316
 317static inline unsigned char *
 318rp_busaccess_byte_en_ptr(struct rp_peer_state *peer,
 319                         struct rp_pkt_busaccess_ext_base *pkt)
 320{
 321    unsigned char *p = (unsigned char *) pkt;
 322
 323    if ((pkt->attributes & RP_BUS_ATTR_EXT_BASE)
 324        && pkt->byte_enable_len) {
 325        assert(pkt->byte_enable_offset >= sizeof *pkt);
 326        assert(pkt->byte_enable_offset + pkt->byte_enable_len
 327               <= pkt->hdr.len + sizeof pkt->hdr);
 328        return p + pkt->byte_enable_offset;
 329    }
 330    return NULL;
 331}
 332
 333size_t __attribute__ ((deprecated))
 334rp_encode_read(uint32_t id, uint32_t dev,
 335               struct rp_pkt_busaccess *pkt,
 336               int64_t clk, uint16_t master_id,
 337               uint64_t addr, uint64_t attr, uint32_t size,
 338               uint32_t width, uint32_t stream_width);
 339
 340size_t __attribute__ ((deprecated))
 341rp_encode_read_resp(uint32_t id, uint32_t dev,
 342                    struct rp_pkt_busaccess *pkt,
 343                    int64_t clk, uint16_t master_id,
 344                    uint64_t addr, uint64_t attr, uint32_t size,
 345                    uint32_t width, uint32_t stream_width);
 346
 347size_t __attribute__ ((deprecated))
 348rp_encode_write(uint32_t id, uint32_t dev,
 349                struct rp_pkt_busaccess *pkt,
 350                int64_t clk, uint16_t master_id,
 351                uint64_t addr, uint64_t attr, uint32_t size,
 352                uint32_t width, uint32_t stream_width);
 353
 354size_t __attribute__ ((deprecated))
 355rp_encode_write_resp(uint32_t id, uint32_t dev,
 356                     struct rp_pkt_busaccess *pkt,
 357                     int64_t clk, uint16_t master_id,
 358                     uint64_t addr, uint64_t attr, uint32_t size,
 359                     uint32_t width, uint32_t stream_width);
 360
 361struct rp_encode_busaccess_in {
 362    uint32_t cmd;
 363    uint32_t id;
 364    uint32_t flags;
 365    uint32_t dev;
 366    int64_t clk;
 367    uint64_t master_id;
 368    uint64_t addr;
 369    uint64_t attr;
 370    uint32_t size;
 371    uint32_t width;
 372    uint32_t stream_width;
 373    uint32_t byte_enable_len;
 374};
 375
 376/* Prepare encode_busaccess input parameters for a packet response.  */
 377static inline void
 378rp_encode_busaccess_in_rsp_init(struct rp_encode_busaccess_in *in,
 379                                struct rp_pkt *pkt) {
 380    memset(in, 0, sizeof *in);
 381    in->cmd = pkt->hdr.cmd;
 382    in->id = pkt->hdr.id;
 383    in->flags = pkt->hdr.flags | RP_PKT_FLAGS_response;
 384    in->dev = pkt->hdr.dev;
 385    /* FIXME: Propagate all master_id fields?  */
 386    in->master_id = pkt->busaccess.master_id;
 387    in->addr = pkt->busaccess.addr;
 388    in->size = pkt->busaccess.len;
 389    in->width = pkt->busaccess.width;
 390    in->stream_width = pkt->busaccess.stream_width;
 391    in->byte_enable_len = 0;
 392}
 393size_t rp_encode_busaccess(struct rp_peer_state *peer,
 394                           struct rp_pkt_busaccess_ext_base *pkt,
 395                           struct rp_encode_busaccess_in *in);
 396
 397size_t rp_encode_interrupt(uint32_t id, uint32_t dev,
 398                           struct rp_pkt_interrupt *pkt,
 399                           int64_t clk,
 400                           uint32_t line, uint64_t vector, uint8_t val);
 401
 402size_t rp_encode_sync(uint32_t id, uint32_t dev,
 403                      struct rp_pkt_sync *pkt,
 404                      int64_t clk);
 405
 406size_t rp_encode_sync_resp(uint32_t id, uint32_t dev,
 407                           struct rp_pkt_sync *pkt,
 408                           int64_t clk);
 409
 410void rp_process_caps(struct rp_peer_state *peer,
 411                     void *caps, size_t caps_len);
 412
 413/* Dynamically resizable remote port pkt.  */
 414
 415typedef struct RemotePortDynPkt {
 416    struct rp_pkt *pkt;
 417    size_t size;
 418} RemotePortDynPkt;
 419
 420/*
 421 * Make sure dpkt is allocated and has enough room.
 422 */
 423
 424void rp_dpkt_alloc(RemotePortDynPkt *dpkt, size_t size);
 425
 426void rp_dpkt_swap(RemotePortDynPkt *a, RemotePortDynPkt *b);
 427
 428/*
 429 * Check if the dpkt is valid. Used for debugging purposes.
 430 */
 431
 432bool rp_dpkt_is_valid(RemotePortDynPkt *dpkt);
 433
 434/*
 435 * Invalidate the dpkt. Used for debugging purposes.
 436 */
 437
 438void rp_dpkt_invalidate(RemotePortDynPkt *dpkt);
 439
 440void rp_dpkt_free(RemotePortDynPkt *dpkt);
 441
 442#endif
 443