LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: RFC on writel and writel_relaxed
From: Benjamin Herrenschmidt @ 2018-03-23  0:16 UTC (permalink / raw)
  To: Sinan Kaya, Oliver
  Cc: linuxppc dev list, linux-rdma@vger.kernel.org, Marc Zyngier,
	Will Deacon
In-Reply-To: <5ccdb208-4664-0a7f-df5d-2e12cbe4c239@codeaurora.org>

On Thu, 2018-03-22 at 12:51 -0500, Sinan Kaya wrote:
> On 3/22/2018 8:52 AM, Benjamin Herrenschmidt wrote:
> > > > No, it's not sufficient.
> > 
> > Just to clarify ... barrier() is just a compiler barrier, it means the
> > compiler will generate things in the order they are written. This isn't
> > sufficient on archs with an OO memory model, where an actual memory
> > barrier instruction needs to be emited.
> 
> Surprisingly, ARM64 GCC compiler generates a write barrier as
> opposed to preventing code reordering.
> 
> I was curious if this is an ARM only thing or not. 

Are you sure of that ? I thought it's the ARM implementation of writel
that had an explicit write barrier in it:

#define writel(v,c)		({ __iowmb(); writel_relaxed((v),(c)); })

And __iowmb() is 

#define __iowmb()		wmb()

Note, I'm a bit dubious about this in ARM:

#define readl(c)		({ u32 __v = readl_relaxed(c); __iormb(); __v; }

Will, Marc, on powerpc, we put a sync *before* the read in readl etc...

The reasoning was there could be some DMA setup followed by a side
effect readl rather than a side effect writel to trigger a DMA. Granted
I wouldn't expect modern devices to be that stupid, but I have vague
memory of some devices back in the day having that sort of read ops.

In general, I though the model offerred by x86 and thus by Linux
readl/writel was full synchronization both before and after the MMIO,
vs either other MMIO or all other forms of ops (cachable memory, locks
etc...).

Also, can't the above readl_relaxed leak out of a lock ?

Cheers,
Ben.

^ permalink raw reply

* Re: DMA Mapping Error in ppc64
From: Oliver @ 2018-03-23  1:19 UTC (permalink / raw)
  To: Jared Bents; +Cc: linuxppc-dev
In-Reply-To: <CAM=7fbdN=sLncGK2hgq2fNWeULdff8opViD9UQ3qj29KTG5tNQ@mail.gmail.com>

On Fri, Mar 23, 2018 at 1:37 AM, Jared Bents
<jared.bents@rockwellcollins.com> wrote:
> Thank you for the response but unfortunately, it looks like I already
> have that and it is being used.  To verify, I commented that out and
> got the failure "dma_direct_alloc_coherent: No suitable zone for pfn
> 0xe0000".  Below is the code flow for function
> ath10k_pci_hif_exchange_bmi_msg which is showing the first dma mapping
> error.
>
> ath10k_pci_hif_exchange_bmi_msg -> dma_map_single ->
> dma_map_single_attrs -> swiotlb_map_page -> dma_capable (returns
> false)
>
>
> dma_capable is what reports the failure in that flow.
>
> static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
> {
> #ifdef CONFIG_SWIOTLB
>     struct dev_archdata *sd = &dev->archdata;
>
>    if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
>         return false;
> #endif
>
>     if (!dev->dma_mask)
>         return false;
>
>     return addr + size - 1 <= *dev->dma_mask;
> }
> Getting the below values:
> addr = 1ee376218
> size = 4
> sd->max_direct_dma_addr = e0000000 which is I believe DMA window size (e0000000)
>
> when executed sd->max_direct_dma_addr(e0000000) && addr(1ee376218) +
> size(4) becomes e0000004 which is > sd->max_direct_dma_addr (e0000000)
>
>
> So even though limit_zone_pfn(ZONE_DMA32, 1UL << (31 - PAGE_SHIFT)) is
> being used in arch/powerpc/platforms/85xx/corenet_generic.c,

> kmemdup(req, req_len, GFP_KERNEL) is returning an address that when
> sent to dma_map_single(), results in a bad map.

You need to use (GFP_KERNEL | GFP_DMA32) to constrain the allocations
to ZONE_DMA32. Without that the kmemdup() will allocate from any zone
so you'll probably get an unmappable address.

That said, the driver probably shouldn't be using kmemdup() here.
DMA-API.txt pretty explicitly says that drivers should not assume that
dma_map_single() will work with arbitrary memory. It should be using
dma_alloc_coherent() or a dma pool here.

> - Jared
>
> On Wed, Mar 21, 2018 at 11:54 PM, Oliver <oohall@gmail.com> wrote:
>> On Thu, Mar 22, 2018 at 8:00 AM, Jared Bents
>> <jared.bents@rockwellcollins.com> wrote:
>>> Hi all,
>>>
>>> Apologies for the amount of information but we've been debugging this
>>> for a while and I wanted to get what we are seeing captured as much as
>>> possible.  We are a T1042 processor and have a total 8GB DDR and our
>>> kernel version is fsl-sdk-v2.0-1703 (linux v4.1.35) as that is the
>>> latest version supplied by NXP.
>>>
>>> A while ago we ported from 32 bit to 64 bit.  Everything continued to
>>> work except the ath10k module we have.  So as a first step, we checked
>>> to see if an ath9k module also failed to work and it was also no
>>> longer working.  The ath10k is working fine on a 32 bit system but
>>> it's not working on 64 bit system as we are getting dma mapping errors
>>> when trying to initialize the wifi modules.
>>>
>>> pci_bus 0002:01: bus scan returning with max=01
>>> pci_bus 0002:01: busn_res: [bus 01] end is updated to 01
>>> pci_bus 0002:00: bus scan returning with max=01
>>> ath10k_pci 0000:01:00.0: unable to get target info from device
>>> ath10k_pci 0000:01:00.0: could not get target info (-5)
>>> ath10k_pci 0000:01:00.0: could not probe fw (-5)
>>> ath10k_pci 0001:01:00.0: Direct firmware load for
>>> ath10k/cal-pci-0001:01:00.0.bin failed with error -2
>>>
>>>
>>> First, we have tried the mainline kernel (v4.15)  to see if that would
>>> fix the issue, it did not.  So I made a patch for the ath10k driver to
>>> restrict to just GFP_DMA areas when allocating memory or creating
>>> sk_buffs and have attached it.  The ath10k wifi modules now initialize
>>> correctly but when I try to connect them and send traffic, they get a
>>> DMA mapping error from the sk_buff that it receives from elsewhere in
>>> the kernel.  So while the driver appears to be fixable with the patch,
>>> the modules are still unusable due to data being sent to the driver
>>> when ath10k_tx is called and it tries to dma map with the provided
>>> skb.  Also, according to the ath10k mailing list, GFP_DMA is not
>>> supposed to be used in general.  The error below is the same sort of
>>> dma mapping error that is seen when initializing the modules without
>>> the patch to OR with GFP_DMA.
>>>
>>> ath10k_pci 0001:01:00.0: failed to transmit packet, dropping: -5
>>>
>>>
>>> We asked on the ath10k mailing list if anyone else is having this
>>> problem and no one else seems to have the issue but they are using
>>> different architectures (ARM or X86). As a result, it does not seem to
>>> be a driver issue to us but something within the PowerPC arch.  So we
>>> dug a little deeper to try to find what addresses being mapped are
>>> working and what address being mapped are not working.
>>>
>>> We found that when the virtual address of data pointer (a member of
>>> sk_buff) is above ~3.7 GB RAM address range then return address from
>>> dma_map_single API is failed to validate in dma_mapping_error
>>> function.
>>>
>>> We also noticed that in a 64bit machine sometimes ping is working and
>>> because of the virtual address is under ~3.7GAM RAM address range.  So
>>> if we set mem=2048M in the bootargs, the ath10k module works
>>> perfectly, however this isn't a real solution since it cuts our
>>> available RAM from 8GB to 2GB.
>>
>> I think there's a known issue with the freescale PCIe root complex
>> where it can't DMA beyond the 4GB mark. There's a workaround in
>> the form of limit_zone_pfn() which you can use to put the lower 4GB into
>> ZONE_DMA32 and allocate from there rather than ZONE_NORMAL.
>> For details of how to use it have a look at corenet_gen_setup_arch() in
>> arch/powerpc/platforms/85xx/corenet_generic.c
>>
>> Hope that helps,
>> Oliver

^ permalink raw reply

* [PATCH] powerpc/eeh: Avoid misleading message "EEH: no capable adapters found"
From: Mauro S. M. Rodrigues @ 2018-03-23  2:10 UTC (permalink / raw)
  To: linuxppc-dev, ruscur, benh, paulus, mpe; +Cc: kernel

Due to recent refactoring in EEH in:
commit b9fde58db7e5 ("powerpc/powernv: Rework EEH initialization on
powernv")
a misleading message was seen in the kernel message buffer:

[    0.108431] EEH: PowerNV platform initialized
[    0.589979] EEH: No capable adapters found

This happened due to the removal of the initialization delay for powernv
platform.

Even though the EEH infrastructure for the devices is eventually
initialized and still works just fine the eeh device probe step is
postponed in order to assure the PEs are created. Later
pnv_eeh_post_init does the probe devices job but at that point the
message was already shown right after eeh_init flow.

This patch introduces a new flag EEH_POSTPONED_PROBE to represent that
temporary state and avoid the message mentioned above and showing the
follow one instead:

[    0.107724] EEH: PowerNV platform initialized
[    4.844825] EEH: PCI Enhanced I/O Error Handling Enabled

Signed-off-by: Mauro S. M. Rodrigues <maurosr@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/eeh.h               | 15 ++++++++-------
 arch/powerpc/kernel/eeh.c                    |  2 +-
 arch/powerpc/platforms/powernv/eeh-powernv.c | 12 +++++++++++-
 3 files changed, 20 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index fd37cc1..d16c3d6 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -36,13 +36,14 @@
 #ifdef CONFIG_EEH
 
 /* EEH subsystem flags */
-#define EEH_ENABLED		0x01	/* EEH enabled		*/
-#define EEH_FORCE_DISABLED	0x02	/* EEH disabled		*/
-#define EEH_PROBE_MODE_DEV	0x04	/* From PCI device	*/
-#define EEH_PROBE_MODE_DEVTREE	0x08	/* From device tree	*/
-#define EEH_VALID_PE_ZERO	0x10	/* PE#0 is valid	*/
-#define EEH_ENABLE_IO_FOR_LOG	0x20	/* Enable IO for log	*/
-#define EEH_EARLY_DUMP_LOG	0x40	/* Dump log immediately	*/
+#define EEH_ENABLED		0x01	/* EEH enabled			     */
+#define EEH_FORCE_DISABLED	0x02	/* EEH disabled			     */
+#define EEH_PROBE_MODE_DEV	0x04	/* From PCI device		     */
+#define EEH_PROBE_MODE_DEVTREE	0x08	/* From device tree		     */
+#define EEH_VALID_PE_ZERO	0x10	/* PE#0 is valid		     */
+#define EEH_ENABLE_IO_FOR_LOG	0x20	/* Enable IO for log		     */
+#define EEH_EARLY_DUMP_LOG	0x40	/* Dump log immediately		     */
+#define EEH_POSTPONED_PROBE	0x80    /* Powernv may postpone device probe */
 
 /*
  * Delay for PE reset, all in ms
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 2b9df00..179ca84 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -1092,7 +1092,7 @@ static int eeh_init(void)
 
 	if (eeh_enabled())
 		pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
-	else
+	else if (!eeh_has_flag(EEH_POSTPONED_PROBE))
 		pr_info("EEH: No capable adapters found\n");
 
 	return ret;
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 33c86c1..9845460 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -223,6 +223,14 @@ int pnv_eeh_post_init(void)
 	eeh_probe_devices();
 	eeh_addr_cache_build();
 
+	if (eeh_has_flag(EEH_POSTPONED_PROBE)) {
+		eeh_clear_flag(EEH_POSTPONED_PROBE);
+		if (eeh_enabled())
+			pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n");
+		else
+			pr_info("EEH: No capable adapters found\n");
+	}
+
 	/* Register OPAL event notifier */
 	eeh_event_irq = opal_event_request(ilog2(OPAL_EVENT_PCI_ERROR));
 	if (eeh_event_irq < 0) {
@@ -384,8 +392,10 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data)
 		return NULL;
 
 	/* Skip if we haven't probed yet */
-	if (phb->ioda.pe_rmap[config_addr] == IODA_INVALID_PE)
+	if (phb->ioda.pe_rmap[config_addr] == IODA_INVALID_PE) {
+		eeh_add_flag(EEH_POSTPONED_PROBE);
 		return NULL;
+	}
 
 	/* Initialize eeh device */
 	edev->class_code = pdn->class_code;
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCH] cxl: disable the lazy approach for irqs in POWERVM environment.
From: Benjamin Herrenschmidt @ 2018-03-23  2:14 UTC (permalink / raw)
  To: Christophe Lombard, linuxppc-dev, fbarrat, vaibhav,
	andrew.donnellan
