LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* linux-next: manual merge of the mfd tree with the powerpc tree
From: Stephen Rothwell @ 2018-01-29  3:02 UTC (permalink / raw)
  To: Lee Jones, Michael Ellerman, Benjamin Herrenschmidt, PowerPC
  Cc: Linux-Next Mailing List, Linux Kernel Mailing List,
	Frederic Barrat, Rui Feng

Hi Lee,

Today's linux-next merge of the mfd tree got conflicts in:

  drivers/misc/Kconfig
  drivers/misc/Makefile

between commit:

  b97f02246e0d ("ocxl: Add Makefile and Kconfig")

from the powerpc tree and commit:

  e455b69ddf9b ("misc: rtsx: Move Realtek Card Reader Driver to misc")

from the mfd tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/misc/Kconfig
index 0534f338c84a,7c0fa24f9067..000000000000
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@@ -508,5 -512,5 +512,6 @@@ source "drivers/misc/mic/Kconfig
  source "drivers/misc/genwqe/Kconfig"
  source "drivers/misc/echo/Kconfig"
  source "drivers/misc/cxl/Kconfig"
 +source "drivers/misc/ocxl/Kconfig"
+ source "drivers/misc/cardreader/Kconfig"
  endmenu
diff --cc drivers/misc/Makefile
index 73326d54e246,8d8cc096063b..000000000000
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@@ -55,7 -55,7 +55,8 @@@ obj-$(CONFIG_CXL_BASE)		+= cxl
  obj-$(CONFIG_ASPEED_LPC_CTRL)	+= aspeed-lpc-ctrl.o
  obj-$(CONFIG_ASPEED_LPC_SNOOP)	+= aspeed-lpc-snoop.o
  obj-$(CONFIG_PCI_ENDPOINT_TEST)	+= pci_endpoint_test.o
 +obj-$(CONFIG_OCXL)		+= ocxl/
+ obj-$(CONFIG_MISC_RTSX)	+= cardreader/
  
  lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o
  lkdtm-$(CONFIG_LKDTM)		+= lkdtm_bugs.o

^ permalink raw reply

* linux-next: manual merge of the pci tree with the powerpc tree
From: Stephen Rothwell @ 2018-01-29  0:36 UTC (permalink / raw)
  To: Bjorn Helgaas, Michael Ellerman, Benjamin Herrenschmidt, PowerPC
  Cc: Linux-Next Mailing List, Linux Kernel Mailing List, Bryant G. Ly

Hi Bjorn,

Today's linux-next merge of the pci tree got a conflict in:

  arch/powerpc/platforms/powernv/eeh-powernv.c

between commit:

  64ba3dc7bf7c ("powerpc/eeh: Update VF config space after EEH")

from the powerpc tree and commit:

  fdabc3fe9982 ("PCI: Add #defines for Completion Timeout Disable feature")

from the pci tree.

The former commit moved the code changed by the latter to another file.
I have added the following merge fix patch:

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Mon, 29 Jan 2018 11:33:24 +1100
Subject: [PATCH] PCI: fix up for "powerpc/eeh: Update VF config space after EEH"

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/kernel/eeh.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index cc649809885e..2b9df0040d6b 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -756,14 +756,14 @@ int eeh_restore_vf_config(struct pci_dn *pdn)
 		eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
 				      2, devctl);
 
-		/* Disable Completion Timeout */
+		/* Disable Completion Timeout if possible */
 		eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCAP2,
 				     4, &cap2);
-		if (cap2 & 0x10) {
+		if (cap2 & PCI_EXP_DEVCAP2_COMP_TMOUT_DIS) {
 			eeh_ops->read_config(pdn,
 					     edev->pcie_cap + PCI_EXP_DEVCTL2,
 					     4, &cap2);
-			cap2 |= 0x10;
+			cap2 |= PCI_EXP_DEVCTL2_COMP_TMOUT_DIS;
 			eeh_ops->write_config(pdn,
 					      edev->pcie_cap + PCI_EXP_DEVCTL2,
 					      4, cap2);
-- 
2.15.1


I fixed it up (see above) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

^ permalink raw reply related

* linux-next: manual merge of the pci tree with the powerpc tree
From: Stephen Rothwell @ 2018-01-29  0:29 UTC (permalink / raw)
  To: Bjorn Helgaas, Michael Ellerman, Benjamin Herrenschmidt, PowerPC
  Cc: Linux-Next Mailing List, Linux Kernel Mailing List, Bryant G. Ly

Hi Bjorn,

Today's linux-next merge of the pci tree got a conflict in:

  include/linux/pci.h

between commit:

  856e1eb9bdd4 ("PCI/AER: Add uevents in AER and EEH error/resume")

from the powerpc tree and commit:

  0aa0f5d1084c ("PCI: Clean up whitespace in linux/pci.h, pci/pci.h")

from the pci tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc include/linux/pci.h
index 881006c7a5d7,a1e10ba7b612..000000000000
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@@ -2280,43 -2267,19 +2269,55 @@@ static inline bool pci_is_thunderbolt_a
  	return false;
  }
  
 +/**
 + * pci_uevent_ers - emit a uevent during recovery path of pci device
 + * @pdev: pci device to check
 + * @err_type: type of error event
 + *
 + */
 +static inline void pci_uevent_ers(struct pci_dev *pdev,
 +				  enum  pci_ers_result err_type)
 +{
 +	int idx = 0;
 +	char *envp[3];
 +
 +	switch (err_type) {
 +	case PCI_ERS_RESULT_NONE:
 +	case PCI_ERS_RESULT_CAN_RECOVER:
 +		envp[idx++] = "ERROR_EVENT=BEGIN_RECOVERY";
 +		envp[idx++] = "DEVICE_ONLINE=0";
 +		break;
 +	case PCI_ERS_RESULT_RECOVERED:
 +		envp[idx++] = "ERROR_EVENT=SUCCESSFUL_RECOVERY";
 +		envp[idx++] = "DEVICE_ONLINE=1";
 +		break;
 +	case PCI_ERS_RESULT_DISCONNECT:
 +		envp[idx++] = "ERROR_EVENT=FAILED_RECOVERY";
 +		envp[idx++] = "DEVICE_ONLINE=0";
 +		break;
 +	default:
 +		break;
 +	}
 +
 +	if (idx > 0) {
 +		envp[idx++] = NULL;
 +		kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
 +	}
 +}
 +
- /* provide the legacy pci_dma_* API */
+ /* Provide the legacy pci_dma_* API */
  #include <linux/pci-dma-compat.h>
  
+ #define pci_printk(level, pdev, fmt, arg...) \
+ 	dev_printk(level, &(pdev)->dev, fmt, ##arg)
+ 
+ #define pci_emerg(pdev, fmt, arg...)	dev_emerg(&(pdev)->dev, fmt, ##arg)
+ #define pci_alert(pdev, fmt, arg...)	dev_alert(&(pdev)->dev, fmt, ##arg)
+ #define pci_crit(pdev, fmt, arg...)	dev_crit(&(pdev)->dev, fmt, ##arg)
+ #define pci_err(pdev, fmt, arg...)	dev_err(&(pdev)->dev, fmt, ##arg)
+ #define pci_warn(pdev, fmt, arg...)	dev_warn(&(pdev)->dev, fmt, ##arg)
+ #define pci_notice(pdev, fmt, arg...)	dev_notice(&(pdev)->dev, fmt, ##arg)
+ #define pci_info(pdev, fmt, arg...)	dev_info(&(pdev)->dev, fmt, ##arg)
+ #define pci_dbg(pdev, fmt, arg...)	dev_dbg(&(pdev)->dev, fmt, ##arg)
+ 
  #endif /* LINUX_PCI_H */

^ permalink raw reply

* Re: [PATCH v2 3/6] gpio: Add GPIO driver for Nintendo Wii
From: Andy Shevchenko @ 2018-01-28 17:31 UTC (permalink / raw)
  To: Jonathan Neuschäfer
  Cc: Linux Kernel Mailing List,
	open list:LINUX FOR POWERPC PA SEMI PWRFICIENT,
	open list:GPIO SUBSYSTEM, devicetree, Albert Herranz,
	Segher Boessenkool, Linus Walleij
In-Reply-To: <20180122050411.32460-4-j.neuschaefer@gmx.net>

On Mon, Jan 22, 2018 at 7:04 AM, Jonathan Neusch=C3=A4fer
<j.neuschaefer@gmx.net> wrote:

Style issues below.

> +#define HW_GPIO_OWNER          0x3c
> +
> +
> +struct hlwd_gpio {

No need extra empty line in between.

> +       struct gpio_chip gpioc;
> +       void __iomem *regs;
> +       struct device *dev;
> +};
> +
> +static int hlwd_gpio_probe(struct platform_device *pdev)
> +{
> +       struct hlwd_gpio *hlwd;
> +       struct resource *regs_resource;
> +       u32 ngpios;
> +       int res;
> +
> +       hlwd =3D devm_kzalloc(&pdev->dev, sizeof(*hlwd), GFP_KERNEL);
> +       if (!hlwd)
> +               return -ENOMEM;
> +

> +       /* Save the struct device pointer so dev_info, etc. can be used. =
*/

Useless.

> +       hlwd->dev =3D &pdev->dev;
> +

> +       regs_resource =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);

> +       if (IS_ERR(regs_resource))
> +               return PTR_ERR(regs_resource);
> +

This is redundant. Below does it for ya.

> +       hlwd->regs =3D devm_ioremap_resource(&pdev->dev, regs_resource);
> +       if (IS_ERR(hlwd->regs))
> +               return PTR_ERR(hlwd->regs);


> +       res =3D bgpio_init(&hlwd->gpioc, &pdev->dev, 4,
> +                       hlwd->regs + HW_GPIOB_IN, hlwd->regs + HW_GPIOB_O=
UT,
> +                       NULL, hlwd->regs + HW_GPIOB_DIR, NULL,
> +                       BGPIOF_BIG_ENDIAN_BYTE_ORDER);

> +

Remove this extra line.

> +       if (res < 0) {
> +               dev_warn(hlwd->dev, "bgpio_init failed: %d\n", res);
> +               return res;
> +       }

> +       if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios))
> +               ngpios =3D 32;

A nit: I would rather go with
res =3D of_property_read(...);
if (res)
  ngpios =3D 32;

--=20
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* [PATCH] macintosh/via-pmu68k: Initialize PMU driver with setup_arch and arch_initcall
From: Finn Thain @ 2018-01-27 23:51 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Geert Uytterhoeven, linux-m68k, linux-kernel, linuxppc-dev

The PMU watchdog will power down the system if the kernel is slow
to start up, e.g. due to unpacking a large initrd. The powerpc
version of this driver (via-pmu.c) has a solution for the same
problem. It uses this call sequence:

setup_arch
	find_via_pmu
		init_pmu
...
arch_initcall
	via_pmu_start

Bring via-pmu68k.c into line with via-pmu.c to fix this issue.

Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Tested-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
---
 arch/m68k/mac/config.c         |  4 ++
 drivers/macintosh/via-pmu68k.c | 89 +++++++++++++++++++++++++++++-------------
 2 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index 95d548d8cc8a..17d9380aa7e6 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -26,6 +26,7 @@
 #include <linux/platform_device.h>
 #include <linux/adb.h>
 #include <linux/cuda.h>
+#include <linux/pmu.h>
 #include <linux/rtc.h>
 
 #include <asm/setup.h>
@@ -906,6 +907,9 @@ static void __init mac_identify(void)
 #ifdef CONFIG_ADB_CUDA
 	find_via_cuda();
 #endif
+#ifdef CONFIG_ADB_PMU68K
+	find_via_pmu();
+#endif
 }
 
 static void __init mac_report_hardware(void)
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 25465fb91ec9..7d9c4baf8c11 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -109,6 +109,7 @@ static int pmu_autopoll(int devs);
 void pmu_poll(void);
 static int pmu_reset_bus(void);
 
