Linux Documentation
 help / color / mirror / Atom feed
* [PATCH] dt-bindings: fix typos and brackets
From: Manuel Ebner @ 2026-07-13 13:47 UTC (permalink / raw)
  To: Conor Dooley, Krzysztof Kozlowski, Rob Herring, devicetree
  Cc: Jonathan Corbet, linux-doc, linux-kernel, Liam Girdwood,
	Mark Brown, Randy Dunlap, Manuel Ebner

Add missing '(', ')', '}'
Remove needless '(', ')', '{', '}'
'lover voltage' -> 'lower voltage'

Signed-off-by: Manuel Ebner <manuelebner@mailbox.org>
---
Sorry for the noise earlier.
---
 Documentation/devicetree/bindings/arm/mediatek.yaml           | 2 +-
 .../devicetree/bindings/arm/qcom,coresight-tpdm.yaml          | 2 +-
 .../bindings/clock/renesas,rcar-usb2-clock-sel.yaml           | 4 ++--
 .../devicetree/bindings/input/gpio-charlieplex-keypad.yaml    | 2 +-
 Documentation/devicetree/bindings/leds/backlight/88pm860x.txt | 1 +
 .../devicetree/bindings/memory-controllers/renesas,dbsc.yaml  | 2 +-
 .../devicetree/bindings/memory-controllers/ti-aemif.txt       | 4 ++--
 Documentation/devicetree/bindings/mips/brcm/soc.txt           | 2 +-
 Documentation/devicetree/bindings/mmc/sdhci-st.txt            | 1 +
 Documentation/devicetree/bindings/phy/phy-miphy365x.txt       | 2 +-
 Documentation/devicetree/bindings/powerpc/ibm,vas.txt         | 2 +-
 Documentation/devicetree/bindings/regulator/max8907.txt       | 1 -
 .../bindings/regulator/mediatek,mt6358-regulator.yaml         | 2 +-
 .../devicetree/bindings/regulator/pbias-regulator.txt         | 1 +
 .../devicetree/bindings/regulator/rohm,bd71837-regulator.yaml | 4 ++--
 .../devicetree/bindings/regulator/rohm,bd71847-regulator.yaml | 4 ++--
 .../devicetree/bindings/sound/mikroe,mikroe-proto.txt         | 1 -
 Documentation/devicetree/bindings/usb/iproc-udc.txt           | 1 +
 18 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml
index 382d0eb4d0af..cd4040ad3437 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek.yaml
@@ -314,7 +314,7 @@ properties:
           - const: google,steelix-sku196608
           - const: google,steelix
           - const: mediatek,mt8186
-      - description: Google Squirtle (Acer Chromebook Spin 311 (R724T)
+      - description: Google Squirtle (Acer Chromebook Spin 311 (R724T))
         items:
           - const: google,squirtle
           - const: mediatek,mt8186
diff --git a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
index 152403f548c3..c7301f1b28c1 100644
--- a/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom,coresight-tpdm.yaml
@@ -9,7 +9,7 @@ title: Trace, Profiling and Diagnostics Monitor - TPDM
 
 description: |
   The TPDM or Monitor serves as data collection component for various dataset
-  types specified in the QPMDA spec. It covers Implementation defined ((ImplDef),
+  types specified in the QPMDA spec. It covers Implementation defined (ImplDef),
   Basic Counts (BC), Tenure Counts (TC), Continuous Multi-Bit (CMB), and Discrete
   Single Bit (DSB). It performs data collection in the data producing clock
   domain and transfers it to the data collection time domain, generally ATB
diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml
index c84f29f1810f..a14be249fa33 100644
--- a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml
+++ b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml
@@ -13,8 +13,8 @@ description: |
   If you connect an external clock to the USB_EXTAL pin only, you should set
   the clock rate to "usb_extal" node only.
   If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module
-  is not needed because this is default setting. (Of course, you can set the
-  clock rates to both "usb_extal" and "usb_xtal" nodes.
+  is not needed because this is default setting (Of course, you can set the
+  clock rates to both "usb_extal" and "usb_xtal" nodes).
 
   Case 1: An external clock connects to R-Car SoC
     +----------+   +--- R-Car ---------------------+
diff --git a/Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml b/Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
index c085de6dab85..c6842c017934 100644
--- a/Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
+++ b/Documentation/devicetree/bindings/input/gpio-charlieplex-keypad.yaml
@@ -11,7 +11,7 @@ maintainers:
   - Hugo Villeneuve <hvilleneuve@dimonoff.com>
 
 description: |
-  The charlieplex keypad supports N^2)-N different key combinations (where N is
+  The charlieplex keypad supports (N^2)-N different key combinations (where N is
   the number of I/O lines). Key presses and releases are detected by configuring
   only one line as output at a time, and reading other line states. This process
   is repeated for each line. Diodes are required to ensure current flows in only
diff --git a/Documentation/devicetree/bindings/leds/backlight/88pm860x.txt b/Documentation/devicetree/bindings/leds/backlight/88pm860x.txt
index 261df2799315..9e17807d2ce5 100644
--- a/Documentation/devicetree/bindings/leds/backlight/88pm860x.txt
+++ b/Documentation/devicetree/bindings/leds/backlight/88pm860x.txt
@@ -13,3 +13,4 @@ Example:
 		};
 		backlight-2 {
 		};
+	};
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.yaml
index 8e3822314b25..30ad2a858844 100644
--- a/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,dbsc.yaml
@@ -13,7 +13,7 @@ description: |
   Renesas SoCs contain one or more memory controllers.  These memory
   controllers differ from one SoC variant to another, and are called by
   different names, e.g. "DDR Bus Controller (DBSC)", "DDR3 Bus State Controller
-  (DBSC3)", or "SDRAM Bus State Controller (SBSC)").
+  (DBSC3)", or "SDRAM Bus State Controller (SBSC)".
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt b/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
index 190437a0c146..3ec0a43d4e67 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/ti-aemif.txt
@@ -111,7 +111,7 @@ Optional child cs node properties:
 
 - ti,cs-read-hold-ns:		read hold width, ns
 				Time between the deactivation of the read
-				strobe and the end of the cycle (which may be
+				strobe and the end of the cycle which may be
 				either an address change or the deactivation of
 				the chip select signal.
 				Minimum value is 1 (0 treated as 1).
@@ -128,7 +128,7 @@ Optional child cs node properties:
 
 - ti,cs-write-hold-ns:		write hold width, ns
 				Time between the deactivation of the write
-				strobe and the end of the cycle (which may be
+				strobe and the end of the cycle which may be
 				either an address change or the deactivation of
 				the chip select signal.
 				Minimum value is 1 (0 treated as 1).
diff --git a/Documentation/devicetree/bindings/mips/brcm/soc.txt b/Documentation/devicetree/bindings/mips/brcm/soc.txt
index 3a66d3c483e1..70cd69a4f173 100644
--- a/Documentation/devicetree/bindings/mips/brcm/soc.txt
+++ b/Documentation/devicetree/bindings/mips/brcm/soc.txt
@@ -45,7 +45,7 @@ each of which may have several associated hardware blocks, which are versioned
 independently (control registers, DDR PHYs, etc.). One might consider
 describing these controllers as a parent "memory controllers" block, which
 contains N sub-nodes (one for each controller in the system), each of which is
-associated with a number of hardware register resources (e.g., its PHY.
+associated with a number of hardware register resources (e.g., its PHY).
 
 == MEMC (MEMory Controller)
 
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
index ccf82b4ee838..5927abf0c634 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-st.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
@@ -71,6 +71,7 @@ mmc0: sdhci@fe81e000 {
 	clock-names	= "mmc";
 	clocks		= <&clk_s_a1_ls 1>;
 	bus-width	= <8>
+};
 
 /* Example SD stih407 family configuration */
 
diff --git a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
index 8772900e056a..e36fac92f0fa 100644
--- a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
+++ b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
@@ -31,7 +31,7 @@ Required properties (port (child) node):
 
 Optional properties (port (child) node):
 - st,sata-gen	     :	Generation of locally attached SATA IP. Expected values
-			are {1,2,3). If not supplied generation 1 hardware will
+			are (1,2,3). If not supplied generation 1 hardware will
 			be expected
 - st,pcie-tx-pol-inv :	Bool property to invert the polarity PCIe Tx (Txn/Txp)
 - st,sata-tx-pol-inv :	Bool property to invert the polarity SATA Tx (Txn/Txp)
diff --git a/Documentation/devicetree/bindings/powerpc/ibm,vas.txt b/Documentation/devicetree/bindings/powerpc/ibm,vas.txt
index bf11d2faf7b8..80ea975697ac 100644
--- a/Documentation/devicetree/bindings/powerpc/ibm,vas.txt
+++ b/Documentation/devicetree/bindings/powerpc/ibm,vas.txt
@@ -10,7 +10,7 @@ Required properties:
 - reg : Should contain 4 pairs of 64-bit fields specifying the Hypervisor
   window context start and length, OS/User window context start and length,
   "Paste address" start and length, "Paste window id" start bit and number
-  of bits)
+  of bits
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/regulator/max8907.txt b/Documentation/devicetree/bindings/regulator/max8907.txt
index 371eccd1cd68..b04c9edd3dcd 100644
--- a/Documentation/devicetree/bindings/regulator/max8907.txt
+++ b/Documentation/devicetree/bindings/regulator/max8907.txt
@@ -66,4 +66,3 @@ Example:
 ...
 			};
 		};
-	};
diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml
index c50402fcba72..4eb635179b6a 100644
--- a/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6358-regulator.yaml
@@ -145,7 +145,7 @@ allOf:
     then:
       patternProperties:
         # Old regulator node name scheme (with prefix and underscores) only
-        # ([^y-] is used to avoid matching -supply
+        # ([^y-]) is used to avoid matching -supply
         "^(?<!buck_)(?<!ldo_)v.*[^y-](?!-supply)$": false
         "^ldo_vsram-": false
         # vsram_core regulator doesn't exist on MT6358
diff --git a/Documentation/devicetree/bindings/regulator/pbias-regulator.txt b/Documentation/devicetree/bindings/regulator/pbias-regulator.txt
index acbcb452a69a..09b07f7ab94a 100644
--- a/Documentation/devicetree/bindings/regulator/pbias-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/pbias-regulator.txt
@@ -30,3 +30,4 @@ Example:
 				regulator-min-microvolt = <1800000>;
 				regulator-max-microvolt = <3000000>;
 			};
+		};
diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml
index 29b350a4f88a..9942ee6c60f3 100644
--- a/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/rohm,bd71837-regulator.yaml
@@ -108,8 +108,8 @@ patternProperties:
       # Setups where regulator (especially the buck8) output voltage is scaled
       # by adding external connection where some other regulator output is
       # connected to feedback-pin (over suitable resistors) is getting popular
-      # amongst users of BD71837. (This allows for example scaling down the
-      # buck8 voltages to suit lover GPU voltages for projects where buck8 is
+      # amongst users of BD71837. This allows for example scaling down the
+      # buck8 voltages to suit lower GPU voltages for projects where buck8 is
       # (ab)used to supply power for GPU.
       #
       # So we allow describing this external connection from DT and scale the
diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml
index 7ba4ccf723d8..158d749edaa3 100644
--- a/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/rohm,bd71847-regulator.yaml
@@ -103,8 +103,8 @@ patternProperties:
       # Setups where regulator (especially the buck8) output voltage is scaled
       # by adding external connection where some other regulator output is
       # connected to feedback-pin (over suitable resistors) is getting popular
-      # amongst users of BD71837. (This allows for example scaling down the
-      # buck8 voltages to suit lover GPU voltages for projects where buck8 is
+      # amongst users of BD71837. This allows for example scaling down the
+      # buck8 voltages to suit lower GPU voltages for projects where buck8 is
       # (ab)used to supply power for GPU.
       #
       # So we allow describing this external connection from DT and scale the
diff --git a/Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt b/Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt
index 912f8fae11c5..d6fdcf457926 100644
--- a/Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt
+++ b/Documentation/devicetree/bindings/sound/mikroe,mikroe-proto.txt
@@ -20,4 +20,3 @@ Example:
 		audio-codec = <&wm8731>;
 		dai-format = "i2s";
         };
-};
diff --git a/Documentation/devicetree/bindings/usb/iproc-udc.txt b/Documentation/devicetree/bindings/usb/iproc-udc.txt
index 272d7faf1a97..6a701ce29ff1 100644
--- a/Documentation/devicetree/bindings/usb/iproc-udc.txt
+++ b/Documentation/devicetree/bindings/usb/iproc-udc.txt
@@ -19,3 +19,4 @@ Example:
 		reg = <0x664e0000 0x2000>;
 		interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>;
 		phys = <&usbdrd_phy>;
+	};
-- 
2.54.0


^ permalink raw reply related

* Re: Question regarding CC list for pt_BR translation patches
From: Jonathan Corbet @ 2026-07-13 13:49 UTC (permalink / raw)
  To: Daniel Pereira, linux-doc
In-Reply-To: <CAMAsx6cLjU1N6zuM47KZcsRhq1ABvRZkw_y57szBHNe1o23tVw@mail.gmail.com>

Daniel Pereira <danielmaraboo@gmail.com> writes:

> Could you please clarify if you prefer to be CC'd on these translation
> patches, or is sending them solely to the mailing list sufficient for
> your review? I want to make sure we are following the community's best
> practices.

It's always best to CC the maintainer(s) directly.  I do keep an eye on
the list, but the chances of something falling through the cracks are
higher if it is not sent to me directly as well.

Thanks,

jon

^ permalink raw reply

* Re: [PATCH 7/8] mm/khugepaged: clarify a comment regarding max_ptes_none check
From: Nico Pache @ 2026-07-13 13:58 UTC (permalink / raw)
  To: Usama Arif
  Cc: linux-doc, linux-kernel, linux-mm, David Hildenbrand,
	Andrew Morton, Lorenzo Stoakes, Zi Yan, Baolin Wang,
	Liam R. Howlett, Ryan Roberts, Dev Jain, Barry Song, Lance Yang,
	Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
	Jonathan Corbet, Shuah Khan
In-Reply-To: <20260706193556.876676-1-usama.arif@linux.dev>

On Mon, Jul 6, 2026 at 1:36 PM Usama Arif <usama.arif@linux.dev> wrote:
>
> On Mon,  6 Jul 2026 09:44:54 -0600 Nico Pache <npache@redhat.com> wrote:
>
> > While reading collapse_scan_pmd, one may be confused on where the deferred
> > max_ptes_none check is done. Expand on this current comment by explaining
> > which function the max_ptes_none check is now done.
> >
> > Suggested-by: David Hildenbrand <david@kernel.org>
> > Signed-off-by: Nico Pache <npache@redhat.com>
> > ---
> >  mm/khugepaged.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/mm/khugepaged.c b/mm/khugepaged.c
> > index 3c6f1254deca..388045a524a3 100644
> > --- a/mm/khugepaged.c
> > +++ b/mm/khugepaged.c
> > @@ -1728,7 +1728,8 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> >
> >       /*
> >        * If PMD is the only enabled order, enforce max_ptes_none, otherwise
> > -      * scan all pages to populate the bitmap for mTHP collapse.
> > +      * scan all pages to populate the bitmap for mTHP collapse. The bitmap
> > +      * is then checked again in mthp_collapse() for each attempted order.
>
> Could be combined with patch 4?

Yeah, sure :)

Thanks
-- Nico

>
>          */
> >       if (enabled_orders != BIT(HPAGE_PMD_ORDER))
> >               ctx.max_ptes_none = KHUGEPAGED_MAX_PTES_LIMIT;
> > --
> > 2.54.0
> >
> >
>


^ permalink raw reply

* Re: [PATCH v6 4/7] bus: mhi: Add QDU100 Sahara variant and firmware fallback
From: Kishore Batta @ 2026-07-13 14:16 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Jonathan Corbet, Shuah Khan, Jeff Hugo, Carl Vanderlip,
	Oded Gabbay, linux-doc, linux-kernel, linux-arm-msm, dri-devel,
	mhi
In-Reply-To: <n45ii7ekxeefuxw2ydwzsx7lqlfczbgg6obrzmzpytl2fin7j5@vbhmrptcjvcb>


On 7/9/2026 11:49 AM, Manivannan Sadhasivam wrote:
> On Wed, Jul 01, 2026 at 04:07:38PM +0530, Kishore Batta wrote:
>> The Sahara driver currently selects a firmware image table based on the
>> attached device, but it does not recognize QDU100 devices that expose the
>> protocol on the SAHARA MHI channel. As a result, the host cannot associate
>> QDU100 devices with the correct firmware namespace during image transfer.
>>
>> Extend the probe time variant selection to match the SAHARA MHI channel and
>> associate it with the QDU100 firmware folder. Add a firmware lookup
>> fallback for cases where an image does not have an explicit entry in the
>> device's firmware table. This allows required images to be provisioned by
>> the platform.
>>
>> This change only affects devices matched on the SAHARA MHI channel and
>> does not change behavior for existing AIC100 and AIC200 devices.
>>
>> Signed-off-by: Kishore Batta <kishore.batta@oss.qualcomm.com>
>> ---
>>   drivers/bus/mhi/host/clients/sahara/sahara.c | 27 +++++++++++++++--
>>   drivers/bus/mhi/host/pci_generic.c           | 45 ++++++++++++++++++++++++++++
>>   2 files changed, 70 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/bus/mhi/host/clients/sahara/sahara.c b/drivers/bus/mhi/host/clients/sahara/sahara.c
>> index e339c67e236af271645ca81cc517efd9eead87e4..9adbd84859073d8024ba2a5fcfa33897439d6759 100644
>> --- a/drivers/bus/mhi/host/clients/sahara/sahara.c
>> +++ b/drivers/bus/mhi/host/clients/sahara/sahara.c
>> @@ -189,6 +189,7 @@ static bool is_streaming(struct sahara_context *context)
>>   
>>   static int sahara_find_image(struct sahara_context *context, u32 image_id)
>>   {
>> +	char *fw_path;
>>   	int ret;
>>   
>>   	if (image_id == context->active_image_id)
>> @@ -201,8 +202,28 @@ static int sahara_find_image(struct sahara_context *context, u32 image_id)
>>   	}
>>   
>>   	if (image_id >= context->table_size || !context->image_table[image_id]) {
>> -		dev_err(&context->mhi_dev->dev, "request for unknown image: %d\n", image_id);
>> -		return -EINVAL;
>> +		if (!context->fw_folder) {
>> +			dev_err(&context->mhi_dev->dev,
>> +				"Request for unknown image: %u (no fw folder)\n", image_id);
>> +			return -EINVAL;
>> +		}
>> +
>> +		fw_path = kasprintf(GFP_KERNEL, "qcom/%s/%u",
>> +				    context->fw_folder, image_id);
>> +		if (!fw_path)
>> +			return -ENOMEM;
>> +
>> +		ret = firmware_request_nowarn(&context->firmware,
>> +					      fw_path,
>> +					      &context->mhi_dev->dev);
>> +		kfree(fw_path);
>> +		if (ret) {
>> +			dev_err(&context->mhi_dev->dev,
>> +				"request for unknown image: %d\n", image_id);
>> +			return -EINVAL;
>> +		}
>> +		context->active_image_id = image_id;
>> +		return 0;
>>   	}
>>   
>>   	/*
>> @@ -870,8 +891,10 @@ static void sahara_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result
>>   
>>   static const struct mhi_device_id sahara_mhi_match_table[] = {
>>   	{ .chan = "QAIC_SAHARA", },
>> +	{ .chan = "SAHARA"},
>>   	{},
>>   };
>> +MODULE_DEVICE_TABLE(mhi, sahara_mhi_match_table);
>>   
> This change should belong to a separate patch.
>
>>   static struct mhi_driver sahara_mhi_driver = {
>>   	.id_table = sahara_mhi_match_table,
>> diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
>> index 391ab146f501c6ce1c81f6138f7c491a49c2f264..82e41632afc555a53dec3d8395558ae039b33bbd 100644
>> --- a/drivers/bus/mhi/host/pci_generic.c
>> +++ b/drivers/bus/mhi/host/pci_generic.c
>> @@ -300,6 +300,43 @@ static const struct mhi_pci_dev_info mhi_qcom_qdu100_info = {
>>   	.reset_on_remove = true,
>>   };
>>   
>> +static const char * const qdu100_image_table[] = {
>> +	[5] = "qcom/qdu100/uefi.elf",
>> +	[8] = "qcom/qdu100/qdsp6sw.mbn",
>> +	[16] = "qcom/qdu100/efs1.bin",
>> +	[17] = "qcom/qdu100/efs2.bin",
>> +	[20] = "qcom/qdu100/efs3.bin",
>> +	[23] = "qcom/qdu100/aop.mbn",
>> +	[25] = "qcom/qdu100/tz.mbn",
>> +	[29] = "qcom/qdu100/zeros_1sector.bin",
>> +	[33] = "qcom/qdu100/hypvm.mbn",
>> +	[34] = "qcom/qdu100/mdmddr.mbn",
>> +	[36] = "qcom/qdu100/multi_image_qti.mbn",
>> +	[37] = "qcom/qdu100/multi_image.mbn",
>> +	[38] = "qcom/qdu100/xbl_config.elf",
>> +	[39] = "qcom/qdu100/abl_userdebug.elf",
>> +	[40] = "qcom/qdu100/zeros_1sector.bin",
>> +	[41] = "qcom/qdu100/devcfg.mbn",
>> +	[42] = "qcom/qdu100/zeros_1sector.bin",
>> +	[45] = "qcom/qdu100/tools_l.elf",
>> +	[46] = "qcom/qdu100/Quantum.elf",
>> +	[47] = "qcom/qdu100/quest.elf",
>> +	[48] = "qcom/qdu100/xbl_ramdump.elf",
>> +	[49] = "qcom/qdu100/shrm.elf",
>> +	[50] = "qcom/qdu100/cpucp.elf",
>> +	[51] = "qcom/qdu100/aop_devcfg.mbn",
>> +	[52] = "qcom/qdu100/fw_csm_gsi_3.0.elf",
>> +	[53] = "qcom/qdu100/qdsp6sw_dtbs.elf",
>> +	[54] = "qcom/qdu100/qupv3fw.elf",
>> +};
>> +
>> +static const struct mhi_sahara_fw_table qdu100_sahara_fw = {
>> +	.image_table = qdu100_image_table,
>> +	.table_size = ARRAY_SIZE(qdu100_image_table),
>> +	.fw_folder = "qdu100",
>> +	.non_streaming = false,
>> +};
>> +
>>   static const struct mhi_channel_config mhi_qcom_sa8775p_channels[] = {
>>   	MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 2048, 1),
>>   	MHI_CHANNEL_CONFIG_DL(47, "IP_SW0", 2048, 2),
>> @@ -1399,6 +1436,14 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>>   
>>   	pci_set_drvdata(pdev, mhi_pdev);
>>   
>> +	/*
>> +	 * Provide Sahara firmware mapping. Sahara consumes it via
>> +	 * mhi_dev->mhi_cntrl->sahara_fw at probe time.
>> +	 */
>> +	if (info == &mhi_qcom_qdu100_info ||
>> +	    (info->name && !strcmp(info->name, "qcom-qdu100")))
>> +		mhi_cntrl->sahara_fw = &qdu100_sahara_fw;
>> +
> Why are you adding QAIC MHI controller config in pci_generic driver? This driver
> only handles Modem devices.
>
> - Mani


Hi Mani, Above one is for QDU100 device. QAIC is not added in this file.

>

^ permalink raw reply

* Re: [PATCH v7 02/12] cpumask: Introduce cpu_preferred_mask
From: Yury Norov @ 2026-07-13 14:53 UTC (permalink / raw)
  To: Shrikanth Hegde
  Cc: linux-kernel, mingo, peterz, juri.lelli, vincent.guittot,
	yury.norov, kprateek.nayak, iii, corbet, tglx, gregkh, pbonzini,
	seanjc, vschneid, huschle, rostedt, dietmar.eggemann, maddy,
	srikar, hdanton, chleroy, vineeth, frederic, arighi, pauld,
	christian.loehle, tj, tommaso.cucinotta, maz, rafael, rdunlap,
	kernellwp, linux-doc
In-Reply-To: <20260709215648.1246821-3-sshegde@linux.ibm.com>

On Fri, Jul 10, 2026 at 03:26:38AM +0530, Shrikanth Hegde wrote:
> Provide cpu_preferred_mask infrastructure. Define get/set macros
> which could be used to get/set CPU state as preferred.
> 
> PREFERRED_CPU config will be selected by the driver which handles
> steal time values. It is going to set/clear preferred CPU state.
> This driver will be called steal_monitor and it is introduced in
> subsequent patches. It periodically samples the steal time and
> decides on preferred CPU state.
> 
> A CPU is set to preferred when it becomes active. Later it may be
> marked as non-preferred depending on steal time values with
> steal_monitor being enabled.
> 
> Always maintain design construct of preferred is subset of active.
> i.e. preferred ⊆ active ⊆ online ⊆ present ⊆ possible
> 
> With PREFERRED_CPU=n, ensure set_cpu_preferred is a nop and get
> method returns the active state in that case.
> 
> Signed-off-by: Shrikanth Hegde <sshegde@linux.ibm.com>
> ---
> v6->v7:
> - removed CONFIG_PREFERRED_CPU as user option.
> - Use do { } while (0) for nop 
> 
>  include/linux/cpumask.h | 24 ++++++++++++++++++++++++
>  kernel/Kconfig.preempt  |  3 +++
>  kernel/cpu.c            |  6 ++++++
>  kernel/sched/core.c     |  5 +++++
>  4 files changed, 38 insertions(+)
> 
> diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
> index d3cda0544954..34d08a3d80e1 100644
> --- a/include/linux/cpumask.h
> +++ b/include/linux/cpumask.h
> @@ -122,12 +122,20 @@ extern struct cpumask __cpu_enabled_mask;
>  extern struct cpumask __cpu_present_mask;
>  extern struct cpumask __cpu_active_mask;
>  extern struct cpumask __cpu_dying_mask;
> +
> +#ifdef CONFIG_PREFERRED_CPU
> +extern struct cpumask __cpu_preferred_mask;
> +#else
> +#define __cpu_preferred_mask __cpu_active_mask
> +#endif
> +
>  #define cpu_possible_mask ((const struct cpumask *)&__cpu_possible_mask)
>  #define cpu_online_mask   ((const struct cpumask *)&__cpu_online_mask)
>  #define cpu_enabled_mask   ((const struct cpumask *)&__cpu_enabled_mask)
>  #define cpu_present_mask  ((const struct cpumask *)&__cpu_present_mask)
>  #define cpu_active_mask   ((const struct cpumask *)&__cpu_active_mask)
>  #define cpu_dying_mask    ((const struct cpumask *)&__cpu_dying_mask)
> +#define cpu_preferred_mask ((const struct cpumask *)&__cpu_preferred_mask)
>  
>  extern atomic_t __num_online_cpus;
>  extern unsigned int __num_possible_cpus;
> @@ -1164,6 +1172,12 @@ void init_cpu_possible(const struct cpumask *src);
>  #define set_cpu_active(cpu, active)	assign_cpu((cpu), &__cpu_active_mask, (active))
>  #define set_cpu_dying(cpu, dying)	assign_cpu((cpu), &__cpu_dying_mask, (dying))
>  
> +#ifdef CONFIG_PREFERRED_CPU
> +#define set_cpu_preferred(cpu, preferred) assign_cpu((cpu), &__cpu_preferred_mask, (preferred))
> +#else
> +#define set_cpu_preferred(cpu, preferred) do { } while (0)
> +#endif
> +
>  void set_cpu_online(unsigned int cpu, bool online);
>  void set_cpu_possible(unsigned int cpu, bool possible);
>  
> @@ -1258,6 +1272,11 @@ static __always_inline bool cpu_dying(unsigned int cpu)
>  	return cpumask_test_cpu(cpu, cpu_dying_mask);
>  }
>  
> +static __always_inline bool cpu_preferred(unsigned int cpu)
> +{
> +	return cpumask_test_cpu(cpu, cpu_preferred_mask);
> +}
> +
>  #else
>  
>  #define num_online_cpus()	1U
> @@ -1296,6 +1315,11 @@ static __always_inline bool cpu_dying(unsigned int cpu)
>  	return false;
>  }
>  
> +static __always_inline bool cpu_preferred(unsigned int cpu)
> +{
> +	return cpu == 0;
> +}
> +
>  #endif /* NR_CPUS > 1 */
>  
>  #define cpu_is_offline(cpu)	unlikely(!cpu_online(cpu))
> diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
> index 88c594c6d7fc..ed02e4431230 100644
> --- a/kernel/Kconfig.preempt
> +++ b/kernel/Kconfig.preempt
> @@ -192,3 +192,6 @@ config SCHED_CLASS_EXT
>  	  For more information:
>  	    Documentation/scheduler/sched-ext.rst
>  	    https://github.com/sched-ext/scx
> +
> +config PREFERRED_CPU
> +	bool