In-Reply-To: <1521736674-13128-1-git-send-email-clombard@linux.vnet.ibm.com>

On Thu, 2018-03-22 at 17:37 +0100, Christophe Lombard wrote:
> The cxl driver cannot disable the interrupt at the device level and has
> to use disable_irq[_nosync] instead.
> To avoid the implementation of the lazy optimisation (the interrupt is
> marked disabled, but the hardware is left unmasked), we can disable it,
> for a particular irq line, by calling
> 'irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY)'.

Why do you need that ? What's wrong with the lazy approach ? It makes
disable_irq/enable_irq faster...

You shouldn't need that unless your device is generating a *LOT* of
irqs while disabled.

> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com>
> ---
>  drivers/misc/cxl/guest.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c
> index f58b4b6c..dc476e1 100644
> --- a/drivers/misc/cxl/guest.c
> +++ b/drivers/misc/cxl/guest.c
> @@ -389,6 +389,7 @@ static void disable_afu_irqs(struct cxl_context *ctx)
>  		hwirq = ctx->irqs.offset[r];
>  		for (i = 0; i < ctx->irqs.range[r]; hwirq++, i++) {
>  			virq = irq_find_mapping(NULL, hwirq);
> +			irq_set_status_flags(virq, IRQ_DISABLE_UNLAZY);
>  			disable_irq(virq);
>  		}
>  	}

^ permalink raw reply

* [PATCH 1/3] powerpc/mm/radix: Remove unused code
From: Aneesh Kumar K.V @ 2018-03-23  4:56 UTC (permalink / raw)
  To: benh, paulus, mpe, mauricfo; +Cc: linuxppc-dev, Aneesh Kumar K.V

These function are not used in the code. Remove them.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 .../powerpc/include/asm/book3s/64/tlbflush-radix.h |  3 --
 arch/powerpc/mm/tlb-radix.c                        | 40 ----------------------
 2 files changed, 43 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
index 8eea90f80e45..19b45ba6caf9 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
@@ -47,9 +47,6 @@ extern void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmad
 #endif
 extern void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr);
 extern void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr);
-extern void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
-				     unsigned long page_size);
-extern void radix__flush_tlb_lpid(unsigned long lpid);
 extern void radix__flush_tlb_all(void);
 extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
 					unsigned long address);
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 71d1b19ad1c0..8ce858ec59e1 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -603,46 +603,6 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr)
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
-void radix__flush_tlb_lpid_va(unsigned long lpid, unsigned long gpa,
-			      unsigned long page_size)
-{
-	unsigned long rb,rs,prs,r;
-	unsigned long ap;
-	unsigned long ric = RIC_FLUSH_TLB;
-
-	ap = mmu_get_ap(radix_get_mmu_psize(page_size));
-	rb = gpa & ~(PPC_BITMASK(52, 63));
-	rb |= ap << PPC_BITLSHIFT(58);
-	rs = lpid & ((1UL << 32) - 1);
-	prs = 0; /* process scoped */
-	r = 1;   /* raidx format */
-
-	asm volatile("ptesync": : :"memory");
-	asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
-		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
-	asm volatile("eieio; tlbsync; ptesync": : :"memory");
-	trace_tlbie(lpid, 0, rb, rs, ric, prs, r);
-}
-EXPORT_SYMBOL(radix__flush_tlb_lpid_va);
-
-void radix__flush_tlb_lpid(unsigned long lpid)
-{
-	unsigned long rb,rs,prs,r;
-	unsigned long ric = RIC_FLUSH_ALL;
-
-	rb = 0x2 << PPC_BITLSHIFT(53); /* IS = 2 */
-	rs = lpid & ((1UL << 32) - 1);
-	prs = 0; /* partition scoped */
-	r = 1;   /* raidx format */
-
-	asm volatile("ptesync": : :"memory");
-	asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
-		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
-	asm volatile("eieio; tlbsync; ptesync": : :"memory");
-	trace_tlbie(lpid, 0, rb, rs, ric, prs, r);
-}
-EXPORT_SYMBOL(radix__flush_tlb_lpid);
-
 void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
 				unsigned long start, unsigned long end)
 {
-- 
2.14.3

^ permalink raw reply related

* [PATCH 2/3] powerpc/mm/radix: Move the functions that does the actual tlbie closer
From: Aneesh Kumar K.V @ 2018-03-23  4:56 UTC (permalink / raw)
  To: benh, paulus, mpe, mauricfo; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <20180323045627.16800-1-aneesh.kumar@linux.vnet.ibm.com>

No functionality change. Just code movement to ease code changes later

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/mm/tlb-radix.c | 64 ++++++++++++++++++++++-----------------------
 1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 8ce858ec59e1..570fdc7b0e74 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -119,6 +119,38 @@ static inline void __tlbie_pid(unsigned long pid, unsigned long ric)
 	trace_tlbie(0, 0, rb, rs, ric, prs, r);
 }
 
+static inline void __tlbiel_va(unsigned long va, unsigned long pid,
+			       unsigned long ap, unsigned long ric)
+{
+	unsigned long rb,rs,prs,r;
+
+	rb = va & ~(PPC_BITMASK(52, 63));
+	rb |= ap << PPC_BITLSHIFT(58);
+	rs = pid << PPC_BITLSHIFT(31);
+	prs = 1; /* process scoped */
+	r = 1;   /* raidx format */
+
+	asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
+		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
+	trace_tlbie(0, 1, rb, rs, ric, prs, r);
+}
+
+static inline void __tlbie_va(unsigned long va, unsigned long pid,
+			      unsigned long ap, unsigned long ric)
+{
+	unsigned long rb,rs,prs,r;
+
+	rb = va & ~(PPC_BITMASK(52, 63));
+	rb |= ap << PPC_BITLSHIFT(58);
+	rs = pid << PPC_BITLSHIFT(31);
+	prs = 1; /* process scoped */
+	r = 1;   /* raidx format */
+
+	asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
+		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
+	trace_tlbie(0, 0, rb, rs, ric, prs, r);
+}
+
 /*
  * We use 128 set in radix mode and 256 set in hpt mode.
  */
@@ -155,22 +187,6 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
 	asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
-static inline void __tlbiel_va(unsigned long va, unsigned long pid,
-			       unsigned long ap, unsigned long ric)
-{
-	unsigned long rb,rs,prs,r;
-
-	rb = va & ~(PPC_BITMASK(52, 63));
-	rb |= ap << PPC_BITLSHIFT(58);
-	rs = pid << PPC_BITLSHIFT(31);
-	prs = 1; /* process scoped */
-	r = 1;   /* raidx format */
-
-	asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
-		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
-	trace_tlbie(0, 1, rb, rs, ric, prs, r);
-}
-
 static inline void __tlbiel_va_range(unsigned long start, unsigned long end,
 				    unsigned long pid, unsigned long page_size,
 				    unsigned long psize)
@@ -203,22 +219,6 @@ static inline void _tlbiel_va_range(unsigned long start, unsigned long end,
 	asm volatile("ptesync": : :"memory");
 }
 
-static inline void __tlbie_va(unsigned long va, unsigned long pid,
-			     unsigned long ap, unsigned long ric)
-{
-	unsigned long rb,rs,prs,r;
-
-	rb = va & ~(PPC_BITMASK(52, 63));
-	rb |= ap << PPC_BITLSHIFT(58);
-	rs = pid << PPC_BITLSHIFT(31);
-	prs = 1; /* process scoped */
-	r = 1;   /* raidx format */
-
-	asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
-		     : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
-	trace_tlbie(0, 0, rb, rs, ric, prs, r);
-}
-
 static inline void __tlbie_va_range(unsigned long start, unsigned long end,
 				    unsigned long pid, unsigned long page_size,
 				    unsigned long psize)
-- 
2.14.3

^ permalink raw reply related

* [PATCH 3/3] powerpc/mm: Fixup tlbie vs store ordering issue on POWER9
From: Aneesh Kumar K.V @ 2018-03-23  4:56 UTC (permalink / raw)
  To: benh, paulus, mpe, mauricfo; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <20180323045627.16800-1-aneesh.kumar@linux.vnet.ibm.com>

On POWER9, under some circumstances, a broadcast TLB invalidation might complete
before all previous stores have drained, potentially allowing stale stores from
becoming visible after the invalidation. This works around it by doubling up
those TLB invalidations which was verified by HW to be sufficient to close the
risk window.

Fixes: 1a472c9dba6b ("powerpc/mm/radix: Add tlbflush routines")
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/cputable.h    |  3 ++-
 arch/powerpc/kvm/book3s_64_mmu_radix.c |  3 +++
 arch/powerpc/kvm/book3s_hv_rm_mmu.c    | 11 +++++++++++
 arch/powerpc/mm/hash_native_64.c       | 16 +++++++++++++++-
 arch/powerpc/mm/pgtable_64.c           |  1 +
 arch/powerpc/mm/tlb-radix.c            | 15 +++++++++++++++
 6 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index a2c5c95882cf..6c151d2e9bd9 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -203,6 +203,7 @@ static inline void cpu_feature_keys_init(void) { }
 #define CPU_FTR_DAWR			LONG_ASM_CONST(0x0400000000000000)
 #define CPU_FTR_DABRX			LONG_ASM_CONST(0x0800000000000000)
 #define CPU_FTR_PMAO_BUG		LONG_ASM_CONST(0x1000000000000000)
+#define CPU_FTR_TLBIE_BUG		LONG_ASM_CONST(0x2000000000000000)
 #define CPU_FTR_POWER9_DD1		LONG_ASM_CONST(0x4000000000000000)
 #define CPU_FTR_POWER9_DD2_1		LONG_ASM_CONST(0x8000000000000000)
 
@@ -465,7 +466,7 @@ static inline void cpu_feature_keys_init(void) { }
 	    CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
 	    CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
 	    CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \
-	    CPU_FTR_PKEY)
+	    CPU_FTR_PKEY | CPU_FTR_TLBIE_BUG)
 #define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \
 			     (~CPU_FTR_SAO))
 #define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index 5cb4e4687107..62f60778177b 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -157,6 +157,9 @@ static void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
 	asm volatile("ptesync": : :"memory");
 	asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
 		     : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
