LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 8/8] net: ethernet: ibm: ibmvnic: Fix some kernel-doc issues
From: Andrew Lunn @ 2020-11-29 19:10 UTC (permalink / raw)
  To: Lee Jones
  Cc: Thomas Falcon, John Allen, linux-kernel, Santiago Leon,
	Jakub Kicinski, netdev, Lijun Pan, Dany Madden, Paul Mackerras,
	Sukadev Bhattiprolu, linuxppc-dev, David S. Miller
In-Reply-To: <20201126133853.3213268-9-lee.jones@linaro.org>

On Thu, Nov 26, 2020 at 01:38:53PM +0000, Lee Jones wrote:
> Fixes the following W=1 kernel build warning(s):
> 
>  from drivers/net/ethernet/ibm/ibmvnic.c:35:
>  inlined from ‘handle_vpd_rsp’ at drivers/net/ethernet/ibm/ibmvnic.c:4124:3:
>  drivers/net/ethernet/ibm/ibmvnic.c:1362: warning: Function parameter or member 'hdr_data' not described in 'build_hdr_data'
>  drivers/net/ethernet/ibm/ibmvnic.c:1362: warning: Excess function parameter 'tot_len' description in 'build_hdr_data'
>  drivers/net/ethernet/ibm/ibmvnic.c:1423: warning: Function parameter or member 'hdr_data' not described in 'create_hdr_descs'
>  drivers/net/ethernet/ibm/ibmvnic.c:1423: warning: Excess function parameter 'data' description in 'create_hdr_descs'
>  drivers/net/ethernet/ibm/ibmvnic.c:1474: warning: Function parameter or member 'txbuff' not described in 'build_hdr_descs_arr'
>  drivers/net/ethernet/ibm/ibmvnic.c:1474: warning: Excess function parameter 'skb' description in 'build_hdr_descs_arr'
>  drivers/net/ethernet/ibm/ibmvnic.c:1474: warning: Excess function parameter 'subcrq' description in 'build_hdr_descs_arr'

Hi Lee

It looks like this should be squashed into the previous patch to this
file.

	Andrew

^ permalink raw reply

* Re: [PATCH 6/8] lazy tlb: shoot lazies, a non-refcounting lazy tlb option
From: Andy Lutomirski @ 2020-11-29 20:16 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: linux-arch, Arnd Bergmann, Peter Zijlstra, X86 ML, LKML,
	Nicholas Piggin, Linux-MM, Mathieu Desnoyers, linuxppc-dev
In-Reply-To: <CALCETrVXUbe8LfNn-Qs+DzrOQaiw+sFUg1J047yByV31SaTOZw@mail.gmail.com>

On Sat, Nov 28, 2020 at 7:54 PM Andy Lutomirski <luto@kernel.org> wrote:
>
> On Sat, Nov 28, 2020 at 8:02 AM Nicholas Piggin <npiggin@gmail.com> wrote:
> >
> > On big systems, the mm refcount can become highly contented when doing
> > a lot of context switching with threaded applications (particularly
> > switching between the idle thread and an application thread).
> >
> > Abandoning lazy tlb slows switching down quite a bit in the important
> > user->idle->user cases, so so instead implement a non-refcounted scheme
> > that causes __mmdrop() to IPI all CPUs in the mm_cpumask and shoot down
> > any remaining lazy ones.
> >
> > Shootdown IPIs are some concern, but they have not been observed to be
> > a big problem with this scheme (the powerpc implementation generated
> > 314 additional interrupts on a 144 CPU system during a kernel compile).
> > There are a number of strategies that could be employed to reduce IPIs
> > if they turn out to be a problem for some workload.
>
> I'm still wondering whether we can do even better.
>

Hold on a sec.. __mmput() unmaps VMAs, frees pagetables, and flushes
the TLB.  On x86, this will shoot down all lazies as long as even a
single pagetable was freed.  (Or at least it will if we don't have a
serious bug, but the code seems okay.  We'll hit pmd_free_tlb, which
sets tlb->freed_tables, which will trigger the IPI.)  So, on
architectures like x86, the shootdown approach should be free.  The
only way it ought to have any excess IPIs is if we have CPUs in
mm_cpumask() that don't need IPI to free pagetables, which could
happen on paravirt.

Can you try to figure out why you saw any increase in IPIs?  It would
be nice if we can make the new code unconditional.

^ permalink raw reply

* [PATCH v6 1/5] PCI: Unify ECAM constants in native PCI Express drivers
From: Krzysztof Wilczyński @ 2020-11-29 23:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Heiko Stuebner, Shawn Lin, Paul Mackerras, Thomas Petazzoni,
	Jonathan Chocron, Toan Le, Will Deacon, Rob Herring,
	Lorenzo Pieralisi, Michal Simek, linux-rockchip,
	bcm-kernel-feedback-list, Jonathan Derrick, linux-pci, Ray Jui,
	Florian Fainelli, linux-rpi-kernel, Jonathan Cameron,
	linux-arm-kernel, Scott Branden, Zhou Wang, Robert Richter,
	linuxppc-dev, Nicolas Saenz Julienne
In-Reply-To: <20201129230743.3006978-1-kw@linux.com>

Add ECAM-related constants to provide a set of standard constants
defining memory address shift values to the byte-level address that can
be used to access the PCI Express Configuration Space, and then move
native PCI Express controller drivers to use the newly introduced
definitions retiring driver-specific ones.

Refactor pci_ecam_map_bus() function to use newly added constants so
that limits to the bus, device function and offset (now limited to 4K as
per the specification) are in place to prevent the defective or
malicious caller from supplying incorrect configuration offset and thus
targeting the wrong device when accessing extended configuration space.
This refactor also allows for the ".bus_shit" initialisers to be dropped
when the user is not using a custom value as a default value will be
used as per the PCI Express Specification.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kw@linux.com>
---
 drivers/pci/controller/dwc/pcie-al.c        | 12 ++-------
 drivers/pci/controller/dwc/pcie-hisi.c      |  2 --
 drivers/pci/controller/pci-aardvark.c       | 13 +++-------
 drivers/pci/controller/pci-host-generic.c   |  1 -
 drivers/pci/controller/pci-thunder-ecam.c   |  1 -
 drivers/pci/controller/pcie-brcmstb.c       | 16 ++----------
 drivers/pci/controller/pcie-rockchip-host.c | 27 ++++++++++-----------
 drivers/pci/controller/pcie-rockchip.h      |  8 +-----
 drivers/pci/controller/pcie-tango.c         |  1 -
 drivers/pci/controller/pcie-xilinx-nwl.c    |  9 ++-----
 drivers/pci/controller/pcie-xilinx.c        | 11 ++-------
 drivers/pci/controller/vmd.c                | 11 ++++-----
 drivers/pci/ecam.c                          | 23 ++++++++++++------
 include/linux/pci-ecam.h                    | 27 +++++++++++++++++++++
 14 files changed, 73 insertions(+), 89 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-al.c b/drivers/pci/controller/dwc/pcie-al.c
