diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
index 9a06f95a3444..f08d0a053051 100644
--- a/docs/system/riscv/virt.rst
+++ b/docs/system/riscv/virt.rst
@@ -116,6 +116,17 @@ The following machine-specific options are supported:
   having AIA IMSIC (i.e. "aia=aplic-imsic" selected). When not specified,
   the default number of per-HART VS-level AIA IMSIC pages is 0.
 
+- strict-dt=[on|off]
+
+  Older firmwares and OS kernels which use deprecated device tree properties
+  or are missing support for new properties may not be tolerant of fully
+  compliant device trees. When divergence to the bindings specifications is
+  harmless for new firmwares and OS kernels which are compliant, then it's
+  considered better to also continue supporting the old firmwares and OS
+  kernels by generating non-compliant device trees, and doing so is the default
+  behavior. This option may be enabled in order to force QEMU to only generate
+  compliant device trees.
+
 Running Linux kernel
 --------------------
 
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index cef41c150aaf..6a6e73b96362 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -552,6 +552,9 @@ static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr base_addr,
                           FDT_IMSIC_INT_CELLS);
     qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller", NULL, 0);
     qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller", NULL, 0);
+    if (s->strict_dt) {
+        qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#msi-cells", 0);
+    }
     qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
                      imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
     qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
@@ -650,15 +653,18 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int socket,
         qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation",
                                aplic_child_phandle, 0x1,
                                VIRT_IRQCHIP_NUM_SOURCES);
-        /*
-         * DEPRECATED_9.1: Compat property kept temporarily
-         * to allow old firmwares to work with AIA. Do *not*
-         * use 'riscv,delegate' in new code: use
-         * 'riscv,delegation' instead.
-         */
-        qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
-                               aplic_child_phandle, 0x1,
-                               VIRT_IRQCHIP_NUM_SOURCES);
+
+        if (!s->strict_dt) {
+            /*
+             * DEPRECATED_9.1: Compat property kept temporarily
+             * to allow old firmwares to work with AIA. Do *not*
+             * use 'riscv,delegate' in new code: use
+             * 'riscv,delegation' instead.
+             */
+            qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
+                                   aplic_child_phandle, 0x1,
+                                   VIRT_IRQCHIP_NUM_SOURCES);
+        }
     }
 
     riscv_socket_fdt_write_id(ms, aplic_name, socket);
@@ -1732,6 +1738,20 @@ static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
     visit_type_OnOffAuto(v, name, &s->acpi, errp);
 }
 
+static bool virt_get_strict_dt(Object *obj, Error **errp)
+{
+    RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
+
+    return s->strict_dt;
+}
+
+static void virt_set_strict_dt(Object *obj, bool value, Error **errp)
+{
+    RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
+
+    s->strict_dt = value;
+}
+
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
                                                         DeviceState *dev)
 {
@@ -1822,6 +1842,11 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
                               NULL, NULL);
     object_class_property_set_description(oc, "acpi",
                                           "Enable ACPI");
+
+    object_class_property_add_bool(oc, "strict-dt",
+                                   virt_get_strict_dt, virt_set_strict_dt);
+    object_class_property_set_description(oc, "strict-dt",
+        "Set to 'on' to generate a fully-compliant DT without deprecated properties");
 }
 
 static const TypeInfo virt_machine_typeinfo = {
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index c0dc41ff9a1a..c3b4c000b80a 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -62,6 +62,7 @@ struct RISCVVirtState {
     OnOffAuto acpi;
     const MemMapEntry *memmap;
     struct GPEXHost *gpex_host;
+    bool strict_dt;
 };
 
 enum {
