2 * QEMU NVM Express Virtual Namespace
4 * Copyright (c) 2019 CNEX Labs
5 * Copyright (c) 2020 Samsung Electronics
8 * Klaus Jensen <k.jensen@samsung.com>
10 * This work is licensed under the terms of the GNU GPL, version 2. See the
11 * COPYING file in the top-level directory.
15 #include "qemu/osdep.h"
16 #include "qemu/units.h"
17 #include "qemu/cutils.h"
19 #include "hw/block/block.h"
20 #include "hw/pci/pci.h"
21 #include "sysemu/sysemu.h"
22 #include "sysemu/block-backend.h"
23 #include "qapi/error.h"
25 #include "hw/qdev-properties.h"
26 #include "hw/qdev-core.h"
31 static void nvme_ns_init(NvmeNamespace
*ns
)
33 NvmeIdNs
*id_ns
= &ns
->id_ns
;
34 int lba_index
= NVME_ID_NS_FLBAS_INDEX(ns
->id_ns
.flbas
);
36 if (blk_get_flags(ns
->blkconf
.blk
) & BDRV_O_UNMAP
) {
37 ns
->id_ns
.dlfeat
= 0x9;
40 id_ns
->lbaf
[lba_index
].ds
= 31 - clz32(ns
->blkconf
.logical_block_size
);
42 id_ns
->nsze
= cpu_to_le64(nvme_ns_nlbas(ns
));
44 /* no thin provisioning */
45 id_ns
->ncap
= id_ns
->nsze
;
46 id_ns
->nuse
= id_ns
->ncap
;
49 static int nvme_ns_init_blk(NvmeCtrl
*n
, NvmeNamespace
*ns
, Error
**errp
)
51 if (!blkconf_blocksizes(&ns
->blkconf
, errp
)) {
55 if (!blkconf_apply_backend_options(&ns
->blkconf
,
56 blk_is_read_only(ns
->blkconf
.blk
),
61 ns
->size
= blk_getlength(ns
->blkconf
.blk
);
63 error_setg_errno(errp
, -ns
->size
, "could not get blockdev size");
67 if (blk_enable_write_cache(ns
->blkconf
.blk
)) {
68 n
->features
.vwc
= 0x1;
74 static int nvme_ns_check_constraints(NvmeNamespace
*ns
, Error
**errp
)
76 if (!ns
->blkconf
.blk
) {
77 error_setg(errp
, "block backend not configured");
84 int nvme_ns_setup(NvmeCtrl
*n
, NvmeNamespace
*ns
, Error
**errp
)
86 if (nvme_ns_check_constraints(ns
, errp
)) {
90 if (nvme_ns_init_blk(n
, ns
, errp
)) {
95 if (nvme_register_namespace(n
, ns
, errp
)) {
102 void nvme_ns_drain(NvmeNamespace
*ns
)
104 blk_drain(ns
->blkconf
.blk
);
107 void nvme_ns_flush(NvmeNamespace
*ns
)
109 blk_flush(ns
->blkconf
.blk
);
112 static void nvme_ns_realize(DeviceState
*dev
, Error
**errp
)
114 NvmeNamespace
*ns
= NVME_NS(dev
);
115 BusState
*s
= qdev_get_parent_bus(dev
);
116 NvmeCtrl
*n
= NVME(s
->parent
);
117 Error
*local_err
= NULL
;
119 if (nvme_ns_setup(n
, ns
, &local_err
)) {
120 error_propagate_prepend(errp
, local_err
,
121 "could not setup namespace: ");
126 static Property nvme_ns_props
[] = {
127 DEFINE_BLOCK_PROPERTIES(NvmeNamespace
, blkconf
),
128 DEFINE_PROP_UINT32("nsid", NvmeNamespace
, params
.nsid
, 0),
129 DEFINE_PROP_END_OF_LIST(),
132 static void nvme_ns_class_init(ObjectClass
*oc
, void *data
)
134 DeviceClass
*dc
= DEVICE_CLASS(oc
);
136 set_bit(DEVICE_CATEGORY_STORAGE
, dc
->categories
);
138 dc
->bus_type
= TYPE_NVME_BUS
;
139 dc
->realize
= nvme_ns_realize
;
140 device_class_set_props(dc
, nvme_ns_props
);
141 dc
->desc
= "Virtual NVMe namespace";
144 static void nvme_ns_instance_init(Object
*obj
)
146 NvmeNamespace
*ns
= NVME_NS(obj
);
147 char *bootindex
= g_strdup_printf("/namespace@%d,0", ns
->params
.nsid
);
149 device_add_bootindex_property(obj
, &ns
->bootindex
, "bootindex",
150 bootindex
, DEVICE(obj
));
155 static const TypeInfo nvme_ns_info
= {
156 .name
= TYPE_NVME_NS
,
157 .parent
= TYPE_DEVICE
,
158 .class_init
= nvme_ns_class_init
,
159 .instance_size
= sizeof(NvmeNamespace
),
160 .instance_init
= nvme_ns_instance_init
,
163 static void nvme_ns_register_types(void)
165 type_register_static(&nvme_ns_info
);
168 type_init(nvme_ns_register_types
)