index f973fbca90cf..af9e51ab1af8 100644
--- a/drivers/pci/controller/dwc/pcie-al.c
+++ b/drivers/pci/controller/dwc/pcie-al.c
@@ -76,7 +76,6 @@ static int al_pcie_init(struct pci_config_window *cfg)
 }
 
 const struct pci_ecam_ops al_pcie_ops = {
-	.bus_shift    = 20,
 	.init         =  al_pcie_init,
 	.pci_ops      = {
 		.map_bus    = al_pcie_map_bus,
@@ -138,8 +137,6 @@ struct al_pcie {
 	struct al_pcie_target_bus_cfg target_bus_cfg;
 };
 
-#define PCIE_ECAM_DEVFN(x)		(((x) & 0xff) << 12)
-
 #define to_al_pcie(x)		dev_get_drvdata((x)->dev)
 
 static inline u32 al_pcie_controller_readl(struct al_pcie *pcie, u32 offset)
@@ -226,11 +223,6 @@ static void __iomem *al_pcie_conf_addr_map_bus(struct pci_bus *bus,
 	struct al_pcie_target_bus_cfg *target_bus_cfg = &pcie->target_bus_cfg;
 	unsigned int busnr_ecam = busnr & target_bus_cfg->ecam_mask;
 	unsigned int busnr_reg = busnr & target_bus_cfg->reg_mask;
-	void __iomem *pci_base_addr;
-
-	pci_base_addr = (void __iomem *)((uintptr_t)pp->va_cfg0_base +
-					 (busnr_ecam << 20) +
-					 PCIE_ECAM_DEVFN(devfn));
 
 	if (busnr_reg != target_bus_cfg->reg_val) {
 		dev_dbg(pcie->pci->dev, "Changing target bus busnum val from 0x%x to 0x%x\n",
@@ -241,7 +233,7 @@ static void __iomem *al_pcie_conf_addr_map_bus(struct pci_bus *bus,
 				       target_bus_cfg->reg_mask);
 	}
 
-	return pci_base_addr + where;
+	return pp->va_cfg0_base + PCIE_ECAM_OFFSET(busnr_ecam, devfn, where);
 }
 
 static struct pci_ops al_child_pci_ops = {
@@ -264,7 +256,7 @@ static void al_pcie_config_prepare(struct al_pcie *pcie)
 
 	target_bus_cfg = &pcie->target_bus_cfg;
 
-	ecam_bus_mask = (pcie->ecam_size >> 20) - 1;
+	ecam_bus_mask = (pcie->ecam_size >> PCIE_ECAM_BUS_SHIFT) - 1;
 	if (ecam_bus_mask > 255) {
 		dev_warn(pcie->dev, "ECAM window size is larger than 256MB. Cutting off at 256\n");
 		ecam_bus_mask = 255;
diff --git a/drivers/pci/controller/dwc/pcie-hisi.c b/drivers/pci/controller/dwc/pcie-hisi.c
index 5ca86796d43a..8fc5960faf28 100644
--- a/drivers/pci/controller/dwc/pcie-hisi.c
+++ b/drivers/pci/controller/dwc/pcie-hisi.c
@@ -100,7 +100,6 @@ static int hisi_pcie_init(struct pci_config_window *cfg)
 }
 
 const struct pci_ecam_ops hisi_pcie_ops = {
-	.bus_shift    = 20,
 	.init         =  hisi_pcie_init,
 	.pci_ops      = {
 		.map_bus    = hisi_pcie_map_bus,
@@ -135,7 +134,6 @@ static int hisi_pcie_platform_init(struct pci_config_window *cfg)
 }
 
 static const struct pci_ecam_ops hisi_pcie_platform_ops = {
-	.bus_shift    = 20,
 	.init         =  hisi_pcie_platform_init,
 	.pci_ops      = {
 		.map_bus    = hisi_pcie_map_bus,
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index 0be485a25327..1043e54c73bd 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/init.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
@@ -164,14 +165,6 @@
 #define PCIE_CONFIG_WR_TYPE0			0xa
 #define PCIE_CONFIG_WR_TYPE1			0xb
 
-#define PCIE_CONF_BUS(bus)			(((bus) & 0xff) << 20)
-#define PCIE_CONF_DEV(dev)			(((dev) & 0x1f) << 15)
-#define PCIE_CONF_FUNC(fun)			(((fun) & 0x7)	<< 12)
-#define PCIE_CONF_REG(reg)			((reg) & 0xffc)
-#define PCIE_CONF_ADDR(bus, devfn, where)	\
-	(PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn))	| \
-	 PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where))
-
 #define PIO_RETRY_CNT			500
 #define PIO_RETRY_DELAY			2 /* 2 us*/
 
@@ -687,7 +680,7 @@ static int advk_pcie_rd_conf(struct pci_bus *bus, u32 devfn,
 	advk_writel(pcie, reg, PIO_CTRL);
 
 	/* Program the address registers */
-	reg = PCIE_CONF_ADDR(bus->number, devfn, where);
+	reg = ALIGN_DOWN(PCIE_ECAM_OFFSET(bus->number, devfn, where), 4);
 	advk_writel(pcie, reg, PIO_ADDR_LS);
 	advk_writel(pcie, 0, PIO_ADDR_MS);
 
@@ -748,7 +741,7 @@ static int advk_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
 	advk_writel(pcie, reg, PIO_CTRL);
 
 	/* Program the address registers */
-	reg = PCIE_CONF_ADDR(bus->number, devfn, where);
+	reg = ALIGN_DOWN(PCIE_ECAM_OFFSET(bus->number, devfn, where), 4);
 	advk_writel(pcie, reg, PIO_ADDR_LS);
 	advk_writel(pcie, 0, PIO_ADDR_MS);
 
diff --git a/drivers/pci/controller/pci-host-generic.c b/drivers/pci/controller/pci-host-generic.c
index b51977abfdf1..63865aeb636b 100644
--- a/drivers/pci/controller/pci-host-generic.c
+++ b/drivers/pci/controller/pci-host-generic.c
@@ -49,7 +49,6 @@ static void __iomem *pci_dw_ecam_map_bus(struct pci_bus *bus,
 }
 
 static const struct pci_ecam_ops pci_dw_ecam_bus_ops = {
-	.bus_shift	= 20,
 	.pci_ops	= {
 		.map_bus	= pci_dw_ecam_map_bus,
 		.read		= pci_generic_config_read,
diff --git a/drivers/pci/controller/pci-thunder-ecam.c b/drivers/pci/controller/pci-thunder-ecam.c
index 7e8835fee5f7..f964fd26f7e0 100644
--- a/drivers/pci/controller/pci-thunder-ecam.c
+++ b/drivers/pci/controller/pci-thunder-ecam.c
@@ -346,7 +346,6 @@ static int thunder_ecam_config_write(struct pci_bus *bus, unsigned int devfn,
 }
 
 const struct pci_ecam_ops pci_thunder_ecam_ops = {
-	.bus_shift	= 20,
 	.pci_ops	= {
 		.map_bus        = pci_ecam_map_bus,
 		.read           = thunder_ecam_config_read,
diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index bea86899bd5d..7fc80fd6f13f 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -22,6 +22,7 @@
 #include <linux/of_pci.h>
 #include <linux/of_platform.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/printk.h>
 #include <linux/reset.h>
 #include <linux/sizes.h>
@@ -127,11 +128,7 @@
 #define  MSI_INT_MASK_CLR		0x14
 
 #define PCIE_EXT_CFG_DATA				0x8000
-
 #define PCIE_EXT_CFG_INDEX				0x9000
-#define  PCIE_EXT_BUSNUM_SHIFT				20
-#define  PCIE_EXT_SLOT_SHIFT				15
-#define  PCIE_EXT_FUNC_SHIFT				12
 
 #define  PCIE_RGR1_SW_INIT_1_PERST_MASK			0x1
 #define  PCIE_RGR1_SW_INIT_1_PERST_SHIFT		0x0
@@ -695,15 +692,6 @@ static bool brcm_pcie_link_up(struct brcm_pcie *pcie)
 	return dla && plu;
 }
 
-/* Configuration space read/write support */
-static inline int brcm_pcie_cfg_index(int busnr, int devfn, int reg)
-{
-	return ((PCI_SLOT(devfn) & 0x1f) << PCIE_EXT_SLOT_SHIFT)
-		| ((PCI_FUNC(devfn) & 0x07) << PCIE_EXT_FUNC_SHIFT)
-		| (busnr << PCIE_EXT_BUSNUM_SHIFT)
-		| (reg & ~3);
-}
-
 static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
 					int where)
 {
@@ -716,7 +704,7 @@ static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
 		return PCI_SLOT(devfn) ? NULL : base + where;
 
 	/* For devices, write to the config space index register */
-	idx = brcm_pcie_cfg_index(bus->number, devfn, 0);
+	idx = PCIE_ECAM_OFFSET(bus->number, devfn, 0);
 	writel(idx, pcie->base + PCIE_EXT_CFG_INDEX);
 	return base + PCIE_EXT_CFG_DATA + where;
 }
diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
index 9705059523a6..f1d08a1b1591 100644
--- a/drivers/pci/controller/pcie-rockchip-host.c
+++ b/drivers/pci/controller/pcie-rockchip-host.c
@@ -157,12 +157,11 @@ static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip,
 				       struct pci_bus *bus, u32 devfn,
 				       int where, int size, u32 *val)
 {
-	u32 busdev;
+	void __iomem *addr;
 
-	busdev = PCIE_ECAM_ADDR(bus->number, PCI_SLOT(devfn),
-				PCI_FUNC(devfn), where);
+	addr = rockchip->reg_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
 
-	if (!IS_ALIGNED(busdev, size)) {
+	if (!IS_ALIGNED((uintptr_t)addr, size)) {
 		*val = 0;
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 	}
@@ -175,11 +174,11 @@ static int rockchip_pcie_rd_other_conf(struct rockchip_pcie *rockchip,
 						AXI_WRAPPER_TYPE1_CFG);
 
 	if (size == 4) {
-		*val = readl(rockchip->reg_base + busdev);
+		*val = readl(addr);
 	} else if (size == 2) {
-		*val = readw(rockchip->reg_base + busdev);
+		*val = readw(addr);
 	} else if (size == 1) {
-		*val = readb(rockchip->reg_base + busdev);
+		*val = readb(addr);
 	} else {
 		*val = 0;
 		return PCIBIOS_BAD_REGISTER_NUMBER;
@@ -191,11 +190,11 @@ static int rockchip_pcie_wr_other_conf(struct rockchip_pcie *rockchip,
 				       struct pci_bus *bus, u32 devfn,
 				       int where, int size, u32 val)
 {
-	u32 busdev;
+	void __iomem *addr;
 
-	busdev = PCIE_ECAM_ADDR(bus->number, PCI_SLOT(devfn),
-				PCI_FUNC(devfn), where);
-	if (!IS_ALIGNED(busdev, size))
+	addr = rockchip->reg_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
+
+	if (!IS_ALIGNED((uintptr_t)addr, size))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	if (pci_is_root_bus(bus->parent))
@@ -206,11 +205,11 @@ static int rockchip_pcie_wr_other_conf(struct rockchip_pcie *rockchip,
 						AXI_WRAPPER_TYPE1_CFG);
 
 	if (size == 4)
-		writel(val, rockchip->reg_base + busdev);
+		writel(val, addr);
 	else if (size == 2)
-		writew(val, rockchip->reg_base + busdev);
+		writew(val, addr);
 	else if (size == 1)
-		writeb(val, rockchip->reg_base + busdev);
+		writeb(val, addr);
 	else
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
diff --git a/drivers/pci/controller/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
index c7d0178fc8c2..1650a5087450 100644
--- a/drivers/pci/controller/pcie-rockchip.h
+++ b/drivers/pci/controller/pcie-rockchip.h
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 
 /*
  * The upper 16 bits of PCIE_CLIENT_CONFIG are a write mask for the lower 16
@@ -178,13 +179,6 @@
 #define MIN_AXI_ADDR_BITS_PASSED		8
 #define PCIE_RC_SEND_PME_OFF			0x11960
 #define ROCKCHIP_VENDOR_ID			0x1d87
-#define PCIE_ECAM_BUS(x)			(((x) & 0xff) << 20)
-#define PCIE_ECAM_DEV(x)			(((x) & 0x1f) << 15)
-#define PCIE_ECAM_FUNC(x)			(((x) & 0x7) << 12)
-#define PCIE_ECAM_REG(x)			(((x) & 0xfff) << 0)
-#define PCIE_ECAM_ADDR(bus, dev, func, reg) \
-	  (PCIE_ECAM_BUS(bus) | PCIE_ECAM_DEV(dev) | \
-	   PCIE_ECAM_FUNC(func) | PCIE_ECAM_REG(reg))
 #define PCIE_LINK_IS_L2(x) \
 	(((x) & PCIE_CLIENT_DEBUG_LTSSM_MASK) == PCIE_CLIENT_DEBUG_LTSSM_L2)
 #define PCIE_LINK_UP(x) \
diff --git a/drivers/pci/controller/pcie-tango.c b/drivers/pci/controller/pcie-tango.c
index d093a8ce4bb1..62a061f1d62e 100644
--- a/drivers/pci/controller/pcie-tango.c
+++ b/drivers/pci/controller/pcie-tango.c
@@ -208,7 +208,6 @@ static int smp8759_config_write(struct pci_bus *bus, unsigned int devfn,
 }
 
 static const struct pci_ecam_ops smp8759_ecam_ops = {
-	.bus_shift	= 20,
 	.pci_ops	= {
 		.map_bus	= pci_ecam_map_bus,
 		.read		= smp8759_config_read,
diff --git a/drivers/pci/controller/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c
index f3cf7d61924f..7f29c2fdcd51 100644
--- a/drivers/pci/controller/pcie-xilinx-nwl.c
+++ b/drivers/pci/controller/pcie-xilinx-nwl.c
@@ -18,6 +18,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
 #include <linux/irqchip/chained_irq.h>
 
@@ -124,8 +125,6 @@
 #define E_ECAM_CR_ENABLE		BIT(0)
 #define E_ECAM_SIZE_LOC			GENMASK(20, 16)
 #define E_ECAM_SIZE_SHIFT		16
-#define ECAM_BUS_LOC_SHIFT		20
-#define ECAM_DEV_LOC_SHIFT		12
 #define NWL_ECAM_VALUE_DEFAULT		12
 
 #define CFG_DMA_REG_BAR			GENMASK(2, 0)
@@ -240,15 +239,11 @@ static void __iomem *nwl_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
 				      int where)
 {
 	struct nwl_pcie *pcie = bus->sysdata;
-	int relbus;
 
 	if (!nwl_pcie_valid_device(bus, devfn))
 		return NULL;
 
-	relbus = (bus->number << ECAM_BUS_LOC_SHIFT) |
-			(devfn << ECAM_DEV_LOC_SHIFT);
-
-	return pcie->ecam_base + relbus + where;
+	return pcie->ecam_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
 }
 
 /* PCIe operations */
diff --git a/drivers/pci/controller/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
index 8523be61bba5..fa5baeb82653 100644
--- a/drivers/pci/controller/pcie-xilinx.c
+++ b/drivers/pci/controller/pcie-xilinx.c
@@ -21,6 +21,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_irq.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/platform_device.h>
 
 #include "../pci.h"
@@ -86,10 +87,6 @@
 /* Phy Status/Control Register definitions */
 #define XILINX_PCIE_REG_PSCR_LNKUP	BIT(11)
 
-/* ECAM definitions */
-#define ECAM_BUS_NUM_SHIFT		20
-#define ECAM_DEV_NUM_SHIFT		12
-
 /* Number of MSI IRQs */
 #define XILINX_NUM_MSI_IRQS		128
 
@@ -183,15 +180,11 @@ static void __iomem *xilinx_pcie_map_bus(struct pci_bus *bus,
 					 unsigned int devfn, int where)
 {
 	struct xilinx_pcie_port *port = bus->sysdata;
-	int relbus;
 
 	if (!xilinx_pcie_valid_device(bus, devfn))
 		return NULL;
 
-	relbus = (bus->number << ECAM_BUS_NUM_SHIFT) |
-		 (devfn << ECAM_DEV_NUM_SHIFT);
-
-	return port->reg_base + relbus + where;
+	return port->reg_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
 }
 
 /* PCIe operations */
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index f375c21ceeb1..1361a79bd1e7 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/msi.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/srcu.h>
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
@@ -328,15 +329,13 @@ static void vmd_remove_irq_domain(struct vmd_dev *vmd)
 static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus,
 				  unsigned int devfn, int reg, int len)
 {
-	char __iomem *addr = vmd->cfgbar +
-			     ((bus->number - vmd->busn_start) << 20) +
-			     (devfn << 12) + reg;
+	unsigned int busnr_ecam = bus->number - vmd->busn_start;
+	u32 offset = PCIE_ECAM_OFFSET(busnr_ecam, devfn, reg);
 
-	if ((addr - vmd->cfgbar) + len >=
-	    resource_size(&vmd->dev->resource[VMD_CFGBAR]))
+	if (offset + len >= resource_size(&vmd->dev->resource[VMD_CFGBAR]))
 		return NULL;
 
-	return addr;
+	return vmd->cfgbar + offset;
 }
 
 /*
diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c
index b54d32a31669..59f91d434859 100644
--- a/drivers/pci/ecam.c
+++ b/drivers/pci/ecam.c
@@ -131,25 +131,36 @@ void __iomem *pci_ecam_map_bus(struct pci_bus *bus, unsigned int devfn,
 			       int where)
 {
 	struct pci_config_window *cfg = bus->sysdata;
+	unsigned int bus_shift = cfg->ops->bus_shift;
 	unsigned int devfn_shift = cfg->ops->bus_shift - 8;
 	unsigned int busn = bus->number;
 	void __iomem *base;
+	u32 bus_offset, devfn_offset;
 
 	if (busn < cfg->busr.start || busn > cfg->busr.end)
 		return NULL;
 
 	busn -= cfg->busr.start;
-	if (per_bus_mapping)
+	if (per_bus_mapping) {
 		base = cfg->winp[busn];
-	else
-		base = cfg->win + (busn << cfg->ops->bus_shift);
-	return base + (devfn << devfn_shift) + where;
+		busn = 0;
+	} else
+		base = cfg->win;
+
+	if (cfg->ops->bus_shift) {
+		bus_offset = (busn & PCIE_ECAM_BUS_MASK) << bus_shift;
+		devfn_offset = (devfn & PCIE_ECAM_DEVFN_MASK) << devfn_shift;
+		where &= PCIE_ECAM_REG_MASK;
+
+		return base + (bus_offset | devfn_offset | where);
+	}
+
+	return base + PCIE_ECAM_OFFSET(busn, devfn, where);
 }
 EXPORT_SYMBOL_GPL(pci_ecam_map_bus);
 
 /* ECAM ops */
 const struct pci_ecam_ops pci_generic_ecam_ops = {
-	.bus_shift	= 20,
 	.pci_ops	= {
 		.map_bus	= pci_ecam_map_bus,
 		.read		= pci_generic_config_read,
@@ -161,7 +172,6 @@ EXPORT_SYMBOL_GPL(pci_generic_ecam_ops);
 #if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
 /* ECAM ops for 32-bit access only (non-compliant) */
 const struct pci_ecam_ops pci_32b_ops = {
-	.bus_shift	= 20,
 	.pci_ops	= {
 		.map_bus	= pci_ecam_map_bus,
 		.read		= pci_generic_config_read32,
@@ -171,7 +181,6 @@ const struct pci_ecam_ops pci_32b_ops = {
 
 /* ECAM ops for 32-bit read only (non-compliant) */
 const struct pci_ecam_ops pci_32b_read_ops = {
-	.bus_shift	= 20,
 	.pci_ops	= {
 		.map_bus	= pci_ecam_map_bus,
 		.read		= pci_generic_config_read32,
diff --git a/include/linux/pci-ecam.h b/include/linux/pci-ecam.h
index 033ce74f02e8..65d3d83015c3 100644
--- a/include/linux/pci-ecam.h
+++ b/include/linux/pci-ecam.h
@@ -9,6 +9,33 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
+/*
+ * Memory address shift values for the byte-level address that
+ * can be used when accessing the PCI Express Configuration Space.
+ */
+
+/*
+ * Enhanced Configuration Access Mechanism (ECAM)
+ *
+ * See PCI Express Base Specification, Revision 5.0, Version 1.0,
+ * Section 7.2.2, Table 7-1, p. 677.
+ */
+#define PCIE_ECAM_BUS_SHIFT	20 /* Bus number */
+#define PCIE_ECAM_DEVFN_SHIFT	12 /* Device and Function number */
+
+#define PCIE_ECAM_BUS_MASK	0xff
+#define PCIE_ECAM_DEVFN_MASK	0xff
+#define PCIE_ECAM_REG_MASK	0xfff /* Limit offset to a maximum of 4K */
+
+#define PCIE_ECAM_BUS(x)	(((x) & PCIE_ECAM_BUS_MASK) << PCIE_ECAM_BUS_SHIFT)
+#define PCIE_ECAM_DEVFN(x)	(((x) & PCIE_ECAM_DEVFN_MASK) << PCIE_ECAM_DEVFN_SHIFT)
+#define PCIE_ECAM_REG(x)	((x) & PCIE_ECAM_REG_MASK)
+
+#define PCIE_ECAM_OFFSET(bus, devfn, where) \
+	(PCIE_ECAM_BUS(bus) | \
+	 PCIE_ECAM_DEVFN(devfn) | \
+	 PCIE_ECAM_REG(where))
+
 /*
  * struct to hold pci ops and bus shift of the config window
  * for a PCI controller.
-- 
2.29.2


^ permalink raw reply related

* [PATCH v6 0/5] PCI: Unify ECAM constants in native PCI Express drivers
From: Krzysztof Wilczyński @ 2020-11-29 23:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Heiko Stuebner, Shawn Lin, Paul Mackerras, Thomas Petazzoni,
	Jonathan Chocron, Toan Le, Will Deacon, Rob Herring,
	Lorenzo Pieralisi, Michal Simek, linux-rockchip,
	bcm-kernel-feedback-list, Jonathan Derrick, linux-pci, Ray Jui,
	Florian Fainelli, linux-rpi-kernel, Jonathan Cameron,
	linux-arm-kernel, Scott Branden, Zhou Wang, Robert Richter,
	linuxppc-dev, Nicolas Saenz Julienne

Unify ECAM-related constants into a single set of standard constants
defining memory address shift values for the byte-level address that can
be used when accessing the PCI Express Configuration Space, and then
move native PCI Express controller drivers to use newly introduced
definitions retiring any driver-specific ones.

The ECAM ("Enhanced Configuration Access Mechanism") is defined by the
PCI Express specification (see PCI Express Base Specification, Revision
5.0, Version 1.0, Section 7.2.2, p. 676), thus most hardware should
implement it the same way.

Most of the native PCI Express controller drivers define their ECAM-related
constants, many of these could be shared, or use open-coded values when
setting the ".bus_shift" field of the "struct pci_ecam_ops".

All of the newly added constants should remove ambiguity and reduce the
number of open-coded values, and also correlate more strongly with the
descriptions in the aforementioned specification (see Table 7-1
"Enhanced Configuration Address Mapping", p. 677).

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kw@linux.com>

--- 
Changed in v6:
  Converted single patch into a series.
  Dropped changes related to PPC 4xx platform.
  Refactored pci_ecam_map_bus() so that bus, device function and offset
  are correctly masked, limiting offset to 4K as per the PCI Express
  Specification.  After the refactor this function will now use sensible
  defaults allowing for removal of the ".bus_shit" initialiser from all
  the users of the "ecam_ops" structure who do not use a non-standard
  ECAM bus shit values.

Changed in v5:
  Removed unused constant "PCIE_ECAM_DEV_SHIFT".
  Refactored ppc4xx_pciex_get_config_base() so that the "offset"
  parameter can be passed to so that the PCIE_ECAM_OFFSET() macro
  can be used.
  Used the ALIGN_DOWN() macro where 32 bit alignment is required
  instead using the 0xffc mask.
  Added CFG_ADDR_CFG_TYPE_1 macro to pci/controller/pcie-iproc.c to
  denote that this is a configuration type 1 address and access type.
  Refactored boundary check in pci/controller/vmd.c as used by the
  vmd_cfg_addr() function following addition of the PCIE_ECAM_OFFSET()
  macro.
  Changed the "bus->number" to simply pass the "bus" argument in the
  PCIE_ECAM_OFFSET() macro.

Changed in v4:
  Removed constants related to "CAM".
  Added more platforms and devices that can use new ECAM macros and
  constants.
  Removed unused ".bus_shift" initialisers from pci-xgene.c as
  xgene_pcie_map_bus() did not use these.

Changes in v3:
  Updated commit message wording.
  Updated regarding custom ECAM bus shift values and concerning PCI base
  configuration space access for Type 1 access.
  Refactored rockchip_pcie_rd_other_conf() and rockchip_pcie_wr_other_conf()
  and removed the "busdev" variable.
  Removed surplus "relbus" variable from nwl_pcie_map_bus() and
  xilinx_pcie_map_bus().
  Renamed the PCIE_ECAM_ADDR() macro to PCIE_ECAM_OFFSET().

Changes in v2:
  Use PCIE_ECAM_ADDR macro when computing ECAM address offset, but drop
  PCI_SLOT and PCI_FUNC macros from the PCIE_ECAM_ADDR macro in favour
  of using a single value for the device/function.

Krzysztof Wilczyński (5):
  PCI: Unify ECAM constants in native PCI Express drivers
  PCI: thunder-pem: Add constant for custom ".bus_shit" initialiser
  PCI: iproc: Convert to use the new ECAM constants
  PCI: vmd: Update type of the __iomem pointers
  PCI: xgene: Removed unused ".bus_shift" initialisers from pci-xgene.c

 drivers/pci/controller/dwc/pcie-al.c        | 12 ++------
 drivers/pci/controller/dwc/pcie-hisi.c      |  2 --
 drivers/pci/controller/pci-aardvark.c       | 13 ++-------
 drivers/pci/controller/pci-host-generic.c   |  1 -
 drivers/pci/controller/pci-thunder-ecam.c   |  1 -
 drivers/pci/controller/pci-thunder-pem.c    | 13 +++++++--
 drivers/pci/controller/pci-xgene.c          |  2 --
 drivers/pci/controller/pcie-brcmstb.c       | 16 ++---------
 drivers/pci/controller/pcie-iproc.c         | 31 ++++++---------------
 drivers/pci/controller/pcie-rockchip-host.c | 27 +++++++++---------
 drivers/pci/controller/pcie-rockchip.h      |  8 +-----
 drivers/pci/controller/pcie-tango.c         |  1 -
 drivers/pci/controller/pcie-xilinx-nwl.c    |  9 ++----
 drivers/pci/controller/pcie-xilinx.c        | 11 ++------
 drivers/pci/controller/vmd.c                | 19 ++++++-------
 drivers/pci/ecam.c                          | 23 ++++++++++-----
 include/linux/pci-ecam.h                    | 27 ++++++++++++++++++
 17 files changed, 96 insertions(+), 120 deletions(-)

-- 
2.29.2


^ permalink raw reply

* [PATCH v6 2/5] PCI: thunder-pem: Add constant for custom ".bus_shit" initialiser
From: Krzysztof Wilczyński @ 2020-11-29 23:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Heiko Stuebner, Shawn Lin, Paul Mackerras, Thomas Petazzoni,
	Jonathan Chocron, Toan Le, Will Deacon, Rob Herring,
	Lorenzo Pieralisi, Michal Simek, linux-rockchip,
	bcm-kernel-feedback-list, Jonathan Derrick, linux-pci, Ray Jui,
	Florian Fainelli, linux-rpi-kernel, Jonathan Cameron,
	linux-arm-kernel, Scott Branden, Zhou Wang, Robert Richter,
	linuxppc-dev, Nicolas Saenz Julienne
In-Reply-To: <20201129230743.3006978-1-kw@linux.com>

Add a custom constant for the ".bus_shit" initialiser to capture
a non-standard platform-specific ECAM bus shift value.

Standard values otherwise defined in the PCI Express Specification
are available in the include/linux/pci-ecam.h.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kw@linux.com>
---
 drivers/pci/controller/pci-thunder-pem.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/pci-thunder-pem.c b/drivers/pci/controller/pci-thunder-pem.c
index 3f847969143e..1a3f70ac61fc 100644
--- a/drivers/pci/controller/pci-thunder-pem.c
+++ b/drivers/pci/controller/pci-thunder-pem.c
@@ -19,6 +19,15 @@
 #define PEM_CFG_WR 0x28
 #define PEM_CFG_RD 0x30
 
+/*
+ * Enhanced Configuration Access Mechanism (ECAM)
+ *
+ * N.B. This is a non-standard platform-specific ECAM bus shift value.  For
+ * standard values defined in the PCI Express Base Specification see
+ * include/linux/pci-ecam.h.
+ */
+#define THUNDER_PCIE_ECAM_BUS_SHIFT	24
+
 struct thunder_pem_pci {
 	u32		ea_entry[3];
 	void __iomem	*pem_reg_base;
@@ -404,7 +413,7 @@ static int thunder_pem_acpi_init(struct pci_config_window *cfg)
 }
 
 const struct pci_ecam_ops thunder_pem_ecam_ops = {
-	.bus_shift	= 24,
+	.bus_shift	= THUNDER_PCIE_ECAM_BUS_SHIFT,
 	.init		= thunder_pem_acpi_init,
 	.pci_ops	= {
 		.map_bus	= pci_ecam_map_bus,
@@ -441,7 +450,7 @@ static int thunder_pem_platform_init(struct pci_config_window *cfg)
 }
 
 static const struct pci_ecam_ops pci_thunder_pem_ops = {
-	.bus_shift	= 24,
+	.bus_shift	= THUNDER_PCIE_ECAM_BUS_SHIFT,
 	.init		= thunder_pem_platform_init,
 	.pci_ops	= {
 		.map_bus	= pci_ecam_map_bus,
-- 
2.29.2


^ permalink raw reply related

* [PATCH v6 3/5] PCI: iproc: Convert to use the new ECAM constants
From: Krzysztof Wilczyński @ 2020-11-29 23:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Heiko Stuebner, Shawn Lin, Paul Mackerras, Thomas Petazzoni,
	Jonathan Chocron, Toan Le, Will Deacon, Rob Herring,
	Lorenzo Pieralisi, Michal Simek, linux-rockchip,
	bcm-kernel-feedback-list, Jonathan Derrick, linux-pci, Ray Jui,
	Florian Fainelli, linux-rpi-kernel, Jonathan Cameron,
	linux-arm-kernel, Scott Branden, Zhou Wang, Robert Richter,
	linuxppc-dev, Nicolas Saenz Julienne
In-Reply-To: <20201129230743.3006978-1-kw@linux.com>

Change interface of the function iproc_pcie_map_ep_cfg_reg() so that use
of PCI_SLOT() and PCI_FUNC() macros and most of the local ECAM-specific
constants can be dropped, and the new PCIE_ECAM_OFFSET() macro can be
used instead.  Use the ALIGN_DOWN() macro to ensure that PCI Express
ECAM offset is always 32 bit aligned.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kw@linux.com>
---
 drivers/pci/controller/pcie-iproc.c | 31 ++++++++---------------------
 1 file changed, 8 insertions(+), 23 deletions(-)

diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index 905e93808243..503662380ff8 100644
--- a/drivers/pci/controller/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
@@ -6,6 +6,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/pci-ecam.h>
 #include <linux/msi.h>
 #include <linux/clk.h>
 #include <linux/module.h>
@@ -39,16 +40,8 @@
 
 #define CFG_IND_ADDR_MASK		0x00001ffc
 
-#define CFG_ADDR_BUS_NUM_SHIFT		20
-#define CFG_ADDR_BUS_NUM_MASK		0x0ff00000
-#define CFG_ADDR_DEV_NUM_SHIFT		15
-#define CFG_ADDR_DEV_NUM_MASK		0x000f8000
-#define CFG_ADDR_FUNC_NUM_SHIFT		12
-#define CFG_ADDR_FUNC_NUM_MASK		0x00007000
-#define CFG_ADDR_REG_NUM_SHIFT		2
 #define CFG_ADDR_REG_NUM_MASK		0x00000ffc
-#define CFG_ADDR_CFG_TYPE_SHIFT		0
-#define CFG_ADDR_CFG_TYPE_MASK		0x00000003
+#define CFG_ADDR_CFG_TYPE_1		1
 
 #define SYS_RC_INTX_MASK		0xf
 
@@ -459,19 +452,15 @@ static inline void iproc_pcie_apb_err_disable(struct pci_bus *bus,
 
 static void __iomem *iproc_pcie_map_ep_cfg_reg(struct iproc_pcie *pcie,
 					       unsigned int busno,
-					       unsigned int slot,
-					       unsigned int fn,
+					       unsigned int devfn,
 					       int where)
 {
 	u16 offset;
 	u32 val;
 
 	/* EP device access */
-	val = (busno << CFG_ADDR_BUS_NUM_SHIFT) |
-		(slot << CFG_ADDR_DEV_NUM_SHIFT) |
-		(fn << CFG_ADDR_FUNC_NUM_SHIFT) |
-		(where & CFG_ADDR_REG_NUM_MASK) |
-		(1 & CFG_ADDR_CFG_TYPE_MASK);
+	val = ALIGN_DOWN(PCIE_ECAM_OFFSET(busno, devfn, where), 4) |
+		CFG_ADDR_CFG_TYPE_1;
 
 	iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_ADDR, val);
 	offset = iproc_pcie_reg_offset(pcie, IPROC_PCIE_CFG_DATA);
@@ -574,8 +563,6 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
 				  int where, int size, u32 *val)
 {
 	struct iproc_pcie *pcie = iproc_data(bus);
-	unsigned int slot = PCI_SLOT(devfn);
-	unsigned int fn = PCI_FUNC(devfn);
 	unsigned int busno = bus->number;
 	void __iomem *cfg_data_p;
 	unsigned int data;
@@ -590,7 +577,7 @@ static int iproc_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
 		return ret;
 	}
 
-	cfg_data_p = iproc_pcie_map_ep_cfg_reg(pcie, busno, slot, fn, where);
+	cfg_data_p = iproc_pcie_map_ep_cfg_reg(pcie, busno, devfn, where);
 
 	if (!cfg_data_p)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -631,13 +618,11 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct iproc_pcie *pcie,
 					    int busno, unsigned int devfn,
 					    int where)
 {
-	unsigned slot = PCI_SLOT(devfn);
-	unsigned fn = PCI_FUNC(devfn);
 	u16 offset;
 
 	/* root complex access */
 	if (busno == 0) {
-		if (slot > 0 || fn > 0)
+		if (PCIE_ECAM_DEVFN(devfn) > 0)
 			return NULL;
 
 		iproc_pcie_write_reg(pcie, IPROC_PCIE_CFG_IND_ADDR,
@@ -649,7 +634,7 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct iproc_pcie *pcie,
 			return (pcie->base + offset);
 	}
 
-	return iproc_pcie_map_ep_cfg_reg(pcie, busno, slot, fn, where);
+	return iproc_pcie_map_ep_cfg_reg(pcie, busno, devfn, where);
 }
 
 static void __iomem *iproc_pcie_bus_map_cfg_bus(struct pci_bus *bus,
-- 
2.29.2


^ permalink raw reply related

* [PATCH v6 4/5] PCI: vmd: Update type of the __iomem pointers
From: Krzysztof Wilczyński @ 2020-11-29 23:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Heiko Stuebner, Shawn Lin, Paul Mackerras, Thomas Petazzoni,
	Jonathan Chocron, Toan Le, Will Deacon, Rob Herring,
	Lorenzo Pieralisi, Michal Simek, linux-rockchip,
	bcm-kernel-feedback-list, Jonathan Derrick, linux-pci, Ray Jui,
	Florian Fainelli, linux-rpi-kernel, Jonathan Cameron,
	linux-arm-kernel, Scott Branden, Zhou Wang, Robert Richter,
	linuxppc-dev, Nicolas Saenz Julienne
In-Reply-To: <20201129230743.3006978-1-kw@linux.com>

Use "void __iomem" instead "char __iomem" pointer type when working with
the accessor functions (with names like readb() or writel(), etc.) to
better match a given accessor function signature where commonly the
address pointing to an I/O memory region would be a "void __iomem"
pointer.

Related:
  https://lwn.net/Articles/102232/

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kw@linux.com>
---
 drivers/pci/controller/vmd.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index 1361a79bd1e7..59fa9a94860f 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -95,7 +95,7 @@ struct vmd_dev {
 	struct pci_dev		*dev;
 
 	spinlock_t		cfg_lock;
-	char __iomem		*cfgbar;
+	void __iomem		*cfgbar;
 
 	int msix_count;
 	struct vmd_irq_list	*irqs;
@@ -326,7 +326,7 @@ static void vmd_remove_irq_domain(struct vmd_dev *vmd)
 	}
 }
 
-static char __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus,
+static void __iomem *vmd_cfg_addr(struct vmd_dev *vmd, struct pci_bus *bus,
 				  unsigned int devfn, int reg, int len)
 {
 	unsigned int busnr_ecam = bus->number - vmd->busn_start;
@@ -346,7 +346,7 @@ static int vmd_pci_read(struct pci_bus *bus, unsigned int devfn, int reg,
 			int len, u32 *value)
 {
 	struct vmd_dev *vmd = vmd_from_bus(bus);
-	char __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len);
+	void __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len);
 	unsigned long flags;
 	int ret = 0;
 
@@ -381,7 +381,7 @@ static int vmd_pci_write(struct pci_bus *bus, unsigned int devfn, int reg,
 			 int len, u32 value)
 {
 	struct vmd_dev *vmd = vmd_from_bus(bus);
-	char __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len);
+	void __iomem *addr = vmd_cfg_addr(vmd, bus, devfn, reg, len);
 	unsigned long flags;
 	int ret = 0;
 
-- 
2.29.2


^ permalink raw reply related

* [PATCH v6 5/5] PCI: xgene: Removed unused ".bus_shift" initialisers from pci-xgene.c
From: Krzysztof Wilczyński @ 2020-11-29 23:07 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Heiko Stuebner, Shawn Lin, Paul Mackerras, Thomas Petazzoni,
	Jonathan Chocron, Toan Le, Will Deacon, Rob Herring,
	Lorenzo Pieralisi, Michal Simek, linux-rockchip,
	bcm-kernel-feedback-list, Jonathan Derrick, linux-pci, Ray Jui,
	Florian Fainelli, linux-rpi-kernel, Jonathan Cameron,
	linux-arm-kernel, Scott Branden, Zhou Wang, Robert Richter,
	linuxppc-dev, Nicolas Saenz Julienne
In-Reply-To: <20201129230743.3006978-1-kw@linux.com>

Removed unused ".bus_shift" initialisers from pci-xgene.c as
xgene_pcie_map_bus() did not use these.

Suggested-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Krzysztof Wilczyński <kw@linux.com>
---
 drivers/pci/controller/pci-xgene.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/pci/controller/pci-xgene.c b/drivers/pci/controller/pci-xgene.c
index 8e0db84f089d..85e7c98265e8 100644
--- a/drivers/pci/controller/pci-xgene.c
+++ b/drivers/pci/controller/pci-xgene.c
@@ -257,7 +257,6 @@ static int xgene_v1_pcie_ecam_init(struct pci_config_window *cfg)
 }
 
 const struct pci_ecam_ops xgene_v1_pcie_ecam_ops = {
-	.bus_shift	= 16,
 	.init		= xgene_v1_pcie_ecam_init,
 	.pci_ops	= {
 		.map_bus	= xgene_pcie_map_bus,
@@ -272,7 +271,6 @@ static int xgene_v2_pcie_ecam_init(struct pci_config_window *cfg)
 }
 
 const struct pci_ecam_ops xgene_v2_pcie_ecam_ops = {
-	.bus_shift	= 16,
 	.init		= xgene_v2_pcie_ecam_init,
 	.pci_ops	= {
 		.map_bus	= xgene_pcie_map_bus,
-- 
2.29.2


^ permalink raw reply related

* [net-next PATCH] net: freescale: ucc_geth: remove unused SKB_ALLOC_TIMEOUT
From: Chris Packham @ 2020-11-30  0:10 UTC (permalink / raw)
  To: leoyang.li, davem, kuba
  Cc: trivial, netdev, Chris Packham, linuxppc-dev, linux-kernel

This was added in commit ce973b141dfa ("[PATCH] Freescale QE UCC gigabit
ethernet driver") but doesn't appear to have been used. Remove it now.

Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
---
 drivers/net/ethernet/freescale/ucc_geth.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h
index 3fe903972195..1a9bdf66a7d8 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.h
+++ b/drivers/net/ethernet/freescale/ucc_geth.h
@@ -882,7 +882,6 @@ struct ucc_geth_hardware_statistics {
 							   addresses */
 
 #define TX_TIMEOUT                              (1*HZ)
-#define SKB_ALLOC_TIMEOUT                       100000
 #define PHY_INIT_TIMEOUT                        100000
 #define PHY_CHANGE_TIME                         2
 
-- 
2.29.2


^ permalink raw reply related

* [PATCH] powerpc/64: Fix an EMIT_BUG_ENTRY in head_64.S
From: Jordan Niethe @ 2020-11-30  0:44 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Jordan Niethe

Commit 63ce271b5e37 ("powerpc/prom: convert PROM_BUG() to standard
trap") added an EMIT_BUG_ENTRY for the trap after the branch to
start_kernel(). The EMIT_BUG_ENTRY was for the address "0b", however the
trap was not labeled with "0". Hence the address used for bug is in
relative_toc() where the previous "0" label is. Label the trap as "0" so
the correct address is used.

Fixes: 63ce271b5e37 ("powerpc/prom: convert PROM_BUG() to standard trap")
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
---
 arch/powerpc/kernel/head_64.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 3bae6286c17c..f63d01c78398 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -995,7 +995,7 @@ start_here_common:
 	bl	start_kernel
 
 	/* Not reached */
-	trap
+0:	trap
 	EMIT_BUG_ENTRY 0b, __FILE__, __LINE__, 0
 	.previous
 
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH] powerpc: fix the allyesconfig build
From: Yunsheng Lin @ 2020-11-30  0:58 UTC (permalink / raw)
  To: Jakub Kicinski, Stephen Rothwell
  Cc: Salil Mehta, Geert Uytterhoeven, Stephen Boyd, Michael Turquette,
	linux-kernel, Nicholas Piggin, linux-clk, linux-renesas-soc,
	Huazhong Tan, Yisen Zhuang, Joel Stanley, netdev, PowerPC,
	David S. Miller, Daniel Axtens
In-Reply-To: <20201128113654.4f2dcabe@kicinski-fedora-pc1c0hjn.DHCP.thefacebook.com>

On 2020/11/29 3:36, Jakub Kicinski wrote:
> On Sat, 28 Nov 2020 16:20:54 +1100 Stephen Rothwell wrote:
>> On Fri, 27 Nov 2020 17:56:42 -0800 Jakub Kicinski <kuba@kernel.org> wrote:
>>>
>>> What's the offending structure in hisilicon? I'd rather have a look
>>> packing structs with pointers in 'em sounds questionable.
>>>
>>> I only see these two:
>>>
>>> $ git grep packed drivers/net/ethernet/hisilicon/
>>> drivers/net/ethernet/hisilicon/hns/hnae.h:struct __packed hnae_desc {
>>> drivers/net/ethernet/hisilicon/hns3/hns3_enet.h:struct __packed hns3_desc {  
>>
>> struct hclge_dbg_reg_type_info which is 28 bytes long due to the
>> included struct struct hclge_dbg_reg_common_msg (which is 12 bytes
>> long).  They are surrounded by #pragma pack(1)/pack().
>>
>> This forces the 2 pointers in each second array element of
>> hclge_dbg_reg_info[] to be 4 byte aligned (where pointers are 8 bytes
>> long on PPC64).
> 
> Ah! Thanks, I don't see a reason for these to be packed. 
> Looks  like an accident, there is no reason to pack anything 
> past struct hclge_dbg_reg_common_msg AFAICT.
> 
> Huawei folks, would you mind sending a fix if the analysis is correct?

Yes, will send a patch to fix that. Thanks for the analysis.

> .
> 

^ permalink raw reply

* Re: [PATCH] powerpc: Allow relative pointers in bug table entries
From: Jordan Niethe @ 2020-11-30  0:59 UTC (permalink / raw)
  To: Christophe Leroy; +Cc: linuxppc-dev
In-Reply-To: <5c997bc4-c859-0db6-f167-37ca37819059@csgroup.eu>

On Sun, Nov 29, 2020 at 6:00 AM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 27/11/2020 à 04:02, Jordan Niethe a écrit :
> > This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit
> > offsets are stored in the bug entries rather than 64-bit pointers.
> >
> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> > ---
> >   arch/powerpc/Kconfig           |  4 ++++
> >   arch/powerpc/include/asm/bug.h | 37 ++++++++++++++++++++++++++++++++--
> >   arch/powerpc/xmon/xmon.c       | 17 ++++++++++++++--
> >   3 files changed, 54 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> > index e9f13fe08492..294108e0e5c6 100644
> > --- a/arch/powerpc/Kconfig
> > +++ b/arch/powerpc/Kconfig
> > @@ -311,6 +311,10 @@ config GENERIC_BUG
> >       default y
> >       depends on BUG
> >
> > +config GENERIC_BUG_RELATIVE_POINTERS
> > +     def_bool y
> > +     depends on GENERIC_BUG
> > +
> >   config SYS_SUPPORTS_APM_EMULATION
> >       default y if PMAC_APM_EMU
> >       bool
> > diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
> > index 338f36cd9934..d03d834042a1 100644
> > --- a/arch/powerpc/include/asm/bug.h
> > +++ b/arch/powerpc/include/asm/bug.h
> > @@ -12,7 +12,11 @@
> >   #ifdef CONFIG_DEBUG_BUGVERBOSE
> >   .macro EMIT_BUG_ENTRY addr,file,line,flags
> >        .section __bug_table,"aw"
> > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>
> As far as I understand, as soon as CONFIG_BUG is selected, GENERIC_BUG is automatically selected so
> GENERIC_BUG_RELATIVE_POINTERS is selected as well. Therefore this #ifndef is never possible.
Thanks, you are right. I'll fix that up.
>
> >   5001:        PPC_LONG \addr, 5002f
> > +#else
> > +5001:         .4byte \addr - 5001b, 5002f - 5001b
> > +#endif /* CONFIG_GENERIC_BUG_RELATIVE_POINTERS */
> >        .short \line, \flags
> >        .org 5001b+BUG_ENTRY_SIZE
> >        .previous
> > @@ -23,7 +27,11 @@
> >   #else
> >   .macro EMIT_BUG_ENTRY addr,file,line,flags
> >        .section __bug_table,"aw"
> > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>
> Same
>
> >   5001:        PPC_LONG \addr
> > +#else
> > +5001:         .4byte \addr - 5001b
> > +#endif /* CONFIG_GENERIC_BUG_RELATIVE_POINTERS */
> >        .short \flags
> >        .org 5001b+BUG_ENTRY_SIZE
> >        .previous
> > @@ -34,20 +42,45 @@
> >   /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
> >      sizeof(struct bug_entry), respectively */
> >   #ifdef CONFIG_DEBUG_BUGVERBOSE
> > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>
> Same
>
> >   #define _EMIT_BUG_ENTRY                             \
> >       ".section __bug_table,\"aw\"\n"         \
> >       "2:\t" PPC_LONG "1b, %0\n"              \
> >       "\t.short %1, %2\n"                     \
> >       ".org 2b+%3\n"                          \
> >       ".previous\n"
> > -#else
> > +
> > +#else /* relative pointers */
> > +
> > +#define _EMIT_BUG_ENTRY                              \
> > +     ".section __bug_table,\"aw\"\n"         \
> > +     "2:\t.4byte 1b - 2b, %0 - 2b\n"         \
> > +     "\t.short %1, %2\n"                     \
> > +     ".org 2b+%3\n"                          \
> > +     ".previous\n"
> > +#endif /* relative pointers */
> > +
> > +#else /* verbose */
> > +
> > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>
> Same
>
> >   #define _EMIT_BUG_ENTRY                             \
> >       ".section __bug_table,\"aw\"\n"         \
> >       "2:\t" PPC_LONG "1b\n"                  \
> >       "\t.short %2\n"                         \
> >       ".org 2b+%3\n"                          \
> >       ".previous\n"
> > -#endif
> > +
> > +#else /* relative pointers */
> > +
> > +#define _EMIT_BUG_ENTRY                              \
> > +     ".section __bug_table,\"aw\"\n"         \
> > +     "2:\t.4byte 1b - 2b\n"          \
> > +     "\t.short %2\n"                         \
> > +     ".org 2b+%3\n"                          \
> > +     ".previous\n"
> > +
> > +#endif /* relative pointers */
> > +#endif /* verbose */
> >
> >   #define BUG_ENTRY(insn, flags, ...)                 \
> >       __asm__ __volatile__(                           \
> > diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> > index 55c43a6c9111..5f7cf7e95767 100644
> > --- a/arch/powerpc/xmon/xmon.c
> > +++ b/arch/powerpc/xmon/xmon.c
> > @@ -1731,6 +1731,9 @@ static void print_bug_trap(struct pt_regs *regs)
> >   #ifdef CONFIG_BUG
> >       const struct bug_entry *bug;
> >       unsigned long addr;
> > +#ifdef CONFIG_DEBUG_BUGVERBOSE
> > +     char *file;
> > +#endif
> >
> >       if (regs->msr & MSR_PR)
> >               return;         /* not in kernel */
> > @@ -1744,10 +1747,20 @@ static void print_bug_trap(struct pt_regs *regs)
> >               return;
> >
> >   #ifdef CONFIG_DEBUG_BUGVERBOSE
> > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>
> Same
>
> > +     file = bug->file;
> > +#else /* relative pointers */
> > +     file = (char *)bug + bug->file_disp;
> > +#endif /* relative pointers */
> >       printf("kernel BUG at %s:%u!\n",
> > -            bug->file, bug->line);
> > +            file, bug->line);
> >   #else
> > -     printf("kernel BUG at %px!\n", (void *)bug->bug_addr);
> > +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>
> Same
>
> > +     addr = bug->addr;
> > +#else /* relative pointers */
> > +     addr = (unsigned long)bug + bug->bug_addr_disp;
> > +#endif /* relative pointers */
> > +     printf("kernel BUG at %px!\n", (void *)addr);
> >   #endif
> >   #endif /* CONFIG_BUG */
> >   }
> >
>
> Christophe

^ permalink raw reply

* [Bug 209869] Kernel 5.10-rc1 fails to boot on a PowerMac G4 3,6 at an early stage
From: bugzilla-daemon @ 2020-11-30  1:36 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-209869-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=209869

Michael Ellerman (michael@ellerman.id.au) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |CLOSED

--- Comment #15 from Michael Ellerman (michael@ellerman.id.au) ---
And the fix is in mainline as of v5.10-rc6.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* Re: [PATCH] powerpc: Allow relative pointers in bug table entries
From: Michael Ellerman @ 2020-11-30  1:42 UTC (permalink / raw)
  To: Christophe Leroy, Jordan Niethe, linuxppc-dev
In-Reply-To: <5c997bc4-c859-0db6-f167-37ca37819059@csgroup.eu>

Christophe Leroy <christophe.leroy@csgroup.eu> writes:
> Le 27/11/2020 à 04:02, Jordan Niethe a écrit :
>> This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit
>> offsets are stored in the bug entries rather than 64-bit pointers.
>> 
>> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
>> ---
>>   arch/powerpc/Kconfig           |  4 ++++
>>   arch/powerpc/include/asm/bug.h | 37 ++++++++++++++++++++++++++++++++--
>>   arch/powerpc/xmon/xmon.c       | 17 ++++++++++++++--
>>   3 files changed, 54 insertions(+), 4 deletions(-)
>> 
>> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
>> index e9f13fe08492..294108e0e5c6 100644
>> --- a/arch/powerpc/Kconfig
>> +++ b/arch/powerpc/Kconfig
>> @@ -311,6 +311,10 @@ config GENERIC_BUG
>>   	default y
>>   	depends on BUG
>>   
>> +config GENERIC_BUG_RELATIVE_POINTERS
>> +	def_bool y
>> +	depends on GENERIC_BUG
>> +
>>   config SYS_SUPPORTS_APM_EMULATION
>>   	default y if PMAC_APM_EMU
>>   	bool
>> diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
>> index 338f36cd9934..d03d834042a1 100644
>> --- a/arch/powerpc/include/asm/bug.h
>> +++ b/arch/powerpc/include/asm/bug.h
>> @@ -12,7 +12,11 @@
>>   #ifdef CONFIG_DEBUG_BUGVERBOSE
>>   .macro EMIT_BUG_ENTRY addr,file,line,flags
>>   	 .section __bug_table,"aw"
>> +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>
> As far as I understand, as soon as CONFIG_BUG is selected, GENERIC_BUG is automatically selected so 
> GENERIC_BUG_RELATIVE_POINTERS is selected as well. Therefore this #ifndef is never possible.

Yeah.

There is one place in the generic code that has an ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
but that's because it has to support arches that don't select it.

In the arch code we know that it's enabled, so there should be no need
for any ifdefs.

cheers

^ permalink raw reply

* [Bug 204789] Boot failure with more than 256G of memory on Power9 with 4K pages & Hash MMU
From: bugzilla-daemon @ 2020-11-30  1:49 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-204789-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=204789

--- Comment #14 from Michael Ellerman (michael@ellerman.id.au) ---
The fix is:
  7746406baa3b ("powerpc/book3s64/hash/4k: Support large linear mapping range
with 4K")

-- 
You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* Re: [PATCH] powerpc: Allow relative pointers in bug table entries
From: Jordan Niethe @ 2020-11-30  1:50 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev
In-Reply-To: <874kl7y609.fsf@mpe.ellerman.id.au>

On Mon, Nov 30, 2020 at 12:42 PM Michael Ellerman <mpe@ellerman.id.au> wrote:
>
> Christophe Leroy <christophe.leroy@csgroup.eu> writes:
> > Le 27/11/2020 à 04:02, Jordan Niethe a écrit :
> >> This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit
> >> offsets are stored in the bug entries rather than 64-bit pointers.
> >>
> >> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
> >> ---
> >>   arch/powerpc/Kconfig           |  4 ++++
> >>   arch/powerpc/include/asm/bug.h | 37 ++++++++++++++++++++++++++++++++--
> >>   arch/powerpc/xmon/xmon.c       | 17 ++++++++++++++--
> >>   3 files changed, 54 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
> >> index e9f13fe08492..294108e0e5c6 100644
> >> --- a/arch/powerpc/Kconfig
> >> +++ b/arch/powerpc/Kconfig
> >> @@ -311,6 +311,10 @@ config GENERIC_BUG
> >>      default y
> >>      depends on BUG
> >>
> >> +config GENERIC_BUG_RELATIVE_POINTERS
> >> +    def_bool y
> >> +    depends on GENERIC_BUG
> >> +
> >>   config SYS_SUPPORTS_APM_EMULATION
> >>      default y if PMAC_APM_EMU
> >>      bool
> >> diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
> >> index 338f36cd9934..d03d834042a1 100644
> >> --- a/arch/powerpc/include/asm/bug.h
> >> +++ b/arch/powerpc/include/asm/bug.h
> >> @@ -12,7 +12,11 @@
> >>   #ifdef CONFIG_DEBUG_BUGVERBOSE
> >>   .macro EMIT_BUG_ENTRY addr,file,line,flags
> >>       .section __bug_table,"aw"
> >> +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
> >
> > As far as I understand, as soon as CONFIG_BUG is selected, GENERIC_BUG is automatically selected so
> > GENERIC_BUG_RELATIVE_POINTERS is selected as well. Therefore this #ifndef is never possible.
>
> Yeah.
>
> There is one place in the generic code that has an ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
> but that's because it has to support arches that don't select it.
>
> In the arch code we know that it's enabled, so there should be no need
> for any ifdefs.
For 32bit, pointers are 4 bytes anyway so it would be pointless to
store a displacement, so won't we need some ifdefs for that?
>
> cheers

^ permalink raw reply

* Re: [PATCH 2/3] powerpc/pseries/hotplug-cpu: fix memleak in dlpar_cpu_add_by_count
From: Michael Ellerman @ 2020-11-30  1:51 UTC (permalink / raw)
  To: Qinglang Miao, Benjamin Herrenschmidt, Paul Mackerras
  Cc: linuxppc-dev, linux-kernel, Qinglang Miao
In-Reply-To: <20201128102001.95323-1-miaoqinglang@huawei.com>

Qinglang Miao <miaoqinglang@huawei.com> writes:
> kfree(cpu_drcs) should be called when it fails to perform
> of_find_node_by_path("/cpus") in dlpar_cpu_add_by_count,
> otherwise there would be a memleak.
>
> In fact, the patch a0ff72f9f5a7 ought to remove kfree in
> find_dlpar_cpus_to_add rather than dlpar_cpu_add_by_count.
> I guess there might be a mistake when apply that one.
>
> Fixes: a0ff72f9f5a7 ("powerpc/pseries/hotplug-cpu: Remove double free in error path")
> Reported-by: Hulk Robot <hulkci@huawei.com>
> Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com>
> ---
>  arch/powerpc/platforms/pseries/hotplug-cpu.c | 1 +
>  1 file changed, 1 insertion(+)

This is already fixed in my next by:

  a40fdaf1420d ("Revert "powerpc/pseries/hotplug-cpu: Remove double free in error path"")

cheers

> diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
> index f2837e33b..4bb1c9f2b 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
> @@ -743,6 +743,7 @@ static int dlpar_cpu_add_by_count(u32 cpus_to_add)
>  	parent = of_find_node_by_path("/cpus");
>  	if (!parent) {
>  		pr_warn("Could not find CPU root node in device tree\n");
> +		kfree(cpu_drcs);
>  		return -1;
>  	}
>  
> -- 
> 2.23.0

^ permalink raw reply

* Re: [RFC PATCH] KVM: PPC: Book3S HV: Remove support for running HPT guest on RPT host without mixed mode support
From: Michael Ellerman @ 2020-11-30  2:40 UTC (permalink / raw)
  To: Nicholas Piggin, kvm-ppc; +Cc: linuxppc-dev, Nicholas Piggin
In-Reply-To: <20201128095232.837260-1-npiggin@gmail.com>

Nicholas Piggin <npiggin@gmail.com> writes:
> This reverts much of commit c01015091a770 ("KVM: PPC: Book3S HV: Run HPT
> guests on POWER9 radix hosts"), which was required to run HPT guests on
> RPT hosts on early POWER9 CPUs without support for "mixed mode", which
> meant the host could not run with MMU on while guests were running.

Would be worth mentioning which CPU versions. 

Looking at the code it seems like it's P9N < 2.2 and P9C < 1.1.

> This code has some corner case bugs, e.g., when the guest hits a machine
> check or HMI the primary locks up waiting for secondaries to switch LPCR
> to host, which they never do. This could all be fixed in software, but
> most CPUs in production have mixed mode support, and those that don't
> are believed to be all in installations that don't use this capability.
> So simplify things and remove support.

Key detail being, AFAICS, you retain enough code to detect that we're in
that configuration and cleanly return an error, rather than crashing or
anything horrible.

Otherwise looks good to me.

cheers

> diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h
> index 078f4648ea27..b6d31bff5209 100644
> --- a/arch/powerpc/include/asm/kvm_book3s_asm.h
> +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h
> @@ -74,16 +74,6 @@ struct kvm_split_mode {
>  	u8		do_nap;
>  	u8		napped[MAX_SMT_THREADS];
>  	struct kvmppc_vcore *vc[MAX_SUBCORES];
> -	/* Bits for changing lpcr on P9 */
> -	unsigned long	lpcr_req;
> -	unsigned long	lpidr_req;
> -	unsigned long	host_lpcr;
> -	u32		do_set;
> -	u32		do_restore;
> -	union {
> -		u32	allphases;
> -		u8	phase[4];
> -	} lpcr_sync;
>  };
>  
>  /*
> @@ -110,7 +100,6 @@ struct kvmppc_host_state {
>  	u8 hwthread_state;
>  	u8 host_ipi;
>  	u8 ptid;		/* thread number within subcore when split */
> -	u8 tid;			/* thread number within whole core */
>  	u8 fake_suspend;
>  	struct kvm_vcpu *kvm_vcpu;
>  	struct kvmppc_vcore *kvm_vcore;
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index c2722ff36e98..21496ea09bf1 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -690,7 +690,6 @@ int main(void)
>  	HSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr);
>  	HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi);
>  	HSTATE_FIELD(HSTATE_PTID, ptid);
> -	HSTATE_FIELD(HSTATE_TID, tid);
>  	HSTATE_FIELD(HSTATE_FAKE_SUSPEND, fake_suspend);
>  	HSTATE_FIELD(HSTATE_MMCR0, host_mmcr[0]);
>  	HSTATE_FIELD(HSTATE_MMCR1, host_mmcr[1]);
> @@ -720,8 +719,6 @@ int main(void)
>  	OFFSET(KVM_SPLIT_LDBAR, kvm_split_mode, ldbar);
>  	OFFSET(KVM_SPLIT_DO_NAP, kvm_split_mode, do_nap);
>  	OFFSET(KVM_SPLIT_NAPPED, kvm_split_mode, napped);
> -	OFFSET(KVM_SPLIT_DO_SET, kvm_split_mode, do_set);
> -	OFFSET(KVM_SPLIT_DO_RESTORE, kvm_split_mode, do_restore);
>  #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
>  
>  #ifdef CONFIG_PPC_BOOK3S_64
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index c94f9595133d..86b78f8e3dde 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -134,7 +134,7 @@ static inline bool nesting_enabled(struct kvm *kvm)
>  }
>  
>  /* If set, the threads on each CPU core have to be in the same MMU mode */
> -static bool no_mixing_hpt_and_radix;
> +static bool no_mixing_hpt_and_radix __read_mostly;
>  
>  static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
>  
> @@ -2855,11 +2855,6 @@ static bool can_dynamic_split(struct kvmppc_vcore *vc, struct core_info *cip)
>  	if (one_vm_per_core && vc->kvm != cip->vc[0]->kvm)
>  		return false;
>  
> -	/* Some POWER9 chips require all threads to be in the same MMU mode */
> -	if (no_mixing_hpt_and_radix &&
> -	    kvm_is_radix(vc->kvm) != kvm_is_radix(cip->vc[0]->kvm))
> -		return false;
> -
>  	if (n_threads < cip->max_subcore_threads)
>  		n_threads = cip->max_subcore_threads;
>  	if (!subcore_config_ok(cip->n_subcores + 1, n_threads))
> @@ -2898,6 +2893,9 @@ static void prepare_threads(struct kvmppc_vcore *vc)
>  	for_each_runnable_thread(i, vcpu, vc) {
>  		if (signal_pending(vcpu->arch.run_task))
>  			vcpu->arch.ret = -EINTR;
> +		else if (no_mixing_hpt_and_radix &&
> +			 kvm_is_radix(vc->kvm) != radix_enabled())
> +			vcpu->arch.ret = -EINVAL;
>  		else if (vcpu->arch.vpa.update_pending ||
>  			 vcpu->arch.slb_shadow.update_pending ||
>  			 vcpu->arch.dtl.update_pending)
> @@ -3103,7 +3101,6 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>  	int controlled_threads;
>  	int trap;
>  	bool is_power8;
> -	bool hpt_on_radix;
>  
>  	/*
>  	 * Remove from the list any threads that have a signal pending
> @@ -3136,11 +3133,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>  	 * this is a HPT guest on a radix host machine where the
>  	 * CPU threads may not be in different MMU modes.
>  	 */
> -	hpt_on_radix = no_mixing_hpt_and_radix && radix_enabled() &&
> -		!kvm_is_radix(vc->kvm);
> -	if (((controlled_threads > 1) &&
> -	     ((vc->num_threads > threads_per_subcore) || !on_primary_thread())) ||
> -	    (hpt_on_radix && vc->kvm->arch.threads_indep)) {
> +	if ((controlled_threads > 1) &&
> +	    ((vc->num_threads > threads_per_subcore) || !on_primary_thread())) {
>  		for_each_runnable_thread(i, vcpu, vc) {
>  			vcpu->arch.ret = -EBUSY;
>  			kvmppc_remove_runnable(vc, vcpu);
> @@ -3208,7 +3202,7 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>  	is_power8 = cpu_has_feature(CPU_FTR_ARCH_207S)
>  		&& !cpu_has_feature(CPU_FTR_ARCH_300);
>  
> -	if (split > 1 || hpt_on_radix) {
> +	if (split > 1) {
>  		sip = &split_info;
>  		memset(&split_info, 0, sizeof(split_info));
>  		for (sub = 0; sub < core_info.n_subcores; ++sub)
> @@ -3230,13 +3224,6 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>  			split_info.subcore_size = subcore_size;
>  		} else {
>  			split_info.subcore_size = 1;
> -			if (hpt_on_radix) {
> -				/* Use the split_info for LPCR/LPIDR changes */
> -				split_info.lpcr_req = vc->lpcr;
> -				split_info.lpidr_req = vc->kvm->arch.lpid;
> -				split_info.host_lpcr = vc->kvm->arch.host_lpcr;
> -				split_info.do_set = 1;
> -			}
>  		}
>  
>  		/* order writes to split_info before kvm_split_mode pointer */
> @@ -3246,7 +3233,6 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>  	for (thr = 0; thr < controlled_threads; ++thr) {
>  		struct paca_struct *paca = paca_ptrs[pcpu + thr];
>  
> -		paca->kvm_hstate.tid = thr;
>  		paca->kvm_hstate.napping = 0;
>  		paca->kvm_hstate.kvm_split_mode = sip;
>  	}
> @@ -3320,10 +3306,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>  	 * When doing micro-threading, poke the inactive threads as well.
>  	 * This gets them to the nap instruction after kvm_do_nap,
>  	 * which reduces the time taken to unsplit later.
> -	 * For POWER9 HPT guest on radix host, we need all the secondary
> -	 * threads woken up so they can do the LPCR/LPIDR change.
>  	 */
> -	if (cmd_bit || hpt_on_radix) {
> +	if (cmd_bit) {
>  		split_info.do_nap = 1;	/* ask secondaries to nap when done */
>  		for (thr = 1; thr < threads_per_subcore; ++thr)
>  			if (!(active & (1 << thr)))
> @@ -3384,19 +3368,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
>  			cpu_relax();
>  			++loops;
>  		}
> -	} else if (hpt_on_radix) {
> -		/* Wait for all threads to have seen final sync */
> -		for (thr = 1; thr < controlled_threads; ++thr) {
> -			struct paca_struct *paca = paca_ptrs[pcpu + thr];
> -
> -			while (paca->kvm_hstate.kvm_split_mode) {
> -				HMT_low();
> -				barrier();
> -			}
> -			HMT_medium();
> -		}
> +		split_info.do_nap = 0;
>  	}
> -	split_info.do_nap = 0;
>  
>  	kvmppc_set_host_core(pcpu);
>  
> @@ -4166,7 +4139,6 @@ int kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, u64 time_limit,
>  
>  	kvmppc_clear_host_core(pcpu);
>  
> -	local_paca->kvm_hstate.tid = 0;
>  	local_paca->kvm_hstate.napping = 0;
>  	local_paca->kvm_hstate.kvm_split_mode = NULL;
>  	kvmppc_start_thread(vcpu, vc);
> @@ -4351,15 +4323,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_vcpu *vcpu)
>  
>  	do {
>  		/*
> -		 * The early POWER9 chips that can't mix radix and HPT threads
> -		 * on the same core also need the workaround for the problem
> -		 * where the TLB would prefetch entries in the guest exit path
> -		 * for radix guests using the guest PIDR value and LPID 0.
> -		 * The workaround is in the old path (kvmppc_run_vcpu())
> -		 * but not the new path (kvmhv_run_single_vcpu()).
> +		 * The TLB prefetch bug fixup is only in the kvmppc_run_vcpu
> +		 * path, which also handles hash and dependent threads mode.
>  		 */
>  		if (kvm->arch.threads_indep && kvm_is_radix(kvm) &&
> -		    !no_mixing_hpt_and_radix)
> +		    !cpu_has_feature(CPU_FTR_P9_RADIX_PREFETCH_BUG))
>  			r = kvmhv_run_single_vcpu(vcpu, ~(u64)0,
>  						  vcpu->arch.vcore->lpcr);
>  		else
> diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
> index 8f58dd20b362..f3d3183249fe 100644
> --- a/arch/powerpc/kvm/book3s_hv_builtin.c
> +++ b/arch/powerpc/kvm/book3s_hv_builtin.c
> @@ -277,8 +277,7 @@ void kvmhv_commence_exit(int trap)
>  	struct kvmppc_vcore *vc = local_paca->kvm_hstate.kvm_vcore;
>  	int ptid = local_paca->kvm_hstate.ptid;
>  	struct kvm_split_mode *sip = local_paca->kvm_hstate.kvm_split_mode;
> -	int me, ee, i, t;
> -	int cpu0;
> +	int me, ee, i;
>  
>  	/* Set our bit in the threads-exiting-guest map in the 0xff00
>  	   bits of vcore->entry_exit_map */
> @@ -320,22 +319,6 @@ void kvmhv_commence_exit(int trap)
>  		if ((ee >> 8) == 0)
>  			kvmhv_interrupt_vcore(vc, ee);
>  	}
> -
> -	/*
> -	 * On POWER9 when running a HPT guest on a radix host (sip != NULL),
> -	 * we have to interrupt inactive CPU threads to get them to
> -	 * restore the host LPCR value.
> -	 */
> -	if (sip->lpcr_req) {
> -		if (cmpxchg(&sip->do_restore, 0, 1) == 0) {
> -			vc = local_paca->kvm_hstate.kvm_vcore;
> -			cpu0 = vc->pcpu + ptid - local_paca->kvm_hstate.tid;
> -			for (t = 1; t < threads_per_core; ++t) {
> -				if (sip->napped[t])
> -					kvmhv_rm_send_ipi(cpu0 + t);
> -			}
> -		}
> -	}
>  }
>  
>  struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv;
> @@ -667,86 +650,6 @@ void kvmppc_bad_interrupt(struct pt_regs *regs)
>  	panic("Bad KVM trap");
>  }
>  
> -/*
> - * Functions used to switch LPCR HR and UPRT bits on all threads
> - * when entering and exiting HPT guests on a radix host.
> - */
> -
> -#define PHASE_REALMODE		1	/* in real mode */
> -#define PHASE_SET_LPCR		2	/* have set LPCR */
> -#define PHASE_OUT_OF_GUEST	4	/* have finished executing in guest */
> -#define PHASE_RESET_LPCR	8	/* have reset LPCR to host value */
> -
> -#define ALL(p)		(((p) << 24) | ((p) << 16) | ((p) << 8) | (p))
> -
> -static void wait_for_sync(struct kvm_split_mode *sip, int phase)
> -{
> -	int thr = local_paca->kvm_hstate.tid;
> -
> -	sip->lpcr_sync.phase[thr] |= phase;
> -	phase = ALL(phase);
> -	while ((sip->lpcr_sync.allphases & phase) != phase) {
> -		HMT_low();
> -		barrier();
> -	}
> -	HMT_medium();
> -}
> -
> -void kvmhv_p9_set_lpcr(struct kvm_split_mode *sip)
> -{
> -	unsigned long rb, set;
> -
> -	/* wait for every other thread to get to real mode */
> -	wait_for_sync(sip, PHASE_REALMODE);
> -
> -	/* Set LPCR and LPIDR */
> -	mtspr(SPRN_LPCR, sip->lpcr_req);
> -	mtspr(SPRN_LPID, sip->lpidr_req);
> -	isync();
> -
> -	/* Invalidate the TLB on thread 0 */
> -	if (local_paca->kvm_hstate.tid == 0) {
> -		sip->do_set = 0;
> -		asm volatile("ptesync" : : : "memory");
> -		for (set = 0; set < POWER9_TLB_SETS_RADIX; ++set) {
> -			rb = TLBIEL_INVAL_SET_LPID +
> -				(set << TLBIEL_INVAL_SET_SHIFT);
> -			asm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : :
> -				     "r" (rb), "r" (0));
> -		}
> -		asm volatile("ptesync" : : : "memory");
> -	}
> -
> -	/* indicate that we have done so and wait for others */
> -	wait_for_sync(sip, PHASE_SET_LPCR);
> -	/* order read of sip->lpcr_sync.allphases vs. sip->do_set */
> -	smp_rmb();
> -}
> -
> -/*
> - * Called when a thread that has been in the guest needs
> - * to reload the host LPCR value - but only on POWER9 when
> - * running a HPT guest on a radix host.
> - */
> -void kvmhv_p9_restore_lpcr(struct kvm_split_mode *sip)
> -{
> -	/* we're out of the guest... */
> -	wait_for_sync(sip, PHASE_OUT_OF_GUEST);
> -
> -	mtspr(SPRN_LPID, 0);
> -	mtspr(SPRN_LPCR, sip->host_lpcr);
> -	isync();
> -
> -	if (local_paca->kvm_hstate.tid == 0) {
> -		sip->do_restore = 0;
> -		smp_wmb();	/* order store of do_restore vs. phase */
> -	}
> -
> -	wait_for_sync(sip, PHASE_RESET_LPCR);
> -	smp_mb();
> -	local_paca->kvm_hstate.kvm_split_mode = NULL;
> -}
> -
>  static void kvmppc_end_cede(struct kvm_vcpu *vcpu)
>  {
>  	vcpu->arch.ceded = 0;
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index cd9995ee8441..d5a9b57ec129 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -85,19 +85,6 @@ _GLOBAL_TOC(kvmppc_hv_entry_trampoline)
>  	RFI_TO_KERNEL
>  
>  kvmppc_call_hv_entry:
> -BEGIN_FTR_SECTION
> -	/* On P9, do LPCR setting, if necessary */
> -	ld	r3, HSTATE_SPLIT_MODE(r13)
> -	cmpdi	r3, 0
> -	beq	46f
> -	lwz	r4, KVM_SPLIT_DO_SET(r3)
> -	cmpwi	r4, 0
> -	beq	46f
> -	bl	kvmhv_p9_set_lpcr
> -	nop
> -46:
> -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
> -
>  	ld	r4, HSTATE_KVM_VCPU(r13)
>  	bl	kvmppc_hv_entry
>  
> @@ -361,11 +348,11 @@ kvm_secondary_got_guest:
>  	LOAD_REG_ADDR(r6, decrementer_max)
>  	ld	r6, 0(r6)
>  	mtspr	SPRN_HDEC, r6
> +BEGIN_FTR_SECTION
>  	/* and set per-LPAR registers, if doing dynamic micro-threading */
>  	ld	r6, HSTATE_SPLIT_MODE(r13)
>  	cmpdi	r6, 0
>  	beq	63f
> -BEGIN_FTR_SECTION
>  	ld	r0, KVM_SPLIT_RPR(r6)
>  	mtspr	SPRN_RPR, r0
>  	ld	r0, KVM_SPLIT_PMMAR(r6)
> @@ -373,16 +360,7 @@ BEGIN_FTR_SECTION
>  	ld	r0, KVM_SPLIT_LDBAR(r6)
>  	mtspr	SPRN_LDBAR, r0
>  	isync
> -FTR_SECTION_ELSE
> -	/* On P9 we use the split_info for coordinating LPCR changes */
> -	lwz	r4, KVM_SPLIT_DO_SET(r6)
> -	cmpwi	r4, 0
> -	beq	1f
> -	mr	r3, r6
> -	bl	kvmhv_p9_set_lpcr
> -	nop
> -1:
> -ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
> +END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
>  63:
>  	/* Order load of vcpu after load of vcore */
>  	lwsync
> @@ -452,19 +430,15 @@ kvm_no_guest:
>  	mtcr	r5
>  	blr
>  
> -53:	HMT_LOW
> +53:
> +BEGIN_FTR_SECTION
> +	HMT_LOW
>  	ld	r5, HSTATE_KVM_VCORE(r13)
>  	cmpdi	r5, 0
>  	bne	60f
>  	ld	r3, HSTATE_SPLIT_MODE(r13)
>  	cmpdi	r3, 0
>  	beq	kvm_no_guest
> -	lwz	r0, KVM_SPLIT_DO_SET(r3)
> -	cmpwi	r0, 0
> -	bne	kvmhv_do_set
> -	lwz	r0, KVM_SPLIT_DO_RESTORE(r3)
> -	cmpwi	r0, 0
> -	bne	kvmhv_do_restore
>  	lbz	r0, KVM_SPLIT_DO_NAP(r3)
>  	cmpwi	r0, 0
>  	beq	kvm_no_guest
> @@ -472,24 +446,19 @@ kvm_no_guest:
>  	b	kvm_unsplit_nap
>  60:	HMT_MEDIUM
>  	b	kvm_secondary_got_guest
> +FTR_SECTION_ELSE
> +	HMT_LOW
> +	ld	r5, HSTATE_KVM_VCORE(r13)
> +	cmpdi	r5, 0
> +	beq	kvm_no_guest
> +	HMT_MEDIUM
> +	b	kvm_secondary_got_guest
> +ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
>  
>  54:	li	r0, KVM_HWTHREAD_IN_KVM
>  	stb	r0, HSTATE_HWTHREAD_STATE(r13)
>  	b	kvm_no_guest
>  
> -kvmhv_do_set:
> -	/* Set LPCR, LPIDR etc. on P9 */
> -	HMT_MEDIUM
> -	bl	kvmhv_p9_set_lpcr
> -	nop
> -	b	kvm_no_guest
> -
> -kvmhv_do_restore:
> -	HMT_MEDIUM
> -	bl	kvmhv_p9_restore_lpcr
> -	nop
> -	b	kvm_no_guest
> -
>  /*
>   * Here the primary thread is trying to return the core to
>   * whole-core mode, so we need to nap.
> @@ -527,7 +496,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
>  	/* Set kvm_split_mode.napped[tid] = 1 */
>  	ld	r3, HSTATE_SPLIT_MODE(r13)
>  	li	r0, 1
> -	lbz	r4, HSTATE_TID(r13)
> +	lhz	r4, PACAPACAINDEX(r13)
> +	clrldi	r4, r4, 61	/* micro-threading => P8 => 8 threads/core */
>  	addi	r4, r4, KVM_SPLIT_NAPPED
>  	stbx	r0, r3, r4
>  	/* Check the do_nap flag again after setting napped[] */
> @@ -1938,24 +1908,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
>  19:	lis	r8,0x7fff		/* MAX_INT@h */
>  	mtspr	SPRN_HDEC,r8
>  
> -16:
> -BEGIN_FTR_SECTION
> -	/* On POWER9 with HPT-on-radix we need to wait for all other threads */
> -	ld	r3, HSTATE_SPLIT_MODE(r13)
> -	cmpdi	r3, 0
> -	beq	47f
> -	lwz	r8, KVM_SPLIT_DO_RESTORE(r3)
> -	cmpwi	r8, 0
> -	beq	47f
> -	bl	kvmhv_p9_restore_lpcr
> -	nop
> -	b	48f
> -47:
> -END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
> -	ld	r8,KVM_HOST_LPCR(r4)
> +16:	ld	r8,KVM_HOST_LPCR(r4)
>  	mtspr	SPRN_LPCR,r8
>  	isync
> -48:
> +
>  #ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
>  	/* Finish timing, if we have a vcpu */
>  	ld	r4, HSTATE_KVM_VCPU(r13)
> @@ -2779,8 +2735,10 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
>  	beq	kvm_end_cede
>  	cmpwi	r0, NAPPING_NOVCPU
>  	beq	kvm_novcpu_wakeup
> +BEGIN_FTR_SECTION
>  	cmpwi	r0, NAPPING_UNSPLIT
>  	beq	kvm_unsplit_wakeup
> +END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
>  	twi	31,0,0 /* Nap state must not be zero */
>  
>  33:	mr	r4, r3
> -- 
> 2.23.0

^ permalink raw reply

* [PATCH] powerpc/xmon: Fix build failure for 8xx
From: Ravi Bangoria @ 2020-11-30  3:44 UTC (permalink / raw)
  To: mpe; +Cc: christophe.leroy, ravi.bangoria, mikey, linuxppc-dev

With CONFIG_PPC_8xx and CONFIG_XMON set, kernel build fails with

  arch/powerpc/xmon/xmon.c:1379:12: error: 'find_free_data_bpt' defined
  but not used [-Werror=unused-function]

Fix it by enclosing find_free_data_bpt() inside #ifndef CONFIG_PPC_8xx.

Reported-by: kernel test robot <lkp@intel.com>
Fixes: 30df74d67d48 ("powerpc/watchpoint/xmon: Support 2nd DAWR")
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com>
---
 arch/powerpc/xmon/xmon.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 55c43a6c9111..5559edf36756 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -1383,6 +1383,7 @@ static long check_bp_loc(unsigned long addr)
 	return 1;
 }
 
+#ifndef CONFIG_PPC_8xx
 static int find_free_data_bpt(void)
 {
 	int i;
@@ -1394,6 +1395,7 @@ static int find_free_data_bpt(void)
 	printf("Couldn't find free breakpoint register\n");
 	return -1;
 }
+#endif
 
 static void print_data_bpts(void)
 {
-- 
2.17.1


^ permalink raw reply related

* Re: [PATCH 1/8] powerpc/64s/powernv: Fix memory corruption when saving SLB entries on MCE
From: Mahesh J Salgaonkar @ 2020-11-30  3:55 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linuxppc-dev, kvm-ppc
In-Reply-To: <20201128070728.825934-2-npiggin@gmail.com>

On 2020-11-28 17:07:21 Sat, Nicholas Piggin wrote:
> This can be hit by an HPT guest running on an HPT host and bring down
> the host, so it's quite important to fix.
> 
> Fixes: 7290f3b3d3e66 ("powerpc/64s/powernv: machine check dump SLB contents")
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>  arch/powerpc/platforms/powernv/setup.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
> index 46115231a3b2..4426a109ec2f 100644
> --- a/arch/powerpc/platforms/powernv/setup.c
> +++ b/arch/powerpc/platforms/powernv/setup.c
> @@ -211,11 +211,16 @@ static void __init pnv_init(void)
>  		add_preferred_console("hvc", 0, NULL);
>  
>  	if (!radix_enabled()) {
> +		size_t size = sizeof(struct slb_entry) * mmu_slb_size;

Acked-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>

Thanks,
-Mahesh.


>  		int i;
>  
>  		/* Allocate per cpu area to save old slb contents during MCE */
> -		for_each_possible_cpu(i)
> -			paca_ptrs[i]->mce_faulty_slbs = memblock_alloc_node(mmu_slb_size, __alignof__(*paca_ptrs[i]->mce_faulty_slbs), cpu_to_node(i));
> +		for_each_possible_cpu(i) {
> +			paca_ptrs[i]->mce_faulty_slbs =
> +					memblock_alloc_node(size,
> +						__alignof__(struct slb_entry),
> +						cpu_to_node(i));
> +		}
>  	}
>  }
>  
> -- 
> 2.23.0
> 

-- 
Mahesh J Salgaonkar

^ permalink raw reply

* [PATCH 2/2] ASoC: bindings: fsl-asoc-card: add compatible string for si476x codec
From: Shengjiu Wang @ 2020-11-30  3:57 UTC (permalink / raw)
  To: timur, nicoleotsuka, Xiubo.Lee, festevam, lgirdwood, broonie,
	perex, tiwai, alsa-devel, linuxppc-dev, linux-kernel, robh+dt,
	devicetree
In-Reply-To: <1606708668-28786-1-git-send-email-shengjiu.wang@nxp.com>

The si476x codec is used for FM radio function on i.MX6
auto board.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
 Documentation/devicetree/bindings/sound/fsl-asoc-card.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
index f339be62e7e4..90d9e9d81624 100644
--- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
+++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt
@@ -40,6 +40,8 @@ The compatible list for this generic sound card currently:
 
  "fsl,imx-audio-tlv320aic32x4"
 
+ "fsl,imx-audio-si476x"
+
 Required properties:
 
   - compatible		: Contains one of entries in the compatible list.
-- 
2.27.0


^ permalink raw reply related

* [PATCH 1/2] ASoC: fsl-asoc-card: Add support for si476x codec
From: Shengjiu Wang @ 2020-11-30  3:57 UTC (permalink / raw)
  To: timur, nicoleotsuka, Xiubo.Lee, festevam, lgirdwood, broonie,
	perex, tiwai, alsa-devel, linuxppc-dev, linux-kernel, robh+dt,
	devicetree

The si476x codec is used for FM radio function on i.MX6
auto board, it only supports recording function.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
 sound/soc/fsl/fsl-asoc-card.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index a2dd3b6b7fec..f62f81ceab0d 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -131,6 +131,13 @@ static const struct snd_soc_dapm_route audio_map_tx[] = {
 	{"CPU-Playback",  NULL, "ASRC-Playback"},
 };
 
+static const struct snd_soc_dapm_route audio_map_rx[] = {
+	/* 1st half -- Normal DAPM routes */
+	{"CPU-Capture",  NULL, "Capture"},
+	/* 2nd half -- ASRC DAPM routes */
+	{"ASRC-Capture",  NULL, "CPU-Capture"},
+};
+
 /* Add all possible widgets into here without being redundant */
 static const struct snd_soc_dapm_widget fsl_asoc_card_dapm_widgets[] = {
 	SND_SOC_DAPM_LINE("Line Out Jack", NULL),
@@ -653,6 +660,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
 		priv->cpu_priv.slot_width = 32;
 		priv->card.dapm_routes = audio_map_tx;
 		priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_tx);
+	} else if (of_device_is_compatible(np, "fsl,imx-audio-si476x")) {
+		codec_dai_name = "si476x-codec";
+		priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS;
+		priv->card.dapm_routes = audio_map_rx;
+		priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx);
 	} else {
 		dev_err(&pdev->dev, "unknown Device Tree compatible\n");
 		ret = -EINVAL;
@@ -869,6 +881,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = {
 	{ .compatible = "fsl,imx-audio-wm8960", },
 	{ .compatible = "fsl,imx-audio-mqs", },
 	{ .compatible = "fsl,imx-audio-wm8524", },
+	{ .compatible = "fsl,imx-audio-si476x", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids);
-- 
2.27.0


^ permalink raw reply related

* Re: [PATCH] powerpc: Allow relative pointers in bug table entries
From: Christophe Leroy @ 2020-11-30  6:27 UTC (permalink / raw)
  To: Jordan Niethe, Michael Ellerman; +Cc: linuxppc-dev
In-Reply-To: <CACzsE9r6GoFANSGw_6SK0R7SZGbU+U0_UvDLH9Pzj_LRBsHJQw@mail.gmail.com>



Le 30/11/2020 à 02:50, Jordan Niethe a écrit :
> On Mon, Nov 30, 2020 at 12:42 PM Michael Ellerman <mpe@ellerman.id.au> wrote:
>>
>> Christophe Leroy <christophe.leroy@csgroup.eu> writes:
>>> Le 27/11/2020 à 04:02, Jordan Niethe a écrit :
>>>> This enables GENERIC_BUG_RELATIVE_POINTERS on Power so that 32-bit
>>>> offsets are stored in the bug entries rather than 64-bit pointers.
>>>>
>>>> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
>>>> ---
>>>>    arch/powerpc/Kconfig           |  4 ++++
>>>>    arch/powerpc/include/asm/bug.h | 37 ++++++++++++++++++++++++++++++++--
>>>>    arch/powerpc/xmon/xmon.c       | 17 ++++++++++++++--
>>>>    3 files changed, 54 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
>>>> index e9f13fe08492..294108e0e5c6 100644
>>>> --- a/arch/powerpc/Kconfig
>>>> +++ b/arch/powerpc/Kconfig
>>>> @@ -311,6 +311,10 @@ config GENERIC_BUG
>>>>       default y
>>>>       depends on BUG
>>>>
>>>> +config GENERIC_BUG_RELATIVE_POINTERS
>>>> +    def_bool y
>>>> +    depends on GENERIC_BUG
>>>> +
>>>>    config SYS_SUPPORTS_APM_EMULATION
>>>>       default y if PMAC_APM_EMU
>>>>       bool
>>>> diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
>>>> index 338f36cd9934..d03d834042a1 100644
>>>> --- a/arch/powerpc/include/asm/bug.h
>>>> +++ b/arch/powerpc/include/asm/bug.h
>>>> @@ -12,7 +12,11 @@
>>>>    #ifdef CONFIG_DEBUG_BUGVERBOSE
>>>>    .macro EMIT_BUG_ENTRY addr,file,line,flags
>>>>        .section __bug_table,"aw"
>>>> +#ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>>>
>>> As far as I understand, as soon as CONFIG_BUG is selected, GENERIC_BUG is automatically selected so
>>> GENERIC_BUG_RELATIVE_POINTERS is selected as well. Therefore this #ifndef is never possible.
>>
>> Yeah.
>>
>> There is one place in the generic code that has an ifndef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
>> but that's because it has to support arches that don't select it.
>>
>> In the arch code we know that it's enabled, so there should be no need
>> for any ifdefs.
> For 32bit, pointers are 4 bytes anyway so it would be pointless to
> store a displacement, so won't we need some ifdefs for that?

I'd say it the other way round:

For 32bit, pointers are 4 bytes anyway so it would be pointless to
make it different from 64bit.

We are definitely not on a performance critical path when dealing with bug entries, so I think it is 
better to keep a common code for PPC32 and PPC64.

Christophe

^ permalink raw reply

* Re: [PATCH 2/3] powerpc/pseries/hotplug-cpu: fix memleak in dlpar_cpu_add_by_count
From: Qinglang Miao @ 2020-11-30  7:28 UTC (permalink / raw)
  To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <871rgby5lb.fsf@mpe.ellerman.id.au>



在 2020/11/30 9:51, Michael Ellerman 写道:
> Qinglang Miao <miaoqinglang@huawei.com> writes:
>> kfree(cpu_drcs) should be called when it fails to perform
>> of_find_node_by_path("/cpus") in dlpar_cpu_add_by_count,
>> otherwise there would be a memleak.
>>
>> In fact, the patch a0ff72f9f5a7 ought to remove kfree in
>> find_dlpar_cpus_to_add rather than dlpar_cpu_add_by_count.
>> I guess there might be a mistake when apply that one.
>>
>> Fixes: a0ff72f9f5a7 ("powerpc/pseries/hotplug-cpu: Remove double free in error path")
>> Reported-by: Hulk Robot <hulkci@huawei.com>
>> Signed-off-by: Qinglang Miao <miaoqinglang@huawei.com>
>> ---
>>   arch/powerpc/platforms/pseries/hotplug-cpu.c | 1 +
>>   1 file changed, 1 insertion(+)
> 
> This is already fixed in my next by:
> 
>    a40fdaf1420d ("Revert "powerpc/pseries/hotplug-cpu: Remove double free in error path"")
> 
> cheers'Revert' sounds resonable to this one, glad to know that.
> 
>> diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
>> index f2837e33b..4bb1c9f2b 100644
>> --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
>> +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
>> @@ -743,6 +743,7 @@ static int dlpar_cpu_add_by_count(u32 cpus_to_add)
>>   	parent = of_find_node_by_path("/cpus");
>>   	if (!parent) {
>>   		pr_warn("Could not find CPU root node in device tree\n");
>> +		kfree(cpu_drcs);
>>   		return -1;
>>   	}
>>   
>> -- 
>> 2.23.0
> .
> 

^ permalink raw reply

* Re: [PATCH v3 01/19] powerpc/64s: move the last of the page fault handling logic to C
From: Aneesh Kumar K.V @ 2020-11-30  7:35 UTC (permalink / raw)
  To: Nicholas Piggin, linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20201128144114.944000-2-npiggin@gmail.com>

Nicholas Piggin <npiggin@gmail.com> writes:

> The page fault handling still has some complex logic particularly around
> hash table handling, in asm. Implement this in C instead.
>

Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>  arch/powerpc/include/asm/book3s/64/mmu-hash.h |   1 +
>  arch/powerpc/include/asm/bug.h                |   1 +
>  arch/powerpc/kernel/exceptions-64s.S          | 131 +++---------------
>  arch/powerpc/mm/book3s64/hash_utils.c         |  77 ++++++----
>  arch/powerpc/mm/fault.c                       |  57 +++++++-
>  5 files changed, 127 insertions(+), 140 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
> index 683a9c7d1b03..bc8c91f2d26f 100644
> --- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
> +++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
> @@ -453,6 +453,7 @@ static inline unsigned long hpt_hash(unsigned long vpn,
>  #define HPTE_LOCAL_UPDATE	0x1
>  #define HPTE_NOHPTE_UPDATE	0x2
>  
> +int do_hash_fault(struct pt_regs *regs, unsigned long ea, unsigned long dsisr);
>  extern int __hash_page_4K(unsigned long ea, unsigned long access,
>  			  unsigned long vsid, pte_t *ptep, unsigned long trap,
>  			  unsigned long flags, int ssize, int subpage_prot);
> diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
> index 338f36cd9934..c0e9b7a967a8 100644
> --- a/arch/powerpc/include/asm/bug.h
> +++ b/arch/powerpc/include/asm/bug.h
> @@ -112,6 +112,7 @@
>  
>  struct pt_regs;
>  extern int do_page_fault(struct pt_regs *, unsigned long, unsigned long);
> +int hash__do_page_fault(struct pt_regs *, unsigned long, unsigned long);
>  extern void bad_page_fault(struct pt_regs *, unsigned long, int);
>  extern void _exception(int, struct pt_regs *, int, unsigned long);
>  extern void _exception_pkey(struct pt_regs *, unsigned long, int);
> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
> index 4d01f09ecf80..336fa1fa39d1 100644
> --- a/arch/powerpc/kernel/exceptions-64s.S
> +++ b/arch/powerpc/kernel/exceptions-64s.S
> @@ -1401,14 +1401,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_HVMODE)
>   *
>   * Handling:
>   * - Hash MMU
> - *   Go to do_hash_page first to see if the HPT can be filled from an entry in
> - *   the Linux page table. Hash faults can hit in kernel mode in a fairly
> + *   Go to do_hash_fault, which attempts to fill the HPT from an entry in the
> + *   Linux page table. Hash faults can hit in kernel mode in a fairly
>   *   arbitrary state (e.g., interrupts disabled, locks held) when accessing
>   *   "non-bolted" regions, e.g., vmalloc space. However these should always be
> - *   backed by Linux page tables.
> + *   backed by Linux page table entries.
>   *
> - *   If none is found, do a Linux page fault. Linux page faults can happen in
> - *   kernel mode due to user copy operations of course.
> + *   If no entry is found the Linux page fault handler is invoked (by
> + *   do_hash_fault). Linux page faults can happen in kernel mode due to user
> + *   copy operations of course.
>   *
>   *   KVM: The KVM HDSI handler may perform a load with MSR[DR]=1 in guest
>   *   MMU context, which may cause a DSI in the host, which must go to the
> @@ -1439,13 +1440,17 @@ EXC_COMMON_BEGIN(data_access_common)
>  	GEN_COMMON data_access
>  	ld	r4,_DAR(r1)
>  	ld	r5,_DSISR(r1)
> +	addi	r3,r1,STACK_FRAME_OVERHEAD
>  BEGIN_MMU_FTR_SECTION
> -	ld	r6,_MSR(r1)
> -	li	r3,0x300
> -	b	do_hash_page		/* Try to handle as hpte fault */
> +	bl	do_hash_fault
>  MMU_FTR_SECTION_ELSE
> -	b	handle_page_fault
> +	bl	do_page_fault
>  ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
> +        cmpdi	r3,0
> +	beq+	interrupt_return
> +	/* We need to restore NVGPRS */
> +	REST_NVGPRS(r1)
> +	b       interrupt_return
>  
>  	GEN_KVM data_access
>  
> @@ -1540,13 +1545,17 @@ EXC_COMMON_BEGIN(instruction_access_common)
>  	GEN_COMMON instruction_access
>  	ld	r4,_DAR(r1)
>  	ld	r5,_DSISR(r1)
> +	addi	r3,r1,STACK_FRAME_OVERHEAD
>  BEGIN_MMU_FTR_SECTION
> -	ld      r6,_MSR(r1)
> -	li	r3,0x400
> -	b	do_hash_page		/* Try to handle as hpte fault */
> +	bl	do_hash_fault
>  MMU_FTR_SECTION_ELSE
> -	b	handle_page_fault
> +	bl	do_page_fault
>  ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX)
> +        cmpdi	r3,0
> +	beq+	interrupt_return
> +	/* We need to restore NVGPRS */
> +	REST_NVGPRS(r1)
> +	b       interrupt_return
>  
>  	GEN_KVM instruction_access
>  
> @@ -3202,99 +3211,3 @@ disable_machine_check:
>  	RFI_TO_KERNEL
>  1:	mtlr	r0
>  	blr
> -
> -/*
> - * Hash table stuff
> - */
> -	.balign	IFETCH_ALIGN_BYTES
> -do_hash_page:
> -#ifdef CONFIG_PPC_BOOK3S_64
> -	lis	r0,(DSISR_BAD_FAULT_64S | DSISR_DABRMATCH | DSISR_KEYFAULT)@h
> -	ori	r0,r0,DSISR_BAD_FAULT_64S@l
> -	and.	r0,r5,r0		/* weird error? */
> -	bne-	handle_page_fault	/* if not, try to insert a HPTE */
> -
> -	/*
> -	 * If we are in an "NMI" (e.g., an interrupt when soft-disabled), then
> -	 * don't call hash_page, just fail the fault. This is required to
> -	 * prevent re-entrancy problems in the hash code, namely perf
> -	 * interrupts hitting while something holds H_PAGE_BUSY, and taking a
> -	 * hash fault. See the comment in hash_preload().
> -	 */
> -	ld	r11, PACA_THREAD_INFO(r13)
> -	lwz	r0,TI_PREEMPT(r11)
> -	andis.	r0,r0,NMI_MASK@h
> -	bne	77f
> -
> -	/*
> -	 * r3 contains the trap number
> -	 * r4 contains the faulting address
> -	 * r5 contains dsisr
> -	 * r6 msr
> -	 *
> -	 * at return r3 = 0 for success, 1 for page fault, negative for error
> -	 */
> -	bl	__hash_page		/* build HPTE if possible */
> -        cmpdi	r3,0			/* see if __hash_page succeeded */
> -
> -	/* Success */
> -	beq	interrupt_return	/* Return from exception on success */
> -
> -	/* Error */
> -	blt-	13f
> -
> -	/* Reload DAR/DSISR into r4/r5 for the DABR check below */
> -	ld	r4,_DAR(r1)
> -	ld      r5,_DSISR(r1)
> -#endif /* CONFIG_PPC_BOOK3S_64 */
> -
> -/* Here we have a page fault that hash_page can't handle. */
> -handle_page_fault:
> -11:	andis.  r0,r5,DSISR_DABRMATCH@h
> -	bne-    handle_dabr_fault
> -	addi	r3,r1,STACK_FRAME_OVERHEAD
> -	bl	do_page_fault
> -	cmpdi	r3,0
> -	beq+	interrupt_return
> -	mr	r5,r3
> -	addi	r3,r1,STACK_FRAME_OVERHEAD
> -	ld	r4,_DAR(r1)
> -	bl	bad_page_fault
> -	b	interrupt_return
> -
> -/* We have a data breakpoint exception - handle it */
> -handle_dabr_fault:
> -	ld      r4,_DAR(r1)
> -	ld      r5,_DSISR(r1)
> -	addi    r3,r1,STACK_FRAME_OVERHEAD
> -	bl      do_break
> -	/*
> -	 * do_break() may have changed the NV GPRS while handling a breakpoint.
> -	 * If so, we need to restore them with their updated values.
> -	 */
> -	REST_NVGPRS(r1)
> -	b       interrupt_return
> -
> -
> -#ifdef CONFIG_PPC_BOOK3S_64
> -/* We have a page fault that hash_page could handle but HV refused
> - * the PTE insertion
> - */
> -13:	mr	r5,r3
> -	addi	r3,r1,STACK_FRAME_OVERHEAD
> -	ld	r4,_DAR(r1)
> -	bl	low_hash_fault
> -	b	interrupt_return
> -#endif
> -
> -/*
> - * We come here as a result of a DSI at a point where we don't want
> - * to call hash_page, such as when we are accessing memory (possibly
> - * user memory) inside a PMU interrupt that occurred while interrupts
> - * were soft-disabled.  We want to invoke the exception handler for
> - * the access, or panic if there isn't a handler.
> - */
> -77:	addi	r3,r1,STACK_FRAME_OVERHEAD
> -	li	r5,SIGSEGV
> -	bl	bad_page_fault
> -	b	interrupt_return
> diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
> index 24702c0a92e0..bfa1b1966218 100644
> --- a/arch/powerpc/mm/book3s64/hash_utils.c
> +++ b/arch/powerpc/mm/book3s64/hash_utils.c
> @@ -1510,16 +1510,40 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap,
>  }
>  EXPORT_SYMBOL_GPL(hash_page);
>  
> -int __hash_page(unsigned long trap, unsigned long ea, unsigned long dsisr,
> -		unsigned long msr)
> +int do_hash_fault(struct pt_regs *regs, unsigned long ea, unsigned long dsisr)
>  {
>  	unsigned long access = _PAGE_PRESENT | _PAGE_READ;
>  	unsigned long flags = 0;
> -	struct mm_struct *mm = current->mm;
> -	unsigned int region_id = get_region_id(ea);
> +	struct mm_struct *mm;
> +	unsigned int region_id;
> +	int err;
> +
> +	if (unlikely(dsisr & (DSISR_BAD_FAULT_64S | DSISR_DABRMATCH | DSISR_KEYFAULT)))
> +		goto _do_page_fault;
> +
> +	/*
> +	 * If we are in an "NMI" (e.g., an interrupt when soft-disabled), then
> +	 * don't call hash_page, just fail the fault. This is required to
> +	 * prevent re-entrancy problems in the hash code, namely perf
> +	 * interrupts hitting while something holds H_PAGE_BUSY, and taking a
> +	 * hash fault. See the comment in hash_preload().
> +	 *
> +	 * We come here as a result of a DSI at a point where we don't want
> +	 * to call hash_page, such as when we are accessing memory (possibly
> +	 * user memory) inside a PMU interrupt that occurred while interrupts
> +	 * were soft-disabled.  We want to invoke the exception handler for
> +	 * the access, or panic if there isn't a handler.
> +	 */
> +	if (unlikely(in_nmi())) {
> +		bad_page_fault(regs, ea, SIGSEGV);
> +		return 0;
> +	}
>  
> +	region_id = get_region_id(ea);
>  	if ((region_id == VMALLOC_REGION_ID) || (region_id == IO_REGION_ID))
>  		mm = &init_mm;
> +	else
> +		mm = current->mm;
>  
>  	if (dsisr & DSISR_NOHPTE)
>  		flags |= HPTE_NOHPTE_UPDATE;
> @@ -1535,13 +1559,31 @@ int __hash_page(unsigned long trap, unsigned long ea, unsigned long dsisr,
>  	 * 2) user space access kernel space.
>  	 */
>  	access |= _PAGE_PRIVILEGED;
> -	if ((msr & MSR_PR) || (region_id == USER_REGION_ID))
> +	if (user_mode(regs) || (region_id == USER_REGION_ID))
>  		access &= ~_PAGE_PRIVILEGED;
>  
> -	if (trap == 0x400)
> +	if (regs->trap == 0x400)
>  		access |= _PAGE_EXEC;
>  
> -	return hash_page_mm(mm, ea, access, trap, flags);
> +	err = hash_page_mm(mm, ea, access, regs->trap, flags);
> +	if (unlikely(err < 0)) {
> +		// failed to instert a hash PTE due to an hypervisor error
> +		if (user_mode(regs)) {
> +			if (IS_ENABLED(CONFIG_PPC_SUBPAGE_PROT) && err == -2)
> +				_exception(SIGSEGV, regs, SEGV_ACCERR, ea);
> +			else
> +				_exception(SIGBUS, regs, BUS_ADRERR, ea);
> +		} else {
> +			bad_page_fault(regs, ea, SIGBUS);
> +		}
> +		err = 0;
> +
> +	} else if (err) {
> +_do_page_fault:
> +		err = hash__do_page_fault(regs, ea, dsisr);
> +	}
> +
> +	return err;
>  }
>  
>  #ifdef CONFIG_PPC_MM_SLICES
> @@ -1841,27 +1883,6 @@ void flush_hash_range(unsigned long number, int local)
>  	}
>  }
>  
> -/*
> - * low_hash_fault is called when we the low level hash code failed
> - * to instert a PTE due to an hypervisor error
> - */
> -void low_hash_fault(struct pt_regs *regs, unsigned long address, int rc)
> -{
> -	enum ctx_state prev_state = exception_enter();
> -
> -	if (user_mode(regs)) {
> -#ifdef CONFIG_PPC_SUBPAGE_PROT
> -		if (rc == -2)
> -			_exception(SIGSEGV, regs, SEGV_ACCERR, address);
> -		else
> -#endif
> -			_exception(SIGBUS, regs, BUS_ADRERR, address);
> -	} else
> -		bad_page_fault(regs, address, SIGBUS);
> -
> -	exception_exit(prev_state);
> -}
> -
>  long hpte_insert_repeating(unsigned long hash, unsigned long vpn,
>  			   unsigned long pa, unsigned long rflags,
>  			   unsigned long vflags, int psize, int ssize)
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index 0add963a849b..e65a49f246ef 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -370,7 +370,9 @@ static void sanity_check_fault(bool is_write, bool is_user,
>  #define page_fault_is_write(__err)	((__err) & DSISR_ISSTORE)
>  #if defined(CONFIG_PPC_8xx)
>  #define page_fault_is_bad(__err)	((__err) & DSISR_NOEXEC_OR_G)
> -#elif defined(CONFIG_PPC64)
> +#elif defined(CONFIG_PPC_BOOK3S_64)
> +#define page_fault_is_bad(__err)	((__err) & (DSISR_BAD_FAULT_64S | DSISR_DABRMATCH))
> +#elif defined(CONFIG_PPC_BOOK3E_64)
>  #define page_fault_is_bad(__err)	((__err) & DSISR_BAD_FAULT_64S)
>  #else
>  #define page_fault_is_bad(__err)	((__err) & DSISR_BAD_FAULT_32S)
> @@ -406,6 +408,9 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
>  		return 0;
>  
>  	if (unlikely(page_fault_is_bad(error_code))) {
> +		if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && (error_code & DSISR_DABRMATCH))
> +			return -1;
> +
>  		if (is_user) {
>  			_exception(SIGBUS, regs, BUS_OBJERR, address);
>  			return 0;
> @@ -548,12 +553,58 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
>  		  unsigned long error_code)
>  {
>  	enum ctx_state prev_state = exception_enter();
> -	int rc = __do_page_fault(regs, address, error_code);
> +	int err;
> +
> +	err = __do_page_fault(regs, address, error_code);
> +
> +#ifdef CONFIG_PPC_BOOK3S_64
> +	/* 32 and 64e handle errors in their asm code */
> +	if (unlikely(err)) {
> +		if (err > 0) {
> +			bad_page_fault(regs, address, err);
> +			err = 0;
> +		} else {
> +			/*
> +			 * do_break() may change NV GPRS while handling the
> +			 * breakpoint. Return -ve to caller to do that.
> +			 */
> +			do_break(regs, address, error_code);
> +		}
> +	}
> +#endif
> +
>  	exception_exit(prev_state);
> -	return rc;
> +
> +	return err;
>  }
>  NOKPROBE_SYMBOL(do_page_fault);
>  
> +#ifdef CONFIG_PPC_BOOK3S_64
> +/* Same as do_page_fault but interrupt entry has already run in do_hash_fault */
> +int hash__do_page_fault(struct pt_regs *regs, unsigned long address,
> +		  unsigned long error_code)
> +{
> +	int err;
> +
> +	err = __do_page_fault(regs, address, error_code);
> +	if (unlikely(err)) {
> +		if (err > 0) {
> +			bad_page_fault(regs, address, err);
> +			err = 0;
> +		} else {
> +			/*
> +			 * do_break() may change NV GPRS while handling the
> +			 * breakpoint. Return -ve to caller to do that.
> +			 */
> +			do_break(regs, address, error_code);
> +		}
> +	}
> +
> +	return err;
> +}
> +NOKPROBE_SYMBOL(hash__do_page_fault);
> +#endif
> +
>  /*
>   * bad_page_fault is called when we have a bad access from the kernel.
>   * It is called from the DSI and ISI handlers in head.S and from some
> -- 
> 2.23.0

^ permalink raw reply


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