LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [RFC PATCH 0/5] powerpc/mm/slice: improve slice speed and stack use
From: Nicholas Piggin @ 2018-02-12 15:24 UTC (permalink / raw)
  To: Christophe LEROY; +Cc: linuxppc-dev, Aneesh Kumar K . V
In-Reply-To: <e2043d70-97a7-b914-f279-4aad76b9bf91@c-s.fr>

On Mon, 12 Feb 2018 16:02:23 +0100
Christophe LEROY <christophe.leroy@c-s.fr> wrote:

> Le 10/02/2018 à 09:11, Nicholas Piggin a écrit :
> > This series intends to improve performance and reduce stack
> > consumption in the slice allocation code. It does it by keeping slice
> > masks in the mm_context rather than compute them for each allocation,
> > and by reducing bitmaps and slice_masks from stacks, using pointers
> > instead where possible.
> > 
> > checkstack.pl gives, before:
> > 0x00000de4 slice_get_unmapped_area [slice.o]:           656
> > 0x00001b4c is_hugepage_only_range [slice.o]:            512
> > 0x0000075c slice_find_area_topdown [slice.o]:           416
> > 0x000004c8 slice_find_area_bottomup.isra.1 [slice.o]:   272
> > 0x00001aa0 slice_set_range_psize [slice.o]:             240
> > 0x00000a64 slice_find_area [slice.o]:                   176
> > 0x00000174 slice_check_fit [slice.o]:                   112
> > 
> > after:
> > 0x00000d70 slice_get_unmapped_area [slice.o]:           320
> > 0x000008f8 slice_find_area [slice.o]:                   144
> > 0x00001860 slice_set_range_psize [slice.o]:             144
> > 0x000018ec is_hugepage_only_range [slice.o]:            144
> > 0x00000750 slice_find_area_bottomup.isra.4 [slice.o]:   128
> > 
> > The benchmark in https://github.com/linuxppc/linux/issues/49 gives, before:
> > $ time ./slicemask
> > real	0m20.712s
> > user	0m5.830s
> > sys	0m15.105s
> > 
> > after:
> > $ time ./slicemask
> > real	0m13.197s
> > user	0m5.409s
> > sys	0m7.779s  
> 
> Hi,
> 
> I tested your serie on an 8xx, on top of patch 
> https://patchwork.ozlabs.org/patch/871675/
> 
> I don't get a result as significant as yours, but there is some 
> improvment anyway:
> 
> ITERATION 500000
> 
> Before:
> 
> root@vgoip:~# time ./slicemask
> real    0m 33.26s
> user    0m 1.94s
> sys     0m 30.85s
> 
> After:
> root@vgoip:~# time ./slicemask
> real    0m 29.69s
> user    0m 2.11s
> sys     0m 27.15s
> 
> Most significant improvment is obtained with the first patch of your serie:
> root@vgoip:~# time ./slicemask
> real    0m 30.85s
> user    0m 1.80s
> sys     0m 28.57s

Okay, thanks. Are you still spending significant time in the slice
code?

> 
> Had to modify your serie a bit, if you are interested I can post it.
> 

Sure, that would be good.

Thanks,
Nick

^ permalink raw reply

* [RFC PATCH 00/12] numa aware allocation for pacas, stacks,
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin

This series allows numa aware allocations for various early data
structures for radix. Hash still has a bolted SLB limitation that
prevents at least pacas and stacks from node-affine allocations.

Since I last posted a feeble attempt at this, I went back and tried
to cover the setup / topology discovery code a bit more thoroughly.
Paca allocation is deferred until quite late, and numa discover is
moved slightly earlier.

Still requires more testing with different platforms, BookE, pseries,
etc., But it seems to work with powernv so far.

Thanks,
Nick

Nicholas Piggin (12):
  powerpc/64s: do not allocate lppaca if we are not virtualized
  powerpc/64: Use array of paca pointers and allocate pacas individually
  powerpc/64s: allocate lppacas individually
  powerpc/64s: allocate slb_shadow structures individually
  mm: make memblock_alloc_base_nid non-static
  powerpc/mm/numa: move numa topology discovery earlier
  powerpc/64: move default SPR recording
  powerpc/setup: cpu_to_phys_id array
  powerpc/64: defer paca allocation until memory topology is discovered
  powerpc/64: allocate pacas per node
  powerpc/64: allocate per-cpu stacks node-local if possible
  powerpc/64s/radix: allocate kernel page tables node-local if possible

 arch/powerpc/include/asm/book3s/64/hash.h    |   2 +-
 arch/powerpc/include/asm/book3s/64/radix.h   |   2 +-
 arch/powerpc/include/asm/kvm_ppc.h           |   8 +-
 arch/powerpc/include/asm/lppaca.h            |  26 +--
 arch/powerpc/include/asm/paca.h              |  16 +-
 arch/powerpc/include/asm/pmc.h               |  13 +-
 arch/powerpc/include/asm/setup.h             |   1 +
 arch/powerpc/include/asm/smp.h               |   5 +-
 arch/powerpc/include/asm/sparsemem.h         |   2 +-
 arch/powerpc/kernel/asm-offsets.c            |   5 +
 arch/powerpc/kernel/crash.c                  |   2 +-
 arch/powerpc/kernel/head_64.S                |  19 ++-
 arch/powerpc/kernel/machine_kexec_64.c       |  37 +++--
 arch/powerpc/kernel/paca.c                   | 236 ++++++++++++++-------------
 arch/powerpc/kernel/prom.c                   |  14 +-
 arch/powerpc/kernel/setup-common.c           |  30 +++-
 arch/powerpc/kernel/setup.h                  |   9 +-
 arch/powerpc/kernel/setup_64.c               |  80 ++++++---
 arch/powerpc/kernel/smp.c                    |  10 +-
 arch/powerpc/kernel/sysfs.c                  |  18 +-
 arch/powerpc/kvm/book3s_hv.c                 |  34 ++--
 arch/powerpc/kvm/book3s_hv_builtin.c         |   2 +-
 arch/powerpc/kvm/book3s_hv_interrupts.S      |   3 +-
 arch/powerpc/kvm/book3s_hv_rmhandlers.S      |   3 +-
 arch/powerpc/mm/hash_utils_64.c              |   2 +-
 arch/powerpc/mm/mem.c                        |   9 +-
 arch/powerpc/mm/numa.c                       |  36 ++--
 arch/powerpc/mm/pgtable-book3s64.c           |   6 +-
 arch/powerpc/mm/pgtable-radix.c              | 178 +++++++++++++-------
 arch/powerpc/mm/tlb-radix.c                  |   2 +-
 arch/powerpc/platforms/85xx/smp.c            |   8 +-
 arch/powerpc/platforms/cell/smp.c            |   4 +-
 arch/powerpc/platforms/powernv/idle.c        |  13 +-
 arch/powerpc/platforms/powernv/setup.c       |   4 +-
 arch/powerpc/platforms/powernv/smp.c         |   2 +-
 arch/powerpc/platforms/powernv/subcore.c     |   2 +-
 arch/powerpc/platforms/pseries/hotplug-cpu.c |   2 +-
 arch/powerpc/platforms/pseries/kexec.c       |   7 +-
 arch/powerpc/platforms/pseries/lpar.c        |   4 +-
 arch/powerpc/platforms/pseries/setup.c       |   2 +-
 arch/powerpc/platforms/pseries/smp.c         |   4 +-
 arch/powerpc/sysdev/xics/icp-native.c        |   2 +-
 arch/powerpc/xmon/xmon.c                     |   2 +-
 include/linux/memblock.h                     |   5 +-
 mm/memblock.c                                |   2 +-
 45 files changed, 527 insertions(+), 346 deletions(-)

-- 
2.16.1

^ permalink raw reply

* [RFC PATCH 01/12] powerpc/64s: do not allocate lppaca if we are not virtualized
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

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

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

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

^ permalink raw reply related

* [RFC PATCH 02/12] powerpc/64: Use array of paca pointers and allocate pacas individually
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

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

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

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

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

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

^ permalink raw reply related

* [RFC PATCH 03/12] powerpc/64s: allocate lppacas individually
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Allocate LPPACAs individually.

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

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

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

^ permalink raw reply related

* [RFC PATCH 04/12] powerpc/64s: allocate slb_shadow structures individually
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Allocate slb_shadow structures individually.

slb_shadow structures are avoided for radix environment.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kernel/paca.c | 65 +++++++++++++++++++++-------------------------
 1 file changed, 30 insertions(+), 35 deletions(-)

diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 6cddb9bdc151..2699f9009286 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -72,41 +72,28 @@ static void __init free_lppaca(struct lppaca *lp)
 #ifdef CONFIG_PPC_BOOK3S_64
 
 /*
- * 3 persistent SLBs are registered here.  The buffer will be zero
+ * 3 persistent SLBs are allocated here.  The buffer will be zero
  * initially, hence will all be invaild until we actually write them.
  *
  * If you make the number of persistent SLB entries dynamic, please also
  * update PR KVM to flush and restore them accordingly.
  */
-static struct slb_shadow * __initdata slb_shadow;
-
-static void __init allocate_slb_shadows(int nr_cpus, int limit)
-{
-	int size = PAGE_ALIGN(sizeof(struct slb_shadow) * nr_cpus);
-
-	if (early_radix_enabled())
-		return;
-
-	slb_shadow = __va(memblock_alloc_base(size, PAGE_SIZE, limit));
-	memset(slb_shadow, 0, size);
-}
-
-static struct slb_shadow * __init init_slb_shadow(int cpu)
+static struct slb_shadow * __init new_slb_shadow(int cpu, unsigned long limit)
 {
 	struct slb_shadow *s;
 
-	if (early_radix_enabled())
-		return NULL;
+	if (cpu != boot_cpuid) {
+		/*
+		 * Boot CPU comes here before early_radix_enabled
+		 * is parsed (e.g., for disable_radix). So allocate
+		 * always and this will be fixed up in free_unused_pacas.
+		 */
+		if (early_radix_enabled())
+			return NULL;
+	}
 
-	s = &slb_shadow[cpu];
-
-	/*
-	 * When we come through here to initialise boot_paca, the slb_shadow
-	 * buffers are not allocated yet. That's OK, we'll get one later in
-	 * boot, but make sure we don't corrupt memory at 0.
-	 */
-	if (!slb_shadow)
-		return NULL;
+	s = __va(memblock_alloc_base(sizeof(*s), L1_CACHE_BYTES, limit));
+	memset(s, 0, sizeof(*s));
 
 	s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
 	s->buffer_length = cpu_to_be32(sizeof(*s));
@@ -114,10 +101,6 @@ static struct slb_shadow * __init init_slb_shadow(int cpu)
 	return s;
 }
 
-#else /* !CONFIG_PPC_BOOK3S_64 */
-
-static void __init allocate_slb_shadows(int nr_cpus, int limit) { }
-
 #endif /* CONFIG_PPC_BOOK3S_64 */
 
 /* The Paca is an array with one entry per processor.  Each contains an
@@ -151,7 +134,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 	new_paca->__current = &init_task;
 	new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
 #ifdef CONFIG_PPC_BOOK3S_64
-	new_paca->slb_shadow_ptr = init_slb_shadow(cpu);
+	new_paca->slb_shadow_ptr = NULL;
 #endif
 
 #ifdef CONFIG_PPC_BOOK3E
@@ -222,13 +205,16 @@ void __init allocate_pacas(void)
 	printk(KERN_DEBUG "Allocated %lu bytes for %u pacas\n",
 			size, nr_cpu_ids);
 
-	allocate_slb_shadows(nr_cpu_ids, limit);
-
 	/* Can't use for_each_*_cpu, as they aren't functional yet */
 	for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
-		initialise_paca(paca_ptrs[cpu], cpu);
+		struct paca_struct *paca = paca_ptrs[cpu];
+
+		initialise_paca(paca, cpu);
 #ifdef CONFIG_PPC_PSERIES
-		paca_ptrs[cpu]->lppaca_ptr = new_lppaca(cpu, limit);
+		paca->lppaca_ptr = new_lppaca(cpu, limit);
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
+		paca->slb_shadow_ptr = new_slb_shadow(cpu, limit);
 #endif
 	}
 }
@@ -263,6 +249,15 @@ void __init free_unused_pacas(void)
 
 	paca_nr_cpu_ids = nr_cpu_ids;
 	paca_ptrs_size = new_ptrs_size;
+
+#ifdef CONFIG_PPC_BOOK3S_64
+	if (early_radix_enabled()) {
+		/* Ugly fixup, see new_slb_shadow() */
+		memblock_free(__pa(paca_ptrs[boot_cpuid]->slb_shadow_ptr),
+				sizeof(struct slb_shadow));
+		paca_ptrs[boot_cpuid]->slb_shadow_ptr = NULL;
+	}
+#endif
 }
 
 void copy_mm_to_paca(struct mm_struct *mm)
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 05/12] mm: make memblock_alloc_base_nid non-static
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

This will be used by powerpc to allocate per-cpu stacks and other
data structures node-local where possible.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 include/linux/memblock.h | 5 ++++-
 mm/memblock.c            | 2 +-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 7ed0f7782d16..c0a729c77340 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -316,9 +316,12 @@ static inline bool memblock_bottom_up(void)
 #define MEMBLOCK_ALLOC_ANYWHERE	(~(phys_addr_t)0)
 #define MEMBLOCK_ALLOC_ACCESSIBLE	0
 
-phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
+phys_addr_t memblock_alloc_range(phys_addr_t size, phys_addr_t align,
 					phys_addr_t start, phys_addr_t end,
 					ulong flags);
+phys_addr_t memblock_alloc_base_nid(phys_addr_t size,
+					phys_addr_t align, phys_addr_t max_addr,
+					int nid, ulong flags);
 phys_addr_t memblock_alloc_base(phys_addr_t size, phys_addr_t align,
 				phys_addr_t max_addr);
 phys_addr_t __memblock_alloc_base(phys_addr_t size, phys_addr_t align,
diff --git a/mm/memblock.c b/mm/memblock.c
index 46aacdfa4f4d..12e5e685e585 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1190,7 +1190,7 @@ phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
 					flags);
 }
 
-static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
+phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
 					phys_addr_t align, phys_addr_t max_addr,
 					int nid, ulong flags)
 {
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 06/12] powerpc/mm/numa: move numa topology discovery earlier
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Split sparsemem initialisation from basic numa topology discovery.

XXX: untested with lpars
---
 arch/powerpc/include/asm/setup.h   |  1 +
 arch/powerpc/kernel/setup-common.c |  3 +++
 arch/powerpc/mm/mem.c              |  5 ++++-
 arch/powerpc/mm/numa.c             | 32 +++++++++++++++++++-------------
 4 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index 469b7fdc9be4..d2bf233aebd5 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -23,6 +23,7 @@ extern void reloc_got2(unsigned long);
 #define PTRRELOC(x)	((typeof(x)) add_reloc_offset((unsigned long)(x)))
 
 void check_for_initrd(void);
+void mem_topology_setup(void);
 void initmem_init(void);
 void setup_panic(void);
 #define ARCH_PANIC_TIMEOUT 180
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index af128ee67248..f8a6b8ad13b4 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -888,6 +888,9 @@ void __init setup_arch(char **cmdline_p)
 	/* Check the SMT related command line arguments (ppc64). */
 	check_smt_enabled();
 
+	/* Parse memory topology */
+	mem_topology_setup();
+
 	/* On BookE, setup per-core TLB data structures. */
 	setup_tlb_core_data();
 
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 1281c6eb3a85..70f7b6426a15 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -213,7 +213,7 @@ walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
 EXPORT_SYMBOL_GPL(walk_system_ram_range);
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-void __init initmem_init(void)
+void __init mem_topology_setup(void)
 {
 	max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
 	min_low_pfn = MEMORY_START >> PAGE_SHIFT;
@@ -225,7 +225,10 @@ void __init initmem_init(void)
 	 * memblock_regions
 	 */
 	memblock_set_node(0, (phys_addr_t)ULLONG_MAX, &memblock.memory, 0);
+}
 
+void __init initmem_init(void)
+{
 	/* XXX need to clip this if using highmem? */
 	sparse_memory_present_with_active_regions(0);
 	sparse_init();
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e9ec465068f1..1eec1bcc03a6 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -836,18 +836,13 @@ static void __init find_possible_nodes(void)
 	of_node_put(rtas);
 }
 
-void __init initmem_init(void)
+void __init mem_topology_setup(void)
 {
-	int nid, cpu;
-
-	max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
-	max_pfn = max_low_pfn;
+	int cpu;
 
 	if (parse_numa_properties())
 		setup_nonnuma();
 
-	memblock_dump_all();
-
 	/*
 	 * Modify the set of possible NUMA nodes to reflect information
 	 * available about the set of online nodes, and the set of nodes
@@ -858,6 +853,23 @@ void __init initmem_init(void)
 
 	find_possible_nodes();
 
+	setup_node_to_cpumask_map();
+
+	reset_numa_cpu_lookup_table();
+
+	for_each_present_cpu(cpu)
+		numa_setup_cpu(cpu);
+}
+
+void __init initmem_init(void)
+{
+	int nid;
+
+	max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
+	max_pfn = max_low_pfn;
+
+	memblock_dump_all();
+
 	for_each_online_node(nid) {
 		unsigned long start_pfn, end_pfn;
 
@@ -868,10 +880,6 @@ void __init initmem_init(void)
 
 	sparse_init();
 
-	setup_node_to_cpumask_map();
-
-	reset_numa_cpu_lookup_table();
-
 	/*
 	 * We need the numa_cpu_lookup_table to be accurate for all CPUs,
 	 * even before we online them, so that we can use cpu_to_{node,mem}
@@ -881,8 +889,6 @@ void __init initmem_init(void)
 	 */
 	cpuhp_setup_state_nocalls(CPUHP_POWER_NUMA_PREPARE, "powerpc/numa:prepare",
 				  ppc_numa_cpu_prepare, ppc_numa_cpu_dead);
-	for_each_present_cpu(cpu)
-		numa_setup_cpu(cpu);
 }
 
 static int __init early_numa(char *p)
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 07/12] powerpc/64: move default SPR recording
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Move this into the early setup code, and don't iterate over CPU masks.
We don't want to call into sysfs so early from setup, and a future patch
won't initialize CPU masks by the time this is called.
---
 arch/powerpc/kernel/paca.c     |  3 +++
 arch/powerpc/kernel/setup.h    |  9 +++------
 arch/powerpc/kernel/setup_64.c |  8 ++++++++
 arch/powerpc/kernel/sysfs.c    | 18 +++++++-----------
 4 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 2699f9009286..e560072f122b 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -133,6 +133,9 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)
 	new_paca->kexec_state = KEXEC_STATE_NONE;
 	new_paca->__current = &init_task;
 	new_paca->data_offset = 0xfeeeeeeeeeeeeeeeULL;
+#ifdef CONFIG_PPC64
+	new_paca->dscr_default = spr_default_dscr;
+#endif
 #ifdef CONFIG_PPC_BOOK3S_64
 	new_paca->slb_shadow_ptr = NULL;
 #endif
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h
index 3fc11e30308f..d144df54ad40 100644
--- a/arch/powerpc/kernel/setup.h
+++ b/arch/powerpc/kernel/setup.h
@@ -45,14 +45,11 @@ void emergency_stack_init(void);
 static inline void emergency_stack_init(void) { };
 #endif
 
-#ifdef CONFIG_PPC64
-void record_spr_defaults(void);
-#else
-static inline void record_spr_defaults(void) { };
-#endif
-
 #ifdef CONFIG_PPC64
 u64 ppc64_bolted_size(void);
+
+/* Default SPR values from firmware/kexec */
+extern unsigned long spr_default_dscr;
 #endif
 
 /*
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 3ce12af4906f..dde34d35d1e7 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -254,6 +254,14 @@ static void cpu_ready_for_interrupts(void)
 	get_paca()->kernel_msr = MSR_KERNEL;
 }
 
+unsigned long spr_default_dscr = 0;
+
+void __init record_spr_defaults(void)
+{
+	if (early_cpu_has_feature(CPU_FTR_DSCR))
+		spr_default_dscr = mfspr(SPRN_DSCR);
+}
+
 /*
  * Early initialization entry point. This is called by head.S
  * with MMU translation disabled. We rely on the "feature" of
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 1f9d94dac3a6..ab4eb61fe659 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -588,21 +588,17 @@ static DEVICE_ATTR(dscr_default, 0600,
 
 static void sysfs_create_dscr_default(void)
 {
-	int err = 0;
-	if (cpu_has_feature(CPU_FTR_DSCR))
-		err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default);
-}
-
-void __init record_spr_defaults(void)
-{
-	int cpu;
-
 	if (cpu_has_feature(CPU_FTR_DSCR)) {
-		dscr_default = mfspr(SPRN_DSCR);
-		for (cpu = 0; cpu < nr_cpu_ids; cpu++)
+		int err = 0;
+		int cpu;
+
+		for_each_possible_cpu(cpu)
 			paca_ptrs[cpu]->dscr_default = dscr_default;
+
+		err = device_create_file(cpu_subsys.dev_root, &dev_attr_dscr_default);
 	}
 }
+
 #endif /* CONFIG_PPC64 */
 
 #ifdef HAS_PPC_PMC_PA6T
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 08/12] powerpc/setup: cpu_to_phys_id array
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Build an array that finds hardware CPU number from logical CPU
number in firmware CPU discovery. Use that rather than setting
paca of other CPUs directly, to begin with. Subsequent patch will
not have pacas allocated at this point.
---
 arch/powerpc/include/asm/smp.h     |  1 +
 arch/powerpc/kernel/prom.c         |  9 ++++++++-
 arch/powerpc/kernel/setup-common.c | 25 ++++++++++++++++++++++++-
 3 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index ec7b299350d9..cfecfee1194b 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -31,6 +31,7 @@
 
 extern int boot_cpuid;
 extern int spinning_secondaries;
+extern u32 *cpu_to_phys_id;
 
 extern void cpu_die(void);
 extern int cpu_to_chip_id(int cpu);
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4dffef947b8a..6b29eb1d06f4 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -872,7 +872,14 @@ int cpu_to_chip_id(int cpu)
 }
 EXPORT_SYMBOL(cpu_to_chip_id);
 
-bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
+bool arch_match_ucpu_phys_id(int cpu, u64 phys_id)
 {
+	/*
+	 * Early firmware scanning must use this rather than
+	 * get_hard_smp_processor_id because we don't have pacas allocated
+	 * until memory topology is discovered.
+	 */
+	if (cpu_to_phys_id != NULL)
+		return (int)phys_id == cpu_to_phys_id[cpu];
 	return (int)phys_id == get_hard_smp_processor_id(cpu);
 }
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index f8a6b8ad13b4..169d7e730aa4 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -437,6 +437,8 @@ static void __init cpu_init_thread_core_maps(int tpc)
 }
 
 
