* Re: [PATCH] powerpc/kvm/booke: fix altivec related build break
From: Michael Ellerman @ 2018-04-27 6:14 UTC (permalink / raw)
To: laurentiu.tudor, kvm-ppc; +Cc: linuxppc-dev, agraf, Laurentiu Tudor
In-Reply-To: <20180426123319.10843-1-laurentiu.tudor@nxp.com>
laurentiu.tudor@nxp.com writes:
> From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
>
> Add missing "altivec unavailable" interrupt injection helper
> thus fixing the linker error below:
>
> arch/powerpc/kvm/emulate_loadstore.o: In function `kvmppc_check_altivec_disabled':
> arch/powerpc/kvm/emulate_loadstore.c: undefined reference to `.kvmppc_core_queue_vec_unavail'
>
> Fixes: 09f984961c137c4b ("KVM: PPC: Book3S: Add MMIO emulation for VMX instructions")
What config are you using to hit this? I'd like to add it to my
auto-builder to catch it in future.
cheers
^ permalink raw reply
* Re: [PATCH 01/11] KVM: PPC: add pt_regs into kvm_vcpu_arch and move vcpu->arch.gpr[] into it
From: kbuild test robot @ 2018-04-27 3:47 UTC (permalink / raw)
To: wei.guo.simon
Cc: kbuild-all, kvm-ppc, Paul Mackerras, kvm, linuxppc-dev, Simon Guo
In-Reply-To: <1524657284-16706-2-git-send-email-wei.guo.simon@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 5424 bytes --]
Hi Simon,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/wei-guo-simon-gmail-com/KVM-PPC-add-pt_regs-into-kvm_vcpu_arch-and-move-vcpu-arch-gpr-into-it/20180427-055410
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc
Note: the linux-review/wei-guo-simon-gmail-com/KVM-PPC-add-pt_regs-into-kvm_vcpu_arch-and-move-vcpu-arch-gpr-into-it/20180427-055410 HEAD 92a7de2f1920f80f57d625d6d07731a00ea99161 builds fine.
It only hurts bisectibility.
All error/warnings (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/kvm_book3s.h:271:0,
from arch/powerpc/kernel/asm-offsets.c:57:
arch/powerpc/include/asm/kvm_book3s_64.h: In function 'copy_from_checkpoint':
>> arch/powerpc/include/asm/kvm_book3s_64.h:493:20: error: 'struct kvm_vcpu_arch' has no member named 'gpr'; did you mean 'qpr'?
memcpy(vcpu->arch.gpr, vcpu->arch.gpr_tm,
^~~
qpr
arch/powerpc/include/asm/kvm_book3s_64.h:494:27: error: 'struct kvm_vcpu_arch' has no member named 'gpr'; did you mean 'qpr'?
sizeof(vcpu->arch.gpr));
^~~
qpr
arch/powerpc/include/asm/kvm_book3s_64.h: In function 'copy_to_checkpoint':
arch/powerpc/include/asm/kvm_book3s_64.h:510:39: error: 'struct kvm_vcpu_arch' has no member named 'gpr'; did you mean 'qpr'?
memcpy(vcpu->arch.gpr_tm, vcpu->arch.gpr,
^~~
qpr
arch/powerpc/include/asm/kvm_book3s_64.h:511:27: error: 'struct kvm_vcpu_arch' has no member named 'gpr'; did you mean 'qpr'?
sizeof(vcpu->arch.gpr));
^~~
qpr
In file included from arch/powerpc/kernel/asm-offsets.c:30:0:
arch/powerpc/kernel/asm-offsets.c: In function 'main':
>> include/linux/compiler-gcc.h:170:2: error: 'struct kvm_vcpu_arch' has no member named 'nip'
__builtin_offsetof(a, b)
^
include/linux/kbuild.h:6:62: note: in definition of macro 'DEFINE'
asm volatile("\n.ascii \"->" #sym " %0 " #val "\"" : : "i" (val))
^~~
include/linux/stddef.h:17:32: note: in expansion of macro '__compiler_offsetof'
#define offsetof(TYPE, MEMBER) __compiler_offsetof(TYPE, MEMBER)
^~~~~~~~~~~~~~~~~~~
>> include/linux/kbuild.h:11:14: note: in expansion of macro 'offsetof'
DEFINE(sym, offsetof(struct str, mem))
^~~~~~~~
>> arch/powerpc/kernel/asm-offsets.c:441:2: note: in expansion of macro 'OFFSET'
OFFSET(VCPU_PC, kvm_vcpu, arch.nip);
^~~~~~
make[2]: *** [arch/powerpc/kernel/asm-offsets.s] Error 1
make[2]: Target '__build' not remade because of errors.
make[1]: *** [prepare0] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [sub-make] Error 2
vim +493 arch/powerpc/include/asm/kvm_book3s_64.h
4bb3c7a0 Paul Mackerras 2018-03-21 481
4bb3c7a0 Paul Mackerras 2018-03-21 482 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
4bb3c7a0 Paul Mackerras 2018-03-21 483 static inline void copy_from_checkpoint(struct kvm_vcpu *vcpu)
4bb3c7a0 Paul Mackerras 2018-03-21 484 {
4bb3c7a0 Paul Mackerras 2018-03-21 485 vcpu->arch.cr = vcpu->arch.cr_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 486 vcpu->arch.xer = vcpu->arch.xer_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 487 vcpu->arch.lr = vcpu->arch.lr_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 488 vcpu->arch.ctr = vcpu->arch.ctr_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 489 vcpu->arch.amr = vcpu->arch.amr_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 490 vcpu->arch.ppr = vcpu->arch.ppr_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 491 vcpu->arch.dscr = vcpu->arch.dscr_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 492 vcpu->arch.tar = vcpu->arch.tar_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 @493 memcpy(vcpu->arch.gpr, vcpu->arch.gpr_tm,
4bb3c7a0 Paul Mackerras 2018-03-21 494 sizeof(vcpu->arch.gpr));
4bb3c7a0 Paul Mackerras 2018-03-21 495 vcpu->arch.fp = vcpu->arch.fp_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 496 vcpu->arch.vr = vcpu->arch.vr_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 497 vcpu->arch.vrsave = vcpu->arch.vrsave_tm;
4bb3c7a0 Paul Mackerras 2018-03-21 498 }
4bb3c7a0 Paul Mackerras 2018-03-21 499
:::::: The code at line 493 was first introduced by commit
:::::: 4bb3c7a0208fc13ca70598efd109901a7cd45ae7 KVM: PPC: Book3S HV: Work around transactional memory bugs in POWER9
:::::: TO: Paul Mackerras <paulus@ozlabs.org>
:::::: CC: Michael Ellerman <mpe@ellerman.id.au>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 23368 bytes --]
^ permalink raw reply
* [PATCH v2] powerpc: Fix deadlock with multiple calls to smp_send_stop
From: Nicholas Piggin @ 2018-04-27 1:51 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin, Abdul Haleem, Michael Ellerman
smp_send_stop can lock up the IPI path for any subsequent calls,
because the receiving CPUs spin in their handler function. This
started becoming a problem with the addition of an smp_send_stop
call in the reboot path, because panics can reboot after doing
their own smp_send_stop.
The NMI IPI variant was fixed with ac61c11566 ("powerpc: Fix
smp_send_stop NMI IPI handling"), which leaves the smp_call_function
variant.
This is fixed by having smp_send_stop only ever do the
smp_call_function once. This is a bit less robust than the NMI IPI
fix, because any other call to smp_call_function after smp_send_stop
could deadlock, but that has always been the case, and it was not
been a problem before.
Cc: Michael Ellerman <mpe@ellerman.id.au>
Fixes: f2748bdfe1573 ("powerpc/powernv: Always stop secondaries before reboot/shutdown")
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
Changes since v1:
- Rebased to powerpc fixes branch which has the NMI IPI fix.
arch/powerpc/kernel/smp.c | 55 +++++++++++++++++++++++++++------------
1 file changed, 39 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 3582f30b60b7..9ca7148b5881 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -565,17 +565,6 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
}
#endif
-static void stop_this_cpu(void *dummy)
-{
- /* Remove this CPU */
- set_cpu_online(smp_processor_id(), false);
-
- hard_irq_disable();
- spin_begin();
- while (1)
- spin_cpu_relax();
-}
-
#ifdef CONFIG_NMI_IPI
static void nmi_stop_this_cpu(struct pt_regs *regs)
{
@@ -583,23 +572,57 @@ static void nmi_stop_this_cpu(struct pt_regs *regs)
* This is a special case because it never returns, so the NMI IPI
* handling would never mark it as done, which makes any later
* smp_send_nmi_ipi() call spin forever. Mark it done now.
+ *
+ * IRQs are already hard disabled by the smp_handle_nmi_ipi.
*/
nmi_ipi_lock();
nmi_ipi_busy_count--;
nmi_ipi_unlock();
- stop_this_cpu(NULL);
+ /* Remove this CPU */
+ set_cpu_online(smp_processor_id(), false);
+
+ spin_begin();
+ while (1)
+ spin_cpu_relax();
}
-#endif
void smp_send_stop(void)
{
-#ifdef CONFIG_NMI_IPI
smp_send_nmi_ipi(NMI_IPI_ALL_OTHERS, nmi_stop_this_cpu, 1000000);
-#else
+}
+
+#else /* CONFIG_NMI_IPI */
+
+static void stop_this_cpu(void *dummy)
+{
+ /* Remove this CPU */
+ set_cpu_online(smp_processor_id(), false);
+
+ hard_irq_disable();
+ spin_begin();
+ while (1)
+ spin_cpu_relax();
+}
+
+void smp_send_stop(void)
+{
+ static bool stopped = false;
+
+ /*
+ * Prevent waiting on csd lock from a previous smp_send_stop.
+ * This is racy, but in general callers try to do the right
+ * thing and only fire off one smp_send_stop (e.g., see
+ * kernel/panic.c)
+ */
+ if (stopped)
+ return;
+
+ stopped = true;
+
smp_call_function(stop_this_cpu, NULL, 0);
-#endif
}
+#endif /* CONFIG_NMI_IPI */
struct thread_info *current_set[NR_CPUS];
--
2.17.0
^ permalink raw reply related
* Re: [PATCH] powerpc/eeh: Avoid misleading message "EEH: no capable adapters found"
From: Russell Currey @ 2018-04-27 0:34 UTC (permalink / raw)
To: Mauro S. M. Rodrigues, linuxppc-dev, benh, paulus, mpe; +Cc: kernel
In-Reply-To: <1521771052-5973-1-git-send-email-maurosr@linux.vnet.ibm.com>
On Thu, 2018-03-22 at 23:10 -0300, Mauro S. M. Rodrigues wrote:
> Due to recent refactoring in EEH in:
> commit b9fde58db7e5 ("powerpc/powernv: Rework EEH initialization on
> powernv")
> a misleading message was seen in the kernel message buffer:
>
> [ 0.108431] EEH: PowerNV platform initialized
> [ 0.589979] EEH: No capable adapters found
>
> This happened due to the removal of the initialization delay for
> powernv
> platform.
>
> Even though the EEH infrastructure for the devices is eventually
> initialized and still works just fine the eeh device probe step is
> postponed in order to assure the PEs are created. Later
> pnv_eeh_post_init does the probe devices job but at that point the
> message was already shown right after eeh_init flow.
>
> This patch introduces a new flag EEH_POSTPONED_PROBE to represent
> that
> temporary state and avoid the message mentioned above and showing the
> follow one instead:
>
> [ 0.107724] EEH: PowerNV platform initialized
> [ 4.844825] EEH: PCI Enhanced I/O Error Handling Enabled
>
> Signed-off-by: Mauro S. M. Rodrigues <maurosr@linux.vnet.ibm.com>
Good idea, thanks for the patch.
Acked-by: Russell Currey <ruscur@russell.cc>
^ permalink raw reply
* [PATCH 3/4] dt-bindings: powerpc/4xx: move 4xx NDFC and EMAC bindings to subsystem directories
From: Rob Herring @ 2018-04-26 21:27 UTC (permalink / raw)
To: devicetree; +Cc: linux-kernel, Mark Rutland, linuxppc-dev
In-Reply-To: <20180426212744.28688-1-robh@kernel.org>
Bindings are supposed to be organized by device class/function. Move a
couple of powerpc 4xx bindings to the correct binding directory.
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/{powerpc/4xx/ndfc.txt => mtd/ibm,ndfc.txt} | 0
.../devicetree/bindings/{powerpc/4xx/emac.txt => net/ibm,emac.txt} | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename Documentation/devicetree/bindings/{powerpc/4xx/ndfc.txt => mtd/ibm,ndfc.txt} (100%)
rename Documentation/devicetree/bindings/{powerpc/4xx/emac.txt => net/ibm,emac.txt} (100%)
diff --git a/Documentation/devicetree/bindings/powerpc/4xx/ndfc.txt b/Documentation/devicetree/bindings/mtd/ibm,ndfc.txt
similarity index 100%
rename from Documentation/devicetree/bindings/powerpc/4xx/ndfc.txt
rename to Documentation/devicetree/bindings/mtd/ibm,ndfc.txt
diff --git a/Documentation/devicetree/bindings/powerpc/4xx/emac.txt b/Documentation/devicetree/bindings/net/ibm,emac.txt
similarity index 100%
rename from Documentation/devicetree/bindings/powerpc/4xx/emac.txt
rename to Documentation/devicetree/bindings/net/ibm,emac.txt
--
2.14.1
^ permalink raw reply
* Re: OOM killer invoked while still one forth of mem is available
From: LEROY Christophe @ 2018-04-26 20:29 UTC (permalink / raw)
To: Michal Hocko; +Cc: linuxppc-dev, linux-mm, David Rientjes
In-Reply-To: <20180426190514.GU17484@dhcp22.suse.cz>
Michal Hocko <mhocko@kernel.org> a =C3=A9crit=C2=A0:
> On Thu 26-04-18 15:28:46, Christophe LEROY wrote:
>>
>>
>> Le 26/04/2018 =C3=A0 15:11, Michal Hocko a =C3=A9crit=C2=A0:
>> > On Thu 26-04-18 08:10:30, Christophe LEROY wrote:
>> > >
>> > >
>> > > Le 25/04/2018 =C3=A0 21:57, David Rientjes a =C3=A9crit=C2=A0:
>> > > > On Tue, 24 Apr 2018, christophe leroy wrote:
>> > > >
>> > > > > Hi
>> > > > >
>> > > > > Allthough there is still about one forth of memory available (79=
76kB
>> > > > > among 32MB), oom-killer is invoked and makes a victim.
>> > > > >
>> > > > > What could be the reason and how could it be solved ?
>> > > > >
>> > > > > [ 54.400754] S99watchdogd-ap invoked oom-killer:
>> > > > > gfp_mask=3D0x27000c0(GFP_KERNEL_ACCOUNT|__GFP_NOTRACK), nodemask=
=3D0,
>> > > > > order=3D1, oom_score_adj=3D0
>> > > > > [ 54.400815] CPU: 0 PID: 777 Comm: S99watchdogd-ap Not tainted
>> > > > > 4.9.85-local-knld-998 #5
>> > > > > [ 54.400830] Call Trace:
>> > > > > [ 54.400910] [c1ca5d10] [c0327d28] dump_header.isra.4+0x54/0x1=
7c
>> > > > > (unreliable)
>> > > > > [ 54.400998] [c1ca5d50] [c0079d88] oom_kill_process+0xc4/0x414
>> > > > > [ 54.401067] [c1ca5d90] [c007a5c8] out_of_memory+0x35c/0x37c
>> > > > > [ 54.401220] [c1ca5dc0] [c007d68c]=20=20
>>=20__alloc_pages_nodemask+0x8ec/0x9a8
>> > > > > [ 54.401318] [c1ca5e70] [c00169d4]=20=20
>>=20copy_process.isra.9.part.10+0xdc/0x10d0
>> > > > > [ 54.401398] [c1ca5f00] [c0017b30] _do_fork+0xcc/0x2a8
>> > > > > [ 54.401473] [c1ca5f40] [c000a660] ret_from_syscall+0x0/0x38
>> > > >
>> > > > Looks like this is because the allocation is order-1, likely the
>> > > > allocation of a struct task_struct for a new process on fork.
>> > >
>> > > I'm not sure I understand what you mean. The allocation is order 1, =
yes,
>> > > does it explains why OOM killer is invoked ?
>> >
>> > Well, not really
>> > [ 54.437414] DMA: 460*4kB (UH) 201*8kB (UH) 121*16kB (UH)=20=20
>>=2043*32kB (UH) 10*64kB (U) 4*128kB (UH) 0*256kB 0*512kB 0*1024kB=20=20
>>=200*2048kB 0*4096kB 0*8192kB =3D 7912kB`
>> >
>> > You should have enough order-1+ pages to proceed.
>> >
>>
>> So, order is 1 so order - 1 is 0,
>
> Not sure what you mean by order - 1, maybe I've confused you. order-1
> means that the order is 1. So free is not all that important. What you
> should look at though is how many order 1+ free blocks are available.
Oh, ok, i thought you were saying order minus one.
So we need an order one, ie a 8k block.
>
>> what's wrong then ? Do the (UH) and (U)
>> means anything special ?
>
> Yes, show_migration_types. But I do not see why unmovable pageblocks
> should block the allocation. This is a GFP_KERNEL allocation request
> essentially - thus unmovable itself. This smells like a bug. We are way
> above reserves which could block the allocation.
Any suggestion on how to investigate that bug ? Anything to trace ?
Christophe
>
>> Otherwise, just above it says 'free:1994', so with
>> 1994 pages free I should have enough to proceed, shouldn't I ?
>
> Not for high order pages as per above...
>
> --
> Michal Hocko
> SUSE Labs
^ permalink raw reply
* Re: [PATCH 1/3] powerpc/nohash: remove hash related code from nohash headers.
From: kbuild test robot @ 2018-04-26 20:28 UTC (permalink / raw)
To: Christophe Leroy
Cc: kbuild-all, Benjamin Herrenschmidt, Paul Mackerras,
Michael Ellerman, linux-kernel, linuxppc-dev
In-Reply-To: <02633d43f29e1ba01865cd334216dc8efb8b4b11.1524587425.git.christophe.leroy@c-s.fr>
[-- Attachment #1: Type: text/plain, Size: 3786 bytes --]
Hi Christophe,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on powerpc/next]
[also build test ERROR on v4.17-rc2 next-20180426]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Christophe-Leroy/powerpc-nohash-remove-hash-related-code-from-nohash-headers/20180425-182026
base: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-ppc64e_defconfig (attached as .config)
compiler: powerpc64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=powerpc
All errors (new ones prefixed by >>):
In file included from arch/powerpc/include/asm/nohash/pgtable.h:6:0,
from arch/powerpc/include/asm/pgtable.h:19,
from include/linux/memremap.h:8,
from include/linux/mm.h:27,
from include/linux/mman.h:5,
from arch/powerpc/kernel/asm-offsets.c:22:
arch/powerpc/include/asm/nohash/64/pgtable.h: In function '__ptep_test_and_clear_young':
>> arch/powerpc/include/asm/nohash/64/pgtable.h:214:6: error: implicit declaration of function 'pte_young'; did you mean 'pte_pud'? [-Werror=implicit-function-declaration]
if (pte_young(*ptep))
^~~~~~~~~
pte_pud
In file included from arch/powerpc/include/asm/pgtable.h:19:0,
from include/linux/memremap.h:8,
from include/linux/mm.h:27,
from include/linux/mman.h:5,
from arch/powerpc/kernel/asm-offsets.c:22:
arch/powerpc/include/asm/nohash/pgtable.h: At top level:
>> arch/powerpc/include/asm/nohash/pgtable.h:20:19: error: static declaration of 'pte_young' follows non-static declaration
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
^~~~~~~~~
In file included from arch/powerpc/include/asm/nohash/pgtable.h:6:0,
from arch/powerpc/include/asm/pgtable.h:19,
from include/linux/memremap.h:8,
from include/linux/mm.h:27,
from include/linux/mman.h:5,
from arch/powerpc/kernel/asm-offsets.c:22:
arch/powerpc/include/asm/nohash/64/pgtable.h:214:6: note: previous implicit declaration of 'pte_young' was here
if (pte_young(*ptep))
^~~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [arch/powerpc/kernel/asm-offsets.s] Error 1
make[2]: Target '__build' not remade because of errors.
make[1]: *** [prepare0] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [sub-make] Error 2
vim +214 arch/powerpc/include/asm/nohash/64/pgtable.h
208
209 static inline int __ptep_test_and_clear_young(struct mm_struct *mm,
210 unsigned long addr, pte_t *ptep)
211 {
212 unsigned long old;
213
> 214 if (pte_young(*ptep))
215 return 0;
216 old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0);
217 return (old & _PAGE_ACCESSED) != 0;
218 }
219 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
220 #define ptep_test_and_clear_young(__vma, __addr, __ptep) \
221 ({ \
222 int __r; \
223 __r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
224 __r; \
225 })
226
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20553 bytes --]
^ permalink raw reply
* Re: OOM killer invoked while still one forth of mem is available
From: Michal Hocko @ 2018-04-26 19:05 UTC (permalink / raw)
To: Christophe LEROY; +Cc: David Rientjes, linux-mm, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <2706829f-6207-89f7-46e6-d32244305ccb@c-s.fr>
On Thu 26-04-18 15:28:46, Christophe LEROY wrote:
>
>
> Le 26/04/2018 à 15:11, Michal Hocko a écrit :
> > On Thu 26-04-18 08:10:30, Christophe LEROY wrote:
> > >
> > >
> > > Le 25/04/2018 à 21:57, David Rientjes a écrit :
> > > > On Tue, 24 Apr 2018, christophe leroy wrote:
> > > >
> > > > > Hi
> > > > >
> > > > > Allthough there is still about one forth of memory available (7976kB
> > > > > among 32MB), oom-killer is invoked and makes a victim.
> > > > >
> > > > > What could be the reason and how could it be solved ?
> > > > >
> > > > > [ 54.400754] S99watchdogd-ap invoked oom-killer:
> > > > > gfp_mask=0x27000c0(GFP_KERNEL_ACCOUNT|__GFP_NOTRACK), nodemask=0,
> > > > > order=1, oom_score_adj=0
> > > > > [ 54.400815] CPU: 0 PID: 777 Comm: S99watchdogd-ap Not tainted
> > > > > 4.9.85-local-knld-998 #5
> > > > > [ 54.400830] Call Trace:
> > > > > [ 54.400910] [c1ca5d10] [c0327d28] dump_header.isra.4+0x54/0x17c
> > > > > (unreliable)
> > > > > [ 54.400998] [c1ca5d50] [c0079d88] oom_kill_process+0xc4/0x414
> > > > > [ 54.401067] [c1ca5d90] [c007a5c8] out_of_memory+0x35c/0x37c
> > > > > [ 54.401220] [c1ca5dc0] [c007d68c] __alloc_pages_nodemask+0x8ec/0x9a8
> > > > > [ 54.401318] [c1ca5e70] [c00169d4] copy_process.isra.9.part.10+0xdc/0x10d0
> > > > > [ 54.401398] [c1ca5f00] [c0017b30] _do_fork+0xcc/0x2a8
> > > > > [ 54.401473] [c1ca5f40] [c000a660] ret_from_syscall+0x0/0x38
> > > >
> > > > Looks like this is because the allocation is order-1, likely the
> > > > allocation of a struct task_struct for a new process on fork.
> > >
> > > I'm not sure I understand what you mean. The allocation is order 1, yes,
> > > does it explains why OOM killer is invoked ?
> >
> > Well, not really
> > [ 54.437414] DMA: 460*4kB (UH) 201*8kB (UH) 121*16kB (UH) 43*32kB (UH) 10*64kB (U) 4*128kB (UH) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB = 7912kB`
> >
> > You should have enough order-1+ pages to proceed.
> >
>
> So, order is 1 so order - 1 is 0,
Not sure what you mean by order - 1, maybe I've confused you. order-1
means that the order is 1. So free is not all that important. What you
should look at though is how many order 1+ free blocks are available.
> what's wrong then ? Do the (UH) and (U)
> means anything special ?
Yes, show_migration_types. But I do not see why unmovable pageblocks
should block the allocation. This is a GFP_KERNEL allocation request
essentially - thus unmovable itself. This smells like a bug. We are way
above reserves which could block the allocation.
> Otherwise, just above it says 'free:1994', so with
> 1994 pages free I should have enough to proceed, shouldn't I ?
Not for high order pages as per above...
--
Michal Hocko
SUSE Labs
^ permalink raw reply
* Re: [RFC v2 3/3] postmigration/memory: Associativity & ibm,dynamic-memory-v2
From: Nathan Fontenot @ 2018-04-26 18:39 UTC (permalink / raw)
To: Michael Bringmann, linuxppc-dev; +Cc: John Allen, Thomas Falcon, Tyrel Datwyler
In-Reply-To: <78156b9a-0b05-9d90-8c31-b3e04f581f94@linux.vnet.ibm.com>
On 04/24/2018 04:35 PM, Michael Bringmann wrote:
> See below.
>
> On 04/24/2018 12:17 PM, Nathan Fontenot wrote:
>> On 02/26/2018 02:53 PM, Michael Bringmann wrote:
>>> postmigration/memory: Now apply changes to the associativity of memory
>>> blocks described by the 'ibm,dynamic-memory-v2' property regarding
>>> the topology of LPARS in Post Migration events.
>>>
>>> * Extend the previous work done for the 'ibm,associativity-lookup-array'
>>> to apply to either property 'ibm,dynamic-memory' or
>>> 'ibm,dynamic-memory-v2', whichever is present.
>>> * Add new code to parse the 'ibm,dynamic-memory-v2' property looking
>>> for differences in block 'assignment', associativity indexes per
>>> block, and any other difference currently known.
>>> * Rewrite some of the original code to parse the 'ibm,dynamic-memory'
>>> property to take advantage of LMB parsing code.
>>>
>>> When block differences are recognized, the memory block may be removed,
>>> added, or updated depending upon the state of the new device tree
>>> property and differences from the migrated value of the property.
>>>
>>
>> The only thing we need to check during LPM is affinity updates, memory
>> is not added or removed as part of LPM.
>>
>> I think a slightly different approach to this may be worth considering.
>> One of the goals of the drmem.c code was to remove the need to parse the
>> device tree for memory directly. For this update, I think we could modify
>> the code that builds the drmem_info data so that it can return a drmem_info
>> struct instead of assuming to set the global one.
>>
>> This change would allow you to do a straight compare on the global vs. the
>> new info from the updated device tree property. I think this would be cleaner
>> and may be able to use the same routine for V1 and V2 properties.
>
> The code dealing with the 'ibm,associativity' array updated cleanly to use
> the same function to scan the LMBs regardless of the version of the properties.
>
> The code dealing with changes to 'ibm,dynamic-memory-v2' is a mirror of the
> code in 'pseries_update_drconf_memory' that deals with changes to the property
> 'ibm,dynamic-memory', so it should also be updated. On the other hand, do we
> need to consider the memory requirements of creating/cloning the drmem_info
> structure to provide a copy based on the new 'dynamic-memory' property?
> Or is this not an issue?
If done correctly, using the drmem code to create a drmem_info struct from
the new memory property would allow us to use the same comparison routine
for v1 and v2 versions of the property.
The size of the drmem_info data is not big enough to be concerned about
memory requirements when making a copy.
-Nathan
>
>>
>>> Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
>>> ---
>>> Changes in RFC v2:
>>> -- Reuse existing parser code from 'drmem.c' in parsing property
>>> 'imb,dynamic-memory-v2' for migration.
>>> -- Fix crash during migration that occurs on non-VPHN systems
>>> when attempting to reset topology timer.
>>> -- Change section of a support function + variable from __init
>>> to normal runtime to make them visible to migration code.
>>> ---
>>> arch/powerpc/include/asm/drmem.h | 8 +
>>> arch/powerpc/mm/drmem.c | 23 ++-
>>> arch/powerpc/mm/numa.c | 3
>>> arch/powerpc/platforms/pseries/hotplug-memory.c | 175 +++++++++++++++++++----
>>> drivers/of/fdt.c | 4 -
>>> include/linux/of_fdt.h | 2
>>> 6 files changed, 170 insertions(+), 45 deletions(-)
>>>
>>> diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h
>>> index 47a7012..e4773c9 100644
>>> --- a/arch/powerpc/include/asm/drmem.h
>>> +++ b/arch/powerpc/include/asm/drmem.h
>>> @@ -92,6 +92,14 @@ void __init walk_drmem_lmbs(struct device_node *dn,
>>> void (*func)(struct drmem_lmb *, const __be32 **));
>>> int drmem_update_dt(void);
>>>
>>> +void walk_drmem_v1_lmbs(const __be32 *prop, const __be32 *data,
>>> + void (*func)(struct drmem_lmb *, const __be32 **));
>>> +
>>> +void read_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell,
>>> + const __be32 **prop);
>>> +void walk_drmem_v2_lmbs(const __be32 *prop, const __be32 *data,
>>> + void (*func)(struct drmem_lmb *, const __be32 **));
>>> +
>>> #ifdef CONFIG_PPC_PSERIES
>>> void __init walk_drmem_lmbs_early(unsigned long node,
>>> void (*func)(struct drmem_lmb *, const __be32 **));
>>> diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c
>>> index 31dbe14..e47a6e0 100644
>>> --- a/arch/powerpc/mm/drmem.c
>>> +++ b/arch/powerpc/mm/drmem.c
>>> @@ -192,7 +192,7 @@ int drmem_update_dt(void)
>>> return rc;
>>> }
>>>
>>> -static void __init read_drconf_v1_cell(struct drmem_lmb *lmb,
>>> +static void read_drconf_v1_cell(struct drmem_lmb *lmb,
>>> const __be32 **prop)
>>> {
>>> const __be32 *p = *prop;
>>> @@ -208,7 +208,7 @@ static void __init read_drconf_v1_cell(struct drmem_lmb *lmb,
>>> *prop = p;
>>> }
>>>
>>> -static void __init __walk_drmem_v1_lmbs(const __be32 *prop, const __be32 *usm,
>>> +void walk_drmem_v1_lmbs(const __be32 *prop, const __be32 *data,
>>> void (*func)(struct drmem_lmb *, const __be32 **))
>>> {
>>> struct drmem_lmb lmb;
>>> @@ -218,11 +218,12 @@ static void __init __walk_drmem_v1_lmbs(const __be32 *prop, const __be32 *usm,
>>>
>>> for (i = 0; i < n_lmbs; i++) {
>>> read_drconf_v1_cell(&lmb, &prop);
>>> - func(&lmb, &usm);
>>> + func(&lmb, &data);
>>> }
>>> }
>>> +EXPORT_SYMBOL(walk_drmem_v1_lmbs);
>>>
>>> -static void __init read_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell,
>>> +void read_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell,
>>> const __be32 **prop)
>>> {
>>> const __be32 *p = *prop;
>>> @@ -235,8 +236,9 @@ static void __init read_drconf_v2_cell(struct of_drconf_cell_v2 *dr_cell,
>>>
>>> *prop = p;
>>> }
>>> +EXPORT_SYMBOL(read_drconf_v2_cell);
>>>
>>> -static void __init __walk_drmem_v2_lmbs(const __be32 *prop, const __be32 *usm,
>>> +void walk_drmem_v2_lmbs(const __be32 *prop, const __be32 *data,
>>> void (*func)(struct drmem_lmb *, const __be32 **))
>>> {
>>> struct of_drconf_cell_v2 dr_cell;
>>> @@ -258,10 +260,11 @@ static void __init __walk_drmem_v2_lmbs(const __be32 *prop, const __be32 *usm,
>>> lmb.aa_index = dr_cell.aa_index;
>>> lmb.flags = dr_cell.flags;
>>>
>>> - func(&lmb, &usm);
>>> + func(&lmb, &data);
>>> }
>>> }
>>> }
>>> +EXPORT_SYMBOL(walk_drmem_v2_lmbs);
>>>
>>> #ifdef CONFIG_PPC_PSERIES
>>> void __init walk_drmem_lmbs_early(unsigned long node,
>>> @@ -280,12 +283,12 @@ void __init walk_drmem_lmbs_early(unsigned long node,
>>>
>>> prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &len);
>>> if (prop) {
>>> - __walk_drmem_v1_lmbs(prop, usm, func);
>>> + walk_drmem_v1_lmbs(prop, usm, func);
>>> } else {
>>> prop = of_get_flat_dt_prop(node, "ibm,dynamic-memory-v2",
>>> &len);
>>> if (prop)
>>> - __walk_drmem_v2_lmbs(prop, usm, func);
>>> + walk_drmem_v2_lmbs(prop, usm, func);
>>> }
>>>
>>> memblock_dump_all();
>>> @@ -340,11 +343,11 @@ void __init walk_drmem_lmbs(struct device_node *dn,
>>>
>>> prop = of_get_property(dn, "ibm,dynamic-memory", NULL);
>>> if (prop) {
>>> - __walk_drmem_v1_lmbs(prop, usm, func);
>>> + walk_drmem_v1_lmbs(prop, usm, func);
>>> } else {
>>> prop = of_get_property(dn, "ibm,dynamic-memory-v2", NULL);
>>> if (prop)
>>> - __walk_drmem_v2_lmbs(prop, usm, func);
>>> + walk_drmem_v2_lmbs(prop, usm, func);
>>> }
>>> }
>>>
>>> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
>>> index 0e573f9..2545fea 100644
>>> --- a/arch/powerpc/mm/numa.c
>>> +++ b/arch/powerpc/mm/numa.c
>>> @@ -1395,7 +1395,8 @@ static void topology_timer_fn(struct timer_list *unused)
>>>
>>> static void reset_topology_timer(void)
>>> {
>>> - mod_timer(&topology_timer, jiffies + topology_timer_secs * HZ);
>>> + if (vphn_enabled)
>>> + mod_timer(&topology_timer, jiffies + topology_timer_secs * HZ);
>>
>> This really looks like a bug fix that should be in a different patch.
>
> Okay.
>
>>
>> -Nathan
>
> Thanks.
> Michael
>
>>
>>> }
>>>
>>> #ifdef CONFIG_SMP
>>> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
>>> index b63181d..bf717e2 100644
>>> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
>>> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
>>> @@ -1051,49 +1051,155 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
>>> return rc;
>>> }
>>>
>>> -struct assoc_arrays {
>>> - u32 n_arrays;
>>> - u32 array_sz;
>>> - const __be32 *arrays;
>>> -};
>>> +static inline int pseries_memory_v2_find_drc(u32 drc_index,
>>> + u64 *base_addr, unsigned long memblock_size,
>>> + struct of_drconf_cell_v2 *dm)
>>> +{
>>> + if ((dm->drc_index <= drc_index) &&
>>> + (drc_index <= (dm->drc_index + dm->seq_lmbs - 1))) {
>>> + int offset = drc_index - dm->drc_index;
>>> +
>>> + (*base_addr) = dm->base_addr +
>>> + (offset * memblock_size);
>>> + } else if (drc_index > (dm->drc_index +
>>> + dm->seq_lmbs - 1)) {
>>> + return -1;
>>> + } else if (dm->drc_index > drc_index) {
>>> + return -1;
>>> + }
>>> +
>>> + return 0;
>>> +}
>>>
>>> -static int pseries_update_ala_memory_aai(int aa_index,
>>> - struct property *dmprop)
>>> +static int pseries_update_drconf_memory_v2(struct of_reconfig_data *pr)
>>> {
>>> - struct of_drconf_cell *drmem;
>>> - u32 entries;
>>> - __be32 *p;
>>> - int i;
>>> - int rc = 0;
>>> + const __be32 *new_drmem, *old_drmem;
>>> + unsigned long memblock_size;
>>> + u32 new_lmb_sets, old_lmb_sets;
>>> + u64 old_base_addr;
>>> + int i, rc = 0;
>>>
>>> - p = (__be32 *) dmprop->value;
>>> - if (!p)
>>> + if (rtas_hp_event)
>>> + return 0;
>>> +
>>> + memblock_size = pseries_memory_block_size();
>>> + if (!memblock_size)
>>> return -EINVAL;
>>>
>>> /* The first int of the property is the number of lmb's
>>> * described by the property. This is followed by an array
>>> - * of of_drconf_cell entries. Get the number of entries
>>> - * and skip to the array of of_drconf_cell's.
>>> + * of of_drconf_cell_v2 entries. Get the number of entries
>>> + * and skip to the array of of_drconf_cell_v2's.
>>> */
>>> - entries = be32_to_cpu(*p++);
>>> - drmem = (struct of_drconf_cell *)p;
>>> + old_drmem = (__be32 *) pr->old_prop->value;
>>> + if (!old_drmem)
>>> + return -EINVAL;
>>> + old_lmb_sets = of_read_number(old_drmem++, 1);
>>>
>>> - for (i = 0; i < entries; i++) {
>>> - if ((be32_to_cpu(drmem[i].aa_index) != aa_index) &&
>>> - (be32_to_cpu(drmem[i].flags) & DRCONF_MEM_ASSIGNED)) {
>>> - rc = dlpar_memory_readd_by_index(
>>> - be32_to_cpu(drmem[i].drc_index));
>>> + new_drmem = (__be32 *)pr->prop->value;
>>> + new_lmb_sets = of_read_number(new_drmem++, 1);
>>> +
>>> + for (i = 0; i < old_lmb_sets; i++) {
>>> + int j;
>>> + struct of_drconf_cell_v2 old_cell, new_cell;
>>> +
>>> + read_drconf_v2_cell(&old_cell, &old_drmem);
>>> + read_drconf_v2_cell(&new_cell, &new_drmem);
>>> +
>>> + for (j = 0; j < new_cell.seq_lmbs; j++) {
>>> + if (pseries_memory_v2_find_drc(
>>> + new_cell.drc_index + j,
>>> + &old_base_addr,
>>> + memblock_size,
>>> + &old_cell))
>>> + continue;
>>> +
>>> + if ((old_cell.flags &
>>> + DRCONF_MEM_ASSIGNED) &&
>>> + (!(new_cell.flags &
>>> + DRCONF_MEM_ASSIGNED))) {
>>> + rc = pseries_remove_memblock(
>>> + old_base_addr,
>>> + memblock_size);
>>> + } else if ((!(old_cell.flags &
>>> + DRCONF_MEM_ASSIGNED)) &&
>>> + (new_cell.flags &
>>> + DRCONF_MEM_ASSIGNED)) {
>>> + rc = memblock_add(
>>> + old_base_addr, memblock_size);
>>> + } else if ((old_cell.aa_index !=
>>> + new_cell.aa_index) &&
>>> + (new_cell.flags &
>>> + DRCONF_MEM_ASSIGNED)) {
>>> + dlpar_memory_readd_by_index(
>>> + new_cell.drc_index + j);
>>> + }
>>> }
>>> }
>>>
>>> - return rc;
>>> + return 0;
>>> +}
>>> +
>>> +struct assoc_arrays {
>>> + u32 n_arrays;
>>> + u32 array_sz;
>>> + const __be32 *arrays;
>>> +};
>>> +
>>> +struct update_ala_memory_aai_struct {
>>> + int aa_index;
>>> +};
>>> +
>>> +static void update_ala_memory_aai_cb(struct drmem_lmb *lmb,
>>> + const __be32 **data)
>>> +{
>>> + struct update_ala_memory_aai_struct *updt =
>>> + (struct update_ala_memory_aai_struct *)*data;
>>> +
>>> + if ((lmb->aa_index != updt->aa_index) &&
>>> + (lmb->flags & DRCONF_MEM_ASSIGNED))
>>> + dlpar_memory_readd_by_index(lmb->drc_index);
>>> +}
>>> +
>>> +static int pseries_update_ala_memory_aai_v1(int aa_index,
>>> + const __be32 *dmprop)
>>> +{
>>> + struct update_ala_memory_aai_struct data = {
>>> + aa_index };
>>> +
>>> + walk_drmem_v1_lmbs(dmprop, (const __be32 *)&data,
>>> + update_ala_memory_aai_cb);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int pseries_update_ala_memory_aai_v2(int aa_index,
>>> + const __be32 *dmprop)
>>> +{
>>> + struct update_ala_memory_aai_struct data = {
>>> + aa_index };
>>> +
>>> + walk_drmem_v2_lmbs(dmprop, (const __be32 *)&data,
>>> + update_ala_memory_aai_cb);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int pseries_update_ala_memory_aai(int v1, int aa_index,
>>> + const __be32 *dmprop)
>>> +{
>>> + if (v1)
>>> + return pseries_update_ala_memory_aai_v1(aa_index, dmprop);
>>> + else
>>> + return pseries_update_ala_memory_aai_v2(aa_index, dmprop);
>>> }
>>>
>>> static int pseries_update_ala_memory(struct of_reconfig_data *pr)
>>> {
>>> struct assoc_arrays new_ala, old_ala;
>>> struct device_node *dn;
>>> - struct property *dmprop;
>>> + const __be32 *dmprop;
>>> + bool v1 = true;
>>> __be32 *p;
>>> int i, lim;
>>>
>>> @@ -1104,10 +1210,15 @@ static int pseries_update_ala_memory(struct of_reconfig_data *pr)
>>> if (!dn)
>>> return -ENODEV;
>>>
>>> - dmprop = of_find_property(dn, "ibm,dynamic-memory", NULL);
>>> + dmprop = of_get_property(dn, "ibm,dynamic-memory", NULL);
>>> if (!dmprop) {
>>> - of_node_put(dn);
>>> - return -ENODEV;
>>> + v1 = false;
>>> + dmprop = of_get_property(dn, "ibm,dynamic-memory-v2",
>>> + NULL);
>>> + if (!dmprop) {
>>> + of_node_put(dn);
>>> + return -ENODEV;
>>> + }
>>> }
>>>
>>> /*
>>> @@ -1149,11 +1260,11 @@ static int pseries_update_ala_memory(struct of_reconfig_data *pr)
>>> new_ala.array_sz))
>>> continue;
>>>
>>> - pseries_update_ala_memory_aai(i, dmprop);
>>> + pseries_update_ala_memory_aai(v1, i, dmprop);
>>> }
>>>
>>> for (i = lim; i < new_ala.n_arrays; i++)
>>> - pseries_update_ala_memory_aai(i, dmprop);
>>> + pseries_update_ala_memory_aai(v1, i, dmprop);
>>>
>>> } else {
>>> /* Update all entries representing these rows;
>>> @@ -1161,7 +1272,7 @@ static int pseries_update_ala_memory(struct of_reconfig_data *pr)
>>> * have equivalent values.
>>> */
>>> for (i = 0; i < lim; i++)
>>> - pseries_update_ala_memory_aai(i, dmprop);
>>> + pseries_update_ala_memory_aai(v1, i, dmprop);
>>> }
>>>
>>> of_node_put(dn);
>>> @@ -1184,6 +1295,8 @@ static int pseries_memory_notifier(struct notifier_block *nb,
>>> case OF_RECONFIG_UPDATE_PROPERTY:
>>> if (!strcmp(rd->prop->name, "ibm,dynamic-memory"))
>>> err = pseries_update_drconf_memory(rd);
>>> + if (!strcmp(rd->prop->name, "ibm,dynamic-memory-v2"))
>>> + err = pseries_update_drconf_memory_v2(rd);
>>> if (!strcmp(rd->prop->name,
>>> "ibm,associativity-lookup-arrays"))
>>> err = pseries_update_ala_memory(rd);
>>> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
>>> index 4675e5a..00df576 100644
>>> --- a/drivers/of/fdt.c
>>> +++ b/drivers/of/fdt.c
>>> @@ -539,7 +539,7 @@ void *of_fdt_unflatten_tree(const unsigned long *blob,
>>> EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
>>>
>>> /* Everything below here references initial_boot_params directly. */
>>> -int __initdata dt_root_addr_cells;
>>> +int dt_root_addr_cells;
>>> int __initdata dt_root_size_cells;
>>>
>>> void *initial_boot_params;
>>> @@ -1013,7 +1013,7 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname,
>>> return 1;
>>> }
>>>
>>> -u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
>>> +u64 dt_mem_next_cell(int s, const __be32 **cellp)
>>> {
>>> const __be32 *p = *cellp;
>>>
>>> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
>>> index 013c541..14c8681 100644
>>> --- a/include/linux/of_fdt.h
>>> +++ b/include/linux/of_fdt.h
>>> @@ -40,7 +40,7 @@ extern void *of_fdt_unflatten_tree(const unsigned long *blob,
>>> struct device_node **mynodes);
>>>
>>> /* TBD: Temporary export of fdt globals - remove when code fully merged */
>>> -extern int __initdata dt_root_addr_cells;
>>> +extern int dt_root_addr_cells;
>>> extern int __initdata dt_root_size_cells;
>>> extern void *initial_boot_params;
>>>
>>
>
^ permalink raw reply
* Re: [RFC v2 1/3] hotplug/mobility: Apply assoc updates for Post Migration Topo
From: Nathan Fontenot @ 2018-04-26 18:31 UTC (permalink / raw)
To: Michael Bringmann, linuxppc-dev; +Cc: John Allen, Thomas Falcon, Tyrel Datwyler
In-Reply-To: <2b3e4948-a21b-423b-fa74-f4ae3ebd5978@linux.vnet.ibm.com>
On 04/24/2018 04:33 PM, Michael Bringmann wrote:
> See comments below:
>
> On 04/24/2018 11:56 AM, Nathan Fontenot wrote:
>> On 02/26/2018 02:52 PM, Michael Bringmann wrote:
>>> hotplug/mobility: Recognize more changes to the associativity of
>>> memory blocks described by the 'ibm,dynamic-memory' and 'cpu'
>>> properties when processing the topology of LPARS in Post Migration
>>> events. Previous efforts only recognized whether a memory block's
>>> assignment had changed in the property. Changes here include:
>>>
>>> * Checking the aa_index values of the old/new properties and 'readd'
>>> any block for which the setting has changed.
>>> * Checking for changes in cpu associativity and making 'readd' calls
>>> when differences are observed.
>>
>> As part of the post-migration updates do you need to hold a lock
>> so that we don't attempt to process any of the cpu/memory changes
>> while the device tree is being updated?
>>
>> You may be able to grab the device hotplug lock for this.
>
> The CPU Re-add process reuses the dlpar_cpu_remove / dlpar_cpu_add
> code for POWERPC. These functions end up invoking device_online() /
> device_offline() which in turn end up invoking the 'cpus_write_lock/unlock'
> around every kernel change to the CPU structures. It was modeled
> on the Memory Re-add process as we discussed a while back, which
> also uses device_online and a corresponding write lock for each
> LMB processed.
>
> Do you see a need for a coarser granularity of locking around
> all or a group of the cpu/memory changes? The data structures
> that the kernel outside of powerpc uses for CPUs and LMBs seem
> to be quite well isolated from the device-tree properties.
My thinking was for memory and CPU updates, the idea being that all
updates are queued up until after the post-LPM device tree updates happens.
Grabbing the device_hotplug lock while updating the device tree would
prevent any of the queued CPU/memory updates from happening.
>
>>
>>>
>>> Signed-off-by: Michael Bringmann <mwb@linux.vnet.ibm.com>
>>> ---
>>> Changes in RFC:
>>> -- Simplify code to update CPU nodes during mobility checks.
>>> Remove functions to generate extra HP_ELOG messages in favor
>>> of direct function calls to dlpar_cpu_readd_by_index.
>>> -- Move check for "cpu" node type from pseries_update_cpu to
>>> pseries_smp_notifier in 'hotplug-cpu.c'
>>> -- Remove functions 'pseries_memory_readd_by_index' and
>>> 'pseries_cpu_readd_by_index' as no longer needed outside of
>>> 'mobility.c'.
>>> ---
>>> arch/powerpc/platforms/pseries/hotplug-cpu.c | 69 +++++++++++++++++++++++
>>> arch/powerpc/platforms/pseries/hotplug-memory.c | 6 ++
>>> 2 files changed, 75 insertions(+)
>>>
>>> diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
>>> index a7d14aa7..91ef22a 100644
>>> --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
>>> +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
>>> @@ -636,6 +636,27 @@ static int dlpar_cpu_remove_by_index(u32 drc_index)
>>> return rc;
>>> }
>>>
>>> +static int dlpar_cpu_readd_by_index(u32 drc_index)
>>> +{
>>> + int rc = 0;
>>> +
>>> + pr_info("Attempting to update CPU, drc index %x\n", drc_index);
>>
>> Should make this say we are re-adding the CPU, it's a bit more specific as
>> to what is really happening.
>
> Okay. I will update the notice from dlpar_memory_readd_by_index, as well.
Looks like your current message mirrors what the memory readd routine has,
let's just keep the message as is.
-Nathan
>>
>>> +
>>> + if (dlpar_cpu_remove_by_index(drc_index))
>>> + rc = -EINVAL;
>>> + else if (dlpar_cpu_add(drc_index))
>>> + rc = -EINVAL;
>>> +
>>> + if (rc)
>>> + pr_info("Failed to update cpu at drc_index %lx\n",
>>> + (unsigned long int)drc_index);
>>> + else
>>> + pr_info("CPU at drc_index %lx was updated\n",
>>> + (unsigned long int)drc_index);
>>> +
>>> + return rc;
>>> +}
>>> +
>>> static int find_dlpar_cpus_to_remove(u32 *cpu_drcs, int cpus_to_remove)
>>> {
>>> struct device_node *dn;
>>> @@ -826,6 +847,9 @@ int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
>>> else
>>> rc = -EINVAL;
>>> break;
>>> + case PSERIES_HP_ELOG_ACTION_READD:
>>> + rc = dlpar_cpu_readd_by_index(drc_index);
>>> + break;
>>> default:
>>> pr_err("Invalid action (%d) specified\n", hp_elog->action);
>>> rc = -EINVAL;
>>> @@ -876,12 +900,53 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count)
>>>
>>> #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
>>>
>>> +static int pseries_update_cpu(struct of_reconfig_data *pr)
>>> +{
>>> + u32 old_entries, new_entries;
>>> + __be32 *p, *old_assoc, *new_assoc;
>>> + int rc = 0;
>>> +
>>> + /* So far, we only handle the 'ibm,associativity' property,
>>> + * here.
>>> + * The first int of the property is the number of domains
>>> + * described. This is followed by an array of level values.
>>> + */
>>> + p = (__be32 *) pr->old_prop->value;
>>> + if (!p)
>>> + return -EINVAL;
>>> + old_entries = be32_to_cpu(*p++);
>>> + old_assoc = p;
>>> +
>>> + p = (__be32 *)pr->prop->value;
>>> + if (!p)
>>> + return -EINVAL;
>>> + new_entries = be32_to_cpu(*p++);
>>> + new_assoc = p;
>>> +
>>> + if (old_entries == new_entries) {
>>> + int sz = old_entries * sizeof(int);
>>> +
>>> + if (!memcmp(old_assoc, new_assoc, sz))
>>> + rc = dlpar_cpu_readd_by_index(
>>> + be32_to_cpu(pr->dn->phandle));
>>> +
>>> + } else {
>>> + rc = dlpar_cpu_readd_by_index(
>>> + be32_to_cpu(pr->dn->phandle));
>>> + }
>>> +
>>> + return rc;
>>> +}
>>
>> Do we need to do the full compare of the new vs. the old affinity property?
>>
>> I would think we would only get an updated property if the property changes.
>> We don't care what changes in the property at this point, only that it changed.
>> You could just call dlpar_cpu_readd_by_index() directly.
>
> Okay.
>
>>
>> -Nathan
>
> Thanks.
> Michael
>
>>
>>> +
>>> static int pseries_smp_notifier(struct notifier_block *nb,
>>> unsigned long action, void *data)
>>> {
>>> struct of_reconfig_data *rd = data;
>>> int err = 0;
>>>
>>> + if (strcmp(rd->dn->type, "cpu"))
>>> + return notifier_from_errno(err);
>>> +
>>> switch (action) {
>>> case OF_RECONFIG_ATTACH_NODE:
>>> err = pseries_add_processor(rd->dn);
>>> @@ -889,6 +954,10 @@ static int pseries_smp_notifier(struct notifier_block *nb,
>>> case OF_RECONFIG_DETACH_NODE:
>>> pseries_remove_processor(rd->dn);
>>> break;
>>> + case OF_RECONFIG_UPDATE_PROPERTY:
>>> + if (!strcmp(rd->prop->name, "ibm,associativity"))
>>> + err = pseries_update_cpu(rd);
>>> + break;
>>> }
>>> return notifier_from_errno(err);
>>> }
>>> diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
>>> index c1578f5..2341eae 100644
>>> --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
>>> +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
>>> @@ -1040,6 +1040,12 @@ static int pseries_update_drconf_memory(struct of_reconfig_data *pr)
>>> memblock_size);
>>> rc = (rc < 0) ? -EINVAL : 0;
>>> break;
>>> + } else if ((be32_to_cpu(old_drmem[i].aa_index) !=
>>> + be32_to_cpu(new_drmem[i].aa_index)) &&
>>> + (be32_to_cpu(new_drmem[i].flags) &
>>> + DRCONF_MEM_ASSIGNED)) {
>>> + rc = dlpar_memory_readd_by_index(
>>> + be32_to_cpu(new_drmem[i].drc_index))> }
>>> }
>>> return rc;
>>>
>>
>
^ permalink raw reply
* Re: [PATCH 2/6] powerpc/64s: Add support for ori barrier_nospec patching
From: Michal Suchánek @ 2018-04-26 16:10 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, npiggin, linux-kernel
In-Reply-To: <20180424041559.32410-2-mpe@ellerman.id.au>
Hello,
On Tue, 24 Apr 2018 14:15:55 +1000
Michael Ellerman <mpe@ellerman.id.au> wrote:
> From: Michal Suchanek <msuchanek@suse.de>
>
> Based on the RFI patching. This is required to be able to disable the
> speculation barrier.
why do you not patch the nospec barrier which is included as part of
the RFI flush code?
I think when debugging the code it would make more sense if RFI is
patched by RFI patcher and nospec by nospec patcher.
A separate question is if the RFI flush would break without the nospec
barrier.
Thanks
Michal
>
> Only one barrier type is supported and it does nothing when the
> firmware does not enable it. Also re-patching modules is not supported
> So the only meaningful thing that can be done is patching out the
> speculation barrier at boot when the user says it is not wanted.
>
> Signed-off-by: Michal Suchanek <msuchanek@suse.de>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> ---
> arch/powerpc/include/asm/barrier.h | 2 +-
> arch/powerpc/include/asm/feature-fixups.h | 9 +++++++++
> arch/powerpc/include/asm/setup.h | 1 +
> arch/powerpc/kernel/security.c | 9 +++++++++
> arch/powerpc/kernel/vmlinux.lds.S | 7 +++++++
> arch/powerpc/lib/feature-fixups.c | 27
> +++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 1
> deletion(-)
>
> diff --git a/arch/powerpc/include/asm/barrier.h
> b/arch/powerpc/include/asm/barrier.h index e582d2c88092..f67b3f6e36be
> 100644 --- a/arch/powerpc/include/asm/barrier.h
> +++ b/arch/powerpc/include/asm/barrier.h
> @@ -81,7 +81,7 @@ do
> {
> \
> * Prevent execution of subsequent instructions until preceding
> branches have
> * been fully resolved and are no longer executing speculatively.
> */
> -#define barrier_nospec_asm ori 31,31,0
> +#define barrier_nospec_asm NOSPEC_BARRIER_FIXUP_SECTION; nop
>
> // This also acts as a compiler barrier due to the memory clobber.
> #define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) :::
> "memory") diff --git a/arch/powerpc/include/asm/feature-fixups.h
> b/arch/powerpc/include/asm/feature-fixups.h index
> 1e82eb3caabd..86ac59e75f36 100644 ---
> a/arch/powerpc/include/asm/feature-fixups.h +++
> b/arch/powerpc/include/asm/feature-fixups.h @@ -195,11 +195,20 @@
> label##3: \
> FTR_ENTRY_OFFSET 951b-952b; \ .popsection;
>
> +#define NOSPEC_BARRIER_FIXUP_SECTION \
> +953: \
> + .pushsection __barrier_nospec_fixup,"a"; \
> + .align 2; \
> +954: \
> + FTR_ENTRY_OFFSET 953b-954b; \
> + .popsection;
> +
>
> #ifndef __ASSEMBLY__
> #include <linux/types.h>
>
> extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
> +extern long __start___barrier_nospec_fixup,
> __stop___barrier_nospec_fixup;
> void apply_feature_fixups(void);
> void setup_feature_keys(void);
> diff --git a/arch/powerpc/include/asm/setup.h
> b/arch/powerpc/include/asm/setup.h index 27fa52ed6d00..afc7280cce3b
> 100644 --- a/arch/powerpc/include/asm/setup.h
> +++ b/arch/powerpc/include/asm/setup.h
> @@ -52,6 +52,7 @@ enum l1d_flush_type {
>
> void setup_rfi_flush(enum l1d_flush_type, bool enable);
> void do_rfi_flush_fixups(enum l1d_flush_type types);
> +void do_barrier_nospec_fixups(bool enable);
>
> #endif /* !__ASSEMBLY__ */
>
> diff --git a/arch/powerpc/kernel/security.c
> b/arch/powerpc/kernel/security.c index bab5a27ea805..b963eae0b0a0
> 100644 --- a/arch/powerpc/kernel/security.c
> +++ b/arch/powerpc/kernel/security.c
> @@ -9,10 +9,19 @@
> #include <linux/seq_buf.h>
>
> #include <asm/security_features.h>
> +#include <asm/setup.h>
>
>
> unsigned long powerpc_security_features __read_mostly =
> SEC_FTR_DEFAULT;
> +static bool barrier_nospec_enabled;
> +
> +static void enable_barrier_nospec(bool enable)
> +{
> + barrier_nospec_enabled = enable;
> + do_barrier_nospec_fixups(enable);
> +}
> +
> ssize_t cpu_show_meltdown(struct device *dev, struct
> device_attribute *attr, char *buf) {
> bool thread_priv;
> diff --git a/arch/powerpc/kernel/vmlinux.lds.S
> b/arch/powerpc/kernel/vmlinux.lds.S index c8af90ff49f0..ff73f498568c
> 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S
> +++ b/arch/powerpc/kernel/vmlinux.lds.S
> @@ -139,6 +139,13 @@ SECTIONS
> *(__rfi_flush_fixup)
> __stop___rfi_flush_fixup = .;
> }
> +
> + . = ALIGN(8);
> + __spec_barrier_fixup : AT(ADDR(__spec_barrier_fixup) -
> LOAD_OFFSET) {
> + __start___barrier_nospec_fixup = .;
> + *(__barrier_nospec_fixup)
> + __stop___barrier_nospec_fixup = .;
> + }
> #endif
>
> EXCEPTION_TABLE(0)
> diff --git a/arch/powerpc/lib/feature-fixups.c
> b/arch/powerpc/lib/feature-fixups.c index 288fe4f0db4e..093c1d2ea5fd
> 100644 --- a/arch/powerpc/lib/feature-fixups.c
> +++ b/arch/powerpc/lib/feature-fixups.c
> @@ -162,6 +162,33 @@ void do_rfi_flush_fixups(enum l1d_flush_type
> types) (types & L1D_FLUSH_MTTRIG) ? "mttrig type"
> : "unknown");
> }
> +
> +void do_barrier_nospec_fixups(bool enable)
> +{
> + unsigned int instr, *dest;
> + long *start, *end;
> + int i;
> +
> + start = PTRRELOC(&__start___barrier_nospec_fixup),
> + end = PTRRELOC(&__stop___barrier_nospec_fixup);
> +
> + instr = 0x60000000; /* nop */
> +
> + if (enable) {
> + pr_info("barrier-nospec: using ORI speculation
> barrier\n");
> + instr = 0x63ff0000; /* ori 31,31,0 speculation
> barrier */
> + }
> +
> + for (i = 0; start < end; start++, i++) {
> + dest = (void *)start + *start;
> +
> + pr_devel("patching dest %lx\n", (unsigned long)dest);
> + patch_instruction(dest, instr);
> + }
> +
> + printk(KERN_DEBUG "barrier-nospec: patched %d locations\n",
> i); +}
> +
> #endif /* CONFIG_PPC_BOOK3S_64 */
>
> void do_lwsync_fixups(unsigned long value, void *fixup_start, void
> *fixup_end)
^ permalink raw reply
* Re: [PATCH 4/6] powerpc/64s: Enable barrier_nospec based on firmware settings
From: Michal Suchánek @ 2018-04-26 16:02 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, linux-kernel, npiggin
In-Reply-To: <20180424041559.32410-4-mpe@ellerman.id.au>
Hello,
On Tue, 24 Apr 2018 14:15:57 +1000
Michael Ellerman <mpe@ellerman.id.au> wrote:
> From: Michal Suchanek <msuchanek@suse.de>
>
> Check what firmware told us and enable/disable the barrier_nospec as
> appropriate.
>
> We err on the side of enabling the barrier, as it's no-op on older
> systems, see the comment for more detail.
>
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> ---
> arch/powerpc/include/asm/setup.h | 1 +
> arch/powerpc/kernel/security.c | 60
> ++++++++++++++++++++++++++++++++++
> arch/powerpc/platforms/powernv/setup.c | 1 +
> arch/powerpc/platforms/pseries/setup.c | 1 + 4 files changed, 63
> insertions(+)
>
> diff --git a/arch/powerpc/include/asm/setup.h
> b/arch/powerpc/include/asm/setup.h index 4335cddc1cf2..aeb175e8a525
> 100644 --- a/arch/powerpc/include/asm/setup.h
> +++ b/arch/powerpc/include/asm/setup.h
> @@ -52,6 +52,7 @@ enum l1d_flush_type {
>
> void setup_rfi_flush(enum l1d_flush_type, bool enable);
> void do_rfi_flush_fixups(enum l1d_flush_type types);
> +void setup_barrier_nospec(void);
> void do_barrier_nospec_fixups(bool enable);
>
> #ifdef CONFIG_PPC_BOOK3S_64
> diff --git a/arch/powerpc/kernel/security.c
> b/arch/powerpc/kernel/security.c index b963eae0b0a0..d1b9639e5e24
> 100644 --- a/arch/powerpc/kernel/security.c
> +++ b/arch/powerpc/kernel/security.c
> @@ -8,6 +8,7 @@
> #include <linux/device.h>
> #include <linux/seq_buf.h>
>
> +#include <asm/debugfs.h>
> #include <asm/security_features.h>
> #include <asm/setup.h>
>
> @@ -22,6 +23,65 @@ static void enable_barrier_nospec(bool enable)
> do_barrier_nospec_fixups(enable);
> }
>
> +void setup_barrier_nospec(void)
> +{
> + bool enable;
> +
> + /*
> + * It would make sense to check SEC_FTR_SPEC_BAR_ORI31 below
> as well.
> + * But there's a good reason not to. The two flags we check
> below are
> + * both are enabled by default in the kernel, so if the
> hcall is not
> + * functional they will be enabled.
> + * On a system where the host firmware has been updated (so
> the ori
> + * functions as a barrier), but on which the hypervisor
> (KVM/Qemu) has
> + * not been updated, we would like to enable the barrier.
> Dropping the
> + * check for SEC_FTR_SPEC_BAR_ORI31 achieves that. The only
> downside is
> + * we potentially enable the barrier on systems where the
> host firmware
> + * is not updated, but that's harmless as it's a no-op.
> + */
> + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
> + security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR);
> +
> + enable_barrier_nospec(enable);
> +}
I am missing the option for the barrier to be disabled by a kernel
commandline argument here.
It does make sense to add a kernel parameter that is checked on boot to
be compatible with other platforms that implement one.
Thanks
Michal
^ permalink raw reply
* [RFC PATCH 6/9] powerpc: mm: migrate: add pmd swap entry to support thp migration.
From: Zi Yan @ 2018-04-26 14:28 UTC (permalink / raw)
To: linux-mm, linux-kernel
Cc: Zi Yan, Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Aneesh Kumar K.V, Ram Pai, Balbir Singh, Naoya Horiguchi,
linuxppc-dev
In-Reply-To: <20180426142804.180152-1-zi.yan@sent.com>
From: Zi Yan <zi.yan@cs.rutgers.edu>
pmd swap soft dirty support is added, too.
Signed-off-by: Zi Yan <zi.yan@cs.rutgers.edu>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Cc: Ram Pai <linuxram@us.ibm.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-mm@kvack.org
---
arch/powerpc/include/asm/book3s/32/pgtable.h | 2 ++
arch/powerpc/include/asm/book3s/64/pgtable.h | 17 +++++++++++++++++
arch/powerpc/include/asm/nohash/32/pgtable.h | 2 ++
arch/powerpc/include/asm/nohash/64/pgtable.h | 2 ++
4 files changed, 23 insertions(+)
diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h
index c615abdce119..866b67a8abf0 100644
--- a/arch/powerpc/include/asm/book3s/32/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
@@ -294,7 +294,9 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
#define __swp_offset(entry) ((entry).val >> 5)
#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 5) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 })
+#define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pmd) >> 3 })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 })
+#define __swp_entry_to_pmd(x) ((pmd_t) { (x).val << 3 })
int map_kernel_page(unsigned long va, phys_addr_t pa, int flags);
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index a6b9f1d74600..6b3c6492071d 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -726,7 +726,9 @@ static inline bool pte_user(pte_t pte)
* Clear bits not found in swap entries here.
*/
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) & ~_PAGE_PTE })
+#define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val((pmd)) & ~_PAGE_PTE })
#define __swp_entry_to_pte(x) __pte((x).val | _PAGE_PTE)
+#define __swp_entry_to_pmd(x) __pmd((x).val | _PAGE_PTE)
#ifdef CONFIG_MEM_SOFT_DIRTY
#define _PAGE_SWP_SOFT_DIRTY (1UL << (SWP_TYPE_BITS + _PAGE_BIT_SWAP_TYPE))
@@ -749,6 +751,21 @@ static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
{
return __pte(pte_val(pte) & ~_PAGE_SWP_SOFT_DIRTY);
}
+
+static inline pmd_t pmd_swp_mksoft_dirty(pmd_t pmd)
+{
+ return __pmd(pmd_val(pmd) | _PAGE_SWP_SOFT_DIRTY);
+}
+
+static inline bool pmd_swp_soft_dirty(pmd_t pmd)
+{
+ return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_SWP_SOFT_DIRTY));
+}
+
+static inline pmd_t pmd_swp_clear_soft_dirty(pmd_t pmd)
+{
+ return __pmd(pmd_val(pmd) & ~_PAGE_SWP_SOFT_DIRTY);
+}
#endif /* CONFIG_HAVE_ARCH_SOFT_DIRTY */
static inline bool check_pte_access(unsigned long access, unsigned long ptev)
diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h
index 03bbd1149530..f6b0534a02d4 100644
--- a/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -337,7 +337,9 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
#define __swp_offset(entry) ((entry).val >> 5)
#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 5) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 3 })
+#define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val(pte) >> 3 })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 3 })
+#define __swp_entry_to_pmd(x) ((pmd_t) { (x).val << 3 })
int map_kernel_page(unsigned long va, phys_addr_t pa, int flags);
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h
index 5c5f75d005ad..5790763c07df 100644
--- a/arch/powerpc/include/asm/nohash/64/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/64/pgtable.h
@@ -342,7 +342,9 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm,
| ((offset) << PTE_RPN_SHIFT) })
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val((pte)) })
+#define __pmd_to_swp_entry(pmd) ((swp_entry_t) { pmd_val((pmd)) })
#define __swp_entry_to_pte(x) __pte((x).val)
+#define __swp_entry_to_pmd(x) __pmd((x).val)
extern int map_kernel_page(unsigned long ea, unsigned long pa,
unsigned long flags);
--
2.17.0
^ permalink raw reply related
* [RFC PATCH 9/9] mm: migrate: enable thp migration for all possible architectures.
From: Zi Yan @ 2018-04-26 14:28 UTC (permalink / raw)
To: linux-mm, linux-kernel
Cc: Zi Yan, Vineet Gupta, linux-snps-arc, Russell King,
Christoffer Dall, Marc Zyngier, linux-arm-kernel, Catalin Marinas,
Will Deacon, Steve Capper, Kristina Martsenko, Dan Williams,
Thomas Gleixner, Ingo Molnar, Kirill A. Shutemov, x86,
Ralf Baechle, James Hogan, Michal Hocko, linux-mips,
Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Aneesh Kumar K.V, Ram Pai, Balbir Singh, Naoya Horiguchi,
linuxppc-dev, Martin Schwidefsky, Heiko Carstens, Janosch Frank,
linux-s390, David S. Miller, sparclinux, Huang, Ying
In-Reply-To: <20180426142804.180152-1-zi.yan@sent.com>
From: Zi Yan <zi.yan@cs.rutgers.edu>
Remove CONFIG_ARCH_ENABLE_THP_MIGRATION. thp migration is enabled along
with transparent hugepage and can be toggled via
/sys/kernel/mm/transparent_hugepage/enable_thp_migration.
Signed-off-by: Zi Yan <zi.yan@cs.rutgers.edu>
Cc: linux-mm@kvack.org
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: linux-snps-arc@lists.infradead.org
Cc: Russell King <linux@armlinux.org.uk>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Kristina Martsenko <kristina.martsenko@arm.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: x86@kernel.org
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: linux-mips@linux-mips.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Cc: Ram Pai <linuxram@us.ibm.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Janosch Frank <frankja@linux.vnet.ibm.com>
Cc: linux-s390@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: "Huang, Ying" <ying.huang@intel.com>
---
arch/x86/Kconfig | 4 ----
arch/x86/include/asm/pgtable.h | 2 --
fs/proc/task_mmu.c | 2 --
include/asm-generic/pgtable.h | 21 ++-------------------
include/linux/huge_mm.h | 9 ++++-----
include/linux/swapops.h | 4 +---
mm/Kconfig | 3 ---
mm/huge_memory.c | 27 ++++++++++++++++++---------
mm/migrate.c | 6 ++----
mm/rmap.c | 5 ++---
10 files changed, 29 insertions(+), 54 deletions(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0fa71a78ec99..e73954e3eef7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2423,10 +2423,6 @@ config ARCH_ENABLE_HUGEPAGE_MIGRATION
def_bool y
depends on X86_64 && HUGETLB_PAGE && MIGRATION
-config ARCH_ENABLE_THP_MIGRATION
- def_bool y
- depends on X86_64 && TRANSPARENT_HUGEPAGE
-
menu "Power management and ACPI options"
config ARCH_HIBERNATION_HEADER
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index b444d83cfc95..f9f54d9b39e3 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -1193,7 +1193,6 @@ static inline pte_t pte_swp_clear_soft_dirty(pte_t pte)
return pte_clear_flags(pte, _PAGE_SWP_SOFT_DIRTY);
}
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
static inline pmd_t pmd_swp_mksoft_dirty(pmd_t pmd)
{
return pmd_set_flags(pmd, _PAGE_SWP_SOFT_DIRTY);
@@ -1209,7 +1208,6 @@ static inline pmd_t pmd_swp_clear_soft_dirty(pmd_t pmd)
return pmd_clear_flags(pmd, _PAGE_SWP_SOFT_DIRTY);
}
#endif
-#endif
#define PKRU_AD_BIT 0x1
#define PKRU_WD_BIT 0x2
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index dd1b2aeb01e8..07a2f028d29a 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1326,7 +1326,6 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
frame = pmd_pfn(pmd) +
((addr & ~PMD_MASK) >> PAGE_SHIFT);
}
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
else if (is_swap_pmd(pmd)) {
swp_entry_t entry = pmd_to_swp_entry(pmd);
unsigned long offset = swp_offset(entry);
@@ -1340,7 +1339,6 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
VM_BUG_ON(!is_pmd_migration_entry(pmd));
page = migration_entry_to_page(entry);
}
-#endif
if (page && page_mapcount(page) == 1)
flags |= PM_MMAP_EXCLUSIVE;
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index f59639afaa39..9dacdd203131 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -674,24 +674,7 @@ static inline void ptep_modify_prot_commit(struct mm_struct *mm,
#define arch_start_context_switch(prev) do {} while (0)
#endif
-#ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY
-#ifndef CONFIG_ARCH_ENABLE_THP_MIGRATION
-static inline pmd_t pmd_swp_mksoft_dirty(pmd_t pmd)
-{
- return pmd;
-}
-
-static inline int pmd_swp_soft_dirty(pmd_t pmd)
-{
- return 0;
-}
-
-static inline pmd_t pmd_swp_clear_soft_dirty(pmd_t pmd)
-{
- return pmd;
-}
-#endif
-#else /* !CONFIG_HAVE_ARCH_SOFT_DIRTY */
+#ifndef CONFIG_HAVE_ARCH_SOFT_DIRTY
static inline int pte_soft_dirty(pte_t pte)
{
return 0;
@@ -946,7 +929,7 @@ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
* redundant with !pmd_present().
*/
if (pmd_none(pmdval) || pmd_trans_huge(pmdval) ||
- (IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION) && !pmd_present(pmdval)))
+ (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && !pmd_present(pmdval)))
return 1;
if (unlikely(pmd_bad(pmdval))) {
pmd_clear_bad(pmd);
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index a8a126259bc4..dc3144bdb7e5 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -59,6 +59,7 @@ enum transparent_hugepage_flag {
TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG,
TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG,
TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG,
+ TRANSPARENT_HUGEPAGE_MIGRATION_FLAG,
#ifdef CONFIG_DEBUG_VM
TRANSPARENT_HUGEPAGE_DEBUG_COW_FLAG,
#endif
@@ -126,6 +127,9 @@ static inline bool transparent_hugepage_enabled(struct vm_area_struct *vma)
#else /* CONFIG_DEBUG_VM */
#define transparent_hugepage_debug_cow() 0
#endif /* CONFIG_DEBUG_VM */
+#define thp_migration_supported() \
+ (transparent_hugepage_flags & \
+ (1<<TRANSPARENT_HUGEPAGE_MIGRATION_FLAG))
extern unsigned long thp_get_unmapped_area(struct file *filp,
unsigned long addr, unsigned long len, unsigned long pgoff,
@@ -240,11 +244,6 @@ void mm_put_huge_zero_page(struct mm_struct *mm);
#define mk_huge_pmd(page, prot) pmd_mkhuge(mk_pmd(page, prot))
-static inline bool thp_migration_supported(void)
-{
- return IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION);
-}
-
#else /* CONFIG_TRANSPARENT_HUGEPAGE */
#define HPAGE_PMD_SHIFT ({ BUILD_BUG(); 0; })
#define HPAGE_PMD_MASK ({ BUILD_BUG(); 0; })
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index 1d3877c39a00..1b723685f887 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -260,7 +260,7 @@ static inline int is_write_migration_entry(swp_entry_t entry)
struct page_vma_mapped_walk;
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
extern void set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
struct page *page);
@@ -295,13 +295,11 @@ static inline int is_pmd_migration_entry(pmd_t pmd)
static inline void set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
struct page *page)
{
- BUILD_BUG();
}
static inline void remove_migration_pmd(struct page_vma_mapped_walk *pvmw,
struct page *new)
{
- BUILD_BUG();
}
static inline void pmd_migration_entry_wait(struct mm_struct *m, pmd_t *p) { }
diff --git a/mm/Kconfig b/mm/Kconfig
index c782e8fb7235..7f29c5c2a8f6 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -262,9 +262,6 @@ config MIGRATION
config ARCH_ENABLE_HUGEPAGE_MIGRATION
bool
-config ARCH_ENABLE_THP_MIGRATION
- bool
-
config PHYS_ADDR_T_64BIT
def_bool 64BIT || ARCH_PHYS_ADDR_T_64BIT
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index a3a1815f8e11..80240bec2e11 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -55,7 +55,8 @@ unsigned long transparent_hugepage_flags __read_mostly =
#endif
(1<<TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG)|
(1<<TRANSPARENT_HUGEPAGE_DEFRAG_KHUGEPAGED_FLAG)|
- (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG);
+ (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG)|
+ (1<<TRANSPARENT_HUGEPAGE_MIGRATION_FLAG);
static struct shrinker deferred_split_shrinker;
@@ -288,6 +289,21 @@ static ssize_t use_zero_page_store(struct kobject *kobj,
static struct kobj_attribute use_zero_page_attr =
__ATTR(use_zero_page, 0644, use_zero_page_show, use_zero_page_store);
+static ssize_t thp_migration_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return single_hugepage_flag_show(kobj, attr, buf,
+ TRANSPARENT_HUGEPAGE_MIGRATION_FLAG);
+}
+static ssize_t thp_migration_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t count)
+{
+ return single_hugepage_flag_store(kobj, attr, buf, count,
+ TRANSPARENT_HUGEPAGE_MIGRATION_FLAG);
+}
+static struct kobj_attribute thp_migration_attr =
+ __ATTR(enable_thp_migration, 0644, thp_migration_show, thp_migration_store);
+
static ssize_t hpage_pmd_size_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
@@ -319,6 +335,7 @@ static struct attribute *hugepage_attr[] = {
&defrag_attr.attr,
&use_zero_page_attr.attr,
&hpage_pmd_size_attr.attr,
+ &thp_migration_attr.attr,
#if defined(CONFIG_SHMEM) && defined(CONFIG_TRANSPARENT_HUGE_PAGECACHE)
&shmem_enabled_attr.attr,
#endif
@@ -924,7 +941,6 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
ret = -EAGAIN;
pmd = *src_pmd;
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
if (unlikely(is_swap_pmd(pmd))) {
swp_entry_t entry = pmd_to_swp_entry(pmd);
@@ -943,7 +959,6 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
ret = 0;
goto out_unlock;
}
-#endif
if (unlikely(!pmd_trans_huge(pmd))) {
pte_free(dst_mm, pgtable);
@@ -1857,7 +1872,6 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
preserve_write = prot_numa && pmd_write(*pmd);
ret = 1;
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
if (is_swap_pmd(*pmd)) {
swp_entry_t entry = pmd_to_swp_entry(*pmd);
@@ -1876,7 +1890,6 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd,
}
goto unlock;
}
-#endif
/*
* Avoid trapping faults against the zero page. The read-only
@@ -2128,7 +2141,6 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
*/
old_pmd = pmdp_invalidate(vma, haddr, pmd);
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
pmd_migration = is_pmd_migration_entry(old_pmd);
if (pmd_migration) {
swp_entry_t entry;
@@ -2136,7 +2148,6 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
entry = pmd_to_swp_entry(old_pmd);
page = pfn_to_page(swp_offset(entry));
} else
-#endif
page = pmd_page(old_pmd);
VM_BUG_ON_PAGE(!page_count(page), page);
page_ref_add(page, HPAGE_PMD_NR - 1);
@@ -2870,7 +2881,6 @@ static int __init split_huge_pages_debugfs(void)
late_initcall(split_huge_pages_debugfs);
#endif
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
void set_pmd_migration_entry(struct page_vma_mapped_walk *pvmw,
struct page *page)
{
@@ -2934,4 +2944,3 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new)
mlock_vma_page(new);
update_mmu_cache_pmd(vma, address, pvmw->pmd);
}
-#endif
diff --git a/mm/migrate.c b/mm/migrate.c
index 507cf9ba21bf..cb9c3af32614 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -220,14 +220,12 @@ static bool remove_migration_pte(struct page *page, struct vm_area_struct *vma,
new = page - pvmw.page->index +
linear_page_index(vma, pvmw.address);
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
/* PMD-mapped THP migration entry */
- if (!pvmw.pte) {
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && !pvmw.pte) {
VM_BUG_ON_PAGE(PageHuge(page) || !PageTransCompound(page), page);
remove_migration_pmd(&pvmw, new);
continue;
}
-#endif
get_page(new);
pte = pte_mkold(mk_pte(new, READ_ONCE(vma->vm_page_prot)));
@@ -353,7 +351,7 @@ void migration_entry_wait_huge(struct vm_area_struct *vma,
__migration_entry_wait(mm, pte, ptl);
}
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
void pmd_migration_entry_wait(struct mm_struct *mm, pmd_t *pmd)
{
spinlock_t *ptl;
diff --git a/mm/rmap.c b/mm/rmap.c
index 8d5337fed37b..f5434f4f3e06 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1369,15 +1369,14 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
mmu_notifier_invalidate_range_start(vma->vm_mm, start, end);
while (page_vma_mapped_walk(&pvmw)) {
-#ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
/* PMD-mapped THP migration entry */
- if (!pvmw.pte && (flags & TTU_MIGRATION)) {
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
+ !pvmw.pte && (flags & TTU_MIGRATION)) {
VM_BUG_ON_PAGE(PageHuge(page) || !PageTransCompound(page), page);
set_pmd_migration_entry(&pvmw, page);
continue;
}
-#endif
/*
* If the page is mlock()d, we cannot swap it out.
--
2.17.0
^ permalink raw reply related
* [RFC PATCH 0/9] Enable THP migration for all possible architectures
From: Zi Yan @ 2018-04-26 14:27 UTC (permalink / raw)
To: linux-mm, linux-kernel
Cc: Zi Yan, Vineet Gupta, linux-snps-arc, Russell King,
Christoffer Dall, Marc Zyngier, linux-arm-kernel, Catalin Marinas,
Will Deacon, Steve Capper, Kristina Martsenko, Dan Williams,
Thomas Gleixner, Ingo Molnar, Kirill A. Shutemov, x86,
Ralf Baechle, James Hogan, Michal Hocko, linux-mips,
Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Aneesh Kumar K.V, Ram Pai, Balbir Singh, Naoya Horiguchi,
linuxppc-dev, Martin Schwidefsky, Heiko Carstens, Janosch Frank,
linux-s390, David S. Miller, sparclinux, Huang, Ying
From: Zi Yan <zi.yan@cs.rutgers.edu>
Hi all,
THP migration is only enabled on x86_64 with a special
ARCH_ENABLE_THP_MIGRATION macro. This patchset enables THP migration for
all architectures that uses transparent hugepage, so that special macro can
be dropped. Instead, THP migration is enabled/disabled via
/sys/kernel/mm/transparent_hugepage/enable_thp_migration.
I grepped for TRANSPARENT_HUGEPAGE in arch folder and got 9 architectures that
are supporting transparent hugepage. I mechanically add __pmd_to_swp_entry() and
__swp_entry_to_pmd() based on existing __pte_to_swp_entry() and
__swp_entry_to_pte() for all these architectures, except tile which is going to
be dropped.
I have successfully compiled all these architectures, but have NOT tested them
due to lack of real hardware. I appreciate your help, if the maintainers of
these architectures can do a quick test with the code from
https://github.com/x-y-z/thp-migration-bench . Please apply patch 9 as well
to enable THP migration.
By enabling THP migration, migrating a 2MB THP on x86_64 machines takes only 1/3
time of migrating equivalent 512 4KB pages.
Hi Naoya, I also add soft dirty support for powerpc and s390. It would be great
if you can take a look at patch 6 & 7.
Feel free to give comments. Thanks.
Cc: linux-mm@kvack.org
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: linux-snps-arc@lists.infradead.org
Cc: Russell King <linux@armlinux.org.uk>
Cc: Christoffer Dall <christoffer.dall@linaro.org>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Kristina Martsenko <kristina.martsenko@arm.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: x86@kernel.org
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: linux-mips@linux-mips.org
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Cc: Ram Pai <linuxram@us.ibm.com>
Cc: Balbir Singh <bsingharora@gmail.com>
Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Janosch Frank <frankja@linux.vnet.ibm.com>
Cc: linux-s390@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>
Cc: sparclinux@vger.kernel.org
Cc: "Huang, Ying" <ying.huang@intel.com>
Zi Yan (9):
arc: mm: migrate: add pmd swap entry to support thp migration.
arm: mm: migrate: add pmd swap entry to support thp migration.
arm64: mm: migrate: add pmd swap entry to support thp migration.
i386: mm: migrate: add pmd swap entry to support thp migration.
mips: mm: migrate: add pmd swap entry to support thp migration.
powerpc: mm: migrate: add pmd swap entry to support thp migration.
s390: mm: migrate: add pmd swap entry to support thp migration.
sparc: mm: migrate: add pmd swap entry to support thp migration.
mm: migrate: enable thp migration for all possible architectures.
arch/arc/include/asm/pgtable.h | 2 ++
arch/arm/include/asm/pgtable.h | 2 ++
arch/arm64/include/asm/pgtable.h | 2 ++
arch/mips/include/asm/pgtable-64.h | 2 ++
arch/powerpc/include/asm/book3s/32/pgtable.h | 2 ++
arch/powerpc/include/asm/book3s/64/pgtable.h | 17 ++++++++++++
arch/powerpc/include/asm/nohash/32/pgtable.h | 2 ++
arch/powerpc/include/asm/nohash/64/pgtable.h | 2 ++
arch/s390/include/asm/pgtable.h | 5 ++++
arch/sparc/include/asm/pgtable_32.h | 2 ++
arch/sparc/include/asm/pgtable_64.h | 2 ++
arch/x86/Kconfig | 4 ---
arch/x86/include/asm/pgtable-2level.h | 2 ++
arch/x86/include/asm/pgtable-3level.h | 2 ++
arch/x86/include/asm/pgtable.h | 2 --
fs/proc/task_mmu.c | 2 --
include/asm-generic/pgtable.h | 21 ++-------------
include/linux/huge_mm.h | 9 +++----
include/linux/swapops.h | 4 +--
mm/Kconfig | 3 ---
mm/huge_memory.c | 27 +++++++++++++-------
mm/migrate.c | 6 ++---
mm/rmap.c | 5 ++--
23 files changed, 73 insertions(+), 54 deletions(-)
--
2.17.0
^ permalink raw reply
* Re: [PATCH v5 1/4] powerpc/fadump: un-register fadump on kexec path.
From: Nicholas Piggin @ 2018-04-26 13:40 UTC (permalink / raw)
To: Mahesh Jagannath Salgaonkar
Cc: linuxppc-dev, Srikar Dronamraju, kernelfans, Aneesh Kumar K.V,
Ananth Narayan, Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <d064a5aa-9568-b83b-3154-c719721de17e@linux.vnet.ibm.com>
On Thu, 26 Apr 2018 18:35:10 +0530
Mahesh Jagannath Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
> On 04/26/2018 06:28 PM, Nicholas Piggin wrote:
> > On Thu, 26 Apr 2018 17:12:03 +0530
> > Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
> >
> >> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
> >>
> >> otherwise the fadump registration in new kexec-ed kernel complains that
> >> fadump is already registered. This makes new kernel to continue using
> >> fadump registered by previous kernel which may lead to invalid vmcore
> >> generation. Hence this patch fixes this issue by un-registering fadump
> >> in fadump_cleanup() which is called during kexec path so that new kernel
> >> can register fadump with new valid values.
> >
> > I assume this series is for 4.17, but it might be good to get this one
> > into the 4.16 fixes branch? Should it go to stable kernels?
>
> You are right. Should I send it out as separate patch ?
Yes I think so.
Thanks,
Nick
^ permalink raw reply
* Re: OOM killer invoked while still one forth of mem is available
From: Christophe LEROY @ 2018-04-26 13:28 UTC (permalink / raw)
To: Michal Hocko; +Cc: David Rientjes, linux-mm, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20180426131154.GQ17484@dhcp22.suse.cz>
Le 26/04/2018 à 15:11, Michal Hocko a écrit :
> On Thu 26-04-18 08:10:30, Christophe LEROY wrote:
>>
>>
>> Le 25/04/2018 à 21:57, David Rientjes a écrit :
>>> On Tue, 24 Apr 2018, christophe leroy wrote:
>>>
>>>> Hi
>>>>
>>>> Allthough there is still about one forth of memory available (7976kB
>>>> among 32MB), oom-killer is invoked and makes a victim.
>>>>
>>>> What could be the reason and how could it be solved ?
>>>>
>>>> [ 54.400754] S99watchdogd-ap invoked oom-killer:
>>>> gfp_mask=0x27000c0(GFP_KERNEL_ACCOUNT|__GFP_NOTRACK), nodemask=0,
>>>> order=1, oom_score_adj=0
>>>> [ 54.400815] CPU: 0 PID: 777 Comm: S99watchdogd-ap Not tainted
>>>> 4.9.85-local-knld-998 #5
>>>> [ 54.400830] Call Trace:
>>>> [ 54.400910] [c1ca5d10] [c0327d28] dump_header.isra.4+0x54/0x17c
>>>> (unreliable)
>>>> [ 54.400998] [c1ca5d50] [c0079d88] oom_kill_process+0xc4/0x414
>>>> [ 54.401067] [c1ca5d90] [c007a5c8] out_of_memory+0x35c/0x37c
>>>> [ 54.401220] [c1ca5dc0] [c007d68c] __alloc_pages_nodemask+0x8ec/0x9a8
>>>> [ 54.401318] [c1ca5e70] [c00169d4] copy_process.isra.9.part.10+0xdc/0x10d0
>>>> [ 54.401398] [c1ca5f00] [c0017b30] _do_fork+0xcc/0x2a8
>>>> [ 54.401473] [c1ca5f40] [c000a660] ret_from_syscall+0x0/0x38
>>>
>>> Looks like this is because the allocation is order-1, likely the
>>> allocation of a struct task_struct for a new process on fork.
>>
>> I'm not sure I understand what you mean. The allocation is order 1, yes,
>> does it explains why OOM killer is invoked ?
>
> Well, not really
> [ 54.437414] DMA: 460*4kB (UH) 201*8kB (UH) 121*16kB (UH) 43*32kB (UH) 10*64kB (U) 4*128kB (UH) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB = 7912kB`
>
> You should have enough order-1+ pages to proceed.
>
So, order is 1 so order - 1 is 0, what's wrong then ? Do the (UH) and
(U) means anything special ? Otherwise, just above it says 'free:1994',
so with 1994 pages free I should have enough to proceed, shouldn't I ?
Am I missing something ?
Christophe
^ permalink raw reply
* Re: OOM killer invoked while still one forth of mem is available
From: Michal Hocko @ 2018-04-26 13:11 UTC (permalink / raw)
To: Christophe LEROY; +Cc: David Rientjes, linux-mm, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <296ea83c-2c00-f1d2-3f62-d8ab8b8fb73c@c-s.fr>
On Thu 26-04-18 08:10:30, Christophe LEROY wrote:
>
>
> Le 25/04/2018 à 21:57, David Rientjes a écrit :
> > On Tue, 24 Apr 2018, christophe leroy wrote:
> >
> > > Hi
> > >
> > > Allthough there is still about one forth of memory available (7976kB
> > > among 32MB), oom-killer is invoked and makes a victim.
> > >
> > > What could be the reason and how could it be solved ?
> > >
> > > [ 54.400754] S99watchdogd-ap invoked oom-killer:
> > > gfp_mask=0x27000c0(GFP_KERNEL_ACCOUNT|__GFP_NOTRACK), nodemask=0,
> > > order=1, oom_score_adj=0
> > > [ 54.400815] CPU: 0 PID: 777 Comm: S99watchdogd-ap Not tainted
> > > 4.9.85-local-knld-998 #5
> > > [ 54.400830] Call Trace:
> > > [ 54.400910] [c1ca5d10] [c0327d28] dump_header.isra.4+0x54/0x17c
> > > (unreliable)
> > > [ 54.400998] [c1ca5d50] [c0079d88] oom_kill_process+0xc4/0x414
> > > [ 54.401067] [c1ca5d90] [c007a5c8] out_of_memory+0x35c/0x37c
> > > [ 54.401220] [c1ca5dc0] [c007d68c] __alloc_pages_nodemask+0x8ec/0x9a8
> > > [ 54.401318] [c1ca5e70] [c00169d4] copy_process.isra.9.part.10+0xdc/0x10d0
> > > [ 54.401398] [c1ca5f00] [c0017b30] _do_fork+0xcc/0x2a8
> > > [ 54.401473] [c1ca5f40] [c000a660] ret_from_syscall+0x0/0x38
> >
> > Looks like this is because the allocation is order-1, likely the
> > allocation of a struct task_struct for a new process on fork.
>
> I'm not sure I understand what you mean. The allocation is order 1, yes,
> does it explains why OOM killer is invoked ?
Well, not really
[ 54.437414] DMA: 460*4kB (UH) 201*8kB (UH) 121*16kB (UH) 43*32kB (UH) 10*64kB (U) 4*128kB (UH) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB 0*8192kB = 7912kB`
You should have enough order-1+ pages to proceed.
--
Michal Hocko
SUSE Labs
^ permalink raw reply
* Re: [PATCH v5 1/4] powerpc/fadump: un-register fadump on kexec path.
From: Mahesh Jagannath Salgaonkar @ 2018-04-26 13:05 UTC (permalink / raw)
To: Nicholas Piggin
Cc: linuxppc-dev, Srikar Dronamraju, kernelfans, Aneesh Kumar K.V,
Ananth Narayan, Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <20180426225757.2a8552e0@roar.ozlabs.ibm.com>
On 04/26/2018 06:28 PM, Nicholas Piggin wrote:
> On Thu, 26 Apr 2018 17:12:03 +0530
> Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
>
>> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>>
>> otherwise the fadump registration in new kexec-ed kernel complains that
>> fadump is already registered. This makes new kernel to continue using
>> fadump registered by previous kernel which may lead to invalid vmcore
>> generation. Hence this patch fixes this issue by un-registering fadump
>> in fadump_cleanup() which is called during kexec path so that new kernel
>> can register fadump with new valid values.
>
> I assume this series is for 4.17, but it might be good to get this one
> into the 4.16 fixes branch? Should it go to stable kernels?
You are right. Should I send it out as separate patch ?
>
>>
>> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>> ---
>> arch/powerpc/kernel/fadump.c | 3 +++
>> 1 file changed, 3 insertions(+)
>>
>> diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
>> index 8ceabef40d3d..07e8396d472b 100644
>> --- a/arch/powerpc/kernel/fadump.c
>> +++ b/arch/powerpc/kernel/fadump.c
>> @@ -1180,6 +1180,9 @@ void fadump_cleanup(void)
>> init_fadump_mem_struct(&fdm,
>> be64_to_cpu(fdm_active->cpu_state_data.destination_address));
>> fadump_invalidate_dump(&fdm);
>> + } else if (fw_dump.dump_registered) {
>> + /* Un-register Firmware-assisted dump if it was registered. */
>> + fadump_unregister_dump(&fdm);
>> }
>> }
>>
>>
>
^ permalink raw reply
* Re: [PATCH v5 1/4] powerpc/fadump: un-register fadump on kexec path.
From: Nicholas Piggin @ 2018-04-26 12:58 UTC (permalink / raw)
To: Mahesh J Salgaonkar
Cc: linuxppc-dev, Srikar Dronamraju, kernelfans, Aneesh Kumar K.V,
Ananth Narayan, Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152474292369.5697.4957552670306451723.stgit@jupiter.in.ibm.com>
On Thu, 26 Apr 2018 17:12:03 +0530
Mahesh J Salgaonkar <mahesh@linux.vnet.ibm.com> wrote:
> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
>
> otherwise the fadump registration in new kexec-ed kernel complains that
> fadump is already registered. This makes new kernel to continue using
> fadump registered by previous kernel which may lead to invalid vmcore
> generation. Hence this patch fixes this issue by un-registering fadump
> in fadump_cleanup() which is called during kexec path so that new kernel
> can register fadump with new valid values.
I assume this series is for 4.17, but it might be good to get this one
into the 4.16 fixes branch? Should it go to stable kernels?
>
> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
> ---
> arch/powerpc/kernel/fadump.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
> index 8ceabef40d3d..07e8396d472b 100644
> --- a/arch/powerpc/kernel/fadump.c
> +++ b/arch/powerpc/kernel/fadump.c
> @@ -1180,6 +1180,9 @@ void fadump_cleanup(void)
> init_fadump_mem_struct(&fdm,
> be64_to_cpu(fdm_active->cpu_state_data.destination_address));
> fadump_invalidate_dump(&fdm);
> + } else if (fw_dump.dump_registered) {
> + /* Un-register Firmware-assisted dump if it was registered. */
> + fadump_unregister_dump(&fdm);
> }
> }
>
>
^ permalink raw reply
* Re: [PATCH v2] powerpc: Fix smp_send_stop NMI IPI handling
From: Nicholas Piggin @ 2018-04-26 12:54 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, Abdul Haleem
In-Reply-To: <877eou5kfm.fsf@concordia.ellerman.id.au>
On Thu, 26 Apr 2018 20:30:37 +1000
Michael Ellerman <mpe@ellerman.id.au> wrote:
> Nicholas Piggin <npiggin@gmail.com> writes:
> > The NMI IPI handler for a receiving CPU increments nmi_ipi_busy_count
> > over the handler function call, which causes later smp_send_nmi_ipi()
> > callers to spin until the call is finished.
> >
> > The smp_send_stop function never returns, so the busy count is never
> > decremeted, which can cause the system to hang in some cases. For
> > example panic() will call smp_send_stop early on, then later in the
> > reboot path, pnv_restart will call smp_send_stop again, which hangs.
> >
> > Fix this by adding a special case to the smp_send_stop handler to
> > decrement the busy count, because it will never return.
> >
> > Fixes: 6bed3237624e3 ("powerpc: use NMI IPI for smp_send_stop")
> > Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
> > Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> > ---
> > Changes since v1:
> > - Reduce #ifdef spaghetti suggested by mpe
>
> Sorry I missed this.
>
> But then saw it in the patchwork listing, which is why I sent my version
> as v3. Which I also merged. Sorry for the confusion.
>
> I'm pretty sure my version is equivalent to this, except for the way the
> #ifdefs are arranged.
>
> The end result of this is nicer than my version, so I'd take a cleanup
> patch to get us to this final state.
That's okay. We end up needing to fix the !NMI case as well, with
"powerpc: Fix deadlock with multiple calls to smp_send_stop", so I
can rediff that and send it up.
Thanks,
Nick
^ permalink raw reply
* [PATCH] powerpc/kvm/booke: fix altivec related build break
From: laurentiu.tudor @ 2018-04-26 12:33 UTC (permalink / raw)
To: kvm-ppc; +Cc: agraf, linuxppc-dev, Laurentiu Tudor
From: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Add missing "altivec unavailable" interrupt injection helper
thus fixing the linker error below:
arch/powerpc/kvm/emulate_loadstore.o: In function `kvmppc_check_altivec_disabled':
arch/powerpc/kvm/emulate_loadstore.c: undefined reference to `.kvmppc_core_queue_vec_unavail'
Fixes: 09f984961c137c4b ("KVM: PPC: Book3S: Add MMIO emulation for VMX instructions")
Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
---
arch/powerpc/kvm/booke.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 6038e2e7aee0..876d4f294fdd 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -305,6 +305,13 @@ void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu)
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_FP_UNAVAIL);
}
+#ifdef CONFIG_ALTIVEC
+void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu)
+{
+ kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ALTIVEC_UNAVAIL);
+}
+#endif
+
void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu)
{
kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DECREMENTER);
--
2.17.0
^ permalink raw reply related
* [PATCH v5 4/4] powerpc/fadump: Do not allow hot-remove memory from fadump reserved area.
From: Mahesh J Salgaonkar @ 2018-04-26 11:42 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Hari Bathini,
Nathan Fontenot, Anshuman Khandual, Ananth Narayan
In-Reply-To: <152474278043.5697.2553982145593952228.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
For fadump to work successfully there should not be any holes in reserved
memory ranges where kernel has asked firmware to move the content of old
kernel memory in event of crash. Now that fadump uses CMA for reserved
area, this memory area is now not protected from hot-remove operations
unless it is cma allocated. Hence, fadump service can fail to re-register
after the hot-remove operation, if hot-removed memory belongs to fadump
reserved region. To avoid this make sure that memory from fadump reserved
area is not hot-removable if fadump is registered.
However, if user still wants to remove that memory, he can do so by
manually stopping fadump service before hot-remove operation.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/fadump.h | 2 +-
arch/powerpc/kernel/fadump.c | 10 ++++++++--
arch/powerpc/platforms/pseries/hotplug-memory.c | 7 +++++--
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index 0bf0d3b37c6e..1771134b514d 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -207,7 +207,7 @@ struct fad_crash_memory_ranges {
unsigned long long size;
};
-extern int is_fadump_boot_memory_area(u64 addr, ulong size);
+extern int is_fadump_memory_area(u64 addr, ulong size);
extern int early_init_dt_scan_fw_dump(unsigned long node,
const char *uname, int depth, void *data);
extern int fadump_reserve_mem(void);
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 16dec2e8bc88..91e10cb82613 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -173,13 +173,19 @@ int __init early_init_dt_scan_fw_dump(unsigned long node,
/*
* If fadump is registered, check if the memory provided
- * falls within boot memory area.
+ * falls within boot memory area and reserved memory area.
*/
-int is_fadump_boot_memory_area(u64 addr, ulong size)
+int is_fadump_memory_area(u64 addr, ulong size)
{
+ u64 d_start = fw_dump.reserve_dump_area_start;
+ u64 d_end = d_start + fw_dump.reserve_dump_area_size;
+
if (!fw_dump.dump_registered)
return 0;
+ if (((addr + size) > d_start) && (addr <= d_end))
+ return 1;
+
return (addr + size) > RMA_START && addr <= fw_dump.boot_memory_size;
}
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index c1578f54c626..e4c658cda3a7 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -389,8 +389,11 @@ static bool lmb_is_removable(struct drmem_lmb *lmb)
phys_addr = lmb->base_addr;
#ifdef CONFIG_FA_DUMP
- /* Don't hot-remove memory that falls in fadump boot memory area */
- if (is_fadump_boot_memory_area(phys_addr, block_sz))
+ /*
+ * Don't hot-remove memory that falls in fadump boot memory area
+ * and memory that is reserved for capturing old kernel memory.
+ */
+ if (is_fadump_memory_area(phys_addr, block_sz))
return false;
#endif
^ permalink raw reply related
* [PATCH v5 3/4] powerpc/fadump: throw proper error message on fadump registration failure.
From: Mahesh J Salgaonkar @ 2018-04-26 11:42 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Hari Bathini,
Nathan Fontenot, Anshuman Khandual, Ananth Narayan
In-Reply-To: <152474278043.5697.2553982145593952228.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
fadump fails to register when there are holes in reserved memory area.
This can happen if user has hot-removed a memory that falls in the fadump
reserved memory area. Throw a meaningful error message to the user in
such case.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/kernel/fadump.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index d44d89c8967f..16dec2e8bc88 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -227,6 +227,36 @@ static int is_boot_memory_area_contiguous(void)
return ret;
}
+/*
+ * Returns 1, if there are no holes in reserved memory area,
+ * 0 otherwise.
+ */
+static int is_reserved_memory_area_contiguous(void)
+{
+ struct memblock_region *reg;
+ unsigned long start, end;
+ unsigned long d_start = fw_dump.reserve_dump_area_start;
+ unsigned long d_end = d_start + fw_dump.reserve_dump_area_size;
+ int ret = 0;
+
+ for_each_memblock(memory, reg) {
+ start = max(d_start, (unsigned long)reg->base);
+ end = min(d_end, (unsigned long)(reg->base + reg->size));
+ if (d_start < end) {
+ /* Memory hole from d_start to start */
+ if (start > d_start)
+ break;
+
+ if (end == d_end) {
+ ret = 1;
+ break;
+ }
+ d_start = end + 1;
+ }
+ }
+ return ret;
+}
+
/* Print firmware assisted dump configurations for debugging purpose. */
static void fadump_show_config(void)
{
@@ -589,6 +619,9 @@ static int register_fw_dump(struct fadump_mem_struct *fdm)
if (!is_boot_memory_area_contiguous())
pr_err("Can't have holes in boot memory area while "
"registering fadump\n");
+ else if (!is_reserved_memory_area_contiguous())
+ pr_err("Can't have holes in reserved memory area while"
+ " registering fadump\n");
printk(KERN_ERR "Failed to register firmware-assisted kernel"
" dump. Parameter Error(%d).\n", rc);
^ permalink raw reply related
* [PATCH v5 2/4] powerpc/fadump: Reservationless firmware assisted dump
From: Mahesh J Salgaonkar @ 2018-04-26 11:42 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Hari Bathini,
Nathan Fontenot, Anshuman Khandual, Ananth Narayan
In-Reply-To: <152474278043.5697.2553982145593952228.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
One of the primary issues with Firmware Assisted Dump (fadump) on Power
is that it needs a large amount of memory to be reserved. On large
systems with TeraBytes of memory, this reservation can be quite
significant.
In some cases, fadump fails if the memory reserved is insufficient, or
if the reserved memory was DLPAR hot-removed.
In the normal case, post reboot, the preserved memory is filtered to
extract only relevant areas of interest using the makedumpfile tool.
While the tool provides flexibility to determine what needs to be part
of the dump and what memory to filter out, all supported distributions
default this to "Capture only kernel data and nothing else".
We take advantage of this default and the Linux kernel's Contiguous
Memory Allocator (CMA) to fundamentally change the memory reservation
model for fadump.
Instead of setting aside a significant chunk of memory nobody can use,
this patch uses CMA instead, to reserve a significant chunk of memory
that the kernel is prevented from using (due to MIGRATE_CMA), but
applications are free to use it. With this fadump will still be able
to capture all of the kernel memory and most of the user space memory
except the user pages that were present in CMA region.
Essentially, on a P9 LPAR with 2 cores, 8GB RAM and current upstream:
[root@zzxx-yy10 ~]# free -m
total used free shared buff/cache available
Mem: 7557 193 6822 12 541 6725
Swap: 4095 0 4095
With this patch:
[root@zzxx-yy10 ~]# free -m
total used free shared buff/cache available
Mem: 8133 194 7464 12 475 7338
Swap: 4095 0 4095
Changes made here are completely transparent to how fadump has
traditionally worked.
Thanks to Aneesh Kumar and Anshuman Khandual for helping us understand
CMA and its usage.
TODO:
- Handle case where CMA reservation spans nodes.
Signed-off-by: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
---
Documentation/powerpc/firmware-assisted-dump.txt | 10 ++-
arch/powerpc/include/asm/fadump.h | 4 +
arch/powerpc/kernel/fadump.c | 84 +++++++++++++++++++---
3 files changed, 87 insertions(+), 11 deletions(-)
diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt
index bdd344aa18d9..f2823a1e3f9d 100644
--- a/Documentation/powerpc/firmware-assisted-dump.txt
+++ b/Documentation/powerpc/firmware-assisted-dump.txt
@@ -113,7 +113,15 @@ header, is usually reserved at an offset greater than boot memory
size (see Fig. 1). This area is *not* released: this region will
be kept permanently reserved, so that it can act as a receptacle
for a copy of the boot memory content in addition to CPU state
-and HPTE region, in the case a crash does occur.
+and HPTE region, in the case a crash does occur. Since this reserved
+memory area is used only after the system crash, there is no point in
+blocking this significant chunk of memory from production kernel.
+Hence, the implementation uses the Linux kernel's Contiguous Memory
+Allocator (CMA) for memory reservation if CMA is configured for kernel.
+With CMA reservation this memory will be available for applications to
+use it, while kernel is prevented from using it. With this fadump will
+still be able to capture all of the kernel memory and most of the user
+space memory except the user pages that were present in CMA region.
o Memory Reservation during first kernel
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index 5a23010af600..0bf0d3b37c6e 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -48,6 +48,10 @@
#define memblock_num_regions(memblock_type) (memblock.memblock_type.cnt)
+/* Alignement per CMA requirement. */
+#define FADUMP_CMA_ALIGNMENT (PAGE_SIZE << \
+ max_t(unsigned long, MAX_ORDER - 1, pageblock_order))
+
/* Firmware provided dump sections */
#define FADUMP_CPU_STATE_DATA 0x0001
#define FADUMP_HPTE_REGION 0x0002
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 07e8396d472b..d44d89c8967f 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -34,6 +34,7 @@
#include <linux/crash_dump.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
+#include <linux/cma.h>
#include <asm/debugfs.h>
#include <asm/page.h>
@@ -45,11 +46,68 @@
static struct fw_dump fw_dump;
static struct fadump_mem_struct fdm;
static const struct fadump_mem_struct *fdm_active;
+#ifdef CONFIG_CMA
+static struct cma *fadump_cma;
+#endif
static DEFINE_MUTEX(fadump_mutex);
struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES];
int crash_mem_ranges;
+#ifdef CONFIG_CMA
+/*
+ * fadump_cma_init() - Initializ CMA area from a fadump reserved memory
+ *
+ * This function initializes CMA area from fadump reserved memory.
+ * The total size of fadump reserved memory covers for boot memory size
+ * + cpu data size + hpte size and metadata.
+ * Initialize only the area equivalent to boot memory size for CMA use.
+ * The reamining portion of fadump reserved memory will be not given
+ * to CMA and pages for thoes will stay reserved. boot memory size is
+ * aligned per CMA requirement to satisy cma_init_reserved_mem() call.
+ * But for some reason even if it fails we still have the memory reservation
+ * with us and we can still continue doing fadump.
+ */
+int __init fadump_cma_init(void)
+{
+ unsigned long long base, size;
+ int rc;
+
+ if (!fw_dump.fadump_enabled)
+ return 0;
+
+ base = fw_dump.reserve_dump_area_start;
+ size = fw_dump.boot_memory_size;
+
+ if (!size)
+ return 0;
+
+ rc = cma_init_reserved_mem(base, size, 0, "fadump_cma", &fadump_cma);
+ if (rc) {
+ pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc);
+ /*
+ * Though the CMA init has failed we still have memory
+ * reservation with us. The reserved memory will be
+ * blocked from production system usage. Hence return 1,
+ * so that we can continue with fadump.
+ */
+ return 1;
+ }
+
+ /*
+ * So we now have successfully initialized cma area for fadump.
+ */
+ pr_info("Initialized 0x%lx bytes cma area at %ldMB from 0x%lx "
+ "bytes of memory reserved for firmware-assisted dump\n",
+ cma_get_size(fadump_cma),
+ (unsigned long)cma_get_base(fadump_cma) >> 20,
+ fw_dump.reserve_dump_area_size);
+ return 1;
+}
+#else
+static int __init fadump_cma_init(void) { return 1; }
+#endif /* CONFIG_CMA */
+
/* Scan the Firmware Assisted dump configuration details. */
int __init early_init_dt_scan_fw_dump(unsigned long node,
const char *uname, int depth, void *data)
@@ -375,8 +433,13 @@ int __init fadump_reserve_mem(void)
*/
if (fdm_active)
fw_dump.boot_memory_size = be64_to_cpu(fdm_active->rmr_region.source_len);
- else
+ else {
fw_dump.boot_memory_size = fadump_calculate_reserve_size();
+#ifdef CONFIG_CMA
+ fw_dump.boot_memory_size = ALIGN(fw_dump.boot_memory_size,
+ FADUMP_CMA_ALIGNMENT);
+#endif
+ }
/*
* Calculate the memory boundary.
@@ -423,8 +486,9 @@ int __init fadump_reserve_mem(void)
fw_dump.fadumphdr_addr =
be64_to_cpu(fdm_active->rmr_region.destination_address) +
be64_to_cpu(fdm_active->rmr_region.source_len);
- pr_debug("fadumphdr_addr = %p\n",
- (void *) fw_dump.fadumphdr_addr);
+ pr_debug("fadumphdr_addr = %pa\n", &fw_dump.fadumphdr_addr);
+ fw_dump.reserve_dump_area_start = base;
+ fw_dump.reserve_dump_area_size = size;
} else {
size = get_fadump_area_size();
@@ -452,10 +516,11 @@ int __init fadump_reserve_mem(void)
(unsigned long)(size >> 20),
(unsigned long)(base >> 20),
(unsigned long)(memblock_phys_mem_size() >> 20));
- }
- fw_dump.reserve_dump_area_start = base;
- fw_dump.reserve_dump_area_size = size;
+ fw_dump.reserve_dump_area_start = base;
+ fw_dump.reserve_dump_area_size = size;
+ return fadump_cma_init();
+ }
return 1;
}
@@ -1146,7 +1211,7 @@ static int fadump_unregister_dump(struct fadump_mem_struct *fdm)
return 0;
}
-static int fadump_invalidate_dump(struct fadump_mem_struct *fdm)
+static int fadump_invalidate_dump(const struct fadump_mem_struct *fdm)
{
int rc = 0;
unsigned int wait_time;
@@ -1177,9 +1242,8 @@ void fadump_cleanup(void)
{
/* Invalidate the registration only if dump is active. */
if (fw_dump.dump_active) {
- init_fadump_mem_struct(&fdm,
- be64_to_cpu(fdm_active->cpu_state_data.destination_address));
- fadump_invalidate_dump(&fdm);
+ /* pass the same memory dump structure provided by platform */
+ fadump_invalidate_dump(fdm_active);
} else if (fw_dump.dump_registered) {
/* Un-register Firmware-assisted dump if it was registered. */
fadump_unregister_dump(&fdm);
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox