hw/block/nvme updates
* NVMe subsystem support (`-device nvme-subsys`) (Minwoo Im) * Namespace (De|At)tachment support (Minwoo Im) * Simple Copy command support (Klaus Jensen) * Flush broadcast support (Gollu Appalanaidu) * QEMUIOVector/QEMUSGList duality refactoring (Klaus Jensen) plus various fixes from Minwoo, Gollu, Dmitry and me. v2: - add `nqn` nvme-subsys device parameter instead of using `id`. (Paolo) -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEUigzqnXi3OaiR2bATeGvMW1PDekFAmBHX5EACgkQTeGvMW1P Dek7ygf9H1g1wwp0Epo3U9z3wCWGcGz6uhBcqEW/T7MtmFg0G50C9iUGKOSe7xtv bWDabGJj0VCCzceeVUtMLfDXtDsekdUEiP/40OWuD3GsMDE7BJj0YIEklPioqa14 maDuFoXbXvgmbPUGIf4IIvmQDTOg22K2oBkjCHA9nbaZM6qxIPC3wRtM77sxXDcW QdKQR4QXOs0lCXUlPdO9PhhnYcxt7k2/WxCKQsdF7ZL7USDkgZ/c7m54MUaw2st4 gQWUAh6vxa+oEjpAjgivCdnmd6B4srpUsvMK3U4UKSpYFXus7teK2x88e8t/plKR 9X0sgL40+PQVI9/CeBh0Z8l/vJYCvg== =WF8v -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/nvme/tags/nvme-next-pull-request' into staging hw/block/nvme updates * NVMe subsystem support (`-device nvme-subsys`) (Minwoo Im) * Namespace (De|At)tachment support (Minwoo Im) * Simple Copy command support (Klaus Jensen) * Flush broadcast support (Gollu Appalanaidu) * QEMUIOVector/QEMUSGList duality refactoring (Klaus Jensen) plus various fixes from Minwoo, Gollu, Dmitry and me. v2: - add `nqn` nvme-subsys device parameter instead of using `id`. (Paolo) # gpg: Signature made Tue 09 Mar 2021 11:44:17 GMT # gpg: using RSA key 522833AA75E2DCE6A24766C04DE1AF316D4F0DE9 # gpg: Good signature from "Klaus Jensen <its@irrelevant.dk>" [unknown] # gpg: aka "Klaus Jensen <k.jensen@samsung.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: DDCA 4D9C 9EF9 31CC 3468 4272 63D5 6FC5 E55D A838 # Subkey fingerprint: 5228 33AA 75E2 DCE6 A247 66C0 4DE1 AF31 6D4F 0DE9 * remotes/nvme/tags/nvme-next-pull-request: (38 commits) hw/block/nvme: support Identify NS Attached Controller List hw/block/nvme: support changed namespace asynchronous event hw/block/nvme: support namespace attachment command hw/block/nvme: refactor nvme_select_ns_iocs hw/block/nvme: support allocated namespace type hw/block/nvme: fix allocated namespace list to 256 hw/block/nvme: fix namespaces array to 1-based hw/block/nvme: support namespace detach hw/block/nvme: refactor nvme_dma hw/block/nvme: remove the req dependency in map functions hw/block/nvme: try to deal with the iov/qsg duality hw/block/nvme: fix strerror printing hw/block/nvme: remove block accounting for write zeroes hw/block/nvme: remove redundant len member in compare context hw/block/nvme: report non-mdts command size limit for dsm hw/block/nvme: add trace event for zone read check hw/block/nvme: fix potential compilation error hw/block/nvme: add identify trace event hw/block/nvme: remove unnecessary endian conversion hw/block/nvme: align zoned.zasl with mdts ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d689ecad07
@ -13,7 +13,7 @@ softmmu_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_TC58128', if_true: files('tc58128.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('nvme.c', 'nvme-ns.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_NVME_PCI', if_true: files('nvme.c', 'nvme-ns.c', 'nvme-subsys.c'))
|
||||
|
||||
specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c'))
|
||||
specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c'))
|
||||
|
@ -63,6 +63,15 @@ static int nvme_ns_init(NvmeNamespace *ns, Error **errp)
|
||||
|
||||
id_ns->npda = id_ns->npdg = npdg - 1;
|
||||
|
||||
if (nvme_ns_shared(ns)) {
|
||||
id_ns->nmic |= NVME_NMIC_NS_SHARED;
|
||||
}
|
||||
|
||||
/* simple copy */
|
||||
id_ns->mssrl = cpu_to_le16(ns->params.mssrl);
|
||||
id_ns->mcl = cpu_to_le32(ns->params.mcl);
|
||||
id_ns->msrc = ns->params.msrc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -154,6 +163,18 @@ static int nvme_ns_zoned_check_calc_geometry(NvmeNamespace *ns, Error **errp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ns->params.max_active_zones) {
|
||||
if (ns->params.max_open_zones > ns->params.max_active_zones) {
|
||||
error_setg(errp, "max_open_zones (%u) exceeds max_active_zones (%u)",
|
||||
ns->params.max_open_zones, ns->params.max_active_zones);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ns->params.max_open_zones) {
|
||||
ns->params.max_open_zones = ns->params.max_active_zones;
|
||||
}
|
||||
}
|
||||
|
||||
if (ns->params.zd_extension_size) {
|
||||
if (ns->params.zd_extension_size & 0x3f) {
|
||||
error_setg(errp,
|
||||
@ -363,16 +384,27 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ns->subsys) {
|
||||
if (nvme_subsys_register_ns(ns, errp)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (nvme_register_namespace(n, ns, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static Property nvme_ns_props[] = {
|
||||
DEFINE_BLOCK_PROPERTIES(NvmeNamespace, blkconf),
|
||||
DEFINE_PROP_LINK("subsys", NvmeNamespace, subsys, TYPE_NVME_SUBSYS,
|
||||
NvmeSubsystem *),
|
||||
DEFINE_PROP_BOOL("detached", NvmeNamespace, params.detached, false),
|
||||
DEFINE_PROP_UINT32("nsid", NvmeNamespace, params.nsid, 0),
|
||||
DEFINE_PROP_UUID("uuid", NvmeNamespace, params.uuid),
|
||||
DEFINE_PROP_UINT16("mssrl", NvmeNamespace, params.mssrl, 128),
|
||||
DEFINE_PROP_UINT32("mcl", NvmeNamespace, params.mcl, 128),
|
||||
DEFINE_PROP_UINT8("msrc", NvmeNamespace, params.msrc, 127),
|
||||
DEFINE_PROP_BOOL("zoned", NvmeNamespace, params.zoned, false),
|
||||
DEFINE_PROP_SIZE("zoned.zone_size", NvmeNamespace, params.zone_size_bs,
|
||||
NVME_DEFAULT_ZONE_SIZE),
|
||||
|
@ -26,9 +26,14 @@ typedef struct NvmeZone {
|
||||
} NvmeZone;
|
||||
|
||||
typedef struct NvmeNamespaceParams {
|
||||
bool detached;
|
||||
uint32_t nsid;
|
||||
QemuUUID uuid;
|
||||
|
||||
uint16_t mssrl;
|
||||
uint32_t mcl;
|
||||
uint8_t msrc;
|
||||
|
||||
bool zoned;
|
||||
bool cross_zone_read;
|
||||
uint64_t zone_size_bs;
|
||||
@ -47,6 +52,9 @@ typedef struct NvmeNamespace {
|
||||
const uint32_t *iocs;
|
||||
uint8_t csi;
|
||||
|
||||
NvmeSubsystem *subsys;
|
||||
QTAILQ_ENTRY(NvmeNamespace) entry;
|
||||
|
||||
NvmeIdNsZoned *id_ns_zoned;
|
||||
NvmeZone *zone_array;
|
||||
QTAILQ_HEAD(, NvmeZone) exp_open_zones;
|
||||
@ -77,6 +85,11 @@ static inline uint32_t nvme_nsid(NvmeNamespace *ns)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline bool nvme_ns_shared(NvmeNamespace *ns)
|
||||
{
|
||||
return !!ns->subsys;
|
||||
}
|
||||
|
||||
static inline NvmeLBAF *nvme_ns_lbaf(NvmeNamespace *ns)
|
||||
{
|
||||
NvmeIdNs *id_ns = &ns->id_ns;
|
||||
|
116
hw/block/nvme-subsys.c
Normal file
116
hw/block/nvme-subsys.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* QEMU NVM Express Subsystem: nvme-subsys
|
||||
*
|
||||
* Copyright (c) 2021 Minwoo Im <minwoo.im.dev@gmail.com>
|
||||
*
|
||||
* This code is licensed under the GNU GPL v2. Refer COPYING.
|
||||
*/
|
||||
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/uuid.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/qdev-core.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "block/aio.h"
|
||||
#include "block/accounting.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "nvme.h"
|
||||
#include "nvme-subsys.h"
|
||||
|
||||
int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp)
|
||||
{
|
||||
NvmeSubsystem *subsys = n->subsys;
|
||||
int cntlid;
|
||||
|
||||
for (cntlid = 0; cntlid < ARRAY_SIZE(subsys->ctrls); cntlid++) {
|
||||
if (!subsys->ctrls[cntlid]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cntlid == ARRAY_SIZE(subsys->ctrls)) {
|
||||
error_setg(errp, "no more free controller id");
|
||||
return -1;
|
||||
}
|
||||
|
||||
subsys->ctrls[cntlid] = n;
|
||||
|
||||
return cntlid;
|
||||
}
|
||||
|
||||
int nvme_subsys_register_ns(NvmeNamespace *ns, Error **errp)
|
||||
{
|
||||
NvmeSubsystem *subsys = ns->subsys;
|
||||
NvmeCtrl *n;
|
||||
int i;
|
||||
|
||||
if (subsys->namespaces[nvme_nsid(ns)]) {
|
||||
error_setg(errp, "namespace %d already registerd to subsy %s",
|
||||
nvme_nsid(ns), subsys->parent_obj.id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
subsys->namespaces[nvme_nsid(ns)] = ns;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(subsys->ctrls); i++) {
|
||||
n = subsys->ctrls[i];
|
||||
|
||||
if (n && nvme_register_namespace(n, ns, errp)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nvme_subsys_setup(NvmeSubsystem *subsys)
|
||||
{
|
||||
const char *nqn = subsys->params.nqn ?
|
||||
subsys->params.nqn : subsys->parent_obj.id;
|
||||
|
||||
snprintf((char *)subsys->subnqn, sizeof(subsys->subnqn),
|
||||
"nqn.2019-08.org.qemu:%s", nqn);
|
||||
}
|
||||
|
||||
static void nvme_subsys_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
NvmeSubsystem *subsys = NVME_SUBSYS(dev);
|
||||
|
||||
nvme_subsys_setup(subsys);
|
||||
}
|
||||
|
||||
static Property nvme_subsystem_props[] = {
|
||||
DEFINE_PROP_STRING("nqn", NvmeSubsystem, params.nqn),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void nvme_subsys_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
|
||||
dc->realize = nvme_subsys_realize;
|
||||
dc->desc = "Virtual NVMe subsystem";
|
||||
|
||||
device_class_set_props(dc, nvme_subsystem_props);
|
||||
}
|
||||
|
||||
static const TypeInfo nvme_subsys_info = {
|
||||
.name = TYPE_NVME_SUBSYS,
|
||||
.parent = TYPE_DEVICE,
|
||||
.class_init = nvme_subsys_class_init,
|
||||
.instance_size = sizeof(NvmeSubsystem),
|
||||
};
|
||||
|
||||
static void nvme_subsys_register_types(void)
|
||||
{
|
||||
type_register_static(&nvme_subsys_info);
|
||||
}
|
||||
|
||||
type_init(nvme_subsys_register_types)
|
60
hw/block/nvme-subsys.h
Normal file
60
hw/block/nvme-subsys.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* QEMU NVM Express Subsystem: nvme-subsys
|
||||
*
|
||||
* Copyright (c) 2021 Minwoo Im <minwoo.im.dev@gmail.com>
|
||||
*
|
||||
* This code is licensed under the GNU GPL v2. Refer COPYING.
|
||||
*/
|
||||
|
||||
#ifndef NVME_SUBSYS_H
|
||||
#define NVME_SUBSYS_H
|
||||
|
||||
#define TYPE_NVME_SUBSYS "nvme-subsys"
|
||||
#define NVME_SUBSYS(obj) \
|
||||
OBJECT_CHECK(NvmeSubsystem, (obj), TYPE_NVME_SUBSYS)
|
||||
|
||||
#define NVME_SUBSYS_MAX_CTRLS 32
|
||||
#define NVME_SUBSYS_MAX_NAMESPACES 256
|
||||
|
||||
typedef struct NvmeCtrl NvmeCtrl;
|
||||
typedef struct NvmeNamespace NvmeNamespace;
|
||||
typedef struct NvmeSubsystem {
|
||||
DeviceState parent_obj;
|
||||
uint8_t subnqn[256];
|
||||
|
||||
NvmeCtrl *ctrls[NVME_SUBSYS_MAX_CTRLS];
|
||||
/* Allocated namespaces for this subsystem */
|
||||
NvmeNamespace *namespaces[NVME_SUBSYS_MAX_NAMESPACES + 1];
|
||||
|
||||
struct {
|
||||
char *nqn;
|
||||
} params;
|
||||
} NvmeSubsystem;
|
||||
|
||||
int nvme_subsys_register_ctrl(NvmeCtrl *n, Error **errp);
|
||||
int nvme_subsys_register_ns(NvmeNamespace *ns, Error **errp);
|
||||
|
||||
static inline NvmeCtrl *nvme_subsys_ctrl(NvmeSubsystem *subsys,
|
||||
uint32_t cntlid)
|
||||
{
|
||||
if (!subsys) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return subsys->ctrls[cntlid];
|
||||
}
|
||||
|
||||
/*
|
||||
* Return allocated namespace of the specified nsid in the subsystem.
|
||||
*/
|
||||
static inline NvmeNamespace *nvme_subsys_ns(NvmeSubsystem *subsys,
|
||||
uint32_t nsid)
|
||||
{
|
||||
if (!subsys) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return subsys->namespaces[nsid];
|
||||
}
|
||||
|
||||
#endif /* NVME_SUBSYS_H */
|
1407
hw/block/nvme.c
1407
hw/block/nvme.c
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@
|
||||
#define HW_NVME_H
|
||||
|
||||
#include "block/nvme.h"
|
||||
#include "nvme-subsys.h"
|
||||
#include "nvme-ns.h"
|
||||
|
||||
#define NVME_MAX_NAMESPACES 256
|
||||
@ -9,6 +10,12 @@
|
||||
#define NVME_DEFAULT_ZONE_SIZE (128 * MiB)
|
||||
#define NVME_DEFAULT_MAX_ZA_SIZE (128 * KiB)
|
||||
|
||||
/*
|
||||
* Subsystem namespace list for allocated namespaces should be larger than
|
||||
* attached namespace list in a controller.
|
||||
*/
|
||||
QEMU_BUILD_BUG_ON(NVME_MAX_NAMESPACES > NVME_SUBSYS_MAX_NAMESPACES);
|
||||
|
||||
typedef struct NvmeParams {
|
||||
char *serial;
|
||||
uint32_t num_queues; /* deprecated since 5.1 */
|
||||
@ -19,7 +26,7 @@ typedef struct NvmeParams {
|
||||
uint32_t aer_max_queued;
|
||||
uint8_t mdts;
|
||||
bool use_intel_id;
|
||||
uint32_t zasl_bs;
|
||||
uint8_t zasl;
|
||||
bool legacy_cmb;
|
||||
} NvmeParams;
|
||||
|
||||
@ -28,6 +35,20 @@ typedef struct NvmeAsyncEvent {
|
||||
NvmeAerResult result;
|
||||
} NvmeAsyncEvent;
|
||||
|
||||
enum {
|
||||
NVME_SG_ALLOC = 1 << 0,
|
||||
NVME_SG_DMA = 1 << 1,
|
||||
};
|
||||
|
||||
typedef struct NvmeSg {
|
||||
int flags;
|
||||
|
||||
union {
|
||||
QEMUSGList qsg;
|
||||
QEMUIOVector iov;
|
||||
};
|
||||
} NvmeSg;
|
||||
|
||||
typedef struct NvmeRequest {
|
||||
struct NvmeSQueue *sq;
|
||||
struct NvmeNamespace *ns;
|
||||
@ -37,8 +58,7 @@ typedef struct NvmeRequest {
|
||||
NvmeCqe cqe;
|
||||
NvmeCmd cmd;
|
||||
BlockAcctCookie acct;
|
||||
QEMUSGList qsg;
|
||||
QEMUIOVector iov;
|
||||
NvmeSg sg;
|
||||
QTAILQ_ENTRY(NvmeRequest)entry;
|
||||
} NvmeRequest;
|
||||
|
||||
@ -68,6 +88,7 @@ static inline const char *nvme_io_opc_str(uint8_t opc)
|
||||
case NVME_CMD_COMPARE: return "NVME_NVM_CMD_COMPARE";
|
||||
case NVME_CMD_WRITE_ZEROES: return "NVME_NVM_CMD_WRITE_ZEROES";
|
||||
case NVME_CMD_DSM: return "NVME_NVM_CMD_DSM";
|
||||
case NVME_CMD_COPY: return "NVME_NVM_CMD_COPY";
|
||||
case NVME_CMD_ZONE_MGMT_SEND: return "NVME_ZONED_CMD_MGMT_SEND";
|
||||
case NVME_CMD_ZONE_MGMT_RECV: return "NVME_ZONED_CMD_MGMT_RECV";
|
||||
case NVME_CMD_ZONE_APPEND: return "NVME_ZONED_CMD_ZONE_APPEND";
|
||||
@ -133,6 +154,7 @@ typedef struct NvmeCtrl {
|
||||
NvmeBus bus;
|
||||
BlockConf conf;
|
||||
|
||||
uint16_t cntlid;
|
||||
bool qs_created;
|
||||
uint32_t page_size;
|
||||
uint16_t page_bits;
|
||||
@ -168,9 +190,19 @@ typedef struct NvmeCtrl {
|
||||
QTAILQ_HEAD(, NvmeAsyncEvent) aer_queue;
|
||||
int aer_queued;
|
||||
|
||||
uint8_t zasl;
|
||||
uint32_t dmrsl;
|
||||
|
||||
/* Namespace ID is started with 1 so bitmap should be 1-based */
|
||||
#define NVME_CHANGED_NSID_SIZE (NVME_MAX_NAMESPACES + 1)
|
||||
DECLARE_BITMAP(changed_nsids, NVME_CHANGED_NSID_SIZE);
|
||||
|
||||
NvmeSubsystem *subsys;
|
||||
|
||||
NvmeNamespace namespace;
|
||||
/*
|
||||
* Attached namespaces to this controller. If subsys is not given, all
|
||||
* namespaces in this list will always be attached.
|
||||
*/
|
||||
NvmeNamespace *namespaces[NVME_MAX_NAMESPACES];
|
||||
NvmeSQueue **sq;
|
||||
NvmeCQueue **cq;
|
||||
@ -189,6 +221,29 @@ static inline NvmeNamespace *nvme_ns(NvmeCtrl *n, uint32_t nsid)
|
||||
return n->namespaces[nsid - 1];
|
||||
}
|
||||
|
||||
static inline bool nvme_ns_is_attached(NvmeCtrl *n, NvmeNamespace *ns)
|
||||
{
|
||||
int nsid;
|
||||
|
||||
for (nsid = 1; nsid <= n->num_namespaces; nsid++) {
|
||||
if (nvme_ns(n, nsid) == ns) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void nvme_ns_attach(NvmeCtrl *n, NvmeNamespace *ns)
|
||||
{
|
||||
n->namespaces[nvme_nsid(ns) - 1] = ns;
|
||||
}
|
||||
|
||||
static inline void nvme_ns_detach(NvmeCtrl *n, NvmeNamespace *ns)
|
||||
{
|
||||
n->namespaces[nvme_nsid(ns) - 1] = NULL;
|
||||
}
|
||||
|
||||
static inline NvmeCQueue *nvme_cq(NvmeRequest *req)
|
||||
{
|
||||
NvmeSQueue *sq = req->sq;
|
||||
|
@ -37,26 +37,36 @@ pci_nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" prp2
|
||||
pci_nvme_map_addr(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64""
|
||||
pci_nvme_map_addr_cmb(uint64_t addr, uint64_t len) "addr 0x%"PRIx64" len %"PRIu64""
|
||||
pci_nvme_map_prp(uint64_t trans_len, uint32_t len, uint64_t prp1, uint64_t prp2, int num_prps) "trans_len %"PRIu64" len %"PRIu32" prp1 0x%"PRIx64" prp2 0x%"PRIx64" num_prps %d"
|
||||
pci_nvme_map_sgl(uint16_t cid, uint8_t typ, uint64_t len) "cid %"PRIu16" type 0x%"PRIx8" len %"PRIu64""
|
||||
pci_nvme_map_sgl(uint8_t typ, uint64_t len) "type 0x%"PRIx8" len %"PRIu64""
|
||||
pci_nvme_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8" opname '%s'"
|
||||
pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode, const char *opname) "cid %"PRIu16" sqid %"PRIu16" opc 0x%"PRIx8" opname '%s'"
|
||||
pci_nvme_flush(uint16_t cid, uint32_t nsid) "cid %"PRIu16" nsid %"PRIu32""
|
||||
pci_nvme_read(uint16_t cid, uint32_t nsid, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" nsid %"PRIu32" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64""
|
||||
pci_nvme_write(uint16_t cid, const char *verb, uint32_t nsid, uint32_t nlb, uint64_t count, uint64_t lba) "cid %"PRIu16" opname '%s' nsid %"PRIu32" nlb %"PRIu32" count %"PRIu64" lba 0x%"PRIx64""
|
||||
pci_nvme_rw_cb(uint16_t cid, const char *blkname) "cid %"PRIu16" blk '%s'"
|
||||
pci_nvme_copy(uint16_t cid, uint32_t nsid, uint16_t nr, uint8_t format) "cid %"PRIu16" nsid %"PRIu32" nr %"PRIu16" format 0x%"PRIx8""
|
||||
pci_nvme_copy_source_range(uint64_t slba, uint32_t nlb) "slba 0x%"PRIx64" nlb %"PRIu32""
|
||||
pci_nvme_copy_in_complete(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_copy_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_block_status(int64_t offset, int64_t bytes, int64_t pnum, int ret, bool zeroed) "offset %"PRId64" bytes %"PRId64" pnum %"PRId64" ret 0x%x zeroed %d"
|
||||
pci_nvme_dsm(uint16_t cid, uint32_t nsid, uint32_t nr, uint32_t attr) "cid %"PRIu16" nsid %"PRIu32" nr %"PRIu32" attr 0x%"PRIx32""
|
||||
pci_nvme_dsm_deallocate(uint16_t cid, uint32_t nsid, uint64_t slba, uint32_t nlb) "cid %"PRIu16" nsid %"PRIu32" slba %"PRIu64" nlb %"PRIu32""
|
||||
pci_nvme_dsm_single_range_limit_exceeded(uint32_t nlb, uint32_t dmrsl) "nlb %"PRIu32" dmrsl %"PRIu32""
|
||||
pci_nvme_compare(uint16_t cid, uint32_t nsid, uint64_t slba, uint32_t nlb) "cid %"PRIu16" nsid %"PRIu32" slba 0x%"PRIx64" nlb %"PRIu32""
|
||||
pci_nvme_compare_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_aio_discard_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_aio_copy_in_cb(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_aio_zone_reset_cb(uint16_t cid, uint64_t zslba) "cid %"PRIu16" zslba 0x%"PRIx64""
|
||||
pci_nvme_aio_flush_cb(uint16_t cid, const char *blkname) "cid %"PRIu16" blk '%s'"
|
||||
pci_nvme_create_sq(uint64_t addr, uint16_t sqid, uint16_t cqid, uint16_t qsize, uint16_t qflags) "create submission queue, addr=0x%"PRIx64", sqid=%"PRIu16", cqid=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16""
|
||||
pci_nvme_create_cq(uint64_t addr, uint16_t cqid, uint16_t vector, uint16_t size, uint16_t qflags, int ien) "create completion queue, addr=0x%"PRIx64", cqid=%"PRIu16", vector=%"PRIu16", qsize=%"PRIu16", qflags=%"PRIu16", ien=%d"
|
||||
pci_nvme_del_sq(uint16_t qid) "deleting submission queue sqid=%"PRIu16""
|
||||
pci_nvme_del_cq(uint16_t cqid) "deleted completion queue, cqid=%"PRIu16""
|
||||
pci_nvme_identify(uint16_t cid, uint8_t cns, uint16_t ctrlid, uint8_t csi) "cid %"PRIu16" cns 0x%"PRIx8" ctrlid %"PRIu16" csi 0x%"PRIx8""
|
||||
pci_nvme_identify_ctrl(void) "identify controller"
|
||||
pci_nvme_identify_ctrl_csi(uint8_t csi) "identify controller, csi=0x%"PRIx8""
|
||||
pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32""
|
||||
pci_nvme_identify_ns_attached_list(uint16_t cntid) "cntid=%"PRIu16""
|
||||
pci_nvme_identify_ns_csi(uint32_t ns, uint8_t csi) "nsid=%"PRIu32", csi=0x%"PRIx8""
|
||||
pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32""
|
||||
pci_nvme_identify_nslist_csi(uint16_t ns, uint8_t csi) "nsid=%"PRIu16", csi=0x%"PRIx8""
|
||||
@ -75,6 +85,8 @@ pci_nvme_aer(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_aer_aerl_exceeded(void) "aerl exceeded"
|
||||
pci_nvme_aer_masked(uint8_t type, uint8_t mask) "type 0x%"PRIx8" mask 0x%"PRIx8""
|
||||
pci_nvme_aer_post_cqe(uint8_t typ, uint8_t info, uint8_t log_page) "type 0x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8""
|
||||
pci_nvme_ns_attachment(uint16_t cid, uint8_t sel) "cid %"PRIu16", sel=0x%"PRIx8""
|
||||
pci_nvme_ns_attachment_attach(uint16_t cntlid, uint32_t nsid) "cntlid=0x%"PRIx16", nsid=0x%"PRIx32""
|
||||
pci_nvme_enqueue_event(uint8_t typ, uint8_t info, uint8_t log_page) "type 0x%"PRIx8" info 0x%"PRIx8" lid 0x%"PRIx8""
|
||||
pci_nvme_enqueue_event_noqueue(int queued) "queued %d"
|
||||
pci_nvme_enqueue_event_masked(uint8_t typ) "type 0x%"PRIx8""
|
||||
@ -107,15 +119,17 @@ pci_nvme_clear_ns_close(uint32_t state, uint64_t slba) "zone state=%"PRIu32", sl
|
||||
pci_nvme_clear_ns_reset(uint32_t state, uint64_t slba) "zone state=%"PRIu32", slba=%"PRIu64" transitioned to Empty state"
|
||||
|
||||
# nvme traces for error conditions
|
||||
pci_nvme_err_mdts(uint16_t cid, size_t len) "cid %"PRIu16" len %zu"
|
||||
pci_nvme_err_mdts(size_t len) "len %zu"
|
||||
pci_nvme_err_zasl(size_t len) "len %zu"
|
||||
pci_nvme_err_req_status(uint16_t cid, uint32_t nsid, uint16_t status, uint8_t opc) "cid %"PRIu16" nsid %"PRIu32" status 0x%"PRIx16" opc 0x%"PRIx8""
|
||||
pci_nvme_err_addr_read(uint64_t addr) "addr 0x%"PRIx64""
|
||||
pci_nvme_err_addr_write(uint64_t addr) "addr 0x%"PRIx64""
|
||||
pci_nvme_err_cfs(void) "controller fatal status"
|
||||
pci_nvme_err_aio(uint16_t cid, const char *errname, uint16_t status) "cid %"PRIu16" err '%s' status 0x%"PRIx16""
|
||||
pci_nvme_err_copy_invalid_format(uint8_t format) "format 0x%"PRIx8""
|
||||
pci_nvme_err_invalid_sgld(uint16_t cid, uint8_t typ) "cid %"PRIu16" type 0x%"PRIx8""
|
||||
pci_nvme_err_invalid_num_sgld(uint16_t cid, uint8_t typ) "cid %"PRIu16" type 0x%"PRIx8""
|
||||
pci_nvme_err_invalid_sgl_excess_length(uint16_t cid) "cid %"PRIu16""
|
||||
pci_nvme_err_invalid_sgl_excess_length(uint32_t residual) "residual %"PRIu32""
|
||||
pci_nvme_err_invalid_dma(void) "PRP/SGL is too small for transfer size"
|
||||
pci_nvme_err_invalid_prplist_ent(uint64_t prplist) "PRP list entry is not page aligned: 0x%"PRIx64""
|
||||
pci_nvme_err_invalid_prp2_align(uint64_t prp2) "PRP2 is not page aligned: 0x%"PRIx64""
|
||||
@ -136,7 +150,6 @@ pci_nvme_err_zone_boundary(uint64_t slba, uint32_t nlb, uint64_t zcap) "lba 0x%"
|
||||
pci_nvme_err_zone_invalid_write(uint64_t slba, uint64_t wp) "lba 0x%"PRIx64" wp 0x%"PRIx64""
|
||||
pci_nvme_err_zone_write_not_ok(uint64_t slba, uint32_t nlb, uint16_t status) "slba=%"PRIu64", nlb=%"PRIu32", status=0x%"PRIx16""
|
||||
pci_nvme_err_zone_read_not_ok(uint64_t slba, uint32_t nlb, uint16_t status) "slba=%"PRIu64", nlb=%"PRIu32", status=0x%"PRIx16""
|
||||
pci_nvme_err_append_too_large(uint64_t slba, uint32_t nlb, uint8_t zasl) "slba=%"PRIu64", nlb=%"PRIu32", zasl=%"PRIu8""
|
||||
pci_nvme_err_insuff_active_res(uint32_t max_active) "max_active=%"PRIu32" zone limit exceeded"
|
||||
pci_nvme_err_insuff_open_res(uint32_t max_open) "max_open=%"PRIu32" zone limit exceeded"
|
||||
pci_nvme_err_zd_extension_map_error(uint32_t zone_idx) "can't map descriptor extension for zone_idx=%"PRIu32""
|
||||
|
@ -566,6 +566,7 @@ enum NvmeAdminCommands {
|
||||
NVME_ADM_CMD_ASYNC_EV_REQ = 0x0c,
|
||||
NVME_ADM_CMD_ACTIVATE_FW = 0x10,
|
||||
NVME_ADM_CMD_DOWNLOAD_FW = 0x11,
|
||||
NVME_ADM_CMD_NS_ATTACHMENT = 0x15,
|
||||
NVME_ADM_CMD_FORMAT_NVM = 0x80,
|
||||
NVME_ADM_CMD_SECURITY_SEND = 0x81,
|
||||
NVME_ADM_CMD_SECURITY_RECV = 0x82,
|
||||
@ -579,6 +580,7 @@ enum NvmeIoCommands {
|
||||
NVME_CMD_COMPARE = 0x05,
|
||||
NVME_CMD_WRITE_ZEROES = 0x08,
|
||||
NVME_CMD_DSM = 0x09,
|
||||
NVME_CMD_COPY = 0x19,
|
||||
NVME_CMD_ZONE_MGMT_SEND = 0x79,
|
||||
NVME_CMD_ZONE_MGMT_RECV = 0x7a,
|
||||
NVME_CMD_ZONE_APPEND = 0x7d,
|
||||
@ -724,9 +726,41 @@ typedef struct QEMU_PACKED NvmeDsmRange {
|
||||
uint64_t slba;
|
||||
} NvmeDsmRange;
|
||||
|
||||
enum {
|
||||
NVME_COPY_FORMAT_0 = 0x0,
|
||||
};
|
||||
|
||||
typedef struct QEMU_PACKED NvmeCopyCmd {
|
||||
uint8_t opcode;
|
||||
uint8_t flags;
|
||||
uint16_t cid;
|
||||
uint32_t nsid;
|
||||
uint32_t rsvd2[4];
|
||||
NvmeCmdDptr dptr;
|
||||
uint64_t sdlba;
|
||||
uint8_t nr;
|
||||
uint8_t control[3];
|
||||
uint16_t rsvd13;
|
||||
uint16_t dspec;
|
||||
uint32_t reftag;
|
||||
uint16_t apptag;
|
||||
uint16_t appmask;
|
||||
} NvmeCopyCmd;
|
||||
|
||||
typedef struct QEMU_PACKED NvmeCopySourceRange {
|
||||
uint8_t rsvd0[8];
|
||||
uint64_t slba;
|
||||
uint16_t nlb;
|
||||
uint8_t rsvd18[6];
|
||||
uint32_t reftag;
|
||||
uint16_t apptag;
|
||||
uint16_t appmask;
|
||||
} NvmeCopySourceRange;
|
||||
|
||||
enum NvmeAsyncEventRequest {
|
||||
NVME_AER_TYPE_ERROR = 0,
|
||||
NVME_AER_TYPE_SMART = 1,
|
||||
NVME_AER_TYPE_NOTICE = 2,
|
||||
NVME_AER_TYPE_IO_SPECIFIC = 6,
|
||||
NVME_AER_TYPE_VENDOR_SPECIFIC = 7,
|
||||
NVME_AER_INFO_ERR_INVALID_DB_REGISTER = 0,
|
||||
@ -738,6 +772,7 @@ enum NvmeAsyncEventRequest {
|
||||
NVME_AER_INFO_SMART_RELIABILITY = 0,
|
||||
NVME_AER_INFO_SMART_TEMP_THRESH = 1,
|
||||
NVME_AER_INFO_SMART_SPARE_THRESH = 2,
|
||||
NVME_AER_INFO_NOTICE_NS_ATTR_CHANGED = 0,
|
||||
};
|
||||
|
||||
typedef struct QEMU_PACKED NvmeAerResult {
|
||||
@ -804,9 +839,13 @@ enum NvmeStatusCodes {
|
||||
NVME_FEAT_NOT_CHANGEABLE = 0x010e,
|
||||
NVME_FEAT_NOT_NS_SPEC = 0x010f,
|
||||
NVME_FW_REQ_SUSYSTEM_RESET = 0x0110,
|
||||
NVME_NS_ALREADY_ATTACHED = 0x0118,
|
||||
NVME_NS_NOT_ATTACHED = 0x011A,
|
||||
NVME_NS_CTRL_LIST_INVALID = 0x011C,
|
||||
NVME_CONFLICTING_ATTRS = 0x0180,
|
||||
NVME_INVALID_PROT_INFO = 0x0181,
|
||||
NVME_WRITE_TO_RO = 0x0182,
|
||||
NVME_CMD_SIZE_LIMIT = 0x0183,
|
||||
NVME_ZONE_BOUNDARY_ERROR = 0x01b8,
|
||||
NVME_ZONE_FULL = 0x01b9,
|
||||
NVME_ZONE_READ_ONLY = 0x01ba,
|
||||
@ -903,6 +942,7 @@ enum NvmeLogIdentifier {
|
||||
NVME_LOG_ERROR_INFO = 0x01,
|
||||
NVME_LOG_SMART_INFO = 0x02,
|
||||
NVME_LOG_FW_SLOT_INFO = 0x03,
|
||||
NVME_LOG_CHANGED_NSLIST = 0x04,
|
||||
NVME_LOG_CMD_EFFECTS = 0x05,
|
||||
};
|
||||
|
||||
@ -918,6 +958,7 @@ typedef struct QEMU_PACKED NvmePSD {
|
||||
uint8_t resv[16];
|
||||
} NvmePSD;
|
||||
|
||||
#define NVME_CONTROLLER_LIST_SIZE 2048
|
||||
#define NVME_IDENTIFY_DATA_SIZE 4096
|
||||
|
||||
enum NvmeIdCns {
|
||||
@ -930,6 +971,7 @@ enum NvmeIdCns {
|
||||
NVME_ID_CNS_CS_NS_ACTIVE_LIST = 0x07,
|
||||
NVME_ID_CNS_NS_PRESENT_LIST = 0x10,
|
||||
NVME_ID_CNS_NS_PRESENT = 0x11,
|
||||
NVME_ID_CNS_NS_ATTACHED_CTRL_LIST = 0x12,
|
||||
NVME_ID_CNS_CS_NS_PRESENT_LIST = 0x1a,
|
||||
NVME_ID_CNS_CS_NS_PRESENT = 0x1b,
|
||||
NVME_ID_CNS_IO_COMMAND_SET = 0x1c,
|
||||
@ -994,7 +1036,7 @@ typedef struct QEMU_PACKED NvmeIdCtrl {
|
||||
uint8_t nvscc;
|
||||
uint8_t rsvd531;
|
||||
uint16_t acwu;
|
||||
uint8_t rsvd534[2];
|
||||
uint16_t ocfs;
|
||||
uint32_t sgls;
|
||||
uint8_t rsvd540[228];
|
||||
uint8_t subnqn[256];
|
||||
@ -1008,10 +1050,25 @@ typedef struct NvmeIdCtrlZoned {
|
||||
uint8_t rsvd1[4095];
|
||||
} NvmeIdCtrlZoned;
|
||||
|
||||
typedef struct NvmeIdCtrlNvm {
|
||||
uint8_t vsl;
|
||||
uint8_t wzsl;
|
||||
uint8_t wusl;
|
||||
uint8_t dmrl;
|
||||
uint32_t dmrsl;
|
||||
uint64_t dmsl;
|
||||
uint8_t rsvd16[4080];
|
||||
} NvmeIdCtrlNvm;
|
||||
|
||||
enum NvmeIdCtrlOaes {
|
||||
NVME_OAES_NS_ATTR = 1 << 8,
|
||||
};
|
||||
|
||||
enum NvmeIdCtrlOacs {
|
||||
NVME_OACS_SECURITY = 1 << 0,
|
||||
NVME_OACS_FORMAT = 1 << 1,
|
||||
NVME_OACS_FW = 1 << 2,
|
||||
NVME_OACS_NS_MGMT = 1 << 3,
|
||||
};
|
||||
|
||||
enum NvmeIdCtrlOncs {
|
||||
@ -1022,6 +1079,19 @@ enum NvmeIdCtrlOncs {
|
||||
NVME_ONCS_FEATURES = 1 << 4,
|
||||
NVME_ONCS_RESRVATIONS = 1 << 5,
|
||||
NVME_ONCS_TIMESTAMP = 1 << 6,
|
||||
NVME_ONCS_COPY = 1 << 8,
|
||||
};
|
||||
|
||||
enum NvmeIdCtrlOcfs {
|
||||
NVME_OCFS_COPY_FORMAT_0 = 1 << 0,
|
||||
};
|
||||
|
||||
enum NvmeIdctrlVwc {
|
||||
NVME_VWC_PRESENT = 1 << 0,
|
||||
NVME_VWC_NSID_BROADCAST_NO_SUPPORT = 0 << 1,
|
||||
NVME_VWC_NSID_BROADCAST_RESERVED = 1 << 1,
|
||||
NVME_VWC_NSID_BROADCAST_CTRL_SPEC = 2 << 1,
|
||||
NVME_VWC_NSID_BROADCAST_SUPPORT = 3 << 1,
|
||||
};
|
||||
|
||||
enum NvmeIdCtrlFrmw {
|
||||
@ -1034,6 +1104,10 @@ enum NvmeIdCtrlLpa {
|
||||
NVME_LPA_EXTENDED = 1 << 2,
|
||||
};
|
||||
|
||||
enum NvmeIdCtrlCmic {
|
||||
NVME_CMIC_MULTI_CTRL = 1 << 1,
|
||||
};
|
||||
|
||||
#define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf)
|
||||
#define NVME_CTRL_SQES_MAX(sqes) (((sqes) >> 4) & 0xf)
|
||||
#define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf)
|
||||
@ -1171,7 +1245,10 @@ typedef struct QEMU_PACKED NvmeIdNs {
|
||||
uint16_t npdg;
|
||||
uint16_t npda;
|
||||
uint16_t nows;
|
||||
uint8_t rsvd74[30];
|
||||
uint16_t mssrl;
|
||||
uint32_t mcl;
|
||||
uint8_t msrc;
|
||||
uint8_t rsvd81[23];
|
||||
uint8_t nguid[16];
|
||||
uint64_t eui64;
|
||||
NvmeLBAF lbaf[16];
|
||||
@ -1199,6 +1276,10 @@ enum NvmeNsIdentifierType {
|
||||
NVME_NIDT_CSI = 0x04,
|
||||
};
|
||||
|
||||
enum NvmeIdNsNmic {
|
||||
NVME_NMIC_NS_SHARED = 1 << 0,
|
||||
};
|
||||
|
||||
enum NvmeCsi {
|
||||
NVME_CSI_NVM = 0x00,
|
||||
NVME_CSI_ZONED = 0x02,
|
||||
@ -1323,6 +1404,7 @@ static inline void _nvme_check_size(void)
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeZonedResult) != 8);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeCqe) != 16);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeDsmRange) != 16);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeCopySourceRange) != 32);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeCmd) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeDeleteQ) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeCreateCq) != 64);
|
||||
@ -1330,6 +1412,7 @@ static inline void _nvme_check_size(void)
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeIdentify) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeRwCmd) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeDsmCmd) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeCopyCmd) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeRangeType) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeErrorLog) != 64);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeFwSlotInfoLog) != 512);
|
||||
@ -1337,6 +1420,7 @@ static inline void _nvme_check_size(void)
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeEffectsLog) != 4096);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) != 4096);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrlZoned) != 4096);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrlNvm) != 4096);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeLBAF) != 4);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeLBAFE) != 16);
|
||||
QEMU_BUILD_BUG_ON(sizeof(NvmeIdNs) != 4096);
|
||||
|
Loading…
Reference in New Issue
Block a user