Linux PCI subsystem development
 help / color / mirror / Atom feed
* [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature.
       [not found] <CGME20260609104453epcas5p327a974e978790e693c0660f27f9b43ef@epcas5p3.samsung.com>
@ 2026-06-09 10:58 ` Shrihari E S
  2026-06-09 10:58   ` [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort Shrihari E S
                     ` (7 more replies)
  0 siblings, 8 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

This series introduces enumeration and configuration support for the
PCIe Unordered I/O (UIO) feature across standard PCIe and CXL ports.
UIO, introduced in PCIe 6.1, relaxes strict transaction ordering rules. UIO is
a PCIe transaction layer enhancement which shifts the ordering control from
fabric to the requester device.

This implementation establishes the essential architectural foundation
required for the OS to discover, negotiate, and configure UIO
capabilities.

UIO in CXL follows CXL.io protocol, where a CXL device can send read/write
request to peer .mem device's HDM decoder at fabric level.

      __________________________________________
     |                                          |
     |              CXL Host Bridge             |
     |              (Root Port/RC)              |
     |__________________________________________|
                         |
      ___________________|______________________
     |                                          |
     |               CXL Switch                 |
     |__________________________________________|
        |                  |                 |
     ___|____           ___|_____         ___|____
    |        |         |         |       |        |
    | Dev A  |         | Dev B   |       | Dev C  |
    | (Req)  |         |(Target) |       |(Target)|
    |________|         |_________|       |________|


For example, consider the topology shown above, in that if the requester device
(Dev A) wants to read data from the target device (Dev C), then Dev A can
prepare UIO command with the targeted HPA of Dev C and can send directly to the
Dev C's HDM decoder at switch level. Here host gets bypassed in the data path.
For this to happen, both the devices and the intermediate fabrics should support
UIO and its dependencies.

The implementation relies on two key dependencies:
    - 256B Flit Mode 
    - Streamlined Virtual Channel (SVC) Extended Capability (from PCIe 6.1)

Key changes include:

SVC Capability: Introduced a new hw/pci/pcie_svc.c module to manage the SVC
                extended capability. It handles the mapping of UIO traffic to
                dedicated virtual channels-VC3 (mandatory) and VC4 (optional).

Port Configuration: Added properties (x-uio-svc, x-uio-svc-opt, x-256b-flit) to
                    PCIe and CXL ports to control UIO states.

CXL Integration: Established a dependency chain in CXL root and upstream ports,
                 where UIO is enabled only if both Flit Mode and SVC initialization
                 succeed. The CXL HDM decoders now advertise UIO support per CXL 4.0
                 specifications.

Patch Layout:

Patch 1 and 2: Refactoring: Move Flit mode handling from PCIe slot to PCIe port
               and extend it to all port types.
Patch 3: Properties: Add SVC capability fields and UIO-related properties
         (x-uio-svc, x-uio-svc-opt) to the PCIe port hierarchy.
Patch 4: CXL Properties: Extend SVC properties to CXL ports and add uio_capable
         logic to root/upstream ports.
Patch 5: CXL HDM Decoder: Integrate UIO capability advertising into CXL HDM 
         decoders.
Patch 6: SVC Module: Implement the core PCIe SVC Extended Capability logic
         in pcie_svc.c.
Patch 7: Integration: Hook SVC initialization into the realize functions
         for all PCIe and CXL ports.
Patch 8: Documentation: Add usage examples for UIO-enabled CXL topologies.

Base commit: 3c99db7705c1a885c795b7c14f751c7a3ba29ed8
Repository: https://gitlab.com/jic23/qemu
Branch: cxl-2026-01-09-draft

Testing: Verified through Linux kernel based enumeration and configuration.

Future work: While the current series establishes the configuration
infrastructure, the upcoming series focuses on UIO data transfer support.
A subsequent patch series to be built on top of this series to add support for
UIO data plane.

Shrihari E S (8):
  Refactor flitmode from PCIESlot to PCIEPort.
  Move 'x-256b-flit' property from cxl_root_port to pcie_root_port.
  Add SVC capability and UIO properties to PCIe ports
  Add Streamlined Virtual Channel (SVC) property to CXL ports
  Wire UIO capability into HDM decoder registers
  Add PCIe Streamlined Virtual Channel (SVC) capability.
  Wire SVC initialization into port realize functions.
  Add documentation for UIO-enabled CXL devices

 docs/system/devices/cxl.rst               |  50 +++++++
 hw/cxl/cxl-component-utils.c              |  29 +++-
 hw/mem/cxl_type3.c                        |   9 +-
 hw/pci-bridge/cxl_downstream.c            |  11 +-
 hw/pci-bridge/cxl_root_port.c             |  13 +-
 hw/pci-bridge/cxl_upstream.c              |   9 +-
 hw/pci-bridge/pci_expander_bridge.c       |   3 +-
 hw/pci-bridge/pcie_root_port.c            |   4 +
 hw/pci-bridge/xio3130_downstream.c        |   4 +
 hw/pci-bridge/xio3130_upstream.c          |   9 ++
 hw/pci/meson.build                        |   2 +-
 hw/pci/pci.c                              |   4 +
 hw/pci/pcie.c                             |  53 ++++++-
 hw/pci/pcie_svc.c                         | 164 ++++++++++++++++++++++
 include/hw/cxl/cxl_component.h            |   2 +-
 include/hw/cxl/cxl_device.h               |   2 +
 include/hw/pci-bridge/cxl_upstream_port.h |   1 +
 include/hw/pci/pcie.h                     |   7 +
 include/hw/pci/pcie_port.h                |  23 ++-
 include/hw/pci/pcie_regs.h                |   1 +
 include/hw/pci/pcie_svc.h                 |  91 ++++++++++++
 21 files changed, 466 insertions(+), 25 deletions(-)
 create mode 100644 hw/pci/pcie_svc.c
 create mode 100644 include/hw/pci/pcie_svc.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort.
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  2026-06-16 13:27     ` Jonathan Cameron
  2026-06-09 10:58   ` [RFC 2/8] hw/pci: Move 'x-256b-flit' property from cxl_root_port to pcie_root_port Shrihari E S
                     ` (6 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

Move the 'flitmode' property from PCIESlot to PCIEPort. This change
allows all the derived ports (PCIe ports or CXL ports) to use this
property.

This is a structural refactor only. There is no functional change in
existing behavior.

Note: This property was added from Davidlohr's BI patch series[1].

[1]: https://lore.kernel.org/all/20251103195209.1319917-2-dave@stgolabs.net/

Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
---
 hw/pci-bridge/cxl_downstream.c | 6 +++---
 hw/pci-bridge/cxl_root_port.c  | 6 +++---
 hw/pci/pcie.c                  | 2 +-
 include/hw/pci/pcie_port.h     | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/pci-bridge/cxl_downstream.c b/hw/pci-bridge/cxl_downstream.c
index d1e27994a3..7c7a1d1221 100644
--- a/hw/pci-bridge/cxl_downstream.c
+++ b/hw/pci-bridge/cxl_downstream.c
@@ -118,7 +118,7 @@ static void cxl_dsp_reset(DeviceState *qdev)
 
 static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl)
 {
-    PCIESlot *s = PCIE_SLOT(d);
+    PCIEPort *p = PCIE_PORT(d);
     CXLDVSECRegisterLocator *regloc_dvsec;
     uint8_t *dvsec;
     int i;
@@ -132,7 +132,7 @@ static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl)
     dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){
         .cap                     = 0x27, /* Cache, IO, Mem, non-MLD */
         .ctrl                    = 0x02, /* IO always enabled */
-        .status                  = s->flitmode ? 0x6 : 0x26, /* lack of 68B */
+        .status                  = p->flitmode ? 0x6 : 0x26, /* lack of 68B */
         .rcvd_mod_ts_data_phase1 = 0xef, /* WTF? */
     };
     cxl_component_create_dvsec(cxl, CXL2_DOWNSTREAM_PORT,
@@ -259,7 +259,7 @@ static const Property cxl_dsp_props[] = {
                                 speed, PCIE_LINK_SPEED_64),
     DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
                                 width, PCIE_LINK_WIDTH_16),
-    DEFINE_PROP_BOOL("x-256b-flit", PCIESlot, flitmode, true),
+    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
 };
 
 static void cxl_dsp_class_init(ObjectClass *oc, const void *data)
diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
index 0ee18ef5c3..df69c5200f 100644
--- a/hw/pci-bridge/cxl_root_port.c
+++ b/hw/pci-bridge/cxl_root_port.c
@@ -112,7 +112,7 @@ static void latch_registers(CXLRootPort *crp)
 
 static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl)
 {
-    PCIESlot *s = PCIE_SLOT(d);
+    PCIEPort *p = PCIE_PORT(d);
     CXLDVSECRegisterLocator *regloc_dvsec;
     uint8_t *dvsec;
     int i;
@@ -135,7 +135,7 @@ static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl)
     dvsec = (uint8_t *)&(CXLDVSECPortFlexBus){
         .cap                     = 0x26, /* IO, Mem, non-MLD */
         .ctrl                    = 0x2,
-        .status                  = s->flitmode ? 0x6 : 0x26, /* lack of 68B */
+        .status                  = p->flitmode ? 0x6 : 0x26, /* lack of 68B */
         .rcvd_mod_ts_data_phase1 = 0xef,
     };
     cxl_component_create_dvsec(cxl, CXL2_ROOT_PORT,
@@ -237,7 +237,7 @@ static const Property gen_rp_props[] = {
                                 speed, PCIE_LINK_SPEED_64),
     DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
                                 width, PCIE_LINK_WIDTH_32),
-    DEFINE_PROP_BOOL("x-256b-flit", PCIESlot, flitmode, true),
+    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
 };
 
 static void cxl_rp_dvsec_write_config(PCIDevice *dev, uint32_t addr,
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 1de0b1e4fd..d452199d85 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -217,7 +217,7 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
         /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
     }
 
-    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->flitmode);
+    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->parent_obj.flitmode);
 }
 
 int pcie_cap_init(PCIDevice *dev, uint8_t offset,
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 53cd64c5ed..1bcc734649 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -33,6 +33,7 @@ struct PCIEPort {
     /*< private >*/
     PCIBridge   parent_obj;
     /*< public >*/
+    bool flitmode;
 
     /* pci express switch port */
     uint8_t     port;
@@ -58,7 +59,6 @@ struct PCIESlot {
 
     PCIExpLinkSpeed speed;
     PCIExpLinkWidth width;
-    bool flitmode;
 
     /* Disable ACS (really for a pcie_root_port) */
     bool        disable_acs;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 2/8] hw/pci: Move 'x-256b-flit' property from cxl_root_port to pcie_root_port.
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
  2026-06-09 10:58   ` [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  2026-06-09 10:58   ` [RFC 3/8] hw/pci: Add SVC capability and UIO properties to PCIe ports Shrihari E S
                     ` (5 subsequent siblings)
  7 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

Relocate 'x-256b-flit' property from cxl_root_port to its parent
pcie_root_port so that both can utilize this property.

This is a pure refactor and does not impact any existing behavior.

Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
---
 hw/pci-bridge/cxl_root_port.c  | 1 -
 hw/pci-bridge/pcie_root_port.c | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
index df69c5200f..e82685d1ab 100644
--- a/hw/pci-bridge/cxl_root_port.c
+++ b/hw/pci-bridge/cxl_root_port.c
@@ -237,7 +237,6 @@ static const Property gen_rp_props[] = {
                                 speed, PCIE_LINK_SPEED_64),
     DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
                                 width, PCIE_LINK_WIDTH_32),
-    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
 };
 
 static void cxl_rp_dvsec_write_config(PCIDevice *dev, uint32_t addr,
diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
index fe3ced5685..eeee24e042 100644
--- a/hw/pci-bridge/pcie_root_port.c
+++ b/hw/pci-bridge/pcie_root_port.c
@@ -152,6 +152,7 @@ static const Property rp_props[] = {
     DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
                     QEMU_PCIE_SLTCAP_PCP_BITNR, true),
     DEFINE_PROP_BOOL("disable-acs", PCIESlot, disable_acs, false),
+    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
 };
 
 static void rp_instance_post_init(Object *obj)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 3/8] hw/pci: Add SVC capability and UIO properties to PCIe ports
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
  2026-06-09 10:58   ` [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort Shrihari E S
  2026-06-09 10:58   ` [RFC 2/8] hw/pci: Move 'x-256b-flit' property from cxl_root_port to pcie_root_port Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  2026-06-16 17:20     ` Jonathan Cameron
  2026-06-09 10:58   ` [RFC 4/8] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports Shrihari E S
                     ` (4 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

From: Dongjoo Seo <dongjoo.seo1@samsung.com>

Implement the Streamlined Virtual Channel (SVC) extended capability
for PCIe ports (Root, Upstream, and Downstream). This capability is
mandatory for enabling Unordered IO (UIO) traffic as per PCIe 6.4
specification [1].

UIO functionality depends on two key prerequisites:
  1. SVC support (SVC3 mandatory, SVC4 optional)
  2. 256-byte Flit mode support

This patch adds the following experimental properties to PCIe ports:
  - x-uio-svc: Enable UIO traffic via SVC3 (mandatory path)
  - x-uio-svc-opt: Enable UIO traffic via SVC4 (optional path)
  - x-256b-flit: Enable 256B flit mode required for UIO

Helper functions are included to manage UIO traffic gating and SVC
configuration. This change lays the groundwork for UIO emulation in
QEMU.

[1]: PCIe 6.4 Specification, Table 2-46 (Streamlined Virtual Channel)

Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
---
 hw/pci-bridge/pcie_root_port.c     |  2 ++
 hw/pci-bridge/xio3130_downstream.c |  3 +++
 hw/pci-bridge/xio3130_upstream.c   |  8 ++++++++
 include/hw/pci/pcie_port.h         | 21 +++++++++++++++++++++
 4 files changed, 34 insertions(+)

diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
index eeee24e042..20554bd854 100644
--- a/hw/pci-bridge/pcie_root_port.c
+++ b/hw/pci-bridge/pcie_root_port.c
@@ -153,6 +153,8 @@ static const Property rp_props[] = {
                     QEMU_PCIE_SLTCAP_PCP_BITNR, true),
     DEFINE_PROP_BOOL("disable-acs", PCIESlot, disable_acs, false),
     DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
+    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
+    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
 };
 
 static void rp_instance_post_init(Object *obj)
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index 0c3fed3053..b0b297bb53 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -137,6 +137,9 @@ static void xio3130_downstream_exitfn(PCIDevice *d)
 static const Property xio3130_downstream_props[] = {
     DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
                     QEMU_PCIE_SLTCAP_PCP_BITNR, true),
+    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
+    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
+    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, false),
 };
 
 static const VMStateDescription vmstate_xio3130_downstream = {
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index 40057b749b..925df5add3 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -24,6 +24,7 @@
 #include "hw/pci/msi.h"
 #include "hw/pci/pcie.h"
 #include "hw/pci/pcie_port.h"
+#include "hw/core/qdev-properties.h"
 #include "migration/vmstate.h"
 #include "qemu/module.h"
 
@@ -123,6 +124,12 @@ static const VMStateDescription vmstate_xio3130_upstream = {
     }
 };
 
+static const Property xio3130_upstream_props[] = {
+    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
+    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
+    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, false),
+};
+
 static void xio3130_upstream_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
@@ -138,6 +145,7 @@ static void xio3130_upstream_class_init(ObjectClass *klass, const void *data)
     dc->desc = "TI X3130 Upstream Port of PCI Express Switch";
     device_class_set_legacy_reset(dc, xio3130_upstream_reset);
     dc->vmsd = &vmstate_xio3130_upstream;
+    device_class_set_props(dc, xio3130_upstream_props);
 }
 
 static const TypeInfo xio3130_upstream_info = {
diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
index 1bcc734649..a6b1b8a6cf 100644
--- a/include/hw/pci/pcie_port.h
+++ b/include/hw/pci/pcie_port.h
@@ -37,8 +37,29 @@ struct PCIEPort {
 
     /* pci express switch port */
     uint8_t     port;
+
+    /*
+     * This field declares Streamlined Virtual Channel (SVC) capability.
+     * Per PCIe 6.4 specification section 7.9.29, a pcie port supports
+     * upto 8 SVCs, in that SVC0 is a default one, SVC3 is for UIO traffic
+     * and SVC 4 is shared by both UIO and non-UIO traffic.
+     */
+    uint32_t    svc;
 };
 
+#define UIO_MANDATORY_SVC 3
+#define UIO_OPTIONAL_SVC 4
+
+static inline bool get_uio_mandatory_svc(PCIEPort *port)
+{
+    return (port->svc >> UIO_MANDATORY_SVC) & 1;
+}
+
+static inline bool get_uio_optional_svc(PCIEPort *port)
+{
+    return (port->svc >> UIO_OPTIONAL_SVC) & 1;
+}
+
 void pcie_port_init_reg(PCIDevice *d);
 
 PCIDevice *pcie_find_port_by_pn(PCIBus *bus, uint8_t pn);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 4/8] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
                     ` (2 preceding siblings ...)
  2026-06-09 10:58   ` [RFC 3/8] hw/pci: Add SVC capability and UIO properties to PCIe ports Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  2026-06-16 17:21     ` Jonathan Cameron
  2026-06-09 10:58   ` [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers Shrihari E S
                     ` (3 subsequent siblings)
  7 siblings, 1 reply; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

Add Unordered IO (UIO) dependent property SVC to CXL ports
(Root, Upstream and Downstream).

The following properties are added to CXL ports:
    - x-uio-svc: Enable UIO traffic via SVC3 (mandatory path)
    - x-uio-svc-opt: Enable UIO traffic via SVC4 (optional path)

Note: 256B flit mode property was already added in CXL ports, so reused it.

Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
---
 hw/pci-bridge/cxl_downstream.c            | 2 ++
 hw/pci-bridge/cxl_root_port.c             | 1 +
 hw/pci-bridge/cxl_upstream.c              | 2 ++
 include/hw/pci-bridge/cxl_upstream_port.h | 1 +
 4 files changed, 6 insertions(+)

diff --git a/hw/pci-bridge/cxl_downstream.c b/hw/pci-bridge/cxl_downstream.c
index 7c7a1d1221..6f6f332c07 100644
--- a/hw/pci-bridge/cxl_downstream.c
+++ b/hw/pci-bridge/cxl_downstream.c
@@ -260,6 +260,8 @@ static const Property cxl_dsp_props[] = {
     DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
                                 width, PCIE_LINK_WIDTH_16),
     DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
+    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
+    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
 };
 
 static void cxl_dsp_class_init(ObjectClass *oc, const void *data)
diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
index e82685d1ab..83fb5968b8 100644
--- a/hw/pci-bridge/cxl_root_port.c
+++ b/hw/pci-bridge/cxl_root_port.c
@@ -53,6 +53,7 @@ typedef struct CXLRootPort {
     CPMUState cpmu;
     MemoryRegion cpmu_registers;
     PCIResReserve res_reserve;
+    bool uio_capable;
 } CXLRootPort;
 
 #define TYPE_CXL_ROOT_PORT "cxl-rp"
diff --git a/hw/pci-bridge/cxl_upstream.c b/hw/pci-bridge/cxl_upstream.c
index ef5480b116..dadad3e15c 100644
--- a/hw/pci-bridge/cxl_upstream.c
+++ b/hw/pci-bridge/cxl_upstream.c
@@ -437,6 +437,8 @@ static const Property cxl_upstream_props[] = {
     DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLUpstreamPort,
                                 width, PCIE_LINK_WIDTH_16),
     DEFINE_PROP_BOOL("x-256b-flit", CXLUpstreamPort, flitmode, false),
+    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
+    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
 };
 
 static void cxl_upstream_class_init(ObjectClass *oc, const void *data)
diff --git a/include/hw/pci-bridge/cxl_upstream_port.h b/include/hw/pci-bridge/cxl_upstream_port.h
index d4186234c8..d23541e23a 100644
--- a/include/hw/pci-bridge/cxl_upstream_port.h
+++ b/include/hw/pci-bridge/cxl_upstream_port.h
@@ -22,6 +22,7 @@ typedef struct CXLUpstreamPort {
     PCIExpLinkSpeed speed;
     PCIExpLinkWidth width;
     bool flitmode;
+    bool uio_capable;
 
     DOECap doe_cdat;
     uint64_t sn;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
                     ` (3 preceding siblings ...)
  2026-06-09 10:58   ` [RFC 4/8] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  2026-06-16 17:40     ` Jonathan Cameron
  2026-06-17 15:45     ` Junjie Cao
  2026-06-09 10:58   ` [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability Shrihari E S
                     ` (2 subsequent siblings)
  7 siblings, 2 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

Plumb the 'uio_capable' flag to CXL HDM decoder capability and
control register interfaces. The UIO bit in the capability register
is now set for CXL Type3 devices and ports when UIO support is
advertised via 'x-uio-svc' property.

Per CXL 4.0 specification Section 8.2.4.20.7, the decoder control
UIO bit is validated against the advertised capability during
HDM decoder commit operations.

Additionally, replace hardcoded HDM decoder control write masks
with spec-aligned 'WRMASK' definitions.

Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
---
 hw/cxl/cxl-component-utils.c        | 29 +++++++++++++++++++++++------
 hw/mem/cxl_type3.c                  |  9 ++++++++-
 hw/pci-bridge/cxl_downstream.c      |  2 +-
 hw/pci-bridge/cxl_root_port.c       |  2 +-
 hw/pci-bridge/cxl_upstream.c        |  3 ++-
 hw/pci-bridge/pci_expander_bridge.c |  3 ++-
 include/hw/cxl/cxl_component.h      |  2 +-
 include/hw/cxl/cxl_device.h         |  2 ++
 8 files changed, 40 insertions(+), 12 deletions(-)

diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
index 31bbedb502..9a5b382272 100644
--- a/hw/cxl/cxl-component-utils.c
+++ b/hw/cxl/cxl-component-utils.c
@@ -13,6 +13,19 @@
 #include "hw/pci/pci.h"
 #include "hw/cxl/cxl.h"
 
+/* CXL 4.0 specification 8.4.2.20.7 */
+#define CXL_HDM_DECODER_CTRL_WRMASK (    \
+    (0xfu << 0)   | /* IG */             \
+    (0xfu << 4)   | /* IW */             \
+    BIT(8)        | /* LOCK_ON_COMMIT */ \
+    BIT(9)        | /* COMMIT */         \
+    BIT(12)       | /* TYPE */           \
+    BIT(13)       | /* BI */             \
+    BIT(14)       | /* UIO */            \
+    (0xfu << 16)  | /* UIG */            \
+    (0xfu << 20)  | /* UIW */            \
+    (0xfu << 24))   /* ISP */
+
 /* CXL r3.1 Section 8.2.4.20.1 CXL HDM Decoder Capability Register */
 int cxl_decoder_count_enc(int count)
 {
@@ -305,7 +318,7 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
 }
 
 static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
-                            enum reg_type type, bool bi)
+                            enum reg_type type, bool bi, bool uio)
 {
     int decoder_count = CXL_HDM_DECODER_COUNT;
     int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
@@ -325,9 +338,12 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
         ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
         ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
     }
-    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO, 0);
+    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO,
+                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio);
     ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
-                     UIO_DECODER_COUNT, 0);
+                     UIO_DECODER_COUNT,
+                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio ?
+                     decoder_count : 0);
     ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, MEMDATA_NXM_CAP, 0);
     ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
                      SUPPORTED_COHERENCY_MODEL,
@@ -341,7 +357,8 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
         write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc] = 0xffffffff;
         write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc] = 0xf0000000;
         write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc] = 0xffffffff;
-        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] = 0x13ff;
+        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] =
+                                             CXL_HDM_DECODER_CTRL_WRMASK;
         if (type == CXL2_DEVICE ||
             type == CXL2_TYPE3_DEVICE ||
             type == CXL2_LOGICAL_DEVICE) {
@@ -391,7 +408,7 @@ static void bi_decoder_init_common(uint32_t *reg_state, uint32_t *write_msk,
 void cxl_component_register_init_common(uint32_t *reg_state,
                                         uint32_t *write_msk,
                                         enum reg_type type,
-                                        bool bi)
+                                        bool bi, bool uio)
 {
     int caps = 0;
 
@@ -431,7 +448,7 @@ void cxl_component_register_init_common(uint32_t *reg_state,
     case CXL2_LOGICAL_DEVICE:
         /* + HDM */
         init_cap_reg(HDM, 5, 1);
-        hdm_init_common(reg_state, write_msk, type, bi);
+        hdm_init_common(reg_state, write_msk, type, bi, uio);
         /* fallthrough */
     case CXL2_DOWNSTREAM_PORT:
     case CXL2_DEVICE:
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index b7ad437cbc..4cdadc3e10 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -590,6 +590,11 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
     /* TODO: Sanity checks that the decoder is possible */
     ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
     ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
+    if (ct3d->uio_capable) {
+        ct3d->uio_enabled = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, UIO);
+    } else {
+        ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, UIO, 0);
+    }
 
     /* Get interleave details for chmu */
     ig = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IG);
@@ -1512,7 +1517,8 @@ void ct3d_reset(DeviceState *dev)
     pcie_cap_fill_link_ep_usp(PCI_DEVICE(dev), ct3d->width, ct3d->speed,
                               ct3d->flitmode);
     cxl_component_register_init_common(reg_state, write_msk,
-                                       CXL2_TYPE3_DEVICE, ct3d->hdmdb);
+                                       CXL2_TYPE3_DEVICE, ct3d->hdmdb,
+                                       ct3d->uio_capable);
     cxl_device_register_init_t3(ct3d, CXL_T3_MSIX_MBOX);
 
     /*
@@ -1552,6 +1558,7 @@ static const Property ct3_props[] = {
                                 width, PCIE_LINK_WIDTH_16),
     DEFINE_PROP_BOOL("x-256b-flit", CXLType3Dev, flitmode, false),
     DEFINE_PROP_BOOL("hdm-db", CXLType3Dev, hdmdb, false),
+    DEFINE_PROP_BOOL("x-uio", CXLType3Dev, uio_capable, false),
     DEFINE_PROP_UINT16("chmu-port", CXLType3Dev, cxl_dstate.chmu[0].port, 0),
 };
 
diff --git a/hw/pci-bridge/cxl_downstream.c b/hw/pci-bridge/cxl_downstream.c
index 6f6f332c07..e0fa6cfdc4 100644
--- a/hw/pci-bridge/cxl_downstream.c
+++ b/hw/pci-bridge/cxl_downstream.c
@@ -42,7 +42,7 @@ static void latch_registers(CXLDownstreamPort *dsp)
     uint32_t *write_msk = dsp->cxl_cstate.crb.cache_mem_regs_write_mask;
 
     cxl_component_register_init_common(reg_state, write_msk,
-                                       CXL2_DOWNSTREAM_PORT, true);
+                                       CXL2_DOWNSTREAM_PORT, true, false);
 }
 
 /* TODO: Look at sharing this code across all CXL port types */
diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
index 83fb5968b8..4be2b400f9 100644
--- a/hw/pci-bridge/cxl_root_port.c
+++ b/hw/pci-bridge/cxl_root_port.c
@@ -108,7 +108,7 @@ static void latch_registers(CXLRootPort *crp)
     uint32_t *write_msk = crp->cxl_cstate.crb.cache_mem_regs_write_mask;
 
     cxl_component_register_init_common(reg_state, write_msk, CXL2_ROOT_PORT,
-                                       true);
+                                       true, crp->uio_capable);
 }
 
 static void build_dvsecs(PCIDevice *d, CXLComponentState *cxl)
diff --git a/hw/pci-bridge/cxl_upstream.c b/hw/pci-bridge/cxl_upstream.c
index dadad3e15c..a75d10e7b4 100644
--- a/hw/pci-bridge/cxl_upstream.c
+++ b/hw/pci-bridge/cxl_upstream.c
@@ -136,7 +136,8 @@ static void latch_registers(CXLUpstreamPort *usp)
     uint32_t *write_msk = usp->cxl_cstate.crb.cache_mem_regs_write_mask;
 
     cxl_component_register_init_common(reg_state, write_msk,
-                                       CXL2_UPSTREAM_PORT, usp->flitmode);
+                                       CXL2_UPSTREAM_PORT, usp->flitmode,
+                                       usp->uio_capable);
     ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, TARGET_COUNT, 8);
 }
 
diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
index 25dfee6a9b..18b61eca20 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -301,7 +301,8 @@ static void pxb_cxl_dev_reset(DeviceState *dev)
     uint32_t *write_msk = cxl_cstate->crb.cache_mem_regs_write_mask;
     int dsp_count = 0;
 
-    cxl_component_register_init_common(reg_state, write_msk, CXL2_RC, false);
+    cxl_component_register_init_common(reg_state, write_msk, CXL2_RC, false,
+                                       false);
     /*
      * The CXL specification allows for host bridges with no HDM decoders
      * if they only have a single root port.
diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
index d734f88d2c..662fdb0833 100644
--- a/include/hw/cxl/cxl_component.h
+++ b/include/hw/cxl/cxl_component.h
@@ -315,7 +315,7 @@ void cxl_component_register_block_init(Object *obj,
                                        const char *type);
 void cxl_component_register_init_common(uint32_t *reg_state,
                                         uint32_t *write_msk,
-                                        enum reg_type type, bool bi);
+                                        enum reg_type type, bool bi, bool uio);
 
 void cxl_component_create_dvsec(CXLComponentState *cxl_cstate,
                                 enum reg_type cxl_dev_type, uint16_t length,
diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h
index 3b5dcb5aec..20a1a90014 100644
--- a/include/hw/cxl/cxl_device.h
+++ b/include/hw/cxl/cxl_device.h
@@ -883,6 +883,8 @@ struct CXLType3Dev {
     PCIExpLinkSpeed speed;
     PCIExpLinkWidth width;
     bool flitmode;
+    bool uio_capable;
+    bool uio_enabled;
 
     /* DOE */
     DOECap doe_cdat;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability.
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
                     ` (4 preceding siblings ...)
  2026-06-09 10:58   ` [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  2026-06-16 18:46     ` Jonathan Cameron
  2026-06-17 15:45     ` Junjie Cao
  2026-06-09 10:58   ` [RFC 7/8] hw/pci: hw/cxl: Wire SVC initialization into port realize functions Shrihari E S
  2026-06-09 10:58   ` [RFC 8/8] cxl: Add documentation for UIO-enabled CXL devices Shrihari E S
  7 siblings, 2 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

From: Dongjoo Seo <dongjoo.seo1@samsung.com>

Implement the PCIe Streamlined Virtual Channel (SVC) Extended
Capability by adding support of capability, control and status
registers per PCIe 6.4 section 7.9.29. This capability is one
of the main requisites for UIO support in both PCIe and CXL ports.

Key changes include:
    - New pcie_svc.c file for SVC capability management.
    - Updated pcie_cap_fill_lnk() to handle flitmode signaling.
    - Implement Lifecycle hooks (reset and config_write) to manage
      SVC state.

Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
---
 hw/pci/meson.build         |   2 +-
 hw/pci/pci.c               |   4 +
 hw/pci/pcie.c              |  53 ++++++++++--
 hw/pci/pcie_svc.c          | 164 +++++++++++++++++++++++++++++++++++++
 include/hw/pci/pcie.h      |   7 ++
 include/hw/pci/pcie_regs.h |   1 +
 include/hw/pci/pcie_svc.h  |  91 ++++++++++++++++++++
 7 files changed, 316 insertions(+), 6 deletions(-)
 create mode 100644 hw/pci/pcie_svc.c
 create mode 100644 include/hw/pci/pcie_svc.h

diff --git a/hw/pci/meson.build b/hw/pci/meson.build
index b9c34b2acf..d55882a0c9 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'))
+pci_ss.add(files('pcie.c', 'pcie_aer.c', 'pcie_svc.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 5996229c81..0469250f42 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -30,6 +30,7 @@
 #include "hw/pci/pci_bridge.h"
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_svc.h"
 #include "hw/core/qdev-properties.h"
 #include "hw/core/qdev-properties-system.h"
 #include "migration/cpr.h"
@@ -568,6 +569,7 @@ static void pci_do_device_reset(PCIDevice *dev)
     msi_reset(dev);
     msix_reset(dev);
     pcie_sriov_pf_reset(dev);
+    pcie_svc_cap_reset(dev);
 }
 
 /*
@@ -1814,6 +1816,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int
     msi_write_config(d, addr, val_in, l);
     msix_write_config(d, addr, val_in, l);
     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);
 }
 
 /***********************************************************/
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index d452199d85..7c7d948e00 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -112,8 +112,9 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
 }
 
 /* Includes setting the target speed default */
-static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
-                              PCIExpLinkSpeed speed, bool flitmode)
+static void pcie_cap_fill_lnk(PCIDevice *dev, uint8_t *exp_cap,
+                              PCIExpLinkWidth width, PCIExpLinkSpeed speed,
+                              bool flitmode)
 {
     /* Clear and fill LNKCAP from what was configured above */
     pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
@@ -160,8 +161,14 @@ static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
     }
 
     if (flitmode) {
-        pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
+        uint32_t pos = dev->exp.exp_cap;
+
+        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
                                    PCI_EXP_LNKSTA2_FLIT);
+        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
+                                   PCI_EXP_FLAGS_FLIT);
+        pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_LNKCTL,
+                                   PCI_EXP_LNKCTL_FLIT_DIS);
     }
 }
 
@@ -180,9 +187,44 @@ void pcie_cap_fill_link_ep_usp(PCIDevice *dev, PCIExpLinkWidth width,
                                QEMU_PCI_EXP_LNKSTA_NLW(width) |
                                QEMU_PCI_EXP_LNKSTA_CLS(speed));
 
-    pcie_cap_fill_lnk(exp_cap, width, speed, flitmode);
+    pcie_cap_fill_lnk(dev, exp_cap, width, speed, flitmode);
 }
 
+void pcie_cap_flit_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
+                                int len)
+{
+    uint8_t *exp_cap;
+    uint16_t lnksta2;
+    uint16_t lnkctl;
+    uint16_t flags;
+
+    if (!pci_is_express(dev) || !dev->exp.exp_cap) {
+        return;
+    }
+
+    if (!ranges_overlap(addr, len,
+                        dev->exp.exp_cap + PCI_EXP_LNKCTL, 2)) {
+        return;
+    }
+
+    exp_cap = dev->config + dev->exp.exp_cap;
+    flags = pci_get_word(exp_cap + PCI_EXP_FLAGS);
+    if (!(flags & PCI_EXP_FLAGS_FLIT)) {
+        return;
+    }
+
+    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) {
+        lnksta2 &= ~PCI_EXP_LNKSTA2_FLIT;
+    } else {
+        lnksta2 |= PCI_EXP_LNKSTA2_FLIT;
+    }
+
+    pci_set_word(exp_cap + PCI_EXP_LNKSTA2, lnksta2);
+ }
+
 static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
 {
     PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
@@ -217,7 +259,8 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
         /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
     }
 
-    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->parent_obj.flitmode);
+    pcie_cap_fill_lnk(dev, exp_cap, s->width, s->speed,
+                      s->parent_obj.flitmode);
 }
 
 int pcie_cap_init(PCIDevice *dev, uint8_t offset,
diff --git a/hw/pci/pcie_svc.c b/hw/pci/pcie_svc.c
new file mode 100644
index 0000000000..84db73de58
--- /dev/null
+++ b/hw/pci/pcie_svc.c
@@ -0,0 +1,164 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * PCIe Streamlined Virtual Channel (SVC) Extended Capability
+ *
+ * Copyright (c) 2026 Samsung Electronics Co., Ltd.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "hw/pci/pci_device.h"
+#include "hw/pci/pcie.h"
+#include "hw/pci/pcie_svc.h"
+#include "hw/pci/pcie_port.h"
+
+static void pcie_svc_update_map(PCIDevice *dev)
+{
+    uint32_t non_uio_ctrl = SVC_VC0_PROTOCOL | SVC_VC_ENABLE;
+    uint32_t uio_ctrl = SVC_UIO_PROTOCOL_SELECTED | SVC_VC_ENABLE;
+    int offset;
+
+    if (!pci_is_express(dev) || !dev->exp.svc_cap) {
+        return;
+    }
+
+    offset = pcie_find_capability(dev, PCI_EXT_CAP_ID_SVC);
+
+    /* SVC VC0 & VC3 initialization */
+    pci_set_long(dev->config + offset + SVC_RES_CTRL(0), BIT(0) | non_uio_ctrl);
+    pci_set_long(dev->config + offset + SVC_RES_CTRL(3), BIT(3) | uio_ctrl);
+
+    /* SVC VC4 initialization - optional */
+    if (dev->exp.svc.uio_opt_svc) {
+        pci_set_long(dev->config + offset + SVC_RES_CTRL(4), BIT(4) | uio_ctrl);
+    }
+}
+
+int pcie_config_uio_svc(PCIDevice *d, Error **errp)
+{
+    PCIEPort *p = PCIE_PORT(d);
+
+    if (!get_uio_mandatory_svc(p)
+        || pcie_svc_cap_init(d, PCI_EXT_CAP_BASE_OFFSET, errp) < 0) {
+        return -1;
+    }
+
+    if (get_uio_optional_svc(p)) {
+        pcie_svc_set_vc4(d, true);
+    }
+
+    return 0;
+}
+
+int pcie_svc_cap_init(PCIDevice *dev, uint16_t offset, Error **errp)
+{
+    uint32_t hdr;
+
+    if (!pci_is_express(dev)) {
+        error_setg(errp, "SVC ECAP requires PCIe");
+        return -EINVAL;
+    }
+
+    /*
+     * If no other ECAPs are present, make SVC the first at 0x100.
+     * This avoids pcie_add_capability() asserting on a non-0x100 offset.
+     */
+    hdr = pci_get_long(dev->config + PCI_CONFIG_SPACE_SIZE);
+    if (hdr == 0) {
+        offset = PCI_CONFIG_SPACE_SIZE;
+    }
+
+    pcie_add_capability(dev, PCI_EXT_CAP_ID_SVC, 1, offset,
+                        PCI_EXT_CAP_SVC_SIZE);
+    dev->exp.svc_cap = offset;
+    dev->exp.svc.ctrl = 0;
+    dev->exp.svc.status = 0;
+    dev->exp.svc.uio_mand_svc = true;
+    dev->exp.svc.uio_opt_svc = false;
+
+    pci_set_long(dev->config + offset + PCIE_SVC_CAP_HEAD_OFFSET,
+                 (NEXT_CAP_OFF | PCIE_SVC_CAP_VER | PCI_EXT_CAP_ID_SVC));
+    pci_set_long(dev->wmask + offset + PCIE_SVC_CTL_OFFSET,
+                 PCIE_SVC_CTL_ENABLE);
+    pci_set_long(dev->config + offset + PCIE_SVC_CAP_OFFSET,
+                 PCIE_SVC_CAP1_EVCC);
+
+    for (int i = 0; i <= PCIE_SVC_CAP1_EVCC; i++) {
+        uint32_t res_cap_value = (1U << 8) | SVC_VC_ID(i);
+        uint32_t res_ctrl_value = SVC_TC_VC_MAP_ENABLE
+                                  | SVC_VC_PROTOCOL_SELECTED
+                                  | SHARED_FLOW_CONTROL_USAGE_LIMIT_ENABLE
+                                  | SHARED_FLOW_CONTROL_USAGE_LIMIT
+                                  | SVC_VC_ENABLE;
+
+        if (i == 0) {
+            res_cap_value = SVC_VC0_PROTOCOL | SVC_VC_ID(i);
+        } else if (i == 3) {
+            res_cap_value = SVC_VC3_PROTOCOL | SVC_VC_ID(i);
+        } else if (i == 4) {
+            res_cap_value = SVC_VC4_PROTOCOL | SVC_VC_ID(i);
+        }
+
+        pci_set_long(dev->config + offset + SVC_RES_CAP(i), res_cap_value);
+        pci_set_long(dev->wmask + offset + SVC_RES_CTRL(i), res_ctrl_value);
+        pci_set_long(dev->config + offset + SVC_RES_STATUS(i), 0);
+    }
+    pcie_svc_update_map(dev);
+    return 0;
+}
+
+void pcie_svc_cap_reset(PCIDevice *dev)
+{
+    uint32_t offset;
+
+    if (!pci_is_express(dev) || !dev->exp.svc_cap) {
+        return;
+    }
+
+    offset = dev->exp.svc_cap;
+    dev->exp.svc.ctrl = 0;
+    dev->exp.svc.status = 0;
+    pcie_svc_update_map(dev);
+    pci_set_long(dev->config + offset + PCIE_SVC_CTL_OFFSET, 0);
+    pci_set_long(dev->config + offset + PCIE_SVC_STA_OFFSET, 0);
+}
+
+void pcie_svc_set_vc4(PCIDevice *dev, bool enable)
+{
+    if (!pci_is_express(dev) || !dev->exp.svc_cap) {
+        return;
+    }
+
+    dev->exp.svc.uio_opt_svc = enable;
+    pcie_svc_update_map(dev);
+}
+
+static void pcie_svc_apply_gating(PCIDevice *dev)
+{
+    uint16_t offset = dev->exp.svc_cap;
+    uint32_t ctrl, status;
+
+    if (!offset) {
+        return;
+    }
+
+    ctrl = pci_get_long(dev->config + offset + PCIE_SVC_CTL_OFFSET);
+    status = pci_get_long(dev->config + offset + PCIE_SVC_STA_OFFSET);
+    dev->exp.svc.ctrl = ctrl;
+    dev->exp.svc.status = status;
+}
+
+void pcie_svc_cap_write_config(PCIDevice *dev,
+                               uint32_t addr, uint32_t val, int len)
+{
+    uint16_t offset = dev->exp.svc_cap;
+
+    if (!offset) {
+        return;
+    }
+
+    if (ranges_overlap(addr, len, offset + PCIE_SVC_CTL_OFFSET, 4)) {
+        pcie_svc_apply_gating(dev);
+    }
+}
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 79808126dc..35db0f0c5e 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -25,6 +25,7 @@
 #include "hw/pci/pcie_regs.h"
 #include "hw/pci/pcie_aer.h"
 #include "hw/pci/pcie_sriov.h"
+#include "hw/pci/pcie_svc.h"
 #include "hw/core/hotplug.h"
 
 typedef struct PCIEPort PCIEPort;
@@ -82,6 +83,10 @@ struct PCIExpressDevice {
     uint16_t sriov_cap;
     PCIESriovPF sriov_pf;
     PCIESriovVF sriov_vf;
+
+    /* Streamlined Virtual Channel (SVC) introduced from PCIe 6.1 */
+    uint16_t svc_cap;
+    PCIESvcCap svc;
 };
 
 #define COMPAT_PROP_PCP "power_controller_present"
@@ -143,6 +148,8 @@ void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num);
 void pcie_ats_init(PCIDevice *dev, uint16_t offset, bool aligned);
 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);
 
 void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
                                Error **errp);
diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
index 33a22229fe..644da744b2 100644
--- a/include/hw/pci/pcie_regs.h
+++ b/include/hw/pci/pcie_regs.h
@@ -81,6 +81,7 @@ typedef enum PCIExpLinkWidth {
 #define PCI_EXP_DEVCAP2_EETLPP          0x200000
 
 #define PCI_EXP_DEVCTL2_EETLPPB         0x8000
+#define  PCI_EXP_LNKCTL_FLIT_DIS        0x2000
 
 /* ARI */
 #define PCI_ARI_VER                     1
diff --git a/include/hw/pci/pcie_svc.h b/include/hw/pci/pcie_svc.h
new file mode 100644
index 0000000000..4872905501
--- /dev/null
+++ b/include/hw/pci/pcie_svc.h
@@ -0,0 +1,91 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * PCIe Streamlined Virtual Channel (SVC) Extended Capability
+ *
+ * Copyright (c) 2026 Samsung Electronics Co., Ltd.
+ */
+
+#ifndef HW_PCIE_SVC_H
+#define HW_PCIE_SVC_H
+
+#include "hw/pci/pci.h"
+#include "qemu/bitops.h"
+
+/*
+ * The PCIe config space starts from 0x00 till 0xFF. In that
+ * extended capability starts from 0x100 and each extended capability
+ * is of dword size (32 bit). So we have to give a proper base offset
+ * value which should be >= 0x100 and <= 0xFF and in between other
+ * capability will also be registerd. We might not know where exactly
+ * SVC extended capability will sit, so to avoid the overlapping we have
+ * to give a very high offset.
+ */
+#define PCI_EXT_CAP_BASE_OFFSET                0x200
+#define PCI_EXT_CAP_ID_SVC                     0x35
+#define PCI_EXT_CAP_SVC_SIZE                   0x74
+
+/* PCIe 6.4 section 7.9.29 */
+#define PCIE_SVC_CAP_HEAD_OFFSET               0x00
+#define PCIE_SVC_CAP_OFFSET                    0x04
+#define PCIE_SVC_CTL_OFFSET                    0x0c
+#define PCIE_SVC_STA_OFFSET                    0x10
+#define PCIE_SVC_CTL_ENABLE                    BIT(0)
+#define PCIE_SVC_CAP1_EVCC                     (0x7 << 0)
+
+/* 7.9.29.1 SVC extended capability header  */
+#define PCIE_SVC_CAP_VER                       (1 << 16)
+#define NEXT_CAP_OFF                           (0 << 20)
+
+/* 7.9.29.6 SVC Resource capability Register */
+#define SVC_RES_CAP_BASE                       0x14
+#define SVC_RES_CAP(n)                         (SVC_RES_CAP_BASE + (n) * 0x0c)
+
+/*
+ * As per Specification SVC VC3 is dedicated to UIO and non-UIO traffic cannot
+ * use that, so for SVC VC3 the value would be 0010. SVC VC4 is an optional VC
+ * for UIO and VC4 can be used by non-UIO traffic as well. So the protocol for
+ * VC4 would be 0011. For SVC VC0, the protocol is 0000. Rest are all reserved
+ * asper table 2-46 in PCIe 6.4 specification.
+ */
+#define SVC_VC0_PROTOCOL                       (0x0 << 8)
+#define SVC_VC3_PROTOCOL                       (0x2 << 8)
+#define SVC_VC4_PROTOCOL                       (0x3 << 8)
+#define SVC_VC_ID(n)                           ((n & 0x7) << 12)
+
+/* 7.9.27.7 SVC Resource Control Register */
+#define SVC_RES_CTRL_BASE                      0x18
+#define SVC_RES_CTRL(n)                        (SVC_RES_CTRL_BASE + (n) * 0x0c)
+#define SVC_VC_ENABLE                          BIT(31)
+#define SHARED_FLOW_CONTROL_USAGE_LIMIT_ENABLE BIT(30)
+#define SVC_VC_PROTOCOL_SELECTED               (0xf << 8)
+#define SVC_UIO_PROTOCOL_SELECTED              (0x2 << 8)
+/*
+ * As per Table 7-350 in 7.9.29.7 in PCIe 6.4 Specification, the protocol
+ * selected should be 0010 for UIO enabled VCs
+ */
+#define SHARED_FLOW_CONTROL_USAGE_LIMIT        (0x7 << 27)
+#define SVC_TC_VC_MAP_ENABLE                   (0xff << 0)
+#define SVC_TC_VC_MAP(n)                       ((n & 0xff) << 0)
+
+/* 7.9.27.8 SVC Resource Status Register */
+#define SVC_RES_STATUS_BASE                    0x1c
+#define SVC_RES_STATUS(n)                      (SVC_RES_STATUS_BASE + \
+                                                (n) * 0x0c)
+#define SVC_VC_NEGO                            BIT(1)
+
+typedef struct PCIESvcCap {
+    uint32_t ctrl;
+    uint32_t status;
+    bool uio_mand_svc;
+    bool uio_opt_svc;
+} PCIESvcCap;
+
+int pcie_config_uio_svc(PCIDevice *d, Error **errp);
+int  pcie_svc_cap_init(PCIDevice *dev, uint16_t offset, Error **errp);
+void pcie_svc_cap_reset(PCIDevice *dev);
+void pcie_svc_set_vc4(PCIDevice *dev, bool enable);
+void pcie_svc_cap_write_config(PCIDevice *dev,
+                               uint32_t addr, uint32_t val, int len);
+
+#endif /* HW_PCIE_SVC_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 7/8] hw/pci: hw/cxl: Wire SVC initialization into port realize functions.
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
                     ` (5 preceding siblings ...)
  2026-06-09 10:58   ` [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  2026-06-17 15:45     ` Junjie Cao
  2026-06-09 10:58   ` [RFC 8/8] cxl: Add documentation for UIO-enabled CXL devices Shrihari E S
  7 siblings, 1 reply; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

Integrate Streamlined Virtual Channel (SVC) capability initialization into the
realize() functions of both PCIe and CXL ports. This change ensures that the
'uio_capable' flag is correctly populated in CXL ports during the initialization
sequence.

'uio_capable' in CXL ports is responsible for enabling UIO capability in
HDM decoder registers.

Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
---
 hw/pci-bridge/cxl_downstream.c     | 1 +
 hw/pci-bridge/cxl_root_port.c      | 5 +++++
 hw/pci-bridge/cxl_upstream.c       | 4 ++++
 hw/pci-bridge/pcie_root_port.c     | 1 +
 hw/pci-bridge/xio3130_downstream.c | 1 +
 hw/pci-bridge/xio3130_upstream.c   | 1 +
 6 files changed, 13 insertions(+)

diff --git a/hw/pci-bridge/cxl_downstream.c b/hw/pci-bridge/cxl_downstream.c
index e0fa6cfdc4..a9eaeb81bb 100644
--- a/hw/pci-bridge/cxl_downstream.c
+++ b/hw/pci-bridge/cxl_downstream.c
@@ -229,6 +229,7 @@ static void cxl_dsp_realize(PCIDevice *d, Error **errp)
                      PCI_BASE_ADDRESS_SPACE_MEMORY |
                          PCI_BASE_ADDRESS_MEM_TYPE_64,
                      &dsp->bar);
+    pcie_config_uio_svc(d, errp);
 
     return;
 
diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
index 4be2b400f9..eafcf59f83 100644
--- a/hw/pci-bridge/cxl_root_port.c
+++ b/hw/pci-bridge/cxl_root_port.c
@@ -164,6 +164,7 @@ static void cxl_rp_realize(DeviceState *dev, Error **errp)
 {
     PCIDevice *pci_dev     = PCI_DEVICE(dev);
     PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev);
+    PCIEPort *p            = PCIE_PORT(dev);
     CXLRootPort *crp       = CXL_ROOT_PORT(dev);
     CXLComponentState *cxl_cstate = &crp->cxl_cstate;
     ComponentRegisters *cregs = &cxl_cstate->crb;
@@ -212,6 +213,10 @@ static void cxl_rp_realize(DeviceState *dev, Error **errp)
                      PCI_BASE_ADDRESS_SPACE_MEMORY |
                      PCI_BASE_ADDRESS_MEM_TYPE_64,
                      &crp->bar);
+    rc = pcie_config_uio_svc(pci_dev, errp);
+    if (p->flitmode && rc >= 0) {
+        crp->uio_capable = true;
+    }
 }
 
 static void cxl_rp_reset_hold(Object *obj, ResetType type)
diff --git a/hw/pci-bridge/cxl_upstream.c b/hw/pci-bridge/cxl_upstream.c
index a75d10e7b4..f6f5713437 100644
--- a/hw/pci-bridge/cxl_upstream.c
+++ b/hw/pci-bridge/cxl_upstream.c
@@ -411,6 +411,10 @@ static void cxl_usp_realize(PCIDevice *d, Error **errp)
         goto err_cap;
     }
 
+    rc = pcie_config_uio_svc(d, errp);
+    if (p->flitmode && rc >= 0) {
+        usp->uio_capable = true;
+    }
     return;
 
 err_cap:
diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
index 20554bd854..5a74b0e978 100644
--- a/hw/pci-bridge/pcie_root_port.c
+++ b/hw/pci-bridge/pcie_root_port.c
@@ -97,6 +97,7 @@ static void rp_realize(PCIDevice *d, Error **errp)
         goto err_int;
     }
 
+    pcie_config_uio_svc(d, errp);
     pcie_cap_arifwd_init(d);
     pcie_cap_deverr_init(d);
     pcie_cap_slot_init(d, s);
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index b0b297bb53..cc19fb1213 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -93,6 +93,7 @@ static void xio3130_downstream_realize(PCIDevice *d, Error **errp)
     if (rc < 0) {
         goto err_msi;
     }
+    pcie_config_uio_svc(d, errp);
     pcie_cap_flr_init(d);
     pcie_cap_deverr_init(d);
     pcie_cap_slot_init(d, s);
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index 925df5add3..c28339dabe 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -84,6 +84,7 @@ static void xio3130_upstream_realize(PCIDevice *d, Error **errp)
     if (rc < 0) {
         goto err_msi;
     }
+    pcie_config_uio_svc(d, errp);
     pcie_cap_flr_init(d);
     pcie_cap_deverr_init(d);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [RFC 8/8] cxl: Add documentation for UIO-enabled CXL devices
  2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
                     ` (6 preceding siblings ...)
  2026-06-09 10:58   ` [RFC 7/8] hw/pci: hw/cxl: Wire SVC initialization into port realize functions Shrihari E S
@ 2026-06-09 10:58   ` Shrihari E S
  7 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-09 10:58 UTC (permalink / raw)
  To: jic23, linux-cxl, linux-pci, qemu-devel, cpgs
  Cc: arun.george, vikash.k5, s.neeraj, shrihari.s, dongjoo.seo1, dave,
	gost.dev

Add a command-line example demonstrating a topology with three CXL Type-3
devices connected via a switch. This example enables Unordered I/O (UIO) on
all ports and endpoints to illustrate the correct usage of UIO-related
properties.

Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
---
 docs/system/devices/cxl.rst | 50 +++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/docs/system/devices/cxl.rst b/docs/system/devices/cxl.rst
index 32b1b5d773..c39721b3f9 100644
--- a/docs/system/devices/cxl.rst
+++ b/docs/system/devices/cxl.rst
@@ -407,6 +407,56 @@ use HDM-DB for coherence, which requires operating in Flit mode::
   -device cxl-type3,bus=swport3,volatile-memdev=cxl-mem3,id=cxl-mem3,sn=0x4 \
   -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
 
+Unordered I/O (UIO) Support
+---------------------------
+
+CXL 3.2 and PCIe 6.1 introduce Unordered I/O (UIO), which allows memory
+transactions to bypass strict ordering requirements, potentially improving
+performance for certain workloads. UIO support requires:
+
+1. **256-byte Flit Mode**: Enabled via ``x-256b-flit=on`` on all ports and devices
+2. **Streamlined Virtual Channel (SVC)**: A PCIe 6.1 extended capability that
+   provides dedicated virtual channels for UIO traffic
+
+The SVC capability defines two paths for UIO traffic:
+
+- **SVC3 (Mandatory)**: Dedicated VC for UIO traffic only (``x-uio-svc=on``)
+- **SVC4 (Optional)**: Shared VC for both UIO and non-UIO traffic
+  (``x-uio-svc-opt=on``)
+
+Both paths require 256B flit mode. The CXL Type 3 device uses the ``x-uio=on``
+property to advertise UIO capability, which is then reflected in the HDM decoder
+capability registers.
+
+**Note**: Per the CXL specification, downstream switch ports do not track UIO
+capability separately; only root ports and upstream ports maintain the UIO
+capability.
+
+An example of 3 type3 devices with volatile memory below a switch. All the devices
+and ports support Unordered IO (UIO) feature which requires Streamlined Virtual Channel
+(SVC) capability and Flit mode::
+
+  qemu-system-x86_64 -M q35,cxl=on -m 4G,maxmem=8G,slots=8 -smp 4 \
+  ...
+  -device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1 \
+  -device cxl-rp,port=0,bus=cxl.1,id=rp13,chassis=0,slot=2,x-uio-svc=on,
+   x-uio-svc-opt=on,x-256b-flit=on,x-speed=64,x-width=32 \
+  -device cxl-upstream,port=2,sn=1234,bus=rp13,id=us0,x-uio-svc=on,
+   x-uio-svc-opt=on,x-256b-flit=on,x-speed=64,x-width=32 \
+  -device cxl-downstream,port=0,bus=us0,id=swport0,chassis=0,slot=4,
+   x-uio-svc=on,x-uio-svc-opt=on,x-256b-flit=on,x-speed=64,x-width=32 \
+  -device cxl-downstream,port=1,bus=us0,id=swport1,chassis=0,slot=5,
+   x-uio-svc=on,x-uio-svc-opt=on,x-256b-flit=on,x-speed=64,x-width=32  \
+  -device cxl-downstream,port=3,bus=us0,id=swport2,chassis=0,slot=6,
+   x-uio-svc=on,x-uio-svc-opt=on,x-256b-flit=on,x-speed=64,x-width=32  \
+  -object memory-backend-ram,id=target-mem1,size=512M \
+  -object memory-backend-ram,id=target-mem2,size=512M \
+  -object memory-backend-ram,id=target-mem3,size=512M \
+  -device cxl-type3,id=mem1,bus=swport0,volatile-memdev=target-mem1,x-uio=on,x-256b-flit=on,sn=1233 \
+  -device cxl-type3,id=mem2,bus=swport1,volatile-memdev=target-mem2,x-uio=on,x-256b-flit=on,sn=1234 \
+  -device cxl-type3,id=mem3,bus=swport2,volatile-memdev=target-mem3,x-uio=on,x-256b-flit=on,sn=1235 \
+  -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=4k
+
 A simple arm/virt example featuring a single direct connected CXL Type 3
 Volatile Memory device::
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort.
  2026-06-09 10:58   ` [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort Shrihari E S
@ 2026-06-16 13:27     ` Jonathan Cameron
  2026-06-24 14:01       ` Shrihari E S
  0 siblings, 1 reply; 25+ messages in thread
From: Jonathan Cameron @ 2026-06-16 13:27 UTC (permalink / raw)
  To: Shrihari E S
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

On Tue,  9 Jun 2026 16:28:29 +0530
Shrihari E S <shrihari.s@samsung.com> wrote:

> Move the 'flitmode' property from PCIESlot to PCIEPort. This change
> allows all the derived ports (PCIe ports or CXL ports) to use this
> property.
> 
> This is a structural refactor only. There is no functional change in
> existing behavior.
> 
> Note: This property was added from Davidlohr's BI patch series[1].
> 
> [1]: https://lore.kernel.org/all/20251103195209.1319917-2-dave@stgolabs.net/
> 
> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
This seems fine to me other than one small thing below.

Given the main changes are in PCIe code though it'll need review from
appropriate maintainers.

> diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
> index 0ee18ef5c3..df69c5200f 100644
> --- a/hw/pci-bridge/cxl_root_port.c
> +++ b/hw/pci-bridge/cxl_root_port.c

>  static void cxl_rp_dvsec_write_config(PCIDevice *dev, uint32_t addr,
> diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
> index 1de0b1e4fd..d452199d85 100644
> --- a/hw/pci/pcie.c
> +++ b/hw/pci/pcie.c
> @@ -217,7 +217,7 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
>          /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
>      }
>  
> -    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->flitmode);
> +    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->parent_obj.flitmode);

I think we should use a cast to the parent object type rather than going directly
into s->parent_obj.  PCIE_PORT(s)->flitmode.

>  }


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 3/8] hw/pci: Add SVC capability and UIO properties to PCIe ports
  2026-06-09 10:58   ` [RFC 3/8] hw/pci: Add SVC capability and UIO properties to PCIe ports Shrihari E S
@ 2026-06-16 17:20     ` Jonathan Cameron
  2026-06-24 14:18       ` Shrihari E S
  0 siblings, 1 reply; 25+ messages in thread
From: Jonathan Cameron @ 2026-06-16 17:20 UTC (permalink / raw)
  To: Shrihari E S
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

On Tue,  9 Jun 2026 16:28:31 +0530
Shrihari E S <shrihari.s@samsung.com> wrote:

> From: Dongjoo Seo <dongjoo.seo1@samsung.com>
> 
> Implement the Streamlined Virtual Channel (SVC) extended capability
> for PCIe ports (Root, Upstream, and Downstream). This capability is
> mandatory for enabling Unordered IO (UIO) traffic as per PCIe 6.4
> specification [1].
> 
> UIO functionality depends on two key prerequisites:
>   1. SVC support (SVC3 mandatory, SVC4 optional)
>   2. 256-byte Flit mode support
> 
> This patch adds the following experimental properties to PCIe ports:
>   - x-uio-svc: Enable UIO traffic via SVC3 (mandatory path)
>   - x-uio-svc-opt: Enable UIO traffic via SVC4 (optional path)

That doesn't feel like naming that will stand the test of time.
I think it needs to mention svc4 in the name.  Or I suppose we could
do something with a single x-uio-svc parameter taking values.


>   - x-256b-flit: Enable 256B flit mode required for UIO
> 
> Helper functions are included to manage UIO traffic gating and SVC
> configuration. This change lays the groundwork for UIO emulation in
> QEMU.
> 
> [1]: PCIe 6.4 Specification, Table 2-46 (Streamlined Virtual Channel)

I'm currently out of the loop for PCIe specs. So if someone else could
review against spec that would be great.

> 
> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
> ---
>  hw/pci-bridge/pcie_root_port.c     |  2 ++
>  hw/pci-bridge/xio3130_downstream.c |  3 +++
>  hw/pci-bridge/xio3130_upstream.c   |  8 ++++++++
>  include/hw/pci/pcie_port.h         | 21 +++++++++++++++++++++
>  4 files changed, 34 insertions(+)
> 
> diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
> index eeee24e042..20554bd854 100644
> --- a/hw/pci-bridge/pcie_root_port.c
> +++ b/hw/pci-bridge/pcie_root_port.c
> @@ -153,6 +153,8 @@ static const Property rp_props[] = {
>                      QEMU_PCIE_SLTCAP_PCP_BITNR, true),
>      DEFINE_PROP_BOOL("disable-acs", PCIESlot, disable_acs, false),
>      DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
> +    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
> +    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
>  };
>  
>  static void rp_instance_post_init(Object *obj)
> diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
> index 0c3fed3053..b0b297bb53 100644
> --- a/hw/pci-bridge/xio3130_downstream.c
> +++ b/hw/pci-bridge/xio3130_downstream.c
> @@ -137,6 +137,9 @@ static void xio3130_downstream_exitfn(PCIDevice *d)
>  static const Property xio3130_downstream_props[] = {
>      DEFINE_PROP_BIT(COMPAT_PROP_PCP, PCIDevice, cap_present,
>                      QEMU_PCIE_SLTCAP_PCP_BITNR, true),
> +    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
> +    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
> +    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, false),
>  };
>  
>  static const VMStateDescription vmstate_xio3130_downstream = {
> diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
> index 40057b749b..925df5add3 100644
> --- a/hw/pci-bridge/xio3130_upstream.c
> +++ b/hw/pci-bridge/xio3130_upstream.c
> @@ -24,6 +24,7 @@
>  #include "hw/pci/msi.h"
>  #include "hw/pci/pcie.h"
>  #include "hw/pci/pcie_port.h"
> +#include "hw/core/qdev-properties.h"
>  #include "migration/vmstate.h"
>  #include "qemu/module.h"
>  
> @@ -123,6 +124,12 @@ static const VMStateDescription vmstate_xio3130_upstream = {
>      }
>  };
>  
> +static const Property xio3130_upstream_props[] = {
> +    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
> +    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
> +    DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, false),
> +};
> +
>  static void xio3130_upstream_class_init(ObjectClass *klass, const void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> @@ -138,6 +145,7 @@ static void xio3130_upstream_class_init(ObjectClass *klass, const void *data)
>      dc->desc = "TI X3130 Upstream Port of PCI Express Switch";
>      device_class_set_legacy_reset(dc, xio3130_upstream_reset);
>      dc->vmsd = &vmstate_xio3130_upstream;
> +    device_class_set_props(dc, xio3130_upstream_props);
>  }
>  
>  static const TypeInfo xio3130_upstream_info = {
> diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
> index 1bcc734649..a6b1b8a6cf 100644
> --- a/include/hw/pci/pcie_port.h
> +++ b/include/hw/pci/pcie_port.h
> @@ -37,8 +37,29 @@ struct PCIEPort {
>  
>      /* pci express switch port */
>      uint8_t     port;
> +
> +    /*
> +     * This field declares Streamlined Virtual Channel (SVC) capability.
> +     * Per PCIe 6.4 specification section 7.9.29, a pcie port supports
> +     * upto 8 SVCs, in that SVC0 is a default one, SVC3 is for UIO traffic
> +     * and SVC 4 is shared by both UIO and non-UIO traffic.

What actually goes in there?  Is this literally the SVC capability content?

> +     */
> +    uint32_t    svc;
>  };
>  
> +#define UIO_MANDATORY_SVC 3
> +#define UIO_OPTIONAL_SVC 4
> +
> +static inline bool get_uio_mandatory_svc(PCIEPort *port)
> +{
> +    return (port->svc >> UIO_MANDATORY_SVC) & 1;

Could just define the field mask given I don't think you ever care about them
being the numeric values themselves. If you need the value defines later, then
fair enough.

If you do switch to defining fields.
	return port->svc & UIO_MANDATORY_SVC;
and rely on boolean cast from non 0 to be true.

Also, do we want to route those two defines through the kernel uapi/linux/pci_regs.h
and then just make use of them in QEMU?

I kind of assume you have some kernel patches as well as this qemu support so
it would form part of that?

> +}
> +
> +static inline bool get_uio_optional_svc(PCIEPort *port)
> +{
> +    return (port->svc >> UIO_OPTIONAL_SVC) & 1;
> +}
> +
>  void pcie_port_init_reg(PCIDevice *d);
>  
>  PCIDevice *pcie_find_port_by_pn(PCIBus *bus, uint8_t pn);


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 4/8] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports
  2026-06-09 10:58   ` [RFC 4/8] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports Shrihari E S
@ 2026-06-16 17:21     ` Jonathan Cameron
  2026-06-24 14:21       ` Shrihari E S
  0 siblings, 1 reply; 25+ messages in thread
From: Jonathan Cameron @ 2026-06-16 17:21 UTC (permalink / raw)
  To: Shrihari E S
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

On Tue,  9 Jun 2026 16:28:32 +0530
Shrihari E S <shrihari.s@samsung.com> wrote:

> Add Unordered IO (UIO) dependent property SVC to CXL ports
> (Root, Upstream and Downstream).
> 
> The following properties are added to CXL ports:
>     - x-uio-svc: Enable UIO traffic via SVC3 (mandatory path)
>     - x-uio-svc-opt: Enable UIO traffic via SVC4 (optional path)
> 
> Note: 256B flit mode property was already added in CXL ports, so reused it.
> 
> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
> ---
>  hw/pci-bridge/cxl_downstream.c            | 2 ++
>  hw/pci-bridge/cxl_root_port.c             | 1 +
>  hw/pci-bridge/cxl_upstream.c              | 2 ++
>  include/hw/pci-bridge/cxl_upstream_port.h | 1 +
>  4 files changed, 6 insertions(+)
> 
> diff --git a/hw/pci-bridge/cxl_downstream.c b/hw/pci-bridge/cxl_downstream.c
> index 7c7a1d1221..6f6f332c07 100644
> --- a/hw/pci-bridge/cxl_downstream.c
> +++ b/hw/pci-bridge/cxl_downstream.c
> @@ -260,6 +260,8 @@ static const Property cxl_dsp_props[] = {
>      DEFINE_PROP_PCIE_LINK_WIDTH("x-width", PCIESlot,
>                                  width, PCIE_LINK_WIDTH_16),
>      DEFINE_PROP_BOOL("x-256b-flit", PCIEPort, flitmode, true),
> +    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
> +    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
>  };
>  
>  static void cxl_dsp_class_init(ObjectClass *oc, const void *data)
> diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
> index e82685d1ab..83fb5968b8 100644
> --- a/hw/pci-bridge/cxl_root_port.c
> +++ b/hw/pci-bridge/cxl_root_port.c
> @@ -53,6 +53,7 @@ typedef struct CXLRootPort {
>      CPMUState cpmu;
>      MemoryRegion cpmu_registers;
>      PCIResReserve res_reserve;
> +    bool uio_capable;
I'd bring these in with a patch that uses them.

This whole thing is simple enough maybe just have it as part of a commit
that uses the properties.

>  } CXLRootPort;
>  
>  #define TYPE_CXL_ROOT_PORT "cxl-rp"
> diff --git a/hw/pci-bridge/cxl_upstream.c b/hw/pci-bridge/cxl_upstream.c
> index ef5480b116..dadad3e15c 100644
> --- a/hw/pci-bridge/cxl_upstream.c
> +++ b/hw/pci-bridge/cxl_upstream.c
> @@ -437,6 +437,8 @@ static const Property cxl_upstream_props[] = {
>      DEFINE_PROP_PCIE_LINK_WIDTH("x-width", CXLUpstreamPort,
>                                  width, PCIE_LINK_WIDTH_16),
>      DEFINE_PROP_BOOL("x-256b-flit", CXLUpstreamPort, flitmode, false),
> +    DEFINE_PROP_BIT("x-uio-svc", PCIEPort, svc, UIO_MANDATORY_SVC, false),
> +    DEFINE_PROP_BIT("x-uio-svc-opt", PCIEPort, svc, UIO_OPTIONAL_SVC, false),
>  };
>  
>  static void cxl_upstream_class_init(ObjectClass *oc, const void *data)
> diff --git a/include/hw/pci-bridge/cxl_upstream_port.h b/include/hw/pci-bridge/cxl_upstream_port.h
> index d4186234c8..d23541e23a 100644
> --- a/include/hw/pci-bridge/cxl_upstream_port.h
> +++ b/include/hw/pci-bridge/cxl_upstream_port.h
> @@ -22,6 +22,7 @@ typedef struct CXLUpstreamPort {
>      PCIExpLinkSpeed speed;
>      PCIExpLinkWidth width;
>      bool flitmode;
> +    bool uio_capable;
>  
>      DOECap doe_cdat;
>      uint64_t sn;


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers
  2026-06-09 10:58   ` [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers Shrihari E S
@ 2026-06-16 17:40     ` Jonathan Cameron
  2026-06-24 14:47       ` Shrihari E S
  2026-06-17 15:45     ` Junjie Cao
  1 sibling, 1 reply; 25+ messages in thread
From: Jonathan Cameron @ 2026-06-16 17:40 UTC (permalink / raw)
  To: Shrihari E S
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

On Tue,  9 Jun 2026 16:28:33 +0530
Shrihari E S <shrihari.s@samsung.com> wrote:

> Plumb the 'uio_capable' flag to CXL HDM decoder capability and
> control register interfaces. The UIO bit in the capability register
> is now set for CXL Type3 devices and ports when UIO support is
> advertised via 'x-uio-svc' property.
> 
> Per CXL 4.0 specification Section 8.2.4.20.7, the decoder control
> UIO bit is validated against the advertised capability during
> HDM decoder commit operations.
> 
> Additionally, replace hardcoded HDM decoder control write masks
> with spec-aligned 'WRMASK' definitions.
I think we should be modifying that depending on whether it is uio_capable
rather than saying it is 'writeable' but 'not writetable' if not UIO capable.

A few other comments inline.

> 
> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
> ---
>  hw/cxl/cxl-component-utils.c        | 29 +++++++++++++++++++++++------
>  hw/mem/cxl_type3.c                  |  9 ++++++++-
>  hw/pci-bridge/cxl_downstream.c      |  2 +-
>  hw/pci-bridge/cxl_root_port.c       |  2 +-
>  hw/pci-bridge/cxl_upstream.c        |  3 ++-
>  hw/pci-bridge/pci_expander_bridge.c |  3 ++-
>  include/hw/cxl/cxl_component.h      |  2 +-
>  include/hw/cxl/cxl_device.h         |  2 ++
>  8 files changed, 40 insertions(+), 12 deletions(-)
> 
> diff --git a/hw/cxl/cxl-component-utils.c b/hw/cxl/cxl-component-utils.c
> index 31bbedb502..9a5b382272 100644
> --- a/hw/cxl/cxl-component-utils.c
> +++ b/hw/cxl/cxl-component-utils.c
> @@ -13,6 +13,19 @@
>  #include "hw/pci/pci.h"
>  #include "hw/cxl/cxl.h"
>  
> +/* CXL 4.0 specification 8.4.2.20.7 */
> +#define CXL_HDM_DECODER_CTRL_WRMASK (    \
> +    (0xfu << 0)   | /* IG */             \
> +    (0xfu << 4)   | /* IW */             \
> +    BIT(8)        | /* LOCK_ON_COMMIT */ \
> +    BIT(9)        | /* COMMIT */         \
> +    BIT(12)       | /* TYPE */           \
> +    BIT(13)       | /* BI */             \
> +    BIT(14)       | /* UIO */            \
> +    (0xfu << 16)  | /* UIG */            \
> +    (0xfu << 20)  | /* UIW */            \
> +    (0xfu << 24))   /* ISP */
Given the FIELD() macro defines appropriate masks, can we build this as
	R_CXL_HDM_DECODER_0_CTRL_IG_MASK |
	R_CXL_HDM_DECODER_0_CTRL_IW_MASK |
etc
That will make it both self documenting and ensure it aligns with the field
defines.  If we get a bug at least it will only be in one place :)

> +
>  /* CXL r3.1 Section 8.2.4.20.1 CXL HDM Decoder Capability Register */
>  int cxl_decoder_count_enc(int count)
>  {
> @@ -305,7 +318,7 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
>  }
>  
>  static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
> -                            enum reg_type type, bool bi)
> +                            enum reg_type type, bool bi, bool uio)
>  {
>      int decoder_count = CXL_HDM_DECODER_COUNT;
>      int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
> @@ -325,9 +338,12 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
>          ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
>          ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
>      }
> -    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO, 0);
> +    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO,
> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio);
>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
> -                     UIO_DECODER_COUNT, 0);
> +                     UIO_DECODER_COUNT,
> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio ?
> +                     decoder_count : 0);
>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, MEMDATA_NXM_CAP, 0);
>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
>                       SUPPORTED_COHERENCY_MODEL,
> @@ -341,7 +357,8 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
>          write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc] = 0xffffffff;
>          write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc] = 0xf0000000;
>          write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc] = 0xffffffff;
> -        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] = 0x13ff;
> +        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] =
> +                                             CXL_HDM_DECODER_CTRL_WRMASK;
I think file at least mostly aligns these long line wraps as
        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] =
            CXL_HDM_DECODER_CTRL_WRMASK;

Given i think this needs to be dependent on whether the device is uio_capable
maybe just bring the mask defines suggested above down here, and modify the
UIO bit to fit whether it should be writeable.


>          if (type == CXL2_DEVICE ||
>              type == CXL2_TYPE3_DEVICE ||
>              type == CXL2_LOGICAL_DEVICE) {
> @@ -391,7 +408,7 @@ static void bi_decoder_init_common(uint32_t *reg_state, uint32_t *write_msk,
>  void cxl_component_register_init_common(uint32_t *reg_state,
>                                          uint32_t *write_msk,
>                                          enum reg_type type,
> -                                        bool bi)
> +                                        bool bi, bool uio)
>  {
>      int caps = 0;
>  
> @@ -431,7 +448,7 @@ void cxl_component_register_init_common(uint32_t *reg_state,
>      case CXL2_LOGICAL_DEVICE:
>          /* + HDM */
>          init_cap_reg(HDM, 5, 1);
> -        hdm_init_common(reg_state, write_msk, type, bi);
> +        hdm_init_common(reg_state, write_msk, type, bi, uio);
>          /* fallthrough */
>      case CXL2_DOWNSTREAM_PORT:
>      case CXL2_DEVICE:
> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
> index b7ad437cbc..4cdadc3e10 100644
> --- a/hw/mem/cxl_type3.c
> +++ b/hw/mem/cxl_type3.c
> @@ -590,6 +590,11 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
>      /* TODO: Sanity checks that the decoder is possible */
>      ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
>      ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
> +    if (ct3d->uio_capable) {
> +        ct3d->uio_enabled = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, UIO);
> +    } else {
> +        ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, UIO, 0);

If it's not supported, shouldn't the write mask stop it being written?  I think
that would be cleaner than overriding any write to 0 here.


> +    }


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability.
  2026-06-09 10:58   ` [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability Shrihari E S
@ 2026-06-16 18:46     ` Jonathan Cameron
  2026-06-24 15:00       ` Shrihari E S
  2026-06-17 15:45     ` Junjie Cao
  1 sibling, 1 reply; 25+ messages in thread
From: Jonathan Cameron @ 2026-06-16 18:46 UTC (permalink / raw)
  To: Shrihari E S
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

On Tue,  9 Jun 2026 16:28:34 +0530
Shrihari E S <shrihari.s@samsung.com> wrote:

> From: Dongjoo Seo <dongjoo.seo1@samsung.com>
> 
> Implement the PCIe Streamlined Virtual Channel (SVC) Extended
> Capability by adding support of capability, control and status
> registers per PCIe 6.4 section 7.9.29. This capability is one
> of the main requisites for UIO support in both PCIe and CXL ports.
> 
> Key changes include:
>     - New pcie_svc.c file for SVC capability management.
>     - Updated pcie_cap_fill_lnk() to handle flitmode signaling.
>     - Implement Lifecycle hooks (reset and config_write) to manage
>       SVC state.
> 
> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
A very quick review on this one as I'm more or less out of time for today
(and not listening to a call ;)

> diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> index 5996229c81..0469250f42 100644
> --- a/hw/pci/pci.c
> +++ b/hw/pci/pci.c

>  /***********************************************************/
> diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
> index d452199d85..7c7d948e00 100644
> --- a/hw/pci/pcie.c
> +++ b/hw/pci/pcie.c
> @@ -112,8 +112,9 @@ pcie_cap_v1_fill(PCIDevice *dev, uint8_t port, uint8_t type, uint8_t version)
>  }
>  
>  /* Includes setting the target speed default */
> -static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
> -                              PCIExpLinkSpeed speed, bool flitmode)
> +static void pcie_cap_fill_lnk(PCIDevice *dev, uint8_t *exp_cap,
> +                              PCIExpLinkWidth width, PCIExpLinkSpeed speed,
> +                              bool flitmode)
>  {
>      /* Clear and fill LNKCAP from what was configured above */
>      pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
> @@ -160,8 +161,14 @@ static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
>      }
>  
>      if (flitmode) {
> -        pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
> +        uint32_t pos = dev->exp.exp_cap;
> +
> +        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
>                                     PCI_EXP_LNKSTA2_FLIT);

Why is this writing a field from LNKSTA2 into FLAGS?

> +        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
> +                                   PCI_EXP_FLAGS_FLIT);
> +        pci_word_test_and_set_mask(dev->wmask + pos + PCI_EXP_LNKCTL,
> +                                   PCI_EXP_LNKCTL_FLIT_DIS);
>      }
>  }
>  

>  static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
>  {
>      PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
> @@ -217,7 +259,8 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
>          /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
>      }
>  
> -    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->parent_obj.flitmode);
> +    pcie_cap_fill_lnk(dev, exp_cap, s->width, s->speed,
> +                      s->parent_obj.flitmode);

As previously I think that should be a PCIE_PORT(s)->flitmode

>  }
>  
>  int pcie_cap_init(PCIDevice *dev, uint8_t offset,
> diff --git a/hw/pci/pcie_svc.c b/hw/pci/pcie_svc.c
> new file mode 100644
> index 0000000000..84db73de58
> --- /dev/null
> +++ b/hw/pci/pcie_svc.c
> @@ -0,0 +1,164 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + * PCIe Streamlined Virtual Channel (SVC) Extended Capability
> + *
> + * Copyright (c) 2026 Samsung Electronics Co., Ltd.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/bitops.h"
> +#include "hw/pci/pci_device.h"
> +#include "hw/pci/pcie.h"
> +#include "hw/pci/pcie_svc.h"
> +#include "hw/pci/pcie_port.h"
> +
> +static void pcie_svc_update_map(PCIDevice *dev)
> +{
> +    uint32_t non_uio_ctrl = SVC_VC0_PROTOCOL | SVC_VC_ENABLE;
> +    uint32_t uio_ctrl = SVC_UIO_PROTOCOL_SELECTED | SVC_VC_ENABLE;
> +    int offset;
> +
> +    if (!pci_is_express(dev) || !dev->exp.svc_cap) {
> +        return;
> +    }
> +
> +    offset = pcie_find_capability(dev, PCI_EXT_CAP_ID_SVC);
> +
> +    /* SVC VC0 & VC3 initialization */
> +    pci_set_long(dev->config + offset + SVC_RES_CTRL(0), BIT(0) | non_uio_ctrl);
> +    pci_set_long(dev->config + offset + SVC_RES_CTRL(3), BIT(3) | uio_ctrl);
> +
> +    /* SVC VC4 initialization - optional */
> +    if (dev->exp.svc.uio_opt_svc) {
> +        pci_set_long(dev->config + offset + SVC_RES_CTRL(4), BIT(4) | uio_ctrl);
> +    }
> +}
> +
> +int pcie_config_uio_svc(PCIDevice *d, Error **errp)
> +{
> +    PCIEPort *p = PCIE_PORT(d);
> +
> +    if (!get_uio_mandatory_svc(p)
> +        || pcie_svc_cap_init(d, PCI_EXT_CAP_BASE_OFFSET, errp) < 0) {

|| on the line above

> +        return -1;
> +    }
> +
> +    if (get_uio_optional_svc(p)) {
> +        pcie_svc_set_vc4(d, true);
> +    }
> +
> +    return 0;
> +}
> +
> +int pcie_svc_cap_init(PCIDevice *dev, uint16_t offset, Error **errp)
> +{
> +    uint32_t hdr;
> +
> +    if (!pci_is_express(dev)) {
> +        error_setg(errp, "SVC ECAP requires PCIe");
> +        return -EINVAL;
> +    }
> +
> +    /*
> +     * If no other ECAPs are present, make SVC the first at 0x100.
> +     * This avoids pcie_add_capability() asserting on a non-0x100 offset.
> +     */
> +    hdr = pci_get_long(dev->config + PCI_CONFIG_SPACE_SIZE);

Is there precedence for this?  Seems like most cases hand code
an offset. I think letting this run has the risk that an ordering
change might end up with this where something else wants to go.

> +    if (hdr == 0) {
> +        offset = PCI_CONFIG_SPACE_SIZE;
> +    }


>  void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
>                                 Error **errp);
> diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
> index 33a22229fe..644da744b2 100644
> --- a/include/hw/pci/pcie_regs.h
> +++ b/include/hw/pci/pcie_regs.h
> @@ -81,6 +81,7 @@ typedef enum PCIExpLinkWidth {
>  #define PCI_EXP_DEVCAP2_EETLPP          0x200000
>  
>  #define PCI_EXP_DEVCTL2_EETLPPB         0x8000
> +#define  PCI_EXP_LNKCTL_FLIT_DIS        0x2000

This extra indent is supposed to associate the field with the register
but the register isn't defined here so it makes little sense.


>  
I see there is some precedence in here for registers that are also defined
in the linux header that is included via hw/pci/pci_regs.h

Maybe we should clean that up a t somepoint.

>  /* ARI */
>  #define PCI_ARI_VER                     1
> diff --git a/include/hw/pci/pcie_svc.h b/include/hw/pci/pcie_svc.h
> new file mode 100644
> index 0000000000..4872905501
> --- /dev/null
> +++ b/include/hw/pci/pcie_svc.h
> @@ -0,0 +1,91 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + *
> + * PCIe Streamlined Virtual Channel (SVC) Extended Capability
> + *
> + * Copyright (c) 2026 Samsung Electronics Co., Ltd.
> + */
> +
> +#ifndef HW_PCIE_SVC_H
> +#define HW_PCIE_SVC_H

Much of this feels like it will end up in pci_regs.h
so maybe just do that from the start.

For this series you'd have to have a patch adding them with
a note on when you expect them to be in the linux header.

> +
> +#include "hw/pci/pci.h"
> +#include "qemu/bitops.h"
> +
> +/*
> + * The PCIe config space starts from 0x00 till 0xFF. In that
> + * extended capability starts from 0x100 and each extended capability
> + * is of dword size (32 bit). So we have to give a proper base offset
> + * value which should be >= 0x100 and <= 0xFF and in between other
> + * capability will also be registerd. We might not know where exactly
> + * SVC extended capability will sit, so to avoid the overlapping we have
> + * to give a very high offset.
> + */
> +#define PCI_EXT_CAP_BASE_OFFSET                0x200
> +#define PCI_EXT_CAP_ID_SVC                     0x35
> +#define PCI_EXT_CAP_SVC_SIZE                   0x74
> +
> +/* PCIe 6.4 section 7.9.29 */
> +#define PCIE_SVC_CAP_HEAD_OFFSET               0x00
> +#define PCIE_SVC_CAP_OFFSET                    0x04

> +#define SVC_TC_VC_MAP(n)                       ((n & 0xff) << 0)
> +
> +/* 7.9.27.8 SVC Resource Status Register */
> +#define SVC_RES_STATUS_BASE                    0x1c
> +#define SVC_RES_STATUS(n)                      (SVC_RES_STATUS_BASE + \
> +                                                (n) * 0x0c)

That's not a nice line break for readabilty. If you have two, move the whole thing to next line.

> +#define SVC_VC_NEGO                            BIT(1)


^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers
  2026-06-09 10:58   ` [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers Shrihari E S
  2026-06-16 17:40     ` Jonathan Cameron
@ 2026-06-17 15:45     ` Junjie Cao
  2026-06-24 15:04       ` Shrihari E S
  1 sibling, 1 reply; 25+ messages in thread
From: Junjie Cao @ 2026-06-17 15:45 UTC (permalink / raw)
  To: Shrihari E S
  Cc: Junjie Cao, jic23, linux-cxl, linux-pci, qemu-devel, cpgs,
	arun.george, vikash.k5, s.neeraj, dongjoo.seo1, dave, gost.dev

Hi Shrihari,

On Tue,  9 Jun 2026 16:28:33 +0530, Shrihari E S wrote:
> +    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO,
> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio);
>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
> -                     UIO_DECODER_COUNT, 0);
> +                     UIO_DECODER_COUNT,
> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio ?
> +                     decoder_count : 0);

CXL2_UPSTREAM_PORT is an enum constant with a non-zero value, so
"|| CXL2_UPSTREAM_PORT" is always true and the type check collapses
to just "uio" -- every type that reaches hdm_init_common() with
uio=true gets the UIO bit set.  Presumably the intent was:

    (type == CXL2_TYPE3_DEVICE || type == CXL2_UPSTREAM_PORT) && uio

I haven't proposed which types should be in that set -- patch 7 sets
crp->uio_capable on the cxl-rp, so a root port may well be intended
here too.  Either way the current expression isn't gating on type.
The same applies to the UIO_DECODER_COUNT line just below.

Many thanks,
Junjie

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability.
  2026-06-09 10:58   ` [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability Shrihari E S
  2026-06-16 18:46     ` Jonathan Cameron
@ 2026-06-17 15:45     ` Junjie Cao
  2026-06-24 15:09       ` Shrihari E S
  1 sibling, 1 reply; 25+ messages in thread
From: Junjie Cao @ 2026-06-17 15:45 UTC (permalink / raw)
  To: Shrihari E S
  Cc: Junjie Cao, jic23, linux-cxl, linux-pci, qemu-devel, cpgs,
	arun.george, vikash.k5, s.neeraj, dongjoo.seo1, dave, gost.dev

Hi Shrihari,

On Tue,  9 Jun 2026 16:28:34 +0530, Shrihari E S wrote:
>      if (flitmode) {
> -        pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
> +        uint32_t pos = dev->exp.exp_cap;
> +
> +        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
>                                     PCI_EXP_LNKSTA2_FLIT);
> +        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
> +                                   PCI_EXP_FLAGS_FLIT);

Following up on Jonathan's observation here -- I'd also noticed a
bogus Interrupt Message Number on a plain flit-mode root port, so I
checked what the stray write actually does to the Flags register.
The impact is wider than just UIO:

The first set_mask writes PCI_EXP_LNKSTA2_FLIT (0x0400) into
PCI_EXP_FLAGS (cap offset 0x02) instead of PCI_EXP_LNKSTA2 (0x32).
0x0400 falls in the Interrupt Message Number field (bits 13:9) of the
Flags register, so a flit-mode port ends up reporting a nonzero
Interrupt Message Number (it reads back as 2).

pcie_cap_fill_lnk() runs for every flit-mode port, and x-256b-flit
defaults to on for pcie-root-port, so even a plain
"-device pcie-root-port" comes up with the corrupted field.

The second line (PCI_EXP_FLAGS_FLIT into Flags) looks correct and
should stay.  The first one looks like a typo in the destination
register -- it was PCI_EXP_LNKSTA2 before this series (visible in the
hunk above), so I'd restore it there rather than drop it.
pcie_cap_flit_write_config() does maintain the LNKSTA2 flit bit, but
only on guest LNKCTL writes; it doesn't run at realize/reset, so
dropping the line would leave LNKSTA2 flit status reading 0 at reset
instead of its pre-series value.

Many thanks,
Junjie

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 7/8] hw/pci: hw/cxl: Wire SVC initialization into port realize functions.
  2026-06-09 10:58   ` [RFC 7/8] hw/pci: hw/cxl: Wire SVC initialization into port realize functions Shrihari E S
@ 2026-06-17 15:45     ` Junjie Cao
  2026-06-24 15:18       ` Shrihari E S
  0 siblings, 1 reply; 25+ messages in thread
From: Junjie Cao @ 2026-06-17 15:45 UTC (permalink / raw)
  To: Shrihari E S
  Cc: Junjie Cao, jic23, linux-cxl, linux-pci, qemu-devel, cpgs,
	arun.george, vikash.k5, s.neeraj, dongjoo.seo1, dave, gost.dev

Hi Shrihari,

On Tue,  9 Jun 2026 16:28:35 +0530, Shrihari E S wrote:
> +    pcie_config_uio_svc(d, errp);
>      pcie_cap_arifwd_init(d);
>      pcie_cap_deverr_init(d);
>      pcie_cap_slot_init(d, s);

In rp_realize() (and the two xio3130 ports) pcie_config_uio_svc() runs
before pcie_aer_init().  pcie_svc_cap_init() falls back to offset 0x100
when no extended capability exists yet, so SVC is placed at 0x100 at
this point -- and then pcie_aer_init() puts AER at the same 0x100 and
overwrites it, while dev->exp.svc_cap still points there.

The visible effect is that "-device pcie-root-port,x-uio-svc=on" comes
up with no SVC capability in the extended config space (the chain is
just AER -> ACS), and no error is reported, so the request is silently
dropped.  I reproduced this by walking the extended capability list of
the root port over ECAM: SVC (0x35) never appears, even though the
property was set.

> +    rc = pcie_config_uio_svc(pci_dev, errp);
> +    if (p->flitmode && rc >= 0) {
> +        crp->uio_capable = true;
> +    }

On cxl-rp this runs a second time: cxl_rp_realize() first calls the
parent rp_realize() (which already calls pcie_config_uio_svc() per the
hunk above) and then calls it again directly.  The first call collides
with AER at 0x100 as above; the second runs after the extended caps
exist, so SVC ends up correctly at 0x200.  So cxl-rp happens to work,
but via a double init.

Just moving the call to after pcie_aer_init() isn't quite enough on
its own: the CXL ports (cxl-rp/usp/dsp) build their DVSECs at fixed
offsets and then add SVC themselves at the end, so if the shared
parent rp_realize() also adds SVC before those DVSECs are built, the
cxl-rp ends up with its DVSECs off the chain.

What worked for me was to move the SVC call after the ECAP inits in
the pure-PCIe paths and skip it in the parent when the device is CXL,
letting the CXL realize functions keep adding it last as they already
do:

  - rp_realize(): move pcie_config_uio_svc() to after pcie_acs_init(),
    guarded by if (!pci_is_cxl(d)) so cxl-rp's own call (which runs
    after build_dvsecs()) remains the one that places SVC.
  - xio3130_upstream/downstream realize(): move the call to after
    pcie_aer_init().
  - cxl-rp/usp/dsp: unchanged, they already add it last.

With that, plain pcie-root-port, the xio3130 switch ports and the CXL
ports all come up with SVC at 0x200, and cxl-rp keeps its four DVSECs.

One thing to note is that this only gets the capability enumerated --
I haven't verified the SVC behaviour beyond that.  Looking at
pcie_svc_cap_write_config()/pcie_svc_apply_gating(), writing the SVC
Enable bit just copies ctrl/status into the shadow struct; no VC
Resource Status bit (the per-VC negotiation bit, SVC_VC_NEGO) is ever
set, and the SVC Status register stays zero.  So a guest that enables
SVC and polls for negotiation wouldn't see anything change.  If the
data-plane series on top is expected to drive that, fine -- I just
wanted to flag that as things stand the enable is observationally a
no-op, in case a driver is expected to key off it.

Many thanks,
Junjie

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort.
  2026-06-16 13:27     ` Jonathan Cameron
@ 2026-06-24 14:01       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 14:01 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 994 bytes --]

>> diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
>> index 0ee18ef5c3..df69c5200f 100644
>> --- a/hw/pci-bridge/cxl_root_port.c
>> +++ b/hw/pci-bridge/cxl_root_port.c
>
>>  static void cxl_rp_dvsec_write_config(PCIDevice *dev, uint32_t addr,
>> diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
>> index 1de0b1e4fd..d452199d85 100644
>> --- a/hw/pci/pcie.c
>> +++ b/hw/pci/pcie.c
>> @@ -217,7 +217,7 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
>>          /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
>>      }
>>
>> -    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->flitmode);
>> +    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->parent_obj.flitmode);
>
>I think we should use a cast to the parent object type rather than going directly
>into s->parent_obj.  PCIE_PORT(s)->flitmode.

Hi Jonathan,

Got your point and it makes sense, will change that in the next version of this patch series. Thanks for the suggestion.

>
>>  }
>

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 3/8] hw/pci: Add SVC capability and UIO properties to PCIe ports
  2026-06-16 17:20     ` Jonathan Cameron
@ 2026-06-24 14:18       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 14:18 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 3784 bytes --]

On 16/06/26 06:20PM, Jonathan Cameron wrote:
>On Tue,  9 Jun 2026 16:28:31 +0530
>Shrihari E S <shrihari.s@samsung.com> wrote:
>
>> From: Dongjoo Seo <dongjoo.seo1@samsung.com>
>>
>> Implement the Streamlined Virtual Channel (SVC) extended capability
>> for PCIe ports (Root, Upstream, and Downstream). This capability is
>> mandatory for enabling Unordered IO (UIO) traffic as per PCIe 6.4
>> specification [1].
>>
>> UIO functionality depends on two key prerequisites:
>>   1. SVC support (SVC3 mandatory, SVC4 optional)
>>   2. 256-byte Flit mode support
>>
>> This patch adds the following experimental properties to PCIe ports:
>>   - x-uio-svc: Enable UIO traffic via SVC3 (mandatory path)
>>   - x-uio-svc-opt: Enable UIO traffic via SVC4 (optional path)
>
>That doesn't feel like naming that will stand the test of time.
>I think it needs to mention svc4 in the name.  Or I suppose we could
>do something with a single x-uio-svc parameter taking values.
>
>

Hi Jonathan,

We thought, 
   - it would be more technical if we add svc3 and svc4 in the
     emulation parameters and
   - would be readable if we advertise the field as UIO mandatory
     SVC (x-uio-svc) and UIO optional SVC (x-uio-svc-opt).

cool will change those to "x-uio-svc3" and "x-uio-svc4" in the
upcoming version.

Thanks.

>>   - x-256b-flit: Enable 256B flit mode required for UIO
>>
>> Helper functions are included to manage UIO traffic gating and SVC
>> configuration. This change lays the groundwork for UIO emulation in
>> QEMU.
>>
>> [1]: PCIe 6.4 Specification, Table 2-46 (Streamlined Virtual Channel)
>
>I'm currently out of the loop for PCIe specs. So if someone else could
>review against spec that would be great.
>
>>
>> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
>> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
>> ---
>>  static const TypeInfo xio3130_upstream_info = {
>> diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h
>> index 1bcc734649..a6b1b8a6cf 100644
>> --- a/include/hw/pci/pcie_port.h
>> +++ b/include/hw/pci/pcie_port.h
>> @@ -37,8 +37,29 @@ struct PCIEPort {
>>
>>      /* pci express switch port */
>>      uint8_t     port;
>> +
>> +    /*
>> +     * This field declares Streamlined Virtual Channel (SVC) capability.
>> +     * Per PCIe 6.4 specification section 7.9.29, a pcie port supports
>> +     * upto 8 SVCs, in that SVC0 is a default one, SVC3 is for UIO traffic
>> +     * and SVC 4 is shared by both UIO and non-UIO traffic.
>
>What actually goes in there?  Is this literally the SVC capability content?
>

Yes, this is the SVC capability of the port and is a bitmap which will be
populated based on the emulation parameters of the port.

>> +     */
>> +    uint32_t    svc;
>>  };
>>
>> +#define UIO_MANDATORY_SVC 3
>> +#define UIO_OPTIONAL_SVC 4
>> +
>> +static inline bool get_uio_mandatory_svc(PCIEPort *port)
>> +{
>> +    return (port->svc >> UIO_MANDATORY_SVC) & 1;
>
>Could just define the field mask given I don't think you ever care about them
>being the numeric values themselves. If you need the value defines later, then
>fair enough.
>
>If you do switch to defining fields.
>	return port->svc & UIO_MANDATORY_SVC;
>and rely on boolean cast from non 0 to be true.
>
>Also, do we want to route those two defines through the kernel uapi/linux/pci_regs.h
>and then just make use of them in QEMU?
>

Actually these are not registers, just a macro definition used to denote SVC3
and SVC4. These definitions are used to enable/verify the bitmap declared
above (uint32_t svc) and I guess routing from linux/pci_regs.h is not
required.

>I kind of assume you have some kernel patches as well as this qemu support so
>it would form part of that?
>

Yeah, we are peparing kernel patches and will be sent out shortly.



[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 4/8] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports
  2026-06-16 17:21     ` Jonathan Cameron
@ 2026-06-24 14:21       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 14:21 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 1398 bytes --]

On 16/06/26 06:21PM, Jonathan Cameron wrote:
>On Tue,  9 Jun 2026 16:28:32 +0530
>Shrihari E S <shrihari.s@samsung.com> wrote:
>
>> Add Unordered IO (UIO) dependent property SVC to CXL ports
>> (Root, Upstream and Downstream).
>>
>> The following properties are added to CXL ports:
>>     - x-uio-svc: Enable UIO traffic via SVC3 (mandatory path)
>>     - x-uio-svc-opt: Enable UIO traffic via SVC4 (optional path)
>>
>> Note: 256B flit mode property was already added in CXL ports, so reused it.
>>
>> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
>> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
>> ---
>>  static void cxl_dsp_class_init(ObjectClass *oc, const void *data)
>> diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
>> index e82685d1ab..83fb5968b8 100644
>> --- a/hw/pci-bridge/cxl_root_port.c
>> +++ b/hw/pci-bridge/cxl_root_port.c
>> @@ -53,6 +53,7 @@ typedef struct CXLRootPort {
>>      CPMUState cpmu;
>>      MemoryRegion cpmu_registers;
>>      PCIResReserve res_reserve;
>> +    bool uio_capable;
>I'd bring these in with a patch that uses them.
>
>This whole thing is simple enough maybe just have it as part of a commit
>that uses the properties.
>

Hi Jonathan,

   Yeah sure will move this field to the patch that uses it. Thought it would be
   a prep patch for the patch that really uses this feature.

Thanks,

>>  } CXLRootPort;


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers
  2026-06-16 17:40     ` Jonathan Cameron
@ 2026-06-24 14:47       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 14:47 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 5392 bytes --]

On 16/06/26 06:40PM, Jonathan Cameron wrote:
>On Tue,  9 Jun 2026 16:28:33 +0530
>Shrihari E S <shrihari.s@samsung.com> wrote:
>
>> Plumb the 'uio_capable' flag to CXL HDM decoder capability and
>> control register interfaces. The UIO bit in the capability register
>> is now set for CXL Type3 devices and ports when UIO support is
>> advertised via 'x-uio-svc' property.
>>
>> Per CXL 4.0 specification Section 8.2.4.20.7, the decoder control
>> UIO bit is validated against the advertised capability during
>> HDM decoder commit operations.
>>
>> Additionally, replace hardcoded HDM decoder control write masks
>> with spec-aligned 'WRMASK' definitions.
>I think we should be modifying that depending on whether it is uio_capable
>rather than saying it is 'writeable' but 'not writetable' if not UIO capable.
>
>A few other comments inline.
>

Hi Jonathan,

   Got your point, will change that in the next version of the patch.

Thanks,

>>
>> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
>> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
>> ---
>> +/* CXL 4.0 specification 8.4.2.20.7 */
>> +#define CXL_HDM_DECODER_CTRL_WRMASK (    \
>> +    (0xfu << 0)   | /* IG */             \
>> +    (0xfu << 4)   | /* IW */             \
>> +    BIT(8)        | /* LOCK_ON_COMMIT */ \
>> +    BIT(9)        | /* COMMIT */         \
>> +    BIT(12)       | /* TYPE */           \
>> +    BIT(13)       | /* BI */             \
>> +    BIT(14)       | /* UIO */            \
>> +    (0xfu << 16)  | /* UIG */            \
>> +    (0xfu << 20)  | /* UIW */            \
>> +    (0xfu << 24))   /* ISP */
>Given the FIELD() macro defines appropriate masks, can we build this as
>	R_CXL_HDM_DECODER_0_CTRL_IG_MASK |
>	R_CXL_HDM_DECODER_0_CTRL_IW_MASK |
>etc
>That will make it both self documenting and ensure it aligns with the field
>defines.  If we get a bug at least it will only be in one place :)
>

Sure, will add those Fields instead of hardcoding.

>> +
>>  /* CXL r3.1 Section 8.2.4.20.1 CXL HDM Decoder Capability Register */
>>  int cxl_decoder_count_enc(int count)
>>  {
>> @@ -305,7 +318,7 @@ static void ras_init_common(uint32_t *reg_state, uint32_t *write_msk)
>>  }
>>
>>  static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
>> -                            enum reg_type type, bool bi)
>> +                            enum reg_type type, bool bi, bool uio)
>>  {
>>      int decoder_count = CXL_HDM_DECODER_COUNT;
>>      int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO;
>> @@ -325,9 +338,12 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
>>          ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 3_6_12_WAY, 0);
>>          ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, 16_WAY, 0);
>>      }
>> -    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO, 0);
>> +    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO,
>> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio);
>>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
>> -                     UIO_DECODER_COUNT, 0);
>> +                     UIO_DECODER_COUNT,
>> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio ?
>> +                     decoder_count : 0);
>>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, MEMDATA_NXM_CAP, 0);
>>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
>>                       SUPPORTED_COHERENCY_MODEL,
>> @@ -341,7 +357,8 @@ static void hdm_init_common(uint32_t *reg_state, uint32_t *write_msk,
>>          write_msk[R_CXL_HDM_DECODER0_BASE_HI + i * hdm_inc] = 0xffffffff;
>>          write_msk[R_CXL_HDM_DECODER0_SIZE_LO + i * hdm_inc] = 0xf0000000;
>>          write_msk[R_CXL_HDM_DECODER0_SIZE_HI + i * hdm_inc] = 0xffffffff;
>> -        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] = 0x13ff;
>> +        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] =
>> +                                             CXL_HDM_DECODER_CTRL_WRMASK;
>I think file at least mostly aligns these long line wraps as
>        write_msk[R_CXL_HDM_DECODER0_CTRL + i * hdm_inc] =
>            CXL_HDM_DECODER_CTRL_WRMASK;
>