This still should depend on PARAVIRT and SMP. And maybe to enforce it
even stronger, your driver should fail to build if PREFERRED_CPU is
disabled. Imagine a scenario when someone makes PREFERRED_CPU
depending on some other config, but doesn't modify your driver. That
way you'll build the STEAL_MONITOR successfully, but because
PREFERRED_CPU is off, you'll end up with non-working functionality at
best, or corrupted cpu_active_mask at worst.

Also, the name 'steal monitor' implies monitoring, while in fact
you're actively affecting the scheduling process.

Maybe 'steal governor'?

Thanks,
Yury

^ permalink raw reply

* Re: [PATCH v8 4/8] mshv: Use hmm_range_fault_unlocked_timeout() for region faults
From: Jason Gunthorpe @ 2026-07-13 14:55 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Stanislav Kinsburskii, airlied, akhilesh, corbet, dakr, david,
	decui, haiyangz, kees, kys, leon, liam, lizhi.hou, ljs, longli,
	lyude, maarten.lankhorst, mamin506, mhocko, mripard, nouveau,
	ogabbay, oleg, rppt, shuah, simona, skhan, surenb, tzimmermann,
	vbabka, wei.liu, dri-devel, linux-mm, linux-doc, linux-hyperv,
	linux-kernel, linux-kselftest, linux-rdma
In-Reply-To: <20260710151216.0397a6f9ac5c7b4ccd274cc1@linux-foundation.org>

On Fri, Jul 10, 2026 at 03:12:16PM -0700, Andrew Morton wrote:
> > +	mutex_lock(&region->mreg_mutex);
> > +
> > +	if (mmu_interval_read_retry(range.notifier, range.notifier_seq)) {
> > +		mutex_unlock(&region->mreg_mutex);
> > +		cond_resched();
> > +		goto again;
> > +	}
> > +
> 
> If the calling process has realtime scheduling policy and either a)
> we're uniprocessor or b) this process and the holder of
> interval_sub->invalidate_seq are both pinned to the same CPU then
> cond_resched() won't do anything, and this might be an infinite loop?

I think hmm and kvm have had this issue for a long time? I don't see
anything in the mmu notifier locking scheme that would alleviate it at
least

So.. In terms of this series I'd leave it, it is no worse than before?

Jason

^ permalink raw reply

* Re: [PATCH net-next v4 02/15] libie: add PCI device initialization helpers to libie
From: Larysa Zaremba @ 2026-07-13 14:55 UTC (permalink / raw)
  To: Tony Nguyen
  Cc: davem, kuba, pabeni, edumazet, andrew+netdev, netdev,
	Phani R Burra, przemyslaw.kitszel, aleksander.lobakin,
	sridhar.samudrala, anjali.singhai, michal.swiatkowski,
	maciej.fijalkowski, emil.s.tantilov, madhu.chittim, joshua.a.hay,
	jacob.e.keller, jayaprakash.shanmugam, jiri, horms, corbet,
	richardcochran, linux-doc, Bharath R, Samuel Salin
In-Reply-To: <20260710215313.1475803-3-anthony.l.nguyen@intel.com>

Sashiko has 1 concern about this patch, and I think it is not very relevant, as 
this is a 32-bit issue on a 200G+ HW, which AI also mentions. Seems like 
checking offsets under ifdefs would be unneccessarily defensive.

Sashiko says:
> commit 0540f7038f92c56e3d90344d11ab6f07b9f6b975
> Author: Phani R Burra <phani.r.burra@intel.com>
> libie: add PCI device initialization helpers to libie
> This patch introduces libie helpers for PCI init, MMIO mapping bookkeeping
> via a list of libie_pci_mmio_region entries, and a lookup helper to
> translate offsets to virtual addresses. The public map/get APIs accept
> resource_size_t offset and size arguments and are intended to be shared by
> idpf and ixd.
> > diff --git a/drivers/net/ethernet/intel/libie/pci.c b/drivers/net/ethernet/intel/libie/pci.c
> > new file mode 100644
> > index 000000000000..a0d3535d6529
> > --- /dev/null
> > +++ b/drivers/net/ethernet/intel/libie/pci.c
> [ ... ]
> > +bool __libie_pci_map_mmio_region(struct libie_mmio_info *mmio_info,
> > +				 resource_size_t offset,
> > +				 resource_size_t size, int num_args, ...)
> > +{
> > +	struct pci_dev *pdev = mmio_info->pdev;
> > +	struct libie_pci_mmio_region *mr;
> > +	resource_size_t end_offset;
> > +	void __iomem *va;
> > +	int bar_idx = 0;
> > +	va_list args;
> > +
> > +	if (num_args) {
> > +		va_start(args, num_args);
> > +		bar_idx = va_arg(args, int);
> > +		va_end(args);
> > +	}
> > +
> > +	/* pci_iomap_range() would silently map less in such case */
> > +	if (!size || check_add_overflow(offset, size, &end_offset) ||
> > +	    end_offset > pci_resource_len(pdev, bar_idx))
> > +		return false;
> Can this API silently truncate the mapping on 32-bit PAE builds?
> The parameters offset and size are resource_size_t, and the bounds check
> above is performed in resource_size_t arithmetic against
> pci_resource_len(), which is fine.
> However, pci_iomap_range() is declared as:
>   void __iomem *pci_iomap_range(struct pci_dev *dev, int bar,
>                                 unsigned long offset,
>                                 unsigned long maxlen);
> On 32-bit configs with CONFIG_PHYS_ADDR_T_64BIT (for example PAE),
> resource_size_t is 64-bit while unsigned long is 32-bit.
> > +	va = pci_iomap_range(mmio_info->pdev, bar_idx, offset, size);
> If a caller passes an offset or size >= 4 GiB that legitimately fits
> within a 64-bit BAR, the libie-level bounds check passes but the values
> are silently truncated when handed to pci_iomap_range(), so the wrong
> sub-range gets mapped and the mr->offset / mr->size stored in the list
> no longer describe the memory actually returned by pci_iomap_range().
> Would it make sense to either reject offset/size that exceed ULONG_MAX
> here, or narrow the map API to unsigned long so the truncation is
> visible at the type level? In-tree idpf and ixd likely never hit this
> today, but the public signature invites the mismatch.
> > +	if (!va) {
> > +		pci_err(pdev, "Failed to map BAR%u region\n", bar_idx);
> > +		return false;
> > +	}
> [ ... ]

^ permalink raw reply

* [PATCH] Documentation: usb: remove dead link to external USB programming guide
From: Utsav Shankar @ 2026-07-13 15:05 UTC (permalink / raw)
  To: Jonathan Corbet; +Cc: Shuah Khan, linux-doc, linux-usb, Utsav Shankar

The "Programming Guide for Linux USB Device Drivers" was last hosted
at lmu.web.psi.ch and is no longer reachable. The original source
(TUM, cs.tum.edu) is also defunct. Remove the dead reference rather
than link to a third-party archive of a 20+ year old, outdated guide.

Signed-off-by: Utsav Shankar <utsaveshan0206@gmail.com>
---
 Documentation/driver-api/usb/writing_usb_driver.rst | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/Documentation/driver-api/usb/writing_usb_driver.rst b/Documentation/driver-api/usb/writing_usb_driver.rst
index 95c4f5d14..6f024e164 100644
--- a/Documentation/driver-api/usb/writing_usb_driver.rst
+++ b/Documentation/driver-api/usb/writing_usb_driver.rst
@@ -322,7 +322,4 @@ http://linux-hotplug.sourceforge.net/
 linux-usb Mailing List Archives:
 https://lore.kernel.org/linux-usb/
 
-Programming Guide for Linux USB Device Drivers:
-https://lmu.web.psi.ch/docu/manuals/software_manuals/linux_sl/usb_linux_programming_guide.pdf
-
 USB Home Page: https://www.usb.org
-- 
2.54.0


^ permalink raw reply related

* Re: [PATCH] PCI: rcar-gen4: Inline GIC_TRANSLATER offset macro
From: Marc Zyngier @ 2026-07-13 15:20 UTC (permalink / raw)
  To: Marek Vasut
  Cc: linux-pci, kernel test robot, Krzysztof Wilczyński,
	Bjorn Helgaas, Catalin Marinas, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Lorenzo Pieralisi, Manivannan Sadhasivam,
	Rob Herring, Yoshihiro Shimoda, devicetree, linux-arm-kernel,
	linux-doc, linux-kernel, linux-renesas-soc
In-Reply-To: <2cb03029-0957-4ed8-98bd-9b3e0e0bce2d@mailbox.org>

On Fri, 10 Jul 2026 14:35:10 +0100,
Marek Vasut <marek.vasut@mailbox.org> wrote:
> 
> On 7/10/26 10:30 AM, Marc Zyngier wrote:
> > On Thu, 09 Jul 2026 21:10:03 +0100,
> > Marek Vasut <marek.vasut+renesas@mailbox.org> wrote:
> >> 
> >> Instead of pulling in the whole linux/irqchip/arm-gic-v3.h , copy the
> >> one GITS_TRANSLATER register offset macro directly into the driver.
> >> This repairs the ability to build the driver on non-ARM non-GIC targets
> >> the way it was possible until now, which retains good build test coverage.
> >> 
> >> Reported-by: kernel test robot <lkp@intel.com>
> >> Closes: https://lore.kernel.org/oe-kbuild-all/202607100310.iQw5m9Uo-lkp@intel.com/
> >> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
> >> ---
> >> Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
> >> Cc: Bjorn Helgaas <bhelgaas@google.com>
> >> Cc: Catalin Marinas <catalin.marinas@arm.com>
> >> Cc: Conor Dooley <conor+dt@kernel.org>
> >> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> >> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> >> Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
> >> Cc: Manivannan Sadhasivam <mani@kernel.org>
> >> Cc: Marc Zyngier <maz@kernel.org>
> >> Cc: Rob Herring <robh@kernel.org>
> >> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> >> Cc: devicetree@vger.kernel.org
> >> Cc: linux-arm-kernel@lists.infradead.org
> >> Cc: linux-doc@vger.kernel.org
> >> Cc: linux-kernel@vger.kernel.org
> >> Cc: linux-pci@vger.kernel.org
> >> Cc: linux-renesas-soc@vger.kernel.org
> >> ---
> >> Note: The alternative I could think of would be ifdeffery which
> >>        is not nice and thwarts the build coverage, or limit the
> >>        driver to ARM/ARM64 in Kconfig which also thwarts the build
> >>        coverage. I could also split off the register macros in
> >>        linux/irqchip/arm-gic-v3.h into some separate header
> >>        linux/irqchip/arm-gic-v3-regs.h and include that which
> >>        might be OKish and avoids duplication. Thoughts ?
> > 
> > No, I'm not hacking something that is purely architecture specific for
> > the purpose of a bizarre integration quirk that should be handled by
> > the boot firmware, and not Linux.
> 
> The PCIe controller is fully controlled by Linux.

And it shouldn't. Why can't your favourite boot-loader use it, like on
any reasonable machine?

	M.

-- 
Jazz isn't dead. It just smells funny.

^ permalink raw reply

* Re: [PATCH v2 0/5] binfmt_misc: bpf-backed binary type handlers
From: Farid Zakaria @ 2026-07-13 15:19 UTC (permalink / raw)
  To: Christian Brauner, Farid Zakaria
  Cc: Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau, Shuah Khan,
	Andrii Nakryiko, Kees Cook, Alexander Viro, Jan Kara,
	Jonathan Corbet, Jann Horn, John Ericson, linux-fsdevel, linux-mm,
	linux-kernel, bpf, linux-doc, linux-kselftest
In-Reply-To: <20260713-unerlaubt-luftkammer-kosmetik-46532d395f9b@brauner>

On Mon Jul 13, 2026 at 1:20 AM PDT, Christian Brauner wrote:
>> > - The single sleepable load op is split into two ops:
>> >
>> >       struct binfmt_misc_ops {
>> >       	bool (*match)(struct linux_binprm *bprm);
>> >       	int (*load)(struct linux_binprm *bprm);
>> >       	char name[BINFMT_MISC_OPS_NAME_MAX];
>> >       };
>> >
>> >   The non-sleepable match program runs from the RCU entry lookup
>> >   walk itself, exactly like magic and extension matching: same
>> >   registration order, same first-match-wins semantics, and it can
>> >   only rely on the prefetched bprm->buf. It must be free of side
>> >   effects since the walk may be restarted.
>> >
>> 
>> Is relying on brpm->buf enough?
>> Right now that's only 256 bytes I think, which is not enough to read
>> segments we might care about. That worked fine when it was just a magic
>> number but the idea with the eBPF program is to make decisions based on
>> more data.
>> 
>> In the selftest I provided, the `PT_INTERP` segment is already at file
>> offset 0x318 (792). I was imaginging NixOS having to support
>> `PT_INTERP_NIX` in order for the produced binaries to be backwards
>> compatible with older kernels.
>> 
>> The other idea would be to make the `match()` broad and select
>> everything but then nearly all ELF64 binaries would match and then pay
>> the price to `load()` and ultimately `-ENOEXEC`. Seems like it would
>> make multiple BPF binfmt programs less useful.
>
> Ok, so your idea is to have multiple bpf programs that look for
> different interpreters. Yeah, then you have to be able to sleep because
> you need to be able to fault. It makes the code uglier but I can see how
> that's useful. I'll see how nice I can make that.
>

I mean... I thought that's the intent to binfmt_misc, to have multiple
handlers -- with the expressiveness of eBPF vs. the limited
magic/extension, it seems like a natural extension to support multiple.
Otherwise anyone on NixOS would be limited to our single handler for all
binaries which seems not ideal?

I'm not knowledgeable enough to comment on the sleep/faulting aspect so
I leave that to your expertise.

>> >   The sleepable load program runs once the walk has committed to the
>> >   entry and does the file reading and the interpreter selection. Both
>> >   ops are mandatory, the struct_ops plumbing enforces the sleepability
>> >   of each, and since bpf_binprm_set_interp() is KF_SLEEPABLE a match
>> >   program cannot select an interpreter by construction.
>> >
>> > - A match is a commitment. A failing load program fails the exec instead
>> >   of falling through to later entries. -ENOEXEC keeps its usual meaning
>> >   and hands the binary to the remaining binary formats, for a handler
>> >   that discovers it cannot serve the binary after all.
>> >
>> >   This kills the part of v1 I disliked the most: the skip cursor and the
>> >   leave-and-rescan loop in load_misc_binary() are gone. The walk is
>> >   never left and re-entered, and 'B' entries need no special semantics
>> >   against concurrent (un)registration anymore.
>> >
>> >   Your v2 changelog note about keeping the bpf retry loop in the
>> >   __free() style is moot as a consequence. The loop no longer exists.
>> >
>> > - The load return convention flipped: 0 now means success after the
>> >   program called bpf_binprm_set_interp(). Returning 0 without having
>> >   selected an interpreter or returning a positive value is treated as
>> >   -ENOEXEC, other negative errnos fail the exec.
>> >
>> >   So the "return bpf_binprm_set_interp(...) ?: 1" idiom from the v1-era
>> >   programs becomes plain "return bpf_binprm_set_interp(...)".
>> >
>> > - The handler name moved from the offset field to the interpreter field
>> >   that field consistently names whoever supplies the interpreter, a path
>> >   for static entries, a handler for 'B' entries. Offset, magic, and mask
>> >   must be empty:
>> >
>> > 	echo ':nix-origin:B::::nix_origin:' > register
>> >
>> > - 'C' is allowed now, v1 rejected it. It behaves exactly as for a static
>> >    entry. The setuid transition stays gated by vfsuid_has_mapping() in
>> >    the caller's user namespace. Which makes 'B' handlers usable for a
>> >    per-binary loader over setuid binaries. 'F' stays rejected as there
>> >    is no fixed interpreter to pre-open (I have other ideas how we'll do
>> >    something like it later.).
>> >
>> > Nothing changed in the exec patch, the fs kfuncs patch, the kfunc
>> > itself, or the registry/namespacing model.
>> >
>> > I can send v3 in a bit if that's ok.
>> 
>> I don't mind at all you sending v3 and in fact I've been enjoying your
>> involvement. I didn't know what to expect when I offered this idea up to
>> the community. 
>> 
>> I'm happy to keep co-developing this with you within a design you feel
>> acceptable with. Please let me know how I can remain engaged and
>> helpful.
>> 
>> One last thing I was thinking about is that we will also need to support
>> $ORIGIN in the shebang path, however I just tested it and this current broad
>> BPF solution can largely handle it [1], with a small wrinkle.
>> 
>>   $ printf '#!$ORIGIN/interp\n' > /opt/app/greet
>>   $ cp ./interp /opt/app/interp     # any interpreter/loader
>>   $ chmod +x /opt/app/greet /opt/app/interp
>> 
>>   # stock kernel: binfmt_script opens the literal "$ORIGIN/interp"
>>   $ /opt/app/greet
>>   bash: /opt/app/greet: $ORIGIN/interp: bad interpreter: No such file or directory
>> 
>>   # with the handler registered, $ORIGIN resolves to the script's dir
>>   $ bpftool struct_ops register shebang_origin.bpf.o /sys/fs/bpf
>>   $ echo ':shebang-origin:B:shebang_origin::::' > /proc/sys/fs/binfmt_misc/register
>>   $ /opt/app/greet
>>   <runs /opt/app/interp, the loader found next to the script>
>> 
>> The wrinkle is that it can't express today is the single optional argument.
>> (i.e. `#!interp arg" -> argv[1]=arg`). We might ned a way to express
>> that in the load.
>
> Ah, fun. binfmt_misc wasn't able to express this at all. It's good to
> close that gap. This can just be done by adding
> bpf_binprm_set_interp_arg().

What is "cool" about this is now it's also a net-new feature for shebags
which the "old" binfmt_misc didn't support. Anyways, I was thining ahead
about what I would need to support $ORIGIN fully and this was
a remaining gap. We also explored this idea in a patch pre-BPF [1] but
now that we've settled on this solution it seems much more natural.


I was recently reached out by some Bazel people who are also interested
in this $ORIGIN support. Interestingly they let me know that
IllumOS/Solaris had support for it as well.

[1] https://github.com/alurm/relocatable-shebangs/blob/18db0da6cd69ce19bb0273f2548a2d96bdaa82b1/relocatable-shebangs.patch

^ permalink raw reply

* Re: [PATCH v2] arch: arm64: add early_param idle=<wfi|yield|nop>
From: Sudeep Holla @ 2026-07-13 15:26 UTC (permalink / raw)
  To: Will Deacon
  Cc: Yureka Lilian, Jonathan Corbet, Shuah Khan, Catalin Marinas,
	Sudeep Holla, Anshuman Khandual, linux-doc, linux-kernel,
	linux-arm-kernel
In-Reply-To: <alTTIx_aw3L0ibqN@willie-the-truck>

On Mon, Jul 13, 2026 at 12:59:31PM +0100, Will Deacon wrote:
> On Mon, Jul 13, 2026 at 10:57:38AM +0100, Sudeep Holla wrote:
> > On Sat, Jul 11, 2026 at 09:35:25AM +0200, Yureka Lilian wrote:
> > > Overriding the idle mechanism might be useful for debugging and performance
> > > testing. Add a cmdline parameter for it, similar to the existing idle=
> > > parameter already present for the x86 and ppc architectures.
> > > 
> > > It is also useful on platforms where the WFI instruction misbehaves,
> > > such as Apple Silicon SoCs. Generally, a misbehaving instruction should
> > > be treated as an erratum and patched using the alternatives framework.
> > > However, in the Apple Silicon case we need more flexibility because it is
> > > difficult to detect whether the erratum applies. For example, Linux VMs
> > > inside macOS have the same MIDR and may even seem like they're running
> > > in EL2 in the case of NV, but should continue using WFI (it's trapped and
> > > handled correctly by the hypervisor there). Thus, we prefer to
> > > let the m1n1 bootloader add the idle=nop parameter[1].
> > > 
> > > Link[1]: https://lore.kernel.org/all/99b69262-e54b-424e-baa2-96ef7013b87a@kernel.org/
> > > Suggested-by: Will Deacon <will@kernel.org>
> > > Signed-off-by: Yureka Lilian <yureka@cyberchaos.dev>
> > > ---
> > > Changes in v2:
> > > - Applied suggestions by Anshuman Khandual (Thanks!)
> > > - Link to v1: https://patch.msgid.link/20260705-arm64-idle-param-v1-1-7454249f473f@cyberchaos.dev
> > > ---
> > >  Documentation/admin-guide/kernel-parameters.txt | 23 +++++++++++++++++++
> > >  arch/arm64/kernel/idle.c                        | 30 +++++++++++++++++++++++--
> > >  arch/arm64/kernel/idle.h                        | 13 +++++++++++
> > >  arch/arm64/lib/delay.c                          |  5 ++++-
> > >  4 files changed, 68 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> > > index b2d7d3540ded..d7f5471edf8f 100644
> > > --- a/Documentation/admin-guide/kernel-parameters.txt
> > > +++ b/Documentation/admin-guide/kernel-parameters.txt
> > > @@ -2239,6 +2239,29 @@ Kernel parameters
> > >  
> > >  			idle=nomwait: Disable mwait for CPU C-states
> > >  
> > > +			[ARM64,EARLY]
> > > +			Format: idle=wfi, idle=yield, idle=nop
> > > +
> > > +			idle=wfi: Use the WFI (Wait For Interrupt) hint
> > > +			instruction in the idle loop. This is the default and
> > > +			allows the CPU to enter a low-power state until an
> > > +			interrupt arrives.
> > 
> > Just curious as when and why one would need to use idle=wfi if that is the
> > default behaviour. I am missing the need to have it.
> 
> It's probably useful to have so that you can override an idle= option
> present earlier in the cmdline. e.g.
> 
> 	idle=nop idle=wfi
> 
> will give you the wfi behaviour, which is handy if the cmdline is
> stitched topgether from different sources.
> 

Thanks, that makes sense.

-- 
Regards,
Sudeep

^ permalink raw reply

* Re: [PATCH v2] arch: arm64: add early_param idle=<wfi|yield|nop>
From: Sudeep Holla @ 2026-07-13 15:36 UTC (permalink / raw)
  To: Anshuman Khandual
  Cc: Yureka Lilian, Jonathan Corbet, Sudeep Holla, Shuah Khan,
	Catalin Marinas, Will Deacon, linux-doc, linux-kernel,
	linux-arm-kernel
In-Reply-To: <22ba1b98-ddc8-4fff-a372-6e4aa2b59c7c@arm.com>

On Mon, Jul 13, 2026 at 05:54:16PM +0530, Anshuman Khandual wrote:
> On 13/07/26 3:27 PM, Sudeep Holla wrote:
> > On Sat, Jul 11, 2026 at 09:35:25AM +0200, Yureka Lilian wrote:
> >> Overriding the idle mechanism might be useful for debugging and performance
> >> testing. Add a cmdline parameter for it, similar to the existing idle=
> >> parameter already present for the x86 and ppc architectures.
> >>
> >> It is also useful on platforms where the WFI instruction misbehaves,
> >> such as Apple Silicon SoCs. Generally, a misbehaving instruction should
> >> be treated as an erratum and patched using the alternatives framework.
> >> However, in the Apple Silicon case we need more flexibility because it is
> >> difficult to detect whether the erratum applies. For example, Linux VMs
> >> inside macOS have the same MIDR and may even seem like they're running
> >> in EL2 in the case of NV, but should continue using WFI (it's trapped and
> >> handled correctly by the hypervisor there). Thus, we prefer to
> >> let the m1n1 bootloader add the idle=nop parameter[1].
> >>
> >> Link[1]: https://lore.kernel.org/all/99b69262-e54b-424e-baa2-96ef7013b87a@kernel.org/
> >> Suggested-by: Will Deacon <will@kernel.org>
> >> Signed-off-by: Yureka Lilian <yureka@cyberchaos.dev>
> >> ---
> >> Changes in v2:
> >> - Applied suggestions by Anshuman Khandual (Thanks!)
> >> - Link to v1: https://patch.msgid.link/20260705-arm64-idle-param-v1-1-7454249f473f@cyberchaos.dev
> >> ---
> >>  Documentation/admin-guide/kernel-parameters.txt | 23 +++++++++++++++++++
> >>  arch/arm64/kernel/idle.c                        | 30 +++++++++++++++++++++++--
> >>  arch/arm64/kernel/idle.h                        | 13 +++++++++++
> >>  arch/arm64/lib/delay.c                          |  5 ++++-
> >>  4 files changed, 68 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> >> index b2d7d3540ded..d7f5471edf8f 100644
> >> --- a/Documentation/admin-guide/kernel-parameters.txt
> >> +++ b/Documentation/admin-guide/kernel-parameters.txt
> >> @@ -2239,6 +2239,29 @@ Kernel parameters
> >>  
> >>  			idle=nomwait: Disable mwait for CPU C-states
> >>  
> >> +			[ARM64,EARLY]
> >> +			Format: idle=wfi, idle=yield, idle=nop
> >> +
> >> +			idle=wfi: Use the WFI (Wait For Interrupt) hint
> >> +			instruction in the idle loop. This is the default and
> >> +			allows the CPU to enter a low-power state until an
> >> +			interrupt arrives.
> > 
> > Just curious as when and why one would need to use idle=wfi if that is the
> > default behaviour. I am missing the need to have it.
> 
> I guess once there is a list to chose options from in the command line,
> should not the default option be listed there as well ?
> 

I don't know if it is a requirement or just a practice. But for reasons
Will mentioned, it becomes a requirement.

-- 
Regards,
Sudeep

^ permalink raw reply

* Re: [PATCH v5 4/6] mm/zswap: Implement proactive writeback
From: Yosry Ahmed @ 2026-07-13 15:53 UTC (permalink / raw)
  To: Hao Jia
  Cc: akpm, tj, hannes, shakeel.butt, mhocko, mkoutny, nphamcs,
	chengming.zhou, muchun.song, roman.gushchin, linux-mm,
	linux-kernel, linux-doc, Hao Jia
In-Reply-To: <30c8df43-9464-8fa0-3614-0ca06b97862e@gmail.com>

On Fri, Jul 10, 2026 at 3:04 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
>
>
>
> On 2026/7/10 04:44, Yosry Ahmed wrote:
> > On Wed, Jul 8, 2026 at 7:15 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
> >>
> >>
> >>
> >> On 2026/7/7 03:33, Yosry Ahmed wrote:
> >>> On Thu, Jul 2, 2026 at 5:32 AM Hao Jia <jiahao.kernel@gmail.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 2026/7/1 19:45, Hao Jia wrote:
> >>>>>
> >>>>>
> >>>>> On 2026/7/1 00:10, Yosry Ahmed wrote:
> >>>>>>>> Before going through more versions we need to figure out if this will
> >>>>>>>> pivot to be a proactive demotion interfcae for swap tiering.
> >>>>>>>>
> >>>>>>>
> >>>>>>> Yes. Should I drop patches 4-6 in the next version and wait for swap
> >>>>>>> tiering to be finalized?
> >>>>>>> We can try to get the non-memcg parts (patches 1-3) merged upstream
> >>>>>>> first. This would also give them plenty of time to bake and catch any
> >>>>>>> potential regressions. Thoughts?
> >>>>>>
> >>>>>> Patches 1-2 can be sent and merged separately, yes. For patch 2,
> >>>>>> please include some numbers for the writeback performance before and
> >>>>>> after batching.
> >>>>>
> >>>>> I'd love to collect some performance data. Do you have any recommended
> >>>>> benchmarks for this?
> >>>>>
> >>>>
> >>>> Perhaps the following test case could work?
> >>>>
> >>>> Test Setup:
> >>>> - Total memory: 32 GB
> >>>> - zswap settings: max_pool_percent=1, accept_threshold_percent=50,
> >>>> shrinker_enabled=N
> >>>> - cgroup constraint: memory.max=1G
> >>>> - Workload: Run the following stress-ng command inside the cgroup for
> >>>> 120s to
> >>>>      continuously force zswap store failures and trigger shrink_worker():
> >>>>
> >>>>      bash -c 'echo $$ > /sys/fs/cgroup/zswaptest/cgroup.procs ; \
> >>>>      exec stress-ng --vm 4 --vm-bytes 4G --vm-keep --vm-method rand-set -t
> >>>> 120s -q'
> >>>>
> >>>> The following comparison results were collected over multiple runs via
> >>>> bpftrace
> >>>> and the 'written_back_pages' sysfs interface:
> >>>>
> >>>>                             Baseline         Patched
> >>>> ---------------------------------------------------
> >>>> shrink_worker wakeups       5,587             878
> >>>> shrink_memcg calls      7,823,853       2,347,320
> >>>> written_back                  257         781,214
> >>>>
> >>>> Conclusion:
> >>>> Under the same workload and duration, the patched kernel shows a
> >>>> significant reduction
> >>>> in both shrink_worker wakeups and shrink_memcg calls, while successfully
> >>>> executing a
> >>>> much higher volume of page writebacks.
> >>>
> >>> Hmm this is actually a bit concerning. Yes, we are invoking the
> >>> shrinker less, but we're writing back *a lot* more memory, orders of
> >>> magnitude more. We are using a batch size of 64, and making ~1/3 of
> >>> the calls to shrink_memcg(), so the number of written back pages
> >>> should be ~20x more, not 3000x more? I think I am missing something.
> >>>
> >>> Also, ideally, the batching wouldn't result in significantly more
> >>> writeback, but a similar amount of writeback over less shrinker
> >>> invocations. If we are writing back significantly more pages then the
> >>> batching logic is probably too aggressive?
> >>
> >> Apologies, I think the test I constructed has a bit of a problem. This
> >> test has very, very heavy memory pressure and is already a very abnormal
> >> case.
> >>
> >> The zswap entry returns the first time because of "second chance" after
> >> setting referenced to false. For the baseline, it scans 1 page per node
> >> each time for 16 loops. During the test, shrink_worker() basically exits
> >> at about 16 pages each time.
> >>
> >> Since stress-ng periodically and randomly writes to this 4G memory, it
> >> keeps triggering zswapin and then waiting to zswapout new zswap entries
> >> after falling below the pool threshold. When the speed of zswapin/out is
> >> far greater than the scanning speed of shrink_worker(), a large number
> >> of zswap entries cannot wait until the second scan for writeback. New
> >> entries are stored on the zswap LRU list again, and the referenced of
> >> the new zswap entries is set to true again. During the test, it was
> >> found that 99.21% of the return values of shrink_memcg_cb() in the
> >> baseline kernel were LRU_ROTATE.
> >
> > Hmm if I understand correctly, you are saying that the current
> > upstream code is actually failing to writeback when it should in the
> > previous test case with very high memory pressure, but it is with
> > batching? If that's the case, I think it's actually really good data
> > to include. However, we should make sure that's what's actually
> > happening. If the current shrinker is not keeping up and failing to
> > writeback, we should observe:
> > 1. shrink_worker() hitting MAX_RECLAIM_RETRIES continuously and bailing.
> > 2. zswap usage consistently remains at/near the limit, and not going
> > down to the acceptance threshold.
> > 3. zswap_store() failing to accept pages and the pages going directly
> > to disk, causing an LRU inversion (hotter pages on disk, colder pages
> > in zswap).
> >
> > Can you confirm that this is what's observed with the high pressure test case?
> >
>
> Apologies, my previous explanation might not have been very clear.
>
> For an entry to be written back, the shrinker must scan the *same* entry
> twice: the first scan sets referenced to false and returns ROTATE, and
> only during the second scan can it be written back.
>
> If a swap entry is zswapin'd between the first and second scan (meaning
> the entry is no longer on the zswap LRU), then this swap entry will not
> be written back by the shrinker. Therefore, the second scan must occur
> before this entry is zswapin'd for it to be possible to be written back.
> So, if the baseline scanning speed is far slower than the lifecycle
> speed of the swap entries, it results in only scanning once. In the
> baseline kernel, 99.21% of the return values of shrink_memcg_cb() are
> LRU_ROTATE, while the patched kernel's shrink_worker() scans at least 64
> * 16 entries in a single pass, resulting in only 58.7% of the return
> values of shrink_memcg_cb() being LRU_ROTATE.

Right, my question is, is the high rate of LRU_ROTATE leading to
failure to writeback in a way that causes zswap store failures (and
pages skipping zswap and going directly to swap)?

>
>               Baseline         Patched
> ---------------------------------------------------
> zswapin       929,096          281,196   <----
> zswapout      982,731        1,058,746
>
> After modifying the kernel to remove the "second chance" algorithm, the
> test data of the baseline kernel roughly conforms to our expectations.
>
> Therefore, the constructed test has a bit of a problem. The second test
> case in my previous email can ensure that the entries on the zswap LRU
> are relatively stable.
>
> It is worth noting that the capacity of the zswap pool will not remain
> constant all the time. Since stress-ng periodically writes to and reads
> from this 4G memory, accessing the pages in the zswap pool will trigger
> zswapin, causing the zswap pool size to decrease. Other pages attempting
> to zswapout into zswap via zswap_store() will fail (until the zswap pool
> size becomes 160M (accept_threshold_percent=50)), but the zswap_store()
> path will wake up shrink_worker() to try to perform scanning and
> writeback. Then stress-ng will continue to read and write memory,
> continuously triggering zswapin to further reduce the zswap pool size
> until the threshold, at which point shrink_memcg() will also stop. Then,
> new zswap entries (with referenced as true) are added to the zswap LRU
> again via zswap_store(), until the zswap pool size reaches 320MB (32 GB
> (Total memory) * 1%). This process repeats continuously during the test.
>
> Thanks,
> Hao
>

^ permalink raw reply

* Re: [PATCH v2 0/5] binfmt_misc: bpf-backed binary type handlers
From: Christian Brauner @ 2026-07-13 15:57 UTC (permalink / raw)
  To: Farid Zakaria
  Cc: Christian Brauner, Alexei Starovoitov, Daniel Borkmann,
	Martin KaFai Lau, Shuah Khan, Andrii Nakryiko, Kees Cook,
	Alexander Viro, Jan Kara, Jonathan Corbet, Jann Horn,
	John Ericson, linux-fsdevel, linux-mm, linux-kernel, bpf,
	linux-doc, linux-kselftest
In-Reply-To: <DJXJM0838IJN.3AJ9MMQ89SUUR@gmail.com>

On 2026-07-13 08:19 -0700, Farid Zakaria wrote:
> On Mon Jul 13, 2026 at 1:20 AM PDT, Christian Brauner wrote:
> >> > - The single sleepable load op is split into two ops:
> >> >
> >> >       struct binfmt_misc_ops {
> >> >       	bool (*match)(struct linux_binprm *bprm);
> >> >       	int (*load)(struct linux_binprm *bprm);
> >> >       	char name[BINFMT_MISC_OPS_NAME_MAX];
> >> >       };
> >> >
> >> >   The non-sleepable match program runs from the RCU entry lookup
> >> >   walk itself, exactly like magic and extension matching: same
> >> >   registration order, same first-match-wins semantics, and it can
> >> >   only rely on the prefetched bprm->buf. It must be free of side
> >> >   effects since the walk may be restarted.
> >> >
> >> 
> >> Is relying on brpm->buf enough?
> >> Right now that's only 256 bytes I think, which is not enough to read
> >> segments we might care about. That worked fine when it was just a magic
> >> number but the idea with the eBPF program is to make decisions based on
> >> more data.
> >> 
> >> In the selftest I provided, the `PT_INTERP` segment is already at file
> >> offset 0x318 (792). I was imaginging NixOS having to support
> >> `PT_INTERP_NIX` in order for the produced binaries to be backwards
> >> compatible with older kernels.
> >> 
> >> The other idea would be to make the `match()` broad and select
> >> everything but then nearly all ELF64 binaries would match and then pay
> >> the price to `load()` and ultimately `-ENOEXEC`. Seems like it would
> >> make multiple BPF binfmt programs less useful.
> >
> > Ok, so your idea is to have multiple bpf programs that look for
> > different interpreters. Yeah, then you have to be able to sleep because
> > you need to be able to fault. It makes the code uglier but I can see how
> > that's useful. I'll see how nice I can make that.
> >
> 
> I mean... I thought that's the intent to binfmt_misc, to have multiple
> handlers -- with the expressiveness of eBPF vs. the limited

I was thinking of having one bpf program per type (elf, python, etc) but
I can see how it's useful to have multiple elf bpf handlers...

> > Ah, fun. binfmt_misc wasn't able to express this at all. It's good to
> > close that gap. This can just be done by adding
> > bpf_binprm_set_interp_arg().
> 
> What is "cool" about this is now it's also a net-new feature for shebags
> which the "old" binfmt_misc didn't support. Anyways, I was thining ahead
> about what I would need to support $ORIGIN fully and this was
> a remaining gap. We also explored this idea in a patch pre-BPF [1] but
> now that we've settled on this solution it seems much more natural.
> 
> 
> I was recently reached out by some Bazel people who are also interested
> in this $ORIGIN support. Interestingly they let me know that

Yeah, for build systemd it's very nice ofc.

> IllumOS/Solaris had support for it as well.

The whole $ORIGIN thing comes from Illumos/Solaris afair. So no big
surprise.


^ permalink raw reply

* Re: [PATCH v6 4/7] bus: mhi: Add QDU100 Sahara variant and firmware fallback
From: Manivannan Sadhasivam @ 2026-07-13 16:19 UTC (permalink / raw)
  To: Kishore Batta
  Cc: Jonathan Corbet, Shuah Khan, Jeff Hugo, Carl Vanderlip,
	Oded Gabbay, linux-doc, linux-kernel, linux-arm-msm, dri-devel,
	mhi
In-Reply-To: <21867efc-b5a8-4ed9-92b4-059a020731a6@oss.qualcomm.com>

On Mon, Jul 13, 2026 at 07:46:02PM +0530, Kishore Batta wrote:
> 
> On 7/9/2026 11:49 AM, Manivannan Sadhasivam wrote:
> > On Wed, Jul 01, 2026 at 04:07:38PM +0530, Kishore Batta wrote:
> > > The Sahara driver currently selects a firmware image table based on the
> > > attached device, but it does not recognize QDU100 devices that expose the
> > > protocol on the SAHARA MHI channel. As a result, the host cannot associate
> > > QDU100 devices with the correct firmware namespace during image transfer.
> > > 
> > > Extend the probe time variant selection to match the SAHARA MHI channel and
> > > associate it with the QDU100 firmware folder. Add a firmware lookup
> > > fallback for cases where an image does not have an explicit entry in the
> > > device's firmware table. This allows required images to be provisioned by
> > > the platform.
> > > 
> > > This change only affects devices matched on the SAHARA MHI channel and
> > > does not change behavior for existing AIC100 and AIC200 devices.
> > > 
> > > Signed-off-by: Kishore Batta <kishore.batta@oss.qualcomm.com>
> > > ---
> > >   drivers/bus/mhi/host/clients/sahara/sahara.c | 27 +++++++++++++++--
> > >   drivers/bus/mhi/host/pci_generic.c           | 45 ++++++++++++++++++++++++++++
> > >   2 files changed, 70 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/bus/mhi/host/clients/sahara/sahara.c b/drivers/bus/mhi/host/clients/sahara/sahara.c
> > > index e339c67e236af271645ca81cc517efd9eead87e4..9adbd84859073d8024ba2a5fcfa33897439d6759 100644
> > > --- a/drivers/bus/mhi/host/clients/sahara/sahara.c
> > > +++ b/drivers/bus/mhi/host/clients/sahara/sahara.c
> > > @@ -189,6 +189,7 @@ static bool is_streaming(struct sahara_context *context)
> > >   static int sahara_find_image(struct sahara_context *context, u32 image_id)
> > >   {
> > > +	char *fw_path;
> > >   	int ret;
> > >   	if (image_id == context->active_image_id)
> > > @@ -201,8 +202,28 @@ static int sahara_find_image(struct sahara_context *context, u32 image_id)
> > >   	}
> > >   	if (image_id >= context->table_size || !context->image_table[image_id]) {
> > > -		dev_err(&context->mhi_dev->dev, "request for unknown image: %d\n", image_id);
> > > -		return -EINVAL;
> > > +		if (!context->fw_folder) {
> > > +			dev_err(&context->mhi_dev->dev,
> > > +				"Request for unknown image: %u (no fw folder)\n", image_id);
> > > +			return -EINVAL;
> > > +		}
> > > +
> > > +		fw_path = kasprintf(GFP_KERNEL, "qcom/%s/%u",
> > > +				    context->fw_folder, image_id);
> > > +		if (!fw_path)
> > > +			return -ENOMEM;
> > > +
> > > +		ret = firmware_request_nowarn(&context->firmware,
> > > +					      fw_path,
> > > +					      &context->mhi_dev->dev);
> > > +		kfree(fw_path);
> > > +		if (ret) {
> > > +			dev_err(&context->mhi_dev->dev,
> > > +				"request for unknown image: %d\n", image_id);
> > > +			return -EINVAL;
> > > +		}
> > > +		context->active_image_id = image_id;
> > > +		return 0;
> > >   	}
> > >   	/*
> > > @@ -870,8 +891,10 @@ static void sahara_mhi_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result
> > >   static const struct mhi_device_id sahara_mhi_match_table[] = {
> > >   	{ .chan = "QAIC_SAHARA", },
> > > +	{ .chan = "SAHARA"},
> > >   	{},
> > >   };
> > > +MODULE_DEVICE_TABLE(mhi, sahara_mhi_match_table);
> > This change should belong to a separate patch.
> > 
> > >   static struct mhi_driver sahara_mhi_driver = {
> > >   	.id_table = sahara_mhi_match_table,
> > > diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
> > > index 391ab146f501c6ce1c81f6138f7c491a49c2f264..82e41632afc555a53dec3d8395558ae039b33bbd 100644
> > > --- a/drivers/bus/mhi/host/pci_generic.c
> > > +++ b/drivers/bus/mhi/host/pci_generic.c
> > > @@ -300,6 +300,43 @@ static const struct mhi_pci_dev_info mhi_qcom_qdu100_info = {
> > >   	.reset_on_remove = true,
> > >   };
> > > +static const char * const qdu100_image_table[] = {
> > > +	[5] = "qcom/qdu100/uefi.elf",
> > > +	[8] = "qcom/qdu100/qdsp6sw.mbn",
> > > +	[16] = "qcom/qdu100/efs1.bin",
> > > +	[17] = "qcom/qdu100/efs2.bin",
> > > +	[20] = "qcom/qdu100/efs3.bin",
> > > +	[23] = "qcom/qdu100/aop.mbn",
> > > +	[25] = "qcom/qdu100/tz.mbn",
> > > +	[29] = "qcom/qdu100/zeros_1sector.bin",
> > > +	[33] = "qcom/qdu100/hypvm.mbn",
> > > +	[34] = "qcom/qdu100/mdmddr.mbn",
> > > +	[36] = "qcom/qdu100/multi_image_qti.mbn",
> > > +	[37] = "qcom/qdu100/multi_image.mbn",
> > > +	[38] = "qcom/qdu100/xbl_config.elf",
> > > +	[39] = "qcom/qdu100/abl_userdebug.elf",
> > > +	[40] = "qcom/qdu100/zeros_1sector.bin",
> > > +	[41] = "qcom/qdu100/devcfg.mbn",
> > > +	[42] = "qcom/qdu100/zeros_1sector.bin",
> > > +	[45] = "qcom/qdu100/tools_l.elf",
> > > +	[46] = "qcom/qdu100/Quantum.elf",
> > > +	[47] = "qcom/qdu100/quest.elf",
> > > +	[48] = "qcom/qdu100/xbl_ramdump.elf",
> > > +	[49] = "qcom/qdu100/shrm.elf",
> > > +	[50] = "qcom/qdu100/cpucp.elf",
> > > +	[51] = "qcom/qdu100/aop_devcfg.mbn",
> > > +	[52] = "qcom/qdu100/fw_csm_gsi_3.0.elf",
> > > +	[53] = "qcom/qdu100/qdsp6sw_dtbs.elf",
> > > +	[54] = "qcom/qdu100/qupv3fw.elf",
> > > +};
> > > +
> > > +static const struct mhi_sahara_fw_table qdu100_sahara_fw = {
> > > +	.image_table = qdu100_image_table,
> > > +	.table_size = ARRAY_SIZE(qdu100_image_table),
> > > +	.fw_folder = "qdu100",
> > > +	.non_streaming = false,
> > > +};
> > > +
> > >   static const struct mhi_channel_config mhi_qcom_sa8775p_channels[] = {
> > >   	MHI_CHANNEL_CONFIG_UL(46, "IP_SW0", 2048, 1),
> > >   	MHI_CHANNEL_CONFIG_DL(47, "IP_SW0", 2048, 2),
> > > @@ -1399,6 +1436,14 @@ static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> > >   	pci_set_drvdata(pdev, mhi_pdev);
> > > +	/*
> > > +	 * Provide Sahara firmware mapping. Sahara consumes it via
> > > +	 * mhi_dev->mhi_cntrl->sahara_fw at probe time.
> > > +	 */
> > > +	if (info == &mhi_qcom_qdu100_info ||
> > > +	    (info->name && !strcmp(info->name, "qcom-qdu100")))
> > > +		mhi_cntrl->sahara_fw = &qdu100_sahara_fw;
> > > +
> > Why are you adding QAIC MHI controller config in pci_generic driver? This driver
> > only handles Modem devices.
> > 
> > - Mani
> 
> 
> Hi Mani, Above one is for QDU100 device. QAIC is not added in this file.
> 

Sorry, my bad. But anyhow, you should provide this mapping table pointer via
'struct mhi_pci_dev_info'.

- Mani

-- 
மணிவண்ணன் சதாசிவம்

^ permalink raw reply

* Re: [PATCH v8 8/8] drm/gpusvm: Use hmm_range_fault_unlocked_timeout() for range faults
From: Matthew Brost @ 2026-07-13 16:30 UTC (permalink / raw)
  To: Stanislav Kinsburskii
  Cc: airlied, akhilesh, akpm, corbet, dakr, david, decui, haiyangz,
	jgg, kees, kys, leon, liam, lizhi.hou, ljs, longli, lyude,
	maarten.lankhorst, mamin506, mhocko, mripard, nouveau, ogabbay,
	oleg, rppt, shuah, simona, skhan, surenb, tzimmermann, vbabka,
	wei.liu, dri-devel, linux-mm, linux-doc, linux-hyperv,
	linux-kernel, linux-kselftest, linux-rdma
In-Reply-To: <178371883977.900500.2198446134676328631.stgit@skinsburskii>

On Fri, Jul 10, 2026 at 02:27:19PM -0700, Stanislav Kinsburskii wrote:

Please send series like this to intel-xe@lists.freedesktop.org list too
as this will trigger our CI which expercises the change paths changed in
this series.

> Several GPU SVM paths take mmap_read_lock() only to call hmm_range_fault(),
> then retry -EBUSY until HMM_RANGE_DEFAULT_TIMEOUT expires. Those paths use
> MMU interval notifiers whose mm matches the mm that was locked for the HMM
> fault.
> 
> Use hmm_range_fault_unlocked_timeout() for those faults and pass the
> remaining retry budget to HMM. The helper owns mmap_lock acquisition and
> refreshes range->notifier_seq internally for each retry, while GPU SVM
> keeps its existing driver-lock validation with mmu_interval_read_retry()
> after a successful fault.
> 
> Leave drm_gpusvm_check_pages() on hmm_range_fault() because that path is
> called with the mmap lock already held by its caller.
> 
> Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
>  drivers/gpu/drm/drm_gpusvm.c |   52 ++++++------------------------------------
>  1 file changed, 7 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
> index 958cb605aedd..6b7a6eaebcd9 100644
> --- a/drivers/gpu/drm/drm_gpusvm.c
> +++ b/drivers/gpu/drm/drm_gpusvm.c
> @@ -788,22 +788,8 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
>  	hmm_range.hmm_pfns = pfns;
>  
>  retry:
> -	hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
> -	mmap_read_lock(range->gpusvm->mm);
> -
> -	while (true) {
> -		err = hmm_range_fault(&hmm_range);
> -		if (err == -EBUSY) {
> -			if (time_after(jiffies, timeout))
> -				break;
> -
> -			hmm_range.notifier_seq =
> -				mmu_interval_read_begin(notifier);
> -			continue;
> -		}
> -		break;
> -	}
> -	mmap_read_unlock(range->gpusvm->mm);
> +	err = hmm_range_fault_unlocked_timeout(&hmm_range,
> +					       max(timeout - jiffies, 1L));
>  	if (err)
>  		goto err_free;
>  
> @@ -1439,21 +1425,8 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
>  	}
>  
>  	hmm_range.hmm_pfns = pfns;
> -	while (true) {
> -		mmap_read_lock(mm);
> -		err = hmm_range_fault(&hmm_range);
> -		mmap_read_unlock(mm);
> -
> -		if (err == -EBUSY) {
> -			if (time_after(jiffies, timeout))
> -				break;
> -
> -			hmm_range.notifier_seq =
> -				mmu_interval_read_begin(notifier);
> -			continue;
> -		}
> -		break;
> -	}
> +	err = hmm_range_fault_unlocked_timeout(&hmm_range,
> +				max_t(long, timeout - jiffies, 1));

Unaligned indentation.

So I'd write this like this to avoid weird wraps:

ctimeout = max_t(long, timeout - jiffies, 1));
err = hmm_range_fault_unlocked_timeout(&hmm_range, ctimeout);

>  	mmput(mm);
>  	if (err)
>  		goto err_free;
> @@ -1736,24 +1709,13 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
>  		return -ENOMEM;
>  
>  	hmm_range.hmm_pfns = pfns;
> -	while (!time_after(jiffies, timeout)) {
> -		hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
> -		if (time_after(jiffies, timeout)) {
> -			err = -ETIME;
> -			break;
> -		}
> -
> -		mmap_read_lock(mm);
> -		err = hmm_range_fault(&hmm_range);
> -		mmap_read_unlock(mm);
> -		if (err != -EBUSY)
> -			break;
> -	}
> +	err = hmm_range_fault_unlocked_timeout(&hmm_range,
> +				max_t(long, timeout - jiffies, 1));
>  

Same here.

Nits, aside LGTM.

Matt

>  	kvfree(pfns);
>  	mmput(mm);
>  
> -	return err;
> +	return err == -EBUSY ? -ETIME : err;
>  }
>  EXPORT_SYMBOL_GPL(drm_gpusvm_range_evict);
>  
> 
> 

^ permalink raw reply

* RE: [PATCH v3 00/11] vfio/pci: Add CXL Type-2 device passthrough support
From: Manish Honap @ 2026-07-13 16:43 UTC (permalink / raw)
  To: Dave Jiang, djbw@kernel.org, alex@shazbot.org, jgg@ziepe.ca,
	jic23@kernel.org, Ankit Agrawal, alejandro.lucero-palau@amd.com,
	alison.schofield@intel.com, dave@stgolabs.net,
	dmatlack@google.com, gourry@gourry.net, ira.weiny@intel.com
  Cc: Neo Jia, Krishnakant Jaju, Vikram Sethi, Zhi Wang,
	kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <6f8bf672-8e10-440c-a396-086f2c71b69f@intel.com>

> -----Original Message-----
> From: Dave Jiang <dave.jiang@intel.com>
> Sent: 10 July 2026 21:57
> To: Manish Honap <mhonap@nvidia.com>; djbw@kernel.org; alex@shazbot.org;
> jgg@ziepe.ca; jic23@kernel.org; Ankit Agrawal <ankita@nvidia.com>;
> alejandro.lucero-palau@amd.com; alison.schofield@intel.com;
> dave@stgolabs.net; dmatlack@google.com; gourry@gourry.net;
> ira.weiny@intel.com
> Cc: Neo Jia <cjia@nvidia.com>; Krishnakant Jaju <kjaju@nvidia.com>;
> Vikram Sethi <vsethi@nvidia.com>; Zhi Wang <zhiw@nvidia.com>;
> kvm@vger.kernel.org; linux-cxl@vger.kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; linux-
> kselftest@vger.kernel.org
> Subject: Re: [PATCH v3 00/11] vfio/pci: Add CXL Type-2 device
> passthrough support
> 
> External email: Use caution opening links or attachments
> 
> 
> On 6/25/26 9:53 AM, mhonap@nvidia.com wrote:
> > From: Manish Honap <mhonap@nvidia.com>
> >
> > CXL Type-2 accelerators (CXL.mem-capable GPUs and similar) cannot be
> > passed through to virtual machines with stock vfio-pci because the
> > driver has no concept of HDM decoder management, HDM region exposure,
> > or component register virtualization.  This series adds those three
> > pieces, sufficient for a guest to use the device's firmware-committed
> > coherent memory under UVM / ATS.
> >
> > v3 is a rewrite of the v2 framework form, responding to Dan's request
> > in the v2 review for "less emulation, narrower interfaces, and a
> > closer mapping to the spec language."
> > In this release, cxl-core exposes four EXPORT_SYMBOL_GPL helpers
> > behind an opaque handle.  vfio-pci becomes a thin transport on top of
> those.
> > Please see "Changes since v2" and "Reviewer feedback addressed" below
> > for the per-area summary.
> >
> > Motivation
> > ==========
> >
> > A CXL Type-2 device exposes its HDM-mapped device memory through HDM
> > decoders that BIOS programs and commits at boot.  To pass such a
> > device to a guest, vfio-pci has to do three things at once:
> >
> >   1. Surface the firmware-committed HDM-mapped HPA range as a guest-
> >      mmappable region.
> >
> >   2. Surface a CXL-spec-compliant view of the CXL Device DVSEC body,
> >      the HDM Decoder Capability block, and the CXL.cache/mem cap-array
> >      prefix, so the guest's CXL driver enumerates the same topology
> >      the host saw.
> >
> >   3. Keep the host's committed decoder configuration intact (the
> >      physical decoder is never reprogrammed) while letting the guest
> >      observe and manage a shadow that follows the per-field write
> >      semantics in the spec.
> >
> > The series builds on Alejandro Lucero-Palau's v28 work applied on
> > for-7.3/cxl-type2-enabling [1] (sfc is the in-tree consumer today).
> > vfio-pci becomes the second consumer.
> >
> > Architecture
> > ============
> >
> > cxl-core owns the CXL semantics.  A new file
> > drivers/cxl/core/passthrough.c (gated by hidden Kconfig
> > CXL_VFIO_PASSTHROUGH) provides four exported symbols:
> >
> >     struct cxl_passthrough *
> >     devm_cxl_passthrough_create(struct device *dev,
> >                                 struct cxl_dev_state *cxlds);
> >
> >     int cxl_passthrough_dvsec_rw(p, off, val, sz, write);
> >     int cxl_passthrough_hdm_rw  (p, off, val,      write);
> >     int cxl_passthrough_cm_rw   (p, off, val,      write);
> >
> > cxl_passthrough is an opaque handle; vfio-pci sees no cxl-internal
> > struct pointers.  The shadows are snapshotted at create time: the
> > DVSEC body from PCI config space dword by dword, the CM cap-array and
> > HDM block from the cxl-core MMIO mapping at cxlds->reg_map.base.
> > Per-field write semantics follow below:
> > CXL r4.0 8.1.3 DVSEC:
> > - LOCK is RWO,
> > - CONTROL/CONTROL2 are RWL gated on CONFIG_LOCK,
> > - STATUS/STATUS2 are RW1C,
> > - RANGE1 is HwInit, RANGE2 is RsvdZ
> > CXL r4.0 8.2.4.20 HDM:
> > - GLOBAL_CTRL RW,
> > - decoder CTRL implements COMMIT/COMMITTED,
> > - decoder BASE/SIZE RWL gated on COMMITTED or LOCK_ON_COMMIT,
> > - cap header HwInit).
> >
> > vfio-pci becomes a thin transport.  The new module
> > drivers/vfio/pci/cxl/ exposes two VFIO regions.
> >
> >   VFIO_REGION_SUBTYPE_CXL (HDM region): mmappable view of the
> >   HDM-mapped HPA. The mmap fault handler calls vmf_insert_pfn() from
> >   the physical HPA. pread/pwrite go through the memremap_wb() kva
> >   captured at bind time.
> >
> >   VFIO_REGION_SUBTYPE_CXL_COMP_REGS (component register shadow):
> >   pread/pwrite only, dword-aligned (-EINVAL on misalignment).
> >   Each dword dispatches by offset to cxl_passthrough_cm_rw() or
> >   cxl_passthrough_hdm_rw(). No shadow state on the vfio side; cxl-core
> >   enforces the spec.
> >
> > CXL DVSEC config-space accesses use a clipping shim in
> > vfio_pci_config_rw_single(). A config-space chunk that crosses the
> > DVSEC body boundary is split: header bytes go through the generic
> > perm-bits path, body bytes go through cxl_passthrough_dvsec_rw().
> > The shim replaces v2's approach of repointing ecap_perms[]
> >
> > Sparse-mmap is exposed on the component BAR so userspace can mmap the
> > non-component portions directly; only the CXL component register
> > sub-range goes through pread/pwrite emulation. The CXL sub-range is
> > also skipped from vfio_pci-core's request_selected_regions() set
> > because cxl-core's devm_cxl_probe_mem() already holds a
> > request_mem_region() on it; the asymmetric skip is matched by an
> > asymmetric release on disable().
> >
> > Scope and out-of-scope
> > ======================
> >
> > In scope (rejected at create time with -EOPNOTSUPP otherwise):
> >
> >   - Firmware-committed devices (HOST_FIRMWARE_COMMITTED set).
> >   - Single HDM decoder (hdm_count == 1).
> >   - No interleave (IW == 0).
> >
> > Out of scope, deferred for follow-on work:
> >
> >   - Multi-decoder devices and interleave.
> >   - Guest-driven (non-firmware-committed) HDM commit.
> >   - Hotplug, FLR, and sibling-function reset of CXL Type-2 devices.
> >
> > Changes since v2
> > ================
> >
> > This is a rewrite, not an incremental update.  The structure of the
> > series changed (20 patches in v2 to 11 in v3) because v3 collapses
> > v2 patches 9-15 (detection, HDM emulation, media readiness, region
> > management, HDM region, DVSEC emulation) into one cxl-core helper file
> > and one vfio-pci consumer.
> >
> > Framework replaced by narrow opaque-handle helpers (patches 6, 8)
> >
> >   v2 carried a generic register-emulation framework split across four
> >   state-machine files in cxl-core.
> >   v3 collapses it into one file: drivers/cxl/core/passthrough.c
> >   exposing the four EXPORT_SYMBOL_GPL helpers above behind a struct
> >   cxl_passthrough opaque handle.
> >
> > Shadow ownership moved into cxl-core (patches 6, 8)
> >
> >   vfio-pci no longer keeps any per-field state. It forwards
> >   (offset, value) into cxl-core, and cxl-core enforces the spec
> >   (RWO, RWL, RW1C, HwInit, RsvdZ) with explicit CXL r4.0 section
> >   references in the switch arms.
> >
> > DVSEC config-space clipping shim (patch 8)
> >
> >   v2 repointed ecap_perms[] to redirect CXL DVSEC reads and writes.
> >   v3 keeps ecap_perms[] untouched and clips per-config-access chunks
> >   at the DVSEC body boundary in vfio_pci_config_rw_single(); header
> bytes
> >   go through the generic perm-bits path, body bytes go through
> >   cxl_passthrough_dvsec_rw(). The shim is local to the per-device
> >   path.
> >
> > CONFIG_VFIO_PCI_CXL gates the new module (patch 7)
> >
> >   v2 had a CONFIG_VFIO_CXL_CORE Kconfig stub; v3 renames it to
> >   CONFIG_VFIO_PCI_CXL to match the vfio-pci naming convention.
> >   The hidden CXL_VFIO_PASSTHROUGH selects the cxl-core helper file
> >   on demand. With both disabled, the cxl-core size is unchanged.
> >
> > UAPI rewritten with named fields (patch 5)
> >
> >   vfio_device_info_cap_cxl in v3 carries:
> >     flags + HOST_FIRMWARE_COMMITTED bit
> >     hdm_region_idx
> >     comp_reg_region_idx
> >     comp_reg_bar
> >     comp_reg_offset
> >     comp_reg_size
> >   The DPA terminology is renamed to HDM region throughout.
> >   CACHE_CAPABLE (HDM-DB indicator) is dropped;
> >   it was informational only in v2 with no caller, and re-adding it
> >   for an active CXL.cache plumbing series later.
> >
> > Selftests trimmed (patch 9)
> >
> >   v2 carried selftests for device detection, capability parsing,
> >   region enumeration, HDM register emulation, HDM mmap with
> >   page-fault insertion, FLR invalidation, and DVSEC register
> >   emulation. v3 keeps a smoke-test set of six focused tests:
> >
> >     device_is_cxl                  GET_INFO advertises FLAGS_CXL
> >                                    and a populated CAP_CXL.
> >     hdm_region_mmap_rw             mmap one page, write+read back.
> >     component_bar_sparse_mmap      SPARSE_MMAP cap excludes the
> >                                    CXL component register sub-range.
> >     comp_regs_cm_cap_array_read    pread of the CM cap-array
> >                                    header at CXL_CM_OFFSET succeeds
> >                                    (CAP_ID == 1).
> >     dvsec_lock_byte_read           pread of the DVSEC CONFIG_LOCK
> >                                    byte through the clipping shim
> >                                    succeeds.
> >     hdm_decoder_commit_fsm         COMMIT / COMMITTED state machine
> >                                    and LOCK_ON_COMMIT behaviour.
> >
> >   FLR invalidation, page-fault insertion under load, and full
> >   DVSEC field-by-field write coverage are deferred to a follow-on
> >   selftest series. The current six are the minimal set that
> >   exercises the kernel-side contract end-to-end.
> >
> > cxl-core prep patches split (patches 1-4)
> >
> >   v3 keeps the cxl-side enablers from v2 patches 1-4 but each as
> >   a standalone change so the cxl maintainer can review the helper
> >   API independently of the vfio consumer:
> >
> >     [1/11] cxl_get_hdm_info()
> >     [2/11] cxl_await_range_active() split from media-ready wait
> >     [3/11] cxl_register_map records BIR + BAR offset
> >     [4/11] component/HDM register defines moved to uapi/cxl/cxl_regs.h
> >
> > Reviewer feedback addressed
> > ===========================
> >
> > Dan
> > ---
> >
> > - VFIO exposes HDM/host-visible region, not raw DPA; docs/UAPI say HDM
> >   region, DPA only inside cxl-core where appropriate.
> > - One vfio-pci device = one HDM region / one decoder, no interleave;
> >   hdm_count != 1 → -EOPNOTSUPP.
> > - Global HDM on DVSEC Range Base treated as legacy; RANGE1/RANGE2
> >   read-only snapshot, guest writes dropped.
> > - No guest/kernel lock games; DVSEC LOCK and HDM LOCK_ON_COMMIT RWO,
> >   fixed at create from firmware snapshot.
> > - Opaque cxl_passthrough handle only; vfio gets HPA via memdev probe +
> >   layout via cxl_get_hdm_info(), rw via helpers.
> > - No multi-region accelerator case in v3; single region enforced,
> >   multi-region deferred.
> > - cxl_await_range_active stays in cxl-core probe; not exported, vfio
> does
> >   not call it.
> > - No guest LOCK→0 reprogram; guest cannot clear LOCK to remap host
> HPA;
> >   kernel uncommit tied to COMMIT, not LOCK alone.
> >
> > Jason / Gregory / Dan
> > ---------------------
> >
> > - memremap(WB) + request_mem_region on HPA; conflicting direct-map/EFI
> use
> >   fails probe with -EBUSY.
> >
> > Jonathan
> > --------
> >
> > - uapi/cxl/cxl_regs.h for register defines so VMMs need no private
> >   kernel headers.
> > - __free() locals on cxl-core/passthrough error paths instead of
> >   struct-owned temporaries.
> > - No "precommitted at probe" assumption; acquire checks COMMITTED in
> >   HDM shadow and refuses if missing.
> >
> > Dave
> > ----
> >
> > - memremap(MEMREMAP_WB) for HDM host mapping (not ioremap_cache).
> > - Renamed cap flag to VFIO_CXL_CAP_HOST_FIRMWARE_COMMITTED for
> clarity.
> > - __free() / DEFINE_FREE() cleanup in new passthrough.c create path.
> >
> > Patch series
> > ============
> >
> >  [1/11] cxl: Add cxl_get_hdm_info() helper for HDM decoder metadata
> > [2/11] cxl: Split cxl_await_range_active() from media-ready wait
> > [3/11] cxl: Record BIR and BAR offset in cxl_register_map  [4/11] cxl:
> > Move component/HDM register defines to
> >         uapi/cxl/cxl_regs.h
> >  [5/11] vfio: UAPI for CXL Type-2 device passthrough  [6/11] cxl: Add
> > register-virtualization helpers for vfio Type-2
> >         passthrough
> >  [7/11] vfio/pci: Add CONFIG_VFIO_PCI_CXL with bind-time CXL Type-2
> >         acquisition
> >  [8/11] vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping
> >         shim
> >  [9/11] selftests/vfio: Add CXL Type-2 device passthrough smoke test
> > [10/11] docs: vfio-pci: Document CXL Type-2 device passthrough [11/11]
> > vfio/pci: Provide opt-out for CXL Type-2 extensions
> >
> > Dependencies
> > ============
> >
> > [1] [PATCH v28 0/5] Type2 device basic support
> > https://lore.kernel.org/linux-cxl/20260618181806.118745-1-alejandro.lu
> > cero-palau@amd.com/
> >
> > [2] Previous version of this patch series [PATCH v2 00/20] vfio/pci:
> > Add CXL Type-2 device passthrough support
> > https://lore.kernel.org/linux-cxl/20260401143917.108413-1-mhonap@nvidi
> > a.com/
> >
> > [3] Companion QEMU series
> > [RFC 0/9] QEMU: CXL Type-2 device passthrough via vfio-pci
> > https://lore.kernel.org/linux-cxl/20260427181235.3003865-1-mhonap@nvid
> > ia.com/
> >
> > Manish Honap (11):
> >   cxl: Add cxl_get_hdm_info() helper for HDM decoder metadata
> >   cxl: Split cxl_await_range_active() from media-ready wait
> >   cxl: Record BIR and BAR offset in cxl_register_map
> >   cxl: Move component/HDM register defines to uapi/cxl/cxl_regs.h
> >   vfio: UAPI for CXL Type-2 device passthrough
> >   cxl: Add register-virtualization helpers for vfio Type-2 passthrough
> >   vfio/pci: Add CONFIG_VFIO_PCI_CXL with bind-time CXL Type-2
> >     acquisition
> >   vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping shim
> >   selftests/vfio: Add CXL Type-2 device passthrough smoke test
> >   docs: vfio-pci: Document CXL Type-2 device passthrough
> >   vfio/pci: Provide opt-out for CXL Type-2 extensions
> >
> >  Documentation/driver-api/index.rst            |   1 +
> >  Documentation/driver-api/vfio-pci-cxl.rst     | 282 ++++++
> >  drivers/cxl/Kconfig                           |   7 +
> >  drivers/cxl/core/Makefile                     |   1 +
> >  drivers/cxl/core/passthrough.c                | 590 ++++++++++++
> >  drivers/cxl/core/pci.c                        |  70 +-
> >  drivers/cxl/core/regs.c                       |  35 +
> >  drivers/cxl/cxl.h                             |  52 +-
> >  drivers/vfio/pci/Kconfig                      |   2 +
> >  drivers/vfio/pci/Makefile                     |   1 +
> >  drivers/vfio/pci/cxl/Kconfig                  |  34 +
> >  drivers/vfio/pci/cxl/Makefile                 |   2 +
> >  drivers/vfio/pci/cxl/vfio_cxl_core.c          | 889
> ++++++++++++++++++
> >  drivers/vfio/pci/cxl/vfio_cxl_priv.h          |  71 ++
> >  drivers/vfio/pci/vfio_pci.c                   |   9 +
> >  drivers/vfio/pci/vfio_pci_config.c            |  31 +
> >  drivers/vfio/pci/vfio_pci_core.c              |  68 +-
> >  drivers/vfio/pci/vfio_pci_priv.h              |  93 ++
> >  drivers/vfio/pci/vfio_pci_rdwr.c              |  17 +
> >  include/cxl/cxl.h                             |  18 +
> >  include/cxl/passthrough.h                     | 121 +++
> >  include/linux/vfio_pci_core.h                 |   8 +
> >  include/uapi/cxl/cxl_regs.h                   |  63 ++
> >  include/uapi/linux/vfio.h                     |  46 +
> >  tools/testing/selftests/vfio/Makefile         |   1 +
> >  .../selftests/vfio/lib/vfio_pci_device.c      |  11 +-
> >  .../selftests/vfio/vfio_cxl_type2_test.c      | 350 +++++++
> >  27 files changed, 2821 insertions(+), 52 deletions(-)  create mode
> > 100644 Documentation/driver-api/vfio-pci-cxl.rst
> >  create mode 100644 drivers/cxl/core/passthrough.c  create mode 100644
> > drivers/vfio/pci/cxl/Kconfig  create mode 100644
> > drivers/vfio/pci/cxl/Makefile  create mode 100644
> > drivers/vfio/pci/cxl/vfio_cxl_core.c
> >  create mode 100644 drivers/vfio/pci/cxl/vfio_cxl_priv.h
> >  create mode 100644 include/cxl/passthrough.h  create mode 100644
> > include/uapi/cxl/cxl_regs.h  create mode 100644
> > tools/testing/selftests/vfio/vfio_cxl_type2_test.c
> >
> > base-commit: 90cf2e0d702c8a132ccbe72e7687f33c04c14658
> 
> Hi Manish,
> b4 seems to be failing with applying on top of this base-commit.
> 

Sorry about this; The series does not apply against a plain mainline
tree because it depends on Alejandro's v28 "Type2 device basic support"

