s390/boot: cleanup number of page table levels setup
authorAlexander Gordeev <agordeev@linux.ibm.com>
Thu, 6 Jul 2023 10:28:17 +0000 (12:28 +0200)
committerHeiko Carstens <hca@linux.ibm.com>
Wed, 16 Aug 2023 13:13:02 +0000 (15:13 +0200)
The separate vmalloc area size check against _REGION2_SIZE
is needed in case user provided insanely large value using
vmalloc= kernel command line parameter. That could lead to
overflow and selecting 3 page table levels instead of 4.

Use size_add() for the overflow check and get rid of the
extra vmalloc area check.

With the current values of CONFIG_MAX_PHYSMEM_BITS and
PAGES_PER_SECTION the sum of maximal possible size of
identity mapping and vmemmap area (derived from these
macros) plus modules area size MODULES_LEN can not
overflow. Thus, that sum is used as first addend while
vmalloc area size is second addend for size_add().

Suggested-by: Heiko Carstens <hca@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/boot/startup.c

index a1f792fcc710d382f1f09a4da86a979e24685286..b058e2a575c1707bd62e870a060315aa6c4a96b5 100644 (file)
@@ -177,6 +177,7 @@ static unsigned long setup_kernel_memory_layout(void)
        unsigned long asce_limit;
        unsigned long rte_size;
        unsigned long pages;
+       unsigned long vsize;
        unsigned long vmax;
 
        pages = ident_map_size / PAGE_SIZE;
@@ -184,11 +185,9 @@ static unsigned long setup_kernel_memory_layout(void)
        vmemmap_size = SECTION_ALIGN_UP(pages) * sizeof(struct page);
 
        /* choose kernel address space layout: 4 or 3 levels. */
-       vmemmap_start = round_up(ident_map_size, _REGION3_SIZE);
-       if (IS_ENABLED(CONFIG_KASAN) ||
-           vmalloc_size > _REGION2_SIZE ||
-           vmemmap_start + vmemmap_size + vmalloc_size + MODULES_LEN >
-                   _REGION2_SIZE) {
+       vsize = round_up(ident_map_size, _REGION3_SIZE) + vmemmap_size + MODULES_LEN;
+       vsize = size_add(vsize, vmalloc_size);
+       if (IS_ENABLED(CONFIG_KASAN) || (vsize > _REGION2_SIZE)) {
                asce_limit = _REGION1_SIZE;
                rte_size = _REGION2_SIZE;
        } else {