+	if (cpu_has_feature(CPU_FTR_TLBIE_BUG))
+		asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
+			     : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
 	asm volatile("ptesync": : :"memory");
 }
 
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 8888e625a999..aebcb718b614 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -473,6 +473,17 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
 			trace_tlbie(kvm->arch.lpid, 0, rbvalues[i],
 				kvm->arch.lpid, 0, 0, 0);
 		}
+
+		if (cpu_has_feature(CPU_FTR_TLBIE_BUG)) {
+			/*
+			 * Need the extra ptesync to make sure we don't
+			 * re-order the tlbie
+			 */
+			asm volatile("ptesync": : :"memory");
+			asm volatile(PPC_TLBIE_5(%0,%1,0,0,0) : :
+				     "r" (rbvalues[0]), "r" (kvm->arch.lpid));
+		}
+
 		asm volatile("eieio; tlbsync; ptesync" : : : "memory");
 		kvm->arch.tlbie_lock = 0;
 	} else {
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 993842f1ed60..45b1772d3097 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -201,6 +201,15 @@ static inline unsigned long  ___tlbie(unsigned long vpn, int psize,
 	return va;
 }
 
+static inline void fixup_tlbie(unsigned long vpn, int psize, int apsize, int ssize)
+{
+	if (cpu_has_feature(CPU_FTR_TLBIE_BUG)) {
+		/* Need the extra ptesync to ensure we don't reorder tlbie*/
+		asm volatile("ptesync": : :"memory");
+		___tlbie(vpn, psize, apsize, ssize);
+	}
+}
+
 static inline void __tlbie(unsigned long vpn, int psize, int apsize, int ssize)
 {
 	unsigned long rb;
@@ -278,6 +287,7 @@ static inline void tlbie(unsigned long vpn, int psize, int apsize,
 		asm volatile("ptesync": : :"memory");
 	} else {
 		__tlbie(vpn, psize, apsize, ssize);
+		fixup_tlbie(vpn, psize, apsize, ssize);
 		asm volatile("eieio; tlbsync; ptesync": : :"memory");
 	}
 	if (lock_tlbie && !use_local)
@@ -771,7 +781,7 @@ static void native_hpte_clear(void)
  */
 static void native_flush_hash_range(unsigned long number, int local)
 {
-	unsigned long vpn;
+	unsigned long vpn = 0;
 	unsigned long hash, index, hidx, shift, slot;
 	struct hash_pte *hptep;
 	unsigned long hpte_v;
@@ -843,6 +853,10 @@ static void native_flush_hash_range(unsigned long number, int local)
 				__tlbie(vpn, psize, psize, ssize);
 			} pte_iterate_hashed_end();
 		}
+		/*
+		 * Just do one more with the last used values.
+		 */
+		fixup_tlbie(vpn, psize, psize, ssize);
 		asm volatile("eieio; tlbsync; ptesync":::"memory");
 
 		if (lock_tlbie)
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c
index 28c980eb4422..adf469f312f2 100644
--- a/arch/powerpc/mm/pgtable_64.c
+++ b/arch/powerpc/mm/pgtable_64.c
@@ -481,6 +481,7 @@ void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0,
 			     "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid));
 		trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0);
 	}
+	/* do we need fixup here ?*/
 	asm volatile("eieio; tlbsync; ptesync" : : : "memory");
 }
 EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry);
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 570fdc7b0e74..264b9e5f97cc 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -151,6 +151,17 @@ static inline void __tlbie_va(unsigned long va, unsigned long pid,
 	trace_tlbie(0, 0, rb, rs, ric, prs, r);
 }
 
+static inline void fixup_tlbie(void)
+{
+	unsigned long pid = 0;
+	unsigned long va = ((1UL << 52) - 1);
+
+	if (cpu_has_feature(CPU_FTR_TLBIE_BUG)) {
+		asm volatile("ptesync": : :"memory");
+		__tlbie_va(va, pid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB);
+	}
+}
+
 /*
  * We use 128 set in radix mode and 256 set in hpt mode.
  */
@@ -184,6 +195,7 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
 {
 	asm volatile("ptesync": : :"memory");
 	__tlbie_pid(pid, ric);
+	fixup_tlbie();
 	asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -237,6 +249,7 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid,
 
 	asm volatile("ptesync": : :"memory");
 	__tlbie_va(va, pid, ap, ric);
+	fixup_tlbie();
 	asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -248,6 +261,7 @@ static inline void _tlbie_va_range(unsigned long start, unsigned long end,
 	if (also_pwc)
 		__tlbie_pid(pid, RIC_FLUSH_PWC);
 	__tlbie_va_range(start, end, pid, page_size, psize);
+	fixup_tlbie();
 	asm volatile("eieio; tlbsync; ptesync": : :"memory");
 }
 
@@ -465,6 +479,7 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
 			if (hflush)
 				__tlbie_va_range(hstart, hend, pid,
 						HPAGE_PMD_SIZE, MMU_PAGE_2M);
+			fixup_tlbie();
 			asm volatile("eieio; tlbsync; ptesync": : :"memory");
 		}
 	}
-- 
2.14.3

^ permalink raw reply related

* Re: [PATCHv5 0/3] enable nr_cpus for powerpc
From: Pingfan Liu @ 2018-03-23  5:28 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: cascardo, gpiccoli, kexec, paulus, Michael Ellerman,
	Benjamin Herrenschmidt
In-Reply-To: <1521088912-31742-1-git-send-email-kernelfans@gmail.com>

Maintainers, ping? Any comment?

Thanks

On Thu, Mar 15, 2018 at 12:41 PM, Pingfan Liu <kernelfans@gmail.com> wrote:
> This topic has a very long history. It comes from Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
> For v3: https://patchwork.ozlabs.org/patch/834860/
> I hope we can acquire it for "kexec -p" soon.
>
> V4->V5:
>   improve the [1/3] implementation based on Benjamin's suggestion.
>
> Mahesh Salgaonkar (1):
>   ppc64 boot: Wait for boot cpu to show up if nr_cpus limit is about to
>     hit.
>
> Pingfan Liu (2):
>   powerpc, cpu: partially unbind the mapping between cpu logical id and
>        its seq in dt
>   powerpc, cpu: handling the special case when boot_cpuid greater than
>     nr_cpus
>
>  arch/powerpc/include/asm/paca.h    |  3 +++
>  arch/powerpc/include/asm/smp.h     |  2 ++
>  arch/powerpc/kernel/paca.c         | 19 ++++++++++++++-----
>  arch/powerpc/kernel/prom.c         | 27 ++++++++++++++++-----------
>  arch/powerpc/kernel/setup-common.c | 35 ++++++++++++++++++++++++++++++++---
>  5 files changed, 67 insertions(+), 19 deletions(-)
>
> --
> 2.7.4
>

^ permalink raw reply

* Re: [PATCH 2/2] powerpc/time: Only set ARCH_HAS_SCALED_CPUTIME on PPC64
From: kbuild test robot @ 2018-03-23  5:40 UTC (permalink / raw)
  To: Christophe Leroy
  Cc: kbuild-all, Benjamin Herrenschmidt, Paul Mackerras,
	Michael Ellerman, Scott Wood, linux-kernel, linuxppc-dev
In-Reply-To: <d253b71638e2af1cac9eb804c935810d0e021841.1521639065.git.christophe.leroy@c-s.fr>

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

Hi Christophe,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on powerpc/next]
[also build test ERROR on v4.16-rc6 next-20180322]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Christophe-Leroy/powerpc-time-inline-arch_vtime_task_switch/20180323-115145
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=powerpc 

All errors (new ones prefixed by >>):

   arch/powerpc/xmon/xmon.c: In function 'dump_one_paca':
>> arch/powerpc/xmon/xmon.c:2426:20: error: 'struct cpu_accounting_data' has no member named 'utime_scaled'
     DUMP(p, accounting.utime_scaled, "llx");
                       ^
   arch/powerpc/xmon/xmon.c:2349:65: note: in definition of macro 'DUMP'
     printf(" %-*s = %#-*"format"\t(0x%lx)\n", 20, #name, 18, paca->name, \
                                                                    ^~~~
   In file included from include/linux/compiler_types.h:58:0,
                    from include/linux/kconfig.h:74,
                    from <command-line>:0:
   include/linux/compiler-gcc.h:170:2: error: 'struct cpu_accounting_data' has no member named 'utime_scaled'
     __builtin_offsetof(a, b)
     ^
   include/linux/stddef.h:17:32: note: in expansion of macro '__compiler_offsetof'
    #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
                                   ^~~~~~~~~~~~~~~~~~~
   arch/powerpc/xmon/xmon.c:2350:3: note: in expansion of macro 'offsetof'
      offsetof(struct paca_struct, name));
      ^~~~~~~~
   arch/powerpc/xmon/xmon.c:2426:2: note: in expansion of macro 'DUMP'
     DUMP(p, accounting.utime_scaled, "llx");
     ^~~~
>> arch/powerpc/xmon/xmon.c:2429:21: error: 'struct cpu_accounting_data' has no member named 'startspurr'; did you mean 'starttime'?
     DUMP(p, accounting.startspurr, "llx");
                        ^
   arch/powerpc/xmon/xmon.c:2349:65: note: in definition of macro 'DUMP'
     printf(" %-*s = %#-*"format"\t(0x%lx)\n", 20, #name, 18, paca->name, \
                                                                    ^~~~
   In file included from include/linux/compiler_types.h:58:0,
                    from include/linux/kconfig.h:74,
                    from <command-line>:0:
>> arch/powerpc/xmon/xmon.c:2429:21: error: 'struct cpu_accounting_data' has no member named 'startspurr'; did you mean 'starttime'?
     DUMP(p, accounting.startspurr, "llx");
                        ^
   include/linux/compiler-gcc.h:170:24: note: in definition of macro '__compiler_offsetof'
     __builtin_offsetof(a, b)
                           ^
   arch/powerpc/xmon/xmon.c:2350:3: note: in expansion of macro 'offsetof'
      offsetof(struct paca_struct, name));
      ^~~~~~~~
   arch/powerpc/xmon/xmon.c:2429:2: note: in expansion of macro 'DUMP'
     DUMP(p, accounting.startspurr, "llx");
     ^~~~
>> arch/powerpc/xmon/xmon.c:2430:20: error: 'struct cpu_accounting_data' has no member named 'utime_sspurr'
     DUMP(p, accounting.utime_sspurr, "llx");
                       ^
   arch/powerpc/xmon/xmon.c:2349:65: note: in definition of macro 'DUMP'
     printf(" %-*s = %#-*"format"\t(0x%lx)\n", 20, #name, 18, paca->name, \
                                                                    ^~~~
   In file included from include/linux/compiler_types.h:58:0,
                    from include/linux/kconfig.h:74,
                    from <command-line>:0:
   include/linux/compiler-gcc.h:170:2: error: 'struct cpu_accounting_data' has no member named 'utime_sspurr'
     __builtin_offsetof(a, b)
     ^
   include/linux/stddef.h:17:32: note: in expansion of macro '__compiler_offsetof'
    #define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
                                   ^~~~~~~~~~~~~~~~~~~
   arch/powerpc/xmon/xmon.c:2350:3: note: in expansion of macro 'offsetof'
      offsetof(struct paca_struct, name));
      ^~~~~~~~
   arch/powerpc/xmon/xmon.c:2430:2: note: in expansion of macro 'DUMP'
     DUMP(p, accounting.utime_sspurr, "llx");
     ^~~~

vim +2426 arch/powerpc/xmon/xmon.c

ddadb6b8e Michael Ellerman    2012-09-13  2331  
ddadb6b8e Michael Ellerman    2012-09-13  2332  	if (setjmp(bus_error_jmp) != 0) {
ddadb6b8e Michael Ellerman    2012-09-13  2333  		printf("*** Error dumping paca for cpu 0x%x!\n", cpu);
ddadb6b8e Michael Ellerman    2012-09-13  2334  		return;
ddadb6b8e Michael Ellerman    2012-09-13  2335  	}
ddadb6b8e Michael Ellerman    2012-09-13  2336  
ddadb6b8e Michael Ellerman    2012-09-13  2337  	catch_memory_errors = 1;
ddadb6b8e Michael Ellerman    2012-09-13  2338  	sync();
ddadb6b8e Michael Ellerman    2012-09-13  2339  
ddadb6b8e Michael Ellerman    2012-09-13  2340  	p = &paca[cpu];
ddadb6b8e Michael Ellerman    2012-09-13  2341  
d81041820 Michael Ellerman    2017-12-06  2342  	printf("paca for cpu 0x%x @ %px:\n", cpu, p);
ddadb6b8e Michael Ellerman    2012-09-13  2343  
ad987fc8e Michael Ellerman    2015-10-14  2344  	printf(" %-*s = %s\n", 20, "possible", cpu_possible(cpu) ? "yes" : "no");
ad987fc8e Michael Ellerman    2015-10-14  2345  	printf(" %-*s = %s\n", 20, "present", cpu_present(cpu) ? "yes" : "no");
ad987fc8e Michael Ellerman    2015-10-14  2346  	printf(" %-*s = %s\n", 20, "online", cpu_online(cpu) ? "yes" : "no");
ddadb6b8e Michael Ellerman    2012-09-13  2347  
ddadb6b8e Michael Ellerman    2012-09-13  2348  #define DUMP(paca, name, format) \
ad987fc8e Michael Ellerman    2015-10-14  2349  	printf(" %-*s = %#-*"format"\t(0x%lx)\n", 20, #name, 18, paca->name, \
ddadb6b8e Michael Ellerman    2012-09-13 @2350  		offsetof(struct paca_struct, name));
ddadb6b8e Michael Ellerman    2012-09-13  2351  
ddadb6b8e Michael Ellerman    2012-09-13  2352  	DUMP(p, lock_token, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2353  	DUMP(p, paca_index, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2354  	DUMP(p, kernel_toc, "lx");
ddadb6b8e Michael Ellerman    2012-09-13  2355  	DUMP(p, kernelbase, "lx");
ddadb6b8e Michael Ellerman    2012-09-13  2356  	DUMP(p, kernel_msr, "lx");
2248fade9 Michael Ellerman    2018-01-11  2357  	DUMP(p, emergency_sp, "px");
729b0f715 Mahesh Salgaonkar   2013-10-30  2358  #ifdef CONFIG_PPC_BOOK3S_64
2248fade9 Michael Ellerman    2018-01-11  2359  	DUMP(p, nmi_emergency_sp, "px");
2248fade9 Michael Ellerman    2018-01-11  2360  	DUMP(p, mc_emergency_sp, "px");
c4f3b52ce Nicholas Piggin     2016-12-20  2361  	DUMP(p, in_nmi, "x");
729b0f715 Mahesh Salgaonkar   2013-10-30  2362  	DUMP(p, in_mce, "x");
ad987fc8e Michael Ellerman    2015-10-14  2363  	DUMP(p, hmi_event_available, "x");
729b0f715 Mahesh Salgaonkar   2013-10-30  2364  #endif
ddadb6b8e Michael Ellerman    2012-09-13  2365  	DUMP(p, data_offset, "lx");
ddadb6b8e Michael Ellerman    2012-09-13  2366  	DUMP(p, hw_cpu_id, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2367  	DUMP(p, cpu_start, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2368  	DUMP(p, kexec_state, "x");
4e0037470 Michael Ellerman    2017-10-19  2369  #ifdef CONFIG_PPC_BOOK3S_64
ad987fc8e Michael Ellerman    2015-10-14  2370  	for (i = 0; i < SLB_NUM_BOLTED; i++) {
ad987fc8e Michael Ellerman    2015-10-14  2371  		u64 esid, vsid;
ad987fc8e Michael Ellerman    2015-10-14  2372  
ad987fc8e Michael Ellerman    2015-10-14  2373  		if (!p->slb_shadow_ptr)
ad987fc8e Michael Ellerman    2015-10-14  2374  			continue;
ad987fc8e Michael Ellerman    2015-10-14  2375  
ad987fc8e Michael Ellerman    2015-10-14  2376  		esid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].esid);
ad987fc8e Michael Ellerman    2015-10-14  2377  		vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid);
ad987fc8e Michael Ellerman    2015-10-14  2378  
ad987fc8e Michael Ellerman    2015-10-14  2379  		if (esid || vsid) {
ad987fc8e Michael Ellerman    2015-10-14  2380  			printf(" slb_shadow[%d]:       = 0x%016lx 0x%016lx\n",
ad987fc8e Michael Ellerman    2015-10-14  2381  				i, esid, vsid);
ad987fc8e Michael Ellerman    2015-10-14  2382  		}
ad987fc8e Michael Ellerman    2015-10-14  2383  	}
ad987fc8e Michael Ellerman    2015-10-14  2384  	DUMP(p, vmalloc_sllp, "x");
ad987fc8e Michael Ellerman    2015-10-14  2385  	DUMP(p, slb_cache_ptr, "x");
ad987fc8e Michael Ellerman    2015-10-14  2386  	for (i = 0; i < SLB_CACHE_ENTRIES; i++)
ad987fc8e Michael Ellerman    2015-10-14  2387  		printf(" slb_cache[%d]:        = 0x%016lx\n", i, p->slb_cache[i]);
274920a3e Michael Ellerman    2018-01-10  2388  
274920a3e Michael Ellerman    2018-01-10  2389  	DUMP(p, rfi_flush_fallback_area, "px");
ad987fc8e Michael Ellerman    2015-10-14  2390  #endif
ad987fc8e Michael Ellerman    2015-10-14  2391  	DUMP(p, dscr_default, "llx");
ad987fc8e Michael Ellerman    2015-10-14  2392  #ifdef CONFIG_PPC_BOOK3E
2248fade9 Michael Ellerman    2018-01-11  2393  	DUMP(p, pgd, "px");
2248fade9 Michael Ellerman    2018-01-11  2394  	DUMP(p, kernel_pgd, "px");
2248fade9 Michael Ellerman    2018-01-11  2395  	DUMP(p, tcd_ptr, "px");
2248fade9 Michael Ellerman    2018-01-11  2396  	DUMP(p, mc_kstack, "px");
2248fade9 Michael Ellerman    2018-01-11  2397  	DUMP(p, crit_kstack, "px");
2248fade9 Michael Ellerman    2018-01-11  2398  	DUMP(p, dbg_kstack, "px");
ad987fc8e Michael Ellerman    2015-10-14  2399  #endif
2248fade9 Michael Ellerman    2018-01-11  2400  	DUMP(p, __current, "px");
ddadb6b8e Michael Ellerman    2012-09-13  2401  	DUMP(p, kstack, "lx");
90d647374 Michael Ellerman    2017-10-09  2402  	printf(" kstack_base          = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1));
ddadb6b8e Michael Ellerman    2012-09-13  2403  	DUMP(p, stab_rr, "lx");
ddadb6b8e Michael Ellerman    2012-09-13  2404  	DUMP(p, saved_r1, "lx");
ddadb6b8e Michael Ellerman    2012-09-13  2405  	DUMP(p, trap_save, "x");
4e26bc4a4 Madhavan Srinivasan 2017-12-20  2406  	DUMP(p, irq_soft_mask, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2407  	DUMP(p, irq_happened, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2408  	DUMP(p, io_sync, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2409  	DUMP(p, irq_work_pending, "x");
ddadb6b8e Michael Ellerman    2012-09-13  2410  	DUMP(p, nap_state_lost, "x");
ad987fc8e Michael Ellerman    2015-10-14  2411  	DUMP(p, sprg_vdso, "llx");
ad987fc8e Michael Ellerman    2015-10-14  2412  
ad987fc8e Michael Ellerman    2015-10-14  2413  #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
ad987fc8e Michael Ellerman    2015-10-14  2414  	DUMP(p, tm_scratch, "llx");
ad987fc8e Michael Ellerman    2015-10-14  2415  #endif
ad987fc8e Michael Ellerman    2015-10-14  2416  
ad987fc8e Michael Ellerman    2015-10-14  2417  #ifdef CONFIG_PPC_POWERNV
2248fade9 Michael Ellerman    2018-01-11  2418  	DUMP(p, core_idle_state_ptr, "px");
ad987fc8e Michael Ellerman    2015-10-14  2419  	DUMP(p, thread_idle_state, "x");
ad987fc8e Michael Ellerman    2015-10-14  2420  	DUMP(p, thread_mask, "x");
ad987fc8e Michael Ellerman    2015-10-14  2421  	DUMP(p, subcore_sibling_mask, "x");
ad987fc8e Michael Ellerman    2015-10-14  2422  #endif
ddadb6b8e Michael Ellerman    2012-09-13  2423  
8c8b73c48 Frederic Weisbecker 2017-01-05  2424  	DUMP(p, accounting.utime, "llx");
8c8b73c48 Frederic Weisbecker 2017-01-05  2425  	DUMP(p, accounting.stime, "llx");
8c8b73c48 Frederic Weisbecker 2017-01-05 @2426  	DUMP(p, accounting.utime_scaled, "llx");
c223c9038 Christophe Leroy    2016-05-17  2427  	DUMP(p, accounting.starttime, "llx");
c223c9038 Christophe Leroy    2016-05-17  2428  	DUMP(p, accounting.starttime_user, "llx");
c223c9038 Christophe Leroy    2016-05-17 @2429  	DUMP(p, accounting.startspurr, "llx");
c223c9038 Christophe Leroy    2016-05-17 @2430  	DUMP(p, accounting.utime_sspurr, "llx");
f828c3d0a Frederic Weisbecker 2017-01-05  2431  	DUMP(p, accounting.steal_time, "llx");
ddadb6b8e Michael Ellerman    2012-09-13  2432  #undef DUMP
ddadb6b8e Michael Ellerman    2012-09-13  2433  
ddadb6b8e Michael Ellerman    2012-09-13  2434  	catch_memory_errors = 0;
ddadb6b8e Michael Ellerman    2012-09-13  2435  	sync();
ddadb6b8e Michael Ellerman    2012-09-13  2436  }
ddadb6b8e Michael Ellerman    2012-09-13  2437  

:::::: The code at line 2426 was first introduced by commit
:::::: 8c8b73c4811f2b5e458a7418dca07d2ef85c7db1 sched/cputime, powerpc: Prepare accounting structure for cputime flush on tick

:::::: TO: Frederic Weisbecker <fweisbec@gmail.com>
:::::: CC: Ingo Molnar <mingo@kernel.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 24150 bytes --]

^ permalink raw reply

* [PATCH] powerpc/eeh: Fix race with driver un/bind
From: Michael Neuling @ 2018-03-23  5:44 UTC (permalink / raw)
  To: mpe; +Cc: linuxppc-dev, benh, ruscur, sam.bobroff, Michael Neuling

The current EEH callbacks can race with a driver unbind. This
can result in a backtraces like this:

[    7.573055] EEH: Frozen PHB#0-PE#1fc detected
[    7.573063] EEH: PE location: S000009, PHB location: N/A
[    7.573069] CPU: 2 PID: 2312 Comm: kworker/u258:3 Not tainted 4.15.6-openpower1 #2
[    7.573078] Workqueue: nvme-wq nvme_reset_work [nvme]
[    7.573080] Call Trace:
[    7.573088] [c000000ff12a3a30] [c0000000005f5000] dump_stack+0x9c/0xd0
[    7.573093]  (unreliable)
[    7.573106] [c000000ff12a3a70] [c00000000002385c] eeh_dev_check_failure+0x420/0x470
[    7.573111] [c000000ff12a3b10] [c00000000002394c] eeh_check_failure+0xa0/0xa4
[    7.573115] [c000000ff12a3b50] [c0080000088c2ff0] nvme_reset_work+0x138/0x1414 [nvme]
[    7.573122] [c000000ff12a3cb0] [c000000000089c78] process_one_work+0x1ec/0x328
[    7.573132] [c000000ff12a3d40] [c00000000008a3b4] worker_thread+0x2e4/0x3a8
[    7.573140] [c000000ff12a3dc0] [c00000000008fed0] kthread+0x14c/0x154
[    7.573150] [c000000ff12a3e30] [c00000000000b594] ret_from_kernel_thread+0x5c/0xc8
[    7.573183] nvme nvme1: Removing after probe failure status: -19
<snip>
cpu 0x23: Vector: 300 (Data Access) at [c000000ff50f3800]
    pc: c0080000089a0eb0: nvme_error_detected+0x4c/0x90 [nvme]
    lr: c000000000026564: eeh_report_error+0xe0/0x110
    sp: c000000ff50f3a80
   msr: 9000000000009033
   dar: 400
 dsisr: 40000000
  current = 0xc000000ff507c000
  paca    = 0xc00000000fdc9d80   softe: 0        irq_happened: 0x01
    pid   = 782, comm = eehd
Linux version 4.15.6-openpower1 (smc@smc-desktop) (gcc version 6.4.0 (Buildroot 2017.11.2-00008-g4b6188e)) #2 SM                                             P Tue Feb 27 12:33:27 PST 2018
enter ? for help
[c000000ff50f3af0] c000000000026564 eeh_report_error+0xe0/0x110
[c000000ff50f3b30] c000000000025520 eeh_pe_dev_traverse+0xc0/0xdc
[c000000ff50f3bc0] c000000000026bd0 eeh_handle_normal_event+0x184/0x4c4
[c000000ff50f3c70] c000000000026ff4 eeh_handle_event+0x30/0x288
[c000000ff50f3d10] c00000000002758c eeh_event_handler+0x124/0x170
[c000000ff50f3dc0] c00000000008fed0 kthread+0x14c/0x154
[c000000ff50f3e30] c00000000000b594 ret_from_kernel_thread+0x5c/0xc8

The first part is an EEH (on boot), the second half is the resulting
crash. nvme probe starts the nvme_reset_work() worker thread. This
worker thread starts touching the device which see a device error
(EEH) and hence queues up an event in the powerpc EEH worker
thread. nvme_reset_work() then continues and runs
nvme_remove_dead_ctrl_work() which results in unbinding the driver
from the device and hence releases all resources. At the same time,
the EEH worker thread starts doing the EEH .error_detected() driver
callback, which no longer works since the resources have been freed.

This fixes the problem in the same way the generic PCIe AER code (in
drivers/pci/pcie/aer/aerdrv_core.c) does. It makes the EEH code hold
the device_lock() before performing the driver EEH callbacks. This
ensures either the callbacks are no longer register, or if they are
registered the driver will not be removed from underneath us.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
 arch/powerpc/kernel/eeh_driver.c | 67 ++++++++++++++++++++++++----------------
 1 file changed, 41 insertions(+), 26 deletions(-)

diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 0c0b66fc5b..7cf946ae9a 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -207,18 +207,18 @@ static void *eeh_report_error(void *data, void *userdata)
 
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
+
+	device_lock(&dev->dev);
 	dev->error_state = pci_channel_io_frozen;
 
 	driver = eeh_pcid_get(dev);
-	if (!driver) return NULL;
+	if (!driver) goto out2;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
-	    !driver->err_handler->error_detected) {
-		eeh_pcid_put(dev);
-		return NULL;
-	}
+	    !driver->err_handler->error_detected)
+		goto out1;
 
 	rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
 
@@ -227,8 +227,11 @@ static void *eeh_report_error(void *data, void *userdata)
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
 	edev->in_error = true;
-	eeh_pcid_put(dev);
 	pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
+out1:
+	eeh_pcid_put(dev);
+out2:
+	device_unlock(&dev->dev);
 	return NULL;
 }
 
