qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
	"Jonathan Cameron" <Jonathan.Cameron@huawei.com>,
	"Igor Mammedov" <imammedo@redhat.com>,
	"Ani Sinha" <anisinha@redhat.com>,
	"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Daniel P. Berrangé" <berrange@redhat.com>,
	"Eduardo Habkost" <eduardo@habkost.net>,
	"Eric Blake" <eblake@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>
Subject: [PULL 33/46] hw/acpi: Generic Port Affinity Structure support
Date: Tue, 4 Jun 2024 15:07:54 -0400	[thread overview]
Message-ID: <b2366d461b9133880913d84742f120d14222a6e6.1717527933.git.mst@redhat.com> (raw)
In-Reply-To: <cover.1717527933.git.mst@redhat.com>

From: Jonathan Cameron <Jonathan.Cameron@huawei.com>

These are very similar to the recently added Generic Initiators
but instead of representing an initiator of memory traffic they
represent an edge point beyond which may lie either targets or
initiators.  Here we add these ports such that they may
be targets of hmat_lb records to describe the latency and
bandwidth from host side initiators to the port.  A descoverable
mechanism such as UEFI CDAT read from CXL devices and switches
is used to discover the remainder fo the path and the OS can build
up full latency and bandwidth numbers as need for work and data
placement decisions.

Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Message-Id: <20240524100507.32106-4-Jonathan.Cameron@huawei.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
 qapi/qom.json                            |  35 ++++++
 include/hw/acpi/acpi_generic_initiator.h |  18 ++-
 include/hw/pci/pci_bridge.h              |   1 +
 hw/acpi/acpi_generic_initiator.c         | 145 +++++++++++++++++------
 hw/pci-bridge/pci_expander_bridge.c      |   1 -
 5 files changed, 160 insertions(+), 40 deletions(-)

diff --git a/qapi/qom.json b/qapi/qom.json
index 38dde6d785..9d1d86bdad 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -826,6 +826,39 @@
   'data': { 'pci-dev': 'str',
             'node': 'uint32' } }
 
+
+##
+# @AcpiGenericPortProperties:
+#
+# Properties for acpi-generic-port objects.
+#
+# @pci-bus: QOM path of the PCI bus of the hostbridge associated with
+#     this SRAT Generic Port Affinity Structure.  This is the same as
+#     the bus parameter for the root ports attached to this host bridge.
+#     The resulting SRAT Generic Port Affinity Structure will refer to
+#     the ACPI object in DSDT that represents the host bridge (e.g.
+#     ACPI0016 for CXL host bridges.) See ACPI 6.5 Section 5.2.16.7 for
+#     more information.
+#
+# @node: Similar to a NUMA node ID, but instead of providing a reference
+#     point used for defining NUMA distances and access characteristics
+#     to memory or from an initiator (e.g. CPU), this node defines the
+#     boundary point between non-discoverable system buses which must be
+#     described by firmware, and a discoverable bus.  NUMA distances
+#     and access characteristics are defined to and from that point.
+#     For system software to establish full initiator to target
+#     characteristics this information must be combined with information
+#     retrieved from the discoverable part of the path.  An example would
+#     use CDAT (see UEFI.org) information read from devices and switches
+#     in conjunction with link characteristics read from PCIe
+#     Configuration space.
+#
+# Since: 9.1
+##
+{ 'struct': 'AcpiGenericPortProperties',
+  'data': { 'pci-bus': 'str',
+            'node': 'uint32' } }
+
 ##
 # @RngProperties:
 #