Sure, will rectify it.

>Given i think this needs to be dependent on whether the device is uio_capable
>maybe just bring the mask defines suggested above down here, and modify the
>UIO bit to fit whether it should be writeable.
>
>

Yeah, got it. Will check the UIO capability first and apply the mask. Thanks for
pointing it out.

>> diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
>> index b7ad437cbc..4cdadc3e10 100644
>> --- a/hw/mem/cxl_type3.c
>> +++ b/hw/mem/cxl_type3.c
>> @@ -590,6 +590,11 @@ static void hdm_decoder_commit(CXLType3Dev *ct3d, int which)
>>      /* TODO: Sanity checks that the decoder is possible */
>>      ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, ERR, 0);
>>      ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, COMMITTED, 1);
>> +    if (ct3d->uio_capable) {
>> +        ct3d->uio_enabled = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, UIO);
>> +    } else {
>> +        ctrl = FIELD_DP32(ctrl, CXL_HDM_DECODER0_CTRL, UIO, 0);
>
>If it's not supported, shouldn't the write mask stop it being written?  I think
>that would be cleaner than overriding any write to 0 here.
>
>

yes, understood. Will do that in the next version of the patch.


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability.
  2026-06-16 18:46     ` Jonathan Cameron
@ 2026-06-24 15:00       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 15:00 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: linux-cxl, linux-pci, qemu-devel, cpgs, arun.george, vikash.k5,
	s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 5846 bytes --]

On 16/06/26 07:46PM, Jonathan Cameron wrote:
>On Tue,  9 Jun 2026 16:28:34 +0530
>Shrihari E S <shrihari.s@samsung.com> wrote:
>
>> From: Dongjoo Seo <dongjoo.seo1@samsung.com>
>>
>> Implement the PCIe Streamlined Virtual Channel (SVC) Extended
>> Capability by adding support of capability, control and status
>> registers per PCIe 6.4 section 7.9.29. This capability is one
>> of the main requisites for UIO support in both PCIe and CXL ports.
>>
>> Key changes include:
>>     - New pcie_svc.c file for SVC capability management.
>>     - Updated pcie_cap_fill_lnk() to handle flitmode signaling.
>>     - Implement Lifecycle hooks (reset and config_write) to manage
>>       SVC state.
>>
>> Signed-off-by: Dongjoo Seo <dongjoo.seo1@samsung.com>
>> Signed-off-by: Shrihari E S <shrihari.s@samsung.com>
>A very quick review on this one as I'm more or less out of time for today
>(and not listening to a call ;)
>
>      pci_long_test_and_clear_mask(exp_cap + PCI_EXP_LNKCAP,
>> @@ -160,8 +161,14 @@ static void pcie_cap_fill_lnk(uint8_t *exp_cap, PCIExpLinkWidth width,
>>      }
>>
>>      if (flitmode) {
>> -        pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
>> +        uint32_t pos = dev->exp.exp_cap;
>> +
>> +        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
>>                                     PCI_EXP_LNKSTA2_FLIT);
>
>Why is this writing a field from LNKSTA2 into FLAGS?
>

Hi Jonathan,

   Sorry, it's a typo. It should be PCI_EXP_LNKSTA2 instead of PCI_EXP_FLAGS.
   will correct it in the next version of patch.

>>  static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
>>  {
>>      PCIESlot *s = (PCIESlot *)object_dynamic_cast(OBJECT(dev), TYPE_PCIE_SLOT);
>> @@ -217,7 +259,8 @@ static void pcie_cap_fill_slot_lnk(PCIDevice *dev)
>>          /* the PCI_EXP_LNKSTA_DLLLA will be set in the hotplug function */
>>      }
>>
>> -    pcie_cap_fill_lnk(exp_cap, s->width, s->speed, s->parent_obj.flitmode);
>> +    pcie_cap_fill_lnk(dev, exp_cap, s->width, s->speed,
>> +                      s->parent_obj.flitmode);
>
>As previously I think that should be a PCIE_PORT(s)->flitmode
>
>>  }

Yeah, will correct it.

>> +int pcie_config_uio_svc(PCIDevice *d, Error **errp)
>> +{
>> +    PCIEPort *p = PCIE_PORT(d);
>> +
>> +    if (!get_uio_mandatory_svc(p)
>> +        || pcie_svc_cap_init(d, PCI_EXT_CAP_BASE_OFFSET, errp) < 0) {
>
>|| on the line above
>

Got it, thanks for pointing out. Will correct this.

>> +int pcie_svc_cap_init(PCIDevice *dev, uint16_t offset, Error **errp)
>> +{
>> +    uint32_t hdr;
>> +
>> +    if (!pci_is_express(dev)) {
>> +        error_setg(errp, "SVC ECAP requires PCIe");
>> +        return -EINVAL;
>> +    }
>> +
>> +    /*
>> +     * If no other ECAPs are present, make SVC the first at 0x100.
>> +     * This avoids pcie_add_capability() asserting on a non-0x100 offset.
>> +     */
>> +    hdr = pci_get_long(dev->config + PCI_CONFIG_SPACE_SIZE);
>
>Is there precedence for this?  Seems like most cases hand code
>an offset. I think letting this run has the risk that an ordering
>change might end up with this where something else wants to go.
>

Yeah, will check the precedence and change it accordingly.

>> +    if (hdr == 0) {
>> +        offset = PCI_CONFIG_SPACE_SIZE;
>> +    }
>
>
>>  void pcie_cap_slot_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
>>                                 Error **errp);
>> diff --git a/include/hw/pci/pcie_regs.h b/include/hw/pci/pcie_regs.h
>> index 33a22229fe..644da744b2 100644
>> --- a/include/hw/pci/pcie_regs.h
>> +++ b/include/hw/pci/pcie_regs.h
>> @@ -81,6 +81,7 @@ typedef enum PCIExpLinkWidth {
>>  #define PCI_EXP_DEVCAP2_EETLPP          0x200000
>>
>>  #define PCI_EXP_DEVCTL2_EETLPPB         0x8000
>> +#define  PCI_EXP_LNKCTL_FLIT_DIS        0x2000
>
>This extra indent is supposed to associate the field with the register
>but the register isn't defined here so it makes little sense.
>
>
>>
>I see there is some precedence in here for registers that are also defined
>in the linux header that is included via hw/pci/pci_regs.h
>
>Maybe we should clean that up a t somepoint.
>
>>  /* ARI */
>>  #define PCI_ARI_VER                     1
>> diff --git a/include/hw/pci/pcie_svc.h b/include/hw/pci/pcie_svc.h
>> new file mode 100644
>> index 0000000000..4872905501
>> --- /dev/null
>> +++ b/include/hw/pci/pcie_svc.h
>> @@ -0,0 +1,91 @@
>> +/*
>> + * SPDX-License-Identifier: GPL-2.0-or-later
>> + *
>> + * PCIe Streamlined Virtual Channel (SVC) Extended Capability
>> + *
>> + * Copyright (c) 2026 Samsung Electronics Co., Ltd.
>> + */
>> +
>> +#ifndef HW_PCIE_SVC_H
>> +#define HW_PCIE_SVC_H
>
>Much of this feels like it will end up in pci_regs.h
>so maybe just do that from the start.
>

We thought that we should follow the same pattern that PCIe SRIOV did
"pcie_sriov.h", so we added pcie_svc.h. I agree that all the register
declaration and definition should go in pci_regs.h. Will do that.

>For this series you'd have to have a patch adding them with
>a note on when you expect them to be in the linux header.
>

Yeah sure.

>> +#define PCI_EXT_CAP_BASE_OFFSET                0x200
>> +#define PCI_EXT_CAP_ID_SVC                     0x35
>> +#define PCI_EXT_CAP_SVC_SIZE                   0x74
>> +
>> +/* PCIe 6.4 section 7.9.29 */
>> +#define PCIE_SVC_CAP_HEAD_OFFSET               0x00
>> +#define PCIE_SVC_CAP_OFFSET                    0x04
>
>> +#define SVC_TC_VC_MAP(n)                       ((n & 0xff) << 0)
>> +
>> +/* 7.9.27.8 SVC Resource Status Register */
>> +#define SVC_RES_STATUS_BASE                    0x1c
>> +#define SVC_RES_STATUS(n)                      (SVC_RES_STATUS_BASE + \
>> +                                                (n) * 0x0c)
>
>That's not a nice line break for readabilty. If you have two, move the whole thing to next line.
>

Sure, will rectify it.


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers
  2026-06-17 15:45     ` Junjie Cao
@ 2026-06-24 15:04       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 15:04 UTC (permalink / raw)
  To: Junjie Cao
  Cc: jic23, linux-cxl, linux-pci, qemu-devel, cpgs, arun.george,
	vikash.k5, s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 1277 bytes --]

On 17/06/26 11:45PM, Junjie Cao wrote:
>Hi Shrihari,
>
>On Tue,  9 Jun 2026 16:28:33 +0530, Shrihari E S wrote:
>> +    ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY, UIO,
>> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio);
>>      ARRAY_FIELD_DP32(reg_state, CXL_HDM_DECODER_CAPABILITY,
>> -                     UIO_DECODER_COUNT, 0);
>> +                     UIO_DECODER_COUNT,
>> +                     (type == CXL2_TYPE3_DEVICE || CXL2_UPSTREAM_PORT) && uio ?
>> +                     decoder_count : 0);
>
>CXL2_UPSTREAM_PORT is an enum constant with a non-zero value, so
>"|| CXL2_UPSTREAM_PORT" is always true and the type check collapses
>to just "uio" -- every type that reaches hdm_init_common() with
>uio=true gets the UIO bit set.  Presumably the intent was:
>
>    (type == CXL2_TYPE3_DEVICE || type == CXL2_UPSTREAM_PORT) && uio
>
>I haven't proposed which types should be in that set -- patch 7 sets
>crp->uio_capable on the cxl-rp, so a root port may well be intended
>here too.  Either way the current expression isn't gating on type.
>The same applies to the UIO_DECODER_COUNT line just below.
>
>Many thanks,
>Junjie

Hi Junjie,

   Thanks for pointing out. Will rectify it in the next version of the patch.

Thanks,

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability.
  2026-06-17 15:45     ` Junjie Cao
@ 2026-06-24 15:09       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 15:09 UTC (permalink / raw)
  To: Junjie Cao
  Cc: jic23, linux-cxl, linux-pci, qemu-devel, cpgs, arun.george,
	vikash.k5, s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 1946 bytes --]

On 17/06/26 11:45PM, Junjie Cao wrote:
>Hi Shrihari,
>
>On Tue,  9 Jun 2026 16:28:34 +0530, Shrihari E S wrote:
>>      if (flitmode) {
>> -        pci_long_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA2,
>> +        uint32_t pos = dev->exp.exp_cap;
>> +
>> +        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
>>                                     PCI_EXP_LNKSTA2_FLIT);
>> +        pci_word_test_and_set_mask(exp_cap + PCI_EXP_FLAGS,
>> +                                   PCI_EXP_FLAGS_FLIT);
>
>Following up on Jonathan's observation here -- I'd also noticed a
>bogus Interrupt Message Number on a plain flit-mode root port, so I
>checked what the stray write actually does to the Flags register.
>The impact is wider than just UIO:
>
>The first set_mask writes PCI_EXP_LNKSTA2_FLIT (0x0400) into
>PCI_EXP_FLAGS (cap offset 0x02) instead of PCI_EXP_LNKSTA2 (0x32).
>0x0400 falls in the Interrupt Message Number field (bits 13:9) of the
>Flags register, so a flit-mode port ends up reporting a nonzero
>Interrupt Message Number (it reads back as 2).
>
>pcie_cap_fill_lnk() runs for every flit-mode port, and x-256b-flit
>defaults to on for pcie-root-port, so even a plain
>"-device pcie-root-port" comes up with the corrupted field.
>
>The second line (PCI_EXP_FLAGS_FLIT into Flags) looks correct and
>should stay.  The first one looks like a typo in the destination
>register -- it was PCI_EXP_LNKSTA2 before this series (visible in the
>hunk above), so I'd restore it there rather than drop it.
>pcie_cap_flit_write_config() does maintain the LNKSTA2 flit bit, but
>only on guest LNKCTL writes; it doesn't run at realize/reset, so
>dropping the line would leave LNKSTA2 flit status reading 0 at reset
>instead of its pre-series value.
>
>Many thanks,
>Junjie

Hi Junjie,

   Yeah, it's a typo. The destination register should be "PCI_EXP_LNKSTA2".
   Thank you for pointing this out. We will rectify it in the next version.

Thanks,


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [RFC 7/8] hw/pci: hw/cxl: Wire SVC initialization into port realize functions.
  2026-06-17 15:45     ` Junjie Cao