+u32 *cpu_to_phys_id = NULL;
+
 /**
  * setup_cpu_maps - initialize the following cpu maps:
  *                  cpu_possible_mask
@@ -463,6 +465,10 @@ void __init smp_setup_cpu_maps(void)
 
 	DBG("smp_setup_cpu_maps()\n");
 
+	cpu_to_phys_id = __va(memblock_alloc(nr_cpu_ids * sizeof(u32),
+							__alignof__(u32)));
+	memset(cpu_to_phys_id, 0, nr_cpu_ids * sizeof(u32));
+
 	for_each_node_by_type(dn, "cpu") {
 		const __be32 *intserv;
 		__be32 cpu_be;
@@ -480,6 +486,7 @@ void __init smp_setup_cpu_maps(void)
 			intserv = of_get_property(dn, "reg", &len);
 			if (!intserv) {
 				cpu_be = cpu_to_be32(cpu);
+				/* XXX: what is this? uninitialized?? */
 				intserv = &cpu_be;	/* assume logical == phys */
 				len = 4;
 			}
@@ -499,8 +506,8 @@ void __init smp_setup_cpu_maps(void)
 						"enable-method", "spin-table");
 
 			set_cpu_present(cpu, avail);
-			set_hard_smp_processor_id(cpu, be32_to_cpu(intserv[j]));
 			set_cpu_possible(cpu, true);
+			cpu_to_phys_id[cpu] = be32_to_cpu(intserv[j]);
 			cpu++;
 		}
 
@@ -835,6 +842,22 @@ static __init void print_system_info(void)
 	pr_info("-----------------------------------------------------\n");
 }
 
+#ifdef CONFIG_SMP
+static void smp_setup_pacas(void)
+{
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu == smp_processor_id())
+			continue;
+		set_hard_smp_processor_id(cpu, cpu_to_phys_id[cpu]);
+	}
+
+	memblock_free(__pa(cpu_to_phys_id), nr_cpu_ids * sizeof(u32));
+	cpu_to_phys_id = NULL;
+}
+#endif
+
 /*
  * Called into from start_kernel this initializes memblock, which is used
  * to manage page allocation until mem_init is called.
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 09/12] powerpc/64: defer paca allocation until memory topology is discovered
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

---
 arch/powerpc/include/asm/paca.h    |  3 +-
 arch/powerpc/kernel/paca.c         | 80 +++++++++++++-------------------------
 arch/powerpc/kernel/prom.c         |  5 ++-
 arch/powerpc/kernel/setup-common.c |  2 +
 4 files changed, 35 insertions(+), 55 deletions(-)

diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index f266b0a7be95..407a8076edd7 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -252,7 +252,8 @@ extern void copy_mm_to_paca(struct mm_struct *mm);
 extern struct paca_struct **paca_ptrs;
 extern void initialise_paca(struct paca_struct *new_paca, int cpu);
 extern void setup_paca(struct paca_struct *new_paca);
-extern void allocate_pacas(void);
+extern void allocate_paca_ptrs(void);
+extern void allocate_paca(int cpu);
 extern void free_unused_pacas(void);
 
 #else /* CONFIG_PPC64 */
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index e560072f122b..981886293369 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -169,12 +169,24 @@ void setup_paca(struct paca_struct *new_paca)
 
 static int __initdata paca_nr_cpu_ids;
 static int __initdata paca_ptrs_size;
+static int __initdata paca_struct_size;
 
-void __init allocate_pacas(void)
+void __init allocate_paca_ptrs(void)
+{
+	paca_nr_cpu_ids = nr_cpu_ids;
+
+	paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
+	paca_ptrs = __va(memblock_alloc(paca_ptrs_size, 0));
+	memset(paca_ptrs, 0x88, paca_ptrs_size);
+}
+
+void __init allocate_paca(int cpu)
 {
 	u64 limit;
-	unsigned long size = 0;
-	int cpu;
+	unsigned long pa;
+	struct paca_struct *paca;
+
+	BUG_ON(cpu >= paca_nr_cpu_ids);
 
 #ifdef CONFIG_PPC_BOOK3S_64
 	/*
@@ -186,69 +198,30 @@ void __init allocate_pacas(void)
 	limit = ppc64_rma_size;
 #endif
 
-	paca_nr_cpu_ids = nr_cpu_ids;
-
-	paca_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
-	paca_ptrs = __va(memblock_alloc_base(paca_ptrs_size, 0, limit));
-	memset(paca_ptrs, 0, paca_ptrs_size);
-
-	size += paca_ptrs_size;
-
-	for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
-		unsigned long pa;
-
-		pa = memblock_alloc_base(sizeof(struct paca_struct),
-						L1_CACHE_BYTES, limit);
-		paca_ptrs[cpu] = __va(pa);
-		memset(paca_ptrs[cpu], 0, sizeof(struct paca_struct));
+	pa = memblock_alloc_base(sizeof(struct paca_struct),
+					L1_CACHE_BYTES, limit);
+	paca = __va(pa);
+	paca_ptrs[cpu] = paca;
+	memset(paca, 0, sizeof(struct paca_struct));
 
-		size += sizeof(struct paca_struct);
-	}
-
-	printk(KERN_DEBUG "Allocated %lu bytes for %u pacas\n",
-			size, nr_cpu_ids);
-
-	/* Can't use for_each_*_cpu, as they aren't functional yet */
-	for (cpu = 0; cpu < nr_cpu_ids; cpu++) {
-		struct paca_struct *paca = paca_ptrs[cpu];
-
-		initialise_paca(paca, cpu);
+	initialise_paca(paca, cpu);
 #ifdef CONFIG_PPC_PSERIES
-		paca->lppaca_ptr = new_lppaca(cpu, limit);
+	paca->lppaca_ptr = new_lppaca(cpu, limit);
 #endif
 #ifdef CONFIG_PPC_BOOK3S_64
-		paca->slb_shadow_ptr = new_slb_shadow(cpu, limit);
+	paca->slb_shadow_ptr = new_slb_shadow(cpu, limit);
 #endif
-	}
+	paca_struct_size += sizeof(struct paca_struct);
 }
 
 void __init free_unused_pacas(void)
 {
-	unsigned long size = 0;
 	int new_ptrs_size;
-	int cpu;
-
-	for (cpu = 0; cpu < paca_nr_cpu_ids; cpu++) {
-		if (!cpu_possible(cpu)) {
-			unsigned long pa = __pa(paca_ptrs[cpu]);
-#ifdef CONFIG_PPC_PSERIES
-			free_lppaca(paca_ptrs[cpu]->lppaca_ptr);
-#endif
-			memblock_free(pa, sizeof(struct paca_struct));
-			paca_ptrs[cpu] = NULL;
-			size += sizeof(struct paca_struct);
-		}
-	}
 
 	new_ptrs_size = sizeof(struct paca_struct *) * nr_cpu_ids;
-	if (new_ptrs_size < paca_ptrs_size) {
+	if (new_ptrs_size < paca_ptrs_size)
 		memblock_free(__pa(paca_ptrs) + new_ptrs_size,
 					paca_ptrs_size - new_ptrs_size);
-		size += paca_ptrs_size - new_ptrs_size;
-	}
-
-	if (size)
-		printk(KERN_DEBUG "Freed %lu bytes for unused pacas\n", size);
 
 	paca_nr_cpu_ids = nr_cpu_ids;
 	paca_ptrs_size = new_ptrs_size;
@@ -261,6 +234,9 @@ void __init free_unused_pacas(void)
 		paca_ptrs[boot_cpuid]->slb_shadow_ptr = NULL;
 	}
 #endif
+
+	printk(KERN_DEBUG "Allocated %u bytes for %u pacas\n",
+			paca_ptrs_size + paca_struct_size, nr_cpu_ids);
 }
 
 void copy_mm_to_paca(struct mm_struct *mm)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 6b29eb1d06f4..175bb0bad1d1 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -365,7 +365,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 	DBG("boot cpu: logical %d physical %d\n", found,
 	    be32_to_cpu(intserv[found_thread]));
 	boot_cpuid = found;
-	set_hard_smp_processor_id(found, be32_to_cpu(intserv[found_thread]));
 
 	/*
 	 * PAPR defines "logical" PVR values for cpus that
@@ -403,7 +402,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 		cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
 	else if (!dt_cpu_ftrs_in_use())
 		cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+	allocate_paca(boot_cpuid);
 #endif
+	set_hard_smp_processor_id(found, be32_to_cpu(intserv[found_thread]));
 
 	return 0;
 }
@@ -744,7 +745,7 @@ void __init early_init_devtree(void *params)
 	 * FIXME .. and the initrd too? */
 	move_device_tree();
 
-	allocate_pacas();
+	allocate_paca_ptrs();
 
 	DBG("Scanning CPUs ...\n");
 
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 169d7e730aa4..5cf6d4d555c4 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -850,6 +850,7 @@ static void smp_setup_pacas(void)
 	for_each_possible_cpu(cpu) {
 		if (cpu == smp_processor_id())
 			continue;
+		allocate_paca(cpu);
 		set_hard_smp_processor_id(cpu, cpu_to_phys_id[cpu]);
 	}
 
@@ -925,6 +926,7 @@ void __init setup_arch(char **cmdline_p)
 	 * so smp_release_cpus() does nothing for them.
 	 */
 #ifdef CONFIG_SMP
+	smp_setup_pacas();
 	smp_release_cpus();
 #endif
 
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 10/12] powerpc/64: allocate pacas per node
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Per-node allocations are possible on 64s with radix that does
not have the bolted SLB limitation.

Hash would be able to do the same if all CPUs had the bottom of
their node-local memory bolted as well. This is left as an
exercise for the reader.
---
 arch/powerpc/kernel/paca.c     | 41 +++++++++++++++++++++++++++++++++++------
 arch/powerpc/kernel/setup_64.c |  4 ++++
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 981886293369..f455e39e51e8 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -20,6 +20,37 @@
 
 #include "setup.h"
 
+static void *__init alloc_paca_data(unsigned long size, unsigned long align,
+				unsigned long limit, int cpu)
+{
+	unsigned long pa;
+	int nid;
+
+	/*
+	 * boot_cpuid paca is allocated very early before cpu_to_node is up.
+	 * Set bottom-up mode, because the boot CPU should be on node-0,
+	 * which will put its paca in the right place.
+	 */
+	if (cpu == boot_cpuid) {
+		nid = -1;
+		memblock_set_bottom_up(true);
+	} else {
+		nid = early_cpu_to_node(cpu);
+	}
+
+	pa = memblock_alloc_base_nid(size, align, limit, nid, MEMBLOCK_NONE);
+	if (!pa) {
+		pa = memblock_alloc_base(size, align, limit);
+		if (!pa)
+			panic("cannot allocate paca data");
+	}
+
+	if (cpu == boot_cpuid)
+		memblock_set_bottom_up(false);
+
+	return __va(pa);
+}
+
 #ifdef CONFIG_PPC_PSERIES
 
 /*
@@ -52,7 +83,7 @@ static struct lppaca * __init new_lppaca(int cpu, unsigned long limit)
 	if (early_cpu_has_feature(CPU_FTR_HVMODE))
 		return NULL;
 
-	lp = __va(memblock_alloc_base(size, 0x400, limit));
+	lp = alloc_paca_data(size, 0x400, limit, cpu);
 	init_lppaca(lp);
 
 	return lp;
@@ -92,7 +123,7 @@ static struct slb_shadow * __init new_slb_shadow(int cpu, unsigned long limit)
 			return NULL;
 	}
 
-	s = __va(memblock_alloc_base(sizeof(*s), L1_CACHE_BYTES, limit));
+	s = alloc_paca_data(sizeof(*s), L1_CACHE_BYTES, limit, cpu);
 	memset(s, 0, sizeof(*s));
 
 	s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
@@ -183,7 +214,6 @@ void __init allocate_paca_ptrs(void)
 void __init allocate_paca(int cpu)
 {
 	u64 limit;
-	unsigned long pa;
 	struct paca_struct *paca;
 
 	BUG_ON(cpu >= paca_nr_cpu_ids);
@@ -198,9 +228,8 @@ void __init allocate_paca(int cpu)
 	limit = ppc64_rma_size;
 #endif
 
-	pa = memblock_alloc_base(sizeof(struct paca_struct),
-					L1_CACHE_BYTES, limit);
-	paca = __va(pa);
+	paca = alloc_paca_data(sizeof(struct paca_struct), L1_CACHE_BYTES,
+				limit, cpu);
 	paca_ptrs[cpu] = paca;
 	memset(paca, 0, sizeof(struct paca_struct));
 
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index dde34d35d1e7..02fa358982e6 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -312,6 +312,10 @@ void __init early_setup(unsigned long dt_ptr)
 	early_init_devtree(__va(dt_ptr));
 
 	/* Now we know the logical id of our boot cpu, setup the paca. */
+	if (boot_cpuid != 0) {
+		/* Poison paca_ptrs[0] again if it's not the boot cpu */
+		memset(&paca_ptrs[0], 0x88, sizeof(paca_ptrs[0]));
+	}
 	setup_paca(paca_ptrs[boot_cpuid]);
 	fixup_boot_paca();
 
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 11/12] powerpc/64: allocate per-cpu stacks node-local if possible
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/kernel/setup_64.c | 51 ++++++++++++++++++++++++++----------------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 02fa358982e6..16ea71fa1ead 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -611,6 +611,21 @@ __init u64 ppc64_bolted_size(void)
 #endif
 }
 
+static void *__init alloc_stack(unsigned long limit, int cpu)
+{
+	unsigned long pa;
+
+	pa = memblock_alloc_base_nid(THREAD_SIZE, THREAD_SIZE, limit,
+					early_cpu_to_node(cpu), MEMBLOCK_NONE);
+	if (!pa) {
+		pa = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
+		if (!pa)
+			panic("cannot allocate stacks");
+	}
+
+	return __va(pa);
+}
+
 void __init irqstack_early_init(void)
 {
 	u64 limit = ppc64_bolted_size();
@@ -622,12 +637,8 @@ void __init irqstack_early_init(void)
 	 * accessed in realmode.
 	 */
 	for_each_possible_cpu(i) {
-		softirq_ctx[i] = (struct thread_info *)
-			__va(memblock_alloc_base(THREAD_SIZE,
-					    THREAD_SIZE, limit));
-		hardirq_ctx[i] = (struct thread_info *)
-			__va(memblock_alloc_base(THREAD_SIZE,
-					    THREAD_SIZE, limit));
+		softirq_ctx[i] = alloc_stack(limit, i);
+		hardirq_ctx[i] = alloc_stack(limit, i);
 	}
 }
 
@@ -635,20 +646,21 @@ void __init irqstack_early_init(void)
 void __init exc_lvl_early_init(void)
 {
 	unsigned int i;
-	unsigned long sp;
 
 	for_each_possible_cpu(i) {
-		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
-		critirq_ctx[i] = (struct thread_info *)__va(sp);
-		paca_ptrs[i]->crit_kstack = __va(sp + THREAD_SIZE);
+		void *sp;
 
-		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
-		dbgirq_ctx[i] = (struct thread_info *)__va(sp);
-		paca_ptrs[i]->dbg_kstack = __va(sp + THREAD_SIZE);
+		sp = alloc_stack(ULONG_MAX, i);
+		critirq_ctx[i] = sp;
+		paca_ptrs[i]->crit_kstack = sp + THREAD_SIZE;
 
-		sp = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
-		mcheckirq_ctx[i] = (struct thread_info *)__va(sp);
-		paca_ptrs[i]->mc_kstack = __va(sp + THREAD_SIZE);
+		sp = alloc_stack(ULONG_MAX, i);
+		dbgirq_ctx[i] = sp;
+		paca_ptrs[i]->dbg_kstack = sp + THREAD_SIZE;
+
+		sp = alloc_stack(ULONG_MAX, i);
+		mcheckirq_ctx[i] = sp;
+		paca_ptrs[i]->mc_kstack = sp + THREAD_SIZE;
 	}
 
 	if (cpu_has_feature(CPU_FTR_DEBUG_LVL_EXC))
@@ -702,20 +714,21 @@ void __init emergency_stack_init(void)
 
 	for_each_possible_cpu(i) {
 		struct thread_info *ti;
-		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+
+		ti = alloc_stack(limit, i);
 		memset(ti, 0, THREAD_SIZE);
 		emerg_stack_init_thread_info(ti, i);
 		paca_ptrs[i]->emergency_sp = (void *)ti + THREAD_SIZE;
 
 #ifdef CONFIG_PPC_BOOK3S_64
 		/* emergency stack for NMI exception handling. */
-		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+		ti = alloc_stack(limit, i);
 		memset(ti, 0, THREAD_SIZE);
 		emerg_stack_init_thread_info(ti, i);
 		paca_ptrs[i]->nmi_emergency_sp = (void *)ti + THREAD_SIZE;
 
 		/* emergency stack for machine check exception handling. */
-		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+		ti = alloc_stack(limit, i);
 		memset(ti, 0, THREAD_SIZE);
 		emerg_stack_init_thread_info(ti, i);
 		paca_ptrs[i]->mc_emergency_sp = (void *)ti + THREAD_SIZE;
-- 
2.16.1

^ permalink raw reply related

* [RFC PATCH 12/12] powerpc/64s/radix: allocate kernel page tables node-local if possible
From: Nicholas Piggin @ 2018-02-12 17:08 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Nicholas Piggin
In-Reply-To: <20180212170822.14612-1-npiggin@gmail.com>

Try to allocate kernel page tables according to the node of
the memory they will map.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 arch/powerpc/include/asm/book3s/64/hash.h  |   2 +-
 arch/powerpc/include/asm/book3s/64/radix.h |   2 +-
 arch/powerpc/include/asm/sparsemem.h       |   2 +-
 arch/powerpc/mm/hash_utils_64.c            |   2 +-
 arch/powerpc/mm/mem.c                      |   4 +-
 arch/powerpc/mm/pgtable-book3s64.c         |   6 +-
 arch/powerpc/mm/pgtable-radix.c            | 178 +++++++++++++++++++----------
 7 files changed, 128 insertions(+), 68 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h
index 0920eff731b3..b1ace9619e94 100644
--- a/arch/powerpc/include/asm/book3s/64/hash.h
+++ b/arch/powerpc/include/asm/book3s/64/hash.h
@@ -201,7 +201,7 @@ extern int __meminit hash__vmemmap_create_mapping(unsigned long start,
 extern void hash__vmemmap_remove_mapping(unsigned long start,
 				     unsigned long page_size);
 
-int hash__create_section_mapping(unsigned long start, unsigned long end);
+int hash__create_section_mapping(unsigned long start, unsigned long end, int nid);
 int hash__remove_section_mapping(unsigned long start, unsigned long end);
 
 #endif /* !__ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h
index 19c44e1495ae..4edcc797cf43 100644
--- a/arch/powerpc/include/asm/book3s/64/radix.h
+++ b/arch/powerpc/include/asm/book3s/64/radix.h
@@ -319,7 +319,7 @@ static inline unsigned long radix__get_tree_size(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-int radix__create_section_mapping(unsigned long start, unsigned long end);
+int radix__create_section_mapping(unsigned long start, unsigned long end, int nid);
 int radix__remove_section_mapping(unsigned long start, unsigned long end);
 #endif /* CONFIG_MEMORY_HOTPLUG */
 #endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/include/asm/sparsemem.h b/arch/powerpc/include/asm/sparsemem.h
index a7916ee6dfb6..bc66712bdc3c 100644
--- a/arch/powerpc/include/asm/sparsemem.h
+++ b/arch/powerpc/include/asm/sparsemem.h
@@ -17,7 +17,7 @@
 #endif /* CONFIG_SPARSEMEM */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-extern int create_section_mapping(unsigned long start, unsigned long end);
+extern int create_section_mapping(unsigned long start, unsigned long end, int nid);
 extern int remove_section_mapping(unsigned long start, unsigned long end);
 
 #ifdef CONFIG_PPC_BOOK3S_64
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 7d07c7e17db6..ceb5494804b2 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -781,7 +781,7 @@ void resize_hpt_for_hotplug(unsigned long new_mem_size)
 	}
 }
 
-int hash__create_section_mapping(unsigned long start, unsigned long end)
+int hash__create_section_mapping(unsigned long start, unsigned long end, int nid)
 {
 	int rc = htab_bolt_mapping(start, end, __pa(start),
 				   pgprot_val(PAGE_KERNEL), mmu_linear_psize,
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 70f7b6426a15..3f75fbb10c87 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -117,7 +117,7 @@ int memory_add_physaddr_to_nid(u64 start)
 }
 #endif
 
-int __weak create_section_mapping(unsigned long start, unsigned long end)
+int __weak create_section_mapping(unsigned long start, unsigned long end, int nid)
 {
 	return -ENODEV;
 }
@@ -136,7 +136,7 @@ int arch_add_memory(int nid, u64 start, u64 size, bool want_memblock)
 	resize_hpt_for_hotplug(memblock_phys_mem_size());
 
 	start = (unsigned long)__va(start);
-	rc = create_section_mapping(start, start + size);
+	rc = create_section_mapping(start, start + size, nid);
 	if (rc) {
 		pr_warn("Unable to create mapping for hot added memory 0x%llx..0x%llx: %d\n",
 			start, start + size, rc);
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c
index 3b65917785a5..2b7375f05408 100644
--- a/arch/powerpc/mm/pgtable-book3s64.c
+++ b/arch/powerpc/mm/pgtable-book3s64.c
@@ -152,12 +152,12 @@ void mmu_cleanup_all(void)
 }
 
 #ifdef CONFIG_MEMORY_HOTPLUG
-int create_section_mapping(unsigned long start, unsigned long end)
+int create_section_mapping(unsigned long start, unsigned long end, int nid)
 {
 	if (radix_enabled())
-		return radix__create_section_mapping(start, end);
+		return radix__create_section_mapping(start, end, nid);
 
-	return hash__create_section_mapping(start, end);
+	return hash__create_section_mapping(start, end, nid);
 }
 
 int remove_section_mapping(unsigned long start, unsigned long end)
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index 573a9a2ee455..716a68baf137 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -46,79 +46,127 @@ static int native_register_process_table(unsigned long base, unsigned long pg_sz
 	return 0;
 }
 
-static __ref void *early_alloc_pgtable(unsigned long size)
+static __ref void *early_alloc_pgtable(unsigned long size, int nid)
 {
+	unsigned long pa = 0;
 	void *pt;
 
-	pt = __va(memblock_alloc_base(size, size, MEMBLOCK_ALLOC_ANYWHERE));
+	if (nid != -1) {
+		pa = memblock_alloc_base_nid(size, size,
+						MEMBLOCK_ALLOC_ANYWHERE,
+						nid, MEMBLOCK_NONE);
+	}
+
+	if (!pa)
+		pa = memblock_alloc_base(size, size, MEMBLOCK_ALLOC_ANYWHERE);
+
+	pt = __va(pa);
 	memset(pt, 0, size);
 
 	return pt;
 }
 
+static int early_map_kernel_page(unsigned long ea, unsigned long pa,
+			  pgprot_t flags,
+			  unsigned int map_page_size,
+			  int nid);
+
 int radix__map_kernel_page(unsigned long ea, unsigned long pa,
 			  pgprot_t flags,
 			  unsigned int map_page_size)
 {
+	unsigned long pfn = pa >> PAGE_SHIFT;
 	pgd_t *pgdp;
 	pud_t *pudp;
 	pmd_t *pmdp;
 	pte_t *ptep;
+
 	/*
 	 * Make sure task size is correct as per the max adddr
 	 */
 	BUILD_BUG_ON(TASK_SIZE_USER64 > RADIX_PGTABLE_RANGE);
-	if (slab_is_available()) {
-		pgdp = pgd_offset_k(ea);
-		pudp = pud_alloc(&init_mm, pgdp, ea);
-		if (!pudp)
-			return -ENOMEM;
-		if (map_page_size == PUD_SIZE) {
-			ptep = (pte_t *)pudp;
-			goto set_the_pte;
-		}
-		pmdp = pmd_alloc(&init_mm, pudp, ea);
-		if (!pmdp)
-			return -ENOMEM;
-		if (map_page_size == PMD_SIZE) {
-			ptep = pmdp_ptep(pmdp);
-			goto set_the_pte;
-		}
-		ptep = pte_alloc_kernel(pmdp, ea);
-		if (!ptep)
-			return -ENOMEM;
-	} else {
-		pgdp = pgd_offset_k(ea);
-		if (pgd_none(*pgdp)) {
-			pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
-			BUG_ON(pudp == NULL);
-			pgd_populate(&init_mm, pgdp, pudp);
-		}
-		pudp = pud_offset(pgdp, ea);
-		if (map_page_size == PUD_SIZE) {
-			ptep = (pte_t *)pudp;
-			goto set_the_pte;
-		}
-		if (pud_none(*pudp)) {
-			pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
-			BUG_ON(pmdp == NULL);
-			pud_populate(&init_mm, pudp, pmdp);
-		}
-		pmdp = pmd_offset(pudp, ea);
-		if (map_page_size == PMD_SIZE) {
-			ptep = pmdp_ptep(pmdp);
-			goto set_the_pte;
-		}
-		if (!pmd_present(*pmdp)) {
-			ptep = early_alloc_pgtable(PAGE_SIZE);
-			BUG_ON(ptep == NULL);
-			pmd_populate_kernel(&init_mm, pmdp, ptep);
-		}
-		ptep = pte_offset_kernel(pmdp, ea);
+	if (unlikely(!slab_is_available()))
+		return early_map_kernel_page(ea, pa, flags, map_page_size,
+						early_pfn_to_nid(pfn));
+
+	/*
+	 * Should make page table allocation functions be able to take a
+	 * node, so we can place kernel page tables on the right nodes after
+	 * boot.
+	 */
+	pgdp = pgd_offset_k(ea);
+	pudp = pud_alloc(&init_mm, pgdp, ea);
+	if (!pudp)
+		return -ENOMEM;
+	if (map_page_size == PUD_SIZE) {
+		ptep = (pte_t *)pudp;
+		goto set_the_pte;
+	}
+	pmdp = pmd_alloc(&init_mm, pudp, ea);
+	if (!pmdp)
+		return -ENOMEM;
+	if (map_page_size == PMD_SIZE) {
+		ptep = pmdp_ptep(pmdp);
+		goto set_the_pte;
 	}
+	ptep = pte_alloc_kernel(pmdp, ea);
+	if (!ptep)
+		return -ENOMEM;
 
 set_the_pte:
-	set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, flags));
+	set_pte_at(&init_mm, ea, ptep, pfn_pte(pfn, flags));
+	smp_wmb();
+	return 0;
+}
+
+static int early_map_kernel_page(unsigned long ea, unsigned long pa,
+			  pgprot_t flags,
+			  unsigned int map_page_size,
+			  int nid)
+{
+	unsigned long pfn = pa >> PAGE_SHIFT;
+	pgd_t *pgdp;
+	pud_t *pudp;
+	pmd_t *pmdp;
+	pte_t *ptep;
+
+	/*
+	 * Make sure task size is correct as per the max adddr
+	 */
+	BUILD_BUG_ON(TASK_SIZE_USER64 > RADIX_PGTABLE_RANGE);
+	if (slab_is_available())
+		return radix__map_kernel_page(ea, pa, flags, map_page_size);
+
+	pgdp = pgd_offset_k(ea);
+	if (pgd_none(*pgdp)) {
+		pudp = early_alloc_pgtable(PUD_TABLE_SIZE, nid);
+		BUG_ON(pudp == NULL);
+		pgd_populate(&init_mm, pgdp, pudp);
+	}
+	pudp = pud_offset(pgdp, ea);
+	if (map_page_size == PUD_SIZE) {
+		ptep = (pte_t *)pudp;
+		goto set_the_pte;
+	}
+	if (pud_none(*pudp)) {
+		pmdp = early_alloc_pgtable(PMD_TABLE_SIZE, nid);
+		BUG_ON(pmdp == NULL);
+		pud_populate(&init_mm, pudp, pmdp);
+	}
+	pmdp = pmd_offset(pudp, ea);
+	if (map_page_size == PMD_SIZE) {
+		ptep = pmdp_ptep(pmdp);
+		goto set_the_pte;
+	}
+	if (!pmd_present(*pmdp)) {
+		ptep = early_alloc_pgtable(PAGE_SIZE, nid);
+		BUG_ON(ptep == NULL);
+		pmd_populate_kernel(&init_mm, pmdp, ptep);
+	}
+	ptep = pte_offset_kernel(pmdp, ea);
+
+set_the_pte:
+	set_pte_at(&init_mm, ea, ptep, pfn_pte(pfn, flags));
 	smp_wmb();
 	return 0;
 }
@@ -209,7 +257,8 @@ static inline void __meminit print_mapping(unsigned long start,
 }
 
 static int __meminit create_physical_mapping(unsigned long start,
-					     unsigned long end)
+					     unsigned long end,
+					     int nid)
 {
 	unsigned long vaddr, addr, mapping_size = 0;
 	pgprot_t prot;
@@ -265,7 +314,7 @@ static int __meminit create_physical_mapping(unsigned long start,
 		else
 			prot = PAGE_KERNEL;
 
-		rc = radix__map_kernel_page(vaddr, addr, prot, mapping_size);
+		rc = early_map_kernel_page(vaddr, addr, prot, mapping_size, nid);
 		if (rc)
 			return rc;
 	}
@@ -274,7 +323,7 @@ static int __meminit create_physical_mapping(unsigned long start,
 	return 0;
 }
 
-static void __init radix_init_pgtable(void)
+void __init radix_init_pgtable(void)
 {
 	unsigned long rts_field;
 	struct memblock_region *reg;
@@ -284,9 +333,11 @@ static void __init radix_init_pgtable(void)
 	/*
 	 * Create the linear mapping, using standard page size for now
 	 */
-	for_each_memblock(memory, reg)
+	for_each_memblock(memory, reg) {
 		WARN_ON(create_physical_mapping(reg->base,
-						reg->base + reg->size));
+						reg->base + reg->size,
+						reg->nid));
+	}
 
 	/* Find out how many PID bits are supported */
 	if (cpu_has_feature(CPU_FTR_HVMODE)) {
@@ -315,7 +366,7 @@ static void __init radix_init_pgtable(void)
 	 * host.
 	 */
 	BUG_ON(PRTB_SIZE_SHIFT > 36);
-	process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT);
+	process_tb = early_alloc_pgtable(1UL << PRTB_SIZE_SHIFT, -1);
 	/*
 	 * Fill in the process table.
 	 */
@@ -790,9 +841,9 @@ static void remove_pagetable(unsigned long start, unsigned long end)
 	radix__flush_tlb_kernel_range(start, end);
 }
 