+static int init_pmu(void);
 static void pmu_start(void);
 static void send_byte(int x);
 static void recv_byte(void);
@@ -171,23 +172,76 @@ static s8 pmu_data_len[256][2] = {
 /*f8*/	{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},
 };
 
-int pmu_probe(void)
+int __init find_via_pmu(void)
 {
-	if (macintosh_config->adb_type == MAC_ADB_PB1) {
+	switch (macintosh_config->adb_type) {
+	case MAC_ADB_PB1:
 		pmu_kind = PMU_68K_V1;
-	} else if (macintosh_config->adb_type == MAC_ADB_PB2) {
+		break;
+	case MAC_ADB_PB2:
 		pmu_kind = PMU_68K_V2;
-	} else {
+		break;
+	default:
+		pmu_kind = PMU_UNKNOWN;
 		return -ENODEV;
 	}
 
 	pmu_state = idle;
 
+	if (!init_pmu())
+		goto fail_init;
+
+	pr_info("adb: PMU 68K driver v0.5 for Unified ADB\n");
+
+	return 1;
+
+fail_init:
+	pmu_kind = PMU_UNKNOWN;
 	return 0;
 }
 
-static int 
-pmu_init(void)
+static int pmu_probe(void)
+{
+	if (pmu_kind == PMU_UNKNOWN)
+		return -ENODEV;
+	return 0;
+}
+
+static int pmu_init(void)
+{
+	if (pmu_kind == PMU_UNKNOWN)
+		return -ENODEV;
+	return 0;
+}
+
+static int __init via_pmu_start(void)
+{
+	if (pmu_kind == PMU_UNKNOWN)
+		return -ENODEV;
+
+	if (request_irq(IRQ_MAC_ADB_SR, pmu_interrupt, 0, "PMU_SR",
+			pmu_interrupt)) {
+		pr_err("%s: can't get SR irq\n", __func__);
+		return -ENODEV;
+	}
+	if (request_irq(IRQ_MAC_ADB_CL, pmu_interrupt, 0, "PMU_CL",
+			pmu_interrupt)) {
+		pr_err("%s: can't get CL irq\n", __func__);
+		free_irq(IRQ_MAC_ADB_SR, pmu_interrupt);
+		return -ENODEV;
+	}
+
+	pmu_fully_inited = 1;
+
+	/* Enable backlight */
+	pmu_enable_backlight(1);
+
+	return 0;
+}
+
+arch_initcall(via_pmu_start);
+
+static int __init init_pmu(void)
 {
 	int timeout;
 	volatile struct adb_request req;
@@ -238,28 +292,7 @@ pmu_init(void)
 	bright_req_2.complete = 1;
 	bright_req_3.complete = 1;
 
-	if (request_irq(IRQ_MAC_ADB_SR, pmu_interrupt, 0, "pmu-shift",
-			pmu_interrupt)) {
-		printk(KERN_ERR "pmu_init: can't get irq %d\n",
-			IRQ_MAC_ADB_SR);
-		return -EAGAIN;
-	}
-	if (request_irq(IRQ_MAC_ADB_CL, pmu_interrupt, 0, "pmu-clock",
-			pmu_interrupt)) {
-		printk(KERN_ERR "pmu_init: can't get irq %d\n",
-			IRQ_MAC_ADB_CL);
-		free_irq(IRQ_MAC_ADB_SR, pmu_interrupt);
-		return -EAGAIN;
-	}
-
-	pmu_fully_inited = 1;
-	
-	/* Enable backlight */
-	pmu_enable_backlight(1);
-
-	printk("adb: PMU 68K driver v0.5 for Unified ADB.\n");
-
-	return 0;
+	return 1;
 }
 
 int
-- 
2.13.6

^ permalink raw reply related

* Re: [PATCH 00/26] KVM: PPC: Book3S PR: Transaction memory support on PR KVM
From: Simon Guo @ 2018-01-27 13:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev, kvm, kvm-ppc
In-Reply-To: <20180123053832.GA3924@fergus.ozlabs.ibm.com>

Hi Paul,
On Tue, Jan 23, 2018 at 04:38:32PM +1100, Paul Mackerras wrote:
> On Thu, Jan 11, 2018 at 06:11:13PM +0800, wei.guo.simon@gmail.com wrote:
> > From: Simon Guo <wei.guo.simon@gmail.com>
> > 
> > In current days, many OS distributions have utilized transaction
> > memory functionality. In PowerPC, HV KVM supports TM. But PR KVM
> > does not.
> > 
> > The drive for the transaction memory support of PR KVM is the
> > openstack Continuous Integration testing - They runs a HV(hypervisor)
> > KVM(as level 1) and then run PR KVM(as level 2) on top of that.
> > 
> > This patch set add transaction memory support on PR KVM.
> 
> Thanks for the patch set.  It mostly looks good, though I have some
> comments on the individual patches.
> 
> I don't see where you are implementing support for userspace accessing
> the TM checkpointed register values using the GET_ONE_REG/SET_ONE_REG
> API.  This would mean that you couldn't migrate a guest that was in
> the middle of a transaction.  We will need to have the one_reg API
> access to the TM checkpoint implemented, though there will be a
> difficulty in that kvmppc_get_one_reg() and kvmppc_set_one_reg() are
> called with the vcpu context loaded.  With your scheme of having the
> TM checkpoint stored in the CPU while the vcpu context is loaded, the
> values you want to access in kvmppc_get/set_one_reg are inaccessible
> since they're stored in the CPU.  You would have to arrange for
> kvmppc_get/set_one_reg to be called without the vcpu context loaded
> (recent patches in the kvm next branch probably make that easier) or
> else explicitly unload and reload the vcpu context in those functions.
> (This is easier in HV KVM since the checkpoint is not in the CPU at
> the point of doing kvmppc_get/set_one_reg.)
Thanks for point it out. I didn't think about it before and will 
investigate. 

I plan to work out this PR KVM HTM kvmppc_get/set_one_reg() 
(and the KVM_SET_REGS you mentioned in another mail) with seperate 
patch/patch set, so that the reworked V2 of current patches can be 
sent out in parallel. In case it is not appropriate for you, please 
let me know.

> 
> There is also complexity added because it's possible for the guest to
> have TM, FP, VEC and VSX all enabled from its point of view but to
> have FP/VEC/VSX not actually enabled in the hardware when the guest is
> running.  As you note in your patch descriptions, this means that the
> guest can do tbegin and create a checkpoint with bogus values for the
> FP/VEC/VSX registers.  Rather than trying to detect and fix up this
> situation after the fact, I would suggest that if the guest has TM
> enabled then we make sure that the real FP/VEC/VSX bits in the MSR
> match what the guest thinks it has.  That way we would avoid the bogus
> checkpoint problem.  (There is still the possibility of getting bogus
> checkpointed FP/VEC/VSX registers if the guest does tbegin with the
> FP/VEC/VSX bits clear in the MSR, but that is the guest's problem to
> deal with.)
Good idea. I will look into kvmppc_set_msr_pr() / kvmppc_giveup_ext()
to simplify the solution.

Thanks for your review and time.

BR,
- Simon

^ permalink raw reply

* Re: [PATCH] powerpc: Add POWER9 copy_page() loop
From: Michael Ellerman @ 2018-01-27 10:06 UTC (permalink / raw)
  To: Anton Blanchard, benh, paulus; +Cc: linuxppc-dev
In-Reply-To: <20170320234046.32718-1-anton@ozlabs.org>

Anton Blanchard <anton@ozlabs.org> writes:

> From: Anton Blanchard <anton@samba.org>
>
> Add a POWER9 optimised copy_page() loop. This loop uses the new D form
> vector loads and stores, and uses dcbz to pre zero the destination.
>
...
> +
> +#ifdef CONFIG_ALTIVEC
> +	mflr	r0
> +	std	r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
> +	std	r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
> +	std	r0,16(r1)
> +	stdu	r1,-STACKFRAMESIZE(r1)
> +	bl	enter_vmx_copy
> +	cmpwi	r3,0
> +	ld	r0,STACKFRAMESIZE+16(r1)
> +	ld	r3,STK_REG(R31)(r1)
> +	ld	r4,STK_REG(R30)(r1)
> +	addi	r1,r1,STACKFRAMESIZE
> +	mtlr	r0
> +
> +	li	r0,((PAGE_SIZE/128)-2)
> +	mtctr	r0
> +
> +	li	r8,256
> +
> +	beq	.Lnonvmx_copy
> +
> +	.balign 16
> +1:	dcbz	r8,r3
> +	lxv	vs32,0(r4)
> +	lxv	vs33,16(r4)

Unfortunately this doesn't build:

  arch/powerpc/lib/copypage_power9.S: Assembler messages:
  arch/powerpc/lib/copypage_power9.S:66: Error: unrecognized opcode: `lxv'
  arch/powerpc/lib/copypage_power9.S:67: Error: unrecognized opcode: `lxv'
  arch/powerpc/lib/copypage_power9.S:68: Error: unrecognized opcode: `stxv'
  arch/powerpc/lib/copypage_power9.S:69: Error: unrecognized opcode: `stxv'


Presumably we need to a .long macro version for older toolchains?

cheers

^ permalink raw reply

* Re: [PATCH V2] powerpc/kernel: Add 'ibm, thread-groups' property for CPU allocation
From: Michael Ellerman @ 2018-01-27  9:52 UTC (permalink / raw)
  To: Michael Bringmann, linuxppc-dev; +Cc: Nathan Fontenot, Michael Bringmann
In-Reply-To: <aeffc542-db28-7d1f-3263-52919b2d07c2@linux.vnet.ibm.com>

Michael Bringmann <mwb@linux.vnet.ibm.com> writes:

> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
> index b15bae2..0a49231 100644
> --- a/arch/powerpc/kernel/prom.c
> +++ b/arch/powerpc/kernel/prom.c
> @@ -303,6 +306,71 @@ static void __init check_cpu_feature_properties(unsigned long node)
>  	}
>  }
>  
> +static void __init early_init_setup_thread_group_mask(unsigned long node,
> +						cpumask_t *thread_group_mask)
> +{
> +	const __be32 *thrgrp;
> +	int len, rc = 0;
> +	u32 cc_type = 0, no_split = 0, thr_per_split = 0;
> +	int j, k;
> +
> +	cpumask_clear(thread_group_mask);
> +
> +	thrgrp = of_get_flat_dt_prop(node, "ibm,thread-groups", &len);
> +	if (!thrgrp)
> +		return;

This breaks booting on all my systems.

cheers

^ permalink raw reply

* Re: [PATCH v2 2/5] powerpc/32: Fix hugepage allocation on 8xx at hint address
From: Michael Ellerman @ 2018-01-27  9:37 UTC (permalink / raw)
  To: Aneesh Kumar K.V, Christophe Leroy, Benjamin Herrenschmidt,
	Paul Mackerras, Scott Wood
  Cc: linux-kernel, linuxppc-dev
In-Reply-To: <87shb2z22l.fsf@linux.vnet.ibm.com>

"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> writes:

> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>
>> On the 8xx, the page size is set in the PMD entry and applies to
>> all pages of the page table pointed by the said PMD entry.
>>
...
>> diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
>> index a9b9083c5e49..79e1378ee303 100644
>> --- a/arch/powerpc/mm/hugetlbpage.c
>> +++ b/arch/powerpc/mm/hugetlbpage.c
>> @@ -553,9 +553,11 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
>>  	struct hstate *hstate = hstate_file(file);
>>  	int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate));
>>  
>> +#ifdef CONFIG_PPC_RADIX_MMU
>>  	if (radix_enabled())
>>  		return radix__hugetlb_get_unmapped_area(file, addr, len,
>>  						       pgoff, flags);
>> +#endif
>
> if (0) didn't remove the following radix__hugetlb_get_unmapped_area for
> you? 

It will remove the call, but you still need at least a prototype, or an
empty static inline.

cheers

^ permalink raw reply

* Re: [PATCH v2 12/13] ocxl: Documentation
From: Michael Ellerman @ 2018-01-27  9:02 UTC (permalink / raw)
  To: Frederic Barrat, Greg KH
  Cc: linuxppc-dev, linux-kernel, arnd, andrew.donnellan, alastair
In-Reply-To: <f457e877-11f8-d89c-dce1-34642c1c9318@linux.vnet.ibm.com>

Frederic Barrat <fbarrat@linux.vnet.ibm.com> writes:

> Le 25/01/2018 =C3=A0 14:17, Greg KH a =C3=A9crit=C2=A0:
>> On Tue, Jan 23, 2018 at 12:31:47PM +0100, Frederic Barrat wrote:
>>> ocxl.rst gives a quick, high-level view of opencapi.
>>>
>>> Update ioctl-number.txt to reflect ioctl numbers being used by the
>>> ocxl driver
>>>
>>> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
>>> ---
>>>   Documentation/ABI/testing/sysfs-class-ocxl |  35 +++++++
>>>   Documentation/accelerators/ocxl.rst        | 160 ++++++++++++++++++++=
+++++++++
>>>   Documentation/ioctl/ioctl-number.txt       |   1 +
>>>   3 files changed, 196 insertions(+)
>>>   create mode 100644 Documentation/ABI/testing/sysfs-class-ocxl
>>>   create mode 100644 Documentation/accelerators/ocxl.rst
>>>
>>> diff --git a/Documentation/ABI/testing/sysfs-class-ocxl b/Documentation=
/ABI/testing/sysfs-class-ocxl
>>> new file mode 100644
>>> index 000000000000..ac11deb71235
>>> --- /dev/null
>>> +++ b/Documentation/ABI/testing/sysfs-class-ocxl
>>> @@ -0,0 +1,35 @@
>>> +What:           /sys/class/ocxl/<afu name>/afu_version
>>> +Date:           January 2018
>>> +Contact:        linuxppc-dev@lists.ozlabs.org
>>> +Description:    read only
>>> +                Version of the AFU, in the format <major>:<minor>
>>> +		Reflects what is read in the configuration space of the AFU
>>=20
>> Odd mix of tabs and spaces in this file, please just use tabs.
>
> Oops! Will fix.

I've already applied it to my test tree, I'll fix it up.

cheers

^ permalink raw reply

* Re: [PATCH RESEND V2 ] powerpc/numa: Invalidate numa_cpu_lookup_table on cpu remove
From: Michael Ellerman @ 2018-01-27  8:58 UTC (permalink / raw)
  To: Nathan Fontenot, linuxppc-dev
In-Reply-To: <151699561194.20320.12952014708209986173.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com>

Nathan Fontenot <nfont@linux.vnet.ibm.com> writes:

> When DLPAR removing a CPU, the unmapping of the cpu from a node in
> unmap_cpu_from_node() should also invalidate the CPUs entry in the
> numa_cpu_lookup_table. There is not a guarantee that on a subsequent
> DLPAR add of the CPU the associativity will be the same and thus
> could be in a different node. Invalidating the entry in the
> numa_cpu_lookup_table causes the associativity to be read from the
> device tree at the time of the add.

This last part seems to contradict the change log of commit d4edc5b6c480
("powerpc: Fix the setup of CPU-to-Node mappings during CPU online"),
which seems to say that we shouldn't be looking at the device tree.

Can you explain to me what I'm missing?

Also when did this break, always? Which commit should I mark this as
fixing?

cheers

^ permalink raw reply

* Re: [PATCH v2 1/6] resource: Extend the PPC32 reserved memory hack
From: Jonathan Neuschäfer @ 2018-01-27  8:00 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Jonathan Neuschäfer, linux-kernel, Tom Lendacky,
	Brijesh Singh, devicetree, Albert Herranz, linux-gpio,
	Thomas Gleixner, Borislav Petkov, linuxppc-dev
In-Reply-To: <87po60uk1y.fsf@concordia.ellerman.id.au>

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

On Wed, Jan 24, 2018 at 12:23:05PM +1100, Michael Ellerman wrote:
> Jonathan Neuschäfer <j.neuschaefer@gmx.net> writes:
[...]
> > Do you have any pointer on how to implement discontiguous memory
> > support? CONFIG_ARCH_SPARSEMEM_ENABLE seems relevant.
> 
> I'm not really sure what the key impediment to it working is.
> 
> You don't need to go all the way to SPARSEMEM, there is DISCONTIGMEM
> which IIUI is quite a bit simpler.
> 
> I'd actually be interested to know what happens (ie. breaks) if you just
> add the two memblocks and leave the hole in between. Is it the generic
> code that breaks or is it something in the powerpc code? If it's the
> later maybe we can do a small fix/hack to work around that.

Ok, I did some experimentation.

First, I made wii_memory_fixups return early, before actually doing
anything[1].

[    0.000000] __ioremap(): phys addr 0xc003000 is RAM lr flipper_pic_init
[    0.000000] flipper-pic: controller at 0x0c003000 mapped to 0x  (null)
[    0.000000] Unable to handle kernel paging request for data at address 0x00000004

* __ioremap_caller detects overlap with RAM like this: p < virt_to_phys(high_memory)
* flipper_pic_init gets NULL from ioremap, but doesn't check for NULL


Then I hacked up __ioremap_caller to use memblock_is_map_memory[2],
because it considers memblocks correctly. The result was that the system
boots further, but then enters the sleep mode where the power LED shines
yellow. In this mode the ARM runs but the PPC doesn't. The same thing
would happen if GPIO 3 ("DC_DC"[3]) was pulled low. These are the last few
lines:

[    0.770324] io scheduler mq-deadline registered
[    0.772472] io scheduler kyber registered

I don't know what exactly is triggering this effect.


Thanks for your help,
Jonathan Neuschäfer


[1]: diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 6e6db1e16d71..cddd5606a63d 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -81,6 +81,9 @@ void __init wii_memory_fixups(void)
 	BUG_ON(memblock.memory.cnt != 2);
 	BUG_ON(!page_aligned(p[0].base) || !page_aligned(p[1].base));
 
+	/* don't fix the memory map */
+	return;
+
 	/* trim unaligned tail */
 	memblock_remove(ALIGN(p[1].base + p[1].size, PAGE_SIZE),
 			(phys_addr_t)ULLONG_MAX);