@ 2026-06-24 15:18       ` Shrihari E S
  0 siblings, 0 replies; 25+ messages in thread
From: Shrihari E S @ 2026-06-24 15:18 UTC (permalink / raw)
  To: Junjie Cao
  Cc: jic23, linux-cxl, linux-pci, qemu-devel, cpgs, arun.george,
	vikash.k5, s.neeraj, dongjoo.seo1, dave, gost.dev

[-- Attachment #1: Type: text/plain, Size: 3536 bytes --]

On 17/06/26 11:45PM, Junjie Cao wrote:
>Hi Shrihari,
>
>On Tue,  9 Jun 2026 16:28:35 +0530, Shrihari E S wrote:
>> +    pcie_config_uio_svc(d, errp);
>>      pcie_cap_arifwd_init(d);
>>      pcie_cap_deverr_init(d);
>>      pcie_cap_slot_init(d, s);
>
>In rp_realize() (and the two xio3130 ports) pcie_config_uio_svc() runs
>before pcie_aer_init().  pcie_svc_cap_init() falls back to offset 0x100
>when no extended capability exists yet, so SVC is placed at 0x100 at
>this point -- and then pcie_aer_init() puts AER at the same 0x100 and
>overwrites it, while dev->exp.svc_cap still points there.
>
>The visible effect is that "-device pcie-root-port,x-uio-svc=on" comes
>up with no SVC capability in the extended config space (the chain is
>just AER -> ACS), and no error is reported, so the request is silently
>dropped.  I reproduced this by walking the extended capability list of
>the root port over ECAM: SVC (0x35) never appears, even though the
>property was set.
>
>> +    rc = pcie_config_uio_svc(pci_dev, errp);
>> +    if (p->flitmode && rc >= 0) {
>> +        crp->uio_capable = true;
>> +    }
>
>On cxl-rp this runs a second time: cxl_rp_realize() first calls the
>parent rp_realize() (which already calls pcie_config_uio_svc() per the
>hunk above) and then calls it again directly.  The first call collides
>with AER at 0x100 as above; the second runs after the extended caps
>exist, so SVC ends up correctly at 0x200.  So cxl-rp happens to work,
>but via a double init.
>
>Just moving the call to after pcie_aer_init() isn't quite enough on
>its own: the CXL ports (cxl-rp/usp/dsp) build their DVSECs at fixed
>offsets and then add SVC themselves at the end, so if the shared
>parent rp_realize() also adds SVC before those DVSECs are built, the
>cxl-rp ends up with its DVSECs off the chain.
>
>What worked for me was to move the SVC call after the ECAP inits in
>the pure-PCIe paths and skip it in the parent when the device is CXL,
>letting the CXL realize functions keep adding it last as they already
>do:
>
>  - rp_realize(): move pcie_config_uio_svc() to after pcie_acs_init(),
>    guarded by if (!pci_is_cxl(d)) so cxl-rp's own call (which runs
>    after build_dvsecs()) remains the one that places SVC.
>  - xio3130_upstream/downstream realize(): move the call to after
>    pcie_aer_init().
>  - cxl-rp/usp/dsp: unchanged, they already add it last.
>
>With that, plain pcie-root-port, the xio3130 switch ports and the CXL
>ports all come up with SVC at 0x200, and cxl-rp keeps its four DVSECs.
>

Hi Junjie,

     Thank you for pointing this bug, got missed in our testing. Will check
     and move the svc_init() function properly in the next version of the patch.

>One thing to note is that this only gets the capability enumerated --
>I haven't verified the SVC behaviour beyond that.  Looking at
>pcie_svc_cap_write_config()/pcie_svc_apply_gating(), writing the SVC
>Enable bit just copies ctrl/status into the shadow struct; no VC
>Resource Status bit (the per-VC negotiation bit, SVC_VC_NEGO) is ever
>set, and the SVC Status register stays zero.  So a guest that enables
>SVC and polls for negotiation wouldn't see anything change.  If the
>data-plane series on top is expected to drive that, fine -- I just
>wanted to flag that as things stand the enable is observationally a
>no-op, in case a driver is expected to key off it.
>
>Many thanks,
>Junjie

Yeah this patch series is meant for enumeration (probe) puprpose only
and yes we have plan to add data plane support as well.

Thanks,
Shrihari


[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2026-06-24  7:30 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CGME20260609104453epcas5p327a974e978790e693c0660f27f9b43ef@epcas5p3.samsung.com>
2026-06-09 10:58 ` [RFC 0/8] pci: cxl: Add enumeration support for Unordered I/O (UIO) feature Shrihari E S
2026-06-09 10:58   ` [RFC 1/8] hw/pci: Refactor flitmode from PCIESlot to PCIEPort Shrihari E S
2026-06-16 13:27     ` Jonathan Cameron
2026-06-24 14:01       ` Shrihari E S
2026-06-09 10:58   ` [RFC 2/8] hw/pci: Move 'x-256b-flit' property from cxl_root_port to pcie_root_port Shrihari E S
2026-06-09 10:58   ` [RFC 3/8] hw/pci: Add SVC capability and UIO properties to PCIe ports Shrihari E S
2026-06-16 17:20     ` Jonathan Cameron
2026-06-24 14:18       ` Shrihari E S
2026-06-09 10:58   ` [RFC 4/8] hw/cxl: Add Streamlined Virtual Channel (SVC) property to CXL ports Shrihari E S
2026-06-16 17:21     ` Jonathan Cameron
2026-06-24 14:21       ` Shrihari E S
2026-06-09 10:58   ` [RFC 5/8] hw/cxl: Wire UIO capability into HDM decoder registers Shrihari E S
2026-06-16 17:40     ` Jonathan Cameron
2026-06-24 14:47       ` Shrihari E S
2026-06-17 15:45     ` Junjie Cao
2026-06-24 15:04       ` Shrihari E S
2026-06-09 10:58   ` [RFC 6/8] hw/pci: Add PCIe Streamlined Virtual Channel (SVC) capability Shrihari E S
2026-06-16 18:46     ` Jonathan Cameron
2026-06-24 15:00       ` Shrihari E S
2026-06-17 15:45     ` Junjie Cao
2026-06-24 15:09       ` Shrihari E S
2026-06-09 10:58   ` [RFC 7/8] hw/pci: hw/cxl: Wire SVC initialization into port realize functions Shrihari E S
2026-06-17 15:45     ` Junjie Cao
2026-06-24 15:18       ` Shrihari E S
2026-06-09 10:58   ` [RFC 8/8] cxl: Add documentation for UIO-enabled CXL devices Shrihari E S

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox