LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] macio airport how standard pccard?
From: René Rebe @ 2017-12-22 15:18 UTC (permalink / raw)
  To: linuxppc-dev

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

Hi all,

I have a nice 1.2 GHz G4 Cube on my desk, and if I could somehow get USB 2 into it, it would be way more useful as a “thin client” ;-)

I was looking at the macio airport kernel glue, but could not immediately figure out how much standard pcmcia/cardbus that is.
Is there any chance I could hack up some kernel patch glue to get a pcmcia/pccard USB 2.0 NEC chip based card working in there - or is it totally hopeless?

Thanks for any tip and merry christmas!

	René Rebe

-- 
 ExactCODE GmbH, Lietzenburger Str. 42, DE-10789 Berlin
 http://exactcode.com | http://exactscan.com | http://ocrkit.com | http://t2-project.org | http://rene.rebe.de


[-- Attachment #2: Type: text/html, Size: 2092 bytes --]

^ permalink raw reply

* Re: [RFC PATCH 4/8] powerpc/64s: put io_sync bit into r14
From: Thiago Jung Bauermann @ 2017-12-22 15:08 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linuxppc-dev
In-Reply-To: <20171220145206.12234-5-npiggin@gmail.com>


Hello Nicholas,

Just a small comment about syntax. I'm afraid I can't comment much about
the substance of the patch.

Nicholas Piggin <npiggin@gmail.com> writes:
> diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h
> index b9ebc3085fb7..182bb9304c79 100644
> --- a/arch/powerpc/include/asm/spinlock.h
> +++ b/arch/powerpc/include/asm/spinlock.h
> @@ -40,16 +40,9 @@
>  #endif
>
>  #if defined(CONFIG_PPC64) && defined(CONFIG_SMP)
> -#define CLEAR_IO_SYNC	(get_paca()->io_sync = 0)
> -#define SYNC_IO		do {						\
> -				if (unlikely(get_paca()->io_sync)) {	\
> -					mb();				\
> -					get_paca()->io_sync = 0;	\
> -				}					\
> -			} while (0)
> +#define CLEAR_IO_SYNC	do { r14_clear_bits(R14_BIT_IO_SYNC); } while(0)

Is there a reason for the do { } while(0) idiom here? If
r14_clear_bits() is an inline function, isn't it a single statement
already?

-- 
Thiago Jung Bauermann
IBM Linux Technology Center

^ permalink raw reply

* Re: [PATCH 1/1] powerpc/pseries: Use the system workqueue as fallback to hotplug workqueue
From: joserz @ 2017-12-22 14:19 UTC (permalink / raw)
  To: David Gibson; +Cc: benh, linuxppc-dev
In-Reply-To: <20171222005410.GB26042@umbus.fritz.box>

On Fri, Dec 22, 2017 at 11:54:10AM +1100, David Gibson wrote:
> On Thu, Dec 21, 2017 at 01:44:48PM -0200, Jose Ricardo Ziviani wrote:
> > The hotplug engine uses its own workqueue to handle IRQ requests, the
> > problem is that such workqueue is initialized not so early in the boot
> > process.
> > 
> > Thus, when the kernel is ready to handle IRQ requests, after the system
> > workqueue is initialized, we have a timeframe where any hotplug issued
> > by the client will result in a kernel panic. That timeframe goes until
> > the hotplug workqueue is initialized.
> > 
> > It would be good to have the hotplug workqueue initialized as soon as
> > the system workqueue but I don't think it is possible. So, this patch
> > uses the system workqueue as a fallback the handle such IRQs.
> > 
> > Signed-off-by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com>
> 
> I don't think this is the right approach.
> 
> It seems to me the bug is that the hotplug interrupt is registered in
> init_ras_IRQ(), before the work queue is initialized in
> pseries_dlpar_init().  We need to correct that ordering.
> 

Oh, this makes much more sense. I'm going to make some tests and send a
v2 then.

Thanks for reviewing it!

> > ---
> >  arch/powerpc/platforms/pseries/dlpar.c | 10 +++++++++-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
> > index 6e35780c5962..0474aa14b5f6 100644
> > --- a/arch/powerpc/platforms/pseries/dlpar.c
> > +++ b/arch/powerpc/platforms/pseries/dlpar.c
> > @@ -399,7 +399,15 @@ void queue_hotplug_event(struct pseries_hp_errorlog *hp_errlog,
> >  		work->errlog = hp_errlog_copy;
> >  		work->hp_completion = hotplug_done;
> >  		work->rc = rc;
> > -		queue_work(pseries_hp_wq, (struct work_struct *)work);
> > +
> > +		/* The hotplug workqueue may happen to be NULL at the moment
> > +		 * this code is executed, during the boot phase. So, in this
> > +		 * scenario, we can fallback to the system workqueue.
> > +		 */
> > +		if (unlikely(pseries_hp_wq == NULL))
> > +			schedule_work((struct work_struct *)work);
> > +		else
> > +			queue_work(pseries_hp_wq, (struct work_struct *)work);
> >  	} else {
> >  		*rc = -ENOMEM;
> >  		kfree(hp_errlog_copy);
> 
> -- 
> David Gibson			| I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
> 				| _way_ _around_!
> http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [RFC PATCH 3/8] powerpc/64s: put the per-cpu data_offset in r14
From: Nicholas Piggin @ 2017-12-22 13:50 UTC (permalink / raw)
  To: Gabriel Paubert; +Cc: linuxppc-dev
In-Reply-To: <20171220175324.uidr5ohzqiwsb6hu@lt-gp.iram.es>

On Wed, 20 Dec 2017 18:53:24 +0100
Gabriel Paubert <paubert@iram.es> wrote:

> On Thu, Dec 21, 2017 at 12:52:01AM +1000, Nicholas Piggin wrote:
> > Shifted left by 16 bits, so the low 16 bits of r14 remain available.
> > This allows per-cpu pointers to be dereferenced with a single extra
> > shift whereas previously it was a load and add.
> > ---
> >  arch/powerpc/include/asm/paca.h   |  5 +++++
> >  arch/powerpc/include/asm/percpu.h |  2 +-
> >  arch/powerpc/kernel/entry_64.S    |  5 -----
> >  arch/powerpc/kernel/head_64.S     |  5 +----
> >  arch/powerpc/kernel/setup_64.c    | 11 +++++++++--
> >  5 files changed, 16 insertions(+), 12 deletions(-)
> > 
> > diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
> > index cd6a9a010895..4dd4ac69e84f 100644
> > --- a/arch/powerpc/include/asm/paca.h
> > +++ b/arch/powerpc/include/asm/paca.h
> > @@ -35,6 +35,11 @@
> >  
> >  register struct paca_struct *local_paca asm("r13");
> >  #ifdef CONFIG_PPC_BOOK3S
> > +/*
> > + * The top 32-bits of r14 is used as the per-cpu offset, shifted by PAGE_SHIFT.  
> 
> Top 32, really? It's 48 in later comments.

Yep, I used 32 to start with but it wasn't enough. Will fix.

Thanks,
Nick

^ permalink raw reply

* [PATCH v5 2/2] cxl: read PHB indications from the device tree
From: Philippe Bergheaud @ 2017-12-22 12:36 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: fbarrat, clombard, benh, Philippe Bergheaud
In-Reply-To: <20171222123624.1880-1-felix@linux.vnet.ibm.com>

Configure the P9 XSL_DSNCTL register with PHB indications found
in the device tree, or else use legacy hard-coded values.

Signed-off-by: Philippe Bergheaud <felix@linux.vnet.ibm.com>
---
Changelog:

v2: New patch. Use the new device tree property "ibm,phb-indications".

v3: No change.

v4: No functional change.
    Drop cosmetic fix in comment.

v5: get_phb_indications():
      - make static variables local to function.
      - return static variable values by arguments.

This patch depends on the following skiboot prerequisite:

https://patchwork.ozlabs.org/patch/849162/
---
 drivers/misc/cxl/cxl.h    |  2 +-
 drivers/misc/cxl/cxllib.c |  2 +-
 drivers/misc/cxl/pci.c    | 42 +++++++++++++++++++++++++++++++++++++-----
 3 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index e46a4062904a..5a6e9a921c2b 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -1062,7 +1062,7 @@ int cxl_psl_purge(struct cxl_afu *afu);
 int cxl_calc_capp_routing(struct pci_dev *dev, u64 *chipid,
 			  u32 *phb_index, u64 *capp_unit_id);
 int cxl_slot_is_switched(struct pci_dev *dev);
-int cxl_get_xsl9_dsnctl(u64 capp_unit_id, u64 *reg);
+int cxl_get_xsl9_dsnctl(struct pci_dev *dev, u64 capp_unit_id, u64 *reg);
 u64 cxl_calculate_sr(bool master, bool kernel, bool real_mode, bool p9);
 
 void cxl_native_irq_dump_regs_psl9(struct cxl_context *ctx);
diff --git a/drivers/misc/cxl/cxllib.c b/drivers/misc/cxl/cxllib.c
index dc9bc1807fdf..61f80d586279 100644
--- a/drivers/misc/cxl/cxllib.c
+++ b/drivers/misc/cxl/cxllib.c
@@ -99,7 +99,7 @@ int cxllib_get_xsl_config(struct pci_dev *dev, struct cxllib_xsl_config *cfg)
 	if (rc)
 		return rc;
 
-	rc = cxl_get_xsl9_dsnctl(capp_unit_id, &cfg->dsnctl);
+	rc = cxl_get_xsl9_dsnctl(dev, capp_unit_id, &cfg->dsnctl);
 	if (rc)
 		return rc;
 	if (cpu_has_feature(CPU_FTR_POWER9_DD1)) {
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 19969ee86d6f..1d38fff2139f 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -409,21 +409,53 @@ int cxl_calc_capp_routing(struct pci_dev *dev, u64 *chipid,
 	return 0;
 }
 
-int cxl_get_xsl9_dsnctl(u64 capp_unit_id, u64 *reg)
+static int get_phb_indications(struct pci_dev *dev, u64* capiind, u64 *asnind,
+			       u64 *nbwind)
+{
+	static u64 nbw, asn, capi = 0;
+	struct device_node *np;
+	const __be32 *prop;
+
+	if (!capi) {
+		if (!(np = pnv_pci_get_phb_node(dev)))
+			return -1;
+
+		prop = of_get_property(np, "ibm,phb-indications", NULL);
+		if (!prop) {
+			nbw = 0x0300UL; /* legacy values */
+			asn = 0x0400UL;
+			capi = 0x0200UL;
+		} else {
+			nbw = (u64)be32_to_cpu(prop[2]);
+			asn = (u64)be32_to_cpu(prop[1]);
+			capi = (u64)be32_to_cpu(prop[0]);
+		}
+		of_node_put(np);
+	}
+	*capiind = capi;
+	*asnind = asn;
+	*nbwind = nbw;
+	return 0;
+}
+
+int cxl_get_xsl9_dsnctl(struct pci_dev *dev, u64 capp_unit_id, u64 *reg)
 {
 	u64 xsl_dsnctl;
+	u64 capiind, asnind, nbwind;
 
 	/*
 	 * CAPI Identifier bits [0:7]
 	 * bit 61:60 MSI bits --> 0
 	 * bit 59 TVT selector --> 0
 	 */
+	if (get_phb_indications(dev, &capiind, &asnind, &nbwind))
+		return -1;
 
 	/*
 	 * Tell XSL where to route data to.
 	 * The field chipid should match the PHB CAPI_CMPM register
 	 */
-	xsl_dsnctl = ((u64)0x2 << (63-7)); /* Bit 57 */
+	xsl_dsnctl = (capiind << (63-15)); /* Bit 57 */
 	xsl_dsnctl |= (capp_unit_id << (63-15));
 
 	/* nMMU_ID Defaults to: b’000001001’*/
@@ -437,14 +469,14 @@ int cxl_get_xsl9_dsnctl(u64 capp_unit_id, u64 *reg)
 		 * nbwind=0x03, bits [57:58], must include capi indicator.
 		 * Not supported on P9 DD1.
 		 */
-		xsl_dsnctl |= ((u64)0x03 << (63-47));
+		xsl_dsnctl |= (nbwind << (63-55));
 
 		/*
 		 * Upper 16b address bits of ASB_Notify messages sent to the
 		 * system. Need to match the PHB’s ASN Compare/Mask Register.
 		 * Not supported on P9 DD1.
 		 */
-		xsl_dsnctl |= ((u64)0x04 << (63-55));
+		xsl_dsnctl |= asnind;
 	}
 
 	*reg = xsl_dsnctl;
@@ -464,7 +496,7 @@ static int init_implementation_adapter_regs_psl9(struct cxl *adapter,
 	if (rc)
 		return rc;
 
-	rc = cxl_get_xsl9_dsnctl(capp_unit_id, &xsl_dsnctl);
+	rc = cxl_get_xsl9_dsnctl(dev, capp_unit_id, &xsl_dsnctl);
 	if (rc)
 		return rc;
 
-- 
2.15.1

^ permalink raw reply related

* [PATCH v5 1/2] powerpc/powernv: Enable tunneled operations
From: Philippe Bergheaud @ 2017-12-22 12:36 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: fbarrat, clombard, benh, Philippe Bergheaud

P9 supports PCI tunneled operations (atomics and as_notify). This
patch adds support for tunneled operations on powernv, with a new
API, to be called by device drivers:

pnv_pci_get_tunnel_ind()
   Tell driver the 16-bit ASN indication used by kernel.

pnv_pci_set_tunnel_bar()
   Tell kernel the Tunnel BAR Response address used by driver.
   This function uses two new OPAL calls, as the PBCQ Tunnel BAR
   register is configured by skiboot.

pnv_pci_get_as_notify_info()
   Return the ASN info of the thread to be woken up.

Signed-off-by: Philippe Bergheaud <felix@linux.vnet.ibm.com>
---
Changelog:

v2: Do not set the ASN indication. Get it from the device tree.

v3: Make pnv_pci_get_phb_node() available when compiling without cxl.

v4: Add pnv_pci_get_as_notify_info().
    Rebase opal call numbers on skiboot 5.9.6.

v5: pnv_pci_get_tunnel_ind():
      - fix node reference count
    pnv_pci_get_as_notify_info():
      - fail if task == NULL
      - read pid from mm->context.id
      - explain that thread.tidr require CONFIG_PPC64

This patch depends on the following skiboot prerequisites:

https://patchwork.ozlabs.org/patch/849162/
https://patchwork.ozlabs.org/patch/849163/
---
 arch/powerpc/include/asm/opal-api.h            |   4 +-
 arch/powerpc/include/asm/opal.h                |   2 +
 arch/powerpc/include/asm/pnv-pci.h             |   5 ++
 arch/powerpc/platforms/powernv/opal-wrappers.S |   2 +
 arch/powerpc/platforms/powernv/pci-cxl.c       |   8 --
 arch/powerpc/platforms/powernv/pci.c           | 106 +++++++++++++++++++++++++
 6 files changed, 118 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h
index 233c7504b1f2..b901f4d9f009 100644
--- a/arch/powerpc/include/asm/opal-api.h
+++ b/arch/powerpc/include/asm/opal-api.h
@@ -201,7 +201,9 @@
 #define OPAL_SET_POWER_SHIFT_RATIO		155
 #define OPAL_SENSOR_GROUP_CLEAR			156
 #define OPAL_PCI_SET_P2P			157
-#define OPAL_LAST				157
+#define OPAL_PCI_GET_PBCQ_TUNNEL_BAR		159
+#define OPAL_PCI_SET_PBCQ_TUNNEL_BAR		160
+#define OPAL_LAST				160
 
 /* Device tree flags */
 
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 0c545f7fc77b..8705e422b893 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -198,6 +198,8 @@ int64_t opal_unregister_dump_region(uint32_t id);
 int64_t opal_slw_set_reg(uint64_t cpu_pir, uint64_t sprn, uint64_t val);
 int64_t opal_config_cpu_idle_state(uint64_t state, uint64_t flag);
 int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number);
