From: Mike Kravetz <hidden> Date: 2020-03-18 22:07:50
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 following 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
Documentation/admin-guide/mm/hugetlbpage.rst | 26 ++++
arch/arm64/include/asm/hugetlb.h | 2 +
arch/arm64/mm/hugetlbpage.c | 30 ++---
arch/powerpc/include/asm/hugetlb.h | 3 +
arch/powerpc/mm/hugetlbpage.c | 30 ++---
arch/riscv/include/asm/hugetlb.h | 3 +
arch/riscv/mm/hugetlbpage.c | 24 ++--
arch/s390/include/asm/hugetlb.h | 3 +
arch/s390/mm/hugetlbpage.c | 24 ++--
arch/sparc/include/asm/hugetlb.h | 3 +
arch/sparc/mm/init_64.c | 42 ++-----
arch/x86/include/asm/hugetlb.h | 3 +
arch/x86/mm/hugetlbpage.c | 23 ++--
include/linux/hugetlb.h | 8 +-
mm/hugetlb.c | 126 ++++++++++++++-----
15 files changed, 198 insertions(+), 152 deletions(-)
--
2.24.1
From: Mike Kravetz <hidden> Date: 2020-03-18 22:07:52
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 <redacted>
---
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 | 24 ++++++++++++++++++------
8 files changed, 18 insertions(+), 109 deletions(-)
@@ -589,21 +589,6 @@ static int __init add_huge_page_size(unsigned long long size)return0;}-staticint__inithugepage_setup_sz(char*str)-{-unsignedlonglongsize;--size=memparse(str,&str);--if(add_huge_page_size(size)!=0){-hugetlb_bad_size();-pr_err("Invalid huge page size specified(%llu)\n",size);-}--return1;-}-__setup("hugepagesz=",hugepage_setup_sz);-staticint__inithugetlbpage_init(void){boolconfigured=false;
@@ -398,28 +398,6 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)returntrue;}--staticint__initsetup_hugepagesz(char*string)-{-unsignedlonglonghugepage_size;-intrc=0;--hugepage_size=memparse(string,&string);--if(!arch_hugetlb_valid_size(hugepage_size)){-hugetlb_bad_size();-pr_err("hugepagesz=%llu not supported by MMU.\n",-hugepage_size);-gotoout;-}--add_huge_page_size(hugepage_size);-rc=1;--out:-returnrc;-}-__setup("hugepagesz=",setup_hugepagesz);#endif /* CONFIG_HUGETLB_PAGE */voidupdate_mmu_cache(structvm_area_struct*vma,unsignedlongaddress,pte_t*ptep)
@@ -3149,12 +3149,6 @@ static int __init hugetlb_init(void)}subsys_initcall(hugetlb_init);-/* Should be called on processing a hugepagesz=... option */-void__inithugetlb_bad_size(void)-{-parsed_valid_hugepagesz=false;-}-void__inithugetlb_add_hstate(unsignedintorder){structhstate*h;
From: Mike Kravetz <hidden> Date: 2020-03-18 22:07:55
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 <redacted>
---
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 | 10 +++++++---
6 files changed, 18 insertions(+), 34 deletions(-)
@@ -584,8 +584,7 @@ static int __init add_huge_page_size(unsigned long long size)if(!arch_hugetlb_valid_size(size))return-EINVAL;-if(!size_to_hstate(size))-hugetlb_add_hstate(shift-PAGE_SHIFT);+hugetlb_add_hstate(shift-PAGE_SHIFT);return0;}
@@ -26,7 +26,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
@@ -195,7 +195,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
From: Mike Kravetz <hidden> Date: 2020-03-18 22:08:00
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 <redacted>
---
arch/arm64/include/asm/hugetlb.h | 2 ++
arch/arm64/mm/hugetlbpage.c | 19 ++++++++++++++-----
arch/powerpc/include/asm/hugetlb.h | 3 +++
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/include/asm/hugetlb.h | 3 +++
arch/riscv/mm/hugetlbpage.c | 28 ++++++++++++++++++----------
arch/s390/include/asm/hugetlb.h | 3 +++
arch/s390/mm/hugetlbpage.c | 18 +++++++++++++-----
arch/sparc/include/asm/hugetlb.h | 3 +++
arch/sparc/mm/init_64.c | 23 ++++++++++++++++-------
arch/x86/include/asm/hugetlb.h | 3 +++
arch/x86/mm/hugetlbpage.c | 21 +++++++++++++++------
include/linux/hugetlb.h | 7 +++++++
mm/hugetlb.c | 16 +++++++++++++---
14 files changed, 126 insertions(+), 43 deletions(-)
@@ -558,7 +558,7 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)returnvma_kernel_pagesize(vma);}-staticint__initadd_huge_page_size(unsignedlonglongsize)+bool__initarch_hugetlb_valid_size(unsignedlonglongsize){intshift=__ffs(size);intmmu_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*thatitfitswithinpagetableandslicelimits.*/if(size<=PAGE_SIZE||!is_power_of_2(size))-return-EINVAL;+returnfalse;mmu_psize=check_and_get_huge_psize(shift);if(mmu_psize<0)-return-EINVAL;+returnfalse;BUG_ON(mmu_psize_defs[mmu_psize].shift!=shift);-/* Return if huge page size has already been setup */-if(size_to_hstate(size))-return0;+returntrue;+}-hugetlb_add_hstate(shift-PAGE_SHIFT);+staticint__initadd_huge_page_size(unsignedlonglongsize)+{+intshift=__ffs(size);++if(!arch_hugetlb_valid_size(size))+return-EINVAL;+if(!size_to_hstate(size))+hugetlb_add_hstate(shift-PAGE_SHIFT);return0;}
@@ -397,7 +393,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)+returnfalse;++returntrue;+}++staticint__initsetup_hugepagesz(char*string)+{+unsignedlonglonghugepage_size;+intrc=0;++hugepage_size=memparse(string,&string);++if(!arch_hugetlb_valid_size(hugepage_size)){hugetlb_bad_size();pr_err("hugepagesz=%llu not supported by MMU.\n",hugepage_size);
From: Mike Kravetz <hidden> Date: 2020-03-18 22:09:03
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.
- Add comments to code
- Describe some of the subtle interactions
- Describe semantics of command line arguments
Signed-off-by: Mike Kravetz <redacted>
---
Documentation/admin-guide/mm/hugetlbpage.rst | 26 +++++++
mm/hugetlb.c | 78 +++++++++++++++-----
2 files changed, 87 insertions(+), 17 deletions(-)
@@ -100,6 +100,32 @@ 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 parameter. However, if hugepages is the+ first or only hugetlb command line parameter it specifies the number+ of huge pages of default size to allocate. The number of huge pages+ of default size specified in this manner can 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 512 2M huge pages being allocated. 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 on the command line. No other hugetlb command line+ parameter is associated with default_hugepagesz. Therefore, it can+ appear anywhere on the command line. 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
From: Will Deacon <will@kernel.org> Date: 2020-03-18 22:10:04
On Wed, Mar 18, 2020 at 03:06:31PM -0700, Mike Kravetz wrote:
quoted hunk
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 <redacted>
---
arch/arm64/include/asm/hugetlb.h | 2 ++
arch/arm64/mm/hugetlbpage.c | 19 ++++++++++++++-----
arch/powerpc/include/asm/hugetlb.h | 3 +++
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/include/asm/hugetlb.h | 3 +++
arch/riscv/mm/hugetlbpage.c | 28 ++++++++++++++++++----------
arch/s390/include/asm/hugetlb.h | 3 +++
arch/s390/mm/hugetlbpage.c | 18 +++++++++++++-----
arch/sparc/include/asm/hugetlb.h | 3 +++
arch/sparc/mm/init_64.c | 23 ++++++++++++++++-------
arch/x86/include/asm/hugetlb.h | 3 +++
arch/x86/mm/hugetlbpage.c | 21 +++++++++++++++------
include/linux/hugetlb.h | 7 +++++++
mm/hugetlb.c | 16 +++++++++++++---
14 files changed, 126 insertions(+), 43 deletions(-)
I'm pretty sure it's possible to have a system without 2M/PMD page
support. We even have a handy-dandy comment about it in
arch/x86/include/asm/required-features.h:
#ifdef CONFIG_X86_64
#ifdef CONFIG_PARAVIRT
/* Paravirtualized systems may not have PSE or PGE available */
#define NEED_PSE 0
...
I *think* you need an X86_FEATURE_PSE check here to be totally correct.
if (size == PMD_SIZE && cpu_feature_enabled(X86_FEATURE_PSE))
return true;
BTW, I prefer cpu_feature_enabled() to boot_cpu_has() because it
includes disabled-features checking. I don't think any of it matters
for these specific features, but I generally prefer it on principle.
From: Mike Kravetz <hidden> Date: 2020-03-18 22:39:50
On 3/18/20 3:09 PM, Will Deacon wrote:
On Wed, Mar 18, 2020 at 03:06:31PM -0700, Mike Kravetz wrote:
quoted
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 <redacted>
---
arch/arm64/include/asm/hugetlb.h | 2 ++
arch/arm64/mm/hugetlbpage.c | 19 ++++++++++++++-----
arch/powerpc/include/asm/hugetlb.h | 3 +++
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/include/asm/hugetlb.h | 3 +++
arch/riscv/mm/hugetlbpage.c | 28 ++++++++++++++++++----------
arch/s390/include/asm/hugetlb.h | 3 +++
arch/s390/mm/hugetlbpage.c | 18 +++++++++++++-----
arch/sparc/include/asm/hugetlb.h | 3 +++
arch/sparc/mm/init_64.c | 23 ++++++++++++++++-------
arch/x86/include/asm/hugetlb.h | 3 +++
arch/x86/mm/hugetlbpage.c | 21 +++++++++++++++------
include/linux/hugetlb.h | 7 +++++++
mm/hugetlb.c | 16 +++++++++++++---
14 files changed, 126 insertions(+), 43 deletions(-)
I'm pretty sure it's possible to have a system without 2M/PMD page
support. We even have a handy-dandy comment about it in
arch/x86/include/asm/required-features.h:
#ifdef CONFIG_X86_64
#ifdef CONFIG_PARAVIRT
/* Paravirtualized systems may not have PSE or PGE available */
#define NEED_PSE 0
...
I *think* you need an X86_FEATURE_PSE check here to be totally correct.
if (size == PMD_SIZE && cpu_feature_enabled(X86_FEATURE_PSE))
return true;
BTW, I prefer cpu_feature_enabled() to boot_cpu_has() because it
includes disabled-features checking. I don't think any of it matters
for these specific features, but I generally prefer it on principle.
Sounds good. I'll incorporate those changes into a v2, unless someone
else with has a different opinion.
BTW, this patch should not really change the way the code works today.
It is mostly a movement of code. Unless I am missing something, the
existing code will always allow setup of PMD_SIZE hugetlb pages.
--
Mike Kravetz
From: Dave Hansen <hidden> Date: 2020-03-18 23:36:59
On 3/18/20 3:52 PM, Mike Kravetz wrote:
Sounds good. I'll incorporate those changes into a v2, unless someone
else with has a different opinion.
BTW, this patch should not really change the way the code works today.
It is mostly a movement of code. Unless I am missing something, the
existing code will always allow setup of PMD_SIZE hugetlb pages.
Hah, I totally skipped over the old code in the diff.
It looks like we'll disable hugetblfs *entirely* if PSE isn't supported.
I think this is actually wrong, but nobody ever noticed. I think you'd
have to be running as a guest under a hypervisor that's lying about PSE
not being supported *and* care about 1GB pages. Nobody does that.
From: Randy Dunlap <rdunlap@infradead.org> Date: 2020-03-19 00:21:39
Hi Mike,
On 3/18/20 3:06 PM, Mike Kravetz wrote:
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.
- Add comments to code
- Describe some of the subtle interactions
- Describe semantics of command line arguments
Signed-off-by: Mike Kravetz <redacted>
---
Documentation/admin-guide/mm/hugetlbpage.rst | 26 +++++++
mm/hugetlb.c | 78 +++++++++++++++-----
2 files changed, 87 insertions(+), 17 deletions(-)
@@ -3214,8 +3238,15 @@ 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 commnad line. The global
typo: command
+ * variable 'parsed_valid_hugepagesz' is used to determine if prior
+ * hugepagesz argument was valid.
+ */
static int __init hugepagesz_setup(char *s)
{
unsigned long long size;
Does any of this need to be updated? (from Documentation/admin-guide/kernel-parameters.txt)
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).
--
~Randy
From: kbuild test robot <hidden> Date: 2020-03-19 00:49:41
Hi Mike,
I love your patch! Yet something to improve:
[auto build test ERROR on next-20200318]
[also build test ERROR on v5.6-rc6]
[cannot apply to arm64/for-next/core powerpc/next sparc/master linus/master sparc-next/master v5.6-rc6 v5.6-rc5 v5.6-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Mike-Kravetz/Clean-up-hugetlb-boot-command-line-processing/20200319-060943
base: 47780d7892b77e922bbe19b5dea99cde06b2f0e5
config: riscv-allyesconfig (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=9.2.0 make.cross ARCH=riscv
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <redacted>
All error/warnings (new ones prefixed by >>):
arch/riscv/mm/hugetlbpage.c: In function 'arch_hugetlb_valid_size':
quoted
arch/riscv/mm/hugetlbpage.c:19:39: error: 'ps' undeclared (first use in this function)
19 | else if (IS_ENABLED(CONFIG_64BIT) && ps == PUD_SIZE)
| ^~
arch/riscv/mm/hugetlbpage.c:19:39: note: each undeclared identifier is reported only once for each function it appears in
quoted
arch/riscv/mm/hugetlbpage.c:20:3: error: 'retrurn' undeclared (first use in this function)
20 | retrurn true;
| ^~~~~~~
quoted
arch/riscv/mm/hugetlbpage.c:20:10: error: expected ';' before 'true'
20 | retrurn true;
| ^~~~~
| ;
In file included from include/linux/printk.h:7,
from include/linux/kernel.h:15,
from include/asm-generic/bug.h:19,
from arch/riscv/include/asm/bug.h:75,
from include/linux/bug.h:5,
from arch/riscv/include/asm/cmpxchg.h:9,
from arch/riscv/include/asm/atomic.h:19,
from include/linux/atomic.h:7,
from include/linux/mm_types_task.h:13,
from include/linux/mm_types.h:5,
from include/linux/hugetlb.h:5,
from arch/riscv/mm/hugetlbpage.c:2:
arch/riscv/mm/hugetlbpage.c: In function 'setup_hugepagesz':
include/linux/kern_levels.h:5:18: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'long long unsigned int' [-Wformat=]
5 | #define KERN_SOH "\001" /* ASCII Start Of Header */
| ^~~~~~
include/linux/kern_levels.h:11:18: note: in expansion of macro 'KERN_SOH'
11 | #define KERN_ERR KERN_SOH "3" /* error conditions */
| ^~~~~~~~
include/linux/printk.h:304:9: note: in expansion of macro 'KERN_ERR'
304 | printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
| ^~~~~~~~
arch/riscv/mm/hugetlbpage.c:35:2: note: in expansion of macro 'pr_err'
35 | pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
| ^~~~~~
arch/riscv/mm/hugetlbpage.c:35:46: note: format string is defined here
35 | pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
| ~~^
| |
| long unsigned int
| %llu
arch/riscv/mm/hugetlbpage.c: In function 'arch_hugetlb_valid_size':
quoted
arch/riscv/mm/hugetlbpage.c:23:1: warning: control reaches end of non-void function [-Wreturn-type]
23 | }
| ^
vim +/ps +19 arch/riscv/mm/hugetlbpage.c
14
15 bool __init arch_hugetlb_valid_size(unsigned long long size)
16 {
17 if (size == HPAGE_SIZE)
18 return true;
> 19 else if (IS_ENABLED(CONFIG_64BIT) && ps == PUD_SIZE)
> 20 retrurn true;
21 else
22 return false;
> 23 }
24
25 static __init int setup_hugepagesz(char *opt)
26 {
27 unsigned long long ps = memparse(opt, &opt);
28
29 if (arch_hugetlb_valid_size(ps)) {
30 hugetlb_add_hstate(ilog2(ps) - PAGE_SHIFT);
31 return 1;
32 }
33
34 hugetlb_bad_size();
> 35 pr_err("hugepagesz: Unsupported page size %lu M\n", ps >> 20);
36 return 0;
37
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
From: kbuild test robot <hidden> Date: 2020-03-19 01:40:16
Hi Mike,
I love your patch! Yet something to improve:
[auto build test ERROR on next-20200318]
[also build test ERROR on v5.6-rc6]
[cannot apply to arm64/for-next/core powerpc/next sparc/master linus/master sparc-next/master v5.6-rc6 v5.6-rc5 v5.6-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Mike-Kravetz/Clean-up-hugetlb-boot-command-line-processing/20200319-060943
base: 47780d7892b77e922bbe19b5dea99cde06b2f0e5
config: i386-defconfig (attached as .config)
compiler: gcc-7 (Debian 7.5.0-5) 7.5.0
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <redacted>
All errors (new ones prefixed by >>):
ld: mm/hugetlb.o: in function `default_hugepagesz_setup':
quoted
hugetlb.c:(.init.text+0x16): undefined reference to `arch_hugetlb_valid_size'
From: Mike Kravetz <hidden> Date: 2020-03-19 02:44:49
On 3/18/20 5:20 PM, Randy Dunlap wrote:
Hi Mike,
On 3/18/20 3:06 PM, Mike Kravetz wrote:
quoted
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.
- Add comments to code
- Describe some of the subtle interactions
- Describe semantics of command line arguments
Signed-off-by: Mike Kravetz <redacted>
---
Documentation/admin-guide/mm/hugetlbpage.rst | 26 +++++++
mm/hugetlb.c | 78 +++++++++++++++-----
2 files changed, 87 insertions(+), 17 deletions(-)
@@ -3214,8 +3238,15 @@ 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 commnad line. The global
typo: command
Thanks
quoted
+ * variable 'parsed_valid_hugepagesz' is used to determine if prior
+ * hugepagesz argument was valid.
+ */
static int __init hugepagesz_setup(char *s)
{
unsigned long long size;
Does any of this need to be updated? (from Documentation/admin-guide/kernel-parameters.txt)
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).
No functional changes should be expected/seen as a result of these patches.
So the documentation here is basically OK. However, it is out of date as
more architectures are supported. In addition, the statement "this option
can be specified multiple times interleaved with hugepages= to reserve
huge pages of different sizes." may need a little clarification. As mentioned
elsewhere, hugepagesz= can only be specified once per huge page size.
I'll make some updates in v2.
--
Mike Kravetz
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 <redacted>
---
arch/arm64/include/asm/hugetlb.h | 2 ++
arch/arm64/mm/hugetlbpage.c | 19 ++++++++++++++-----
arch/powerpc/include/asm/hugetlb.h | 3 +++
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/include/asm/hugetlb.h | 3 +++
arch/riscv/mm/hugetlbpage.c | 28 ++++++++++++++++++----------
arch/s390/include/asm/hugetlb.h | 3 +++
arch/s390/mm/hugetlbpage.c | 18 +++++++++++++-----
arch/sparc/include/asm/hugetlb.h | 3 +++
arch/sparc/mm/init_64.c | 23 ++++++++++++++++-------
arch/x86/include/asm/hugetlb.h | 3 +++
arch/x86/mm/hugetlbpage.c | 21 +++++++++++++++------
include/linux/hugetlb.h | 7 +++++++
mm/hugetlb.c | 16 +++++++++++++---
14 files changed, 126 insertions(+), 43 deletions(-)
@@ -558,7 +558,7 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)returnvma_kernel_pagesize(vma);}-staticint__initadd_huge_page_size(unsignedlonglongsize)+bool__initarch_hugetlb_valid_size(unsignedlonglongsize){intshift=__ffs(size);intmmu_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*thatitfitswithinpagetableandslicelimits.*/if(size<=PAGE_SIZE||!is_power_of_2(size))-return-EINVAL;+returnfalse;mmu_psize=check_and_get_huge_psize(shift);if(mmu_psize<0)-return-EINVAL;+returnfalse;BUG_ON(mmu_psize_defs[mmu_psize].shift!=shift);-/* Return if huge page size has already been setup */-if(size_to_hstate(size))-return0;+returntrue;+}-hugetlb_add_hstate(shift-PAGE_SHIFT);+staticint__initadd_huge_page_size(unsignedlonglongsize)+{+intshift=__ffs(size);++if(!arch_hugetlb_valid_size(size))+return-EINVAL;+if(!size_to_hstate(size))+hugetlb_add_hstate(shift-PAGE_SHIFT);return0;}
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 <redacted>
---
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 | 24 ++++++++++++++++++------
8 files changed, 18 insertions(+), 109 deletions(-)
@@ -3149,12 +3149,6 @@ static int __init hugetlb_init(void)}subsys_initcall(hugetlb_init);-/* Should be called on processing a hugepagesz=... option */-void__inithugetlb_bad_size(void)-{-parsed_valid_hugepagesz=false;-}-void__inithugetlb_add_hstate(unsignedintorder){structhstate*h;
@@ -3224,6 +3218,24 @@ static int __init hugetlb_nrpages_setup(char *s)}__setup("hugepages=",hugetlb_nrpages_setup);+staticint__inithugepagesz_setup(char*s)+{+unsignedlonglongsize;+char*saved_s=s;++size=memparse(s,&s);
You don't use s after that, so you can pass NULL instead of &s and avoid
the saved_s
From: Mike Kravetz <hidden> Date: 2020-03-19 17:08:33
On 3/19/20 12:04 AM, Christophe Leroy wrote:
Le 18/03/2020 à 23:06, Mike Kravetz a écrit :
quoted
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 <redacted>
---
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 | 24 ++++++++++++++++++------
8 files changed, 18 insertions(+), 109 deletions(-)
@@ -3149,12 +3149,6 @@ static int __init hugetlb_init(void)}subsys_initcall(hugetlb_init);-/* Should be called on processing a hugepagesz=... option */-void__inithugetlb_bad_size(void)-{-parsed_valid_hugepagesz=false;-}-void__inithugetlb_add_hstate(unsignedintorder){structhstate*h;
@@ -3224,6 +3218,24 @@ static int __init hugetlb_nrpages_setup(char *s)}__setup("hugepages=",hugetlb_nrpages_setup);+staticint__inithugepagesz_setup(char*s)+{+unsignedlonglongsize;+char*saved_s=s;++size=memparse(s,&s);
You don't use s after that, so you can pass NULL instead of &s and avoid the saved_s
From: Mike Kravetz <hidden> Date: 2020-03-19 18:19:31
On 3/19/20 12:00 AM, Christophe Leroy wrote:
Le 18/03/2020 à 23:06, Mike Kravetz a écrit :
quoted
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 <redacted>
---
arch/arm64/include/asm/hugetlb.h | 2 ++
arch/arm64/mm/hugetlbpage.c | 19 ++++++++++++++-----
arch/powerpc/include/asm/hugetlb.h | 3 +++
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/include/asm/hugetlb.h | 3 +++
arch/riscv/mm/hugetlbpage.c | 28 ++++++++++++++++++----------
arch/s390/include/asm/hugetlb.h | 3 +++
arch/s390/mm/hugetlbpage.c | 18 +++++++++++++-----
arch/sparc/include/asm/hugetlb.h | 3 +++
arch/sparc/mm/init_64.c | 23 ++++++++++++++++-------
arch/x86/include/asm/hugetlb.h | 3 +++
arch/x86/mm/hugetlbpage.c | 21 +++++++++++++++------
include/linux/hugetlb.h | 7 +++++++
mm/hugetlb.c | 16 +++++++++++++---
14 files changed, 126 insertions(+), 43 deletions(-)
@@ -558,7 +558,7 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)returnvma_kernel_pagesize(vma);}-staticint__initadd_huge_page_size(unsignedlonglongsize)+bool__initarch_hugetlb_valid_size(unsignedlonglongsize){intshift=__ffs(size);intmmu_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*thatitfitswithinpagetableandslicelimits.*/if(size<=PAGE_SIZE||!is_power_of_2(size))-return-EINVAL;+returnfalse;mmu_psize=check_and_get_huge_psize(shift);if(mmu_psize<0)-return-EINVAL;+returnfalse;BUG_ON(mmu_psize_defs[mmu_psize].shift!=shift);-/* Return if huge page size has already been setup */-if(size_to_hstate(size))-return0;+returntrue;+}-hugetlb_add_hstate(shift-PAGE_SHIFT);+staticint__initadd_huge_page_size(unsignedlonglongsize)+{+intshift=__ffs(size);++if(!arch_hugetlb_valid_size(size))+return-EINVAL;+if(!size_to_hstate(size))+hugetlb_add_hstate(shift-PAGE_SHIFT);return0;}
@@ -3224,12 +3224,22 @@ static int __init hugetlb_nrpages_setup(char *s)}__setup("hugepages=",hugetlb_nrpages_setup);-staticint__inithugetlb_default_setup(char*s)+staticint__initdefault_hugepagesz_setup(char*s){-default_hstate_size=memparse(s,&s);+unsignedlonglongsize;
Why unsigned long long ?
default_hstate_size is long.
Only because memparse is defined as unsigned long long. I actually took
this from the existing powerpc hugetlb setup code. There are no compiler
warnings/issues assigning unsigned long long to long on 64 bit builds.
Thought there would be on 32 bit platformes.
That was also the reason for making the argument to arch_hugetlb_valid_size
be unsigned long long. So that it would match the type from memparse.
I suppose making these unsigned long and casting would be OK based on the
expected sizes.
I can't imagine 32 bits platforms having a hugepage with a 64 bits size.
quoted
+ char *saved_s = s;
+
+ size = memparse(s, &s);
The updated s is not reused after that so you can pass NULL instead of &s and then you don't need the saved_s.
Thanks for this and all the comments. I will incorporate in v2.
--
Mike Kravetz
From: Mina Almasry <hidden> Date: 2020-03-23 23:43:37
On Wed, Mar 18, 2020 at 3:07 PM Mike Kravetz [off-list ref] wrote:
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 <redacted>
---
arch/arm64/include/asm/hugetlb.h | 2 ++
arch/arm64/mm/hugetlbpage.c | 19 ++++++++++++++-----
arch/powerpc/include/asm/hugetlb.h | 3 +++
arch/powerpc/mm/hugetlbpage.c | 20 +++++++++++++-------
arch/riscv/include/asm/hugetlb.h | 3 +++
arch/riscv/mm/hugetlbpage.c | 28 ++++++++++++++++++----------
arch/s390/include/asm/hugetlb.h | 3 +++
arch/s390/mm/hugetlbpage.c | 18 +++++++++++++-----
arch/sparc/include/asm/hugetlb.h | 3 +++
arch/sparc/mm/init_64.c | 23 ++++++++++++++++-------
arch/x86/include/asm/hugetlb.h | 3 +++
arch/x86/mm/hugetlbpage.c | 21 +++++++++++++++------
include/linux/hugetlb.h | 7 +++++++
mm/hugetlb.c | 16 +++++++++++++---
14 files changed, 126 insertions(+), 43 deletions(-)
With build fixes:
Acked-by: Mina Almasry <redacted>
From: Mina Almasry <hidden> Date: 2020-03-23 23:56:57
On Thu, Mar 19, 2020 at 12:04 AM Christophe Leroy
[off-list ref] wrote:
Le 18/03/2020 à 23:06, Mike Kravetz a écrit :
quoted
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 <redacted>
---
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 | 24 ++++++++++++++++++------
8 files changed, 18 insertions(+), 109 deletions(-)
@@ -3149,12 +3149,6 @@ static int __init hugetlb_init(void)}subsys_initcall(hugetlb_init);-/* Should be called on processing a hugepagesz=... option */-void__inithugetlb_bad_size(void)-{-parsed_valid_hugepagesz=false;-}-void__inithugetlb_add_hstate(unsignedintorder){structhstate*h;
@@ -3224,6 +3218,24 @@ static int __init hugetlb_nrpages_setup(char *s)}__setup("hugepages=",hugetlb_nrpages_setup);+staticint__inithugepagesz_setup(char*s)+{+unsignedlonglongsize;+char*saved_s=s;++size=memparse(s,&s);
You don't use s after that, so you can pass NULL instead of &s and avoid
the saved_s
From: Mina Almasry <hidden> Date: 2020-03-24 00:01:20
On Wed, Mar 18, 2020 at 3:07 PM Mike Kravetz [off-list ref] wrote:
quoted hunk
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 <redacted>
---
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 | 10 +++++++---
6 files changed, 18 insertions(+), 34 deletions(-)
@@ -584,8 +584,7 @@ static int __init add_huge_page_size(unsigned long long size)if(!arch_hugetlb_valid_size(size))return-EINVAL;-if(!size_to_hstate(size))-hugetlb_add_hstate(shift-PAGE_SHIFT);+hugetlb_add_hstate(shift-PAGE_SHIFT);return0;}
@@ -26,7 +26,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
@@ -195,7 +195,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
Not too familiar with the code but I'm a bit confused by this print.
AFAICT this prints the warning when hugepagesz= refers to a hugepage
that is already added via hugetlb_add_hstate, but there is a default
hstate added here without the user specifying hugepagesz, no? Does
that mean the warning prints if you specify this size? Maybe then
clarify the message like:
'HugeTLB: hugepage size already supported: xxxxx' or
'HugeTLB: hugepage size xxxx specified twice or is default size, ignoring.'
Or don't print anything if it's the default size.
From: Mike Kravetz <hidden> Date: 2020-03-24 00:18:15
On 3/23/20 5:01 PM, Mina Almasry wrote:
On Wed, Mar 18, 2020 at 3:07 PM Mike Kravetz [off-list ref] wrote:
quoted
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 <redacted>
---
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 | 10 +++++++---
6 files changed, 18 insertions(+), 34 deletions(-)
@@ -584,8 +584,7 @@ static int __init add_huge_page_size(unsigned long long size)if(!arch_hugetlb_valid_size(size))return-EINVAL;-if(!size_to_hstate(size))-hugetlb_add_hstate(shift-PAGE_SHIFT);+hugetlb_add_hstate(shift-PAGE_SHIFT);return0;}
@@ -26,7 +26,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
@@ -195,7 +195,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
Not too familiar with the code but I'm a bit confused by this print.
AFAICT this prints the warning when hugepagesz= refers to a hugepage
that is already added via hugetlb_add_hstate, but there is a default
hstate added here without the user specifying hugepagesz, no?
Correct.
Does
that mean the warning prints if you specify this size?
The code which adds the default hstate (in hugetlb_init) runs after this
code which is reading/processing command line options. So, the case you
are concerned with will not happen.
Thanks for taking a look,
--
Mike Kravetz
'HugeTLB: hugepage size already supported: xxxxx' or
'HugeTLB: hugepage size xxxx specified twice or is default size, ignoring.'
Or don't print anything if it's the default size.
From: Mina Almasry <hidden> Date: 2020-03-24 00:23:29
On Mon, Mar 23, 2020 at 5:17 PM Mike Kravetz [off-list ref] wrote:
On 3/23/20 5:01 PM, Mina Almasry wrote:
quoted
On Wed, Mar 18, 2020 at 3:07 PM Mike Kravetz [off-list ref] wrote:
quoted
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 <redacted>
---
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 | 10 +++++++---
6 files changed, 18 insertions(+), 34 deletions(-)
@@ -584,8 +584,7 @@ static int __init add_huge_page_size(unsigned long long size)if(!arch_hugetlb_valid_size(size))return-EINVAL;-if(!size_to_hstate(size))-hugetlb_add_hstate(shift-PAGE_SHIFT);+hugetlb_add_hstate(shift-PAGE_SHIFT);return0;}
@@ -26,7 +26,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
@@ -195,7 +195,7 @@ bool __init arch_hugetlb_valid_size(unsigned long long size)static__initintgigantic_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);return0;}
Not too familiar with the code but I'm a bit confused by this print.
AFAICT this prints the warning when hugepagesz= refers to a hugepage
that is already added via hugetlb_add_hstate, but there is a default
hstate added here without the user specifying hugepagesz, no?
Correct.
quoted
Does
that mean the warning prints if you specify this size?
The code which adds the default hstate (in hugetlb_init) runs after this
code which is reading/processing command line options. So, the case you
are concerned with will not happen.
Thanks for taking a look,
--
Mike Kravetz
quoted
'HugeTLB: hugepage size already supported: xxxxx' or
'HugeTLB: hugepage size xxxx specified twice or is default size, ignoring.'
Or don't print anything if it's the default size.
From: Mina Almasry <hidden> Date: 2020-03-24 00:43:18
On Wed, Mar 18, 2020 at 3:07 PM Mike Kravetz [off-list ref] wrote:
With all hugetlb page processing done in a single file clean up code.
Now that all hugepage page processing is done in a single file, clean
up the code.
quoted hunk
- Make code match desired semantics
- Update documentation with semantics
- Make all warnings and errors messages start with 'HugeTLB:'.
- Consistently name command line parsing routines.
- Add comments to code
- Describe some of the subtle interactions
- Describe semantics of command line arguments
Signed-off-by: Mike Kravetz <redacted>
---
Documentation/admin-guide/mm/hugetlbpage.rst | 26 +++++++
mm/hugetlb.c | 78 +++++++++++++++-----
2 files changed, 87 insertions(+), 17 deletions(-)
@@ -100,6 +100,32 @@ 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 parameter. However, if hugepages is the+ first or only hugetlb command line parameter it specifies the number+ of huge pages of default size to allocate. The number of huge pages+ of default size specified in this manner can 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 512 2M huge pages being allocated. 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 on the command line. No other hugetlb command line+ parameter is associated with default_hugepagesz. Therefore, it can+ appear anywhere on the command line. Valid default huge page size is+ architecture dependent.
Maybe specify what happens/should happen in a case like:
hugepages=100 default_hugepagesz=1G
Does that allocate 100 2MB pages or 100 1G pages? Assuming the default
size is 2MB.
Also, regarding Randy's comment. It may be nice to keep these docs in
one place only, so we don't have to maintain 2 docs in sync.
quoted hunk
+
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
@@ -2954,7 +2954,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);}}
@@ -3058,7 +3058,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;
@@ -3109,19 +3109,35 @@ static int __init hugetlb_init(void)if(!hugepages_supported())return0;-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);-}-+/*+*MakesureHPAGE_SIZE(HUGETLB_PAGE_ORDER)hstateexists.Some+*architecturesdependonsetupbeingdonehere.+*+*Ifavaliddefaulthugepagesizewasspecifiedonthecommandline,+*addassociatedhstateifnecessary.Ifnot,setdefault_hstate_size+*todefaultsize.default_hstate_idxisusedatruntimetoidentify+*thedefaulthugepagesize/hstate.+*/+hugetlb_add_hstate(HUGETLB_PAGE_ORDER);+if(default_hstate_size)+hugetlb_add_hstate(ilog2(default_hstate_size)-PAGE_SHIFT);+elsedefault_hstate_size=HPAGE_SIZE;-hugetlb_add_hstate(HUGETLB_PAGE_ORDER);-}default_hstate_idx=hstate_index(size_to_hstate(default_hstate_size));++/*+*default_hstate_max_huge_pages!=0indicatesacount(hugepages=)+*specifiedbeforeasize(hugepagesz=).Usethiscountforthe+*defaulthugepagesize,unlessaspecificvaluewasspecifiedfor+*thissizeinahugepagesz/hugepagespair.+*/if(default_hstate_max_huge_pages){if(!default_hstate.max_huge_pages)-default_hstate.max_huge_pages=default_hstate_max_huge_pages;+default_hstate.max_huge_pages=+default_hstate_max_huge_pages;+else+pr_warn("HugeTLB: First hugepages=%lu kB ignored\n",+default_hstate_max_huge_pages);}hugetlb_init_hstates();
@@ -3174,20 +3190,27 @@ void __init hugetlb_add_hstate(unsigned int order)parsed_hstate=h;}-staticint__inithugetlb_nrpages_setup(char*s)+/*+*hugepagescommandlineprocessing+*hugepagesmustnormallyfollowsavalidhugepagszspecification.Ifnot,
'hugepages must' or 'hugepages normally follows'
+ * ignore the hugepages value. hugepages can also be the first huge page
+ * command line option in which case it 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 "
+ pr_warn("HugeTLB: hugepages = %s preceded by "
"an unsupported hugepagesz, ignoring\n", s);
parsed_valid_hugepagesz = true;
return 1;
}
/*
- * !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".
*/
else if (!hugetlb_max_hstate)
mhp = &default_hstate_max_huge_pages;
We don't set parsed_valid_hugepagesz to false at the end of this
function, shouldn't we? Parsing a hugepages= value should 'consume' a
previously defined hugepagesz= value, so that this is invalid IIUC:
hugepagesz=x hugepages=z hugepages=y
quoted hunk
@@ -3195,7 +3218,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");+ pr_warn("HugeTLB: hugepages= specified twice without interleaving hugepagesz=, ignoring hugepages=%s\n",+ s); return 1; }
@@ -3214,8 +3238,15 @@ 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 commnad 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 long size;
@@ -3230,16 +3261,23 @@ static int __init hugepagesz_setup(char *s) } if (size_to_hstate(size)) {+ parsed_valid_hugepagesz = false; pr_warn("HugeTLB: hugepagesz %s specified twice, ignoring\n", saved_s); return 0; }+ parsed_valid_hugepagesz = true; hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT); return 1; } __setup("hugepagesz=", hugepagesz_setup);+/*+ * default_hugepagesz command line input+ * Only one instance of default_hugepagesz allowed on command line. Do not+ * add hstate here as that will confuse hugepagesz/hugepages processing.+ */ static int __init default_hugepagesz_setup(char *s) { unsigned long long size;
On Wed, Mar 18, 2020 at 3:07 PM Mike Kravetz [off-list ref] wrote:
quoted
With all hugetlb page processing done in a single file clean up code.
Now that all hugepage page processing is done in a single file, clean
up the code.
quoted
- Make code match desired semantics
- Update documentation with semantics
- Make all warnings and errors messages start with 'HugeTLB:'.
- Consistently name command line parsing routines.
- Add comments to code
- Describe some of the subtle interactions
- Describe semantics of command line arguments
Signed-off-by: Mike Kravetz <redacted>
---
Documentation/admin-guide/mm/hugetlbpage.rst | 26 +++++++
mm/hugetlb.c | 78 +++++++++++++++-----
2 files changed, 87 insertions(+), 17 deletions(-)
@@ -100,6 +100,32 @@ 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 parameter. However, if hugepages is the+ first or only hugetlb command line parameter it specifies the number+ of huge pages of default size to allocate. The number of huge pages+ of default size specified in this manner can 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 512 2M huge pages being allocated. 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 on the command line. No other hugetlb command line+ parameter is associated with default_hugepagesz. Therefore, it can+ appear anywhere on the command line. Valid default huge page size is+ architecture dependent.
Maybe specify what happens/should happen in a case like:
hugepages=100 default_hugepagesz=1G
Does that allocate 100 2MB pages or 100 1G pages? Assuming the default
size is 2MB.
Also, regarding Randy's comment. It may be nice to keep these docs in
one place only, so we don't have to maintain 2 docs in sync.
quoted
+
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
@@ -2954,7 +2954,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);}}
@@ -3058,7 +3058,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;
@@ -3109,19 +3109,35 @@ static int __init hugetlb_init(void)if(!hugepages_supported())return0;-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);-}-+/*+*MakesureHPAGE_SIZE(HUGETLB_PAGE_ORDER)hstateexists.Some+*architecturesdependonsetupbeingdonehere.+*+*Ifavaliddefaulthugepagesizewasspecifiedonthecommandline,+*addassociatedhstateifnecessary.Ifnot,setdefault_hstate_size+*todefaultsize.default_hstate_idxisusedatruntimetoidentify+*thedefaulthugepagesize/hstate.+*/+hugetlb_add_hstate(HUGETLB_PAGE_ORDER);+if(default_hstate_size)+hugetlb_add_hstate(ilog2(default_hstate_size)-PAGE_SHIFT);+elsedefault_hstate_size=HPAGE_SIZE;-hugetlb_add_hstate(HUGETLB_PAGE_ORDER);-}default_hstate_idx=hstate_index(size_to_hstate(default_hstate_size));++/*+*default_hstate_max_huge_pages!=0indicatesacount(hugepages=)+*specifiedbeforeasize(hugepagesz=).Usethiscountforthe+*defaulthugepagesize,unlessaspecificvaluewasspecifiedfor+*thissizeinahugepagesz/hugepagespair.+*/if(default_hstate_max_huge_pages){if(!default_hstate.max_huge_pages)-default_hstate.max_huge_pages=default_hstate_max_huge_pages;+default_hstate.max_huge_pages=+default_hstate_max_huge_pages;+else+pr_warn("HugeTLB: First hugepages=%lu kB ignored\n",+default_hstate_max_huge_pages);}hugetlb_init_hstates();
@@ -3174,20 +3190,27 @@ void __init hugetlb_add_hstate(unsigned int order)parsed_hstate=h;}-staticint__inithugetlb_nrpages_setup(char*s)+/*+*hugepagescommandlineprocessing+*hugepagesmustnormallyfollowsavalidhugepagszspecification.Ifnot,
'hugepages must' or 'hugepages normally follows'
quoted
+ * ignore the hugepages value. hugepages can also be the first huge page
+ * command line option in which case it 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 "
+ pr_warn("HugeTLB: hugepages = %s preceded by "
"an unsupported hugepagesz, ignoring\n", s);
parsed_valid_hugepagesz = true;
return 1;
}
/*
- * !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".
*/
else if (!hugetlb_max_hstate)
mhp = &default_hstate_max_huge_pages;
We don't set parsed_valid_hugepagesz to false at the end of this
function, shouldn't we? Parsing a hugepages= value should 'consume' a
previously defined hugepagesz= value, so that this is invalid IIUC:
hugepagesz=x hugepages=z hugepages=y
In this case, we'll get:
"HugeTLB: hugepages= specified twice without interleaving hugepagesz=, ignoring
hugepages=y"
quoted
@@ -3195,7 +3218,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");+ pr_warn("HugeTLB: hugepages= specified twice without interleaving hugepagesz=, ignoring hugepages=%s\n",+ s); return 1; }
@@ -3214,8 +3238,15 @@ 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 commnad 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 long size;
@@ -3230,16 +3261,23 @@ static int __init hugepagesz_setup(char *s) } if (size_to_hstate(size)) {+ parsed_valid_hugepagesz = false; pr_warn("HugeTLB: hugepagesz %s specified twice, ignoring\n", saved_s); return 0; }+ parsed_valid_hugepagesz = true; hugetlb_add_hstate(ilog2(size) - PAGE_SHIFT); return 1; } __setup("hugepagesz=", hugepagesz_setup);+/*+ * default_hugepagesz command line input+ * Only one instance of default_hugepagesz allowed on command line. Do not+ * add hstate here as that will confuse hugepagesz/hugepages processing.+ */ static int __init default_hugepagesz_setup(char *s) { unsigned long long size;
From: Mike Kravetz <hidden> Date: 2020-03-25 01:13:38
On 3/23/20 8:47 PM, Longpeng (Mike, Cloud Infrastructure Service Product Dept.) wrote:
On 2020/3/24 8:43, Mina Almasry wrote:
quoted
On Wed, Mar 18, 2020 at 3:07 PM Mike Kravetz [off-list ref] wrote:
quoted
+default_hugepagesz - Specify the default huge page size. This parameter can
+ only be specified on the command line. No other hugetlb command line
+ parameter is associated with default_hugepagesz. Therefore, it can
+ appear anywhere on the command line. Valid default huge page size is
+ architecture dependent.
Maybe specify what happens/should happen in a case like:
hugepages=100 default_hugepagesz=1G
Does that allocate 100 2MB pages or 100 1G pages? Assuming the default
size is 2MB.
That will allocate 100 1G pages as 1G is the default. However, if the
command line reads:
hugepages=100 default_hugepagesz=1G hugepages=200
You will get this warning,
HugeTLB: First hugepages=104857600 kB ignored
quoted
Also, regarding Randy's comment. It may be nice to keep these docs in
one place only, so we don't have to maintain 2 docs in sync.
Let me think about that a bit. We should probably expand the
kernel-parameters doc. Or, we should at least make it more clear. This
doc also talks about the command line parameters and in general goes into
more detail. However, more people read kernel-parameters doc.
quoted
quoted
+
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
-static int __init hugetlb_nrpages_setup(char *s)
+/*
+ * hugepages command line processing
+ * hugepages must normally follows a valid hugepagsz specification. If not,
'hugepages must' or 'hugepages normally follows'
quoted
+ * ignore the hugepages value. hugepages can also be the first huge page
+ * command line option in which case it 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 "
+ pr_warn("HugeTLB: hugepages = %s preceded by "
"an unsupported hugepagesz, ignoring\n", s);
parsed_valid_hugepagesz = true;
return 1;
}
/*
- * !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".
*/
else if (!hugetlb_max_hstate)
mhp = &default_hstate_max_huge_pages;
We don't set parsed_valid_hugepagesz to false at the end of this
function, shouldn't we? Parsing a hugepages= value should 'consume' a
previously defined hugepagesz= value, so that this is invalid IIUC:
hugepagesz=x hugepages=z hugepages=y
In this case, we'll get:
"HugeTLB: hugepages= specified twice without interleaving hugepagesz=, ignoring
hugepages=y"
Thanks Longpeng (Mike),
I believe that is the desired message in this situation. The code uses saved
values of mhp (max hstate pointer) to catch this condition. Setting
parsed_valid_hugepagesz to false would result in the message:
HugeTLB: hugepages=y preceded by an unsupported hugepagesz, ignoring
Thanks for all your comments I will incorporate in v2 and send later this
week.
--
Mike Kravetz
I'm pretty sure it's possible to have a system without 2M/PMD page
support. We even have a handy-dandy comment about it in
arch/x86/include/asm/required-features.h:
#ifdef CONFIG_X86_64
#ifdef CONFIG_PARAVIRT
/* Paravirtualized systems may not have PSE or PGE available */
#define NEED_PSE 0
...
I *think* you need an X86_FEATURE_PSE check here to be totally correct.
if (size == PMD_SIZE && cpu_feature_enabled(X86_FEATURE_PSE))
return true;
BTW, I prefer cpu_feature_enabled() to boot_cpu_has() because it
includes disabled-features checking. I don't think any of it matters
for these specific features, but I generally prefer it on principle.
Sounds good. I'll incorporate those changes into a v2, unless someone
else with has a different opinion.
BTW, this patch should not really change the way the code works today.
It is mostly a movement of code. Unless I am missing something, the
existing code will always allow setup of PMD_SIZE hugetlb pages.
Hi Mike,
Inspired by Dave's opinion, it seems the x86-specific hugepages_supported should
also need to use cpu_feature_enabled instead.
Also, I wonder if the hugepages_supported is correct ? There're two arch
specific hugepages_supported:
x86:
#define hugepages_supported() boot_cpu_has(X86_FEATURE_PSE)
and
s390:
#define hugepages_supported() (MACHINE_HAS_EDAT1)
Is it possible that x86 has X86_FEATURE_GBPAGES but hasn't X86_FEATURE_GBPAGES
or s390 has MACHINE_HAS_EDAT2 but hasn't MACHINE_HAS_EDAT1 ?
---
Regards,
Longpeng(Mike)
From: Christian Borntraeger <hidden> Date: 2020-03-25 09:38:57
On 25.03.20 03:58, Longpeng (Mike, Cloud Infrastructure Service Product Dept.) wrote:
[...]
Hi Mike,
Inspired by Dave's opinion, it seems the x86-specific hugepages_supported should
also need to use cpu_feature_enabled instead.
Also, I wonder if the hugepages_supported is correct ? There're two arch
specific hugepages_supported:
x86:
#define hugepages_supported() boot_cpu_has(X86_FEATURE_PSE)
and
s390:
#define hugepages_supported() (MACHINE_HAS_EDAT1)
Is it possible that x86 has X86_FEATURE_GBPAGES but hasn't X86_FEATURE_GBPAGES
or s390 has MACHINE_HAS_EDAT2 but hasn't MACHINE_HAS_EDAT1 ?
The s390 architecture says that
When EDAT-2 applies, the following function is available in the DAT process:
- EDAT-1 applies.
[..]
So if the machine has EDAT-2 it also has EDAT-1.
From: Mike Kravetz <hidden> Date: 2020-03-26 22:04:51
On 3/18/20 4:36 PM, Dave Hansen wrote:
On 3/18/20 3:52 PM, Mike Kravetz wrote:
quoted
Sounds good. I'll incorporate those changes into a v2, unless someone
else with has a different opinion.
BTW, this patch should not really change the way the code works today.
It is mostly a movement of code. Unless I am missing something, the
existing code will always allow setup of PMD_SIZE hugetlb pages.
Hah, I totally skipped over the old code in the diff.
It looks like we'll disable hugetblfs *entirely* if PSE isn't supported.
I think this is actually wrong, but nobody ever noticed. I think you'd
have to be running as a guest under a hypervisor that's lying about PSE
not being supported *and* care about 1GB pages. Nobody does that.
Actually, !PSE will disable hugetlbfs a little later in the boot process.
You are talking about hugepages_supported() correct?
I think something really bad could happen in this situation (!PSE and
X86_FEATURE_GBPAGES). When parsing 'hugepages=' for gigantic pages we
immediately allocate from bootmem. This happens before later checks in
hugetlb_init for hugepages_supported(). So, I think we would end up
allocating GB pages from bootmem and not be able to use or free them. :(
Perhaps it would be best to check hugepages_supported() when parsing
hugetlb command line options. If not enabled, throw an error. This
will be much easier to do after moving all command line parsing to
arch independent code.
Is that a sufficient way to address this concern? I think it is a good
change in any case.
--
Mike Kravetz
From: Dave Hansen <hidden> Date: 2020-03-26 23:11:00
On 3/26/20 2:56 PM, Mike Kravetz wrote:
Perhaps it would be best to check hugepages_supported() when parsing
hugetlb command line options. If not enabled, throw an error. This
will be much easier to do after moving all command line parsing to
arch independent code.
Yeah, that sounds sane.
Is that a sufficient way to address this concern? I think it is a good
change in any case.
(Thanks to Kirill for pointing this out.)
So, it turns out the x86 huge page enumeration is totally buggered.
X86_FEATURE_PSE is actually meaningless on 64-bit (and 32-bit PAE). All
CPUs architecturally support 2MB pages regardless of X86_FEATURE_PSE and
the state of CR4.PSE.
So, on x86_64 at least, hugepages_supported() should *always* return 1.
1GB page support can continue to be dependent on X86_FEATURE_GBPAGES.