From: Shrihari E S <shrihari.s@samsung.com>
To: jic23@kernel.org, junjie.cao@intel.com,
linux-cxl@vger.kernel.org, linux-pci@vger.kernel.org,
qemu-devel@nongnu.org
Cc: shrihari.s@samsung.com, arun.george@samsung.com,
cpgs@samsung.com, dave@stgolabs.net, dongjoo.seo1@samsung.com,
gost.dev@samsung.com, s.neeraj@samsung.com,
vikash.k5@samsung.com
Subject: [RFC V2 08/10] hw/pci: Add PCIe Device3 capability support
Date: Wed, 26 Aug 2026 11:04:08 +0530 [thread overview]
Message-ID: <2044366277.121787732104098.JavaMail.epsvc@epcpadp1new> (raw)
In-Reply-To: <20260826053410.1322176-1-shrihari.s@samsung.com>
This commit adds Device3 support to the PCIe devices, with which
an endpoint can be exposed as a UIO requester or completer, based
on its configuration.
Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
---
hw/mem/cxl_type3.c | 1 +
hw/pci/meson.build | 2 +-
hw/pci/pci.c | 2 +
hw/pci/pcie.c | 30 +++++++
hw/pci/pcie_dev3.c | 165 +++++++++++++++++++++++++++++++++++++
include/hw/pci/pcie.h | 6 ++
include/hw/pci/pcie_dev3.h | 29 +++++++
include/hw/pci/pcie_regs.h | 30 +++++++
8 files changed, 264 insertions(+), 1 deletion(-)
create mode 100644 hw/pci/pcie_dev3.c
create mode 100644 include/hw/pci/pcie_dev3.h
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index 24bf4f8309..0adf2e8b3e 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -17,6 +17,7 @@
#include "hw/mem/memory-device.h"
#include "hw/mem/pc-dimm.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pcie_dev3.h"
#include "hw/core/qdev-properties.h"
#include "hw/core/qdev-properties-system.h"
#include "qapi/error.h"
diff --git a/hw/pci/meson.build b/hw/pci/meson.build
index d55882a0c9..0a7f3b162a 100644
--- a/hw/pci/meson.build
+++ b/hw/pci/meson.build
@@ -14,7 +14,7 @@ pci_ss.add(files(
# The functions in these modules can be used by devices too. Since we
# allow plugging PCIe devices into PCI buses, include them even if
# CONFIG_PCI_EXPRESS=n.
-pci_ss.add(files('pcie.c', 'pcie_aer.c', 'pcie_svc.c'))
+pci_ss.add(files('pcie.c', 'pcie_aer.c', 'pcie_svc.c', 'pcie_dev3.c'))
pci_ss.add(files('pcie_doe.c'))
system_ss.add(when: 'CONFIG_PCI_EXPRESS', if_true: files('pcie_port.c', 'pcie_host.c'))
system_ss.add_all(when: 'CONFIG_PCI', if_true: pci_ss)
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 0469250f42..600f41fc95 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -570,6 +570,7 @@ static void pci_do_device_reset(PCIDevice *dev)
msix_reset(dev);
pcie_sriov_pf_reset(dev);
pcie_svc_cap_reset(dev);
+ pcie_dev3_cap_reset(dev);
}
/*
@@ -1818,6 +1819,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int
pcie_sriov_config_write(d, addr, val_in, l);
pcie_cap_flit_write_config(d, addr, val_in, l);
pcie_svc_cap_write_config(d, addr, val_in, l);
+ pcie_dev3_cap_write_config(d, addr, val_in, l);
}
/***********************************************************/
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index cc1cc500ab..6b8cc0f948 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -190,6 +190,32 @@ void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
pcie_cap_fill_lnk(dev, exp_cap, width, speed, flitmode);
}
+bool pcie_link_flit_active(PCIDevice *dev)
+{
+ uint8_t *exp_cap;
+ uint16_t lnksta2;
+ uint16_t lnkctl;
+ uint16_t flags;
+
+ if (!pci_is_express(dev) || !dev->exp.exp_cap) {
+ return false;
+ }
+
+ exp_cap = dev->config + dev->exp.exp_cap;
+ flags = pci_get_word(exp_cap + PCI_EXP_FLAGS);
+ if (!(flags & PCI_EXP_FLAGS_FLIT)) {
+ return false;
+ }
+ lnkctl = pci_get_word(exp_cap + PCI_EXP_LNKCTL);
+ lnksta2 = pci_get_word(exp_cap + PCI_EXP_LNKSTA2);
+
+ if (lnkctl & PCI_EXP_LNKCTL_FLIT_DIS) {
+ return false;
+ }
+
+ return lnksta2 & PCI_EXP_LNKSTA2_FLIT;
+}
+
void pcie_cap_flit_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
int len)
{
@@ -223,6 +249,10 @@ void pcie_cap_flit_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
}
pci_set_word(exp_cap + PCI_EXP_LNKSTA2, lnksta2);
+ if (dev->exp.dev3_cap) {
+ pcie_dev3_cap_flit_update(dev);
+ }
+
}
static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
diff --git a/hw/pci/pcie_dev3.c b/hw/pci/pcie_dev3.c
new file mode 100644
index 0000000000..d6794bd3fe
--- /dev/null
+++ b/hw/pci/pcie_dev3.c
@@ -0,0 +1,165 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * PCIe Device3 Extended Capability
+ *
+ * Copyright (c) 2026 Samsung Electronics Co., Ltd.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/pci/pci_device.h"
+#include "hw/pci/pcie.h"
+#include "hw/pci/pcie_port.h"
+#include "hw/pci/pcie_dev3.h"
+
+static uint32_t pcie_dev3_cap_offset(PCIDevice *dev)
+{
+ return dev->exp.dev3_cap;
+}
+
+int pcie_dev3_cap_init(PCIDevice *dev, uint32_t offset,
+ bool uio_req, bool uio_comp, Error **errp)
+{
+ uint32_t devcap3 = 0;
+ uint32_t wmask = 0;
+
+ if (!pci_is_express(dev)) {
+ error_setg(errp, "Device 3 ECAP requires PCIe");
+ return -EINVAL;
+ }
+
+ pcie_add_capability(dev, PCI_EXT_CAP_ID_DEV3, 1, offset, PCI_DEV3_SIZEOF);
+ pci_set_long(dev->config + offset + PCI_DEV3_CAP_HEAD,
+ (PCI_DEV3_CAP_ID | PCI_DEV3_CAP_VER |
+ PCI_DEV3_NEXT_CAP_OFF));
+ dev->exp.dev3_cap = offset;
+ dev->exp.dev3.uio_req = uio_req;
+ dev->exp.dev3.uio_comp = uio_comp;
+
+ /*
+ * In this implementation, 14-bit tag support is only advertised
+ * when UIO is enabled. A real device may support 14-bit tags
+ * independently of UIO.
+ */
+ if (uio_comp) {
+ devcap3 |= PCI_DEV3_CAP_TAG_COMP | PCI_DEV3_CAP_UIO_COMP;
+ }
+ if (uio_req) {
+ devcap3 |= PCI_DEV3_CAP_TAG_REQ | PCI_DEV3_CAP_UIO_REQ;
+ wmask |= PCI_DEV3_CTL_TAG_REQ_EN |
+ PCI_DEV3_CTL_UIO_REQ_EN |
+ PCI_DEV3_CTL_UIO_256B_DIS;
+ /*
+ * A UIO requester must be able to issue DMA transactions.
+ * Enable PCI_COMMAND_MASTER in the PCI command register so the
+ * device's bus master bit is set when the requester capability
+ * is advertised.
+ */
+ pci_set_word(dev->config + PCI_COMMAND,
+ pci_get_word(dev->config + PCI_COMMAND) |
+ PCI_COMMAND_MASTER);
+ }
+
+ pci_set_long(dev->config + offset + PCI_DEV3_CAP_OFFSET, devcap3);
+ pci_set_long(dev->wmask + offset + PCI_DEV3_CTL_OFFSET, wmask);
+
+ return 0;
+}
+
+void pcie_dev3_cap_reset(PCIDevice *dev)
+{
+ uint32_t off = pcie_dev3_cap_offset(dev);
+
+ if (!off) {
+ return;
+ }
+
+ pci_set_long(dev->config + off + PCI_DEV3_CTL_OFFSET, 0);
+ pci_set_long(dev->config + off + PCI_DEV3_STA_OFFSET, 0);
+ pcie_dev3_apply_gating(dev);
+}
+
+void pcie_dev3_apply_gating(PCIDevice *dev)
+{
+ uint32_t off = pcie_dev3_cap_offset(dev);
+ uint32_t devctl3;
+ uint32_t devsta3;
+ bool flit;
+
+ if (!off) {
+ return;
+ }
+
+ flit = pcie_link_flit_active(dev);
+ devctl3 = pci_get_long(dev->config + off + PCI_DEV3_CTL_OFFSET);
+ devsta3 = pci_get_long(dev->config + off + PCI_DEV3_STA_OFFSET);
+ if (!dev->exp.dev3.uio_req || !flit) {
+ devctl3 &= ~(PCI_DEV3_CTL_TAG_REQ_EN |
+ PCI_DEV3_CTL_UIO_REQ_EN |
+ PCI_DEV3_CTL_UIO_256B_DIS);
+ pci_set_long(dev->config + off + PCI_DEV3_CTL_OFFSET, devctl3);
+ }
+
+ if (flit) {
+ devsta3 |= PCI_DEV3_STA_SEGMENT_CAP;
+ } else {
+ devsta3 &= ~PCI_DEV3_STA_SEGMENT_CAP;
+ }
+ pci_set_long(dev->config + off + PCI_DEV3_STA_OFFSET, devsta3);
+}
+
+void pcie_dev3_cap_write_config(PCIDevice *dev,
+ uint32_t addr, uint32_t val, int len)
+{
+ uint32_t off = pcie_dev3_cap_offset(dev);
+
+ if (!off) {
+ return;
+ }
+
+ if (ranges_overlap(addr, len, off + PCI_DEV3_CTL_OFFSET, 4)) {
+ pcie_dev3_apply_gating(dev);
+ }
+}
+
+void pcie_dev3_cap_flit_update(PCIDevice *dev)
+{
+ uint32_t off = pcie_dev3_cap_offset(dev);
+ if (!off) {
+ return;
+ }
+
+ uint32_t devsta3 = pci_get_long(dev->config + off + PCI_DEV3_STA_OFFSET);
+ if (pcie_link_flit_active(dev)) {
+ devsta3 |= PCI_DEV3_STA_SEGMENT_CAP;
+ } else {
+ devsta3 &= ~PCI_DEV3_STA_SEGMENT_CAP;
+ }
+ pci_set_long(dev->config + off + PCI_DEV3_STA_OFFSET, devsta3);
+}
+
+bool pcie_dev3_uio_enabled(PCIDevice *dev)
+{
+ uint32_t off = pcie_dev3_cap_offset(dev);
+ uint32_t devctl3;
+
+ if (!off || !dev->exp.dev3.uio_req || !pcie_link_flit_active(dev)) {
+ return false;
+ }
+
+ devctl3 = pci_get_long(dev->config + off + PCI_DEV3_CTL_OFFSET);
+ return devctl3 & PCI_DEV3_CTL_UIO_REQ_EN;
+}
+
+bool pcie_dev3_tag_req_enabled(PCIDevice *dev)
+{
+ uint32_t off = pcie_dev3_cap_offset(dev);
+ uint32_t devctl3;
+
+ if (!off || !dev->exp.dev3.uio_req || !pcie_link_flit_active(dev)) {
+ return false;
+ }
+
+ devctl3 = pci_get_long(dev->config + off + PCI_DEV3_CTL_OFFSET);
+ return devctl3 & PCI_DEV3_CTL_TAG_REQ_EN;
+}
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 2feeb022f0..e997f3a456 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -26,6 +26,7 @@
#include "hw/pci/pcie_aer.h"
#include "hw/pci/pcie_sriov.h"
#include "hw/pci/pcie_svc.h"
+#include "hw/pci/pcie_dev3.h"
#include "hw/core/hotplug.h"
typedef struct PCIEPort PCIEPort;
@@ -87,6 +88,10 @@ struct PCIExpressDevice {
/* Streamlined Virtual Channel (SVC) introduced from PCIe 6.1 */
uint32_t svc_cap;
PCIESvcCap svc;
+
+ /* PCIe Device 3 Capability */
+ uint32_t dev3_cap;
+ struct PCIEDev3Cap dev3;
};
#define COMPAT_PROP_PCP "power_controller_present"
@@ -150,6 +155,7 @@ void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
PCIExpLinkSpeed speed, bool flitmode);
void pcie_cap_flit_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len);
+bool pcie_link_flit_active(PCIDevice *dev);
void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
diff --git a/include/hw/pci/pcie_dev3.h b/include/hw/pci/pcie_dev3.h
new file mode 100644
index 0000000000..0a49835ab4
--- /dev/null
+++ b/include/hw/pci/pcie_dev3.h
@@ -0,0 +1,29 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * PCIe Device3 Extended Capability
+ *
+ * Copyright (c) 2026 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef HW_PCIE_DEV3_H
+#define HW_PCIE_DEV3_H
+
+#include "hw/pci/pci.h"
+
+typedef struct PCIEDev3Cap {
+ bool uio_req;
+ bool uio_comp;
+} PCIEDev3Cap;
+
+int pcie_dev3_cap_init(PCIDevice *dev, uint32_t offset,
+ bool uio_req, bool uio_comp, Error **errp);
+void pcie_dev3_cap_reset(PCIDevice *dev);
+void pcie_dev3_cap_write_config(PCIDevice *dev,
+ uint32_t addr, uint32_t val, int len);
+void pcie_dev3_cap_flit_update(PCIDevice *dev);
+bool pcie_dev3_uio_enabled(PCIDevice *dev);
+bool pcie_dev3_tag_req_enabled(PCIDevice *dev);
+void pcie_dev3_apply_gating(PCIDevice *dev);
+
+#endif /* HW_PCIE_DEV3_H */
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 566754646c..326195a199 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -237,4 +237,34 @@ typedef enum PCIExpLinkWidth {
#define PCI_SVC_RES_STATUS(n) (PCI_SVC_RES_STATUS_BASE + ((n) * 0x0c))
#define PCI_SVC_VC_NEGO BIT(1)
+/* PCIe Device 3 capability structure. PCIe 6.4 Specification Section 7.7.9 */
+#define PCI_EXT_CAP_ID_DEV3 0x2f
+
+#define PCI_DEV3_CAP_HEAD 0x00
+#define PCI_DEV3_CAP_OFFSET 0x04
+#define PCI_DEV3_CTL_OFFSET 0x08
+#define PCI_DEV3_STA_OFFSET 0x0c
+#define PCI_DEV3_SIZEOF 0x10
+
+/* Section 7.7.9.1 Device 3 Extended Capability Header. */
+#define PCI_DEV3_CAP_ID (0x2f << 0)
+#define PCI_DEV3_CAP_VER (0x1 << 16)
+#define PCI_DEV3_NEXT_CAP_OFF (0x0 << 20)
+
+/* Section 7.7.9.3 Device 3 capability register */
+#define PCI_DMWR_REQ_SUPPORTED BIT(0)
+#define PCI_DEV3_CAP_TAG_COMP BIT(1)
+#define PCI_DEV3_CAP_TAG_REQ BIT(2)
+#define PCI_L0P_SUPPORTED BIT(3)
+#define PCI_DEV3_CAP_UIO_COMP BIT(10)
+#define PCI_DEV3_CAP_UIO_REQ BIT(11)
+
+/* Section 7.7.9.3 Device Control 3 Register */
+#define PCI_DEV3_CTL_TAG_REQ_EN BIT(2)
+#define PCI_DEV3_CTL_UIO_REQ_EN BIT(7)
+#define PCI_DEV3_CTL_UIO_256B_DIS BIT(8)
+
+/* Section 7.7.9.4 Device Status 3 Register */
+#define PCI_DEV3_STA_SEGMENT_CAP BIT(3)
+
#endif /* QEMU_PCIE_REGS_H */
--
2.34.1
next prev parent reply other threads:[~2026-08-26 8:15 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20260826052014epcas5p11846c6a40fcec4ec4ba441ceb26e5dcc@epcas5p1.samsung.com>
[not found] ` <20260826053410.1322176-1-shrihari.s@samsung.com>
2026-08-26 5:34 ` [RFC V2 01/10] hw/pci: Refactor flitmode from PCIESlot to PCIEPort Shrihari E S
2026-08-26 5:34 ` [RFC V2 02/10] hw/pci: Move 'x-256b-flit' property from cxl_root_port to pcie_root_port Shrihari E S
2026-08-30 7:20 ` Junjie Cao
2026-08-26 5:34 ` [RFC V2 03/10] hw/pci: Add SVC capability and UIO properties to PCIe ports Shrihari E S
2026-08-30 7:20 ` Junjie Cao
2026-08-26 5:34 ` [RFC V2 04/10] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports Shrihari E S
2026-08-26 5:34 ` [RFC V2 05/10] hw/cxl: Wire UIO capability into HDM decoder and DVSEC registers Shrihari E S
2026-08-30 7:21 ` Junjie Cao
2026-09-10 9:37 ` Shrihari E S
2026-08-26 5:34 ` [RFC V2 06/10] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability Shrihari E S
2026-08-30 7:21 ` Junjie Cao
2026-09-10 8:40 ` Shrihari E S
2026-08-26 5:34 ` [RFC V2 07/10] hw/pci: hw/cxl: Wire SVC initialization into port realize functions Shrihari E S
2026-08-30 7:22 ` Junjie Cao
2026-08-26 5:34 ` Shrihari E S [this message]
2026-08-30 7:22 ` [RFC V2 08/10] hw/pci: Add PCIe Device3 capability support Junjie Cao
2026-08-26 5:34 ` [RFC V2 09/10] hw/cxl: Wire SVC and Dev3 capability to CXL Type 3 device Shrihari E S
2026-08-30 7:23 ` Junjie Cao
2026-08-26 5:34 ` [RFC V2 10/10] cxl: Add documentation for CXL UIO support Shrihari E S
2026-08-30 7:23 ` Junjie Cao
[not found] <CGME20260826051958epcas5p3db6cf2ef9115168c5d8dcec7bdb9b8c3@epcas5p3.samsung.com>
2026-08-26 5:34 ` [RFC V2 0/9] hw/pci: hw/cxl: Add UIO support in CXL and PCIe stack Shrihari E S
2026-08-30 7:19 ` Junjie Cao
2026-09-10 8:22 ` Shrihari E S
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=2044366277.121787732104098.JavaMail.epsvc@epcpadp1new \
--to=shrihari.s@samsung.com \
--cc=arun.george@samsung.com \
--cc=cpgs@samsung.com \
--cc=dave@stgolabs.net \
--cc=dongjoo.seo1@samsung.com \
--cc=gost.dev@samsung.com \
--cc=jic23@kernel.org \
--cc=junjie.cao@intel.com \
--cc=linux-cxl@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=qemu-devel@nongnu.org \
--cc=s.neeraj@samsung.com \
--cc=vikash.k5@samsung.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.