@@ -251,15 +254,14 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
 
+	device_lock(&dev->dev);
 	driver = eeh_pcid_get(dev);
-	if (!driver) return NULL;
+	if (!driver) goto out2;
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->mmio_enabled ||
-	    (edev->mode & EEH_DEV_NO_HANDLER)) {
-		eeh_pcid_put(dev);
-		return NULL;
-	}
+	    (edev->mode & EEH_DEV_NO_HANDLER))
+		goto out1;
 
 	rc = driver->err_handler->mmio_enabled(dev);
 
@@ -267,7 +269,10 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
 	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
 
+out1:
 	eeh_pcid_put(dev);
+out2:
+	device_unlock(&dev->dev);
 	return NULL;
 }
 
@@ -290,20 +295,20 @@ static void *eeh_report_reset(void *data, void *userdata)
 
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
+
+	device_lock(&dev->dev);
 	dev->error_state = pci_channel_io_normal;
 
 	driver = eeh_pcid_get(dev);
-	if (!driver) return NULL;
+	if (!driver) goto out2;
 
 	eeh_enable_irq(dev);
 
 	if (!driver->err_handler ||
 	    !driver->err_handler->slot_reset ||
 	    (edev->mode & EEH_DEV_NO_HANDLER) ||
-	    (!edev->in_error)) {
-		eeh_pcid_put(dev);
-		return NULL;
-	}
+	    (!edev->in_error))
+		goto out1;
 
 	rc = driver->err_handler->slot_reset(dev);
 	if ((*res == PCI_ERS_RESULT_NONE) ||
@@ -311,7 +316,10 @@ static void *eeh_report_reset(void *data, void *userdata)
 	if (*res == PCI_ERS_RESULT_DISCONNECT &&
 	     rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
 
+out1:
 	eeh_pcid_put(dev);
+out2:
+	device_unlock(&dev->dev);
 	return NULL;
 }
 
@@ -362,10 +370,12 @@ static void *eeh_report_resume(void *data, void *userdata)
 
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
+
+	device_lock(&dev->dev);
 	dev->error_state = pci_channel_io_normal;
 
 	driver = eeh_pcid_get(dev);
-	if (!driver) return NULL;
+	if (!driver) goto out2;
 
 	was_in_error = edev->in_error;
 	edev->in_error = false;
@@ -375,18 +385,20 @@ static void *eeh_report_resume(void *data, void *userdata)
 	    !driver->err_handler->resume ||
 	    (edev->mode & EEH_DEV_NO_HANDLER) || !was_in_error) {
 		edev->mode &= ~EEH_DEV_NO_HANDLER;
-		eeh_pcid_put(dev);
-		return NULL;
+		goto out1;
 	}
 
 	driver->err_handler->resume(dev);
 
-	eeh_pcid_put(dev);
 	pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
+out1:
+	eeh_pcid_put(dev);
 #ifdef CONFIG_PCI_IOV
 	if (eeh_ops->notify_resume && eeh_dev_to_pdn(edev))
 		eeh_ops->notify_resume(eeh_dev_to_pdn(edev));
 #endif
+out2:
+	device_unlock(&dev->dev);
 	return NULL;
 }
 
@@ -406,23 +418,26 @@ static void *eeh_report_failure(void *data, void *userdata)
 
 	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
 		return NULL;
+
+	device_lock(&dev->dev);
 	dev->error_state = pci_channel_io_perm_failure;
 
 	driver = eeh_pcid_get(dev);
-	if (!driver) return NULL;
+	if (!driver) goto out2;
 
 	eeh_disable_irq(dev);
 
 	if (!driver->err_handler ||
-	    !driver->err_handler->error_detected) {
-		eeh_pcid_put(dev);
-		return NULL;
-	}
+	    !driver->err_handler->error_detected)
+		goto out1;
 
 	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
 
-	eeh_pcid_put(dev);
 	pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
+out1:
+	eeh_pcid_put(dev);
+out2:
+	device_unlock(&dev->dev);
 	return NULL;
 }
 
-- 
2.14.1

^ permalink raw reply related

* [PATCH] powerpc/64s: Fix i-side SLB miss bad address handler saving nonvolatile GPRs
From: Nicholas Piggin @ 2018-03-23  5:53 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin, Paul Mackerras

The SLB bad address handler's trap number fixup does not preserve the
low bit that indicates nonvolatile GPRs have not been saved. This
leads save_nvgprs to skip saving them, and subsequent functions and
return from interrupt will think they are saved.

This causes kernel branch-to-garbage debugging to not have correct
registers, can also cause userspace to have its registers clobbered
after a segfault.

Fixes: f0f558b131 ("powerpc/mm: Preserve CFAR value on SLB miss caused by access to bogus address")
Cc: Paul Mackerras <paulus@ozlabs.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kernel/exceptions-64s.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 3ac87e53b3da..1ecfd8ffb098 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -706,7 +706,7 @@ EXC_COMMON_BEGIN(bad_addr_slb)
 	ld	r3, PACA_EXSLB+EX_DAR(r13)
 	std	r3, _DAR(r1)
 	beq	cr6, 2f
-	li	r10, 0x480		/* fix trap number for I-SLB miss */
+	li	r10, 0x481		/* fix trap number for I-SLB miss */
 	std	r10, _TRAP(r1)
 2:	bl	save_nvgprs
 	addi	r3, r1, STACK_FRAME_OVERHEAD
-- 
2.16.1

^ permalink raw reply related

* Re: [PATCH 3/3] powerpc/mm: Fixup tlbie vs store ordering issue on POWER9
From: Michael Ellerman @ 2018-03-23  5:55 UTC (permalink / raw)
  To: Aneesh Kumar K.V, benh, paulus, mauricfo; +Cc: linuxppc-dev, Aneesh Kumar K.V
In-Reply-To: <20180323045627.16800-3-aneesh.kumar@linux.vnet.ibm.com>

"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> writes:
> diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
> index a2c5c95882cf..6c151d2e9bd9 100644
> --- a/arch/powerpc/include/asm/cputable.h
> +++ b/arch/powerpc/include/asm/cputable.h
> @@ -465,7 +466,7 @@ static inline void cpu_feature_keys_init(void) { }
>  	    CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
>  	    CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | \
>  	    CPU_FTR_ARCH_207S | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | \
> -	    CPU_FTR_PKEY)
> +	    CPU_FTR_PKEY | CPU_FTR_TLBIE_BUG)

We also need to enable this when we're using DT_CPU_FTRS.

We're still working out the best way to handle that sort of thing long
term, for now I'll just fold in a quirk that turns this feature on for
all Power9 revisions. We can do a follow-up patch to make that
conditional later.

diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 0bcfb0f256e1..553514cd6c27 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -709,6 +709,9 @@ static __init void cpufeatures_cpu_quirks(void)
 		cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1;
 	else if ((version & 0xffffefff) == 0x004e0201)
 		cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
+
+	if ((version & 0xffff0000) == 0x004e0000)
+		cur_cpu_spec->cpu_features |= CPU_FTR_TLBIE_BUG;
 }
 

cheers

^ permalink raw reply related

* Re: [PATCH 3/3] powerpc/mm: Fixup tlbie vs store ordering issue on POWER9
From: Benjamin Herrenschmidt @ 2018-03-23  6:28 UTC (permalink / raw)
  To: Aneesh Kumar K.V, paulus, mpe, mauricfo; +Cc: linuxppc-dev
In-Reply-To: <20180323045627.16800-3-aneesh.kumar@linux.vnet.ibm.com>

On Fri, 2018-03-23 at 10:26 +0530, Aneesh Kumar K.V wrote:
> +#define CPU_FTR_TLBIE_BUG              LONG_ASM_CONST(0x2000000000000000)

I did ask you to make this CPU_FTR_POWER9_TLBIE_BUG...

Cheers,
Ben

^ permalink raw reply

* Re: [PATCH] powerpc/eeh: Fix race with driver un/bind
From: Benjamin Herrenschmidt @ 2018-03-23  6:33 UTC (permalink / raw)
  To: Michael Neuling, mpe; +Cc: linuxppc-dev, ruscur, sam.bobroff
In-Reply-To: <20180323054417.3268-1-mikey@neuling.org>

On Fri, 2018-03-23 at 16:44 +1100, Michael Neuling wrote:

 .../...

> This fixes the problem in the same way the generic PCIe AER code (in
> drivers/pci/pcie/aer/aerdrv_core.c) does. It makes the EEH code hold
> the device_lock() before performing the driver EEH callbacks. This
> ensures either the callbacks are no longer register, or if they are
> registered the driver will not be removed from underneath us.
> 
> Signed-off-by: Michael Neuling <mikey@neuling.org>

Generally ok, minor nits though and do we want a CC stable ?

> ---
>  arch/powerpc/kernel/eeh_driver.c | 67 ++++++++++++++++++++++++----------------
>  1 file changed, 41 insertions(+), 26 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
> index 0c0b66fc5b..7cf946ae9a 100644
> --- a/arch/powerpc/kernel/eeh_driver.c
> +++ b/arch/powerpc/kernel/eeh_driver.c
> @@ -207,18 +207,18 @@ static void *eeh_report_error(void *data, void *userdata)
>  
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
> +
> +	device_lock(&dev->dev);
>  	dev->error_state = pci_channel_io_frozen;
>  
>  	driver = eeh_pcid_get(dev);
> -	if (!driver) return NULL;
> +	if (!driver) goto out2;

I don't like out1/out2, why not call them out_nodev and out_no_handler
? (same comment for the other ones).
>  
>  	eeh_disable_irq(dev);
>  
>  	if (!driver->err_handler ||
> -	    !driver->err_handler->error_detected) {
> -		eeh_pcid_put(dev);
> -		return NULL;
> -	}
> +	    !driver->err_handler->error_detected)
> +		goto out1;
>  
>  	rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen);
>  
> @@ -227,8 +227,11 @@ static void *eeh_report_error(void *data, void *userdata)
>  	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
>  
>  	edev->in_error = true;
> -	eeh_pcid_put(dev);
>  	pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
> +out1:
> +	eeh_pcid_put(dev);
> +out2:

This also changes doing the uevent while holding a reference and the
the device lock, is that ok ? (I guess a reference is a good thing, the
device lock, not sure... I hope so but you should at least document it
as a chance in the cset comment).

> +	device_unlock(&dev->dev);
>  	return NULL;
>  }
>  
> @@ -251,15 +254,14 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
>  
> +	device_lock(&dev->dev);
>  	driver = eeh_pcid_get(dev);
> -	if (!driver) return NULL;
> +	if (!driver) goto out2;
>  
>  	if (!driver->err_handler ||
>  	    !driver->err_handler->mmio_enabled ||
> -	    (edev->mode & EEH_DEV_NO_HANDLER)) {
> -		eeh_pcid_put(dev);
> -		return NULL;
> -	}
> +	    (edev->mode & EEH_DEV_NO_HANDLER))
> +		goto out1;
>  
>  	rc = driver->err_handler->mmio_enabled(dev);
>  
> @@ -267,7 +269,10 @@ static void *eeh_report_mmio_enabled(void *data, void *userdata)
>  	if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
>  	if (*res == PCI_ERS_RESULT_NONE) *res = rc;
>  
> +out1:
>  	eeh_pcid_put(dev);
> +out2:
> +	device_unlock(&dev->dev);
>  	return NULL;
>  }
>  
> @@ -290,20 +295,20 @@ static void *eeh_report_reset(void *data, void *userdata)
>  
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
> +
> +	device_lock(&dev->dev);
>  	dev->error_state = pci_channel_io_normal;
>  
>  	driver = eeh_pcid_get(dev);
> -	if (!driver) return NULL;
> +	if (!driver) goto out2;
>  
>  	eeh_enable_irq(dev);
>  
>  	if (!driver->err_handler ||
>  	    !driver->err_handler->slot_reset ||
>  	    (edev->mode & EEH_DEV_NO_HANDLER) ||
> -	    (!edev->in_error)) {
> -		eeh_pcid_put(dev);
> -		return NULL;
> -	}
> +	    (!edev->in_error))
> +		goto out1;
>  
>  	rc = driver->err_handler->slot_reset(dev);
>  	if ((*res == PCI_ERS_RESULT_NONE) ||
> @@ -311,7 +316,10 @@ static void *eeh_report_reset(void *data, void *userdata)
>  	if (*res == PCI_ERS_RESULT_DISCONNECT &&
>  	     rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
>  
> +out1:
>  	eeh_pcid_put(dev);
> +out2:
> +	device_unlock(&dev->dev);
>  	return NULL;
>  }
>  
> @@ -362,10 +370,12 @@ static void *eeh_report_resume(void *data, void *userdata)
>  
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
> +
> +	device_lock(&dev->dev);
>  	dev->error_state = pci_channel_io_normal;
>  
>  	driver = eeh_pcid_get(dev);
> -	if (!driver) return NULL;
> +	if (!driver) goto out2;
>  
>  	was_in_error = edev->in_error;
>  	edev->in_error = false;
> @@ -375,18 +385,20 @@ static void *eeh_report_resume(void *data, void *userdata)
>  	    !driver->err_handler->resume ||
>  	    (edev->mode & EEH_DEV_NO_HANDLER) || !was_in_error) {
>  		edev->mode &= ~EEH_DEV_NO_HANDLER;
> -		eeh_pcid_put(dev);
> -		return NULL;
> +		goto out1;
>  	}
>  
>  	driver->err_handler->resume(dev);
>  
> -	eeh_pcid_put(dev);
>  	pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
> +out1:
> +	eeh_pcid_put(dev);
>  #ifdef CONFIG_PCI_IOV
>  	if (eeh_ops->notify_resume && eeh_dev_to_pdn(edev))
>  		eeh_ops->notify_resume(eeh_dev_to_pdn(edev));
>  #endif
> +out2:
> +	device_unlock(&dev->dev);
>  	return NULL;
>  }
>  
> @@ -406,23 +418,26 @@ static void *eeh_report_failure(void *data, void *userdata)
>  
>  	if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe))
>  		return NULL;
> +
> +	device_lock(&dev->dev);
>  	dev->error_state = pci_channel_io_perm_failure;
>  
>  	driver = eeh_pcid_get(dev);
> -	if (!driver) return NULL;
> +	if (!driver) goto out2;
>  
>  	eeh_disable_irq(dev);
>  
>  	if (!driver->err_handler ||
> -	    !driver->err_handler->error_detected) {
> -		eeh_pcid_put(dev);
> -		return NULL;
> -	}
> +	    !driver->err_handler->error_detected)
> +		goto out1;
>  
>  	driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
>  
> -	eeh_pcid_put(dev);
>  	pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
> +out1:
> +	eeh_pcid_put(dev);
> +out2:
> +	device_unlock(&dev->dev);
>  	return NULL;
>  }
>  

^ permalink raw reply

* Re: [PATCH 1/3] powerpc/mm/radix: Remove unused code
From: Nicholas Piggin @ 2018-03-23  7:33 UTC (permalink / raw)
  To: Aneesh Kumar K.V; +Cc: benh, paulus, mpe, mauricfo, linuxppc-dev
In-Reply-To: <20180323045627.16800-1-aneesh.kumar@linux.vnet.ibm.com>

On Fri, 23 Mar 2018 10:26:25 +0530
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:

> These function are not used in the code. Remove them.
> 
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>

You already acked this one :)

https://patchwork.ozlabs.org/patch/868852/

^ permalink raw reply

* [PATCH 1/6] libnvdimm: Add of_node to region and bus descriptors
From: Oliver O'Halloran @ 2018-03-23  8:12 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: devicetree, linuxppc-dev, Oliver O'Halloran

We want to be able to cross reference the region and bus devices
with the device tree node that they were spawned from. libNVDIMM
handles creating the actual devices for these internally, so we
need to pass in a pointer to the relevant node in the descriptor.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Acked-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/nvdimm/bus.c         | 1 +
 drivers/nvdimm/region_devs.c | 1 +
 include/linux/libnvdimm.h    | 3 +++
 3 files changed, 5 insertions(+)

diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 78eabc3a1ab1..c6106914f396 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -358,6 +358,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
 	nvdimm_bus->dev.release = nvdimm_bus_release;
 	nvdimm_bus->dev.groups = nd_desc->attr_groups;
 	nvdimm_bus->dev.bus = &nvdimm_bus_type;
+	nvdimm_bus->dev.of_node = nd_desc->of_node;
 	dev_set_name(&nvdimm_bus->dev, "ndbus%d", nvdimm_bus->id);
 	rc = device_register(&nvdimm_bus->dev);
 	if (rc) {
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index e6d01911e092..2f1d5771100e 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1005,6 +1005,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
 	dev->parent = &nvdimm_bus->dev;
 	dev->type = dev_type;
 	dev->groups = ndr_desc->attr_groups;
+	dev->of_node = ndr_desc->of_node;
 	nd_region->ndr_size = resource_size(ndr_desc->res);
 	nd_region->ndr_start = ndr_desc->res->start;
 	nd_device_register(dev);
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index ff855ed965fb..f61cb5050297 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -76,12 +76,14 @@ typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,
 		struct nvdimm *nvdimm, unsigned int cmd, void *buf,
 		unsigned int buf_len, int *cmd_rc);
 
+struct device_node;
 struct nvdimm_bus_descriptor {
 	const struct attribute_group **attr_groups;
 	unsigned long bus_dsm_mask;
 	unsigned long cmd_mask;
 	struct module *module;
 	char *provider_name;
+	struct device_node *of_node;
 	ndctl_fn ndctl;
 	int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc);
 	int (*clear_to_send)(struct nvdimm_bus_descriptor *nd_desc,
@@ -123,6 +125,7 @@ struct nd_region_desc {
 	int num_lanes;
 	int numa_node;
 	unsigned long flags;
+	struct device_node *of_node;
 };
 
 struct device;
-- 
2.9.5

^ permalink raw reply related

* [PATCH 2/6] libnvdimm: Add nd_region_destroy()
From: Oliver O'Halloran @ 2018-03-23  8:12 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: devicetree, linuxppc-dev, Oliver O'Halloran
In-Reply-To: <20180323081209.31387-1-oohall@gmail.com>

Currently there's no way to remove a region from and nvdimm_bus without
tearing down the whole bus. This patch adds an API for removing a single
region from the bus so that we can implement a sensible unbind operation
for the of_nd_region platform driver.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 drivers/nvdimm/region_devs.c | 6 ++++++
 include/linux/libnvdimm.h    | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 2f1d5771100e..76f46fd1fae0 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1039,6 +1039,12 @@ struct nd_region *nvdimm_blk_region_create(struct nvdimm_bus *nvdimm_bus,
 }
 EXPORT_SYMBOL_GPL(nvdimm_blk_region_create);
 
+void nd_region_destroy(struct nd_region *region)
+{
+	nd_device_unregister(&region->dev, ND_SYNC);
+}
+EXPORT_SYMBOL_GPL(nd_region_destroy);
+
 struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus,
 		struct nd_region_desc *ndr_desc)
 {
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index f61cb5050297..df21ca176e98 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -192,6 +192,7 @@ struct nd_region *nvdimm_blk_region_create(struct nvdimm_bus *nvdimm_bus,
 		struct nd_region_desc *ndr_desc);
 struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus,
 		struct nd_region_desc *ndr_desc);
