* Re: [PATCH v2 00/12] arm64: dts: imx8mp: Correct PAD settings for PMIC_nINT
From: Frank Li @ 2026-03-27 14:32 UTC (permalink / raw)
To: Peng Fan (OSS)
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Laurent Pinchart,
Shawn Guo, Daniel Scally, Marco Felsch, Gilles Talis,
Viorel Suman, Shengjiu Wang, Jagan Teki, Manoj Sai, Matteo Lisi,
Ray Chang, Richard Hu, Heiko Schocher, Martyn Welch, Josua Mayer,
Goran Rađenović, Börge Strümpfel,
Christoph Niedermaier, Marek Vasut, devicetree, imx,
linux-arm-kernel, linux-kernel, kernel, Peng Fan, Kieran Bingham
In-Reply-To: <20260326-imx8mp-dts-fix-v2-v2-0-62c4ce727448@nxp.com>
On Thu, Mar 26, 2026 at 03:28:04PM +0800, Peng Fan (OSS) wrote:
> As reported in [1], there is interrupt storm for i.MX8MP DEBIX Model A.
> Per schematic, there is no on board PULL-UP resistors for GPIO1_IO03,
> so need to set PAD PUE and PU together to make pull up work properly.
>
> DEBIX Model SOM also has same issue as reported in [2].
>
> I gave a check on current i.MX8MP based boards, most boards have wrong
> PAD settings with PMIC_nINT. It is low level triggered interrupt.
> many boards only set PU, but PUE not set, so pull up not work properly.
>
> Patch 1 and 2 are to fix issue that confirmed by Laurent and Kieran.
>
> I checked AB2 and NAVQ schematic, so these two boards are also having
> same issue.
>
> For other boards, I not able to find any public schematics. For per
> the DT settings(interrupt is configured LOW LEVEL trigger), so PMIC_nINT
> should be configured as PULL UP, per NXP reference design, there is no
> on-board resistors for PMIC_nINT, it counts on SoC internal PULL. So I think
> these boards are also having issues. But I use phase "there might be" in
> commit log.
>
> The last two patches, I think the PAD settings are wrong, but not sure
> they have interrupt storm issues, so just correct the settings.
>
> For imx8mp-skov-reva.dtsi, I am not sure whether it needs same fix, so
> not touch it.
>
> [1] https://lore.kernel.org/all/20260323105858.GA2185714@killaraus.ideasonboard.com/
> [2] https://lore.kernel.org/all/20260324194353.GB2352505@killaraus.ideasonboard.com/
>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
> Changes in V2:
> - Fix more boards
> - Drop preceding zero
> - Link to v1: https://lore.kernel.org/all/20260324-imx8mp-dts-fix-v1-1-df0eb2f62543@nxp.com/
>
> ---
> Peng Fan (12):
> arm64: dts: imx8mp-debix-model-a: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-debix-som-a: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-navqp: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-ab2: Correct PAD settings for PMIC_nINT
This one squash to 7adad1a52c420 ("arm64: dts: imx8mp-ab2: add support for NXP i.MX8MP audio board (version 2)")
because it is still in my tree.
> arm64: dts: imx8mp-icore-mx8mp: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-edm-g: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-aristainetos3a-som-v1: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-nitrogen-som: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-sr-som: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-ultra-mach-sbc: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-dhcom-som: Correct PAD settings for PMIC_nINT
> arm64: dts: imx8mp-data-modul-edm-sbc: Correct PAD settings for PMIC_nINT
Other apply to 7.0 fixes branch. Thanks
Frank
>
> arch/arm64/boot/dts/freescale/imx8mp-ab2.dts | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-aristainetos3a-som-v1.dtsi | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-debix-model-a.dts | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-debix-som-a-bmb-08.dts | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-debix-som-a.dtsi | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-edm-g.dtsi | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-icore-mx8mp.dtsi | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-navqp.dts | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-nitrogen-som.dtsi | 2 +-
> arch/arm64/boot/dts/freescale/imx8mp-sr-som.dtsi | 4 ++--
> arch/arm64/boot/dts/freescale/imx8mp-ultra-mach-sbc.dts | 4 ++--
> 13 files changed, 15 insertions(+), 15 deletions(-)
> ---
> base-commit: 66ba480978ce390e631e870b740a3406e3eb6b01
> change-id: 20260326-imx8mp-dts-fix-v2-89ede7320c6a
>
> Best regards,
> --
> Peng Fan <peng.fan@nxp.com>
>
^ permalink raw reply
* Re: [RFT PATCH v3] ARM: omap1: enable real software node lookup of GPIOs on Nokia 770
From: Bartosz Golaszewski @ 2026-03-27 14:22 UTC (permalink / raw)
To: Aaro Koskinen
Cc: Janusz Krzysztofik, Arnd Bergmann, Bartosz Golaszewski,
Tony Lindgren, Russell King, Dmitry Torokhov, Hans de Goede,
Linux-OMAP, linux-arm-kernel, linux-kernel, Kevin Hilman
In-Reply-To: <acaOlGcGQEZHQ_mJ@darkstar.musicnaut.iki.fi>
On Fri, Mar 27, 2026 at 3:05 PM Aaro Koskinen <aaro.koskinen@iki.fi> wrote:
>
> Hi,
>
> On Thu, Mar 26, 2026 at 09:57:31AM +0100, Bartosz Golaszewski wrote:
> > On Mon, Mar 16, 2026 at 9:50 AM Bartosz Golaszewski <brgl@kernel.org> wrote:
> > > On Fri, Mar 6, 2026 at 1:31 AM Kevin Hilman <khilman@kernel.org> wrote:
> > > > Bartosz Golaszewski <brgl@kernel.org> writes:
> > > > > On Thu, Feb 12, 2026 at 12:46 PM Arnd Bergmann <arnd@kernel.org> wrote:
> > > > >> On Thu, Feb 12, 2026, at 12:25, Bartosz Golaszewski wrote:
> > > > >> > Currently the board file for Nokia 770 creates dummy software nodes not
> > > > >> > attached in any way to the actual GPIO controller devices and uses the
> > > > >> > fact that GPIOLIB matching swnode's name to the GPIO chip's label during
> > > > >> > software node lookup. This behavior is wrong and we want to remove it.
> > > > >> > To that end, we need to first convert all existing users to creating
> > > > >> > actual fwnode links.
> > > > >> >
> > > > >> > Create real software nodes for GPIO controllers on OMAP16xx and
> > > > >> > reference them from the software nodes in the nokia board file.
> > > > >> >
> > > > >> > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> > > > >>
> > > > >> Acked-by: Arnd Bergmann <arnd@arndb.de>
> > > > >
> > > > > Aaro, Janusz: Can you please pick it up for v7.1?
> > > >
> > > > I can take this via the OMAP tree once I have confirmation from
> > > > Aaro/Janusz that they've tested.
> >
> > Hi again! Any chance we could get this queued? Janusz, Aaro: any objections?
>
> Unfortunately the patch doesn't work - 770 just dies silently. This
> means that e.g. CBUS GPIOs are not working as those are needed to keep
> the device powered. I'll try to figure out how to debug this...
>
> A.
Hmm, I'm wondering if there's a race with consumers already requesting
the GPIOs after the controller device is registered but before the
software node is added. I'll send a version with software nodes being
registered first, then passes as firmware nodes to the platform device
API before the device is registered.
Bart
^ permalink raw reply
* [PATCH] MAINTAINERS: Add Rockchip keyword matching
From: Sebastian Reichel @ 2026-03-27 14:21 UTC (permalink / raw)
To: Heiko Stuebner
Cc: linux-kernel, linux-arm-kernel, linux-rockchip, Sebastian Reichel
Add keyword based matching for 'ARM/Rockchip SoC support'. This will
match rockchip, Rockchip, RockChip and ROCKCHIP separated by any
whitespace character or underscores.
The goal is to match arm64 defconfig patches, which should go through
the Rockchip tree as they right now only match the LKML and thus are
easily lost. The keyword matching is quite good for this, since it
also applies to the commit message and the config options itself might
not give any hint about being relevant for Rockchip.
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
This is not perfect (people need to write good commit messages), but
should improve the current situation quite a bit.
---
MAINTAINERS | 2 ++
1 file changed, 2 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 55af015174a5..9f036f812823 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3416,6 +3416,8 @@ F: drivers/i2c/busses/i2c-rk3x.c
F: drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
F: sound/soc/rockchip/
N: rockchip
+K: \b[Rr]ock[Cc]hip\b
+K: (?:\b|_)ROCKCHIP(?:\b|_)
ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES
M: Krzysztof Kozlowski <krzk@kernel.org>
---
base-commit: 2e930174c99bf75c71f898779f3ce777d7db6fd1
change-id: 20260327-maintainers-rockchip-keyword-a805c1523f43
Best regards,
--
Sebastian Reichel <sebastian.reichel@collabora.com>
^ permalink raw reply related
* [PATCH 2/2] arm64: dts: ti: k3-pinctrl: sort shift values numerically
From: Rasmus Villemoes @ 2026-03-27 14:15 UTC (permalink / raw)
To: Nishanth Menon, Vignesh Raghavendra, Tero Kristo
Cc: linux-arm-kernel, Rasmus Villemoes
In-Reply-To: <20260327141513.1250499-1-linux@rasmusvillemoes.dk>
The macros are easier to read when the values are sorted numerically.
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
---
arch/arm64/boot/dts/ti/k3-pinctrl.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/boot/dts/ti/k3-pinctrl.h b/arch/arm64/boot/dts/ti/k3-pinctrl.h
index bdccb153e089..4491898d8294 100644
--- a/arch/arm64/boot/dts/ti/k3-pinctrl.h
+++ b/arch/arm64/boot/dts/ti/k3-pinctrl.h
@@ -10,15 +10,15 @@
#define WKUP_LVL_EN_SHIFT (7)
#define WKUP_LVL_POL_SHIFT (8)
+#define DEBOUNCE_SHIFT (11)
#define ST_EN_SHIFT (14)
+#define FORCE_DS_EN_SHIFT (15)
#define PULLUDEN_SHIFT (16)
#define PULLTYPESEL_SHIFT (17)
#define RXACTIVE_SHIFT (18)
#define DRV_STR_SHIFT (19)
#define ISO_OVERRIDE_EN_SHIFT (22)
#define ISO_BYPASS_EN_SHIFT (23)
-#define DEBOUNCE_SHIFT (11)
-#define FORCE_DS_EN_SHIFT (15)
#define DS_EN_SHIFT (24)
#define DS_OUT_DIS_SHIFT (25)
#define DS_OUT_VAL_SHIFT (26)
--
2.53.0
^ permalink raw reply related
* [PATCH 1/2] arm64: dts: ti: k3-pinctrl: consistently use tabs for alignment
From: Rasmus Villemoes @ 2026-03-27 14:15 UTC (permalink / raw)
To: Nishanth Menon, Vignesh Raghavendra, Tero Kristo
Cc: linux-arm-kernel, Rasmus Villemoes
In-Reply-To: <20260327141513.1250499-1-linux@rasmusvillemoes.dk>
Currently, there's a mix of spaces and tabs used for aligning the
bodies of the macros, even within the same block. Use tabs throughout
for consistency.
No functional change; 'git diff -w' produces no output.
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
---
arch/arm64/boot/dts/ti/k3-pinctrl.h | 78 ++++++++++++++---------------
1 file changed, 39 insertions(+), 39 deletions(-)
diff --git a/arch/arm64/boot/dts/ti/k3-pinctrl.h b/arch/arm64/boot/dts/ti/k3-pinctrl.h
index dc8e03ae74c8..bdccb153e089 100644
--- a/arch/arm64/boot/dts/ti/k3-pinctrl.h
+++ b/arch/arm64/boot/dts/ti/k3-pinctrl.h
@@ -8,15 +8,15 @@
#ifndef DTS_ARM64_TI_K3_PINCTRL_H
#define DTS_ARM64_TI_K3_PINCTRL_H
-#define WKUP_LVL_EN_SHIFT (7)
-#define WKUP_LVL_POL_SHIFT (8)
+#define WKUP_LVL_EN_SHIFT (7)
+#define WKUP_LVL_POL_SHIFT (8)
#define ST_EN_SHIFT (14)
#define PULLUDEN_SHIFT (16)
#define PULLTYPESEL_SHIFT (17)
#define RXACTIVE_SHIFT (18)
-#define DRV_STR_SHIFT (19)
-#define ISO_OVERRIDE_EN_SHIFT (22)
-#define ISO_BYPASS_EN_SHIFT (23)
+#define DRV_STR_SHIFT (19)
+#define ISO_OVERRIDE_EN_SHIFT (22)
+#define ISO_BYPASS_EN_SHIFT (23)
#define DEBOUNCE_SHIFT (11)
#define FORCE_DS_EN_SHIFT (15)
#define DS_EN_SHIFT (24)
@@ -24,7 +24,7 @@
#define DS_OUT_VAL_SHIFT (26)
#define DS_PULLUD_EN_SHIFT (27)
#define DS_PULLTYPE_SEL_SHIFT (28)
-#define WKUP_EN_SHIFT (29)
+#define WKUP_EN_SHIFT (29)
/* Schmitt trigger configuration */
#define ST_DISABLE (0 << ST_EN_SHIFT)
@@ -39,28 +39,28 @@
#define INPUT_EN (1 << RXACTIVE_SHIFT)
#define INPUT_DISABLE (0 << RXACTIVE_SHIFT)
-#define DS_PULL_DISABLE (1 << DS_PULLUD_EN_SHIFT)
-#define DS_PULL_ENABLE (0 << DS_PULLUD_EN_SHIFT)
+#define DS_PULL_DISABLE (1 << DS_PULLUD_EN_SHIFT)
+#define DS_PULL_ENABLE (0 << DS_PULLUD_EN_SHIFT)
-#define DS_PULL_UP (1 << DS_PULLTYPE_SEL_SHIFT | DS_PULL_ENABLE)
-#define DS_PULL_DOWN (0 << DS_PULLTYPE_SEL_SHIFT | DS_PULL_ENABLE)
+#define DS_PULL_UP (1 << DS_PULLTYPE_SEL_SHIFT | DS_PULL_ENABLE)
+#define DS_PULL_DOWN (0 << DS_PULLTYPE_SEL_SHIFT | DS_PULL_ENABLE)
-#define DS_STATE_EN (1 << DS_EN_SHIFT)
-#define DS_STATE_DISABLE (0 << DS_EN_SHIFT)
+#define DS_STATE_EN (1 << DS_EN_SHIFT)
+#define DS_STATE_DISABLE (0 << DS_EN_SHIFT)
-#define DS_INPUT_EN (1 << DS_OUT_DIS_SHIFT | DS_STATE_EN)
-#define DS_INPUT_DISABLE (0 << DS_OUT_DIS_SHIFT | DS_STATE_EN)
+#define DS_INPUT_EN (1 << DS_OUT_DIS_SHIFT | DS_STATE_EN)
+#define DS_INPUT_DISABLE (0 << DS_OUT_DIS_SHIFT | DS_STATE_EN)
-#define DS_OUT_VALUE_ZERO (0 << DS_OUT_VAL_SHIFT)
-#define DS_OUT_VALUE_ONE (1 << DS_OUT_VAL_SHIFT)
+#define DS_OUT_VALUE_ZERO (0 << DS_OUT_VAL_SHIFT)
+#define DS_OUT_VALUE_ONE (1 << DS_OUT_VAL_SHIFT)
/* Configuration to enable wake-up on pin activity */
-#define WKUP_ENABLE (1 << WKUP_EN_SHIFT)
-#define WKUP_DISABLE (0 << WKUP_EN_SHIFT)
-#define WKUP_ON_LEVEL (1 << WKUP_LVL_EN_SHIFT)
-#define WKUP_ON_EDGE (0 << WKUP_LVL_EN_SHIFT)
-#define WKUP_LEVEL_LOW (0 << WKUP_LVL_POL_SHIFT)
-#define WKUP_LEVEL_HIGH (1 << WKUP_LVL_POL_SHIFT)
+#define WKUP_ENABLE (1 << WKUP_EN_SHIFT)
+#define WKUP_DISABLE (0 << WKUP_EN_SHIFT)
+#define WKUP_ON_LEVEL (1 << WKUP_LVL_EN_SHIFT)
+#define WKUP_ON_EDGE (0 << WKUP_LVL_EN_SHIFT)
+#define WKUP_LEVEL_LOW (0 << WKUP_LVL_POL_SHIFT)
+#define WKUP_LEVEL_HIGH (1 << WKUP_LVL_POL_SHIFT)
/* Only these macros are expected be used directly in device tree files */
#define PIN_OUTPUT (INPUT_DISABLE | PULL_DISABLE)
@@ -82,14 +82,14 @@
#define PIN_DEBOUNCE_CONF5 (5 << DEBOUNCE_SHIFT)
#define PIN_DEBOUNCE_CONF6 (6 << DEBOUNCE_SHIFT)
-#define PIN_DRIVE_STRENGTH_NOMINAL (0 << DRV_STR_SHIFT)
-#define PIN_DRIVE_STRENGTH_SLOW (1 << DRV_STR_SHIFT)
-#define PIN_DRIVE_STRENGTH_FAST (2 << DRV_STR_SHIFT)
+#define PIN_DRIVE_STRENGTH_NOMINAL (0 << DRV_STR_SHIFT)
+#define PIN_DRIVE_STRENGTH_SLOW (1 << DRV_STR_SHIFT)
+#define PIN_DRIVE_STRENGTH_FAST (2 << DRV_STR_SHIFT)
#define PIN_DS_FORCE_DISABLE (0 << FORCE_DS_EN_SHIFT)
#define PIN_DS_FORCE_ENABLE (1 << FORCE_DS_EN_SHIFT)
-#define PIN_DS_ISO_OVERRIDE_DISABLE (0 << ISO_OVERRIDE_EN_SHIFT)
-#define PIN_DS_ISO_OVERRIDE_ENABLE (1 << ISO_OVERRIDE_EN_SHIFT)
+#define PIN_DS_ISO_OVERRIDE_DISABLE (0 << ISO_OVERRIDE_EN_SHIFT)
+#define PIN_DS_ISO_OVERRIDE_ENABLE (1 << ISO_OVERRIDE_EN_SHIFT)
#define PIN_DS_OUT_ENABLE (0 << DS_OUT_DIS_SHIFT)
#define PIN_DS_OUT_DISABLE (1 << DS_OUT_DIS_SHIFT)
#define PIN_DS_OUT_VALUE_ZERO (0 << DS_OUT_VAL_SHIFT)
@@ -98,18 +98,18 @@
#define PIN_DS_PULLUD_DISABLE (1 << DS_PULLUD_EN_SHIFT)
#define PIN_DS_PULL_DOWN (0 << DS_PULLTYPE_SEL_SHIFT)
#define PIN_DS_PULL_UP (1 << DS_PULLTYPE_SEL_SHIFT)
-#define PIN_DS_ISO_BYPASS (1 << ISO_BYPASS_EN_SHIFT)
-#define PIN_DS_ISO_BYPASS_DISABLE (0 << ISO_BYPASS_EN_SHIFT)
-
-#define PIN_DS_OUTPUT_LOW (DS_INPUT_DISABLE | DS_OUT_VALUE_ZERO)
-#define PIN_DS_OUTPUT_HIGH (DS_INPUT_DISABLE | DS_OUT_VALUE_ONE)
-#define PIN_DS_INPUT (DS_INPUT_EN | DS_PULL_DISABLE)
-#define PIN_DS_INPUT_PULLUP (DS_INPUT_EN | DS_PULL_UP)
-#define PIN_DS_INPUT_PULLDOWN (DS_INPUT_EN | DS_PULL_DOWN)
-
-#define PIN_WKUP_EN_LEVEL_LOW (WKUP_ENABLE | WKUP_ON_LEVEL | WKUP_LEVEL_LOW)
-#define PIN_WKUP_EN_LEVEL_HIGH (WKUP_ENABLE | WKUP_ON_LEVEL | WKUP_LEVEL_HIGH)
-#define PIN_WKUP_EN (WKUP_ENABLE | WKUP_ON_EDGE)
+#define PIN_DS_ISO_BYPASS (1 << ISO_BYPASS_EN_SHIFT)
+#define PIN_DS_ISO_BYPASS_DISABLE (0 << ISO_BYPASS_EN_SHIFT)
+
+#define PIN_DS_OUTPUT_LOW (DS_INPUT_DISABLE | DS_OUT_VALUE_ZERO)
+#define PIN_DS_OUTPUT_HIGH (DS_INPUT_DISABLE | DS_OUT_VALUE_ONE)
+#define PIN_DS_INPUT (DS_INPUT_EN | DS_PULL_DISABLE)
+#define PIN_DS_INPUT_PULLUP (DS_INPUT_EN | DS_PULL_UP)
+#define PIN_DS_INPUT_PULLDOWN (DS_INPUT_EN | DS_PULL_DOWN)
+
+#define PIN_WKUP_EN_LEVEL_LOW (WKUP_ENABLE | WKUP_ON_LEVEL | WKUP_LEVEL_LOW)
+#define PIN_WKUP_EN_LEVEL_HIGH (WKUP_ENABLE | WKUP_ON_LEVEL | WKUP_LEVEL_HIGH)
+#define PIN_WKUP_EN (WKUP_ENABLE | WKUP_ON_EDGE)
/* Default mux configuration for gpio-ranges to use with pinctrl */
#define PIN_GPIO_RANGE_IOPAD (PIN_INPUT | 7)
--
2.53.0
^ permalink raw reply related
* [PATCH 0/2] arm64: dts: ti: k3-pinctrl: some minor cleanup
From: Rasmus Villemoes @ 2026-03-27 14:15 UTC (permalink / raw)
To: Nishanth Menon, Vignesh Raghavendra, Tero Kristo
Cc: linux-arm-kernel, Rasmus Villemoes
I stumbled on a few things one might want to clean up. No functional change.
Rasmus Villemoes (2):
arm64: dts: ti: k3-pinctrl: consistently use tabs for alignment
arm64: dts: ti: k3-pinctrl: sort shift values numerically
arch/arm64/boot/dts/ti/k3-pinctrl.h | 82 ++++++++++++++---------------
1 file changed, 41 insertions(+), 41 deletions(-)
--
2.53.0
^ permalink raw reply
* Re: [PATCH 6/9] dt-bindings: i2c: apple,i2c: Add t8122 compatible
From: Andi Shyti @ 2026-03-27 14:15 UTC (permalink / raw)
To: Janne Grunau
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Lorenzo Pieralisi,
Sven Peter, Neal Gompa, Wim Van Sebroeck, Guenter Roeck,
Linus Walleij, Mark Kettenis, Uwe Kleine-König,
Sasha Finkelstein, devicetree, linux-kernel, asahi,
linux-arm-kernel, linux-watchdog, linux-gpio, linux-i2c,
linux-pwm
In-Reply-To: <20260320-apple-m3-initial-devicetrees-v1-6-5842e1e393a8@jannau.net>
Hi Janne,
On Fri, Mar 20, 2026 at 01:23:24PM +0100, Janne Grunau wrote:
> The i2c block on the Apple silicon t8122 (M3) SoC is compatible with the
> existing driver. Add "apple,t8122-i2c" as SoC specific compatible under
> "apple,t8103-i2c" used by the deriver.
>
> Signed-off-by: Janne Grunau <j@jannau.net>
Acked-by: Andi Shyti <andi.shyti@kernel.org>
Thanks,
Andi
^ permalink raw reply
* Re: [PATCH v20 06/10] power: reset: Add psci-reboot-mode driver
From: Lorenzo Pieralisi @ 2026-03-27 14:14 UTC (permalink / raw)
To: Shivendra Pratap
Cc: Arnd Bergmann, Bjorn Andersson, Sebastian Reichel, Rob Herring,
Souvik Chakravarty, Krzysztof Kozlowski, Andy Yan,
Matthias Brugger, Mark Rutland, Conor Dooley, Konrad Dybcio,
John Stultz, Moritz Fischer, Bartosz Golaszewski, Sudeep Holla,
Florian Fainelli, Krzysztof Kozlowski, Dmitry Baryshkov,
Mukesh Ojha, Andre Draszik, Kathiravan Thirumoorthy, linux-pm,
linux-kernel, linux-arm-kernel, linux-arm-msm, devicetree,
Srinivas Kandagatla
In-Reply-To: <20260304-arm-psci-system_reset2-vendor-reboots-v20-6-cf7d346b8372@oss.qualcomm.com>
On Wed, Mar 04, 2026 at 11:33:06PM +0530, Shivendra Pratap wrote:
> PSCI supports different types of resets like COLD reset, ARCH WARM
> reset, vendor-specific resets. Currently there is no common driver that
> handles all supported psci resets at one place. Additionally, there is
> no common mechanism to issue the supported psci resets from userspace.
>
> Add a PSCI reboot mode driver and define two types of PSCI resets in the
> driver as reboot-modes: predefined resets controlled by Linux
> reboot_mode and customizable resets defined by SoC vendors in their
> device tree under the psci:reboot-mode node.
>
> Register the driver with the reboot-mode framework to interface these
> resets to userspace. When userspace initiates a supported command, pass
> the reset arguments to the PSCI driver to enable command-based reset.
>
> This change allows userspace to issue supported PSCI reset commands
> using the standard reboot system calls while enabling SoC vendors to
> define their specific resets for PSCI.
>
> Signed-off-by: Shivendra Pratap <shivendra.pratap@oss.qualcomm.com>
> ---
> drivers/power/reset/Kconfig | 10 +++
> drivers/power/reset/Makefile | 1 +
> drivers/power/reset/psci-reboot-mode.c | 119 +++++++++++++++++++++++++++++++++
Add an entry into MAINTAINERS.POWER STATE COORDINATION INTERFACE for this
specific file because I'd like to keep an eye on it, if you don't mind.
Creating a MAINTAINER entry just for this seems overkill to me, it
does not look like it is done for other reboot mode drivers.
Thanks,
Lorenzo
> 3 files changed, 130 insertions(+)
>
> diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
> index f6c1bcbb57deff3568d6b1b326454add3b3bbf06..529d6c7d3555601f7b7e6199acd29838030fcef2 100644
> --- a/drivers/power/reset/Kconfig
> +++ b/drivers/power/reset/Kconfig
> @@ -348,6 +348,16 @@ config NVMEM_REBOOT_MODE
> then the bootloader can read it and take different
> action according to the mode.
>
> +config PSCI_REBOOT_MODE
> + bool "PSCI reboot mode driver"
> + depends on OF && ARM_PSCI_FW
> + select REBOOT_MODE
> + help
> + Say y here will enable PSCI reboot mode driver. This gets
> + the PSCI reboot mode arguments and passes them to psci
> + driver. psci driver uses these arguments for issuing
> + device reset into different boot states.
> +
> config POWER_MLXBF
> tristate "Mellanox BlueField power handling driver"
> depends on (GPIO_MLXBF2 || GPIO_MLXBF3) && ACPI
> diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
> index 0e4ae6f6b5c55729cf60846d47e6fe0fec24f3cc..49774b42cdf61fd57a5b70f286c65c9d66bbc0cb 100644
> --- a/drivers/power/reset/Makefile
> +++ b/drivers/power/reset/Makefile
> @@ -40,4 +40,5 @@ obj-$(CONFIG_REBOOT_MODE) += reboot-mode.o
> obj-$(CONFIG_SYSCON_REBOOT_MODE) += syscon-reboot-mode.o
> obj-$(CONFIG_POWER_RESET_SC27XX) += sc27xx-poweroff.o
> obj-$(CONFIG_NVMEM_REBOOT_MODE) += nvmem-reboot-mode.o
> +obj-$(CONFIG_PSCI_REBOOT_MODE) += psci-reboot-mode.o
> obj-$(CONFIG_POWER_MLXBF) += pwr-mlxbf.o
> diff --git a/drivers/power/reset/psci-reboot-mode.c b/drivers/power/reset/psci-reboot-mode.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..86bef195228b0924704c2936b99f6801c14ff1b1
> --- /dev/null
> +++ b/drivers/power/reset/psci-reboot-mode.c
> @@ -0,0 +1,119 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + */
> +
> +#include <linux/device/faux.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/of.h>
> +#include <linux/psci.h>
> +#include <linux/reboot.h>
> +#include <linux/reboot-mode.h>
> +#include <linux/types.h>
> +
> +/*
> + * Predefined reboot-modes are defined as per the values
> + * of enum reboot_mode defined in the kernel: reboot.c.
> + */
> +static struct mode_info psci_resets[] = {
> + { .mode = "warm", .magic = REBOOT_WARM},
> + { .mode = "soft", .magic = REBOOT_SOFT},
> + { .mode = "cold", .magic = REBOOT_COLD},
> +};
> +
> +static void psci_reboot_mode_set_predefined_modes(struct reboot_mode_driver *reboot)
> +{
> + INIT_LIST_HEAD(&reboot->predefined_modes);
> + for (u32 i = 0; i < ARRAY_SIZE(psci_resets); i++) {
> + /* Prepare the magic with arg1 as 0 and arg2 as per pre-defined mode */
> + psci_resets[i].magic = REBOOT_MODE_MAGIC(0, psci_resets[i].magic);
> + INIT_LIST_HEAD(&psci_resets[i].list);
> + list_add_tail(&psci_resets[i].list, &reboot->predefined_modes);
> + }
> +}
> +
> +/*
> + * arg1 is reset_type(Low 32 bit of magic).
> + * arg2 is cookie(High 32 bit of magic).
> + * If reset_type is 0, cookie will be used to decide the reset command.
> + */
> +static int psci_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic)
> +{
> + u32 reset_type = REBOOT_MODE_ARG1(magic);
> + u32 cookie = REBOOT_MODE_ARG2(magic);
> +
> + if (reset_type == 0) {
> + if (cookie == REBOOT_WARM || cookie == REBOOT_SOFT)
> + psci_set_reset_cmd(true, 0, 0);
> + else
> + psci_set_reset_cmd(false, 0, 0);
> + } else {
> + psci_set_reset_cmd(true, reset_type, cookie);
> + }
> +
> + return NOTIFY_DONE;
> +}
> +
> +static int psci_reboot_mode_register_device(struct faux_device *fdev)
> +{
> + struct reboot_mode_driver *reboot;
> + int ret;
> +
> + reboot = devm_kzalloc(&fdev->dev, sizeof(*reboot), GFP_KERNEL);
> + if (!reboot)
> + return -ENOMEM;
> +
> + psci_reboot_mode_set_predefined_modes(reboot);
> + reboot->write = psci_reboot_mode_write;
> + reboot->dev = &fdev->dev;
> +
> + ret = devm_reboot_mode_register(&fdev->dev, reboot);
> + if (ret) {
> + dev_err_probe(&fdev->dev, ret, "devm_reboot_mode_register failed %d\n", ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static int __init psci_reboot_mode_init(void)
> +{
> + struct device_node *psci_np;
> + struct faux_device *fdev;
> + struct device_node *np;
> + int ret;
> +
> + psci_np = of_find_compatible_node(NULL, NULL, "arm,psci-1.0");
> + if (!psci_np)
> + return -ENODEV;
> + /*
> + * Look for reboot-mode in the psci node. Even if the reboot-mode
> + * node is not defined in psci, continue to register with the
> + * reboot-mode driver and let the dev.ofnode be set as NULL.
> + */
> + np = of_find_node_by_name(psci_np, "reboot-mode");
> +
> + fdev = faux_device_create("psci-reboot-mode", NULL, NULL);
> + if (!fdev) {
> + ret = -ENODEV;
> + goto error;
> + }
> +
> + device_set_node(&fdev->dev, of_fwnode_handle(np));
> + ret = psci_reboot_mode_register_device(fdev);
> + if (ret)
> + goto error;
> +
> + return 0;
> +
> +error:
> + of_node_put(np);
> + if (fdev) {
> + device_set_node(&fdev->dev, NULL);
> + faux_device_destroy(fdev);
> + }
> +
> + return ret;
> +}
> +device_initcall(psci_reboot_mode_init);
>
> --
> 2.34.1
>
^ permalink raw reply
* Re: [PATCH v2] i2c: rk3x: add support for SCL OE debounce and slave hold recovery
From: Andi Shyti @ 2026-03-27 14:13 UTC (permalink / raw)
To: Anand Moon
Cc: Heiko Stuebner, moderated list:ARM/Rockchip SoC support,
open list:ARM/Rockchip SoC support,
open list:I2C SUBSYSTEM HOST DRIVERS, open list, David Wu
In-Reply-To: <20260321105146.7419-1-linux.amoon@gmail.com>
Hi Anand,
...
> @@ -1125,6 +1141,17 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
> }
> }
>
> + /*
> + * If a timeout occurred and the slave is holding SCL,
> + * re-apply the timings/dividers to attempt recovery.
> + */
> + if (ret == -ETIMEDOUT && i2c->soc_data->has_scl_oe_debounce) {
> + if (ipd & REG_INT_SLV_HDSCL) {
> + dev_err(i2c->dev, "SCL hold by slave detected, resetting timings.\n");
> + rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk));
argh! this nests i2c->lock. rk3x_i2c_xfer_common() already holds
it when calling rk3x_i2c_adapt_div().
Andi
> + }
> + }
> +
^ permalink raw reply
* Re: [PATCH v20 06/10] power: reset: Add psci-reboot-mode driver
From: Bartosz Golaszewski @ 2026-03-27 14:09 UTC (permalink / raw)
To: Lorenzo Pieralisi
Cc: Shivendra Pratap, Florian Fainelli, Krzysztof Kozlowski,
Dmitry Baryshkov, Mukesh Ojha, Andre Draszik,
Kathiravan Thirumoorthy, linux-pm, linux-kernel, linux-arm-kernel,
linux-arm-msm, devicetree, Srinivas Kandagatla, Arnd Bergmann,
Bjorn Andersson, Sebastian Reichel, Rob Herring,
Souvik Chakravarty, Krzysztof Kozlowski, Andy Yan,
Matthias Brugger, Mark Rutland, Conor Dooley, Konrad Dybcio,
John Stultz, Moritz Fischer, Sudeep Holla
In-Reply-To: <acaPSW6VeYceoMnO@lpieralisi>
On Fri, Mar 27, 2026 at 3:08 PM Lorenzo Pieralisi <lpieralisi@kernel.org> wrote:
>
> On Fri, Mar 06, 2026 at 02:32:46PM +0100, Bartosz Golaszewski wrote:
> > On Thu, Mar 5, 2026 at 6:07 PM Shivendra Pratap
> > <shivendra.pratap@oss.qualcomm.com> wrote:
> > >
> > > >
> > > > You should pass the address of this function in faux_device_ops instead of
> > > > calling it directly.
> > >
> > > In last patch, we were using a probe function. As faux_device_create,
> > > calls the probe from its internal operations, "of_node" can only be
> > > assigned from inside of faux device probe.
> > >
> > > As our primary requirement is to assign reboot-mode of_node to the faux
> > > device, thought to make it this way. (As we did not want to assign it
> > > inside the faux device probe).
> > >
> >
> > TBH This sounds like a limitation of the faux device API. I'll Cc you
> > on a patch proposing to extend it with the ability of using a firmware
> > node to describe the device. If it works for you, you can integrate it
> > into your series and use it.
>
> What's the status on this matter ?
>
I looked around and didn't find any good reason for adding this after
all so I dropped it.
Bart
^ permalink raw reply
* Re: [PATCH v20 06/10] power: reset: Add psci-reboot-mode driver
From: Lorenzo Pieralisi @ 2026-03-27 14:08 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Shivendra Pratap, Florian Fainelli, Krzysztof Kozlowski,
Dmitry Baryshkov, Mukesh Ojha, Andre Draszik,
Kathiravan Thirumoorthy, linux-pm, linux-kernel, linux-arm-kernel,
linux-arm-msm, devicetree, Srinivas Kandagatla, Arnd Bergmann,
Bjorn Andersson, Sebastian Reichel, Rob Herring,
Souvik Chakravarty, Krzysztof Kozlowski, Andy Yan,
Matthias Brugger, Mark Rutland, Conor Dooley, Konrad Dybcio,
John Stultz, Moritz Fischer, Sudeep Holla
In-Reply-To: <CAMRc=McUdboG0ziWmUf+h9mUiuGesaFk2v27z_Opbw-AF33C0g@mail.gmail.com>
On Fri, Mar 06, 2026 at 02:32:46PM +0100, Bartosz Golaszewski wrote:
> On Thu, Mar 5, 2026 at 6:07 PM Shivendra Pratap
> <shivendra.pratap@oss.qualcomm.com> wrote:
> >
> > >
> > > You should pass the address of this function in faux_device_ops instead of
> > > calling it directly.
> >
> > In last patch, we were using a probe function. As faux_device_create,
> > calls the probe from its internal operations, "of_node" can only be
> > assigned from inside of faux device probe.
> >
> > As our primary requirement is to assign reboot-mode of_node to the faux
> > device, thought to make it this way. (As we did not want to assign it
> > inside the faux device probe).
> >
>
> TBH This sounds like a limitation of the faux device API. I'll Cc you
> on a patch proposing to extend it with the ability of using a firmware
> node to describe the device. If it works for you, you can integrate it
> into your series and use it.
What's the status on this matter ?
Thanks,
Lorenzo
^ permalink raw reply
* Re: [PATCH v20 04/10] firmware: psci: Introduce command-based reset in psci_sys_reset
From: Lorenzo Pieralisi @ 2026-03-27 14:07 UTC (permalink / raw)
To: Shivendra Pratap
Cc: Arnd Bergmann, Bjorn Andersson, Sebastian Reichel, Rob Herring,
Souvik Chakravarty, Krzysztof Kozlowski, Andy Yan,
Matthias Brugger, Mark Rutland, Conor Dooley, Konrad Dybcio,
John Stultz, Moritz Fischer, Bartosz Golaszewski, Sudeep Holla,
Florian Fainelli, Krzysztof Kozlowski, Dmitry Baryshkov,
Mukesh Ojha, Andre Draszik, Kathiravan Thirumoorthy, linux-pm,
linux-kernel, linux-arm-kernel, linux-arm-msm, devicetree,
Srinivas Kandagatla
In-Reply-To: <20260304-arm-psci-system_reset2-vendor-reboots-v20-4-cf7d346b8372@oss.qualcomm.com>
On Wed, Mar 04, 2026 at 11:33:04PM +0530, Shivendra Pratap wrote:
> PSCI currently supports only COLD reset and ARCH WARM reset based on the
> Linux reboot_mode variable. The PSCI specification now includes
> SYSTEM_RESET2 for vendor-specific resets, but there's no mechanism to
> issue these through psci_sys_reset.
>
> Add a command-based reset mechanism that allows external drivers to set
> the psci reset command via a new psci_set_reset_cmd() function.
>
> The psci command-based reset is disabled by default and the
> psci_sys_reset follows its original flow until a psci_reset command is
> set. In kernel panic path, psci_reset command is ignored.
If it is function calls you should add parenthesis (eg psci_sys_reset ->
psci_sys_reset()).
You must explain why the kernel panic path requires separate handling
here AND in the code - think about looking at this years down the line
and figure out why kernel panics are special here.
> Signed-off-by: Shivendra Pratap <shivendra.pratap@oss.qualcomm.com>
> ---
> drivers/firmware/psci/psci.c | 45 ++++++++++++++++++++++++++++++++++++++++++--
> include/linux/psci.h | 2 ++
> 2 files changed, 45 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/firmware/psci/psci.c b/drivers/firmware/psci/psci.c
> index 38ca190d4a22d6e7e0f06420e8478a2b0ec2fe6f..ae6f7a0aead913d740070080d4b2a3da15b29485 100644
> --- a/drivers/firmware/psci/psci.c
> +++ b/drivers/firmware/psci/psci.c
> @@ -51,6 +51,15 @@ static int resident_cpu = -1;
> struct psci_operations psci_ops;
> static enum arm_smccc_conduit psci_conduit = SMCCC_CONDUIT_NONE;
>
> +struct psci_sys_reset_params {
> + u32 system_reset;
> + u32 reset_type;
> + u32 cookie;
> + bool cmd;
> +};
> +
> +static struct psci_sys_reset_params psci_reset;
> +
> bool psci_tos_resident_on(int cpu)
> {
> return cpu == resident_cpu;
> @@ -80,6 +89,28 @@ static u32 psci_cpu_suspend_feature;
> static bool psci_system_reset2_supported;
> static bool psci_system_off2_hibernate_supported;
>
> +/**
> + * psci_set_reset_cmd - Sets the psci_reset_cmd for command-based
> + * reset which will be used in psci_sys_reset call.
> + *
> + * @cmd_sys_rst2: Set to true for SYSTEM_RESET2 based resets.
> + * @cmd_reset_type: Set the reset_type argument for psci_sys_reset.
> + * @cmd_cookie: Set the cookie argument for psci_sys_reset.
> + */
> +void psci_set_reset_cmd(bool cmd_sys_rst2, u32 cmd_reset_type, u32 cmd_cookie)
> +{
I don't think cmd_sys_rst2 is needed, as a replied in a different thread.
> + if (cmd_sys_rst2 && psci_system_reset2_supported) {
> + psci_reset.system_reset = PSCI_FN_NATIVE(1_1, SYSTEM_RESET2);
> + psci_reset.reset_type = cmd_reset_type;
> + psci_reset.cookie = cmd_cookie;
> + } else {
> + psci_reset.system_reset = PSCI_0_2_FN_SYSTEM_RESET;
> + psci_reset.reset_type = 0;
> + psci_reset.cookie = 0;
> + }
> + psci_reset.cmd = true;
> +}
> +
> static inline bool psci_has_ext_power_state(void)
> {
> return psci_cpu_suspend_feature &
> @@ -309,14 +340,24 @@ static int get_set_conduit_method(const struct device_node *np)
> static int psci_sys_reset(struct notifier_block *nb, unsigned long action,
> void *data)
> {
> - if ((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) &&
> - psci_system_reset2_supported) {
> + if (((reboot_mode == REBOOT_WARM || reboot_mode == REBOOT_SOFT) &&
> + psci_system_reset2_supported) && (panic_in_progress() || !psci_reset.cmd)) {
> /*
> * reset_type[31] = 0 (architectural)
> * reset_type[30:0] = 0 (SYSTEM_WARM_RESET)
> * cookie = 0 (ignored by the implementation)
> */
> invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, 0, 0);
> + } else if (!panic_in_progress() && psci_reset.cmd) {
> + /*
> + * Commands are being set in psci_set_reset_cmd
> + * This issues, SYSTEM_RESET2 arch warm reset or
> + * SYSTEM_RESET2 vendor-specific reset or
> + * a SYSTEM_RESET cold reset in accordance with
> + * the reboot-mode command.
> + */
> + invoke_psci_fn(psci_reset.system_reset, psci_reset.reset_type,
> + psci_reset.cookie, 0);
> } else {
> invoke_psci_fn(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0);
This is very hard to parse. IMO, what you should do is:
- Split this into two different paths: reboot_mode vs psci_reset.cmd == true.
- Document very clearly why a panic needs separate handling.
Something like:
if (psci_reset.cmd)
handle_reset_cmd();
else
handle_reboot_mode();
I don't think we are far from converging but I want to be able to maintain
this code going forward.
Thanks,
Lorenzo
> }
> diff --git a/include/linux/psci.h b/include/linux/psci.h
> index 4ca0060a3fc42ba1ca751c7862fb4ad8dda35a4c..d13ceca88eab8932894051e7c86e806c2ad8a73a 100644
> --- a/include/linux/psci.h
> +++ b/include/linux/psci.h
> @@ -45,8 +45,10 @@ struct psci_0_1_function_ids get_psci_0_1_function_ids(void);
>
> #if defined(CONFIG_ARM_PSCI_FW)
> int __init psci_dt_init(void);
> +void psci_set_reset_cmd(bool cmd_sys_rst2, u32 cmd_reset_type, u32 cmd_cookie);
> #else
> static inline int psci_dt_init(void) { return 0; }
> +static inline void psci_set_reset_cmd(bool cmd_sys_rst2, u32 cmd_reset_type, u32 cmd_cookie) { }
> #endif
>
> #if defined(CONFIG_ARM_PSCI_FW) && defined(CONFIG_ACPI)
>
> --
> 2.34.1
>
^ permalink raw reply
* Re: [RFT PATCH v3] ARM: omap1: enable real software node lookup of GPIOs on Nokia 770
From: Aaro Koskinen @ 2026-03-27 14:05 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Janusz Krzysztofik, Arnd Bergmann, Bartosz Golaszewski,
Tony Lindgren, Russell King, Dmitry Torokhov, Hans de Goede,
Linux-OMAP, linux-arm-kernel, linux-kernel, Kevin Hilman
In-Reply-To: <CAMRc=MeYMe1gXjiYuQJpNWchp+V1uLkuRuyO3ohQjfAcg9q3MQ@mail.gmail.com>
Hi,
On Thu, Mar 26, 2026 at 09:57:31AM +0100, Bartosz Golaszewski wrote:
> On Mon, Mar 16, 2026 at 9:50 AM Bartosz Golaszewski <brgl@kernel.org> wrote:
> > On Fri, Mar 6, 2026 at 1:31 AM Kevin Hilman <khilman@kernel.org> wrote:
> > > Bartosz Golaszewski <brgl@kernel.org> writes:
> > > > On Thu, Feb 12, 2026 at 12:46 PM Arnd Bergmann <arnd@kernel.org> wrote:
> > > >> On Thu, Feb 12, 2026, at 12:25, Bartosz Golaszewski wrote:
> > > >> > Currently the board file for Nokia 770 creates dummy software nodes not
> > > >> > attached in any way to the actual GPIO controller devices and uses the
> > > >> > fact that GPIOLIB matching swnode's name to the GPIO chip's label during
> > > >> > software node lookup. This behavior is wrong and we want to remove it.
> > > >> > To that end, we need to first convert all existing users to creating
> > > >> > actual fwnode links.
> > > >> >
> > > >> > Create real software nodes for GPIO controllers on OMAP16xx and
> > > >> > reference them from the software nodes in the nokia board file.
> > > >> >
> > > >> > Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
> > > >>
> > > >> Acked-by: Arnd Bergmann <arnd@arndb.de>
> > > >
> > > > Aaro, Janusz: Can you please pick it up for v7.1?
> > >
> > > I can take this via the OMAP tree once I have confirmation from
> > > Aaro/Janusz that they've tested.
>
> Hi again! Any chance we could get this queued? Janusz, Aaro: any objections?
Unfortunately the patch doesn't work - 770 just dies silently. This
means that e.g. CBUS GPIOs are not working as those are needed to keep
the device powered. I'll try to figure out how to debug this...
A.
^ permalink raw reply
* Re: [PATCH v2 0/2] PCI: dwc: Add multi-port controller support
From: Neil Armstrong @ 2026-03-27 14:04 UTC (permalink / raw)
To: Sumit Kumar, Bjorn Helgaas, Jingoo Han, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Krzysztof Kozlowski, Alim Akhtar, Richard Zhu, Lucas Stach,
Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Yue Wang, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Paul Walmsley, Greentime Hu, Samuel Holland, Chuanhua Lei,
Marek Vasut, Yoshihiro Shimoda, Geert Uytterhoeven, Magnus Damm,
Pratyush Anand, Thierry Reding, Jonathan Hunter
Cc: linux-pci, linux-kernel, linux-arm-kernel, linux-samsung-soc, imx,
linux-amlogic, linux-arm-msm, linux-renesas-soc, linux-tegra,
linux-riscv
In-Reply-To: <20260305-dt-parser-v2-0-85836db8dc06@oss.qualcomm.com>
Le 05/03/2026 à 07:20, Sumit Kumar a écrit :
> This series adds support for multi-port PCIe controllers in the DesignWare
> driver. Currently, the driver only supports a single Root Port with
> controller-level properties, which doesn't work for multi-port controllers
> where each port may have different configurations.
>
> This series introduces a per-port structure and parsing API that allows
> each Root Port to be configured independently via pcie@N child nodes in
> device tree, while maintaining backward compatibility with existing
> single-port bindings.
>
> Signed-off-by: Sumit Kumar <sumit.kumar@oss.qualcomm.com>
> ---
> Changes in v2:
> - Fix error code preservation in dw_pcie_resume_noirq() to return actual
> error from dw_pcie_wait_for_link() instead of hardcoded -ETIMEDOUT (Mani).
> - Initialize ret variable to -ENOENT in dw_pcie_parse_root_ports() (Mani).
> - dw_pcie_host_init(): Remove -ENOENT error skipping to make parsing
> failures fatal for now, add TODO comment about making properties
> optional later (Mani).
> - Link to v1: https://lore.kernel.org/r/20260105-dt-parser-v1-0-b11c63cb5e2c@oss.qualcomm.com
>
> ---
> Sumit Kumar (2):
> PCI: API changes for multi-port controller support
> PCI: dwc: Add multi-port controller support
>
> drivers/pci/controller/dwc/pci-exynos.c | 4 +-
> drivers/pci/controller/dwc/pci-imx6.c | 15 +-
> drivers/pci/controller/dwc/pci-meson.c | 1 -
> drivers/pci/controller/dwc/pcie-designware-host.c | 175 ++++++++++++++++++----
> drivers/pci/controller/dwc/pcie-designware.c | 32 ++--
> drivers/pci/controller/dwc/pcie-designware.h | 17 ++-
> drivers/pci/controller/dwc/pcie-fu740.c | 6 +-
> drivers/pci/controller/dwc/pcie-intel-gw.c | 13 +-
> drivers/pci/controller/dwc/pcie-qcom-common.c | 5 +-
> drivers/pci/controller/dwc/pcie-qcom-ep.c | 4 +-
> drivers/pci/controller/dwc/pcie-qcom.c | 4 +-
> drivers/pci/controller/dwc/pcie-rcar-gen4.c | 13 +-
> drivers/pci/controller/dwc/pcie-spear13xx.c | 5 +-
> drivers/pci/controller/dwc/pcie-tegra194.c | 4 +-
> drivers/pci/of.c | 6 +-
> drivers/pci/pci.h | 2 +
> 16 files changed, 232 insertions(+), 74 deletions(-)
> ---
> base-commit: 097a6c336d0080725c626fda118ecfec448acd0f
> change-id: 20251010-dt-parser-98b50ce18fc1
>
> Best regards,
Tested on meson-pci (boot log https://gitlab.com/amlogic-foss/abcd-linux-test/-/jobs/13677061036)
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # On Bananapi M2S
Thanks,
Neil
^ permalink raw reply
* [PATCH v4 36/38] KVM: arm64: Extend pKVM page ownership selftests to cover guest hvcs
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Now that the guest can share and unshare memory with the host using
hypercalls, extend the pKVM page ownership selftest to exercise these
new transitions.
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 30 +++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 05a5b145e303..0921efb8a16f 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -1812,11 +1812,41 @@ void pkvm_ownership_selftest(void *base)
assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn);
assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
+ selftest_state.host = PKVM_PAGE_SHARED_BORROWED;
+ selftest_state.guest[0] = PKVM_PAGE_SHARED_OWNED;
+ assert_transition_res(0, __pkvm_guest_share_host, vcpu, gfn);
+ assert_transition_res(-EPERM, __pkvm_guest_share_host, vcpu, gfn);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn + 1, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn + 1, 1, vcpu, prot);
+ assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1);
+ assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1);
+ assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn);
+ assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn);
+ assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
+
+ selftest_state.host = PKVM_NOPAGE;
+ selftest_state.guest[0] = PKVM_PAGE_OWNED;
+ assert_transition_res(0, __pkvm_guest_unshare_host, vcpu, gfn);
+ assert_transition_res(-EPERM, __pkvm_guest_unshare_host, vcpu, gfn);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn + 1, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn + 1, 1, vcpu, prot);
+ assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1);
+ assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1);
+ assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn);
+ assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn);
+ assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
+
selftest_state.host = PKVM_PAGE_OWNED;
selftest_state.guest[0] = PKVM_POISON;
assert_transition_res(0, __pkvm_host_force_reclaim_page_guest, phys);
assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
+ assert_transition_res(-EHWPOISON, __pkvm_guest_share_host, vcpu, gfn);
+ assert_transition_res(-EHWPOISON, __pkvm_guest_unshare_host, vcpu, gfn);
selftest_state.host = PKVM_NOPAGE;
selftest_state.guest[1] = PKVM_PAGE_OWNED;
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 38/38] drivers/virt: pkvm: Add Kconfig dependency on DMA_RESTRICTED_POOL
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
pKVM guests practically rely on CONFIG_DMA_RESTRICTED_POOL=y in order
to establish shared memory regions with the host for virtio buffers.
Make CONFIG_ARM_PKVM_GUEST depend on CONFIG_DMA_RESTRICTED_POOL to avoid
the inevitable segmentation faults experience if you have the former but
not the latter.
Reported-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
---
drivers/virt/coco/pkvm-guest/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/virt/coco/pkvm-guest/Kconfig b/drivers/virt/coco/pkvm-guest/Kconfig
index d2f344f1f98f..928b8e1668cc 100644
--- a/drivers/virt/coco/pkvm-guest/Kconfig
+++ b/drivers/virt/coco/pkvm-guest/Kconfig
@@ -1,6 +1,6 @@
config ARM_PKVM_GUEST
bool "Arm pKVM protected guest driver"
- depends on ARM64
+ depends on ARM64 && DMA_RESTRICTED_POOL
help
Protected guests running under the pKVM hypervisor on arm64
are isolated from the host and must issue hypercalls to enable
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 34/38] KVM: arm64: Register 'selftest_vm' in the VM table
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
In preparation for extending the pKVM page ownership selftests to cover
forceful reclaim of donated pages, rework the creation of the
'selftest_vm' so that it is registered in the VM table while the tests
are running.
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 2 +
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 53 ++++---------------
arch/arm64/kvm/hyp/nvhe/pkvm.c | 49 +++++++++++++++++
3 files changed, 61 insertions(+), 43 deletions(-)
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index 99d8398afe20..5031879ccb87 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -76,6 +76,8 @@ static __always_inline void __load_host_stage2(void)
#ifdef CONFIG_NVHE_EL2_DEBUG
void pkvm_ownership_selftest(void *base);
+struct pkvm_hyp_vcpu *init_selftest_vm(void *virt);
+void teardown_selftest_vm(void);
#else
static inline void pkvm_ownership_selftest(void *base) { }
#endif
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 6525f9fa274c..b2c9ea105701 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -1646,53 +1646,18 @@ struct pkvm_expected_state {
static struct pkvm_expected_state selftest_state;
static struct hyp_page *selftest_page;
-
-static struct pkvm_hyp_vm selftest_vm = {
- .kvm = {
- .arch = {
- .mmu = {
- .arch = &selftest_vm.kvm.arch,
- .pgt = &selftest_vm.pgt,
- },
- },
- },
-};
-
-static struct pkvm_hyp_vcpu selftest_vcpu = {
- .vcpu = {
- .arch = {
- .hw_mmu = &selftest_vm.kvm.arch.mmu,
- },
- .kvm = &selftest_vm.kvm,
- },
-};
-
-static void init_selftest_vm(void *virt)
-{
- struct hyp_page *p = hyp_virt_to_page(virt);
- int i;
-
- selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
- WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));
-
- for (i = 0; i < pkvm_selftest_pages(); i++) {
- if (p[i].refcount)
- continue;
- p[i].refcount = 1;
- hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
- }
-}
+static struct pkvm_hyp_vcpu *selftest_vcpu;
static u64 selftest_ipa(void)
{
- return BIT(selftest_vm.pgt.ia_bits - 1);
+ return BIT(selftest_vcpu->vcpu.arch.hw_mmu->pgt->ia_bits - 1);
}
static void assert_page_state(void)
{
void *virt = hyp_page_to_virt(selftest_page);
u64 size = PAGE_SIZE << selftest_page->order;
- struct pkvm_hyp_vcpu *vcpu = &selftest_vcpu;
+ struct pkvm_hyp_vcpu *vcpu = selftest_vcpu;
u64 phys = hyp_virt_to_phys(virt);
u64 ipa[2] = { selftest_ipa(), selftest_ipa() + PAGE_SIZE };
struct pkvm_hyp_vm *vm;
@@ -1707,10 +1672,10 @@ static void assert_page_state(void)
WARN_ON(__hyp_check_page_state_range(phys, size, selftest_state.hyp));
hyp_unlock_component();
- guest_lock_component(&selftest_vm);
+ guest_lock_component(vm);
WARN_ON(__guest_check_page_state_range(vm, ipa[0], size, selftest_state.guest[0]));
WARN_ON(__guest_check_page_state_range(vm, ipa[1], size, selftest_state.guest[1]));
- guest_unlock_component(&selftest_vm);
+ guest_unlock_component(vm);
}
#define assert_transition_res(res, fn, ...) \
@@ -1723,14 +1688,15 @@ void pkvm_ownership_selftest(void *base)
{
enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_RWX;
void *virt = hyp_alloc_pages(&host_s2_pool, 0);
- struct pkvm_hyp_vcpu *vcpu = &selftest_vcpu;
- struct pkvm_hyp_vm *vm = &selftest_vm;
+ struct pkvm_hyp_vcpu *vcpu;
u64 phys, size, pfn, gfn;
+ struct pkvm_hyp_vm *vm;
WARN_ON(!virt);
selftest_page = hyp_virt_to_page(virt);
selftest_page->refcount = 0;
- init_selftest_vm(base);
+ selftest_vcpu = vcpu = init_selftest_vm(base);
+ vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
size = PAGE_SIZE << selftest_page->order;
phys = hyp_virt_to_phys(virt);
@@ -1854,6 +1820,7 @@ void pkvm_ownership_selftest(void *base)
selftest_state.hyp = PKVM_PAGE_OWNED;
assert_transition_res(0, __pkvm_host_donate_hyp, pfn, 1);
+ teardown_selftest_vm();
selftest_page->refcount = 1;
hyp_put_page(&host_s2_pool, virt);
}
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index ebfd9904ede6..794a19fa911d 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -727,6 +727,55 @@ void __pkvm_unreserve_vm(pkvm_handle_t handle)
hyp_spin_unlock(&vm_table_lock);
}
+#ifdef CONFIG_NVHE_EL2_DEBUG
+static struct pkvm_hyp_vm selftest_vm = {
+ .kvm = {
+ .arch = {
+ .mmu = {
+ .arch = &selftest_vm.kvm.arch,
+ .pgt = &selftest_vm.pgt,
+ },
+ },
+ },
+};
+
+static struct pkvm_hyp_vcpu selftest_vcpu = {
+ .vcpu = {
+ .arch = {
+ .hw_mmu = &selftest_vm.kvm.arch.mmu,
+ },
+ .kvm = &selftest_vm.kvm,
+ },
+};
+
+struct pkvm_hyp_vcpu *init_selftest_vm(void *virt)
+{
+ struct hyp_page *p = hyp_virt_to_page(virt);
+ int i;
+
+ selftest_vm.kvm.arch.mmu.vtcr = host_mmu.arch.mmu.vtcr;
+ WARN_ON(kvm_guest_prepare_stage2(&selftest_vm, virt));
+
+ for (i = 0; i < pkvm_selftest_pages(); i++) {
+ if (p[i].refcount)
+ continue;
+ p[i].refcount = 1;
+ hyp_put_page(&selftest_vm.pool, hyp_page_to_virt(&p[i]));
+ }
+
+ selftest_vm.kvm.arch.pkvm.handle = __pkvm_reserve_vm();
+ insert_vm_table_entry(selftest_vm.kvm.arch.pkvm.handle, &selftest_vm);
+ return &selftest_vcpu;
+}
+
+void teardown_selftest_vm(void)
+{
+ hyp_spin_lock(&vm_table_lock);
+ remove_vm_table_entry(selftest_vm.kvm.arch.pkvm.handle);
+ hyp_spin_unlock(&vm_table_lock);
+}
+#endif /* CONFIG_NVHE_EL2_DEBUG */
+
/*
* Initialize the hypervisor copy of the VM state using host-donated memory.
*
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 35/38] KVM: arm64: Extend pKVM page ownership selftests to cover forced reclaim
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Extend the pKVM page ownership selftests to forcefully reclaim a donated
page and check that it cannot be re-donated at the same IPA.
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index b2c9ea105701..05a5b145e303 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -1813,8 +1813,20 @@ void pkvm_ownership_selftest(void *base)
assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
selftest_state.host = PKVM_PAGE_OWNED;
- selftest_state.guest[0] = PKVM_NOPAGE;
- assert_transition_res(0, __pkvm_host_reclaim_page_guest, gfn, vm);
+ selftest_state.guest[0] = PKVM_POISON;
+ assert_transition_res(0, __pkvm_host_force_reclaim_page_guest, phys);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
+
+ selftest_state.host = PKVM_NOPAGE;
+ selftest_state.guest[1] = PKVM_PAGE_OWNED;
+ assert_transition_res(0, __pkvm_host_donate_guest, pfn, gfn + 1, vcpu);
+
+ selftest_state.host = PKVM_PAGE_OWNED;
+ selftest_state.guest[1] = PKVM_NOPAGE;
+ assert_transition_res(0, __pkvm_host_reclaim_page_guest, gfn + 1, vm);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
selftest_state.host = PKVM_NOPAGE;
selftest_state.hyp = PKVM_PAGE_OWNED;
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 37/38] KVM: arm64: Rename PKVM_PAGE_STATE_MASK
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Rename PKVM_PAGE_STATE_MASK to PKVM_PAGE_STATE_VMEMMAP_MASK to make it
clear that the mask applies to the page state recorded in the entries
of the 'hyp_vmemmap', rather than page states stored elsewhere (e.g. in
the ptes).
Suggested-by: Alexandru Elisei <alexandru.elisei@arm.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/include/nvhe/memory.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h
index 4cedb720c75d..b50712d47f6d 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/memory.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h
@@ -37,7 +37,7 @@ enum pkvm_page_state {
*/
PKVM_POISON = BIT(2),
};
-#define PKVM_PAGE_STATE_MASK (BIT(0) | BIT(1))
+#define PKVM_PAGE_STATE_VMEMMAP_MASK (BIT(0) | BIT(1))
#define PKVM_PAGE_STATE_PROT_MASK (KVM_PGTABLE_PROT_SW0 | KVM_PGTABLE_PROT_SW1)
static inline enum kvm_pgtable_prot pkvm_mkstate(enum kvm_pgtable_prot prot,
@@ -114,12 +114,12 @@ static inline void set_host_state(struct hyp_page *p, enum pkvm_page_state state
static inline enum pkvm_page_state get_hyp_state(struct hyp_page *p)
{
- return p->__hyp_state_comp ^ PKVM_PAGE_STATE_MASK;
+ return p->__hyp_state_comp ^ PKVM_PAGE_STATE_VMEMMAP_MASK;
}
static inline void set_hyp_state(struct hyp_page *p, enum pkvm_page_state state)
{
- p->__hyp_state_comp = state ^ PKVM_PAGE_STATE_MASK;
+ p->__hyp_state_comp = state ^ PKVM_PAGE_STATE_VMEMMAP_MASK;
}
/*
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 32/38] KVM: arm64: Add some initial documentation for pKVM
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Add some initial documentation for pKVM to help people understand what
is supported, the limitations of protected VMs when compared to
non-protected VMs and also what is left to do.
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
.../admin-guide/kernel-parameters.txt | 4 +-
Documentation/virt/kvm/arm/index.rst | 1 +
Documentation/virt/kvm/arm/pkvm.rst | 106 ++++++++++++++++++
3 files changed, 109 insertions(+), 2 deletions(-)
create mode 100644 Documentation/virt/kvm/arm/pkvm.rst
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 03a550630644..44854a67bc63 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3247,8 +3247,8 @@ Kernel parameters
for the host. To force nVHE on VHE hardware, add
"arm64_sw.hvhe=0 id_aa64mmfr1.vh=0" to the
command-line.
- "nested" is experimental and should be used with
- extreme caution.
+ "nested" and "protected" are experimental and should be
+ used with extreme caution.
kvm-arm.vgic_v3_group0_trap=
[KVM,ARM,EARLY] Trap guest accesses to GICv3 group-0
diff --git a/Documentation/virt/kvm/arm/index.rst b/Documentation/virt/kvm/arm/index.rst
index ec09881de4cf..0856b4942e05 100644
--- a/Documentation/virt/kvm/arm/index.rst
+++ b/Documentation/virt/kvm/arm/index.rst
@@ -10,6 +10,7 @@ ARM
fw-pseudo-registers
hyp-abi
hypercalls
+ pkvm
pvtime
ptp_kvm
vcpu-features
diff --git a/Documentation/virt/kvm/arm/pkvm.rst b/Documentation/virt/kvm/arm/pkvm.rst
new file mode 100644
index 000000000000..514992a79a83
--- /dev/null
+++ b/Documentation/virt/kvm/arm/pkvm.rst
@@ -0,0 +1,106 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================
+Protected KVM (pKVM)
+====================
+
+**NOTE**: pKVM is currently an experimental, development feature and
+subject to breaking changes as new isolation features are implemented.
+Please reach out to the developers at kvmarm@lists.linux.dev if you have
+any questions.
+
+Overview
+========
+
+Booting a host kernel with '``kvm-arm.mode=protected``' enables
+"Protected KVM" (pKVM). During boot, pKVM installs a stage-2 identity
+map page-table for the host and uses it to isolate the hypervisor
+running at EL2 from the rest of the host running at EL1/0.
+
+pKVM permits creation of protected virtual machines (pVMs) by passing
+the ``KVM_VM_TYPE_ARM_PROTECTED`` machine type identifier to the
+``KVM_CREATE_VM`` ioctl(). The hypervisor isolates pVMs from the host by
+unmapping pages from the stage-2 identity map as they are accessed by a
+pVM. Hypercalls are provided for a pVM to share specific regions of its
+IPA space back with the host, allowing for communication with the VMM.
+A Linux guest must be configured with ``CONFIG_ARM_PKVM_GUEST=y`` in
+order to issue these hypercalls.
+
+See hypercalls.rst for more details.
+
+Isolation mechanisms
+====================
+
+pKVM relies on a number of mechanisms to isolate PVMs from the host:
+
+CPU memory isolation
+--------------------
+
+Status: Isolation of anonymous memory and metadata pages.
+
+Metadata pages (e.g. page-table pages and '``struct kvm_vcpu``' pages)
+are donated from the host to the hypervisor during pVM creation and
+are consequently unmapped from the stage-2 identity map until the pVM is
+destroyed.
+
+Similarly to regular KVM, pages are lazily mapped into the guest in
+response to stage-2 page faults handled by the host. However, when
+running a pVM, these pages are first pinned and then unmapped from the
+stage-2 identity map as part of the donation procedure. This gives rise
+to some user-visible differences when compared to non-protected VMs,
+largely due to the lack of MMU notifiers:
+
+* Memslots cannot be moved or deleted once the pVM has started running.
+* Read-only memslots and dirty logging are not supported.
+* With the exception of swap, file-backed pages cannot be mapped into a
+ pVM.
+* Donated pages are accounted against ``RLIMIT_MLOCK`` and so the VMM
+ must have a sufficient resource limit or be granted ``CAP_IPC_LOCK``.
+ The lack of a runtime reclaim mechanism means that memory locked for
+ a pVM will remain locked until the pVM is destroyed.
+* Changes to the VMM address space (e.g. a ``MAP_FIXED`` mmap() over a
+ mapping associated with a memslot) are not reflected in the guest and
+ may lead to loss of coherency.
+* Accessing pVM memory that has not been shared back will result in the
+ delivery of a SIGSEGV.
+* If a system call accesses pVM memory that has not been shared back
+ then it will either return ``-EFAULT`` or forcefully reclaim the
+ memory pages. Reclaimed memory is zeroed by the hypervisor and a
+ subsequent attempt to access it in the pVM will return ``-EFAULT``
+ from the ``VCPU_RUN`` ioctl().
+
+CPU state isolation
+-------------------
+
+Status: **Unimplemented.**
+
+DMA isolation using an IOMMU
+----------------------------
+
+Status: **Unimplemented.**
+
+Proxying of Trustzone services
+------------------------------
+
+Status: FF-A and PSCI calls from the host are proxied by the pKVM
+hypervisor.
+
+The FF-A proxy ensures that the host cannot share pVM or hypervisor
+memory with Trustzone as part of a "confused deputy" attack.
+
+The PSCI proxy ensures that CPUs always have the stage-2 identity map
+installed when they are executing in the host.
+
+Protected VM firmware (pvmfw)
+-----------------------------
+
+Status: **Unimplemented.**
+
+Resources
+=========
+
+Quentin Perret's KVM Forum 2022 talk entitled "Protected KVM on arm64: A
+technical deep dive" remains a good resource for learning more about
+pKVM, despite some of the details having changed in the meantime:
+
+https://www.youtube.com/watch?v=9npebeVFbFw
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 33/38] KVM: arm64: Extend pKVM page ownership selftests to cover guest donation
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Extend the pKVM page ownership selftests to donate and reclaim a page
to/from a guest.
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 898bd5d767ce..6525f9fa274c 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -1749,6 +1749,7 @@ void pkvm_ownership_selftest(void *base)
assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size);
assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, 1, vm);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
selftest_state.host = PKVM_PAGE_OWNED;
selftest_state.hyp = PKVM_NOPAGE;
@@ -1768,6 +1769,7 @@ void pkvm_ownership_selftest(void *base)
assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, 1, vm);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
assert_transition_res(0, hyp_pin_shared_mem, virt, virt + size);
assert_transition_res(0, hyp_pin_shared_mem, virt, virt + size);
@@ -1780,6 +1782,7 @@ void pkvm_ownership_selftest(void *base)
assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, 1, vm);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
hyp_unpin_shared_mem(virt, virt + size);
assert_page_state();
@@ -1799,6 +1802,7 @@ void pkvm_ownership_selftest(void *base)
assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
assert_transition_res(-ENOENT, __pkvm_host_unshare_guest, gfn, 1, vm);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size);
selftest_state.host = PKVM_PAGE_OWNED;
@@ -1815,6 +1819,7 @@ void pkvm_ownership_selftest(void *base)
assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn);
assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn);
assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
assert_transition_res(-EPERM, hyp_pin_shared_mem, virt, virt + size);
selftest_state.guest[1] = PKVM_PAGE_SHARED_BORROWED;
@@ -1828,6 +1833,23 @@ void pkvm_ownership_selftest(void *base)
selftest_state.host = PKVM_PAGE_OWNED;
assert_transition_res(0, __pkvm_host_unshare_guest, gfn + 1, 1, vm);
+ selftest_state.host = PKVM_NOPAGE;
+ selftest_state.guest[0] = PKVM_PAGE_OWNED;
+ assert_transition_res(0, __pkvm_host_donate_guest, pfn, gfn, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_donate_guest, pfn, gfn + 1, vcpu);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn, 1, vcpu, prot);
+ assert_transition_res(-EPERM, __pkvm_host_share_guest, pfn, gfn + 1, 1, vcpu, prot);
+ assert_transition_res(-EPERM, __pkvm_host_share_ffa, pfn, 1);
+ assert_transition_res(-EPERM, __pkvm_host_donate_hyp, pfn, 1);
+ assert_transition_res(-EPERM, __pkvm_host_share_hyp, pfn);
+ assert_transition_res(-EPERM, __pkvm_host_unshare_hyp, pfn);
+ assert_transition_res(-EPERM, __pkvm_hyp_donate_host, pfn, 1);
+
+ selftest_state.host = PKVM_PAGE_OWNED;
+ selftest_state.guest[0] = PKVM_NOPAGE;
+ assert_transition_res(0, __pkvm_host_reclaim_page_guest, gfn, vm);
+
selftest_state.host = PKVM_NOPAGE;
selftest_state.hyp = PKVM_PAGE_OWNED;
assert_transition_res(0, __pkvm_host_donate_hyp, pfn, 1);
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 30/38] KVM: arm64: Implement the MEM_UNSHARE hypercall for protected VMs
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Implement the ARM_SMCCC_KVM_FUNC_MEM_UNSHARE hypercall to allow
protected VMs to unshare memory that was previously shared with the host
using the ARM_SMCCC_KVM_FUNC_MEM_SHARE hypercall.
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 1 +
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 34 +++++++++++++++++++
arch/arm64/kvm/hyp/nvhe/pkvm.c | 22 ++++++++++++
3 files changed, 57 insertions(+)
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index fea8aecae5ef..99d8398afe20 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -35,6 +35,7 @@ extern unsigned long hyp_nr_cpus;
int __pkvm_prot_finalize(void);
int __pkvm_host_share_hyp(u64 pfn);
int __pkvm_guest_share_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn);
+int __pkvm_guest_unshare_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn);
int __pkvm_host_unshare_hyp(u64 pfn);
int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages);
int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages);
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index e005a5690c65..898bd5d767ce 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -991,6 +991,40 @@ int __pkvm_guest_share_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn)
return ret;
}
+int __pkvm_guest_unshare_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn)
+{
+ struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
+ u64 meta, phys, ipa = hyp_pfn_to_phys(gfn);
+ kvm_pte_t pte;
+ int ret;
+
+ host_lock_component();
+ guest_lock_component(vm);
+
+ ret = get_valid_guest_pte(vm, ipa, &pte, &phys);
+ if (ret)
+ goto unlock;
+
+ ret = -EPERM;
+ if (pkvm_getstate(kvm_pgtable_stage2_pte_prot(pte)) != PKVM_PAGE_SHARED_OWNED)
+ goto unlock;
+ if (__host_check_page_state_range(phys, PAGE_SIZE, PKVM_PAGE_SHARED_BORROWED))
+ goto unlock;
+
+ ret = 0;
+ meta = host_stage2_encode_gfn_meta(vm, gfn);
+ WARN_ON(host_stage2_set_owner_metadata_locked(phys, PAGE_SIZE,
+ PKVM_ID_GUEST, meta));
+ WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, PAGE_SIZE, phys,
+ pkvm_mkstate(KVM_PGTABLE_PROT_RWX, PKVM_PAGE_OWNED),
+ &vcpu->vcpu.arch.pkvm_memcache, 0));
+unlock:
+ guest_unlock_component(vm);
+ host_unlock_component();
+
+ return ret;
+}
+
int __pkvm_host_unshare_hyp(u64 pfn)
{
u64 phys = hyp_pfn_to_phys(pfn);
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 1dc9225073c4..ebfd9904ede6 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -1019,6 +1019,19 @@ static bool pkvm_memshare_call(u64 *ret, struct kvm_vcpu *vcpu, u64 *exit_code)
return false;
}
+static void pkvm_memunshare_call(u64 *ret, struct kvm_vcpu *vcpu)
+{
+ struct pkvm_hyp_vcpu *hyp_vcpu;
+ u64 ipa = smccc_get_arg1(vcpu);
+
+ if (!PAGE_ALIGNED(ipa))
+ return;
+
+ hyp_vcpu = container_of(vcpu, struct pkvm_hyp_vcpu, vcpu);
+ if (!__pkvm_guest_unshare_host(hyp_vcpu, hyp_phys_to_pfn(ipa)))
+ ret[0] = SMCCC_RET_SUCCESS;
+}
+
/*
* Handler for protected VM HVC calls.
*
@@ -1036,6 +1049,7 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO);
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_SHARE);
+ val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_UNSHARE);
break;
case ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID:
if (smccc_get_arg1(vcpu) ||
@@ -1054,6 +1068,14 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
handled = pkvm_memshare_call(val, vcpu, exit_code);
break;
+ case ARM_SMCCC_VENDOR_HYP_KVM_MEM_UNSHARE_FUNC_ID:
+ if (smccc_get_arg2(vcpu) ||
+ smccc_get_arg3(vcpu)) {
+ break;
+ }
+
+ pkvm_memunshare_call(val, vcpu);
+ break;
default:
/* Punt everything else back to the host, for now. */
handled = false;
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 29/38] KVM: arm64: Implement the MEM_SHARE hypercall for protected VMs
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Implement the ARM_SMCCC_KVM_FUNC_MEM_SHARE hypercall to allow protected
VMs to share memory (e.g. the swiotlb bounce buffers) back to the host.
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 1 +
arch/arm64/kvm/hyp/nvhe/mem_protect.c | 32 ++++++++++
arch/arm64/kvm/hyp/nvhe/pkvm.c | 61 +++++++++++++++++++
3 files changed, 94 insertions(+)
diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
index 8bc9a2489298..fea8aecae5ef 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
@@ -34,6 +34,7 @@ extern unsigned long hyp_nr_cpus;
int __pkvm_prot_finalize(void);
int __pkvm_host_share_hyp(u64 pfn);
+int __pkvm_guest_share_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn);
int __pkvm_host_unshare_hyp(u64 pfn);
int __pkvm_host_donate_hyp(u64 pfn, u64 nr_pages);
int __pkvm_hyp_donate_host(u64 pfn, u64 nr_pages);
diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
index 6fc2c77a6920..e005a5690c65 100644
--- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c
+++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c
@@ -959,6 +959,38 @@ int __pkvm_host_share_hyp(u64 pfn)
return ret;
}
+int __pkvm_guest_share_host(struct pkvm_hyp_vcpu *vcpu, u64 gfn)
+{
+ struct pkvm_hyp_vm *vm = pkvm_hyp_vcpu_to_hyp_vm(vcpu);
+ u64 phys, ipa = hyp_pfn_to_phys(gfn);
+ kvm_pte_t pte;
+ int ret;
+
+ host_lock_component();
+ guest_lock_component(vm);
+
+ ret = get_valid_guest_pte(vm, ipa, &pte, &phys);
+ if (ret)
+ goto unlock;
+
+ ret = -EPERM;
+ if (pkvm_getstate(kvm_pgtable_stage2_pte_prot(pte)) != PKVM_PAGE_OWNED)
+ goto unlock;
+ if (__host_check_page_state_range(phys, PAGE_SIZE, PKVM_NOPAGE))
+ goto unlock;
+
+ ret = 0;
+ WARN_ON(kvm_pgtable_stage2_map(&vm->pgt, ipa, PAGE_SIZE, phys,
+ pkvm_mkstate(KVM_PGTABLE_PROT_RWX, PKVM_PAGE_SHARED_OWNED),
+ &vcpu->vcpu.arch.pkvm_memcache, 0));
+ WARN_ON(__host_set_page_state_range(phys, PAGE_SIZE, PKVM_PAGE_SHARED_BORROWED));
+unlock:
+ guest_unlock_component(vm);
+ host_unlock_component();
+
+ return ret;
+}
+
int __pkvm_host_unshare_hyp(u64 pfn)
{
u64 phys = hyp_pfn_to_phys(pfn);
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 8b32bf37acc3..1dc9225073c4 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -967,6 +967,58 @@ int __pkvm_finalize_teardown_vm(pkvm_handle_t handle)
hyp_spin_unlock(&vm_table_lock);
return err;
}
+
+static u64 __pkvm_memshare_page_req(struct kvm_vcpu *vcpu, u64 ipa)
+{
+ u64 elr;
+
+ /* Fake up a data abort (level 3 translation fault on write) */
+ vcpu->arch.fault.esr_el2 = (ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT) |
+ ESR_ELx_WNR | ESR_ELx_FSC_FAULT |
+ FIELD_PREP(ESR_ELx_FSC_LEVEL, 3);
+
+ /* Shuffle the IPA around into the HPFAR */
+ vcpu->arch.fault.hpfar_el2 = (HPFAR_EL2_NS | (ipa >> 8)) & HPFAR_MASK;
+
+ /* This is a virtual address. 0's good. Let's go with 0. */
+ vcpu->arch.fault.far_el2 = 0;
+
+ /* Rewind the ELR so we return to the HVC once the IPA is mapped */
+ elr = read_sysreg(elr_el2);
+ elr -= 4;
+ write_sysreg(elr, elr_el2);
+
+ return ARM_EXCEPTION_TRAP;
+}
+
+static bool pkvm_memshare_call(u64 *ret, struct kvm_vcpu *vcpu, u64 *exit_code)
+{
+ struct pkvm_hyp_vcpu *hyp_vcpu;
+ u64 ipa = smccc_get_arg1(vcpu);
+
+ if (!PAGE_ALIGNED(ipa))
+ goto out_guest;
+
+ hyp_vcpu = container_of(vcpu, struct pkvm_hyp_vcpu, vcpu);
+ switch (__pkvm_guest_share_host(hyp_vcpu, hyp_phys_to_pfn(ipa))) {
+ case 0:
+ ret[0] = SMCCC_RET_SUCCESS;
+ goto out_guest;
+ case -ENOENT:
+ /*
+ * Convert the exception into a data abort so that the page
+ * being shared is mapped into the guest next time.
+ */
+ *exit_code = __pkvm_memshare_page_req(vcpu, ipa);
+ goto out_host;
+ }
+
+out_guest:
+ return true;
+out_host:
+ return false;
+}
+
/*
* Handler for protected VM HVC calls.
*
@@ -983,6 +1035,7 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);
val[0] |= BIT(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO);
+ val[0] |= BIT(ARM_SMCCC_KVM_FUNC_MEM_SHARE);
break;
case ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID:
if (smccc_get_arg1(vcpu) ||
@@ -993,6 +1046,14 @@ bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
val[0] = PAGE_SIZE;
break;
+ case ARM_SMCCC_VENDOR_HYP_KVM_MEM_SHARE_FUNC_ID:
+ if (smccc_get_arg2(vcpu) ||
+ smccc_get_arg3(vcpu)) {
+ break;
+ }
+
+ handled = pkvm_memshare_call(val, vcpu, exit_code);
+ break;
default:
/* Punt everything else back to the host, for now. */
handled = false;
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 28/38] KVM: arm64: Add hvc handler at EL2 for hypercalls from protected VMs
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Add a hypercall handler at EL2 for hypercalls originating from protected
VMs. For now, this implements only the FEATURES and MEMINFO calls, but
subsequent patches will implement the SHARE and UNSHARE functions
necessary for virtio.
Unhandled hypercalls (including PSCI) are passed back to the host.
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/include/nvhe/pkvm.h | 1 +
arch/arm64/kvm/hyp/nvhe/pkvm.c | 37 ++++++++++++++++++++++++++
arch/arm64/kvm/hyp/nvhe/switch.c | 1 +
3 files changed, 39 insertions(+)
diff --git a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
index a5a7bb453f3e..c904647d2f76 100644
--- a/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
+++ b/arch/arm64/kvm/hyp/include/nvhe/pkvm.h
@@ -88,6 +88,7 @@ struct pkvm_hyp_vm *get_pkvm_hyp_vm(pkvm_handle_t handle);
struct pkvm_hyp_vm *get_np_pkvm_hyp_vm(pkvm_handle_t handle);
void put_pkvm_hyp_vm(struct pkvm_hyp_vm *hyp_vm);
+bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code);
bool kvm_handle_pvm_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code);
bool kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu, u64 *exit_code);
void kvm_init_pvm_id_regs(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 5269ac20d2fb..8b32bf37acc3 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -4,6 +4,8 @@
* Author: Fuad Tabba <tabba@google.com>
*/
+#include <kvm/arm_hypercalls.h>
+
#include <linux/kvm_host.h>
#include <linux/mm.h>
@@ -965,3 +967,38 @@ int __pkvm_finalize_teardown_vm(pkvm_handle_t handle)
hyp_spin_unlock(&vm_table_lock);
return err;
}
+/*
+ * Handler for protected VM HVC calls.
+ *
+ * Returns true if the hypervisor has handled the exit (and control
+ * should return to the guest) or false if it hasn't (and the handling
+ * should be performed by the host).
+ */
+bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code)
+{
+ u64 val[4] = { SMCCC_RET_INVALID_PARAMETER };
+ bool handled = true;
+
+ switch (smccc_get_function(vcpu)) {
+ case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
+ val[0] = BIT(ARM_SMCCC_KVM_FUNC_FEATURES);
+ val[0] |= BIT(ARM_SMCCC_KVM_FUNC_HYP_MEMINFO);
+ break;
+ case ARM_SMCCC_VENDOR_HYP_KVM_HYP_MEMINFO_FUNC_ID:
+ if (smccc_get_arg1(vcpu) ||
+ smccc_get_arg2(vcpu) ||
+ smccc_get_arg3(vcpu)) {
+ break;
+ }
+
+ val[0] = PAGE_SIZE;
+ break;
+ default:
+ /* Punt everything else back to the host, for now. */
+ handled = false;
+ }
+
+ if (handled)
+ smccc_set_retval(vcpu, val[0], val[1], val[2], val[3]);
+ return handled;
+}
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index 779089e42681..51bd88dc6012 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -190,6 +190,7 @@ static const exit_handler_fn hyp_exit_handlers[] = {
static const exit_handler_fn pvm_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX] = NULL,
+ [ESR_ELx_EC_HVC64] = kvm_handle_pvm_hvc64,
[ESR_ELx_EC_SYS64] = kvm_handle_pvm_sys64,
[ESR_ELx_EC_SVE] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_FP_ASIMD] = kvm_hyp_handle_fpsimd,
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
* [PATCH v4 31/38] KVM: arm64: Allow userspace to create protected VMs when pKVM is enabled
From: Will Deacon @ 2026-03-27 14:00 UTC (permalink / raw)
To: kvmarm
Cc: linux-arm-kernel, Will Deacon, Marc Zyngier, Oliver Upton,
Joey Gouly, Suzuki K Poulose, Zenghui Yu, Catalin Marinas,
Quentin Perret, Fuad Tabba, Vincent Donnefort, Mostafa Saleh,
Alexandru Elisei
In-Reply-To: <20260327140039.21228-1-will@kernel.org>
Introduce a new VM type for KVM/arm64 to allow userspace to request the
creation of a "protected VM" when the host has booted with pKVM enabled.
For now, this feature results in a taint on first use as many aspects of
a protected VM are not yet protected!
Tested-by: Fuad Tabba <tabba@google.com>
Tested-by: Mostafa Saleh <smostafa@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/kvm_pkvm.h | 2 +-
arch/arm64/kvm/arm.c | 8 +++++++-
arch/arm64/kvm/mmu.c | 3 ---
arch/arm64/kvm/pkvm.c | 8 +++++++-
include/uapi/linux/kvm.h | 5 +++++
5 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h
index 7041e398fb4c..2954b311128c 100644
--- a/arch/arm64/include/asm/kvm_pkvm.h
+++ b/arch/arm64/include/asm/kvm_pkvm.h
@@ -17,7 +17,7 @@
#define HYP_MEMBLOCK_REGIONS 128
-int pkvm_init_host_vm(struct kvm *kvm);
+int pkvm_init_host_vm(struct kvm *kvm, unsigned long type);
int pkvm_create_hyp_vm(struct kvm *kvm);
bool pkvm_hyp_vm_is_created(struct kvm *kvm);
void pkvm_destroy_hyp_vm(struct kvm *kvm);
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3589fc08266c..c2b666a46893 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -203,6 +203,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
int ret;
+ if (type & ~KVM_VM_TYPE_ARM_MASK)
+ return -EINVAL;
+
mutex_init(&kvm->arch.config_lock);
#ifdef CONFIG_LOCKDEP
@@ -234,9 +237,12 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
* If any failures occur after this is successful, make sure to
* call __pkvm_unreserve_vm to unreserve the VM in hyp.
*/
- ret = pkvm_init_host_vm(kvm);
+ ret = pkvm_init_host_vm(kvm, type);
if (ret)
goto err_uninit_mmu;
+ } else if (type & KVM_VM_TYPE_ARM_PROTECTED) {
+ ret = -EINVAL;
+ goto err_uninit_mmu;
}
kvm_vgic_early_init(kvm);
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 6a4151e3e4a3..45358ae8a300 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -881,9 +881,6 @@ static int kvm_init_ipa_range(struct kvm_s2_mmu *mmu, unsigned long type)
u64 mmfr0, mmfr1;
u32 phys_shift;
- if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
- return -EINVAL;
-
phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
if (is_protected_kvm_enabled()) {
phys_shift = kvm_ipa_limit;
diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c
index da0a45dab203..632852648012 100644
--- a/arch/arm64/kvm/pkvm.c
+++ b/arch/arm64/kvm/pkvm.c
@@ -219,9 +219,10 @@ void pkvm_destroy_hyp_vm(struct kvm *kvm)
mutex_unlock(&kvm->arch.config_lock);
}
-int pkvm_init_host_vm(struct kvm *kvm)
+int pkvm_init_host_vm(struct kvm *kvm, unsigned long type)
{
int ret;
+ bool protected = type & KVM_VM_TYPE_ARM_PROTECTED;
if (pkvm_hyp_vm_is_created(kvm))
return -EINVAL;
@@ -236,6 +237,11 @@ int pkvm_init_host_vm(struct kvm *kvm)
return ret;
kvm->arch.pkvm.handle = ret;
+ kvm->arch.pkvm.is_protected = protected;
+ if (protected) {
+ pr_warn_once("kvm: protected VMs are experimental and for development only, tainting kernel\n");
+ add_taint(TAINT_USER, LOCKDEP_STILL_OK);
+ }
return 0;
}
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 80364d4dbebb..073b2bcaf560 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -703,6 +703,11 @@ struct kvm_enable_cap {
#define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL
#define KVM_VM_TYPE_ARM_IPA_SIZE(x) \
((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
+
+#define KVM_VM_TYPE_ARM_PROTECTED (1UL << 31)
+#define KVM_VM_TYPE_ARM_MASK (KVM_VM_TYPE_ARM_IPA_SIZE_MASK | \
+ KVM_VM_TYPE_ARM_PROTECTED)
+
/*
* ioctls for /dev/kvm fds:
*/
--
2.53.0.1018.g2bb0e51243-goog
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox