diff --git a/include/block/nvme.h b/include/block/nvme.h
index f82b5ffc2c1d..95ffe4412679 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -922,6 +922,19 @@ typedef struct NvmeEffectsLog {
     uint8_t     resv[2048];
 } NvmeEffectsLog;
 
+typedef struct NvmeTelemetry {
+    uint8_t     lid;
+    uint8_t     rsvd1[4];
+    uint8_t     ieee[3];
+    uint16_t    tda1lb;
+    uint16_t    tda2lb;
+    uint16_t    tda3lb;
+    uint8_t     rsvd14[368];
+    uint8_t     tda;
+    uint8_t     tdgn;
+    uint8_t     ri[128];
+} NvmeTelemetry;
+
 enum {
     NVME_CMD_EFF_CSUPP      = 1 << 0,
     NVME_CMD_EFF_LBCC       = 1 << 1,
@@ -937,6 +950,8 @@ enum NvmeLogIdentifier {
     NVME_LOG_SMART_INFO     = 0x02,
     NVME_LOG_FW_SLOT_INFO   = 0x03,
     NVME_LOG_CMD_EFFECTS    = 0x05,
+    NVME_LOG_TEL_HOST_INIT  = 0x07,
+    NVME_LOG_TEL_CTRL_INIT  = 0x08,
 };
 
 typedef struct QEMU_PACKED NvmePSD {
@@ -1067,9 +1082,10 @@ enum NvmeIdCtrlFrmw {
 };
 
 enum NvmeIdCtrlLpa {
-    NVME_LPA_NS_SMART = 1 << 0,
-    NVME_LPA_CSE      = 1 << 1,
-    NVME_LPA_EXTENDED = 1 << 2,
+    NVME_LPA_NS_SMART   = 1 << 0,
+    NVME_LPA_CSE        = 1 << 1,
+    NVME_LPA_EXTENDED   = 1 << 2,
+    NVME_LPA_TELEMETRY  = 1 << 3,
 };
 
 enum NvmeIdCtrlCmic {
@@ -1395,5 +1411,6 @@ static inline void _nvme_check_size(void)
     QEMU_BUILD_BUG_ON(sizeof(NvmeSglDescriptor) != 16);
     QEMU_BUILD_BUG_ON(sizeof(NvmeIdNsDescr) != 4);
     QEMU_BUILD_BUG_ON(sizeof(NvmeZoneDescr) != 64);
+    QEMU_BUILD_BUG_ON(sizeof(NvmeTelemetry) != 512);
 }
 #endif
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 547a3073ef1b..01b92a6f66c8 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2908,6 +2908,33 @@ static uint16_t nvme_cmd_effects(NvmeCtrl *n, uint8_t csi, uint32_t buf_len,
                     DMA_DIRECTION_FROM_DEVICE, req);
 }
 
+static uint16_t nvme_telemetry(NvmeCtrl *n, uint8_t lid, uint32_t buf_len,
+                               uint64_t off, NvmeRequest *req)
+{
+    NvmeTelemetry telemetry = {
+        .lid     = lid,
+        .ieee[0] = 0x00,
+        .ieee[1] = 0x54,
+        .ieee[2] = 0x52,
+    };
+
+    uint32_t trans_len;
+
+    if (buf_len & 0x1ff || off & 0x1ff) {
+        trace_pci_nvme_telemetry_log_invalid(buf_len, off);
+        return NVME_INVALID_FIELD | NVME_DNR;
+    }
+
+    if (off >= sizeof(telemetry)) {
+        return NVME_INVALID_FIELD | NVME_DNR;
+    }
+
+    trans_len = MIN(sizeof(telemetry) - off, buf_len);
+
+    return nvme_dma(n, (uint8_t *)&telemetry + off, trans_len,
+                    DMA_DIRECTION_FROM_DEVICE, req);
+}
+
 static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req)
 {
     NvmeCmd *cmd = &req->cmd;
@@ -2954,6 +2981,9 @@ static uint16_t nvme_get_log(NvmeCtrl *n, NvmeRequest *req)
         return nvme_fw_log_info(n, len, off, req);
     case NVME_LOG_CMD_EFFECTS:
         return nvme_cmd_effects(n, csi, len, off, req);
+    case NVME_LOG_TEL_HOST_INIT:
+    case NVME_LOG_TEL_CTRL_INIT:
+        return nvme_telemetry(n, lid, len, off, req);
     default:
         trace_pci_nvme_err_invalid_log_page(nvme_cid(req), lid);
         return NVME_INVALID_FIELD | NVME_DNR;
@@ -4707,7 +4737,8 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice *pci_dev)
     id->acl = 3;
     id->aerl = n->params.aerl;
     id->frmw = (NVME_NUM_FW_SLOTS << 1) | NVME_FRMW_SLOT1_RO;
-    id->lpa = NVME_LPA_NS_SMART | NVME_LPA_CSE | NVME_LPA_EXTENDED;
+    id->lpa = NVME_LPA_NS_SMART | NVME_LPA_CSE | NVME_LPA_EXTENDED |
+        NVME_LPA_TELEMETRY;
 
     /* recommended default value (~70 C) */
     id->wctemp = cpu_to_le16(NVME_TEMPERATURE_WARNING);
diff --git a/hw/block/trace-events b/hw/block/trace-events
index b6e972d733a6..500d991a0a14 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -110,6 +110,7 @@ pci_nvme_set_descriptor_extension(uint64_t slba, uint32_t zone_idx) "set zone de
 pci_nvme_zd_extension_set(uint32_t zone_idx) "set descriptor extension for zone_idx=%"PRIu32""
 pci_nvme_clear_ns_close(uint32_t state, uint64_t slba) "zone state=%"PRIu32", slba=%"PRIu64" transitioned to Closed state"
 pci_nvme_clear_ns_reset(uint32_t state, uint64_t slba) "zone state=%"PRIu32", slba=%"PRIu64" transitioned to Empty state"
+pci_nvme_telemetry_log_invalid(size_t len, uint64_t offset) "len %zu offset %"PRIu64""
 
 # nvme traces for error conditions
 pci_nvme_err_mdts(uint16_t cid, size_t len) "cid %"PRIu16" len %zu"