[2]: diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index f6c7f54c0515..bff581003c50 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -154,8 +154,7 @@ __ioremap_caller(phys_addr_t addr, unsigned long size, unsigned long flags,
 	 * Don't allow anybody to remap normal RAM that we're using.
 	 * mem_init() sets high_memory so only do the check after that.
 	 */
-	if (slab_is_available() && (p < virt_to_phys(high_memory)) &&
-	    !(__allow_ioremap_reserved && memblock_is_region_reserved(p, size))) {
+	if (slab_is_available() && memblock_is_map_memory(p)) {
 		printk("__ioremap(): phys addr 0x%llx is RAM lr %ps\n",
 		       (unsigned long long)p, __builtin_return_address(0));
 		return NULL;
[3]: http://wiibrew.org/wiki/Hardware/Hollywood_GPIOs

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply related

* Re: [RFC PATCH] powerpc/powernv: Provide a way to force a core into SMT4 mode
From: Nicholas Piggin @ 2018-01-27  4:47 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20180127024546.GB5360@fergus.ozlabs.ibm.com>

On Sat, 27 Jan 2018 13:45:46 +1100
Paul Mackerras <paulus@ozlabs.org> wrote:

> On Sat, Jan 27, 2018 at 10:27:35AM +1000, Nicholas Piggin wrote:
> > On Thu, 25 Jan 2018 16:05:12 +1100
> > Paul Mackerras <paulus@ozlabs.org> wrote:
> >   
> > > POWER9 processors up to and including "Nimbus" v2.2 have hardware
> > > bugs relating to transactional memory and thread reconfiguration.
> > > One of these bugs has a workaround which is to get the core into
> > > SMT4 state temporarily.  This workaround is only needed when
> > > running bare-metal.  
> > 
> > How often will this be triggered, in practice? If it's infrequent,
> > then would it be better to just do a smp_call_function on siblings
> > and get them all spinning there? I'm looking sadly at the added
> > sync...  
> 
> We'll need to do this every time we exit a guest vcpu and the CPU is
> in "fake suspend" state, which will be the next exit after entering
> the vcpu when its MSR[TS] = 0b01 (suspend state).  If the vcpu does a
> tresume or treclaim in fake suspend state, that causes a softpatch
> interrupt; the CPU doesn't get out of fake suspend state because of
> any guest instruction, only via hypervisor action.
> 
> So it could be very rare or it could be quite frequent, depending on
> how much usage the guest makes of TM and how long it spends in suspend
> state.
> 
> The smp_call_function on siblings wouldn't work in the case where some
> threads are off-line, since it only works on online CPUs.  Also we
> would need to spin in the function being called on the other CPUs
> (otherwise you could get the situation where they wake up serially and
> you never have 3 or 4 threads simultaneously active), which would make
> me worry about deadlocks in the case where multiple threads are
> concurrently trying to get the core into SMT4 mode.
> 
> If you can think of a way to eliminate the sync without introducing a
> race, I'm all ears.  I haven't been able to.

Okay thanks for the details, yes it would have to be more complex than
a NULL function, I didn't realize offline CPUs would have to be involved.
I'll have a think about it.

A sync is about 1% of the stop/wake overhead, e.g., measured on P9 here
http://patchwork.ozlabs.org/patch/839017/

So it's not a showstopper. The approach seems like it should work AFAIKS.

Thanks,
Nick

^ permalink raw reply

* Re: [RFC PATCH] powerpc/powernv: Provide a way to force a core into SMT4 mode
From: Paul Mackerras @ 2018-01-27  2:45 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linuxppc-dev
In-Reply-To: <20180127102735.5075a560@roar.ozlabs.ibm.com>

On Sat, Jan 27, 2018 at 10:27:35AM +1000, Nicholas Piggin wrote:
> On Thu, 25 Jan 2018 16:05:12 +1100
> Paul Mackerras <paulus@ozlabs.org> wrote:
> 
> > POWER9 processors up to and including "Nimbus" v2.2 have hardware
> > bugs relating to transactional memory and thread reconfiguration.
> > One of these bugs has a workaround which is to get the core into
> > SMT4 state temporarily.  This workaround is only needed when
> > running bare-metal.
> 
> How often will this be triggered, in practice? If it's infrequent,
> then would it be better to just do a smp_call_function on siblings
> and get them all spinning there? I'm looking sadly at the added
> sync...

We'll need to do this every time we exit a guest vcpu and the CPU is
in "fake suspend" state, which will be the next exit after entering
the vcpu when its MSR[TS] = 0b01 (suspend state).  If the vcpu does a
tresume or treclaim in fake suspend state, that causes a softpatch
interrupt; the CPU doesn't get out of fake suspend state because of
any guest instruction, only via hypervisor action.

So it could be very rare or it could be quite frequent, depending on
how much usage the guest makes of TM and how long it spends in suspend
state.

The smp_call_function on siblings wouldn't work in the case where some
threads are off-line, since it only works on online CPUs.  Also we
would need to spin in the function being called on the other CPUs
(otherwise you could get the situation where they wake up serially and
you never have 3 or 4 threads simultaneously active), which would make
me worry about deadlocks in the case where multiple threads are
concurrently trying to get the core into SMT4 mode.

If you can think of a way to eliminate the sync without introducing a
race, I'm all ears.  I haven't been able to.

Paul.

^ permalink raw reply

* Re: [RFC PATCH] powerpc/powernv: Provide a way to force a core into SMT4 mode
From: Paul Mackerras @ 2018-01-27  2:34 UTC (permalink / raw)
  To: Ram Pai; +Cc: linuxppc-dev
In-Reply-To: <20180127010610.GA5428@ram.oc3035372033.ibm.com>

On Fri, Jan 26, 2018 at 05:06:10PM -0800, Ram Pai wrote:
> On Thu, Jan 25, 2018 at 04:05:12PM +1100, Paul Mackerras wrote:
> > POWER9 processors up to and including "Nimbus" v2.2 have hardware
> > bugs relating to transactional memory and thread reconfiguration.
> > One of these bugs has a workaround which is to get the core into
> > SMT4 state temporarily.  This workaround is only needed when
> > running bare-metal.
> 
> ..snip..
> >   */
> >  _GLOBAL(power9_idle_stop)
> >  	std	r3, PACA_REQ_PSSCR(r13)
> 	
> this instruction can go a little later and save a few cycles, in the
> case it need not have to stop ?
> 
> > +	sync
> > +	lwz	r5, PACA_DONT_STOP(r13)
> > +	cmpwi	r5, 0
> > +	bne	1f
> 
> I mean 'std r3, ...' can move here.

That would introduce a race condition, where this thread would miss
seeing the other thread's store to paca->dont_stop, and the other
thread would miss seeing this thread's store to paca->requested_psscr.

> > +	/* order setting dont_stop vs testing requested_psscr */
> > +	mb();
> > +	for (thr = 0; thr < threads_per_core; ++thr) {
> > +		if (!tpaca[thr].requested_psscr)
> > +			++awake_threads;
> > +		else
> > +			poke_threads |= (1 << thr);
> 
> 			ppc_msgsnd(...)  can be called here in the else part?

It could, but I wanted to avoid disturbing the other threads with the
msgsnd if it was not necessary.  Hence the second loop to do the
msgsnds once we have determined that we really need to do them.

> 	
> > +	}
> > +
> > +	/* If at least 3 threads are awake, the core is in SMT4 already */
> 
> small nitpick --  this comment mentions SMT4 and 3 threads. But the code
> is generically applicable to SMTn and (n-1) threads.

Sure - it's easier to understand a concrete example than something
more general, that's why the comment is about the specific use case
not the general capability of the code.

> > +	if (awake_threads < threads_per_core - 1) {
> 
> 
> > +		/* We have to wake some threads; we'll use msgsnd */
> > +		for (thr = 0; thr < threads_per_core; ++thr) {
> > +			if (poke_threads & (1 << thr))
> > +				ppc_msgsnd(PPC_DBELL_MSGTYPE, 0,
> > +					   tpaca[thr].hw_cpu_id);
> > +		}
> 
> and this loop can be deleted, which inturn can leads to further optimizations.

... at the cost of other threads taking doorbell interrupts
unnecessarily.  I thought it better to put more burden on the thread
needing this synchronization and less on the other threads (on
average).

Paul.

^ permalink raw reply

* Re: [RFC PATCH] powerpc/powernv: Provide a way to force a core into SMT4 mode
From: Ram Pai @ 2018-01-27  1:06 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20180125050512.GA18744@fergus.ozlabs.ibm.com>

On Thu, Jan 25, 2018 at 04:05:12PM +1100, Paul Mackerras wrote:
> POWER9 processors up to and including "Nimbus" v2.2 have hardware
> bugs relating to transactional memory and thread reconfiguration.
> One of these bugs has a workaround which is to get the core into
> SMT4 state temporarily.  This workaround is only needed when
> running bare-metal.

..snip..

> 
> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
> ---
>  arch/powerpc/include/asm/paca.h       |  3 ++
>  arch/powerpc/kernel/asm-offsets.c     |  1 +
>  arch/powerpc/kernel/idle_book3s.S     | 15 +++++++++
>  arch/powerpc/platforms/powernv/idle.c | 62 +++++++++++++++++++++++++++++++++++
>  4 files changed, 81 insertions(+)
> 
..snip..
>  	STOP_SPR(STOP_PID, pid);
>  	STOP_SPR(STOP_LDBAR, ldbar);
> diff --git a/arch/powerpc/kernel/idle_book3s.S b/arch/powerpc/kernel/idle_book3s.S
> index 01e1c19..4a7f88c 100644
> --- a/arch/powerpc/kernel/idle_book3s.S
> +++ b/arch/powerpc/kernel/idle_book3s.S
> @@ -430,10 +430,23 @@ ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66);		\
>   */
>  _GLOBAL(power9_idle_stop)
>  	std	r3, PACA_REQ_PSSCR(r13)
	
this instruction can go a little later and save a few cycles, in the
case it need not have to stop ?

> +	sync
> +	lwz	r5, PACA_DONT_STOP(r13)
> +	cmpwi	r5, 0
> +	bne	1f

I mean 'std r3, ...' can move here.

>  	mtspr 	SPRN_PSSCR,r3
>  	LOAD_REG_ADDR(r4,power_enter_stop)
>  	b	pnv_powersave_common
>  	/* No return */
> +1:
> +	/*
> +	 * We get here when TM / thread reconfiguration bug workaround
> +	 * code wants to get the CPU into SMT4 mode, and therefore
> +	 * we are being asked not to stop.
> +	 */
> +	li	r3, 0
> +	std	r3, PACA_REQ_PSSCR(r13)
> +	blr		/* return 0 for wakeup cause / SRR1 value */
> 
>  /*
>   * On waking up from stop 0,1,2 with ESL=1 on POWER9 DD1,
> @@ -584,6 +597,8 @@ FTR_SECTION_ELSE_NESTED(71)
>  	mfspr	r5, SPRN_PSSCR
>  	rldicl  r5,r5,4,60
>  ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_POWER9_DD1, 71)
> +	li	r0, 0		/* clear requested_psscr to say we're awake */
> +	std	r0, PACA_REQ_PSSCR(r13)
>  	cmpd	cr4,r5,r4
>  	bge	cr4,pnv_wakeup_tb_loss /* returns to caller */
> 
> diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
> index 443d5ca..72d5a85 100644
> --- a/arch/powerpc/platforms/powernv/idle.c
> +++ b/arch/powerpc/platforms/powernv/idle.c
> @@ -24,6 +24,7 @@
>  #include <asm/code-patching.h>
>  #include <asm/smp.h>
>  #include <asm/runlatch.h>
> +#include <asm/dbell.h>
> 
>  #include "powernv.h"
>  #include "subcore.h"
> @@ -387,6 +388,67 @@ void power9_idle(void)
>  	power9_idle_type(pnv_default_stop_val, pnv_default_stop_mask);
>  }
> 
> +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> +/*
> + * This is used in working around bugs in thread reconfiguration
> + * on POWER9 (at least up to Nimbus DD2.2) relating to transactional
> + * memory and the way that XER[SO] is checkpointed.
> + * This function forces the core into SMT4 in order by asking
> + * all other threads not to stop, and sending a message to any
> + * that are in a stop state.
> + * Must be called with preemption disabled.
> + */
> +void pnv_power9_force_smt4(void)
> +{
> +	int cpu, cpu0, thr;
> +	struct paca_struct *tpaca;
> +	int awake_threads = 1;		/* this thread is awake */
> +	int poke_threads = 0;
> +
> +	cpu = smp_processor_id();
> +	cpu0 = cpu & ~(threads_per_core - 1);
> +	tpaca = &paca[cpu0];
> +	for (thr = 0; thr < threads_per_core; ++thr) {
> +		if (cpu != cpu0 + thr)
> +			atomic_inc(&tpaca[thr].dont_stop);
> +	}
> +	/* order setting dont_stop vs testing requested_psscr */
> +	mb();
> +	for (thr = 0; thr < threads_per_core; ++thr) {
> +		if (!tpaca[thr].requested_psscr)
> +			++awake_threads;
> +		else
> +			poke_threads |= (1 << thr);

			ppc_msgsnd(...)  can be called here in the else part?
	
> +	}
> +
> +	/* If at least 3 threads are awake, the core is in SMT4 already */

small nitpick --  this comment mentions SMT4 and 3 threads. But the code
is generically applicable to SMTn and (n-1) threads.

> +	if (awake_threads < threads_per_core - 1) {


> +		/* We have to wake some threads; we'll use msgsnd */
> +		for (thr = 0; thr < threads_per_core; ++thr) {
> +			if (poke_threads & (1 << thr))
> +				ppc_msgsnd(PPC_DBELL_MSGTYPE, 0,
> +					   tpaca[thr].hw_cpu_id);
> +		}

and this loop can be deleted, which inturn can leads to further optimizations.


> +		/* now spin until at least 3 threads are awake */
> +		do {
> +			for (thr = 0; thr < threads_per_core; ++thr) {
> +				if ((poke_threads & (1 << thr)) &&
> +				    !tpaca[thr].requested_psscr) {
> +					++awake_threads;
> +					poke_threads &= ~(1 << thr);
> +				}
> +			}
> +		} while (awake_threads < threads_per_core - 1);
> +	}
> +	/* clear all the dont_stop flags */
> +	for (thr = 0; thr < threads_per_core; ++thr) {
> +		if (cpu != cpu0 + thr)
> +			atomic_dec(&tpaca[thr].dont_stop);
> +	}
> +}
> +EXPORT_SYMBOL_GPL(pnv_power9_force_smt4);
> +#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
> +
>  #ifdef CONFIG_HOTPLUG_CPU
>  static void pnv_program_cpu_hotplug_lpcr(unsigned int cpu, u64 lpcr_val)
>  {
> -- 
> 2.7.4

-- 
Ram Pai

^ permalink raw reply

* Re: [RFC PATCH] powerpc/powernv: Provide a way to force a core into SMT4 mode
From: Nicholas Piggin @ 2018-01-27  0:27 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <20180125050512.GA18744@fergus.ozlabs.ibm.com>

On Thu, 25 Jan 2018 16:05:12 +1100
Paul Mackerras <paulus@ozlabs.org> wrote:

> POWER9 processors up to and including "Nimbus" v2.2 have hardware
> bugs relating to transactional memory and thread reconfiguration.
> One of these bugs has a workaround which is to get the core into
> SMT4 state temporarily.  This workaround is only needed when
> running bare-metal.

How often will this be triggered, in practice? If it's infrequent,
then would it be better to just do a smp_call_function on siblings
and get them all spinning there? I'm looking sadly at the added
sync...

Thanks,
Nick

^ permalink raw reply

* Re: [PATCH RESEND V2 ] powerpc/numa: Invalidate numa_cpu_lookup_table on cpu remove
From: Tyrel Datwyler @ 2018-01-27  0:19 UTC (permalink / raw)
  To: Nathan Fontenot, linuxppc-dev
In-Reply-To: <151699561194.20320.12952014708209986173.stgit@ltcalpine2-lp14.aus.stglabs.ibm.com>

On 01/26/2018 11:41 AM, Nathan Fontenot wrote:
> When DLPAR removing a CPU, the unmapping of the cpu from a node in
> unmap_cpu_from_node() should also invalidate the CPUs entry in the
> numa_cpu_lookup_table. There is not a guarantee that on a subsequent
> DLPAR add of the CPU the associativity will be the same and thus
> could be in a different node. Invalidating the entry in the
> numa_cpu_lookup_table causes the associativity to be read from the
> device tree at the time of the add.
> 
> The current behavior of not invalidating the CPUs entry in the
> numa_cpu_lookup_table can result in scenarios where the the topology
> layout of CPUs in the partition does not match the device tree
> or the topology reported by the HMC.
> 
> Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

Reviewed-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>

> ---
> 
> Originally sent Dec. 5 2017, no reply, resending.
> 
> Updates for V2: Move the invalidation from unmap_cpu_from_node to
> pseries_remove_processor, the former routine is also called during cpu
> offline and we do not want to invalidate during cpu offline.
> 
>  arch/powerpc/include/asm/topology.h          |    5 +++++
>  arch/powerpc/mm/numa.c                       |    5 -----
>  arch/powerpc/platforms/pseries/hotplug-cpu.c |    2 ++
>  3 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
> index 88187c285c70..1c02e6900f78 100644
> --- a/arch/powerpc/include/asm/topology.h
> +++ b/arch/powerpc/include/asm/topology.h
> @@ -44,6 +44,11 @@ extern int sysfs_add_device_to_node(struct device *dev, int nid);
>  extern void sysfs_remove_device_from_node(struct device *dev, int nid);
>  extern int numa_update_cpu_topology(bool cpus_locked);
> 
> +static inline void update_numa_cpu_lookup_table(unsigned int cpu, int node)
> +{
> +	numa_cpu_lookup_table[cpu] = node;
> +}
> +
>  static inline int early_cpu_to_node(int cpu)
>  {
>  	int nid;
> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index 268c7a2d9a5b..7ec3a0d787d3 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -143,11 +143,6 @@ static void reset_numa_cpu_lookup_table(void)
>  		numa_cpu_lookup_table[cpu] = -1;
>  }
> 
> -static void update_numa_cpu_lookup_table(unsigned int cpu, int node)
> -{
> -	numa_cpu_lookup_table[cpu] = node;
> -}
> -
>  static void map_cpu_to_node(int cpu, int node)
>  {
>  	update_numa_cpu_lookup_table(cpu, node);
> diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
> index a7d14aa7bb7c..09083ad82f7a 100644
> --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
> +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
> @@ -36,6 +36,7 @@
>  #include <asm/xics.h>
>  #include <asm/xive.h>
>  #include <asm/plpar_wrappers.h>
> +#include <asm/topology.h>
> 
>  #include "pseries.h"
>  #include "offline_states.h"
> @@ -331,6 +332,7 @@ static void pseries_remove_processor(struct device_node *np)
>  			BUG_ON(cpu_online(cpu));
>  			set_cpu_present(cpu, false);
>  			set_hard_smp_processor_id(cpu, -1);
> +			update_numa_cpu_lookup_table(cpu, -1);
>  			break;
>  		}
>  		if (cpu >= nr_cpu_ids)
> 

^ permalink raw reply

* [PATCH RESEND V2 ] powerpc/numa: Invalidate numa_cpu_lookup_table on cpu remove
From: Nathan Fontenot @ 2018-01-26 19:41 UTC (permalink / raw)
  To: linuxppc-dev

When DLPAR removing a CPU, the unmapping of the cpu from a node in
unmap_cpu_from_node() should also invalidate the CPUs entry in the
numa_cpu_lookup_table. There is not a guarantee that on a subsequent
DLPAR add of the CPU the associativity will be the same and thus
could be in a different node. Invalidating the entry in the
numa_cpu_lookup_table causes the associativity to be read from the
device tree at the time of the add.

The current behavior of not invalidating the CPUs entry in the
numa_cpu_lookup_table can result in scenarios where the the topology
layout of CPUs in the partition does not match the device tree
or the topology reported by the HMC.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
---

Originally sent Dec. 5 2017, no reply, resending.

Updates for V2: Move the invalidation from unmap_cpu_from_node to
pseries_remove_processor, the former routine is also called during cpu
offline and we do not want to invalidate during cpu offline.

 arch/powerpc/include/asm/topology.h          |    5 +++++
 arch/powerpc/mm/numa.c                       |    5 -----
 arch/powerpc/platforms/pseries/hotplug-cpu.c |    2 ++
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index 88187c285c70..1c02e6900f78 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -44,6 +44,11 @@ extern int sysfs_add_device_to_node(struct device *dev, int nid);
 extern void sysfs_remove_device_from_node(struct device *dev, int nid);
 extern int numa_update_cpu_topology(bool cpus_locked);
 
+static inline void update_numa_cpu_lookup_table(unsigned int cpu, int node)
+{
+	numa_cpu_lookup_table[cpu] = node;
+}
+
 static inline int early_cpu_to_node(int cpu)
 {
 	int nid;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 268c7a2d9a5b..7ec3a0d787d3 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -143,11 +143,6 @@ static void reset_numa_cpu_lookup_table(void)
 		numa_cpu_lookup_table[cpu] = -1;
 }
 
-static void update_numa_cpu_lookup_table(unsigned int cpu, int node)
-{
-	numa_cpu_lookup_table[cpu] = node;
-}
-
 static void map_cpu_to_node(int cpu, int node)
 {
 	update_numa_cpu_lookup_table(cpu, node);
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index a7d14aa7bb7c..09083ad82f7a 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -36,6 +36,7 @@
 #include <asm/xics.h>
 #include <asm/xive.h>
 #include <asm/plpar_wrappers.h>
+#include <asm/topology.h>
 
 #include "pseries.h"
 #include "offline_states.h"
@@ -331,6 +332,7 @@ static void pseries_remove_processor(struct device_node *np)
 			BUG_ON(cpu_online(cpu));
 			set_cpu_present(cpu, false);
 			set_hard_smp_processor_id(cpu, -1);
+			update_numa_cpu_lookup_table(cpu, -1);
 			break;
 		}
 		if (cpu >= nr_cpu_ids)

^ permalink raw reply related

* [PATCH] crypto: talitos: fix Kernel Oops on hashing an empty file
From: Christophe Leroy @ 2018-01-26 16:09 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller; +Cc: linux-crypto, linux-kernel, linuxppc-dev

Performing the hash of an empty file leads to a kernel Oops

[   44.504600] Unable to handle kernel paging request for data at address 0x0000000c
[   44.512819] Faulting instruction address: 0xc02d2be8
[   44.524088] Oops: Kernel access of bad area, sig: 11 [#1]
[   44.529171] BE PREEMPT CMPC885
[   44.532232] CPU: 0 PID: 491 Comm: md5sum Not tainted 4.15.0-rc8-00211-g3a968610b6ea #81
[   44.540814] NIP:  c02d2be8 LR: c02d2984 CTR: 00000000
[   44.545812] REGS: c6813c90 TRAP: 0300   Not tainted  (4.15.0-rc8-00211-g3a968610b6ea)
[   44.554223] MSR:  00009032 <EE,ME,IR,DR,RI>  CR: 48222822  XER: 20000000
[   44.560855] DAR: 0000000c DSISR: c0000000
[   44.560855] GPR00: c02d28fc c6813d40 c6828000 c646fa40 00000001 00000001 00000001 00000000
[   44.560855] GPR08: 0000004c 00000000 c000bfcc 00000000 28222822 100280d4 00000000 10020008
[   44.560855] GPR16: 00000000 00000020 00000000 00000000 10024008 00000000 c646f9f0 c6179a10
[   44.560855] GPR24: 00000000 00000001 c62f0018 c6179a10 00000000 c6367a30 c62f0000 c646f9c0
[   44.598542] NIP [c02d2be8] ahash_process_req+0x448/0x700
[   44.603751] LR [c02d2984] ahash_process_req+0x1e4/0x700
[   44.608868] Call Trace:
[   44.611329] [c6813d40] [c02d28fc] ahash_process_req+0x15c/0x700 (unreliable)
[   44.618302] [c6813d90] [c02060c4] hash_recvmsg+0x11c/0x210
[   44.623716] [c6813db0] [c0331354] ___sys_recvmsg+0x98/0x138
[   44.629226] [c6813eb0] [c03332c0] __sys_recvmsg+0x40/0x84
[   44.634562] [c6813f10] [c03336c0] SyS_socketcall+0xb8/0x1d4
[   44.640073] [c6813f40] [c000d1ac] ret_from_syscall+0x0/0x38
[   44.645530] Instruction dump:
[   44.648465] 38c00001 7f63db78 4e800421 7c791b78 54690ffe 0f090000 80ff0190 2f870000
[   44.656122] 40befe50 2f990001 409e0210 813f01bc <8129000c> b39e003a 7d29c214 913e003c

This patch fixes that Oops by checking if src is NULL.

Fixes: 6a1e8d14156d4 ("crypto: talitos - making mapping helpers more generic")
Cc: <stable@vger.kernel.org>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 drivers/crypto/talitos.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 9c80e0cb1664..6882fa2f8bad 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -1138,6 +1138,10 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src,
 	struct talitos_private *priv = dev_get_drvdata(dev);
 	bool is_sec1 = has_ftr_sec1(priv);
 
+	if (!src) {
+		to_talitos_ptr(ptr, 0, 0, is_sec1);
+		return 1;
+	}
 	if (sg_count == 1) {
 		to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1);
 		return sg_count;
-- 
2.13.3

^ permalink raw reply related

* Re: [PATCH v2 12/13] ocxl: Documentation
From: Frederic Barrat @ 2018-01-26 15:10 UTC (permalink / raw)
  To: Greg KH; +Cc: linuxppc-dev, linux-kernel, arnd, mpe, andrew.donnellan, alastair
In-Reply-To: <20180125131748.GB8576@kroah.com>



Le 25/01/2018 à 14:17, Greg KH a écrit :
> On Tue, Jan 23, 2018 at 12:31:47PM +0100, Frederic Barrat wrote:
>> ocxl.rst gives a quick, high-level view of opencapi.
>>
>> Update ioctl-number.txt to reflect ioctl numbers being used by the
>> ocxl driver
>>
>> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com>
>> ---
>>   Documentation/ABI/testing/sysfs-class-ocxl |  35 +++++++
>>   Documentation/accelerators/ocxl.rst        | 160 +++++++++++++++++++++++++++++
>>   Documentation/ioctl/ioctl-number.txt       |   1 +
>>   3 files changed, 196 insertions(+)
>>   create mode 100644 Documentation/ABI/testing/sysfs-class-ocxl
>>   create mode 100644 Documentation/accelerators/ocxl.rst
>>
>> diff --git a/Documentation/ABI/testing/sysfs-class-ocxl b/Documentation/ABI/testing/sysfs-class-ocxl
>> new file mode 100644
>> index 000000000000..ac11deb71235
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-class-ocxl
>> @@ -0,0 +1,35 @@
>> +What:           /sys/class/ocxl/<afu name>/afu_version
>> +Date:           January 2018
>> +Contact:        linuxppc-dev@lists.ozlabs.org
>> +Description:    read only
>> +                Version of the AFU, in the format <major>:<minor>
>> +		Reflects what is read in the configuration space of the AFU
> 
> Odd mix of tabs and spaces in this file, please just use tabs.

Oops! Will fix.

   Fred


> thanks,
> 
> greg k-h
> 

^ permalink raw reply

* [PATCH 2/2] selftests/powerpc: Add core file test for Protection Key registers
From: Thiago Jung Bauermann @ 2018-01-26  5:55 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: linux-kselftest, linux-kernel, Michael Ellerman, Ram Pai,
	Thiago Jung Bauermann
In-Reply-To: <20180126055523.29456-1-bauerman@linux.vnet.ibm.com>

This test verifies that the AMR, IAMR and UAMOR are being written to a
process' core file.

Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
---
 tools/testing/selftests/powerpc/ptrace/Makefile    |   5 +-
 tools/testing/selftests/powerpc/ptrace/core-pkey.c | 460 +++++++++++++++++++++
 2 files changed, 464 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/ptrace/core-pkey.c

diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index 707ba734faf2..a10916c3f3e1 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
               ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \
-              ptrace-tm-spd-vsx ptrace-tm-spr ptrace-pkey
+              ptrace-tm-spd-vsx ptrace-tm-spr ptrace-pkey core-pkey
 
 include ../../lib.mk
 
@@ -12,6 +12,9 @@ CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie
 ptrace-pkey: ../harness.c ../utils.c ../lib/reg.S ptrace.h child.h ptrace-pkey.c
 	$(LINK.c) $^ $(LDLIBS) -pthread -o $@
 
+core-pkey: ../harness.c ../utils.c ../lib/reg.S ptrace.h child.h core-pkey.c
+	$(LINK.c) $^ $(LDLIBS) -pthread -o $@
+
 $(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
 
 clean:
diff --git a/tools/testing/selftests/powerpc/ptrace/core-pkey.c b/tools/testing/selftests/powerpc/ptrace/core-pkey.c
new file mode 100644
index 000000000000..ddbe0f2caf70
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/core-pkey.c
@@ -0,0 +1,460 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Ptrace test for Memory Protection Key registers
+ *
+ * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
+ * Copyright (C) 2018 IBM Corporation.
+ */
+#include <limits.h>
+#include <linux/kernel.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "ptrace.h"
+#include "child.h"
+
+#ifndef __NR_pkey_alloc
+#define __NR_pkey_alloc		384
+#endif
+
+#ifndef __NR_pkey_free
+#define __NR_pkey_free		385
+#endif
+
+#ifndef NT_PPC_PKEY
+#define NT_PPC_PKEY		0x110
+#endif
+
+#ifndef PKEY_DISABLE_EXECUTE
+#define PKEY_DISABLE_EXECUTE	0x4
+#endif
+
+#define AMR_BITS_PER_PKEY 2
+#define PKEY_REG_BITS (sizeof(u64) * 8)
+#define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY))
+
+#define CORE_FILE_LIMIT	(5 * 1024 * 1024)	/* 5 MB should be enough */
+
+static const char core_pattern_file[] = "/proc/sys/kernel/core_pattern";
+
+static const char user_write[] = "[User Write (Running)]";
+static const char core_read_running[] = "[Core Read (Running)]";
+
+/* Information shared between the parent and the child. */
+struct shared_info {
+	struct child_sync child_sync;
+
+	/* AMR value the parent expects to read in the core file. */
+	unsigned long amr;
+
+	/* IAMR value the parent expects to read in the core file. */
+	unsigned long iamr;
+
+	/* UAMOR value the parent expects to read in the core file. */
+	unsigned long uamor;
+
+	/* When the child crashed. */
+	time_t core_time;
+};
+
+static int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights)
+{
+	return syscall(__NR_pkey_alloc, flags, init_access_rights);
+}
+
+static int sys_pkey_free(int pkey)
+{
+	return syscall(__NR_pkey_free, pkey);
+}
+
+static int increase_core_file_limit(void)
+{
+	struct rlimit rlim;
+	int ret;
+
+	ret = getrlimit(RLIMIT_CORE, &rlim);
+	FAIL_IF(ret);
+
+	if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < CORE_FILE_LIMIT) {
+		rlim.rlim_cur = CORE_FILE_LIMIT;
+
+		if (rlim.rlim_max != RLIM_INFINITY &&
+		    rlim.rlim_max < CORE_FILE_LIMIT)
+			rlim.rlim_max = CORE_FILE_LIMIT;
+
+		ret = setrlimit(RLIMIT_CORE, &rlim);
+		FAIL_IF(ret);
+	}
+
+	ret = getrlimit(RLIMIT_FSIZE, &rlim);
+	FAIL_IF(ret);
+
+	if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < CORE_FILE_LIMIT) {
+		rlim.rlim_cur = CORE_FILE_LIMIT;
+
+		if (rlim.rlim_max != RLIM_INFINITY &&
+		    rlim.rlim_max < CORE_FILE_LIMIT)
+			rlim.rlim_max = CORE_FILE_LIMIT;
+
+		ret = setrlimit(RLIMIT_FSIZE, &rlim);
+		FAIL_IF(ret);
+	}
+
+	return TEST_PASS;
+}
+
+static int child(struct shared_info *info)
+{
+	bool disable_execute = true;
+	int pkey1, pkey2, pkey3;
+	int *ptr, ret;
+
+	/* Wait until parent fills out the initial register values. */
+	ret = wait_parent(&info->child_sync);
+	if (ret)
+		return ret;
+
+	ret = increase_core_file_limit();
+	FAIL_IF(ret);
+
+	/* Get some pkeys so that we can change their bits in the AMR. */
+	pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE);
+	if (pkey1 < 0) {
+		pkey1 = sys_pkey_alloc(0, 0);
+		FAIL_IF(pkey1 < 0);
+
+		disable_execute = false;
+	}
+
+	pkey2 = sys_pkey_alloc(0, 0);
+	FAIL_IF(pkey2 < 0);
+
+	pkey3 = sys_pkey_alloc(0, 0);
+	FAIL_IF(pkey3 < 0);
+
+	info->amr |= 3ul << pkeyshift(pkey1) | 2ul << pkeyshift(pkey2);
+
+	if (disable_execute)
+		info->iamr |= 1ul << pkeyshift(pkey1);
+
+	info->uamor |= 3ul << pkeyshift(pkey1) | 3ul << pkeyshift(pkey2);
+
+	printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n",
+	       user_write, info->amr, pkey1, pkey2, pkey3);
+
+	mtspr(SPRN_AMR, info->amr);
+
+	/*
+	 * We won't use pkey3. This tests whether the kernel restores the UAMOR
+	 * permissions after a key is freed.
+	 */
+	sys_pkey_free(pkey3);
+
+	info->core_time = time(NULL);
+
+	/* Crash. */
+	ptr = 0;
+	*ptr = 1;
+
+	/* Shouldn't get here. */
+	FAIL_IF(true);
+
+	return TEST_FAIL;
+}
+
+/* Return file size if filename exists and pass sanity check, or zero if not. */
+static off_t try_core_file(const char *filename, struct shared_info *info,
+			   pid_t pid)
+{
+	struct stat buf;
+	int ret;
+
+	ret = stat(filename, &buf);
+	if (ret == -1)
+		return TEST_FAIL;
+
+	/* Make sure we're not using a stale core file. */
+	return buf.st_mtime >= info->core_time ? buf.st_size : TEST_FAIL;
+}
+
+static Elf64_Nhdr *next_note(Elf64_Nhdr *nhdr)
+{
+	return (void *) nhdr + sizeof(*nhdr) +
+		__ALIGN_KERNEL(nhdr->n_namesz, 4) +
+		__ALIGN_KERNEL(nhdr->n_descsz, 4);
+}
+
+static int check_core_file(struct shared_info *info, Elf64_Ehdr *ehdr,
+			   off_t core_size)
+{
+	unsigned long *regs;
+	Elf64_Phdr *phdr;
+	Elf64_Nhdr *nhdr;
+	size_t phdr_size;
+	void *p = ehdr, *note;
+	int ret;
+
+	ret = memcmp(ehdr->e_ident, ELFMAG, SELFMAG);
+	FAIL_IF(ret);
+
+	FAIL_IF(ehdr->e_type != ET_CORE);
+	FAIL_IF(ehdr->e_machine != EM_PPC64);
+	FAIL_IF(ehdr->e_phoff == 0 || ehdr->e_phnum == 0);
+
+	/*
+	 * e_phnum is at most 65535 so calculating the size of the
+	 * program header cannot overflow.
+	 */
+	phdr_size = sizeof(*phdr) * ehdr->e_phnum;
+
+	/* Sanity check the program header table location. */
+	FAIL_IF(ehdr->e_phoff + phdr_size < ehdr->e_phoff);
+	FAIL_IF(ehdr->e_phoff + phdr_size > core_size);
+
+	/* Find the PT_NOTE segment. */
+	for (phdr = p + ehdr->e_phoff;
+	     (void *) phdr < p + ehdr->e_phoff + phdr_size;
+	     phdr += ehdr->e_phentsize)
+		if (phdr->p_type == PT_NOTE)
+			break;
+
+	FAIL_IF((void *) phdr >= p + ehdr->e_phoff + phdr_size);
+
+	/* Find the NT_PPC_PKEY note. */
+	for (nhdr = p + phdr->p_offset;
+	     (void *) nhdr < p + phdr->p_offset + phdr->p_filesz;
+	     nhdr = next_note(nhdr))
+		if (nhdr->n_type == NT_PPC_PKEY)
+			break;
+
+	FAIL_IF((void *) nhdr >= p + phdr->p_offset + phdr->p_filesz);
+	FAIL_IF(nhdr->n_descsz == 0);
+
+	p = nhdr;
+	note = p + sizeof(*nhdr) + __ALIGN_KERNEL(nhdr->n_namesz, 4);
+
+	regs = (unsigned long *) note;
+
+	printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
+	       core_read_running, regs[0], regs[1], regs[2]);
+
+	FAIL_IF(regs[0] != info->amr);
+	FAIL_IF(regs[1] != info->iamr);
+	FAIL_IF(regs[2] != info->uamor);
+
+	return TEST_PASS;
+}
+
+static int parent(struct shared_info *info, pid_t pid)
+{
+	char *filenames, *filename[3];
+	int fd, i, ret, status;
+	unsigned long regs[3];
+	off_t core_size;
+	void *core;
+
+	/*
+	 * Get the initial values for AMR, IAMR and UAMOR and communicate them
+	 * to the child.
+	 */
+	ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	info->amr = regs[0];
+	info->iamr = regs[1];
+	info->uamor = regs[2];
+
+	/* Wake up child so that it can set itself up. */
+	ret = prod_child(&info->child_sync);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait(&status);
+	if (ret != pid) {
+		printf("Child's exit status not captured\n");
+		return TEST_FAIL;
+	} else if (!WIFSIGNALED(status) || !WCOREDUMP(status)) {
+		printf("Child didn't dump core\n");
+		return TEST_FAIL;
+	}
+
+	/* Construct array of core file names to try. */
+
+	filename[0] = filenames = malloc(PATH_MAX);
+	if (!filenames) {
+		perror("Error allocating memory");
+		return TEST_FAIL;
+	}
+
+	ret = snprintf(filename[0], PATH_MAX, "core-pkey.%d", pid);
+	if (ret < 0 || ret >= PATH_MAX) {
+		ret = TEST_FAIL;
+		goto out;
+	}
+
+	filename[1] = filename[0] + ret + 1;
+	ret = snprintf(filename[1], PATH_MAX - ret - 1, "core.%d", pid);
+	if (ret < 0 || ret >= PATH_MAX - ret - 1) {
+		ret = TEST_FAIL;
+		goto out;
+	}
+	filename[2] = "core";
+
+	for (i = 0; i < 3; i++) {
+		core_size = try_core_file(filename[i], info, pid);
+		if (core_size != TEST_FAIL)
+			break;
+	}
+
+	if (i == 3) {
+		printf("Couldn't find core file\n");
+		ret = TEST_FAIL;
+		goto out;
+	}
+
+	fd = open(filename[i], O_RDONLY);
+	if (fd == -1) {
+		perror("Error opening core file");
+		ret = TEST_FAIL;
+		goto out;
+	}
+
+	core = mmap(NULL, core_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	if (core == (void *) -1) {
+		perror("Error mmaping core file");
+		ret = TEST_FAIL;
+		goto out;
+	}
+
+	ret = check_core_file(info, core, core_size);
+
+	munmap(core, core_size);
+	close(fd);
+	unlink(filename[i]);
+
+ out:
+	free(filenames);
+
+	return ret;
+}
+
+static int write_core_pattern(const char *core_pattern)
+{
+	size_t len = strlen(core_pattern), ret;
+	FILE *f;
+
+	f = fopen(core_pattern_file, "w");
+	if (!f) {
+		perror("Error writing to core_pattern file");
+		return TEST_FAIL;
+	}
+
+	ret = fwrite(core_pattern, 1, len, f);
+	fclose(f);
+	if (ret != len) {
+		perror("Error writing to core_pattern file");
+		return TEST_FAIL;
+	}
+
+	return TEST_PASS;
+}
+
+static int setup_core_pattern(char **core_pattern_, bool *changed_)
+{
+	FILE *f;
+	char *core_pattern;
+	int ret;
+
+	core_pattern = malloc(PATH_MAX);
+	if (!core_pattern) {
+		perror("Error allocating memory");
+		return TEST_FAIL;
+	}
+
+	f = fopen(core_pattern_file, "r");
+	if (!f) {
+		perror("Error opening core_pattern file");
+		ret = TEST_FAIL;
+		goto out;
+	}
+
+	ret = fread(core_pattern, 1, PATH_MAX, f);
+	fclose(f);
+	if (!ret) {
+		perror("Error reading core_pattern file");
+		ret = TEST_FAIL;
+		goto out;
+	}
+
+	/* Check whether we can predict the name of the core file. */
+	if (!strcmp(core_pattern, "core") || !strcmp(core_pattern, "core.%p"))
+		*changed_ = false;
+	else {
+		ret = write_core_pattern("core-pkey.%p");
+		if (ret)
+			goto out;
+
+		*changed_ = true;
+	}
+
+	*core_pattern_ = core_pattern;
+	ret = TEST_PASS;
+
+ out:
+	if (ret)
+		free(core_pattern);
+
+	return ret;
+}
+
+static int core_pkey(void)
+{
+	char *core_pattern;
+	bool changed_core_pattern;
+	struct shared_info *info;
+	int shm_id;
+	int ret;
+	pid_t pid;
+
+	ret = setup_core_pattern(&core_pattern, &changed_core_pattern);
+	if (ret)
+		return ret;
+
+	shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT);
+	info = shmat(shm_id, NULL, 0);
+
+	ret = init_child_sync(&info->child_sync);
+	if (ret)
+		return ret;
+
+	pid = fork();
+	if (pid < 0) {
+		perror("fork() failed");
+		ret = TEST_FAIL;
+	} else if (pid == 0)
+		ret = child(info);
+	else
+		ret = parent(info, pid);
+
+	shmdt(info);
+
+	if (pid) {
+		destroy_child_sync(&info->child_sync);
+		shmctl(shm_id, IPC_RMID, NULL);
+
+		if (changed_core_pattern)
+			write_core_pattern(core_pattern);
+	}
+
+	free(core_pattern);
+
+	return ret;
+}
+
+int main(int argc, char *argv[])
+{
+	return test_harness(core_pkey, "core_pkey");
+}

^ permalink raw reply related

* [PATCH 1/2] selftests/powerpc: Add ptrace tests for Protection Key registers
From: Thiago Jung Bauermann @ 2018-01-26  5:55 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: linux-kselftest, linux-kernel, Michael Ellerman, Ram Pai,
	Thiago Jung Bauermann
In-Reply-To: <20180126055523.29456-1-bauerman@linux.vnet.ibm.com>

This test exercises read and write access to the AMR, IAMR and UAMOR.

Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
---
 tools/testing/selftests/powerpc/include/reg.h      |   1 +
 tools/testing/selftests/powerpc/ptrace/Makefile    |   5 +-
 tools/testing/selftests/powerpc/ptrace/child.h     | 130 ++++++++
 .../testing/selftests/powerpc/ptrace/ptrace-pkey.c | 326 +++++++++++++++++++++
 tools/testing/selftests/powerpc/ptrace/ptrace.h    |  37 +++
 5 files changed, 498 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/ptrace/child.h
 create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c

diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h
index 4afdebcce4cd..7f348c059bc2 100644
--- a/tools/testing/selftests/powerpc/include/reg.h
+++ b/tools/testing/selftests/powerpc/include/reg.h
@@ -54,6 +54,7 @@
 #define SPRN_DSCR_PRIV 0x11	/* Privilege State DSCR */
 #define SPRN_DSCR      0x03	/* Data Stream Control Register */
 #define SPRN_PPR       896	/* Program Priority Register */
