hw/block/nvme: support the get/set features select and save fields

Since the device does not have any persistent state storage, no
features are "saveable" and setting the Save (SV) field in any Set
Features command will result in a Feature Identifier Not Saveable status
code.

Similarly, if the Select (SEL) field is set to request saved values, the
devices will (as it should) return the default values instead.

Since this also introduces "Supported Capabilities", the nsid field is
now also checked for validity wrt. the feature being get/set'ed.

Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
Reviewed-by: Dmitry Fomichev <dmitry.fomichev@wdc.com>
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Message-Id: <20200706061303.246057-13-its@irrelevant.dk>
This commit is contained in:
Klaus Jensen 2020-07-06 08:12:57 +02:00
parent 1302e48e49
commit 7c46310d29
3 changed files with 119 additions and 15 deletions

View file

@ -664,7 +664,7 @@ enum NvmeStatusCodes {
NVME_INVALID_QUEUE_DEL = 0x010c,
NVME_FID_NOT_SAVEABLE = 0x010d,
NVME_FEAT_NOT_CHANGEABLE = 0x010e,
NVME_FID_NOT_NSID_SPEC = 0x010f,
NVME_FEAT_NOT_NS_SPEC = 0x010f,
NVME_FW_REQ_SUSYSTEM_RESET = 0x0110,
NVME_CONFLICTING_ATTRS = 0x0180,
NVME_INVALID_PROT_INFO = 0x0181,
@ -908,9 +908,32 @@ enum NvmeFeatureIds {
NVME_FID_MAX = 0x100,
};
typedef enum NvmeFeatureCap {
NVME_FEAT_CAP_SAVE = 1 << 0,
NVME_FEAT_CAP_NS = 1 << 1,
NVME_FEAT_CAP_CHANGE = 1 << 2,
} NvmeFeatureCap;
typedef enum NvmeGetFeatureSelect {
NVME_GETFEAT_SELECT_CURRENT = 0x0,
NVME_GETFEAT_SELECT_DEFAULT = 0x1,
NVME_GETFEAT_SELECT_SAVED = 0x2,
NVME_GETFEAT_SELECT_CAP = 0x3,
} NvmeGetFeatureSelect;
#define NVME_GETSETFEAT_FID_MASK 0xff
#define NVME_GETSETFEAT_FID(dw10) (dw10 & NVME_GETSETFEAT_FID_MASK)
#define NVME_GETFEAT_SELECT_SHIFT 8
#define NVME_GETFEAT_SELECT_MASK 0x7
#define NVME_GETFEAT_SELECT(dw10) \
((dw10 >> NVME_GETFEAT_SELECT_SHIFT) & NVME_GETFEAT_SELECT_MASK)
#define NVME_SETFEAT_SAVE_SHIFT 31
#define NVME_SETFEAT_SAVE_MASK 0x1
#define NVME_SETFEAT_SAVE(dw10) \
((dw10 >> NVME_SETFEAT_SAVE_SHIFT) & NVME_SETFEAT_SAVE_MASK)
typedef struct QEMU_PACKED NvmeRangeType {
uint8_t type;
uint8_t attributes;
@ -927,6 +950,8 @@ typedef struct QEMU_PACKED NvmeLBAF {
uint8_t rp;
} NvmeLBAF;
#define NVME_NSID_BROADCAST 0xffffffff
typedef struct QEMU_PACKED NvmeIdNs {
uint64_t nsze;
uint64_t ncap;