@@ -953,6 +986,7 @@
 { 'enum': 'ObjectType',
   'data': [
     'acpi-generic-initiator',
+    'acpi-generic-port',
     'authz-list',
     'authz-listfile',
     'authz-pam',
@@ -1025,6 +1059,7 @@
   'discriminator': 'qom-type',
   'data': {
       'acpi-generic-initiator':     'AcpiGenericInitiatorProperties',
+      'acpi-generic-port':          'AcpiGenericPortProperties',
       'authz-list':                 'AuthZListProperties',
       'authz-listfile':             'AuthZListFileProperties',
       'authz-pam':                  'AuthZPAMProperties',
diff --git a/include/hw/acpi/acpi_generic_initiator.h b/include/hw/acpi/acpi_generic_initiator.h
index dd4be19c8f..1a899af30f 100644
--- a/include/hw/acpi/acpi_generic_initiator.h
+++ b/include/hw/acpi/acpi_generic_initiator.h
@@ -30,6 +30,12 @@ typedef struct AcpiGenericInitiator {
     AcpiGenericNode parent;
 } AcpiGenericInitiator;
 
+#define TYPE_ACPI_GENERIC_PORT "acpi-generic-port"
+
+typedef struct AcpiGenericPort {
+    AcpiGenericInitiator parent;
+} AcpiGenericPort;
+
 /*
  * ACPI 6.3:
  * Table 5-81 Flags – Generic Initiator Affinity Structure
@@ -49,8 +55,16 @@ typedef enum {
  * Table 5-80 Device Handle - PCI
  */
 typedef struct PCIDeviceHandle {
-    uint16_t segment;
-    uint16_t bdf;
+    union {
+        struct {
+            uint16_t segment;
+            uint16_t bdf;
+        };
+        struct {
+            uint64_t hid;
+            uint32_t uid;
+        };
+    };
 } PCIDeviceHandle;
 
 void build_srat_generic_pci_initiator(GArray *table_data);
diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
index 5cd452115a..5456e24883 100644
--- a/include/hw/pci/pci_bridge.h
+++ b/include/hw/pci/pci_bridge.h
@@ -102,6 +102,7 @@ typedef struct PXBPCIEDev {
     PXBDev parent_obj;
 } PXBPCIEDev;
 
+#define TYPE_PXB_CXL_BUS "pxb-cxl-bus"
 #define TYPE_PXB_DEV "pxb"
 OBJECT_DECLARE_SIMPLE_TYPE(PXBDev, PXB_DEV)
 
diff --git a/hw/acpi/acpi_generic_initiator.c b/hw/acpi/acpi_generic_initiator.c
index c054e0e27d..78b80dcf08 100644
--- a/hw/acpi/acpi_generic_initiator.c
+++ b/hw/acpi/acpi_generic_initiator.c
@@ -7,6 +7,7 @@
 #include "hw/acpi/acpi_generic_initiator.h"
 #include "hw/acpi/aml-build.h"
 #include "hw/boards.h"
+#include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_device.h"
 #include "qemu/error-report.h"
 
@@ -18,6 +19,10 @@ typedef struct AcpiGenericInitiatorClass {
      AcpiGenericNodeClass parent_class;
 } AcpiGenericInitiatorClass;
 
+typedef struct AcpiGenericPortClass {
+    AcpiGenericInitiatorClass parent;
+} AcpiGenericPortClass;
+
 OBJECT_DEFINE_ABSTRACT_TYPE(AcpiGenericNode, acpi_generic_node,
                             ACPI_GENERIC_NODE, OBJECT)
 
@@ -30,6 +35,13 @@ OBJECT_DEFINE_TYPE_WITH_INTERFACES(AcpiGenericInitiator, acpi_generic_initiator,
 
 OBJECT_DECLARE_SIMPLE_TYPE(AcpiGenericInitiator, ACPI_GENERIC_INITIATOR)
 
+OBJECT_DEFINE_TYPE_WITH_INTERFACES(AcpiGenericPort, acpi_generic_port,
+                   ACPI_GENERIC_PORT, ACPI_GENERIC_NODE,
+                   { TYPE_USER_CREATABLE },
+                   { NULL })
+
+OBJECT_DECLARE_SIMPLE_TYPE(AcpiGenericPort, ACPI_GENERIC_PORT)
+
 static void acpi_generic_node_init(Object *obj)
 {
     AcpiGenericNode *gn = ACPI_GENERIC_NODE(obj);
@@ -53,6 +65,14 @@ static void acpi_generic_initiator_finalize(Object *obj)
 {
 }
 
+static void acpi_generic_port_init(Object *obj)
+{
+}
+
+static void acpi_generic_port_finalize(Object *obj)
+{
+}
+
 static void acpi_generic_node_set_pci_device(Object *obj, const char *val,
                                              Error **errp)
 {
@@ -79,42 +99,61 @@ static void acpi_generic_node_set_node(Object *obj, Visitor *v,
     }
 
     gn->node = value;
-    ms->numa_state->nodes[gn->node].has_gi = true;
+    if (object_dynamic_cast(obj, TYPE_ACPI_GENERIC_INITIATOR)) {
+        ms->numa_state->nodes[gn->node].has_gi = true;
+    }
 }
 
 static void acpi_generic_node_class_init(ObjectClass *oc, void *data)
 {
-    object_class_property_add_str(oc, "pci-dev", NULL,
-        acpi_generic_node_set_pci_device);
     object_class_property_add(oc, "node", "int", NULL,
         acpi_generic_node_set_node, NULL, NULL);
 }
 
 static void acpi_generic_initiator_class_init(ObjectClass *oc, void *data)
 {
+    object_class_property_add_str(oc, "pci-dev", NULL,
+        acpi_generic_node_set_pci_device);
+}
+
+static void acpi_generic_port_class_init(ObjectClass *oc, void *data)
+{
+    /*
+     * Despite the ID representing a root bridge bus, same storage
+     * can be used.
+     */
+    object_class_property_add_str(oc, "pci-bus", NULL,
+        acpi_generic_node_set_pci_device);
 }
 
 /*
  * ACPI 6.3:
  * Table 5-78 Generic Initiator Affinity Structure
+ * ACPI 6.5:
+ * Table 5-67 Generic Port Affinity Structure
  */
 static void
-build_srat_generic_pci_initiator_affinity(GArray *table_data, int node,
-                                          PCIDeviceHandle *handle)
+build_srat_generic_node_affinity(GArray *table_data, int node,
+                                 PCIDeviceHandle *handle, bool gp, bool pci)
 {
-    uint8_t index;
-
-    build_append_int_noprefix(table_data, 5, 1);  /* Type */
+    build_append_int_noprefix(table_data, gp ? 6 : 5, 1);  /* Type */
     build_append_int_noprefix(table_data, 32, 1); /* Length */
     build_append_int_noprefix(table_data, 0, 1);  /* Reserved */
-    build_append_int_noprefix(table_data, 1, 1);  /* Device Handle Type: PCI */
+    /* Device Handle Type: PCI / ACPI */
+    build_append_int_noprefix(table_data, pci ? 1 : 0, 1);
     build_append_int_noprefix(table_data, node, 4);  /* Proximity Domain */
 
     /* Device Handle - PCI */
-    build_append_int_noprefix(table_data, handle->segment, 2);
-    build_append_int_noprefix(table_data, handle->bdf, 2);
-    for (index = 0; index < 12; index++) {
-        build_append_int_noprefix(table_data, 0, 1);
+    if (pci) {
+        /* Device Handle - PCI */
+        build_append_int_noprefix(table_data, handle->segment, 2);
+        build_append_int_noprefix(table_data, handle->bdf, 2);
+        build_append_int_noprefix(table_data, 0, 12);
+    } else {
+        /* Device Handle - ACPI */
+        build_append_int_noprefix(table_data, handle->hid, 8);
+        build_append_int_noprefix(table_data, handle->uid, 4);
+        build_append_int_noprefix(table_data, 0, 4);
     }
 
     build_append_int_noprefix(table_data, GEN_AFFINITY_ENABLED, 4); /* Flags */
@@ -127,37 +166,69 @@ static int build_all_acpi_generic_initiators(Object *obj, void *opaque)
     GArray *table_data = opaque;
     PCIDeviceHandle dev_handle;
     AcpiGenericNode *gn;
-    PCIDevice *pci_dev;
     Object *o;
 
-    if (!object_dynamic_cast(obj, TYPE_ACPI_GENERIC_INITIATOR)) {
+    if (!object_dynamic_cast(obj, TYPE_ACPI_GENERIC_NODE)) {
         return 0;
     }
 
     gn = ACPI_GENERIC_NODE(obj);
-    if (gn->node >= ms->numa_state->num_nodes) {
-        error_printf("%s: Specified node %d is invalid.\n",
-                     TYPE_ACPI_GENERIC_INITIATOR, gn->node);
-        exit(1);
+
+    if (object_dynamic_cast(OBJECT(gn), TYPE_ACPI_GENERIC_INITIATOR)) {
+        PCIDevice *pci_dev;
+
+        if (gn->node >= ms->numa_state->num_nodes) {
+            error_printf("%s: node %d is invalid.\n",
+                         TYPE_ACPI_GENERIC_INITIATOR, gn->node);
+            exit(1);
+        }
+
+        o = object_resolve_path_type(gn->pci_dev, TYPE_PCI_DEVICE, NULL);
+        if (!o) {
+            error_printf("%s: device must be a PCI device.\n",
+                         TYPE_ACPI_GENERIC_INITIATOR);
+            exit(1);
+        }
+        pci_dev = PCI_DEVICE(o);
+
+        dev_handle.segment = 0;
+        dev_handle.bdf = PCI_BUILD_BDF(pci_bus_num(pci_get_bus(pci_dev)),
+                                       pci_dev->devfn);
+        build_srat_generic_node_affinity(table_data,
+                                         gn->node, &dev_handle, false, true);
+
+        return 0;
+    } else { /* TYPE_ACPI_GENERIC_PORT */
+        PCIBus *bus;
+        const char *hid = "ACPI0016";
+
+        if (gn->node >= ms->numa_state->num_nodes) {
+            error_printf("%s: node %d is invalid.\n",
+                         TYPE_ACPI_GENERIC_PORT, gn->node);
+            exit(1);
+        }
+
+        o = object_resolve_path_type(gn->pci_dev, TYPE_PCI_BUS, NULL);
+        if (!o) {
+            error_printf("%s: device must be a PCI host bridge.\n",
+                         TYPE_ACPI_GENERIC_PORT);
+            exit(1);
+        }
+        bus = PCI_BUS(o);
+        /* Need to know if this is a PXB Bus so below an expander bridge */
+        if (!object_dynamic_cast(OBJECT(bus), TYPE_PXB_CXL_BUS)) {
+            error_printf("%s: device is not a bus below a host bridge.\n",
+                         TYPE_ACPI_GENERIC_PORT);
+            exit(1);
+        }
+        /* Copy without trailing NULL */
+        memcpy(&dev_handle.hid, hid, sizeof(dev_handle.hid));
+        dev_handle.uid = pci_bus_num(bus);
+        build_srat_generic_node_affinity(table_data,
+                                         gn->node, &dev_handle, true, false);
+
+        return 0;
     }
-
-    o = object_resolve_path_type(gn->pci_dev, TYPE_PCI_DEVICE, NULL);
-    if (!o) {
-        error_printf("%s: Specified device must be a PCI device.\n",
-                     TYPE_ACPI_GENERIC_INITIATOR);
-        exit(1);
-    }
-
-    pci_dev = PCI_DEVICE(o);
-
-    dev_handle.segment = 0;
-    dev_handle.bdf = PCI_BUILD_BDF(pci_bus_num(pci_get_bus(pci_dev)),
-                                   pci_dev->devfn);
-
-    build_srat_generic_pci_initiator_affinity(table_data,
-                                              gn->node, &dev_handle);
-
-    return 0;
 }
 
 void build_srat_generic_pci_initiator(GArray *table_data)
diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
index 0411ad31ea..f5431443b9 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -38,7 +38,6 @@ DECLARE_INSTANCE_CHECKER(PXBBus, PXB_BUS,
 DECLARE_INSTANCE_CHECKER(PXBBus, PXB_PCIE_BUS,
                          TYPE_PXB_PCIE_BUS)
 
-#define TYPE_PXB_CXL_BUS "pxb-cxl-bus"
 DECLARE_INSTANCE_CHECKER(PXBBus, PXB_CXL_BUS,
                          TYPE_PXB_CXL_BUS)
 
-- 
MST



  parent reply	other threads:[~2024-06-04 19:08 UTC|newest]

Thread overview: 60+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-04 19:05 [PULL 00/46] virtio: features,fixes Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 01/46] vhost: dirty log should be per backend type Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 02/46] vhost: Perform memory section dirty scans once per iteration Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 03/46] vhost-vdpa: check vhost_vdpa_set_vring_ready() return value Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 04/46] virtio-pci: Fix the use of an uninitialized irqfd Michael S. Tsirkin
2024-06-05  7:27   ` Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 05/46] virtio/virtio-pci: Handle extra notification data Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 06/46] virtio: Prevent creation of device using notification-data with ioeventfd Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 07/46] virtio-mmio: Handle extra notification data Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 08/46] virtio-ccw: " Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 09/46] vhost/vhost-user: Add VIRTIO_F_NOTIFICATION_DATA to vhost feature bits Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 10/46] Fix vhost user assertion when sending more than one fd Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 11/46] vhost-vsock: add VIRTIO_F_RING_PACKED to feature_bits Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 12/46] hw/virtio: Fix obtain the buffer id from the last descriptor Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 13/46] virtio-pci: only reset pm state during resetting Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 14/46] vhost-user-gpu: fix import of DMABUF Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 15/46] Revert "vhost-user: fix lost reconnect" Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 16/46] vhost-user: fix lost reconnect again Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 17/46] hw/cxl/mailbox: change CCI cmd set structure to be a member, not a reference Michael S. Tsirkin
2024-06-04 19:06 ` [PULL 18/46] hw/cxl/mailbox: interface to add CCI commands to an existing CCI Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 19/46] hw/cxl/cxl-mailbox-utils: Add dc_event_log_size field to output payload of identify memory device command Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 20/46] hw/cxl/cxl-mailbox-utils: Add dynamic capacity region representative and mailbox command support Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 21/46] include/hw/cxl/cxl_device: Rename mem_size as static_mem_size for type3 memory devices Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 22/46] hw/mem/cxl_type3: Add support to create DC regions to " Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 23/46] hw/mem/cxl-type3: Refactor ct3_build_cdat_entries_for_mr to take mr size instead of mr as argument Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 24/46] hw/mem/cxl_type3: Add host backend and address space handling for DC regions Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 25/46] hw/mem/cxl_type3: Add DC extent list representative and get DC extent list mailbox support Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 26/46] hw/cxl/cxl-mailbox-utils: Add mailbox commands to support add/release dynamic capacity response Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 27/46] hw/cxl/events: Add qmp interfaces to add/release dynamic capacity extents Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 28/46] hw/mem/cxl_type3: Add DPA range validation for accesses to DC regions Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 29/46] hw/cxl/cxl-mailbox-utils: Add superset extent release mailbox support Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 30/46] hw/mem/cxl_type3: Allow to release extent superset in QMP interface Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 31/46] hw/acpi/GI: Fix trivial parameter alignment issue Michael S. Tsirkin
2024-06-04 19:07 ` [PULL 32/46] hw/acpi: Insert an acpi-generic-node base under acpi-generic-initiator Michael S. Tsirkin
2024-06-04 19:07 ` Michael S. Tsirkin [this message]
2024-06-04 19:08 ` [PULL 34/46] bios-tables-test: Allow for new acpihmat-generic-x test data Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 35/46] bios-tables-test: Add complex SRAT / HMAT test for GI GP Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 36/46] bios-tables-test: Add data for complex numa test (GI, GP etc) Michael S. Tsirkin
2024-06-05 14:39   ` Richard Henderson
2024-06-05 15:27     ` Jonathan Cameron via
2024-06-05 15:49       ` Jonathan Cameron via
2024-06-05 16:01       ` Richard Henderson
2024-06-05 16:08         ` Jonathan Cameron via
2024-06-05 16:11           ` Jonathan Cameron via
2024-06-05 16:54             ` Richard Henderson
2024-06-05 17:19               ` Jonathan Cameron via
2024-06-04 19:08 ` [PULL 37/46] scripts/update-linux-headers: Copy setup_data.h to correct directory Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 38/46] linux-headers: update to 6.10-rc1 Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 39/46] hw/misc/pvpanic: centralize definition of supported events Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 40/46] tests/qtest/pvpanic: use centralized " Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 41/46] hw/misc/pvpanic: add support for normal shutdowns Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 42/46] pvpanic: Emit GUEST_PVSHUTDOWN QMP event on pvpanic shutdown signal Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 43/46] tests/qtest/pvpanic: add tests for pvshutdown event Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 44/46] Revert "docs/specs/pvpanic: mark shutdown event as not implemented" Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 45/46] virtio-pci: Fix the failure process in kvm_virtio_pci_vector_use_one() Michael S. Tsirkin
2024-06-04 19:08 ` [PULL 46/46] hw/cxl: Fix read from bogus memory Michael S. Tsirkin
2024-06-05  7:27 ` [PULL 00/46] virtio: features,fixes Michael S. Tsirkin
2024-06-05 14:44   ` Richard Henderson
2024-06-25 13:06 ` Peter Maydell
2024-06-25 14:01   ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b2366d461b9133880913d84742f120d14222a6e6.1717527933.git.mst@redhat.com \
    --to=mst@redhat.com \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=anisinha@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=eblake@redhat.com \
    --cc=eduardo@habkost.net \
    --cc=imammedo@redhat.com \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).