+#define SPRN_AMR       13	/* Authority Mask Register - problem state */
 
 /* TEXASR register bits */
 #define TEXASR_FC	0xFE00000000000000
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile
index 480305266504..707ba734faf2 100644
--- a/tools/testing/selftests/powerpc/ptrace/Makefile
+++ b/tools/testing/selftests/powerpc/ptrace/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \
               ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \
-              ptrace-tm-spd-vsx ptrace-tm-spr
+              ptrace-tm-spd-vsx ptrace-tm-spr ptrace-pkey
 
 include ../../lib.mk
 
@@ -9,6 +9,9 @@ all: $(TEST_PROGS)
 
 CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie
 
+ptrace-pkey: ../harness.c ../utils.c ../lib/reg.S ptrace.h child.h ptrace-pkey.c
+	$(LINK.c) $^ $(LDLIBS) -pthread -o $@
+
 $(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h
 
 clean:
diff --git a/tools/testing/selftests/powerpc/ptrace/child.h b/tools/testing/selftests/powerpc/ptrace/child.h
new file mode 100644
index 000000000000..40c1a6d92111
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/child.h
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Helper functions to sync execution between parent and child processes.
+ *
+ * Copyright 2018, Thiago Jung Bauermann, IBM Corporation.
+ */
+#include <stdio.h>
+#include <stdbool.h>
+#include <semaphore.h>
+
+/*
+ * Information in a shared memory location for synchronization between child and
+ * parent.
+ */
+struct child_sync {
+	/* The parent waits on this semaphore. */
+	sem_t sem_parent;
+
+	/* If true, the child should give up as well. */
+	bool parent_gave_up;
+
+	/* The child waits on this semaphore. */
+	sem_t sem_child;
+
+	/* If true, the parent should give up as well. */
+	bool child_gave_up;
+};
+
+#define CHILD_FAIL_IF(x, sync)						\
+	do {								\
+		if (x) {						\
+			fprintf(stderr,					\
+				"[FAIL] Test FAILED on line %d\n", __LINE__); \
+			(sync)->child_gave_up = true;			\
+			prod_parent(sync);				\
+			return 1;					\
+		}							\
+	} while (0)
+
+#define PARENT_FAIL_IF(x, sync)						\
+	do {								\
+		if (x) {						\
+			fprintf(stderr,					\
+				"[FAIL] Test FAILED on line %d\n", __LINE__); \
+			(sync)->parent_gave_up = true;			\
+			prod_child(sync);				\
+			return 1;					\
+		}							\
+	} while (0)
+
+int init_child_sync(struct child_sync *sync)
+{
+	int ret;
+
+	ret = sem_init(&sync->sem_parent, 1, 0);
+	if (ret) {
+		perror("Semaphore initialization failed");
+		return 1;
+	}
+
+	ret = sem_init(&sync->sem_child, 1, 0);
+	if (ret) {
+		perror("Semaphore initialization failed");
+		return 1;
+	}
+
+	return 0;
+}
+
+void destroy_child_sync(struct child_sync *sync)
+{
+	sem_destroy(&sync->sem_parent);
+	sem_destroy(&sync->sem_child);
+}
+
+int wait_child(struct child_sync *sync)
+{
+	int ret;
+
+	/* Wait until the child prods us. */
+	ret = sem_wait(&sync->sem_parent);
+	if (ret) {
+		perror("Error waiting for child");
+		return 1;
+	}
+
+	return sync->child_gave_up;
+}
+
+int prod_child(struct child_sync *sync)
+{
+	int ret;
+
+	/* Unblock the child now. */
+	ret = sem_post(&sync->sem_child);
+	if (ret) {
+		perror("Error prodding child");
+		return 1;
+	}
+
+	return 0;
+}
+
+int wait_parent(struct child_sync *sync)
+{
+	int ret;
+
+	/* Wait until the parent prods us. */
+	ret = sem_wait(&sync->sem_child);
+	if (ret) {
+		perror("Error waiting for parent");
+		return 1;
+	}
+
+	return sync->parent_gave_up;
+}
+
+int prod_parent(struct child_sync *sync)
+{
+	int ret;
+
+	/* Unblock the parent now. */
+	ret = sem_post(&sync->sem_parent);
+	if (ret) {
+		perror("Error prodding parent");
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c b/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c
new file mode 100644
index 000000000000..8332b9338d39
--- /dev/null
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Ptrace test for Memory Protection Key registers
+ *
+ * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
+ * Copyright (C) 2018 IBM Corporation.
+ */
+#include "ptrace.h"
+#include "child.h"
+
+#ifndef __NR_pkey_alloc
+#define __NR_pkey_alloc		384
+#endif
+
+#ifndef __NR_pkey_free
+#define __NR_pkey_free		385
+#endif
+
+#ifndef NT_PPC_PKEY
+#define NT_PPC_PKEY		0x110
+#endif
+
+#ifndef PKEY_DISABLE_EXECUTE
+#define PKEY_DISABLE_EXECUTE	0x4
+#endif
+
+#define AMR_BITS_PER_PKEY 2
+#define PKEY_REG_BITS (sizeof(u64) * 8)
+#define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY))
+
+static const char user_read[] = "[User Read (Running)]";
+static const char user_write[] = "[User Write (Running)]";
+static const char ptrace_read_running[] = "[Ptrace Read (Running)]";
+static const char ptrace_write_running[] = "[Ptrace Write (Running)]";
+
+/* Information shared between the parent and the child. */
+struct shared_info {
+	struct child_sync child_sync;
+
+	/* AMR value the parent expects to read from the child. */
+	unsigned long amr1;
+
+	/* AMR value the parent is expected to write to the child. */
+	unsigned long amr2;
+
+	/* AMR value that ptrace should refuse to write to the child. */
+	unsigned long amr3;
+
+	/* IAMR value the parent expects to read from the child. */
+	unsigned long expected_iamr;
+
+	/* UAMOR value the parent expects to read from the child. */
+	unsigned long expected_uamor;
+
+	/*
+	 * IAMR and UAMOR values that ptrace should refuse to write to the child
+	 * (even though they're valid ones) because userspace doesn't have
+	 * access to those registers.
+	 */
+	unsigned long new_iamr;
+	unsigned long new_uamor;
+};
+
+static int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights)
+{
+	return syscall(__NR_pkey_alloc, flags, init_access_rights);
+}
+
+static int sys_pkey_free(int pkey)
+{
+	return syscall(__NR_pkey_free, pkey);
+}
+
+static int child(struct shared_info *info)
+{
+	unsigned long reg;
+	bool disable_execute = true;
+	int pkey1, pkey2, pkey3;
+	int ret;
+
+	/* Wait until parent fills out the initial register values. */
+	ret = wait_parent(&info->child_sync);
+	if (ret)
+		return ret;
+
+	/* Get some pkeys so that we can change their bits in the AMR. */
+	pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE);
+	if (pkey1 < 0) {
+		pkey1 = sys_pkey_alloc(0, 0);
+		CHILD_FAIL_IF(pkey1 < 0, &info->child_sync);
+
+		disable_execute = false;
+	}
+
+	pkey2 = sys_pkey_alloc(0, 0);
+	CHILD_FAIL_IF(pkey2 < 0, &info->child_sync);
+
+	pkey3 = sys_pkey_alloc(0, 0);
+	CHILD_FAIL_IF(pkey3 < 0, &info->child_sync);
+
+	info->amr1 |= 3ul << pkeyshift(pkey1);
+	info->amr2 |= 3ul << pkeyshift(pkey2);
+	info->amr3 |= info->amr2 | 3ul << pkeyshift(pkey3);
+
+	if (disable_execute)
+		info->expected_iamr |= 1ul << pkeyshift(pkey1);
+
+	info->expected_uamor |= 3ul << pkeyshift(pkey1) |
+				3ul << pkeyshift(pkey2);
+	info->new_iamr |= 1ul << pkeyshift(pkey1) | 1ul << pkeyshift(pkey2);
+	info->new_uamor |= 3ul << pkeyshift(pkey1);
+
+	/*
+	 * We won't use pkey3. We just want a plausible but invalid key to test
+	 * whether ptrace will let us write to AMR bits we are not supposed to.
+	 *
+	 * This also tests whether the kernel restores the UAMOR permissions
+	 * after a key is freed.
+	 */
+	sys_pkey_free(pkey3);
+
+	printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n",
+	       user_write, info->amr1, pkey1, pkey2, pkey3);
+
+	mtspr(SPRN_AMR, info->amr1);
+
+	/* Wait for parent to read our AMR value and write a new one. */
+	ret = prod_parent(&info->child_sync);
+	CHILD_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait_parent(&info->child_sync);
+	if (ret)
+		return ret;
+
+	reg = mfspr(SPRN_AMR);
+
+	printf("%-30s AMR: %016lx\n", user_read, reg);
+
+	CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
+
+	/*
+	 * Wait for parent to try to write an invalid AMR value.
+	 */
+	ret = prod_parent(&info->child_sync);
+	CHILD_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait_parent(&info->child_sync);
+	if (ret)
+		return ret;
+
+	reg = mfspr(SPRN_AMR);
+
+	printf("%-30s AMR: %016lx\n", user_read, reg);
+
+	CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
+
+	/*
+	 * Wait for parent to try to write an IAMR and a UAMOR value. We can't
+	 * verify them, but we can verify that the AMR didn't change.
+	 */
+	ret = prod_parent(&info->child_sync);
+	CHILD_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait_parent(&info->child_sync);
+	if (ret)
+		return ret;
+
+	reg = mfspr(SPRN_AMR);
+
+	printf("%-30s AMR: %016lx\n", user_read, reg);
+
+	CHILD_FAIL_IF(reg != info->amr2, &info->child_sync);
+
+	/* Now let parent now that we are finished. */
+
+	ret = prod_parent(&info->child_sync);
+	CHILD_FAIL_IF(ret, &info->child_sync);
+
+	return TEST_PASS;
+}
+
+static int parent(struct shared_info *info, pid_t pid)
+{
+	unsigned long regs[3];
+	int ret, status;
+
+	/*
+	 * Get the initial values for AMR, IAMR and UAMOR and communicate them
+	 * to the child.
+	 */
+	ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	info->amr1 = info->amr2 = info->amr3 = regs[0];
+	info->expected_iamr = info->new_iamr = regs[1];
+	info->expected_uamor = info->new_uamor = regs[2];
+
+	/* Wake up child so that it can set itself up. */
+	ret = prod_child(&info->child_sync);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait_child(&info->child_sync);
+	if (ret)
+		return ret;
+
+	/* Verify that we can read the pkey registers from the child. */
+	ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
+	       ptrace_read_running, regs[0], regs[1], regs[2]);
+
+	PARENT_FAIL_IF(regs[0] != info->amr1, &info->child_sync);
+	PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync);
+	PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync);
+
+	/* Write valid AMR value in child. */
+	ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->amr2, 1);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	printf("%-30s AMR: %016lx\n", ptrace_write_running, info->amr2);
+
+	/* Wake up child so that it can verify it changed. */
+	ret = prod_child(&info->child_sync);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait_child(&info->child_sync);
+	if (ret)
+		return ret;
+
+	/* Write invalid AMR value in child. */
+	ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->amr3, 1);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	printf("%-30s AMR: %016lx\n", ptrace_write_running, info->amr3);
+
+	/* Wake up child so that it can verify it didn't change. */
+	ret = prod_child(&info->child_sync);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait_child(&info->child_sync);
+	if (ret)
+		return ret;
+
+	/* Try to write to IAMR. */
+	regs[0] = info->amr1;
+	regs[1] = info->new_iamr;
+	ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 2);
+	PARENT_FAIL_IF(!ret, &info->child_sync);
+
+	printf("%-30s AMR: %016lx IAMR: %016lx\n",
+	       ptrace_write_running, regs[0], regs[1]);
+
+	/* Try to write to IAMR and UAMOR. */
+	regs[2] = info->new_uamor;
+	ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 3);
+	PARENT_FAIL_IF(!ret, &info->child_sync);
+
+	printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
+	       ptrace_write_running, regs[0], regs[1], regs[2]);
+
+	/* Verify that all registers still have their expected values. */
+	ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n",
+	       ptrace_read_running, regs[0], regs[1], regs[2]);
+
+	PARENT_FAIL_IF(regs[0] != info->amr2, &info->child_sync);
+	PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync);
+	PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync);
+
+	/* Wake up child so that it can verify AMR didn't change and wrap up. */
+	ret = prod_child(&info->child_sync);
+	PARENT_FAIL_IF(ret, &info->child_sync);
+
+	ret = wait(&status);
+	if (ret != pid) {
+		printf("Child's exit status not captured\n");
+		ret = TEST_PASS;
+	} else if (!WIFEXITED(status)) {
+		printf("Child exited abnormally\n");
+		ret = TEST_FAIL;
+	} else
+		ret = WEXITSTATUS(status) ? TEST_FAIL : TEST_PASS;
+
+	return ret;
+}
+
+static int ptrace_pkey(void)
+{
+	struct shared_info *info;
+	int shm_id;
+	int ret;
+	pid_t pid;
+
+	shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT);
+	info = shmat(shm_id, NULL, 0);
+
+	ret = init_child_sync(&info->child_sync);
+	if (ret)
+		return ret;
+
+	pid = fork();
+	if (pid < 0) {
+		perror("fork() failed");
+		ret = TEST_FAIL;
+	} else if (pid == 0)
+		ret = child(info);
+	else
+		ret = parent(info, pid);
+
+	shmdt(info);
+
+	if (pid) {
+		destroy_child_sync(&info->child_sync);
+		shmctl(shm_id, IPC_RMID, NULL);
+	}
+
+	return ret;
+}
+
+int main(int argc, char *argv[])
+{
+	return test_harness(ptrace_pkey, "ptrace_pkey");
+}
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h
index 19fb825270a1..d2c9c4c2b5ee 100644
--- a/tools/testing/selftests/powerpc/ptrace/ptrace.h
+++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h
@@ -102,6 +102,43 @@ int cont_trace(pid_t child)
 	return TEST_PASS;
 }
 