-int __ref radix__create_section_mapping(unsigned long start, unsigned long end)
+int __ref radix__create_section_mapping(unsigned long start, unsigned long end, int nid)
 {
-	return create_physical_mapping(start, end);
+	return create_physical_mapping(start, end, nid);
 }
 
 int radix__remove_section_mapping(unsigned long start, unsigned long end)
@@ -809,8 +860,17 @@ int __meminit radix__vmemmap_create_mapping(unsigned long start,
 {
 	/* Create a PTE encoding */
 	unsigned long flags = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_KERNEL_RW;
+	int nid = early_pfn_to_nid(phys >> PAGE_SHIFT);
+	int ret;
+
+	if (!slab_is_available())
+		ret = early_map_kernel_page(start, phys, __pgprot(flags),
+								page_size, nid);
+	else
+		ret = radix__map_kernel_page(start, phys, __pgprot(flags),
+								page_size);
+	BUG_ON(ret);
 
-	BUG_ON(radix__map_kernel_page(start, phys, __pgprot(flags), page_size));
 	return 0;
 }
 
-- 
2.16.1

^ permalink raw reply related

* Re: Build regressions/improvements in v4.16-rc1
From: James Hogan @ 2018-02-12 12:54 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Linux Kernel Mailing List, Jose Ricardo Ziviani,
	Michael Bringmann, Rob Gardner, sparclinux, linuxppc-dev,
	Linux MIPS Mailing List, adi-buildroot-devel
In-Reply-To: <CAMuHMdW5qRH93CMyRL-gbWgiA_rnizErbjNtSMT5b3d58N3ZTQ@mail.gmail.com>

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

On Mon, Feb 12, 2018 at 11:28:32AM +0100, Geert Uytterhoeven wrote:
> On Mon, Feb 12, 2018 at 11:17 AM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
> > Below is the list of build error/warning regressions/improvements in
> > v4.16-rc1[1] compared to v4.15[2].
> >
> > Summarized:
> >   - build errors: +13/-5
> >   - build warnings: +1653/-1537
> >
> > Note that there may be false regressions, as some logs are incomplete.
> > Still, they're build errors/warnings.
> >
> > Happy fixing! ;-)
> >
> > Thanks to the linux-next team for providing the build service.
> >
> > [1] http://kisskb.ellerman.id.au/kisskb/head/7928b2cbe55b2a410a0f5c1f154610059c57b1b2/ (all 273 configs)
> > [2] http://kisskb.ellerman.id.au/kisskb/head/d8a5b80568a9cb66810e75b182018e9edb68e8ff/ (271 out of 273 configs)
> >
> >
> > *** ERRORS ***
...
> >   + /home/kisskb/slave/src/drivers/net/ethernet/intel/i40e/i40e_ethtool.c: error: implicit declaration of function 'cmpxchg64' [-Werror=implicit-function-declaration]:  => 4443:6, 4443:2
> 
> mips{,el}-allmodconfig

FYI I reported this here:
https://lkml.kernel.org/r/20180207150907.GB5092@saruman

but I haven't seen any action on it yet.

Cheers
James

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [RFC PATCH 0/5] powerpc/mm/slice: improve slice speed and stack use
From: Christophe LEROY @ 2018-02-12 17:42 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linuxppc-dev, Aneesh Kumar K . V, Michael Ellerman
In-Reply-To: <20180213012442.45b6f49b@roar.ozlabs.ibm.com>



Le 12/02/2018 à 16:24, Nicholas Piggin a écrit :
> On Mon, 12 Feb 2018 16:02:23 +0100
> Christophe LEROY <christophe.leroy@c-s.fr> wrote:
> 
>> Le 10/02/2018 à 09:11, Nicholas Piggin a écrit :
>>> This series intends to improve performance and reduce stack
>>> consumption in the slice allocation code. It does it by keeping slice
>>> masks in the mm_context rather than compute them for each allocation,
>>> and by reducing bitmaps and slice_masks from stacks, using pointers
>>> instead where possible.
>>>
>>> checkstack.pl gives, before:
>>> 0x00000de4 slice_get_unmapped_area [slice.o]:           656
>>> 0x00001b4c is_hugepage_only_range [slice.o]:            512
>>> 0x0000075c slice_find_area_topdown [slice.o]:           416
>>> 0x000004c8 slice_find_area_bottomup.isra.1 [slice.o]:   272
>>> 0x00001aa0 slice_set_range_psize [slice.o]:             240
>>> 0x00000a64 slice_find_area [slice.o]:                   176
>>> 0x00000174 slice_check_fit [slice.o]:                   112
>>>
>>> after:
>>> 0x00000d70 slice_get_unmapped_area [slice.o]:           320
>>> 0x000008f8 slice_find_area [slice.o]:                   144
>>> 0x00001860 slice_set_range_psize [slice.o]:             144
>>> 0x000018ec is_hugepage_only_range [slice.o]:            144
>>> 0x00000750 slice_find_area_bottomup.isra.4 [slice.o]:   128
>>>
>>> The benchmark in https://github.com/linuxppc/linux/issues/49 gives, before:
>>> $ time ./slicemask
>>> real	0m20.712s
>>> user	0m5.830s
>>> sys	0m15.105s
>>>
>>> after:
>>> $ time ./slicemask
>>> real	0m13.197s
>>> user	0m5.409s
>>> sys	0m7.779s
>>
>> Hi,
>>
>> I tested your serie on an 8xx, on top of patch
>> https://patchwork.ozlabs.org/patch/871675/
>>
>> I don't get a result as significant as yours, but there is some
>> improvment anyway:
>>
>> ITERATION 500000
>>
>> Before:
>>
>> root@vgoip:~# time ./slicemask
>> real    0m 33.26s
>> user    0m 1.94s
>> sys     0m 30.85s
>>
>> After:
>> root@vgoip:~# time ./slicemask
>> real    0m 29.69s
>> user    0m 2.11s
>> sys     0m 27.15s
>>
>> Most significant improvment is obtained with the first patch of your serie:
>> root@vgoip:~# time ./slicemask
>> real    0m 30.85s
>> user    0m 1.80s
>> sys     0m 28.57s
> 
> Okay, thanks. Are you still spending significant time in the slice
> code?

Do you mean am I still updating my patches ? No I hope we are at last 
run with v4 now that Aneesh has tagged all of them as reviewed-by himself.
Once the serie has been accepted, my next step will be to backport at 
least the 3 first ones in kernel 4.14

> 
>>
>> Had to modify your serie a bit, if you are interested I can post it.
>>
> 
> Sure, that would be good.

Ok, lets share it. The patch are not 100% clean.

Christophe

^ permalink raw reply

* [RFC REBASED 1/5] powerpc/mm/slice: pass pointers to struct slice_mask where possible
From: Christophe Leroy @ 2018-02-12 18:12 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev

Pass around const pointers to struct slice_mask where possible, rather
than copies of slice_mask, to reduce stack and call overhead.

checkstack.pl gives, before:
0x00000de4 slice_get_unmapped_area [slice.o]:		656
0x00001b4c is_hugepage_only_range [slice.o]:		512
0x0000075c slice_find_area_topdown [slice.o]:		416
0x000004c8 slice_find_area_bottomup.isra.1 [slice.o]:	272
0x00001aa0 slice_set_range_psize [slice.o]:		240
0x00000a64 slice_find_area [slice.o]:			176
0x00000174 slice_check_fit [slice.o]:			112

after:
0x00000bd4 slice_get_unmapped_area [slice.o]:		496
0x000017cc is_hugepage_only_range [slice.o]:		352
0x00000758 slice_find_area [slice.o]:			144
0x00001750 slice_set_range_psize [slice.o]:		144
0x00000180 slice_check_fit [slice.o]:			128
0x000005b0 slice_find_area_bottomup.isra.2 [slice.o]:	128

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 rebased on top of "[v4,3/5] powerpc/mm/slice: Fix hugepage allocation at hint address on 8xx" (https://patchwork.ozlabs.org/patch/871675/)

 arch/powerpc/mm/slice.c | 81 +++++++++++++++++++++++++++----------------------
 1 file changed, 44 insertions(+), 37 deletions(-)

diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 549704dfa777..db1278ac21c2 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -50,19 +50,21 @@ struct slice_mask {
 #ifdef DEBUG
 int _slice_debug = 1;
 
-static void slice_print_mask(const char *label, struct slice_mask mask)
+static void slice_print_mask(const char *label, const struct slice_mask *mask)
 {
 	if (!_slice_debug)
 		return;
-	pr_devel("%s low_slice: %*pbl\n", label, (int)SLICE_NUM_LOW, &mask.low_slices);
-	pr_devel("%s high_slice: %*pbl\n", label, (int)SLICE_NUM_HIGH, mask.high_slices);
+	pr_devel("%s low_slice: %*pbl\n", label,
+			(int)SLICE_NUM_LOW, &mask->low_slices);
+	pr_devel("%s high_slice: %*pbl\n", label,
+			(int)SLICE_NUM_HIGH, mask->high_slices);
 }
 
 #define slice_dbg(fmt...) do { if (_slice_debug) pr_devel(fmt); } while (0)
 
 #else
 
-static void slice_print_mask(const char *label, struct slice_mask mask) {}
+static void slice_print_mask(const char *label, const struct slice_mask *mask) {}
 #define slice_dbg(fmt...)
 
 #endif
@@ -145,7 +147,8 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret,
 			__set_bit(i, ret->high_slices);
 }
 
-static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_mask *ret,
+static void slice_mask_for_size(struct mm_struct *mm, int psize,
+				struct slice_mask *ret,
 				unsigned long high_limit)
 {
 	unsigned char *hpsizes;
@@ -174,7 +177,8 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma
 }
 
 static int slice_check_fit(struct mm_struct *mm,
-			   struct slice_mask mask, struct slice_mask available)
+			   const struct slice_mask *mask,
+			   const struct slice_mask *available)
 {
 	DECLARE_BITMAP(result, SLICE_NUM_HIGH);
 	/*
@@ -183,11 +187,11 @@ static int slice_check_fit(struct mm_struct *mm,
 	 */
 	unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
 
-	slice_bitmap_and(result, mask.high_slices, available.high_slices,
+	slice_bitmap_and(result, mask->high_slices, available->high_slices,
 			 slice_count);
 
-	return (mask.low_slices & available.low_slices) == mask.low_slices &&
-		slice_bitmap_equal(result, mask.high_slices, slice_count);
+	return (mask->low_slices & available->low_slices) == mask->low_slices &&
+		slice_bitmap_equal(result, mask->high_slices, slice_count);
 }
 
 static void slice_flush_segments(void *parm)
@@ -207,7 +211,8 @@ static void slice_flush_segments(void *parm)
 #endif
 }
 
-static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
+static void slice_convert(struct mm_struct *mm,
+				const struct slice_mask *mask, int psize)
 {
 	int index, mask_index;
 	/* Write the new slice psize bits */
@@ -225,7 +230,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
 
 	lpsizes = mm->context.low_slices_psize;
 	for (i = 0; i < SLICE_NUM_LOW; i++)
-		if (mask.low_slices & (1u << i))
+		if (mask->low_slices & (1u << i))
 			lpsizes = (lpsizes & ~(0xful << (i * 4))) |
 				(((unsigned long)psize) << (i * 4));
 
@@ -236,7 +241,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
 	for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) {
 		mask_index = i & 0x1;
 		index = i >> 1;
-		if (test_bit(i, mask.high_slices))
+		if (test_bit(i, mask->high_slices))
 			hpsizes[index] = (hpsizes[index] &
 					  ~(0xf << (mask_index * 4))) |
 				(((unsigned long)psize) << (mask_index * 4));
@@ -259,26 +264,25 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
  * 'available' slice_mark.
  */
 static bool slice_scan_available(unsigned long addr,
-				 struct slice_mask available,
-				 int end,
-				 unsigned long *boundary_addr)
+				 const struct slice_mask *available,
+				 int end, unsigned long *boundary_addr)
 {
 	unsigned long slice;
 	if (addr < SLICE_LOW_TOP) {
 		slice = GET_LOW_SLICE_INDEX(addr);
 		*boundary_addr = (slice + end) << SLICE_LOW_SHIFT;
-		return !!(available.low_slices & (1u << slice));
+		return !!(available->low_slices & (1u << slice));
 	} else {
 		slice = GET_HIGH_SLICE_INDEX(addr);
 		*boundary_addr = (slice + end) ?
 			((slice + end) << SLICE_HIGH_SHIFT) : SLICE_LOW_TOP;
-		return !!test_bit(slice, available.high_slices);
+		return !!test_bit(slice, available->high_slices);
 	}
 }
 
 static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
 					      unsigned long len,