I created this patchseries on `origin/for-7.3/cxl-type2-enabling' with
base commit as 90cf2e0d702c and applied Alejandro's patch-v28. on this
tree, I see the patches can be applied correctly.

I see Srirangan has based his reset series on Linus's tree. I will follow
similar guidelines for v4.



^ permalink raw reply

* RE: [PATCH v3 00/11] vfio/pci: Add CXL Type-2 device passthrough support
From: Manish Honap @ 2026-07-13 16:44 UTC (permalink / raw)
  To: Richard Cheng
  Cc: djbw@kernel.org, alex@shazbot.org, jgg@ziepe.ca, jic23@kernel.org,
	dave.jiang@intel.com, Ankit Agrawal,
	alejandro.lucero-palau@amd.com, alison.schofield@intel.com,
	dave@stgolabs.net, dmatlack@google.com, gourry@gourry.net,
	ira.weiny@intel.com, Neo Jia, Krishnakant Jaju, Vikram Sethi,
	Zhi Wang, kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <aj5Brc9beJhsDdJr@MWDK4CY14F>



> -----Original Message-----
> From: Richard Cheng <icheng@nvidia.com>
> Sent: 26 June 2026 14:47
> To: Manish Honap <mhonap@nvidia.com>
> Cc: djbw@kernel.org; alex@shazbot.org; jgg@ziepe.ca; jic23@kernel.org;
> dave.jiang@intel.com; Ankit Agrawal <ankita@nvidia.com>;
> alejandro.lucero-palau@amd.com; alison.schofield@intel.com;
> dave@stgolabs.net; dmatlack@google.com; gourry@gourry.net;
> ira.weiny@intel.com; Neo Jia <cjia@nvidia.com>; Krishnakant Jaju
> <kjaju@nvidia.com>; Vikram Sethi <vsethi@nvidia.com>; Zhi Wang
> <zhiw@nvidia.com>; kvm@vger.kernel.org; linux-cxl@vger.kernel.org;
> linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org; linux-
> kselftest@vger.kernel.org
> Subject: Re: [PATCH v3 00/11] vfio/pci: Add CXL Type-2 device
> passthrough support
> 
> On Thu, Jun 25, 2026 at 10:23:56PM +0800, mhonap@nvidia.com wrote:
> > From: Manish Honap <mhonap@nvidia.com>
> >
> > CXL Type-2 accelerators (CXL.mem-capable GPUs and similar) cannot be
> > passed through to virtual machines with stock vfio-pci because the
> > driver has no concept of HDM decoder management, HDM region exposure,
> > or component register virtualization.  This series adds those three
> > pieces, sufficient for a guest to use the device's firmware-committed
> > coherent memory under UVM / ATS.
> >
> > v3 is a rewrite of the v2 framework form, responding to Dan's request
> > in the v2 review for "less emulation, narrower interfaces, and a
> > closer mapping to the spec language."
> > In this release, cxl-core exposes four EXPORT_SYMBOL_GPL helpers
> > behind an opaque handle.  vfio-pci becomes a thin transport on top of
> those.
> > Please see "Changes since v2" and "Reviewer feedback addressed" below
> > for the per-area summary.
> >
> 
> Hi Manish,
> 
> Thanks for the work, I ran some test with your patches applied on a real
> CXL type-2 device, it's a GPU with a FW-committed HDM decoder. I want to
> report the result early, the acquire path works, but the first CPU
> access to the mapped HDM region crash the host.
> 
> So device BDF is 0002:81:00.0 , with CXLCtl: Cache+ IO+ Mem+, HDM
> decoder firmware-committed.
> 
> Binding the device to vfio-pci brought the CXL Type-2 path up cleanly
> """
> # modprobe vfio-pci
> # echo vfio-pci > /sys/bus/pci/devices/0002:81:00.0/driver_override
> # echo 0002:81:00.0 > /sys/bus/pci/drivers_probe """
> 
> A meme0/endpoint19/region1 appeared, and selftest device_is_cxl()
> passed.
> 
> When running the 9th patch's selftest
> """
> # sudo ./vfio_cxl_type2_test 0002:81:00.0 ok 1 cxl_type2.device_is_cxl #
> RUN  cxl_type2.hdm_region_mmap_rw """
> At this point, the machine hung and crash.
> 
> hdm_region_mmap_rw mmaps the HDM region and does a CPU read/write to it.
> That = access never returned. I couldn't capture dmesg or trace before
> it crashed.
> 
> I'm not sure if this is a platform/FW issue or something in how the
> region is mapped.
> Have you exercised hdm_region_mmap_rw() against your machine? or only
> cxl_test mock?
> 
> If a guest can hang the host just by touching its mapped memory, it
> needs to be fixed.
> 

Hello Richard, thank you for your suggestion.

I missed to update some details in the cover letter. Since
vfio-cxl-reset support patches are not included in this patch, I performed
testing of these patches on my system with reset disabled in
vfio_pci_core_{enable,disable} and vfio_pci_ioctl_reset. So, I had not seen
the host crash error Richard observed. I saw all the selftests complete
without any host side issue. I will make sure to include vfio-cxl-reset
support based on Srirangan's patch v09 when posting the kernel patch v4.

Regardless of the root cause, I agree that userspace must not be able to hang
the host by touching its own mapping. Marking this must-fix for v4.

In v4 cover letter, I will provide details of all the patches used while
testing the patch series.

> Best regards,
> Richard Cheng.
> 
> 
> 
> > Motivation
> > ==========
> >
> > A CXL Type-2 device exposes its HDM-mapped device memory through HDM
> > decoders that BIOS programs and commits at boot.  To pass such a
> > device to a guest, vfio-pci has to do three things at once:
> >
> >   1. Surface the firmware-committed HDM-mapped HPA range as a guest-
> >      mmappable region.
> >
> >   2. Surface a CXL-spec-compliant view of the CXL Device DVSEC body,
> >      the HDM Decoder Capability block, and the CXL.cache/mem cap-array
> >      prefix, so the guest's CXL driver enumerates the same topology
> >      the host saw.
> >
> >   3. Keep the host's committed decoder configuration intact (the
> >      physical decoder is never reprogrammed) while letting the guest
> >      observe and manage a shadow that follows the per-field write
> >      semantics in the spec.
> >
> > The series builds on Alejandro Lucero-Palau's v28 work applied on
> > for-7.3/cxl-type2-enabling [1] (sfc is the in-tree consumer today).
> > vfio-pci becomes the second consumer.
> >
> > Architecture
> > ============
> >
> > cxl-core owns the CXL semantics.  A new file
> > drivers/cxl/core/passthrough.c (gated by hidden Kconfig
> > CXL_VFIO_PASSTHROUGH) provides four exported symbols:
> >
> >     struct cxl_passthrough *
> >     devm_cxl_passthrough_create(struct device *dev,
> >                                 struct cxl_dev_state *cxlds);
> >
> >     int cxl_passthrough_dvsec_rw(p, off, val, sz, write);
> >     int cxl_passthrough_hdm_rw  (p, off, val,      write);
> >     int cxl_passthrough_cm_rw   (p, off, val,      write);
> >
> > cxl_passthrough is an opaque handle; vfio-pci sees no cxl-internal
> > struct pointers.  The shadows are snapshotted at create time: the
> > DVSEC body from PCI config space dword by dword, the CM cap-array and
> > HDM block from the cxl-core MMIO mapping at cxlds->reg_map.base.
> > Per-field write semantics follow below:
> > CXL r4.0 8.1.3 DVSEC:
> > - LOCK is RWO,
> > - CONTROL/CONTROL2 are RWL gated on CONFIG_LOCK,
> > - STATUS/STATUS2 are RW1C,
> > - RANGE1 is HwInit, RANGE2 is RsvdZ
> > CXL r4.0 8.2.4.20 HDM:
> > - GLOBAL_CTRL RW,
> > - decoder CTRL implements COMMIT/COMMITTED,
> > - decoder BASE/SIZE RWL gated on COMMITTED or LOCK_ON_COMMIT,
> > - cap header HwInit).
> >
> > vfio-pci becomes a thin transport.  The new module
> > drivers/vfio/pci/cxl/ exposes two VFIO regions.
> >
> >   VFIO_REGION_SUBTYPE_CXL (HDM region): mmappable view of the
> >   HDM-mapped HPA. The mmap fault handler calls vmf_insert_pfn() from
> >   the physical HPA. pread/pwrite go through the memremap_wb() kva
> >   captured at bind time.
> >
> >   VFIO_REGION_SUBTYPE_CXL_COMP_REGS (component register shadow):
> >   pread/pwrite only, dword-aligned (-EINVAL on misalignment).
> >   Each dword dispatches by offset to cxl_passthrough_cm_rw() or
> >   cxl_passthrough_hdm_rw(). No shadow state on the vfio side; cxl-core
> >   enforces the spec.
> >
> > CXL DVSEC config-space accesses use a clipping shim in
> > vfio_pci_config_rw_single(). A config-space chunk that crosses the
> > DVSEC body boundary is split: header bytes go through the generic
> > perm-bits path, body bytes go through cxl_passthrough_dvsec_rw().
> > The shim replaces v2's approach of repointing ecap_perms[]
> >
> > Sparse-mmap is exposed on the component BAR so userspace can mmap the
> > non-component portions directly; only the CXL component register
> > sub-range goes through pread/pwrite emulation. The CXL sub-range is
> > also skipped from vfio_pci-core's request_selected_regions() set
> > because cxl-core's devm_cxl_probe_mem() already holds a
> > request_mem_region() on it; the asymmetric skip is matched by an
> > asymmetric release on disable().
> >
> > Scope and out-of-scope
> > ======================
> >
> > In scope (rejected at create time with -EOPNOTSUPP otherwise):
> >
> >   - Firmware-committed devices (HOST_FIRMWARE_COMMITTED set).
> >   - Single HDM decoder (hdm_count == 1).
> >   - No interleave (IW == 0).
> >
> > Out of scope, deferred for follow-on work:
> >
> >   - Multi-decoder devices and interleave.
> >   - Guest-driven (non-firmware-committed) HDM commit.
> >   - Hotplug, FLR, and sibling-function reset of CXL Type-2 devices.
> >
> > Changes since v2
> > ================
> >
> > This is a rewrite, not an incremental update.  The structure of the
> > series changed (20 patches in v2 to 11 in v3) because v3 collapses
> > v2 patches 9-15 (detection, HDM emulation, media readiness, region
> > management, HDM region, DVSEC emulation) into one cxl-core helper file
> > and one vfio-pci consumer.
> >
> > Framework replaced by narrow opaque-handle helpers (patches 6, 8)
> >
> >   v2 carried a generic register-emulation framework split across four
> >   state-machine files in cxl-core.
> >   v3 collapses it into one file: drivers/cxl/core/passthrough.c
> >   exposing the four EXPORT_SYMBOL_GPL helpers above behind a struct
> >   cxl_passthrough opaque handle.
> >
> > Shadow ownership moved into cxl-core (patches 6, 8)
> >
> >   vfio-pci no longer keeps any per-field state. It forwards
> >   (offset, value) into cxl-core, and cxl-core enforces the spec
> >   (RWO, RWL, RW1C, HwInit, RsvdZ) with explicit CXL r4.0 section
> >   references in the switch arms.
> >
> > DVSEC config-space clipping shim (patch 8)
> >
> >   v2 repointed ecap_perms[] to redirect CXL DVSEC reads and writes.
> >   v3 keeps ecap_perms[] untouched and clips per-config-access chunks
> >   at the DVSEC body boundary in vfio_pci_config_rw_single(); header
> bytes
> >   go through the generic perm-bits path, body bytes go through
> >   cxl_passthrough_dvsec_rw(). The shim is local to the per-device
> >   path.
> >
> > CONFIG_VFIO_PCI_CXL gates the new module (patch 7)
> >
> >   v2 had a CONFIG_VFIO_CXL_CORE Kconfig stub; v3 renames it to
> >   CONFIG_VFIO_PCI_CXL to match the vfio-pci naming convention.
> >   The hidden CXL_VFIO_PASSTHROUGH selects the cxl-core helper file
> >   on demand. With both disabled, the cxl-core size is unchanged.
> >
> > UAPI rewritten with named fields (patch 5)
> >
> >   vfio_device_info_cap_cxl in v3 carries:
> >     flags + HOST_FIRMWARE_COMMITTED bit
> >     hdm_region_idx
> >     comp_reg_region_idx
> >     comp_reg_bar
> >     comp_reg_offset
> >     comp_reg_size
> >   The DPA terminology is renamed to HDM region throughout.
> >   CACHE_CAPABLE (HDM-DB indicator) is dropped;
> >   it was informational only in v2 with no caller, and re-adding it
> >   for an active CXL.cache plumbing series later.
> >
> > Selftests trimmed (patch 9)
> >
> >   v2 carried selftests for device detection, capability parsing,
> >   region enumeration, HDM register emulation, HDM mmap with
> >   page-fault insertion, FLR invalidation, and DVSEC register
> >   emulation. v3 keeps a smoke-test set of six focused tests:
> >
> >     device_is_cxl                  GET_INFO advertises FLAGS_CXL
> >                                    and a populated CAP_CXL.
> >     hdm_region_mmap_rw             mmap one page, write+read back.
> >     component_bar_sparse_mmap      SPARSE_MMAP cap excludes the
> >                                    CXL component register sub-range.
> >     comp_regs_cm_cap_array_read    pread of the CM cap-array
> >                                    header at CXL_CM_OFFSET succeeds
> >                                    (CAP_ID == 1).
> >     dvsec_lock_byte_read           pread of the DVSEC CONFIG_LOCK
> >                                    byte through the clipping shim
> >                                    succeeds.
> >     hdm_decoder_commit_fsm         COMMIT / COMMITTED state machine
> >                                    and LOCK_ON_COMMIT behaviour.
> >
> >   FLR invalidation, page-fault insertion under load, and full
> >   DVSEC field-by-field write coverage are deferred to a follow-on
> >   selftest series. The current six are the minimal set that
> >   exercises the kernel-side contract end-to-end.
> >
> > cxl-core prep patches split (patches 1-4)
> >
> >   v3 keeps the cxl-side enablers from v2 patches 1-4 but each as
> >   a standalone change so the cxl maintainer can review the helper
> >   API independently of the vfio consumer:
> >
> >     [1/11] cxl_get_hdm_info()
> >     [2/11] cxl_await_range_active() split from media-ready wait
> >     [3/11] cxl_register_map records BIR + BAR offset
> >     [4/11] component/HDM register defines moved to uapi/cxl/cxl_regs.h
> >
> > Reviewer feedback addressed
> > ===========================
> >
> > Dan
> > ---
> >
> > - VFIO exposes HDM/host-visible region, not raw DPA; docs/UAPI say HDM
> >   region, DPA only inside cxl-core where appropriate.
> > - One vfio-pci device = one HDM region / one decoder, no interleave;
> >   hdm_count != 1 → -EOPNOTSUPP.
> > - Global HDM on DVSEC Range Base treated as legacy; RANGE1/RANGE2
> >   read-only snapshot, guest writes dropped.
> > - No guest/kernel lock games; DVSEC LOCK and HDM LOCK_ON_COMMIT RWO,
> >   fixed at create from firmware snapshot.
> > - Opaque cxl_passthrough handle only; vfio gets HPA via memdev probe +
> >   layout via cxl_get_hdm_info(), rw via helpers.
> > - No multi-region accelerator case in v3; single region enforced,
> >   multi-region deferred.
> > - cxl_await_range_active stays in cxl-core probe; not exported, vfio
> does
> >   not call it.
> > - No guest LOCK→0 reprogram; guest cannot clear LOCK to remap host
> HPA;
> >   kernel uncommit tied to COMMIT, not LOCK alone.
> >
> > Jason / Gregory / Dan
> > ---------------------
> >
> > - memremap(WB) + request_mem_region on HPA; conflicting direct-map/EFI
> use
> >   fails probe with -EBUSY.
> >
> > Jonathan
> > --------
> >
> > - uapi/cxl/cxl_regs.h for register defines so VMMs need no private
> >   kernel headers.
> > - __free() locals on cxl-core/passthrough error paths instead of
> >   struct-owned temporaries.
> > - No "precommitted at probe" assumption; acquire checks COMMITTED in
> >   HDM shadow and refuses if missing.
> >
> > Dave
> > ----
> >
> > - memremap(MEMREMAP_WB) for HDM host mapping (not ioremap_cache).
> > - Renamed cap flag to VFIO_CXL_CAP_HOST_FIRMWARE_COMMITTED for
> clarity.
> > - __free() / DEFINE_FREE() cleanup in new passthrough.c create path.
> >
> > Patch series
> > ============
> >
> >  [1/11] cxl: Add cxl_get_hdm_info() helper for HDM decoder metadata
> > [2/11] cxl: Split cxl_await_range_active() from media-ready wait
> > [3/11] cxl: Record BIR and BAR offset in cxl_register_map  [4/11] cxl:
> > Move component/HDM register defines to
> >         uapi/cxl/cxl_regs.h
> >  [5/11] vfio: UAPI for CXL Type-2 device passthrough  [6/11] cxl: Add
> > register-virtualization helpers for vfio Type-2
> >         passthrough
> >  [7/11] vfio/pci: Add CONFIG_VFIO_PCI_CXL with bind-time CXL Type-2
> >         acquisition
> >  [8/11] vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping
> >         shim
> >  [9/11] selftests/vfio: Add CXL Type-2 device passthrough smoke test
> > [10/11] docs: vfio-pci: Document CXL Type-2 device passthrough [11/11]
> > vfio/pci: Provide opt-out for CXL Type-2 extensions
> >
> > Dependencies
> > ============
> >
> > [1] [PATCH v28 0/5] Type2 device basic support
> > https://lore.kernel.org/linux-cxl/20260618181806.118745-1-alejandro.lu
> > cero-palau@amd.com/
> >
> > [2] Previous version of this patch series [PATCH v2 00/20] vfio/pci:
> > Add CXL Type-2 device passthrough support
> > https://lore.kernel.org/linux-cxl/20260401143917.108413-1-mhonap@nvidi
> > a.com/
> >
> > [3] Companion QEMU series
> > [RFC 0/9] QEMU: CXL Type-2 device passthrough via vfio-pci
> > https://lore.kernel.org/linux-cxl/20260427181235.3003865-1-mhonap@nvid
> > ia.com/
> >
> > Manish Honap (11):
> >   cxl: Add cxl_get_hdm_info() helper for HDM decoder metadata
> >   cxl: Split cxl_await_range_active() from media-ready wait
> >   cxl: Record BIR and BAR offset in cxl_register_map
> >   cxl: Move component/HDM register defines to uapi/cxl/cxl_regs.h
> >   vfio: UAPI for CXL Type-2 device passthrough
> >   cxl: Add register-virtualization helpers for vfio Type-2 passthrough
> >   vfio/pci: Add CONFIG_VFIO_PCI_CXL with bind-time CXL Type-2
> >     acquisition
> >   vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping shim
> >   selftests/vfio: Add CXL Type-2 device passthrough smoke test
> >   docs: vfio-pci: Document CXL Type-2 device passthrough
> >   vfio/pci: Provide opt-out for CXL Type-2 extensions
> >
> >  Documentation/driver-api/index.rst            |   1 +
> >  Documentation/driver-api/vfio-pci-cxl.rst     | 282 ++++++
> >  drivers/cxl/Kconfig                           |   7 +
> >  drivers/cxl/core/Makefile                     |   1 +
> >  drivers/cxl/core/passthrough.c                | 590 ++++++++++++
> >  drivers/cxl/core/pci.c                        |  70 +-
> >  drivers/cxl/core/regs.c                       |  35 +
> >  drivers/cxl/cxl.h                             |  52 +-
> >  drivers/vfio/pci/Kconfig                      |   2 +
> >  drivers/vfio/pci/Makefile                     |   1 +
> >  drivers/vfio/pci/cxl/Kconfig                  |  34 +
> >  drivers/vfio/pci/cxl/Makefile                 |   2 +
> >  drivers/vfio/pci/cxl/vfio_cxl_core.c          | 889
> ++++++++++++++++++
> >  drivers/vfio/pci/cxl/vfio_cxl_priv.h          |  71 ++
> >  drivers/vfio/pci/vfio_pci.c                   |   9 +
> >  drivers/vfio/pci/vfio_pci_config.c            |  31 +
> >  drivers/vfio/pci/vfio_pci_core.c              |  68 +-
> >  drivers/vfio/pci/vfio_pci_priv.h              |  93 ++
> >  drivers/vfio/pci/vfio_pci_rdwr.c              |  17 +
> >  include/cxl/cxl.h                             |  18 +
> >  include/cxl/passthrough.h                     | 121 +++
> >  include/linux/vfio_pci_core.h                 |   8 +
> >  include/uapi/cxl/cxl_regs.h                   |  63 ++
> >  include/uapi/linux/vfio.h                     |  46 +
> >  tools/testing/selftests/vfio/Makefile         |   1 +
> >  .../selftests/vfio/lib/vfio_pci_device.c      |  11 +-
> >  .../selftests/vfio/vfio_cxl_type2_test.c      | 350 +++++++
> >  27 files changed, 2821 insertions(+), 52 deletions(-)  create mode
> > 100644 Documentation/driver-api/vfio-pci-cxl.rst
> >  create mode 100644 drivers/cxl/core/passthrough.c  create mode 100644
> > drivers/vfio/pci/cxl/Kconfig  create mode 100644
> > drivers/vfio/pci/cxl/Makefile  create mode 100644
> > drivers/vfio/pci/cxl/vfio_cxl_core.c
> >  create mode 100644 drivers/vfio/pci/cxl/vfio_cxl_priv.h
> >  create mode 100644 include/cxl/passthrough.h  create mode 100644
> > include/uapi/cxl/cxl_regs.h  create mode 100644
> > tools/testing/selftests/vfio/vfio_cxl_type2_test.c
> >
> > base-commit: 90cf2e0d702c8a132ccbe72e7687f33c04c14658
> > --
> > 2.25.1
> >
> >

^ permalink raw reply

* RE: [PATCH v3 01/11] cxl: Add cxl_get_hdm_info() helper for HDM decoder metadata
From: Manish Honap @ 2026-07-13 16:44 UTC (permalink / raw)
  To: Dan Williams (nvidia), alex@shazbot.org, jgg@ziepe.ca,
	jic23@kernel.org, dave.jiang@intel.com, Ankit Agrawal,
	alejandro.lucero-palau@amd.com, alison.schofield@intel.com,
	dave@stgolabs.net, dmatlack@google.com, gourry@gourry.net,
	ira.weiny@intel.com
  Cc: Neo Jia, Krishnakant Jaju, Vikram Sethi, Zhi Wang,
	kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <6a50444528cae_3c589810050@djbw-dev.notmuch>



> -----Original Message-----
> From: Dan Williams (nvidia) <djbw@kernel.org>
> Sent: 10 July 2026 06:31
> To: Manish Honap <mhonap@nvidia.com>; djbw@kernel.org; alex@shazbot.org;
> jgg@ziepe.ca; jic23@kernel.org; dave.jiang@intel.com; Ankit Agrawal
> <ankita@nvidia.com>; alejandro.lucero-palau@amd.com;
> alison.schofield@intel.com; dave@stgolabs.net; dmatlack@google.com;
> gourry@gourry.net; ira.weiny@intel.com
> Cc: Neo Jia <cjia@nvidia.com>; Krishnakant Jaju <kjaju@nvidia.com>;
> Vikram Sethi <vsethi@nvidia.com>; Zhi Wang <zhiw@nvidia.com>; Manish
> Honap <mhonap@nvidia.com>; kvm@vger.kernel.org; linux-
> cxl@vger.kernel.org; linux-doc@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-kselftest@vger.kernel.org
> Subject: Re: [PATCH v3 01/11] cxl: Add cxl_get_hdm_info() helper for HDM
> decoder metadata
> 
> External email: Use caution opening links or attachments
> 
> 
> mhonap@ wrote:
> > From: Manish Honap <mhonap@nvidia.com>
> >
> > cxl_probe_component_regs() finds the HDM decoder block during device
> > probe and caches its location, but does not record the decoder count
> > and does not expose the result outside drivers/cxl/.
> >
> > In-kernel cxl drivers (Type-2 accelerator drivers, vfio-cxl) need the
> > decoder count and the byte offset and size of the HDM block without
> > re-running the probe sequence.
> >
> > Record decoder_cnt in rmap->count when parsing the HDM capability in
> > cxl_probe_component_regs(), extend struct cxl_reg_map with a count
> > member, and add cxl_get_hdm_info() to return offset, size, and count
> > from the cached map.  Export under the CXL namespace.
> >
> > Signed-off-by: Manish Honap <mhonap@nvidia.com>
> > ---
> >  drivers/cxl/core/pci.c  | 33 +++++++++++++++++++++++++++++++++
> > drivers/cxl/core/regs.c |  1 +
> >  include/cxl/cxl.h       |  4 ++++
> >  3 files changed, 38 insertions(+)
> >
> > diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index
> > 2bcd683aa286..c917608c16f9 100644
> > --- a/drivers/cxl/core/pci.c
> > +++ b/drivers/cxl/core/pci.c
> > @@ -449,6 +449,39 @@ int cxl_hdm_decode_init(struct cxl_dev_state
> > *cxlds, struct cxl_hdm *cxlhdm,  }
> > EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, "CXL");
> >
> > +/**
> > + * cxl_get_hdm_info - Get HDM decoder register block location and
> > +count
> > + * @cxlds: CXL device state (must have component regs enumerated via
> > + *      cxl_probe_component_regs())
> > + * @count:  number of HDM decoders (from HDM Capability bits [3:0])
> > + * @offset: byte offset of HDM decoder block within the component
> register BAR
> > + * @size:   size in bytes of the HDM decoder block
> > + *
> > + * Exported for cxl drivers (in-kernel accelerator drivers, vfio-cxl)
> > +that
> > + * need HDM decoder metadata from the cached component-register map
> > +without
> > + * re-running the probe sequence.
> > + *
> > + * Return: 0 on success. -ENODEV if the HDM decoder block is not
> present.
> > + */
> > +int cxl_get_hdm_info(struct cxl_dev_state *cxlds, u8 *count,
> > +                  resource_size_t *offset, resource_size_t *size) {
> > +     struct cxl_reg_map *hdm =
> > +&cxlds->reg_map.component_map.hdm_decoder;
> > +
> > +     if (WARN_ON(!count || !offset || !size))
> > +             return -EINVAL;
> > +
> > +     if (!hdm->valid)
> > +             return -ENODEV;
> > +
> > +     *count  = hdm->count;
> > +     *offset = hdm->offset;
> > +     *size   = hdm->size;
> > +
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_NS_GPL(cxl_get_hdm_info, "CXL");
> 
> This is the same information that the CXL reset patches need to cache on
> the PCI device. Effectively this level of CXL information deserves to be
> as accessible as PCI BAR information, and should not need cxl_dev_state
> context to fetch it.
> 
> So it would be good to depend on that rather than invent a new export
> mechanism.

Agreed. I will make sure to base the patch-v04 on Srirangan Madhavan's CXL
reset v09 (base: 8cdeaa50eae8).
(HDM info is read directly from pdev->hdm at open_device(). No new
cxl_get_hdm_info() export is introduced.)

^ permalink raw reply

* RE: [PATCH v3 05/11] vfio: UAPI for CXL Type-2 device passthrough
From: Manish Honap @ 2026-07-13 16:44 UTC (permalink / raw)
  To: Alex Williamson
  Cc: djbw@kernel.org, jgg@ziepe.ca, jic23@kernel.org,
	dave.jiang@intel.com, Ankit Agrawal,
	alejandro.lucero-palau@amd.com, alison.schofield@intel.com,
	dave@stgolabs.net, dmatlack@google.com, gourry@gourry.net,
	ira.weiny@intel.com, Neo Jia, Krishnakant Jaju, Vikram Sethi,
	Zhi Wang, kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <20260710162322.012be635@shazbot.org>



> -----Original Message-----
> From: Alex Williamson <alex@shazbot.org>
> Sent: 11 July 2026 03:53
> To: Manish Honap <mhonap@nvidia.com>
> Cc: djbw@kernel.org; jgg@ziepe.ca; jic23@kernel.org;
> dave.jiang@intel.com; Ankit Agrawal <ankita@nvidia.com>;
> alejandro.lucero-palau@amd.com; alison.schofield@intel.com;
> dave@stgolabs.net; dmatlack@google.com; gourry@gourry.net;
> ira.weiny@intel.com; Neo Jia <cjia@nvidia.com>; Krishnakant Jaju
> <kjaju@nvidia.com>; Vikram Sethi <vsethi@nvidia.com>; Zhi Wang
> <zhiw@nvidia.com>; kvm@vger.kernel.org; linux-cxl@vger.kernel.org;
> linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org; linux-
> kselftest@vger.kernel.org; alex@shazbot.org
> Subject: Re: [PATCH v3 05/11] vfio: UAPI for CXL Type-2 device
> passthrough
> 
> External email: Use caution opening links or attachments
> 
> 
> On Thu, 25 Jun 2026 22:24:01 +0530
> <mhonap@nvidia.com> wrote:
> > diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
> > index 5de618a3a5ee..3707d53c4de5 100644
> > --- a/include/uapi/linux/vfio.h
> > +++ b/include/uapi/linux/vfio.h
> > @@ -215,6 +215,7 @@ struct vfio_device_info {
> >  #define VFIO_DEVICE_FLAGS_FSL_MC (1 << 6)    /* vfio-fsl-mc device */
> >  #define VFIO_DEVICE_FLAGS_CAPS       (1 << 7)        /* Info supports
> caps */
> >  #define VFIO_DEVICE_FLAGS_CDX        (1 << 8)        /* vfio-cdx
> device */
> > +#define VFIO_DEVICE_FLAGS_CXL        (1 << 9)        /* vfio-cxl
> Type-2 device */
> 
> Would we define a different flag for type-1/3 if we ever found a need to
> expose them through vfio?

Yes. The current flag is named VFIO_DEVICE_FLAGS_CXL and refers to
Type-2 specifically. If Type-1 or Type-3 support is added later, a
separate flag (or a VFIO_DEVICE_INFO_CAP sub-type field) would
distinguish them. I can rename it VFIO_DEVICE_FLAGS_CXL_TYPE2 now if
that is preferable; please advise.

> 
> >       __u32   num_regions;    /* Max region index + 1 */
> >       __u32   num_irqs;       /* Max IRQ index + 1 */
> >       __u32   cap_offset;     /* Offset within info struct of first
> cap */
> > @@ -257,6 +258,36 @@ struct vfio_device_info_cap_pci_atomic_comp {
> >       __u32 reserved;
> >  };
> >
> > +/*
> > + * VFIO_DEVICE_INFO capability for CXL Type-2 passthrough devices.
> > + * Present when VFIO_DEVICE_FLAGS_CXL is set on
> vfio_device_info::flags.
> > + *
> > + * @flags: VFIO_CXL_CAP_HOST_FIRMWARE_COMMITTED indicates the host
> CXL
> > + *   subsystem committed the endpoint HDM decoder.
> > + * @hdm_region_idx: VFIO region index for the HDM memory region
> > + *   (subtype VFIO_REGION_SUBTYPE_CXL).
> > + * @comp_reg_region_idx: VFIO region index for the CXL Component
> > + *   Register shadow (subtype VFIO_REGION_SUBTYPE_CXL_COMP_REGS).
> 
> These regions are self describing via the noted CXL subtypes, what's the
> purpose of double reporting them here?

Agreed; I will try to minimize the noise here.

> 
> > + * @comp_reg_bar: PCI BAR index that contains the CXL component
> > + *   register block.  Get-region-info on this BAR returns a
> > + *   VFIO_REGION_INFO_CAP_SPARSE_MMAP that excludes the CXL block.
> > + * @comp_reg_offset: byte offset of the CXL component register block
> > + *   within @comp_reg_bar.
> > + * @comp_reg_size: byte size of the CXL component register block.
> 
> Why don't we describe all of these via a capability on the relevant
> region info?

okay, I will have v4 to remove hdm_region_idx, comp_reg_region_idx,
comp_reg_bar, comp_reg_offset, and comp_reg_size from
vfio_device_info_cap_cxl. The device-level cap will only have flags.

This will also result in component register details to move to a new
VFIO_REGION_INFO_CAP_CXL_COMP_REGS capability on the comp-reg region
info, carrying comp_reg_bar, comp_reg_offset, and comp_reg_size.

Regions will remain self-describing via VFIO_REGION_SUBTYPE_CXL and
VFIO_REGION_SUBTYPE_CXL_COMP_REGS.

> 
> Does that leave this device level capability describing the device as
> type-2 (by existence), with only a flags field to declare HDM as
> firmware committed, for future compatibility should we support non-fw
> committed?  Thanks,
> 
> Alex

Yes, I will shape the v4 in this direction. The device-level CAP_CXL
shrinks to "this is a CXL device" (by existence) plus a flags field whose
only defined bit today is HOST_FIRMWARE_COMMITTED, leaving
room for a future non-fw-committed mode. Everything else moves to region
caps. Thanks for this suggestion.


^ permalink raw reply

* RE: [PATCH v3 06/11] cxl: Add register-virtualization helpers for vfio Type-2 passthrough
From: Manish Honap @ 2026-07-13 16:46 UTC (permalink / raw)
  To: Dan Williams (nvidia), alex@shazbot.org, jgg@ziepe.ca,
	jic23@kernel.org, dave.jiang@intel.com, Ankit Agrawal,
	alejandro.lucero-palau@amd.com, alison.schofield@intel.com,
	dave@stgolabs.net, dmatlack@google.com, gourry@gourry.net,
	ira.weiny@intel.com
  Cc: Neo Jia, Krishnakant Jaju, Vikram Sethi, Zhi Wang,
	kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <6a516a9e86b8_3cfbb510040@djbw-dev.notmuch>



> -----Original Message-----
> From: Dan Williams (nvidia) <djbw@kernel.org>
> Sent: 11 July 2026 03:27
> To: Manish Honap <mhonap@nvidia.com>; djbw@kernel.org; alex@shazbot.org;
> jgg@ziepe.ca; jic23@kernel.org; dave.jiang@intel.com; Ankit Agrawal
> <ankita@nvidia.com>; alejandro.lucero-palau@amd.com;
> alison.schofield@intel.com; dave@stgolabs.net; dmatlack@google.com;
> gourry@gourry.net; ira.weiny@intel.com
> Cc: Neo Jia <cjia@nvidia.com>; Krishnakant Jaju <kjaju@nvidia.com>;
> Vikram Sethi <vsethi@nvidia.com>; Zhi Wang <zhiw@nvidia.com>; Manish
> Honap <mhonap@nvidia.com>; kvm@vger.kernel.org; linux-
> cxl@vger.kernel.org; linux-doc@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-kselftest@vger.kernel.org
> Subject: Re: [PATCH v3 06/11] cxl: Add register-virtualization helpers
> for vfio Type-2 passthrough
> 
> External email: Use caution opening links or attachments
> 
> 
> mhonap@ wrote:
> > From: Manish Honap <mhonap@nvidia.com>
> >
> > vfio-pci needs the CXL Device DVSEC body, the HDM Decoder Capability
> > block, and the CXL.cache/mem cap-array prefix to be virtualized toward
> > a KVM guest in a CXL-spec-compliant way.
> >
> > Introduce a narrow helper API owned by cxl-core:
> >
> >   struct cxl_passthrough *
> >   devm_cxl_passthrough_create(struct device *dev,
> >                               struct cxl_dev_state *cxlds);
> >
> >   int cxl_passthrough_dvsec_rw(struct cxl_passthrough *p, u32 off,
> >                                u32 *val, size_t sz, bool write);
> >   int cxl_passthrough_hdm_rw(struct cxl_passthrough *p, u32 off,
> >                              u32 *val, bool write);
> >   int cxl_passthrough_cm_rw(struct cxl_passthrough *p, u32 off,
> >                             u32 *val, bool write);
> >
> > Each helper takes a per-device mutex covering the DVSEC + HDM shadows
> > (the CM cap-array snapshot is immutable after create) and dispatches
> > by offset to a hand-written write handler against CXL r4.0 §8.1.3
> > (DVSEC: LOCK is RWO, CONTROL/CONTROL2 are RWL gated on CONFIG_LOCK,
> > STATUS/STATUS2 are RW1C, RANGE1 is HwInit, RANGE2 is RsvdZ) and
> > §8.2.4.20 (HDM: GLOBAL_CTRL RW, decoder CTRL implements
> > COMMIT/COMMITTED, decoder BASE/SIZE RWL gated on COMMITTED or
> > LOCK_ON_COMMIT, cap header HwInit).
> >
> > Writes to the CM cap-array are silently discarded because the
> > cap-array headers are RO per CXL r4.0 §8.2.4; the write parameter is
> > kept on the rw API to make the drop policy explicit at the call site.
> >
> > The shadows are snapshotted at create time: the DVSEC body from PCI
> > config space dword-at-a-time, the CM cap-array and HDM block from the
> > cxl-core MMIO mapping at cxlds->reg_map.base.  This preserves
> > firmware-committed values so the guest reads what the host BIOS
> > committed, while writes update the shadow per the per-field write
> > semantics above.
> >
> > The file is gated by the hidden Kconfig CXL_VFIO_PASSTHROUGH so the
> > passthrough code stays out of cxl_core when no vfio consumer is
> configured.
> >
> > Scope: firmware-committed, single-decoder, no-interleave Type-2
> > passthrough.  Multi-decoder, interleave, and hotplug are out-of-scope
> > and rejected at create time (-EOPNOTSUPP for hdm_count != 1).
> 
> Hi Manish, many style comments below, but one hard concern to highlight
> is that some component capability registers require 64-bit access.
> 
> >
> > Signed-off-by: Manish Honap <mhonap@nvidia.com>
> > ---
> >  drivers/cxl/Kconfig            |   7 +
> >  drivers/cxl/core/Makefile      |   1 +
> >  drivers/cxl/core/passthrough.c | 590
> > +++++++++++++++++++++++++++++++++
> 
> Likely this should be called vfio.c because nothing in this file is
> relevant to the rest of the CXL core. However, it is not even clear
> there is value in it living in drivers/cxl/.
> 
> A lot of this code is a VFIO backend implemnentation detail, not
> anything that CXL core needs. It also seems to have little if any
> dependency on any core symbols. Does it really belong in
> drivers/cxl/core/?

okay, agreed on the direction. For v4 I'll move this out of
drivers/cxl/core/ into the vfio-cxl backend under
drivers/vfio/pci/cxl/, which resolves several of these at once:
- the file/struct/header get vfio-oriented names
- EXPORT_SYMBOL_NS_GPL("CXL") exports go away

Any spec-defined register defines that must be shared will move to
include/cxl/ rather than being duplicated.

> 
> >  include/cxl/passthrough.h      | 121 +++++++
> >  4 files changed, 719 insertions(+)
> >  create mode 100644 drivers/cxl/core/passthrough.c  create mode 100644
> > include/cxl/passthrough.h
> >
> > diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig index
> > 80aeb0d556bd..7c874d486a9c 100644
> > --- a/drivers/cxl/Kconfig
> > +++ b/drivers/cxl/Kconfig
> > @@ -19,6 +19,13 @@ menuconfig CXL_BUS
> >
> >  if CXL_BUS
> >
> > +config CXL_VFIO_PASSTHROUGH
> > +     bool
> > +     # Hidden symbol selected by VFIO_PCI_CXL to pull
> > +     # drivers/cxl/core/passthrough.c into cxl_core when a vfio
> > +     # Type-2 passthrough consumer is configured.  Keep silent: no
> > +     # help text, no default, no user-visible prompt.
> 
> No need for a paragraph of documentation to explain why this prompt has
> no documention. If probably just be called CXL_VFIO.

okay. I will name the Kconfig symbol to CXL_VFIO and remove the paragraph.

> 
> > +
> >  config CXL_PCI
> >       tristate "PCI manageability"
> >       default CXL_BUS
> > diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile
> > index ce7213818d3c..0cc80bd35a88 100644
> > --- a/drivers/cxl/core/Makefile
> > +++ b/drivers/cxl/core/Makefile
> > @@ -22,3 +22,4 @@ cxl_core-$(CONFIG_CXL_EDAC_MEM_FEATURES) += edac.o
> >  cxl_core-$(CONFIG_CXL_RAS) += ras.o
> >  cxl_core-$(CONFIG_CXL_RAS) += ras_rch.o
> >  cxl_core-$(CONFIG_CXL_ATL) += atl.o
> > +cxl_core-$(CONFIG_CXL_VFIO_PASSTHROUGH) += passthrough.o
> > diff --git a/drivers/cxl/core/passthrough.c
> > b/drivers/cxl/core/passthrough.c new file mode 100644 index
> > 000000000000..b89829586024
> > --- /dev/null
> > +++ b/drivers/cxl/core/passthrough.c
> > @@ -0,0 +1,590 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/* Copyright(c) 2026 NVIDIA Corporation. All rights reserved.
> > + *
> > + * vfio-pci Type-2 device passthrough — CXL register virtualization.
> > + *
> > + * Owns the CXL spec-defined virtualization semantics for the
> > + *   - CXL Device DVSEC capability body  (CXL r4.0 §8.1.3)
> > + *   - HDM Decoder Capability block      (CXL r4.0 §8.2.4.20)
> > + *   - CXL.cache/mem (CM) cap-array      (CXL r4.0 §8.2.4)
> > + *
> > + * vfio-pci is the only caller.  This file is NOT a generic emulation
> > + * framework: every register the guest may touch has a hand-written
> > + * write handler against the spec.  Reads serve from a shadow
> > + * snapshotted at create time; writes update the shadow per the spec
> > + * attribute mode for that field.
> > + *
> > + * Scope: firmware-committed, single-decoder, no-interleave Type-2
> > + * passthrough.  Multi-decoder, interleave, and hotplug are
> > + * out-of-scope and rejected at create time.
> > + */
> > +
> > +#include <linux/bitfield.h>
> > +#include <linux/bitops.h>
> > +#include <linux/cleanup.h>
> > +#include <linux/device.h>
> > +#include <linux/export.h>
> > +#include <linux/io.h>
> > +#include <linux/mutex.h>
> > +#include <linux/pci.h>
> > +#include <linux/pci_ids.h>
> > +#include <linux/pci_regs.h>
> > +#include <linux/slab.h>
> > +#include <linux/types.h>
> > +#include <linux/unaligned.h>
> > +
> > +#include <uapi/cxl/cxl_regs.h>
> > +
> > +#include <cxlpci.h>
> > +#include <cxlmem.h>
> > +#include <cxl/cxl.h>
> > +#include <cxl/passthrough.h>
> > +
> > +#include "core.h"
> > +
> > +/* DVSEC CXL Device body offsets — relative to DVSEC capability
> start.
> > + * Body begins at PCI_DVSEC_CXL_CAP (0x0a); preceding bytes are the
> > +PCI
> > + * ext-cap header and DVSEC headers handled by the generic vfio
> > + * perm-bits path.
> > + */
> > +#define DVSEC_OFF_CAPABILITY         PCI_DVSEC_CXL_CAP       /* 0x0a,
> u16 */
> > +#define DVSEC_OFF_CONTROL            PCI_DVSEC_CXL_CTRL      /* 0x0c,
> u16 */
> > +#define DVSEC_OFF_STATUS             0x0e                    /* u16
> */
> > +#define DVSEC_OFF_CONTROL2           0x10                    /* u16
> */
> > +#define DVSEC_OFF_STATUS2            0x12                    /* u16
> */
> > +#define DVSEC_OFF_LOCK                       0x14
> /* u16 */
> > +#define DVSEC_OFF_RANGE1_SIZE_HI     0x18                    /* u32
> */
> > +#define DVSEC_OFF_RANGE1_SIZE_LO     0x1c
> > +#define DVSEC_OFF_RANGE1_BASE_HI     0x20
> > +#define DVSEC_OFF_RANGE1_BASE_LO     0x24
> > +#define DVSEC_OFF_RANGE2_SIZE_HI     0x28
> > +#define DVSEC_OFF_RANGE2_SIZE_LO     0x2c
> > +#define DVSEC_OFF_RANGE2_BASE_HI     0x30
> > +#define DVSEC_OFF_RANGE2_BASE_LO     0x34
> > +#define DVSEC_BODY_END                       0x38
> 
> Please do not duplicate the existing definitions in
> include/uapi/linux/pci_regs.h.
> 
> > +
> > +#define DVSEC_LOCK_CONFIG_LOCK               BIT(0)
> 
> > +
> > +/* HDM Decoder Capability block offsets — relative to HDM block base.
> > + * Decoder N register set starts at 0x10 + N * 0x20.
> > + */
> > +#define HDM_OFF_CAP_HEADER           0x00
> > +#define HDM_OFF_GLOBAL_CTRL          0x04
> > +#define HDM_DEC_BASE                 0x10
> > +#define HDM_DEC_STRIDE                       0x20
> > +#define HDM_DEC_OFF_BASE_LO(n)               (HDM_DEC_BASE + (n) *
> HDM_DEC_STRIDE + 0x00)
> > +#define HDM_DEC_OFF_BASE_HI(n)               (HDM_DEC_BASE + (n) *
> HDM_DEC_STRIDE + 0x04)
> > +#define HDM_DEC_OFF_SIZE_LO(n)               (HDM_DEC_BASE + (n) *
> HDM_DEC_STRIDE + 0x08)
> > +#define HDM_DEC_OFF_SIZE_HI(n)               (HDM_DEC_BASE + (n) *
> HDM_DEC_STRIDE + 0x0c)
> > +#define HDM_DEC_OFF_CTRL(n)          (HDM_DEC_BASE + (n) *
> HDM_DEC_STRIDE + 0x10)
> > +
> > +/* HDM Decoder CTRL bits per CXL r4.0 §8.2.4.20.5. */
> > +#define HDM_CTRL_LOCK_ON_COMMIT              BIT(8)
> > +#define HDM_CTRL_COMMIT                      BIT(9)
> > +#define HDM_CTRL_COMMITTED           BIT(10)
> > +#define HDM_CTRL_ERR_NOT_COMMITTED   BIT(11)
> 
> Please do not duplicate the definitions in drivers/cxl/cxl.h?
> 
> If you move this file to drivers/vfio/ then also move the definitions to
> include/cxl/.

okay; I will fix both these duplicates as suggested.

> 
> > +struct cxl_passthrough {
> 
> This structure should be called cxl_vfio so that any grep for "vfio" in
> drivers/cxl/ brings up this code. Otherwise "passthrough" is not a term
> I would expect someone to understand is immediately vfio related. Even
> drivers/vfio/ barely uses the term.

okay, agreed.

> 
> > +     struct cxl_dev_state *cxlds;
> > +
> > +     /* DVSEC body shadow.  Byte-indexed by (off -
> PCI_DVSEC_CXL_CAP).
> > +      * Allocated rounded up to a dword so dword reads at the tail
> > +      * never overrun.
> > +      */
> > +     u8 *dvsec_shadow;
> > +     u16 dvsec_size;                 /* full DVSEC cap length, incl.
> headers */
> > +     bool dvsec_config_locked;
> > +
> > +     /* HDM block shadow.  Byte-indexed; size = hdm_reg_size. */
> > +     u8 *hdm_shadow;
> > +     resource_size_t hdm_reg_size;
> > +
> > +     /* CM cap-array snapshot.  Dword-indexed by (off / 4) where off
> > +      * is the byte offset from CXL_CM_OFFSET.  Read-only after
> create.
> > +      */
> > +     __le32 *cm_snapshot;
> > +     size_t cm_snapshot_dwords;
> > +
> > +     /* Covers dvsec_shadow + dvsec_config_locked + hdm_shadow.
> > +      * cm_snapshot is immutable after create; no lock needed.  Leaf-
> > +      * level: no entry point holding this mutex calls into cxl-bus
> or
> > +      * vfio.
> > +      */
> > +     struct mutex lock;
> > +};
> > +
> > +/* ------------------------------------------------------------------
> */
> > +/* Snapshot helpers
> */
> > +/* ------------------------------------------------------------------
> > +*/
> > +
> > +/* Read the DVSEC body bytes [PCI_DVSEC_CXL_CAP, dvsec_size) from PCI
> > + * config space into the shadow.
> > + *
> > + * The body starts at PCI_DVSEC_CXL_CAP (0x0a), which is word-aligned
> > +but
> > + * NOT dword-aligned, and CXL r4.0 §8.1.3 places six 16-bit
> > +descriptors
> > + * (CAPABILITY through LOCK) at offsets 0x0a..0x14 before any 32-bit
> > + * field.  Strict-alignment PCIe host bridges (e.g. ARM64 ECAM)
> > +reject
> > + * misaligned dword config accesses with PCIBIOS_BAD_REGISTER_NUMBER;
> > + * snapshot at the natural granularity of the body's 16-bit
> > +descriptors
> > + * (2-byte stride) so every offset in the range is naturally aligned.
> > + */
> > +static int snapshot_dvsec_body(struct cxl_passthrough *p) {
> > +     struct pci_dev *pdev = to_pci_dev(p->cxlds->dev);
> > +     u16 dvsec = p->cxlds->cxl_dvsec;
> > +     u16 off;
> > +     u16 word;
> > +     int rc;
> > +
> > +     for (off = PCI_DVSEC_CXL_CAP; off < p->dvsec_size; off += 2) {
> > +             rc = pci_read_config_word(pdev, dvsec + off, &word);
> > +             if (rc)
> > +                     return -EIO;
> > +             put_unaligned_le16(word, p->dvsec_shadow +
> > +                                (off - PCI_DVSEC_CXL_CAP));
> > +     }
> > +     return 0;
> > +}
> > +
> > +/* Read the CM cap-array prefix [CXL_CM_OFFSET, hdm_reg_offset) from
> > + * MMIO into cm_snapshot, and the HDM block [hdm_reg_offset,
> > + * hdm_reg_offset + hdm_reg_size) into hdm_shadow.
> > + *
> > + * @base is a short-lived kva for the component register block,
> > + * established by the caller via ioremap() against cxlds-
> >reg_map.resource.
> > + * cxl_setup_regs() drops its own ioremap (clears reg_map.base) after
> > +the
> > + * cap-array probe completes, so this function cannot rely on
> > + * cxlds->reg_map.base being valid; the caller passes a fresh mapping
> > + * here and releases it once snapshot data has been copied into the
> > + * in-memory shadows.
> 
> This commentary is point in time research about how the CXL core
> behaves. I do not see a reason for devm_cxl_vfio_create() to document
> the semantics of cxl_setup_regs().
> 
> If you want to add documentation that explains how cxl_setup_regs()
> works that belongs on cxl_setup_regs() directly.
> 
> Lastly cxl_setup_regs() is a convenience function for the cxl_pci driver
> that wants to parse the component register block into per capability
> sparse mappings. The only functionality this implementation wants is the
> base resource address, but that might change with the next comment.
> 
> > + */
> > +static void snapshot_cm_and_hdm(struct cxl_passthrough *p,
> > +                             void __iomem *base,
> > +                             resource_size_t hdm_off) {
> > +     size_t i;
> > +
> > +     for (i = 0; i < p->cm_snapshot_dwords; i++)
> > +             p->cm_snapshot[i] = cpu_to_le32(readl(base +
> CXL_CM_OFFSET +
> > +                                                   i * 4));
> 
> Unfortunately there are some registers that are 64-bit only registers.
> 
> The spec says: "A 64-bit register shall be accessed as an 8-byte
> quantity. Partial reads are not permitted."
> 
> That means if a device has a link capability structure, a CHMU, or a
> CPMU then this implementation will violate that requirement. Maybe the
> implemetnation indeed needs to limit the component register blocks that
> are supported.

okay, agreed. For v4 I'll constrain the supported set: at acquire time,
walk the CM cap-array and reject (-EOPNOTSUPP) any block that contains a
capability requiring 64-bit access (link cap / CHMU / CPMU), which is
consistent with the already-narrow single-decoder, no-interleave,
fw-precommitted scope.

Adding true 8-byte access to both the emu table and the COMP_REGS region is
possible later but I'd rather not widen scope in this series.

> 
> > +
> > +     for (i = 0; i < p->hdm_reg_size / 4; i++)
> > +             put_unaligned_le32(readl(base + hdm_off + i * 4),
> > +                                p->hdm_shadow + i * 4); }
> > +
> > +/* ------------------------------------------------------------------
> */
> > +/* devres
> */
> > +/* ------------------------------------------------------------------
> > +*/
> > +
> > +static void cxl_passthrough_release(struct device *dev, void *res) {
> > +     struct cxl_passthrough *p = *(struct cxl_passthrough **)res;
> > +
> > +     kfree(p->dvsec_shadow);
> > +     kfree(p->hdm_shadow);
> > +     kfree(p->cm_snapshot);
> > +     mutex_destroy(&p->lock);
> > +     kfree(p);
> > +}
> > +
> > +struct cxl_passthrough *
> > +devm_cxl_passthrough_create(struct device *dev, struct cxl_dev_state
> > +*cxlds) {
> > +     struct cxl_passthrough **dres;
> > +     struct cxl_passthrough *p;
> > +     struct pci_dev *pdev;
> > +     resource_size_t hdm_off, hdm_size;
> > +     size_t dvsec_shadow_size;
> > +     u8 hdm_count;
> > +     u32 hdr;
> > +     int rc;
> > +
> > +     /*
> > +      * cxl_setup_regs() releases its short-lived ioremap before
> returning,
> > +      * so reg_map.base is NULL by the time we run.  Validate the
> persistent
> > +      * fields (resource address and size) instead; the local ioremap
> > +      * established further below covers the snapshot reads.
> > +      */
> 
> This is the cxl_setup_regs() documentation again.
> 
> 
> > +     if (!dev || !cxlds || !cxlds->dev || !cxlds->cxl_dvsec ||
> > +         !cxlds->reg_map.resource || !cxlds->reg_map.max_size)
> > +             return ERR_PTR(-EINVAL);
> > +
> > +     pdev = to_pci_dev(cxlds->dev);
> > +
> > +     rc = cxl_get_hdm_info(cxlds, &hdm_count, &hdm_off, &hdm_size);
> > +     if (rc)
> > +             return ERR_PTR(rc);
> > +     if (hdm_count != 1 || !hdm_size || hdm_off <= CXL_CM_OFFSET ||
> > +         !IS_ALIGNED(hdm_size, 4))
> > +             return ERR_PTR(-EOPNOTSUPP);
> > +
> > +     p = kzalloc_obj(*p, GFP_KERNEL);
> > +     if (!p)
> > +             return ERR_PTR(-ENOMEM);
> > +
> > +     mutex_init(&p->lock);
> > +     p->cxlds = cxlds;
> > +     p->hdm_reg_size = hdm_size;
> > +
> > +     /* DVSEC body length from PCI ext-cap header. */
> > +     rc = pci_read_config_dword(pdev, cxlds->cxl_dvsec +
> PCI_DVSEC_HEADER1,
> > +                                &hdr);
> > +     if (rc) {
> > +             rc = -EIO;
> > +             goto err;
> > +     }
> > +     p->dvsec_size = PCI_DVSEC_HEADER1_LEN(hdr);
> > +     if (p->dvsec_size < DVSEC_BODY_END) {
> > +             rc = -EINVAL;
> > +             goto err;
> > +     }
> > +
> > +     dvsec_shadow_size = round_up(p->dvsec_size - PCI_DVSEC_CXL_CAP,
> 4);
> > +     p->dvsec_shadow = kzalloc(dvsec_shadow_size, GFP_KERNEL);
> > +     if (!p->dvsec_shadow) {
> > +             rc = -ENOMEM;
> > +             goto err;
> > +     }
> > +
> > +     p->cm_snapshot_dwords = (hdm_off - CXL_CM_OFFSET) / 4;
> > +     p->cm_snapshot = kcalloc(p->cm_snapshot_dwords, sizeof(__le32),
> > +                              GFP_KERNEL);
> > +     if (!p->cm_snapshot) {
> > +             rc = -ENOMEM;
> > +             goto err;
> > +     }
> > +
> > +     p->hdm_shadow = kzalloc(hdm_size, GFP_KERNEL);
> > +     if (!p->hdm_shadow) {
> > +             rc = -ENOMEM;
> > +             goto err;
> > +     }
> > +
> > +     rc = snapshot_dvsec_body(p);
> > +     if (rc)
> > +             goto err;
> > +
> > +     {
> > +             void __iomem *base;
> 
> Just declare this at the top and skip the new scope, or just make this a
> helper function.

okay. I will change this.

> 
> > +
> > +             /*
> > +              * Bind-time-only ioremap.  cxl_setup_regs() has already
> > +              * released the cxl-core ioremap (see comment on the
> entry
> > +              * gate).  Take a fresh, short-lived mapping for the
> > +              * snapshot, then release it; all subsequent reads serve
> > +              * from the in-memory shadows.
> > +              */
> 
> More redundant explanation of the cxl_setup_pci_regs() semantics.
> 
> > +             base = ioremap(cxlds->reg_map.resource,
> > +                            cxlds->reg_map.max_size);
> > +             if (!base) {
> > +                     rc = -ENOMEM;
> > +                     goto err;
> > +             }
> > +             snapshot_cm_and_hdm(p, base, hdm_off);
> > +             iounmap(base);
> > +     }
> > +
> > +     dres = devres_alloc(cxl_passthrough_release, sizeof(*dres),
> > +                         GFP_KERNEL);
> > +     if (!dres) {
> > +             rc = -ENOMEM;
> > +             goto err;
> > +     }
> > +     *dres = p;
> > +     devres_add(dev, dres);
> 
> This is just:
> 
> rc = devm_add_action_or_reset(dev, cxl_passthrough_release, p); if (rc)
>         return ERR_PTR(rc);
> 

okay, I will update this.

> > +     return p;
> > +
> > +err:
> > +     kfree(p->dvsec_shadow);
> > +     kfree(p->cm_snapshot);
> > +     kfree(p->hdm_shadow);
> > +     mutex_destroy(&p->lock);
> > +     kfree(p);
> > +     return ERR_PTR(rc);
> > +}
> > +EXPORT_SYMBOL_NS_GPL(devm_cxl_passthrough_create, "CXL");
> > +
> > +/* ------------------------------------------------------------------
> */
> > +/* DVSEC write semantics
> */
> > +/* ------------------------------------------------------------------
> > +*/
> > +
> > +static u16 dvsec_shadow_get_u16(struct cxl_passthrough *p, u16 off) {
> > +     return get_unaligned_le16(p->dvsec_shadow + (off -
> > +PCI_DVSEC_CXL_CAP)); }
> > +
> > +static void dvsec_shadow_set_u16(struct cxl_passthrough *p, u16 off,
> > +u16 val) {
> > +     put_unaligned_le16(val, p->dvsec_shadow + (off -
> > +PCI_DVSEC_CXL_CAP)); }
> > +
> > +/* Apply a write to a single DVSEC field at @off, with the field's
> > + * native width (2 for descriptors, 4 for RANGE entries).  @width is
> > + * the field's spec width; @new is the merged value to apply.  Caller
> > + * holds p->lock.
> > + */
> > +static void dvsec_apply_write(struct cxl_passthrough *p, u16 off,
> size_t width,
> > +                           u32 new)
> > +{
> > +     u16 cur16;
> > +
> > +     switch (off) {
> > +     case DVSEC_OFF_CAPABILITY:
> > +             /* HwInit — drop. */
> > +             return;
> > +     case DVSEC_OFF_CONTROL:
> > +     case DVSEC_OFF_CONTROL2:
> > +             /* RWL — gated on CONFIG_LOCK. */
> > +             if (p->dvsec_config_locked)
> > +                     return;
> > +             dvsec_shadow_set_u16(p, off, (u16)new);
> > +             return;
> > +     case DVSEC_OFF_STATUS:
> > +     case DVSEC_OFF_STATUS2:
> > +             /* RW1C — clear bits where the guest wrote 1. */
> > +             cur16 = dvsec_shadow_get_u16(p, off);
> > +             dvsec_shadow_set_u16(p, off, cur16 & ~(u16)new);
> > +             return;
> > +     case DVSEC_OFF_LOCK:
> > +             /* RWO — first 1-write latches CONFIG_LOCK; subsequent
> > +              * writes are ignored.
> > +              */
> > +             cur16 = dvsec_shadow_get_u16(p, off);
> > +             if (cur16 & DVSEC_LOCK_CONFIG_LOCK)
> > +                     return;
> > +             if (new & DVSEC_LOCK_CONFIG_LOCK) {
> > +                     dvsec_shadow_set_u16(p, off,
> > +                                          cur16 |
> DVSEC_LOCK_CONFIG_LOCK);
> > +                     p->dvsec_config_locked = true;
> > +             }
> > +             return;
> > +     case DVSEC_OFF_RANGE1_SIZE_HI:
> > +     case DVSEC_OFF_RANGE1_SIZE_LO:
> > +     case DVSEC_OFF_RANGE1_BASE_HI:
> > +     case DVSEC_OFF_RANGE1_BASE_LO:
> > +             /* HwInit — drop. */
> > +             return;
> > +     case DVSEC_OFF_RANGE2_SIZE_HI:
> > +     case DVSEC_OFF_RANGE2_SIZE_LO:
> > +     case DVSEC_OFF_RANGE2_BASE_HI:
> > +     case DVSEC_OFF_RANGE2_BASE_LO:
> > +             /* RsvdZ — drop. */
> > +             return;
> > +     default:
> > +             /* Reserved offsets inside the modelled body: drop. */
> > +             (void)width;
> > +             return;
> > +     }
> > +}
> > +
> > +/* Map a byte offset @off inside the DVSEC body to the natural-width
> > + * field that contains it: returns the field's base offset (16-bit
> > + * aligned for descriptors, 32-bit aligned for RANGE entries) and
> width.
> > + * Returns false if @off lies outside any modelled field.
> > + */
> > +static bool dvsec_field_at(u16 off, u16 *field_off, size_t *width) {
> > +     if (off >= DVSEC_OFF_CAPABILITY && off <
> DVSEC_OFF_RANGE1_SIZE_HI) {
> > +             *field_off = ALIGN_DOWN(off, 2);
> > +             *width = 2;
> > +             return true;
> > +     }
> > +     if (off >= DVSEC_OFF_RANGE1_SIZE_HI && off < DVSEC_BODY_END) {
> > +             *field_off = ALIGN_DOWN(off, 4);
> > +             *width = 4;
> > +             return true;
> > +     }
> > +     return false;
> > +}
> > +
> > +int cxl_passthrough_dvsec_rw(struct cxl_passthrough *p, u32 off, u32
> *val,
> > +                          size_t sz, bool write) {
> > +     u8 *shadow;
> > +     u16 field_off;
> > +     size_t field_width;
> > +     u32 cur, merged;
> > +     u32 sub_shift;
> > +     u32 width_mask;
> > +
> > +     if (!p || !val)
> > +             return -EINVAL;
> > +     if (sz != 1 && sz != 2 && sz != 4)
> > +             return -EINVAL;
> > +     if (off < PCI_DVSEC_CXL_CAP || off + sz > p->dvsec_size)
> > +             return -EINVAL;
> > +
> > +     guard(mutex)(&p->lock);
> > +
> > +     shadow = p->dvsec_shadow + (off - PCI_DVSEC_CXL_CAP);
> > +
> > +     if (!write) {
> > +             switch (sz) {
> > +             case 1:
> > +                     *val = *shadow;
> > +                     break;
> > +             case 2:
> > +                     *val = get_unaligned_le16(shadow);
> > +                     break;
> > +             case 4:
> > +                     *val = get_unaligned_le32(shadow);
> > +                     break;
> > +             }
> > +             return 0;
> > +     }
> > +
> > +     if (!dvsec_field_at(off, &field_off, &field_width))
> > +             return 0;       /* outside any modelled field: drop */
> > +
> > +     /* Read-modify-merge the field at its natural width. */
> > +     if (field_width == 2)
> > +             cur = dvsec_shadow_get_u16(p, field_off);
> > +     else
> > +             cur = get_unaligned_le32(p->dvsec_shadow +
> > +                                      (field_off -
> > + PCI_DVSEC_CXL_CAP));
> > +
> > +     width_mask = (sz == 4) ? 0xffffffff : (sz == 2 ? 0xffff : 0xff);
> > +     sub_shift = (off - field_off) * 8;
> > +     merged = cur & ~(width_mask << sub_shift);
> > +     merged |= (*val & width_mask) << sub_shift;
> > +
> > +     dvsec_apply_write(p, field_off, field_width, merged);
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_NS_GPL(cxl_passthrough_dvsec_rw, "CXL");
> 
> Hmm, no other "CXL" namespace consumer would ever care about this
> mechanism.  The export goes away if this file moves drivers/vfio/. If
> there is a good argument to stay in drivers/cxl/ then it should be
> EXPORT_SYMBOL_FOR_MODULES.

okay, I will update this part and move this file to drivers/vfio/

> 
> > +
> > +/* ------------------------------------------------------------------
> */
> > +/* HDM write semantics
> */
> > +/* ------------------------------------------------------------------
> > +*/
> > +
> > +static u32 hdm_shadow_get(struct cxl_passthrough *p, u32 off) {
> > +     return get_unaligned_le32(p->hdm_shadow + off); }
> > +
> > +static void hdm_shadow_set(struct cxl_passthrough *p, u32 off, u32
> > +val) {
> > +     put_unaligned_le32(val, p->hdm_shadow + off); }
> > +
> > +/* Decoder index for a per-decoder register offset. */ static u32
> > +hdm_decoder_of(u32 off) {
> > +     return (off - HDM_DEC_BASE) / HDM_DEC_STRIDE; }
> > +
> > +static u32 hdm_decoder_field(u32 off) {
> > +     return (off - HDM_DEC_BASE) % HDM_DEC_STRIDE; }
> > +
> > +static void hdm_decoder_ctrl_write(struct cxl_passthrough *p, u32
> > +off, u32 val) {
> > +     u32 cur = hdm_shadow_get(p, off);
> > +     u32 next;
> > +
> > +     /* Once COMMITTED, only the COMMIT toggle is honoured.
> Releasing
> > +      * COMMIT clears COMMITTED and Lock-on-Commit per CXL r4.0
> > +      * §8.2.4.20.5.
> > +      */
> > +     if (cur & HDM_CTRL_COMMITTED) {
> > +             next = (cur & ~HDM_CTRL_COMMIT) | (val &
> HDM_CTRL_COMMIT);
> > +             if (!(val & HDM_CTRL_COMMIT)) {
> > +                     next &= ~HDM_CTRL_COMMITTED;
> > +                     next &= ~HDM_CTRL_LOCK_ON_COMMIT;
> 
> No, when the decoder is locked its commit bit becomes read-only. Only
> reset can clear lock-on-commit.
> 

okay, I will update this behaviour in v4:
When LOCK_ON_COMMIT is set in the shadow:
- Writes that attempt to clear COMMITTED are dropped.
- COMMIT becomes read-only (writes to COMMIT=0 are dropped).
- LOCK_ON_COMMIT clears only when the device reset path refreshes the
  shadow from hardware.

> 
> > +             }
> > +             hdm_shadow_set(p, off, next);
> > +             return;
> > +     }
> > +
> > +     next = val & ~(HDM_CTRL_COMMITTED | HDM_CTRL_ERR_NOT_COMMITTED);
> > +     if (val & HDM_CTRL_COMMIT)
> > +             next |= HDM_CTRL_COMMITTED;
> > +     hdm_shadow_set(p, off, next);
> > +}
> > +
> > +static void hdm_decoder_basesize_write(struct cxl_passthrough *p, u32
> off,
> > +                                    u32 val) {
> > +     u32 n = hdm_decoder_of(off);
> > +     u32 ctrl = hdm_shadow_get(p, HDM_DEC_OFF_CTRL(n));
> > +
> > +     /* RWL — BASE/SIZE locked when the decoder is committed or
> > +      * lock-on-commit has been latched.
> > +      */
> > +     if (ctrl & (HDM_CTRL_COMMITTED | HDM_CTRL_LOCK_ON_COMMIT))
> > +             return;
> > +     hdm_shadow_set(p, off, val);
> > +}
> > +
> > +int cxl_passthrough_hdm_rw(struct cxl_passthrough *p, u32 off, u32
> *val,
> > +                        bool write)
> > +{
> > +     u32 field;
> > +
> > +     if (!p || !val)
> > +             return -EINVAL;
> > +     if (!IS_ALIGNED(off, 4) || off + 4 > p->hdm_reg_size)
> > +             return -EINVAL;
> > +
> > +     guard(mutex)(&p->lock);
> > +
> > +     if (!write) {
> > +             *val = hdm_shadow_get(p, off);
> > +             return 0;
> > +     }
> > +
> > +     switch (off) {
> > +     case HDM_OFF_CAP_HEADER:
> > +             /* HwInit — drop. */
> > +             return 0;
> > +     case HDM_OFF_GLOBAL_CTRL:
> > +             /* RW — shadow. */
> > +             hdm_shadow_set(p, off, *val);
> > +             return 0;
> > +     }
> > +
> > +     if (off < HDM_DEC_BASE)
> > +             return 0;       /* gap before per-decoder regs: drop */
> > +
> > +     field = hdm_decoder_field(off);
> > +     switch (field) {
> > +     case 0x00: case 0x04:   /* BASE_LO / BASE_HI */
> > +     case 0x08: case 0x0c:   /* SIZE_LO / SIZE_HI */
> > +             hdm_decoder_basesize_write(p, off, *val);
> > +             return 0;
> > +     case 0x10:              /* CTRL */
> > +             hdm_decoder_ctrl_write(p, off, *val);
> > +             return 0;
> > +     default:
> > +             /* TARGET_LIST_{LO,HI} and other per-decoder bytes are
> > +              * accepted as plain RW shadow for the firmware-
> committed
> > +              * scope; multi-decoder / interleave behaviour is
> > +              * out-of-scope.
> > +              */
> > +             hdm_shadow_set(p, off, *val);
> > +             return 0;
> > +     }
> > +}
> > +EXPORT_SYMBOL_NS_GPL(cxl_passthrough_hdm_rw, "CXL");
> 
> 
> > +
> > +/* ------------------------------------------------------------------
> */
> > +/* CM cap-array snapshot
> */
> > +/* ------------------------------------------------------------------
> > +*/
> > +
> > +int cxl_passthrough_cm_rw(struct cxl_passthrough *p, u32 off, u32
> *val,
> > +                       bool write)
> > +{
> > +     if (!p || !val)
> > +             return -EINVAL;
> > +     if (!IS_ALIGNED(off, 4) || off / 4 >= p->cm_snapshot_dwords)
> > +             return -EINVAL;
> > +
> > +     if (write)
> > +             return 0;       /* cap-array headers are RO; drop. */
> > +
> > +     *val = le32_to_cpu(p->cm_snapshot[off / 4]);
> > +     return 0;
> > +}
> > +EXPORT_SYMBOL_NS_GPL(cxl_passthrough_cm_rw, "CXL");
> > diff --git a/include/cxl/passthrough.h b/include/cxl/passthrough.h new
> > file mode 100644 index 000000000000..43214b0d34f6
> > --- /dev/null
> > +++ b/include/cxl/passthrough.h
> 
> This file becomes private to drivers/vfio if it moves.
> 
> Otherwise it needs s/passthrough/vfio/ as mentioned earlier.

Agreed, I will update this in v4.

> 
> > @@ -0,0 +1,121 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/* Copyright(c) 2026 NVIDIA Corporation. All rights reserved.
> > + *
> > + * CXL register virtualization helpers for vfio-pci Type-2
> passthrough.
> > + *
> > + * See Documentation/driver-api/vfio-pci-cxl.rst for the ownership
> > + * contract.  In short: cxl-core owns the per-device DVSEC body, HDM
> > + * Decoder block, and CM cap-array shadows; vfio-pci is a transport
> > + * that forwards guest reads and writes through the helpers below.
> > + *
> > + * The helpers are not a generic emulation framework.  Each register
> > + * is hand-coded against CXL r4.0 §8.1.3 and §8.2.4.20.  Adding a new
> > + * field is "add a case", not "add a mode".
> > + */
> > +#ifndef __CXL_PASSTHROUGH_H__
> > +#define __CXL_PASSTHROUGH_H__
> > +
> > +#include <linux/types.h>
> > +
> > +struct cxl_dev_state;
> > +struct cxl_passthrough;
> > +struct device;
> > +
> > +/**
> > + * devm_cxl_passthrough_create - snapshot a Type-2 device's DVSEC +
> HDM +
> > + * CM cap-array shadows and return the opaque handle the rw helpers
> > + * operate on.
> > + *
> > + * @dev: device whose devres lifetime bounds the returned handle.
> > + * @cxlds: CXL device state with cxlds->cxl_dvsec populated and
> > + *      cxlds->reg_map.resource and cxlds->reg_map.max_size
> describing
> > + *      the component register block.  cxlds->reg_map.base is NOT
> > + *      required; cxl_pci_setup_regs() releases its short-lived
> > + *      ioremap before returning, so this helper takes a local
> > + *      bind-time ioremap against cxlds->reg_map.resource for the
> > + *      duration of the snapshot.
> 
> More out of place cxl_pci_setup_regs() documentation...

okay, I will resolve this part.

> 
> > + *
> > + * On success the returned handle is bound to @dev's devres so unwind
> > + * happens automatically when @dev is unbound.  The handle must not
> be
> > + * freed by the caller.
> > + *
> > + * Return: a valid &struct cxl_passthrough on success, ERR_PTR(-
> errno)
> > + * on failure.
> > + */
> > +struct cxl_passthrough *
> > +devm_cxl_passthrough_create(struct device *dev, struct cxl_dev_state
> *cxlds);
> > +
> > +/**
> > + * cxl_passthrough_dvsec_rw - read or write the CXL Device DVSEC body
> shadow.
> > + *
> > + * @p: handle from devm_cxl_passthrough_create().
> > + * @off: byte offset from the start of the DVSEC capability.  Must be
> > + *    >= PCI_DVSEC_CXL_CAP and (off + sz) must lie inside the DVSEC.
> > + *    Accesses to the PCI ext-cap header bytes (off <
> PCI_DVSEC_CXL_CAP)
> > + *    are the caller's responsibility; they belong on the generic
> > + *    perm-bits path, not here.
> > + * @val: pointer to a u32 holding the read result or the write value.
> > + *    The low @sz bytes of *val are the payload; upper bytes ignored
> > + *    for writes and zero for reads.
> > + * @sz: 1, 2, or 4.  Other values return -EINVAL.
> > + * @write: false for read, true for write.
> > + *
> > + * Reads serve from the shadow.  Writes update the shadow per the
> spec
> > + * attribute mode for the addressed field (LOCK is RWO,
> CONTROL/CONTROL2
> > + * are RWL gated on CONFIG_LOCK, STATUS/STATUS2 are RW1C, RANGE1/2
> are
> > + * HwInit, Reserved/RsvdZ silently consumed).
> > + *
> > + * Known limitation: a 4-byte write whose @off straddles a 16-bit
> DVSEC
> > + * field boundary (CONTROL/STATUS at 0x0c/0x0e, CONTROL2/STATUS2 at
> > + * 0x10/0x12) applies only the field containing the first byte of the
> > + * access; the adjacent 16-bit field is not updated by the same
> write.
> > + * Standard CXL register-access patterns issue separate 2-byte
> accesses
> > + * to CONTROL, STATUS, CONTROL2 and STATUS2, so this corner case is
> > + * documented rather than handled.
> > + *
> > + * Return: 0 on success; -EINVAL on out-of-range or bad size.
> > + */
> > +int cxl_passthrough_dvsec_rw(struct cxl_passthrough *p, u32 off, u32
> *val,
> > +                          size_t sz, bool write);
> > +
> > +/**
> > + * cxl_passthrough_hdm_rw - read or write the HDM Decoder block
> shadow.
> > + *
> > + * @p: handle from devm_cxl_passthrough_create().
> > + * @off: byte offset from the HDM block base; must be 4-byte aligned
> and
> > + *    (off + 4) <= hdm_reg_size.  Sub-dword access is not supported
> on
> > + *    HDM registers per CXL r4.0 §8.2.4.
> > + * @val: pointer to a u32 holding the read result or the write value.
> > + * @write: false for read, true for write.
> > + *
> > + * Reads serve from the shadow.  Writes implement the per-decoder
> > + * COMMIT/COMMITTED handshake (CTRL) and the RWL gating on BASE/SIZE
> > + * imposed by COMMITTED|LOCK_ON_COMMIT.  GLOBAL_CTRL is RW; the cap
> > + * header is HwInit (writes dropped); other offsets in the per-
> decoder
> > + * stride are RW shadow.
> > + *
> > + * Return: 0 on success; -EINVAL on misalignment or out-of-range.
> > + */
> > +int cxl_passthrough_hdm_rw(struct cxl_passthrough *p, u32 off, u32
> *val,
> > +                        bool write);
> > +
> > +/**
> > + * cxl_passthrough_cm_rw - read or write the CXL.cache/mem cap-array
> snapshot.
> > + *
> > + * @p: handle from devm_cxl_passthrough_create().
> > + * @off: byte offset from CXL_CM_OFFSET (the start of the CM cap-
> array
> > + *    header in the component register block); must be 4-byte aligned
> > + *    and (off + 4) <= cm_snapshot_size.
> > + * @val: pointer to a u32 holding the read result; ignored on write.
> > + * @write: false for read.  Writes to the cap-array are silently
> dropped
> > + *      (the array headers are RO per CXL r4.0 §8.2.4); the @write
> > + *      parameter is present only to keep the API symmetric with the
> > + *      other rw helpers and to make the drop policy explicit at the
> > + *      call site.
> > + *
> > + * Return: 0 on success; -EINVAL on misalignment or out-of-range.
> > + */
> > +int cxl_passthrough_cm_rw(struct cxl_passthrough *p, u32 off, u32
> *val,
> > +                       bool write);
> > +
> > +#endif /* __CXL_PASSTHROUGH_H__ */
> > --
> > 2.25.1
> 


^ permalink raw reply

* RE: [PATCH v3 07/11] vfio/pci: Add CONFIG_VFIO_PCI_CXL with bind-time CXL Type-2 acquisition
From: Manish Honap @ 2026-07-13 16:48 UTC (permalink / raw)
  To: Alex Williamson
  Cc: djbw@kernel.org, jgg@ziepe.ca, jic23@kernel.org,
	dave.jiang@intel.com, Ankit Agrawal,
	alejandro.lucero-palau@amd.com, alison.schofield@intel.com,
	dave@stgolabs.net, dmatlack@google.com, gourry@gourry.net,
	ira.weiny@intel.com, Neo Jia, Krishnakant Jaju, Vikram Sethi,
	Zhi Wang, kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <20260710162316.29cf8107@shazbot.org>



> -----Original Message-----
> From: Alex Williamson <alex@shazbot.org>
> Sent: 11 July 2026 03:53
> To: Manish Honap <mhonap@nvidia.com>
> Cc: djbw@kernel.org; jgg@ziepe.ca; jic23@kernel.org;
> dave.jiang@intel.com; Ankit Agrawal <ankita@nvidia.com>;
> alejandro.lucero-palau@amd.com; alison.schofield@intel.com;
> dave@stgolabs.net; dmatlack@google.com; gourry@gourry.net;
> ira.weiny@intel.com; Neo Jia <cjia@nvidia.com>; Krishnakant Jaju
> <kjaju@nvidia.com>; Vikram Sethi <vsethi@nvidia.com>; Zhi Wang
> <zhiw@nvidia.com>; kvm@vger.kernel.org; linux-cxl@vger.kernel.org;
> linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org; linux-
> kselftest@vger.kernel.org; alex@shazbot.org
> Subject: Re: [PATCH v3 07/11] vfio/pci: Add CONFIG_VFIO_PCI_CXL with
> bind-time CXL Type-2 acquisition
> 
> External email: Use caution opening links or attachments
> 
> 
> On Thu, 25 Jun 2026 22:24:03 +0530
> <mhonap@nvidia.com> wrote:
> 
> > From: Manish Honap <mhonap@nvidia.com>
> >
> > Wire vfio-pci-core to acquire CXL Type-2 device state at PCI bind and
> > release it at PCI unbind, mirroring the existing vfio_pci_zdev_*
> > integration model.
> 
> I don't follow, zpci has the following matching hooks:
> 
>  - vfio_pci_zdev_open_device
>  - vfio_pci_zdev_close_device
> 
> Plus it also has:
> 
>  - vfio_pci_info_zdev_add_caps
> 
> What about those suggest "zdev state" is acquired at bind and released
> on unbind?
> 
> >  Four lifecycle hooks are introduced — vfio_pci_cxl_acquire / _release
> > / _open / _close — with !-config stubs that return -ENODEV / 0 / 0 /
> > no-op respectively so vfio-pci behaviour is unchanged when
> > CONFIG_VFIO_PCI_CXL=n.
> >
> > vfio_pci_cxl_acquire() implements the bind sequence:
> >
> >   - pcie_is_cxl() and CXL Device DVSEC discovery (-ENODEV if absent
> >     or if MEM_CAPABLE clear — caller falls back to plain vfio-pci)
> >   - devm_cxl_dev_state_create() with struct vfio_pci_cxl_state
> >     embedding cxl_dev_state at offset 0 (required by the 7-arg
> >     macro's static_assert in include/cxl/cxl.h)
> >   - pci_enable_device_mem(), cxl_pci_setup_regs(), cxl_get_hdm_info()
> >     (rejecting hdm_count != 1), cxl_regblock_get_bar_info(),
> >     cxl_await_range_active()
> 
> The cover letter claims otherwise:
> 
>   "- cxl_await_range_active stays in cxl-core probe; not exported, vfio
>   does not call it."
> 
> It's exported in 2/ and called below.
> 
> >   - devm_cxl_passthrough_create() to snapshot the DVSEC body, HDM
> >     block, and CM cap-array shadows owned by cxl-core
> >   - pci_disable_device() — clears PCI_COMMAND_MASTER but NOT
> >     PCI_COMMAND_MEMORY, so cxl-core MMIO accesses from the next step
> >     still succeed
> >   - devm_cxl_probe_mem() to register the cxl_memdev, enumerate the
> >     endpoint port, and attach the firmware-committed autoregion
> >   - request_mem_region() + memremap_wb() of the autoregion's HPA so
> >     the HDM VFIO region can serve guest accesses through it
> 
> How does this interact with:
> 
>  - The device making use of low power states while idle
>  - Repeatability per tenant instance
>  - Protection of tenant data per instance
> 
> The culmination of all of these, plus the basic housekeeping of
> maintaining the lightest touch on the device, including keeping the
> device in the minimum state of functionality outside of an actual user,
> is why I would expect to perform acquire/release as part of open/close.

The cover letter description is wrong. During my earlier thought process,
creating a region during probe seemed a correct option as any later requirement
where region needs to be already created at probe emerged, we will have easier
way to handle it. I will give some more thought to update v4 to acquire
CXL state in open_device() and release it in close_device(), matching zpci.

> 
> Could a low power transition invalidate the state established by
> acquire, leading to the issue Richard encountered?

okay, I will take care of this part. Since vfio-cxl-reset support was not
present in this series, I was testing with reset mechanism commented out
in vfio layer. I will incorporate reset support in next series and test this
case before posting the v4.

> 
> Also, on the direct calls to cxl functions, I thought one of our goals
> was to avoid vfio-pci statically pulling in CXL module dependencies.
> To achieve that, it seems like at some point we need to detect that we
> have a CXL device (pcie_is_cxl(pdev)), do a request_module() to load
> vfio-cxl, where the init function would register callback ops with vfio-
> pci-core and each dependent device would acquire a reference to the
> vfio-cxl module.
> 

okay, I will add a separate vfio-cxl.ko. The user will never mention vfio-cxl.
vfio-cxl.ko just needs to be loaded before the VFIO fd is
opened. Rest of the sequence will be as suggested: vfio-pci-core sees
pcie_is_cxl(pdev) == true, do a request_module for vfio-cxl...

If vfio-cxl.ko is not loaded, the device opens as a plain PCI device with
no CXL capabilities.

So, the "enlighten vfio-pci about CXL" goal is still fully intact: the
CXL-aware code is in the vfio tree (drivers/vfio/pci/cxl/vfio.c), owned
by vfio but invoked by vfio-pci-core. The device binding model will still
be same as earlier (bind to vfio-pci)

> > diff --git a/include/linux/vfio_pci_core.h
> > b/include/linux/vfio_pci_core.h index 89165b769e5c..541c1911e090
> > 100644
> > --- a/include/linux/vfio_pci_core.h
> > +++ b/include/linux/vfio_pci_core.h
> > @@ -142,6 +142,13 @@ struct vfio_pci_core_device {
> >       struct notifier_block   nb;
> >       struct rw_semaphore     memory_lock;
> >       struct list_head        dmabufs;
> > +     /*
> > +      * Opaque pointer to struct vfio_pci_cxl_state (defined in
> > +      * drivers/vfio/pci/cxl/vfio_cxl_priv.h).  Set by
> > +      * vfio_pci_cxl_acquire() at PCI bind; NULL on non-CXL devices
> > +      * and when CONFIG_VFIO_PCI_CXL=n.
> > +      */
> > +     void                    *cxl;
> 
> Use a forward declaration rather than void, that avoids half your
> comment.  The remainder of the comment is just explaining the obvious
> parts of the code, unnecessary.  Thanks,

okay; I will rectify this.

> 
> Alex

^ permalink raw reply

* RE: [PATCH v3 08/11] vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping shim
From: Manish Honap @ 2026-07-13 16:48 UTC (permalink / raw)
  To: Dan Williams (nvidia), alex@shazbot.org, jgg@ziepe.ca,
	jic23@kernel.org, dave.jiang@intel.com, Ankit Agrawal,
	alejandro.lucero-palau@amd.com, alison.schofield@intel.com,
	dave@stgolabs.net, dmatlack@google.com, gourry@gourry.net,
	ira.weiny@intel.com
  Cc: Neo Jia, Krishnakant Jaju, Vikram Sethi, Zhi Wang,
	kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <6a516d7e2216f_3cfbb510079@djbw-dev.notmuch>



> -----Original Message-----
> From: Dan Williams (nvidia) <djbw@kernel.org>
> Sent: 11 July 2026 03:39
> To: Manish Honap <mhonap@nvidia.com>; djbw@kernel.org; alex@shazbot.org;
> jgg@ziepe.ca; jic23@kernel.org; dave.jiang@intel.com; Ankit Agrawal
> <ankita@nvidia.com>; alejandro.lucero-palau@amd.com;
> alison.schofield@intel.com; dave@stgolabs.net; dmatlack@google.com;
> gourry@gourry.net; ira.weiny@intel.com
> Cc: Neo Jia <cjia@nvidia.com>; Krishnakant Jaju <kjaju@nvidia.com>;
> Vikram Sethi <vsethi@nvidia.com>; Zhi Wang <zhiw@nvidia.com>; Manish
> Honap <mhonap@nvidia.com>; kvm@vger.kernel.org; linux-
> cxl@vger.kernel.org; linux-doc@vger.kernel.org; linux-
> kernel@vger.kernel.org; linux-kselftest@vger.kernel.org
> Subject: Re: [PATCH v3 08/11] vfio/pci/cxl: Add HDM + COMP_REGS regions
> and DVSEC clipping shim
> 
> External email: Use caution opening links or attachments
> 
> 
> mhonap@ wrote:
> > From: Manish Honap <mhonap@nvidia.com>
> >
> > Complete the vfio-pci-core integration of CXL Type-2 device
> > passthrough by exposing two VFIO regions to userspace, wiring DVSEC
> > config-space accesses through cxl-core's register-virtualization
> > helpers, and reserving the CXL component register block from BAR mmap
> > and BAR resource claim.
> >
> > HDM region (VFIO_REGION_SUBTYPE_CXL):
> >   - mmappable view of the device's firmware-committed HPA range
> >   - mmap fault handler calls vmf_insert_pfn() from the physical HPA
> >     so the guest gets the same backing memory the host sees
> >   - pread/pwrite go through the memremap_wb() kva captured at
> >     bind time by vfio_cxl_map_hdm()
> >
> > COMP_REGS region (VFIO_REGION_SUBTYPE_CXL_COMP_REGS):
> >   - pread/pwrite only, dword-aligned (-EINVAL on misalignment)
> >   - thin transport: each dword dispatches by offset to
> >     cxl_passthrough_cm_rw() (CM cap-array snapshot) or
> >     cxl_passthrough_hdm_rw() (HDM Decoder block).  No shadow buffer
> >     on the vfio side; all per-field semantics live in cxl-core.
> >
> > DVSEC config-space access:
> >   - vfio_pci_cxl_config_boundary() clips a chunk at the CXL Device
> >     DVSEC body edge in vfio_pci_config_rw_single() so the generic
> >     perm-bits path handles the DVSEC header bytes and the CXL hook
> >     handles the body bytes.  The clipping shim is used instead of
> >     re-pointing the ecap_perms[] readfn/writefn (which would mutate
> >     a module-init static and race across multiple CXL devices).
> >   - vfio_pci_cxl_config_rw() forwards clipped accesses to
> >     cxl_passthrough_dvsec_rw(); cxl-core enforces the per-field
> >     write semantics (LOCK/RWO, CONTROL/RWL, STATUS/RW1C,
> >     RANGE1/HwInit, RANGE2/RsvdZ).
> >
> > GET_INFO / GET_REGION_INFO:
> >   - VFIO_DEVICE_INFO_CAP_CXL advertises the two region indices, the
> >     component BAR layout, and HOST_FIRMWARE_COMMITTED.
> >   - GET_REGION_INFO on the component BAR returns a sparse-mmap cap
> >     that excludes [comp_reg_offset, comp_reg_offset+comp_reg_size).
> >
> > BAR resource handling:
> >   - cxl-core holds request_mem_region() on the CXL component
> >     register sub-range from devm_cxl_probe_mem(), so vfio_pci-core's
> >     pci_request_selected_regions() on the full BAR would collide.
> >     map_bars() skips the request for the component BAR (still iomaps
> >     it; vfio holds the BAR via driver binding); disable() mirrors
> >     the asymmetric skip.
> >   - mmap of the component BAR refuses any range overlapping the CXL
> >     sub-range via vfio_pci_cxl_mmap_overlaps_comp_regs().
> >
> > vfio_pci_cxl_open() now registers both VFIO regions; close()
> > unregisters them.  Raw BAR rw redirect into the CXL sub-range is
> > intentionally not implemented: VMMs use the COMP_REGS region directly.
> 
> I jumped ahead in the review to see how passthrough.c was being used.
> 
> This patch is doing a lot which raises the risk that individual
> proposals within it are going to raise questions.
> 
> > Signed-off-by: Manish Honap <mhonap@nvidia.com>
> > ---
> >  drivers/vfio/pci/cxl/vfio_cxl_core.c | 521
> ++++++++++++++++++++++++++-
> >  drivers/vfio/pci/vfio_pci_config.c   |  31 ++
> >  drivers/vfio/pci/vfio_pci_core.c     |  44 ++-
> >  drivers/vfio/pci/vfio_pci_priv.h     |  72 ++++
> >  drivers/vfio/pci/vfio_pci_rdwr.c     |  17 +
> >  5 files changed, 679 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/vfio/pci/cxl/vfio_cxl_core.c
> > b/drivers/vfio/pci/cxl/vfio_cxl_core.c
> > index 42cd00bbe869..8a00b776d7c7 100644
> > --- a/drivers/vfio/pci/cxl/vfio_cxl_core.c
> > +++ b/drivers/vfio/pci/cxl/vfio_cxl_core.c
> > @@ -123,12 +123,24 @@ static int vfio_cxl_probe_regs(struct
> vfio_pci_cxl_state *cxl)
> >       if (rc)
> >               return rc;
> >
> > +     /*
> > +      * The CXL Component Register block is a fixed 64 KiB area (CXL
> r4.0
> > +      * §8.2.3).  cxl_pci_setup_regs() records the remaining BAR
> length
> > +      * after the regblock offset in reg_map.max_size, which is an
> upper
> > +      * bound, not the spec-defined size.  Bail if the BAR does not
> have
> > +      * room for a full component register block at the recorded
> offset,
> > +      * and publish the spec size so the UAPI, sparse-mmap exclusion,
> and
> > +      * COMP_REGS region all agree on the same window.
> > +      */
> > +     if (cxlds->reg_map.max_size < CXL_COMPONENT_REG_BLOCK_SIZE)
> > +             return -ENXIO;
> 
> This feels like a generic check that should not be vfio specific...
> 
> Indeed it is an existing check in cxl_decode_regblock() that already
> makes this assertion.

Agreed - I'll drop the duplicate and rely on cxl-core's existing
assertion in cxl_decode_regblock(), publishing the spec block size from
there rather than re-checking on the vfio side.

> 
> >       cxl->info.hdm_count               = hdm_count;
> >       cxl->info.hdm_reg_offset          = hdm_off;
> >       cxl->info.hdm_reg_size            = hdm_size;
> >       cxl->info.comp_reg_bir            = bir;
> >       cxl->info.comp_reg_offset         = bar_off;
> > -     cxl->info.comp_reg_size           = cxlds->reg_map.max_size;
> > +     cxl->info.comp_reg_size           =
> CXL_COMPONENT_REG_BLOCK_SIZE;
> >       cxl->info.host_firmware_committed = true;
> >
> >       /*
> > @@ -354,16 +366,515 @@ void vfio_pci_cxl_release(struct
> vfio_pci_core_device *vdev)
> >       vdev->cxl = NULL;
> >  }
> >
> > +static int vfio_pci_cxl_register_hdm(struct vfio_pci_core_device
> > +*vdev); static int vfio_pci_cxl_register_comp_regs(struct
> > +vfio_pci_core_device *vdev);
> > +
> >  int vfio_pci_cxl_open(struct vfio_pci_core_device *vdev)  {
> > +     struct vfio_pci_cxl_state *cxl = vdev->cxl;
> > +     int rc;
> > +
> > +     if (!cxl)
> > +             return 0;       /* plain vfio-pci device */
> > +
> > +     rc = vfio_pci_cxl_register_comp_regs(vdev);
> > +     if (rc) {
> > +             pci_warn(vdev->pdev,
> > +                      "vfio-cxl: COMP_REGS region register failed
> (%d)\n",
> > +                      rc);
> > +             return rc;
> > +     }
> > +
> > +     rc = vfio_pci_cxl_register_hdm(vdev);
> > +     if (rc) {
> > +             pci_warn(vdev->pdev,
> > +                      "vfio-cxl: HDM region register failed (%d)\n",
> rc);
> > +             /*
> > +              * COMP_REGS already registered above.  vfio core does
> not
> > +              * call close_device() when open_device() returns an
> error,
> > +              * so roll back the COMP_REGS dynamic region here to
> avoid
> > +              * a leaked half-registered open state.
> > +              */
> > +             vfio_pci_cxl_close(vdev);
> > +             return rc;
> > +     }
> > +     return 0;
> > +}
> > +
> > +void vfio_pci_cxl_close(struct vfio_pci_core_device *vdev) {
> > +     struct vfio_pci_cxl_state *cxl = vdev->cxl;
> > +     unsigned int i;
> > +
> > +     if (!cxl)
> > +             return;
> > +
> > +     for (i = vdev->num_regions; i > 0; i--) {
> > +             struct vfio_pci_region *r = &vdev->region[i - 1];
> > +
> > +             if (r->data != cxl)
> > +                     break;
> > +             if (r->ops->release)
> > +                     r->ops->release(vdev, r);
> > +             vdev->num_regions--;
> > +     }
> > +}
> > +
> > +/* ------------------------------------------------------------------
> */
> > +/* HDM region: mmappable view of the device's HPA range
> */
> > +/* ------------------------------------------------------------------
> > +*/
> > +
> > +static vm_fault_t hdm_region_fault(struct vm_fault *vmf) {
> > +     struct vm_area_struct *vma = vmf->vma;
> > +     struct vfio_pci_cxl_state *cxl = vma->vm_private_data;
> > +     unsigned long off = (vmf->address - vma->vm_start) +
> > +                         (vma->vm_pgoff << PAGE_SHIFT);
> > +     phys_addr_t pa;
> > +
> > +     if (!cxl || !cxl->info.hpa_size)
> > +             return VM_FAULT_SIGBUS;
> > +     if (off >= cxl->info.hpa_size)
> > +             return VM_FAULT_SIGBUS;
> > +
> > +     pa = cxl->info.hpa_base + off;
> > +     return vmf_insert_pfn(vma, vmf->address, PHYS_PFN(pa));
> 
> It seems unfortunate that this reimplements vfio_pci_mmap_ops without
> huge mapping support. If CXL is going to be a first class citizen in
> vfio then why not extend vfio_pci_core_device with the concept that
> devices can have HDM ranges, or some scheme to address large mappings
> from day one.
> 
> [..]
> > diff --git a/drivers/vfio/pci/vfio_pci_core.c
> > b/drivers/vfio/pci/vfio_pci_core.c
> > index 05ab4ae59157..2d2dae278d1e 100644
> > --- a/drivers/vfio/pci/vfio_pci_core.c
> > +++ b/drivers/vfio/pci/vfio_pci_core.c
> > @@ -501,6 +501,23 @@ static void vfio_pci_core_map_bars(struct
> vfio_pci_core_device *vdev)
> >               if (!pci_resource_len(pdev, i))
> >                       continue;
> >
> > +             /*
> > +              * cxl-core already holds request_mem_region() on the
> CXL
> > +              * component register sub-range of this BAR.  Skip the
> > +              * full-BAR request so we do not collide with that
> > +              * sub-region; vfio still owns the BAR via the driver
> > +              * binding and the iomap below succeeds without a region
> > +              * claim.
> > +              */
> 
> Rather than working around a problem in the CXL core why not fix it?
> This is the second time someone has run across a conflict with
> devm_cxl_iomap_block() when trying to reuse CXL code.
> 
> devm_cxl_iomap_block() was a response to folks wanting /dev/mem access
> to CXL BAR space. When VFIO owns the whole BAR it should be blocking
> /dev/mem access to enforce going through VFIO.
> 
> I think this looks like a flag on cxl_register_map that only cxl_pci
> sets to indicate the legacy special mode of doing piecemeal resource
> requests of just the component registers. External CXL drivers likely
> just want to own the whole BAR and not workaround an internal detail
> like this.

okay, I will check this part and handle this in v4 as suggested.

^ permalink raw reply

* RE: [PATCH v3 08/11] vfio/pci/cxl: Add HDM + COMP_REGS regions and DVSEC clipping shim
From: Manish Honap @ 2026-07-13 16:48 UTC (permalink / raw)
  To: Alex Williamson
  Cc: djbw@kernel.org, jgg@ziepe.ca, jic23@kernel.org,
	dave.jiang@intel.com, Ankit Agrawal,
	alejandro.lucero-palau@amd.com, alison.schofield@intel.com,
	dave@stgolabs.net, dmatlack@google.com, gourry@gourry.net,
	ira.weiny@intel.com, Neo Jia, Krishnakant Jaju, Vikram Sethi,
	Zhi Wang, kvm@vger.kernel.org, linux-cxl@vger.kernel.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, Manish Honap
In-Reply-To: <20260710162309.2c257883@shazbot.org>



> -----Original Message-----
> From: Alex Williamson <alex@shazbot.org>
> Sent: 11 July 2026 03:53
> To: Manish Honap <mhonap@nvidia.com>
> Cc: djbw@kernel.org; jgg@ziepe.ca; jic23@kernel.org;
> dave.jiang@intel.com; Ankit Agrawal <ankita@nvidia.com>;
> alejandro.lucero-palau@amd.com; alison.schofield@intel.com;
> dave@stgolabs.net; dmatlack@google.com; gourry@gourry.net;
> ira.weiny@intel.com; Neo Jia <cjia@nvidia.com>; Krishnakant Jaju
> <kjaju@nvidia.com>; Vikram Sethi <vsethi@nvidia.com>; Zhi Wang
> <zhiw@nvidia.com>; kvm@vger.kernel.org; linux-cxl@vger.kernel.org;
> linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org; linux-
> kselftest@vger.kernel.org; alex@shazbot.org
> Subject: Re: [PATCH v3 08/11] vfio/pci/cxl: Add HDM + COMP_REGS regions
> and DVSEC clipping shim
> 
> External email: Use caution opening links or attachments
> 
> 
> On Thu, 25 Jun 2026 22:24:04 +0530
> <mhonap@nvidia.com> wrote:
> > diff --git a/drivers/vfio/pci/vfio_pci_config.c
> > b/drivers/vfio/pci/vfio_pci_config.c
> > index a10ed733f0e3..b9f30a33515a 100644
> > --- a/drivers/vfio/pci/vfio_pci_config.c
> > +++ b/drivers/vfio/pci/vfio_pci_config.c
> > @@ -1898,8 +1898,15 @@ ssize_t vfio_pci_config_rw_single(struct
> vfio_pci_core_device *vdev,
> >       /*
> >        * Chop accesses into aligned chunks containing no more than a
> >        * single capability.  Caller increments to the next chunk.
> > +      *
> > +      * For CXL Type-2 devices also clip at the CXL Device DVSEC body
> > +      * boundary so the generic perm-bits path handles the DVSEC
> > +      * header bytes and the CXL hook handles the body bytes; without
> > +      * this clip a 32-bit access at dvsec + 0x08 would span the
> > +      * generic Header2 word and the CXL CAPABILITY word.
> >        */
> >       count = min(count, vfio_pci_cap_remaining_dword(vdev, *ppos));
> > +     count = min(count, vfio_pci_cxl_config_boundary(vdev, *ppos));
> >       if (count >= 4 && !(*ppos % 4))
> >               count = 4;
> >       else if (count >= 2 && !(*ppos % 2)) @@ -1909,6 +1916,30 @@
> > ssize_t vfio_pci_config_rw_single(struct vfio_pci_core_device *vdev,
> >
> >       ret = count;
> >
> > +     /*
> > +      * Give the CXL Type-2 hook first claim on this access: if the
> > +      * range lies inside the CXL Device DVSEC body, forward it to
> > +      * cxl-core's register-virtualization helpers instead of the
> > +      * standard perm-bits path.  -ENOENT means "not for me; use the
> > +      * default path"; any other negative value is a hard error.
> > +      */
> > +     if (vdev->cxl) {
> > +             __le32 le_val = 0;
> > +             ssize_t cxl_ret;
> > +
> > +             if (iswrite && copy_from_user(&le_val, buf, count))
> > +                     return -EFAULT;
> > +             cxl_ret = vfio_pci_cxl_config_rw(vdev, *ppos, count,
> &le_val,
> > +                                              iswrite);
> > +             if (cxl_ret >= 0) {
> > +                     if (!iswrite && copy_to_user(buf, &le_val,
> count))
> > +                             return -EFAULT;
> > +                     return cxl_ret;
> > +             }
> > +             if (cxl_ret != -ENOENT)
> > +                     return cxl_ret;
> > +     }
> > +
> 
> I think the solution here is just to set the .readfn and .writefn for
> PCI_EXT_CAP_ID_DVSEC to dvsec specific handlers, rather than the raw
> write and direct read handlers.  The new handlers would detect whether
> the reference is to the CXL DVSEC body, possibly via ranges stored in
> vdev->cxl, and either call through to CXL handlers via cxl_ops
> (previously suggested), or fall through to the raw/direct handlers.

okay, I will have handling for this in v4.

> 
> >       cap_id = vdev->pci_config_map[*ppos];
> >
> >       if (cap_id == PCI_CAP_ID_INVALID) { diff --git
> > a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
> > index 05ab4ae59157..2d2dae278d1e 100644
> > --- a/drivers/vfio/pci/vfio_pci_core.c
> > +++ b/drivers/vfio/pci/vfio_pci_core.c
> > @@ -501,6 +501,23 @@ static void vfio_pci_core_map_bars(struct
> vfio_pci_core_device *vdev)
> >               if (!pci_resource_len(pdev, i))
> >                       continue;
> >
> > +             /*
> > +              * cxl-core already holds request_mem_region() on the
> CXL
> > +              * component register sub-range of this BAR.  Skip the
> > +              * full-BAR request so we do not collide with that
> > +              * sub-region; vfio still owns the BAR via the driver
> > +              * binding and the iomap below succeeds without a region
> > +              * claim.
> > +              */
> > +             if (vdev->cxl && bar ==
> vfio_pci_cxl_get_component_reg_bar(vdev)) {
> > +                     vdev->barmap[bar] = pci_iomap(pdev, bar, 0);
> > +                     if (!vdev->barmap[bar]) {
> > +                             pci_dbg(pdev, "Failed to iomap region
> %d\n", bar);
> > +                             vdev->barmap[bar] = IOMEM_ERR_PTR(-
> ENOMEM);
> > +                     }
> > +                     continue;
> > +             }
> > +
> >               if (pci_request_selected_regions(pdev, 1 << bar,
> "vfio")) {
> >                       pci_dbg(pdev, "Failed to reserve region %d\n",
> bar);
> >                       vdev->barmap[bar] = IOMEM_ERR_PTR(-EBUSY); @@
> > -701,7 +718,10 @@ void vfio_pci_core_disable(struct
> vfio_pci_core_device *vdev)
> >               if (IS_ERR_OR_NULL(vdev->barmap[bar]))
> >                       continue;
> >               pci_iounmap(pdev, vdev->barmap[bar]);
> > -             pci_release_selected_regions(pdev, 1 << bar);
> > +             /* Mirror the asymmetric setup-time skip in map_bars().
> */
> > +             if (!(vdev->cxl &&
> > +                   i == vfio_pci_cxl_get_component_reg_bar(vdev)))
> > +                     pci_release_selected_regions(pdev, 1 << bar);
> 
> It would be much less ugly to create
> vfio_pci_{request,release}_selected_region() wrappers that mask whether
> the region is actually requested or released than to disrupt the code
> flow like this.  Likewise below, think about creating wrappers that do
> the right thing for cxl and are no-ops otherwise.  For example, embed
> the vdev->cxl test into the function to cleanup the callers.  Thanks,
> 

Agreed. I will add helper routines for this as suggested.

> Alex
> 
> >               vdev->barmap[bar] = NULL;
> >       }
> >
> > @@ -1051,6 +1071,16 @@ static int vfio_pci_ioctl_get_info(struct
> vfio_pci_core_device *vdev,
> >       info.num_regions = VFIO_PCI_NUM_REGIONS + vdev->num_regions;
> >       info.num_irqs = VFIO_PCI_NUM_IRQS;
> >
> > +     if (vdev->cxl) {
> > +             ret = vfio_pci_cxl_get_info(vdev, &caps);
> > +             if (ret) {
> > +                     pci_warn(vdev->pdev,
> > +                              "Failed to add CXL info capability\n");
> > +                     return ret;
> > +             }
> > +             info.flags |= VFIO_DEVICE_FLAGS_CXL;
> > +     }
> > +
> >       ret = vfio_pci_info_zdev_add_caps(vdev, &caps);
> >       if (ret && ret != -ENODEV) {
> >               pci_warn(vdev->pdev,
> > @@ -1093,6 +1123,12 @@ int vfio_pci_ioctl_get_region_info(struct
> vfio_device *core_vdev,
> >       struct pci_dev *pdev = vdev->pdev;
> >       int i, ret;
> >
> > +     if (vdev->cxl) {
> > +             ret = vfio_pci_cxl_get_region_info(vdev, info, caps);
> > +             if (ret != -ENOTTY)
> > +                     return ret;
> > +     }
> > +
> >       switch (info->index) {
> >       case VFIO_PCI_CONFIG_REGION_INDEX:
> >               info->offset = VFIO_PCI_INDEX_TO_OFFSET(info->index);

^ permalink raw reply

* What's cooking in zh_CN (Jul 2026)
From: Weijie Yuan @ 2026-07-13 16:49 UTC (permalink / raw)
  To: linux-doc
  Cc: Alex Shi, Yanteng Si, Dongliang Mu, Ben Guo, Gary Guo, Yan Zhu,
	Doehyun Baek, Jiandong Qiu, chengyaqiang

Hi all,

Since I made many noise these days on the list, which took up a lot of
maintainers' time. This email summarizes the patches for zh_CN that are
currently pending on the mailing list.

-----------------------------------------------------------------------

* Ben Guo (2026-07-13) 4 commits
  [PATCH v2 0/4] docs/zh_CN: update rust documentation translations
  [PATCH v2 1/4] docs/zh_CN: Update rust/quick-start.rst translation
  [PATCH v2 2/4] docs/zh_CN: Update rust/general-information.rst translation
  [PATCH v2 3/4] docs/zh_CN: Update rust/arch-support.rst translation
  [PATCH v2 4/4] docs/zh_CN: Update rust/testing.rst translation

  Reviewed by Dongliang, a part needs to be revised. Expecting a reroll.

  cf. https://lore.kernel.org/linux-doc/17094968-1385-4dba-aae8-5d93a2aaf59e@hust.edu.cn/
  source: https://lore.kernel.org/linux-doc/cover.1783905132.git.ben.guo@openatom.club/

* Doehyun Baek (2026-07-08) 7 commits
  [PATCH v6 0/7] docs/zh_CN: update DAMON translations
  [PATCH v6 1/7] docs/zh_CN: update DAMON design translation
  [PATCH v6 2/7] docs/zh_CN: add DAMON_STAT usage translation
  [PATCH v6 3/7] docs/zh_CN: update DAMON index translation
  [PATCH v6 4/7] docs/zh_CN: update DAMON start translation
  [PATCH v6 5/7] docs/zh_CN: update DAMON usage translation
  [PATCH v6 6/7] docs/zh_CN: update DAMON reclaim translation
  [PATCH v6 7/7] docs/zh_CN: update DAMON LRU sort translation

  Needs review.

  source: https://lore.kernel.org/linux-doc/20260708073246.1652828-1-doehyunbaek@gmail.com/

* Jiandong Qiu 2026-07-06 2 commits
  [PATCH v3 0/2] docs/zh_CN: update translation of doc-guide/sphinx.rst
  [PATCH v3 1/2] docs/zh_CN: add process/changes.rst translation
  [PATCH v3 2/2] docs/zh_CN: update sphinx.rst translation

  Waiting for response(s) to review comment(s). & Needs review.

  cf. https://lore.kernel.org/linux-doc/ak1SG5mw7y2UZrvR@wyuan.org/
  source: https://lore.kernel.org/linux-doc/20260706151358.2103703-1-qiujiandong1998@gmail.com/

* Yan Zhu (2026-06-12) 10 commits
  [not found] <cover.1781105672.git.zhuyan2015@qq.com>
  [PATCH 01/10] docs/zh_CN: add LSM/index Chinese translation
  [PATCH 02/10] docs/zh_CN: add LSM/apparmor Chinese translation
  [PATCH 03/10] docs/zh_CN: add LSM/LoadPin Chinese translation
  [PATCH 04/10] docs/zh_CN: add LSM/SELinux Chinese translation
  [PATCH 05/10] docs/zh_CN: add LSM/Smack Chinese translation
  [PATCH 06/10] docs/zh_CN: add LSM/tomoyo Chinese translation
  [PATCH 07/10] docs/zh_CN: add LSM/Yama Chinese translation
  [PATCH 08/10] docs/zh_CN: add LSM/SafeSetID Chinese translation
  [PATCH 09/10] docs/zh_CN: add LSM/ipe Chinese translation
  [PATCH 10/10] docs/zh_CN: add LSM/landlock Chinese translation

  Needs review.

  source: https://lore.kernel.org/linux-doc/tencent_7080BF6BB8F05936649DDC091FFD8C45210A@qq.com/
  Note: cover letter missing on lore archive.

* chengyaqiang (2026-05-22) 1 commit
  [PATCH] docs/zh_CN: fix KASAN SW_TAGS mode description

  Reviewed by Dongliang and Zenghui, will merge to docs-next @alex ?

  source: https://lore.kernel.org/linux-doc/20260522075735.2022734-1-chengyaqiang@chengyaqiang.com/

* Haoyang Liu (2026-03-05) 1 commit
  [PATCH] docs/zh_CN: fix an inconsistent statement in dev-tools/testing-overview

  Expecting a reroll.

  cf. https://lore.kernel.org/linux-doc/29bd0dbc-c6f9-43ce-b95f-4e787e3fe9c3@gmail.com/
  source: https://lore.kernel.org/linux-doc/20260305192048.16405-1-tttturtleruss@gmail.com/

-----------------------------------------------------------------------

Okay, I have checked the 200 most recent messages on the mailing list,
going back to 15:09 UTC on February 25, 2026. If I have missed anything,
or I made a mistake somewhere, please let me know.

As you may have noticed, I borrowed (stole) this idea from Junio C
Hamano. Sending this kind of message, somewhat like a weekly status
report, not only helps maintainers keep track of outstanding work, but
also lets contributors know the current status of their patches.

More importantly, it gives newcomers an overview of the current state of
the project. New contributors can begin not only by submitting patches,
but also by reviewing patches already posted to the mailing list,
thereby learning how our workflow operates. This may also help reduce
the review burden on our friendly maintainers.

I would like to try this kind of periodic report as an experimental
effort, with its frequency adjusted according to the size of the patch
backlog and the level of activity on the mailing list. What do you
think? Please feel free to make comments.

By the way, I borrowed the subject line directly from Git's "What's
cooking in git.git". Does anyone have a better suggestion for the name? ;-)

Thanks,
Weijie

^ permalink raw reply


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