* Re: Constantly map and unmap of streaming DMA buffers with IOMMU backend might cause serious performance problem
From: Robin Murphy @ 2020-05-15 22:12 UTC (permalink / raw)
To: Song Bao Hua, hch@lst.de
Cc: davidm@hpl.hp.com, ralf@oss.sgi.com, Linuxarm,
linux@armlinux.org.uk, iommu@lists.linux-foundation.org,
sailer@ife.ee.ethz.ch, Jay.Estabrook@compaq.com,
dagum@barrel.engr.sgi.com, andrea@suse.de, grundler@cup.hp.com,
jens.axboe@oracle.com, linux-arm-kernel@lists.infradead.org,
m.szyprowski@samsung.com
In-Reply-To: <B926444035E5E2439431908E3842AFD249F9F4@DGGEMI525-MBS.china.huawei.com>
On 2020-05-15 22:33, Song Bao Hua wrote:
>> Subject: Re: Constantly map and unmap of streaming DMA buffers with
>> IOMMU backend might cause serious performance problem
>>
>> On Fri, May 15, 2020 at 01:10:21PM +0100, Robin Murphy wrote:
>>>> Meanwhile, for the safety of buffers, lower-layer drivers need to make
>> certain the buffers have already been unmapped in iommu before those
>> buffers go back to buddy for other users.
>>>
>>> That sounds like it would only have benefit in a very small set of specific
>>> circumstances, and would be very difficult to generalise to buffers that
>>> are mapped via dma_map_page() or dma_map_single(). Furthermore, a
>>> high-level API that affects a low-level driver's interpretation of
>>> mid-layer API calls without the mid-layer's knowledge sounds like a hideous
>>> abomination of anti-design. If a mid-layer API lends itself to inefficiency
>>> at the lower level, it would seem a lot cleaner and more robust to extend
>>> *that* API for stateful buffer reuse. Failing that, it might possibly be
>>> appropriate to approach this at the driver level - many of the cleverer
>>> network drivers already implement buffer pools to recycle mapped SKBs
>>> internally, couldn't the "zip driver" simply try doing something like that
>>> for itself?
>>
>> Exactly. If you upper consumer of the DMA API keeps reusing the same
>> pages just map them once and use dma_sync_* to transfer ownership as
>> needed.
>
> The problem is that the lower-layer drivers don't know if upper consumer keeps reusing the same pages. They are running in different software layers.
> For example, Consumer is here in mm/zswap.c
> static int zswap_frontswap_store(unsigned type, pgoff_t offset,
> struct page *page)
> {
> ...
> /* compress */
> dst = get_cpu_var(zswap_dstmem);
> ...
> ret = crypto_comp_compress(tfm, src, PAGE_SIZE, dst, &dlen);
> ...
> }
>
> But the lower-layer driver is in drivers/crypto/...
>
> Meanwhile, the lower-layer driver couldn't cache the pointers of buffer address coming from consumers to detect if the upper-layer is using the same page.
> Because the same page might come from different users or come from the different stages of the same user with different permissions.
Indeed the driver can't cache arbitrary pointers, but if typical buffers
are small enough it can copy the data into its own already-mapped page,
dma_sync it, and perform the DMA operation from there. That might even
be more or less what your first suggestion was, but I'm still not quite
sure.
> For example, consumer A uses the buffer as destination, then returns it to buddy, but consumer B gets the same buffer and uses it as source.
>
> Another possibility is
> Consumer A uses the buffer, returns it to buddy, after some time, it allocates a buffer again, but gets the same buffer from buddy like before.
>
> For the safety of the buffer, lower-layer driver must guarantee the buffer is unmapped when the buffer returns to buddy.
>
> I think only the upper-layer consumer knows if it is reusing the buffer.
Right, and if reusing buffers is common in crypto callers, then there's
an argument for "set up reusable buffer", "process updated buffer" and
"clean up buffer" operations to be added to the crypto API itself, such
that the underlying drivers can then optimise for DMA usage in a robust
and obvious way if they want to (or just implement the setup and
teardown as no-ops and still do a full map/unmap in each "process" call
if they don't).
Robin.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* RE: Constantly map and unmap of streaming DMA buffers with IOMMU backend might cause serious performance problem
From: Song Bao Hua @ 2020-05-15 21:33 UTC (permalink / raw)
To: hch@lst.de, Robin Murphy
Cc: davidm@hpl.hp.com, ralf@oss.sgi.com, Linuxarm,
linux@armlinux.org.uk, iommu@lists.linux-foundation.org,
sailer@ife.ee.ethz.ch, Jay.Estabrook@compaq.com,
dagum@barrel.engr.sgi.com, andrea@suse.de, grundler@cup.hp.com,
jens.axboe@oracle.com, linux-arm-kernel@lists.infradead.org,
m.szyprowski@samsung.com
In-Reply-To: <20200515144522.GA25652@lst.de>
> Subject: Re: Constantly map and unmap of streaming DMA buffers with
> IOMMU backend might cause serious performance problem
>
> On Fri, May 15, 2020 at 01:10:21PM +0100, Robin Murphy wrote:
> >> Meanwhile, for the safety of buffers, lower-layer drivers need to make
> certain the buffers have already been unmapped in iommu before those
> buffers go back to buddy for other users.
> >
> > That sounds like it would only have benefit in a very small set of specific
> > circumstances, and would be very difficult to generalise to buffers that
> > are mapped via dma_map_page() or dma_map_single(). Furthermore, a
> > high-level API that affects a low-level driver's interpretation of
> > mid-layer API calls without the mid-layer's knowledge sounds like a hideous
> > abomination of anti-design. If a mid-layer API lends itself to inefficiency
> > at the lower level, it would seem a lot cleaner and more robust to extend
> > *that* API for stateful buffer reuse. Failing that, it might possibly be
> > appropriate to approach this at the driver level - many of the cleverer
> > network drivers already implement buffer pools to recycle mapped SKBs
> > internally, couldn't the "zip driver" simply try doing something like that
> > for itself?
>
> Exactly. If you upper consumer of the DMA API keeps reusing the same
> pages just map them once and use dma_sync_* to transfer ownership as
> needed.
The problem is that the lower-layer drivers don't know if upper consumer keeps reusing the same pages. They are running in different software layers.
For example, Consumer is here in mm/zswap.c
static int zswap_frontswap_store(unsigned type, pgoff_t offset,
struct page *page)
{
...
/* compress */
dst = get_cpu_var(zswap_dstmem);
...
ret = crypto_comp_compress(tfm, src, PAGE_SIZE, dst, &dlen);
...
}
But the lower-layer driver is in drivers/crypto/...
Meanwhile, the lower-layer driver couldn't cache the pointers of buffer address coming from consumers to detect if the upper-layer is using the same page.
Because the same page might come from different users or come from the different stages of the same user with different permissions.
For example, consumer A uses the buffer as destination, then returns it to buddy, but consumer B gets the same buffer and uses it as source.
Another possibility is
Consumer A uses the buffer, returns it to buddy, after some time, it allocates a buffer again, but gets the same buffer from buddy like before.
For the safety of the buffer, lower-layer driver must guarantee the buffer is unmapped when the buffer returns to buddy.
I think only the upper-layer consumer knows if it is reusing the buffer.
Thanks
Barry
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 1/4] PCI/ATS: Only enable ATS for trusted devices
From: Bjorn Helgaas @ 2020-05-15 21:18 UTC (permalink / raw)
To: Jean-Philippe Brucker
Cc: alex.williamson, ashok.raj, linux-pci, joro, robin.murphy, iommu,
bhelgaas, will, dwmw2, linux-arm-kernel, baolu.lu
In-Reply-To: <20200515104359.1178606-2-jean-philippe@linaro.org>
On Fri, May 15, 2020 at 12:43:59PM +0200, Jean-Philippe Brucker wrote:
> Add pci_ats_supported(), which checks whether a device has an ATS
> capability, and whether it is trusted. A device is untrusted if it is
> plugged into an external-facing port such as Thunderbolt and could be
> spoof an existing device to exploit weaknesses in the IOMMU
> configuration. PCIe ATS is one such weaknesses since it allows
> endpoints to cache IOMMU translations and emit transactions with
> 'Translated' Address Type (10b) that partially bypass the IOMMU
> translation.
>
> The SMMUv3 and VT-d IOMMU drivers already disallow ATS and transactions
> with 'Translated' Address Type for untrusted devices. Add the check to
> pci_enable_ats() to let other drivers (AMD IOMMU for now) benefit from
> it.
>
> By checking ats_cap, the pci_ats_supported() helper also returns whether
> ATS was globally disabled with pci=noats, and could later include more
> things, for example whether the whole PCIe hierarchy down to the
> endpoint supports ATS.
>
> Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
> ---
> include/linux/pci-ats.h | 3 +++
> drivers/pci/ats.c | 18 +++++++++++++++++-
> 2 files changed, 20 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h
> index d08f0869f1213e..f75c307f346de9 100644
> --- a/include/linux/pci-ats.h
> +++ b/include/linux/pci-ats.h
> @@ -6,11 +6,14 @@
>
> #ifdef CONFIG_PCI_ATS
> /* Address Translation Service */
> +bool pci_ats_supported(struct pci_dev *dev);
> int pci_enable_ats(struct pci_dev *dev, int ps);
> void pci_disable_ats(struct pci_dev *dev);
> int pci_ats_queue_depth(struct pci_dev *dev);
> int pci_ats_page_aligned(struct pci_dev *dev);
> #else /* CONFIG_PCI_ATS */
> +static inline bool pci_ats_supported(struct pci_dev *d)
> +{ return false; }
> static inline int pci_enable_ats(struct pci_dev *d, int ps)
> { return -ENODEV; }
> static inline void pci_disable_ats(struct pci_dev *d) { }
> diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
> index 390e92f2d8d1fc..15fa0c37fd8e44 100644
> --- a/drivers/pci/ats.c
> +++ b/drivers/pci/ats.c
> @@ -30,6 +30,22 @@ void pci_ats_init(struct pci_dev *dev)
> dev->ats_cap = pos;
> }
>
> +/**
> + * pci_ats_supported - check if the device can use ATS
> + * @dev: the PCI device
> + *
> + * Returns true if the device supports ATS and is allowed to use it, false
> + * otherwise.
> + */
> +bool pci_ats_supported(struct pci_dev *dev)
> +{
> + if (!dev->ats_cap)
> + return false;
> +
> + return !dev->untrusted;
> +}
> +EXPORT_SYMBOL_GPL(pci_ats_supported);
> +
> /**
> * pci_enable_ats - enable the ATS capability
> * @dev: the PCI device
> @@ -42,7 +58,7 @@ int pci_enable_ats(struct pci_dev *dev, int ps)
> u16 ctrl;
> struct pci_dev *pdev;
>
> - if (!dev->ats_cap)
> + if (!pci_ats_supported(dev))
> return -EINVAL;
>
> if (WARN_ON(dev->ats_enabled))
> --
> 2.26.2
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: kexec: arm: possible overwrite of initrd
From: Russell King - ARM Linux admin @ 2020-05-15 21:06 UTC (permalink / raw)
To: Corentin Labbe; +Cc: kexec, ebiederm, linux-arm-kernel, linux-kernel
In-Reply-To: <20200515135712.GA5979@Red>
On Fri, May 15, 2020 at 03:57:12PM +0200, Corentin Labbe wrote:
> Hello
>
> Following https://lkml.org/lkml/2020/4/6/96 I was able to boot my Cubieboard4 via kexec reliabily.
You can try increasing the kernel size that kexec thinks the kernel
needs, but it should be extremely accurate with modern kexec.
--image-size $((0x01dc8154 + 0x10000))
will add 64k on top of what you currently have. Note where the first
figure comes from (you'll find it in the debug output, see
"Resulting kernel space").
The best I can say is try playing around with that - but, kexec's
calculations should be spot on to stop the booting kernel from
overwriting the initrd.
The only way to debug that is to get the booted kernel to hexdump the
initrd so it's possible to see what happened to it.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 10.2Mbps down 587kbps up
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v4 3/4] soc: amlogic: meson-ee-pwrc: add support for Meson8/Meson8b/Meson8m2
From: Martin Blumenstingl @ 2020-05-15 20:47 UTC (permalink / raw)
To: khilman, linux-amlogic
Cc: devicetree, narmstrong, Martin Blumenstingl, linux-kernel,
robh+dt, linux-arm-kernel
In-Reply-To: <20200515204709.1505498-1-martin.blumenstingl@googlemail.com>
This adds support for the power domains on Meson8/Meson8b/Meson8m2.
Meson8 doesn't use any reset lines while Meson8b and Meson8m2 use the
same set of reset lines (which is different from the newer SoCs).
Add dedicated compatible strings for Meson8, Meson8b and Meson8m2 to
support these differences.
Notable differences between Meson8 and G12A are:
- there is no HHI_VPU_MEM_PD_REG2 on the 32-bit SoCs
- the Meson8b datasheet describes an "audio DSP memory" power domain
which is used for the hardware audio decoder
- the "amlogic,ao-sysctrl" only includes the power management related
registers on the 32-bit SoCs, meaning the for example the
AO_RTI_GEN_PWR_SLEEP0 register is at offset (0x2 << 2) rather than
(0x3a << 2). As result of this (0x38 << 2) is subtracted from the
register offsets, which is the start of the power management related
registers.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/soc/amlogic/meson-ee-pwrc.c | 86 ++++++++++++++++++++++++++---
1 file changed, 77 insertions(+), 9 deletions(-)
diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c
index 3f0261d53ad9..390eb0dd0a79 100644
--- a/drivers/soc/amlogic/meson-ee-pwrc.c
+++ b/drivers/soc/amlogic/meson-ee-pwrc.c
@@ -14,13 +14,22 @@
#include <linux/reset-controller.h>
#include <linux/reset.h>
#include <linux/clk.h>
+#include <dt-bindings/power/meson8-power.h>
#include <dt-bindings/power/meson-g12a-power.h>
#include <dt-bindings/power/meson-sm1-power.h>
/* AO Offsets */
-#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2)
-#define AO_RTI_GEN_PWR_ISO0 (0x3b << 2)
+#define GX_AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2)
+#define GX_AO_RTI_GEN_PWR_ISO0 (0x3b << 2)
+
+/*
+ * Meson8/Meson8b/Meson8m2 only expose the power management registers of the
+ * AO-bus as syscon. 0x3a from GX translates to 0x02, 0x3b translates to 0x03
+ * and so on.
+ */
+#define MESON8_AO_RTI_GEN_PWR_SLEEP0 (0x02 << 2)
+#define MESON8_AO_RTI_GEN_PWR_ISO0 (0x03 << 2)
/* HHI Offsets */
@@ -67,17 +76,24 @@ struct meson_ee_pwrc_domain_data {
/* TOP Power Domains */
static struct meson_ee_pwrc_top_domain g12a_pwrc_vpu = {
- .sleep_reg = AO_RTI_GEN_PWR_SLEEP0,
+ .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
+ .sleep_mask = BIT(8),
+ .iso_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
+ .iso_mask = BIT(9),
+};
+
+static struct meson_ee_pwrc_top_domain meson8_pwrc_vpu = {
+ .sleep_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
.sleep_mask = BIT(8),
- .iso_reg = AO_RTI_GEN_PWR_SLEEP0,
+ .iso_reg = MESON8_AO_RTI_GEN_PWR_SLEEP0,
.iso_mask = BIT(9),
};
#define SM1_EE_PD(__bit) \
{ \
- .sleep_reg = AO_RTI_GEN_PWR_SLEEP0, \
+ .sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0, \
.sleep_mask = BIT(__bit), \
- .iso_reg = AO_RTI_GEN_PWR_ISO0, \
+ .iso_reg = GX_AO_RTI_GEN_PWR_ISO0, \
.iso_mask = BIT(__bit), \
}
@@ -124,10 +140,20 @@ static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
};
-static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_eth[] = {
+static struct meson_ee_pwrc_mem_domain meson_pwrc_mem_eth[] = {
{ HHI_MEM_PD_REG0, GENMASK(3, 2) },
};
+static struct meson_ee_pwrc_mem_domain meson8_pwrc_audio_dsp_mem[] = {
+ { HHI_MEM_PD_REG0, GENMASK(1, 0) },
+};
+
+static struct meson_ee_pwrc_mem_domain meson8_pwrc_mem_vpu[] = {
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+ VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = {
VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
@@ -201,7 +227,27 @@ static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain);
static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
[PWRC_G12A_VPU_ID] = VPU_PD("VPU", &g12a_pwrc_vpu, g12a_pwrc_mem_vpu,
pwrc_ee_get_power, 11, 2),
- [PWRC_G12A_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
+ [PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
+};
+
+static struct meson_ee_pwrc_domain_desc meson8_pwrc_domains[] = {
+ [PWRC_MESON8_VPU_ID] = VPU_PD("VPU", &meson8_pwrc_vpu,
+ meson8_pwrc_mem_vpu, pwrc_ee_get_power,
+ 0, 1),
+ [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
+ meson_pwrc_mem_eth),
+ [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
+ meson8_pwrc_audio_dsp_mem),
+};
+
+static struct meson_ee_pwrc_domain_desc meson8b_pwrc_domains[] = {
+ [PWRC_MESON8_VPU_ID] = VPU_PD("VPU", &meson8_pwrc_vpu,
+ meson8_pwrc_mem_vpu, pwrc_ee_get_power,
+ 11, 1),
+ [PWRC_MESON8_ETHERNET_MEM_ID] = MEM_PD("ETHERNET_MEM",
+ meson_pwrc_mem_eth),
+ [PWRC_MESON8_AUDIO_DSP_MEM_ID] = MEM_PD("AUDIO_DSP_MEM",
+ meson8_pwrc_audio_dsp_mem),
};
static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
@@ -216,7 +262,7 @@ static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = {
[PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d,
pwrc_ee_get_power),
[PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio),
- [PWRC_SM1_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth),
+ [PWRC_SM1_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
};
struct meson_ee_pwrc_domain {
@@ -470,12 +516,34 @@ static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
.domains = g12a_pwrc_domains,
};
+static struct meson_ee_pwrc_domain_data meson_ee_m8_pwrc_data = {
+ .count = ARRAY_SIZE(meson8_pwrc_domains),
+ .domains = meson8_pwrc_domains,
+};
+
+static struct meson_ee_pwrc_domain_data meson_ee_m8b_pwrc_data = {
+ .count = ARRAY_SIZE(meson8b_pwrc_domains),
+ .domains = meson8b_pwrc_domains,
+};
+
static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = {
.count = ARRAY_SIZE(sm1_pwrc_domains),
.domains = sm1_pwrc_domains,
};
static const struct of_device_id meson_ee_pwrc_match_table[] = {
+ {
+ .compatible = "amlogic,meson8-pwrc",
+ .data = &meson_ee_m8_pwrc_data,
+ },
+ {
+ .compatible = "amlogic,meson8b-pwrc",
+ .data = &meson_ee_m8b_pwrc_data,
+ },
+ {
+ .compatible = "amlogic,meson8m2-pwrc",
+ .data = &meson_ee_m8b_pwrc_data,
+ },
{
.compatible = "amlogic,meson-g12a-pwrc",
.data = &meson_ee_g12a_pwrc_data,
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 4/4] soc: amlogic: meson-ee-pwrc: add support for the Meson GX SoCs
From: Martin Blumenstingl @ 2020-05-15 20:47 UTC (permalink / raw)
To: khilman, linux-amlogic
Cc: devicetree, narmstrong, Martin Blumenstingl, linux-kernel,
robh+dt, linux-arm-kernel
In-Reply-To: <20200515204709.1505498-1-martin.blumenstingl@googlemail.com>
Add support for the Meson GX SoCs to the meson-ee-pwrc driver.
The power domains on the GX SoCs are very similar to G12A. The only
known differences so far are:
- The GX SoCs do not have the HHI_VPU_MEM_PD_REG2 register (for the
VPU power-domain)
- The GX SoCs have an additional reset line called "dvin"
Reviewed-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/soc/amlogic/meson-ee-pwrc.c | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/amlogic/meson-ee-pwrc.c b/drivers/soc/amlogic/meson-ee-pwrc.c
index 390eb0dd0a79..43665b77aa9e 100644
--- a/drivers/soc/amlogic/meson-ee-pwrc.c
+++ b/drivers/soc/amlogic/meson-ee-pwrc.c
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <dt-bindings/power/meson8-power.h>
#include <dt-bindings/power/meson-g12a-power.h>
+#include <dt-bindings/power/meson-gxbb-power.h>
#include <dt-bindings/power/meson-sm1-power.h>
/* AO Offsets */
@@ -75,7 +76,7 @@ struct meson_ee_pwrc_domain_data {
/* TOP Power Domains */
-static struct meson_ee_pwrc_top_domain g12a_pwrc_vpu = {
+static struct meson_ee_pwrc_top_domain gx_pwrc_vpu = {
.sleep_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
.sleep_mask = BIT(8),
.iso_reg = GX_AO_RTI_GEN_PWR_SLEEP0,
@@ -140,6 +141,12 @@ static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = {
VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
};
+static struct meson_ee_pwrc_mem_domain gxbb_pwrc_mem_vpu[] = {
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG0),
+ VPU_MEMPD(HHI_VPU_MEM_PD_REG1),
+ VPU_HHI_MEMPD(HHI_MEM_PD_REG0),
+};
+
static struct meson_ee_pwrc_mem_domain meson_pwrc_mem_eth[] = {
{ HHI_MEM_PD_REG0, GENMASK(3, 2) },
};
@@ -225,11 +232,17 @@ static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = {
static bool pwrc_ee_get_power(struct meson_ee_pwrc_domain *pwrc_domain);
static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = {
- [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &g12a_pwrc_vpu, g12a_pwrc_mem_vpu,
+ [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, g12a_pwrc_mem_vpu,
pwrc_ee_get_power, 11, 2),
[PWRC_G12A_ETH_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
};
+static struct meson_ee_pwrc_domain_desc gxbb_pwrc_domains[] = {
+ [PWRC_GXBB_VPU_ID] = VPU_PD("VPU", &gx_pwrc_vpu, gxbb_pwrc_mem_vpu,
+ pwrc_ee_get_power, 12, 2),
+ [PWRC_GXBB_ETHERNET_MEM_ID] = MEM_PD("ETH", meson_pwrc_mem_eth),
+};
+
static struct meson_ee_pwrc_domain_desc meson8_pwrc_domains[] = {
[PWRC_MESON8_VPU_ID] = VPU_PD("VPU", &meson8_pwrc_vpu,
meson8_pwrc_mem_vpu, pwrc_ee_get_power,
@@ -516,6 +529,11 @@ static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = {
.domains = g12a_pwrc_domains,
};
+static struct meson_ee_pwrc_domain_data meson_ee_gxbb_pwrc_data = {
+ .count = ARRAY_SIZE(gxbb_pwrc_domains),
+ .domains = gxbb_pwrc_domains,
+};
+
static struct meson_ee_pwrc_domain_data meson_ee_m8_pwrc_data = {
.count = ARRAY_SIZE(meson8_pwrc_domains),
.domains = meson8_pwrc_domains,
@@ -544,6 +562,10 @@ static const struct of_device_id meson_ee_pwrc_match_table[] = {
.compatible = "amlogic,meson8m2-pwrc",
.data = &meson_ee_m8b_pwrc_data,
},
+ {
+ .compatible = "amlogic,meson-gxbb-pwrc",
+ .data = &meson_ee_gxbb_pwrc_data,
+ },
{
.compatible = "amlogic,meson-g12a-pwrc",
.data = &meson_ee_g12a_pwrc_data,
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 2/4] dt-bindings: power: meson-ee-pwrc: add support for the Meson GX SoCs
From: Martin Blumenstingl @ 2020-05-15 20:47 UTC (permalink / raw)
To: khilman, linux-amlogic
Cc: devicetree, narmstrong, Martin Blumenstingl, linux-kernel,
robh+dt, Rob Herring, linux-arm-kernel
In-Reply-To: <20200515204709.1505498-1-martin.blumenstingl@googlemail.com>
The power domains on the GX SoCs are very similar to G12A. The only
known differences so far are:
- The GX SoCs do not have the HHI_VPU_MEM_PD_REG2 register (for the
VPU power-domain)
- The GX SoCs have an additional reset line called "dvin"
Add a new compatible string and adjust the reset line expectations for
these SoCs.
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
.../bindings/power/amlogic,meson-ee-pwrc.yaml | 28 +++++++++++++++++++
include/dt-bindings/power/meson-gxbb-power.h | 13 +++++++++
2 files changed, 41 insertions(+)
create mode 100644 include/dt-bindings/power/meson-gxbb-power.h
diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
index 2a1c933ae434..51a6fac892e3 100644
--- a/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
+++ b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
@@ -26,6 +26,7 @@ properties:
- amlogic,meson8-pwrc
- amlogic,meson8b-pwrc
- amlogic,meson8m2-pwrc
+ - amlogic,meson-gxbb-pwrc
- amlogic,meson-g12a-pwrc
- amlogic,meson-sm1-pwrc
@@ -42,9 +43,11 @@ properties:
resets:
minItems: 11
+ maxItems: 12
reset-names:
minItems: 11
+ maxItems: 12
"#power-domain-cells":
const: 1
@@ -80,6 +83,31 @@ allOf:
- resets
- reset-names
+ - if:
+ properties:
+ compatible:
+ enum:
+ - amlogic,meson-gxbb-pwrc
+ then:
+ properties:
+ reset-names:
+ items:
+ - const: viu
+ - const: venc
+ - const: vcbus
+ - const: bt656
+ - const: dvin
+ - const: rdma
+ - const: venci
+ - const: vencp
+ - const: vdac
+ - const: vdi6
+ - const: vencl
+ - const: vid_lock
+ required:
+ - resets
+ - reset-names
+
- if:
properties:
compatible:
diff --git a/include/dt-bindings/power/meson-gxbb-power.h b/include/dt-bindings/power/meson-gxbb-power.h
new file mode 100644
index 000000000000..1262dac696c0
--- /dev/null
+++ b/include/dt-bindings/power/meson-gxbb-power.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef _DT_BINDINGS_MESON_GXBB_POWER_H
+#define _DT_BINDINGS_MESON_GXBB_POWER_H
+
+#define PWRC_GXBB_VPU_ID 0
+#define PWRC_GXBB_ETHERNET_MEM_ID 1
+
+#endif
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 1/4] dt-bindings: power: meson-ee-pwrc: add support for Meson8/8b/8m2
From: Martin Blumenstingl @ 2020-05-15 20:47 UTC (permalink / raw)
To: khilman, linux-amlogic
Cc: devicetree, narmstrong, Martin Blumenstingl, linux-kernel,
robh+dt, Rob Herring, linux-arm-kernel
In-Reply-To: <20200515204709.1505498-1-martin.blumenstingl@googlemail.com>
The power domains on the 32-bit Meson8/Meson8b/Meson8m2 SoCs are very
similar to what G12A still uses. The (known) differences are:
- Meson8 doesn't use any reset lines at all
- Meson8b and Meson8m2 use the same reset lines, which are different
from what the 64-bit SoCs use
- there is no "vapb" clock on the older SoCs
- amlogic,ao-sysctrl cannot point to the whole AO sysctrl region but
only the power management related registers
Add a new compatible string and adjust clock and reset line expectations
for each SoC.
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
.../bindings/power/amlogic,meson-ee-pwrc.yaml | 74 +++++++++++++++----
include/dt-bindings/power/meson8-power.h | 13 ++++
2 files changed, 72 insertions(+), 15 deletions(-)
create mode 100644 include/dt-bindings/power/meson8-power.h
diff --git a/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
index 6c6079fe1351..2a1c933ae434 100644
--- a/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
+++ b/Documentation/devicetree/bindings/power/amlogic,meson-ee-pwrc.yaml
@@ -23,13 +23,19 @@ description: |+
properties:
compatible:
enum:
+ - amlogic,meson8-pwrc
+ - amlogic,meson8b-pwrc
+ - amlogic,meson8m2-pwrc
- amlogic,meson-g12a-pwrc
- amlogic,meson-sm1-pwrc
clocks:
- minItems: 2
+ minItems: 1
+ maxItems: 2
clock-names:
+ minItems: 1
+ maxItems: 2
items:
- const: vpu
- const: vapb
@@ -38,18 +44,7 @@ properties:
minItems: 11
reset-names:
- items:
- - const: viu
- - const: venc
- - const: vcbus
- - const: bt656
- - const: rdma
- - const: venci
- - const: vencp
- - const: vdac
- - const: vdi6
- - const: vencl
- - const: vid_lock
+ minItems: 11
"#power-domain-cells":
const: 1
@@ -59,12 +54,61 @@ properties:
allOf:
- $ref: /schemas/types.yaml#/definitions/phandle
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - amlogic,meson8b-pwrc
+ - amlogic,meson8m2-pwrc
+ then:
+ properties:
+ reset-names:
+ items:
+ - const: dblk
+ - const: pic_dc
+ - const: hdmi_apb
+ - const: hdmi_system
+ - const: venci
+ - const: vencp
+ - const: vdac
+ - const: vencl
+ - const: viu
+ - const: venc
+ - const: rdma
+ required:
+ - resets
+ - reset-names
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - amlogic,meson-g12a-pwrc
+ - amlogic,meson-sm1-pwrc
+ then:
+ properties:
+ reset-names:
+ items:
+ - const: viu
+ - const: venc
+ - const: vcbus
+ - const: bt656
+ - const: rdma
+ - const: venci
+ - const: vencp
+ - const: vdac
+ - const: vdi6
+ - const: vencl
+ - const: vid_lock
+ required:
+ - resets
+ - reset-names
+
required:
- compatible
- clocks
- clock-names
- - resets
- - reset-names
- "#power-domain-cells"
- amlogic,ao-sysctrl
diff --git a/include/dt-bindings/power/meson8-power.h b/include/dt-bindings/power/meson8-power.h
new file mode 100644
index 000000000000..dd8b2ddb82a7
--- /dev/null
+++ b/include/dt-bindings/power/meson8-power.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
+/*
+ * Copyright (c) 2019 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+#ifndef _DT_BINDINGS_MESON8_POWER_H
+#define _DT_BINDINGS_MESON8_POWER_H
+
+#define PWRC_MESON8_VPU_ID 0
+#define PWRC_MESON8_ETHERNET_MEM_ID 1
+#define PWRC_MESON8_AUDIO_DSP_MEM_ID 2
+
+#endif /* _DT_BINDINGS_MESON8_POWER_H */
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 0/4] meson-ee-pwrc: support for Meson8/8b/8m2 and GX
From: Martin Blumenstingl @ 2020-05-15 20:47 UTC (permalink / raw)
To: khilman, linux-amlogic
Cc: devicetree, narmstrong, Martin Blumenstingl, linux-kernel,
robh+dt, linux-arm-kernel
This series adds support for all "older" SoCs to the meson-ee-pwrc
driver. I wanted to compare as much as I could between my Meson8b EC-100
(Endless Mini) and the Le Potato board so I added support for GXBB, GXL
and GXM as well as for the SoCs that I'm actually working on. I will
send the ARM64 dts patches once all of this is reviewed and merged.
I successfully tested the Meson8b part on EC-100 where u-boot does not
initialize the VPU controller. So this the board where I have been
struggling most.
Kevin, I'm not sure if this can still make it into v5.8. If the
series as a whole can't make it for some reason then I'd appreciate if
patches #1 and #2 could end in v5.8 so I can push the .dts patches for
v5.9.
Changes since v3 at [2]:
- added Rob's Reviewed-by to patches #1 and #2 - thank you!
- add a GX_ prefix to AO_RTI_GEN_PWR_{SLEEP0,ISO} and add new #defines
for MESON8_AO_RTI_GEN_PWR_{SLEEP0,ISO} based on Neil's suggestion.
- rename meson8_pwrc_mem_eth to meson_pwrc_mem_eth as suggested by
Neil (thanks!) because it's the same for all platforms
- rename gxbb_pwrc_vpu to gx_pwrc_vpu as suggested by Neil (thanks)
- added Neil's Reviewed-by to patches #3 and #4
Changes since v2 at [1]:
- don't remove the "reset-names" property from the main description
(only make it optional and switch from items to minItems) to fix
a dt_binding_check found by Rob (or his bot) - thanks and sorry!
Changes since v1 at [0]:
- rename PWRC_GXBB_ETH_ID to PWRC_GXBB_ETHERNET_MEM_ID. Spotted by
Neil, thanks!
- update cover-letter since Neil confirmed (thanks!) that the "dvin"
reset really belongs to the VPU on GXBB, GXL and GXM
- removed RFC status
[0] https://patchwork.kernel.org/cover/11489163/
[1] https://patchwork.kernel.org/cover/11496013/
[2] https://patchwork.kernel.org/cover/11499791/
Martin Blumenstingl (4):
dt-bindings: power: meson-ee-pwrc: add support for Meson8/8b/8m2
dt-bindings: power: meson-ee-pwrc: add support for the Meson GX SoCs
soc: amlogic: meson-ee-pwrc: add support for Meson8/Meson8b/Meson8m2
soc: amlogic: meson-ee-pwrc: add support for the Meson GX SoCs
.../bindings/power/amlogic,meson-ee-pwrc.yaml | 102 +++++++++++++---
drivers/soc/amlogic/meson-ee-pwrc.c | 112 ++++++++++++++++--
include/dt-bindings/power/meson-gxbb-power.h | 13 ++
include/dt-bindings/power/meson8-power.h | 13 ++
4 files changed, 214 insertions(+), 26 deletions(-)
create mode 100644 include/dt-bindings/power/meson-gxbb-power.h
create mode 100644 include/dt-bindings/power/meson8-power.h
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: PTRACE_SYSEMU behavior difference on arm64
From: Keno Fischer @ 2020-05-15 20:43 UTC (permalink / raw)
To: Will Deacon
Cc: Catalin Marinas, Will Deacon, Linux Kernel Mailing List,
Oleg Nesterov, Sudeep Holla, linux-arm-kernel
In-Reply-To: <20200515121346.GA22919@willie-the-truck>
On Fri, May 15, 2020 at 8:13 AM Will Deacon <will@kernel.org> wrote:
> But it also
> means that nobody is using this on arm64, so we could also consider removing
> it entirely. Did you spot this because you are trying to use it for
> something or just by inspection/unit-testing?
No, I was trying to port a tool from x86 and nothing made sense for
many hours :). (it was quite a bit of debugging, because the
syscall that it was supposed to skip installed a seccomp filter,
which then later veto'd random syscalls making the
symptoms quite confusing). Having PTRACE_SYSEMU isn't
critical, but we might as well support it.
It makes things a bit more efficient and is probably safer
(if it works correctly ;). The patch is fairly small. Will validate
and then send it here for review.
Keno
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 0/6] Clean up Shadow Call Stack patches for 5.8
From: Sami Tolvanen @ 2020-05-15 20:42 UTC (permalink / raw)
To: Will Deacon
Cc: Kees Cook, Jann Horn, Peter Zijlstra, Catalin Marinas, LKML,
Mark Rutland, kernel-team, Ard Biesheuvel, linux-arm-kernel
In-Reply-To: <20200515172756.27185-1-will@kernel.org>
On Fri, May 15, 2020 at 10:28 AM Will Deacon <will@kernel.org> wrote:
>
> Hi all,
>
> Here's a series of cleanups I hacked together on top of a modified v13
> of the Shadow Call Stack patches from Sami:
>
> https://lore.kernel.org/r/20200515172355.GD23334@willie-the-truck
>
> The main changes are:
>
> * Move code out of arch/arm64 and into the core implementation
> * Store the full SCS stack pointer instead of the offset
> * Code simplification and general style things
>
> I'd like to queue this on top early next week so that it can spend some
> quality time in linux-next.
>
> Cheers,
>
> Will
>
> Cc: Sami Tolvanen <samitolvanen@google.com>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Mark Rutland <mark.rutland@am.com>
> Cc: Jann Horn <jannh@google.com>
> Cc: Ard Biesheuvel <ardb@kernel.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: <kernel-team@android.com>
>
> --->8
>
> Will Deacon (6):
> arm64: scs: Store absolute SCS stack pointer value in thread_info
> scs: Move accounting into alloc/free functions
> arm64: scs: Use 'scs_sp' register alias for x18
> scs: Move scs_overflow_check() out of architecture code
> scs: Remove references to asm/scs.h from core code
> scs: Move DEFINE_SCS macro into core code
>
> arch/Kconfig | 4 +--
> arch/arm64/include/asm/scs.h | 29 ++++------------
> arch/arm64/include/asm/thread_info.h | 4 +--
> arch/arm64/kernel/asm-offsets.c | 2 +-
> arch/arm64/kernel/entry.S | 10 +++---
> arch/arm64/kernel/head.S | 2 +-
> arch/arm64/kernel/process.c | 2 --
> arch/arm64/kernel/scs.c | 6 +---
> include/linux/scs.h | 16 +++++----
> kernel/sched/core.c | 3 ++
> kernel/scs.c | 52 +++++++++++++---------------
> 11 files changed, 55 insertions(+), 75 deletions(-)
>
> --
> 2.26.2.761.g0e0b3e54be-goog
Thanks, Will. I tested these on my SCS tree and didn't run into any
issues. Looks good to me.
Sami
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH for-5.8 v1 1/1] ARM: dts: meson8m2: Use the Meson8m2 specific USB2 PHY compatible
From: Martin Blumenstingl @ 2020-05-15 20:25 UTC (permalink / raw)
To: khilman, linux-amlogic
Cc: Martin Blumenstingl, linux-kernel, linux-arm-kernel
Use the Meson8m2 specific USB2 PHY compatible string. The 3.10 vendor
kernel has at least one known difference between Meson8 and Meson8m2:
Meson8m2 sets the ACA_ENABLE bit while Meson8 doesn't.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
This has a runtime dependency on the meson8b-usb2 PHY series from [0].
That one is queued for v5.8 so it would be great if this could make it
into v5.8 as well.
This patch is meant to apply on top of my other series titled "ARM:
dts: meson8b/m2: RGMII improvements" from [1]
[0] https://patchwork.kernel.org/cover/11544233/
[1] https://patchwork.kernel.org/cover/11544215/
arch/arm/boot/dts/meson8m2.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/meson8m2.dtsi b/arch/arm/boot/dts/meson8m2.dtsi
index 96b37d5e9afd..2397ba06d608 100644
--- a/arch/arm/boot/dts/meson8m2.dtsi
+++ b/arch/arm/boot/dts/meson8m2.dtsi
@@ -65,6 +65,14 @@ &saradc {
compatible = "amlogic,meson8m2-saradc", "amlogic,meson-saradc";
};
+&usb0_phy {
+ compatible = "amlogic,meson8m2-usb2-phy", "amlogic,meson-mx-usb2-phy";
+};
+
+&usb1_phy {
+ compatible = "amlogic,meson8m2-usb2-phy", "amlogic,meson-mx-usb2-phy";
+};
+
&wdt {
compatible = "amlogic,meson8m2-wdt", "amlogic,meson8b-wdt";
};
--
2.26.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [GIT PULL] arm64 fixes for 5.7-rc6
From: pr-tracker-bot @ 2020-05-15 20:00 UTC (permalink / raw)
To: Catalin Marinas
Cc: Will Deacon, Linus Torvalds, linux-kernel, linux-arm-kernel, hch
In-Reply-To: <20200515172443.GA1749@gaia>
The pull request you sent on Fri, 15 May 2020 18:24:45 +0100:
> git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux tags/arm64-fixes
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/01d8a7480304a2f0e196459eb4061e171d9e9922
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.wiki.kernel.org/userdoc/prtracker
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC PATCH v2 0/3] Prefer working VT console over SPCR and device-tree chosen stdout-path
From: Alper Nebi Yasak @ 2020-05-15 19:27 UTC (permalink / raw)
To: Petr Mladek
Cc: Feng Tang, Benjamin Herrenschmidt, Eric Biggers,
Greg Kroah-Hartman, Nicolas Pitre, linux-kernel, Steven Rostedt,
Daniel Vetter, Sergey Senozhatsky, Arvind Sankar, Grzegorz Halat,
linux-serial, Jiri Slaby, Lukas Wunner, Andrew Morton,
Andy Shevchenko, Sam Ravnborg, David S. Miller, linux-arm-kernel
In-Reply-To: <20200513143755.GM17734@linux-b0ei>
On 13/05/2020 17:37, Petr Mladek wrote:
> On Thu 2020-04-30 19:14:34, Alper Nebi Yasak wrote:
>> | "console=tty0" | (no console arg) |
>> ------------------+-----------------------+-----------------------+
>> QEMU VM | tty0 -WU (EC p ) | ttyAMA0 -W- (EC a) |
>> (w/ SPCR) | ttyAMA0 -W- (E a) |
>> |
>
> The SPCR handling is inconsistent over architectures, see
> https://lkml.kernel.org/r/20180830123849.26163-1-prarit@redhat.com
>
> IMHO, arm developers decided that consoles defined by SPCR are always
> enabled when existing.
I'm OK with those being enabled. Though, I hope "not registering tty0"
wasn't an explicit decision, but maybe an oversight/trade-off due to
assuming SPCR code will only run on servers without displays (where tty0
wouldn't matter). (I understand it might be too late to change that.)
So I'd want the 2nd column to be: tty0(EC) ttyAMA0(E) at best, and
ttyAMA0(EC) tty0(E) at worst.
> In 1st column: tty0 is the preferred console because it is defined
> on the commandline.
>
> In 2nd column: tty0 is not enabled at all because another console was
> defined by SPCR. Note that ttySX and ttyX consoles are registered only
> as a fallback when there is no other console defined.
>
> The following code is responsible for the fallback, see register_console()
>
> /*
> * See if we want to use this console driver. If we
> * didn't select a console we take the first one
> * that registers here.
> */
> if (!has_preferred) {
> if (newcon->index < 0)
> newcon->index = 0;
> if (newcon->setup == NULL ||
> newcon->setup(newcon, NULL) == 0) {
> newcon->flags |= CON_ENABLED;
> if (newcon->device) {
> newcon->flags |= CON_CONSDEV;
> has_preferred = true;
> }
> }
> }
>
>
>> ------------------+-----------------------+-----------------------+
>> Chromebook Plus | tty0 -WU (EC p ) | ttyS2 -W- (EC p a) |
>> (w/ stdout-path) | | tty0 -WU (E ) |
>
> Hmm, of_console_check() explicitly ignores the console defined by
> stdout-path when there is a console on the commandline. This explains
> 1st column.
>
> I am not sure about 2nd column. My guess is that ttyX consoles are
> tried first. tty0 is registered as a fallback because there is no
> other console at the moment. ttyS2 is tried later and it is
> registered because it is in stdout-patch and there is no console
> in the command line. It is somehow consistent with CONFIG_VT_CONSOLE
> description.
>
> Sadly, it is different logic than with SPCR :-(
I like the fact that this one has tty0. For example, Debian's installer
iterates over /proc/consoles and launches itself on all the consoles it
finds there, so it wouldn't launch on my chromebook's screen if tty0
wasn't included (just like it doesn't launch on a QEMU aarch64 VM's
framebuffer).
>> ------------------+-----------------------+-----------------------+
>> Chromebook Plus | tty0 -WU (EC p ) | tty0 -WU (EC p ) |
>> (w/o either) | | |
>> ------------------+-----------------------+-----------------------+
>
> This variant is easy and everyone would probably expect this.
I think things run roughly in the following order (from what I can
decipher from kernel messages) and I think it matches your explanations:
| ACPI SPCR | dt chosen stdout-path |
+=================================+=================================+
| acpi_parse_spcr() | |
| -> add_preferred_console(uart0) | |
| (if not on x86) | |
+---------------------------------+---------------------------------+
| console_setup() |
| -> add_preferred_console(tty0) |
| (if console=tty0) |
+---------------------------------+---------------------------------+
| register_console(vt) |
+---------------------------------+---------------------------------+
| | of_console_check() |
| | -> add_preferred_console(uart2) |
| | (if no console arg) |
+---------------------------------+---------------------------------+
| register_console(serial) |
+---------------------------------+---------------------------------+
> Regarding the description of CONFIG_VT_CONSOLE option. I am afraid
> that it was created and true only before SPCR and device tree support
> was introduced.
OK. Assuming these changes won't go any further, maybe I'll try
documenting the current behavior in relevant places.
> Now, it is really sad that SPCR and device tree have different
> behavior even across architectures. But I am afraid that we could
> not change it without breaking many setups.
>
> The only common rules are:
>
> + The last console on the command line should always be the
> preferred one when defined.
>
> + Consoles defined by the device (SPCR, device tree) are used
> when there is no commandline.
>
> + ttyX or ttySX are used as a fallback when nothing else is defined.
>
>
> My suggestion is:
>
> + Fix SPCR setting or device tree of your device when the defaults
> are not as expected.
Maybe I can get QEMU's SPCR use conditional on the existence a
framebuffer, and get distributions to remove stdout-path from certain
device-trees; but that would disable the serial console completely
(instead of having it enabled where tty0 is still preferred).
> + Use command line to force your value when the defaults are not
> as expected and you could not change them.
This works; but I'd have to know the machine's serial configuration in
advance to put it in the cmdline as "console=<serial> console=tty0", or
lose the serial console as in the above. (A "console=dt" like that
"console=spcr" patch you linked to would be useful here if it existed.)
Both seem imperfect in that sense, but tolerable.
> I am afraid that we could not fix your problem on the kernel side. It
> would broke other setups that depend on the existing behavior.
>
> Best Regards,
> Petr
Thanks for the detailed reply.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 5/9] dt-bindings: dmaengine: convert Actions Semi Owl SoCs bindings to yaml
From: Amit Tomer @ 2020-05-15 19:24 UTC (permalink / raw)
To: André Przywara
Cc: devicetree, linux-actions, cristian.ciocaltea, Rob Herring,
Manivannan Sadhasivam, Andreas Färber, linux-arm-kernel
In-Reply-To: <CABHD4K_BpHMSypfdiQKeRfHOgdO8e7ekU0TKBmqisDe_+4hGPg@mail.gmail.com>
> But having it under reg: looks bit odd to me, no?
>
> reg:
> - description: ...
>
> Or did you mean something else ?
Ah, I see you wanted to have description for individual items, for instance one
for reg, one for interrupts and clock etc..
Thanks
Amit
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v4] ACPI/IORT: Fix PMCG node single ID mapping handling.
From: Tuan Phan @ 2020-05-15 19:24 UTC (permalink / raw)
Cc: Lorenzo Pieralisi, Neil Leeder, Hanjun Guo, Rafael J. Wysocki,
linux-kernel, Shameer Kolothum, linux-acpi, Sudeep Holla, patches,
Robin Murphy, linux-arm-kernel, Len Brown
An IORT PMCG node can have no ID mapping if its overflow interrupt is
wire based therefore the code that parses the PMCG node can not assume
the node will always have a single mapping present at index 0.
Fix iort_get_id_mapping_index() by checking for an overflow interrupt
and mapping count.
Fixes: 24e516049360 ("ACPI/IORT: Add support for PMCG").
Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Hanjun Guo <guoahanjun@huawei.com>
Signed-off-by: Tuan Phan <tuanphan@os.amperecomputing.com>
---
v1 -> v2:
- Use pmcg node to detect wired base overflow interrupt.
v2 -> v3:
- Address Hanjun and Robin's comments.
v3 -> v4:
- Update the title and description as mentioned by Lorenzo.
drivers/acpi/arm64/iort.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index ed3d2d1..12bb70e 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -414,6 +414,7 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
static int iort_get_id_mapping_index(struct acpi_iort_node *node)
{
struct acpi_iort_smmu_v3 *smmu;
+ struct acpi_iort_pmcg *pmcg;
switch (node->type) {
case ACPI_IORT_NODE_SMMU_V3:
@@ -441,6 +442,10 @@ static int iort_get_id_mapping_index(struct acpi_iort_node *node)
return smmu->id_mapping_index;
case ACPI_IORT_NODE_PMCG:
+ pmcg = (struct acpi_iort_pmcg *)node->node_data;
+ if (pmcg->overflow_gsiv || node->mapping_count == 0)
+ return -EINVAL;
+
return 0;
default:
return -EINVAL;
--
2.7.4
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v1 5/9] dt-bindings: dmaengine: convert Actions Semi Owl SoCs bindings to yaml
From: Amit Tomer @ 2020-05-15 19:05 UTC (permalink / raw)
To: André Przywara
Cc: devicetree, linux-actions, cristian.ciocaltea, Rob Herring,
Manivannan Sadhasivam, Andreas Färber, linux-arm-kernel
In-Reply-To: <afc0d7f3-d763-b936-988c-d802b86836bc@arm.com>
Hi,
> Could you replace those "maxItems: 1" here and below with:
> - description: ...., copying in the explanation from the .txt binding?
> That should serve the same purpose as "maxItems: 1", but is more
> descriptive.
But having it under reg: looks bit odd to me, no?
reg:
- description: ...
Or did you mean something else ?
Thanks
-Amit
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 8/9] arm64: dts: actions: Add MMC controller support for S700
From: Amit Tomer @ 2020-05-15 18:41 UTC (permalink / raw)
To: André Przywara
Cc: devicetree, linux-actions, cristian.ciocaltea, Rob Herring,
Manivannan Sadhasivam, Andreas Färber, linux-arm-kernel
In-Reply-To: <b2ad8a81-619f-5f35-9596-c2061ae15e4c@arm.com>
Hi,
> I was wondering if we should add a SoC specific compatible here, to be
> on the safe side. The BSP driver seems to differentiate between S900 and
> S700, although it looks like only to cover some misplaced platform setup.
>
> But if we later find a problem, the DTs stay the same, and the driver
> can easily be fixed.
>
> So, using "actions,s700-mmc", "actions,owl-mmc" here, adding this combo
> to the binding, but leaving the driver alone for now.
I think, it can be a good idea to have this extra compatible string that may
be needed when MMC driver evolves to support more features which requires
data to be differentiated based on SoC.
Thanks
Amit
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 03/14] arm64: add support for folded p4d page tables
From: Andrew Morton @ 2020-05-15 18:40 UTC (permalink / raw)
To: Mike Rapoport
Cc: Rich Felker, linux-ia64, Geert Uytterhoeven, linux-sh,
Benjamin Herrenschmidt, linux-mm, Paul Mackerras, linux-hexagon,
Will Deacon, kvmarm, Jonas Bonn, linux-arch, Brian Cain,
Marc Zyngier, Russell King, Ley Foon Tan, Mike Rapoport,
Catalin Marinas, Julien Thierry, uclinux-h8-devel, Fenghua Yu,
Arnd Bergmann, Suzuki K Poulose, kvm-ppc, Stefan Kristiansson,
openrisc, Stafford Horne, Guan Xuetao, linux-arm-kernel,
Christophe Leroy, Tony Luck, Yoshinori Sato, linux-kernel,
James Morse, Michael Ellerman, nios2-dev, linuxppc-dev
In-Reply-To: <20200414153455.21744-4-rppt@kernel.org>
On Tue, 14 Apr 2020 18:34:44 +0300 Mike Rapoport <rppt@kernel.org> wrote:
> Implement primitives necessary for the 4th level folding, add walks of p4d
> level where appropriate, replace 5level-fixup.h with pgtable-nop4d.h and
> remove __ARCH_USE_5LEVEL_HACK.
This needed some rework due to arm changes in linux-next. Please check
my handiwork and test it once I've merged this into linux-next?
Rejects were
--- arch/arm64/include/asm/pgtable.h~arm64-add-support-for-folded-p4d-page-tables
+++ arch/arm64/include/asm/pgtable.h
@@ -596,49 +604,50 @@ static inline phys_addr_t pud_page_paddr
#define pud_ERROR(pud) __pud_error(__FILE__, __LINE__, pud_val(pud))
-#define pgd_none(pgd) (!pgd_val(pgd))
-#define pgd_bad(pgd) (!(pgd_val(pgd) & 2))
-#define pgd_present(pgd) (pgd_val(pgd))
+#define p4d_none(p4d) (!p4d_val(p4d))
+#define p4d_bad(p4d) (!(p4d_val(p4d) & 2))
+#define p4d_present(p4d) (p4d_val(p4d))
-static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
+static inline void set_p4d(p4d_t *p4dp, p4d_t p4d)
{
- if (in_swapper_pgdir(pgdp)) {
- set_swapper_pgd(pgdp, pgd);
+ if (in_swapper_pgdir(p4dp)) {
+ set_swapper_pgd((pgd_t *)p4dp, __pgd(p4d_val(p4d)));
return;
}
- WRITE_ONCE(*pgdp, pgd);
+ WRITE_ONCE(*p4dp, p4d);
dsb(ishst);
isb();
}
-static inline void pgd_clear(pgd_t *pgdp)
+static inline void p4d_clear(p4d_t *p4dp)
{
- set_pgd(pgdp, __pgd(0));
+ set_p4d(p4dp, __p4d(0));
}
-static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
+static inline phys_addr_t p4d_page_paddr(p4d_t p4d)
{
- return __pgd_to_phys(pgd);
+ return __p4d_to_phys(p4d);
}
/* Find an entry in the frst-level page table. */
#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
-#define pud_offset_phys(dir, addr) (pgd_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pud_t))
+#define pud_offset_phys(dir, addr) (p4d_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pud_t))
#define pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr))))
#define pud_set_fixmap(addr) ((pud_t *)set_fixmap_offset(FIX_PUD, addr))
-#define pud_set_fixmap_offset(pgd, addr) pud_set_fixmap(pud_offset_phys(pgd, addr))
+#define pud_set_fixmap_offset(p4d, addr) pud_set_fixmap(pud_offset_phys(p4d, addr))
#define pud_clear_fixmap() clear_fixmap(FIX_PUD)
-#define pgd_page(pgd) pfn_to_page(__phys_to_pfn(__pgd_to_phys(pgd)))
+#define p4d_page(p4d) pfn_to_page(__phys_to_pfn(__p4d_to_phys(p4d)))
/* use ONLY for statically allocated translation tables */
#define pud_offset_kimg(dir,addr) ((pud_t *)__phys_to_kimg(pud_offset_phys((dir), (addr))))
#else
+#define p4d_page_paddr(p4d) ({ BUILD_BUG(); 0;})
#define pgd_page_paddr(pgd) ({ BUILD_BUG(); 0;})
/* Match pud_offset folding in <asm/generic/pgtable-nopud.h> */
and
--- arch/arm64/kvm/mmu.c~arm64-add-support-for-folded-p4d-page-tables
+++ arch/arm64/kvm/mmu.c
@@ -469,7 +517,7 @@ static void stage2_flush_memslot(struct
do {
next = stage2_pgd_addr_end(kvm, addr, end);
if (!stage2_pgd_none(kvm, *pgd))
- stage2_flush_puds(kvm, pgd, addr, next);
+ stage2_flush_p4ds(kvm, pgd, addr, next);
} while (pgd++, addr = next, addr != end);
}
Result:
From: Mike Rapoport <rppt@linux.ibm.com>
Subject: arm64: add support for folded p4d page tables
Implement primitives necessary for the 4th level folding, add walks of p4d
level where appropriate, replace 5level-fixup.h with pgtable-nop4d.h and
remove __ARCH_USE_5LEVEL_HACK.
Link: http://lkml.kernel.org/r/20200414153455.21744-4-rppt@kernel.org
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Brian Cain <bcain@codeaurora.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Geert Uytterhoeven <geert+renesas@glider.be>
Cc: Guan Xuetao <gxt@pku.edu.cn>
Cc: James Morse <james.morse@arm.com>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Julien Thierry <julien.thierry.kdev@gmail.com>
Cc: Ley Foon Tan <ley.foon.tan@intel.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Rich Felker <dalias@libc.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Stafford Horne <shorne@gmail.com>
Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Will Deacon <will@kernel.org>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
arch/arm64/include/asm/kvm_mmu.h | 10 -
arch/arm64/include/asm/pgalloc.h | 10 -
arch/arm64/include/asm/pgtable-types.h | 5
arch/arm64/include/asm/pgtable.h | 37 ++-
arch/arm64/include/asm/stage2_pgtable.h | 48 +++--
arch/arm64/kernel/hibernate.c | 44 +++-
arch/arm64/kvm/mmu.c | 209 ++++++++++++++++++----
arch/arm64/mm/fault.c | 9
arch/arm64/mm/hugetlbpage.c | 15 +
arch/arm64/mm/kasan_init.c | 26 ++
arch/arm64/mm/mmu.c | 52 +++--
arch/arm64/mm/pageattr.c | 7
12 files changed, 368 insertions(+), 104 deletions(-)
--- a/arch/arm64/include/asm/kvm_mmu.h~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/include/asm/kvm_mmu.h
@@ -172,8 +172,8 @@ void kvm_clear_hyp_idmap(void);
__pmd(__phys_to_pmd_val(__pa(ptep)) | PMD_TYPE_TABLE)
#define kvm_mk_pud(pmdp) \
__pud(__phys_to_pud_val(__pa(pmdp)) | PMD_TYPE_TABLE)
-#define kvm_mk_pgd(pudp) \
- __pgd(__phys_to_pgd_val(__pa(pudp)) | PUD_TYPE_TABLE)
+#define kvm_mk_p4d(pmdp) \
+ __p4d(__phys_to_p4d_val(__pa(pmdp)) | PUD_TYPE_TABLE)
#define kvm_set_pud(pudp, pud) set_pud(pudp, pud)
@@ -299,6 +299,12 @@ static inline bool kvm_s2pud_young(pud_t
#define hyp_pud_table_empty(pudp) kvm_page_empty(pudp)
#endif
+#ifdef __PAGETABLE_P4D_FOLDED
+#define hyp_p4d_table_empty(p4dp) (0)
+#else
+#define hyp_p4d_table_empty(p4dp) kvm_page_empty(p4dp)
+#endif
+
struct kvm;
#define kvm_flush_dcache_to_poc(a,l) __flush_dcache_area((a), (l))
--- a/arch/arm64/include/asm/pgalloc.h~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/include/asm/pgalloc.h
@@ -73,17 +73,17 @@ static inline void pud_free(struct mm_st
free_page((unsigned long)pudp);
}
-static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pudp, pgdval_t prot)
+static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot)
{
- set_pgd(pgdp, __pgd(__phys_to_pgd_val(pudp) | prot));
+ set_p4d(p4dp, __p4d(__phys_to_p4d_val(pudp) | prot));
}
-static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgdp, pud_t *pudp)
+static inline void p4d_populate(struct mm_struct *mm, p4d_t *p4dp, pud_t *pudp)
{
- __pgd_populate(pgdp, __pa(pudp), PUD_TYPE_TABLE);
+ __p4d_populate(p4dp, __pa(pudp), PUD_TYPE_TABLE);
}
#else
-static inline void __pgd_populate(pgd_t *pgdp, phys_addr_t pudp, pgdval_t prot)
+static inline void __p4d_populate(p4d_t *p4dp, phys_addr_t pudp, p4dval_t prot)
{
BUILD_BUG();
}
--- a/arch/arm64/include/asm/pgtable.h~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/include/asm/pgtable.h
@@ -298,6 +298,11 @@ static inline pte_t pgd_pte(pgd_t pgd)
return __pte(pgd_val(pgd));
}
+static inline pte_t p4d_pte(p4d_t p4d)
+{
+ return __pte(p4d_val(p4d));
+}
+
static inline pte_t pud_pte(pud_t pud)
{
return __pte(pud_val(pud));
@@ -401,6 +406,9 @@ static inline pmd_t pmd_mkdevmap(pmd_t p
#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd))
+#define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
+#define __phys_to_p4d_val(phys) __phys_to_pte_val(phys)
+
#define __pgd_to_phys(pgd) __pte_to_phys(pgd_pte(pgd))
#define __phys_to_pgd_val(phys) __phys_to_pte_val(phys)
@@ -592,49 +600,50 @@ static inline phys_addr_t pud_page_paddr
#define pud_ERROR(pud) __pud_error(__FILE__, __LINE__, pud_val(pud))
-#define pgd_none(pgd) (!pgd_val(pgd))
-#define pgd_bad(pgd) (!(pgd_val(pgd) & 2))
-#define pgd_present(pgd) (pgd_val(pgd))
+#define p4d_none(p4d) (!p4d_val(p4d))
+#define p4d_bad(p4d) (!(p4d_val(p4d) & 2))
+#define p4d_present(p4d) (p4d_val(p4d))
-static inline void set_pgd(pgd_t *pgdp, pgd_t pgd)
+static inline void set_p4d(p4d_t *p4dp, p4d_t p4d)
{
- if (in_swapper_pgdir(pgdp)) {
- set_swapper_pgd(pgdp, pgd);
+ if (in_swapper_pgdir(p4dp)) {
+ set_swapper_pgd((pgd_t *)p4dp, __pgd(p4d_val(p4d)));
return;
}
- WRITE_ONCE(*pgdp, pgd);
+ WRITE_ONCE(*p4dp, p4d);
dsb(ishst);
isb();
}
-static inline void pgd_clear(pgd_t *pgdp)
+static inline void p4d_clear(p4d_t *p4dp)
{
- set_pgd(pgdp, __pgd(0));
+ set_p4d(p4dp, __p4d(0));
}
-static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
+static inline phys_addr_t p4d_page_paddr(p4d_t p4d)
{
- return __pgd_to_phys(pgd);
+ return __p4d_to_phys(p4d);
}
/* Find an entry in the frst-level page table. */
#define pud_index(addr) (((addr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
-#define pud_offset_phys(dir, addr) (pgd_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pud_t))
+#define pud_offset_phys(dir, addr) (p4d_page_paddr(READ_ONCE(*(dir))) + pud_index(addr) * sizeof(pud_t))
#define pud_offset(dir, addr) ((pud_t *)__va(pud_offset_phys((dir), (addr))))
#define pud_set_fixmap(addr) ((pud_t *)set_fixmap_offset(FIX_PUD, addr))
-#define pud_set_fixmap_offset(pgd, addr) pud_set_fixmap(pud_offset_phys(pgd, addr))
+#define pud_set_fixmap_offset(p4d, addr) pud_set_fixmap(pud_offset_phys(p4d, addr))
#define pud_clear_fixmap() clear_fixmap(FIX_PUD)
-#define pgd_page(pgd) phys_to_page(__pgd_to_phys(pgd))
+#define p4d_page(p4d) pfn_to_page(__phys_to_pfn(__p4d_to_phys(p4d)))
/* use ONLY for statically allocated translation tables */
#define pud_offset_kimg(dir,addr) ((pud_t *)__phys_to_kimg(pud_offset_phys((dir), (addr))))
#else
+#define p4d_page_paddr(p4d) ({ BUILD_BUG(); 0;})
#define pgd_page_paddr(pgd) ({ BUILD_BUG(); 0;})
/* Match pud_offset folding in <asm/generic/pgtable-nopud.h> */
--- a/arch/arm64/include/asm/pgtable-types.h~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/include/asm/pgtable-types.h
@@ -14,6 +14,7 @@
typedef u64 pteval_t;
typedef u64 pmdval_t;
typedef u64 pudval_t;
+typedef u64 p4dval_t;
typedef u64 pgdval_t;
/*
@@ -44,13 +45,11 @@ typedef struct { pteval_t pgprot; } pgpr
#define __pgprot(x) ((pgprot_t) { (x) } )
#if CONFIG_PGTABLE_LEVELS == 2
-#define __ARCH_USE_5LEVEL_HACK
#include <asm-generic/pgtable-nopmd.h>
#elif CONFIG_PGTABLE_LEVELS == 3
-#define __ARCH_USE_5LEVEL_HACK
#include <asm-generic/pgtable-nopud.h>
#elif CONFIG_PGTABLE_LEVELS == 4
-#include <asm-generic/5level-fixup.h>
+#include <asm-generic/pgtable-nop4d.h>
#endif
#endif /* __ASM_PGTABLE_TYPES_H */
--- a/arch/arm64/include/asm/stage2_pgtable.h~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/include/asm/stage2_pgtable.h
@@ -68,41 +68,67 @@ static inline bool kvm_stage2_has_pud(st
#define S2_PUD_SIZE (1UL << S2_PUD_SHIFT)
#define S2_PUD_MASK (~(S2_PUD_SIZE - 1))
-static inline bool stage2_pgd_none(struct kvm *kvm, pgd_t pgd)
+#define stage2_pgd_none(kvm, pgd) pgd_none(pgd)
+#define stage2_pgd_clear(kvm, pgd) pgd_clear(pgd)
+#define stage2_pgd_present(kvm, pgd) pgd_present(pgd)
+#define stage2_pgd_populate(kvm, pgd, p4d) pgd_populate(NULL, pgd, p4d)
+
+static inline p4d_t *stage2_p4d_offset(struct kvm *kvm,
+ pgd_t *pgd, unsigned long address)
+{
+ return p4d_offset(pgd, address);
+}
+
+static inline void stage2_p4d_free(struct kvm *kvm, p4d_t *p4d)
+{
+}
+
+static inline bool stage2_p4d_table_empty(struct kvm *kvm, p4d_t *p4dp)
+{
+ return false;
+}
+
+static inline phys_addr_t stage2_p4d_addr_end(struct kvm *kvm,
+ phys_addr_t addr, phys_addr_t end)
+{
+ return end;
+}
+
+static inline bool stage2_p4d_none(struct kvm *kvm, p4d_t p4d)
{
if (kvm_stage2_has_pud(kvm))
- return pgd_none(pgd);
+ return p4d_none(p4d);
else
return 0;
}
-static inline void stage2_pgd_clear(struct kvm *kvm, pgd_t *pgdp)
+static inline void stage2_p4d_clear(struct kvm *kvm, p4d_t *p4dp)
{
if (kvm_stage2_has_pud(kvm))
- pgd_clear(pgdp);
+ p4d_clear(p4dp);
}
-static inline bool stage2_pgd_present(struct kvm *kvm, pgd_t pgd)
+static inline bool stage2_p4d_present(struct kvm *kvm, p4d_t p4d)
{
if (kvm_stage2_has_pud(kvm))
- return pgd_present(pgd);
+ return p4d_present(p4d);
else
return 1;
}
-static inline void stage2_pgd_populate(struct kvm *kvm, pgd_t *pgd, pud_t *pud)
+static inline void stage2_p4d_populate(struct kvm *kvm, p4d_t *p4d, pud_t *pud)
{
if (kvm_stage2_has_pud(kvm))
- pgd_populate(NULL, pgd, pud);
+ p4d_populate(NULL, p4d, pud);
}
static inline pud_t *stage2_pud_offset(struct kvm *kvm,
- pgd_t *pgd, unsigned long address)
+ p4d_t *p4d, unsigned long address)
{
if (kvm_stage2_has_pud(kvm))
- return pud_offset(pgd, address);
+ return pud_offset(p4d, address);
else
- return (pud_t *)pgd;
+ return (pud_t *)p4d;
}
static inline void stage2_pud_free(struct kvm *kvm, pud_t *pud)
--- a/arch/arm64/kernel/hibernate.c~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/kernel/hibernate.c
@@ -184,6 +184,7 @@ static int trans_pgd_map_page(pgd_t *tra
pgprot_t pgprot)
{
pgd_t *pgdp;
+ p4d_t *p4dp;
pud_t *pudp;
pmd_t *pmdp;
pte_t *ptep;
@@ -196,7 +197,15 @@ static int trans_pgd_map_page(pgd_t *tra
pgd_populate(&init_mm, pgdp, pudp);
}
- pudp = pud_offset(pgdp, dst_addr);
+ p4dp = p4d_offset(pgdp, dst_addr);
+ if (p4d_none(READ_ONCE(*p4dp))) {
+ pudp = (void *)get_safe_page(GFP_ATOMIC);
+ if (!pudp)
+ return -ENOMEM;
+ p4d_populate(&init_mm, p4dp, pudp);
+ }
+
+ pudp = pud_offset(p4dp, dst_addr);
if (pud_none(READ_ONCE(*pudp))) {
pmdp = (void *)get_safe_page(GFP_ATOMIC);
if (!pmdp)
@@ -419,7 +428,7 @@ static int copy_pmd(pud_t *dst_pudp, pud
return 0;
}
-static int copy_pud(pgd_t *dst_pgdp, pgd_t *src_pgdp, unsigned long start,
+static int copy_pud(p4d_t *dst_p4dp, p4d_t *src_p4dp, unsigned long start,
unsigned long end)
{
pud_t *dst_pudp;
@@ -427,15 +436,15 @@ static int copy_pud(pgd_t *dst_pgdp, pgd
unsigned long next;
unsigned long addr = start;
- if (pgd_none(READ_ONCE(*dst_pgdp))) {
+ if (p4d_none(READ_ONCE(*dst_p4dp))) {
dst_pudp = (pud_t *)get_safe_page(GFP_ATOMIC);
if (!dst_pudp)
return -ENOMEM;
- pgd_populate(&init_mm, dst_pgdp, dst_pudp);
+ p4d_populate(&init_mm, dst_p4dp, dst_pudp);
}
- dst_pudp = pud_offset(dst_pgdp, start);
+ dst_pudp = pud_offset(dst_p4dp, start);
- src_pudp = pud_offset(src_pgdp, start);
+ src_pudp = pud_offset(src_p4dp, start);
do {
pud_t pud = READ_ONCE(*src_pudp);
@@ -454,6 +463,27 @@ static int copy_pud(pgd_t *dst_pgdp, pgd
return 0;
}
+static int copy_p4d(pgd_t *dst_pgdp, pgd_t *src_pgdp, unsigned long start,
+ unsigned long end)
+{
+ p4d_t *dst_p4dp;
+ p4d_t *src_p4dp;
+ unsigned long next;
+ unsigned long addr = start;
+
+ dst_p4dp = p4d_offset(dst_pgdp, start);
+ src_p4dp = p4d_offset(src_pgdp, start);
+ do {
+ next = p4d_addr_end(addr, end);
+ if (p4d_none(READ_ONCE(*src_p4dp)))
+ continue;
+ if (copy_pud(dst_p4dp, src_p4dp, addr, next))
+ return -ENOMEM;
+ } while (dst_p4dp++, src_p4dp++, addr = next, addr != end);
+
+ return 0;
+}
+
static int copy_page_tables(pgd_t *dst_pgdp, unsigned long start,
unsigned long end)
{
@@ -466,7 +496,7 @@ static int copy_page_tables(pgd_t *dst_p
next = pgd_addr_end(addr, end);
if (pgd_none(READ_ONCE(*src_pgdp)))
continue;
- if (copy_pud(dst_pgdp, src_pgdp, addr, next))
+ if (copy_p4d(dst_pgdp, src_pgdp, addr, next))
return -ENOMEM;
} while (dst_pgdp++, src_pgdp++, addr = next, addr != end);
--- a/arch/arm64/kvm/mmu.c~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/kvm/mmu.c
@@ -158,13 +158,22 @@ static void *mmu_memory_cache_alloc(stru
static void clear_stage2_pgd_entry(struct kvm *kvm, pgd_t *pgd, phys_addr_t addr)
{
- pud_t *pud_table __maybe_unused = stage2_pud_offset(kvm, pgd, 0UL);
+ p4d_t *p4d_table __maybe_unused = stage2_p4d_offset(kvm, pgd, 0UL);
stage2_pgd_clear(kvm, pgd);
kvm_tlb_flush_vmid_ipa(kvm, addr);
- stage2_pud_free(kvm, pud_table);
+ stage2_p4d_free(kvm, p4d_table);
put_page(virt_to_page(pgd));
}
+static void clear_stage2_p4d_entry(struct kvm *kvm, p4d_t *p4d, phys_addr_t addr)
+{
+ pud_t *pud_table __maybe_unused = stage2_pud_offset(kvm, p4d, 0);
+ stage2_p4d_clear(kvm, p4d);
+ kvm_tlb_flush_vmid_ipa(kvm, addr);
+ stage2_pud_free(kvm, pud_table);
+ put_page(virt_to_page(p4d));
+}
+
static void clear_stage2_pud_entry(struct kvm *kvm, pud_t *pud, phys_addr_t addr)
{
pmd_t *pmd_table __maybe_unused = stage2_pmd_offset(kvm, pud, 0);
@@ -208,12 +217,20 @@ static inline void kvm_pud_populate(pud_
dsb(ishst);
}
-static inline void kvm_pgd_populate(pgd_t *pgdp, pud_t *pudp)
+static inline void kvm_p4d_populate(p4d_t *p4dp, pud_t *pudp)
{
- WRITE_ONCE(*pgdp, kvm_mk_pgd(pudp));
+ WRITE_ONCE(*p4dp, kvm_mk_p4d(pudp));
dsb(ishst);
}
+static inline void kvm_pgd_populate(pgd_t *pgdp, p4d_t *p4dp)
+{
+#ifndef __PAGETABLE_P4D_FOLDED
+ WRITE_ONCE(*pgdp, kvm_mk_pgd(p4dp));
+ dsb(ishst);
+#endif
+}
+
/*
* Unmapping vs dcache management:
*
@@ -293,13 +310,13 @@ static void unmap_stage2_pmds(struct kvm
clear_stage2_pud_entry(kvm, pud, start_addr);
}
-static void unmap_stage2_puds(struct kvm *kvm, pgd_t *pgd,
+static void unmap_stage2_puds(struct kvm *kvm, p4d_t *p4d,
phys_addr_t addr, phys_addr_t end)
{
phys_addr_t next, start_addr = addr;
pud_t *pud, *start_pud;
- start_pud = pud = stage2_pud_offset(kvm, pgd, addr);
+ start_pud = pud = stage2_pud_offset(kvm, p4d, addr);
do {
next = stage2_pud_addr_end(kvm, addr, end);
if (!stage2_pud_none(kvm, *pud)) {
@@ -317,6 +334,23 @@ static void unmap_stage2_puds(struct kvm
} while (pud++, addr = next, addr != end);
if (stage2_pud_table_empty(kvm, start_pud))
+ clear_stage2_p4d_entry(kvm, p4d, start_addr);
+}
+
+static void unmap_stage2_p4ds(struct kvm *kvm, pgd_t *pgd,
+ phys_addr_t addr, phys_addr_t end)
+{
+ phys_addr_t next, start_addr = addr;
+ p4d_t *p4d, *start_p4d;
+
+ start_p4d = p4d = stage2_p4d_offset(kvm, pgd, addr);
+ do {
+ next = stage2_p4d_addr_end(kvm, addr, end);
+ if (!stage2_p4d_none(kvm, *p4d))
+ unmap_stage2_puds(kvm, p4d, addr, next);
+ } while (p4d++, addr = next, addr != end);
+
+ if (stage2_p4d_table_empty(kvm, start_p4d))
clear_stage2_pgd_entry(kvm, pgd, start_addr);
}
@@ -351,7 +385,7 @@ static void unmap_stage2_range(struct kv
break;
next = stage2_pgd_addr_end(kvm, addr, end);
if (!stage2_pgd_none(kvm, *pgd))
- unmap_stage2_puds(kvm, pgd, addr, next);
+ unmap_stage2_p4ds(kvm, pgd, addr, next);
/*
* If the range is too large, release the kvm->mmu_lock
* to prevent starvation and lockup detector warnings.
@@ -391,13 +425,13 @@ static void stage2_flush_pmds(struct kvm
} while (pmd++, addr = next, addr != end);
}
-static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd,
+static void stage2_flush_puds(struct kvm *kvm, p4d_t *p4d,
phys_addr_t addr, phys_addr_t end)
{
pud_t *pud;
phys_addr_t next;
- pud = stage2_pud_offset(kvm, pgd, addr);
+ pud = stage2_pud_offset(kvm, p4d, addr);
do {
next = stage2_pud_addr_end(kvm, addr, end);
if (!stage2_pud_none(kvm, *pud)) {
@@ -409,6 +443,20 @@ static void stage2_flush_puds(struct kvm
} while (pud++, addr = next, addr != end);
}
+static void stage2_flush_p4ds(struct kvm *kvm, pgd_t *pgd,
+ phys_addr_t addr, phys_addr_t end)
+{
+ p4d_t *p4d;
+ phys_addr_t next;
+
+ p4d = stage2_p4d_offset(kvm, pgd, addr);
+ do {
+ next = stage2_p4d_addr_end(kvm, addr, end);
+ if (!stage2_p4d_none(kvm, *p4d))
+ stage2_flush_puds(kvm, p4d, addr, next);
+ } while (p4d++, addr = next, addr != end);
+}
+
static void stage2_flush_memslot(struct kvm *kvm,
struct kvm_memory_slot *memslot)
{
@@ -421,7 +469,7 @@ static void stage2_flush_memslot(struct
do {
next = stage2_pgd_addr_end(kvm, addr, end);
if (!stage2_pgd_none(kvm, *pgd))
- stage2_flush_puds(kvm, pgd, addr, next);
+ stage2_flush_p4ds(kvm, pgd, addr, next);
if (next != end)
cond_resched_lock(&kvm->mmu_lock);
@@ -454,12 +502,21 @@ static void stage2_flush_vm(struct kvm *
static void clear_hyp_pgd_entry(pgd_t *pgd)
{
- pud_t *pud_table __maybe_unused = pud_offset(pgd, 0UL);
+ p4d_t *p4d_table __maybe_unused = p4d_offset(pgd, 0UL);
pgd_clear(pgd);
- pud_free(NULL, pud_table);
+ p4d_free(NULL, p4d_table);
put_page(virt_to_page(pgd));
}
+static void clear_hyp_p4d_entry(p4d_t *p4d)
+{
+ pud_t *pud_table __maybe_unused = pud_offset(p4d, 0);
+ VM_BUG_ON(p4d_huge(*p4d));
+ p4d_clear(p4d);
+ pud_free(NULL, pud_table);
+ put_page(virt_to_page(p4d));
+}
+
static void clear_hyp_pud_entry(pud_t *pud)
{
pmd_t *pmd_table __maybe_unused = pmd_offset(pud, 0);
@@ -511,12 +568,12 @@ static void unmap_hyp_pmds(pud_t *pud, p
clear_hyp_pud_entry(pud);
}
-static void unmap_hyp_puds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end)
+static void unmap_hyp_puds(p4d_t *p4d, phys_addr_t addr, phys_addr_t end)
{
phys_addr_t next;
pud_t *pud, *start_pud;
- start_pud = pud = pud_offset(pgd, addr);
+ start_pud = pud = pud_offset(p4d, addr);
do {
next = pud_addr_end(addr, end);
/* Hyp doesn't use huge puds */
@@ -525,6 +582,23 @@ static void unmap_hyp_puds(pgd_t *pgd, p
} while (pud++, addr = next, addr != end);
if (hyp_pud_table_empty(start_pud))
+ clear_hyp_p4d_entry(p4d);
+}
+
+static void unmap_hyp_p4ds(pgd_t *pgd, phys_addr_t addr, phys_addr_t end)
+{
+ phys_addr_t next;
+ p4d_t *p4d, *start_p4d;
+
+ start_p4d = p4d = p4d_offset(pgd, addr);
+ do {
+ next = p4d_addr_end(addr, end);
+ /* Hyp doesn't use huge p4ds */
+ if (!p4d_none(*p4d))
+ unmap_hyp_puds(p4d, addr, next);
+ } while (p4d++, addr = next, addr != end);
+
+ if (hyp_p4d_table_empty(start_p4d))
clear_hyp_pgd_entry(pgd);
}
@@ -548,7 +622,7 @@ static void __unmap_hyp_range(pgd_t *pgd
do {
next = pgd_addr_end(addr, end);
if (!pgd_none(*pgd))
- unmap_hyp_puds(pgd, addr, next);
+ unmap_hyp_p4ds(pgd, addr, next);
} while (pgd++, addr = next, addr != end);
}
@@ -658,7 +732,7 @@ static int create_hyp_pmd_mappings(pud_t
return 0;
}
-static int create_hyp_pud_mappings(pgd_t *pgd, unsigned long start,
+static int create_hyp_pud_mappings(p4d_t *p4d, unsigned long start,
unsigned long end, unsigned long pfn,
pgprot_t prot)
{
@@ -669,7 +743,7 @@ static int create_hyp_pud_mappings(pgd_t
addr = start;
do {
- pud = pud_offset(pgd, addr);
+ pud = pud_offset(p4d, addr);
if (pud_none_or_clear_bad(pud)) {
pmd = pmd_alloc_one(NULL, addr);
@@ -691,12 +765,45 @@ static int create_hyp_pud_mappings(pgd_t
return 0;
}
+static int create_hyp_p4d_mappings(pgd_t *pgd, unsigned long start,
+ unsigned long end, unsigned long pfn,
+ pgprot_t prot)
+{
+ p4d_t *p4d;
+ pud_t *pud;
+ unsigned long addr, next;
+ int ret;
+
+ addr = start;
+ do {
+ p4d = p4d_offset(pgd, addr);
+
+ if (p4d_none(*p4d)) {
+ pud = pud_alloc_one(NULL, addr);
+ if (!pud) {
+ kvm_err("Cannot allocate Hyp pud\n");
+ return -ENOMEM;
+ }
+ kvm_p4d_populate(p4d, pud);
+ get_page(virt_to_page(p4d));
+ }
+
+ next = p4d_addr_end(addr, end);
+ ret = create_hyp_pud_mappings(p4d, addr, next, pfn, prot);
+ if (ret)
+ return ret;
+ pfn += (next - addr) >> PAGE_SHIFT;
+ } while (addr = next, addr != end);
+
+ return 0;
+}
+
static int __create_hyp_mappings(pgd_t *pgdp, unsigned long ptrs_per_pgd,
unsigned long start, unsigned long end,
unsigned long pfn, pgprot_t prot)
{
pgd_t *pgd;
- pud_t *pud;
+ p4d_t *p4d;
unsigned long addr, next;
int err = 0;
@@ -707,18 +814,18 @@ static int __create_hyp_mappings(pgd_t *
pgd = pgdp + kvm_pgd_index(addr, ptrs_per_pgd);
if (pgd_none(*pgd)) {
- pud = pud_alloc_one(NULL, addr);
- if (!pud) {
- kvm_err("Cannot allocate Hyp pud\n");
+ p4d = p4d_alloc_one(NULL, addr);
+ if (!p4d) {
+ kvm_err("Cannot allocate Hyp p4d\n");
err = -ENOMEM;
goto out;
}
- kvm_pgd_populate(pgd, pud);
+ kvm_pgd_populate(pgd, p4d);
get_page(virt_to_page(pgd));
}
next = pgd_addr_end(addr, end);
- err = create_hyp_pud_mappings(pgd, addr, next, pfn, prot);
+ err = create_hyp_p4d_mappings(pgd, addr, next, pfn, prot);
if (err)
goto out;
pfn += (next - addr) >> PAGE_SHIFT;
@@ -1015,22 +1122,40 @@ void kvm_free_stage2_pgd(struct kvm *kvm
free_pages_exact(pgd, stage2_pgd_size(kvm));
}
-static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+static p4d_t *stage2_get_p4d(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
phys_addr_t addr)
{
pgd_t *pgd;
- pud_t *pud;
+ p4d_t *p4d;
pgd = kvm->arch.pgd + stage2_pgd_index(kvm, addr);
if (stage2_pgd_none(kvm, *pgd)) {
if (!cache)
return NULL;
- pud = mmu_memory_cache_alloc(cache);
- stage2_pgd_populate(kvm, pgd, pud);
+ p4d = mmu_memory_cache_alloc(cache);
+ stage2_pgd_populate(kvm, pgd, p4d);
get_page(virt_to_page(pgd));
}
- return stage2_pud_offset(kvm, pgd, addr);
+ return stage2_p4d_offset(kvm, pgd, addr);
+}
+
+static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+ phys_addr_t addr)
+{
+ p4d_t *p4d;
+ pud_t *pud;
+
+ p4d = stage2_get_p4d(kvm, cache, addr);
+ if (stage2_p4d_none(kvm, *p4d)) {
+ if (!cache)
+ return NULL;
+ pud = mmu_memory_cache_alloc(cache);
+ stage2_p4d_populate(kvm, p4d, pud);
+ get_page(virt_to_page(p4d));
+ }
+
+ return stage2_pud_offset(kvm, p4d, addr);
}
static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
@@ -1423,18 +1548,18 @@ static void stage2_wp_pmds(struct kvm *k
}
/**
- * stage2_wp_puds - write protect PGD range
+ * stage2_wp_puds - write protect P4D range
* @pgd: pointer to pgd entry
* @addr: range start address
* @end: range end address
*/
-static void stage2_wp_puds(struct kvm *kvm, pgd_t *pgd,
+static void stage2_wp_puds(struct kvm *kvm, p4d_t *p4d,
phys_addr_t addr, phys_addr_t end)
{
pud_t *pud;
phys_addr_t next;
- pud = stage2_pud_offset(kvm, pgd, addr);
+ pud = stage2_pud_offset(kvm, p4d, addr);
do {
next = stage2_pud_addr_end(kvm, addr, end);
if (!stage2_pud_none(kvm, *pud)) {
@@ -1449,6 +1574,26 @@ static void stage2_wp_puds(struct kvm *
}
/**
+ * stage2_wp_p4ds - write protect PGD range
+ * @pgd: pointer to pgd entry
+ * @addr: range start address
+ * @end: range end address
+ */
+static void stage2_wp_p4ds(struct kvm *kvm, pgd_t *pgd,
+ phys_addr_t addr, phys_addr_t end)
+{
+ p4d_t *p4d;
+ phys_addr_t next;
+
+ p4d = stage2_p4d_offset(kvm, pgd, addr);
+ do {
+ next = stage2_p4d_addr_end(kvm, addr, end);
+ if (!stage2_p4d_none(kvm, *p4d))
+ stage2_wp_puds(kvm, p4d, addr, next);
+ } while (p4d++, addr = next, addr != end);
+}
+
+/**
* stage2_wp_range() - write protect stage2 memory region range
* @kvm: The KVM pointer
* @addr: Start address of range
@@ -1475,7 +1620,7 @@ static void stage2_wp_range(struct kvm *
break;
next = stage2_pgd_addr_end(kvm, addr, end);
if (stage2_pgd_present(kvm, *pgd))
- stage2_wp_puds(kvm, pgd, addr, next);
+ stage2_wp_p4ds(kvm, pgd, addr, next);
} while (pgd++, addr = next, addr != end);
}
--- a/arch/arm64/mm/fault.c~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/mm/fault.c
@@ -145,6 +145,7 @@ static void show_pte(unsigned long addr)
pr_alert("[%016lx] pgd=%016llx", addr, pgd_val(pgd));
do {
+ p4d_t *p4dp, p4d;
pud_t *pudp, pud;
pmd_t *pmdp, pmd;
pte_t *ptep, pte;
@@ -152,7 +153,13 @@ static void show_pte(unsigned long addr)
if (pgd_none(pgd) || pgd_bad(pgd))
break;
- pudp = pud_offset(pgdp, addr);
+ p4dp = p4d_offset(pgdp, addr);
+ p4d = READ_ONCE(*p4dp);
+ pr_cont(", p4d=%016llx", p4d_val(p4d));
+ if (p4d_none(p4d) || p4d_bad(p4d))
+ break;
+
+ pudp = pud_offset(p4dp, addr);
pud = READ_ONCE(*pudp);
pr_cont(", pud=%016llx", pud_val(pud));
if (pud_none(pud) || pud_bad(pud))
--- a/arch/arm64/mm/hugetlbpage.c~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/mm/hugetlbpage.c
@@ -67,11 +67,13 @@ static int find_num_contig(struct mm_str
pte_t *ptep, size_t *pgsize)
{
pgd_t *pgdp = pgd_offset(mm, addr);
+ p4d_t *p4dp;
pud_t *pudp;
pmd_t *pmdp;
*pgsize = PAGE_SIZE;
- pudp = pud_offset(pgdp, addr);
+ p4dp = p4d_offset(pgdp, addr);
+ pudp = pud_offset(p4dp, addr);
pmdp = pmd_offset(pudp, addr);
if ((pte_t *)pmdp == ptep) {
*pgsize = PMD_SIZE;
@@ -217,12 +219,14 @@ pte_t *huge_pte_alloc(struct mm_struct *
unsigned long addr, unsigned long sz)
{
pgd_t *pgdp;
+ p4d_t *p4dp;
pud_t *pudp;
pmd_t *pmdp;
pte_t *ptep = NULL;
pgdp = pgd_offset(mm, addr);
- pudp = pud_alloc(mm, pgdp, addr);
+ p4dp = p4d_offset(pgdp, addr);
+ pudp = pud_alloc(mm, p4dp, addr);
if (!pudp)
return NULL;
@@ -261,6 +265,7 @@ pte_t *huge_pte_offset(struct mm_struct
unsigned long addr, unsigned long sz)
{
pgd_t *pgdp;
+ p4d_t *p4dp;
pud_t *pudp, pud;
pmd_t *pmdp, pmd;
@@ -268,7 +273,11 @@ pte_t *huge_pte_offset(struct mm_struct
if (!pgd_present(READ_ONCE(*pgdp)))
return NULL;
- pudp = pud_offset(pgdp, addr);
+ p4dp = p4d_offset(pgdp, addr);
+ if (!p4d_present(READ_ONCE(*p4dp)))
+ return NULL;
+
+ pudp = pud_offset(p4dp, addr);
pud = READ_ONCE(*pudp);
if (sz != PUD_SIZE && pud_none(pud))
return NULL;
--- a/arch/arm64/mm/kasan_init.c~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/mm/kasan_init.c
@@ -84,17 +84,17 @@ static pmd_t *__init kasan_pmd_offset(pu
return early ? pmd_offset_kimg(pudp, addr) : pmd_offset(pudp, addr);
}
-static pud_t *__init kasan_pud_offset(pgd_t *pgdp, unsigned long addr, int node,
+static pud_t *__init kasan_pud_offset(p4d_t *p4dp, unsigned long addr, int node,
bool early)
{
- if (pgd_none(READ_ONCE(*pgdp))) {
+ if (p4d_none(READ_ONCE(*p4dp))) {
phys_addr_t pud_phys = early ?
__pa_symbol(kasan_early_shadow_pud)
: kasan_alloc_zeroed_page(node);
- __pgd_populate(pgdp, pud_phys, PMD_TYPE_TABLE);
+ __p4d_populate(p4dp, pud_phys, PMD_TYPE_TABLE);
}
- return early ? pud_offset_kimg(pgdp, addr) : pud_offset(pgdp, addr);
+ return early ? pud_offset_kimg(p4dp, addr) : pud_offset(p4dp, addr);
}
static void __init kasan_pte_populate(pmd_t *pmdp, unsigned long addr,
@@ -126,11 +126,11 @@ static void __init kasan_pmd_populate(pu
} while (pmdp++, addr = next, addr != end && pmd_none(READ_ONCE(*pmdp)));
}
-static void __init kasan_pud_populate(pgd_t *pgdp, unsigned long addr,
+static void __init kasan_pud_populate(p4d_t *p4dp, unsigned long addr,
unsigned long end, int node, bool early)
{
unsigned long next;
- pud_t *pudp = kasan_pud_offset(pgdp, addr, node, early);
+ pud_t *pudp = kasan_pud_offset(p4dp, addr, node, early);
do {
next = pud_addr_end(addr, end);
@@ -138,6 +138,18 @@ static void __init kasan_pud_populate(pg
} while (pudp++, addr = next, addr != end && pud_none(READ_ONCE(*pudp)));
}
+static void __init kasan_p4d_populate(pgd_t *pgdp, unsigned long addr,
+ unsigned long end, int node, bool early)
+{
+ unsigned long next;
+ p4d_t *p4dp = p4d_offset(pgdp, addr);
+
+ do {
+ next = p4d_addr_end(addr, end);
+ kasan_pud_populate(p4dp, addr, next, node, early);
+ } while (p4dp++, addr = next, addr != end);
+}
+
static void __init kasan_pgd_populate(unsigned long addr, unsigned long end,
int node, bool early)
{
@@ -147,7 +159,7 @@ static void __init kasan_pgd_populate(un
pgdp = pgd_offset_k(addr);
do {
next = pgd_addr_end(addr, end);
- kasan_pud_populate(pgdp, addr, next, node, early);
+ kasan_p4d_populate(pgdp, addr, next, node, early);
} while (pgdp++, addr = next, addr != end);
}
--- a/arch/arm64/mm/mmu.c~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/mm/mmu.c
@@ -290,18 +290,19 @@ static void alloc_init_pud(pgd_t *pgdp,
{
unsigned long next;
pud_t *pudp;
- pgd_t pgd = READ_ONCE(*pgdp);
+ p4d_t *p4dp = p4d_offset(pgdp, addr);
+ p4d_t p4d = READ_ONCE(*p4dp);
- if (pgd_none(pgd)) {
+ if (p4d_none(p4d)) {
phys_addr_t pud_phys;
BUG_ON(!pgtable_alloc);
pud_phys = pgtable_alloc(PUD_SHIFT);
- __pgd_populate(pgdp, pud_phys, PUD_TYPE_TABLE);
- pgd = READ_ONCE(*pgdp);
+ __p4d_populate(p4dp, pud_phys, PUD_TYPE_TABLE);
+ p4d = READ_ONCE(*p4dp);
}
- BUG_ON(pgd_bad(pgd));
+ BUG_ON(p4d_bad(p4d));
- pudp = pud_set_fixmap_offset(pgdp, addr);
+ pudp = pud_set_fixmap_offset(p4dp, addr);
do {
pud_t old_pud = READ_ONCE(*pudp);
@@ -672,6 +673,7 @@ static void __init map_kernel(pgd_t *pgd
READ_ONCE(*pgd_offset_k(FIXADDR_START)));
} else if (CONFIG_PGTABLE_LEVELS > 3) {
pgd_t *bm_pgdp;
+ p4d_t *bm_p4dp;
pud_t *bm_pudp;
/*
* The fixmap shares its top level pgd entry with the kernel
@@ -681,7 +683,8 @@ static void __init map_kernel(pgd_t *pgd
*/
BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
bm_pgdp = pgd_offset_raw(pgdp, FIXADDR_START);
- bm_pudp = pud_set_fixmap_offset(bm_pgdp, FIXADDR_START);
+ bm_p4dp = p4d_offset(bm_pgdp, FIXADDR_START);
+ bm_pudp = pud_set_fixmap_offset(bm_p4dp, FIXADDR_START);
pud_populate(&init_mm, bm_pudp, lm_alias(bm_pmd));
pud_clear_fixmap();
} else {
@@ -715,6 +718,7 @@ void __init paging_init(void)
int kern_addr_valid(unsigned long addr)
{
pgd_t *pgdp;
+ p4d_t *p4dp;
pud_t *pudp, pud;
pmd_t *pmdp, pmd;
pte_t *ptep, pte;
@@ -726,7 +730,11 @@ int kern_addr_valid(unsigned long addr)
if (pgd_none(READ_ONCE(*pgdp)))
return 0;
- pudp = pud_offset(pgdp, addr);
+ p4dp = p4d_offset(pgdp, addr);
+ if (p4d_none(READ_ONCE(*p4dp)))
+ return 0;
+
+ pudp = pud_offset(p4dp, addr);
pud = READ_ONCE(*pudp);
if (pud_none(pud))
return 0;
@@ -1069,6 +1077,7 @@ int __meminit vmemmap_populate(unsigned
unsigned long addr = start;
unsigned long next;
pgd_t *pgdp;
+ p4d_t *p4dp;
pud_t *pudp;
pmd_t *pmdp;
@@ -1079,7 +1088,11 @@ int __meminit vmemmap_populate(unsigned
if (!pgdp)
return -ENOMEM;
- pudp = vmemmap_pud_populate(pgdp, addr, node);
+ p4dp = vmemmap_p4d_populate(pgdp, addr, node);
+ if (!p4dp)
+ return -ENOMEM;
+
+ pudp = vmemmap_pud_populate(p4dp, addr, node);
if (!pudp)
return -ENOMEM;
@@ -1114,11 +1127,12 @@ void vmemmap_free(unsigned long start, u
static inline pud_t * fixmap_pud(unsigned long addr)
{
pgd_t *pgdp = pgd_offset_k(addr);
- pgd_t pgd = READ_ONCE(*pgdp);
+ p4d_t *p4dp = p4d_offset(pgdp, addr);
+ p4d_t p4d = READ_ONCE(*p4dp);
- BUG_ON(pgd_none(pgd) || pgd_bad(pgd));
+ BUG_ON(p4d_none(p4d) || p4d_bad(p4d));
- return pud_offset_kimg(pgdp, addr);
+ return pud_offset_kimg(p4dp, addr);
}
static inline pmd_t * fixmap_pmd(unsigned long addr)
@@ -1144,25 +1158,27 @@ static inline pte_t * fixmap_pte(unsigne
*/
void __init early_fixmap_init(void)
{
- pgd_t *pgdp, pgd;
+ pgd_t *pgdp;
+ p4d_t *p4dp, p4d;
pud_t *pudp;
pmd_t *pmdp;
unsigned long addr = FIXADDR_START;
pgdp = pgd_offset_k(addr);
- pgd = READ_ONCE(*pgdp);
+ p4dp = p4d_offset(pgdp, addr);
+ p4d = READ_ONCE(*p4dp);
if (CONFIG_PGTABLE_LEVELS > 3 &&
- !(pgd_none(pgd) || pgd_page_paddr(pgd) == __pa_symbol(bm_pud))) {
+ !(p4d_none(p4d) || p4d_page_paddr(p4d) == __pa_symbol(bm_pud))) {
/*
* We only end up here if the kernel mapping and the fixmap
* share the top level pgd entry, which should only happen on
* 16k/4 levels configurations.
*/
BUG_ON(!IS_ENABLED(CONFIG_ARM64_16K_PAGES));
- pudp = pud_offset_kimg(pgdp, addr);
+ pudp = pud_offset_kimg(p4dp, addr);
} else {
- if (pgd_none(pgd))
- __pgd_populate(pgdp, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
+ if (p4d_none(p4d))
+ __p4d_populate(p4dp, __pa_symbol(bm_pud), PUD_TYPE_TABLE);
pudp = fixmap_pud(addr);
}
if (pud_none(READ_ONCE(*pudp)))
--- a/arch/arm64/mm/pageattr.c~arm64-add-support-for-folded-p4d-page-tables
+++ a/arch/arm64/mm/pageattr.c
@@ -198,6 +198,7 @@ void __kernel_map_pages(struct page *pag
bool kernel_page_present(struct page *page)
{
pgd_t *pgdp;
+ p4d_t *p4dp;
pud_t *pudp, pud;
pmd_t *pmdp, pmd;
pte_t *ptep;
@@ -210,7 +211,11 @@ bool kernel_page_present(struct page *pa
if (pgd_none(READ_ONCE(*pgdp)))
return false;
- pudp = pud_offset(pgdp, addr);
+ p4dp = p4d_offset(pgdp, addr);
+ if (p4d_none(READ_ONCE(*p4dp)))
+ return false;
+
+ pudp = pud_offset(p4dp, addr);
pud = READ_ONCE(*pudp);
if (pud_none(pud))
return false;
_
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCHv2 0/7] Support inhibiting input devices
From: Hans de Goede @ 2020-05-15 18:19 UTC (permalink / raw)
To: Andrzej Pietrasiewicz, linux-input, linux-acpi, linux-iio,
linux-arm-kernel, linux-samsung-soc, linux-tegra, patches,
ibm-acpi-devel, platform-driver-x86
Cc: Nick Dyer, Benjamin Tissoires, Laxman Dewangan,
Peter Meerwald-Stadler, kernel, Fabio Estevam, Lars-Peter Clausen,
Krzysztof Kozlowski, Jonathan Hunter, Kukjin Kim, NXP Linux Team,
Sylvain Lemieux, Len Brown, Peter Hutterer, Michael Hennerich,
Sascha Hauer, Henrique de Moraes Holschuh, Vladimir Zapolskiy,
Barry Song, Ferruh Yigit, Dmitry Torokhov, Rafael J . Wysocki,
Thierry Reding, Sangwon Jee, Pengutronix Kernel Team,
Hartmut Knaack, Shawn Guo, Jonathan Cameron
In-Reply-To: <20200515164943.28480-1-andrzej.p@collabora.com>
Hi Andrezj,
On 5/15/20 6:49 PM, Andrzej Pietrasiewicz wrote:
> Userspace might want to implement a policy to temporarily disregard input
> from certain devices, including not treating them as wakeup sources.
>
> An example use case is a laptop, whose keyboard can be folded under the
> screen to create tablet-like experience. The user then must hold the laptop
> in such a way that it is difficult to avoid pressing the keyboard keys. It
> is therefore desirable to temporarily disregard input from the keyboard,
> until it is folded back. This obviously is a policy which should be kept
> out of the kernel, but the kernel must provide suitable means to implement
> such a policy.
Actually libinput already binds together (inside libinput) SW_TABLET_MODE
generating evdev nodes and e.g. internal keyboards on devices with 360°
hinges for this reason. libinput simply closes the /dev/input/event#
node when folded and re-opens it when the keyboard should become active
again. Thus not only suppresses events but allows e.g. touchpads to
enter runtime suspend mode which saves power. Typically closing the
/dev/input/event# node will also disable the device as wakeup source.
So I wonder what this series actually adds for functionality for
userspace which can not already be achieved this way?
I also noticed that you keep the device open (do not call the
input_device's close callback) when inhibited and just throw away
any events generated. This seems inefficient and may lead to
the internal state getting out of sync. What if a key is pressed
while inhibited and then the device is uninhibited while the key
is still pressed? Now the press event is lost and userspace
querying the current state will see the pressed key as being
released.
On top of this you add special inhibit and uninhibit callbacks
and implement those for just a few devices. How do these differ
from just closing the device and later opening it again ?
Also using a sysfs property for this is very weird given that the
rest of the evdev interface is using ioctls for everything...
So all in all I see a lot of question marks here and I think we
need to have a detailed discussion about what use-cases this
series tries to enable before moving forward with this.
Regards,
Hans
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 0/2] irqchip/gic-v3-its: Balance LPI affinity across CPUs
From: John Garry @ 2020-05-15 18:09 UTC (permalink / raw)
To: Marc Zyngier, linux-kernel, linux-arm-kernel
Cc: Jason Cooper, chenxiang, Ming Lei, Zhou Wang, Thomas Gleixner,
kernel-team
In-Reply-To: <20200515165752.121296-1-maz@kernel.org>
On 15/05/2020 17:57, Marc Zyngier wrote:
> When mapping a LPI, the ITS driver picks the first possible
> affinity, which is in most cases CPU0, assuming that if
> that's not suitable, someone will come and set the affinity
> to something more interesting.
>
> It apparently isn't the case, and people complain of poor
> performance when many interrupts are glued to the same CPU.
> So let's place the interrupts by finding the "least loaded"
> CPU (that is, the one that has the fewer LPIs mapped to it).
> So called 'managed' interrupts are an interesting case where
> the affinity is actually dictated by the kernel itself, and
> we should honor this.
>
Cheers Marc, I ran these again and the figures look good:
NVMe with nvme.use_threaded_interrupts=1/0
Before: 1000K/1100K IOPS
After: 1100K/1400K IOPS
For some reason v5.7-rc5 looks more stable than rc4 (which I tested
previously).
Tested-by: John Garry <john.garry@huawei.com>
> * From v3:
> - Always pre-decrement/post-increment affinity to avoid useless
> changes of affinity (John)
> - Don't use the node mask as a superset of the proposed affinity
> as the ACPI tables can't really describe this (John)
> - Rebased on v5.7-rc5
>
> * From v2:
> - Split accounting from CPU selection
> - Track managed and unmanaged interrupts separately
>
> Marc Zyngier (2):
> irqchip/gic-v3-its: Track LPI distribution on a per CPU basis
> irqchip/gic-v3-its: Balance initial LPI affinity across CPUs
>
> drivers/irqchip/irq-gic-v3-its.c | 170 ++++++++++++++++++++++++++-----
> 1 file changed, 143 insertions(+), 27 deletions(-)
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 6/6] scs: Move DEFINE_SCS macro into core code
From: Will Deacon @ 2020-05-15 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: kernel-team, Kees Cook, Jann Horn, Peter Zijlstra,
Catalin Marinas, Mark Rutland, Sami Tolvanen, Will Deacon,
Ard Biesheuvel, linux-arm-kernel
In-Reply-To: <20200515172756.27185-1-will@kernel.org>
Defining static shadow call stacks is not architecture-specific, so move
the DEFINE_SCS() macro into the core header file.
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/kernel/scs.c | 4 ----
include/linux/scs.h | 4 ++++
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kernel/scs.c b/arch/arm64/kernel/scs.c
index 955875dff9e1..e8f7ff45dd8f 100644
--- a/arch/arm64/kernel/scs.c
+++ b/arch/arm64/kernel/scs.c
@@ -8,10 +8,6 @@
#include <linux/percpu.h>
#include <linux/scs.h>
-/* Allocate a static per-CPU shadow stack */
-#define DEFINE_SCS(name) \
- DEFINE_PER_CPU(unsigned long [SCS_SIZE/sizeof(long)], name) \
-
DEFINE_SCS(irq_shadow_call_stack);
#ifdef CONFIG_ARM_SDE_INTERFACE
diff --git a/include/linux/scs.h b/include/linux/scs.h
index 2fd3df50e93e..6dec390cf154 100644
--- a/include/linux/scs.h
+++ b/include/linux/scs.h
@@ -26,6 +26,10 @@
/* An illegal pointer value to mark the end of the shadow stack. */
#define SCS_END_MAGIC (0x5f6UL + POISON_POINTER_DELTA)
+/* Allocate a static per-CPU shadow stack */
+#define DEFINE_SCS(name) \
+ DEFINE_PER_CPU(unsigned long [SCS_SIZE/sizeof(long)], name) \
+
#define task_scs(tsk) (task_thread_info(tsk)->scs_base)
#define task_scs_sp(tsk) (task_thread_info(tsk)->scs_sp)
--
2.26.2.761.g0e0b3e54be-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 5/6] scs: Remove references to asm/scs.h from core code
From: Will Deacon @ 2020-05-15 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: kernel-team, Kees Cook, Jann Horn, Peter Zijlstra,
Catalin Marinas, Mark Rutland, Sami Tolvanen, Will Deacon,
Ard Biesheuvel, linux-arm-kernel
In-Reply-To: <20200515172756.27185-1-will@kernel.org>
asm/scs.h is no longer needed by the core code, so remove a redundant
header inclusion and update the stale Kconfig text.
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/Kconfig | 4 ++--
kernel/scs.c | 1 -
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 45dfca9a98d3..2e6f843d87c4 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -537,8 +537,8 @@ config ARCH_SUPPORTS_SHADOW_CALL_STACK
bool
help
An architecture should select this if it supports Clang's Shadow
- Call Stack, has asm/scs.h, and implements runtime support for shadow
- stack switching.
+ Call Stack and implements runtime support for shadow stack
+ switching.
config SHADOW_CALL_STACK
bool "Clang Shadow Call Stack"
diff --git a/kernel/scs.c b/kernel/scs.c
index faf0ecd7b893..222a7a9ad543 100644
--- a/kernel/scs.c
+++ b/kernel/scs.c
@@ -10,7 +10,6 @@
#include <linux/scs.h>
#include <linux/slab.h>
#include <linux/vmstat.h>
-#include <asm/scs.h>
static struct kmem_cache *scs_cache;
--
2.26.2.761.g0e0b3e54be-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 4/6] scs: Move scs_overflow_check() out of architecture code
From: Will Deacon @ 2020-05-15 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: kernel-team, Kees Cook, Jann Horn, Peter Zijlstra,
Catalin Marinas, Mark Rutland, Sami Tolvanen, Will Deacon,
Ard Biesheuvel, linux-arm-kernel
In-Reply-To: <20200515172756.27185-1-will@kernel.org>
There is nothing architecture-specific about scs_overflow_check() as
it's just a trivial wrapper around scs_corrupted().
For parity with task_stack_end_corrupted(), rename scs_corrupted() to
task_scs_end_corrupted() and call it from schedule_debug() when
CONFIG_SCHED_STACK_END_CHECK_is enabled. Finally, remove the unused
scs_overflow_check() function entirely.
This has absolutely no impact on architectures that do not support SCS
(currently arm64 only).
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/scs.h | 18 ------------------
arch/arm64/kernel/process.c | 2 --
arch/arm64/kernel/scs.c | 2 +-
include/linux/scs.h | 4 ++--
kernel/sched/core.c | 3 +++
kernel/scs.c | 3 ++-
6 files changed, 8 insertions(+), 24 deletions(-)
diff --git a/arch/arm64/include/asm/scs.h b/arch/arm64/include/asm/scs.h
index d46efdd2060a..eaa2cd92e4c1 100644
--- a/arch/arm64/include/asm/scs.h
+++ b/arch/arm64/include/asm/scs.h
@@ -24,24 +24,6 @@
.endm
#endif /* CONFIG_SHADOW_CALL_STACK */
-#else /* __ASSEMBLY__ */
-
-#include <linux/scs.h>
-
-#ifdef CONFIG_SHADOW_CALL_STACK
-
-static inline void scs_overflow_check(struct task_struct *tsk)
-{
- if (unlikely(scs_corrupted(tsk)))
- panic("corrupted shadow stack detected inside scheduler\n");
-}
-
-#else /* CONFIG_SHADOW_CALL_STACK */
-
-static inline void scs_overflow_check(struct task_struct *tsk) {}
-
-#endif /* CONFIG_SHADOW_CALL_STACK */
-
#endif /* __ASSEMBLY __ */
#endif /* _ASM_SCS_H */
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index a35d3318492c..56be4cbf771f 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -52,7 +52,6 @@
#include <asm/mmu_context.h>
#include <asm/processor.h>
#include <asm/pointer_auth.h>
-#include <asm/scs.h>
#include <asm/stacktrace.h>
#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK)
@@ -516,7 +515,6 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
entry_task_switch(next);
uao_thread_switch(next);
ssbs_thread_switch(next);
- scs_overflow_check(next);
/*
* Complete any pending TLB or cache maintenance on this CPU in case
diff --git a/arch/arm64/kernel/scs.c b/arch/arm64/kernel/scs.c
index adc97f826fab..955875dff9e1 100644
--- a/arch/arm64/kernel/scs.c
+++ b/arch/arm64/kernel/scs.c
@@ -6,7 +6,7 @@
*/
#include <linux/percpu.h>
-#include <asm/scs.h>
+#include <linux/scs.h>
/* Allocate a static per-CPU shadow stack */
#define DEFINE_SCS(name) \
diff --git a/include/linux/scs.h b/include/linux/scs.h
index 0eb2485ef832..2fd3df50e93e 100644
--- a/include/linux/scs.h
+++ b/include/linux/scs.h
@@ -47,7 +47,7 @@ static inline unsigned long *__scs_magic(void *s)
return (unsigned long *)(s + SCS_SIZE) - 1;
}
-static inline bool scs_corrupted(struct task_struct *tsk)
+static inline bool task_scs_end_corrupted(struct task_struct *tsk)
{
unsigned long *magic = __scs_magic(task_scs(tsk));
unsigned long sz = task_scs_sp(tsk) - task_scs(tsk);
@@ -60,8 +60,8 @@ static inline bool scs_corrupted(struct task_struct *tsk)
static inline void scs_init(void) {}
static inline void scs_task_reset(struct task_struct *tsk) {}
static inline int scs_prepare(struct task_struct *tsk, int node) { return 0; }
-static inline bool scs_corrupted(struct task_struct *tsk) { return false; }
static inline void scs_release(struct task_struct *tsk) {}
+static inline bool task_scs_end_corrupted(struct task_struct *tsk) { return false; }
#endif /* CONFIG_SHADOW_CALL_STACK */
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 934e03cfaec7..a1d815a11b90 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -3878,6 +3878,9 @@ static inline void schedule_debug(struct task_struct *prev, bool preempt)
#ifdef CONFIG_SCHED_STACK_END_CHECK
if (task_stack_end_corrupted(prev))
panic("corrupted stack end detected inside scheduler\n");
+
+ if (task_scs_end_corrupted(prev))
+ panic("corrupted shadow stack detected inside scheduler\n");
#endif
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
diff --git a/kernel/scs.c b/kernel/scs.c
index aea841cd7586..faf0ecd7b893 100644
--- a/kernel/scs.c
+++ b/kernel/scs.c
@@ -98,7 +98,8 @@ void scs_release(struct task_struct *tsk)
if (!s)
return;
- WARN(scs_corrupted(tsk), "corrupted shadow stack detected when freeing task\n");
+ WARN(task_scs_end_corrupted(tsk),
+ "corrupted shadow stack detected when freeing task\n");
scs_check_usage(tsk);
scs_free(s);
}
--
2.26.2.761.g0e0b3e54be-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH 3/6] arm64: scs: Use 'scs_sp' register alias for x18
From: Will Deacon @ 2020-05-15 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: kernel-team, Kees Cook, Jann Horn, Peter Zijlstra,
Catalin Marinas, Mark Rutland, Sami Tolvanen, Will Deacon,
Ard Biesheuvel, linux-arm-kernel
In-Reply-To: <20200515172756.27185-1-will@kernel.org>
x18 holds the SCS stack pointer value, so introduce a register alias to
make this easier to read in assembly code.
Signed-off-by: Will Deacon <will@kernel.org>
---
arch/arm64/include/asm/scs.h | 6 ++++--
arch/arm64/kernel/entry.S | 10 +++++-----
arch/arm64/kernel/head.S | 2 +-
3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/include/asm/scs.h b/arch/arm64/include/asm/scs.h
index 6b8cf4352fe3..d46efdd2060a 100644
--- a/arch/arm64/include/asm/scs.h
+++ b/arch/arm64/include/asm/scs.h
@@ -7,12 +7,14 @@
#include <asm/asm-offsets.h>
#ifdef CONFIG_SHADOW_CALL_STACK
+ scs_sp .req x18
+
.macro scs_load tsk, tmp
- ldr x18, [\tsk, #TSK_TI_SCS_SP]
+ ldr scs_sp, [\tsk, #TSK_TI_SCS_SP]
.endm
.macro scs_save tsk, tmp
- str x18, [\tsk, #TSK_TI_SCS_SP]
+ str scs_sp, [\tsk, #TSK_TI_SCS_SP]
.endm
#else
.macro scs_load tsk, tmp
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index cb0516e6f963..741faf0706f1 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -394,7 +394,7 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
.macro irq_stack_entry
mov x19, sp // preserve the original sp
#ifdef CONFIG_SHADOW_CALL_STACK
- mov x24, x18 // preserve the original shadow stack
+ mov x24, scs_sp // preserve the original shadow stack
#endif
/*
@@ -416,7 +416,7 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
#ifdef CONFIG_SHADOW_CALL_STACK
/* also switch to the irq shadow stack */
- adr_this_cpu x18, irq_shadow_call_stack, x26
+ adr_this_cpu scs_sp, irq_shadow_call_stack, x26
#endif
9998:
@@ -430,7 +430,7 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
.macro irq_stack_exit
mov sp, x19
#ifdef CONFIG_SHADOW_CALL_STACK
- mov x18, x24
+ mov scs_sp, x24
#endif
.endm
@@ -1071,9 +1071,9 @@ SYM_CODE_START(__sdei_asm_handler)
#ifdef CONFIG_SHADOW_CALL_STACK
/* Use a separate shadow call stack for normal and critical events */
cbnz w4, 3f
- adr_this_cpu dst=x18, sym=sdei_shadow_call_stack_normal, tmp=x6
+ adr_this_cpu dst=scs_sp, sym=sdei_shadow_call_stack_normal, tmp=x6
b 4f
-3: adr_this_cpu dst=x18, sym=sdei_shadow_call_stack_critical, tmp=x6
+3: adr_this_cpu dst=scs_sp, sym=sdei_shadow_call_stack_critical, tmp=x6
4:
#endif
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 2b01c19c5483..1293baddfd20 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -426,7 +426,7 @@ SYM_FUNC_START_LOCAL(__primary_switched)
mov x29, sp
#ifdef CONFIG_SHADOW_CALL_STACK
- adr_l x18, init_shadow_call_stack // Set shadow call stack
+ adr_l scs_sp, init_shadow_call_stack // Set shadow call stack
#endif
str_l x21, __fdt_pointer, x5 // Save FDT pointer
--
2.26.2.761.g0e0b3e54be-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ 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