-					      struct slice_mask available,
+					      const struct slice_mask *available,
 					      int psize, unsigned long high_limit)
 {
 	int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
@@ -324,7 +328,7 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
 
 static unsigned long slice_find_area_topdown(struct mm_struct *mm,
 					     unsigned long len,
-					     struct slice_mask available,
+					     const struct slice_mask *available,
 					     int psize, unsigned long high_limit)
 {
 	int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
@@ -382,7 +386,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
 
 
 static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
-				     struct slice_mask mask, int psize,
+				     const struct slice_mask *mask, int psize,
 				     int topdown, unsigned long high_limit)
 {
 	if (topdown)
@@ -391,14 +395,16 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
 		return slice_find_area_bottomup(mm, len, mask, psize, high_limit);
 }
 
-static inline void slice_or_mask(struct slice_mask *dst, struct slice_mask *src)
+static inline void slice_or_mask(struct slice_mask *dst,
+					const struct slice_mask *src)
 {
 	dst->low_slices |= src->low_slices;
 	slice_bitmap_or(dst->high_slices, dst->high_slices, src->high_slices,
 			SLICE_NUM_HIGH);
 }
 
-static inline void slice_andnot_mask(struct slice_mask *dst, struct slice_mask *src)
+static inline void slice_andnot_mask(struct slice_mask *dst,
+					const struct slice_mask *src)
 {
 	dst->low_slices &= ~src->low_slices;
 
@@ -483,7 +489,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	 * already
 	 */
 	slice_mask_for_size(mm, psize, &good_mask, high_limit);
-	slice_print_mask(" good_mask", good_mask);
+	slice_print_mask(" good_mask", &good_mask);
 
 	/*
 	 * Here "good" means slices that are already the right page size,
@@ -517,12 +523,12 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	if (addr != 0 || fixed) {
 		/* Build a mask for the requested range */
 		slice_range_to_mask(addr, len, &mask);
-		slice_print_mask(" mask", mask);
+		slice_print_mask(" mask", &mask);
 
 		/* Check if we fit in the good mask. If we do, we just return,
 		 * nothing else to do
 		 */
-		if (slice_check_fit(mm, mask, good_mask)) {
+		if (slice_check_fit(mm, &mask, &good_mask)) {
 			slice_dbg(" fits good !\n");
 			return addr;
 		}
@@ -530,7 +536,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 		/* Now let's see if we can find something in the existing
 		 * slices for that size
 		 */
-		newaddr = slice_find_area(mm, len, good_mask,
+		newaddr = slice_find_area(mm, len, &good_mask,
 					  psize, topdown, high_limit);
 		if (newaddr != -ENOMEM) {
 			/* Found within the good mask, we don't have to setup,
@@ -546,9 +552,10 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	 */
 	slice_mask_for_free(mm, &potential_mask, high_limit);
 	slice_or_mask(&potential_mask, &good_mask);
-	slice_print_mask(" potential", potential_mask);
+	slice_print_mask(" potential", &potential_mask);
 
-	if ((addr != 0 || fixed) && slice_check_fit(mm, mask, potential_mask)) {
+	if ((addr != 0 || fixed) &&
+			slice_check_fit(mm, &mask, &potential_mask)) {
 		slice_dbg(" fits potential !\n");
 		goto convert;
 	}
@@ -563,7 +570,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	 * anywhere in the good area.
 	 */
 	if (addr) {
-		addr = slice_find_area(mm, len, good_mask,
+		addr = slice_find_area(mm, len, &good_mask,
 				       psize, topdown, high_limit);
 		if (addr != -ENOMEM) {
 			slice_dbg(" found area at 0x%lx\n", addr);
@@ -574,14 +581,14 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	/* Now let's see if we can find something in the existing slices
 	 * for that size plus free slices
 	 */
-	addr = slice_find_area(mm, len, potential_mask,
+	addr = slice_find_area(mm, len, &potential_mask,
 			       psize, topdown, high_limit);
 
 #ifdef CONFIG_PPC_64K_PAGES
 	if (addr == -ENOMEM && psize == MMU_PAGE_64K) {
 		/* retry the search with 4k-page slices included */
 		slice_or_mask(&potential_mask, &compat_mask);
-		addr = slice_find_area(mm, len, potential_mask,
+		addr = slice_find_area(mm, len, &potential_mask,
 				       psize, topdown, high_limit);
 	}
 #endif
@@ -591,14 +598,14 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 
 	slice_range_to_mask(addr, len, &mask);
 	slice_dbg(" found potential area at 0x%lx\n", addr);
-	slice_print_mask(" mask", mask);
+	slice_print_mask(" mask", &mask);
 
  convert:
 	slice_andnot_mask(&mask, &good_mask);
 	slice_andnot_mask(&mask, &compat_mask);
 	if (mask.low_slices ||
 	    !slice_bitmap_empty(mask.high_slices, SLICE_NUM_HIGH)) {
-		slice_convert(mm, mask, psize);
+		slice_convert(mm, &mask, psize);
 		if (psize > MMU_PAGE_BASE)
 			on_each_cpu(slice_flush_segments, mm, 1);
 	}
@@ -727,7 +734,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 	VM_BUG_ON(radix_enabled());
 
 	slice_range_to_mask(start, len, &mask);
-	slice_convert(mm, mask, psize);
+	slice_convert(mm, &mask, psize);
 }
 
 #ifdef CONFIG_HUGETLB_PAGE
@@ -774,9 +781,9 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 #if 0 /* too verbose */
 	slice_dbg("is_hugepage_only_range(mm=%p, addr=%lx, len=%lx)\n",
 		 mm, addr, len);
-	slice_print_mask(" mask", mask);
-	slice_print_mask(" available", available);
+	slice_print_mask(" mask", &mask);
+	slice_print_mask(" available", &available);
 #endif
-	return !slice_check_fit(mm, mask, available);
+	return !slice_check_fit(mm, &mask, &available);
 }
 #endif
-- 
2.13.3

^ permalink raw reply related

* [RFC REBASED 2/5] powerpc/mm/slice: implement a slice mask cache
From: Christophe Leroy @ 2018-02-12 18:12 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <02a62db83282b5ef3e0e8281fdc46fa91beffc86.1518382747.git.christophe.leroy@c-s.fr>

Calculating the slice mask can become a signifcant overhead for
get_unmapped_area. This patch adds a struct slice_mask for
each page size in the mm_context, and keeps these in synch with
the slices psize arrays and slb_addr_limit.

This saves about 30% kernel time on a single-page mmap/munmap micro
benchmark.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 arch/powerpc/include/asm/book3s/64/mmu.h |  20 ++++++-
 arch/powerpc/include/asm/mmu-8xx.h       |  16 ++++-
 arch/powerpc/mm/slice.c                  | 100 ++++++++++++++++++++++++++-----
 3 files changed, 118 insertions(+), 18 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
index 0abeb0e2d616..b6d136fd8ffd 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -80,6 +80,16 @@ struct spinlock;
 /* Maximum possible number of NPUs in a system. */
 #define NV_MAX_NPUS 8
 
+/*
+ * One bit per slice. We have lower slices which cover 256MB segments
+ * upto 4G range. That gets us 16 low slices. For the rest we track slices
+ * in 1TB size.
+ */
+struct slice_mask {
+	u64 low_slices;
+	DECLARE_BITMAP(high_slices, SLICE_NUM_HIGH);
+};
+
 typedef struct {
 	mm_context_id_t id;
 	u16 user_psize;		/* page size index */
@@ -91,9 +101,17 @@ typedef struct {
 	struct npu_context *npu_context;
 
 #ifdef CONFIG_PPC_MM_SLICES
+	unsigned long slb_addr_limit;
 	u64 low_slices_psize;	/* SLB page size encodings */
 	unsigned char high_slices_psize[SLICE_ARRAY_SIZE];
-	unsigned long slb_addr_limit;
+# ifdef CONFIG_PPC_64K_PAGES
+	struct slice_mask mask_64k;
+# endif
+	struct slice_mask mask_4k;
+# ifdef CONFIG_HUGETLB_PAGE
+	struct slice_mask mask_16m;
+	struct slice_mask mask_16g;
+# endif
 #else
 	u16 sllp;		/* SLB page size encoding */
 #endif
diff --git a/arch/powerpc/include/asm/mmu-8xx.h b/arch/powerpc/include/asm/mmu-8xx.h
index b324ab46d838..b97d4ed3dddf 100644
--- a/arch/powerpc/include/asm/mmu-8xx.h
+++ b/arch/powerpc/include/asm/mmu-8xx.h
@@ -187,15 +187,29 @@
 #define M_APG3		0x00000060
 
 #ifndef __ASSEMBLY__
+struct slice_mask {
+	u64 low_slices;
+	DECLARE_BITMAP(high_slices, 0);
+};
+
 typedef struct {
 	unsigned int id;
 	unsigned int active;
 	unsigned long vdso_base;
 #ifdef CONFIG_PPC_MM_SLICES
+	unsigned long slb_addr_limit;
 	u16 user_psize;		/* page size index */
 	u64 low_slices_psize;	/* page size encodings */
 	unsigned char high_slices_psize[0];
-	unsigned long slb_addr_limit;
+# ifdef CONFIG_PPC_16K_PAGES
+	struct slice_mask mask_16k;
+# else
+	struct slice_mask mask_4k;
+# endif
+# ifdef CONFIG_HUGETLB_PAGE
+	struct slice_mask mask_512k;
+	struct slice_mask mask_8m;
+# endif
 #endif
 } mm_context_t;
 
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index db1278ac21c2..ddf015d2d05b 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -37,15 +37,6 @@
 #include <asm/hugetlb.h>
 
 static DEFINE_SPINLOCK(slice_convert_lock);
-/*
- * One bit per slice. We have lower slices which cover 256MB segments
- * upto 4G range. That gets us 16 low slices. For the rest we track slices
- * in 1TB size.
- */
-struct slice_mask {
-	u64 low_slices;
-	DECLARE_BITMAP(high_slices, SLICE_NUM_HIGH);
-};
 
 #ifdef DEBUG
 int _slice_debug = 1;
@@ -147,7 +138,7 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret,
 			__set_bit(i, ret->high_slices);
 }
 
-static void slice_mask_for_size(struct mm_struct *mm, int psize,
+static void calc_slice_mask_for_size(struct mm_struct *mm, int psize,
 				struct slice_mask *ret,
 				unsigned long high_limit)
 {
@@ -176,6 +167,72 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize,
 	}
 }
 
+#ifdef CONFIG_PPC_BOOK3S_64
+static void recalc_slice_mask_cache(struct mm_struct *mm)
+{
+	unsigned long l = mm->context.slb_addr_limit;
+	calc_slice_mask_for_size(mm, MMU_PAGE_4K, &mm->context.mask_4k, l);
+#ifdef CONFIG_PPC_64K_PAGES
+	calc_slice_mask_for_size(mm, MMU_PAGE_64K, &mm->context.mask_64k, l);
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+	calc_slice_mask_for_size(mm, MMU_PAGE_16M, &mm->context.mask_16m, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_16G, &mm->context.mask_16g, l);
+#endif
+}
+
+static const struct slice_mask *slice_mask_for_size(struct mm_struct *mm, int psize)
+{
+#ifdef CONFIG_PPC_64K_PAGES
+	if (psize == MMU_PAGE_64K)
+		return &mm->context.mask_64k;
+#endif
+	if (psize == MMU_PAGE_4K)
+		return &mm->context.mask_4k;
+#ifdef CONFIG_HUGETLB_PAGE
+	if (psize == MMU_PAGE_16M)
+		return &mm->context.mask_16m;
+	if (psize == MMU_PAGE_16G)
+		return &mm->context.mask_16g;
+#endif
+	BUG();
+}
+#elif defined(CONFIG_PPC_8xx)
+static void recalc_slice_mask_cache(struct mm_struct *mm)
+{
+	unsigned long l = mm->context.slb_addr_limit;
+#ifdef CONFIG_PPC_16K_PAGES
+	calc_slice_mask_for_size(mm, MMU_PAGE_16K, &mm->context.mask_16k, l);
+#else
+	calc_slice_mask_for_size(mm, MMU_PAGE_4K, &mm->context.mask_4k, l);
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+	calc_slice_mask_for_size(mm, MMU_PAGE_512K, &mm->context.mask_512k, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_8M, &mm->context.mask_8m, l);
+#endif
+}
+
+static const struct slice_mask *slice_mask_for_size(struct mm_struct *mm, int psize)
+{
+#ifdef CONFIG_PPC_16K_PAGES
+	if (psize == MMU_PAGE_16K)
+		return &mm->context.mask_16k;
+#else
+	if (psize == MMU_PAGE_4K)
+		return &mm->context.mask_4k;
+#endif
+#ifdef CONFIG_HUGETLB_PAGE
+	if (psize == MMU_PAGE_512K)
+		return &mm->context.mask_512k;
+	if (psize == MMU_PAGE_8M)
+		return &mm->context.mask_8m;
+#endif
+	BUG();
+}
+#else
+#error "Must define the slice masks for page sizes supported by the platform"
+#endif
+
 static int slice_check_fit(struct mm_struct *mm,
 			   const struct slice_mask *mask,
 			   const struct slice_mask *available)
@@ -251,6 +308,8 @@ static void slice_convert(struct mm_struct *mm,
 		  (unsigned long)mm->context.low_slices_psize,
 		  (unsigned long)mm->context.high_slices_psize);
 
+	recalc_slice_mask_cache(mm);
+
 	spin_unlock_irqrestore(&slice_convert_lock, flags);
 
 	copro_flush_all_slbs(mm);
@@ -449,7 +508,14 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	}
 
 	if (high_limit > mm->context.slb_addr_limit) {
+		unsigned long flags;
+
 		mm->context.slb_addr_limit = high_limit;
+
+		spin_lock_irqsave(&slice_convert_lock, flags);
+		recalc_slice_mask_cache(mm);
+		spin_unlock_irqrestore(&slice_convert_lock, flags);
+
 		on_each_cpu(slice_flush_segments, mm, 1);
 	}
 
@@ -488,7 +554,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	/* First make up a "good" mask of slices that have the right size
 	 * already
 	 */
-	slice_mask_for_size(mm, psize, &good_mask, high_limit);
+	good_mask = *slice_mask_for_size(mm, psize);
 	slice_print_mask(" good_mask", &good_mask);
 
 	/*
@@ -513,7 +579,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 #ifdef CONFIG_PPC_64K_PAGES
 	/* If we support combo pages, we can allow 64k pages in 4k slices */
 	if (psize == MMU_PAGE_64K) {
-		slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask, high_limit);
+		compat_mask = *slice_mask_for_size(mm, MMU_PAGE_4K);
 		if (fixed)
 			slice_or_mask(&good_mask, &compat_mask);
 	}
@@ -695,7 +761,7 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 		goto bail;
 
 	mm->context.user_psize = psize;
-	wmb();
+	wmb(); /* Why? */
 
 	lpsizes = mm->context.low_slices_psize;
 	for (i = 0; i < SLICE_NUM_LOW; i++)
@@ -722,6 +788,9 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 		  (unsigned long)mm->context.low_slices_psize,
 		  (unsigned long)mm->context.high_slices_psize);
 
+	recalc_slice_mask_cache(mm);
+	spin_unlock_irqrestore(&slice_convert_lock, flags);
+	return;
  bail:
 	spin_unlock_irqrestore(&slice_convert_lock, flags);
 }
@@ -762,18 +831,17 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 {
 	struct slice_mask mask, available;
 	unsigned int psize = mm->context.user_psize;
-	unsigned long high_limit = mm->context.slb_addr_limit;
 
 	if (radix_enabled())
 		return 0;
 
 	slice_range_to_mask(addr, len, &mask);
-	slice_mask_for_size(mm, psize, &available, high_limit);
+	available = *slice_mask_for_size(mm, psize);
 #ifdef CONFIG_PPC_64K_PAGES
 	/* We need to account for 4k slices too */
 	if (psize == MMU_PAGE_64K) {
 		struct slice_mask compat_mask;
-		slice_mask_for_size(mm, MMU_PAGE_4K, &compat_mask, high_limit);
+		compat_mask = *slice_mask_for_size(mm, MMU_PAGE_4K);
 		slice_or_mask(&available, &compat_mask);
 	}
 #endif
-- 
2.13.3

^ permalink raw reply related

* [RFC REBASED 3/5] powerpc/mm/slice: implement slice_check_range_fits
From: Christophe Leroy @ 2018-02-12 18:12 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <02a62db83282b5ef3e0e8281fdc46fa91beffc86.1518382747.git.christophe.leroy@c-s.fr>

Rather than build slice masks from a range then use that to check for
fit in a candidate mask, implement slice_check_range_fits that checks
if a range fits in a mask directly.

This allows several structures to be removed from stacks, and also we
don't expect a huge range in a lot of these cases, so building and
comparing a full mask is going to be more expensive than testing just
one or two bits of the range.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 arch/powerpc/mm/slice.c | 68 ++++++++++++++++++++++++++-----------------------
 1 file changed, 36 insertions(+), 32 deletions(-)

diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index ddf015d2d05b..311168ca3939 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -233,22 +233,36 @@ static const struct slice_mask *slice_mask_for_size(struct mm_struct *mm, int ps
 #error "Must define the slice masks for page sizes supported by the platform"
 #endif
 
-static int slice_check_fit(struct mm_struct *mm,
-			   const struct slice_mask *mask,
-			   const struct slice_mask *available)
+static bool slice_check_range_fits(struct mm_struct *mm,
+			   const struct slice_mask *available,
+			   unsigned long start, unsigned long len)
 {
-	DECLARE_BITMAP(result, SLICE_NUM_HIGH);
-	/*
-	 * Make sure we just do bit compare only to the max
-	 * addr limit and not the full bit map size.
-	 */
-	unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
+	unsigned long end = start + len - 1;
+	u64 low_slices = 0;
+
+	if (start < SLICE_LOW_TOP) {
+		unsigned long mend = min(end,
+					 (unsigned long)(SLICE_LOW_TOP - 1));
+
+		low_slices = (1u << (GET_LOW_SLICE_INDEX(mend) + 1))
+				- (1u << GET_LOW_SLICE_INDEX(start));
+	}
+	if ((low_slices & available->low_slices) != low_slices)
+		return false;
+
+	if ((start + len) > SLICE_LOW_TOP) {
+		unsigned long start_index = GET_HIGH_SLICE_INDEX(start);
+		unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT));
+		unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index;
+		unsigned long i;
 
-	slice_bitmap_and(result, mask->high_slices, available->high_slices,
-			 slice_count);
+		for (i = start_index; i < start_index + count; i++) {
+			if (!test_bit(i, available->high_slices))
+				return false;
+		}
+	}
 
-	return (mask->low_slices & available->low_slices) == mask->low_slices &&
-		slice_bitmap_equal(result, mask->high_slices, slice_count);
+	return true;
 }
 
 static void slice_flush_segments(void *parm)
@@ -519,12 +533,6 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 		on_each_cpu(slice_flush_segments, mm, 1);
 	}
 
-	/*
-	 * init different masks
-	 */
-	mask.low_slices = 0;
-	slice_bitmap_zero(mask.high_slices, SLICE_NUM_HIGH);
-
 	/* silence stupid warning */;
 	potential_mask.low_slices = 0;
 	slice_bitmap_zero(potential_mask.high_slices, SLICE_NUM_HIGH);
@@ -586,15 +594,11 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 #endif
 
 	/* First check hint if it's valid or if we have MAP_FIXED */
-	if (addr != 0 || fixed) {
-		/* Build a mask for the requested range */
-		slice_range_to_mask(addr, len, &mask);
-		slice_print_mask(" mask", &mask);
-
+	if (addr || fixed) {
 		/* Check if we fit in the good mask. If we do, we just return,
 		 * nothing else to do
 		 */
-		if (slice_check_fit(mm, &mask, &good_mask)) {
+		if (slice_check_range_fits(mm, &good_mask, addr, len)) {
 			slice_dbg(" fits good !\n");
 			return addr;
 		}
@@ -620,10 +624,11 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	slice_or_mask(&potential_mask, &good_mask);
 	slice_print_mask(" potential", &potential_mask);
 
-	if ((addr != 0 || fixed) &&
-			slice_check_fit(mm, &mask, &potential_mask)) {
-		slice_dbg(" fits potential !\n");
-		goto convert;
+	if (addr || fixed) {
+		if (slice_check_range_fits(mm, &potential_mask, addr, len)) {
+			slice_dbg(" fits potential !\n");
+			goto convert;
+		}
 	}
 
 	/* If we have MAP_FIXED and failed the above steps, then error out */
@@ -829,13 +834,12 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 			   unsigned long len)
 {
-	struct slice_mask mask, available;
+	struct slice_mask available;
 	unsigned int psize = mm->context.user_psize;
 
 	if (radix_enabled())
 		return 0;
 
-	slice_range_to_mask(addr, len, &mask);
 	available = *slice_mask_for_size(mm, psize);
 #ifdef CONFIG_PPC_64K_PAGES
 	/* We need to account for 4k slices too */
@@ -852,6 +856,6 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 	slice_print_mask(" mask", &mask);
 	slice_print_mask(" available", &available);
 #endif
-	return !slice_check_fit(mm, &mask, &available);
+	return !slice_check_range_fits(mm, &available, addr, len);
 }
 #endif
-- 
2.13.3

^ permalink raw reply related

* [RFC REBASED 4/5] powerpc/mm/slice: Use const pointers to cached slice masks where possible
From: Christophe Leroy @ 2018-02-12 18:12 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <02a62db83282b5ef3e0e8281fdc46fa91beffc86.1518382747.git.christophe.leroy@c-s.fr>

The slice_mask cache was a basic conversion which copied the slice
mask into caller's structures, because that's how the original code
worked. In most cases the pointer can be used directly instead, saving
a copy and an on-stack structure.

This also converts the slice_mask bit operation helpers to be the usual
3-operand kind, which is clearer to work with. And we remove some
unnecessary intermediate bitmaps, reducing stack and copy overhead
further.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 arch/powerpc/include/asm/book3s/64/slice.h |  7 +++
 arch/powerpc/include/asm/nohash/32/slice.h |  6 +++
 arch/powerpc/mm/slice.c                    | 77 ++++++++++++++++++------------
 3 files changed, 59 insertions(+), 31 deletions(-)

diff --git a/arch/powerpc/include/asm/book3s/64/slice.h b/arch/powerpc/include/asm/book3s/64/slice.h
index f9a2c8bd7a77..be1ce8e91ad1 100644
--- a/arch/powerpc/include/asm/book3s/64/slice.h
+++ b/arch/powerpc/include/asm/book3s/64/slice.h
@@ -63,6 +63,13 @@ static inline void slice_bitmap_set(unsigned long *map, unsigned int start,
 {
 	bitmap_set(map, start, nbits);
 }
+
+static inline void slice_bitmap_copy(unsigned long *dst,
+				     const unsigned long *src,
+				     unsigned int nbits)
+{
+	bitmap_copy(dst, src, nbits);
+}
 #endif /* __ASSEMBLY__ */
 
 #else /* CONFIG_PPC_MM_SLICES */
diff --git a/arch/powerpc/include/asm/nohash/32/slice.h b/arch/powerpc/include/asm/nohash/32/slice.h
index bcb4924f7d22..38f041e01a0a 100644
--- a/arch/powerpc/include/asm/nohash/32/slice.h
+++ b/arch/powerpc/include/asm/nohash/32/slice.h
@@ -58,6 +58,12 @@ static inline void slice_bitmap_set(unsigned long *map, unsigned int start,
 				    unsigned int nbits)
 {
 }
+
+static inline void slice_bitmap_copy(unsigned long *dst,
+				     const unsigned long *src,
+				     unsigned int nbits)
+{
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* CONFIG_PPC_MM_SLICES */
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index 311168ca3939..b8b691369c29 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -468,21 +468,30 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
 		return slice_find_area_bottomup(mm, len, mask, psize, high_limit);
 }
 
-static inline void slice_or_mask(struct slice_mask *dst,
+static inline void slice_copy_mask(struct slice_mask *dst,
 					const struct slice_mask *src)
 {
-	dst->low_slices |= src->low_slices;
-	slice_bitmap_or(dst->high_slices, dst->high_slices, src->high_slices,
+	dst->low_slices = src->low_slices;
+	slice_bitmap_copy(dst->high_slices, src->high_slices, SLICE_NUM_HIGH);
+}
+
+static inline void slice_or_mask(struct slice_mask *dst,
+				 const struct slice_mask *src1,
+				 const struct slice_mask *src2)
+{
+	dst->low_slices = src1->low_slices | src2->low_slices;
+	slice_bitmap_or(dst->high_slices, src1->high_slices, src2->high_slices,
 			SLICE_NUM_HIGH);
 }
 
 static inline void slice_andnot_mask(struct slice_mask *dst,
-					const struct slice_mask *src)
+				     const struct slice_mask *src1,
+				     const struct slice_mask *src2)
 {
-	dst->low_slices &= ~src->low_slices;
+	dst->low_slices = src1->low_slices & ~src2->low_slices;
 
-	slice_bitmap_andnot(dst->high_slices, dst->high_slices,
-			    src->high_slices, SLICE_NUM_HIGH);
+	slice_bitmap_andnot(dst->high_slices, src1->high_slices,
+			    src2->high_slices, SLICE_NUM_HIGH);
 }
 
 #ifdef CONFIG_PPC_64K_PAGES
@@ -495,10 +504,10 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 				      unsigned long flags, unsigned int psize,
 				      int topdown)
 {
-	struct slice_mask mask;
 	struct slice_mask good_mask;
 	struct slice_mask potential_mask;
-	struct slice_mask compat_mask;
+	const struct slice_mask *maskp;
+	const struct slice_mask *compat_maskp = NULL;
 	int fixed = (flags & MAP_FIXED);
 	int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
 	unsigned long page_size = 1UL << pshift;
@@ -537,9 +546,6 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	potential_mask.low_slices = 0;
 	slice_bitmap_zero(potential_mask.high_slices, SLICE_NUM_HIGH);
 
-	compat_mask.low_slices = 0;
-	slice_bitmap_zero(compat_mask.high_slices, SLICE_NUM_HIGH);
-
 	/* Sanity checks */
 	BUG_ON(mm->task_size == 0);
 	BUG_ON(mm->context.slb_addr_limit == 0);
@@ -562,7 +568,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	/* First make up a "good" mask of slices that have the right size
 	 * already
 	 */
-	good_mask = *slice_mask_for_size(mm, psize);
+	maskp = slice_mask_for_size(mm, psize);
 	slice_print_mask(" good_mask", &good_mask);
 
 	/*
@@ -587,11 +593,16 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 #ifdef CONFIG_PPC_64K_PAGES
 	/* If we support combo pages, we can allow 64k pages in 4k slices */
 	if (psize == MMU_PAGE_64K) {
-		compat_mask = *slice_mask_for_size(mm, MMU_PAGE_4K);
+		compat_maskp = slice_mask_for_size(mm, MMU_PAGE_4K);
 		if (fixed)
-			slice_or_mask(&good_mask, &compat_mask);
-	}
+			slice_or_mask(&good_mask, maskp, compat_maskp);
+		else
+			slice_copy_mask(&good_mask, maskp);
+	} else
 #endif
+	{
+		slice_copy_mask(&good_mask, maskp);
+	}
 
 	/* First check hint if it's valid or if we have MAP_FIXED */
 	if (addr || fixed) {
@@ -621,7 +632,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	 * empty and thus can be converted
 	 */
 	slice_mask_for_free(mm, &potential_mask, high_limit);
-	slice_or_mask(&potential_mask, &good_mask);
+	slice_or_mask(&potential_mask, &potential_mask, &good_mask);
 	slice_print_mask(" potential", &potential_mask);
 
 	if (addr || fixed) {
@@ -658,7 +669,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 #ifdef CONFIG_PPC_64K_PAGES
 	if (addr == -ENOMEM && psize == MMU_PAGE_64K) {
 		/* retry the search with 4k-page slices included */
-		slice_or_mask(&potential_mask, &compat_mask);
+		slice_or_mask(&potential_mask, &potential_mask, compat_maskp);
 		addr = slice_find_area(mm, len, &potential_mask,
 				       psize, topdown, high_limit);
 	}
@@ -667,16 +678,17 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	if (addr == -ENOMEM)
 		return -ENOMEM;
 
-	slice_range_to_mask(addr, len, &mask);
+	slice_range_to_mask(addr, len, &potential_mask);
 	slice_dbg(" found potential area at 0x%lx\n", addr);
-	slice_print_mask(" mask", &mask);
+	slice_print_mask(" mask", maskp);
 
  convert:
-	slice_andnot_mask(&mask, &good_mask);
-	slice_andnot_mask(&mask, &compat_mask);
-	if (mask.low_slices ||
-	    !slice_bitmap_empty(mask.high_slices, SLICE_NUM_HIGH)) {
-		slice_convert(mm, &mask, psize);
+	slice_andnot_mask(&potential_mask, &potential_mask, &good_mask);
+	if (compat_maskp && !fixed)
+		slice_andnot_mask(&potential_mask, &potential_mask, compat_maskp);
+	if (potential_mask.low_slices ||
+	    !slice_bitmap_empty(potential_mask.high_slices, SLICE_NUM_HIGH)) {
+		slice_convert(mm, &potential_mask, psize);
 		if (psize > MMU_PAGE_BASE)
 			on_each_cpu(slice_flush_segments, mm, 1);
 	}
@@ -834,19 +846,22 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 			   unsigned long len)
 {
-	struct slice_mask available;
+	const struct slice_mask *maskp;
 	unsigned int psize = mm->context.user_psize;
 
 	if (radix_enabled())
 		return 0;
 
-	available = *slice_mask_for_size(mm, psize);
+	maskp = slice_mask_for_size(mm, psize);
 #ifdef CONFIG_PPC_64K_PAGES
 	/* We need to account for 4k slices too */
 	if (psize == MMU_PAGE_64K) {
-		struct slice_mask compat_mask;
-		compat_mask = *slice_mask_for_size(mm, MMU_PAGE_4K);
-		slice_or_mask(&available, &compat_mask);
+		const struct slice_mask *compat_maskp;
+		struct slice_mask available;
+
+		compat_maskp = slice_mask_for_size(mm, MMU_PAGE_4K);
+		slice_or_mask(&available, maskp, compat_maskp);
+		return !slice_check_range_fits(mm, &available, addr, len);
 	}
 #endif
 
@@ -856,6 +871,6 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 	slice_print_mask(" mask", &mask);
 	slice_print_mask(" available", &available);
 #endif
-	return !slice_check_range_fits(mm, &available, addr, len);
+	return !slice_check_range_fits(mm, maskp, addr, len);
 }
 #endif
-- 
2.13.3

^ permalink raw reply related

* [RFC REBASED 5/5] powerpc/mm/slice: use the dynamic high slice size to limit bitmap operations
From: Christophe Leroy @ 2018-02-12 18:12 UTC (permalink / raw)
  To: Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <02a62db83282b5ef3e0e8281fdc46fa91beffc86.1518382747.git.christophe.leroy@c-s.fr>

The number of high slices a process might use now depends on its
address space size, and what allocation address it has requested.

This patch uses that limit throughout call chains where possible,
rather than use the fixed SLICE_NUM_HIGH for bitmap operations.
This saves some cost for processes that don't use very large address
spaces.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
 arch/powerpc/mm/slice.c | 111 ++++++++++++++++++++++++++----------------------
 1 file changed, 60 insertions(+), 51 deletions(-)

diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index b8b691369c29..683ff4604ab4 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -61,13 +61,12 @@ static void slice_print_mask(const char *label, const struct slice_mask *mask) {
 #endif
 
 static void slice_range_to_mask(unsigned long start, unsigned long len,
-				struct slice_mask *ret)
+				struct slice_mask *ret,
+				unsigned long high_slices)
 {
 	unsigned long end = start + len - 1;
 
 	ret->low_slices = 0;
-	slice_bitmap_zero(ret->high_slices, SLICE_NUM_HIGH);
-
 	if (start < SLICE_LOW_TOP) {
 		unsigned long mend = min(end,
 					 (unsigned long)(SLICE_LOW_TOP - 1));
@@ -76,6 +75,7 @@ static void slice_range_to_mask(unsigned long start, unsigned long len,
 			- (1u << GET_LOW_SLICE_INDEX(start));
 	}
 
+	slice_bitmap_zero(ret->high_slices, high_slices);
 	if ((start + len) > SLICE_LOW_TOP) {
 		unsigned long start_index = GET_HIGH_SLICE_INDEX(start);
 		unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT));
@@ -119,28 +119,27 @@ static int slice_high_has_vma(struct mm_struct *mm, unsigned long slice)
 }
 
 static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret,
-				unsigned long high_limit)
+				unsigned long high_slices)
 {
 	unsigned long i;
 
 	ret->low_slices = 0;
-	slice_bitmap_zero(ret->high_slices, SLICE_NUM_HIGH);
-
 	for (i = 0; i < SLICE_NUM_LOW; i++)
 		if (!slice_low_has_vma(mm, i))
 			ret->low_slices |= 1u << i;
 
-	if (high_limit <= SLICE_LOW_TOP)
+	if (!high_slices)
 		return;
 
-	for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++)
+	slice_bitmap_zero(ret->high_slices, high_slices);
+	for (i = 0; i < high_slices; i++)
 		if (!slice_high_has_vma(mm, i))
 			__set_bit(i, ret->high_slices);
 }
 
 static void calc_slice_mask_for_size(struct mm_struct *mm, int psize,
 				struct slice_mask *ret,
-				unsigned long high_limit)
+				unsigned long high_slices)
 {
 	unsigned char *hpsizes;
 	int index, mask_index;
@@ -148,18 +147,17 @@ static void calc_slice_mask_for_size(struct mm_struct *mm, int psize,
 	u64 lpsizes;
 
 	ret->low_slices = 0;
-	slice_bitmap_zero(ret->high_slices, SLICE_NUM_HIGH);
-
 	lpsizes = mm->context.low_slices_psize;
 	for (i = 0; i < SLICE_NUM_LOW; i++)
 		if (((lpsizes >> (i * 4)) & 0xf) == psize)
 			ret->low_slices |= 1u << i;
 
-	if (high_limit <= SLICE_LOW_TOP)
+	if (!high_slices)
 		return;
 
+	slice_bitmap_zero(ret->high_slices, high_slices);
 	hpsizes = mm->context.high_slices_psize;
-	for (i = 0; i < GET_HIGH_SLICE_INDEX(high_limit); i++) {
+	for (i = 0; i < high_slices; i++) {
 		mask_index = i & 0x1;
 		index = i >> 1;
 		if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == psize)
@@ -168,16 +166,15 @@ static void calc_slice_mask_for_size(struct mm_struct *mm, int psize,
 }
 
 #ifdef CONFIG_PPC_BOOK3S_64
-static void recalc_slice_mask_cache(struct mm_struct *mm)
+static void recalc_slice_mask_cache(struct mm_struct *mm, unsigned long high_slices)
 {
-	unsigned long l = mm->context.slb_addr_limit;
-	calc_slice_mask_for_size(mm, MMU_PAGE_4K, &mm->context.mask_4k, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_4K, &mm->context.mask_4k, high_slices);
 #ifdef CONFIG_PPC_64K_PAGES
-	calc_slice_mask_for_size(mm, MMU_PAGE_64K, &mm->context.mask_64k, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_64K, &mm->context.mask_64k, high_slices);
 #endif
 #ifdef CONFIG_HUGETLB_PAGE
-	calc_slice_mask_for_size(mm, MMU_PAGE_16M, &mm->context.mask_16m, l);
-	calc_slice_mask_for_size(mm, MMU_PAGE_16G, &mm->context.mask_16g, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_16M, &mm->context.mask_16m, high_slices);
+	calc_slice_mask_for_size(mm, MMU_PAGE_16G, &mm->context.mask_16g, high_slices);
 #endif
 }
 
@@ -198,17 +195,16 @@ static const struct slice_mask *slice_mask_for_size(struct mm_struct *mm, int ps
 	BUG();
 }
 #elif defined(CONFIG_PPC_8xx)
-static void recalc_slice_mask_cache(struct mm_struct *mm)
+static void recalc_slice_mask_cache(struct mm_struct *mm, unsigned long high_slices)
 {
-	unsigned long l = mm->context.slb_addr_limit;
 #ifdef CONFIG_PPC_16K_PAGES
-	calc_slice_mask_for_size(mm, MMU_PAGE_16K, &mm->context.mask_16k, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_16K, &mm->context.mask_16k, high_slices);
 #else
-	calc_slice_mask_for_size(mm, MMU_PAGE_4K, &mm->context.mask_4k, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_4K, &mm->context.mask_4k, high_slices);
 #endif
 #ifdef CONFIG_HUGETLB_PAGE
-	calc_slice_mask_for_size(mm, MMU_PAGE_512K, &mm->context.mask_512k, l);
-	calc_slice_mask_for_size(mm, MMU_PAGE_8M, &mm->context.mask_8m, l);
+	calc_slice_mask_for_size(mm, MMU_PAGE_512K, &mm->context.mask_512k, high_slices);
+	calc_slice_mask_for_size(mm, MMU_PAGE_8M, &mm->context.mask_8m, high_slices);
 #endif
 }
 
@@ -290,6 +286,7 @@ static void slice_convert(struct mm_struct *mm,
 	unsigned char *hpsizes;
 	u64 lpsizes;
 	unsigned long i, flags;
+	unsigned long high_slices;
 
 	slice_dbg("slice_convert(mm=%p, psize=%d)\n", mm, psize);
 	slice_print_mask(" mask", mask);
@@ -309,7 +306,8 @@ static void slice_convert(struct mm_struct *mm,
 	mm->context.low_slices_psize = lpsizes;
 
 	hpsizes = mm->context.high_slices_psize;
-	for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) {
+	high_slices = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
+	for (i = 0; i < high_slices; i++) {
 		mask_index = i & 0x1;
 		index = i >> 1;
 		if (test_bit(i, mask->high_slices))
@@ -322,7 +320,7 @@ static void slice_convert(struct mm_struct *mm,
 		  (unsigned long)mm->context.low_slices_psize,
 		  (unsigned long)mm->context.high_slices_psize);
 
-	recalc_slice_mask_cache(mm);
+	recalc_slice_mask_cache(mm, high_slices);
 
 	spin_unlock_irqrestore(&slice_convert_lock, flags);
 
@@ -469,29 +467,32 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
 }
 
 static inline void slice_copy_mask(struct slice_mask *dst,
-					const struct slice_mask *src)
+					const struct slice_mask *src,
+					unsigned long high_slices)
 {
 	dst->low_slices = src->low_slices;
-	slice_bitmap_copy(dst->high_slices, src->high_slices, SLICE_NUM_HIGH);
+	slice_bitmap_copy(dst->high_slices, src->high_slices, high_slices);
 }
 
 static inline void slice_or_mask(struct slice_mask *dst,
-				 const struct slice_mask *src1,
-				 const struct slice_mask *src2)
+					const struct slice_mask *src1,
+					const struct slice_mask *src2,
+					unsigned long high_slices)
 {
 	dst->low_slices = src1->low_slices | src2->low_slices;
 	slice_bitmap_or(dst->high_slices, src1->high_slices, src2->high_slices,
-			SLICE_NUM_HIGH);
+			high_slices);
 }
 
 static inline void slice_andnot_mask(struct slice_mask *dst,
-				     const struct slice_mask *src1,
-				     const struct slice_mask *src2)
+					const struct slice_mask *src1,
+					const struct slice_mask *src2,
+					unsigned long high_slices)
 {
 	dst->low_slices = src1->low_slices & ~src2->low_slices;
 
 	slice_bitmap_andnot(dst->high_slices, src1->high_slices,
-			    src2->high_slices, SLICE_NUM_HIGH);
+			    src2->high_slices, high_slices);
 }
 
 #ifdef CONFIG_PPC_64K_PAGES
@@ -514,6 +515,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	struct mm_struct *mm = current->mm;
 	unsigned long newaddr;
 	unsigned long high_limit;
+	unsigned long high_slices;
 
 	high_limit = DEFAULT_MAP_WINDOW;
 	if (addr >= high_limit || (fixed && (addr + len > high_limit)))
@@ -530,13 +532,14 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 			return -ENOMEM;
 	}
 
+	high_slices = GET_HIGH_SLICE_INDEX(high_limit);
 	if (high_limit > mm->context.slb_addr_limit) {
 		unsigned long flags;
 
 		mm->context.slb_addr_limit = high_limit;
 
 		spin_lock_irqsave(&slice_convert_lock, flags);
-		recalc_slice_mask_cache(mm);
+		recalc_slice_mask_cache(mm, high_slices);
 		spin_unlock_irqrestore(&slice_convert_lock, flags);
 
 		on_each_cpu(slice_flush_segments, mm, 1);
@@ -544,7 +547,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 
 	/* silence stupid warning */;
 	potential_mask.low_slices = 0;
-	slice_bitmap_zero(potential_mask.high_slices, SLICE_NUM_HIGH);
+	slice_bitmap_zero(potential_mask.high_slices, high_slices);
 
 	/* Sanity checks */
 	BUG_ON(mm->task_size == 0);
@@ -595,13 +598,13 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	if (psize == MMU_PAGE_64K) {
 		compat_maskp = slice_mask_for_size(mm, MMU_PAGE_4K);
 		if (fixed)
-			slice_or_mask(&good_mask, maskp, compat_maskp);
+			slice_or_mask(&good_mask, maskp, compat_maskp, high_slices);
 		else
-			slice_copy_mask(&good_mask, maskp);
+			slice_copy_mask(&good_mask, maskp, high_slices);
 	} else
 #endif
 	{
-		slice_copy_mask(&good_mask, maskp);
+		slice_copy_mask(&good_mask, maskp, high_slices);
 	}
 
 	/* First check hint if it's valid or if we have MAP_FIXED */
@@ -631,8 +634,8 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	 * We don't fit in the good mask, check what other slices are
 	 * empty and thus can be converted
 	 */
-	slice_mask_for_free(mm, &potential_mask, high_limit);
-	slice_or_mask(&potential_mask, &potential_mask, &good_mask);
+	slice_mask_for_free(mm, &potential_mask, high_slices);
+	slice_or_mask(&potential_mask, &potential_mask, &good_mask, high_slices);
 	slice_print_mask(" potential", &potential_mask);
 
 	if (addr || fixed) {
@@ -669,7 +672,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 #ifdef CONFIG_PPC_64K_PAGES
 	if (addr == -ENOMEM && psize == MMU_PAGE_64K) {
 		/* retry the search with 4k-page slices included */
-		slice_or_mask(&potential_mask, &potential_mask, compat_maskp);
+		slice_or_mask(&potential_mask, &potential_mask, compat_maskp, high_slices);
 		addr = slice_find_area(mm, len, &potential_mask,
 				       psize, topdown, high_limit);
 	}
@@ -678,16 +681,16 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
 	if (addr == -ENOMEM)
 		return -ENOMEM;
 
-	slice_range_to_mask(addr, len, &potential_mask);
+	slice_range_to_mask(addr, len, &potential_mask, high_slices);
 	slice_dbg(" found potential area at 0x%lx\n", addr);
 	slice_print_mask(" mask", maskp);
 
  convert:
-	slice_andnot_mask(&potential_mask, &potential_mask, &good_mask);
+	slice_andnot_mask(&potential_mask, &potential_mask, &good_mask, high_slices);
 	if (compat_maskp && !fixed)
-		slice_andnot_mask(&potential_mask, &potential_mask, compat_maskp);
+		slice_andnot_mask(&potential_mask, &potential_mask, compat_maskp, high_slices);
 	if (potential_mask.low_slices ||
-	    !slice_bitmap_empty(potential_mask.high_slices, SLICE_NUM_HIGH)) {
+	    !slice_bitmap_empty(potential_mask.high_slices, high_slices)) {
 		slice_convert(mm, &potential_mask, psize);
 		if (psize > MMU_PAGE_BASE)
 			on_each_cpu(slice_flush_segments, mm, 1);
@@ -764,6 +767,7 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 	int index, mask_index;
 	unsigned char *hpsizes;
 	unsigned long flags, lpsizes;
+	unsigned long high_slices;
 	unsigned int old_psize;
 	int i;
 
@@ -789,7 +793,8 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 	mm->context.low_slices_psize = lpsizes;
 
 	hpsizes = mm->context.high_slices_psize;
-	for (i = 0; i < SLICE_NUM_HIGH; i++) {
+	high_slices = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
+	for (i = 0; i < high_slices; i++) {
 		mask_index = i & 0x1;
 		index = i >> 1;
 		if (((hpsizes[index] >> (mask_index * 4)) & 0xf) == old_psize)
@@ -805,7 +810,7 @@ void slice_set_user_psize(struct mm_struct *mm, unsigned int psize)
 		  (unsigned long)mm->context.low_slices_psize,
 		  (unsigned long)mm->context.high_slices_psize);
 
-	recalc_slice_mask_cache(mm);
+	recalc_slice_mask_cache(mm, high_slices);
 	spin_unlock_irqrestore(&slice_convert_lock, flags);
 	return;
  bail:
@@ -816,10 +821,12 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
 			   unsigned long len, unsigned int psize)
 {
 	struct slice_mask mask;
+	unsigned long high_slices;
 
 	VM_BUG_ON(radix_enabled());
 
-	slice_range_to_mask(start, len, &mask);
+	high_slices = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
+	slice_range_to_mask(start, len, &mask, high_slices);
 	slice_convert(mm, &mask, psize);
 }
 
@@ -858,9 +865,11 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
 	if (psize == MMU_PAGE_64K) {
 		const struct slice_mask *compat_maskp;
 		struct slice_mask available;
+		unsigned long high_slices;
 
 		compat_maskp = slice_mask_for_size(mm, MMU_PAGE_4K);
-		slice_or_mask(&available, maskp, compat_maskp);
+		high_slices = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
+		slice_or_mask(&available, maskp, compat_maskp, high_slices);
 		return !slice_check_range_fits(mm, &available, addr, len);
 	}
 #endif
-- 
2.13.3

^ permalink raw reply related

* samples/seccomp/ broken when cross compiling s390, ppc allyesconfig
From: Michal Hocko @ 2018-02-12 13:37 UTC (permalink / raw)
  To: Will Drewry; +Cc: LKML, linuxppc-dev, linux-s390

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

Hi,
my build test machinery chokes on samples/seccomp when cross compiling
s390 and ppc64 allyesconfig. This has been the case for quite some
time already but I never found time to look at the problem and report
it. It seems this is not new issue and similar thing happend for
MIPS e9107f88c985 ("samples/seccomp/Makefile: do not build tests if
cross-compiling for MIPS").

The build logs are attached.

What is the best way around this? Should we simply skip compilation on
cross compile or is actually anybody relying on that? Or should I simply
disable it for s390 and ppc?
-- 
Michal Hocko
SUSE Labs

[-- Attachment #2: s390-20180201_102415.log --]
[-- Type: text/plain, Size: 59615 bytes --]

=== Config /home/mhocko/work/build-test/configs/s390/allyesconfig
security/integrity/ima/ima_api.c: In function 'ima_audit_measurement':
security/integrity/ima/ima_api.c:337:1: warning: 'ima_audit_measurement' uses dynamic stack allocation
 }
 ^
arch/s390/crypto/aes_s390.c: In function 'fallback_blk_dec':
arch/s390/crypto/aes_s390.c:217:1: warning: 'fallback_blk_dec' uses dynamic stack allocation
 }
 ^
arch/s390/crypto/aes_s390.c: In function 'fallback_blk_enc':
arch/s390/crypto/aes_s390.c:234:1: warning: 'fallback_blk_enc' uses dynamic stack allocation
 }
 ^
arch/s390/crypto/aes_s390.c: In function 'xts_aes_decrypt':
arch/s390/crypto/aes_s390.c:607:1: warning: 'xts_aes_decrypt' uses dynamic stack allocation
 }
 ^
arch/s390/crypto/aes_s390.c: In function 'xts_aes_encrypt':
arch/s390/crypto/aes_s390.c:593:1: warning: 'xts_aes_encrypt' uses dynamic stack allocation
 }
 ^
security/integrity/ima/ima_crypto.c: In function 'ima_calc_field_array_hash_tfm.isra.3':
security/integrity/ima/ima_crypto.c:491:1: warning: 'ima_calc_field_array_hash_tfm.isra.3' uses dynamic stack allocation
 }
 ^
security/integrity/ima/ima_crypto.c: In function 'ima_calc_file_hash':
security/integrity/ima/ima_crypto.c:441:1: warning: 'ima_calc_file_hash' uses dynamic stack allocation
 }
 ^
security/integrity/ima/ima_crypto.c: In function 'ima_calc_buffer_hash':
security/integrity/ima/ima_crypto.c:628:1: warning: 'ima_calc_buffer_hash' uses dynamic stack allocation
 }
 ^
security/integrity/ima/ima_crypto.c: In function 'ima_calc_boot_aggregate':
security/integrity/ima/ima_crypto.c:682:1: warning: 'ima_calc_boot_aggregate' uses dynamic stack allocation
 }
 ^
security/keys/dh.c: In function 'keyctl_dh_compute_kdf':
security/keys/dh.c:237:1: warning: 'keyctl_dh_compute_kdf' uses dynamic stack allocation
 }
 ^
security/keys/big_key.c: In function 'big_key_crypt':
security/keys/big_key.c:130:1: warning: 'big_key_crypt' uses dynamic stack allocation
 }
 ^
security/apparmor/crypto.c: In function 'aa_calc_hash':
security/apparmor/crypto.c:64:1: warning: 'aa_calc_hash' uses dynamic stack allocation
 }
 ^
security/apparmor/crypto.c: In function 'aa_calc_profile_hash':
security/apparmor/crypto.c:106:1: warning: 'aa_calc_profile_hash' uses dynamic stack allocation
 }
 ^
security/keys/encrypted-keys/encrypted.c: In function 'calc_hash':
security/keys/encrypted-keys/encrypted.c:337:1: warning: 'calc_hash' uses dynamic stack allocation
 }
 ^
crypto/cipher.c: In function 'cipher_crypt_unaligned':
crypto/cipher.c:76:1: warning: 'cipher_crypt_unaligned' uses dynamic stack allocation
 }
 ^
drivers/android/binder_alloc.c: In function 'binder_alloc_shrinker_init':
drivers/android/binder_alloc.c:1008:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&binder_shrinker);
  ^
drivers/gpio/gpiolib.c: In function 'gpiod_get_array_value_complex':
drivers/gpio/gpiolib.c:2644:1: warning: 'gpiod_get_array_value_complex' uses dynamic stack allocation
 }
 ^
drivers/gpio/gpiolib.c: In function 'gpiod_set_array_value_complex':
drivers/gpio/gpiolib.c:2873:1: warning: 'gpiod_set_array_value_complex' uses dynamic stack allocation
 }
 ^
