qemu/hw/block/nvme.h
<<
>>
Prefs
   1#ifndef HW_NVME_H
   2#define HW_NVME_H
   3
   4#include "block/nvme.h"
   5#include "hw/pci/pci.h"
   6#include "nvme-subsys.h"
   7#include "nvme-ns.h"
   8
   9#define NVME_DEFAULT_ZONE_SIZE   (128 * MiB)
  10#define NVME_DEFAULT_MAX_ZA_SIZE (128 * KiB)
  11
  12typedef struct NvmeParams {
  13    char     *serial;
  14    uint32_t num_queues; /* deprecated since 5.1 */
  15    uint32_t max_ioqpairs;
  16    uint16_t msix_qsize;
  17    uint32_t cmb_size_mb;
  18    uint8_t  aerl;
  19    uint32_t aer_max_queued;
  20    uint8_t  mdts;
  21    uint8_t  vsl;
  22    bool     use_intel_id;
  23    uint8_t  zasl;
  24    bool     legacy_cmb;
  25} NvmeParams;
  26
  27typedef struct NvmeAsyncEvent {
  28    QTAILQ_ENTRY(NvmeAsyncEvent) entry;
  29    NvmeAerResult result;
  30} NvmeAsyncEvent;
  31
  32enum {
  33    NVME_SG_ALLOC = 1 << 0,
  34    NVME_SG_DMA   = 1 << 1,
  35};
  36
  37typedef struct NvmeSg {
  38    int flags;
  39
  40    union {
  41        QEMUSGList   qsg;
  42        QEMUIOVector iov;
  43    };
  44} NvmeSg;
  45
  46typedef struct NvmeRequest {
  47    struct NvmeSQueue       *sq;
  48    struct NvmeNamespace    *ns;
  49    BlockAIOCB              *aiocb;
  50    uint16_t                status;
  51    void                    *opaque;
  52    NvmeCqe                 cqe;
  53    NvmeCmd                 cmd;
  54    BlockAcctCookie         acct;
  55    NvmeSg                  sg;
  56    QTAILQ_ENTRY(NvmeRequest)entry;
  57} NvmeRequest;
  58
  59typedef struct NvmeBounceContext {
  60    NvmeRequest *req;
  61
  62    struct {
  63        QEMUIOVector iov;
  64        uint8_t *bounce;
  65    } data, mdata;
  66} NvmeBounceContext;
  67
  68static inline const char *nvme_adm_opc_str(uint8_t opc)
  69{
  70    switch (opc) {
  71    case NVME_ADM_CMD_DELETE_SQ:        return "NVME_ADM_CMD_DELETE_SQ";
  72    case NVME_ADM_CMD_CREATE_SQ:        return "NVME_ADM_CMD_CREATE_SQ";
  73    case NVME_ADM_CMD_GET_LOG_PAGE:     return "NVME_ADM_CMD_GET_LOG_PAGE";
  74    case NVME_ADM_CMD_DELETE_CQ:        return "NVME_ADM_CMD_DELETE_CQ";
  75    case NVME_ADM_CMD_CREATE_CQ:        return "NVME_ADM_CMD_CREATE_CQ";
  76    case NVME_ADM_CMD_IDENTIFY:         return "NVME_ADM_CMD_IDENTIFY";
  77    case NVME_ADM_CMD_ABORT:            return "NVME_ADM_CMD_ABORT";
  78    case NVME_ADM_CMD_SET_FEATURES:     return "NVME_ADM_CMD_SET_FEATURES";
  79    case NVME_ADM_CMD_GET_FEATURES:     return "NVME_ADM_CMD_GET_FEATURES";
  80    case NVME_ADM_CMD_ASYNC_EV_REQ:     return "NVME_ADM_CMD_ASYNC_EV_REQ";
  81    case NVME_ADM_CMD_NS_ATTACHMENT:    return "NVME_ADM_CMD_NS_ATTACHMENT";
  82    case NVME_ADM_CMD_FORMAT_NVM:       return "NVME_ADM_CMD_FORMAT_NVM";
  83    default:                            return "NVME_ADM_CMD_UNKNOWN";
  84    }
  85}
  86
  87static inline const char *nvme_io_opc_str(uint8_t opc)
  88{
  89    switch (opc) {
  90    case NVME_CMD_FLUSH:            return "NVME_NVM_CMD_FLUSH";
  91    case NVME_CMD_WRITE:            return "NVME_NVM_CMD_WRITE";
  92    case NVME_CMD_READ:             return "NVME_NVM_CMD_READ";
  93    case NVME_CMD_COMPARE:          return "NVME_NVM_CMD_COMPARE";
  94    case NVME_CMD_WRITE_ZEROES:     return "NVME_NVM_CMD_WRITE_ZEROES";
  95    case NVME_CMD_DSM:              return "NVME_NVM_CMD_DSM";
  96    case NVME_CMD_VERIFY:           return "NVME_NVM_CMD_VERIFY";
  97    case NVME_CMD_COPY:             return "NVME_NVM_CMD_COPY";
  98    case NVME_CMD_ZONE_MGMT_SEND:   return "NVME_ZONED_CMD_MGMT_SEND";
  99    case NVME_CMD_ZONE_MGMT_RECV:   return "NVME_ZONED_CMD_MGMT_RECV";
 100    case NVME_CMD_ZONE_APPEND:      return "NVME_ZONED_CMD_ZONE_APPEND";
 101    default:                        return "NVME_NVM_CMD_UNKNOWN";
 102    }
 103}
 104
 105typedef struct NvmeSQueue {
 106    struct NvmeCtrl *ctrl;
 107    uint16_t    sqid;
 108    uint16_t    cqid;
 109    uint32_t    head;
 110    uint32_t    tail;
 111    uint32_t    size;
 112    uint64_t    dma_addr;
 113    QEMUTimer   *timer;
 114    NvmeRequest *io_req;
 115    QTAILQ_HEAD(, NvmeRequest) req_list;
 116    QTAILQ_HEAD(, NvmeRequest) out_req_list;
 117    QTAILQ_ENTRY(NvmeSQueue) entry;
 118} NvmeSQueue;
 119
 120typedef struct NvmeCQueue {
 121    struct NvmeCtrl *ctrl;
 122    uint8_t     phase;
 123    uint16_t    cqid;
 124    uint16_t    irq_enabled;
 125    uint32_t    head;
 126    uint32_t    tail;
 127    uint32_t    vector;
 128    uint32_t    size;
 129    uint64_t    dma_addr;
 130    QEMUTimer   *timer;
 131    QTAILQ_HEAD(, NvmeSQueue) sq_list;
 132    QTAILQ_HEAD(, NvmeRequest) req_list;
 133} NvmeCQueue;
 134
 135#define TYPE_NVME_BUS "nvme-bus"
 136#define NVME_BUS(obj) OBJECT_CHECK(NvmeBus, (obj), TYPE_NVME_BUS)
 137
 138typedef struct NvmeBus {
 139    BusState parent_bus;
 140} NvmeBus;
 141
 142#define TYPE_NVME "nvme"
 143#define NVME(obj) \
 144        OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME)
 145
 146typedef struct NvmeFeatureVal {
 147    struct {
 148        uint16_t temp_thresh_hi;
 149        uint16_t temp_thresh_low;
 150    };
 151    uint32_t    async_config;
 152} NvmeFeatureVal;
 153
 154typedef struct NvmeCtrl {
 155    PCIDevice    parent_obj;
 156    MemoryRegion bar0;
 157    MemoryRegion iomem;
 158    NvmeBar      bar;
 159    NvmeParams   params;
 160    NvmeBus      bus;
 161
 162    uint16_t    cntlid;
 163    bool        qs_created;
 164    uint32_t    page_size;
 165    uint16_t    page_bits;
 166    uint16_t    max_prp_ents;
 167    uint16_t    cqe_size;
 168    uint16_t    sqe_size;
 169    uint32_t    reg_size;
 170    uint32_t    num_namespaces;
 171    uint32_t    max_q_ents;
 172    uint8_t     outstanding_aers;
 173    uint32_t    irq_status;
 174    uint64_t    host_timestamp;                 /* Timestamp sent by the host */
 175    uint64_t    timestamp_set_qemu_clock_ms;    /* QEMU clock time */
 176    uint64_t    starttime_ms;
 177    uint16_t    temperature;
 178    uint8_t     smart_critical_warning;
 179
 180    struct {
 181        MemoryRegion mem;
 182        uint8_t      *buf;
 183        bool         cmse;
 184        hwaddr       cba;
 185    } cmb;
 186
 187    struct {
 188        HostMemoryBackend *dev;
 189        bool              cmse;
 190        hwaddr            cba;
 191    } pmr;
 192
 193    uint8_t     aer_mask;
 194    NvmeRequest **aer_reqs;
 195    QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue;
 196    int         aer_queued;
 197
 198    uint32_t    dmrsl;
 199
 200    /* Namespace ID is started with 1 so bitmap should be 1-based */
 201#define NVME_CHANGED_NSID_SIZE  (NVME_MAX_NAMESPACES + 1)
 202    DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE);
 203
 204    NvmeSubsystem   *subsys;
 205
 206    NvmeNamespace   namespace;
 207    /*
 208     * Attached namespaces to this controller.  If subsys is not given, all
 209     * namespaces in this list will always be attached.
 210     */
 211    NvmeNamespace   *namespaces[NVME_MAX_NAMESPACES];
 212    NvmeSQueue      **sq;
 213    NvmeCQueue      **cq;
 214    NvmeSQueue      admin_sq;
 215    NvmeCQueue      admin_cq;
 216    NvmeIdCtrl      id_ctrl;
 217    NvmeFeatureVal  features;
 218} NvmeCtrl;
 219
 220static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
 221{
 222    if (!nsid || nsid > n->num_namespaces) {
 223        return NULL;
 224    }
 225
 226    return n->namespaces[nsid - 1];
 227}
 228
 229static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
 230{
 231    NvmeSQueue *sq = req->sq;
 232    NvmeCtrl *n = sq->ctrl;
 233
 234    return n->cq[sq->cqid];
 235}
 236
 237static inline NvmeCtrl *nvme_ctrl(NvmeRequest *req)
 238{
 239    NvmeSQueue *sq = req->sq;
 240    return sq->ctrl;
 241}
 242
 243static inline uint16_t nvme_cid(NvmeRequest *req)
 244{
 245    if (!req) {
 246        return 0xffff;
 247    }
 248
 249    return le16_to_cpu(req->cqe.cid);
 250}
 251
 252typedef enum NvmeTxDirection {
 253    NVME_TX_DIRECTION_TO_DEVICE   = 0,
 254    NVME_TX_DIRECTION_FROM_DEVICE = 1,
 255} NvmeTxDirection;
 256
 257void nvme_attach_ns(NvmeCtrl *n, NvmeNamespace *ns);
 258uint16_t nvme_bounce_data(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
 259                          NvmeTxDirection dir, NvmeRequest *req);
 260uint16_t nvme_bounce_mdata(NvmeCtrl *n, uint8_t *ptr, uint32_t len,
 261                           NvmeTxDirection dir, NvmeRequest *req);
 262void nvme_rw_complete_cb(void *opaque, int ret);
 263uint16_t nvme_map_dptr(NvmeCtrl *n, NvmeSg *sg, size_t len,
 264                       NvmeCmd *cmd);
 265
 266#endif /* HW_NVME_H */
 267