+void nd_region_destroy(struct nd_region *region);
 void *nd_region_provider_data(struct nd_region *nd_region);
 void *nd_blk_region_provider_data(struct nd_blk_region *ndbr);
 void nd_blk_region_set_provider_data(struct nd_blk_region *ndbr, void *data);
-- 
2.9.5

^ permalink raw reply related

* [PATCH 3/6] libnvdimm: Add device-tree based driver
From: Oliver O'Halloran @ 2018-03-23  8:12 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: devicetree, linuxppc-dev, Oliver O'Halloran
In-Reply-To: <20180323081209.31387-1-oohall@gmail.com>

This patch adds peliminary device-tree bindings for the NVDIMM driver.
Currently this only supports one bus (created at probe time) which all
regions are added to with individual regions being created by a platform
device driver.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
I suspect the platform driver should be holding a reference to the
created region. I left that out here since previously Dan has said
he'd rather keep the struct device internal to libnvdimm and the only
other way a region device can disappear is when the bus is unregistered.
---
 MAINTAINERS                |   8 +++
 drivers/nvdimm/Kconfig     |  10 ++++
 drivers/nvdimm/Makefile    |   1 +
 drivers/nvdimm/of_nvdimm.c | 130 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 149 insertions(+)
 create mode 100644 drivers/nvdimm/of_nvdimm.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4e62756936fa..e3fc47fbfc7a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8035,6 +8035,14 @@ Q:	https://patchwork.kernel.org/project/linux-nvdimm/list/
 S:	Supported
 F:	drivers/nvdimm/pmem*
 
+LIBNVDIMM: DEVICETREE BINDINGS
+M:	Oliver O'Halloran <oohall@gmail.com>
+L:	linux-nvdimm@lists.01.org
+Q:	https://patchwork.kernel.org/project/linux-nvdimm/list/
+S:	Supported
+F:	drivers/nvdimm/of_nvdimm.c
+F:	Documentation/devicetree/bindings/nvdimm/nvdimm-bus.txt
+
 LIBNVDIMM: NON-VOLATILE MEMORY DEVICE SUBSYSTEM
 M:	Dan Williams <dan.j.williams@intel.com>
 L:	linux-nvdimm@lists.01.org
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index a65f2e1d9f53..505a9bbbe49f 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -102,4 +102,14 @@ config NVDIMM_DAX
 
 	  Select Y if unsure
 
+config OF_NVDIMM
+	tristate "Device-tree support for NVDIMMs"
+	depends on OF
+	default LIBNVDIMM
+	help
+	  Allows byte addressable persistent memory regions to be described in the
+	  device-tree.
+
+	  Select Y if unsure.
+
 endif
diff --git a/drivers/nvdimm/Makefile b/drivers/nvdimm/Makefile
index 70d5f3ad9909..fd6a5838aa25 100644
--- a/drivers/nvdimm/Makefile
+++ b/drivers/nvdimm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
 obj-$(CONFIG_ND_BTT) += nd_btt.o
 obj-$(CONFIG_ND_BLK) += nd_blk.o
 obj-$(CONFIG_X86_PMEM_LEGACY) += nd_e820.o
+obj-$(CONFIG_OF_NVDIMM) += of_nvdimm.o
 
 nd_pmem-y := pmem.o
 
diff --git a/drivers/nvdimm/of_nvdimm.c b/drivers/nvdimm/of_nvdimm.c
new file mode 100644
index 000000000000..79c28291f420
--- /dev/null
+++ b/drivers/nvdimm/of_nvdimm.c
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#define pr_fmt(fmt) "of_nvdimm: " fmt
+
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/libnvdimm.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+/*
+ * Container bus stuff.  For now we just chunk regions into a default
+ * bus with no ndctl support. In the future we'll add some mechanism
+ * for dispatching regions into the correct bus type, but this is useful
+ * for now.
+ */
+struct nvdimm_bus_descriptor bus_desc;
+struct nvdimm_bus *bus;
+
+/* region driver */
+
+static const struct attribute_group *region_attr_groups[] = {
+	&nd_region_attribute_group,
+	&nd_device_attribute_group,
+	NULL,
+};
+
+static const struct attribute_group *bus_attr_groups[] = {
+	&nvdimm_bus_attribute_group,
+	NULL,
+};
+
+static int of_nd_region_probe(struct platform_device *pdev)
+{
+	struct nd_region_desc ndr_desc;
+	struct resource temp_res;
+	struct nd_region *region;
+	struct device_node *np;
+
+	np = dev_of_node(&pdev->dev);
+	if (!np)
+		return -ENXIO;
+
+	pr_err("registering region for %pOF\n", np);
+
+	if (of_address_to_resource(np, 0, &temp_res)) {
+		pr_warn("Unable to parse reg[0] for %pOF\n", np);
+		return -ENXIO;
+	}
+
+	memset(&ndr_desc, 0, sizeof(ndr_desc));
+	ndr_desc.res = &temp_res;
+	ndr_desc.of_node = np;
+	ndr_desc.attr_groups = region_attr_groups;
+	ndr_desc.numa_node = of_node_to_nid(np);
+	set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
+
+	/*
+	 * NB: libnvdimm copies the data from ndr_desc into it's own structures
+	 * so passing stack pointers is fine.
+	 */
+	if (of_get_property(np, "volatile", NULL))
+		region = nvdimm_volatile_region_create(bus, &ndr_desc);
+	else
+		region = nvdimm_pmem_region_create(bus, &ndr_desc);
+
+	pr_warn("registered pmem region %px\n", region);
+	if (!region)
+		return -ENXIO;
+
+	platform_set_drvdata(pdev, region);
+
+	return 0;
+}
+
+static int of_nd_region_remove(struct platform_device *pdev)
+{
+	struct nd_region *r = platform_get_drvdata(pdev);
+
+	nd_region_destroy(r);
+
+	return 0;
+}
+
+static const struct of_device_id of_nd_region_match[] = {
+	{ .compatible = "nvdimm-region" },
+	{ },
+};
+
+static struct platform_driver of_nd_region_driver = {
+	.probe = of_nd_region_probe,
+	.remove = of_nd_region_remove,
+	.driver = {
+		.name = "of_nd_region",
+		.owner = THIS_MODULE,
+		.of_match_table = of_nd_region_match,
+	},
+};
+
+/* bus wrangling */
+
+static int __init of_nvdimm_init(void)
+{
+	/* register  */
+	bus_desc.attr_groups = bus_attr_groups;
+	bus_desc.provider_name = "of_nvdimm";
+	bus_desc.module = THIS_MODULE;
+
+	/* does parent == NULL work? */
+	bus = nvdimm_bus_register(NULL, &bus_desc);
+	if (!bus)
+		return -ENODEV;
+
+	platform_driver_register(&of_nd_region_driver);
+
+	return 0;
+}
+module_init(of_nvdimm_init);
+
+static void __init of_nvdimm_exit(void)
+{
+	nvdimm_bus_unregister(bus);
+	platform_driver_unregister(&of_nd_region_driver);
+}
+module_exit(of_nvdimm_exit);
+
+MODULE_DEVICE_TABLE(of, of_nd_region_match);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("IBM Corporation");
-- 
2.9.5

^ permalink raw reply related

* [PATCH 4/6] libnvdimm/of: Symlink platform and region devices
From: Oliver O'Halloran @ 2018-03-23  8:12 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: devicetree, linuxppc-dev, Oliver O'Halloran
In-Reply-To: <20180323081209.31387-1-oohall@gmail.com>

Add a way direct link between the region and the platform device that
creates the region.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 drivers/nvdimm/of_nvdimm.c   | 11 +++++++++++
 drivers/nvdimm/region_devs.c | 13 +++++++++++++
 include/linux/libnvdimm.h    |  1 +
 3 files changed, 25 insertions(+)

diff --git a/drivers/nvdimm/of_nvdimm.c b/drivers/nvdimm/of_nvdimm.c
index 79c28291f420..28f4ca23a690 100644
--- a/drivers/nvdimm/of_nvdimm.c
+++ b/drivers/nvdimm/of_nvdimm.c
@@ -37,6 +37,7 @@ static int of_nd_region_probe(struct platform_device *pdev)
 	struct resource temp_res;
 	struct nd_region *region;
 	struct device_node *np;
+	int rc;
 
 	np = dev_of_node(&pdev->dev);
 	if (!np)
@@ -71,6 +72,15 @@ static int of_nd_region_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, region);
 
+	/*
+	 * Add a symlink to the ndbus region object. Without this there's no
+	 * simple way to go from the platform device to the region it spawned.
+	 */
+	rc = sysfs_create_link(&pdev->dev.kobj,
+				nd_region_kobj(region), "region");
+	if (rc)
+		pr_warn("Failed to create symlink to region (rc = %d)!\n", rc);
+
 	return 0;
 }
 
@@ -78,6 +88,7 @@ static int of_nd_region_remove(struct platform_device *pdev)
 {
 	struct nd_region *r = platform_get_drvdata(pdev);
 
+	sysfs_delete_link(&pdev->dev.kobj, nd_region_kobj(r), "region");
 	nd_region_destroy(r);
 
 	return 0;
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 76f46fd1fae0..af09acc1d93b 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1054,6 +1054,19 @@ struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus,
 }
 EXPORT_SYMBOL_GPL(nvdimm_volatile_region_create);
 
+struct kobject *nd_region_kobj(struct nd_region *region)
+{
+	/*
+	 * region init is async so we need to explicitly synchronise
+	 * to prevent handing out a kobj reference before device_add()
+	 * has been run
+	 */
+	nd_synchronize();
+
+	return &region->dev.kobj;
+}
+EXPORT_SYMBOL_GPL(nd_region_kobj);
+
 /**
  * nvdimm_flush - flush any posted write queues between the cpu and pmem media
  * @nd_region: blk or interleaved pmem region
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index df21ca176e98..a4b3663bac38 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -172,6 +172,7 @@ struct nvdimm_bus_descriptor *to_nd_desc(struct nvdimm_bus *nvdimm_bus);
 struct device *to_nvdimm_bus_dev(struct nvdimm_bus *nvdimm_bus);
 const char *nvdimm_name(struct nvdimm *nvdimm);
 struct kobject *nvdimm_kobj(struct nvdimm *nvdimm);
+struct kobject *nd_region_kobj(struct nd_region *region);
 unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm);
 void *nvdimm_provider_data(struct nvdimm *nvdimm);
 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
-- 
2.9.5

^ permalink raw reply related

* [PATCH 5/6] powerpc/powernv: Create platform devs for nvdimm buses
From: Oliver O'Halloran @ 2018-03-23  8:12 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: devicetree, linuxppc-dev, Oliver O'Halloran
In-Reply-To: <20180323081209.31387-1-oohall@gmail.com>

Scan the devicetree for an nvdimm-bus compatible and create
a platform device for them.

Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 arch/powerpc/platforms/powernv/opal.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index c15182765ff5..a16f4b63ccf2 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -821,6 +821,9 @@ static int __init opal_init(void)
 	/* Create i2c platform devices */
 	opal_pdev_init("ibm,opal-i2c");
 
+	/* Handle non-volatile memory devices */
+	opal_pdev_init("nvdimm-region");
+
 	/* Setup a heatbeat thread if requested by OPAL */
 	opal_init_heartbeat();
 
-- 
2.9.5

^ permalink raw reply related

