* [PATCH v3] powerpc/64: Option to use ELF V2 ABI for big-endian kernels
From: Nicholas Piggin @ 2020-04-29 1:19 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin
Provide an option to build big-endian kernels using the ELF V2 ABI. This works
on GCC and clang (since about 2014). it is is not officially supported by the
GNU toolchain, but it can give big-endian kernels some useful advantages of
the V2 ABI (e.g., less stack usage).
Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org>
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
Since v1:
- Improved the override flavour name suggested by Segher.
- Improved changelog wording.
Since v2:
- Improved changelog, help text, to use the name ELF V2 ABI in the spec,
and clarify things a bit more, suggested by Segher.
- For option name, match the ELF_ABI_v1/2 which is already in the kernel.
- Prefix options with PPC64_ to avoid arch clashes or confusion.
- "elfv2" is the toolchain name of the ABI, so I kept that in the crypto
perl scripts.
arch/powerpc/Kconfig | 21 +++++++++++++++++++++
arch/powerpc/Makefile | 15 ++++++++++-----
arch/powerpc/boot/Makefile | 4 ++++
drivers/crypto/vmx/Makefile | 8 ++++++--
drivers/crypto/vmx/ppc-xlate.pl | 10 ++++++----
5 files changed, 47 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 924c541a9260..444867e07039 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -147,6 +147,7 @@ config PPC
select ARCH_WEAK_RELEASE_ACQUIRE
select BINFMT_ELF
select BUILDTIME_TABLE_SORT
+ select PPC64_BUILD_ELF_ABI_V2 if PPC64 && CPU_LITTLE_ENDIAN
select CLONE_BACKWARDS
select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN
select DYNAMIC_FTRACE if FUNCTION_TRACER
@@ -541,6 +542,26 @@ config KEXEC_FILE
config ARCH_HAS_KEXEC_PURGATORY
def_bool KEXEC_FILE
+config PPC64_BUILD_ELF_ABI_V2
+ bool
+
+config PPC64_BUILD_BIG_ENDIAN_ELF_ABI_V2
+ bool "Build big-endian kernel using ELF V2 ABI (EXPERIMENTAL)"
+ depends on PPC64 && CPU_BIG_ENDIAN && EXPERT
+ default n
+ select PPC64_BUILD_ELF_ABI_V2
+ help
+ This builds the kernel image using the "Power Architecture 64-Bit ELF
+ V2 ABI Specification", which has a reduced stack overhead and faster
+ function calls. This internal kernel ABI option does not affect
+ userspace compatibility.
+
+ The V2 ABI is standard for 64-bit little-endian, but for big-endian
+ it is less well tested by kernel and toolchain. However some distros
+ build userspace this way, and it can produce a functioning kernel.
+
+ This requires gcc 4.9 or newer and binutils 2.24 or newer.
+
config RELOCATABLE
bool "Build a relocatable kernel"
depends on PPC64 || (FLATMEM && (44x || FSL_BOOKE))
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index f310c32e88a4..baf477d100b2 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -92,10 +92,14 @@ endif
ifdef CONFIG_PPC64
ifndef CONFIG_CC_IS_CLANG
-cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1)
-cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mcall-aixdesc)
-aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1)
-aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mabi=elfv2
+ifdef CONFIG_PPC64_BUILD_ELF_ABI_V2
+cflags-y += $(call cc-option,-mabi=elfv2,$(call cc-option,-mcall-aixdesc))
+aflags-y += $(call cc-option,-mabi=elfv2)
+else
+cflags-y += $(call cc-option,-mabi=elfv1)
+cflags-y += $(call cc-option,-mcall-aixdesc)
+aflags-y += $(call cc-option,-mabi=elfv1)
+endif
endif
endif
@@ -144,7 +148,7 @@ endif
CFLAGS-$(CONFIG_PPC64) := $(call cc-option,-mtraceback=no)
ifndef CONFIG_CC_IS_CLANG
-ifdef CONFIG_CPU_LITTLE_ENDIAN
+ifdef CONFIG_PPC64_BUILD_ELF_ABI_V2
CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2,$(call cc-option,-mcall-aixdesc))
AFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2)
else
@@ -153,6 +157,7 @@ CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcall-aixdesc)
AFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv1)
endif
endif
+
CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,$(call cc-option,-mminimal-toc))
CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mno-pointers-to-nested-functions)
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index c53a1b8bba8b..d27e85413c84 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -41,6 +41,10 @@ endif
BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include)
+ifdef CONFIG_PPC64_BUILD_ELF_ABI_V2
+BOOTCFLAGS += $(call cc-option,-mabi=elfv2)
+endif
+
ifdef CONFIG_CPU_BIG_ENDIAN
BOOTCFLAGS += -mbig-endian
else
diff --git a/drivers/crypto/vmx/Makefile b/drivers/crypto/vmx/Makefile
index 709670d2b553..751ffca694aa 100644
--- a/drivers/crypto/vmx/Makefile
+++ b/drivers/crypto/vmx/Makefile
@@ -5,18 +5,22 @@ vmx-crypto-objs := vmx.o aesp8-ppc.o ghashp8-ppc.o aes.o aes_cbc.o aes_ctr.o aes
ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
override flavour := linux-ppc64le
else
+ifdef CONFIG_PPC64_BUILD_ELF_ABI_V2
+override flavour := linux-ppc64-elfv2
+else
override flavour := linux-ppc64
endif
+endif
quiet_cmd_perl = PERL $@
cmd_perl = $(PERL) $(<) $(flavour) > $(@)
targets += aesp8-ppc.S ghashp8-ppc.S
-$(obj)/aesp8-ppc.S: $(src)/aesp8-ppc.pl FORCE
+$(obj)/aesp8-ppc.S: $(src)/aesp8-ppc.pl $(src)/ppc-xlate.pl FORCE
$(call if_changed,perl)
-$(obj)/ghashp8-ppc.S: $(src)/ghashp8-ppc.pl FORCE
+$(obj)/ghashp8-ppc.S: $(src)/ghashp8-ppc.pl $(src)/ppc-xlate.pl FORCE
$(call if_changed,perl)
clean-files := aesp8-ppc.S ghashp8-ppc.S
diff --git a/drivers/crypto/vmx/ppc-xlate.pl b/drivers/crypto/vmx/ppc-xlate.pl
index 36db2ef09e5b..b583898c11ae 100644
--- a/drivers/crypto/vmx/ppc-xlate.pl
+++ b/drivers/crypto/vmx/ppc-xlate.pl
@@ -9,6 +9,8 @@ open STDOUT,">$output" || die "can't open $output: $!";
my %GLOBALS;
my $dotinlocallabels=($flavour=~/linux/)?1:0;
+my $elfv2abi=(($flavour =~ /linux-ppc64le/) or ($flavour =~ /linux-ppc64-elfv2/))?1:0;
+my $dotfunctions=($elfv2abi=~1)?0:1;
################################################################
# directives which need special treatment on different platforms
@@ -40,7 +42,7 @@ my $globl = sub {
};
my $text = sub {
my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text";
- $ret = ".abiversion 2\n".$ret if ($flavour =~ /linux.*64le/);
+ $ret = ".abiversion 2\n".$ret if ($elfv2abi);
$ret;
};
my $machine = sub {
@@ -56,8 +58,8 @@ my $size = sub {
if ($flavour =~ /linux/)
{ shift;
my $name = shift; $name =~ s|^[\.\_]||;
- my $ret = ".size $name,.-".($flavour=~/64$/?".":"").$name;
- $ret .= "\n.size .$name,.-.$name" if ($flavour=~/64$/);
+ my $ret = ".size $name,.-".($dotfunctions?".":"").$name;
+ $ret .= "\n.size .$name,.-.$name" if ($dotfunctions);
$ret;
}
else
@@ -142,7 +144,7 @@ my $vmr = sub {
# Some ABIs specify vrsave, special-purpose register #256, as reserved
# for system use.
-my $no_vrsave = ($flavour =~ /linux-ppc64le/);
+my $no_vrsave = ($elfv2abi);
my $mtspr = sub {
my ($f,$idx,$ra) = @_;
if ($idx == 256 && $no_vrsave) {
--
2.23.0
^ permalink raw reply related
* Re: [PATCH v3 00/29] Convert files to ReST - part 2
From: Jan Harkes @ 2020-04-28 19:25 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Linux Doc Mailing List, Mauro Carvalho Chehab, linux-usb,
linux-kernel, linux-xfs, linux-cachefs, linux-fsdevel,
linuxppc-dev
In-Reply-To: <20200428130128.22c4b973@lwn.net>
On Tue, Apr 28, 2020 at 03:09:51PM -0400, Jonathan Corbet wrote:
> So I'm happy to merge this set, but there is one thing that worries me a
> bit...
>
> > fs/coda/Kconfig | 2 +-
>
> I'd feel a bit better if I could get an ack or two from filesystem folks
> before I venture that far out of my own yard...what say you all?
I acked the Coda parts on the first iteration of this patch. I have no
problem with you merging them.
Jan
^ permalink raw reply
* Re: [PATCH v2] powerpc/64: BE option to use ELFv2 ABI for big endian kernels
From: Nicholas Piggin @ 2020-04-29 0:57 UTC (permalink / raw)
To: Segher Boessenkool; +Cc: linuxppc-dev
In-Reply-To: <20200428234046.GP17645@gate.crashing.org>
Excerpts from Segher Boessenkool's message of April 29, 2020 9:40 am:
> Hi!
>
> On Tue, Apr 28, 2020 at 09:25:17PM +1000, Nicholas Piggin wrote:
>> +config BUILD_BIG_ENDIAN_ELF_V2
>> + bool "Build big-endian kernel using ELFv2 ABI (EXPERIMENTAL)"
>> + depends on PPC64 && CPU_BIG_ENDIAN && EXPERT
>> + default n
>> + select BUILD_ELF_V2
>> + help
>> + This builds the kernel image using the ELFv2 ABI, which has a
>> + reduced stack overhead and faster function calls. This does not
>> + affect the userspace ABIs.
>> +
>> + ELFv2 is the standard ABI for little-endian, but for big-endian
>> + this is an experimental option that is less tested (kernel and
>> + toolchain). This requires gcc 4.9 or newer and binutils 2.24 or
>> + newer.
>
> Is it clear that this is only for 64-bit? Maybe this text should fit
> that in somewhere?
Don't know if it's necessary, the option only appears when 64-bit is
selected.
> It's not obvious to people who do not already know that ELFv2 is just
> the (nick-)name of a particular ABI, not a new kind of ELF (it is just
> version 1 ELF in fact), and that ABI is for 64-bit Power only.
I blame toolchain for -mabi=elfv2 ! And also some blame on ABI document
which is called ELF V2 ABI rather than ELF ABI V2 which would have been
unambiguous.
Kernel mostly gets it right (in the code I didn't write), and uses these
#if defined(_CALL_ELF) && _CALL_ELF == 2
#define PPC64_ELF_ABI_v2
#else
#define PPC64_ELF_ABI_v1
#endif
I can go through and change all my stuff and config options to ELF_ABI_v2.
Thanks,
Nick
^ permalink raw reply
* Re: [PATCH v2 3/3] mm/page_alloc: Keep memoryless cpuless node 0 offline
From: Andrew Morton @ 2020-04-28 23:59 UTC (permalink / raw)
To: Srikar Dronamraju
Cc: Michal Hocko, Linus Torvalds, linux-kernel, linux-mm, Mel Gorman,
Kirill A. Shutemov, Christopher Lameter, linuxppc-dev,
Vlastimil Babka
In-Reply-To: <20200428093836.27190-4-srikar@linux.vnet.ibm.com>
On Tue, 28 Apr 2020 15:08:36 +0530 Srikar Dronamraju <srikar@linux.vnet.ibm.com> wrote:
> Currently Linux kernel with CONFIG_NUMA on a system with multiple
> possible nodes, marks node 0 as online at boot. However in practice,
> there are systems which have node 0 as memoryless and cpuless.
>
> This can cause numa_balancing to be enabled on systems with only one node
> with memory and CPUs. The existence of this dummy node which is cpuless and
> memoryless node can confuse users/scripts looking at output of lscpu /
> numactl.
>
> By marking, N_ONLINE as NODE_MASK_NONE, lets stop assuming that Node 0 is
> always online.
>
> ...
>
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -116,8 +116,10 @@ EXPORT_SYMBOL(latent_entropy);
> */
> nodemask_t node_states[NR_NODE_STATES] __read_mostly = {
> [N_POSSIBLE] = NODE_MASK_ALL,
> +#ifdef CONFIG_NUMA
> + [N_ONLINE] = NODE_MASK_NONE,
> +#else
> [N_ONLINE] = { { [0] = 1UL } },
> -#ifndef CONFIG_NUMA
> [N_NORMAL_MEMORY] = { { [0] = 1UL } },
> #ifdef CONFIG_HIGHMEM
> [N_HIGH_MEMORY] = { { [0] = 1UL } },
So on all other NUMA machines, when does node 0 get marked online?
This change means that for some time during boot, such machines will
now be running with node 0 marked as offline. What are the
implications of this? Will something break?
^ permalink raw reply
* Re: [PATCH v2] powerpc/64: BE option to use ELFv2 ABI for big endian kernels
From: Segher Boessenkool @ 2020-04-28 23:40 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: linuxppc-dev
In-Reply-To: <20200428112517.1402927-1-npiggin@gmail.com>
Hi!
On Tue, Apr 28, 2020 at 09:25:17PM +1000, Nicholas Piggin wrote:
> +config BUILD_BIG_ENDIAN_ELF_V2
> + bool "Build big-endian kernel using ELFv2 ABI (EXPERIMENTAL)"
> + depends on PPC64 && CPU_BIG_ENDIAN && EXPERT
> + default n
> + select BUILD_ELF_V2
> + help
> + This builds the kernel image using the ELFv2 ABI, which has a
> + reduced stack overhead and faster function calls. This does not
> + affect the userspace ABIs.
> +
> + ELFv2 is the standard ABI for little-endian, but for big-endian
> + this is an experimental option that is less tested (kernel and
> + toolchain). This requires gcc 4.9 or newer and binutils 2.24 or
> + newer.
Is it clear that this is only for 64-bit? Maybe this text should fit
that in somewhere?
It's not obvious to people who do not already know that ELFv2 is just
the (nick-)name of a particular ABI, not a new kind of ELF (it is just
version 1 ELF in fact), and that ABI is for 64-bit Power only.
Segher
^ permalink raw reply
* Re: [PATCH net] ibmvnic: Fall back to 16 H_SEND_SUB_CRQ_INDIRECT entries with old FW
From: Juliet Kim @ 2020-04-28 22:29 UTC (permalink / raw)
To: Thomas Falcon, netdev; +Cc: linuxppc-dev
In-Reply-To: <8617ba73-8a05-51c4-e52b-164687cecf07@linux.ibm.com>
On 4/28/20 10:35 AM, Thomas Falcon wrote:
> On 4/27/20 12:33 PM, Juliet Kim wrote:
>> The maximum entries for H_SEND_SUB_CRQ_INDIRECT has increased on
>> some platforms from 16 to 128. If Live Partition Mobility is used
>> to migrate a running OS image from a newer source platform to an
>> older target platform, then H_SEND_SUB_CRQ_INDIRECT will fail with
>> H_PARAMETER if 128 entries are queued.
>>
>> Fix this by falling back to 16 entries if H_PARAMETER is returned
>> from the hcall().
>
> Thanks for the submission, but I am having a hard time believing that this is what is happening since the driver does not support sending multiple frames per hypervisor call at this time. Even if it were the case, this approach would omit frame data needed by the VF, so the second attempt may still fail. Are there system logs available that show the driver is attempting to send transmissions with greater than 16 descriptors?
>
> Thanks,
>
> Tom
>
>
I am trying to confirm.
Juliet
>>
>> Signed-off-by: Juliet Kim <julietk@linux.vnet.ibm.com>
>> ---
>> drivers/net/ethernet/ibm/ibmvnic.c | 11 +++++++++++
>> 1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
>> index 4bd33245bad6..b66c2f26a427 100644
>> --- a/drivers/net/ethernet/ibm/ibmvnic.c
>> +++ b/drivers/net/ethernet/ibm/ibmvnic.c
>> @@ -1656,6 +1656,17 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
>> lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
>> (u64)tx_buff->indir_dma,
>> (u64)num_entries);
>> +
>> + /* Old firmware accepts max 16 num_entries */
>> + if (lpar_rc == H_PARAMETER && num_entries > 16) {
>> + tx_crq.v1.n_crq_elem = 16;
>> + tx_buff->num_entries = 16;
>> + lpar_rc = send_subcrq_indirect(adapter,
>> + handle_array[queue_num],
>> + (u64)tx_buff->indir_dma,
>> + 16);
>> + }
>> +
>> dma_unmap_single(dev, tx_buff->indir_dma,
>> sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
>> } else {
^ permalink raw reply
* [PATCH v4 2/4] hugetlbfs: move hugepagesz= parsing to arch independent code
From: Mike Kravetz @ 2020-04-28 20:56 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Dave Hansen, Heiko Carstens, Peter Xu, Paul Mackerras,
Will Deacon, Mina Almasry, Jonathan Corbet, Christian Borntraeger,
Ingo Molnar, Catalin Marinas, Longpeng, Albert Ou, Vasily Gorbik,
Paul Walmsley, Thomas Gleixner, Gerald Schaefer,
Nitesh Narayan Lal, Randy Dunlap, Palmer Dabbelt, Andrew Morton,
David S . Miller, Mike Kravetz
In-Reply-To: <20200428205614.246260-1-mike.kravetz@oracle.com>
Now that architectures provide arch_hugetlb_valid_size(), parsing
of "hugepagesz=" can be done in architecture independent code.
Create a single routine to handle hugepagesz= parsing and remove
all arch specific routines. We can also remove the interface
hugetlb_bad_size() as this is no longer used outside arch independent
code.
This also provides consistent behavior of hugetlbfs command line
options. The hugepagesz= option should only be specified once for
a specific size, but some architectures allow multiple instances.
This appears to be more of an oversight when code was added by some
architectures to set up ALL huge pages sizes.
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Mina Almasry <almasrymina@google.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Acked-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> [s390]
Acked-by: Will Deacon <will@kernel.org>
---
arch/arm64/mm/hugetlbpage.c | 15 ---------------
arch/powerpc/mm/hugetlbpage.c | 15 ---------------
arch/riscv/mm/hugetlbpage.c | 16 ----------------
arch/s390/mm/hugetlbpage.c | 18 ------------------
arch/sparc/mm/init_64.c | 22 ----------------------
arch/x86/mm/hugetlbpage.c | 16 ----------------
include/linux/hugetlb.h | 1 -
mm/hugetlb.c | 23 +++++++++++++++++------
8 files changed, 17 insertions(+), 109 deletions(-)
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 069b96ee2aec..f706b821aba6 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -476,18 +476,3 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long ps = memparse(opt, &opt);
-
- if (arch_hugetlb_valid_size(ps)) {
- add_huge_page_size(ps);
- return 1;
- }
-
- hugetlb_bad_size();
- pr_err("hugepagesz: Unsupported page size %lu K\n", ps >> 10);
- return 0;
-}
-__setup("hugepagesz=", setup_hugepagesz);
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index de54d2a37830..2c3fa0a7787b 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -589,21 +589,6 @@ static int __init add_huge_page_size(unsigned long long size)
return 0;
}
-static int __init hugepage_setup_sz(char *str)
-{
- unsigned long long size;
-
- size = memparse(str, &str);
-
- if (add_huge_page_size(size) != 0) {
- hugetlb_bad_size();
- pr_err("Invalid huge page size specified(%llu)\n", size);
- }
-
- return 1;
-}
-__setup("hugepagesz=", hugepage_setup_sz);
-
static int __init hugetlbpage_init(void)
{
bool configured = false;
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index da1f516bc451..4e5d7e9f0eef 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -22,22 +22,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long ps = memparse(opt, &opt);
-
- if (arch_hugetlb_valid_size(ps)) {
- hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
- return 1;
- }
-
- hugetlb_bad_size();
- pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
- return 0;
-
-}
-__setup("hugepagesz=", setup_hugepagesz);
-
#ifdef CONFIG_CONTIG_ALLOC
static __init int gigantic_pages_init(void)
{
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index ac25b207624c..242dfc0d462d 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -261,24 +261,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long size;
- char *string = opt;
-
- size = memparse(opt, &opt);
- if (arch_hugetlb_valid_size(size)) {
- hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
- } else {
- hugetlb_bad_size();
- pr_err("hugepagesz= specifies an unsupported page size %s\n",
- string);
- return 0;
- }
- return 1;
-}
-__setup("hugepagesz=", setup_hugepagesz);
-
static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 2bfe8e22b706..4618f96fd30f 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -397,28 +397,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return true;
}
-
-static int __init setup_hugepagesz(char *string)
-{
- unsigned long long hugepage_size;
- int rc = 0;
-
- hugepage_size = memparse(string, &string);
-
- if (!arch_hugetlb_valid_size((unsigned long)hugepage_size)) {
- hugetlb_bad_size();
- pr_err("hugepagesz=%llu not supported by MMU.\n",
- hugepage_size);
- goto out;
- }
-
- add_huge_page_size(hugepage_size);
- rc = 1;
-
-out:
- return rc;
-}
-__setup("hugepagesz=", setup_hugepagesz);
#endif /* CONFIG_HUGETLB_PAGE */
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 1c4372bfe782..937d640a89e3 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -191,22 +191,6 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
return false;
}
-static __init int setup_hugepagesz(char *opt)
-{
- unsigned long ps = memparse(opt, &opt);
-
- if (arch_hugetlb_valid_size(ps)) {
- hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
- } else {
- hugetlb_bad_size();
- printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
- ps >> 20);
- return 0;
- }
- return 1;
-}
-__setup("hugepagesz=", setup_hugepagesz);
-
#ifdef CONFIG_CONTIG_ALLOC
static __init int gigantic_pages_init(void)
{
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 2eb15f5ab01e..0c13706054ef 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -519,7 +519,6 @@ int huge_add_to_page_cache(struct page *page, struct address_space *mapping,
int __init __alloc_bootmem_huge_page(struct hstate *h);
int __init alloc_bootmem_huge_page(struct hstate *h);
-void __init hugetlb_bad_size(void);
void __init hugetlb_add_hstate(unsigned order);
bool __init arch_hugetlb_valid_size(unsigned long size);
struct hstate *size_to_hstate(unsigned long size);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 63ca4241ea87..6a8454bc2917 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3262,12 +3262,6 @@ bool __init __attribute((weak)) arch_hugetlb_valid_size(unsigned long size)
return size == HPAGE_SIZE;
}
-/* Should be called on processing a hugepagesz=... option */
-void __init hugetlb_bad_size(void)
-{
- parsed_valid_hugepagesz = false;
-}
-
void __init hugetlb_add_hstate(unsigned int order)
{
struct hstate *h;
@@ -3337,6 +3331,23 @@ static int __init hugetlb_nrpages_setup(char *s)
}
__setup("hugepages=", hugetlb_nrpages_setup);
+static int __init hugepagesz_setup(char *s)
+{
+ unsigned long size;
+
+ size = (unsigned long)memparse(s, NULL);
+
+ if (!arch_hugetlb_valid_size(size)) {
+ parsed_valid_hugepagesz = false;
+ pr_err("HugeTLB: unsupported hugepagesz %s\n", s);
+ return 0;
+ }
+
+ hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
+ return 1;
+}
+__setup("hugepagesz=", hugepagesz_setup);
+
static int __init default_hugepagesz_setup(char *s)
{
unsigned long size;
--
2.25.4
^ permalink raw reply related
* [PATCH v4 3/4] hugetlbfs: remove hugetlb_add_hstate() warning for existing hstate
From: Mike Kravetz @ 2020-04-28 20:56 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Dave Hansen, Heiko Carstens, Peter Xu, Paul Mackerras,
Will Deacon, Mina Almasry, Anders Roxell, Jonathan Corbet,
Christian Borntraeger, Ingo Molnar, Catalin Marinas, Longpeng,
Albert Ou, Vasily Gorbik, Paul Walmsley, Thomas Gleixner,
Gerald Schaefer, Nitesh Narayan Lal, Randy Dunlap, Palmer Dabbelt,
Andrew Morton, David S . Miller, Mike Kravetz
In-Reply-To: <20200428205614.246260-1-mike.kravetz@oracle.com>
The routine hugetlb_add_hstate prints a warning if the hstate already
exists. This was originally done as part of kernel command line
parsing. If 'hugepagesz=' was specified more than once, the warning
pr_warn("hugepagesz= specified twice, ignoring\n");
would be printed.
Some architectures want to enable all huge page sizes. They would
call hugetlb_add_hstate for all supported sizes. However, this was
done after command line processing and as a result hstates could have
already been created for some sizes. To make sure no warning were
printed, there would often be code like:
if (!size_to_hstate(size)
hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT)
The only time we want to print the warning is as the result of command
line processing. So, remove the warning from hugetlb_add_hstate and
add it to the single arch independent routine processing "hugepagesz=".
After this, calls to size_to_hstate() in arch specific code can be
removed and hugetlb_add_hstate can be called without worrying about
warning messages.
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Mina Almasry <almasrymina@google.com>
Acked-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> [s390]
Acked-by: Will Deacon <will@kernel.org>
Tested-by: Anders Roxell <anders.roxell@linaro.org>
---
arch/arm64/mm/hugetlbpage.c | 16 ++++------------
arch/powerpc/mm/hugetlbpage.c | 3 +--
arch/riscv/mm/hugetlbpage.c | 2 +-
arch/sparc/mm/init_64.c | 19 ++++---------------
arch/x86/mm/hugetlbpage.c | 2 +-
mm/hugetlb.c | 9 ++++++---
6 files changed, 17 insertions(+), 34 deletions(-)
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index f706b821aba6..14bed8f4674a 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -441,22 +441,14 @@ void huge_ptep_clear_flush(struct vm_area_struct *vma,
clear_flush(vma->vm_mm, addr, ptep, pgsize, ncontig);
}
-static void __init add_huge_page_size(unsigned long size)
-{
- if (size_to_hstate(size))
- return;
-
- hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
-}
-
static int __init hugetlbpage_init(void)
{
#ifdef CONFIG_ARM64_4K_PAGES
- add_huge_page_size(PUD_SIZE);
+ hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
#endif
- add_huge_page_size(CONT_PMD_SIZE);
- add_huge_page_size(PMD_SIZE);
- add_huge_page_size(CONT_PTE_SIZE);
+ hugetlb_add_hstate((CONT_PMD_SHIFT + PMD_SHIFT) - PAGE_SHIFT);
+ hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate((CONT_PTE_SHIFT + PAGE_SHIFT) - PAGE_SHIFT);
return 0;
}
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 2c3fa0a7787b..4d5ed1093615 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -584,8 +584,7 @@ static int __init add_huge_page_size(unsigned long long size)
if (!arch_hugetlb_valid_size((unsigned long)size))
return -EINVAL;
- if (!size_to_hstate(size))
- hugetlb_add_hstate(shift - PAGE_SHIFT);
+ hugetlb_add_hstate(shift - PAGE_SHIFT);
return 0;
}
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index 4e5d7e9f0eef..932dadfdca54 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -26,7 +26,7 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
static __init int gigantic_pages_init(void)
{
/* With CONTIG_ALLOC, we can allocate gigantic pages at runtime */
- if (IS_ENABLED(CONFIG_64BIT) && !size_to_hstate(1UL << PUD_SHIFT))
+ if (IS_ENABLED(CONFIG_64BIT))
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
return 0;
}
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 4618f96fd30f..ae819a16d07a 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -325,23 +325,12 @@ static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_inde
}
#ifdef CONFIG_HUGETLB_PAGE
-static void __init add_huge_page_size(unsigned long size)
-{
- unsigned int order;
-
- if (size_to_hstate(size))
- return;
-
- order = ilog2(size) - PAGE_SHIFT;
- hugetlb_add_hstate(order);
-}
-
static int __init hugetlbpage_init(void)
{
- add_huge_page_size(1UL << HPAGE_64K_SHIFT);
- add_huge_page_size(1UL << HPAGE_SHIFT);
- add_huge_page_size(1UL << HPAGE_256MB_SHIFT);
- add_huge_page_size(1UL << HPAGE_2GB_SHIFT);
+ hugetlb_add_hstate(HPAGE_64K_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(HPAGE_256MB_SHIFT - PAGE_SHIFT);
+ hugetlb_add_hstate(HPAGE_2GB_SHIFT - PAGE_SHIFT);
return 0;
}
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 937d640a89e3..cf5781142716 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -195,7 +195,7 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
static __init int gigantic_pages_init(void)
{
/* With compaction or CMA we can allocate gigantic pages at runtime */
- if (boot_cpu_has(X86_FEATURE_GBPAGES) && !size_to_hstate(1UL << PUD_SHIFT))
+ if (boot_cpu_has(X86_FEATURE_GBPAGES))
hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
return 0;
}
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 6a8454bc2917..2ae0e506cfc7 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3222,8 +3222,7 @@ static int __init hugetlb_init(void)
}
default_hstate_size = HPAGE_SIZE;
- if (!size_to_hstate(default_hstate_size))
- hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
+ hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
}
default_hstate_idx = hstate_index(size_to_hstate(default_hstate_size));
if (default_hstate_max_huge_pages) {
@@ -3268,7 +3267,6 @@ void __init hugetlb_add_hstate(unsigned int order)
unsigned long i;
if (size_to_hstate(PAGE_SIZE << order)) {
- pr_warn("hugepagesz= specified twice, ignoring\n");
return;
}
BUG_ON(hugetlb_max_hstate >= HUGE_MAX_HSTATE);
@@ -3343,6 +3341,11 @@ static int __init hugepagesz_setup(char *s)
return 0;
}
+ if (size_to_hstate(size)) {
+ pr_warn("HugeTLB: hugepagesz %s specified twice, ignoring\n", s);
+ return 0;
+ }
+
hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
return 1;
}
--
2.25.4
^ permalink raw reply related
* [PATCH v4 4/4] hugetlbfs: clean up command line processing
From: Mike Kravetz @ 2020-04-28 20:56 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Dave Hansen, Heiko Carstens, Peter Xu, Paul Mackerras,
Sandipan Das, Will Deacon, Mina Almasry, Jonathan Corbet,
Christian Borntraeger, Ingo Molnar, Catalin Marinas, Longpeng,
Albert Ou, Vasily Gorbik, Paul Walmsley, Thomas Gleixner,
Gerald Schaefer, Nitesh Narayan Lal, Randy Dunlap, Palmer Dabbelt,
Andrew Morton, David S . Miller, Mike Kravetz
In-Reply-To: <20200428205614.246260-1-mike.kravetz@oracle.com>
With all hugetlb page processing done in a single file clean up code.
- Make code match desired semantics
- Update documentation with semantics
- Make all warnings and errors messages start with 'HugeTLB:'.
- Consistently name command line parsing routines.
- Warn if !hugepages_supported() and command line parameters have
been specified.
- Add comments to code
- Describe some of the subtle interactions
- Describe semantics of command line arguments
This patch also fixes issues with implicitly setting the number of
gigantic huge pages to preallocate. Previously on X86 command line,
hugepages=2 default_hugepagesz=1G
would result in zero 1G pages being preallocated and,
# grep HugePages_Total /proc/meminfo
HugePages_Total: 0
# sysctl -a | grep nr_hugepages
vm.nr_hugepages = 2
vm.nr_hugepages_mempolicy = 2
# cat /proc/sys/vm/nr_hugepages
2
After this patch 2 gigantic pages will be preallocated and all the
proc, sysfs, sysctl and meminfo files will accurately reflect this.
To address the issue with gigantic pages, a small change in behavior
was made to command line processing. Previously the command line,
hugepages=128 default_hugepagesz=2M hugepagesz=2M hugepages=256
would result in the allocation of 256 2M huge pages. The value 128
would be ignored without any warning. After this patch, 128 2M pages
will be allocated and a warning message will be displayed indicating
the value of 256 is ignored. This change in behavior is required
because allocation of implicitly specified gigantic pages must be done
when the default_hugepagesz= is encountered for gigantic pages.
Previously the code waited until later in the boot process (hugetlb_init),
to allocate pages of default size. However the bootmem allocator required
for gigantic allocations is not available at this time.
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> [s390]
Acked-by: Will Deacon <will@kernel.org>
Tested-by: Sandipan Das <sandipan@linux.ibm.com>
---
.../admin-guide/kernel-parameters.txt | 40 +++--
Documentation/admin-guide/mm/hugetlbpage.rst | 35 ++++
mm/hugetlb.c | 149 ++++++++++++++----
3 files changed, 179 insertions(+), 45 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 7bc83f3d9bdf..cbe657b86d0e 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -834,12 +834,15 @@
See also Documentation/networking/decnet.txt.
default_hugepagesz=
- [same as hugepagesz=] The size of the default
- HugeTLB page size. This is the size represented by
- the legacy /proc/ hugepages APIs, used for SHM, and
- default size when mounting hugetlbfs filesystems.
- Defaults to the default architecture's huge page size
- if not specified.
+ [HW] The size of the default HugeTLB page. This is
+ the size represented by the legacy /proc/ hugepages
+ APIs. In addition, this is the default hugetlb size
+ used for shmget(), mmap() and mounting hugetlbfs
+ filesystems. If not specified, defaults to the
+ architecture's default huge page size. Huge page
+ sizes are architecture dependent. See also
+ Documentation/admin-guide/mm/hugetlbpage.rst.
+ Format: size[KMG]
deferred_probe_timeout=
[KNL] Debugging option to set a timeout in seconds for
@@ -1479,13 +1482,24 @@
hugepages using the cma allocator. If enabled, the
boot-time allocation of gigantic hugepages is skipped.
- hugepages= [HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
- hugepagesz= [HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
- On x86-64 and powerpc, this option can be specified
- multiple times interleaved with hugepages= to reserve
- huge pages of different sizes. Valid pages sizes on
- x86-64 are 2M (when the CPU supports "pse") and 1G
- (when the CPU supports the "pdpe1gb" cpuinfo flag).
+ hugepages= [HW] Number of HugeTLB pages to allocate at boot.
+ If this follows hugepagesz (below), it specifies
+ the number of pages of hugepagesz to be allocated.
+ If this is the first HugeTLB parameter on the command
+ line, it specifies the number of pages to allocate for
+ the default huge page size. See also
+ Documentation/admin-guide/mm/hugetlbpage.rst.
+ Format: <integer>
+
+ hugepagesz=
+ [HW] The size of the HugeTLB pages. This is used in
+ conjunction with hugepages (above) to allocate huge
+ pages of a specific size at boot. The pair
+ hugepagesz=X hugepages=Y can be specified once for
+ each supported huge page size. Huge page sizes are
+ architecture dependent. See also
+ Documentation/admin-guide/mm/hugetlbpage.rst.
+ Format: size[KMG]
hung_task_panic=
[KNL] Should the hung task detector generate panics.
diff --git a/Documentation/admin-guide/mm/hugetlbpage.rst b/Documentation/admin-guide/mm/hugetlbpage.rst
index 1cc0bc78d10e..5026e58826e2 100644
--- a/Documentation/admin-guide/mm/hugetlbpage.rst
+++ b/Documentation/admin-guide/mm/hugetlbpage.rst
@@ -100,6 +100,41 @@ with a huge page size selection parameter "hugepagesz=<size>". <size> must
be specified in bytes with optional scale suffix [kKmMgG]. The default huge
page size may be selected with the "default_hugepagesz=<size>" boot parameter.
+Hugetlb boot command line parameter semantics
+hugepagesz - Specify a huge page size. Used in conjunction with hugepages
+ parameter to preallocate a number of huge pages of the specified
+ size. Hence, hugepagesz and hugepages are typically specified in
+ pairs such as:
+ hugepagesz=2M hugepages=512
+ hugepagesz can only be specified once on the command line for a
+ specific huge page size. Valid huge page sizes are architecture
+ dependent.
+hugepages - Specify the number of huge pages to preallocate. This typically
+ follows a valid hugepagesz or default_hugepagesz parameter. However,
+ if hugepages is the first or only hugetlb command line parameter it
+ implicitly specifies the number of huge pages of default size to
+ allocate. If the number of huge pages of default size is implicitly
+ specified, it can not be overwritten by a hugepagesz,hugepages
+ parameter pair for the default size.
+ For example, on an architecture with 2M default huge page size:
+ hugepages=256 hugepagesz=2M hugepages=512
+ will result in 256 2M huge pages being allocated and a warning message
+ indicating that the hugepages=512 parameter is ignored. If a hugepages
+ parameter is preceded by an invalid hugepagesz parameter, it will
+ be ignored.
+default_hugepagesz - Specify the default huge page size. This parameter can
+ only be specified once on the command line. default_hugepagesz can
+ optionally be followed by the hugepages parameter to preallocate a
+ specific number of huge pages of default size. The number of default
+ sized huge pages to preallocate can also be implicitly specified as
+ mentioned in the hugepages section above. Therefore, on an
+ architecture with 2M default huge page size:
+ hugepages=256
+ default_hugepagesz=2M hugepages=256
+ hugepages=256 default_hugepagesz=2M
+ will all result in 256 2M huge pages being allocated. Valid default
+ huge page size is architecture dependent.
+
When multiple huge page sizes are supported, ``/proc/sys/vm/nr_hugepages``
indicates the current number of pre-allocated huge pages of the default size.
Thus, one can use the following command to dynamically allocate/deallocate
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 2ae0e506cfc7..8852b0b12270 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -59,8 +59,8 @@ __initdata LIST_HEAD(huge_boot_pages);
/* for command line parsing */
static struct hstate * __initdata parsed_hstate;
static unsigned long __initdata default_hstate_max_huge_pages;
-static unsigned long __initdata default_hstate_size;
static bool __initdata parsed_valid_hugepagesz = true;
+static bool __initdata parsed_default_hugepagesz;
/*
* Protects updates to hugepage_freelists, hugepage_activelist, nr_huge_pages,
@@ -3060,7 +3060,7 @@ static void __init hugetlb_sysfs_init(void)
err = hugetlb_sysfs_add_hstate(h, hugepages_kobj,
hstate_kobjs, &hstate_attr_group);
if (err)
- pr_err("Hugetlb: Unable to add hstate %s", h->name);
+ pr_err("HugeTLB: Unable to add hstate %s", h->name);
}
}
@@ -3164,7 +3164,7 @@ static void hugetlb_register_node(struct node *node)
nhs->hstate_kobjs,
&per_node_hstate_attr_group);
if (err) {
- pr_err("Hugetlb: Unable to add hstate %s for node %d\n",
+ pr_err("HugeTLB: Unable to add hstate %s for node %d\n",
h->name, node->dev.id);
hugetlb_unregister_node(node);
break;
@@ -3212,22 +3212,41 @@ static int __init hugetlb_init(void)
{
int i;
- if (!hugepages_supported())
+ if (!hugepages_supported()) {
+ if (hugetlb_max_hstate || default_hstate_max_huge_pages)
+ pr_warn("HugeTLB: huge pages not supported, ignoring associated command-line parameters\n");
return 0;
+ }
- if (!size_to_hstate(default_hstate_size)) {
- if (default_hstate_size != 0) {
- pr_err("HugeTLB: unsupported default_hugepagesz %lu. Reverting to %lu\n",
- default_hstate_size, HPAGE_SIZE);
+ /*
+ * Make sure HPAGE_SIZE (HUGETLB_PAGE_ORDER) hstate exists. Some
+ * architectures depend on setup being done here.
+ */
+ hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
+ if (!parsed_default_hugepagesz) {
+ /*
+ * If we did not parse a default huge page size, set
+ * default_hstate_idx to HPAGE_SIZE hstate. And, if the
+ * number of huge pages for this default size was implicitly
+ * specified, set that here as well.
+ * Note that the implicit setting will overwrite an explicit
+ * setting. A warning will be printed in this case.
+ */
+ default_hstate_idx = hstate_index(size_to_hstate(HPAGE_SIZE));
+ if (default_hstate_max_huge_pages) {
+ if (default_hstate.max_huge_pages) {
+ char buf[32];
+
+ string_get_size(huge_page_size(&default_hstate),
+ 1, STRING_UNITS_2, buf, 32);
+ pr_warn("HugeTLB: Ignoring hugepages=%lu associated with %s page size\n",
+ default_hstate.max_huge_pages, buf);
+ pr_warn("HugeTLB: Using hugepages=%lu for number of default huge pages\n",
+ default_hstate_max_huge_pages);
+ }
+ default_hstate.max_huge_pages =
+ default_hstate_max_huge_pages;
}
-
- default_hstate_size = HPAGE_SIZE;
- hugetlb_add_hstate(HUGETLB_PAGE_ORDER);
- }
- default_hstate_idx = hstate_index(size_to_hstate(default_hstate_size));
- if (default_hstate_max_huge_pages) {
- if (!default_hstate.max_huge_pages)
- default_hstate.max_huge_pages = default_hstate_max_huge_pages;
}
hugetlb_cma_check();
@@ -3287,20 +3306,29 @@ void __init hugetlb_add_hstate(unsigned int order)
parsed_hstate = h;
}
-static int __init hugetlb_nrpages_setup(char *s)
+/*
+ * hugepages command line processing
+ * hugepages normally follows a valid hugepagsz or default_hugepagsz
+ * specification. If not, ignore the hugepages value. hugepages can also
+ * be the first huge page command line option in which case it implicitly
+ * specifies the number of huge pages for the default size.
+ */
+static int __init hugepages_setup(char *s)
{
unsigned long *mhp;
static unsigned long *last_mhp;
if (!parsed_valid_hugepagesz) {
- pr_warn("hugepages = %s preceded by "
- "an unsupported hugepagesz, ignoring\n", s);
+ pr_warn("HugeTLB: hugepages=%s does not follow a valid hugepagesz, ignoring\n", s);
parsed_valid_hugepagesz = true;
- return 1;
+ return 0;
}
+
/*
- * !hugetlb_max_hstate means we haven't parsed a hugepagesz= parameter yet,
- * so this hugepages= parameter goes to the "default hstate".
+ * !hugetlb_max_hstate means we haven't parsed a hugepagesz= parameter
+ * yet, so this hugepages= parameter goes to the "default hstate".
+ * Otherwise, it goes with the previously parsed hugepagesz or
+ * default_hugepagesz.
*/
else if (!hugetlb_max_hstate)
mhp = &default_hstate_max_huge_pages;
@@ -3308,8 +3336,8 @@ static int __init hugetlb_nrpages_setup(char *s)
mhp = &parsed_hstate->max_huge_pages;
if (mhp == last_mhp) {
- pr_warn("hugepages= specified twice without interleaving hugepagesz=, ignoring\n");
- return 1;
+ pr_warn("HugeTLB: hugepages= specified twice without interleaving hugepagesz=, ignoring hugepages=%s\n", s);
+ return 0;
}
if (sscanf(s, "%lu", mhp) <= 0)
@@ -3327,42 +3355,99 @@ static int __init hugetlb_nrpages_setup(char *s)
return 1;
}
-__setup("hugepages=", hugetlb_nrpages_setup);
+__setup("hugepages=", hugepages_setup);
+/*
+ * hugepagesz command line processing
+ * A specific huge page size can only be specified once with hugepagesz.
+ * hugepagesz is followed by hugepages on the command line. The global
+ * variable 'parsed_valid_hugepagesz' is used to determine if prior
+ * hugepagesz argument was valid.
+ */
static int __init hugepagesz_setup(char *s)
{
unsigned long size;
+ struct hstate *h;
+ parsed_valid_hugepagesz = false;
size = (unsigned long)memparse(s, NULL);
if (!arch_hugetlb_valid_size(size)) {
- parsed_valid_hugepagesz = false;
- pr_err("HugeTLB: unsupported hugepagesz %s\n", s);
+ pr_err("HugeTLB: unsupported hugepagesz=%s\n", s);
return 0;
}
- if (size_to_hstate(size)) {
- pr_warn("HugeTLB: hugepagesz %s specified twice, ignoring\n", s);
- return 0;
+ h = size_to_hstate(size);
+ if (h) {
+ /*
+ * hstate for this size already exists. This is normally
+ * an error, but is allowed if the existing hstate is the
+ * default hstate. More specifically, it is only allowed if
+ * the number of huge pages for the default hstate was not
+ * previously specified.
+ */
+ if (!parsed_default_hugepagesz || h != &default_hstate ||
+ default_hstate.max_huge_pages) {
+ pr_warn("HugeTLB: hugepagesz=%s specified twice, ignoring\n", s);
+ return 0;
+ }
+
+ /*
+ * No need to call hugetlb_add_hstate() as hstate already
+ * exists. But, do set parsed_hstate so that a following
+ * hugepages= parameter will be applied to this hstate.
+ */
+ parsed_hstate = h;
+ parsed_valid_hugepagesz = true;
+ return 1;
}
hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
+ parsed_valid_hugepagesz = true;
return 1;
}
__setup("hugepagesz=", hugepagesz_setup);
+/*
+ * default_hugepagesz command line input
+ * Only one instance of default_hugepagesz allowed on command line.
+ */
static int __init default_hugepagesz_setup(char *s)
{
unsigned long size;
+ parsed_valid_hugepagesz = false;
+ if (parsed_default_hugepagesz) {
+ pr_err("HugeTLB: default_hugepagesz previously specified, ignoring %s\n", s);
+ return 0;
+ }
+
size = (unsigned long)memparse(s, NULL);
if (!arch_hugetlb_valid_size(size)) {
- pr_err("HugeTLB: unsupported default_hugepagesz %s\n", s);
+ pr_err("HugeTLB: unsupported default_hugepagesz=%s\n", s);
return 0;
}
- default_hstate_size = size;
+ hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
+ parsed_valid_hugepagesz = true;
+ parsed_default_hugepagesz = true;
+ default_hstate_idx = hstate_index(size_to_hstate(size));
+
+ /*
+ * The number of default huge pages (for this size) could have been
+ * specified as the first hugetlb parameter: hugepages=X. If so,
+ * then default_hstate_max_huge_pages is set. If the default huge
+ * page size is gigantic (>= MAX_ORDER), then the pages must be
+ * allocated here from bootmem allocator.
+ */
+ if (default_hstate_max_huge_pages) {
+ default_hstate.max_huge_pages = default_hstate_max_huge_pages;
+ if (hstate_is_gigantic(&default_hstate))
+ hugetlb_hstate_alloc_pages(&default_hstate);
+ default_hstate_max_huge_pages = 0;
+ }
+
return 1;
}
__setup("default_hugepagesz=", default_hugepagesz_setup);
--
2.25.4
^ permalink raw reply related
* [PATCH v4 0/4] Clean up hugetlb boot command line processing
From: Mike Kravetz @ 2020-04-28 20:56 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Dave Hansen, Heiko Carstens, Peter Xu, Paul Mackerras,
Will Deacon, Mina Almasry, Jonathan Corbet, Christian Borntraeger,
Ingo Molnar, Catalin Marinas, Longpeng, Albert Ou, Vasily Gorbik,
Paul Walmsley, Thomas Gleixner, Nitesh Narayan Lal, Randy Dunlap,
Palmer Dabbelt, Andrew Morton, David S . Miller, Mike Kravetz
v4 -
Fixed huge page order definitions for arm64 (Qian Cai)
Removed hugepages_supported() checks in command line processing as
powerpc does not set hugepages_supported until later in boot (Sandipan)
Added Acks, Reviews and Tested (Will, Gerald, Anders, Sandipan)
v3 -
Used weak attribute method of defining arch_hugetlb_valid_size.
This eliminates changes to arch specific hugetlb.h files (Peter)
Updated documentation (Peter, Randy)
Fixed handling of implicitly specified gigantic page preallocation
in existing code and removed documentation of such. There is now
no difference between handling of gigantic and non-gigantic pages.
(Peter, Nitesh).
This requires the most review as there is a small change to
undocumented behavior. See patch 4 commit message for details.
Added Acks and Reviews (Mina, Peter)
v2 -
Fix build errors with patch 1 (Will)
Change arch_hugetlb_valid_size arg to unsigned long and remove
irrelevant 'extern' keyword (Christophe)
Documentation and other misc changes (Randy, Christophe, Mina)
Do not process command line options if !hugepages_supported()
(Dave, but it sounds like we may want to additional changes to
hugepages_supported() for x86? If that is needed I would prefer
a separate patch.)
Longpeng(Mike) reported a weird message from hugetlb command line processing
and proposed a solution [1]. While the proposed patch does address the
specific issue, there are other related issues in command line processing.
As hugetlbfs evolved, updates to command line processing have been made to
meet immediate needs and not necessarily in a coordinated manner. The result
is that some processing is done in arch specific code, some is done in arch
independent code and coordination is problematic. Semantics can vary between
architectures.
The patch series does the following:
- Define arch specific arch_hugetlb_valid_size routine used to validate
passed huge page sizes.
- Move hugepagesz= command line parsing out of arch specific code and into
an arch independent routine.
- Clean up command line processing to follow desired semantics and
document those semantics.
[1] https://lore.kernel.org/linux-mm/20200305033014.1152-1-longpeng2@huawei.com
Mike Kravetz (4):
hugetlbfs: add arch_hugetlb_valid_size
hugetlbfs: move hugepagesz= parsing to arch independent code
hugetlbfs: remove hugetlb_add_hstate() warning for existing hstate
hugetlbfs: clean up command line processing
.../admin-guide/kernel-parameters.txt | 40 ++--
Documentation/admin-guide/mm/hugetlbpage.rst | 35 ++++
arch/arm64/mm/hugetlbpage.c | 30 +--
arch/powerpc/mm/hugetlbpage.c | 30 +--
arch/riscv/mm/hugetlbpage.c | 24 +--
arch/s390/mm/hugetlbpage.c | 24 +--
arch/sparc/mm/init_64.c | 43 +----
arch/x86/mm/hugetlbpage.c | 23 +--
include/linux/hugetlb.h | 2 +-
mm/hugetlb.c | 180 ++++++++++++++----
10 files changed, 260 insertions(+), 171 deletions(-)
--
2.25.4
^ permalink raw reply
* [PATCH v4 1/4] hugetlbfs: add arch_hugetlb_valid_size
From: Mike Kravetz @ 2020-04-28 20:56 UTC (permalink / raw)
To: linux-mm, linux-kernel, linux-arm-kernel, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, linux-doc
Cc: Dave Hansen, Heiko Carstens, Peter Xu, Paul Mackerras,
Will Deacon, Mina Almasry, Jonathan Corbet, Christian Borntraeger,
Ingo Molnar, Catalin Marinas, Longpeng, Albert Ou, Vasily Gorbik,
Paul Walmsley, Thomas Gleixner, Gerald Schaefer,
Nitesh Narayan Lal, Randy Dunlap, Palmer Dabbelt, Andrew Morton,
David S . Miller, Mike Kravetz
In-Reply-To: <20200428205614.246260-1-mike.kravetz@oracle.com>
The architecture independent routine hugetlb_default_setup sets up
the default huge pages size. It has no way to verify if the passed
value is valid, so it accepts it and attempts to validate at a later
time. This requires undocumented cooperation between the arch specific
and arch independent code.
For architectures that support more than one huge page size, provide
a routine arch_hugetlb_valid_size to validate a huge page size.
hugetlb_default_setup can use this to validate passed values.
arch_hugetlb_valid_size will also be used in a subsequent patch to
move processing of the "hugepagesz=" in arch specific code to a common
routine in arch independent code.
Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
Acked-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> [s390]
Acked-by: Will Deacon <will@kernel.org>
---
arch/arm64/mm/hugetlbpage.c | 17 +++++++++++++----
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/mm/hugetlbpage.c | 26 +++++++++++++++++---------
arch/s390/mm/hugetlbpage.c | 16 ++++++++++++----
arch/sparc/mm/init_64.c | 24 ++++++++++++++++--------
arch/x86/mm/hugetlbpage.c | 17 +++++++++++++----
include/linux/hugetlb.h | 1 +
mm/hugetlb.c | 21 ++++++++++++++++++---
8 files changed, 103 insertions(+), 39 deletions(-)
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index bbeb6a5a6ba6..069b96ee2aec 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -462,17 +462,26 @@ static int __init hugetlbpage_init(void)
}
arch_initcall(hugetlbpage_init);
-static __init int setup_hugepagesz(char *opt)
+bool __init arch_hugetlb_valid_size(unsigned long size)
{
- unsigned long ps = memparse(opt, &opt);
-
- switch (ps) {
+ switch (size) {
#ifdef CONFIG_ARM64_4K_PAGES
case PUD_SIZE:
#endif
case CONT_PMD_SIZE:
case PMD_SIZE:
case CONT_PTE_SIZE:
+ return true;
+ }
+
+ return false;
+}
+
+static __init int setup_hugepagesz(char *opt)
+{
+ unsigned long ps = memparse(opt, &opt);
+
+ if (arch_hugetlb_valid_size(ps)) {
add_huge_page_size(ps);
return 1;
}
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 33b3461d91e8..de54d2a37830 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -558,7 +558,7 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
return vma_kernel_pagesize(vma);
}
-static int __init add_huge_page_size(unsigned long long size)
+bool __init arch_hugetlb_valid_size(unsigned long size)
{
int shift = __ffs(size);
int mmu_psize;
@@ -566,20 +566,26 @@ static int __init add_huge_page_size(unsigned long long size)
/* Check that it is a page size supported by the hardware and
* that it fits within pagetable and slice limits. */
if (size <= PAGE_SIZE || !is_power_of_2(size))
- return -EINVAL;
+ return false;
mmu_psize = check_and_get_huge_psize(shift);
if (mmu_psize < 0)
- return -EINVAL;
+ return false;
BUG_ON(mmu_psize_defs[mmu_psize].shift != shift);
- /* Return if huge page size has already been setup */
- if (size_to_hstate(size))
- return 0;
+ return true;
+}
- hugetlb_add_hstate(shift - PAGE_SHIFT);
+static int __init add_huge_page_size(unsigned long long size)
+{
+ int shift = __ffs(size);
+
+ if (!arch_hugetlb_valid_size((unsigned long)size))
+ return -EINVAL;
+ if (!size_to_hstate(size))
+ hugetlb_add_hstate(shift - PAGE_SHIFT);
return 0;
}
diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c
index a6189ed36c5f..da1f516bc451 100644
--- a/arch/riscv/mm/hugetlbpage.c
+++ b/arch/riscv/mm/hugetlbpage.c
@@ -12,21 +12,29 @@ int pmd_huge(pmd_t pmd)
return pmd_leaf(pmd);
}
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+ if (size == HPAGE_SIZE)
+ return true;
+ else if (IS_ENABLED(CONFIG_64BIT) && size == PUD_SIZE)
+ return true;
+ else
+ return false;
+}
+
static __init int setup_hugepagesz(char *opt)
{
unsigned long ps = memparse(opt, &opt);
- if (ps == HPAGE_SIZE) {
- hugetlb_add_hstate(HPAGE_SHIFT - PAGE_SHIFT);
- } else if (IS_ENABLED(CONFIG_64BIT) && ps == PUD_SIZE) {
- hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
- } else {
- hugetlb_bad_size();
- pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
- return 0;
+ if (arch_hugetlb_valid_size(ps)) {
+ hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
+ return 1;
}
- return 1;
+ hugetlb_bad_size();
+ pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
+ return 0;
+
}
__setup("hugepagesz=", setup_hugepagesz);
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index f01daddcbc5e..ac25b207624c 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -251,16 +251,24 @@ follow_huge_pud(struct mm_struct *mm, unsigned long address,
return pud_page(*pud) + ((address & ~PUD_MASK) >> PAGE_SHIFT);
}
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+ if (MACHINE_HAS_EDAT1 && size == PMD_SIZE)
+ return true;
+ else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE)
+ return true;
+ else
+ return false;
+}
+
static __init int setup_hugepagesz(char *opt)
{
unsigned long size;
char *string = opt;
size = memparse(opt, &opt);
- if (MACHINE_HAS_EDAT1 && size == PMD_SIZE) {
- hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
- } else if (MACHINE_HAS_EDAT2 && size == PUD_SIZE) {
- hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+ if (arch_hugetlb_valid_size(size)) {
+ hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT);
} else {
hugetlb_bad_size();
pr_err("hugepagesz= specifies an unsupported page size %s\n",
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 1cf0d666dea3..2bfe8e22b706 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -360,16 +360,11 @@ static void __init pud_huge_patch(void)
__asm__ __volatile__("flush %0" : : "r" (addr));
}
-static int __init setup_hugepagesz(char *string)
+bool __init arch_hugetlb_valid_size(unsigned long size)
{
- unsigned long long hugepage_size;
- unsigned int hugepage_shift;
+ unsigned int hugepage_shift = ilog2(size);
unsigned short hv_pgsz_idx;
unsigned int hv_pgsz_mask;
- int rc = 0;
-
- hugepage_size = memparse(string, &string);
- hugepage_shift = ilog2(hugepage_size);
switch (hugepage_shift) {
case HPAGE_16GB_SHIFT:
@@ -397,7 +392,20 @@ static int __init setup_hugepagesz(char *string)
hv_pgsz_mask = 0;
}
- if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U) {
+ if ((hv_pgsz_mask & cpu_pgsz_mask) == 0U)
+ return false;
+
+ return true;
+}
+
+static int __init setup_hugepagesz(char *string)
+{
+ unsigned long long hugepage_size;
+ int rc = 0;
+
+ hugepage_size = memparse(string, &string);
+
+ if (!arch_hugetlb_valid_size((unsigned long)hugepage_size)) {
hugetlb_bad_size();
pr_err("hugepagesz=%llu not supported by MMU.\n",
hugepage_size);
diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
index 5bfd5aef5378..1c4372bfe782 100644
--- a/arch/x86/mm/hugetlbpage.c
+++ b/arch/x86/mm/hugetlbpage.c
@@ -181,13 +181,22 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
#endif /* CONFIG_HUGETLB_PAGE */
#ifdef CONFIG_X86_64
+bool __init arch_hugetlb_valid_size(unsigned long size)
+{
+ if (size == PMD_SIZE)
+ return true;
+ else if (size == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES))
+ return true;
+ else
+ return false;
+}
+
static __init int setup_hugepagesz(char *opt)
{
unsigned long ps = memparse(opt, &opt);
- if (ps == PMD_SIZE) {
- hugetlb_add_hstate(PMD_SHIFT - PAGE_SHIFT);
- } else if (ps == PUD_SIZE && boot_cpu_has(X86_FEATURE_GBPAGES)) {
- hugetlb_add_hstate(PUD_SHIFT - PAGE_SHIFT);
+
+ if (arch_hugetlb_valid_size(ps)) {
+ hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
} else {
hugetlb_bad_size();
printk(KERN_ERR "hugepagesz: Unsupported page size %lu M\n",
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 43a1cef8f0f1..2eb15f5ab01e 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -521,6 +521,7 @@ int __init alloc_bootmem_huge_page(struct hstate *h);
void __init hugetlb_bad_size(void);
void __init hugetlb_add_hstate(unsigned order);
+bool __init arch_hugetlb_valid_size(unsigned long size);
struct hstate *size_to_hstate(unsigned long size);
#ifndef HUGE_MAX_HSTATE
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index bcabbe02192b..63ca4241ea87 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -3256,6 +3256,12 @@ static int __init hugetlb_init(void)
}
subsys_initcall(hugetlb_init);
+/* Overwritten by architectures with more huge page sizes */
+bool __init __attribute((weak)) arch_hugetlb_valid_size(unsigned long size)
+{
+ return size == HPAGE_SIZE;
+}
+
/* Should be called on processing a hugepagesz=... option */
void __init hugetlb_bad_size(void)
{
@@ -3331,12 +3337,21 @@ static int __init hugetlb_nrpages_setup(char *s)
}
__setup("hugepages=", hugetlb_nrpages_setup);
-static int __init hugetlb_default_setup(char *s)
+static int __init default_hugepagesz_setup(char *s)
{
- default_hstate_size = memparse(s, &s);
+ unsigned long size;
+
+ size = (unsigned long)memparse(s, NULL);
+
+ if (!arch_hugetlb_valid_size(size)) {
+ pr_err("HugeTLB: unsupported default_hugepagesz %s\n", s);
+ return 0;
+ }
+
+ default_hstate_size = size;
return 1;
}
-__setup("default_hugepagesz=", hugetlb_default_setup);
+__setup("default_hugepagesz=", default_hugepagesz_setup);
static unsigned int cpuset_mems_nr(unsigned int *array)
{
--
2.25.4
^ permalink raw reply related
* [PATCH] fixup! signal: factor copy_siginfo_to_external32 from copy_siginfo_to_user32
From: Arnd Bergmann @ 2020-04-28 19:56 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Arnd Bergmann, Jeremy Kerr, linux-kernel, Eric W . Biederman,
linux-fsdevel, Andrew Morton, linuxppc-dev, Alexander Viro
In-Reply-To: <20200428074827.GA19846@lst.de>
I think I found a way to improve the x32 handling:
This is a simplification over Christoph's "[PATCH 2/7] signal: factor
copy_siginfo_to_external32 from copy_siginfo_to_user32", reducing the
x32 specifics in the common code to a single #ifdef/#endif check, in
order to keep it more readable for everyone else.
Christoph, if you like it, please fold into your patch.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Jeremy Kerr <jk@ozlabs.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: "Eric W . Biederman" <ebiederm@xmission.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/x86/include/asm/compat.h | 10 ++++++++++
arch/x86/kernel/signal.c | 23 +++++++++++++++++++++++
kernel/signal.c | 15 ++-------------
3 files changed, 35 insertions(+), 13 deletions(-)
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 52e9f3480f69..9341ea3da757 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -214,7 +214,17 @@ static inline bool in_compat_syscall(void)
#endif
struct compat_siginfo;
+#ifdef CONFIG_X86_X32_ABI
int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
const kernel_siginfo_t *from, bool x32_ABI);
+#else
+int copy_siginfo_to_user32(struct compat_siginfo __user *to,
+ const kernel_siginfo_t *from);
+static inline int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
+ const kernel_siginfo_t *from, bool x32_ABI)
+{
+ return copy_siginfo_to_user32(to, from);
+}
+#endif
#endif /* _ASM_X86_COMPAT_H */
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 83b74fb38c8f..0e166571d28b 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -511,6 +511,29 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
}
#endif /* CONFIG_X86_32 */
+#ifdef CONFIG_X86_X32_ABI
+int copy_siginfo_to_user32(struct compat_siginfo __user *to,
+ const struct kernel_siginfo *from)
+{
+ return __copy_siginfo_to_user32(to, from, in_x32_syscall());
+}
+
+int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
+ const struct kernel_siginfo *from, bool x32_ABI)
+{
+ struct compat_siginfo new;
+
+ copy_siginfo_to_external32(&new, from);
+ if (x32_ABI && from->si_signo == SIGCHLD) {
+ new._sifields._sigchld_x32._utime = from->si_utime;
+ new._sifields._sigchld_x32._stime = from->si_stime;
+ }
+ if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
+ return -EFAULT;
+ return 0;
+}
+#endif
+
static int x32_setup_rt_frame(struct ksignal *ksig,
compat_sigset_t *set,
struct pt_regs *regs)
diff --git a/kernel/signal.c b/kernel/signal.c
index 1a81602050b4..935facca4860 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3318,29 +3318,18 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
}
}
+#ifndef CONFIG_X86_X32_ABI
int copy_siginfo_to_user32(struct compat_siginfo __user *to,
const struct kernel_siginfo *from)
-#if defined(CONFIG_X86_X32_ABI) || defined(CONFIG_IA32_EMULATION)
-{
- return __copy_siginfo_to_user32(to, from, in_x32_syscall());
-}
-int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
- const struct kernel_siginfo *from, bool x32_ABI)
-#endif
{
struct compat_siginfo new;
copy_siginfo_to_external32(&new, from);
-#ifdef CONFIG_X86_X32_ABI
- if (x32_ABI && from->si_signo == SIGCHLD) {
- new._sifields._sigchld_x32._utime = from->si_utime;
- new._sifields._sigchld_x32._stime = from->si_stime;
- }
-#endif
if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
return -EFAULT;
return 0;
}
+#endif
static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
const struct compat_siginfo *from)
--
2.26.0
^ permalink raw reply related
* Re: [PATCH v3 00/29] Convert files to ReST - part 2
From: Jonathan Corbet @ 2020-04-28 19:01 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Doc Mailing List, linux-usb, linux-kernel, codalist,
linux-xfs, linux-cachefs, linux-fsdevel, linuxppc-dev
In-Reply-To: <cover.1588021877.git.mchehab+huawei@kernel.org>
On Mon, 27 Apr 2020 23:16:52 +0200
Mauro Carvalho Chehab <mchehab+huawei@kernel.org> wrote:
> This is the second part of a series I wrote sometime ago where I manually
> convert lots of files to be properly parsed by Sphinx as ReST files.
>
> As it touches on lot of stuff, this series is based on today's linux-next,
> at tag next-20190617.
>
> The first version of this series had 57 patches. The first part with 28 patches
> were already merged. Right now, there are still ~76 patches pending applying
> (including this series), and that's because I opted to do ~1 patch per converted
> directory.
>
> That sounds too much to be send on a single round. So, I'm opting to split
> it on 3 parts for the conversion, plus a final patch adding orphaned books
> to existing ones.
>
> Those patches should probably be good to be merged either by subsystem
> maintainers or via the docs tree.
So I'm happy to merge this set, but there is one thing that worries me a
bit...
> fs/cachefiles/Kconfig | 4 +-
> fs/coda/Kconfig | 2 +-
> fs/configfs/inode.c | 2 +-
> fs/configfs/item.c | 2 +-
> fs/fscache/Kconfig | 8 +-
> fs/fscache/cache.c | 8 +-
> fs/fscache/cookie.c | 2 +-
> fs/fscache/object.c | 4 +-
> fs/fscache/operation.c | 2 +-
> fs/locks.c | 2 +-
> include/linux/configfs.h | 2 +-
> include/linux/fs_context.h | 2 +-
> include/linux/fscache-cache.h | 4 +-
> include/linux/fscache.h | 42 +-
> include/linux/lsm_hooks.h | 2 +-
I'd feel a bit better if I could get an ack or two from filesystem folks
before I venture that far out of my own yard...what say you all?
Thanks,
jon
^ permalink raw reply
* Re: [RFC PATCH] powerpc/spufs: fix copy_to_user while atomic
From: Christoph Hellwig @ 2020-04-28 17:11 UTC (permalink / raw)
To: Jeremy Kerr
Cc: Arnd Bergmann, linuxppc-dev, linux-kernel, Eric W . Biederman,
linux-fsdevel, Andrew Morton, Linus Torvalds, Christoph Hellwig,
Alexander Viro
In-Reply-To: <20200428120207.15728-1-jk@ozlabs.org>
FYI, these little hunks reduce the difference to my version, maybe
you can fold them in?
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index c62d77ddaf7d3..1861436a6091d 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2107,7 +2107,6 @@ static const struct file_operations spufs_wbox_info_fops = {
static void ___spufs_dma_info_read(struct spu_context *ctx,
struct spu_dma_info *info)
{
- struct mfc_cq_sr *qp, *spuqp;
int i;
info->dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
@@ -2116,8 +2115,8 @@ static void ___spufs_dma_info_read(struct spu_context *ctx,
info->dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
info->dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
for (i = 0; i < 16; i++) {
- qp = &info->dma_info_command_data[i];
- spuqp = &ctx->csa.priv2.spuq[i];
+ struct mfc_cq_sr *qp = &info->dma_info_command_data[i];
+ struct mfc_cq_sr *qp, *spuqp = &ctx->csa.priv2.spuq[i];
qp->mfc_cq_data0_RW = spuqp->mfc_cq_data0_RW;
qp->mfc_cq_data1_RW = spuqp->mfc_cq_data1_RW;
@@ -2166,7 +2165,7 @@ static const struct file_operations spufs_dma_info_fops = {
};
static void ___spufs_proxydma_info_read(struct spu_context *ctx,
- struct spu_proxydma_info *info)
+ struct spu_proxydma_info *info)
{
int i;
^ permalink raw reply related
* Re: [RFC PATCH v2 4/7] powerpc/ppc-opcode: consolidate powerpc instructions from bpf_jit.h
From: Naveen N. Rao @ 2020-04-28 16:19 UTC (permalink / raw)
To: Balamuruhan S, mpe
Cc: ravi.bangoria, jniethe5, paulus, sandipan, linuxppc-dev
In-Reply-To: <20200424070853.443969-5-bala24@linux.ibm.com>
Balamuruhan S wrote:
> move macro definitions of powerpc instructions from bpf_jit.h to ppc-opcode.h
> and adopt the users of the macros accordingly. `PPC_MR()` is defined twice in
> bpf_jit.h, remove the duplicate one.
>
> Signed-off-by: Balamuruhan S <bala24@linux.ibm.com>
> ---
> arch/powerpc/include/asm/ppc-opcode.h | 139 +++++++++++++
> arch/powerpc/net/bpf_jit.h | 166 ++-------------
> arch/powerpc/net/bpf_jit32.h | 24 +--
> arch/powerpc/net/bpf_jit64.h | 12 +-
> arch/powerpc/net/bpf_jit_comp.c | 132 ++++++------
> arch/powerpc/net/bpf_jit_comp64.c | 278 +++++++++++++-------------
> 6 files changed, 378 insertions(+), 373 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h
> index 2ae0afc5c2bb..6b9a891884be 100644
> --- a/arch/powerpc/include/asm/ppc-opcode.h
> +++ b/arch/powerpc/include/asm/ppc-opcode.h
> @@ -79,6 +79,16 @@
> #define IMM_L(i) ((uintptr_t)(i) & 0xffff)
> #define IMM_DS(i) ((uintptr_t)(i) & 0xfffc)
>
> +/*
> + * 16-bit immediate helper macros: HA() is for use with sign-extending instrs
> + * (e.g. LD, ADDI). If the bottom 16 bits is "-ve", add another bit into the
> + * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000).
> + */
> +#define IMM_H(i) ((uintptr_t)(i)>>16)
> +#define IMM_HA(i) (((uintptr_t)(i)>>16) + \
> + (((uintptr_t)(i) & 0x8000) >> 15))
> +
Not needed for this patch series, but at some point, we should move over
to using the PPC_LO(), PPC_HI() and PPC_HA() macros that are defined
later in this file.
- Naveen
^ permalink raw reply
* Re: [RFC PATCH v2 0/7] consolidate PowerPC instruction encoding macros
From: Naveen N. Rao @ 2020-04-28 16:15 UTC (permalink / raw)
To: Balamuruhan S, mpe
Cc: ravi.bangoria, jniethe5, paulus, sandipan, linuxppc-dev
In-Reply-To: <20200424070853.443969-1-bala24@linux.ibm.com>
Balamuruhan S wrote:
> ppc-opcode.h have base instruction encoding wrapped with stringify_in_c()
> for raw encoding to have compatibility. But there are redundant macros for
> base instruction encodings in bpf, instruction emulation test infrastructure
> and powerpc selftests.
>
> Currently PPC_INST_* macros are used for encoding instruction opcode and PPC_*
> for raw instuction encoding, this rfc patchset introduces PPC_RAW_* macros for
> base instruction encoding and reuse it from elsewhere. With this change we can
> avoid redundant macro definitions in multiple files and start adding new
> instructions in ppc-opcode.h in future.
>
> Changes in v2:
> -------------
> Fix review comments/suggestions from Naveen and Michael Ellerman,
>
> * Rename PPC_ENCODE_* to PPC_RAW_* for base instruction encoding macros.
> * Split the patches that does mass renaming and make them simpler that just
> adds new macros.
> * Keep the patch to update all the existing names later (patch 6).
> * Lot of PPC_INST_* macros are used only in ppc-opcode.h for PPC_* macros,
> fold PPC_INST_* encoding into PPC_RAW_* to avoid using them accidentally.
> * Fixed clipped macros that was due to a typo/copy-paste
> * Consolidated all the instruction encoding macros from bpf_jit.h to
> ppc-opcode.h
> * squashed patch that removes the duplicate macro PPC_MR() in bpf_jit.h
> * merge few changes in bpf_jit files from patch 2 into patch 3
> * few fixes in powerpc selftest stringloops Makefile
> * build tested for ppc64le_defconfig, ppc64e_defconfig and pmac32_defconfig
> * Rebased on next branch of linuxppc tree
>
> Testing:
> -------
> * Tested it by compiling vmlinux and comparing objdump of it with and without
> the patchset and observed that it remains same,
>
> # diff vmlinux_objdump vmlinux_rfc_objdump
> 2c2
> < vmlinux: file format elf64-powerpcle
> ---
> > vmlinux_rfc: file format elf64-powerpcle
>
> * Tested building it with this changes for Fedora30 config, booted VM
> with powerpc next and powerpc next + patchset to run powerpc selftest and
> ftrace selftest. There were couple of failures that were common and
> patchset did not introduce any new failures.
>
> ftrace selftest:
> ---------------
> # # of passed: 96
> # # of failed: 1
> # # of unresolved: 7
> # # of untested: 0
> # # of unsupported: 1
> # # of xfailed: 1
> # # of undefined(test bug): 0
> not ok 1 selftests: ftrace: ftracetest # exit=1
>
> powerpc selftest:
> ----------------
> not ok 7 selftests: powerpc/dscr: dscr_sysfs_thread_test # exit=1
> not ok 20 selftests: powerpc/pmu/ebb: lost_exception_test # TIMEOUT
> not ok 2 selftests: powerpc/security: spectre_v2 # exit=1
>
> Thanks to Naveen, Sandipan and Michael on overall suggestions/improvements.
>
> I would request for review and suggestions to make it better.
>
> v1: https://lists.ozlabs.org/pipermail/linuxppc-dev/2020-March/206494.html
>
> Balamuruhan S (7):
> powerpc/ppc-opcode: introduce PPC_RAW_* macros for base instruction
> encoding
> powerpc/ppc-opcode: move ppc instruction encoding from
> test_emulate_step
> powerpc/bpf_jit: reuse instruction macros from ppc-opcode.h
> powerpc/ppc-opcode: consolidate powerpc instructions from bpf_jit.h
> powerpc/ppc-opcode: reuse raw instruction macros to stringify
> powerpc/ppc-opcode: fold PPC_INST_* macros into PPC_RAW_* macros
> powerpc/selftest: reuse ppc-opcode macros to avoid redundancy
>
> arch/powerpc/include/asm/ppc-opcode.h | 706 +++++++++++-------
> arch/powerpc/lib/test_emulate_step.c | 155 ++--
> arch/powerpc/net/bpf_jit.h | 184 +----
> arch/powerpc/net/bpf_jit32.h | 34 +-
> arch/powerpc/net/bpf_jit64.h | 16 +-
> arch/powerpc/net/bpf_jit_comp.c | 134 ++--
> arch/powerpc/net/bpf_jit_comp64.c | 298 ++++----
> .../selftests/powerpc/stringloops/Makefile | 34 +-
> .../powerpc/stringloops/asm/asm-const.h | 1 +
> .../powerpc/stringloops/asm/ppc-opcode.h | 36 +-
> 10 files changed, 762 insertions(+), 836 deletions(-)
> create mode 120000 tools/testing/selftests/powerpc/stringloops/asm/asm-const.h
> mode change 100644 => 120000 tools/testing/selftests/powerpc/stringloops/asm/ppc-opcode.h
This LGTM. Except the last patch:
Acked-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Tested-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Thanks!
- Naveen
^ permalink raw reply
* Re: [RFC PATCH v2 7/7] powerpc/selftest: reuse ppc-opcode macros to avoid redundancy
From: Naveen N. Rao @ 2020-04-28 16:14 UTC (permalink / raw)
To: Balamuruhan S, mpe
Cc: ravi.bangoria, jniethe5, paulus, sandipan, linuxppc-dev
In-Reply-To: <20200424070853.443969-8-bala24@linux.ibm.com>
Balamuruhan S wrote:
> Avoid redefining macros to encode ppc instructions instead reuse it from
> ppc-opcode.h, Makefile changes are necessary to compile memcmp_64.S with
> __ASSEMBLY__ defined from selftests.
>
> Signed-off-by: Balamuruhan S <bala24@linux.ibm.com>
> ---
> .../selftests/powerpc/stringloops/Makefile | 34 ++++++++++++++----
> .../powerpc/stringloops/asm/asm-const.h | 1 +
> .../powerpc/stringloops/asm/ppc-opcode.h | 36 +------------------
> 3 files changed, 29 insertions(+), 42 deletions(-)
> create mode 120000 tools/testing/selftests/powerpc/stringloops/asm/asm-const.h
> mode change 100644 => 120000 tools/testing/selftests/powerpc/stringloops/asm/ppc-opcode.h
>
> diff --git a/tools/testing/selftests/powerpc/stringloops/Makefile b/tools/testing/selftests/powerpc/stringloops/Makefile
> index 7fc0623d85c3..efe76c5a5b94 100644
> --- a/tools/testing/selftests/powerpc/stringloops/Makefile
> +++ b/tools/testing/selftests/powerpc/stringloops/Makefile
> @@ -1,26 +1,44 @@
> # SPDX-License-Identifier: GPL-2.0
> # The loops are all 64-bit code
> -CFLAGS += -I$(CURDIR)
> +GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
> +CFLAGS += -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) -I$(CURDIR)/../include
I'm not sure why there are some extra flags added here. Not sure if it
is required for this change, or if they are separate changes. Trying to
build this from 'tools/testing/selftests/powerpc/' with 'make
stringloops' shows slightly different compile flags being used.
- Naveen
^ permalink raw reply
* Re: [PATCH v8 8/8] powerpc/vdso: Provide __kernel_clock_gettime64() on vdso32
From: Arnd Bergmann @ 2020-04-28 16:05 UTC (permalink / raw)
To: Christophe Leroy
Cc: Nathan Lynch, linux-arch, linux-kernel@vger.kernel.org,
Paul Mackerras, Andy Lutomirski, Thomas Gleixner,
Vincenzo Frascino, linuxppc-dev
In-Reply-To: <e78344d3fcc1d33bfb1782e430b7f0529f6c612f.1588079622.git.christophe.leroy@c-s.fr>
On Tue, Apr 28, 2020 at 3:16 PM Christophe Leroy
<christophe.leroy@c-s.fr> wrote:
>
> Provides __kernel_clock_gettime64() on vdso32. This is the
> 64 bits version of __kernel_clock_gettime() which is
> y2038 compliant.
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Looks good to me
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
There was a bug on ARM for the corresponding function, so far it is unclear
if this was a problem related to particular hardware, the 32-bit kernel code,
or the common implementation of clock_gettime64 in the vdso library,
see https://github.com/richfelker/musl-cross-make/issues/96
Just to be sure that powerpc is not affected by the same issue, can you
confirm that repeatedly calling clock_gettime64 on powerpc32, alternating
between vdso and syscall, results in monotically increasing times?
Arnd
^ permalink raw reply
* Re: [RFC PATCH] powerpc/spufs: fix copy_to_user while atomic
From: Arnd Bergmann @ 2020-04-28 16:00 UTC (permalink / raw)
To: Jeremy Kerr
Cc: linuxppc-dev, linux-kernel@vger.kernel.org, Eric W . Biederman,
Linux FS-devel Mailing List, Andrew Morton, Linus Torvalds,
Christoph Hellwig, Alexander Viro
In-Reply-To: <20200428120207.15728-1-jk@ozlabs.org>
On Tue, Apr 28, 2020 at 2:05 PM Jeremy Kerr <jk@ozlabs.org> wrote:
>
> Currently, we may perform a copy_to_user (through
> simple_read_from_buffer()) while holding a context's register_lock,
> while accessing the context save area.
>
> This change uses a temporary buffers for the context save area data,
> which we then pass to simple_read_from_buffer.
>
> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
> ---
Thanks for fixing this!
I wonder how far it should be backported, given that this has been broken for
14 years now.
Fixes: bf1ab978be23 ("[POWERPC] coredump: Add SPU elf notes to coredump.")
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
^ permalink raw reply
* Re: [PATCH net] ibmvnic: Fall back to 16 H_SEND_SUB_CRQ_INDIRECT entries with old FW
From: Thomas Falcon @ 2020-04-28 15:35 UTC (permalink / raw)
To: Juliet Kim, netdev; +Cc: linuxppc-dev
In-Reply-To: <20200427173343.16626-1-julietk@linux.vnet.ibm.com>
On 4/27/20 12:33 PM, Juliet Kim wrote:
> The maximum entries for H_SEND_SUB_CRQ_INDIRECT has increased on
> some platforms from 16 to 128. If Live Partition Mobility is used
> to migrate a running OS image from a newer source platform to an
> older target platform, then H_SEND_SUB_CRQ_INDIRECT will fail with
> H_PARAMETER if 128 entries are queued.
>
> Fix this by falling back to 16 entries if H_PARAMETER is returned
> from the hcall().
Thanks for the submission, but I am having a hard time believing that
this is what is happening since the driver does not support sending
multiple frames per hypervisor call at this time. Even if it were the
case, this approach would omit frame data needed by the VF, so the
second attempt may still fail. Are there system logs available that show
the driver is attempting to send transmissions with greater than 16
descriptors?
Thanks,
Tom
>
> Signed-off-by: Juliet Kim <julietk@linux.vnet.ibm.com>
> ---
> drivers/net/ethernet/ibm/ibmvnic.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
> index 4bd33245bad6..b66c2f26a427 100644
> --- a/drivers/net/ethernet/ibm/ibmvnic.c
> +++ b/drivers/net/ethernet/ibm/ibmvnic.c
> @@ -1656,6 +1656,17 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)
> lpar_rc = send_subcrq_indirect(adapter, handle_array[queue_num],
> (u64)tx_buff->indir_dma,
> (u64)num_entries);
> +
> + /* Old firmware accepts max 16 num_entries */
> + if (lpar_rc == H_PARAMETER && num_entries > 16) {
> + tx_crq.v1.n_crq_elem = 16;
> + tx_buff->num_entries = 16;
> + lpar_rc = send_subcrq_indirect(adapter,
> + handle_array[queue_num],
> + (u64)tx_buff->indir_dma,
> + 16);
> + }
> +
> dma_unmap_single(dev, tx_buff->indir_dma,
> sizeof(tx_buff->indir_arr), DMA_TO_DEVICE);
> } else {
^ permalink raw reply
* Re: [PATCH v8 8/8] powerpc/vdso: Provide __kernel_clock_gettime64() on vdso32
From: Christophe Leroy @ 2020-04-28 15:03 UTC (permalink / raw)
To: Russell Currey; +Cc: linuxppc-dev
In-Reply-To: <e78344d3fcc1d33bfb1782e430b7f0529f6c612f.1588079622.git.christophe.leroy@c-s.fr>
Hi,
On 04/28/2020 01:16 PM, Christophe Leroy wrote:
> Provides __kernel_clock_gettime64() on vdso32. This is the
> 64 bits version of __kernel_clock_gettime() which is
> y2038 compliant.
>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Why does snowpatch still report upstream failure ? This is fixed in
latest powerpc/merge which is
commit d9e4eabb775e1ba56d83bd4047de2413a21f87ce
Merge: 54dc28ff5e0b 51184ae37e05
Author: Michael Ellerman <mpe@ellerman.id.au>
Date: Tue Apr 28 09:01:47 2020 +1000
Automatic merge of branches 'master', 'next' and 'fixes' into merge
Looks like snowpatch is still using
commit 54dc28ff5e0b3585224d49a31b53e030342ca5c3
Merge: 5d23fec1ac1d b2768df24ec4
Author: Michael Ellerman <mpe@ellerman.id.au>
Date: Sun Apr 26 09:44:18 2020 +1000
Automatic merge of branches 'master', 'next' and 'fixes' into merge
Why ?
Christophe
> ---
> arch/powerpc/kernel/vdso32/gettimeofday.S | 9 +++++++++
> arch/powerpc/kernel/vdso32/vdso32.lds.S | 1 +
> arch/powerpc/kernel/vdso32/vgettimeofday.c | 6 ++++++
> 3 files changed, 16 insertions(+)
>
> diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S
> index fd7b01c51281..a6e29f880e0e 100644
> --- a/arch/powerpc/kernel/vdso32/gettimeofday.S
> +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S
> @@ -35,6 +35,15 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
> cvdso_call __c_kernel_clock_gettime
> V_FUNCTION_END(__kernel_clock_gettime)
>
> +/*
> + * Exact prototype of clock_gettime64()
> + *
> + * int __kernel_clock_gettime64(clockid_t clock_id, struct __timespec64 *ts);
> + *
> + */
> +V_FUNCTION_BEGIN(__kernel_clock_gettime64)
> + cvdso_call __c_kernel_clock_gettime64
> +V_FUNCTION_END(__kernel_clock_gettime64)
>
> /*
> * Exact prototype of clock_getres()
> diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S
> index 6cf729612268..05b462143238 100644
> --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S
> +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S
> @@ -144,6 +144,7 @@ VERSION
> #ifndef CONFIG_PPC_BOOK3S_601
> __kernel_gettimeofday;
> __kernel_clock_gettime;
> + __kernel_clock_gettime64;
> __kernel_clock_getres;
> __kernel_time;
> __kernel_get_tbfreq;
> diff --git a/arch/powerpc/kernel/vdso32/vgettimeofday.c b/arch/powerpc/kernel/vdso32/vgettimeofday.c
> index 0b9ab4c22ef2..f7f71fecf4ed 100644
> --- a/arch/powerpc/kernel/vdso32/vgettimeofday.c
> +++ b/arch/powerpc/kernel/vdso32/vgettimeofday.c
> @@ -11,6 +11,12 @@ int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
> return __cvdso_clock_gettime32_data(vd, clock, ts);
> }
>
> +int __c_kernel_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts,
> + const struct vdso_data *vd)
> +{
> + return __cvdso_clock_gettime_data(vd, clock, ts);
> +}
> +
> int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz,
> const struct vdso_data *vd)
> {
^ permalink raw reply
* [PATCH v2 2/2] powerpc/kprobes: Check return value of patch_instruction()
From: Naveen N. Rao @ 2020-04-28 14:03 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Steven Rostedt
In-Reply-To: <cover.1588082133.git.naveen.n.rao@linux.vnet.ibm.com>
patch_instruction() can fail in some scenarios. Add appropriate error
checking so that such failures are caught and logged, and suitable error
code is returned.
Fixes: d07df82c43be8 ("powerpc/kprobes: Move kprobes over to patch_instruction()")
Fixes: f3eca95638931 ("powerpc/kprobes/optprobes: Use patch_instruction()")
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/kernel/kprobes.c | 13 +++-
arch/powerpc/kernel/optprobes.c | 109 +++++++++++++++++++++++---------
2 files changed, 89 insertions(+), 33 deletions(-)
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index 81efb605113e..9eb1cc05ddd5 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -19,6 +19,7 @@
#include <linux/extable.h>
#include <linux/kdebug.h>
#include <linux/slab.h>
+#include <linux/bug.h>
#include <asm/code-patching.h>
#include <asm/cacheflush.h>
#include <asm/sstep.h>
@@ -138,13 +139,21 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
void arch_arm_kprobe(struct kprobe *p)
{
- patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
+ int rc = patch_instruction(p->addr, BREAKPOINT_INSTRUCTION);
+
+ if (WARN_ON(rc))
+ pr_err("Failed to patch trap at 0x%pK: %d\n",
+ (void *)p->addr, rc);
}
NOKPROBE_SYMBOL(arch_arm_kprobe);
void arch_disarm_kprobe(struct kprobe *p)
{
- patch_instruction(p->addr, p->opcode);
+ int rc = patch_instruction(p->addr, p->opcode);
+
+ if (WARN_ON(rc))
+ pr_err("Failed to remove trap at 0x%pK: %d\n",
+ (void *)p->addr, rc);
}
NOKPROBE_SYMBOL(arch_disarm_kprobe);
diff --git a/arch/powerpc/kernel/optprobes.c b/arch/powerpc/kernel/optprobes.c
index 024f7aad1952..20897600db2e 100644
--- a/arch/powerpc/kernel/optprobes.c
+++ b/arch/powerpc/kernel/optprobes.c
@@ -139,52 +139,80 @@ void arch_remove_optimized_kprobe(struct optimized_kprobe *op)
}
}
+#define PATCH_INSN_OR_GOTO(addr, instr, label) \
+do { \
+ int rc = patch_instruction((unsigned int *)(addr), instr); \
+ if (rc) { \
+ pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \
+ __func__, __LINE__, \
+ (void *)(addr), (void *)(addr), rc); \
+ goto label; \
+ } \
+} while (0)
+
/*
* emulate_step() requires insn to be emulated as
* second parameter. Load register 'r4' with the
* instruction.
*/
-void patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
+static int patch_imm32_load_insns(unsigned int val, kprobe_opcode_t *addr)
{
/* addis r4,0,(insn)@h */
- patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(4) |
- ((val >> 16) & 0xffff));
+ PATCH_INSN_OR_GOTO(addr, PPC_INST_ADDIS | ___PPC_RT(4) |
+ ((val >> 16) & 0xffff),
+ patch_err);
addr++;
/* ori r4,r4,(insn)@l */
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(4) |
- ___PPC_RS(4) | (val & 0xffff));
+ PATCH_INSN_OR_GOTO(addr, PPC_INST_ORI | ___PPC_RA(4) |
+ ___PPC_RS(4) | (val & 0xffff),
+ patch_err);
+
+ return 0;
+
+patch_err:
+ return -EFAULT;
}
/*
* Generate instructions to load provided immediate 64-bit value
* to register 'r3' and patch these instructions at 'addr'.
*/
-void patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
+static int patch_imm64_load_insns(unsigned long val, kprobe_opcode_t *addr)
{
/* lis r3,(op)@highest */
- patch_instruction(addr, PPC_INST_ADDIS | ___PPC_RT(3) |
- ((val >> 48) & 0xffff));
+ PATCH_INSN_OR_GOTO(addr, PPC_INST_ADDIS | ___PPC_RT(3) |
+ ((val >> 48) & 0xffff),
+ patch_err);
addr++;
/* ori r3,r3,(op)@higher */
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 32) & 0xffff));
+ PATCH_INSN_OR_GOTO(addr, PPC_INST_ORI | ___PPC_RA(3) |
+ ___PPC_RS(3) | ((val >> 32) & 0xffff),
+ patch_err);
addr++;
/* rldicr r3,r3,32,31 */
- patch_instruction(addr, PPC_INST_RLDICR | ___PPC_RA(3) |
- ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31));
+ PATCH_INSN_OR_GOTO(addr, PPC_INST_RLDICR | ___PPC_RA(3) |
+ ___PPC_RS(3) | __PPC_SH64(32) | __PPC_ME64(31),
+ patch_err);
addr++;
/* oris r3,r3,(op)@h */
- patch_instruction(addr, PPC_INST_ORIS | ___PPC_RA(3) |
- ___PPC_RS(3) | ((val >> 16) & 0xffff));
+ PATCH_INSN_OR_GOTO(addr, PPC_INST_ORIS | ___PPC_RA(3) |
+ ___PPC_RS(3) | ((val >> 16) & 0xffff),
+ patch_err);
addr++;
/* ori r3,r3,(op)@l */
- patch_instruction(addr, PPC_INST_ORI | ___PPC_RA(3) |
- ___PPC_RS(3) | (val & 0xffff));
+ PATCH_INSN_OR_GOTO(addr, PPC_INST_ORI | ___PPC_RA(3) |
+ ___PPC_RS(3) | (val & 0xffff),
+ patch_err);
+
+ return 0;
+
+patch_err:
+ return -EFAULT;
}
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
@@ -216,30 +244,33 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
* be within 32MB on either side of the current instruction.
*/
b_offset = (unsigned long)buff - (unsigned long)p->addr;
- if (!is_offset_in_branch_range(b_offset))
+ if (!is_offset_in_branch_range(b_offset)) {
+ rc = -ERANGE;
goto error;
+ }
/* Check if the return address is also within 32MB range */
b_offset = (unsigned long)(buff + TMPL_RET_IDX) -
(unsigned long)nip;
- if (!is_offset_in_branch_range(b_offset))
+ if (!is_offset_in_branch_range(b_offset)) {
+ rc = -ERANGE;
goto error;
+ }
/* Setup template */
/* We can optimize this via patch_instruction_window later */
size = (TMPL_END_IDX * sizeof(kprobe_opcode_t)) / sizeof(int);
pr_devel("Copying template to %p, size %lu\n", buff, size);
- for (i = 0; i < size; i++) {
- rc = patch_instruction(buff + i, *(optprobe_template_entry + i));
- if (rc < 0)
- goto error;
- }
+ for (i = 0; i < size; i++)
+ PATCH_INSN_OR_GOTO(buff + i, *(optprobe_template_entry + i),
+ patch_err);
/*
* Fixup the template with instructions to:
* 1. load the address of the actual probepoint
*/
- patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX);
+ if (patch_imm64_load_insns((unsigned long)op, buff + TMPL_OP_IDX))
+ goto patch_err;
/*
* 2. branch to optimized_callback() and emulate_step()
@@ -248,6 +279,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
emulate_step_addr = (kprobe_opcode_t *)ppc_kallsyms_lookup_name("emulate_step");
if (!op_callback_addr || !emulate_step_addr) {
WARN(1, "Unable to lookup optimized_callback()/emulate_step()\n");
+ rc = -ERANGE;
goto error;
}
@@ -259,21 +291,29 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
(unsigned long)emulate_step_addr,
BRANCH_SET_LINK);
- if (!branch_op_callback || !branch_emulate_step)
+ if (!branch_op_callback || !branch_emulate_step) {
+ rc = -ERANGE;
goto error;
+ }
+
+ PATCH_INSN_OR_GOTO(buff + TMPL_CALL_HDLR_IDX, branch_op_callback,
+ patch_err);
- patch_instruction(buff + TMPL_CALL_HDLR_IDX, branch_op_callback);
- patch_instruction(buff + TMPL_EMULATE_IDX, branch_emulate_step);
+ PATCH_INSN_OR_GOTO(buff + TMPL_EMULATE_IDX, branch_emulate_step,
+ patch_err);
/*
* 3. load instruction to be emulated into relevant register, and
*/
- patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX);
+ if (patch_imm32_load_insns(*p->ainsn.insn, buff + TMPL_INSN_IDX))
+ goto patch_err;
/*
* 4. branch back from trampoline
*/
- patch_branch(buff + TMPL_RET_IDX, (unsigned long)nip, 0);
+ PATCH_INSN_OR_GOTO(buff + TMPL_RET_IDX,
+ create_branch(buff + TMPL_RET_IDX, (unsigned long)nip, 0),
+ patch_err);
flush_icache_range((unsigned long)buff,
(unsigned long)(&buff[TMPL_END_IDX]));
@@ -282,9 +322,11 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *p)
return 0;
+patch_err:
+ rc = -EFAULT;
error:
free_ppc_optinsn_slot(buff, 0);
- return -ERANGE;
+ return rc;
}
@@ -307,6 +349,7 @@ void arch_optimize_kprobes(struct list_head *oplist)
{
struct optimized_kprobe *op;
struct optimized_kprobe *tmp;
+ int rc;
list_for_each_entry_safe(op, tmp, oplist, list) {
/*
@@ -315,9 +358,13 @@ void arch_optimize_kprobes(struct list_head *oplist)
*/
memcpy(op->optinsn.copied_insn, op->kp.addr,
RELATIVEJUMP_SIZE);
- patch_instruction(op->kp.addr,
+ rc = patch_instruction(op->kp.addr,
create_branch((unsigned int *)op->kp.addr,
(unsigned long)op->optinsn.insn, 0));
+ if (rc)
+ pr_err("%s:%d: Error patching instruction at 0x%pK: %d\n",
+ __func__, __LINE__,
+ (void *)(op->kp.addr), rc);
list_del_init(&op->list);
}
}
--
2.25.1
^ permalink raw reply related
* [PATCH v2 0/2] powerpc: Enhance error handling with patch_instruction()
From: Naveen N. Rao @ 2020-04-28 14:03 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Steven Rostedt
Changes in v2:
- Change macro to use 'goto' instead of 'return'
- Rename macro to indicate use of 'goto'
- Convert more patch_instruction() uses in optprobes to use the new
macro.
- Drop 1st patch, which added error checking in do_patch_instruction()
since that is being covered in a separate patchset.
v1:
http://lkml.kernel.org/r/cover.1587654213.git.naveen.n.rao@linux.vnet.ibm.com
- Naveen
Naveen N. Rao (2):
powerpc/ftrace: Simplify error checking when patching instructions
powerpc/kprobes: Check return value of patch_instruction()
arch/powerpc/kernel/kprobes.c | 13 +++-
arch/powerpc/kernel/optprobes.c | 109 +++++++++++++++++++++--------
arch/powerpc/kernel/trace/ftrace.c | 96 +++++++++++++++----------
3 files changed, 149 insertions(+), 69 deletions(-)
base-commit: 8299da600ad05b8aa0f15ec0f5f03bd40e37d6f0
--
2.25.1
^ permalink raw reply
* [PATCH v2 1/2] powerpc/ftrace: Simplify error checking when patching instructions
From: Naveen N. Rao @ 2020-04-28 14:03 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Steven Rostedt
In-Reply-To: <cover.1588082133.git.naveen.n.rao@linux.vnet.ibm.com>
Introduce a macro PATCH_INSN_OR_GOTO() to simplify instruction patching,
and to make the error messages more uniform and useful:
- print an error message that includes the original return value
- print the function name and line numbers, so that the offending
location is clear
- goto a label which always return -EPERM, which ftrace_bug() expects
for proper error handling
Also eliminate use of patch_branch() since most such uses already call
create_branch() for error checking before patching. Instead, use the
return value from create_branch() with PATCH_INSN_OR_GOTO().
Signed-off-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
---
arch/powerpc/kernel/trace/ftrace.c | 96 +++++++++++++++++++-----------
1 file changed, 60 insertions(+), 36 deletions(-)
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index 7ea0ca044b65..63edbd48af42 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -31,6 +31,17 @@
#ifdef CONFIG_DYNAMIC_FTRACE
+#define PATCH_INSN_OR_GOTO(addr, instr, label) \
+do { \
+ int rc = patch_instruction((unsigned int *)(addr), instr); \
+ if (rc) { \
+ pr_err("%s:%d Error patching instruction at 0x%pK (%pS): %d\n", \
+ __func__, __LINE__, \
+ (void *)(addr), (void *)(addr), rc); \
+ goto label; \
+ } \
+} while (0)
+
/*
* We generally only have a single long_branch tramp and at most 2 or 3 plt
* tramps generated. But, we don't use the plt tramps currently. We also allot
@@ -78,10 +89,12 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
}
/* replace the text with the new text */
- if (patch_instruction((unsigned int *)ip, new))
- return -EPERM;
+ PATCH_INSN_OR_GOTO(ip, new, patch_err);
return 0;
+
+patch_err:
+ return -EPERM;
}
/*
@@ -204,12 +217,12 @@ __ftrace_make_nop(struct module *mod,
}
#endif /* CONFIG_MPROFILE_KERNEL */
- if (patch_instruction((unsigned int *)ip, pop)) {
- pr_err("Patching NOP failed.\n");
- return -EPERM;
- }
+ PATCH_INSN_OR_GOTO(ip, pop, patch_err);
return 0;
+
+patch_err:
+ return -EPERM;
}
#else /* !PPC64 */
@@ -276,10 +289,12 @@ __ftrace_make_nop(struct module *mod,
op = PPC_INST_NOP;
- if (patch_instruction((unsigned int *)ip, op))
- return -EPERM;
+ PATCH_INSN_OR_GOTO(ip, op, patch_err);
return 0;
+
+patch_err:
+ return -EPERM;
}
#endif /* PPC64 */
#endif /* CONFIG_MODULES */
@@ -322,7 +337,7 @@ static int add_ftrace_tramp(unsigned long tramp)
*/
static int setup_mcount_compiler_tramp(unsigned long tramp)
{
- int i, op;
+ unsigned int i, op;
unsigned long ptr;
static unsigned long ftrace_plt_tramps[NUM_FTRACE_TRAMPS];
@@ -366,16 +381,14 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
#else
ptr = ppc_global_function_entry((void *)ftrace_caller);
#endif
- if (!create_branch((void *)tramp, ptr, 0)) {
+ op = create_branch((void *)tramp, ptr, 0);
+ if (!op) {
pr_debug("%ps is not reachable from existing mcount tramp\n",
(void *)ptr);
return -1;
}
- if (patch_branch((unsigned int *)tramp, ptr, 0)) {
- pr_debug("REL24 out of range!\n");
- return -1;
- }
+ PATCH_INSN_OR_GOTO(tramp, op, patch_err);
if (add_ftrace_tramp(tramp)) {
pr_debug("No tramp locations left\n");
@@ -383,6 +396,9 @@ static int setup_mcount_compiler_tramp(unsigned long tramp)
}
return 0;
+
+patch_err:
+ return -EPERM;
}
static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
@@ -416,12 +432,12 @@ static int __ftrace_make_nop_kernel(struct dyn_ftrace *rec, unsigned long addr)
}
}
- if (patch_instruction((unsigned int *)ip, PPC_INST_NOP)) {
- pr_err("Patching NOP failed.\n");
- return -EPERM;
- }
+ PATCH_INSN_OR_GOTO(ip, PPC_INST_NOP, patch_err);
return 0;
+
+patch_err:
+ return -EPERM;
}
int ftrace_make_nop(struct module *mod,
@@ -557,17 +573,18 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
}
/* Ensure branch is within 24 bits */
- if (!create_branch(ip, tramp, BRANCH_SET_LINK)) {
+ op[0] = create_branch(ip, tramp, BRANCH_SET_LINK);
+ if (!op[0]) {
pr_err("Branch out of range\n");
return -EINVAL;
}
- if (patch_branch(ip, tramp, BRANCH_SET_LINK)) {
- pr_err("REL24 out of range!\n");
- return -EINVAL;
- }
+ PATCH_INSN_OR_GOTO(ip, op[0], patch_err);
return 0;
+
+patch_err:
+ return -EPERM;
}
#else /* !CONFIG_PPC64: */
@@ -603,10 +620,12 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
pr_devel("write to %lx\n", rec->ip);
- if (patch_instruction((unsigned int *)ip, op))
- return -EPERM;
+ PATCH_INSN_OR_GOTO(ip, op, patch_err);
return 0;
+
+patch_err:
+ return -EPERM;
}
#endif /* CONFIG_PPC64 */
#endif /* CONFIG_MODULES */
@@ -650,12 +669,18 @@ static int __ftrace_make_call_kernel(struct dyn_ftrace *rec, unsigned long addr)
return -EINVAL;
}
- if (patch_branch(ip, tramp, BRANCH_SET_LINK)) {
- pr_err("Error patching branch to ftrace tramp!\n");
+ op = create_branch(ip, tramp, BRANCH_SET_LINK);
+ if (!op) {
+ pr_err("Branch out of range\n");
return -EINVAL;
}
+ PATCH_INSN_OR_GOTO(ip, op, patch_err);
+
return 0;
+
+patch_err:
+ return -EPERM;
}
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
@@ -748,10 +773,8 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
/* The new target may be within range */
if (test_24bit_addr(ip, addr)) {
/* within range */
- if (patch_branch((unsigned int *)ip, addr, BRANCH_SET_LINK)) {
- pr_err("REL24 out of range!\n");
- return -EINVAL;
- }
+ op = create_branch((unsigned int *)ip, addr, BRANCH_SET_LINK);
+ PATCH_INSN_OR_GOTO(ip, op, patch_err);
return 0;
}
@@ -776,17 +799,18 @@ __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
}
/* Ensure branch is within 24 bits */
- if (!create_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
+ op = create_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK);
+ if (!op) {
pr_err("Branch out of range\n");
return -EINVAL;
}
- if (patch_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) {
- pr_err("REL24 out of range!\n");
- return -EINVAL;
- }
+ PATCH_INSN_OR_GOTO(ip, op, patch_err);
return 0;
+
+patch_err:
+ return -EPERM;
}
#endif
--
2.25.1
^ permalink raw reply related
* Re: [RFC PATCH] powerpc/spufs: fix copy_to_user while atomic
From: Christoph Hellwig @ 2020-04-28 13:54 UTC (permalink / raw)
To: Jeremy Kerr
Cc: Arnd Bergmann, linuxppc-dev, linux-kernel, Eric W . Biederman,
linux-fsdevel, Andrew Morton, Linus Torvalds, Christoph Hellwig,
Alexander Viro
In-Reply-To: <20200428120207.15728-1-jk@ozlabs.org>
On Tue, Apr 28, 2020 at 08:02:07PM +0800, Jeremy Kerr wrote:
> Currently, we may perform a copy_to_user (through
> simple_read_from_buffer()) while holding a context's register_lock,
> while accessing the context save area.
>
> This change uses a temporary buffers for the context save area data,
> which we then pass to simple_read_from_buffer.
>
> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
> ---
>
> Christoph - this fixes the copy_to_user while atomic, hopefully with
> only minimal distruption to your series.
I recognize plenty of sniplets from that :) Your patch looks good
to me:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ 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