Merge tag 'pull-nvme-20250227' of https://gitlab.com/birkelund/qemu into staging

nvme queue

# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCgAdFiEEUigzqnXi3OaiR2bATeGvMW1PDekFAmfAMFEACgkQTeGvMW1P
# DenstAf9GuLVxVUhKDlAJwyRl9Z3lrPMkKwoYF2B75fmqJhW0wZh5VSh6z/s5Qx7
# h/5soFrAMlcZPg5FO0OkY9d4psPlDHBPnuGqX2zLxx0zZnpC/QThSa6hzmETDwfv
# mXEMA/AnXar9MqjrbeR2QjVRphP9mzWpaK7JLmvX9KYvMVxqXSEq5TuylbIeyBQ5
# rSWlVnuKvVLRVtavDpZjHAk5q6CgO1nQ0N3IyIjZmllphCgrJVX5PMtiLur3dPSF
# nYv2TR3uZJmlHR9qsFEc1aIBKNSBhwBJljRuIJe+yFTI8rxCClNlqMQOfgBJp4z6
# GYHm0w0p0NLn/V5dTqLsJoHs20u46A==
# =703u
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 27 Feb 2025 17:28:49 HKT
# 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

* tag 'pull-nvme-20250227' of https://gitlab.com/birkelund/qemu:
  hw/nvme: remove nvme_aio_err()
  hw/nvme: set error status code explicitly for misc commands
  hw/nvme: only set command abort requested when cancelled due to Abort
  hw/nvme: rework csi handling
  hw/nvme: be compliant wrt. dsm processing limits
  nvme: fix iocs status code values
  hw/nvme: add knob for doorbell buffer config support
  hw/nvme: make oacs dynamic
  hw/nvme: always initialize a subsystem
  hw/nvme: Add OCP SMART / Health Information Extended Log Page

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi
2025-03-03 10:20:48 +08:00
5 changed files with 373 additions and 230 deletions
+7
View File
@@ -53,6 +53,13 @@ parameters.
Vendor ID. Set this to ``on`` to revert to the unallocated Intel ID
previously used.
``ocp`` (default: ``off``)
The Open Compute Project defines the Datacenter NVMe SSD Specification that
sits on top of NVMe. It describes additional commands and NVMe behaviors
specific for the Datacenter. When this option is ``on`` OCP features such as
the SMART / Health information extended log become available in the
controller. We emulate version 5 of this log page.
Additional Namespaces
---------------------
+287 -173
View File
File diff suppressed because it is too large Load Diff
+14 -48
View File
@@ -727,25 +727,14 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
uint32_t nsid = ns->params.nsid;
int i;
if (!n->subsys) {
/* If no subsys, the ns cannot be attached to more than one ctrl. */
ns->params.shared = false;
if (ns->params.detached) {
error_setg(errp, "detached requires that the nvme device is "
"linked to an nvme-subsys device");
return;
}
} else {
/*
* If this namespace belongs to a subsystem (through a link on the
* controller device), reparent the device.
*/
if (!qdev_set_parent_bus(dev, &subsys->bus.parent_bus, errp)) {
return;
}
ns->subsys = subsys;
ns->endgrp = &subsys->endgrp;
assert(subsys);
/* reparent to subsystem bus */
if (!qdev_set_parent_bus(dev, &subsys->bus.parent_bus, errp)) {
return;
}
ns->subsys = subsys;
ns->endgrp = &subsys->endgrp;
if (nvme_ns_setup(ns, errp)) {
return;
@@ -753,7 +742,7 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
if (!nsid) {
for (i = 1; i <= NVME_MAX_NAMESPACES; i++) {
if (nvme_ns(n, i) || nvme_subsys_ns(subsys, i)) {
if (nvme_subsys_ns(subsys, i)) {
continue;
}
@@ -765,38 +754,15 @@ static void nvme_ns_realize(DeviceState *dev, Error **errp)
error_setg(errp, "no free namespace id");
return;
}
} else {
if (nvme_ns(n, nsid) || nvme_subsys_ns(subsys, nsid)) {
error_setg(errp, "namespace id '%d' already allocated", nsid);
return;
}
} else if (nvme_subsys_ns(subsys, nsid)) {
error_setg(errp, "namespace id '%d' already allocated", nsid);
return;
}
if (subsys) {
subsys->namespaces[nsid] = ns;
subsys->namespaces[nsid] = ns;
ns->id_ns.endgid = cpu_to_le16(0x1);
ns->id_ns_ind.endgrpid = cpu_to_le16(0x1);
if (ns->params.detached) {
return;
}
if (ns->params.shared) {
for (i = 0; i < ARRAY_SIZE(subsys->ctrls); i++) {
NvmeCtrl *ctrl = subsys->ctrls[i];
if (ctrl && ctrl != SUBSYS_SLOT_RSVD) {
nvme_attach_ns(ctrl, ns);
}
}
return;
}
}
nvme_attach_ns(n, ns);
ns->id_ns.endgid = cpu_to_le16(0x1);
ns->id_ns_ind.endgrpid = cpu_to_le16(0x1);
}
static const Property nvme_ns_props[] = {
+10 -1
View File
@@ -237,7 +237,6 @@ typedef struct NvmeNamespace {
NvmeLBAF lbaf;
unsigned int nlbaf;
size_t lbasz;
const uint32_t *iocs;
uint8_t csi;
uint16_t status;
int attached;
@@ -539,12 +538,14 @@ typedef struct NvmeParams {
bool auto_transition_zones;
bool legacy_cmb;
bool ioeventfd;
bool dbcs;
uint16_t sriov_max_vfs;
uint16_t sriov_vq_flexible;
uint16_t sriov_vi_flexible;
uint32_t sriov_max_vq_per_vf;
uint32_t sriov_max_vi_per_vf;
bool msix_exclusive_bar;
bool ocp;
struct {
bool mem;
@@ -583,6 +584,14 @@ typedef struct NvmeCtrl {
uint64_t dbbuf_eis;
bool dbbuf_enabled;
struct {
uint32_t acs[256];
struct {
uint32_t nvm[256];
uint32_t zoned[256];
} iocs;
} cse;
struct {
MemoryRegion mem;
uint8_t *buf;
+55 -8
View File
@@ -142,9 +142,9 @@ enum NvmeCapMask {
((cap) |= (uint64_t)((val) & CAP_CMBS_MASK) << CAP_CMBS_SHIFT)
enum NvmeCapCss {
NVME_CAP_CSS_NVM = 1 << 0,
NVME_CAP_CSS_CSI_SUPP = 1 << 6,
NVME_CAP_CSS_ADMIN_ONLY = 1 << 7,
NVME_CAP_CSS_NCSS = 1 << 0,
NVME_CAP_CSS_IOCSS = 1 << 6,
NVME_CAP_CSS_NOIOCSS = 1 << 7,
};
enum NvmeCcShift {
@@ -177,7 +177,7 @@ enum NvmeCcMask {
enum NvmeCcCss {
NVME_CC_CSS_NVM = 0x0,
NVME_CC_CSS_CSI = 0x6,
NVME_CC_CSS_ALL = 0x6,
NVME_CC_CSS_ADMIN_ONLY = 0x7,
};
@@ -906,8 +906,7 @@ enum NvmeStatusCodes {
NVME_SGL_DESCR_TYPE_INVALID = 0x0011,
NVME_INVALID_USE_OF_CMB = 0x0012,
NVME_INVALID_PRP_OFFSET = 0x0013,
NVME_CMD_SET_CMB_REJECTED = 0x002b,
NVME_INVALID_CMD_SET = 0x002c,
NVME_COMMAND_INTERRUPTED = 0x0021,
NVME_FDP_DISABLED = 0x0029,
NVME_INVALID_PHID_LIST = 0x002a,
NVME_LBA_RANGE = 0x0080,
@@ -940,6 +939,10 @@ enum NvmeStatusCodes {
NVME_INVALID_SEC_CTRL_STATE = 0x0120,
NVME_INVALID_NUM_RESOURCES = 0x0121,
NVME_INVALID_RESOURCE_ID = 0x0122,
NVME_IOCS_NOT_SUPPORTED = 0x0129,
NVME_IOCS_NOT_ENABLED = 0x012a,
NVME_IOCS_COMBINATION_REJECTED = 0x012b,
NVME_INVALID_IOCS = 0x012c,
NVME_CONFLICTING_ATTRS = 0x0180,
NVME_INVALID_PROT_INFO = 0x0181,
NVME_WRITE_TO_RO = 0x0182,
@@ -1015,6 +1018,40 @@ typedef struct QEMU_PACKED NvmeSmartLog {
uint8_t reserved2[320];
} NvmeSmartLog;
typedef struct QEMU_PACKED NvmeSmartLogExtended {
uint64_t physical_media_units_written[2];
uint64_t physical_media_units_read[2];
uint64_t bad_user_blocks;
uint64_t bad_system_nand_blocks;
uint64_t xor_recovery_count;
uint64_t uncorrectable_read_error_count;
uint64_t soft_ecc_error_count;
uint64_t end2end_correction_counts;
uint8_t system_data_percent_used;
uint8_t refresh_counts[7];
uint64_t user_data_erase_counts;
uint16_t thermal_throttling_stat_and_count;
uint16_t dssd_spec_version[3];
uint64_t pcie_correctable_error_count;
uint32_t incomplete_shutdowns;
uint32_t rsvd116;
uint8_t percent_free_blocks;
uint8_t rsvd121[7];
uint16_t capacity_health;
uint8_t nvme_errata_ver;
uint8_t rsvd131[5];
uint64_t unaligned_io;
uint64_t security_ver_num;
uint64_t total_nuse;
uint64_t plp_start_count[2];
uint64_t endurance_estimate[2];
uint64_t pcie_retraining_count;
uint64_t power_state_change_count;
uint8_t rsvd208[286];
uint16_t log_page_version;
uint64_t log_page_guid[2];
} NvmeSmartLogExtended;
#define NVME_SMART_WARN_MAX 6
enum NvmeSmartWarn {
NVME_SMART_SPARE = 1 << 0,
@@ -1052,6 +1089,12 @@ enum NvmeLogIdentifier {
NVME_LOG_FDP_RUH_USAGE = 0x21,
NVME_LOG_FDP_STATS = 0x22,
NVME_LOG_FDP_EVENTS = 0x23,
NVME_LOG_VENDOR_START = 0xc0,
NVME_LOG_VENDOR_END = 0xff,
};
enum NvmeOcpLogIdentifier {
NVME_OCP_EXTENDED_SMART_INFO = 0xc0,
};
typedef struct QEMU_PACKED NvmePSD {
@@ -1167,6 +1210,8 @@ typedef struct NvmeIdCtrlZoned {
uint8_t rsvd1[4095];
} NvmeIdCtrlZoned;
#define NVME_ID_CTRL_NVM_DMRL_MAX 255
typedef struct NvmeIdCtrlNvm {
uint8_t vsl;
uint8_t wzsl;
@@ -1192,9 +1237,10 @@ enum NvmeIdCtrlOacs {
NVME_OACS_SECURITY = 1 << 0,
NVME_OACS_FORMAT = 1 << 1,
NVME_OACS_FW = 1 << 2,
NVME_OACS_NS_MGMT = 1 << 3,
NVME_OACS_NMS = 1 << 3,
NVME_OACS_DIRECTIVES = 1 << 5,
NVME_OACS_DBBUF = 1 << 8,
NVME_OACS_VMS = 1 << 7,
NVME_OACS_DBCS = 1 << 8,
};
enum NvmeIdCtrlOncs {
@@ -1899,6 +1945,7 @@ static inline void _nvme_check_size(void)
QEMU_BUILD_BUG_ON(sizeof(NvmeErrorLog) != 64);
QEMU_BUILD_BUG_ON(sizeof(NvmeFwSlotInfoLog) != 512);
QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLog) != 512);
QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLogExtended) != 512);
QEMU_BUILD_BUG_ON(sizeof(NvmeEffectsLog) != 4096);
QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) != 4096);
QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrlZoned) != 4096);