drivers/atm/ambassador.c: In function 'do_loader_command':
drivers/atm/ambassador.c:1762:45: warning: passing argument 1 of 'virt_to_bus' discards 'volatile' qualifier from pointer target type
   wr_mem (dev, offsetof(amb_mem, doorbell), virt_to_bus (lb) & ~onegigmask);
                                             ^
In file included from ./arch/s390/include/asm/io.h:79:0,
                 from ./include/linux/io.h:25,
                 from ./include/linux/pci.h:33,
                 from drivers/atm/ambassador.c:27:
./include/asm-generic/io.h:946:29: note: expected 'void *' but argument is of type 'volatile struct loader_block *'
 static inline unsigned long virt_to_bus(void *address)
                             ^
In file included from samples/seccomp/bpf-fancy.c:21:0:
samples/seccomp/bpf-helper.h:135:2: error: #error __BITS_PER_LONG value unusable.
 #error __BITS_PER_LONG value unusable.
  ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
samples/seccomp/bpf-fancy.c: In function ‘main’:
samples/seccomp/bpf-fancy.c:38:11: error: ‘__NR_exit’ undeclared (first use in this function)
   SYSCALL(__NR_exit, ALLOW),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:38:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_exit, ALLOW),
   ^
samples/seccomp/bpf-fancy.c:38:11: note: each undeclared identifier is reported only once for each function it appears in
   SYSCALL(__NR_exit, ALLOW),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:38:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_exit, ALLOW),
   ^
samples/seccomp/bpf-fancy.c:39:11: error: ‘__NR_exit_group’ undeclared (first use in this function)
   SYSCALL(__NR_exit_group, ALLOW),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:39:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_exit_group, ALLOW),
   ^
samples/seccomp/bpf-fancy.c:40:11: error: ‘__NR_write’ undeclared (first use in this function)
   SYSCALL(__NR_write, JUMP(&l, write_fd)),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:40:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_write, JUMP(&l, write_fd)),
   ^
samples/seccomp/bpf-fancy.c:41:11: error: ‘__NR_read’ undeclared (first use in this function)
   SYSCALL(__NR_read, JUMP(&l, read)),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:41:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_read, JUMP(&l, read)),
   ^
samples/seccomp/bpf-fancy.c:45:3: warning: implicit declaration of function ‘ARG’ [-Wimplicit-function-declaration]
   ARG(0),
   ^
samples/seccomp/bpf-fancy.c:45:3: warning: missing braces around initializer [-Wmissing-braces]
samples/seccomp/bpf-fancy.c:45:3: warning: (near initialization for ‘filter[11]’) [-Wmissing-braces]
samples/seccomp/bpf-fancy.c:46:3: warning: implicit declaration of function ‘JNE’ [-Wimplicit-function-declaration]
   JNE(STDIN_FILENO, DENY),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:48:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  ^
samples/seccomp/bpf-fancy.c:46:21: note: in expansion of macro ‘DENY’
   JNE(STDIN_FILENO, DENY),
                     ^
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:48:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  ^
samples/seccomp/bpf-fancy.c:48:27: note: in expansion of macro ‘DENY’
   JNE((unsigned long)buf, DENY),
                           ^
samples/seccomp/bpf-fancy.c:50:3: warning: implicit declaration of function ‘JGE’ [-Wimplicit-function-declaration]
   JGE(sizeof(buf), DENY),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:48:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  ^
samples/seccomp/bpf-fancy.c:50:20: note: in expansion of macro ‘DENY’
   JGE(sizeof(buf), DENY),
                    ^
samples/seccomp/bpf-fancy.c:51:3: warning: braces around scalar initializer [enabled by default]
   ALLOW,
   ^
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: braces around scalar initializer [enabled by default]
   LABEL(&l, write_fd),
   ^
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:55:3: warning: implicit declaration of function ‘JEQ’ [-Wimplicit-function-declaration]
   JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:55:22: note: in expansion of macro ‘JUMP’
   JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
                      ^
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:56:22: note: in expansion of macro ‘JUMP’
   JEQ(STDERR_FILENO, JUMP(&l, write_buf)),
                      ^
samples/seccomp/bpf-fancy.c:57:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:61:28: note: in expansion of macro ‘JUMP’
   JEQ((unsigned long)msg1, JUMP(&l, msg1_len)),
                            ^
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:62:28: note: in expansion of macro ‘JUMP’
   JEQ((unsigned long)msg2, JUMP(&l, msg2_len)),
                            ^
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:63:27: note: in expansion of macro ‘JUMP’
   JEQ((unsigned long)buf, JUMP(&l, buf_len)),
                           ^
samples/seccomp/bpf-fancy.c:68:3: warning: implicit declaration of function ‘JLT’ [-Wimplicit-function-declaration]
   JLT(sizeof(msg1), ALLOW),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:46:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  ^
samples/seccomp/bpf-fancy.c:68:21: note: in expansion of macro ‘ALLOW’
   JLT(sizeof(msg1), ALLOW),
                     ^
samples/seccomp/bpf-fancy.c:69:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: braces around scalar initializer [enabled by default]
   LABEL(&l, msg2_len),
   ^
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:46:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  ^
samples/seccomp/bpf-fancy.c:73:21: note: in expansion of macro ‘ALLOW’
   JLT(sizeof(msg2), ALLOW),
                     ^
samples/seccomp/bpf-fancy.c:74:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: braces around scalar initializer [enabled by default]
   LABEL(&l, buf_len),
   ^
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
In file included from samples/seccomp/bpf-helper.c:17:0:
samples/seccomp/bpf-helper.h:135:2: error: #error __BITS_PER_LONG value unusable.
 #error __BITS_PER_LONG value unusable.
  ^
samples/seccomp/bpf-fancy.c:76:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:46:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  ^
samples/seccomp/bpf-fancy.c:78:20: note: in expansion of macro ‘ALLOW’
   JLT(sizeof(buf), ALLOW),
                    ^
samples/seccomp/bpf-fancy.c:79:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:97:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1));
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:98:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1);
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:100:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2));
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:101:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDERR_FILENO, buf, bytes);
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:103:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2);
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
make[2]: *** [samples/seccomp/bpf-helper.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[2]: *** [samples/seccomp/bpf-fancy.o] Error 1
make[1]: *** [samples/seccomp] Error 2
make: *** [samples] Error 2
make: *** Waiting for unfinished jobs....
drivers/dma/dmatest.c: In function 'dmatest_func':
drivers/dma/dmatest.c:804:1: warning: 'dmatest_func' uses dynamic stack allocation
 }
 ^
drivers/crypto/inside-secure/safexcel_cipher.c: In function 'safexcel_cipher_exit_inv':
drivers/crypto/inside-secure/safexcel_cipher.c:459:1: warning: 'safexcel_cipher_exit_inv' uses dynamic stack allocation
 }
 ^
drivers/crypto/inside-secure/safexcel_hash.c: In function 'safexcel_ahash_exit_inv':
drivers/crypto/inside-secure/safexcel_hash.c:486:1: warning: 'safexcel_ahash_exit_inv' uses dynamic stack allocation
 }
 ^
drivers/crypto/chelsio/chcr_algo.c: In function 'chcr_cipher_fallback':
drivers/crypto/chelsio/chcr_algo.c:716:1: warning: 'chcr_cipher_fallback' uses dynamic stack allocation
 }
 ^
drivers/crypto/chelsio/chcr_algo.c: In function 'chcr_ahash_setkey':
drivers/crypto/chelsio/chcr_algo.c:1904:1: warning: 'chcr_ahash_setkey' uses dynamic stack allocation
 }
 ^
drivers/crypto/chelsio/chcr_algo.c: In function 'chcr_authenc_setkey':
drivers/crypto/chelsio/chcr_algo.c:3326:1: warning: 'chcr_authenc_setkey' uses dynamic stack allocation
 }
 ^
crypto/seqiv.c: In function 'seqiv_aead_encrypt':
crypto/seqiv.c:115:1: warning: 'seqiv_aead_encrypt' uses dynamic stack allocation
 }
 ^
sound/core/pcm_native.c: In function 'constrain_params_by_rules':
sound/core/pcm_native.c:434:1: warning: 'constrain_params_by_rules' uses dynamic stack allocation
 }
 ^
crypto/echainiv.c: In function 'echainiv_encrypt':
crypto/echainiv.c:88:1: warning: 'echainiv_encrypt' uses dynamic stack allocation
 }
 ^
crypto/shash.c: In function 'crypto_shash_update':
crypto/shash.c:111:1: warning: 'crypto_shash_update' uses dynamic stack allocation
 }
 ^
crypto/shash.c: In function 'crypto_shash_final':
crypto/shash.c:146:1: warning: 'crypto_shash_final' uses dynamic stack allocation
 }
 ^
drivers/crypto/qce/ablkcipher.c: In function 'qce_ablkcipher_crypt':
drivers/crypto/qce/ablkcipher.c:229:1: warning: 'qce_ablkcipher_crypt' uses dynamic stack allocation
 }
 ^
drivers/of/unittest.c: In function 'of_unittest_printf_one':
drivers/of/unittest.c:276:1: warning: 'of_unittest_printf_one' uses dynamic stack allocation
 }
 ^
drivers/block/cryptoloop.c: In function 'cryptoloop_transfer':
drivers/block/cryptoloop.c:167:1: warning: 'cryptoloop_transfer' uses dynamic stack allocation
 }
 ^
drivers/crypto/mediatek/mtk-sha.c: In function 'mtk_sha_finish':
drivers/crypto/mediatek/mtk-sha.c:637:1: warning: 'mtk_sha_finish' uses dynamic stack allocation
 }
 ^
drivers/crypto/mediatek/mtk-sha.c: In function 'mtk_sha_setkey':
drivers/crypto/mediatek/mtk-sha.c:834:1: warning: 'mtk_sha_setkey' uses dynamic stack allocation
 }
 ^
drivers/nfc/s3fwrn5/firmware.c: In function 's3fwrn5_fw_download':
drivers/nfc/s3fwrn5/firmware.c:501:1: warning: 's3fwrn5_fw_download' uses dynamic stack allocation
 }
 ^
drivers/mmc/core/pwrseq_simple.c: In function 'mmc_pwrseq_simple_set_gpios_value.isra.9':
drivers/mmc/core/pwrseq_simple.c:52:1: warning: 'mmc_pwrseq_simple_set_gpios_value.isra.9' uses dynamic stack allocation
 }
 ^
drivers/infiniband/sw/rxe/rxe_req.c: In function 'rxe_requester':
drivers/infiniband/sw/rxe/rxe_req.c:759:1: warning: 'rxe_requester' uses dynamic stack allocation
 }
 ^
crypto/hmac.c: In function 'hmac_setkey':
crypto/hmac.c:88:1: warning: 'hmac_setkey' uses dynamic stack allocation
 }
 ^
drivers/block/drbd/drbd_receiver.c: In function 'drbd_do_auth':
drivers/block/drbd/drbd_receiver.c:5397:1: warning: 'drbd_do_auth' uses dynamic stack allocation
 }
 ^
drivers/block/drbd/drbd_worker.c: In function 'drbd_csum_ee':
drivers/block/drbd/drbd_worker.c:325:1: warning: 'drbd_csum_ee' uses dynamic stack allocation
 }
 ^
drivers/block/drbd/drbd_worker.c: In function 'drbd_csum_bio':
drivers/block/drbd/drbd_worker.c:352:1: warning: 'drbd_csum_bio' uses dynamic stack allocation
 }
 ^
drivers/misc/tifm_7xx1.c: In function 'tifm_7xx1_resume':
drivers/misc/tifm_7xx1.c:298:1: warning: 'tifm_7xx1_resume' uses dynamic stack allocation
 }
 ^
drivers/infiniband/sw/rxe/rxe_recv.c: In function 'rxe_rcv':
drivers/infiniband/sw/rxe/rxe_recv.c:421:1: warning: 'rxe_rcv' uses dynamic stack allocation
 }
 ^
crypto/xcbc.c: In function 'crypto_xcbc_digest_setkey':
crypto/xcbc.c:80:1: warning: 'crypto_xcbc_digest_setkey' uses dynamic stack allocation
 }
 ^
drivers/crypto/s5p-sss.c: In function 's5p_hash_final':
drivers/crypto/s5p-sss.c:1589:1: warning: 's5p_hash_final' uses dynamic stack allocation
 }
 ^
drivers/net/ppp/ppp_mppe.c: In function 'get_new_key_from_sha':
drivers/net/ppp/ppp_mppe.c:158:1: warning: 'get_new_key_from_sha' uses dynamic stack allocation
 }
 ^
drivers/net/ppp/ppp_mppe.c: In function 'mppe_rekey':
drivers/net/ppp/ppp_mppe.c:195:1: warning: 'mppe_rekey' uses dynamic stack allocation
 }
 ^
drivers/net/ppp/ppp_mppe.c: In function 'mppe_decompress':
drivers/net/ppp/ppp_mppe.c:666:1: warning: 'mppe_decompress' uses dynamic stack allocation
 }
 ^
drivers/net/ppp/ppp_mppe.c: In function 'mppe_compress':
drivers/net/ppp/ppp_mppe.c:441:1: warning: 'mppe_compress' uses dynamic stack allocation
 }
 ^
drivers/input/joystick/analog.c:176:2: warning: #warning Precise timer not defined for this architecture. [-Wcpp]
 #warning Precise timer not defined for this architecture.
  ^
drivers/gpu/drm/i2c/tda998x_drv.c: In function 'reg_write_range':
drivers/gpu/drm/i2c/tda998x_drv.c:489:1: warning: 'reg_write_range' uses dynamic stack allocation
 }
 ^
drivers/net/phy/mdio-mux-gpio.c: In function 'mdio_mux_gpio_switch_fn':
drivers/net/phy/mdio-mux-gpio.c:42:1: warning: 'mdio_mux_gpio_switch_fn' uses dynamic stack allocation
 }
 ^
drivers/iio/humidity/hts221_i2c.c: In function 'hts221_i2c_write':
drivers/iio/humidity/hts221_i2c.c:59:1: warning: 'hts221_i2c_write' uses dynamic stack allocation
 }
 ^
drivers/md/dm-stripe.c: In function 'stripe_status':
drivers/md/dm-stripe.c:395:1: warning: 'stripe_status' uses dynamic stack allocation
 }
 ^
drivers/infiniband/sw/rxe/rxe_mr.c: In function 'rxe_mem_copy':
drivers/infiniband/sw/rxe/rxe_mr.c:431:1: warning: 'rxe_mem_copy' uses dynamic stack allocation
 }
 ^
drivers/md/dm-bufio.c: In function 'dm_bufio_client_create':
drivers/md/dm-bufio.c:1756:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&c->shrinker);
  ^
drivers/infiniband/sw/rxe/rxe_icrc.c: In function 'rxe_icrc_hdr':
drivers/infiniband/sw/rxe/rxe_icrc.c:96:1: warning: 'rxe_icrc_hdr' uses dynamic stack allocation
 }
 ^
net/ceph/crypto.c: In function 'ceph_crypt':
net/ceph/crypto.c:293:1: warning: 'ceph_crypt' uses dynamic stack allocation
 }
 ^
drivers/gpio/gpio-max3191x.c: In function 'max3191x_probe':
drivers/gpio/gpio-max3191x.c:437:1: warning: 'max3191x_probe' uses dynamic stack allocation
 }
 ^
drivers/md/dm-crypt.c: In function 'crypt_iv_essiv_init':
drivers/md/dm-crypt.c:345:1: warning: 'crypt_iv_essiv_init' uses dynamic stack allocation
 }
 ^
drivers/md/dm-crypt.c: In function 'crypt_iv_tcw_whitening.isra.28':
drivers/md/dm-crypt.c:787:1: warning: 'crypt_iv_tcw_whitening.isra.28' uses dynamic stack allocation
 }
 ^
drivers/md/dm-crypt.c: In function 'crypt_iv_lmk_one.isra.29':
drivers/md/dm-crypt.c:640:1: warning: 'crypt_iv_lmk_one.isra.29' uses dynamic stack allocation
 }
 ^
drivers/mtd/nftlmount.c: In function 'check_free_sectors.isra.2':
drivers/mtd/nftlmount.c:298:1: warning: 'check_free_sectors.isra.2' uses dynamic stack allocation
 }
 ^
drivers/mtd/inftlmount.c: In function 'INFTL_formatblock':
drivers/mtd/inftlmount.c:428:1: warning: 'INFTL_formatblock' uses dynamic stack allocation
 }
 ^
net/bridge/netfilter/ebtables.c: In function 'compat_copy_everything_to_user':
net/bridge/netfilter/ebtables.c:1884:1: warning: 'compat_copy_everything_to_user' uses dynamic stack allocation
 }
 ^
drivers/input/keyboard/stmpe-keypad.c: In function 'stmpe_keypad_irq':
drivers/input/keyboard/stmpe-keypad.c:184:1: warning: 'stmpe_keypad_irq' uses dynamic stack allocation
 }
 ^
crypto/cbc.c: In function 'crypto_cbc_decrypt':
crypto/cbc.c:79:1: warning: 'crypto_cbc_decrypt' uses dynamic stack allocation
 }
 ^
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c: In function 'vpdstrtou16.constprop':
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c:700:1: warning: 'vpdstrtou16.constprop' uses dynamic stack allocation
 }
 ^
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c: In function 'vpdstrtouint.constprop':
drivers/net/ethernet/chelsio/cxgb3/t3_hw.c:691:1: warning: 'vpdstrtouint.constprop' uses dynamic stack allocation
 }
 ^
drivers/iio/potentiometer/ds1803.c: In function 'ds1803_read_raw':
drivers/iio/potentiometer/ds1803.c:86:1: warning: 'ds1803_read_raw' uses dynamic stack allocation
 }
 ^
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c: In function 'st_lsm6dsx_read_fifo':
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c:306:1: warning: 'st_lsm6dsx_read_fifo' uses dynamic stack allocation
 }
 ^
kernel/events/ring_buffer.c: In function 'perf_output_begin_forward':
kernel/events/ring_buffer.c:237:1: warning: 'perf_output_begin_forward' uses dynamic stack allocation
 }
 ^
kernel/events/ring_buffer.c: In function 'perf_output_begin_backward':
kernel/events/ring_buffer.c:243:1: warning: 'perf_output_begin_backward' uses dynamic stack allocation
 }
 ^
kernel/events/ring_buffer.c: In function 'perf_output_begin':
kernel/events/ring_buffer.c:251:1: warning: 'perf_output_begin' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_log_throttle':
kernel/events/core.c:7266:1: warning: 'perf_log_throttle' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_log_itrace_start':
kernel/events/core.c:7307:1: warning: 'perf_log_itrace_start' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_event_switch_output':
kernel/events/core.c:7199:1: warning: 'perf_event_switch_output' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_event_task_output':
kernel/events/core.c:6483:1: warning: 'perf_event_task_output' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_event_namespaces_output':
kernel/events/core.c:6676:1: warning: 'perf_event_namespaces_output' uses dynamic stack allocation
 }
 ^
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c: In function 'st_lsm6dsx_i2c_write':
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c:53:1: warning: 'st_lsm6dsx_i2c_write' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_event_read_event':
kernel/events/core.c:6204:1: warning: 'perf_event_read_event' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_event_comm_output':
kernel/events/core.c:6577:1: warning: 'perf_event_comm_output' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_event_mmap_output':
kernel/events/core.c:6839:1: warning: 'perf_event_mmap_output' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_swevent_hrtimer':
kernel/events/core.c:8607:1: warning: 'perf_swevent_hrtimer' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_event_aux_event':
kernel/events/core.c:7107:1: warning: 'perf_event_aux_event' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_log_lost_samples':
kernel/events/core.c:7140:1: warning: 'perf_log_lost_samples' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function 'perf_tp_event':
kernel/events/core.c:7944:1: warning: 'perf_tp_event' uses dynamic stack allocation
 }
 ^