* [PATCH 6/6] doc/devicetree: NVDIMM region documentation
From: Oliver O'Halloran @ 2018-03-23  8:12 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: devicetree, linuxppc-dev, Oliver O'Halloran
In-Reply-To: <20180323081209.31387-1-oohall@gmail.com>

Add device-tree binding documentation for the nvdimm region driver.

Cc: devicetree@vger.kernel.org
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
---
 .../devicetree/bindings/nvdimm/nvdimm-region.txt   | 45 ++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/nvdimm/nvdimm-region.txt

diff --git a/Documentation/devicetree/bindings/nvdimm/nvdimm-region.txt b/Documentation/devicetree/bindings/nvdimm/nvdimm-region.txt
new file mode 100644
index 000000000000..02091117ff16
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvdimm/nvdimm-region.txt
@@ -0,0 +1,45 @@
+Device-tree bindings for NVDIMM memory regions
+-----------------------------------------------------
+
+Non-volatile DIMMs are memory modules used to provide (cacheable) main memory
+that retains its contents across power cycles. In more practical terms, they
+are kind of storage device where the contents can be accessed by the CPU
+directly, rather than indirectly via a storage controller or similar. The an
+nvdimm-region specifies a physical address range that is hosted on an NVDIMM
+device.
+
+Bindings for the region nodes:
+-----------------------------
+
+Required properties:
+	- compatible = "nvdimm-region"
+
+	- reg = <base, size>;
+		The system physical address range of this nvdimm region.
+
+Optional properties:
+	- Any relevant NUMA assocativity properties for the target platform.
+	- A "volatile" property indicating that this region is actually in
+	  normal DRAM and does not require cache flushes after each write.
+
+A complete example:
+--------------------
+
+/ {
+	#size-cells = <2>;
+	#address-cells = <2>;
+
+	platform {
+		region@5000 {
+			compatible = "nvdimm-region;
+			reg = <0x00000001 0x00000000 0x00000000 0x40000000>
+
+		};
+
+		region@6000 {
+			compatible = "nvdimm-region";
+			reg = <0x00000001 0x00000000 0x00000000 0x40000000>
+			volatile;
+		};
+	};
+};
-- 
2.9.5

^ permalink raw reply related

* Re: [PATCH v2] crypto: talitos - fix IPsec cipher in length
From: Horia Geantă @ 2018-03-23  8:17 UTC (permalink / raw)
  To: Christophe Leroy, Herbert Xu, David S. Miller
  Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20180322095701.4563E6F352@po15720vm.idsi0.si.c-s.fr>

On 3/22/2018 11:57 AM, Christophe Leroy wrote:=0A=
> For SEC 2.x+, cipher in length must contain only the ciphertext length.=
=0A=
          ^^^^ turns out this should be 3.x+=0A=
=0A=
> In case of using hardware ICV checking, the ICV length is provided via=0A=
> the "extent" field of the descriptor pointer.=0A=
> =0A=
> Cc: <stable@vger.kernel.org> # 4.8+=0A=
> Fixes: 549bd8bc5987 ("crypto: talitos - Implement AEAD for SEC1 using HMA=
C_SNOOP_NO_AFEU")=0A=
> Reported-by: Horia Geant=E3 <horia.geanta@nxp.com>=0A=
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>=0A=
Tested-by: Horia Geant=E3 <horia.geanta@nxp.com>=0A=
=0A=
Thanks,=0A=
Horia=0A=
=0A=

^ permalink raw reply

* Re: [PATCH 01/19] powerpc/powermac: Mark variable x as unused
From: christophe leroy @ 2018-03-23  9:18 UTC (permalink / raw)
  To: Mathieu Malaterre, Michael Ellerman
  Cc: linux-kernel, kvm-ppc, Paul Mackerras, linuxppc-dev
In-Reply-To: <20180322202007.23088-2-malat@debian.org>



Le 22/03/2018 à 21:19, Mathieu Malaterre a écrit :
> Since the value of x is never intended to be read, declare it with gcc
> attribute as unused. Fix warning treated as error with W=1:
> 
>    arch/powerpc/platforms/powermac/bootx_init.c:471:21: error: variable ‘x’ set but not used [-Werror=unused-but-set-variable]
> 
> Signed-off-by: Mathieu Malaterre <malat@debian.org>
> ---
>   arch/powerpc/platforms/powermac/bootx_init.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c
> index c3c9bbb3573a..d3ce55dae78f 100644
> --- a/arch/powerpc/platforms/powermac/bootx_init.c
> +++ b/arch/powerpc/platforms/powermac/bootx_init.c
> @@ -468,7 +468,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4)
>   	boot_infos_t *bi = (boot_infos_t *) r4;
>   	unsigned long hdr;
>   	unsigned long space;
> -	unsigned long ptr, x;
> +	unsigned long ptr, x __maybe_unused;

Why not use fault_in_pages_readable() instead of the hardcoded part that 
uses x ?

If you decide to keep it as is, at least x should be declared inside the 
if (bi->version < 4)

Christophe


>   	char *model;
>   	unsigned long offset = reloc_offset();
>   
> 

---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus

^ permalink raw reply

* Re: [bug?] Access was denied by memory protection keys in execute-only address
From: Li Wang @ 2018-03-23  9:27 UTC (permalink / raw)
  To: Ram Pai, Cyril Hrubis, Jan Stancek
  Cc: Michael Ellerman, ltp, linux-mm, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20180322070900.GA5605@ram.oc3035372033.ibm.com>

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

On Thu, Mar 22, 2018 at 3:09 PM, Ram Pai <linuxram@us.ibm.com> wrote:

> On Wed, Mar 21, 2018 at 02:53:00PM +0800, Li Wang wrote:
> >    On Wed, Mar 21, 2018 at 5:58 AM, Ram Pai <[1]linuxram@us.ibm.com>
> wrote:
> >
> >      On Fri, Mar 09, 2018 at 11:43:00AM +0800, Li Wang wrote:
> >      >    On Fri, Mar 9, 2018 at 12:45 AM, Ram Pai
> >      <[1][2]linuxram@us.ibm.com> wrote:
> >      >
> >      >      On Thu, Mar 08, 2018 at 11:19:12PM +1100, Michael Ellerman
> wrote:
> >      >      > Li Wang <[2][3]liwang@redhat.com> writes:
> >      >      > > Hi,
> >      >      > >
> >      >      am wondering if the slightly different cpu behavior is
> dependent
> ..snip..
> >      on the
> >      >      version of the firmware/microcode?
> >      >
> >      >    ​I also run this reproducer on series ppc kvm machines, but
> none of
> >      them
> >      >    get the FAIL.
> >      >    If you need some more HW info, pls let me know.​
> >
> >      Hi Li,
> >
> >         Can you try the following patch and see if it solves your
> problem.
> >
> >    ​It only works on power7 lpar machine.
> >
> >    But for p8 lpar, it still get failure as that before, the thing I
> wondered
> >    is
> >    that why not disable the pkey_execute_disable_supported on p8 machine?
>
> It turns out to be a testcase bug.  On Big endian powerpc ABI, function
> ptrs are basically pointers to function descriptors.  The testcase
> copies functions which results in function descriptors getting copied.
> You have to apply the following patch to your test case for it to
> operate as intended.  Thanks to Michael Ellermen for helping me out.
> Otherwise I would be scratching my head for ever.
>

​Thanks for the explanation, I learned something new about this. :)

And the worth to say, seems the patch only works on powerpc arch,
others(x86_64, etc)
that does not works well, so a simple workaround is to isolate the code
changes
to powerpc system?


Hi Cyril & Jan,

Could any of you take a look at this patch, comments?



>
>
> diff --git a/testcases/kernel/syscalls/mprotect/mprotect04.c
> b/testcases/kernel/syscalls/mprotect/mprotect04.c
> index 1173afd..9fe9001 100644
> --- a/testcases/kernel/syscalls/mprotect/mprotect04.c
> +++ b/testcases/kernel/syscalls/mprotect/mprotect04.c
> @@ -189,18 +189,30 @@ static void clear_cache(void *start, int len)
>  #endif
>  }
>
> +typedef struct {
> +       uintptr_t entry;
> +       uintptr_t toc;
> +       uintptr_t env;
> +} func_descr_t;
> +
> +typedef void (*func_ptr_t)(void);
> +
>  /*
>   * Copy page where &exec_func resides. Also try to copy subsequent page
>   * in case exec_func is close to page boundary.
>   */
> -static void *get_func(void *mem)
> +void *get_func(void *mem)
>  {
>         uintptr_t page_sz = getpagesize();
>         uintptr_t page_mask = ~(page_sz - 1);
> -       uintptr_t func_page_offset = (uintptr_t)&exec_func & (page_sz - 1);
> -       void *func_copy_start = mem + func_page_offset;
> -       void *page_to_copy = (void *)((uintptr_t)&exec_func & page_mask);
> +       uintptr_t func_page_offset;
> +       void *func_copy_start, *page_to_copy;
>         void *mem_start = mem;
> +       func_descr_t *opd =  (func_descr_t *)&exec_func;
> +
> +       func_page_offset = (uintptr_t)opd->entry & (page_sz - 1);
> +       func_copy_start = mem + func_page_offset;
> +       page_to_copy = (void *)((uintptr_t)opd->entry & page_mask);
>
>         /* copy 1st page, if it's not present something is wrong */
>         if (!page_present(page_to_copy)) {
> @@ -228,15 +240,17 @@ static void *get_func(void *mem)
>
>  static void testfunc_protexec(void)
>  {
> -       void (*func)(void);
>         void *p;
> +       func_ptr_t func;
> +       func_descr_t opd;
>
>         sig_caught = 0;
>
>         p = SAFE_MMAP(cleanup, 0, copy_sz, PROT_READ | PROT_WRITE,
>                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
>
> -       func = get_func(p);
> +       opd.entry = (uintptr_t)get_func(p);
> +       func = (func_ptr_t)&opd;
>
>         /* Change the protection to PROT_EXEC. */
>         TEST(mprotect(p, copy_sz, PROT_EXEC));
>
>
> RP
>
>


-- 
Li Wang
liwang@redhat.com

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

^ permalink raw reply

* Re: [PATCH 02/19] powerpc/powermac: Mark variable x as unused
From: christophe leroy @ 2018-03-23  9:38 UTC (permalink / raw)
  To: Mathieu Malaterre, Michael Ellerman
  Cc: linux-kernel, kvm-ppc, Paul Mackerras, linuxppc-dev
In-Reply-To: <20180322202007.23088-3-malat@debian.org>



Le 22/03/2018 à 21:19, Mathieu Malaterre a écrit :
> Since the value of x is never intended to be read, declare it with gcc
> attribute as unused. Fix warning treated as error with W=1:
> 
>    arch/powerpc/platforms/powermac/udbg_scc.c:76:9: error: variable ‘x’ set but not used [-Werror=unused-but-set-variable]
> 
> Signed-off-by: Mathieu Malaterre <malat@debian.org>
> ---
>   arch/powerpc/platforms/powermac/udbg_scc.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c
> index d83135a9830e..c38ca406df1a 100644
> --- a/arch/powerpc/platforms/powermac/udbg_scc.c
> +++ b/arch/powerpc/platforms/powermac/udbg_scc.c
> @@ -73,7 +73,7 @@ void udbg_scc_init(int force_scc)
>   	struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
>   	struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
>   	const char *path;
> -	int i, x;
> +	int i, x __maybe_unused;

You could just replace 'x = in_8(sccc)' by 'in_8(sccc)' and get rid of 
the x.

Christophe


>   
>   	escc = of_find_node_by_name(NULL, "escc");
>   	if (escc == NULL)
> 

---
L'absence de virus dans ce courrier électronique a été vérifiée par le logiciel antivirus Avast.
https://www.avast.com/antivirus

^ 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