* [PATCH v2 1/4] hw/pci: add IDE + TEE capability to PCIe root port
2026-09-04 16:05 [PATCH v2 0/4] RME-DA preparatory work Jim MacArthur
@ 2026-09-04 16:05 ` Jim MacArthur
2026-09-04 21:12 ` Michael S. Tsirkin
2026-09-04 16:05 ` [PATCH v2 2/4] sata: add SPDM + IDE + TEE pci support Jim MacArthur
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Jim MacArthur @ 2026-09-04 16:05 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, John Snow, Denis V. Lunev, qemu-block,
Jim MacArthur, Pierrick Bouvier, Pierrick Bouvier
From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
hw/pci-bridge/gen_pcie_root_port.c | 8 ++++++++
hw/pci/pcie.c | 15 +++++++++++++++
include/hw/pci/pcie.h | 3 +++
include/hw/pci/pcie_regs.h | 4 ++++
4 files changed, 30 insertions(+)
diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
index 5434d693d9..452ebf69b3 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -26,6 +26,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(GenPCIERootPort, GEN_PCIE_ROOT_PORT)
#define GEN_PCIE_ROOT_PORT_AER_OFFSET 0x100
#define GEN_PCIE_ROOT_PORT_ACS_OFFSET \
(GEN_PCIE_ROOT_PORT_AER_OFFSET + PCI_ERR_SIZEOF)
+#define GEN_PCIE_ROOT_PORT_ACS_END \
+ (GEN_PCIE_ROOT_PORT_ACS_OFFSET + PCI_ACS_SIZEOF)
#define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR 1
#define GEN_PCIE_ROOT_DEFAULT_IO_RANGE 4096
@@ -100,6 +102,12 @@ static void gen_rp_realize(DeviceState *dev, Error **errp)
d->wmask[PCI_IO_BASE] = 0;
d->wmask[PCI_IO_LIMIT] = 0;
}
+
+ uint32_t offset = GEN_PCIE_ROOT_PORT_ACS_END;
+ pcie_ide_init(d, offset);
+ offset += PCI_IDE_SIZEOF;
+
+ pcie_cap_tee_init(d);
}
static const VMStateDescription vmstate_rp_dev = {
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 4622c75e48..b9ead826ed 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -968,6 +968,12 @@ void pcie_cap_flr_write_config(PCIDevice *dev,
}
}
+void pcie_cap_tee_init(PCIDevice *dev)
+{
+ pci_long_test_and_set_mask(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCAP,
+ PCI_EXP_DEVCAP_TEE);
+}
+
/* Alternative Routing-ID Interpretation (ARI)
* forwarding support for root and downstream ports
*/
@@ -1371,6 +1377,15 @@ uint32_t pcie_pri_get_req_alloc(const PCIDevice *dev)
return pci_get_long(dev->config + dev->exp.pri_cap + PCI_PRI_ALLOC_REQ);
}
+/* IDE */
+void pcie_ide_init(PCIDevice *dev, uint16_t offset)
+{
+ pcie_add_capability(dev, PCI_EXT_CAP_ID_IDE, PCI_IDE_VER,
+ offset, PCI_IDE_SIZEOF);
+ uint32_t cap = PCI_IDE_CAP_SELECTIVE;
+ pci_set_byte(dev->config + offset + PCI_IDE_CAP, cap);
+}
+
bool pcie_pri_enabled(const PCIDevice *dev)
{
if (!pci_is_express(dev) || !dev->exp.pri_cap) {
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 71ba94874b..db66678252 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -123,6 +123,8 @@ void pcie_cap_flr_init(PCIDevice *dev);
void pcie_cap_flr_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len);
+void pcie_cap_tee_init(PCIDevice *dev);
+
/* ARI forwarding capability and control */
void pcie_cap_arifwd_init(PCIDevice *dev);
void pcie_cap_arifwd_reset(PCIDevice *dev);
@@ -161,6 +163,7 @@ void pcie_pasid_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width,
bool exec_perm, bool priv_mod);
void pcie_pri_init(PCIDevice *dev, uint16_t offset, uint32_t outstanding_pr_cap,
bool prg_response_pasid_req);
+void pcie_ide_init(PCIDevice *dev, uint16_t offset);
uint32_t pcie_pri_get_req_alloc(const PCIDevice *dev);
bool pcie_pri_enabled(const PCIDevice *dev);
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 33a22229fe..aa21177411 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -182,4 +182,8 @@ typedef enum PCIExpLinkWidth {
#define PCI_DOE_VER 0x1
#define PCI_DOE_SIZEOF 24
+/* IDE */
+#define PCI_IDE_VER 0x1
+#define PCI_IDE_SIZEOF 12
+
#endif /* QEMU_PCIE_REGS_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 1/4] hw/pci: add IDE + TEE capability to PCIe root port
2026-09-04 16:05 ` [PATCH v2 1/4] hw/pci: add IDE + TEE capability to PCIe root port Jim MacArthur
@ 2026-09-04 21:12 ` Michael S. Tsirkin
0 siblings, 0 replies; 8+ messages in thread
From: Michael S. Tsirkin @ 2026-09-04 21:12 UTC (permalink / raw)
To: Jim MacArthur
Cc: qemu-devel, John Snow, Denis V. Lunev, qemu-block,
Pierrick Bouvier
On Fri, Sep 04, 2026 at 05:05:01PM +0100, Jim MacArthur wrote:
> From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
>
Please include a commit log explaining the motivation,
alternatives and result.
A possible format:
Currently .... as a result .... we can not .... because ....
To fix ... and then ...
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
> ---
> hw/pci-bridge/gen_pcie_root_port.c | 8 ++++++++
> hw/pci/pcie.c | 15 +++++++++++++++
> include/hw/pci/pcie.h | 3 +++
> include/hw/pci/pcie_regs.h | 4 ++++
> 4 files changed, 30 insertions(+)
>
> diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
> index 5434d693d9..452ebf69b3 100644
> --- a/hw/pci-bridge/gen_pcie_root_port.c
> +++ b/hw/pci-bridge/gen_pcie_root_port.c
> @@ -26,6 +26,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(GenPCIERootPort, GEN_PCIE_ROOT_PORT)
> #define GEN_PCIE_ROOT_PORT_AER_OFFSET 0x100
> #define GEN_PCIE_ROOT_PORT_ACS_OFFSET \
> (GEN_PCIE_ROOT_PORT_AER_OFFSET + PCI_ERR_SIZEOF)
> +#define GEN_PCIE_ROOT_PORT_ACS_END \
> + (GEN_PCIE_ROOT_PORT_ACS_OFFSET + PCI_ACS_SIZEOF)
>
> #define GEN_PCIE_ROOT_PORT_MSIX_NR_VECTOR 1
> #define GEN_PCIE_ROOT_DEFAULT_IO_RANGE 4096
> @@ -100,6 +102,12 @@ static void gen_rp_realize(DeviceState *dev, Error **errp)
> d->wmask[PCI_IO_BASE] = 0;
> d->wmask[PCI_IO_LIMIT] = 0;
> }
> +
> + uint32_t offset = GEN_PCIE_ROOT_PORT_ACS_END;
> + pcie_ide_init(d, offset);
> + offset += PCI_IDE_SIZEOF;
> +
> + pcie_cap_tee_init(d);
> }
>
> static const VMStateDescription vmstate_rp_dev = {
> diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
> index 4622c75e48..b9ead826ed 100644
> --- a/hw/pci/pcie.c
> +++ b/hw/pci/pcie.c
> @@ -968,6 +968,12 @@ void pcie_cap_flr_write_config(PCIDevice *dev,
> }
> }
>
> +void pcie_cap_tee_init(PCIDevice *dev)
> +{
> + pci_long_test_and_set_mask(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCAP,
> + PCI_EXP_DEVCAP_TEE);
> +}
> +
> /* Alternative Routing-ID Interpretation (ARI)
> * forwarding support for root and downstream ports
> */
> @@ -1371,6 +1377,15 @@ uint32_t pcie_pri_get_req_alloc(const PCIDevice *dev)
> return pci_get_long(dev->config + dev->exp.pri_cap + PCI_PRI_ALLOC_REQ);
> }
>
> +/* IDE */
> +void pcie_ide_init(PCIDevice *dev, uint16_t offset)
> +{
> + pcie_add_capability(dev, PCI_EXT_CAP_ID_IDE, PCI_IDE_VER,
> + offset, PCI_IDE_SIZEOF);
> + uint32_t cap = PCI_IDE_CAP_SELECTIVE;
> + pci_set_byte(dev->config + offset + PCI_IDE_CAP, cap);
> +}
> +
> bool pcie_pri_enabled(const PCIDevice *dev)
> {
> if (!pci_is_express(dev) || !dev->exp.pri_cap) {
> diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
> index 71ba94874b..db66678252 100644
> --- a/include/hw/pci/pcie.h
> +++ b/include/hw/pci/pcie.h
> @@ -123,6 +123,8 @@ void pcie_cap_flr_init(PCIDevice *dev);
> void pcie_cap_flr_write_config(PCIDevice *dev,
> uint32_t addr, uint32_t val, int len);
>
> +void pcie_cap_tee_init(PCIDevice *dev);
> +
> /* ARI forwarding capability and control */
> void pcie_cap_arifwd_init(PCIDevice *dev);
> void pcie_cap_arifwd_reset(PCIDevice *dev);
> @@ -161,6 +163,7 @@ void pcie_pasid_init(PCIDevice *dev, uint16_t offset, uint8_t pasid_width,
> bool exec_perm, bool priv_mod);
> void pcie_pri_init(PCIDevice *dev, uint16_t offset, uint32_t outstanding_pr_cap,
> bool prg_response_pasid_req);
> +void pcie_ide_init(PCIDevice *dev, uint16_t offset);
>
> uint32_t pcie_pri_get_req_alloc(const PCIDevice *dev);
> bool pcie_pri_enabled(const PCIDevice *dev);
> diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
> index 33a22229fe..aa21177411 100644
> --- a/include/hw/pci/pcie_regs.h
> +++ b/include/hw/pci/pcie_regs.h
> @@ -182,4 +182,8 @@ typedef enum PCIExpLinkWidth {
> #define PCI_DOE_VER 0x1
> #define PCI_DOE_SIZEOF 24
>
> +/* IDE */
> +#define PCI_IDE_VER 0x1
> +#define PCI_IDE_SIZEOF 12
> +
> #endif /* QEMU_PCIE_REGS_H */
>
> --
> 2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/4] sata: add SPDM + IDE + TEE pci support
2026-09-04 16:05 [PATCH v2 0/4] RME-DA preparatory work Jim MacArthur
2026-09-04 16:05 ` [PATCH v2 1/4] hw/pci: add IDE + TEE capability to PCIe root port Jim MacArthur
@ 2026-09-04 16:05 ` Jim MacArthur
2026-09-04 16:05 ` [PATCH v2 3/4] hw/pci: add DVSEC RMEDA capability to PCIe root port Jim MacArthur
2026-09-04 16:05 ` [PATCH v2 4/4] hw/pci/msi: extract msi_message_address_register Jim MacArthur
3 siblings, 0 replies; 8+ messages in thread
From: Jim MacArthur @ 2026-09-04 16:05 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, John Snow, Denis V. Lunev, qemu-block,
Jim MacArthur, Pierrick Bouvier, Pierrick Bouvier
From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Replaces the ICH9 config_write/config_read which versions which will use
DOE to write/read config if we have an SPDM port and DOE capability.
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
hw/ide/ich.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index b00987f08d..d2731598ea 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -70,6 +70,7 @@
#include "hw/ide/pci.h"
#include "hw/ide/ahci-pci.h"
#include "ahci-internal.h"
+#include "system/spdm-socket.h"
#define ICH9_MSI_CAP_OFFSET 0x80
#define ICH9_SATA_CAP_OFFSET 0xA8
@@ -90,6 +91,10 @@ static const VMStateDescription vmstate_ich9_ahci = {
},
};
+static const Property ich_props[] = {
+ DEFINE_PROP_UINT16("spdm_port", PCIDevice, spdm_port, 0),
+};
+
static void pci_ich9_ahci_update_irq(void *opaque, int irq_num, int level)
{
PCIDevice *pci_dev = opaque;
@@ -120,6 +125,27 @@ static void pci_ich9_ahci_init(Object *obj)
d->ahci.irq = &d->irq;
}
+static bool pcie_doe_spdm_rsp(DOECap *doe_cap)
+{
+ void *req = pcie_doe_get_write_mbox_ptr(doe_cap);
+ uint32_t req_len = pcie_doe_get_obj_len(req) * 4;
+ void *rsp = doe_cap->read_mbox;
+ uint32_t rsp_len = SPDM_SOCKET_MAX_MESSAGE_BUFFER_SIZE;
+
+ uint32_t recvd = spdm_socket_rsp(doe_cap->spdm_socket,
+ SPDM_SOCKET_TRANSPORT_TYPE_PCI_DOE,
+ req, req_len, rsp, rsp_len);
+ doe_cap->read_mbox_len += DIV_ROUND_UP(recvd, 4);
+
+ return recvd != 0;
+}
+
+static DOEProtocol doe_spdm_prot[] = {
+ { PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_CMA, pcie_doe_spdm_rsp },
+ { PCI_VENDOR_ID_PCI_SIG, PCI_SIG_DOE_SECURED_CMA, pcie_doe_spdm_rsp },
+ { }
+};
+
static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
{
AHCIPCIState *d;
@@ -145,6 +171,8 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
pci_register_bar(dev, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY,
&d->ahci.mem);
+ pcie_endpoint_cap_init(dev, 0xa8 + 0x8); /* right after SATA */
+
sata_cap_offset = pci_add_capability(dev, PCI_CAP_ID_SATA,
ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE,
errp);
@@ -165,6 +193,25 @@ static void pci_ich9_ahci_realize(PCIDevice *dev, Error **errp)
/* Any error other than -ENOTSUP(board's MSI support is broken)
* is a programming error. Fall back to INTx silently on -ENOTSUP */
assert(!ret || ret == -ENOTSUP);
+
+ uint16_t cap_offset = PCI_CONFIG_SPACE_SIZE;
+
+ if (dev->spdm_port) {
+ pcie_doe_init(dev, &dev->doe_spdm, cap_offset,
+ doe_spdm_prot, true, 0);
+ cap_offset += PCI_DOE_SIZEOF;
+
+ dev->doe_spdm.spdm_socket = spdm_socket_connect(dev->spdm_port,
+ errp);
+ assert(dev->doe_spdm.spdm_socket > 0);
+ }
+
+ /* ide */
+ pcie_ide_init(dev, cap_offset);
+ cap_offset += PCI_IDE_SIZEOF;
+
+ /* tee */
+ pcie_cap_tee_init(dev);
}
static void pci_ich9_uninit(PCIDevice *dev)
@@ -176,18 +223,41 @@ static void pci_ich9_uninit(PCIDevice *dev)
ahci_uninit(&d->ahci);
}
+static uint32_t ich_read_config(PCIDevice *dev, uint32_t address, int len)
+{
+ uint32_t val;
+ if (dev->spdm_port && pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE)) {
+ if (pcie_doe_read_config(&dev->doe_spdm, address, len, &val)) {
+ return val;
+ }
+ }
+ return pci_default_read_config(dev, address, len);
+}
+
+static void ich_write_config(PCIDevice *dev, uint32_t address,
+ uint32_t val, int len)
+{
+ if (pcie_find_capability(dev, PCI_EXT_CAP_ID_DOE)) {
+ pcie_doe_write_config(&dev->doe_spdm, address, val, len);
+ }
+ pci_default_write_config(dev, address, val, len);
+}
+
static void ich_ahci_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
k->realize = pci_ich9_ahci_realize;
+ k->config_write = ich_write_config;
+ k->config_read = ich_read_config;
k->exit = pci_ich9_uninit;
k->vendor_id = PCI_VENDOR_ID_INTEL;
k->device_id = PCI_DEVICE_ID_INTEL_82801IR;
k->revision = 0x02;
k->class_id = PCI_CLASS_STORAGE_SATA;
dc->vmsd = &vmstate_ich9_ahci;
+ device_class_set_props(dc, ich_props);
device_class_set_legacy_reset(dc, pci_ich9_reset);
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}
@@ -199,7 +269,7 @@ static const TypeInfo ich_ahci_info = {
.instance_init = pci_ich9_ahci_init,
.class_init = ich_ahci_class_init,
.interfaces = (const InterfaceInfo[]) {
- { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+ { INTERFACE_PCIE_DEVICE },
{ },
},
};
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2 3/4] hw/pci: add DVSEC RMEDA capability to PCIe root port
2026-09-04 16:05 [PATCH v2 0/4] RME-DA preparatory work Jim MacArthur
2026-09-04 16:05 ` [PATCH v2 1/4] hw/pci: add IDE + TEE capability to PCIe root port Jim MacArthur
2026-09-04 16:05 ` [PATCH v2 2/4] sata: add SPDM + IDE + TEE pci support Jim MacArthur
@ 2026-09-04 16:05 ` Jim MacArthur
2026-09-04 21:11 ` Michael S. Tsirkin
2026-09-04 16:05 ` [PATCH v2 4/4] hw/pci/msi: extract msi_message_address_register Jim MacArthur
3 siblings, 1 reply; 8+ messages in thread
From: Jim MacArthur @ 2026-09-04 16:05 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, John Snow, Denis V. Lunev, qemu-block,
Jim MacArthur, Pierrick Bouvier, Viresh Kumar, Pierrick Bouvier
From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
After this we can see all the capabilities listed for the PCIe bridge:
00:05.0 PCI bridge: Red Hat, Inc. QEMU PCIe Root port (prog-if 00 [Normal decode])
...
Capabilities: [54] Express (v2) Root Port (Slot+), IntMsgNum 0
...
Capabilities: [48] MSI-X: Enable+ Count=1 Masked-
Vector table: BAR=0 offset=00000000
PBA: BAR=0 offset=00000800
Capabilities: [40] Subsystem: Red Hat, Inc. Device 0000
Capabilities: [100 v2] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr+
PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+
ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr- CorrIntErr- HeaderOF-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+ CorrIntErr+ HeaderOF+
AERCap: First Error Pointer: 00, ECRCGenCap+ ECRCGenEn- ECRCChkCap+ ECRCChkEn-
MultHdrRecCap+ MultHdrRecEn- TLPPfxPres- HdrLogCap-
HeaderLog: 00000000 00000000 00000000 00000000
RootCmd: CERptEn+ NFERptEn+ FERptEn+
RootSta: CERcvd- MultCERcvd- UERcvd- MultUERcvd-
FirstFatal- NonFatalMsg- FatalMsg- IntMsgNum 0
ErrorSrc: ERR_COR: 0000 ERR_FATAL/NONFATAL: 0000
Capabilities: [148 v1] Access Control Services
ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl- DirectTrans+
ACSCtl: SrcValid+ TransBlk- ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl- DirectTrans-
Capabilities: [150 v1] Designated Vendor-Specific: Vendor=13b5 ID=ff01 Rev=0 Len=16 <?>
Capabilities: [164 v1] Integrity & Data Encryption
IDECap: Lnk=0 Sel=1 FlowThru- PartHdr- Aggr- PCPC- IDE_KM- Alg='AES-GCM-256-96b' TCs=1 TeeLim-
IDECtl: FTEn-
[170]SelectiveIDE#0 Cap: RID#=0
[174]SelectiveIDE#0 Ctl: En- NPR- PR- CPL- PCRC- CFG- HdrEnc=no Alg='AES-GCM-256-96b' TC0 ID0
[178]SelectiveIDE#0 Sta: insecure RecvChkFail-
[17c]SelectiveIDE#0 RID: Valid- Base=0 Limit=0 SegBase=0
Kernel driver in use: pcieport
---
hw/pci-bridge/gen_pcie_root_port.c | 30 ++++++++++++++++++++++++++++++
include/hw/pci/pcie_regs.h | 4 ++++
2 files changed, 34 insertions(+)
diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
index 452ebf69b3..035212508d 100644
--- a/hw/pci-bridge/gen_pcie_root_port.c
+++ b/hw/pci-bridge/gen_pcie_root_port.c
@@ -104,6 +104,36 @@ static void gen_rp_realize(DeviceState *dev, Error **errp)
}
uint32_t offset = GEN_PCIE_ROOT_PORT_ACS_END;
+ /*
+ * dvsec rme-da
+ * https://developer.arm.com/documentation/den0129/latest/
+ * Arm RME System Architecture
+ * 0x0000 RMEDA_ECH See B3.2.6.2.1 RME-DA Extended Capability Header
+ * 0x0004 RMEDA_HEAD1 See B3.2.6.2.2 RME-DA DVSEC Header 1
+ * 0x0008 RMEDA_HEAD2 See B3.2.6.2.3 RME-DA DVSEC Header 2
+ * 0x000C RMEDA_CTL1 See B3.2.6.2.4 RME-DA Control register 1
+ * 0x0010 RMEDA_CTL2 See B3.2.6.2.5 RME-DA Control register 2
+ */
+ pcie_add_capability(d, PCI_EXT_CAP_ID_DVSEC, PCI_RMEDA_VER, offset,
+ PCI_RMEDA_SIZEOF);
+ const uint32_t header1 = 0x010013b5;
+ const uint32_t header2 = 0xFF01;
+ const uint32_t ctl1 = 0x1; /* support tdisp */
+ const uint32_t ctl2 = 0x0; /* unlocked */
+ pci_set_long(d->config + offset + 0x4, header1);
+ pci_set_long(d->config + offset + 0x8, header2);
+ pci_set_long(d->config + offset + 0xC, ctl1);
+ pci_set_long(d->config + offset + 0x10, ctl2);
+ d->wmask[offset + 0xC] = 0xff;
+ d->wmask[offset + 0xC + 1] = 0xff;
+ d->wmask[offset + 0xC + 2] = 0xff;
+ d->wmask[offset + 0xC + 3] = 0xff;
+ d->wmask[offset + 0x10] = 0xff;
+ d->wmask[offset + 0x10 + 1] = 0xff;
+ d->wmask[offset + 0x10 + 2] = 0xff;
+ d->wmask[offset + 0x10 + 3] = 0xff;
+ offset += PCI_RMEDA_SIZEOF;
+
pcie_ide_init(d, offset);
offset += PCI_IDE_SIZEOF;
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index aa21177411..233378fd79 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -186,4 +186,8 @@ typedef enum PCIExpLinkWidth {
#define PCI_IDE_VER 0x1
#define PCI_IDE_SIZEOF 12
+/* RME-DA */
+#define PCI_RMEDA_VER 0x1
+#define PCI_RMEDA_SIZEOF 20
+
#endif /* QEMU_PCIE_REGS_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 3/4] hw/pci: add DVSEC RMEDA capability to PCIe root port
2026-09-04 16:05 ` [PATCH v2 3/4] hw/pci: add DVSEC RMEDA capability to PCIe root port Jim MacArthur
@ 2026-09-04 21:11 ` Michael S. Tsirkin
0 siblings, 0 replies; 8+ messages in thread
From: Michael S. Tsirkin @ 2026-09-04 21:11 UTC (permalink / raw)
To: Jim MacArthur
Cc: qemu-devel, John Snow, Denis V. Lunev, qemu-block,
Pierrick Bouvier, Viresh Kumar
On Fri, Sep 04, 2026 at 05:05:03PM +0100, Jim MacArthur wrote:
> From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
>
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
>
> After this we can see all the capabilities listed for the PCIe bridge:
>
> 00:05.0 PCI bridge: Red Hat, Inc. QEMU PCIe Root port (prog-if 00 [Normal decode])
>
> ...
>
> Capabilities: [54] Express (v2) Root Port (Slot+), IntMsgNum 0
>
> ...
>
> Capabilities: [48] MSI-X: Enable+ Count=1 Masked-
> Vector table: BAR=0 offset=00000000
> PBA: BAR=0 offset=00000800
> Capabilities: [40] Subsystem: Red Hat, Inc. Device 0000
> Capabilities: [100 v2] Advanced Error Reporting
> UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
> ECRC- UnsupReq- ACSViol- UncorrIntErr- BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
> PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
> UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP-
> ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr+
> PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
> UESvrt: DLP+ SDES+ TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+
> ECRC- UnsupReq- ACSViol- UncorrIntErr+ BlockedTLP- AtomicOpBlocked- TLPBlockedErr-
> PoisonTLPBlocked- DMWrReqBlocked- IDECheck- MisIDETLP- PCRC_CHECK- TLPXlatBlocked-
> CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr- CorrIntErr- HeaderOF-
> CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- AdvNonFatalErr+ CorrIntErr+ HeaderOF+
> AERCap: First Error Pointer: 00, ECRCGenCap+ ECRCGenEn- ECRCChkCap+ ECRCChkEn-
> MultHdrRecCap+ MultHdrRecEn- TLPPfxPres- HdrLogCap-
> HeaderLog: 00000000 00000000 00000000 00000000
> RootCmd: CERptEn+ NFERptEn+ FERptEn+
> RootSta: CERcvd- MultCERcvd- UERcvd- MultUERcvd-
> FirstFatal- NonFatalMsg- FatalMsg- IntMsgNum 0
> ErrorSrc: ERR_COR: 0000 ERR_FATAL/NONFATAL: 0000
> Capabilities: [148 v1] Access Control Services
> ACSCap: SrcValid+ TransBlk+ ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl- DirectTrans+
> ACSCtl: SrcValid+ TransBlk- ReqRedir+ CmpltRedir+ UpstreamFwd+ EgressCtrl- DirectTrans-
> Capabilities: [150 v1] Designated Vendor-Specific: Vendor=13b5 ID=ff01 Rev=0 Len=16 <?>
> Capabilities: [164 v1] Integrity & Data Encryption
> IDECap: Lnk=0 Sel=1 FlowThru- PartHdr- Aggr- PCPC- IDE_KM- Alg='AES-GCM-256-96b' TCs=1 TeeLim-
> IDECtl: FTEn-
> [170]SelectiveIDE#0 Cap: RID#=0
> [174]SelectiveIDE#0 Ctl: En- NPR- PR- CPL- PCRC- CFG- HdrEnc=no Alg='AES-GCM-256-96b' TC0 ID0
> [178]SelectiveIDE#0 Sta: insecure RecvChkFail-
> [17c]SelectiveIDE#0 RID: Valid- Base=0 Limit=0 SegBase=0
> Kernel driver in use: pcieport
> ---
> hw/pci-bridge/gen_pcie_root_port.c | 30 ++++++++++++++++++++++++++++++
> include/hw/pci/pcie_regs.h | 4 ++++
> 2 files changed, 34 insertions(+)
>
> diff --git a/hw/pci-bridge/gen_pcie_root_port.c b/hw/pci-bridge/gen_pcie_root_port.c
> index 452ebf69b3..035212508d 100644
> --- a/hw/pci-bridge/gen_pcie_root_port.c
> +++ b/hw/pci-bridge/gen_pcie_root_port.c
> @@ -104,6 +104,36 @@ static void gen_rp_realize(DeviceState *dev, Error **errp)
> }
>
> uint32_t offset = GEN_PCIE_ROOT_PORT_ACS_END;
> + /*
> + * dvsec rme-da
> + * https://developer.arm.com/documentation/den0129/latest/
> + * Arm RME System Architecture
> + * 0x0000 RMEDA_ECH See B3.2.6.2.1 RME-DA Extended Capability Header
> + * 0x0004 RMEDA_HEAD1 See B3.2.6.2.2 RME-DA DVSEC Header 1
> + * 0x0008 RMEDA_HEAD2 See B3.2.6.2.3 RME-DA DVSEC Header 2
> + * 0x000C RMEDA_CTL1 See B3.2.6.2.4 RME-DA Control register 1
> + * 0x0010 RMEDA_CTL2 See B3.2.6.2.5 RME-DA Control register 2
> + */
> + pcie_add_capability(d, PCI_EXT_CAP_ID_DVSEC, PCI_RMEDA_VER, offset,
> + PCI_RMEDA_SIZEOF);
don't put declarations after code.
> + const uint32_t header1 = 0x010013b5;
> + const uint32_t header2 = 0xFF01;
what are these things?
> + const uint32_t ctl1 = 0x1; /* support tdisp */
> + const uint32_t ctl2 = 0x0; /* unlocked */
so why do we need these vars? just open-code.
> + pci_set_long(d->config + offset + 0x4, header1);
> + pci_set_long(d->config + offset + 0x8, header2);
> + pci_set_long(d->config + offset + 0xC, ctl1);
> + pci_set_long(d->config + offset + 0x10, ctl2);
> + d->wmask[offset + 0xC] = 0xff;
> + d->wmask[offset + 0xC + 1] = 0xff;
> + d->wmask[offset + 0xC + 2] = 0xff;
> + d->wmask[offset + 0xC + 3] = 0xff;
> + d->wmask[offset + 0x10] = 0xff;
> + d->wmask[offset + 0x10 + 1] = 0xff;
> + d->wmask[offset + 0x10 + 2] = 0xff;
> + d->wmask[offset + 0x10 + 3] = 0xff;
> + offset += PCI_RMEDA_SIZEOF;
> +
> pcie_ide_init(d, offset);
> offset += PCI_IDE_SIZEOF;
You can't unconditionally change config space, this will break
cross version migration.
You must use a property (beginning with "x-") and compat machinery.
Besides, having all root ports on all arches have this capability
looks very strange. For example not everything supports tdisp.
> diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
> index aa21177411..233378fd79 100644
> --- a/include/hw/pci/pcie_regs.h
> +++ b/include/hw/pci/pcie_regs.h
> @@ -186,4 +186,8 @@ typedef enum PCIExpLinkWidth {
> #define PCI_IDE_VER 0x1
> #define PCI_IDE_SIZEOF 12
>
> +/* RME-DA */
> +#define PCI_RMEDA_VER 0x1
> +#define PCI_RMEDA_SIZEOF 20
> +
> #endif /* QEMU_PCIE_REGS_H */
>
> --
> 2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 4/4] hw/pci/msi: extract msi_message_address_register
2026-09-04 16:05 [PATCH v2 0/4] RME-DA preparatory work Jim MacArthur
` (2 preceding siblings ...)
2026-09-04 16:05 ` [PATCH v2 3/4] hw/pci: add DVSEC RMEDA capability to PCIe root port Jim MacArthur
@ 2026-09-04 16:05 ` Jim MacArthur
2026-09-04 16:14 ` Philippe Mathieu-Daudé
3 siblings, 1 reply; 8+ messages in thread
From: Jim MacArthur @ 2026-09-04 16:05 UTC (permalink / raw)
To: qemu-devel
Cc: Michael S. Tsirkin, John Snow, Denis V. Lunev, qemu-block,
Jim MacArthur, Pierrick Bouvier, Pierrick Bouvier
From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
We need to access this address from smmu, to know if we are translating
an MSI.
Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
---
hw/pci/msi.c | 19 +++++++++++++------
include/hw/pci/msi.h | 1 +
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/hw/pci/msi.c b/hw/pci/msi.c
index b9f5b45920..7361776ace 100644
--- a/hw/pci/msi.c
+++ b/hw/pci/msi.c
@@ -137,6 +137,18 @@ void msi_set_message(PCIDevice *dev, MSIMessage msg)
pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data);
}
+uint64_t msi_message_address_register(PCIDevice *dev)
+{
+ uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
+ bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
+
+ if (msi64bit) {
+ return pci_get_quad(dev->config + msi_address_lo_off(dev));
+ } else {
+ return pci_get_long(dev->config + msi_address_lo_off(dev));
+ }
+}
+
static MSIMessage msi_prepare_message(PCIDevice *dev, unsigned int vector)
{
uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
@@ -146,12 +158,7 @@ static MSIMessage msi_prepare_message(PCIDevice *dev, unsigned int vector)
assert(vector < nr_vectors);
- if (msi64bit) {
- msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev));
- } else {
- msg.address = pci_get_long(dev->config + msi_address_lo_off(dev));
- }
-
+ msg.address = msi_message_address_register(dev);
/* upper bit 31:16 is zero */
msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
if (nr_vectors > 1) {
diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h
index abcfd13925..6f0e02c0fb 100644
--- a/include/hw/pci/msi.h
+++ b/include/hw/pci/msi.h
@@ -32,6 +32,7 @@ extern bool msi_nonbroken;
void msi_set_message(PCIDevice *dev, MSIMessage msg);
MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector);
+uint64_t msi_message_address_register(PCIDevice *dev);
bool msi_enabled(const PCIDevice *dev);
void msi_set_enabled(PCIDevice *dev);
int msi_init(struct PCIDevice *dev, uint8_t offset,
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2 4/4] hw/pci/msi: extract msi_message_address_register
2026-09-04 16:05 ` [PATCH v2 4/4] hw/pci/msi: extract msi_message_address_register Jim MacArthur
@ 2026-09-04 16:14 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 8+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-09-04 16:14 UTC (permalink / raw)
To: Jim MacArthur, qemu-devel
Cc: Michael S. Tsirkin, John Snow, Denis V. Lunev, qemu-block,
Pierrick Bouvier
Hi Jim,
On 4/9/26 18:05, Jim MacArthur wrote:
> From: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
>
> We need to access this address from smmu, to know if we are translating
> an MSI.
>
> Signed-off-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> Signed-off-by: Jim MacArthur <jim.macarthur@linaro.org>
> ---
> hw/pci/msi.c | 19 +++++++++++++------
> include/hw/pci/msi.h | 1 +
> 2 files changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/hw/pci/msi.c b/hw/pci/msi.c
> index b9f5b45920..7361776ace 100644
> --- a/hw/pci/msi.c
> +++ b/hw/pci/msi.c
> @@ -137,6 +137,18 @@ void msi_set_message(PCIDevice *dev, MSIMessage msg)
> pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data);
> }
>
> +uint64_t msi_message_address_register(
const
> PCIDevice *dev)
> +{
> + uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
> + bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
> +
> + if (msi64bit) {
> + return pci_get_quad(dev->config + msi_address_lo_off(dev));
> + } else {
> + return pci_get_long(dev->config + msi_address_lo_off(dev));
> + }
> +}
> +
> static MSIMessage msi_prepare_message(PCIDevice *dev, unsigned int vector)
> {
> uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
> @@ -146,12 +158,7 @@ static MSIMessage msi_prepare_message(PCIDevice *dev, unsigned int vector)
>
> assert(vector < nr_vectors);
>
> - if (msi64bit) {
> - msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev));
> - } else {
> - msg.address = pci_get_long(dev->config + msi_address_lo_off(dev));
> - }
> -
> + msg.address = msi_message_address_register(dev);
> /* upper bit 31:16 is zero */
> msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
> if (nr_vectors > 1) {
> diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h
> index abcfd13925..6f0e02c0fb 100644
> --- a/include/hw/pci/msi.h
> +++ b/include/hw/pci/msi.h
> @@ -32,6 +32,7 @@ extern bool msi_nonbroken;
>
> void msi_set_message(PCIDevice *dev, MSIMessage msg);
> MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector);
> +uint64_t msi_message_address_register(PCIDevice *dev);
While this file lacks documentation, it would be good to start adding
some for new methods ;)
With doc+const:
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 8+ messages in thread