kernel/events/core.c: In function '___perf_sw_event':
kernel/events/core.c:7632:1: warning: '___perf_sw_event' uses dynamic stack allocation
 }
 ^
crypto/pcbc.c: In function 'crypto_pcbc_decrypt':
crypto/pcbc.c:185:1: warning: 'crypto_pcbc_decrypt' uses dynamic stack allocation
 }
 ^
crypto/cts.c: In function 'cts_cbc_encrypt':
crypto/cts.c:129:1: warning: 'cts_cbc_encrypt' uses dynamic stack allocation
 }
 ^
crypto/pcbc.c: In function 'crypto_pcbc_encrypt':
crypto/pcbc.c:113:1: warning: 'crypto_pcbc_encrypt' uses dynamic stack allocation
 }
 ^
crypto/cts.c: In function 'cts_cbc_decrypt':
crypto/cts.c:221:1: warning: 'cts_cbc_decrypt' uses dynamic stack allocation
 }
 ^
net/core/rtnetlink.c: In function 'rtnl_newlink':
net/core/rtnetlink.c:2864:1: warning: 'rtnl_newlink' uses dynamic stack allocation
 }
 ^
mm/slub.c: In function 'unfreeze_partials.isra.48':
mm/slub.c:2221:1: warning: 'unfreeze_partials.isra.48' uses dynamic stack allocation
 }
 ^
mm/slub.c: In function 'get_partial_node.isra.49':
mm/slub.c:1853:1: warning: 'get_partial_node.isra.49' uses dynamic stack allocation
 }
 ^
mm/slub.c: In function 'deactivate_slab.isra.50':
mm/slub.c:2153:1: warning: 'deactivate_slab.isra.50' uses dynamic stack allocation
 }
 ^
mm/slub.c: In function '___slab_alloc':
mm/slub.c:2606:1: warning: '___slab_alloc' uses dynamic stack allocation
 }
 ^
crypto/ctr.c: In function 'crypto_ctr_crypt':
crypto/ctr.c:155:1: warning: 'crypto_ctr_crypt' uses dynamic stack allocation
 }
 ^
mm/slub.c: In function '__slab_free':
mm/slub.c:2907:1: warning: '__slab_free' uses dynamic stack allocation
 }
 ^
drivers/net/ethernet/marvell/mvpp2.c: In function 'mvpp2_swf_bm_pool_init':
drivers/net/ethernet/marvell/mvpp2.c:548:2: warning: overflow in implicit constant conversion [-Woverflow]
  ((total_size) - NET_SKB_PAD - MVPP2_SKB_SHINFO_SIZE)
  ^
drivers/net/ethernet/marvell/mvpp2.c:788:34: note: in expansion of macro 'MVPP2_RX_MAX_PKT_SIZE'
 #define MVPP2_BM_SHORT_PKT_SIZE  MVPP2_RX_MAX_PKT_SIZE(512)
                                  ^
drivers/net/ethernet/marvell/mvpp2.c:4277:8: note: in expansion of macro 'MVPP2_BM_SHORT_PKT_SIZE'
        MVPP2_BM_SHORT_PKT_SIZE);
        ^
drivers/net/wan/lmc/lmc_main.c: In function 'lmc_softreset':
drivers/net/wan/lmc/lmc_main.c:1854:37: warning: passing argument 1 of 'virt_to_bus' discards 'volatile' qualifier from pointer target type
         sc->lmc_rxring[i].buffer2 = virt_to_bus (&sc->lmc_rxring[i + 1]);
                                     ^
In file included from ./arch/s390/include/asm/io.h:79:0,
                 from ./include/linux/io.h:25,
                 from ./include/linux/pci.h:33,
                 from drivers/net/wan/lmc/lmc_main.c:49:
./include/asm-generic/io.h:946:29: note: expected 'void *' but argument is of type 'volatile struct tulip_desc_t *'
 static inline unsigned long virt_to_bus(void *address)
                             ^
drivers/net/wan/lmc/lmc_main.c:1863:41: warning: passing argument 1 of 'virt_to_bus' discards 'volatile' qualifier from pointer target type
         sc->lmc_rxring[i - 1].buffer2 = virt_to_bus(&sc->lmc_rxring[0]); /* Point back to the start */
                                         ^
In file included from ./arch/s390/include/asm/io.h:79:0,
                 from ./include/linux/io.h:25,
                 from ./include/linux/pci.h:33,
                 from drivers/net/wan/lmc/lmc_main.c:49:
./include/asm-generic/io.h:946:29: note: expected 'void *' but argument is of type 'volatile struct tulip_desc_t *'
 static inline unsigned long virt_to_bus(void *address)
                             ^
In file included from drivers/net/wan/lmc/lmc.h:5:0,
                 from drivers/net/wan/lmc/lmc_main.c:71:
drivers/net/wan/lmc/lmc_main.c:1865:36: warning: passing argument 1 of 'virt_to_bus' discards 'volatile' qualifier from pointer target type
     LMC_CSR_WRITE (sc, csr_rxlist, virt_to_bus (sc->lmc_rxring)); /* write base address */
                                    ^
drivers/net/wan/lmc/lmc_var.h:47:8: note: in definition of macro 'LMC_CSR_WRITE'
  outl((val), (sc)->lmc_csrs.reg)
        ^
In file included from ./arch/s390/include/asm/io.h:79:0,
                 from ./include/linux/io.h:25,
                 from ./include/linux/pci.h:33,
                 from drivers/net/wan/lmc/lmc_main.c:49:
./include/asm-generic/io.h:946:29: note: expected 'void *' but argument is of type 'volatile struct tulip_desc_t *'
 static inline unsigned long virt_to_bus(void *address)
                             ^
drivers/net/wan/lmc/lmc_main.c:1876:37: warning: passing argument 1 of 'virt_to_bus' discards 'volatile' qualifier from pointer target type
         sc->lmc_txring[i].buffer2 = virt_to_bus (&sc->lmc_txring[i + 1]);
                                     ^
In file included from ./arch/s390/include/asm/io.h:79:0,
                 from ./include/linux/io.h:25,
                 from ./include/linux/pci.h:33,
                 from drivers/net/wan/lmc/lmc_main.c:49:
./include/asm-generic/io.h:946:29: note: expected 'void *' but argument is of type 'volatile struct tulip_desc_t *'
 static inline unsigned long virt_to_bus(void *address)
                             ^
drivers/net/wan/lmc/lmc_main.c:1878:37: warning: passing argument 1 of 'virt_to_bus' discards 'volatile' qualifier from pointer target type
     sc->lmc_txring[i - 1].buffer2 = virt_to_bus (&sc->lmc_txring[0]);
                                     ^
In file included from ./arch/s390/include/asm/io.h:79:0,
                 from ./include/linux/io.h:25,
                 from ./include/linux/pci.h:33,
                 from drivers/net/wan/lmc/lmc_main.c:49:
./include/asm-generic/io.h:946:29: note: expected 'void *' but argument is of type 'volatile struct tulip_desc_t *'
 static inline unsigned long virt_to_bus(void *address)
                             ^
In file included from drivers/net/wan/lmc/lmc.h:5:0,
                 from drivers/net/wan/lmc/lmc_main.c:71:
drivers/net/wan/lmc/lmc_main.c:1879:36: warning: passing argument 1 of 'virt_to_bus' discards 'volatile' qualifier from pointer target type
     LMC_CSR_WRITE (sc, csr_txlist, virt_to_bus (sc->lmc_txring));
                                    ^
drivers/net/wan/lmc/lmc_var.h:47:8: note: in definition of macro 'LMC_CSR_WRITE'
  outl((val), (sc)->lmc_csrs.reg)
        ^
In file included from ./arch/s390/include/asm/io.h:79:0,
                 from ./include/linux/io.h:25,
                 from ./include/linux/pci.h:33,
                 from drivers/net/wan/lmc/lmc_main.c:49:
./include/asm-generic/io.h:946:29: note: expected 'void *' but argument is of type 'volatile struct tulip_desc_t *'
 static inline unsigned long virt_to_bus(void *address)
                             ^
lib/btree.c: In function 'btree_get_prev':
lib/btree.c:360:1: warning: 'btree_get_prev' uses dynamic stack allocation
 }
 ^
lib/btree.c: In function 'btree_merge':
lib/btree.c:673:1: warning: 'btree_merge' uses dynamic stack allocation
 }
 ^
crypto/ccm.c: In function 'crypto_ccm_auth':
crypto/ccm.c:235:1: warning: 'crypto_ccm_auth' uses dynamic stack allocation
 }
 ^
net/mac802154/llsec.c: In function 'llsec_do_encrypt':
net/mac802154/llsec.c:707:1: warning: 'llsec_do_encrypt' uses dynamic stack allocation
 }
 ^
net/mac802154/llsec.c: In function 'llsec_do_decrypt.isra.7':
net/mac802154/llsec.c:912:1: warning: 'llsec_do_decrypt.isra.7' uses dynamic stack allocation
 }
 ^
crypto/gcm.c: In function 'crypto_rfc4543_crypt':
crypto/gcm.c:1061:1: warning: 'crypto_rfc4543_crypt' uses dynamic stack allocation
 }
 ^
drivers/gpio/gpio-stmpe.c: In function 'stmpe_gpio_irq':
drivers/gpio/gpio-stmpe.c:422:1: warning: 'stmpe_gpio_irq' uses dynamic stack allocation
 }
 ^
drivers/staging/android/ashmem.c: In function 'ashmem_init':
drivers/staging/android/ashmem.c:867:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&ashmem_shrinker);
  ^
net/llc/llc_sap.c: In function 'llc_sap_handler':
net/llc/llc_sap.c:442:1: warning: 'llc_sap_handler' uses dynamic stack allocation
 }
 ^
drivers/input/touchscreen/cyttsp4_core.c: In function 'cyttsp4_irq':
drivers/input/touchscreen/cyttsp4_core.c:1243:1: warning: 'cyttsp4_irq' uses dynamic stack allocation
 }
 ^
drivers/md/dm-raid1.c: In function 'mirror_status':
drivers/md/dm-raid1.c:1446:1: warning: 'mirror_status' uses dynamic stack allocation
 }
 ^
drivers/md/dm-raid1.c: In function 'mirror_flush':
drivers/md/dm-raid1.c:285:1: warning: 'mirror_flush' uses dynamic stack allocation
 }
 ^
drivers/md/dm-raid1.c: In function 'do_writes':
drivers/md/dm-raid1.c:790:1: warning: 'do_writes' uses dynamic stack allocation
 }
 ^
net/netfilter/nfnetlink.c: In function 'nfnetlink_rcv_msg':
net/netfilter/nfnetlink.c:225:1: warning: 'nfnetlink_rcv_msg' uses dynamic stack allocation
 }
 ^
net/netfilter/nfnetlink.c: In function 'nfnetlink_rcv':
net/netfilter/nfnetlink.c:516:1: warning: 'nfnetlink_rcv' uses dynamic stack allocation
 }
 ^
drivers/staging/ccree/ssi_cipher.c: In function 'ssi_blkcipher_setkey':
drivers/staging/ccree/ssi_cipher.c:419:1: warning: 'ssi_blkcipher_setkey' uses dynamic stack allocation
 }
 ^
drivers/staging/android/ion/ion_heap.c: In function 'ion_heap_init_shrinker':
drivers/staging/android/ion/ion_heap.c:315:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&heap->shrinker);
  ^
crypto/cryptd.c: In function 'cryptd_skcipher_decrypt':
crypto/cryptd.c:530:1: warning: 'cryptd_skcipher_decrypt' uses dynamic stack allocation
 }
 ^
crypto/cryptd.c: In function 'cryptd_skcipher_encrypt':
crypto/cryptd.c:502:1: warning: 'cryptd_skcipher_encrypt' uses dynamic stack allocation
 }
 ^
arch/s390/kernel/perf_cpum_sf.c: In function 'perf_push_sample':
arch/s390/kernel/perf_cpum_sf.c:1071:1: warning: 'perf_push_sample' uses dynamic stack allocation
 }
 ^
net/core/pktgen.c: In function 'pktgen_if_write':
net/core/pktgen.c:1799:1: warning: 'pktgen_if_write' uses dynamic stack allocation
 }
 ^
lib/libcrc32c.c: In function 'crc32c':
lib/libcrc32c.c:59:1: warning: 'crc32c' uses dynamic stack allocation
 }
 ^
kernel/trace/ftrace.c: In function 'ftrace_mod_callback':
kernel/trace/ftrace.c:4092:1: warning: 'ftrace_mod_callback' uses dynamic stack allocation
 }
 ^
drivers/gpu/drm/ttm/ttm_page_alloc.c: In function 'ttm_pool_mm_shrink_init':
drivers/gpu/drm/ttm/ttm_page_alloc.c:485:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&manager->mm_shrink);
  ^
drivers/md/dm-verity-fec.c: In function 'fec_decode_rsb':
drivers/md/dm-verity-fec.c:403:1: warning: 'fec_decode_rsb' uses dynamic stack allocation
 }
 ^
drivers/power/supply/da9150-fg.c: In function 'da9150_fg_read_attr.isra.4':
drivers/power/supply/da9150-fg.c:108:1: warning: 'da9150_fg_read_attr.isra.4' uses dynamic stack allocation
 }
 ^
net/openvswitch/actions.c: In function 'ovs_fragment':
net/openvswitch/actions.c:943:1: warning: 'ovs_fragment' uses dynamic stack allocation
 }
 ^
kernel/smp.c: In function 'smp_call_function_single':
kernel/smp.c:307:1: warning: 'smp_call_function_single' uses dynamic stack allocation
 }
 ^
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c: In function 'vchiq_dump_service_use_state':
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c:3153:1: warning: 'vchiq_dump_service_use_state' uses dynamic stack allocation
 }
 ^
net/ipv6/xfrm6_state.c: In function '__xfrm6_sort':
net/ipv6/xfrm6_state.c:84:1: warning: '__xfrm6_sort' uses dynamic stack allocation
 }
 ^
drivers/net/ethernet/neterion/vxge/vxge-config.c: In function 'vxge_hw_device_hw_info_get':
drivers/net/ethernet/neterion/vxge/vxge-config.c:1089:1: warning: 'vxge_hw_device_hw_info_get' uses dynamic stack allocation
 }
 ^
fs/crypto/keyinfo.c: In function 'fscrypt_get_encryption_info':
fs/crypto/keyinfo.c:354:1: warning: 'fscrypt_get_encryption_info' uses dynamic stack allocation
 }
 ^
fs/ecryptfs/crypto.c: In function 'ecryptfs_hash_digest':
fs/ecryptfs/crypto.c:75:1: warning: 'ecryptfs_hash_digest' uses dynamic stack allocation
 }
 ^
net/netfilter/nfnetlink_cttimeout.c: In function 'ctnl_timeout_parse_policy':
net/netfilter/nfnetlink_cttimeout.c:68:1: warning: 'ctnl_timeout_parse_policy' uses dynamic stack allocation
 }
 ^
lib/reed_solomon/reed_solomon.c: In function 'decode_rs8':
lib/reed_solomon/reed_solomon.c:329:1: warning: 'decode_rs8' uses dynamic stack allocation
 }
 ^
lib/reed_solomon/reed_solomon.c: In function 'decode_rs16':
lib/reed_solomon/reed_solomon.c:373:1: warning: 'decode_rs16' uses dynamic stack allocation
 }
 ^
net/netfilter/nfnetlink_cthelper.c: In function 'nfnl_cthelper_update_policy_all.isra.9':
net/netfilter/nfnetlink_cthelper.c:344:1: warning: 'nfnl_cthelper_update_policy_all.isra.9' uses dynamic stack allocation
 }
 ^
net/ipv6/proc.c: In function 'snmp6_seq_show_item':
net/ipv6/proc.c:214:1: warning: 'snmp6_seq_show_item' uses dynamic stack allocation
 }
 ^
net/ipv6/proc.c: In function 'snmp6_seq_show_item64.isra.1.constprop':
net/ipv6/proc.c:227:1: warning: 'snmp6_seq_show_item64.isra.1.constprop' uses dynamic stack allocation
 }
 ^
drivers/md/dm-integrity.c: In function 'integrity_sector_checksum':
drivers/md/dm-integrity.c:1231:1: warning: 'integrity_sector_checksum' uses dynamic stack allocation
 }
 ^
drivers/md/dm-integrity.c: In function 'rw_section_mac':
drivers/md/dm-integrity.c:558:1: warning: 'rw_section_mac' uses dynamic stack allocation
 }
 ^
drivers/md/dm-integrity.c: In function 'do_journal_write':
drivers/md/dm-integrity.c:1974:1: warning: 'do_journal_write' uses dynamic stack allocation
 }
 ^
drivers/md/dm-integrity.c: In function 'integrity_metadata':
drivers/md/dm-integrity.c:1335:1: warning: 'integrity_metadata' uses dynamic stack allocation
 }
 ^
drivers/md/dm-integrity.c: In function '__journal_read_write':
drivers/md/dm-integrity.c:1568:1: warning: '__journal_read_write' uses dynamic stack allocation
 }
 ^
net/rds/connection.c: In function 'rds_for_each_conn_info':
net/rds/connection.c:565:1: warning: 'rds_for_each_conn_info' uses dynamic stack allocation
 }
 ^
net/rds/connection.c: In function 'rds_conn_info':
net/rds/connection.c:646:1: warning: 'rds_conn_info' uses dynamic stack allocation
 }
 ^
crypto/authenc.c: In function 'crypto_authenc_encrypt':
crypto/authenc.c:233:1: warning: 'crypto_authenc_encrypt' uses dynamic stack allocation
 }
 ^
crypto/authencesn.c: In function 'crypto_authenc_esn_copy':
crypto/authencesn.c:193:1: warning: 'crypto_authenc_esn_copy' uses dynamic stack allocation
 }
 ^
drivers/target/iscsi/iscsi_target.c: In function 'iscsit_send_datain':
drivers/target/iscsi/iscsi_target.c:2852:1: warning: 'iscsit_send_datain' uses dynamic stack allocation
 }
 ^
lib/bch.c: In function 'init_bch':
lib/bch.c:1336:1: warning: 'init_bch' uses dynamic stack allocation
 }
 ^
lib/bch.c: In function 'find_affine4_roots':
lib/bch.c:540:1: warning: 'find_affine4_roots' uses dynamic stack allocation
 }
 ^
net/ipv4/proc.c: In function 'snmp_seq_show':
net/ipv4/proc.c:462:1: warning: 'snmp_seq_show' uses dynamic stack allocation
 }
 ^
drivers/usb/wusbcore/crypto.c: In function 'wusb_ccm_mac':
drivers/usb/wusbcore/crypto.c:282:1: warning: 'wusb_ccm_mac' uses dynamic stack allocation
 }
 ^
drivers/usb/misc/usbtest.c: In function 'test_queue':
drivers/usb/misc/usbtest.c:2067:1: warning: 'test_queue' uses dynamic stack allocation
 }
 ^
drivers/scsi/device_handler/scsi_dh_emc.c: In function 'send_trespass_cmd':
drivers/scsi/device_handler/scsi_dh_emc.c:294:1: warning: 'send_trespass_cmd' uses dynamic stack allocation
 }
 ^
drivers/scsi/device_handler/scsi_dh_rdac.c: In function 'send_mode_select':
drivers/scsi/device_handler/scsi_dh_rdac.c:581:1: warning: 'send_mode_select' uses dynamic stack allocation
 }
 ^
net/sctp/sm_make_chunk.c: In function 'sctp_pack_cookie.isra.8':
net/sctp/sm_make_chunk.c:1687:1: warning: 'sctp_pack_cookie.isra.8' uses dynamic stack allocation
 }
 ^
net/sctp/sm_make_chunk.c: In function 'sctp_unpack_cookie':
net/sctp/sm_make_chunk.c:1866:1: warning: 'sctp_unpack_cookie' uses dynamic stack allocation
 }
 ^
drivers/scsi/device_handler/scsi_dh_alua.c: In function 'alua_rtpg':
drivers/scsi/device_handler/scsi_dh_alua.c:715:1: warning: 'alua_rtpg' uses dynamic stack allocation
 }
 ^
drivers/scsi/device_handler/scsi_dh_alua.c: In function 'alua_rtpg_work':
drivers/scsi/device_handler/scsi_dh_alua.c:856:1: warning: 'alua_rtpg_work' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_prime_packet_security':
net/rxrpc/rxkad.c:141:1: warning: 'rxkad_prime_packet_security' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_verify_packet_1':
net/rxrpc/rxkad.c:398:1: warning: 'rxkad_verify_packet_1' uses dynamic stack allocation
 }
 ^
drivers/target/iscsi/cxgbit/cxgbit_target.c: In function 'cxgbit_tx_datain_iso.isra.31':
drivers/target/iscsi/cxgbit/cxgbit_target.c:501:1: warning: 'cxgbit_tx_datain_iso.isra.31' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_verify_packet_2':
net/rxrpc/rxkad.c:498:1: warning: 'rxkad_verify_packet_2' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_verify_packet':
net/rxrpc/rxkad.c:563:1: warning: 'rxkad_verify_packet' uses dynamic stack allocation
 }
 ^
fs/f2fs/checkpoint.c: In function 'get_checkpoint_version':
fs/f2fs/checkpoint.c:749:1: warning: 'get_checkpoint_version' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_decrypt_response.isra.5':
net/rxrpc/rxkad.c:1042:1: warning: 'rxkad_decrypt_response.isra.5' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_encrypt_response.isra.6':
net/rxrpc/rxkad.c:765:1: warning: 'rxkad_encrypt_response.isra.6' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_secure_packet_encrypt.isra.8':
net/rxrpc/rxkad.c:242:1: warning: 'rxkad_secure_packet_encrypt.isra.8' uses dynamic stack allocation
 }
 ^
net/rxrpc/rxkad.c: In function 'rxkad_secure_packet':
net/rxrpc/rxkad.c:312:1: warning: 'rxkad_secure_packet' uses dynamic stack allocation
 }
 ^
fs/f2fs/checkpoint.c: In function 'do_checkpoint':
fs/f2fs/checkpoint.c:1342:1: warning: 'do_checkpoint' uses dynamic stack allocation
 }
 ^
fs/btrfs/raid56.c: In function 'finish_parity_scrub':
fs/btrfs/raid56.c:2477:1: warning: 'finish_parity_scrub' uses dynamic stack allocation
 }
 ^
fs/btrfs/raid56.c: In function 'finish_rmw':
fs/btrfs/raid56.c:1332:1: warning: 'finish_rmw' uses dynamic stack allocation
 }
 ^
net/sunrpc/auth_gss/gss_krb5_crypto.c: In function 'gss_krb5_cts_crypt':
net/sunrpc/auth_gss/gss_krb5_crypto.c:727:1: warning: 'gss_krb5_cts_crypt' uses dynamic stack allocation
 }
 ^