+int64_t opal_pci_get_pbcq_tunnel_bar(uint64_t phb_id, uint64_t *addr);
+int64_t opal_pci_set_pbcq_tunnel_bar(uint64_t phb_id, uint64_t addr);
 int64_t opal_ipmi_send(uint64_t interface, struct opal_ipmi_msg *msg,
 		uint64_t msg_len);
 int64_t opal_ipmi_recv(uint64_t interface, struct opal_ipmi_msg *msg,
diff --git a/arch/powerpc/include/asm/pnv-pci.h b/arch/powerpc/include/asm/pnv-pci.h
index 3e5cf251ad9a..c69de3276b5e 100644
--- a/arch/powerpc/include/asm/pnv-pci.h
+++ b/arch/powerpc/include/asm/pnv-pci.h
@@ -29,6 +29,11 @@ extern int pnv_pci_set_power_state(uint64_t id, uint8_t state,
 extern int pnv_pci_set_p2p(struct pci_dev *initiator, struct pci_dev *target,
 			   u64 desc);
 
+extern int pnv_pci_get_tunnel_ind(struct pci_dev *dev, uint64_t *ind);
+extern int pnv_pci_set_tunnel_bar(struct pci_dev *dev, uint64_t addr,
+				  int enable);
+extern int pnv_pci_get_as_notify_info(struct task_struct *task, u32 *lpid,
+				      u32 *pid, u32 *tid);
 int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode);
 int pnv_cxl_ioda_msi_setup(struct pci_dev *dev, unsigned int hwirq,
 			   unsigned int virq);
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 6f4b00a2ac46..5da790fb7fef 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -320,3 +320,5 @@ OPAL_CALL(opal_set_powercap,			OPAL_SET_POWERCAP);
 OPAL_CALL(opal_get_power_shift_ratio,		OPAL_GET_POWER_SHIFT_RATIO);
 OPAL_CALL(opal_set_power_shift_ratio,		OPAL_SET_POWER_SHIFT_RATIO);
 OPAL_CALL(opal_sensor_group_clear,		OPAL_SENSOR_GROUP_CLEAR);
+OPAL_CALL(opal_pci_get_pbcq_tunnel_bar,		OPAL_PCI_GET_PBCQ_TUNNEL_BAR);
+OPAL_CALL(opal_pci_set_pbcq_tunnel_bar,		OPAL_PCI_SET_PBCQ_TUNNEL_BAR);
diff --git a/arch/powerpc/platforms/powernv/pci-cxl.c b/arch/powerpc/platforms/powernv/pci-cxl.c
index 94498a04558b..cee003de63af 100644
--- a/arch/powerpc/platforms/powernv/pci-cxl.c
+++ b/arch/powerpc/platforms/powernv/pci-cxl.c
@@ -16,14 +16,6 @@
 
 #include "pci.h"
 
-struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
-{
-	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-
-	return of_node_get(hose->dn);
-}
-EXPORT_SYMBOL(pnv_pci_get_phb_node);
-
 int pnv_phb_to_cxl_mode(struct pci_dev *dev, uint64_t mode)
 {
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 5422f4a6317c..0059fdba086c 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/msi.h>
 #include <linux/iommu.h>
+#include <linux/sched/mm.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
@@ -38,6 +39,7 @@
 #include "pci.h"
 
 static DEFINE_MUTEX(p2p_mutex);
+static DEFINE_MUTEX(tunnel_mutex);
 
 int pnv_pci_get_slot_id(struct device_node *np, uint64_t *id)
 {
@@ -1092,6 +1094,110 @@ int pnv_pci_set_p2p(struct pci_dev *initiator, struct pci_dev *target, u64 desc)
 }
 EXPORT_SYMBOL_GPL(pnv_pci_set_p2p);
 
+struct device_node *pnv_pci_get_phb_node(struct pci_dev *dev)
+{
+	struct pci_controller *hose = pci_bus_to_host(dev->bus);
+
+	return of_node_get(hose->dn);
+}
+EXPORT_SYMBOL(pnv_pci_get_phb_node);
+
+int pnv_pci_get_tunnel_ind(struct pci_dev *dev, u64 *asnind)
+{
+	struct device_node *np;
+	const __be32 *prop;
+
+	if (!(np = pnv_pci_get_phb_node(dev)))
+		return -ENXIO;
+
+	prop = of_get_property(np, "ibm,phb-indications", NULL);
+	of_node_put(np);
+
+	if (!prop || !prop[1])
+		return -ENXIO;
+
+	*asnind = (u64)be32_to_cpu(prop[1]);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_get_tunnel_ind);
+
+int pnv_pci_set_tunnel_bar(struct pci_dev *dev, u64 addr, int enable)
+{
+	__be64 val;
+	struct pci_controller *hose;
+	struct pnv_phb *phb;
+	u64 tunnel_bar;
+	int rc;
+
+	if (!opal_check_token(OPAL_PCI_GET_PBCQ_TUNNEL_BAR))
+		return -ENXIO;
+	if (!opal_check_token(OPAL_PCI_SET_PBCQ_TUNNEL_BAR))
+		return -ENXIO;
+
+	hose = pci_bus_to_host(dev->bus);
+	phb = hose->private_data;
+
+	mutex_lock(&tunnel_mutex);
+	rc = opal_pci_get_pbcq_tunnel_bar(phb->opal_id, &val);
+	if (rc != OPAL_SUCCESS) {
+		rc = -EIO;
+		goto out;
+	}
+	tunnel_bar = be64_to_cpu(val);
+	if (enable) {
+		/*
+		* Only one device per PHB can use atomics.
+		* Our policy is first-come, first-served.
+		*/
+		if (tunnel_bar) {
+			rc = -EBUSY;
+			goto out;
+		}
+	} else {
+		/*
+		* The device that owns atomics and wants to release
+		* them must pass the same address with enable == 0.
+		*/
+		if (tunnel_bar != addr) {
+			rc = -EPERM;
+			goto out;
+		}
+		addr = 0x0ULL;
+	}
+	rc = opal_pci_set_pbcq_tunnel_bar(phb->opal_id, addr);
+	rc = opal_error_code(rc);
+out:
+	mutex_unlock(&tunnel_mutex);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_set_tunnel_bar);
+
+#ifdef CONFIG_PPC64	/* for thread.tidr */
+int pnv_pci_get_as_notify_info(struct task_struct *task, u32 *lpid, u32 *pid,
+			       u32 *tid)
+{
+	struct mm_struct *mm = NULL;
+
+	if (task == NULL)
+		return -EINVAL;
+
+	mm = get_task_mm(task);
+	if (mm == NULL)
+		return -EINVAL;
+	/*
+	 * Caller is keeping a reference on mm_users for as long
+	 * as XSL uses the memory context
+	 */
+	*pid = mm->context.id;
+	mmput(mm);
+
+	*tid = task->thread.tidr;
+	*lpid = mfspr(SPRN_LPID);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pnv_pci_get_as_notify_info);
+#endif
+
 void pnv_pci_shutdown(void)
 {
 	struct pci_controller *hose;
-- 
2.15.1

^ permalink raw reply related

* [PATCH] SB600 for the Nemo board has non-zero devices on non-root bus
From: Christian Zigotzky @ 2017-12-22 12:11 UTC (permalink / raw)
  To: Michael Ellerman, Bjorn Helgaas, Darren Stevens,
	linux-pci@vger.kernel.org, Bjorn Helgaas, Olof Johansson,
	linuxppc-dev
In-Reply-To: <87zi6bnh5t.fsf@concordia.ellerman.id.au>

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

Hi Michael,

Thanks a lot for your reply! :-)

I have found two interesting lines in the device tree:

compatible       "pasemi,nemo"
model            "pasemi,nemo"

What do you think?

Please find attached the output of `lsprop /proc/device-tree`.

Thanks,
Christian


On 22.12.2017 12:19, Michael Ellerman wrote:
 >
 > I suspect Darren was referring to all of sb600_set_flag().
 >
 > What we'd really like is to be able to do something like:
 >
 > void __init pas_pci_init(void)
 > {
 >     ...
 >
 >     if (of_find_compatible_node(NULL, NULL, "nemo-something"))
 >         pci_set_flag(PCI_SCAN_ALL_PCIE_DEVS).
 >
 >
 > But I don't know if there's anything in the NEMO device tree that we can
 > use to uniquely identify those machines? ie. the "nemo-something" string.
 >
 > Can you attach the output of `lsprop /proc/device-tree` ?
 >
 > cheers
 >



[-- Attachment #2: nemo_device-tree.txt --]
[-- Type: text/plain, Size: 30529 bytes --]

compatible       "pasemi,nemo"
		 "pasemi,pa6t-1682m"
		 "PA6T-1682M"
		 "pasemi,pwrficient"
		 "pasemi"
device_type      "bootrom"
model            "pasemi,nemo"
#interrupt-cells 00000002
#address-cells   00000002
#size-cells      00000002
linux,phandle    7fdff018 (2145382424)
platform-open-pic 00000000 fc000000 00000000 00041000
name             ""

/proc/device-tree/sdc@fc000000:
compatible       "1682m-sdc"
		 "pasemi,pwrficient-sdc"
		 "pasemi,sdc"
device_type      "sdc"
#address-cells   00000001
#size-cells      00000001
reg              00000000 fc000000 00000000 00800000
linux,phandle    7fe2f458 (2145580120)
name             "sdc"

/proc/device-tree/sdc@fc000000/rng@fc105000:
compatible       "1682m-rng"
		 "pasemi,pwrficient-rng"
		 "pasemi,rng"
device_type      "rng"
reg              fc105000 00001000
linux,phandle    7fe2fdd0 (2145582544)
name             "rng"

/proc/device-tree/sdc@fc000000/mdio@0:
compatible       "gpio-mdio"
mdc-pin          00000005
#address-cells   00000001
#size-cells      00000000
reg              00000000 00000000
linux,phandle    7fe3d5a0 (2145637792)
mdio-pin         00000006
name             "mdio"

/proc/device-tree/sdc@fc000000/mdio@0/ethernet-phy@0:
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000007 00000001
reg              00000000
linux,phandle    7fe3d860 (2145638496)
name             "ethernet-phy"

/proc/device-tree/sdc@fc000000/openpic@fc000000:
compatible       "pasemi,pwrficient-openpic"
		 "chrp,open-pic"
device_type      "open-pic"
msi-available-ranges 00000200 00000200
#interrupt-cells 00000002
#address-cells   00000000
reg              fc000000 00100000
linux,phandle    7fe2f6e8 (2145580776)
name             "openpic"
interrupt-controller

/proc/device-tree/sdc@fc000000/gizmo@fc104000:
compatible       "1682m-gizmo"
		 "pasemi,pwrficient-gizmo"
		 "pasemi,gizmo"
device_type      "gizmo"
reg              fc104000 00001000
linux,phandle    7fe2fbf0 (2145582064)
name             "gizmo"

/proc/device-tree/sdc@fc000000/gpio@fc103000:
compatible       "1682m-gpio"
		 "pasemi,pwrficient-gpio"
		 "pasemi,gpio"
device_type      "gpio"
reg              fc103000 00001000
linux,phandle    7fe2fa18 (2145581592)
name             "gpio"

/proc/device-tree/options:
MENU_2_LABEL     "Debian Sid/experimental Kernel 4.9"
MENU_4_COMMAND   "set pmu -astate=A4 ; ramdisk -z -addr=0x24000000 -fatfs cf0:slitaz25.gz ; boot -elf -noints -fatfs cf0:vmlinux-3.13.14"
ETH0_HWADDR      "00:50:C2:20:DA:9E"
CFE_MEMORYSIZE   "8192"
MENU_5_LABEL     "Fedora 17 Kernel 3.13.9"
MENU_8_LABEL     "ubuntu MATE 16.04.2 LTS Kernel 4.9"
MENU_1_COMMAND   "setenv amigaboot_quiet Y ;boot -fs=iso atapi0.1:amigaboot.of"
MENU_8_COMMAND   "set pmu -astate=A4 ; setenv bootargs "root=/dev/sdb1 quiet ro splash" ; boot -elf -noints -fatfs cf0:vmlinux-4.9"
bootargs         "root=/dev/sda4"
STARTUP          "speed;menu"
MENU_DEFAULT     "0"
MENU_0_LABEL     "AmigaOS"
MENU_5_COMMAND   73657420 706d7520 2d617374 6174653d
		 4134203b 20736574 656e7620 626f6f74
		 61726773 20227264 2e6d643d 30207264
		 2e6c766d 3d302072 642e646d 3d302053
		 5953464f 4e543d54 72756520 4b455954
		 41424c45 3d646520 72642e6c 756b733d
		 3020726f 6f743d2f 6465762f 73646233
		 204c414e 473d6465 5f44452e 5554462d
		 [191 bytes total]
MENU_3_LABEL     "ubuntu MATE 17.04 Kernel 4.9"
MENU_6_LABEL     "Fedora 25 PPC64 Kernel 4.9"
MENU_2_COMMAND   "set pmu -astate=A4 ; setenv bootargs "root=/dev/sda4" ; boot -elf -noints -fatfs cf0:vmlinux-4.9"
MENU_9_LABEL     "openSUSE Tumbleweed Kernel 4.14"
speed            "set pmu -astate=A4"
MENU_9_COMMAND   "set pmu -astate=A4 ; setenv bootargs "root=/dev/sdb6 splash=silent" ; boot -elf -noints -fatfs cf0:vmlinux-4.14"
BOOT_CONSOLE     "pcconsole0"
CFE_VERSION      "PAS-2.0.30"
little-endian?   00000000
MENU_6_COMMAND   "set pmu -astate=A4 ; setenv bootargs "root=/dev/sdb4" ; boot -elf -noints -fatfs cf0:vmlinux-4.9"
CFE_BOARDNAME    "NEMO"
MENU_1_LABEL     "AmigaOS CD Boot"
MENU_4_LABEL     "SliTaz Snapshot 25 Kernel 3.13.14"
MENU_3_COMMAND   "set pmu -astate=A4 ; setenv bootargs "root=/dev/sdb7 quiet ro splash" ; boot -elf -noints -fatfs cf0:vmlinux-4.9"
MENU_7_LABEL     "openSUSE 11.1 Kernel 4.13"
os4_commandline  "DEBUGLEVEL=0 SERIAL"
MENU_0_COMMAND   "setenv amigaboot_quiet Y ;boot -fs=amigafs ide0.0:amigaboot.of"
linux,phandle    7fe2f1f0 (2145579504)
MENU_TIMEOUT     "6"
MENU_7_COMMAND   "set pmu -astate=A4 ; setenv bootargs "root=/dev/sdb5" ; boot -elf -noints -fatfs cf0:vmlinux-4.13"
framebuffer      "800/600/8/0x90000000/832"
name             "options"

/proc/device-tree/chosen:
linux,stdout-package 7fe35880 (2145605760)
bootargs         "root=/dev/sda4"
cpu              7fe30698 (2145584792)
stdout           7fe35990 (2145606032)
memory           7fe316c8 (2145588936)
stdin            7fe35990 (2145606032)
linux,stdout-path "/bootconsole"
sdc-interrupt-controller 7fe2f6e8 (2145580776)
linux,phandle    7fe34628 (2145601064)
name             "chosen"

/proc/device-tree/openprom:
device_type      "BootROM"
model            "Open Firmware 3"
linux,phandle    7fe2f2f0 (2145579760)
name             "openprom"

/proc/device-tree/localbus@f0000000:
compatible       "pasemi,localbus"
		 "localbus"
device_type      "localbus"
ranges           00000000 00000000 f0000000 0c000000
#interrupt-cells 00000002
#address-cells   00000001
#size-cells      00000001
reg              00000000 f0000000 00000000 0c000000
linux,phandle    7fe342e0 (2145600224)
name             "localbus"

/proc/device-tree/localbus@f0000000/cf@1000000:
compatible       "pasemi,chitra-cf"
		 "pasemi,electra-cf"
		 "electra-cf"
card-3v-gpio     0000000a (10)
device_type      "electra-cf"
card-vsense-gpio 00000001
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000000 00000001
reg              00000000 00001000 01000000 00001000
card-detect-gpio 0000000e (14)
linux,phandle    7fe3da70 (2145639024)
card-5v-gpio     0000000b (11)
name             "cf"

/proc/device-tree/memory:
device_type      "memory"
available        00000000 00000000 00000000 7fd1d000
		 00000001 00000000 00000001 80000000
reg              00000000 00000000 00000000 80000000
		 00000001 00000000 00000001 80000000
linux,phandle    7fe316c8 (2145588936)
name             "memory"

/proc/device-tree/pxp@0,e0000000:
compatible       "pasemi,rootbus"
		 "pa-pxp"
device_type      "pci"
interrupt-map-mask 00000000 00000000 00000000 000000ff
model            "pa"
ranges           00000000 00000000 e0000000 00000000
		 e0000000 00000000 10000000 01000000
		 00000000 00000000 00000000 fc800000
		 00000000 00800000 02000000 00000000
		 80000000 00000000 80000000 00000000
		 60000000 02000000 00000000 e0000000
		 00000000 e0000000 00000000 00100000
		 02000000 00000000 fd800000 00000000
		 [168 bytes total]
#interrupt-cells 00000001
bus-range        00000000 000000ff
#address-cells   00000003
interrupt-map    00000000 00000000 00000000 00000030
		 7fe2f6e8 00000030 00000001 00000000
		 00000000 00000000 00000031 7fe2f6e8
		 00000031 00000001 00000000 00000000
		 00000000 00000032 7fe2f6e8 00000032
		 00000001 00000000 00000000 00000000
		 00000033 7fe2f6e8 00000033 00000001
#size-cells      00000002
reg              00000000 e0000000 00000000 10000000
linux,phandle    7fe2ffa8 (2145583016)
name             "pxp"
interrupt-controller

/proc/device-tree/pxp@0,e0000000/i2c@1c,2:
assigned-addresses 8100e210 00000000 007f0280 00000000 00000040
device_type      "i2c"
revision-id      00000001
class-code       000c0500 (787712)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000048 00000001
device-id        0000a003 (40963)
reg              0000e200 00000000 00000000 00000000 00000000
		 0100e210 00000000 00000000 00000000 00000040
linux,phandle    7fe33c80 (2145598592)
name             "i2c"

/proc/device-tree/pxp@0,e0000000/pci@8:
device_type      "pci"
revision-id      00000012 (18)
class-code       000b2000 (729088)
vendor-id        00001959 (6489)
device-id        0000a000 (40960)
reg              00004000 00000000 00000000 00000000 00000000
linux,phandle    7fe383f8 (2145616888)
name             "pci"

/proc/device-tree/pxp@0,e0000000/serial@1d,1:
current-speed    0001c200 (115200)
compatible       "ns16550"
		 "pciclass,0700"
assigned-addresses 8100e910 00000000 007f02f8 00000000 00000008
device_type      "serial"
revision-id      00000002
class-code       00070003 (458755)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       0000004a 00000001
device-id        0000a004 (40964)
reg              0000e900 00000000 00000000 00000000 00000000
		 0100e910 00000000 00000000 00000000 00000008
clock-frequency  07f28155 (133333333)
linux,phandle    7fe31db0 (2145590704)
name             "serial"

/proc/device-tree/pxp@0,e0000000/pci@1b:
device_type      "pci"
revision-id      00000011 (17)
class-code       00088000 (557056)
vendor-id        00001959 (6489)
device-id        0000a00b (40971)
reg              0000d800 00000000 00000000 00000000 00000000
linux,phandle    7fe38d78 (2145619320)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11,2:
device_type      "pci"
revision-id      00000011 (17)
class-code       00060400 (394240)
vendor-id        00001959 (6489)
#interrupt-cells 00000001
bus-range        00000008 00000008
#address-cells   00000003
#size-cells      00000002
device-id        0000a002 (40962)
reg              00008a00 00000000 00000000 00000000 00000000
linux,phandle    7fe367d0 (2145609680)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@4:
device_type      "pci"
revision-id      00000011 (17)
class-code       00050000 (327680)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000058 00000001
device-id        0000a00a (40970)
reg              00002000 00000000 00000000 00000000 00000000
linux,phandle    7fe37d08 (2145615112)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@10:
device_type      "pci"
revision-id      00000011 (17)
class-code       00060400 (394240)
ranges           01000000 00000000 00002000 01000000
		 00000000 00002000 00000000 00001000
		 02000000 00000000 90000000 02000000
		 00000000 90000000 00000000 10100000
vendor-id        00001959 (6489)
#interrupt-cells 00000001
bus-range        00000001 00000001
#address-cells   00000003
#size-cells      00000002
device-id        0000a002 (40962)
reg              00008000 00000000 00000000 00000000 00000000
linux,phandle    7fe374d8 (2145613016)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@10/pci@0,1:
assigned-addresses 82010110 00000000 a0040000 00000000 00004000
device_type      "pci"
revision-id      00000000
subsystem-id     0000aa88 (43656)
class-code       00040300 (262912)
vendor-id        00001002 (4098)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000031 00000001
device-id        0000aa88 (43656)
reg              00010100 00000000 00000000 00000000 00000000
		 02010110 00000000 00000000 00000000 00004000
subsystem-vendor-id 00001682 (5762)
linux,phandle    7fe39948 (2145622344)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@10/pci@0:
assigned-addresses c2010010 00000000 90000000 00000000 10000000
		 82010018 00000000 a0020000 00000000 00020000
		 81010020 00000000 00002000 00000000 00000100
device_type      "pci"
revision-id      00000000
subsystem-id     00003107 (12551)
class-code       00030000 (196608)
vendor-id        00001002 (4098)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000030 00000001
device-id        00006738 (26424)
reg              00010000 00000000 00000000 00000000 00000000
		 42010010 00000000 00000000 00000000 10000000
		 02010018 00000000 00000000 00000000 00020000
		 01010020 00000000 00000000 00000000 00000100
subsystem-vendor-id 00001682 (5762)
linux,phandle    7fe39458 (2145621080)
name             "pci"

/proc/device-tree/pxp@0,e0000000/i2c@1c,1:
assigned-addresses 8100e110 00000000 007f0240 00000000 00000040
device_type      "i2c"
revision-id      00000001
class-code       000c0500 (787712)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000047 00000001
device-id        0000a003 (40963)
reg              0000e100 00000000 00000000 00000000 00000000
		 0100e110 00000000 00000000 00000000 00000040
linux,phandle    7fe33890 (2145597584)
name             "i2c"

/proc/device-tree/pxp@0,e0000000/pci@1e:
assigned-addresses 8100f010 00000000 007f0400 00000000 00000100
		 8100f014 00000000 007f0500 00000000 00000100
device_type      "pci"
revision-id      00000012 (18)
class-code       000601ff (393727)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000051 00000001
device-id        0000a008 (40968)
reg              0000f000 00000000 00000000 00000000 00000000
		 0100f010 00000000 00000000 00000000 00000100
		 0100f014 00000000 00000000 00000000 00000100
linux,phandle    7fe39040 (2145620032)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@9:
device_type      "pci"
revision-id      00000012 (18)
class-code       000b2000 (729088)
vendor-id        00001959 (6489)
device-id        0000a000 (40960)
reg              00004800 00000000 00000000 00000000 00000000
linux,phandle    7fe386c0 (2145617600)
name             "pci"

/proc/device-tree/pxp@0,e0000000/io-bridge@0:
compatible       "pasemi,1682m-iob"
		 "pasemi,io-bridge"
assigned-addresses 82000000 00000000 e0000000 00000000 00002000
		 c2000000 00000000 fd800000 00000000 00001000
device_type      "isa"
revision-id      00000012 (18)
class-code       00060000 (393216)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000056 00000001
device-id        0000a001 (40961)
reg              00000000 00000000 00000000 00000000 00000000
		 82000000 00000000 e0000000 00000000 00002000
		 c2000000 00000000 fd800000 00000000 00001000
linux,phandle    7fe32728 (2145593128)
name             "io-bridge"

/proc/device-tree/pxp@0,e0000000/pci@15:
assigned-addresses 82000000 00000000 e00a8000 00000000 00001000
device_type      "pci"
revision-id      00000011 (17)
class-code       00020000 (131072)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000044 00000001
device-id        0000a006 (40966)
reg              0000a800 00000000 00000000 00000000 00000000
		 82000000 00000000 e00a8000 00000000 00001000
linux,phandle    7fe38988 (2145618312)
name             "pci"

/proc/device-tree/pxp@0,e0000000/dma-engine@1a:
compatible       "1682m-dma"
		 "pasemi,dma-engine"
assigned-addresses 82000000 00000000 e00d0000 00000000 00001000
device_type      "dma-engine"
revision-id      00000012 (18)
class-code       000801ff (524799)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000080 00000001
device-id        0000a007 (40967)
reg              0000d000 00000000 00000000 00000000 00000000
		 82000000 00000000 e00d0000 00000000 00001000
linux,phandle    7fe322b8 (2145591992)
name             "dma-engine"

/proc/device-tree/pxp@0,e0000000/pci@11,3:
device_type      "pci"
revision-id      00000011 (17)
class-code       00060400 (394240)
vendor-id        00001959 (6489)
#interrupt-cells 00000001
bus-range        00000009 00000009
#address-cells   00000003
#size-cells      00000002
device-id        0000a002 (40962)
reg              00008b00 00000000 00000000 00000000 00000000
linux,phandle    7fe363a8 (2145608616)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@5:
device_type      "pci"
revision-id      00000011 (17)
class-code       00050000 (327680)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       0000005a 00000001
device-id        0000a00a (40970)
reg              00002800 00000000 00000000 00000000 00000000
linux,phandle    7fe38080 (2145616000)
name             "pci"

/proc/device-tree/pxp@0,e0000000/i2c@1c:
assigned-addresses 8100e010 00000000 007f0200 00000000 00000040
device_type      "i2c"
revision-id      00000001
class-code       000c0500 (787712)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000046 00000001
device-id        0000a003 (40963)
reg              0000e000 00000000 00000000 00000000 00000000
		 0100e010 00000000 00000000 00000000 00000040
linux,phandle    7fe334a0 (2145596576)
name             "i2c"

/proc/device-tree/pxp@0,e0000000/cache-controller@1:
compatible       "pasemi,1682m-l2c"
		 "pasemi,l2c"
device_type      "cache-controller"
revision-id      00000011 (17)
class-code       00058000 (360448)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000052 00000001
device-id        0000a009 (40969)
reg              00000800 00000000 00000000 00000000 00000000
linux,phandle    7fe32bc8 (2145594312)
name             "cache-controller"

/proc/device-tree/pxp@0,e0000000/pci@11:
device_type      "pci"
revision-id      00000011 (17)
class-code       00060400 (394240)
ranges           01000000 00000000 00000000 01000000
		 00000000 00000000 00000000 00004000
		 02000000 00000000 a0100000 02000000
		 00000000 a0100000 00000000 00300000
vendor-id        00001959 (6489)
#interrupt-cells 00000001
bus-range        00000005 00000006
#address-cells   00000003
#size-cells      00000002
device-id        0000a002 (40962)
reg              00008800 00000000 00000000 00000000 00000000
linux,phandle    7fe37020 (2145611808)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@14,1:
assigned-addresses 8105a110 00000000 00001030 00000000 00000008
		 8105a114 00000000 00001054 00000000 00000004
		 8105a118 00000000 00001038 00000000 00000008
		 8105a11c 00000000 00001050 00000000 00000004
		 8105a120 00000000 00001000 00000000 00000010
device_type      "pci"
revision-id      00000000
class-code       00010183 (65923)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       00000009 00000001
device-id        0000438c (17292)
reg              0005a100 00000000 00000000 00000000 00000000 0105a110
		 00000000 00000000 00000000 00000008 0105a114 00000000
		 00000000 00000000 00000004 0105a118 00000000 00000000
		 00000000 00000008 0105a11c 00000000 00000000 00000000
		 00000004 0105a120 00000000 00000000 00000000 00000010
linux,phandle    7fe3bfb0 (2145632176)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@13,5:
assigned-addresses 82059d10 00000000 a0209800 00000000 00000100
device_type      "pci"
revision-id      00000000
class-code       000c0320 (787232)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       0000000c 00000001
device-id        00004386 (17286)
reg              00059d00 00000000 00000000 00000000 00000000
		 02059d10 00000000 00000000 00000000 00000100
linux,phandle    7fe3b858 (2145630296)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@13,3:
assigned-addresses 82059b10 00000000 a0204000 00000000 00001000
device_type      "pci"
revision-id      00000000
class-code       000c0310 (787216)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       0000000a 00000001
device-id        0000438a (17290)
reg              00059b00 00000000 00000000 00000000 00000000
		 02059b10 00000000 00000000 00000000 00001000
linux,phandle    7fe3b078 (2145628280)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@14:
assigned-addresses 8105a010 00000000 00001020 00000000 00000010
		 8205a014 00000000 a0209000 00000000 00000400
device_type      "pci"
revision-id      00000014 (20)
class-code       000c0500 (787712)
vendor-id        00001002 (4098)
device-id        00004385 (17285)
reg              0005a000 00000000 00000000 00000000 00000000
		 0105a010 00000000 00000000 00000000 00000010
		 0205a014 00000000 00000000 00000000 00000400
linux,phandle    7fe3bc48 (2145631304)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@13,1:
assigned-addresses 82059910 00000000 a0207000 00000000 00001000
device_type      "pci"
revision-id      00000000
class-code       000c0310 (787216)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       0000000a 00000001
device-id        00004388 (17288)
reg              00059900 00000000 00000000 00000000 00000000
		 02059910 00000000 00000000 00000000 00001000
linux,phandle    7fe3a898 (2145626264)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@12:
assigned-addresses 81059010 00000000 00001040 00000000 00000008 81059014
		 00000000 0000105c 00000000 00000004 81059018 00000000
		 00001048 00000000 00000008 8105901c 00000000 00001058
		 00000000 00000004 81059020 00000000 00001010 00000000
		 00000010 82059024 00000000 a0209400 00000000 00000400
device_type      "pci"
revision-id      00000000
class-code       0001018f (65935)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       00000009 00000001
device-id        00004380 (17280)
reg              00059000 00000000 00000000 00000000
		 00000000 01059010 00000000 00000000
		 00000000 00000008 01059014 00000000
		 00000000 00000000 00000004 01059018
		 00000000 00000000 00000000 00000008
		 0105901c 00000000 00000000 00000000
		 00000004 01059020 00000000 00000000
		 00000000 00000010 02059024 00000000
		 [140 bytes total]
linux,phandle    7fe39de8 (2145623528)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@12/ide0.0:
device_type      "block"
linux,phandle    7fe3a2a0 (2145624736)
name             "ide0.0"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@12/atapi0.1:
device_type      "block"
linux,phandle    7fe3a3a0 (2145624992)
name             "atapi0.1"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@14,4:
device_type      "pci"
revision-id      00000000
class-code       00060400 (394240)
ranges           01000000 00000000 00003000 01000000
		 00000000 00003000 00000000 00001000
		 02000000 00000000 a0300000 02000000
		 00000000 a0300000 00000000 00100000
vendor-id        00001002 (4098)
#interrupt-cells 00000001
bus-range        00000006 00000006
#address-cells   00000003
#size-cells      00000002
device-id        00004384 (17284)
reg              0005a400 00000000 00000000 00000000 00000000
linux,phandle    7fe3cc20 (2145635360)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@14,4/pci@5:
assigned-addresses 81062810 00000000 00003000 00000000 00000100
		 82062814 00000000 a0310000 00000000 00000100
device_type      "pci"
revision-id      00000010 (16)
subsystem-id     00008139 (33081)
class-code       00020000 (131072)
vendor-id        000010ec (4332)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       00000004 00000001
device-id        00008139 (33081)
reg              00062800 00000000 00000000 00000000 00000000
		 01062810 00000000 00000000 00000000 00000100
		 02062814 00000000 00000000 00000000 00000100
subsystem-vendor-id 000010ec (4332)
linux,phandle    7fe3d0d8 (2145636568)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@14,2:
assigned-addresses 8205a210 00000000 a0200000 00000000 00004000
device_type      "pci"
revision-id      00000000
subsystem-id     00001000 (4096)
class-code       00040300 (262912)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       00000009 00000001
device-id        00004383 (17283)
reg              0005a200 00000000 00000000 00000000 00000000
		 0205a210 00000000 00000000 00000000 00004000
subsystem-vendor-id 00001888 (6280)
linux,phandle    7fe3c440 (2145633344)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@13,4:
assigned-addresses 82059c10 00000000 a0205000 00000000 00001000
device_type      "pci"
revision-id      00000000
class-code       000c0310 (787216)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       0000000b 00000001
device-id        0000438b (17291)
reg              00059c00 00000000 00000000 00000000 00000000
		 02059c10 00000000 00000000 00000000 00001000
linux,phandle    7fe3b468 (2145629288)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@13,2:
assigned-addresses 82059a10 00000000 a0206000 00000000 00001000
device_type      "pci"
revision-id      00000000
class-code       000c0310 (787216)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       0000000b 00000001
device-id        00004389 (17289)
reg              00059a00 00000000 00000000 00000000 00000000
		 02059a10 00000000 00000000 00000000 00001000
linux,phandle    7fe3ac88 (2145627272)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@13:
assigned-addresses 82059810 00000000 a0208000 00000000 00001000
device_type      "pci"
revision-id      00000000
class-code       000c0310 (787216)
vendor-id        00001002 (4098)
interrupt-parent 7fe2ffa8 (2145583016)
interrupts       00000009 00000001
device-id        00004387 (17287)
reg              00059800 00000000 00000000 00000000 00000000
		 02059810 00000000 00000000 00000000 00001000
linux,phandle    7fe3a4a8 (2145625256)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11/pci@14,3:
assigned-addresses 8205a310 00000000 a0100000 00000000 00100000
device_type      "pci"
revision-id      00000000
class-code       00060100 (393472)
vendor-id        00001002 (4098)
device-id        0000438d (17293)
reg              0005a300 00000000 00000000 00000000 00000000
		 0205a310 00000000 00000000 00000000 00100000
linux,phandle    7fe3c8e0 (2145634528)
name             "pci"

/proc/device-tree/pxp@0,e0000000/pci@11,1:
device_type      "pci"
revision-id      00000011 (17)
class-code       00060400 (394240)
vendor-id        00001959 (6489)
#interrupt-cells 00000001
bus-range        00000007 00000007
#address-cells   00000003
#size-cells      00000002
device-id        0000a002 (40962)
reg              00008900 00000000 00000000 00000000 00000000
linux,phandle    7fe36bf8 (2145610744)
name             "pci"

/proc/device-tree/pxp@0,e0000000/serial@1d:
current-speed    0001c200 (115200)
compatible       "ns16550"
		 "pciclass,0700"
assigned-addresses 8100e810 00000000 007f03f8 00000000 00000008
device_type      "serial"
revision-id      00000002
class-code       00070003 (458755)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000049 00000001
device-id        0000a004 (40964)
reg              0000e800 00000000 00000000 00000000 00000000
		 0100e810 00000000 00000000 00000000 00000008
clock-frequency  07f28155 (133333333)
linux,phandle    7fe318a8 (2145589416)
name             "serial"

/proc/device-tree/pxp@0,e0000000/ethernet@14,3:
phy-handle       7fe3d860 (2145638496)
compatible       "pasemi,1682m-gmac"
		 "pasemi,ethernet"
assigned-addresses 82000000 00000000 e00a3000 00000000 00001000
local-mac-address 02 00 ffffffe0 0a 30 00                              ....0.
device_type      "ethernet"
revision-id      00000011 (17)
class-code       00020000 (131072)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000043 00000001
device-id        0000a005 (40965)
reg              0000a300 00000000 00000000 00000000 00000000
		 82000000 00000000 e00a3000 00000000 00001000
linux,phandle    7fe32fd0 (2145595344)
name             "ethernet"

/proc/device-tree/pxp@0,e0000000/pci@3:
device_type      "pci"
revision-id      00000013 (19)
class-code       00080080 (524416)
vendor-id        00001959 (6489)
interrupt-parent 7fe2f6e8 (2145580776)
interrupts       00000054 00000001
device-id        0000a00c (40972)
reg              00001800 00000000 00000000 00000000 00000000
linux,phandle    7fe37990 (2145614224)
name             "pci"

/proc/device-tree/lpc@fe000000:
device_type      "lpc"
ranges           fe000000 00000000 fe000000 02000000
#address-cells   00000001
#size-cells      00000001
reg              00000000 fe000000 00000000 02000000
linux,phandle    7fe34070 (2145599600)
name             "lpc"

/proc/device-tree/bootconsole:
device_type      "bootconsole"
linux,phandle    7fe35880 (2145605760)
name             "bootconsole"

/proc/device-tree/cpus:
#address-cells   00000001
#size-cells      00000000
linux,phandle    7fe30540 (2145584448)
name             "cpus"

/proc/device-tree/cpus/PowerPC,PA6T@0:
bus-frequency    35a4e900 (900000000)
64-bit          
timebase-frequency 03f940aa (66666666)
graphics        
device_type      "cpu"
ibm,segment-page-sizes 0000000c 00000000 00000001 0000000c
		 00000000 0000000e 00000020 00000001
		 0000000e 00000001 00000010 00000110
		 00000001 00000010 00000003 00000012
		 00000130 00000001 00000012 0000000f
		 00000014 00000030 00000001 00000014
		 0000001f 00000018 00000100 00000001
		 00000018 00000000 0000001e 00000120
		 [140 bytes total]
i-cache-line-size 00000040 (64)
cpu-version      00900102 (9437442)
i-cache-block-size 00000040 (64)
reg              00000000
d-cache-block-size 00000040 (64)
clock-frequency  6b49d200 (1800000000)
ibm,processor-segment-sizes 0000001c 00000028
linux,phandle    7fe30698 (2145584792)
d-cache-size     00010000 (65536)
i-cache-size     00010000 (65536)
general-purpose 
name             "PowerPC,PA6T"
ibm,processor-page-sizes 0000000c 0000000e 00000010 00000012
		 00000014 00000018 0000001e
d-cache-sets     00000002
i-cache-sets     00000002
d-cache-line-size 00000040 (64)

/proc/device-tree/cpus/PowerPC,PA6T@1:
bus-frequency    35a4e900 (900000000)
64-bit          
timebase-frequency 03f940aa (66666666)
graphics        
device_type      "cpu"
ibm,segment-page-sizes 0000000c 00000000 00000001 0000000c
		 00000000 0000000e 00000020 00000001
		 0000000e 00000001 00000010 00000110
		 00000001 00000010 00000003 00000012
		 00000130 00000001 00000012 0000000f
		 00000014 00000030 00000001 00000014
		 0000001f 00000018 00000100 00000001
		 00000018 00000000 0000001e 00000120
		 [140 bytes total]
i-cache-line-size 00000040 (64)
cpu-version      00900102 (9437442)
i-cache-block-size 00000040 (64)
reg              00000001
d-cache-block-size 00000040 (64)
clock-frequency  6b49d200 (1800000000)
ibm,processor-segment-sizes 0000001c 00000028
linux,phandle    7fe30eb0 (2145586864)
d-cache-size     00010000 (65536)
i-cache-size     00010000 (65536)
general-purpose 
name             "PowerPC,PA6T"
ibm,processor-page-sizes 0000000c 0000000e 00000010 00000012
		 00000014 00000018 0000001e
d-cache-sets     00000002
i-cache-sets     00000002
d-cache-line-size 00000040 (64)

^ permalink raw reply

* Re: [PATCH] powerpc/mm: Simplify _PAGE_RO handling in page table dump
From: Christophe LEROY @ 2017-12-22 12:11 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20170509141626.F30E767954@pc13941vm.idsi0.si.c-s.fr>

Ping ?

Le 09/05/2017 à 16:16, Christophe Leroy a écrit :
> Commit fd893fe56a130 ("powerpc/mm: Fix missing page attributes in
> page table dump") added support of _PAGE_RO attribute.
> 
> This patch makes it more simple
> 
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> ---
>   arch/powerpc/mm/dump_linuxpagetables.c | 7 +------
>   1 file changed, 1 insertion(+), 6 deletions(-)
> 
> diff --git a/arch/powerpc/mm/dump_linuxpagetables.c b/arch/powerpc/mm/dump_linuxpagetables.c
> index d659345a98d6..eeef51107cff 100644
> --- a/arch/powerpc/mm/dump_linuxpagetables.c
> +++ b/arch/powerpc/mm/dump_linuxpagetables.c
> @@ -121,13 +121,8 @@ static const struct flag_info flag_array[] = {
>   		.set	= "user",
>   		.clear	= "    ",
>   	}, {
> -#if _PAGE_RO == 0
> -		.mask	= _PAGE_RW,
> +		.mask	= _PAGE_RW | _PAGE_RO,
>   		.val	= _PAGE_RW,
> -#else
> -		.mask	= _PAGE_RO,
> -		.val	= 0,
> -#endif
>   		.set	= "rw",
>   		.clear	= "ro",
>   	}, {
> 

^ permalink raw reply

* Re: [PATCH v5] powerpc/mm: Only read faulting instruction when necessary in do_page_fault()
From: Christophe LEROY @ 2017-12-22 12:10 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	Scott Wood
  Cc: linuxppc-dev, linux-kernel
In-Reply-To: <20170808070859.A3F3A653E4@po15668-vm-win7.idsi0.si.c-s.fr>

Hi Michael,

Did you have a chance to have a look ?

Christophe

Le 08/08/2017 à 09:08, Christophe Leroy a écrit :
> Commit a7a9dcd882a67 ("powerpc: Avoid taking a data miss on every
> userspace instruction miss") has shown that limiting the read of
> faulting instruction to likely cases improves performance.
> 
> This patch goes further into this direction by limiting the read
> of the faulting instruction to the only cases where it is definitly
> needed.
> 
> On an MPC885, with the same benchmark app as in the commit referred
> above, we see a reduction of 4000 dTLB misses (approx 3%):
> 
> Before the patch:
>   Performance counter stats for './fault 500' (10 runs):
> 
>           720495838      cpu-cycles		( +-  0.04% )
>              141769      dTLB-load-misses	( +-  0.02% )
>               52722      iTLB-load-misses	( +-  0.01% )
>               19611      faults			( +-  0.02% )
> 
>         5.750535176 seconds time elapsed		( +-  0.16% )
> 
> With the patch:
>   Performance counter stats for './fault 500' (10 runs):
> 
>           717669123      cpu-cycles		( +-  0.02% )
>              137344      dTLB-load-misses	( +-  0.03% )
>               52731      iTLB-load-misses	( +-  0.01% )
>               19614      faults			( +-  0.03% )
> 
>         5.728423115 seconds time elapsed		( +-  0.14% )
> 
> The proper work of the huge stack expansion was tested with the
> following app:
> 
> #include <stdlib.h>
> #include <stdio.h>
> 
> int main(int argc, char **argv)
> {
> 	char buf[1024 * 1025];
> 
> 	sprintf(buf, "Hello world !\n");
> 	printf(buf);
> 
> 	exit(0);
> }
> 
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> ---
>   I'm wondering if it really worth it to do something so complex. Is there really a chance that the
>   get_user() faults ? It would mean that an instruction that as just been executed has been in the
>   meantime swapped out. Is that really a possibility ? I'd expect not, which would mean that we
>   could limit it to __get_user_inatomic() and then not implement this complex unlocking and retry stuff.
> 
>   v5: Reworked to fit after Benh do_fault improvement and rebased on top of powerpc/merge (65152902e43fef)
> 
>   v4: Rebased on top of powerpc/next (f718d426d7e42e) and doing access_ok() verification before __get_user_xxx()
> 
>   v3: Do a first try with pagefault disabled before releasing the semaphore
> 
>   v2: Changes 'if (cond1) if (cond2)' by 'if (cond1 && cond2)'
> 
>   arch/powerpc/mm/fault.c | 90 +++++++++++++++++++++++++++++++++++--------------
>   1 file changed, 65 insertions(+), 25 deletions(-)
> 
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index f88fac3d281b..7a218f69f956 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -68,26 +68,58 @@ static inline bool notify_page_fault(struct pt_regs *regs)
>   /*
>    * Check whether the instruction at regs->nip is a store using
>    * an update addressing form which will update r1.
> + * If no, returns STACK_EXPANSION_BAD
> + * If yes, returns STACK_EXPANSION_GOOD
> + * In addition, the result is ored with STACK_EXPANSION_UNLOCKED if the
> + * semaphore has been released
>    */
> -static bool store_updates_sp(struct pt_regs *regs)
> +
> +#define STACK_EXPANSION_BAD		0
> +#define STACK_EXPANSION_GOOD		1
> +#define STACK_EXPANSION_LOCKED		0
> +#define STACK_EXPANSION_UNLOCKED	2
> +
> +int store_updates_sp(struct pt_regs *regs)
>   {
>   	unsigned int inst;
> +	unsigned int __user *nip = (unsigned int __user *)regs->nip;
> +	int ret;
> +	int sema = STACK_EXPANSION_LOCKED;
> +
> +	/*
> +	 * We want to do this outside mmap_sem, because reading code around nip
> +	 * can result in fault, which will cause a deadlock when called with
> +	 * mmap_sem held. However, we do a first try with pagefault disabled as
> +	 * a fault here is very unlikely.
> +	 */
> +	if (!access_ok(VERIFY_READ, nip, sizeof(inst)))
> +		return STACK_EXPANSION_BAD | STACK_EXPANSION_LOCKED;
> +
> +	pagefault_disable();
> +	ret = __get_user_inatomic(inst, nip);
> +	pagefault_enable();
> +	if (ret) {
> +		up_read(&current->mm->mmap_sem);
> +		sema = STACK_EXPANSION_UNLOCKED;
> +		if (__get_user(inst, nip))
> +			return STACK_EXPANSION_BAD | STACK_EXPANSION_UNLOCKED;
> +	}
>   
> -	if (get_user(inst, (unsigned int __user *)regs->nip))
> -		return false;
>   	/* check for 1 in the rA field */
>   	if (((inst >> 16) & 0x1f) != 1)
> -		return false;
> +		return STACK_EXPANSION_BAD | sema;
> +
>   	/* check major opcode */
>   	switch (inst >> 26) {
> +	case 62:	/* std or stdu */
> +		if ((inst & 3) == 0)
> +			break;
>   	case 37:	/* stwu */
>   	case 39:	/* stbu */
>   	case 45:	/* sthu */
>   	case 53:	/* stfsu */
>   	case 55:	/* stfdu */
> -		return true;
> -	case 62:	/* std or stdu */
> -		return (inst & 3) == 1;
> +		return STACK_EXPANSION_GOOD | sema;
>   	case 31:
>   		/* check minor opcode */
>   		switch ((inst >> 1) & 0x3ff) {
> @@ -97,10 +129,10 @@ static bool store_updates_sp(struct pt_regs *regs)
>   		case 439:	/* sthux */
>   		case 695:	/* stfsux */
>   		case 759:	/* stfdux */
> -			return true;
> +			return STACK_EXPANSION_GOOD | sema;
>   		}
>   	}
> -	return false;
> +	return STACK_EXPANSION_BAD | sema;
>   }
>   /*
>    * do_page_fault error handling helpers
> @@ -220,9 +252,9 @@ static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
>   	return is_exec || (address >= TASK_SIZE);
>   }
>   
> -static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
> -				struct vm_area_struct *vma,
> -				bool store_update_sp)
> +int query_stack_expansion(struct pt_regs *regs, unsigned long address,
> +			  struct vm_area_struct *vma, bool store_update_sp,
> +			  unsigned int flags)
>   {
>   	/*
>   	 * N.B. The POWER/Open ABI allows programs to access up to
> @@ -237,7 +269,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
>   		/* get user regs even if this fault is in kernel mode */
>   		struct pt_regs *uregs = current->thread.regs;
>   		if (uregs == NULL)
> -			return true;
> +			return STACK_EXPANSION_BAD;
>   
>   		/*
>   		 * A user-mode access to an address a long way below
> @@ -251,10 +283,16 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
>   		 * between the last mapped region and the stack will
>   		 * expand the stack rather than segfaulting.
>   		 */
> -		if (address + 2048 < uregs->gpr[1] && !store_update_sp)
> -			return true;
> +		if (address + 2048 < uregs->gpr[1]) {
> +			if (store_update_sp)
> +				return STACK_EXPANSION_GOOD;
> +			if (!(flags & (FAULT_FLAG_USER)) ||
> +			    !(flags & (FAULT_FLAG_WRITE)))
> +				return STACK_EXPANSION_BAD;
> +			return store_updates_sp(regs);
> +		}
>   	}
> -	return false;
> +	return STACK_EXPANSION_GOOD;
>   }
>   
>   static bool access_error(bool is_write, bool is_exec,
> @@ -386,6 +424,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
>   	int is_write = page_fault_is_write(error_code);
>   	int fault, major = 0;
>   	bool store_update_sp = false;
> +	int query;
>   
>   	if (notify_page_fault(regs))
>   		return 0;
> @@ -427,14 +466,6 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
>   
>   	perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
>   
> -	/*
> -	 * We want to do this outside mmap_sem, because reading code around nip
> -	 * can result in fault, which will cause a deadlock when called with
> -	 * mmap_sem held
> -	 */
> -	if (is_write && is_user)
> -		store_update_sp = store_updates_sp(regs);
> -
>   	if (is_user)
>   		flags |= FAULT_FLAG_USER;
>   	if (is_write)
> @@ -481,8 +512,17 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
>   		return bad_area(regs, address);
>   
>   	/* The stack is being expanded, check if it's valid */
> -	if (unlikely(bad_stack_expansion(regs, address, vma, store_update_sp)))
> +	query = query_stack_expansion(regs, address, vma, store_update_sp,
> +				      flags);
> +	if (unlikely(!(query & STACK_EXPANSION_GOOD))) {
> +		if (query & STACK_EXPANSION_UNLOCKED)
> +			return bad_area_nosemaphore(regs, address);
>   		return bad_area(regs, address);
> +	}
> +	if (unlikely(query & STACK_EXPANSION_UNLOCKED)) {
> +		store_update_sp = true;
> +		goto retry;
> +	}
>   
>   	/* Try to expand it */
>   	if (unlikely(expand_stack(vma, address)))
> 

^ permalink raw reply

* Re: [PATCH] KVM: PPC: Book3S: fix XIVE migration of pending interrupts
From: Greg Kurz @ 2017-12-22 11:58 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Paul Mackerras, Laurent Vivier, Cédric Le Goater, kvm-ppc,
	Benjamin Herrenschmidt, linuxppc-dev
In-Reply-To: <87wp1fnh27.fsf@concordia.ellerman.id.au>

On Fri, 22 Dec 2017 22:22:08 +1100
Michael Ellerman <mpe@ellerman.id.au> wrote:

> Paul Mackerras <paulus@ozlabs.org> writes:
>=20
> > On Fri, Dec 22, 2017 at 03:34:20PM +1100, Michael Ellerman wrote: =20
> >> Laurent Vivier <lvivier@redhat.com> writes:
> >>  =20
> >> > On 12/12/2017 13:02, C=C3=A9dric Le Goater wrote: =20
> >> >> When restoring a pending interrupt, we are setting the Q bit to for=
ce
> >> >> a retrigger in xive_finish_unmask(). But we also need to force an E=
OI
> >> >> in this case to reach the same initial state : P=3D1, Q=3D0.
> >> >>=20
> >> >> This can be done by not setting 'old_p' for pending interrupts which
> >> >> will inform xive_finish_unmask() that an EOI needs to be sent.
> >> >>=20
> >> >> Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> >> >> Signed-off-by: C=C3=A9dric Le Goater <clg@kaod.org>
> >> >> ---
> >> >>=20
> >> >>  Tested with a guest running iozone.
> >> >>=20
> >> >>  arch/powerpc/kvm/book3s_xive.c | 4 ++--
> >> >>  1 file changed, 2 insertions(+), 2 deletions(-) =20
> >> >
> >> > We really need this patch to fix VM migration on POWER9.
> >> > When will it be merged? =20
> >>=20
> >> Paul is away, so I'll merge it via the powerpc tree.
> >>=20
> >> I'll mark it:
> >>=20
> >>   Fixes: 5af50993850a ("KVM: PPC: Book3S HV: Native usage of the XIVE =
interrupt controller")
> >>   Cc: stable@vger.kernel.org # v4.12+ =20
> >
> > Thanks for doing that.
> >
> > If you felt like merging Alexey's patch "KVM: PPC: Book3S PR: Fix WIMG
> > handling under pHyp" with my acked-by, that would be fine too.  The
> > commit message needs a little work - the reason for using HPTE_R_M is
> > not just because it seems to work, but because current POWER
> > processors require M set on mappings for normal pages, and pHyp
> > enforces that. =20
>=20
> OK. I saw this too late, but I'll pick that one up next week. If someone
> sends me an updated change log I will merge all of their patches for
> ever.
>=20

Really ? Opportunity makes the thief, so here's my take :P

8<---------------------------------------------------------------------->8
KVM: PPC: Book3S: fix XIVE migration of pending interrupts

96df226 "KVM: PPC: Book3S PR: Preserve storage control bits" added WIMG
bits preserving but it missed 2 special cases:
- a magic page in kvmppc_mmu_book3s_64_xlate() and
- guest real mode in kvmppc_handle_pagefault().

For these ptes WIMG were 0 and pHyp failed on these causing a guest to
stop in the very beginning at NIP=3D0x100 (due to bd9166ffe
"KVM: PPC: Book3S PR: Exit KVM on failed mapping").

According to LoPAPR v1.1 14.5.4.1.2 H_ENTER:

 The hypervisor checks that the WIMG bits within the PTE are appropriate
 for the physical page number else H_Parameter return. (For System Memory
 pages WIMG=3D0010, or, 1110 if the SAO option is enabled, and for IO pages
 WIMG=3D01**.)

This hence initializes WIMG to non-zero value HPTE_R_M (0x10), as expected
by pHyp.

Fixes: 96df226 "KVM: PPC: Book3S PR: Preserve storage control bits"
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
8<---------------------------------------------------------------------->8

Cheers,

--
Greg

> cheers
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: WARNING: CPU: 0 PID: 2777 at arch/powerpc/mm/hugetlbpage.c:354 h,ugetlb_free_pgd_range+0xc8/0x1e4
From: Christophe LEROY @ 2017-12-22 12:03 UTC (permalink / raw)
  To: Aneesh Kumar K.V, linuxppc-dev@lists.ozlabs.org, Michael Ellerman
In-Reply-To: <752a6444-dc65-88e0-343f-d3361ec042cc@c-s.fr>



Le 22/12/2017 à 10:32, Christophe LEROY a écrit :
> 
> 
> Le 20/12/2017 à 13:17, Christophe LEROY a écrit :
>> Trying to malloc() with libhugetlbfs, it runs indefinitly doing page 
>> faults in do_page_fault()/hugetlb_fault().
>> When interrupting the blocked app with CTRL+C, I get the following 
>> WARNING:
>>
>> Any idea of what can be wrong ? I'm on a 8xx with 512k huge pages.
> 
> 
> It looks like something goes wrong when the app tries to mmap a 
> hugetlbpage at a given address.
> When it requests the page with a NULL address, it works well.
> 
> Any idea ?

Now I have found the reason:

I have something allocated

10000000-10001000 r-xp 00000000 00:0f 2597       /root/malloc
10010000-10011000 rwxp 00000000 00:0f 2597       /root/malloc

And mmap() accepts the hint, which is in the same PMD which is not a 
huge PMD:

mmap(0x10080000, 524288, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS|0x40000, -1, 0) = 0x10080000

Apparently, hugetlb_get_unmapped_area() doesn't care about that.

What should we do to handle it ? Have our own 
hugetlb_get_unmapped_area(), which does all the same, checking this in 
addition ?

Christophe

> 
> Christophe
> 
>>
>> [162980.035629] WARNING: CPU: 0 PID: 2777 at 
>> arch/powerpc/mm/hugetlbpage.c:354 h
>> ugetlb_free_pgd_range+0xc8/0x1e4
>> [162980.035699] CPU: 0 PID: 2777 Comm: malloc Tainted: G W       4.14.6-s
>> 3k-dev-ga8e8e8b176-svn9134 #85
>> [162980.035744] task: c67e2c00 task.stack: c668e000
>> [162980.035783] NIP:  c000fe18 LR: c00e1eec CTR: c00f90c0
>> [162980.035830] REGS: c668fc20 TRAP: 0700   Tainted: G W        (4.14.6-s
>> 3k-dev-ga8e8e8b176-svn9134)
>> [162980.035854] MSR:  00029032 <EE,ME,IR,DR,RI>  CR: 24044224 XER: 
>> 20000000
>> [162980.036003]
>> [162980.036003] GPR00: c00e1eec c668fcd0 c67e2c00 00000010 c6869410 
>> 10080000 000
>> 00000 77fb4000
>> [162980.036003] GPR08: ffff0001 0683c001 00000000 ffffff80 44028228 
>> 10018a34 000
>> 04008 418004fc
>> [162980.036003] GPR16: c668e000 00040100 c668e000 c06c0000 c668fe78 
>> c668e000 c68
>> 35ba0 c668fd48
>> [162980.036003] GPR24: 00000000 73ffffff 74000000 00000001 77fb4000 
>> 100fffff 101
>> 00000 10100000
>> [162980.036743] NIP [c000fe18] hugetlb_free_pgd_range+0xc8/0x1e4
>> [162980.036839] LR [c00e1eec] free_pgtables+0x12c/0x150
>> [162980.036861] Call Trace:
>> [162980.036939] [c668fcd0] [c00f0774] unlink_anon_vmas+0x1c4/0x214 
>> (unreliable)
>> [162980.037040] [c668fd10] [c00e1eec] free_pgtables+0x12c/0x150
>> [162980.037118] [c668fd40] [c00eabac] exit_mmap+0xe8/0x1b4
>> [162980.037210] [c668fda0] [c0019710] mmput.part.9+0x20/0xd8
>> [162980.037301] [c668fdb0] [c001ecb0] do_exit+0x1f0/0x93c
>> [162980.037386] [c668fe00] [c001f478] do_group_exit+0x40/0xcc
>> [162980.037479] [c668fe10] [c002a76c] get_signal+0x47c/0x614
>> [162980.037570] [c668fe70] [c0007840] do_signal+0x54/0x244
>> [162980.037654] [c668ff30] [c0007ae8] do_notify_resume+0x34/0x88
>> [162980.037744] [c668ff40] [c000dae8] do_user_signal+0x74/0xc4
>> [162980.037781] Instruction dump:
>> [162980.037821] 7fdff378 81370000 54a3463a 80890020 7d24182e 7c841a14 
>> 712a0004 4
>> 082ff94
>> [162980.038014] 2f890000 419e0010 712a0ff0 408200e0 <0fe00000> 
>> 54a9000a 7f984840
>>   419d0094
>> [162980.038216] ---[ end trace c0ceeca8e7a5800a ]---
>> [162980.038754] BUG: non-zero nr_ptes on freeing mm: 1
>> [162985.363322] BUG: non-zero nr_ptes on freeing mm: -1
>>
>> Christophe

^ permalink raw reply

* Re: KVM: PPC: Book3S HV: Fix pending_pri value in kvmppc_xive_get_icp()
From: Michael Ellerman @ 2017-12-22 11:24 UTC (permalink / raw)
  To: Laurent Vivier, kvm-ppc; +Cc: linux-kernel, Cédric Le Goater, linuxppc-dev
In-Reply-To: <20171212172356.2397-1-lvivier@redhat.com>

On Tue, 2017-12-12 at 17:23:56 UTC, Laurent Vivier wrote:
> When we migrate a VM from a POWER8 host (XICS) to a POWER9 host
> (XICS-on-XIVE), we have an error:
> 
> qemu-kvm: Unable to restore KVM interrupt controller state \
>           (0xff000000) for CPU 0: Invalid argument
> 
> This is because kvmppc_xics_set_icp() checks the new state
> is internaly consistent, and especially:
> 
> ...
>    1129         if (xisr == 0) {
>    1130                 if (pending_pri != 0xff)
>    1131                         return -EINVAL;
> ...
> 
> On the other side, kvmppc_xive_get_icp() doesn't set
> neither the pending_pri value, nor the xisr value (set to 0)
> (and kvmppc_xive_set_icp() ignores the pending_pri value)
> 
> As xisr is 0, pending_pri must be set to 0xff.
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Applied to powerpc fixes, thanks.

https://git.kernel.org/powerpc/c/7333b5aca412d6ad02667b5a513485

cheers

^ permalink raw reply

* Re: KVM: PPC: Book3S: fix XIVE migration of pending interrupts
From: Michael Ellerman @ 2017-12-22 11:24 UTC (permalink / raw)
  To: Cédric Le Goater, kvm-ppc, Paul Mackerras,
	Benjamin Herrenschmidt
  Cc: linuxppc-dev, Cédric Le Goater
In-Reply-To: <20171212120204.6799-1-clg@kaod.org>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 746 bytes --]

On Tue, 2017-12-12 at 12:02:04 UTC, =?utf-8?q?C=C3=A9dric_Le_Goater?= wrote:
> When restoring a pending interrupt, we are setting the Q bit to force
> a retrigger in xive_finish_unmask(). But we also need to force an EOI
> in this case to reach the same initial state : P=1, Q=0.
> 
> This can be done by not setting 'old_p' for pending interrupts which
> will inform xive_finish_unmask() that an EOI needs to be sent.
> 
> Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> Reviewed-by: Laurent Vivier <lvivier@redhat.com>
> Tested-by: Laurent Vivier <lvivier@redhat.com>

Applied to powerpc fixes, thanks.

https://git.kernel.org/powerpc/c/dc1c4165d189350cb51bdd3057deb6

cheers

^ permalink raw reply

* Re: [PATCH] KVM: PPC: Book3S: fix XIVE migration of pending interrupts
From: Michael Ellerman @ 2017-12-22 11:22 UTC (permalink / raw)
  To: Laurent Vivier, Paul Mackerras
  Cc: Cédric Le Goater, kvm-ppc, Benjamin Herrenschmidt,
	linuxppc-dev
In-Reply-To: <f7e4d221-aa4a-5166-62f7-b0eec735cb57@redhat.com>

Laurent Vivier <lvivier@redhat.com> writes:

> On 22/12/2017 08:54, Paul Mackerras wrote:
>> On Fri, Dec 22, 2017 at 03:34:20PM +1100, Michael Ellerman wrote:
>>> Laurent Vivier <lvivier@redhat.com> writes:
>>>
>>>> On 12/12/2017 13:02, C=C3=A9dric Le Goater wrote:
>>>>> When restoring a pending interrupt, we are setting the Q bit to force
>>>>> a retrigger in xive_finish_unmask(). But we also need to force an EOI
>>>>> in this case to reach the same initial state : P=3D1, Q=3D0.
>>>>>
>>>>> This can be done by not setting 'old_p' for pending interrupts which
>>>>> will inform xive_finish_unmask() that an EOI needs to be sent.
>>>>>
>>>>> Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>>>> Signed-off-by: C=C3=A9dric Le Goater <clg@kaod.org>
>>>>> ---
>>>>>
>>>>>  Tested with a guest running iozone.
>>>>>
>>>>>  arch/powerpc/kvm/book3s_xive.c | 4 ++--
>>>>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>>>
>>>> We really need this patch to fix VM migration on POWER9.
>>>> When will it be merged?
>>>
>>> Paul is away, so I'll merge it via the powerpc tree.
>>>
>>> I'll mark it:
>>>
>>>   Fixes: 5af50993850a ("KVM: PPC: Book3S HV: Native usage of the XIVE i=
nterrupt controller")
>>>   Cc: stable@vger.kernel.org # v4.12+
>>=20
>> Thanks for doing that.
>>=20
>> If you felt like merging Alexey's patch "KVM: PPC: Book3S PR: Fix WIMG
>> handling under pHyp" with my acked-by, that would be fine too.  The
>> commit message needs a little work - the reason for using HPTE_R_M is
>> not just because it seems to work, but because current POWER
>> processors require M set on mappings for normal pages, and pHyp
>> enforces that.
>
> We also need:
>
> KVM: PPC: Book3S HV: Fix pending_pri value in kvmppc_xive_get_icp()

I've merged that one.

cheers

^ permalink raw reply

* Re: [PATCH] KVM: PPC: Book3S: fix XIVE migration of pending interrupts
From: Michael Ellerman @ 2017-12-22 11:22 UTC (permalink / raw)
  To: Paul Mackerras
  Cc: Laurent Vivier, Cédric Le Goater, kvm-ppc,
	Benjamin Herrenschmidt, linuxppc-dev
In-Reply-To: <20171222075430.GB6945@fergus.ozlabs.ibm.com>

Paul Mackerras <paulus@ozlabs.org> writes:

> On Fri, Dec 22, 2017 at 03:34:20PM +1100, Michael Ellerman wrote:
>> Laurent Vivier <lvivier@redhat.com> writes:
>>=20
>> > On 12/12/2017 13:02, C=C3=A9dric Le Goater wrote:
>> >> When restoring a pending interrupt, we are setting the Q bit to force
>> >> a retrigger in xive_finish_unmask(). But we also need to force an EOI
>> >> in this case to reach the same initial state : P=3D1, Q=3D0.
>> >>=20
>> >> This can be done by not setting 'old_p' for pending interrupts which
>> >> will inform xive_finish_unmask() that an EOI needs to be sent.
>> >>=20
>> >> Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>> >> Signed-off-by: C=C3=A9dric Le Goater <clg@kaod.org>
>> >> ---
>> >>=20
>> >>  Tested with a guest running iozone.
>> >>=20
>> >>  arch/powerpc/kvm/book3s_xive.c | 4 ++--
>> >>  1 file changed, 2 insertions(+), 2 deletions(-)
>> >
>> > We really need this patch to fix VM migration on POWER9.
>> > When will it be merged?
>>=20
>> Paul is away, so I'll merge it via the powerpc tree.
>>=20
>> I'll mark it:
>>=20
>>   Fixes: 5af50993850a ("KVM: PPC: Book3S HV: Native usage of the XIVE in=
terrupt controller")
>>   Cc: stable@vger.kernel.org # v4.12+
>
> Thanks for doing that.
>
> If you felt like merging Alexey's patch "KVM: PPC: Book3S PR: Fix WIMG
> handling under pHyp" with my acked-by, that would be fine too.  The
> commit message needs a little work - the reason for using HPTE_R_M is
> not just because it seems to work, but because current POWER
> processors require M set on mappings for normal pages, and pHyp
> enforces that.

OK. I saw this too late, but I'll pick that one up next week. If someone
sends me an updated change log I will merge all of their patches for
ever.

cheers

^ permalink raw reply

* Re: [PATCH] SB600 for the Nemo board has non-zero devices on non-root bus
From: Michael Ellerman @ 2017-12-22 11:19 UTC (permalink / raw)
  To: Christian Zigotzky, Bjorn Helgaas, Darren Stevens,
	linux-pci@vger.kernel.org, Bjorn Helgaas, Olof Johansson,
	linuxppc-dev
In-Reply-To: <af18fb51-a0bc-68e2-7594-5583e3090f98@xenosoft.de>

Christian Zigotzky <chzigotzky@xenosoft.de> writes:

> Hi Bjorn,
>
> Sorry I'm bothering you again. Is this small out of tree init routine in=
=20
> the Nemo patch? I haven't get an answer from Darren yet and I didn't=20
> found the small out of tree init routine in the Nemo patch. Please find=20
> attached the Nemo patch. Maybe you can find this small out of tree init=20
> routine.
>
> What do you think of this following code?
>
> if (sb600_bus =3D=3D -1)
> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 {
> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 busp =3D pci_find_bus(0, 0);
> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 pa_pxp_read_config(busp, PCI_DEVFN(17,0),=20
> PCI_SECONDARY_BUS, 1, &val);
> +
> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 sb600_bus =3D val;
> +
> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 printk(KERN_CRIT "NEMO SB600 on bus %d.\n",sb600_bus);
> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }

I suspect Darren was referring to all of sb600_set_flag().

What we'd really like is to be able to do something like:

void __init pas_pci_init(void)
{
	...

	if (of_find_compatible_node(NULL, NULL, "nemo-something"))
		pci_set_flag(PCI_SCAN_ALL_PCIE_DEVS).


But I don't know if there's anything in the NEMO device tree that we can
use to uniquely identify those machines? ie. the "nemo-something" string.

Can you attach the output of `lsprop /proc/device-tree` ?

cheers

^ permalink raw reply

* [PATCH 9/9] powerpc/64s: Use array of lppaca pointers and allocate lppacas individually
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

Similary to the previous patch, allocate LPPACAs individually.

We no longer allocate lppacas in an array, so this patch removes the 1kB
static alignment for the structure, and enforce the PAPR alignment
requirements at allocation time. We can not reduce the 1kB allocation size
however, due to existing KVM hypervisors.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/lppaca.h      | 24 ++++-----
 arch/powerpc/kernel/machine_kexec_64.c | 15 ++++--
 arch/powerpc/kernel/paca.c             | 89 ++++++++++++----------------------
 arch/powerpc/kvm/book3s_hv.c           |  3 +-
 arch/powerpc/mm/numa.c                 |  4 +-
 arch/powerpc/platforms/pseries/kexec.c |  7 ++-
 6 files changed, 63 insertions(+), 79 deletions(-)

diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index 6e4589eee2da..65d589689f01 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -36,14 +36,16 @@
 #include <asm/mmu.h>
 
 /*
- * We only have to have statically allocated lppaca structs on
- * legacy iSeries, which supports at most 64 cpus.
- */
-#define NR_LPPACAS	1
-
-/*
- * The Hypervisor barfs if the lppaca crosses a page boundary.  A 1k
- * alignment is sufficient to prevent this
+ * The lppaca is the "virtual processor area" registered with the hypervisor,
+ * H_REGISTER_VPA etc.
+ *
+ * According to PAPR, the structure is 640 bytes long, must be L1 cache line
+ * aligned, and must not cross a 4kB boundary. Its size field must be at
+ * least 640 bytes (but may be more).
+ *
+ * Pre-v4.14 KVM hypervisors reject the VPA if its size field is smaller than
+ * 1kB, so we dynamically allocate 1kB and advertise size as 1kB, but keep
+ * this structure as the canonical 640 byte size.
  */
 struct lppaca {
 	/* cacheline 1 contains read-only data */
@@ -97,11 +99,9 @@ struct lppaca {
 
 	__be32	page_ins;		/* CMO Hint - # page ins by OS */
 	u8	reserved11[148];
-	volatile __be64 dtl_idx;		/* Dispatch Trace Log head index */
+	volatile __be64 dtl_idx;	/* Dispatch Trace Log head index */
 	u8	reserved12[96];
-} __attribute__((__aligned__(0x400)));
-
-extern struct lppaca lppaca[];
+} ____cacheline_aligned;
 
 #define lppaca_of(cpu)	(*paca_ptrs[cpu]->lppaca_ptr)
 
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index a250e3331f94..1044bf15d5ed 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -323,17 +323,24 @@ void default_machine_kexec(struct kimage *image)
 	kexec_stack.thread_info.cpu = current_thread_info()->cpu;
 
 	/* We need a static PACA, too; copy this CPU's PACA over and switch to
-	 * it.  Also poison per_cpu_offset to catch anyone using non-static
-	 * data.
+	 * it. Also poison per_cpu_offset and NULL lppaca to catch anyone using
+	 * non-static data.
 	 */
 	memcpy(&kexec_paca, get_paca(), sizeof(struct paca_struct));
 	kexec_paca.data_offset = 0xedeaddeadeeeeeeeUL;
+#ifdef CONFIG_PPC_PSERIES
+	kexec_paca.lppaca_ptr = NULL;
+#endif
 	paca_ptrs[kexec_paca.paca_index] = &kexec_paca;
+
 	setup_paca(&kexec_paca);
 
-	/* XXX: If anyone does 'dynamic lppacas' this will also need to be
-	 * switched to a static version!
+	/*
+	 * The lppaca should be unregistered at this point so the HV won't
+	 * touch it. In the case of a crash, none of the lppacas are
+	 * unregistered so there is not much we can do about it here.
 	 */
+
 	/*
 	 * On Book3S, the copy must happen with the MMU off if we are either
 	 * using Radix page tables or we are not in an LPAR since we can
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index eef4891c9af6..6cddb9bdc151 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -23,82 +23,50 @@
 #ifdef CONFIG_PPC_PSERIES
 
 /*
- * The structure which the hypervisor knows about - this structure
- * should not cross a page boundary.  The vpa_init/register_vpa call
- * is now known to fail if the lppaca structure crosses a page
- * boundary.  The lppaca is also used on POWER5 pSeries boxes.
- * The lppaca is 640 bytes long, and cannot readily
- * change since the hypervisor knows its layout, so a 1kB alignment
- * will suffice to ensure that it doesn't cross a page boundary.
+ * See asm/lppaca.h for more detail.
+ *
+ * lppaca structures must must be 1kB in size, L1 cache line aligned,
+ * and not cross 4kB boundary. A 1kB size and 1kB alignment will satisfy
+ * these requirements.
  */
-struct lppaca lppaca[] = {
-	[0 ... (NR_LPPACAS-1)] = {
+static inline void init_lppaca(struct lppaca *lppaca)
+{
+	BUILD_BUG_ON(sizeof(struct lppaca) != 640);
+
+	*lppaca = (struct lppaca) {
 		.desc = cpu_to_be32(0xd397d781),	/* "LpPa" */
-		.size = cpu_to_be16(sizeof(struct lppaca)),
+		.size = cpu_to_be16(0x400),
 		.fpregs_in_use = 1,
 		.slb_count = cpu_to_be16(64),
 		.vmxregs_in_use = 0,
-		.page_ins = 0,
-	},
+		.page_ins = 0, };
 };
 
-static struct lppaca *extra_lppacas;
-static long __initdata lppaca_size;
-
-static void __init allocate_lppacas(int nr_cpus, unsigned long limit)
-{
-	if (early_cpu_has_feature(CPU_FTR_HVMODE))
-		return;
-
-	if (nr_cpus <= NR_LPPACAS)
-		return;
-
-	lppaca_size = PAGE_ALIGN(sizeof(struct lppaca) *
-				 (nr_cpus - NR_LPPACAS));
-	extra_lppacas = __va(memblock_alloc_base(lppaca_size,
-						 PAGE_SIZE, limit));
-}
-
-static struct lppaca * __init new_lppaca(int cpu)
+static struct lppaca * __init new_lppaca(int cpu, unsigned long limit)
 {
 	struct lppaca *lp;
+	size_t size = 0x400;
+
+	BUILD_BUG_ON(size < sizeof(struct lppaca));
 
 	if (early_cpu_has_feature(CPU_FTR_HVMODE))
 		return NULL;
 
-	if (cpu < NR_LPPACAS)
-		return &lppaca[cpu];
-
-	lp = extra_lppacas + (cpu - NR_LPPACAS);
-	*lp = lppaca[0];
+	lp = __va(memblock_alloc_base(size, 0x400, limit));
+	init_lppaca(lp);
 
 	return lp;
 }
 
-static void __init free_lppacas(void)
+static void __init free_lppaca(struct lppaca *lp)
 {
-	long new_size = 0, nr;
+	size_t size = 0x400;
 
 	if (early_cpu_has_feature(CPU_FTR_HVMODE))
 		return;
 
-	if (!lppaca_size)
-		return;
-	nr = num_possible_cpus() - NR_LPPACAS;
-	if (nr > 0)
-		new_size = PAGE_ALIGN(nr * sizeof(struct lppaca));
-	if (new_size >= lppaca_size)
-		return;
-
-	memblock_free(__pa(extra_lppacas) + new_size, lppaca_size - new_size);
-	lppaca_size = new_size;
+	memblock_free(__pa(lp), size);
 }
-
-#else
-
-static inline void allocate_lppacas(int nr_cpus, unsigned long limit) { }
-static inline void free_lppacas(void) { }
-
 #endif /* CONFIG_PPC_BOOK3S */
 
 #ifdef CONFIG_PPC_BOOK3S_64
@@ -167,7 +135,7 @@ EXPORT_SYMBOL(paca_ptrs);
 void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 {
 #ifdef CONFIG_PPC_PSERIES
-	new_paca->lppaca_ptr = new_lppaca(cpu);
+	new_paca->lppaca_ptr = NULL;
 #endif
 #ifdef CONFIG_PPC_BOOK3E
 	new_paca->kernel_pgd = swapper_pg_dir;
@@ -254,13 +222,15 @@ void __init allocate_pacas(void)
 	printk(KERN_DEBUG "Allocated %lu bytes for %u pacas\n",
 			size, nr_cpu_ids);
 
-	allocate_lppacas(nr_cpu_ids, limit);
-
 	allocate_slb_shadows(nr_cpu_ids, limit);
 
 	/* Can't use for_each_*_cpu, as they aren't functional yet */
-	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
 		initialise_paca(paca_ptrs[cpu], cpu);
+#ifdef CONFIG_PPC_PSERIES
+		paca_ptrs[cpu]->lppaca_ptr = new_lppaca(cpu, limit);
+#endif
+	}
 }
 
 void __init free_unused_pacas(void)
@@ -272,6 +242,9 @@ void __init free_unused_pacas(void)
 	for (cpu = 0; cpu < paca_nr_cpu_ids; cpu++) {
 		if (!cpu_possible(cpu)) {
 			unsigned long pa = __pa(paca_ptrs[cpu]);
+#ifdef CONFIG_PPC_PSERIES
+			free_lppaca(paca_ptrs[cpu]->lppaca_ptr);
+#endif
 			memblock_free(pa, sizeof(struct paca_struct));
 			paca_ptrs[cpu] = NULL;
 			size += sizeof(struct paca_struct);
@@ -288,8 +261,6 @@ void __init free_unused_pacas(void)
 	if (size)
 		printk(KERN_DEBUG "Freed %lu bytes for unused pacas\n", size);
 
-	free_lppacas();
-
 	paca_nr_cpu_ids = nr_cpu_ids;
 	paca_ptrs_size = new_ptrs_size;
 }
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cd0daac779af..e79c61fa78e9 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -497,7 +497,8 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,
 		 * use 640 bytes of the structure though, so we should accept
 		 * clients that set a size of 640.
 		 */
-		if (len < 640)
+		BUILD_BUG_ON(sizeof(struct lppaca) != 640);
+		if (len < sizeof(struct lppaca))
 			break;
 		vpap = &tvcpu->arch.vpa;
 		err = 0;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index adb6364f4091..0f8e5d997437 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1190,7 +1190,7 @@ static void setup_cpu_associativity_change_counters(void)
 	for_each_possible_cpu(cpu) {
 		int i;
 		u8 *counts = vphn_cpu_change_counts[cpu];
-		volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts;
+		volatile u8 *hypervisor_counts = lppaca_of(cpu).vphn_assoc_counts;
 
 		for (i = 0; i < distance_ref_points_depth; i++)
 			counts[i] = hypervisor_counts[i];
@@ -1216,7 +1216,7 @@ static int update_cpu_associativity_changes_mask(void)
 	for_each_possible_cpu(cpu) {
 		int i, changed = 0;
 		u8 *counts = vphn_cpu_change_counts[cpu];
-		volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts;
+		volatile u8 *hypervisor_counts = lppaca_of(cpu).vphn_assoc_counts;
 
 		for (i = 0; i < distance_ref_points_depth; i++) {
 			if (hypervisor_counts[i] != counts[i]) {
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
index eeb13429d685..3fe126796975 100644
--- a/arch/powerpc/platforms/pseries/kexec.c
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -23,7 +23,12 @@
 
 void pseries_kexec_cpu_down(int crash_shutdown, int secondary)
 {
-	/* Don't risk a hypervisor call if we're crashing */
+	/*
+	 * Don't risk a hypervisor call if we're crashing
+	 * XXX: Why? The hypervisor is not crashing. It might be better
+	 * to at least attempt unregister to avoid the hypervisor stepping
+	 * on our memory.
+	 */
 	if (firmware_has_feature(FW_FEATURE_SPLPAR) && !crash_shutdown) {
 		int ret;
 		int cpu = smp_processor_id();
-- 
2.15.0

^ permalink raw reply related

* [PATCH 8/9] powerpc/64: Use array of paca pointers and allocate pacas individually
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

Change the paca array into an array of pointers to pacas. Allocate
pacas individually.

This allows flexibility in where the PACAs are allocated. Future work
will allocate them node-local. Platforms that don't have address limits
on PACAs would be able to defer PACA allocations until later in boot
rather than allocate all possible ones up-front then freeing unused.

This is slightly more overhead (one additional indirection) for cross
CPU paca references, but those aren't too common.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/kvm_ppc.h           |  8 ++--
 arch/powerpc/include/asm/lppaca.h            |  2 +-
 arch/powerpc/include/asm/paca.h              |  4 +-
 arch/powerpc/include/asm/smp.h               |  4 +-
 arch/powerpc/kernel/crash.c                  |  2 +-
 arch/powerpc/kernel/head_64.S                | 19 ++++----
 arch/powerpc/kernel/machine_kexec_64.c       | 22 ++++-----
 arch/powerpc/kernel/paca.c                   | 70 +++++++++++++++++++---------
 arch/powerpc/kernel/setup_64.c               | 18 +++----
 arch/powerpc/kernel/smp.c                    | 10 ++--
 arch/powerpc/kernel/sysfs.c                  |  2 +-
 arch/powerpc/kvm/book3s_hv.c                 | 31 ++++++------
 arch/powerpc/kvm/book3s_hv_builtin.c         |  2 +-
 arch/powerpc/mm/tlb-radix.c                  |  2 +-
 arch/powerpc/platforms/85xx/smp.c            |  8 ++--
 arch/powerpc/platforms/cell/smp.c            |  4 +-
 arch/powerpc/platforms/powernv/idle.c        | 13 +++---
 arch/powerpc/platforms/powernv/setup.c       |  4 +-
 arch/powerpc/platforms/powernv/smp.c         |  2 +-
 arch/powerpc/platforms/powernv/subcore.c     |  2 +-
 arch/powerpc/platforms/pseries/hotplug-cpu.c |  2 +-
 arch/powerpc/platforms/pseries/lpar.c        |  4 +-
 arch/powerpc/platforms/pseries/setup.c       |  2 +-
 arch/powerpc/platforms/pseries/smp.c         |  4 +-
 arch/powerpc/sysdev/xics/icp-native.c        |  2 +-
 arch/powerpc/xmon/xmon.c                     |  2 +-
 26 files changed, 140 insertions(+), 105 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 941c2a3f231b..bde76baf8ae3 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -432,15 +432,15 @@ struct openpic;
 extern void kvm_cma_reserve(void) __init;
 static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
 {
-	paca[cpu].kvm_hstate.xics_phys = (void __iomem *)addr;
+	paca_ptrs[cpu]->kvm_hstate.xics_phys = (void __iomem *)addr;
 }
 
 static inline void kvmppc_set_xive_tima(int cpu,
 					unsigned long phys_addr,
 					void __iomem *virt_addr)
 {
-	paca[cpu].kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr;
-	paca[cpu].kvm_hstate.xive_tima_virt = virt_addr;
+	paca_ptrs[cpu]->kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr;
+	paca_ptrs[cpu]->kvm_hstate.xive_tima_virt = virt_addr;
 }
 
 static inline u32 kvmppc_get_xics_latch(void)
@@ -454,7 +454,7 @@ static inline u32 kvmppc_get_xics_latch(void)
 
 static inline void kvmppc_set_host_ipi(int cpu, u8 host_ipi)
 {
-	paca[cpu].kvm_hstate.host_ipi = host_ipi;
+	paca_ptrs[cpu]->kvm_hstate.host_ipi = host_ipi;
 }
 
 static inline void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h
index d0a2a2f99564..6e4589eee2da 100644
--- a/arch/powerpc/include/asm/lppaca.h
+++ b/arch/powerpc/include/asm/lppaca.h
@@ -103,7 +103,7 @@ struct lppaca {
 
 extern struct lppaca lppaca[];
 
-#define lppaca_of(cpu)	(*paca[cpu].lppaca_ptr)
+#define lppaca_of(cpu)	(*paca_ptrs[cpu]->lppaca_ptr)
 
 /*
  * We are using a non architected field to determine if a partition is
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index f83fc885fba8..09efab1a9854 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -236,10 +236,10 @@ struct paca_struct {
 	struct sibling_subcore_state *sibling_subcore_state;
 #endif
 #endif
-};
+} ____cacheline_aligned;
 
 extern void copy_mm_to_paca(struct mm_struct *mm);
-extern struct paca_struct *paca;
+extern struct paca_struct **paca_ptrs;
 extern void initialise_paca(struct paca_struct *new_paca, int cpu);
 extern void setup_paca(struct paca_struct *new_paca);
 extern void allocate_pacas(void);
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index fac963e10d39..ec7b299350d9 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -170,12 +170,12 @@ static inline const struct cpumask *cpu_sibling_mask(int cpu)
 #ifdef CONFIG_PPC64
 static inline int get_hard_smp_processor_id(int cpu)
 {
-	return paca[cpu].hw_cpu_id;
+	return paca_ptrs[cpu]->hw_cpu_id;
 }
 
 static inline void set_hard_smp_processor_id(int cpu, int phys)
 {
-	paca[cpu].hw_cpu_id = phys;
+	paca_ptrs[cpu]->hw_cpu_id = phys;
 }
 #else
 /* 32-bit */
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
index cbabb5adccd9..99eb8fd87d6f 100644
--- a/arch/powerpc/kernel/crash.c
+++ b/arch/powerpc/kernel/crash.c
@@ -230,7 +230,7 @@ static void __maybe_unused crash_kexec_wait_realmode(int cpu)
 		if (i == cpu)
 			continue;
 
-		while (paca[i].kexec_state < KEXEC_STATE_REAL_MODE) {
+		while (paca_ptrs[i]->kexec_state < KEXEC_STATE_REAL_MODE) {
 			barrier();
 			if (!cpu_possible(i) || !cpu_online(i) || (msecs <= 0))
 				break;
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index aa71a90f5222..23b849f0e403 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -392,19 +392,20 @@ generic_secondary_common_init:
 	 * physical cpu id in r24, we need to search the pacas to find
 	 * which logical id maps to our physical one.
 	 */
-	LOAD_REG_ADDR(r13, paca)	/* Load paca pointer		 */
-	ld	r13,0(r13)		/* Get base vaddr of paca array	 */
 #ifndef CONFIG_SMP
-	addi	r13,r13,PACA_SIZE	/* know r13 if used accidentally */
 	b	kexec_wait		/* wait for next kernel if !SMP	 */
 #else
+	LOAD_REG_ADDR(r8, paca_ptrs)	/* Load paca_ptrs pointe	 */
+	ld	r8,0(r8)		/* Get base vaddr of array	 */
 	LOAD_REG_ADDR(r7, nr_cpu_ids)	/* Load nr_cpu_ids address       */
 	lwz	r7,0(r7)		/* also the max paca allocated 	 */
 	li	r5,0			/* logical cpu id                */
-1:	lhz	r6,PACAHWCPUID(r13)	/* Load HW procid from paca      */
+1:
+	sldi	r9,r5,3			/* get paca_ptrs[] index from cpu id */
+	ldx	r13,r9,r8		/* r13 = paca_ptrs[cpu id]       */
+	lhz	r6,PACAHWCPUID(r13)	/* Load HW procid from paca      */
 	cmpw	r6,r24			/* Compare to our id             */
 	beq	2f
-	addi	r13,r13,PACA_SIZE	/* Loop to next PACA on miss     */
 	addi	r5,r5,1
 	cmpw	r5,r7			/* Check if more pacas exist     */
 	blt	1b
@@ -756,10 +757,10 @@ _GLOBAL(pmac_secondary_start)
 	mtmsrd	r3			/* RI on */
 
 	/* Set up a paca value for this processor. */
-	LOAD_REG_ADDR(r4,paca)		/* Load paca pointer		*/
-	ld	r4,0(r4)		/* Get base vaddr of paca array	*/
-	mulli	r13,r24,PACA_SIZE	/* Calculate vaddr of right paca */
-	add	r13,r13,r4		/* for this processor.		*/
+	LOAD_REG_ADDR(r4,paca_ptrs)	/* Load paca pointer		*/
+	ld	r4,0(r4)		/* Get base vaddr of paca_ptrs array */
+	sldi	r5,r24,3		/* get paca_ptrs[] index from cpu id */
+	ldx	r13,r5,r4		/* r13 = paca_ptrs[cpu id]       */
 	SET_PACA(r13)			/* Save vaddr of paca in an SPRG*/
 
 	/* Mark interrupts soft and hard disabled (they might be enabled
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c
index 49d34d7271e7..a250e3331f94 100644
--- a/arch/powerpc/kernel/machine_kexec_64.c
+++ b/arch/powerpc/kernel/machine_kexec_64.c
@@ -168,24 +168,25 @@ static void kexec_prepare_cpus_wait(int wait_state)
 	 * are correctly onlined.  If somehow we start a CPU on boot with RTAS
 	 * start-cpu, but somehow that CPU doesn't write callin_cpu_map[] in
 	 * time, the boot CPU will timeout.  If it does eventually execute
-	 * stuff, the secondary will start up (paca[].cpu_start was written) and
-	 * get into a peculiar state.  If the platform supports
-	 * smp_ops->take_timebase(), the secondary CPU will probably be spinning
-	 * in there.  If not (i.e. pseries), the secondary will continue on and
-	 * try to online itself/idle/etc. If it survives that, we need to find
-	 * these possible-but-not-online-but-should-be CPUs and chaperone them
-	 * into kexec_smp_wait().
+	 * stuff, the secondary will start up (paca_ptrs[]->cpu_start was
+	 * written) and get into a peculiar state.
+	 * If the platform supports smp_ops->take_timebase(), the secondary CPU
+	 * will probably be spinning in there.  If not (i.e. pseries), the
+	 * secondary will continue on and try to online itself/idle/etc. If it
+	 * survives that, we need to find these
+	 * possible-but-not-online-but-should-be CPUs and chaperone them into
+	 * kexec_smp_wait().
 	 */
 	for_each_online_cpu(i) {
 		if (i == my_cpu)
 			continue;
 
-		while (paca[i].kexec_state < wait_state) {
+		while (paca_ptrs[i]->kexec_state < wait_state) {
 			barrier();
 			if (i != notified) {
 				printk(KERN_INFO "kexec: waiting for cpu %d "
 				       "(physical %d) to enter %i state\n",
-				       i, paca[i].hw_cpu_id, wait_state);
+				       i, paca_ptrs[i]->hw_cpu_id, wait_state);
 				notified = i;
 			}
 		}
@@ -327,8 +328,7 @@ void default_machine_kexec(struct kimage *image)
 	 */
 	memcpy(&kexec_paca, get_paca(), sizeof(struct paca_struct));
 	kexec_paca.data_offset = 0xedeaddeadeeeeeeeUL;
-	paca = (struct paca_struct *)RELOC_HIDE(&kexec_paca, 0) -
-		kexec_paca.paca_index;
+	paca_ptrs[kexec_paca.paca_index] = &kexec_paca;
 	setup_paca(&kexec_paca);
 
 	/* XXX: If anyone does 'dynamic lppacas' this will also need to be
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 5900540e2ff8..eef4891c9af6 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -161,8 +161,8 @@ static void __init allocate_slb_shadows(int nr_cpus, int limit) { }
  * processors.  The processor VPD array needs one entry per physical
  * processor (not thread).
  */
-struct paca_struct *paca;
-EXPORT_SYMBOL(paca);
+struct paca_struct **paca_ptrs __read_mostly;
+EXPORT_SYMBOL(paca_ptrs);
 
 void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 {
@@ -213,11 +213,13 @@ void setup_paca(struct paca_struct *new_paca)
 
 }
 
-static int __initdata paca_size;
+static int __initdata paca_nr_cpu_ids;
+static int __initdata paca_ptrs_size;
 
 void __init allocate_pacas(void)
 {
 	u64 limit;
+	unsigned long size = 0;
 	int cpu;
 
 #ifdef CONFIG_PPC_BOOK3S_64
@@ -230,13 +232,27 @@ void __init allocate_pacas(void)
 	limit = ppc64_rma_size;
 #endif
 
-	paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids);
+	paca_nr_cpu_ids = nr_cpu_ids;
 
-	paca = __va(memblock_alloc_base(paca_size, PAGE_SIZE, limit));
-	memset(paca, 0, paca_size);
+	paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
+	paca_ptrs = __va(memblock_alloc_base(paca_ptrs_size, 0, limit));
+	memset(paca_ptrs, 0, paca_ptrs_size);
 
-	printk(KERN_DEBUG "Allocated %u bytes for %u pacas at %p\n",
-		paca_size, nr_cpu_ids, paca);
+	size += paca_ptrs_size;
+
+	for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
+		unsigned long pa;
+
+		pa = memblock_alloc_base(sizeof(struct paca_struct),
+						L1_CACHE_BYTES, limit);
+		paca_ptrs[cpu] = __va(pa);
+		memset(paca_ptrs[cpu], 0, sizeof(struct paca_struct));
+
+		size += sizeof(struct paca_struct);
+	}
+
+	printk(KERN_DEBUG "Allocated %lu bytes for %u pacas\n",
+			size, nr_cpu_ids);
 
 	allocate_lppacas(nr_cpu_ids, limit);
 
@@ -244,26 +260,38 @@ void __init allocate_pacas(void)
 
 	/* Can't use for_each_*_cpu, as they aren't functional yet */
 	for (cpu = 0; cpu < nr_cpu_ids; cpu++)
-		initialise_paca(&paca[cpu], cpu);
+		initialise_paca(paca_ptrs[cpu], cpu);
 }
 
 void __init free_unused_pacas(void)
 {
-	int new_size;
-
-	new_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids);
-
-	if (new_size >= paca_size)
-		return;
-
-	memblock_free(__pa(paca) + new_size, paca_size - new_size);
-
-	printk(KERN_DEBUG "Freed %u bytes for unused pacas\n",
-		paca_size - new_size);
+	unsigned long size = 0;
+	int new_ptrs_size;
+	int cpu;
 
-	paca_size = new_size;
+	for (cpu = 0; cpu < paca_nr_cpu_ids; cpu++) {
+		if (!cpu_possible(cpu)) {
+			unsigned long pa = __pa(paca_ptrs[cpu]);
+			memblock_free(pa, sizeof(struct paca_struct));
+			paca_ptrs[cpu] = NULL;
+			size += sizeof(struct paca_struct);
+		}
+	}
+
+	new_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
+	if (new_ptrs_size < paca_ptrs_size) {
+		memblock_free(__pa(paca_ptrs) + new_ptrs_size,
+					paca_ptrs_size - new_ptrs_size);
+		size += paca_ptrs_size - new_ptrs_size;
+	}
+
+	if (size)
+		printk(KERN_DEBUG "Freed %lu bytes for unused pacas\n", size);
 
 	free_lppacas();
+
+	paca_nr_cpu_ids = nr_cpu_ids;
+	paca_ptrs_size = new_ptrs_size;
 }
 
 void copy_mm_to_paca(struct mm_struct *mm)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index a2b731052084..2557708eaaca 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -108,7 +108,7 @@ void __init setup_tlb_core_data(void)
 		if (cpu_first_thread_sibling(boot_cpuid) == first)
 			first = boot_cpuid;
 
-		paca[cpu].tcd_ptr = &paca[first].tcd;
+		paca_ptrs[cpu]->tcd_ptr = &paca_ptrs[first]->tcd;
 
 		/*
 		 * If we have threads, we need either tlbsrx.
@@ -300,7 +300,7 @@ void __init early_setup(unsigned long dt_ptr)
 	early_init_devtree(__va(dt_ptr));
 
 	/* Now we know the logical id of our boot cpu, setup the paca. */
-	setup_paca(&paca[boot_cpuid]);
+	setup_paca(paca_ptrs[boot_cpuid]);
 	fixup_boot_paca();
 
 	/*
@@ -624,15 +624,15 @@ void __init exc_lvl_early_init(void)
 	for_each_possible_cpu(i) {
 		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
 		critirq_ctx[i] = (struct thread_info *)__va(sp);
-		paca[i].crit_kstack = __va(sp + THREAD_SIZE);
+		paca_ptrs[i]->crit_kstack = __va(sp + THREAD_SIZE);
 
 		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
 		dbgirq_ctx[i] = (struct thread_info *)__va(sp);
-		paca[i].dbg_kstack = __va(sp + THREAD_SIZE);
+		paca_ptrs[i]->dbg_kstack = __va(sp + THREAD_SIZE);
 
 		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
 		mcheckirq_ctx[i] = (struct thread_info *)__va(sp);
-		paca[i].mc_kstack = __va(sp + THREAD_SIZE);
+		paca_ptrs[i]->mc_kstack = __va(sp + THREAD_SIZE);
 	}
 
 	if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC))
@@ -689,20 +689,20 @@ void __init emergency_stack_init(void)
 		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
 		memset(ti, 0, THREAD_SIZE);
 		emerg_stack_init_thread_info(ti, i);
-		paca[i].emergency_sp = (void *)ti + THREAD_SIZE;
+		paca_ptrs[i]->emergency_sp = (void *)ti + THREAD_SIZE;
 
 #ifdef CONFIG_PPC_BOOK3S_64
 		/* emergency stack for NMI exception handling. */
 		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
 		memset(ti, 0, THREAD_SIZE);
 		emerg_stack_init_thread_info(ti, i);
-		paca[i].nmi_emergency_sp = (void *)ti + THREAD_SIZE;
+		paca_ptrs[i]->nmi_emergency_sp = (void *)ti + THREAD_SIZE;
 
 		/* emergency stack for machine check exception handling. */
 		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
 		memset(ti, 0, THREAD_SIZE);
 		emerg_stack_init_thread_info(ti, i);
-		paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE;
+		paca_ptrs[i]->mc_emergency_sp = (void *)ti + THREAD_SIZE;
 #endif
 	}
 }
@@ -758,7 +758,7 @@ void __init setup_per_cpu_areas(void)
 	delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
 	for_each_possible_cpu(cpu) {
                 __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
-		paca[cpu].data_offset = __per_cpu_offset[cpu];
+		paca_ptrs[cpu]->data_offset = __per_cpu_offset[cpu];
 	}
 }
 #endif
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index e0a4c1f82e25..1b456776bf5a 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -123,8 +123,8 @@ int smp_generic_kick_cpu(int nr)
 	 * cpu_start field to become non-zero After we set cpu_start,
 	 * the processor will continue on to secondary_start
 	 */
-	if (!paca[nr].cpu_start) {
-		paca[nr].cpu_start = 1;
+	if (!paca_ptrs[nr]->cpu_start) {
+		paca_ptrs[nr]->cpu_start = 1;
 		smp_mb();
 		return 0;
 	}
@@ -639,7 +639,7 @@ void smp_prepare_boot_cpu(void)
 {
 	BUG_ON(smp_processor_id() != boot_cpuid);
 #ifdef CONFIG_PPC64
-	paca[boot_cpuid].__current = current;
+	paca_ptrs[boot_cpuid]->__current = current;
 #endif
 	set_numa_node(numa_cpu_lookup_table[boot_cpuid]);
 	current_set[boot_cpuid] = task_thread_info(current);
@@ -730,8 +730,8 @@ static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle)
 	struct thread_info *ti = task_thread_info(idle);
 
 #ifdef CONFIG_PPC64
-	paca[cpu].__current = idle;
-	paca[cpu].kstack = (unsigned long)ti + THREAD_SIZE - STACK_FRAME_OVERHEAD;
+	paca_ptrs[cpu]->__current = idle;
+	paca_ptrs[cpu]->kstack = (unsigned long)ti + THREAD_SIZE - STACK_FRAME_OVERHEAD;
 #endif
 	ti->cpu = cpu;
 	secondary_ti = current_set[cpu] = ti;
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index b8d4a1dac39f..e689e444cd7b 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -598,7 +598,7 @@ void __init record_spr_defaults(void)
 	if (cpu_has_feature(CPU_FTR_DSCR)) {
 		dscr_default = mfspr(SPRN_DSCR);
 		for (cpu = 0; cpu < nr_cpu_ids; cpu++)
-			paca[cpu].dscr_default = dscr_default;
+			paca_ptrs[cpu]->dscr_default = dscr_default;
 	}
 }
 #endif /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 2d46037ce936..cd0daac779af 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -169,7 +169,7 @@ static bool kvmppc_ipi_thread(int cpu)
 
 #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP)
 	if (cpu >= 0 && cpu < nr_cpu_ids) {
-		if (paca[cpu].kvm_hstate.xics_phys) {
+		if (paca_ptrs[cpu]->kvm_hstate.xics_phys) {
 			xics_wake_cpu(cpu);
 			return true;
 		}
@@ -2124,7 +2124,7 @@ static int kvmppc_grab_hwthread(int cpu)
 	struct paca_struct *tpaca;
 	long timeout = 10000;
 
-	tpaca = &paca[cpu];
+	tpaca = paca_ptrs[cpu];
 
 	/* Ensure the thread won't go into the kernel if it wakes */
 	tpaca->kvm_hstate.kvm_vcpu = NULL;
@@ -2157,7 +2157,7 @@ static void kvmppc_release_hwthread(int cpu)
 {
 	struct paca_struct *tpaca;
 
-	tpaca = &paca[cpu];
+	tpaca = paca_ptrs[cpu];
 	tpaca->kvm_hstate.hwthread_req = 0;
 	tpaca->kvm_hstate.kvm_vcpu = NULL;
 	tpaca->kvm_hstate.kvm_vcore = NULL;
@@ -2223,7 +2223,7 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc)
 		vcpu->arch.thread_cpu = cpu;
 		cpumask_set_cpu(cpu, &kvm->arch.cpu_in_guest);
 	}
-	tpaca = &paca[cpu];
+	tpaca = paca_ptrs[cpu];
 	tpaca->kvm_hstate.kvm_vcpu = vcpu;
 	tpaca->kvm_hstate.ptid = cpu - vc->pcpu;
 	/* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */
@@ -2248,7 +2248,7 @@ static void kvmppc_wait_for_nap(int n_threads)
 		 * for any threads that still have a non-NULL vcore ptr.
 		 */
 		for (i = 1; i < n_threads; ++i)
-			if (paca[cpu + i].kvm_hstate.kvm_vcore)
+			if (paca_ptrs[cpu + i]->kvm_hstate.kvm_vcore)
 				break;
 		if (i == n_threads) {
 			HMT_medium();
@@ -2258,7 +2258,7 @@ static void kvmppc_wait_for_nap(int n_threads)
 	}
 	HMT_medium();
 	for (i = 1; i < n_threads; ++i)
-		if (paca[cpu + i].kvm_hstate.kvm_vcore)
+		if (paca_ptrs[cpu + i]->kvm_hstate.kvm_vcore)
 			pr_err("KVM: CPU %d seems to be stuck\n", cpu + i);
 }
 
@@ -2788,9 +2788,11 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
 	}
 
 	for (thr = 0; thr < controlled_threads; ++thr) {
-		paca[pcpu + thr].kvm_hstate.tid = thr;
-		paca[pcpu + thr].kvm_hstate.napping = 0;
-		paca[pcpu + thr].kvm_hstate.kvm_split_mode = sip;
+		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;
 	}
 
 	/* Initiate micro-threading (split-core) on POWER8 if required */
@@ -2908,7 +2910,9 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
 	} else if (hpt_on_radix) {
 		/* Wait for all threads to have seen final sync */
 		for (thr = 1; thr < controlled_threads; ++thr) {
-			while (paca[pcpu + thr].kvm_hstate.kvm_split_mode) {
+			struct paca_struct *paca = paca_ptrs[pcpu + thr];
+
+			while (paca->kvm_hstate.kvm_split_mode) {
 				HMT_low();
 				barrier();
 			}
@@ -4378,7 +4382,7 @@ static int kvm_init_subcore_bitmap(void)
 		int node = cpu_to_node(first_cpu);
 
 		/* Ignore if it is already allocated. */
-		if (paca[first_cpu].sibling_subcore_state)
+		if (paca_ptrs[first_cpu]->sibling_subcore_state)
 			continue;
 
 		sibling_subcore_state =
@@ -4393,7 +4397,8 @@ static int kvm_init_subcore_bitmap(void)
 		for (j = 0; j < threads_per_core; j++) {
 			int cpu = first_cpu + j;
 
-			paca[cpu].sibling_subcore_state = sibling_subcore_state;
+			paca_ptrs[cpu]->sibling_subcore_state =
+						sibling_subcore_state;
 		}
 	}
 	return 0;
@@ -4420,7 +4425,7 @@ static int kvmppc_book3s_init_hv(void)
 
 	/*
 	 * We need a way of accessing the XICS interrupt controller,
-	 * either directly, via paca[cpu].kvm_hstate.xics_phys, or
+	 * either directly, via paca_ptrs[cpu]->kvm_hstate.xics_phys, or
 	 * indirectly, via OPAL.
 	 */
 #ifdef CONFIG_SMP
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index 49a2c7825e04..de18299f92b7 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -251,7 +251,7 @@ void kvmhv_rm_send_ipi(int cpu)
 	    return;
 
 	/* Else poke the target with an IPI */
-	xics_phys = paca[cpu].kvm_hstate.xics_phys;
+	xics_phys = paca_ptrs[cpu]->kvm_hstate.xics_phys;
 	if (xics_phys)
 		__raw_rm_writeb(IPI_PRIORITY, xics_phys + XICS_MFRR);
 	else
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 884f4b705b57..760087cb3128 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -659,7 +659,7 @@ extern void radix_kvm_prefetch_workaround(struct mm_struct *mm)
 		for (; sib <= cpu_last_thread_sibling(cpu) && !flush; sib++) {
 			if (sib == cpu)
 				continue;
-			if (paca[sib].kvm_hstate.kvm_vcpu)
+			if (paca_ptrs[sib]->kvm_hstate.kvm_vcpu)
 				flush = true;
 		}
 		if (flush)
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index f51fd35f4618..7e966f4cf19a 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -147,7 +147,7 @@ static void qoriq_cpu_kill(unsigned int cpu)
 	for (i = 0; i < 500; i++) {
 		if (is_cpu_dead(cpu)) {
 #ifdef CONFIG_PPC64
-			paca[cpu].cpu_start = 0;
+			paca_ptrs[cpu]->cpu_start = 0;
 #endif
 			return;
 		}
@@ -328,7 +328,7 @@ static int smp_85xx_kick_cpu(int nr)
 		return ret;
 
 done:
-	paca[nr].cpu_start = 1;
+	paca_ptrs[nr]->cpu_start = 1;
 	generic_set_cpu_up(nr);
 
 	return ret;
@@ -409,14 +409,14 @@ void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary)
 	}
 
 	if (disable_threadbit) {
-		while (paca[disable_cpu].kexec_state < KEXEC_STATE_REAL_MODE) {
+		while (paca_ptrs[disable_cpu]->kexec_state < KEXEC_STATE_REAL_MODE) {
 			barrier();
 			now = mftb();
 			if (!notified && now - start > 1000000) {
 				pr_info("%s/%d: waiting for cpu %d to enter KEXEC_STATE_REAL_MODE (%d)\n",
 					__func__, smp_processor_id(),
 					disable_cpu,
-					paca[disable_cpu].kexec_state);
+					paca_ptrs[disable_cpu]->kexec_state);
 				notified = true;
 			}
 		}
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c
index f84d52a2db40..1aeac5761e0b 100644
--- a/arch/powerpc/platforms/cell/smp.c
+++ b/arch/powerpc/platforms/cell/smp.c
@@ -83,7 +83,7 @@ static inline int smp_startup_cpu(unsigned int lcpu)
 	pcpu = get_hard_smp_processor_id(lcpu);
 
 	/* Fixup atomic count: it exited inside IRQ handler. */
-	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;
+	task_thread_info(paca_ptrs[lcpu]->__current)->preempt_count	= 0;
 
 	/*
 	 * If the RTAS start-cpu token does not exist then presume the
@@ -126,7 +126,7 @@ static int smp_cell_kick_cpu(int nr)
 	 * cpu_start field to become non-zero After we set cpu_start,
 	 * the processor will continue on to secondary_start
 	 */
-	paca[nr].cpu_start = 1;
+	paca_ptrs[nr]->cpu_start = 1;
 
 	return 0;
 }
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 443d5ca71995..5b2ca71ee551 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -80,7 +80,7 @@ static int pnv_save_sprs_for_deep_states(void)
 
 	for_each_possible_cpu(cpu) {
 		uint64_t pir = get_hard_smp_processor_id(cpu);
-		uint64_t hsprg0_val = (uint64_t)&paca[cpu];
+		uint64_t hsprg0_val = (uint64_t)paca_ptrs[cpu];
 
 		rc = opal_slw_set_reg(pir, SPRN_HSPRG0, hsprg0_val);
 		if (rc != 0)
@@ -173,12 +173,12 @@ static void pnv_alloc_idle_core_states(void)
 		for (j = 0; j < threads_per_core; j++) {
 			int cpu = first_cpu + j;
 
-			paca[cpu].core_idle_state_ptr = core_idle_state;
-			paca[cpu].thread_idle_state = PNV_THREAD_RUNNING;
-			paca[cpu].thread_mask = 1 << j;
+			paca_ptrs[cpu]->core_idle_state_ptr = core_idle_state;
+			paca_ptrs[cpu]->thread_idle_state = PNV_THREAD_RUNNING;
+			paca_ptrs[cpu]->thread_mask = 1 << j;
 			if (!cpu_has_feature(CPU_FTR_POWER9_DD1))
 				continue;
-			paca[cpu].thread_sibling_pacas =
+			paca_ptrs[cpu]->thread_sibling_pacas =
 				kmalloc_node(paca_ptr_array_size,
 					     GFP_KERNEL, node);
 		}
@@ -749,7 +749,8 @@ static int __init pnv_init_idle_states(void)
 			for (i = 0; i < threads_per_core; i++) {
 				int j = base_cpu + i;
 
-				paca[j].thread_sibling_pacas[idx] = &paca[cpu];
+				paca_ptrs[j]->thread_sibling_pacas[idx] =
+					paca_ptrs[cpu];
 			}
 		}
 	}
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 1edfbc1e40f4..71cc1ded803d 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -205,7 +205,7 @@ static void pnv_kexec_wait_secondaries_down(void)
 			if (i != notified) {
 				printk(KERN_INFO "kexec: waiting for cpu %d "
 				       "(physical %d) to enter OPAL\n",
-				       i, paca[i].hw_cpu_id);
+				       i, paca_ptrs[i]->hw_cpu_id);
 				notified = i;
 			}
 
@@ -217,7 +217,7 @@ static void pnv_kexec_wait_secondaries_down(void)
 			if (timeout-- == 0) {
 				printk(KERN_ERR "kexec: timed out waiting for "
 				       "cpu %d (physical %d) to enter OPAL\n",
-				       i, paca[i].hw_cpu_id);
+				       i, paca_ptrs[i]->hw_cpu_id);
 				break;
 			}
 		}
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index ba030669eca1..85bedcf18c4e 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -78,7 +78,7 @@ static int pnv_smp_kick_cpu(int nr)
 	 * If we already started or OPAL is not supported, we just
 	 * kick the CPU via the PACA
 	 */
-	if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPAL))
+	if (paca_ptrs[nr]->cpu_start || !firmware_has_feature(FW_FEATURE_OPAL))
 		goto kick;
 
 	/*
diff --git a/arch/powerpc/platforms/powernv/subcore.c b/arch/powerpc/platforms/powernv/subcore.c
index 596ae2e98040..45563004feda 100644
--- a/arch/powerpc/platforms/powernv/subcore.c
+++ b/arch/powerpc/platforms/powernv/subcore.c
@@ -280,7 +280,7 @@ void update_subcore_sibling_mask(void)
 		int offset = (tid / threads_per_subcore) * threads_per_subcore;
 		int mask = sibling_mask_first_cpu << offset;
 
-		paca[cpu].subcore_sibling_mask = mask;
+		paca_ptrs[cpu]->subcore_sibling_mask = mask;
 
 	}
 }
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index a7d14aa7bb7c..b3f4bdab1bbe 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -233,7 +233,7 @@ static void pseries_cpu_die(unsigned int cpu)
 	 * done here.  Change isolate state to Isolate and
 	 * change allocation-state to Unusable.
 	 */
-	paca[cpu].cpu_start = 0;
+	paca_ptrs[cpu]->cpu_start = 0;
 }
 
 /*
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 0ee4a469a4ae..b6d2ecce33eb 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -99,7 +99,7 @@ void vpa_init(int cpu)
 	 * reports that.  All SPLPAR support SLB shadow buffer.
 	 */
 	if (!radix_enabled() && firmware_has_feature(FW_FEATURE_SPLPAR)) {
-		addr = __pa(paca[cpu].slb_shadow_ptr);
+		addr = __pa(paca_ptrs[cpu]->slb_shadow_ptr);
 		ret = register_slb_shadow(hwcpu, addr);
 		if (ret)
 			pr_err("WARNING: SLB shadow buffer registration for "
@@ -111,7 +111,7 @@ void vpa_init(int cpu)
 	/*
 	 * Register dispatch trace log, if one has been allocated.
 	 */
-	pp = &paca[cpu];
+	pp = paca_ptrs[cpu];
 	dtl = pp->dispatch_log;
 	if (dtl) {
 		pp->dtl_ridx = 0;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 28b286df0e91..0aae4172ce17 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -246,7 +246,7 @@ static int alloc_dispatch_logs(void)
 		return 0;
 
 	for_each_possible_cpu(cpu) {
-		pp = &paca[cpu];
+		pp = paca_ptrs[cpu];
 		dtl = kmem_cache_alloc(dtl_cache, GFP_KERNEL);
 		if (!dtl) {
 			pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index 2e184829e5d4..d506bf661f0f 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -110,7 +110,7 @@ static inline int smp_startup_cpu(unsigned int lcpu)
 	}
 
 	/* Fixup atomic count: it exited inside IRQ handler. */
-	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;
+	task_thread_info(paca_ptrs[lcpu]->__current)->preempt_count	= 0;
 #ifdef CONFIG_HOTPLUG_CPU
 	if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE)
 		goto out;
@@ -165,7 +165,7 @@ static int smp_pSeries_kick_cpu(int nr)
 	 * cpu_start field to become non-zero After we set cpu_start,
 	 * the processor will continue on to secondary_start
 	 */
-	paca[nr].cpu_start = 1;
+	paca_ptrs[nr]->cpu_start = 1;
 #ifdef CONFIG_HOTPLUG_CPU
 	set_preferred_offline_state(nr, CPU_STATE_ONLINE);
 
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index 1459f4e8b698..37bfbc54aacb 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -164,7 +164,7 @@ void icp_native_cause_ipi_rm(int cpu)
 	 * Just like the cause_ipi functions, it is required to
 	 * include a full barrier before causing the IPI.
 	 */
-	xics_phys = paca[cpu].kvm_hstate.xics_phys;
+	xics_phys = paca_ptrs[cpu]->kvm_hstate.xics_phys;
 	mb();
 	__raw_rm_writeb(IPI_PRIORITY, xics_phys + XICS_MFRR);
 }
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index cab24f549e7c..cf70b4a57e45 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2327,7 +2327,7 @@ static void dump_one_paca(int cpu)
 	catch_memory_errors = 1;
 	sync();
 
-	p = &paca[cpu];
+	p = paca_ptrs[cpu];
 
 	printf("paca for cpu 0x%x @ %px:\n", cpu, p);
 
-- 
2.15.0

^ permalink raw reply related

* [PATCH 7/9] powerpc/64s: do not allocate lppaca if we are not virtualized
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

The "lppaca" is a structure registered with the hypervisor. This
is unnecessary when running on non-virtualised platforms. One field
from the lppaca (pmcregs_in_use) is also used by the host, so move
the host part out into the paca (lppaca field is still updated in
guest mode).

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/paca.h         |  8 ++++++--
 arch/powerpc/include/asm/pmc.h          | 13 ++++++++++++-
 arch/powerpc/kernel/asm-offsets.c       |  5 +++++
 arch/powerpc/kernel/paca.c              | 16 +++++++++++++---
 arch/powerpc/kvm/book3s_hv_interrupts.S |  3 +--
 arch/powerpc/kvm/book3s_hv_rmhandlers.S |  3 +--
 6 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 3892db93b837..f83fc885fba8 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -58,7 +58,7 @@ struct task_struct;
  * processor.
  */
 struct paca_struct {
-#ifdef CONFIG_PPC_BOOK3S
+#ifdef CONFIG_PPC_PSERIES
 	/*
 	 * Because hw_cpu_id, unlike other paca fields, is accessed
 	 * routinely from other CPUs (from the IRQ code), we stick to
@@ -67,7 +67,8 @@ struct paca_struct {
 	 */
 
 	struct lppaca *lppaca_ptr;	/* Pointer to LpPaca for PLIC */
-#endif /* CONFIG_PPC_BOOK3S */
+#endif /* CONFIG_PPC_PSERIES */
+
 	/*
 	 * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c 
 	 * load lock_token and paca_index with a single lwz
@@ -159,6 +160,9 @@ struct paca_struct {
 	u64 saved_r1;			/* r1 save for RTAS calls or PM */
 	u64 saved_msr;			/* MSR saved here by enter_rtas */
 	u16 trap_save;			/* Used when bad stack is encountered */
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	u8 pmcregs_in_use;		/* pseries puts this in lppaca */
+#endif
 	u8 soft_enabled;		/* irq soft-enable flag */
 	u8 irq_happened;		/* irq happened while soft-disabled */
 	u8 io_sync;			/* writel() needs spin_unlock sync */
diff --git a/arch/powerpc/include/asm/pmc.h b/arch/powerpc/include/asm/pmc.h
index 5a9ede4962cb..7ac3586c38ab 100644
--- a/arch/powerpc/include/asm/pmc.h
+++ b/arch/powerpc/include/asm/pmc.h
@@ -31,10 +31,21 @@ void ppc_enable_pmcs(void);
 
 #ifdef CONFIG_PPC_BOOK3S_64
 #include <asm/lppaca.h>
+#include <asm/firmware.h>
 
 static inline void ppc_set_pmu_inuse(int inuse)
 {
-	get_lppaca()->pmcregs_in_use = inuse;
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
+	if (firmware_has_feature(FW_FEATURE_LPAR)) {
+#ifdef CONFIG_PPC_PSERIES
+		get_lppaca()->pmcregs_in_use = inuse;
+#endif
+	} else {
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+		get_paca()->pmcregs_in_use = inuse;
+#endif
+	}
+#endif
 }
 
 extern void power4_enable_pmcs(void);
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 3f6316bcde4e..a7c355c8c467 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -221,12 +221,17 @@ int main(void)
 	OFFSET(PACA_EXMC, paca_struct, exmc);
 	OFFSET(PACA_EXSLB, paca_struct, exslb);
 	OFFSET(PACA_EXNMI, paca_struct, exnmi);
+#ifdef CONFIG_PPC_PSERIES
 	OFFSET(PACALPPACAPTR, paca_struct, lppaca_ptr);
+#endif
 	OFFSET(PACA_SLBSHADOWPTR, paca_struct, slb_shadow_ptr);
 	OFFSET(SLBSHADOW_STACKVSID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid);
 	OFFSET(SLBSHADOW_STACKESID, slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid);
 	OFFSET(SLBSHADOW_SAVEAREA, slb_shadow, save_area);
 	OFFSET(LPPACA_PMCINUSE, lppaca, pmcregs_in_use);
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+	OFFSET(PACA_PMCINUSE, paca_struct, pmcregs_in_use);
+#endif
 	OFFSET(LPPACA_DTLIDX, lppaca, dtl_idx);
 	OFFSET(LPPACA_YIELDCOUNT, lppaca, yield_count);
 	OFFSET(PACA_DTL_RIDX, paca_struct, dtl_ridx);
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 95ffedf14885..5900540e2ff8 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -20,7 +20,7 @@
 
 #include "setup.h"
 
-#ifdef CONFIG_PPC_BOOK3S
+#ifdef CONFIG_PPC_PSERIES
 
 /*
  * The structure which the hypervisor knows about - this structure
@@ -47,6 +47,9 @@ static long __initdata lppaca_size;
 
 static void __init allocate_lppacas(int nr_cpus, unsigned long limit)
 {
+	if (early_cpu_has_feature(CPU_FTR_HVMODE))
+		return;
+
 	if (nr_cpus <= NR_LPPACAS)
 		return;
 
@@ -60,6 +63,9 @@ static struct lppaca * __init new_lppaca(int cpu)
 {
 	struct lppaca *lp;
 
+	if (early_cpu_has_feature(CPU_FTR_HVMODE))
+		return NULL;
+
 	if (cpu < NR_LPPACAS)
 		return &lppaca[cpu];
 
@@ -73,6 +79,9 @@ static void __init free_lppacas(void)
 {
 	long new_size = 0, nr;
 
+	if (early_cpu_has_feature(CPU_FTR_HVMODE))
+		return;
+
 	if (!lppaca_size)
 		return;
 	nr = num_possible_cpus() - NR_LPPACAS;
@@ -157,9 +166,10 @@ EXPORT_SYMBOL(paca);
 
 void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 {
-#ifdef CONFIG_PPC_BOOK3S
+#ifdef CONFIG_PPC_PSERIES
 	new_paca->lppaca_ptr = new_lppaca(cpu);
-#else
+#endif
+#ifdef CONFIG_PPC_BOOK3E
 	new_paca->kernel_pgd = swapper_pg_dir;
 #endif
 	new_paca->lock_token = 0x8000;
diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S
index dc54373c8780..0e8493033288 100644
--- a/arch/powerpc/kvm/book3s_hv_interrupts.S
+++ b/arch/powerpc/kvm/book3s_hv_interrupts.S
@@ -79,8 +79,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
 	li	r5, 0
 	mtspr	SPRN_MMCRA, r5
 	isync
-	ld	r3, PACALPPACAPTR(r13)	/* is the host using the PMU? */
-	lbz	r5, LPPACA_PMCINUSE(r3)
+	lbz	r5, PACA_PMCINUSE(r13)	/* is the host using the PMU? */
 	cmpwi	r5, 0
 	beq	31f			/* skip if not */
 	mfspr	r5, SPRN_MMCR1
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 2659844784b8..fc772448de8b 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -113,8 +113,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
 	mtspr	SPRN_SPRG_VDSO_WRITE,r3
 
 	/* Reload the host's PMU registers */
-	ld	r3, PACALPPACAPTR(r13)	/* is the host using the PMU? */
-	lbz	r4, LPPACA_PMCINUSE(r3)
+	lbz	r4, PACA_PMCINUSE(r13) /* is the host using the PMU? */
 	cmpwi	r4, 0
 	beq	23f			/* skip if not */
 BEGIN_FTR_SECTION
-- 
2.15.0

^ permalink raw reply related

* [PATCH 6/9] powerpc/64s: Relax PACA address limitations
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

Book3S PACA memory allocation is restricted by the RMA limit and also
must not take SLB faults when accessed in virtual mode. Currently a
fixed 256MB limit is used for this, which is imprecise and sub-optimal.

Update the paca allocation limits to use use the ppc64_rma_size for RMA
limit, and share the safe_stack_limit() that is currently used for stack
allocations that must not take virtual mode faults.

The safe_stack_limit() name is changed to ppc64_bolted_size() to match
ppc64_rma_size and some comments are updated, but code unchanged.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kernel/paca.c     | 13 +++++++------
 arch/powerpc/kernel/setup.h    |  4 ++++
 arch/powerpc/kernel/setup_64.c | 22 ++++++++++++++--------
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index d6597038931d..95ffedf14885 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -18,6 +18,8 @@
 #include <asm/pgtable.h>
 #include <asm/kexec.h>
 
+#include "setup.h"
+
 #ifdef CONFIG_PPC_BOOK3S
 
 /*
@@ -208,15 +210,14 @@ void __init allocate_pacas(void)
 	u64 limit;
 	int cpu;
 
-	limit = ppc64_rma_size;
-
 #ifdef CONFIG_PPC_BOOK3S_64
 	/*
-	 * We can't take SLB misses on the paca, and we want to access them
-	 * in real mode, so allocate them within the RMA and also within
-	 * the first segment.
+	 * We access pacas in real mode, and cannot take SLB faults
+	 * on them when in virtual mode, so allocate them accordingly.
 	 */
-	limit = min(0x10000000ULL, limit);
+	limit = min(ppc64_bolted_size(), ppc64_rma_size);
+#else
+	limit = ppc64_rma_size;
 #endif
 
 	paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids);
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h
index 21c18071d9d5..3fc11e30308f 100644
--- a/arch/powerpc/kernel/setup.h
+++ b/arch/powerpc/kernel/setup.h
@@ -51,6 +51,10 @@ void record_spr_defaults(void);
 static inline void record_spr_defaults(void) { };
 #endif
 
+#ifdef CONFIG_PPC64
+u64 ppc64_bolted_size(void);
+#endif
+
 /*
  * Having this in kvm_ppc.h makes include dependencies too
  * tricky to solve for setup-common.c so have it here.
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index d3124c302146..a2b731052084 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -565,24 +565,30 @@ void __init initialize_cache_info(void)
 	DBG(" <- initialize_cache_info()\n");
 }
 
-/* This returns the limit below which memory accesses to the linear
- * mapping are guarnateed not to cause a TLB or SLB miss. This is
- * used to allocate interrupt or emergency stacks for which our
- * exception entry path doesn't deal with being interrupted.
+/*
+ * This returns the limit below which memory accesses to the linear
+ * mapping are guarnateed not to cause an architectural exception (e.g.,
+ * TLB or SLB miss fault).
+ *
+ * This is used to allocate PACAs and various interrupt stacks that
+ * that are accessed early in interrupt handlers that must not cause
+ * re-entrant interrupts.
  */
-static __init u64 safe_stack_limit(void)
+__init u64 ppc64_bolted_size(void)
 {
 #ifdef CONFIG_PPC_BOOK3E
 	/* Freescale BookE bolts the entire linear mapping */
+	/* XXX: BookE ppc64_rma_limit setup seems to disagree? */
 	if (mmu_has_feature(MMU_FTR_TYPE_FSL_E))
 		return linear_map_top;
 	/* Other BookE, we assume the first GB is bolted */
 	return 1ul << 30;
 #else
+	/* BookS radix, does not take faults on linear mapping */
 	if (early_radix_enabled())
 		return ULONG_MAX;
 
-	/* BookS, the first segment is bolted */
+	/* BookS hash, the first segment is bolted */
 	if (mmu_has_feature(MMU_FTR_1T_SEGMENT))
 		return 1UL << SID_SHIFT_1T;
 	return 1UL << SID_SHIFT;
@@ -591,7 +597,7 @@ static __init u64 safe_stack_limit(void)
 
 void __init irqstack_early_init(void)
 {
-	u64 limit = safe_stack_limit();
+	u64 limit = ppc64_bolted_size();
 	unsigned int i;
 
 	/*
@@ -676,7 +682,7 @@ void __init emergency_stack_init(void)
 	 * initialized in kernel/irq.c. These are initialized here in order
 	 * to have emergency stacks available as early as possible.
 	 */
-	limit = min(safe_stack_limit(), ppc64_rma_size);
+	limit = min(ppc64_bolted_size(), ppc64_rma_size);
 
 	for_each_possible_cpu(i) {
 		struct thread_info *ti;
-- 
2.15.0

^ permalink raw reply related

* [PATCH 5/9] powerpc/pseries: lift RTAS limit for hash
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

With the previous patch to switch to 64-bit mode after returning from
RTAS and before doing any memory accesses, the RMA limit need not be
clamped to 1GB to avoid RTAS bugs.

Keep the 1GB limit for older firmware (although this is more of a kernel
concern than RTAS), and remove it starting with POWER9.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/mm/hash_utils_64.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 8922e069b073..3c1bc1e6fa91 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -1830,11 +1830,13 @@ void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
 	 * non-virtualized 64-bit hash MMU systems don't have a limitation
 	 * on real mode access.
 	 *
-	 * We also clamp it to 1G to avoid some funky things
-	 * such as RTAS bugs etc...
+	 * For guests on platforms before POWER9, we clamp the it limit to 1G
+	 * to avoid some funky things such as RTAS bugs etc...
 	 */
 	if (!early_cpu_has_feature(CPU_FTR_HVMODE)) {
-		ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+		ppc64_rma_size = first_memblock_size;
+		if (!early_cpu_has_feature(CPU_FTR_ARCH_300))
+			ppc64_rma_size = min_t(u64, ppc64_rma_size, 0x40000000);
 
 		/* Finally limit subsequent allocations */
 		memblock_set_current_limit(ppc64_rma_size);
-- 
2.15.0

^ permalink raw reply related

* [PATCH 4/9] powerpc/pseries: lift RTAS limit for radix
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

With the previous patch to switch to 64-bit mode after returning from
RTAS and before doing any memory accesses, the RMA limit need not be
clamped to 1GB to avoid RTAS bugs.

Keep the 1GB limit for older firmware (although this is more of a kernel
concern than RTAS), and remove it starting with POWER9.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/mm/pgtable-radix.c | 21 ++++-----------------
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index 6606216f1992..b8c49e6623ae 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -623,23 +623,10 @@ void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
 	 */
 	BUG_ON(first_memblock_base != 0);
 
-	if (!early_cpu_has_feature(CPU_FTR_HVMODE)) {
-		/*
-		 * Radix mode guests are not limited by RMA / VRMA addressing.
-		 *
-		 * We do clamp addresses to 1GB to avoid some funky things
-		 * such as RTAS bugs.
-		 */
-		ppc64_rma_size = 0x40000000;
-		/*
-		 * Finally limit subsequent allocations. We really don't want
-		 * to limit the memblock allocations to rma_size. FIXME!! should
-		 * we even limit at all ?
-		 */
-		memblock_set_current_limit(first_memblock_base + first_memblock_size);
-	} else {
-		ppc64_rma_size = ULONG_MAX;
-	}
+	/*
+	 * Radix mode is not limited by RMA / VRMA addressing.
+	 */
+	ppc64_rma_size = ULONG_MAX;
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-- 
2.15.0

^ permalink raw reply related

* [PATCH 3/9] powerpc/64: rtas avoid accessing paca in 32-bit mode
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

Commit 177ba7c647f3 ("powerpc/mm/radix: Limit paca allocation in radix")
limited the paca allocation address to 1G on pSeries because RTAS return
accesses the paca in 32-bit mode:

    On return from RTAS we access the paca variables and we have 64 bit
    disabled. This requires us to limit paca in 32 bit range.

    Fix this by setting ppc64_rma_size to first_memblock_size/1G range.

Avoid this limit by switching to 64-bit mode before accessing any memory.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kernel/entry_64.S | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 36878b6ee8b8..371c05fe250a 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -1083,6 +1083,17 @@ __enter_rtas:
 rtas_return_loc:
 	FIXUP_ENDIAN
 
+	/*
+	 * Clear RI and set SF before anything.
+	 */
+	mfmsr   r6
+	li	r0,MSR_RI
+	andc	r6,r6,r0
+	sldi	r0,r0,(MSR_SF_LG - MSR_RI_LG)
+	or	r6,r6,r0
+	sync
+	mtmsrd  r6
+
 	/* relocation is off at this point */
 	GET_PACA(r4)
 	clrldi	r4,r4,2			/* convert to realmode address */
@@ -1091,12 +1102,6 @@ rtas_return_loc:
 0:	mflr	r3
 	ld	r3,(1f-0b)(r3)		/* get &rtas_restore_regs */
 
-	mfmsr   r6
-	li	r0,MSR_RI
-	andc	r6,r6,r0
-	sync	
-	mtmsrd  r6
-        
         ld	r1,PACAR1(r4)           /* Restore our SP */
         ld	r4,PACASAVEDMSR(r4)     /* Restore our MSR */
 
-- 
2.15.0

^ permalink raw reply related

* [PATCH 2/9] powerpc/pseries: radix is not subject to RMA limit, remove it
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

The radix guest is not subject to the paravirtualized HPT VRMA limit,
so remove that from ppc64_rma_size calculation for that platform.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/mm/pgtable-radix.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index d73816960825..6606216f1992 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -625,15 +625,12 @@ void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
 
 	if (!early_cpu_has_feature(CPU_FTR_HVMODE)) {
 		/*
-		 * We limit the allocation that depend on ppc64_rma_size
-		 * to first_memblock_size. We also clamp it to 1GB to
-		 * avoid some funky things such as RTAS bugs.
+		 * Radix mode guests are not limited by RMA / VRMA addressing.
 		 *
-		 * On radix config we really don't have a limitation
-		 * on real mode access. But keeping it as above works
-		 * well enough.
+		 * We do clamp addresses to 1GB to avoid some funky things
+		 * such as RTAS bugs.
 		 */
-		ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+		ppc64_rma_size = 0x40000000;
 		/*
 		 * Finally limit subsequent allocations. We really don't want
 		 * to limit the memblock allocations to rma_size. FIXME!! should
-- 
2.15.0

^ permalink raw reply related

* [PATCH 1/9] powerpc/powernv: Remove real mode access limit for early allocations
From: Nicholas Piggin @ 2017-12-22 11:17 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Aneesh Kumar K . V
In-Reply-To: <20171222111716.13101-1-npiggin@gmail.com>

This removes the RMA limit on powernv platform, which constrains
early allocations such as PACAs and stacks. There are still other
restrictions that must be followed, such as bolted SLB limits, but
real mode addressing has no constraints.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/mm/hash_utils_64.c | 20 +++++++++++++-------
 arch/powerpc/mm/pgtable-radix.c | 37 +++++++++++++++++++++----------------
 2 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 655a5a9a183d..8922e069b073 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -1825,16 +1825,22 @@ void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
 	 */
 	BUG_ON(first_memblock_base != 0);
 
-	/* On LPAR systems, the first entry is our RMA region,
-	 * non-LPAR 64-bit hash MMU systems don't have a limitation
-	 * on real mode access, but using the first entry works well
-	 * enough. We also clamp it to 1G to avoid some funky things
+	/*
+	 * On virtualized systems the first entry is our RMA region aka VRMA,
+	 * non-virtualized 64-bit hash MMU systems don't have a limitation
+	 * on real mode access.
+	 *
+	 * We also clamp it to 1G to avoid some funky things
 	 * such as RTAS bugs etc...
 	 */
-	ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+	if (!early_cpu_has_feature(CPU_FTR_HVMODE)) {
+		ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
 
-	/* Finally limit subsequent allocations */
-	memblock_set_current_limit(ppc64_rma_size);
+		/* Finally limit subsequent allocations */
+		memblock_set_current_limit(ppc64_rma_size);
+	} else {
+		ppc64_rma_size = ULONG_MAX;
+	}
 }
 
 #ifdef CONFIG_DEBUG_FS
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index cfbbee941a76..d73816960825 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -622,22 +622,27 @@ void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
 	 * physical on those processors
 	 */
 	BUG_ON(first_memblock_base != 0);
-	/*
-	 * We limit the allocation that depend on ppc64_rma_size
-	 * to first_memblock_size. We also clamp it to 1GB to
-	 * avoid some funky things such as RTAS bugs.
-	 *
-	 * On radix config we really don't have a limitation
-	 * on real mode access. But keeping it as above works
-	 * well enough.
-	 */
-	ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
-	/*
-	 * Finally limit subsequent allocations. We really don't want
-	 * to limit the memblock allocations to rma_size. FIXME!! should
-	 * we even limit at all ?
-	 */
-	memblock_set_current_limit(first_memblock_base + first_memblock_size);
+
+	if (!early_cpu_has_feature(CPU_FTR_HVMODE)) {
+		/*
+		 * We limit the allocation that depend on ppc64_rma_size
+		 * to first_memblock_size. We also clamp it to 1GB to
+		 * avoid some funky things such as RTAS bugs.
+		 *
+		 * On radix config we really don't have a limitation
+		 * on real mode access. But keeping it as above works
+		 * well enough.
+		 */
+		ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000);
+		/*
+		 * Finally limit subsequent allocations. We really don't want
+		 * to limit the memblock allocations to rma_size. FIXME!! should
+		 * we even limit at all ?
+		 */
+		memblock_set_current_limit(first_memblock_base + first_memblock_size);
+	} else {
+		ppc64_rma_size = ULONG_MAX;
+	}
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-- 
2.15.0

^ permalink raw reply related


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