diff --git a/block.c b/block.c
index 5944124845..f0390196f2 100644
--- a/block.c
+++ b/block.c
@@ -1968,11 +1968,12 @@ char *bdrv_perm_names(uint64_t perm)
         uint64_t perm;
         const char *name;
     } permissions[] = {
-        { BLK_PERM_CONSISTENT_READ, "consistent read" },
-        { BLK_PERM_WRITE,           "write" },
-        { BLK_PERM_WRITE_UNCHANGED, "write unchanged" },
-        { BLK_PERM_RESIZE,          "resize" },
-        { BLK_PERM_GRAPH_MOD,       "change children" },
+        { BLK_PERM_CONSISTENT_READ,  "consistent read" },
+        { BLK_PERM_WRITE,            "write" },
+        { BLK_PERM_WRITE_UNCHANGED,  "write unchanged" },
+        { BLK_PERM_RESIZE,           "resize" },
+        { BLK_PERM_GRAPH_MOD,        "change children" },
+        { BLK_PERM_SUPPORT_HM_ZONED, "attach hm-zoned" },
         { 0, NULL }
     };
 
@@ -4678,6 +4679,21 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
     *nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
 }
 
+BdrvZonedModel bdrv_get_zoned_model(BlockDriverState *bs)
+{
+    return bs->bl.zoned_model;
+}
+
+bool bdrv_is_hm_zoned(BlockDriverState *bs)
+{
+    /*
+     * Host Aware zone devices are supposed to be able to work
+     * just like regular block devices. Thus, we only consider
+     * Host Managed devices to be zoned here.
+     */
+    return bdrv_get_zoned_model(bs) == BDRV_ZONED_MODEL_HM;
+}
+
 bool bdrv_is_sg(BlockDriverState *bs)
 {
     return bs->sg;
@@ -4871,11 +4887,12 @@ static void xdbg_graph_add_edge(XDbgBlockGraphConstructor *gr, void *parent,
     } PermissionMap;
 
     static const PermissionMap permissions[] = {
-        { BLK_PERM_CONSISTENT_READ, BLOCK_PERMISSION_CONSISTENT_READ },
-        { BLK_PERM_WRITE,           BLOCK_PERMISSION_WRITE },
-        { BLK_PERM_WRITE_UNCHANGED, BLOCK_PERMISSION_WRITE_UNCHANGED },
-        { BLK_PERM_RESIZE,          BLOCK_PERMISSION_RESIZE },
-        { BLK_PERM_GRAPH_MOD,       BLOCK_PERMISSION_GRAPH_MOD },
+        { BLK_PERM_CONSISTENT_READ,  BLOCK_PERMISSION_CONSISTENT_READ },
+        { BLK_PERM_WRITE,            BLOCK_PERMISSION_WRITE },
+        { BLK_PERM_WRITE_UNCHANGED,  BLOCK_PERMISSION_WRITE_UNCHANGED },
+        { BLK_PERM_RESIZE,           BLOCK_PERMISSION_RESIZE },
+        { BLK_PERM_GRAPH_MOD,        BLOCK_PERMISSION_GRAPH_MOD },
+        { BLK_PERM_SUPPORT_HM_ZONED, BLOCK_PERMISSION_SUPPORT_HM_ZONED },
         { 0, 0 }
     };
     const PermissionMap *p;
diff --git a/include/block/block.h b/include/block/block.h
index 124ad40809..46cfa5bfa9 100644
--- a/include/block/block.h
+++ b/include/block/block.h
@@ -271,18 +271,33 @@ enum {
      */
     BLK_PERM_GRAPH_MOD          = 0x10,
 
-    BLK_PERM_ALL                = 0x1f,
+    /**
+     * This permission is required to open host-managed zoned block devices.
+     */
+    BLK_PERM_SUPPORT_HM_ZONED   = 0x20,
+
+    BLK_PERM_ALL                = 0x3f,
 
     DEFAULT_PERM_PASSTHROUGH    = BLK_PERM_CONSISTENT_READ
                                  | BLK_PERM_WRITE
                                  | BLK_PERM_WRITE_UNCHANGED
-                                 | BLK_PERM_RESIZE,
+                                 | BLK_PERM_RESIZE
+                                 | BLK_PERM_SUPPORT_HM_ZONED,
 
     DEFAULT_PERM_UNCHANGED      = BLK_PERM_ALL & ~DEFAULT_PERM_PASSTHROUGH,
 };
 
 char *bdrv_perm_names(uint64_t perm);
 
+/*
+ * Known zoned device models.
+ */
+typedef enum {
+    BDRV_ZONED_MODEL_NONE, /* Regular block device */
+    BDRV_ZONED_MODEL_HA,   /* Host-aware zoned block device */
+    BDRV_ZONED_MODEL_HM,   /* Host-managed zoned block device */
+} BdrvZonedModel;
+
 /* disk I/O throttling */
 void bdrv_init(void);
 void bdrv_init_with_whitelist(void);
@@ -359,6 +374,8 @@ int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
 BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts,
                                BlockDriverState *in_bs, Error **errp);
 void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
+BdrvZonedModel bdrv_get_zoned_model(BlockDriverState *bs);
+bool bdrv_is_hm_zoned(BlockDriverState *bs);
 void bdrv_refresh_limits(BlockDriverState *bs, Error **errp);
 int bdrv_commit(BlockDriverState *bs);
 int bdrv_change_backing_file(BlockDriverState *bs,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 0422acdf1c..928cbae9a5 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -635,6 +635,9 @@ typedef struct BlockLimits {
 
     /* maximum number of iovec elements */
     int max_iov;
+
+    /* Zoned device model. Zero value indicates a regular block device */
+    BdrvZonedModel zoned_model;
 } BlockLimits;
 
 typedef struct BdrvOpBlocker BdrvOpBlocker;
diff --git a/qapi/block-core.json b/qapi/block-core.json
index e6edd641f1..860a8e16e5 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1803,11 +1803,14 @@
 # @graph-mod: This permission is required to change the node that this
 #             BdrvChild points to.
 #
+# @support-hm-zoned: This permission is required to attach host-managed
+#                    zoned devices.
+#
 # Since: 4.0
 ##
   { 'enum': 'BlockPermission',
     'data': [ 'consistent-read', 'write', 'write-unchanged', 'resize',
-              'graph-mod' ] }
+              'graph-mod', 'support-hm-zoned' ] }
 ##
 # @XDbgBlockGraphEdge:
 #