net/sunrpc/auth_gss/gss_krb5_crypto.c: In function 'krb5_encrypt':
net/sunrpc/auth_gss/gss_krb5_crypto.c:91:1: warning: 'krb5_encrypt' uses dynamic stack allocation
 }
 ^
net/sunrpc/auth_gss/gss_krb5_crypto.c: In function 'krb5_decrypt':
net/sunrpc/auth_gss/gss_krb5_crypto.c:129:1: warning: 'krb5_decrypt' uses dynamic stack allocation
 }
 ^
net/sunrpc/auth_gss/gss_krb5_crypto.c: In function 'gss_encrypt_xdr_buf':
net/sunrpc/auth_gss/gss_krb5_crypto.c:554:1: warning: 'gss_encrypt_xdr_buf' uses dynamic stack allocation
 }
 ^
net/sunrpc/auth_gss/gss_krb5_crypto.c: In function 'gss_decrypt_xdr_buf':
net/sunrpc/auth_gss/gss_krb5_crypto.c:633:1: warning: 'gss_decrypt_xdr_buf' uses dynamic stack allocation
 }
 ^
net/sunrpc/auth_gss/gss_krb5_crypto.c: In function 'gss_krb5_aes_encrypt':
net/sunrpc/auth_gss/gss_krb5_crypto.c:848:1: warning: 'gss_krb5_aes_encrypt' uses dynamic stack allocation
 }
 ^
net/sunrpc/auth_gss/gss_krb5_crypto.c: In function 'gss_krb5_aes_decrypt':
net/sunrpc/auth_gss/gss_krb5_crypto.c:941:1: warning: 'gss_krb5_aes_decrypt' uses dynamic stack allocation
 }
 ^
net/sctp/auth.c: In function 'sctp_auth_calculate_hmac':
net/sctp/auth.c:762:1: warning: 'sctp_auth_calculate_hmac' uses dynamic stack allocation
 }
 ^
fs/btrfs/hash.c: In function 'btrfs_crc32c':
fs/btrfs/hash.c:54:1: warning: 'btrfs_crc32c' uses dynamic stack allocation
 }
 ^
drivers/scsi/osd/osd_initiator.c: In function 'osd_req_decode_sense_full':
drivers/scsi/osd/osd_initiator.c:1955:1: warning: 'osd_req_decode_sense_full' uses dynamic stack allocation
 }
 ^
net/netfilter/nf_tables_api.c: In function 'nft_obj_init':
net/netfilter/nf_tables_api.c:4438:1: warning: 'nft_obj_init' uses dynamic stack allocation
 }
 ^
crypto/algif_hash.c: In function 'hash_accept':
crypto/algif_hash.c:281:1: warning: 'hash_accept' uses dynamic stack allocation
 }
 ^
fs/isofs/compress.c: In function 'zisofs_fill_pages':
fs/isofs/compress.c:291:1: warning: 'zisofs_fill_pages' uses dynamic stack allocation
 }
 ^
fs/isofs/compress.c: In function 'zisofs_readpage':
fs/isofs/compress.c:361:1: warning: 'zisofs_readpage' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'vli_mmod_fast':
crypto/ecc.c:533:1: warning: 'vli_mmod_fast' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'vli_mod_square_fast':
crypto/ecc.c:553:1: warning: 'vli_mod_square_fast' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'vli_mod_mult_fast':
crypto/ecc.c:543:1: warning: 'vli_mod_mult_fast' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'xycz_add_c':
crypto/ecc.c:841:1: warning: 'xycz_add_c' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'xycz_add':
crypto/ecc.c:784:1: warning: 'xycz_add' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'apply_z':
crypto/ecc.c:720:1: warning: 'apply_z' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'ecc_point_mult.isra.0':
crypto/ecc.c:896:1: warning: 'ecc_point_mult.isra.0' uses dynamic stack allocation
 }
 ^
crypto/algif_aead.c: In function 'aead_recvmsg':
crypto/algif_aead.c:358:1: warning: 'aead_recvmsg' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'ecc_gen_privkey':
crypto/ecc.c:984:1: warning: 'ecc_gen_privkey' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'ecc_make_pub_key':
crypto/ecc.c:1020:1: warning: 'ecc_make_pub_key' uses dynamic stack allocation
 }
 ^
crypto/ecc.c: In function 'crypto_ecdh_shared_secret':
crypto/ecc.c:1070:1: warning: 'crypto_ecdh_shared_secret' uses dynamic stack allocation
 }
 ^
crypto/async_tx/async_pq.c: In function 'async_gen_syndrome':
crypto/async_tx/async_pq.c:266:1: warning: 'async_gen_syndrome' uses dynamic stack allocation
 }
 ^
crypto/async_tx/raid6test.c: In function 'raid6_dual_recov.constprop':
crypto/async_tx/raid6test.c:128:1: warning: 'raid6_dual_recov.constprop' uses dynamic stack allocation
 }
 ^
fs/nfs/super.c: In function 'nfs_show_stats':
fs/nfs/super.c:890:1: warning: 'nfs_show_stats' uses dynamic stack allocation
 }
 ^
drivers/scsi/ufs/ufshcd.c: In function 'ufs_get_device_desc':
drivers/scsi/ufs/ufshcd.c:6072:1: warning: 'ufs_get_device_desc' uses dynamic stack allocation
 }
 ^
drivers/scsi/ufs/ufshcd.c: In function 'ufshcd_probe_hba':
drivers/scsi/ufs/ufshcd.c:6448:1: warning: 'ufshcd_probe_hba' uses dynamic stack allocation
 }
 ^
drivers/scsi/dpt_i2o.c: In function 'adpt_i2o_passthru':
drivers/scsi/dpt_i2o.c:1894:1: warning: 'adpt_i2o_passthru' uses dynamic stack allocation
 }
 ^
fs/ntfs/compress.c: In function 'ntfs_read_compressed_block':
fs/ntfs/compress.c:960:1: warning: 'ntfs_read_compressed_block' uses dynamic stack allocation
 }
 ^
fs/ntfs/aops.c: In function 'ntfs_write_mst_block':
fs/ntfs/aops.c:1329:1: warning: 'ntfs_write_mst_block' uses dynamic stack allocation
 }
 ^
fs/ntfs/mft.c: In function 'ntfs_sync_mft_mirror':
fs/ntfs/mft.c:637:1: warning: 'ntfs_sync_mft_mirror' uses dynamic stack allocation
 }
 ^
fs/ntfs/mft.c: In function 'write_mft_record_nolock':
fs/ntfs/mft.c:845:1: warning: 'write_mft_record_nolock' uses dynamic stack allocation
 }
 ^
fs/pstore/ram_core.c: In function 'persistent_ram_decode_rs8.isra.6':
fs/pstore/ram_core.c:120:1: warning: 'persistent_ram_decode_rs8.isra.6' uses dynamic stack allocation
 }
 ^
fs/pstore/ram_core.c: In function 'persistent_ram_encode_rs8.isra.7':
fs/pstore/ram_core.c:108:1: warning: 'persistent_ram_encode_rs8.isra.7' uses dynamic stack allocation
 }
 ^
fs/nfsd/nfs4recover.c: In function 'nfs4_make_rec_clidname':
fs/nfsd/nfs4recover.c:147:1: warning: 'nfs4_make_rec_clidname' uses dynamic stack allocation
 }
 ^
fs/reiserfs/inode.c: In function 'reiserfs_new_inode':
fs/reiserfs/inode.c:2162:1: warning: 'reiserfs_new_inode' uses dynamic stack allocation
 }
 ^
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c: In function 'acr_r352_ls_write_wpr':
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c:451:1: warning: 'acr_r352_ls_write_wpr' uses dynamic stack allocation
 }
 ^
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c: In function 'acr_ls_msgqueue_post_run':
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c:100:1: warning: 'acr_ls_msgqueue_post_run' uses dynamic stack allocation
 }
 ^
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c: In function 'acr_r352_load':
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c:815:1: warning: 'acr_r352_load' uses dynamic stack allocation
 }
 ^
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c: In function 'acr_r367_ls_write_wpr':
drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r367.c:302:1: warning: 'acr_r367_ls_write_wpr' uses dynamic stack allocation
 }
 ^

[-- Attachment #3: ppc64-20180201_104635.log --]
[-- Type: text/plain, Size: 19619 bytes --]

=== Config /home/mhocko/work/build-test/configs/powerpc64/allmodconfig
drivers/android/binder_alloc.c: In function 'binder_alloc_shrinker_init':
drivers/android/binder_alloc.c:1008:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&binder_shrinker);
  ^
In file included from samples/seccomp/bpf-fancy.c:21:0:
samples/seccomp/bpf-helper.h:135:2: error: #error __BITS_PER_LONG value unusable.
 #error __BITS_PER_LONG value unusable.
  ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
samples/seccomp/bpf-fancy.c: In function ‘main’:
samples/seccomp/bpf-fancy.c:38:11: error: ‘__NR_exit’ undeclared (first use in this function)
   SYSCALL(__NR_exit, ALLOW),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:38:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_exit, ALLOW),
   ^
samples/seccomp/bpf-fancy.c:38:11: note: each undeclared identifier is reported only once for each function it appears in
   SYSCALL(__NR_exit, ALLOW),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:38:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_exit, ALLOW),
   ^
samples/seccomp/bpf-fancy.c:39:11: error: ‘__NR_exit_group’ undeclared (first use in this function)
   SYSCALL(__NR_exit_group, ALLOW),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:39:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_exit_group, ALLOW),
   ^
samples/seccomp/bpf-fancy.c:40:11: error: ‘__NR_write’ undeclared (first use in this function)
   SYSCALL(__NR_write, JUMP(&l, write_fd)),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:40:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_write, JUMP(&l, write_fd)),
   ^
samples/seccomp/bpf-fancy.c:41:11: error: ‘__NR_read’ undeclared (first use in this function)
   SYSCALL(__NR_read, JUMP(&l, read)),
           ^
./usr/include/linux/filter.h:52:69: note: in definition of macro ‘BPF_JUMP’
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                                                     ^
samples/seccomp/bpf-fancy.c:41:3: note: in expansion of macro ‘SYSCALL’
   SYSCALL(__NR_read, JUMP(&l, read)),
   ^
samples/seccomp/bpf-fancy.c:45:3: warning: implicit declaration of function ‘ARG’ [-Wimplicit-function-declaration]
   ARG(0),
   ^
samples/seccomp/bpf-fancy.c:45:3: warning: missing braces around initializer [-Wmissing-braces]
samples/seccomp/bpf-fancy.c:45:3: warning: (near initialization for ‘filter[11]’) [-Wmissing-braces]
samples/seccomp/bpf-fancy.c:46:3: warning: implicit declaration of function ‘JNE’ [-Wimplicit-function-declaration]
   JNE(STDIN_FILENO, DENY),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:48:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  ^
samples/seccomp/bpf-fancy.c:46:21: note: in expansion of macro ‘DENY’
   JNE(STDIN_FILENO, DENY),
                     ^
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:48:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  ^
samples/seccomp/bpf-fancy.c:48:27: note: in expansion of macro ‘DENY’
   JNE((unsigned long)buf, DENY),
                           ^
samples/seccomp/bpf-fancy.c:50:3: warning: implicit declaration of function ‘JGE’ [-Wimplicit-function-declaration]
   JGE(sizeof(buf), DENY),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:48:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
  ^
samples/seccomp/bpf-fancy.c:50:20: note: in expansion of macro ‘DENY’
   JGE(sizeof(buf), DENY),
                    ^
samples/seccomp/bpf-fancy.c:51:3: warning: braces around scalar initializer [enabled by default]
   ALLOW,
   ^
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:51:3: warning: (near initialization for ‘filter[12].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: braces around scalar initializer [enabled by default]
   LABEL(&l, write_fd),
   ^
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:53:3: warning: (near initialization for ‘filter[12].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:55:3: warning: implicit declaration of function ‘JEQ’ [-Wimplicit-function-declaration]
   JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:55:22: note: in expansion of macro ‘JUMP’
   JEQ(STDOUT_FILENO, JUMP(&l, write_buf)),
                      ^
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:56:22: note: in expansion of macro ‘JUMP’
   JEQ(STDERR_FILENO, JUMP(&l, write_buf)),
                      ^
samples/seccomp/bpf-fancy.c:57:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:57:3: warning: (near initialization for ‘filter[13].k’) [enabled by default]
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:61:28: note: in expansion of macro ‘JUMP’
   JEQ((unsigned long)msg1, JUMP(&l, msg1_len)),
                            ^
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:62:28: note: in expansion of macro ‘JUMP’
   JEQ((unsigned long)msg2, JUMP(&l, msg2_len)),
                            ^
./usr/include/linux/filter.h:52:35: error: expected expression before ‘{’ token
 #define BPF_JUMP(code, k, jt, jf) { (unsigned short)(code), jt, jf, k }
                                   ^
samples/seccomp/bpf-helper.h:50:2: note: in expansion of macro ‘BPF_JUMP’
  BPF_JUMP(BPF_JMP+BPF_JA, FIND_LABEL((labels), (label)), \
  ^
samples/seccomp/bpf-fancy.c:63:27: note: in expansion of macro ‘JUMP’
   JEQ((unsigned long)buf, JUMP(&l, buf_len)),
                           ^
samples/seccomp/bpf-fancy.c:68:3: warning: implicit declaration of function ‘JLT’ [-Wimplicit-function-declaration]
   JLT(sizeof(msg1), ALLOW),
   ^
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:46:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  ^
samples/seccomp/bpf-fancy.c:68:21: note: in expansion of macro ‘ALLOW’
   JLT(sizeof(msg1), ALLOW),
                     ^
samples/seccomp/bpf-fancy.c:69:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:69:3: warning: (near initialization for ‘filter[18].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: braces around scalar initializer [enabled by default]
   LABEL(&l, msg2_len),
   ^
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:71:3: warning: (near initialization for ‘filter[18].k’) [enabled by default]
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:46:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  ^
samples/seccomp/bpf-fancy.c:73:21: note: in expansion of macro ‘ALLOW’
   JLT(sizeof(msg2), ALLOW),
                     ^
samples/seccomp/bpf-fancy.c:74:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:74:3: warning: (near initialization for ‘filter[19].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: braces around scalar initializer [enabled by default]
   LABEL(&l, buf_len),
   ^
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:76:3: warning: (near initialization for ‘filter[19].k’) [enabled by default]
In file included from samples/seccomp/bpf-fancy.c:13:0:
./usr/include/linux/filter.h:49:27: error: expected expression before ‘{’ token
 #define BPF_STMT(code, k) { (unsigned short)(code), 0, 0, k }
                           ^
samples/seccomp/bpf-helper.h:46:2: note: in expansion of macro ‘BPF_STMT’
  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
  ^
samples/seccomp/bpf-fancy.c:78:20: note: in expansion of macro ‘ALLOW’
   JLT(sizeof(buf), ALLOW),
                    ^
samples/seccomp/bpf-fancy.c:79:3: warning: braces around scalar initializer [enabled by default]
   DENY,
   ^
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: excess elements in scalar initializer [enabled by default]
samples/seccomp/bpf-fancy.c:79:3: warning: (near initialization for ‘filter[20].jf’) [enabled by default]
samples/seccomp/bpf-fancy.c:97:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1));
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:98:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1);
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:100:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2));
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:101:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDERR_FILENO, buf, bytes);
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
samples/seccomp/bpf-fancy.c:103:2: warning: passing argument 1 of ‘syscall’ makes integer from pointer without a cast [enabled by default]
  syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2);
  ^
In file included from samples/seccomp/bpf-fancy.c:19:0:
/usr/include/unistd.h:1061:17: note: expected ‘long int’ but argument is of type ‘struct sock_filter *’
 extern long int syscall (long int __sysno, ...) __THROW;
                 ^
make[2]: *** [samples/seccomp/bpf-fancy.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from samples/seccomp/bpf-helper.c:17:0:
samples/seccomp/bpf-helper.h:135:2: error: #error __BITS_PER_LONG value unusable.
 #error __BITS_PER_LONG value unusable.
  ^
make[2]: *** [samples/seccomp/bpf-helper.o] Error 1
make[1]: *** [samples/seccomp] Error 2
make[1]: *** Waiting for unfinished jobs....
make: *** [samples] Error 2
make: *** Waiting for unfinished jobs....
drivers/staging/android/ashmem.c: In function 'ashmem_init':
drivers/staging/android/ashmem.c:867:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&ashmem_shrinker);
  ^
drivers/staging/android/ion/ion_heap.c: In function 'ion_heap_init_shrinker':
drivers/staging/android/ion/ion_heap.c:315:2: warning: ignoring return value of 'register_shrinker', declared with attribute warn_unused_result [-Wunused-result]
  register_shrinker(&heap->shrinker);
  ^

^ permalink raw reply

* Re: [PATCH] headers: untangle kmemleak.h from mm.h
From: Randy Dunlap @ 2018-02-12 19:40 UTC (permalink / raw)
  To: Michael Ellerman, LKML, Linux MM, Andrew Morton, Fengguang Wu
  Cc: linux-s390, John Johansen, netdev@vger.kernel.org, X86 ML,
	linux-wireless, virtualization, iommu, Greg Kroah-Hartman,
	sparclinux, linuxppc-dev, Dmitry Kasatkin
In-Reply-To: <87zi4ev1d2.fsf@concordia.ellerman.id.au>

On 02/12/2018 04:28 AM, Michael Ellerman wrote:
> Randy Dunlap <rdunlap@infradead.org> writes:
> 
>> From: Randy Dunlap <rdunlap@infradead.org>
>>
>> Currently <linux/slab.h> #includes <linux/kmemleak.h> for no obvious
>> reason. It looks like it's only a convenience, so remove kmemleak.h
>> from slab.h and add <linux/kmemleak.h> to any users of kmemleak_*
>> that don't already #include it.
>> Also remove <linux/kmemleak.h> from source files that do not use it.
>>
>> This is tested on i386 allmodconfig and x86_64 allmodconfig. It
>> would be good to run it through the 0day bot for other $ARCHes.
>> I have neither the horsepower nor the storage space for the other
>> $ARCHes.
>>
>> [slab.h is the second most used header file after module.h; kernel.h
>> is right there with slab.h. There could be some minor error in the
>> counting due to some #includes having comments after them and I
>> didn't combine all of those.]
>>
>> This is Lingchi patch #1 (death by a thousand cuts, applied to kernel
>> header files).
>>
>> Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
> 
> I threw it at a random selection of configs and so far the only failures
> I'm seeing are:
> 
>   lib/test_firmware.c:134:2: error: implicit declaration of function 'vfree' [-Werror=implicit-function-declaration]                                                                                                          
>   lib/test_firmware.c:620:25: error: implicit declaration of function 'vzalloc' [-Werror=implicit-function-declaration]
>   lib/test_firmware.c:620:2: error: implicit declaration of function 'vzalloc' [-Werror=implicit-function-declaration]
>   security/integrity/digsig.c:146:2: error: implicit declaration of function 'vfree' [-Werror=implicit-function-declaration]
> 

Both of those source files need to #include <linux/vmalloc.h>.

> Full results trickling in here, not all the failures there are caused by
> this patch, ie. some configs are broken in mainline:
> 
>   http://kisskb.ellerman.id.au/kisskb/head/13396/
> 
> cheers

:)

-- 
~Randy

^ permalink raw reply

* Re: [PATCH 2/4] powerpc/vas: Fix cleanup when VAS is not configured
From: Sukadev Bhattiprolu @ 2018-02-12 20:25 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Benjamin Herrenschmidt, mikey, hbabu, linuxppc-dev, linux-kernel
In-Reply-To: <87d11awzkp.fsf@concordia.ellerman.id.au>

Michael Ellerman [mpe@ellerman.id.au] wrote:
> Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> writes:
> 
> > When VAS is not configured in the system, make sure to remove
> > the VAS debugfs directory and unregister the platform driver.
> >
> > Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> ...
> > diff --git a/arch/powerpc/platforms/powernv/vas.c b/arch/powerpc/platforms/powernv/vas.c
> > index aebbe95..f83e27d8 100644
> > --- a/arch/powerpc/platforms/powernv/vas.c
> > +++ b/arch/powerpc/platforms/powernv/vas.c
> > @@ -169,8 +169,11 @@ static int __init vas_init(void)
> >  		found++;
> >  	}
> >  
> > -	if (!found)
> > +	if (!found) {
> > +		platform_driver_unregister(&vas_driver);
> > +		vas_cleanup_dbgdir();
> >  		return -ENODEV;
> > +	}
> 
> The better patch would be to move the call to vas_init_dbgdir() down
> here, where we know we have successfully registered the driver.

Well, when VAS is configured, init_vas_instance() expects the top level
"vas" debugfs dir to already be setup.

We could have each init_vas_instance() assume it is the first and
unconditionally call vas_init_dbgdir(). vas_init_dbgdir() could make
sure to initialize only once.

Or, we could make a separate pass countng "ibm,vas" nodes. If there are
none, skip both steps (dbgdir and registering platform driver).

Sukadev

^ permalink raw reply

* Re: KVM compile error
From: Christian Zigotzky @ 2018-02-12 20:57 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: linuxppc-dev, kvm-ppc@vger.kernel.org
In-Reply-To: <84E200BC-4202-4BAD-85C2-C8ED6E464FCC@xenosoft.de>

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

Hello Michael,

I compiled the RC1 of kernel 4.16 today. Unfortunately the issue with KVM still exists.
I get the error 'label out defined but not used' (see error messages below).

Link to the rc1 kernel config without KVM: http://www.xenosoft.de/cyrus-4.16-rc1.config

Link to the git kernel config with KVM: http://www.xenosoft.de/cyrus-4.16-alpha10.config

Thanks,
Christian

Sent from my iPhone

> On 12. Feb 2018, at 13:04, Christian Zigotzky <chzigotzky@xenosoft.de> wrote:
> 
> It‘s only an info. I tried to compile the latest git version yesterday and I got this error. I will try to compile the RC1 today and test if this error still exists.
> 
> Cheers,
> Christian
> 
> Sent from my iPhone
> 
>> On 12. Feb 2018, at 12:08, Michael Ellerman <mpe@ellerman.id.au> wrote:
>> 
>> Christian Zigotzky <chzigotzky@xenosoft.de> writes:
>> 
>>> Just for info: KVM doesn’t compile currently.
>>> 
>>> Error messages:
>>> 
>>> CC      arch/powerpc/kvm/powerpc.o
>>> arch/powerpc/kvm/powerpc.c: In function 'kvm_arch_vcpu_ioctl_run':
>>> arch/powerpc/kvm/powerpc.c:1611:1: error: label 'out' defined but not used [-Werror=unused-label]
>>> out:
>>> ^
>>> cc1: all warnings being treated as errors
>> 
>> I don't see this, which compiler/config/commit is that?
>> 
>> cheers
> 

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

^ 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