+int ptrace_read_regs(pid_t child, unsigned long type, unsigned long regs[],
+		     int n)
+{
+	struct iovec iov;
+	long ret;
+
+	FAIL_IF(start_trace(child));
+
+	iov.iov_base = regs;
+	iov.iov_len = n * sizeof(unsigned long);
+
+	ret = ptrace(PTRACE_GETREGSET, child, type, &iov);
+	FAIL_IF(ret != 0);
+
+	FAIL_IF(stop_trace(child));
+
+	return TEST_PASS;
+}
+
+long ptrace_write_regs(pid_t child, unsigned long type, unsigned long regs[],
+		       int n)
+{
+	struct iovec iov;
+	long ret;
+
+	FAIL_IF(start_trace(child));
+
+	iov.iov_base = regs;
+	iov.iov_len = n * sizeof(unsigned long);
+
+	ret = ptrace(PTRACE_SETREGSET, child, type, &iov);
+
+	FAIL_IF(stop_trace(child));
+
+	return ret;
+}
+
 /* TAR, PPR, DSCR */
 int show_tar_registers(pid_t child, unsigned long *out)
 {

^ permalink raw reply related

* [PATCH 0/2] Testcases for protection keys feature in powerpc/next
From: Thiago Jung Bauermann @ 2018-01-26  5:55 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: linux-kselftest, linux-kernel, Michael Ellerman, Ram Pai,
	Thiago Jung Bauermann

Ram Pai submitted a separate series containing the rework of the x86 test and
also the powerpc-specific tests:

https://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=24741

There's a bug in the powerpc tests where they expect the AMR, IAMR and UAMOR
registers to be zeroed when a process starts. This is currently true on powernv
but isn't on LPARs, where key 31 is reserved and its bits are set. This causes
the tests to fail on that platform.

This series fixes the bug and now the tests pass on both powernv and LPAR
machines running powerpc/next. I think it's worth submitting these tests
separately from the one coming from x86 so here they are.

Thiago Jung Bauermann (2):
  selftests/powerpc: Add ptrace tests for Protection Key registers
  selftests/powerpc: Add core file test for Protection Key registers

 tools/testing/selftests/powerpc/include/reg.h      |   1 +
 tools/testing/selftests/powerpc/ptrace/Makefile    |   8 +-
 tools/testing/selftests/powerpc/ptrace/child.h     | 130 ++++++
 tools/testing/selftests/powerpc/ptrace/core-pkey.c | 460 +++++++++++++++++++++
 .../testing/selftests/powerpc/ptrace/ptrace-pkey.c | 326 +++++++++++++++
 tools/testing/selftests/powerpc/ptrace/ptrace.h    |  37 ++
 6 files changed, 961 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/powerpc/ptrace/child.h
 create mode 100644 tools/testing/selftests/powerpc/ptrace/core-pkey.c
 create mode 100644 tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c

^ permalink raw reply

* Re: [RFC PATCH v2 0/1] of: easier debugging for node life cycle issues
From: Frank Rowand @ 2018-01-26  1:08 UTC (permalink / raw)
  To: Tyrel Datwyler, Wolfram Sang
  Cc: devicetree, linux-kernel, Steven Rostedt, linux-renesas-soc,
	Rob Herring, Geert Uytterhoeven, linuxppc-dev
In-Reply-To: <c20ffeb2-f17a-ddab-7327-b8854b301d18@linux.vnet.ibm.com>

On 01/25/18 15:53, Tyrel Datwyler wrote:
> On 01/25/2018 01:49 PM, Frank Rowand wrote:
>> Hi Wolfram,
>>
>> On 01/25/18 03:03, Steven Rostedt wrote:
>>> On Wed, 24 Jan 2018 22:55:13 -0800
>>> Frank Rowand <frowand.list@gmail.com> wrote:
>>>
>>>> Hi Steve,
>>>
>>>>
>>>> Off the top of your head, can you tell me know early in the boot
>>>> process a trace_event can be called and successfully provide the
>>>> data to someone trying to debug early boot issues?
>>>
>>> The trace events are enabled by early_initcall().
>>
>> < snip >
>>
>> This means that ftrace can not be used for the of_node_get(),
>> of_node_put(), and of_node_release() debug info, because
>> these functions are called before early_initcall().  Please
>> use pr_debug() for these functions.
> 
> I would argue that early boot debugging doesn't completely negate the
> usefulness of this tracing infrastructure.

I did not say or imply that it did.  I am pointing out that this
implementation does not meet the needs of other use cases.  And
potentially provides misleading information (or more precisely
misleading lack of information) in some other use cases.


> I get that no information
> is available in the trace up until ftrace is setup by its
> early_initcall, but I still found issues after early boot using this
> patch and I would hope that it would be somewhat obvious if
> references are out of whack once the ftrace data becomes available.
> In the dynamic case on Power we often do reconfig well after boot on
> live systems which produces a lot of reference put/gets. This patch
> made it easy to identify several reference leaks and underflows in
> our attach and detach logic with the added aid of being able to turn
> on the stacktrace for each call in the ftrace data.

Yes, you can get stacktraces relatively easily.  This is the strongest
argument for using ftrace.

My assumption has been that the stack trace is useful for of_node_get()
and of_node_put().  Is there _large_ value to the stack trace for
of_reconfig_notify()?


> Another thought is it would be nice if we could have the best of both
> worlds such that the tracepoints were pr_debugs up until the ftrace
> early_initcall. Or, I suppose we could ifdef it and make the ftrace
> tracepoints a configuration option, such that if it wasn't configured
> we implement the tracepoint functions as pr_debugs. This makes early
> boot an option. Just spit balling ideas.

An overly complex solution.  This is just debug.  Worst case alternative
is that the patches live on, out of tree.  So nope.


> 
> -Tyrel
> 
>>
>> As far as I know, the of_reconfig_notify() could remain an
>> ftrace instrumented function.  But now that the only thing
>> that would be ftrace instrumented is of_reconfig_notify(),
>> I don't see a strong justification for changing the existing
>> pr_debug() calls to an ftrace alternative.  Though I suspect
>> the original author of the patch still might desire to have
>> the "#ifdef DEBUG" surrounding the pr_debug() calls removed
>> since one of his issues was having to recompile his kernel
>> to do his debugging.
>>
>> -Frank
>>
> 
> 

^ permalink raw reply


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