* Re: [PATCH v3 04/17] y2038: s390: Remove unneeded ipc uapi header files
From: Heiko Carstens @ 2018-04-20 7:54 UTC (permalink / raw)
To: Arnd Bergmann
Cc: y2038, linux-kernel, linux-api, linux-arch, libc-alpha, tglx,
deepa.kernel, viro, ebiederm, albert.aribaud, linux-s390,
schwidefsky, x86, catalin.marinas, will.deacon, linux-mips,
jhogan, ralf, linuxppc-dev, sparclinux
In-Reply-To: <20180419143737.606138-5-arnd@arndb.de>
On Thu, Apr 19, 2018 at 04:37:24PM +0200, Arnd Bergmann wrote:
> The s390 msgbuf/sembuf/shmbuf header files are all identical to the
> version from asm-generic.
>
> This patch removes the files and replaces them with 'generic-y'
> statements, to avoid having to modify each copy when we extend sysvipc
> to deal with 64-bit time_t in 32-bit user space.
>
> Note that unlike alpha and ia64, the ipcbuf.h header file is slightly
> different here, so I'm leaving the private copy.
>
> To deal with 32-bit compat tasks, we also have to adapt the definitions
> of compat_{shm,sem,msg}id_ds to match the changes to the respective
> asm-generic files.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> arch/s390/include/asm/compat.h | 32 ++++++++++++------------
> arch/s390/include/uapi/asm/Kbuild | 3 +++
> arch/s390/include/uapi/asm/msgbuf.h | 38 ----------------------------
> arch/s390/include/uapi/asm/sembuf.h | 30 -----------------------
> arch/s390/include/uapi/asm/shmbuf.h | 49 -------------------------------------
> 5 files changed, 19 insertions(+), 133 deletions(-)
> delete mode 100644 arch/s390/include/uapi/asm/msgbuf.h
> delete mode 100644 arch/s390/include/uapi/asm/sembuf.h
> delete mode 100644 arch/s390/include/uapi/asm/shmbuf.h
FWIW,
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com>
^ permalink raw reply
* [PATCH 4/4] powerpc: Allow LD_DEAD_CODE_DATA_ELIMINATION to be selected
From: Nicholas Piggin @ 2018-04-20 7:34 UTC (permalink / raw)
To: linuxppc-dev
Cc: Nicholas Piggin, linux-arch, linux-kbuild, Christophe Leroy,
Nicolas Pitre
In-Reply-To: <20180420073414.23169-1-npiggin@gmail.com>
This requires further changes to linker script to KEEP some tables
and wildcard compiler generated sections into the right place. This
includes pp32 modifications from Christophe Leroy.
When compiling powernv_defconfig with this option:
text data bss dec filename
11827621 4810490 1341080 17979191 vmlinux
11752437 4598858 1338776 17690071 vmlinux.dcde
Resulting kernel is almost 400kB smaller (and still boots).
[ppc32 numbers here]
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/vmlinux.lds.S | 22 +++++++++++-----------
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c32a181a7cbb..ee6dbe2efc8b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -205,6 +205,7 @@ config PPC
select HAVE_KPROBES
select HAVE_KPROBES_ON_FTRACE
select HAVE_KRETPROBES
+ select HAVE_LD_DEAD_CODE_DATA_ELIMINATION
select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
select HAVE_MEMBLOCK
select HAVE_MEMBLOCK_NODE_MAP
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index c8af90ff49f0..89381dc959ce 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -89,7 +89,7 @@ SECTIONS
*/
.text BLOCK(0) : AT(ADDR(.text) - LOAD_OFFSET) {
#ifdef CONFIG_LD_HEAD_STUB_CATCH
- *(.linker_stub_catch);
+ KEEP(*(.linker_stub_catch));
. = . ;
#endif
@@ -98,7 +98,7 @@ SECTIONS
ALIGN_FUNCTION();
#endif
/* careful! __ftr_alt_* sections need to be close to .text */
- *(.text.hot .text .text.fixup .text.unlikely .fixup __ftr_alt_* .ref.text);
+ *(.text.hot .text .text.[0-9a-zA-Z_]* .text.fixup .text.unlikely .fixup __ftr_alt_* .ref.text);
SCHED_TEXT
CPUIDLE_TEXT
LOCK_TEXT
@@ -170,10 +170,10 @@ SECTIONS
.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
INIT_DATA
__vtop_table_begin = .;
- *(.vtop_fixup);
+ KEEP(*(.vtop_fixup));
__vtop_table_end = .;
__ptov_table_begin = .;
- *(.ptov_fixup);
+ KEEP(*(.ptov_fixup));
__ptov_table_end = .;
}
@@ -194,26 +194,26 @@ SECTIONS
. = ALIGN(8);
__ftr_fixup : AT(ADDR(__ftr_fixup) - LOAD_OFFSET) {
__start___ftr_fixup = .;
- *(__ftr_fixup)
+ KEEP(*(__ftr_fixup))
__stop___ftr_fixup = .;
}
. = ALIGN(8);
__mmu_ftr_fixup : AT(ADDR(__mmu_ftr_fixup) - LOAD_OFFSET) {
__start___mmu_ftr_fixup = .;
- *(__mmu_ftr_fixup)
+ KEEP(*(__mmu_ftr_fixup))
__stop___mmu_ftr_fixup = .;
}
. = ALIGN(8);
__lwsync_fixup : AT(ADDR(__lwsync_fixup) - LOAD_OFFSET) {
__start___lwsync_fixup = .;
- *(__lwsync_fixup)
+ KEEP(*(__lwsync_fixup))
__stop___lwsync_fixup = .;
}
#ifdef CONFIG_PPC64
. = ALIGN(8);
__fw_ftr_fixup : AT(ADDR(__fw_ftr_fixup) - LOAD_OFFSET) {
__start___fw_ftr_fixup = .;
- *(__fw_ftr_fixup)
+ KEEP(*(__fw_ftr_fixup))
__stop___fw_ftr_fixup = .;
}
#endif
@@ -226,7 +226,7 @@ SECTIONS
. = ALIGN(8);
.machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) {
__machine_desc_start = . ;
- *(.machine.desc)
+ KEEP(*(.machine.desc))
__machine_desc_end = . ;
}
#ifdef CONFIG_RELOCATABLE
@@ -274,7 +274,7 @@ SECTIONS
.data : AT(ADDR(.data) - LOAD_OFFSET) {
DATA_DATA
*(.data.rel*)
- *(.sdata)
+ *(SDATA_MAIN)
*(.sdata2)
*(.got.plt) *(.got)
*(.plt)
@@ -289,7 +289,7 @@ SECTIONS
.opd : AT(ADDR(.opd) - LOAD_OFFSET) {
__start_opd = .;
- *(.opd)
+ KEEP(*(.opd))
__end_opd = .;
}
--
2.17.0
^ permalink raw reply related
* [PATCH 3/4] kbuild: Allow LD_DEAD_CODE_DATA_ELIMINATION to be selectable if enabled
From: Nicholas Piggin @ 2018-04-20 7:34 UTC (permalink / raw)
To: linuxppc-dev
Cc: Nicholas Piggin, linux-arch, linux-kbuild, Christophe Leroy,
Nicolas Pitre
In-Reply-To: <20180420073414.23169-1-npiggin@gmail.com>
Architectures that are capable can select
HAVE_LD_DEAD_CODE_DATA_ELIMINATION to enable selection of that
option (as an EXPERT kernel option).
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/Kconfig | 15 ---------------
init/Kconfig | 27 +++++++++++++++++++++++++++
2 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 8e0d665c8d53..3234b73d4626 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -596,21 +596,6 @@ config CC_STACKPROTECTOR_AUTO
endchoice
-config LD_DEAD_CODE_DATA_ELIMINATION
- bool
- help
- Select this if the architecture wants to do dead code and
- data elimination with the linker by compiling with
- -ffunction-sections -fdata-sections and linking with
- --gc-sections.
-
- This requires that the arch annotates or otherwise protects
- its external entry points from being discarded. Linker scripts
- must also merge .text.*, .data.*, and .bss.* correctly into
- output sections. Care must be taken not to pull in unrelated
- sections (e.g., '.text.init'). Typically '.' in section names
- is used to distinguish them from label names / C identifiers.
-
config HAVE_ARCH_WITHIN_STACK_FRAMES
bool
help
diff --git a/init/Kconfig b/init/Kconfig
index f013afc74b11..1706d963766b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1038,6 +1038,33 @@ config CC_OPTIMIZE_FOR_SIZE
endchoice
+config HAVE_LD_DEAD_CODE_DATA_ELIMINATION
+ bool
+ help
+ This requires that the arch annotates or otherwise protects
+ its external entry points from being discarded. Linker scripts
+ must also merge .text.*, .data.*, and .bss.* correctly into
+ output sections. Care must be taken not to pull in unrelated
+ sections (e.g., '.text.init'). Typically '.' in section names
+ is used to distinguish them from label names / C identifiers.
+
+config LD_DEAD_CODE_DATA_ELIMINATION
+ bool "Dead code and data elimination (EXPERIMENTAL)"
+ depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
+ depends on EXPERT
+ help
+ Select this if the architecture wants to do dead code and
+ data elimination with the linker by compiling with
+ -ffunction-sections -fdata-sections, and linking with
+ --gc-sections.
+
+ This can reduce on disk and in-memory size of the kernel
+ code and static data, particularly for small configs and
+ on small systems. This has the possibility of introducing
+ silently broken kernel if the required annotations are not
+ present. This option is not well tested yet, so use at your
+ own risk.
+
config SYSCTL
bool
--
2.17.0
^ permalink raw reply related
* [PATCH 2/4] kbuild: LD_DEAD_CODE_DATA_ELIMINATION no -ffunction-sections/-fdata-sections for module build
From: Nicholas Piggin @ 2018-04-20 7:34 UTC (permalink / raw)
To: linuxppc-dev
Cc: Nicholas Piggin, linux-arch, linux-kbuild, Christophe Leroy,
Nicolas Pitre
In-Reply-To: <20180420073414.23169-1-npiggin@gmail.com>
Modules do not tend to cope with -ffunction-sections, even though they
do not link with -gc-sections. It may be possible for unused symbols to
be trimmed from modules, but in general that would take much more work
in architecture module linker scripts.
For now, enable these only for kernel build.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index e811e0c509c5..2ed651403bb4 100644
--- a/Makefile
+++ b/Makefile
@@ -799,8 +799,8 @@ KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
endif
ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
-KBUILD_CFLAGS += $(call cc-option,-ffunction-sections,)
-KBUILD_CFLAGS += $(call cc-option,-fdata-sections,)
+KBUILD_CFLAGS_KERNEL += $(call cc-option,-ffunction-sections,)
+KBUILD_CFLAGS_KERNEL += $(call cc-option,-fdata-sections,)
endif
# arch Makefile may override CC so keep this after arch Makefile is included
--
2.17.0
^ permalink raw reply related
* [PATCH 1/4] kbuild: Fix asm-generic/vmlinux.lds.h for LD_DEAD_CODE_DATA_ELIMINATION
From: Nicholas Piggin @ 2018-04-20 7:34 UTC (permalink / raw)
To: linuxppc-dev
Cc: Nicholas Piggin, linux-arch, linux-kbuild, Christophe Leroy,
Nicolas Pitre
In-Reply-To: <20180420073414.23169-1-npiggin@gmail.com>
KEEP more tables, and add the function/data section wildcard to more
section selections.
This is a little ad-hoc at the moment, but kernel code should be moved
to consistently use .text..x (note: double dots) for explicit sections
and all references to it in the linker script can be made with
TEXT_MAIN, and similarly for other sections.
For now, let's see if major architectures move to enabling this option
then we can do some refactoring passes. Otherwise if it remains unused
or superseded by LTO, this may not be required.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
include/asm-generic/vmlinux.lds.h | 49 ++++++++++++++++++-------------
1 file changed, 29 insertions(+), 20 deletions(-)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 278841c75b97..23f5f8d22f56 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -64,15 +64,24 @@
* generates .data.identifier sections, which need to be pulled in with
* .data. We don't want to pull in .data..other sections, which Linux
* has defined. Same for text and bss.
+ *
+ * RODATA_MAIN is not used because existing code already defines .rodata.x
+ * sections to be brought in with rodata.
*/
#ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
#define TEXT_MAIN .text .text.[0-9a-zA-Z_]*
#define DATA_MAIN .data .data.[0-9a-zA-Z_]*
+#define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]*
+#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]*
#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]*
+#define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]*
#else
#define TEXT_MAIN .text
#define DATA_MAIN .data
+#define SDATA_MAIN .sdata
+#define RODATA_MAIN .rodata
#define BSS_MAIN .bss
+#define SBSS_MAIN .sbss
#endif
/*
@@ -105,7 +114,7 @@
#ifdef CONFIG_FTRACE_MCOUNT_RECORD
#define MCOUNT_REC() . = ALIGN(8); \
VMLINUX_SYMBOL(__start_mcount_loc) = .; \
- *(__mcount_loc) \
+ KEEP(*(__mcount_loc)) \
VMLINUX_SYMBOL(__stop_mcount_loc) = .;
#else
#define MCOUNT_REC()
@@ -113,7 +122,7 @@
#ifdef CONFIG_TRACE_BRANCH_PROFILING
#define LIKELY_PROFILE() VMLINUX_SYMBOL(__start_annotated_branch_profile) = .; \
- *(_ftrace_annotated_branch) \
+ KEEP(*(_ftrace_annotated_branch)) \
VMLINUX_SYMBOL(__stop_annotated_branch_profile) = .;
#else
#define LIKELY_PROFILE()
@@ -121,7 +130,7 @@
#ifdef CONFIG_PROFILE_ALL_BRANCHES
#define BRANCH_PROFILE() VMLINUX_SYMBOL(__start_branch_profile) = .; \
- *(_ftrace_branch) \
+ KEEP(*(_ftrace_branch)) \
VMLINUX_SYMBOL(__stop_branch_profile) = .;
#else
#define BRANCH_PROFILE()
@@ -238,8 +247,8 @@
*(DATA_MAIN) \
*(.ref.data) \
*(.data..shared_aligned) /* percpu related */ \
- MEM_KEEP(init.data) \
- MEM_KEEP(exit.data) \
+ MEM_KEEP(init.data*) \
+ MEM_KEEP(exit.data*) \
*(.data.unlikely) \
VMLINUX_SYMBOL(__start_once) = .; \
*(.data.once) \
@@ -289,8 +298,8 @@
VMLINUX_SYMBOL(__start_init_task) = .; \
VMLINUX_SYMBOL(init_thread_union) = .; \
VMLINUX_SYMBOL(init_stack) = .; \
- *(.data..init_task) \
- *(.data..init_thread_info) \
+ KEEP(*(.data..init_task)) \
+ KEEP(*(.data..init_thread_info)) \
. = VMLINUX_SYMBOL(__start_init_task) + THREAD_SIZE; \
VMLINUX_SYMBOL(__end_init_task) = .;
@@ -487,8 +496,8 @@
*(.text.hot TEXT_MAIN .text.fixup .text.unlikely) \
*(.text..refcount) \
*(.ref.text) \
- MEM_KEEP(init.text) \
- MEM_KEEP(exit.text) \
+ MEM_KEEP(init.text*) \
+ MEM_KEEP(exit.text*) \
/* sched.text is aling to function alignment to secure we have same
@@ -538,7 +547,7 @@
VMLINUX_SYMBOL(__softirqentry_text_end) = .;
/* Section used for early init (in .S files) */
-#define HEAD_TEXT *(.head.text)
+#define HEAD_TEXT KEEP(*(.head.text))
#define HEAD_TEXT_SECTION \
.head.text : AT(ADDR(.head.text) - LOAD_OFFSET) { \
@@ -579,11 +588,11 @@
/* init and exit section handling */
#define INIT_DATA \
KEEP(*(SORT(___kentry+*))) \
- *(.init.data) \
- MEM_DISCARD(init.data) \
+ *(.init.data init.data.*) \
+ MEM_DISCARD(init.data*) \
KERNEL_CTORS() \
MCOUNT_REC() \
- *(.init.rodata) \
+ *(.init.rodata .init.rodata.*) \
FTRACE_EVENTS() \
TRACE_SYSCALLS() \
KPROBE_BLACKLIST() \
@@ -602,16 +611,16 @@
EARLYCON_TABLE()
#define INIT_TEXT \
- *(.init.text) \
+ *(.init.text .init.text.*) \
*(.text.startup) \
- MEM_DISCARD(init.text)
+ MEM_DISCARD(init.text*)
#define EXIT_DATA \
- *(.exit.data) \
+ *(.exit.data .exit.data.*) \
*(.fini_array) \
*(.dtors) \
- MEM_DISCARD(exit.data) \
- MEM_DISCARD(exit.rodata)
+ MEM_DISCARD(exit.data*) \
+ MEM_DISCARD(exit.rodata*)
#define EXIT_TEXT \
*(.exit.text) \
@@ -629,7 +638,7 @@
. = ALIGN(sbss_align); \
.sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { \
*(.dynsbss) \
- *(.sbss) \
+ *(SBSS_MAIN) \
*(.scommon) \
}
@@ -754,7 +763,7 @@
#define NOTES \
.notes : AT(ADDR(.notes) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_notes) = .; \
- *(.note.*) \
+ KEEP(*(.note.*)) \
VMLINUX_SYMBOL(__stop_notes) = .; \
}
--
2.17.0
^ permalink raw reply related
* [PATCH 0/4] LD_DEAD_CODE_DATA_ELIMINATION fixes and enabling for powerpc
From: Nicholas Piggin @ 2018-04-20 7:34 UTC (permalink / raw)
To: linuxppc-dev
Cc: Nicholas Piggin, linux-arch, linux-kbuild, Christophe Leroy,
Nicolas Pitre
A few people have been interested in this again. And I promised
if it remains dead code it should be removed, so I would like to
have another try.
I think I got snagged on the modules problem last time and did
not take the time to work it out, this time I just turned off the
compile options for modules (the linker option was never set anyway
so no loss).
This includes some linker script catches and ideas from others, I
didn't documnt them all, but thanks for looking.
I would be interested to help other archs get this working too, if
anybody needs some help.
Thanks,
Nick
Nicholas Piggin (4):
kbuild: Fix asm-generic/vmlinux.lds.h for
LD_DEAD_CODE_DATA_ELIMINATION
kbuild: LD_DEAD_CODE_DATA_ELIMINATION no
-ffunction-sections/-fdata-sections for module build
kbuild: Allow LD_DEAD_CODE_DATA_ELIMINATION to be selectable if
enabled
powerpc: Allow LD_DEAD_CODE_DATA_ELIMINATION to be selected
Makefile | 4 +--
arch/Kconfig | 15 ----------
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/vmlinux.lds.S | 22 +++++++-------
include/asm-generic/vmlinux.lds.h | 49 ++++++++++++++++++-------------
init/Kconfig | 27 +++++++++++++++++
6 files changed, 70 insertions(+), 48 deletions(-)
--
2.17.0
^ permalink raw reply
* Re: [PATCH v2 6/7] ocxl: Add an IOCTL so userspace knows what CPU features are available
From: Andrew Donnellan @ 2018-04-20 7:25 UTC (permalink / raw)
To: Alastair D'Silva, linuxppc-dev
Cc: linux-kernel, linux-doc, mikey, vaibhav, aneesh.kumar, malat,
felix, pombredanne, sukadev, npiggin, gregkh, arnd, fbarrat,
corbet, Alastair D'Silva
In-Reply-To: <20180418010810.30937-7-alastair@au1.ibm.com>
On 18/04/18 11:08, Alastair D'Silva wrote:
> From: Alastair D'Silva <alastair@d-silva.org>
>
> In order for a userspace AFU driver to call the Power9 specific
> OCXL_IOCTL_ENABLE_P9_WAIT, it needs to verify that it can actually
> make that call.
>
> Signed-off-by: Alastair D'Silva <alastair@d-silva.org>
Looks good to me
Acked-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com>
> ---
> Documentation/accelerators/ocxl.rst | 1 -
> drivers/misc/ocxl/file.c | 25 +++++++++++++++++++++++++
> include/uapi/misc/ocxl.h | 4 ++++
> 3 files changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/accelerators/ocxl.rst b/Documentation/accelerators/ocxl.rst
> index ddcc58d01cfb..7904adcc07fd 100644
> --- a/Documentation/accelerators/ocxl.rst
> +++ b/Documentation/accelerators/ocxl.rst
> @@ -157,7 +157,6 @@ OCXL_IOCTL_GET_METADATA:
> Obtains configuration information from the card, such at the size of
> MMIO areas, the AFU version, and the PASID for the current context.
>
> -
This is stray
--
Andrew Donnellan OzLabs, ADL Canberra
andrew.donnellan@au1.ibm.com IBM Australia Limited
^ permalink raw reply
* Re: [PATCH v5 06/10] powerpc64/ftrace: Disable ftrace during kvm entry/exit
From: Naveen N. Rao @ 2018-04-20 6:31 UTC (permalink / raw)
To: Steven Rostedt
Cc: linuxppc-dev, Michael Ellerman, Paul Mackerras,
Satheesh Rajendran
In-Reply-To: <20180419112216.173f8fd6@gandalf.local.home>
Steven Rostedt wrote:
> On Thu, 19 Apr 2018 12:34:05 +0530
> "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
>=20
>> 2. If we are a secondary thread in Power8, then we would be in nap due
>> to SMT being disabled. We are woken up by an IPI to enter the guest. In
>> this scenario, we enter the guest through kvm_start_guest(). We disable
>> ftrace at this point. In this scenario, ftrace would only get re-enabled
>> on the secondary thread when SMT is re-enabled (via start_secondary()).
>>=20
> trace_hardirqs_off();
>> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/=
book3s_hv_rmhandlers.S
>> index bd63fa8a08b5..2c3cbe0067b2 100644
>> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
>> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
>> @@ -342,6 +342,9 @@ kvm_start_guest:
>> =20
>> ld r2,PACATOC(r13)
>> =20
>=20
> You may want to add a comment here about where ftrace gets re-enabled.
Sure. That would be:
/*
* If this is the primary thread, ftrace will get re-enabled when we
* go back to the hypervisor in kvmppc_run_core(). For secondary threads=20
* on Power8, ftrace will get enabled when SMT is re-enabled through the=20
* start_secondary() cpu bringup path.
*/
- Naveen
=
^ permalink raw reply
* [PATCH v4 5/7] powerpc/fadump: Update documentation to reflect CMA reservation.
From: Mahesh J Salgaonkar @ 2018-04-20 5:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Ananth Narayan,
Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152420062000.31037.770773018944092449.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
Documentation/powerpc/firmware-assisted-dump.txt | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt
index 30b32f879219..2ab13270b050 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. 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.
The first kernel, during fadump registration, prepares ELF core header
that contains necessary information for the coredump of the 1st kernel
^ permalink raw reply related
* [PATCH v4 7/7] powerpc/fadump: Do not allow hot-remove memory from fadump reserved area.
From: Mahesh J Salgaonkar @ 2018-04-20 5:05 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Ananth Narayan,
Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152420062000.31037.770773018944092449.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. But this memory area is currently not
protected from hot-remove operations. 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 03d5140a6f0d..5c0a88821ae9 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -212,7 +212,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 4884ab796f4a..2fda1e4a6318 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -162,13 +162,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 v4 6/7] powerpc/fadump: throw proper error message on fadump registration failure.
From: Mahesh J Salgaonkar @ 2018-04-20 5:05 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Ananth Narayan,
Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152420062000.31037.770773018944092449.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 7f76924ab190..4884ab796f4a 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -216,6 +216,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)
{
@@ -634,6 +664,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 v4 4/7] powerpc/fadump: Reservationless firmware assisted dump
From: Mahesh J Salgaonkar @ 2018-04-20 5:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Ananth Narayan, Srikar Dronamraju, kernelfans,
Ananth N Mavinakayanahalli, Aneesh Kumar K.V, Hari Bathini,
Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152420062000.31037.770773018944092449.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>
---
arch/powerpc/kernel/fadump.c | 120 ++++++++++++++++++++++++++++++++++++------
1 file changed, 103 insertions(+), 17 deletions(-)
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 16b3e8c5cae0..7f76924ab190 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,57 @@
static struct fw_dump fw_dump;
static struct fadump_mem_struct fdm;
static const struct fadump_mem_struct *fdm_active;
+static struct cma *fadump_cma;
static DEFINE_MUTEX(fadump_mutex);
struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES];
int crash_mem_ranges;
+/*
+ * fadump_cma_reserve() - reserve area for fadump memory reservation
+ *
+ * This function reserves memory from early allocator. It should be
+ * called by arch specific code once the memblock allocator
+ * has been activated.
+ */
+int __init fadump_cma_reserve(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.reserve_dump_area_size;
+ pr_debug("Original reserve area base %ld, size %ld\n",
+ (unsigned long)base >> 20,
+ (unsigned long)size >> 20);
+ if (!size)
+ return 0;
+
+ rc = cma_declare_contiguous(base, size, 0, 0, 0, false,
+ "fadump_cma", &fadump_cma);
+ if (rc) {
+ printk(KERN_ERR "fadump: Failed to reserve cma area for "
+ "firmware-assisted dump, %d\n", rc);
+ fw_dump.reserve_dump_area_size = 0;
+ return 0;
+ }
+ /*
+ * So we now have cma area reserved for fadump. base may be different
+ * from what we requested.
+ */
+ fw_dump.reserve_dump_area_start = cma_get_base(fadump_cma);
+ fw_dump.reserve_dump_area_size = cma_get_size(fadump_cma);
+ printk("Reserved %ldMB cma area at %ldMB for firmware-assisted dump "
+ "(System RAM: %ldMB)\n",
+ cma_get_size(fadump_cma) >> 20,
+ (unsigned long)cma_get_base(fadump_cma) >> 20,
+ (unsigned long)(memblock_phys_mem_size() >> 20));
+ return 1;
+}
+
/* 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)
@@ -496,8 +543,9 @@ int __init fadump_reserve_mem(void)
pr_info("Number of kernel Dump sections: %d\n",
be16_to_cpu(fdm_active->header.dump_num_sections));
fw_dump.fadumphdr_addr = get_fadump_metadata_base(fdm_active);
- 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();
@@ -514,21 +562,10 @@ int __init fadump_reserve_mem(void)
!memblock_is_region_reserved(base, size))
break;
}
- if ((base > (memory_boundary - size)) ||
- memblock_reserve(base, size)) {
- pr_err("Failed to reserve memory\n");
- return 0;
- }
-
- pr_info("Reserved %ldMB of memory at %ldMB for firmware-"
- "assisted dump (System RAM: %ldMB)\n",
- (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;
+ return fadump_cma_reserve();
}
-
- fw_dump.reserve_dump_area_start = base;
- fw_dump.reserve_dump_area_size = size;
return 1;
}
@@ -1191,6 +1228,39 @@ static unsigned long init_fadump_header(unsigned long addr)
return addr;
}
+static unsigned long allocate_metadata_area(void)
+{
+ int nr_pages;
+ unsigned long size;
+ struct page *page = NULL;
+
+ /*
+ * Check if fadump cma region is activated.
+ * fadump_cma->count == 0 means cma activation has failed. This means
+ * that the fadump reserved memory now will not be visible/available
+ * for user applications to use. It will be as good as old fadump
+ * behaviour of blocking this memory chunk from production system
+ * use. CMA activation failure does not mean that fadump will not
+ * work. Will continue to setup fadump.
+ */
+ if (!fadump_cma || !cma_get_size(fadump_cma)) {
+ pr_warn("fadump cma region activation failed.\n");
+ return 0;
+ }
+
+ size = get_fadump_metadata_size();
+ nr_pages = ALIGN(size, PAGE_SIZE) >> PAGE_SHIFT;
+ pr_info("Fadump metadata size = %ld (nr_pages = %d)\n", size, nr_pages);
+
+ page = cma_alloc(fadump_cma, nr_pages, 0, GFP_KERNEL);
+ if (page) {
+ pr_debug("Allocated fadump metadata area at %ldMB (cma)\n",
+ (unsigned long)page_to_phys(page) >> 20);
+ return page_to_phys(page);
+ }
+ return 0;
+}
+
static int register_fadump(void)
{
unsigned long addr;
@@ -1643,8 +1713,24 @@ int __init setup_fadump(void)
fadump_invalidate_release_mem();
}
/* Initialize the kernel dump memory structure for FAD registration. */
- else if (fw_dump.reserve_dump_area_size)
+ else if (fw_dump.reserve_dump_area_size) {
+ /*
+ * By this time cma area has been activated. Allocate memory
+ * for metadata from fadump cma region. Since this is very
+ * early during boot we are guaranteed to get metadata cma
+ * allocation at address fw_dump.reserve_dump_area_start.
+ *
+ * During fadump registration, metadata region is used
+ * to setup fadump header and ELF core header. We don't want
+ * this region to be touched by anyone. Allocating metadata
+ * region memory from fadump cma will make sure that this
+ * region will not given to any user space application.
+ * However the rest of the fadump cma memory is still free
+ * to be used by user applications.
+ */
+ allocate_metadata_area();
init_fadump_mem_struct(&fdm, fw_dump.reserve_dump_area_start);
+ }
fadump_init_files();
return 1;
^ permalink raw reply related
* [PATCH v4 3/7] powerpc/fadump: un-register fadump on kexec path.
From: Mahesh J Salgaonkar @ 2018-04-20 5:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Ananth Narayan,
Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152420062000.31037.770773018944092449.stgit@jupiter.in.ibm.com>
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.
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 43bfa535d0ea..16b3e8c5cae0 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -1276,6 +1276,9 @@ void fadump_cleanup(void)
/* Invalidate the registration only if dump is active. */
if (fw_dump.dump_active) {
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
* [PATCH v4 2/7] powerpc/fadump: Update documentation to reflect the metadata region movement.
From: Mahesh J Salgaonkar @ 2018-04-20 5:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Ananth Narayan,
Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152420062000.31037.770773018944092449.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Metadata region that holds fadump header and ELF header is now placed at
the start of reserved memory area. Update the documentation accordingly
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
Documentation/powerpc/firmware-assisted-dump.txt | 33 ++++++++++++++--------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/Documentation/powerpc/firmware-assisted-dump.txt b/Documentation/powerpc/firmware-assisted-dump.txt
index bdd344aa18d9..30b32f879219 100644
--- a/Documentation/powerpc/firmware-assisted-dump.txt
+++ b/Documentation/powerpc/firmware-assisted-dump.txt
@@ -115,17 +115,26 @@ 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.
+The first kernel, during fadump registration, prepares ELF core header
+that contains necessary information for the coredump of the 1st kernel
+which includes its physical memory layout. This ELF header and some more
+additional data is stored in the area called metadata region at the start
+of the reserved memory area. The implementation maintains the compatibility
+between production/capture kernels irrespective of their kernel versions.
+Both combination older/newer and newer/older works fine.
+
o Memory Reservation during first kernel
Low memory Top of memory
0 boot memory size |
| | |<--Reserved dump area -->| |
V V | Permanent Reservation | V
- +-----------+----------/ /---+---+----+-----------+----+------+
- | | |CPU|HPTE| DUMP |ELF | |
- +-----------+----------/ /---+---+----+-----------+----+------+
- | ^
- | |
+ +-----------+----------/ /---+----+---+----+-----------+------+
+ | | |ELF |CPU|HPTE| DUMP | |
+ +-----------+---------/ /----+----+---+----+-----------+------+
+ | ^ ^
+ | | |
+ | metadata region |
\ /
-------------------------------------------
Boot memory content gets transferred to
@@ -137,14 +146,14 @@ and HPTE region, in the case a crash does occur.
Low memory Top of memory
0 boot memory size |
- | |<------------- Reserved dump area ----------- -->|
+ | |<------------- Reserved dump area -------------->|
V V V
- +-----------+----------/ /---+---+----+-----------+----+------+
- | | |CPU|HPTE| DUMP |ELF | |
- +-----------+----------/ /---+---+----+-----------+----+------+
- | |
- V V
- Used by second /proc/vmcore
+ +-----------+----------/ /---+----+----+---------------+------+
+ | | |ELF |CPU|HPTE| DUMP | |
+ +-----------+----------/ /---+----+----+---------------+------+
+ | |
+ V V
+ Used by second /proc/vmcore
kernel to boot
Fig. 2
^ permalink raw reply related
* [PATCH v4 1/7] powerpc/fadump: Move the metadata region to start of the reserved area.
From: Mahesh J Salgaonkar @ 2018-04-20 5:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Ananth Narayan,
Hari Bathini, Nathan Fontenot, Anshuman Khandual
In-Reply-To: <152420062000.31037.770773018944092449.stgit@jupiter.in.ibm.com>
From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
Currently the metadata region that holds crash info structure and ELF core
header is placed towards the end of reserved memory area. This patch places
it at the beginning of the reserved memory area. It also introduces
additional dump section called metadata section to communicate location
of metadata region to 2nd kernel. This patch also maintains the
compatibility between production/capture kernels irrespective of their
kernel versions. Both combination older/newer and newer/older works fine.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
arch/powerpc/include/asm/fadump.h | 9 ++
arch/powerpc/kernel/fadump.c | 177 ++++++++++++++++++++++++++++++++-----
2 files changed, 160 insertions(+), 26 deletions(-)
diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h
index 5a23010af600..03d5140a6f0d 100644
--- a/arch/powerpc/include/asm/fadump.h
+++ b/arch/powerpc/include/asm/fadump.h
@@ -53,6 +53,11 @@
#define FADUMP_HPTE_REGION 0x0002
#define FADUMP_REAL_MODE_REGION 0x0011
+/* User define dump sections.
+ * Per PAPR: 0x0100 - 0xFFFF OS defined source types
+ */
+#define FADUMP_METADATA_REGION 0x0100
+
/* Dump request flag */
#define FADUMP_REQUEST_FLAG 0x00000001
@@ -61,6 +66,9 @@
#define FADUMP_UNREGISTER 2
#define FADUMP_INVALIDATE 3
+/* Number of dump sections requested by kernel */
+#define FADUMP_NUM_SECTIONS 4
+
/* Dump status flag */
#define FADUMP_ERROR_FLAG 0x2000
@@ -119,6 +127,7 @@ struct fadump_mem_struct {
struct fadump_section cpu_state_data;
struct fadump_section hpte_region;
struct fadump_section rmr_region;
+ struct fadump_section metadata_region;
};
/* Firmware-assisted dump configuration details. */
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 8ceabef40d3d..43bfa535d0ea 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -188,17 +188,40 @@ static void fadump_show_config(void)
pr_debug("Boot memory size : %lx\n", fw_dump.boot_memory_size);
}
+static unsigned long get_fadump_metadata_size(void)
+{
+ unsigned long size = 0;
+
+ size += sizeof(struct fadump_crash_info_header);
+ size += sizeof(struct elfhdr); /* ELF core header.*/
+ size += sizeof(struct elf_phdr); /* place holder for cpu notes */
+ /* Program headers for crash memory regions. */
+ size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 2);
+
+ size = PAGE_ALIGN(size);
+ pr_debug("fadump Metadata size is %ld\n", size);
+ return size;
+}
+
static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
unsigned long addr)
{
+ uint16_t num_sections = 0;
+ unsigned long metadata_base = 0;
+ unsigned long metadata_size = 0;
+
if (!fdm)
return 0;
+ /* Skip the fadump metadata area. */
+ metadata_base = addr;
+ metadata_size = get_fadump_metadata_size();
+ addr += metadata_size;
+
memset(fdm, 0, sizeof(struct fadump_mem_struct));
addr = addr & PAGE_MASK;
fdm->header.dump_format_version = cpu_to_be32(0x00000001);
- fdm->header.dump_num_sections = cpu_to_be16(3);
fdm->header.dump_status_flag = 0;
fdm->header.offset_first_dump_section =
cpu_to_be32((u32)offsetof(struct fadump_mem_struct, cpu_state_data));
@@ -222,6 +245,7 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
fdm->cpu_state_data.source_address = 0;
fdm->cpu_state_data.source_len = cpu_to_be64(fw_dump.cpu_state_data_size);
fdm->cpu_state_data.destination_address = cpu_to_be64(addr);
+ num_sections++;
addr += fw_dump.cpu_state_data_size;
/* hpte region section */
@@ -230,6 +254,7 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
fdm->hpte_region.source_address = 0;
fdm->hpte_region.source_len = cpu_to_be64(fw_dump.hpte_region_size);
fdm->hpte_region.destination_address = cpu_to_be64(addr);
+ num_sections++;
addr += fw_dump.hpte_region_size;
/* RMA region section */
@@ -238,8 +263,27 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
fdm->rmr_region.source_address = cpu_to_be64(RMA_START);
fdm->rmr_region.source_len = cpu_to_be64(fw_dump.boot_memory_size);
fdm->rmr_region.destination_address = cpu_to_be64(addr);
+ num_sections++;
addr += fw_dump.boot_memory_size;
+ /*
+ * fadump metadata section.
+ * This section will help 2nd kernel to locate the metadata base
+ * looking at source_address. This entry will also copy the metadata
+ * content after the RMR region dump data, so that old kernels that
+ * does not support this section can still find the metadata to
+ * process fadump.
+ */
+ fdm->metadata_region.request_flag = cpu_to_be32(FADUMP_REQUEST_FLAG);
+ fdm->metadata_region.source_data_type =
+ cpu_to_be16(FADUMP_METADATA_REGION);
+ fdm->metadata_region.source_address = cpu_to_be64(metadata_base);
+ fdm->metadata_region.source_len = cpu_to_be64(metadata_size);
+ fdm->metadata_region.destination_address = cpu_to_be64(addr);
+ num_sections++;
+
+ fdm->header.dump_num_sections = cpu_to_be16(num_sections);
+ BUILD_BUG_ON(num_sections != FADUMP_NUM_SECTIONS);
return addr;
}
@@ -325,12 +369,12 @@ static unsigned long get_fadump_area_size(void)
size += fw_dump.cpu_state_data_size;
size += fw_dump.hpte_region_size;
size += fw_dump.boot_memory_size;
- size += sizeof(struct fadump_crash_info_header);
- size += sizeof(struct elfhdr); /* ELF core header.*/
- size += sizeof(struct elf_phdr); /* place holder for cpu notes */
- /* Program headers for crash memory regions. */
- size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 2);
-
+ size += get_fadump_metadata_size();
+ /* Add it twice. We will ask platform to move metadata contents
+ * at rmr_region.destination_address + source_len, so that old
+ * kernels also can get metadata to process fadump successfully.
+ */
+ size += get_fadump_metadata_size();
size = PAGE_ALIGN(size);
return size;
}
@@ -355,6 +399,35 @@ static void __init fadump_reserve_crash_area(unsigned long base,
}
}
+static inline unsigned long get_fadump_metadata_base(
+ const struct fadump_mem_struct *fdm)
+{
+ const struct fadump_section *dump_section;
+ uint16_t num_sections;
+
+ /* Scan through all dump sections to find out metadata section. */
+ dump_section = &fdm->cpu_state_data;
+ num_sections = be16_to_cpu(fdm->header.dump_num_sections);
+
+ while (num_sections--) {
+ uint16_t type = be16_to_cpu(dump_section->source_data_type);
+ if (type == FADUMP_METADATA_REGION)
+ return be64_to_cpu(dump_section->source_address);
+
+ dump_section++;
+ }
+
+ /*
+ * Support the older kernel which does not contain metadata
+ * dump section. We end up here only when fadump is active and
+ * the previously crashed kernel is old kernel which had metadata
+ * section at the top of the reserved memory.
+ */
+ BUG_ON(fw_dump.dump_active == 0);
+ return be64_to_cpu(fdm->rmr_region.destination_address) +
+ be64_to_cpu(fdm->rmr_region.source_len);
+}
+
int __init fadump_reserve_mem(void)
{
unsigned long base, size, memory_boundary;
@@ -420,9 +493,9 @@ int __init fadump_reserve_mem(void)
size = memory_boundary - base;
fadump_reserve_crash_area(base, size);
- fw_dump.fadumphdr_addr =
- be64_to_cpu(fdm_active->rmr_region.destination_address) +
- be64_to_cpu(fdm_active->rmr_region.source_len);
+ pr_info("Number of kernel Dump sections: %d\n",
+ be16_to_cpu(fdm_active->header.dump_num_sections));
+ fw_dump.fadumphdr_addr = get_fadump_metadata_base(fdm_active);
pr_debug("fadumphdr_addr = %p\n",
(void *) fw_dump.fadumphdr_addr);
} else {
@@ -821,6 +894,38 @@ static int __init fadump_build_cpu_notes(const struct fadump_mem_struct *fdm)
}
+static int validate_dump(const struct fadump_mem_struct *fdm_active)
+{
+ const struct fadump_section *dump_section;
+ uint16_t num_sections = 0;
+ int rc = 0;
+
+ num_sections = be16_to_cpu(fdm_active->header.dump_num_sections);
+ dump_section = &fdm_active->cpu_state_data;
+
+ if ((be16_to_cpu(fdm_active->header.dump_status_flag)
+ == FADUMP_ERROR_FLAG)) {
+ pr_err("Error occured while taking a dump by platform\n");
+ rc = -EINVAL;
+ }
+
+ /* Print Section type and error flags for failed dump section. */
+ while (num_sections--) {
+ if (dump_section->error_flags != 0 ||
+ (dump_section->source_len != dump_section->bytes_dumped)) {
+ pr_err("Section: %04x, Error flag: %04x, "
+ "Bytes Req: %llx, Bytes Dumped: %llx\n",
+ be16_to_cpu(dump_section->source_data_type),
+ be16_to_cpu(dump_section->error_flags),
+ be64_to_cpu(dump_section->source_len),
+ be64_to_cpu(dump_section->bytes_dumped));
+ rc = -EINVAL;
+ }
+ dump_section++;
+ }
+ return rc;
+}
+
/*
* Validate and process the dump data stored by firmware before exporting
* it through '/proc/vmcore'.
@@ -834,17 +939,10 @@ static int __init process_fadump(const struct fadump_mem_struct *fdm_active)
return -EINVAL;
/* Check if the dump data is valid. */
- if ((be16_to_cpu(fdm_active->header.dump_status_flag) == FADUMP_ERROR_FLAG) ||
- (fdm_active->cpu_state_data.error_flags != 0) ||
- (fdm_active->rmr_region.error_flags != 0)) {
+ rc = validate_dump(fdm_active);
+ if (rc) {
printk(KERN_ERR "Dump taken by platform is not valid\n");
- return -EINVAL;
- }
- if ((fdm_active->rmr_region.bytes_dumped !=
- fdm_active->rmr_region.source_len) ||
- !fdm_active->cpu_state_data.bytes_dumped) {
- printk(KERN_ERR "Dump taken by platform is incomplete\n");
- return -EINVAL;
+ return rc;
}
/* Validate the fadump crash info header */
@@ -1107,7 +1205,7 @@ static int register_fadump(void)
fadump_setup_crash_memory_ranges();
- addr = be64_to_cpu(fdm.rmr_region.destination_address) + be64_to_cpu(fdm.rmr_region.source_len);
+ addr = be64_to_cpu(fdm.metadata_region.source_address);
/* Initialize fadump crash info header. */
addr = init_fadump_header(addr);
vaddr = __va(addr);
@@ -1146,7 +1244,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 +1275,7 @@ 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);
+ fadump_invalidate_dump(fdm_active);
}
}
@@ -1250,6 +1346,35 @@ static void fadump_release_memory(unsigned long begin, unsigned long end)
fadump_release_reserved_area(begin, end);
}
+static inline unsigned long get_fadump_prev_mstart(
+ const struct fadump_mem_struct *fdm)
+{
+ const struct fadump_section *dump_section;
+ uint16_t num_sections;
+
+ /* This function is called only when fadump is active. */
+ BUG_ON(fw_dump.dump_active == 0);
+
+ /* Scan through all dump sections to find out metadata section. */
+ dump_section = &fdm->cpu_state_data;
+ num_sections = be16_to_cpu(fdm->header.dump_num_sections);
+
+ while (num_sections--) {
+ uint16_t type = be16_to_cpu(dump_section->source_data_type);
+ if (type == FADUMP_METADATA_REGION)
+ return be64_to_cpu(dump_section->source_address);
+
+ dump_section++;
+ }
+
+ /*
+ * Support the older kernel which does not contain metadata
+ * dump section. For older kernel reserved memory start is
+ * at cpu_state_data.destination_address.
+ */
+ return be64_to_cpu(fdm->cpu_state_data.destination_address);
+}
+
static void fadump_invalidate_release_mem(void)
{
unsigned long reserved_area_start, reserved_area_end;
@@ -1261,7 +1386,7 @@ static void fadump_invalidate_release_mem(void)
return;
}
- destination_address = be64_to_cpu(fdm_active->cpu_state_data.destination_address);
+ destination_address = get_fadump_prev_mstart(fdm_active);
fadump_cleanup();
mutex_unlock(&fadump_mutex);
^ permalink raw reply related
* [PATCH v4 0/7] powerpc/fadump: Improvements and fixes for firmware-assisted dump.
From: Mahesh J Salgaonkar @ 2018-04-20 5:04 UTC (permalink / raw)
To: linuxppc-dev
Cc: Srikar Dronamraju, kernelfans, Aneesh Kumar K.V, Ananth Narayan,
Hari Bathini, Nathan Fontenot, Anshuman Khandual
One of the primary issues with Firmware Assisted Dump (fadump) on Power
is that it needs a large amount of memory to be reserved. This reserved
memory is used for saving the contents of old crashed kernel's memory before
fadump capture kernel uses old kernel's memory area to boot. However, This
reserved memory area stays unused until system crash and isn't available
for production kernel to use.
Instead of setting aside a significant chunk of memory that nobody can use,
take advantage Linux kernel's Contiguous Memory Allocator (CMA) feature,
to reserve a significant chunk of memory that the kernel is prevented from
using , but applications are free to use it.
Patch 1 moves the metadata region to the start of the reserved area for easy
handling/detection of metadata region in second kernel.
Patch 4 implements the usage of CMA region to allow production kernel to
use that memory for applications usage, making fadump reservationless.
Patch 3, 6 and 7 fixes various fadump issues and bugs.
Changes in V4:
- patch 1: Make fadump compatible irrespective of kernel versions.
- patch 4: moved out of the series and been posted seperatly at
http://patchwork.ozlabs.org/patch/896716/
- Documentation update about CMA reservation.
Changes in V3:
- patch 1 & 2: move metadata region and documentation update.
- patch 7: Un-register the faudmp on kexec path
---
Mahesh Salgaonkar (7):
powerpc/fadump: Move the metadata region to start of the reserved area.
powerpc/fadump: Update documentation to reflect the metadata region movement.
powerpc/fadump: un-register fadump on kexec path.
powerpc/fadump: Reservationless firmware assisted dump
powerpc/fadump: Update documentation to reflect CMA reservation.
powerpc/fadump: throw proper error message on fadump registration failure.
powerpc/fadump: Do not allow hot-remove memory from fadump reserved area.
Documentation/powerpc/firmware-assisted-dump.txt | 43 ++-
arch/powerpc/include/asm/fadump.h | 11 +
arch/powerpc/kernel/fadump.c | 343 +++++++++++++++++++---
arch/powerpc/platforms/pseries/hotplug-memory.c | 7
4 files changed, 343 insertions(+), 61 deletions(-)
--
Signature
^ permalink raw reply
* Re: [PATCH 1/2] powernv/npu: Do a PID GPU TLB flush when invalidating a large address range
From: Alistair Popple @ 2018-04-20 3:51 UTC (permalink / raw)
To: linuxppc-dev; +Cc: mpe, mhairgrove, arbab
In-Reply-To: <20180417091129.23069-1-alistair@popple.id.au>
Sorry, forgot to include:
Fixes: 1ab66d1fbada ("powerpc/powernv: Introduce address translation services for Nvlink2")
Thanks
On Tuesday, 17 April 2018 7:11:28 PM AEST Alistair Popple wrote:
> The NPU has a limited number of address translation shootdown (ATSD)
> registers and the GPU has limited bandwidth to process ATSDs. This can
> result in contention of ATSD registers leading to soft lockups on some
> threads, particularly when invalidating a large address range in
> pnv_npu2_mn_invalidate_range().
>
> At some threshold it becomes more efficient to flush the entire GPU TLB for
> the given MM context (PID) than individually flushing each address in the
> range. This patch will result in ranges greater than 2MB being converted
> from 32+ ATSDs into a single ATSD which will flush the TLB for the given
> PID on each GPU.
>
> Signed-off-by: Alistair Popple <alistair@popple.id.au>
> ---
> arch/powerpc/platforms/powernv/npu-dma.c | 23 +++++++++++++++++++----
> 1 file changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
> index 94801d8e7894..dc34662e9df9 100644
> --- a/arch/powerpc/platforms/powernv/npu-dma.c
> +++ b/arch/powerpc/platforms/powernv/npu-dma.c
> @@ -40,6 +40,13 @@
> DEFINE_SPINLOCK(npu_context_lock);
>
> /*
> + * When an address shootdown range exceeds this threshold we invalidate the
> + * entire TLB on the GPU for the given PID rather than each specific address in
> + * the range.
> + */
> +#define ATSD_THRESHOLD (2*1024*1024)
> +
> +/*
> * Other types of TCE cache invalidation are not functional in the
> * hardware.
> */
> @@ -675,11 +682,19 @@ static void pnv_npu2_mn_invalidate_range(struct mmu_notifier *mn,
> struct npu_context *npu_context = mn_to_npu_context(mn);
> unsigned long address;
>
> - for (address = start; address < end; address += PAGE_SIZE)
> - mmio_invalidate(npu_context, 1, address, false);
> + if (end - start > ATSD_THRESHOLD) {
> + /*
> + * Just invalidate the entire PID if the address range is too
> + * large.
> + */
> + mmio_invalidate(npu_context, 0, 0, true);
> + } else {
> + for (address = start; address < end; address += PAGE_SIZE)
> + mmio_invalidate(npu_context, 1, address, false);
>
> - /* Do the flush only on the final addess == end */
> - mmio_invalidate(npu_context, 1, address, true);
> + /* Do the flush only on the final addess == end */
> + mmio_invalidate(npu_context, 1, address, true);
> + }
> }
>
> static const struct mmu_notifier_ops nv_nmmu_notifier_ops = {
>
^ permalink raw reply
* Re: [PATCH 2/2] powernv/npu: Prevent overwriting of pnv_npu2_init_contex() callback parameters
From: Alistair Popple @ 2018-04-20 3:51 UTC (permalink / raw)
To: linuxppc-dev; +Cc: mpe, mhairgrove, arbab
In-Reply-To: <20180411063855.5451-2-alistair@popple.id.au>
Sorry, forgot to include:
Fixes: 1ab66d1fbada ("powerpc/powernv: Introduce address translation services for Nvlink2")
Thanks
On Wednesday, 11 April 2018 4:38:55 PM AEST Alistair Popple wrote:
> There is a single npu context per set of callback parameters. Callers
> should be prevented from overwriting existing callback values so instead
> return an error if different parameters are passed.
>
> Signed-off-by: Alistair Popple <alistair@popple.id.au>
> ---
> arch/powerpc/include/asm/powernv.h | 2 +-
> arch/powerpc/platforms/powernv/npu-dma.c | 16 +++++++++++++---
> 2 files changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/powernv.h b/arch/powerpc/include/asm/powernv.h
> index dc5f6a5d4575..362ea12a4501 100644
> --- a/arch/powerpc/include/asm/powernv.h
> +++ b/arch/powerpc/include/asm/powernv.h
> @@ -15,7 +15,7 @@
> extern void powernv_set_nmmu_ptcr(unsigned long ptcr);
> extern struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
> unsigned long flags,
> - struct npu_context *(*cb)(struct npu_context *, void *),
> + void (*cb)(struct npu_context *, void *),
> void *priv);
> extern void pnv_npu2_destroy_context(struct npu_context *context,
> struct pci_dev *gpdev);
> diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
> index cb77162f4e7a..193f43ea3fbc 100644
> --- a/arch/powerpc/platforms/powernv/npu-dma.c
> +++ b/arch/powerpc/platforms/powernv/npu-dma.c
> @@ -407,7 +407,7 @@ struct npu_context {
> bool nmmu_flush;
>
> /* Callback to stop translation requests on a given GPU */
> - struct npu_context *(*release_cb)(struct npu_context *, void *);
> + void (*release_cb)(struct npu_context *context, void *priv);
>
> /*
> * Private pointer passed to the above callback for usage by
> @@ -705,7 +705,7 @@ static const struct mmu_notifier_ops nv_nmmu_notifier_ops = {
> */
> struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
> unsigned long flags,
> - struct npu_context *(*cb)(struct npu_context *, void *),
> + void (*cb)(struct npu_context *, void *),
> void *priv)
> {
> int rc;
> @@ -763,8 +763,18 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
> */
> spin_lock(&npu_context_lock);
> npu_context = mm->context.npu_context;
> - if (npu_context)
> + if (npu_context) {
> + if (npu_context->release_cb != cb ||
> + npu_context->priv != priv) {
> + spin_unlock(&npu_context_lock);
> + opal_npu_destroy_context(nphb->opal_id, mm->context.id,
> + PCI_DEVID(gpdev->bus->number,
> + gpdev->devfn));
> + return ERR_PTR(-EINVAL);
> + }
> +
> WARN_ON(!kref_get_unless_zero(&npu_context->kref));
> + }
> spin_unlock(&npu_context_lock);
>
> if (!npu_context) {
>
^ permalink raw reply
* Re: [PATCH 1/2] powernv/npu: Add lock to prevent race in concurrent context init/destroy
From: Alistair Popple @ 2018-04-20 3:50 UTC (permalink / raw)
To: linuxppc-dev; +Cc: mpe, mhairgrove, arbab
In-Reply-To: <20180411063855.5451-1-alistair@popple.id.au>
Sorry, forgot to include:
Fixes: 1ab66d1fbada ("powerpc/powernv: Introduce address translation services for Nvlink2")
Thanks
On Wednesday, 11 April 2018 4:38:54 PM AEST Alistair Popple wrote:
> The pnv_npu2_init_context() and pnv_npu2_destroy_context() functions are
> used to allocate/free contexts to allow address translation and shootdown
> by the NPU on a particular GPU. Context initialisation is implicitly safe
> as it is protected by the requirement mmap_sem be held in write mode,
> however pnv_npu2_destroy_context() does not require mmap_sem to be held and
> it is not safe to call with a concurrent initialisation for a different
> GPU.
>
> It was assumed the driver would ensure destruction was not called
> concurrently with initialisation. However the driver may be simplified by
> allowing concurrent initialisation and destruction for different GPUs. As
> npu context creation/destruction is not a performance critical path and the
> critical section is not large a single spinlock is used for simplicity.
>
> Signed-off-by: Alistair Popple <alistair@popple.id.au>
> ---
> arch/powerpc/platforms/powernv/npu-dma.c | 51 ++++++++++++++++++++++++++------
> 1 file changed, 42 insertions(+), 9 deletions(-)
>
> diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c
> index 1cbef1f9cd37..cb77162f4e7a 100644
> --- a/arch/powerpc/platforms/powernv/npu-dma.c
> +++ b/arch/powerpc/platforms/powernv/npu-dma.c
> @@ -34,6 +34,12 @@
> #define npu_to_phb(x) container_of(x, struct pnv_phb, npu)
>
> /*
> + * spinlock to protect initialisation of an npu_context for a particular
> + * mm_struct.
> + */
> +DEFINE_SPINLOCK(npu_context_lock);
> +
> +/*
> * Other types of TCE cache invalidation are not functional in the
> * hardware.
> */
> @@ -694,7 +700,8 @@ static const struct mmu_notifier_ops nv_nmmu_notifier_ops = {
> * Returns an error if there no contexts are currently available or a
> * npu_context which should be passed to pnv_npu2_handle_fault().
> *
> - * mmap_sem must be held in write mode.
> + * mmap_sem must be held in write mode and must not be called from interrupt
> + * context.
> */
> struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
> unsigned long flags,
> @@ -741,7 +748,9 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
> /*
> * Setup the NPU context table for a particular GPU. These need to be
> * per-GPU as we need the tables to filter ATSDs when there are no
> - * active contexts on a particular GPU.
> + * active contexts on a particular GPU. It is safe for these to be
> + * called concurrently with destroy as the OPAL call takes appropriate
> + * locks and refcounts on init/destroy.
> */
> rc = opal_npu_init_context(nphb->opal_id, mm->context.id, flags,
> PCI_DEVID(gpdev->bus->number, gpdev->devfn));
> @@ -752,8 +761,19 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
> * We store the npu pci device so we can more easily get at the
> * associated npus.
> */
> + spin_lock(&npu_context_lock);
> npu_context = mm->context.npu_context;
> + if (npu_context)
> + WARN_ON(!kref_get_unless_zero(&npu_context->kref));
> + spin_unlock(&npu_context_lock);
> +
> if (!npu_context) {
> + /*
> + * We can set up these fields without holding the
> + * npu_context_lock as the npu_context hasn't been returned to
> + * the caller meaning it can't be destroyed. Parallel allocation
> + * is protected against by mmap_sem.
> + */
> rc = -ENOMEM;
> npu_context = kzalloc(sizeof(struct npu_context), GFP_KERNEL);
> if (npu_context) {
> @@ -772,8 +792,6 @@ struct npu_context *pnv_npu2_init_context(struct pci_dev *gpdev,
> }
>
> mm->context.npu_context = npu_context;
> - } else {
> - WARN_ON(!kref_get_unless_zero(&npu_context->kref));
> }
>
> npu_context->release_cb = cb;
> @@ -811,15 +829,16 @@ static void pnv_npu2_release_context(struct kref *kref)
> mm_context_remove_copro(npu_context->mm);
>
> npu_context->mm->context.npu_context = NULL;
> - mmu_notifier_unregister(&npu_context->mn,
> - npu_context->mm);
> -
> - kfree(npu_context);
> }
>
> +/*
> + * Destroy a context on the given GPU. May free the npu_context if it is no
> + * longer active on any GPUs. Must not be called from interrupt context.
> + */
> void pnv_npu2_destroy_context(struct npu_context *npu_context,
> struct pci_dev *gpdev)
> {
> + int removed;
> struct pnv_phb *nphb;
> struct npu *npu;
> struct pci_dev *npdev = pnv_pci_get_npu_dev(gpdev, 0);
> @@ -841,7 +860,21 @@ void pnv_npu2_destroy_context(struct npu_context *npu_context,
> WRITE_ONCE(npu_context->npdev[npu->index][nvlink_index], NULL);
> opal_npu_destroy_context(nphb->opal_id, npu_context->mm->context.id,
> PCI_DEVID(gpdev->bus->number, gpdev->devfn));
> - kref_put(&npu_context->kref, pnv_npu2_release_context);
> + spin_lock(&npu_context_lock);
> + removed = kref_put(&npu_context->kref, pnv_npu2_release_context);
> + spin_unlock(&npu_context_lock);
> +
> + /*
> + * We need to do this outside of pnv_npu2_release_context so that it is
> + * outside the spinlock as mmu_notifier_destroy uses SRCU.
> + */
> + if (removed) {
> + mmu_notifier_unregister(&npu_context->mn,
> + npu_context->mm);
> +
> + kfree(npu_context);
> + }
> +
> }
> EXPORT_SYMBOL(pnv_npu2_destroy_context);
>
>
^ permalink raw reply
* [REVIEW][PATCH 15/17] signal: Add TRAP_UNK si_code for undiagnosted trap exceptions
From: Eric W. Biederman @ 2018-04-20 1:04 UTC (permalink / raw)
To: linux-arch
Cc: linux-kernel, linux-api, Eric W. Biederman, linux-alpha,
linuxppc-dev
In-Reply-To: <878t9ilmhv.fsf@xmission.com>
Both powerpc and alpha have cases where they wronly set si_code to 0
in combination with SIGTRAP and don't mean SI_USER.
About half the time this is because the architecture can not report
accurately what kind of trap exception triggered the trap exception.
The other half the time it looks like no one has bothered to
figure out an appropriate si_code.
For the cases where the architecture does not have enough information
or is too lazy to figure out exactly what kind of trap exception
it is define TRAP_UNK.
Cc: linux-api@vger.kernel.org
Cc: linux-arch@vger.kernel.org
Cc: linux-alpha@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
arch/x86/kernel/signal_compat.c | 2 +-
include/uapi/asm-generic/siginfo.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 14c057f29979..9ccbf0576cd0 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -29,7 +29,7 @@ static inline void signal_compat_build_tests(void)
BUILD_BUG_ON(NSIGFPE != 15);
BUILD_BUG_ON(NSIGSEGV != 7);
BUILD_BUG_ON(NSIGBUS != 5);
- BUILD_BUG_ON(NSIGTRAP != 4);
+ BUILD_BUG_ON(NSIGTRAP != 5);
BUILD_BUG_ON(NSIGCHLD != 6);
BUILD_BUG_ON(NSIGSYS != 1);
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 558b902f18d4..80e2a7227205 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -249,7 +249,8 @@ typedef struct siginfo {
#define TRAP_TRACE 2 /* process trace trap */
#define TRAP_BRANCH 3 /* process taken branch trap */
#define TRAP_HWBKPT 4 /* hardware breakpoint/watchpoint */
-#define NSIGTRAP 4
+#define TRAP_UNK 5 /* undiagnosed trap */
+#define NSIGTRAP 5
/*
* There is an additional set of SIGTRAP si_codes used by ptrace
--
2.14.1
^ permalink raw reply related
* [REVIEW][PATCH 13/17] signal/powerpc: Replace FPE_FIXME with FPE_FLTUNK
From: Eric W. Biederman @ 2018-04-20 1:04 UTC (permalink / raw)
To: linux-arch
Cc: linux-kernel, linux-api, Eric W. Biederman, Paul Mackerras,
Kumar Gala, Michael Ellerman, Benjamin Herrenschmidt,
linuxppc-dev
In-Reply-To: <878t9ilmhv.fsf@xmission.com>
Using an si_code of 0 that aliases with SI_USER is clearly the
wrong thing todo, and causes problems in interesting ways.
The newly defined FPE_FLTUNK semantically appears to fit the
bill so use it instead.
Cc: Paul Mackerras <paulus@samba.org>
Cc: Kumar Gala <kumar.gala@freescale.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: linuxppc-dev@lists.ozlabs.org
Fixes: 9bad068c24d7 ("[PATCH] ppc32: support for e500 and 85xx")
Fixes: 0ed70f6105ef ("PPC32: Provide proper siginfo information on various exceptions.")
History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
arch/powerpc/include/uapi/asm/siginfo.h | 7 -------
arch/powerpc/kernel/traps.c | 6 +++---
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/uapi/asm/siginfo.h b/arch/powerpc/include/uapi/asm/siginfo.h
index 9f142451a01f..0437afc9ef3c 100644
--- a/arch/powerpc/include/uapi/asm/siginfo.h
+++ b/arch/powerpc/include/uapi/asm/siginfo.h
@@ -15,13 +15,6 @@
#include <asm-generic/siginfo.h>
-/*
- * SIGFPE si_codes
- */
-#ifdef __KERNEL__
-#define FPE_FIXME 0 /* Broken dup of SI_USER */
-#endif /* __KERNEL__ */
-
/*
* SIGTRAP si_codes
*/
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 087855caf6a9..fdf9400beec8 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1031,7 +1031,7 @@ static void emulate_single_step(struct pt_regs *regs)
static inline int __parse_fpscr(unsigned long fpscr)
{
- int ret = FPE_FIXME;
+ int ret = FPE_FLTUNK;
/* Invalid operation */
if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
@@ -1972,7 +1972,7 @@ void SPEFloatingPointException(struct pt_regs *regs)
extern int do_spe_mathemu(struct pt_regs *regs);
unsigned long spefscr;
int fpexc_mode;
- int code = FPE_FIXME;
+ int code = FPE_FLTUNK;
int err;
flush_spe_to_thread(current);
@@ -2041,7 +2041,7 @@ void SPEFloatingPointRoundException(struct pt_regs *regs)
printk(KERN_ERR "unrecognized spe instruction "
"in %s at %lx\n", current->comm, regs->nip);
} else {
- _exception(SIGFPE, regs, FPE_FIXME, regs->nip);
+ _exception(SIGFPE, regs, FPE_FLTUNK, regs->nip);
return;
}
}
--
2.14.1
^ permalink raw reply related
* [REVIEW][PATCH 17/17] signal/powerpc: Replace TRAP_FIXME with TRAP_UNK
From: Eric W. Biederman @ 2018-04-20 1:04 UTC (permalink / raw)
To: linux-arch
Cc: linux-kernel, linux-api, Eric W. Biederman, Paul Mackerras,
Kumar Gala, Michael Ellerman, Benjamin Herrenschmidt,
linuxppc-dev
In-Reply-To: <878t9ilmhv.fsf@xmission.com>
Using an si_code of 0 that aliases with SI_USER is clearly the wrong
thing todo, and causes problems in interesting ways.
For use in unknown_exception the recently defined TRAP_UNK
semantically is a perfect fit. For use in RunModeException it looks
like something more specific than TRAP_UNK could be used. No one has
bothered to find a better fit than the broken si_code of 0 in all of
these years and I don't see an obvious better fit so TRAP_UNK is
switching RunModeException to return TRAP_UNK is clearly an
improvement.
Recent history suggests no actually cares about crazy corner
cases of the kernel behavior like this so I don't expect any
regressions from changing this. However if something does
happen this change is easy to revert.
Though I wonder if SIGKILL might not be a better fit.
Cc: Paul Mackerras <paulus@samba.org>
Cc: Kumar Gala <kumar.gala@freescale.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: linuxppc-dev@lists.ozlabs.org
Fixes: 9bad068c24d7 ("[PATCH] ppc32: support for e500 and 85xx")
Fixes: 0ed70f6105ef ("PPC32: Provide proper siginfo information on various exceptions.")
History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
---
arch/powerpc/include/uapi/asm/siginfo.h | 8 --------
arch/powerpc/kernel/traps.c | 4 ++--
2 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/include/uapi/asm/siginfo.h b/arch/powerpc/include/uapi/asm/siginfo.h
index 0437afc9ef3c..1d51d9b88221 100644
--- a/arch/powerpc/include/uapi/asm/siginfo.h
+++ b/arch/powerpc/include/uapi/asm/siginfo.h
@@ -15,12 +15,4 @@
#include <asm-generic/siginfo.h>
-/*
- * SIGTRAP si_codes
- */
-#ifdef __KERNEL__
-#define TRAP_FIXME 0 /* Broken dup of SI_USER */
-#endif /* __KERNEL__ */
-
-
#endif /* _ASM_POWERPC_SIGINFO_H */
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index fdf9400beec8..0e17dcb48720 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -969,7 +969,7 @@ void unknown_exception(struct pt_regs *regs)
printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
regs->nip, regs->msr, regs->trap);
- _exception(SIGTRAP, regs, TRAP_FIXME, 0);
+ _exception(SIGTRAP, regs, TRAP_UNK, 0);
exception_exit(prev_state);
}
@@ -991,7 +991,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)
void RunModeException(struct pt_regs *regs)
{
- _exception(SIGTRAP, regs, TRAP_FIXME, 0);
+ _exception(SIGTRAP, regs, TRAP_UNK, 0);
}
void single_step_exception(struct pt_regs *regs)
--
2.14.1
^ permalink raw reply related
* Re: [PATCH v3 01/17] y2038: asm-generic: Extend sysvipc data structures
From: Eric W. Biederman @ 2018-04-19 22:12 UTC (permalink / raw)
To: Arnd Bergmann
Cc: y2038 Mailman List, Linux Kernel Mailing List, Linux API,
linux-arch, GNU C Library, Thomas Gleixner, Deepa Dinamani,
Al Viro, Albert ARIBAUD, linux-s390, Martin Schwidefsky,
the arch/x86 maintainers, Catalin Marinas, Will Deacon,
open list:RALINK MIPS ARCHITECTURE, James Hogan, Ralf Baechle,
linuxppc-dev, sparclinux
In-Reply-To: <CAK8P3a2KR+0ZE5jHSmO6pSuiRPH83p75KetuQuHL1atChcTJGA@mail.gmail.com>
Arnd Bergmann <arnd@arndb.de> writes:
> On Thu, Apr 19, 2018 at 5:20 PM, Arnd Bergmann <arnd@arndb.de> wrote:
>> On Thu, Apr 19, 2018 at 4:59 PM, Eric W. Biederman <ebiederm@xmission.com> wrote:
>>> I suspect you want to use __kernel_ulong_t here instead of a raw
>>> unsigned long. If nothing else it seems inconsistent to use typedefs
>>> in one half of the structure and no typedefs in the other half.
>>
>> Good catch, there is definitely something wrong here, but I think using
>> __kernel_ulong_t for all members would also be wrong, as that
>> still changes the layout on x32, which effectively is
>>
>> struct msqid64_ds {
>> ipc64_perm msg_perm;
>> u64 msg_stime;
>> u32 __unused1;
>> /* 32 bit implict padding */
>> u64 msg_rtime;
>> u32 __unused2;
>> /* 32 bit implict padding */
>> u64 msg_ctime;
>> u32 __unused3;
>> /* 32 bit implict padding */
>> __kernel_pid_t shm_cpid; /* pid of creator */
>> __kernel_pid_t shm_lpid; /* pid of last operator */
>> ....
>> };
>>
>> The choices here would be to either use a mix of
>> __kernel_ulong_t and unsigned long, or taking the x32
>> version back into arch/x86/include/uapi/asm/ so the
>> generic version at least makes some sense.
>>
>> I can't use __kernel_time_t for the lower half on 32-bit
>> since it really should be unsigned.
>
> After thinking about it some more, I conclude that the structure is simply
> incorrect on x32: The __kernel_ulong_t usage was introduced in 2013
> in commit b9cd5ca22d67 ("uapi: Use __kernel_ulong_t in struct
> msqid64_ds") and apparently was correct initially as __BITS_PER_LONG
> evaluated to 64, but it broke with commit f4b4aae18288 ("x86/headers/uapi:
> Fix __BITS_PER_LONG value for x32 builds") that changed the value
> of __BITS_PER_LONG and introduced the extra padding in 2015.
>
> The same change apparently also broke a lot of other definitions, e.g.
>
> $ echo "#include <linux/types.h>" | gcc -mx32 -E -xc - | grep -A3
> __kernel_size_t
> typedef unsigned int __kernel_size_t;
> typedef int __kernel_ssize_t;
> typedef int __kernel_ptrdiff_t;
>
> Those used to be defined as 'unsigned long long' and 'long long'
> respectively, so now all kernel interfaces using those on x32
> became incompatible!
That seems like a real mess.
Is this just for the uapi header as seen by userspace? I expect we are
using the a normal kernel interface with 64bit longs and 64bit pointers
when we build the kernel.
If this is just a header as seen from userspace mess it seems
unfortunate but fixable.
Eric
^ permalink raw reply
* Re: [PATCH v3 01/17] y2038: asm-generic: Extend sysvipc data structures
From: Arnd Bergmann @ 2018-04-19 21:24 UTC (permalink / raw)
To: Eric W. Biederman
Cc: y2038 Mailman List, Linux Kernel Mailing List, Linux API,
linux-arch, GNU C Library, Thomas Gleixner, Deepa Dinamani,
Al Viro, Albert ARIBAUD, linux-s390, Martin Schwidefsky,
the arch/x86 maintainers, Catalin Marinas, Will Deacon,
open list:RALINK MIPS ARCHITECTURE, James Hogan, Ralf Baechle,
linuxppc-dev, sparclinux
In-Reply-To: <CAK8P3a196QYoM1egagMuZw4WhiwRiO83Qpj0CxoCeVQBEaj-gw@mail.gmail.com>
On Thu, Apr 19, 2018 at 5:20 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thu, Apr 19, 2018 at 4:59 PM, Eric W. Biederman <ebiederm@xmission.com> wrote:
>> I suspect you want to use __kernel_ulong_t here instead of a raw
>> unsigned long. If nothing else it seems inconsistent to use typedefs
>> in one half of the structure and no typedefs in the other half.
>
> Good catch, there is definitely something wrong here, but I think using
> __kernel_ulong_t for all members would also be wrong, as that
> still changes the layout on x32, which effectively is
>
> struct msqid64_ds {
> ipc64_perm msg_perm;
> u64 msg_stime;
> u32 __unused1;
> /* 32 bit implict padding */
> u64 msg_rtime;
> u32 __unused2;
> /* 32 bit implict padding */
> u64 msg_ctime;
> u32 __unused3;
> /* 32 bit implict padding */
> __kernel_pid_t shm_cpid; /* pid of creator */
> __kernel_pid_t shm_lpid; /* pid of last operator */
> ....
> };
>
> The choices here would be to either use a mix of
> __kernel_ulong_t and unsigned long, or taking the x32
> version back into arch/x86/include/uapi/asm/ so the
> generic version at least makes some sense.
>
> I can't use __kernel_time_t for the lower half on 32-bit
> since it really should be unsigned.
After thinking about it some more, I conclude that the structure is simply
incorrect on x32: The __kernel_ulong_t usage was introduced in 2013
in commit b9cd5ca22d67 ("uapi: Use __kernel_ulong_t in struct
msqid64_ds") and apparently was correct initially as __BITS_PER_LONG
evaluated to 64, but it broke with commit f4b4aae18288 ("x86/headers/uapi:
Fix __BITS_PER_LONG value for x32 builds") that changed the value
of __BITS_PER_LONG and introduced the extra padding in 2015.
The same change apparently also broke a lot of other definitions, e.g.
$ echo "#include <linux/types.h>" | gcc -mx32 -E -xc - | grep -A3
__kernel_size_t
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
Those used to be defined as 'unsigned long long' and 'long long'
respectively, so now all kernel interfaces using those on x32
became incompatible!
Arnd
^ permalink raw reply
* Re: [PATCH v5 06/10] powerpc64/ftrace: Disable ftrace during kvm entry/exit
From: Steven Rostedt @ 2018-04-19 15:22 UTC (permalink / raw)
To: Naveen N. Rao
Cc: Michael Ellerman, linuxppc-dev, Paul Mackerras,
Satheesh Rajendran
In-Reply-To: <62b77045b205b008946b793fe31effb155b335be.1524121038.git.naveen.n.rao@linux.vnet.ibm.com>
On Thu, 19 Apr 2018 12:34:05 +0530
"Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com> wrote:
> 2. If we are a secondary thread in Power8, then we would be in nap due
> to SMT being disabled. We are woken up by an IPI to enter the guest. In
> this scenario, we enter the guest through kvm_start_guest(). We disable
> ftrace at this point. In this scenario, ftrace would only get re-enabled
> on the secondary thread when SMT is re-enabled (via start_secondary()).
>
trace_hardirqs_off();
> diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> index bd63fa8a08b5..2c3cbe0067b2 100644
> --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
> @@ -342,6 +342,9 @@ kvm_start_guest:
>
> ld r2,PACATOC(r13)
>
You may want to add a comment here about where ftrace gets re-enabled.
-- Steve
> + li r0,0
> + stb r0,PACA_FTRACE_ENABLED(r13)
> +
> li r0,KVM_HWTHREAD_IN_KVM
> stb r0,HSTATE_HWTHREAD_STATE(r13)
>
^ permalink raw reply
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