* [PATCH v7 12/14] powerpc/mm: Enable full randomisation of memory mappings
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Do like most other architectures and provide randomisation also to
"legacy" memory mappings, by adding the random factor to
mm->mmap_base in arch_pick_mmap_layout().
See commit 8b8addf891de ("x86/mm/32: Enable full randomization on
i386 and X86_32") for all explanations and benefits of that mmap
randomisation.
At the moment, slice_find_area_bottomup() doesn't use mm->mmap_base
but uses the fixed TASK_UNMAPPED_BASE instead.
slice_find_area_bottomup() being used as a fallback to
slice_find_area_topdown(), it can't use mm->mmap_base
directly.
Instead of always using TASK_UNMAPPED_BASE as base address, leave
it to the caller. When called from slice_find_area_topdown()
TASK_UNMAPPED_BASE is used. Otherwise mm->mmap_base is used.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/mm/book3s64/slice.c | 18 +++++++-----------
arch/powerpc/mm/mmap.c | 2 +-
2 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/arch/powerpc/mm/book3s64/slice.c b/arch/powerpc/mm/book3s64/slice.c
index 03681042b807..c0b58afb9a47 100644
--- a/arch/powerpc/mm/book3s64/slice.c
+++ b/arch/powerpc/mm/book3s64/slice.c
@@ -276,20 +276,18 @@ static bool slice_scan_available(unsigned long addr,
}
static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
- unsigned long len,
+ unsigned long addr, unsigned long len,
const struct slice_mask *available,
int psize, unsigned long high_limit)
{
int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
- unsigned long addr, found, next_end;
+ unsigned long found, next_end;
struct vm_unmapped_area_info info;
info.flags = 0;
info.length = len;
info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
info.align_offset = 0;
-
- addr = TASK_UNMAPPED_BASE;
/*
* Check till the allow max value for this mmap request
*/
@@ -322,12 +320,12 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
}
static unsigned long slice_find_area_topdown(struct mm_struct *mm,
- unsigned long len,
+ unsigned long addr, unsigned long len,
const struct slice_mask *available,
int psize, unsigned long high_limit)
{
int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
- unsigned long addr, found, prev;
+ unsigned long found, prev;
struct vm_unmapped_area_info info;
unsigned long min_addr = max(PAGE_SIZE, mmap_min_addr);
@@ -335,8 +333,6 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
info.length = len;
info.align_mask = PAGE_MASK & ((1ul << pshift) - 1);
info.align_offset = 0;
-
- addr = mm->mmap_base;
/*
* If we are trying to allocate above DEFAULT_MAP_WINDOW
* Add the different to the mmap_base.
@@ -377,7 +373,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
* can happen with large stack limits and large mmap()
* allocations.
*/
- return slice_find_area_bottomup(mm, len, available, psize, high_limit);
+ return slice_find_area_bottomup(mm, TASK_UNMAPPED_BASE, len, available, psize, high_limit);
}
@@ -386,9 +382,9 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
int topdown, unsigned long high_limit)
{
if (topdown)
- return slice_find_area_topdown(mm, len, mask, psize, high_limit);
+ return slice_find_area_topdown(mm, mm->mmap_base, len, mask, psize, high_limit);
else
- return slice_find_area_bottomup(mm, len, mask, psize, high_limit);
+ return slice_find_area_bottomup(mm, mm->mmap_base, len, mask, psize, high_limit);
}
static inline void slice_copy_mask(struct slice_mask *dst,
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
index 5972d619d274..d9eae456558a 100644
--- a/arch/powerpc/mm/mmap.c
+++ b/arch/powerpc/mm/mmap.c
@@ -96,7 +96,7 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
* bit is set, or if the expected stack growth is unlimited:
*/
if (mmap_is_legacy(rlim_stack)) {
- mm->mmap_base = TASK_UNMAPPED_BASE;
+ mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
mm->get_unmapped_area = arch_get_unmapped_area;
} else {
mm->mmap_base = mmap_base(random_factor, rlim_stack);
--
2.33.1
^ permalink raw reply related
* [PATCH v7 11/14] powerpc/mm: Move get_unmapped_area functions to slice.c
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
hugetlb_get_unmapped_area() is now identical to the
generic version if only RADIX is enabled, so move it
to slice.c and let it fallback on the generic one
when HASH MMU is not compiled in.
Do the same with arch_get_unmapped_area() and
arch_get_unmapped_area_topdown().
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/include/asm/book3s/64/mmu.h | 6 ----
arch/powerpc/include/asm/book3s/64/slice.h | 6 ++++
arch/powerpc/mm/book3s64/slice.c | 42 ++++++++++++++++++++++
arch/powerpc/mm/hugetlbpage.c | 21 -----------
arch/powerpc/mm/mmap.c | 36 -------------------
5 files changed, 48 insertions(+), 63 deletions(-)
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h
index ba5b1becf518..db47524fa8ea 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu.h
@@ -4,12 +4,6 @@
#include <asm/page.h>
-#ifdef CONFIG_HUGETLB_PAGE
-#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-#endif
-#define HAVE_ARCH_UNMAPPED_AREA
-#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
-
#ifndef __ASSEMBLY__
/*
* Page size definition
diff --git a/arch/powerpc/include/asm/book3s/64/slice.h b/arch/powerpc/include/asm/book3s/64/slice.h
index 5b0f7105bc8b..b8eb4ad271b9 100644
--- a/arch/powerpc/include/asm/book3s/64/slice.h
+++ b/arch/powerpc/include/asm/book3s/64/slice.h
@@ -4,6 +4,12 @@
#ifndef __ASSEMBLY__
+#ifdef CONFIG_HUGETLB_PAGE
+#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#endif
+#define HAVE_ARCH_UNMAPPED_AREA
+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+
#define SLICE_LOW_SHIFT 28
#define SLICE_LOW_TOP (0x100000000ul)
#define SLICE_NUM_LOW (SLICE_LOW_TOP >> SLICE_LOW_SHIFT)
diff --git a/arch/powerpc/mm/book3s64/slice.c b/arch/powerpc/mm/book3s64/slice.c
index e4382713746d..03681042b807 100644
--- a/arch/powerpc/mm/book3s64/slice.c
+++ b/arch/powerpc/mm/book3s64/slice.c
@@ -639,6 +639,32 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
}
EXPORT_SYMBOL_GPL(slice_get_unmapped_area);
+unsigned long arch_get_unmapped_area(struct file *filp,
+ unsigned long addr,
+ unsigned long len,
+ unsigned long pgoff,
+ unsigned long flags)
+{
+ if (radix_enabled())
+ return generic_get_unmapped_area(filp, addr, len, pgoff, flags);
+
+ return slice_get_unmapped_area(addr, len, flags,
+ mm_ctx_user_psize(¤t->mm->context), 0);
+}
+
+unsigned long arch_get_unmapped_area_topdown(struct file *filp,
+ const unsigned long addr0,
+ const unsigned long len,
+ const unsigned long pgoff,
+ const unsigned long flags)
+{
+ if (radix_enabled())
+ return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags);
+
+ return slice_get_unmapped_area(addr0, len, flags,
+ mm_ctx_user_psize(¤t->mm->context), 1);
+}
+
unsigned int notrace get_slice_psize(struct mm_struct *mm, unsigned long addr)
{
unsigned char *psizes;
@@ -766,4 +792,20 @@ unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
return 1UL << mmu_psize_to_shift(get_slice_psize(vma->vm_mm, vma->vm_start));
}
+
+static int file_to_psize(struct file *file)
+{
+ struct hstate *hstate = hstate_file(file);
+ return shift_to_mmu_psize(huge_page_shift(hstate));
+}
+
+unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ if (radix_enabled())
+ return generic_hugetlb_get_unmapped_area(file, addr, len, pgoff, flags);
+
+ return slice_get_unmapped_area(addr, len, flags, file_to_psize(file), 1);
+}
#endif
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index bfd7f4af1e58..eb9de09e49a3 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -542,27 +542,6 @@ struct page *follow_huge_pd(struct vm_area_struct *vma,
return page;
}
-#ifdef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-static inline int file_to_psize(struct file *file)
-{
- struct hstate *hstate = hstate_file(file);
- return shift_to_mmu_psize(huge_page_shift(hstate));
-}
-
-unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags)
-{
- if (radix_enabled())
- return generic_hugetlb_get_unmapped_area(file, addr, len,
- pgoff, flags);
-#ifdef CONFIG_PPC_64S_HASH_MMU
- return slice_get_unmapped_area(addr, len, flags, file_to_psize(file), 1);
-#endif
- BUG();
-}
-#endif
-
bool __init arch_hugetlb_valid_size(unsigned long size)
{
int shift = __ffs(size);
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
index 46781d0103d1..5972d619d274 100644
--- a/arch/powerpc/mm/mmap.c
+++ b/arch/powerpc/mm/mmap.c
@@ -80,42 +80,6 @@ static inline unsigned long mmap_base(unsigned long rnd,
return PAGE_ALIGN(DEFAULT_MAP_WINDOW - gap - rnd);
}
-#ifdef HAVE_ARCH_UNMAPPED_AREA
-unsigned long arch_get_unmapped_area(struct file *filp,
- unsigned long addr,
- unsigned long len,
- unsigned long pgoff,
- unsigned long flags)
-{
- if (radix_enabled())
- return generic_get_unmapped_area(filp, addr, len, pgoff, flags);
-
-#ifdef CONFIG_PPC_64S_HASH_MMU
- return slice_get_unmapped_area(addr, len, flags,
- mm_ctx_user_psize(¤t->mm->context), 0);
-#else
- BUG();
-#endif
-}
-
-unsigned long arch_get_unmapped_area_topdown(struct file *filp,
- const unsigned long addr0,
- const unsigned long len,
- const unsigned long pgoff,
- const unsigned long flags)
-{
- if (radix_enabled())
- return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags);
-
-#ifdef CONFIG_PPC_64S_HASH_MMU
- return slice_get_unmapped_area(addr0, len, flags,
- mm_ctx_user_psize(¤t->mm->context), 1);
-#else
- BUG();
-#endif
-}
-#endif /* HAVE_ARCH_UNMAPPED_AREA */
-
/*
* This function, called very early during the creation of a new
* process VM image, sets up which VM layout function to use:
--
2.33.1
^ permalink raw reply related
* [PATCH v7 05/14] sizes.h: Add SZ_1T macro
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: Krzysztof Wilczyński, will@kernel.org,
catalin.marinas@arm.com, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, linux-pci@vger.kernel.org, Bjorn Helgaas,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org, Toan Le,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Today drivers/pci/controller/pci-xgene.c defines SZ_1T
Move it into linux/sizes.h so that it can be re-used elsewhere.
Cc: Toan Le <toan@os.amperecomputing.com>
Cc: linux-pci@vger.kernel.org
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Krzysztof Wilczyński <kw@linux.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
---
drivers/pci/controller/pci-xgene.c | 1 -
include/linux/sizes.h | 2 ++
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/pci-xgene.c b/drivers/pci/controller/pci-xgene.c
index 56d0d50338c8..716dcab5ca47 100644
--- a/drivers/pci/controller/pci-xgene.c
+++ b/drivers/pci/controller/pci-xgene.c
@@ -49,7 +49,6 @@
#define EN_REG 0x00000001
#define OB_LO_IO 0x00000002
#define XGENE_PCIE_DEVICEID 0xE004
-#define SZ_1T (SZ_1G*1024ULL)
#define PIPE_PHY_RATE_RD(src) ((0xc000 & (u32)(src)) >> 0xe)
#define XGENE_V1_PCI_EXP_CAP 0x40
diff --git a/include/linux/sizes.h b/include/linux/sizes.h
index 1ac79bcee2bb..84aa448d8bb3 100644
--- a/include/linux/sizes.h
+++ b/include/linux/sizes.h
@@ -47,6 +47,8 @@
#define SZ_8G _AC(0x200000000, ULL)
#define SZ_16G _AC(0x400000000, ULL)
#define SZ_32G _AC(0x800000000, ULL)
+
+#define SZ_1T _AC(0x10000000000, ULL)
#define SZ_64T _AC(0x400000000000, ULL)
#endif /* __LINUX_SIZES_H__ */
--
2.33.1
^ permalink raw reply related
* [PATCH v7 10/14] powerpc/mm: Use generic_hugetlb_get_unmapped_area()
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Use the generic version of arch_hugetlb_get_unmapped_area()
which is now available at all time.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/include/asm/book3s/64/hugetlb.h | 4 --
arch/powerpc/mm/book3s64/radix_hugetlbpage.c | 55 --------------------
arch/powerpc/mm/hugetlbpage.c | 4 +-
3 files changed, 1 insertion(+), 62 deletions(-)
diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb.h b/arch/powerpc/include/asm/book3s/64/hugetlb.h
index 12e150e615b7..b37a28f62cf6 100644
--- a/arch/powerpc/include/asm/book3s/64/hugetlb.h
+++ b/arch/powerpc/include/asm/book3s/64/hugetlb.h
@@ -8,10 +8,6 @@
*/
void radix__flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
void radix__local_flush_hugetlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
-extern unsigned long
-radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags);
extern void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep,
diff --git a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
index 23d3e08911d3..d2fb776febb4 100644
--- a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
+++ b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
@@ -41,61 +41,6 @@ void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma, unsigned long st
radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize);
}
-/*
- * A vairant of hugetlb_get_unmapped_area doing topdown search
- * FIXME!! should we do as x86 does or non hugetlb area does ?
- * ie, use topdown or not based on mmap_is_legacy check ?
- */
-unsigned long
-radix__hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags)
-{
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
- struct hstate *h = hstate_file(file);
- int fixed = (flags & MAP_FIXED);
- unsigned long high_limit;
- struct vm_unmapped_area_info info;
-
- high_limit = DEFAULT_MAP_WINDOW;
- if (addr >= high_limit || (fixed && (addr + len > high_limit)))
- high_limit = TASK_SIZE;
-
- if (len & ~huge_page_mask(h))
- return -EINVAL;
- if (len > high_limit)
- return -ENOMEM;
-
- if (fixed) {
- if (addr > high_limit - len)
- return -ENOMEM;
- if (prepare_hugepage_range(file, addr, len))
- return -EINVAL;
- return addr;
- }
-
- if (addr) {
- addr = ALIGN(addr, huge_page_size(h));
- vma = find_vma(mm, addr);
- if (high_limit - len >= addr && addr >= mmap_min_addr &&
- (!vma || addr + len <= vm_start_gap(vma)))
- return addr;
- }
- /*
- * We are always doing an topdown search here. Slice code
- * does that too.
- */
- info.flags = VM_UNMAPPED_AREA_TOPDOWN;
- info.length = len;
- info.low_limit = max(PAGE_SIZE, mmap_min_addr);
- info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW);
- info.align_mask = PAGE_MASK & ~huge_page_mask(h);
- info.align_offset = 0;
-
- return vm_unmapped_area(&info);
-}
-
void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep,
pte_t old_pte, pte_t pte)
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index f18b3a1d18f0..bfd7f4af1e58 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -553,11 +553,9 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags)
{
-#ifdef CONFIG_PPC_RADIX_MMU
if (radix_enabled())
- return radix__hugetlb_get_unmapped_area(file, addr, len,
+ return generic_hugetlb_get_unmapped_area(file, addr, len,
pgoff, flags);
-#endif
#ifdef CONFIG_PPC_64S_HASH_MMU
return slice_get_unmapped_area(addr, len, flags, file_to_psize(file), 1);
#endif
--
2.33.1
^ permalink raw reply related
* [PATCH v7 09/14] powerpc/mm: Use generic_get_unmapped_area() and call it from arch_get_unmapped_area()
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Use the generic version of arch_get_unmapped_area() which
is now available at all time instead of its copy
radix__arch_get_unmapped_area()
To allow that for PPC64, add arch_get_mmap_base() and
arch_get_mmap_end() macros.
Instead of setting mm->get_unmapped_area() to either
arch_get_unmapped_area() or generic_get_unmapped_area(),
always set it to arch_get_unmapped_area() and call
generic_get_unmapped_area() from there when radix is enabled.
Do the same with radix__arch_get_unmapped_area_topdown()
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/include/asm/task_size_64.h | 8 ++
arch/powerpc/mm/mmap.c | 127 ++----------------------
2 files changed, 14 insertions(+), 121 deletions(-)
diff --git a/arch/powerpc/include/asm/task_size_64.h b/arch/powerpc/include/asm/task_size_64.h
index 38fdf8041d12..5a709951c901 100644
--- a/arch/powerpc/include/asm/task_size_64.h
+++ b/arch/powerpc/include/asm/task_size_64.h
@@ -72,4 +72,12 @@
#define STACK_TOP_MAX TASK_SIZE_USER64
#define STACK_TOP (is_32bit_task() ? STACK_TOP_USER32 : STACK_TOP_USER64)
+#define arch_get_mmap_base(addr, base) \
+ (((addr) > DEFAULT_MAP_WINDOW) ? (base) + TASK_SIZE - DEFAULT_MAP_WINDOW : (base))
+
+#define arch_get_mmap_end(addr, len, flags) \
+ (((addr) > DEFAULT_MAP_WINDOW) || \
+ (((flags) & MAP_FIXED) && ((addr) + (len) > DEFAULT_MAP_WINDOW)) ? TASK_SIZE : \
+ DEFAULT_MAP_WINDOW)
+
#endif /* _ASM_POWERPC_TASK_SIZE_64_H */
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
index 9b0d6e395bc0..46781d0103d1 100644
--- a/arch/powerpc/mm/mmap.c
+++ b/arch/powerpc/mm/mmap.c
@@ -81,115 +81,15 @@ static inline unsigned long mmap_base(unsigned long rnd,
}
#ifdef HAVE_ARCH_UNMAPPED_AREA
-#ifdef CONFIG_PPC_RADIX_MMU
-/*
- * Same function as generic code used only for radix, because we don't need to overload
- * the generic one. But we will have to duplicate, because hash select
- * HAVE_ARCH_UNMAPPED_AREA
- */
-static unsigned long
-radix__arch_get_unmapped_area(struct file *filp, unsigned long addr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags)
-{
- struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma;
- int fixed = (flags & MAP_FIXED);
- unsigned long high_limit;
- struct vm_unmapped_area_info info;
-
- high_limit = DEFAULT_MAP_WINDOW;
- if (addr >= high_limit || (fixed && (addr + len > high_limit)))
- high_limit = TASK_SIZE;
-
- if (len > high_limit)
- return -ENOMEM;
-
- if (fixed) {
- if (addr > high_limit - len)
- return -ENOMEM;
- return addr;
- }
-
- if (addr) {
- addr = PAGE_ALIGN(addr);
- vma = find_vma(mm, addr);
- if (high_limit - len >= addr && addr >= mmap_min_addr &&
- (!vma || addr + len <= vm_start_gap(vma)))
- return addr;
- }
-
- info.flags = 0;
- info.length = len;
- info.low_limit = mm->mmap_base;
- info.high_limit = high_limit;
- info.align_mask = 0;
-
- return vm_unmapped_area(&info);
-}
-
-static unsigned long
-radix__arch_get_unmapped_area_topdown(struct file *filp,
- const unsigned long addr0,
- const unsigned long len,
- const unsigned long pgoff,
- const unsigned long flags)
-{
- struct vm_area_struct *vma;
- struct mm_struct *mm = current->mm;
- unsigned long addr = addr0;
- int fixed = (flags & MAP_FIXED);
- unsigned long high_limit;
- struct vm_unmapped_area_info info;
-
- high_limit = DEFAULT_MAP_WINDOW;
- if (addr >= high_limit || (fixed && (addr + len > high_limit)))
- high_limit = TASK_SIZE;
-
- if (len > high_limit)
- return -ENOMEM;
-
- if (fixed) {
- if (addr > high_limit - len)
- return -ENOMEM;
- return addr;
- }
-
- if (addr) {
- addr = PAGE_ALIGN(addr);
- vma = find_vma(mm, addr);
- if (high_limit - len >= addr && addr >= mmap_min_addr &&
- (!vma || addr + len <= vm_start_gap(vma)))
- return addr;
- }
-
- info.flags = VM_UNMAPPED_AREA_TOPDOWN;
- info.length = len;
- info.low_limit = max(PAGE_SIZE, mmap_min_addr);
- info.high_limit = mm->mmap_base + (high_limit - DEFAULT_MAP_WINDOW);
- info.align_mask = 0;
-
- addr = vm_unmapped_area(&info);
- if (!(addr & ~PAGE_MASK))
- return addr;
- VM_BUG_ON(addr != -ENOMEM);
-
- /*
- * A failed mmap() very likely causes application failure,
- * so fall back to the bottom-up function here. This scenario
- * can happen with large stack limits and large mmap()
- * allocations.
- */
- return radix__arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
-}
-#endif
-
unsigned long arch_get_unmapped_area(struct file *filp,
unsigned long addr,
unsigned long len,
unsigned long pgoff,
unsigned long flags)
{
+ if (radix_enabled())
+ return generic_get_unmapped_area(filp, addr, len, pgoff, flags);
+
#ifdef CONFIG_PPC_64S_HASH_MMU
return slice_get_unmapped_area(addr, len, flags,
mm_ctx_user_psize(¤t->mm->context), 0);
@@ -204,6 +104,9 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
const unsigned long pgoff,
const unsigned long flags)
{
+ if (radix_enabled())
+ return generic_get_unmapped_area_topdown(filp, addr0, len, pgoff, flags);
+
#ifdef CONFIG_PPC_64S_HASH_MMU
return slice_get_unmapped_area(addr0, len, flags,
mm_ctx_user_psize(¤t->mm->context), 1);
@@ -213,21 +116,6 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
}
#endif /* HAVE_ARCH_UNMAPPED_AREA */
-static void radix__arch_pick_mmap_layout(struct mm_struct *mm,
- unsigned long random_factor,
- struct rlimit *rlim_stack)
-{
-#ifdef CONFIG_PPC_RADIX_MMU
- if (mmap_is_legacy(rlim_stack)) {
- mm->mmap_base = TASK_UNMAPPED_BASE;
- mm->get_unmapped_area = radix__arch_get_unmapped_area;
- } else {
- mm->mmap_base = mmap_base(random_factor, rlim_stack);
- mm->get_unmapped_area = radix__arch_get_unmapped_area_topdown;
- }
-#endif
-}
-
/*
* This function, called very early during the creation of a new
* process VM image, sets up which VM layout function to use:
@@ -239,9 +127,6 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
if (current->flags & PF_RANDOMIZE)
random_factor = arch_mmap_rnd();
- if (radix_enabled())
- return radix__arch_pick_mmap_layout(mm, random_factor,
- rlim_stack);
/*
* Fall back to the standard layout if the personality
* bit is set, or if the expected stack growth is unlimited:
--
2.33.1
^ permalink raw reply related
* [PATCH v7 08/14] powerpc/mm: Remove CONFIG_PPC_MM_SLICES
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org, Nicholas Piggin,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
CONFIG_PPC_MM_SLICES is always selected by hash book3s/64.
CONFIG_PPC_MM_SLICES is never selected by other platforms.
Remove it.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/hugetlb.h | 2 +-
arch/powerpc/include/asm/paca.h | 7 -------
arch/powerpc/kernel/paca.c | 5 -----
arch/powerpc/mm/book3s64/Makefile | 3 +--
arch/powerpc/mm/book3s64/hash_utils.c | 14 --------------
arch/powerpc/mm/hugetlbpage.c | 2 +-
arch/powerpc/mm/mmap.c | 4 ++--
arch/powerpc/platforms/Kconfig.cputype | 4 ----
8 files changed, 5 insertions(+), 36 deletions(-)
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h
index 962708fa1017..46e0b9dc77bf 100644
--- a/arch/powerpc/include/asm/hugetlb.h
+++ b/arch/powerpc/include/asm/hugetlb.h
@@ -24,7 +24,7 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
unsigned long addr,
unsigned long len)
{
- if (IS_ENABLED(CONFIG_PPC_MM_SLICES) && !radix_enabled())
+ if (IS_ENABLED(CONFIG_PPC_64S_HASH_MMU) && !radix_enabled())
return slice_is_hugepage_only_range(mm, addr, len);
return 0;
}
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 295573a82c66..bd4dd02e61c8 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -152,16 +152,9 @@ struct paca_struct {
struct tlb_core_data tcd;
#endif /* CONFIG_PPC_BOOK3E */
-#ifdef CONFIG_PPC_BOOK3S
#ifdef CONFIG_PPC_64S_HASH_MMU
-#ifdef CONFIG_PPC_MM_SLICES
unsigned char mm_ctx_low_slices_psize[BITS_PER_LONG / BITS_PER_BYTE];
unsigned char mm_ctx_high_slices_psize[SLICE_ARRAY_SIZE];
-#else
- u16 mm_ctx_user_psize;
- u16 mm_ctx_sllp;
-#endif
-#endif
#endif
/*
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 39da688a9455..ba593fd60124 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -344,15 +344,10 @@ void copy_mm_to_paca(struct mm_struct *mm)
{
mm_context_t *context = &mm->context;
-#ifdef CONFIG_PPC_MM_SLICES
VM_BUG_ON(!mm_ctx_slb_addr_limit(context));
memcpy(&get_paca()->mm_ctx_low_slices_psize, mm_ctx_low_slices(context),
LOW_SLICE_ARRAY_SZ);
memcpy(&get_paca()->mm_ctx_high_slices_psize, mm_ctx_high_slices(context),
TASK_SLICE_ARRAY_SZ(context));
-#else /* CONFIG_PPC_MM_SLICES */
- get_paca()->mm_ctx_user_psize = context->user_psize;
- get_paca()->mm_ctx_sllp = context->sllp;
-#endif
}
#endif /* CONFIG_PPC_64S_HASH_MMU */
diff --git a/arch/powerpc/mm/book3s64/Makefile b/arch/powerpc/mm/book3s64/Makefile
index af2f3e75d458..d527dc8e30a8 100644
--- a/arch/powerpc/mm/book3s64/Makefile
+++ b/arch/powerpc/mm/book3s64/Makefile
@@ -5,7 +5,7 @@ ccflags-y := $(NO_MINIMAL_TOC)
obj-y += mmu_context.o pgtable.o trace.o
ifdef CONFIG_PPC_64S_HASH_MMU
CFLAGS_REMOVE_slb.o = $(CC_FLAGS_FTRACE)
-obj-y += hash_pgtable.o hash_utils.o hash_tlb.o slb.o
+obj-y += hash_pgtable.o hash_utils.o hash_tlb.o slb.o slice.o
obj-$(CONFIG_PPC_HASH_MMU_NATIVE) += hash_native.o
obj-$(CONFIG_PPC_4K_PAGES) += hash_4k.o
obj-$(CONFIG_PPC_64K_PAGES) += hash_64k.o
@@ -21,7 +21,6 @@ obj-$(CONFIG_PPC_RADIX_MMU) += radix_hugetlbpage.o
endif
obj-$(CONFIG_SPAPR_TCE_IOMMU) += iommu_api.o
obj-$(CONFIG_PPC_PKEY) += pkeys.o
-obj-$(CONFIG_PPC_MM_SLICES) += slice.o
# Instrumenting the SLB fault path can lead to duplicate SLB entries
KCOV_INSTRUMENT_slb.o := n
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
index 7abf82a698d3..154a5a860959 100644
--- a/arch/powerpc/mm/book3s64/hash_utils.c
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -1264,7 +1264,6 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
return pp;
}
-#ifdef CONFIG_PPC_MM_SLICES
static unsigned int get_paca_psize(unsigned long addr)
{
unsigned char *psizes;
@@ -1281,12 +1280,6 @@ static unsigned int get_paca_psize(unsigned long addr)
return (psizes[index >> 1] >> (mask_index * 4)) & 0xF;
}
-#else
-unsigned int get_paca_psize(unsigned long addr)
-{
- return get_paca()->mm_ctx_user_psize;
-}
-#endif
/*
* Demote a segment to using 4k pages.
@@ -1710,7 +1703,6 @@ DEFINE_INTERRUPT_HANDLER_RAW(do_hash_fault)
return 0;
}
-#ifdef CONFIG_PPC_MM_SLICES
static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
{
int psize = get_slice_psize(mm, ea);
@@ -1727,12 +1719,6 @@ static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
return true;
}
-#else
-static bool should_hash_preload(struct mm_struct *mm, unsigned long ea)
-{
- return true;
-}
-#endif
static void hash_preload(struct mm_struct *mm, pte_t *ptep, unsigned long ea,
bool is_exec, unsigned long trap)
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 0eec3b61bd13..f18b3a1d18f0 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -558,7 +558,7 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
return radix__hugetlb_get_unmapped_area(file, addr, len,
pgoff, flags);
#endif
-#ifdef CONFIG_PPC_MM_SLICES
+#ifdef CONFIG_PPC_64S_HASH_MMU
return slice_get_unmapped_area(addr, len, flags, file_to_psize(file), 1);
#endif
BUG();
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c
index c475cf810aa8..9b0d6e395bc0 100644
--- a/arch/powerpc/mm/mmap.c
+++ b/arch/powerpc/mm/mmap.c
@@ -190,7 +190,7 @@ unsigned long arch_get_unmapped_area(struct file *filp,
unsigned long pgoff,
unsigned long flags)
{
-#ifdef CONFIG_PPC_MM_SLICES
+#ifdef CONFIG_PPC_64S_HASH_MMU
return slice_get_unmapped_area(addr, len, flags,
mm_ctx_user_psize(¤t->mm->context), 0);
#else
@@ -204,7 +204,7 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
const unsigned long pgoff,
const unsigned long flags)
{
-#ifdef CONFIG_PPC_MM_SLICES
+#ifdef CONFIG_PPC_64S_HASH_MMU
return slice_get_unmapped_area(addr0, len, flags,
mm_ctx_user_psize(¤t->mm->context), 1);
#else
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 87bc1929ee5a..c775b566e7b4 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -376,7 +376,6 @@ config SPE
config PPC_64S_HASH_MMU
bool "Hash MMU Support"
depends on PPC_BOOK3S_64
- select PPC_MM_SLICES
default y
help
Enable support for the Power ISA Hash style MMU. This is implemented
@@ -450,9 +449,6 @@ config PPC_BOOK3E_MMU
def_bool y
depends on FSL_BOOKE || PPC_BOOK3E
-config PPC_MM_SLICES
- bool
-
config PPC_HAVE_PMU_SUPPORT
bool
--
2.33.1
^ permalink raw reply related
* [PATCH v7 07/14] powerpc/mm: Make slice specific to book3s/64
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org, Nicholas Piggin,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Since commit 555904d07eef ("powerpc/8xx: MM_SLICE is not needed
anymore") only book3s/64 selects CONFIG_PPC_MM_SLICES.
Move slice.c into mm/book3s64/
Move necessary stuff in asm/book3s/64/slice.h and
remove asm/slice.h
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 1 +
arch/powerpc/include/asm/book3s/64/slice.h | 18 ++++++++
arch/powerpc/include/asm/page.h | 1 -
arch/powerpc/include/asm/slice.h | 46 -------------------
arch/powerpc/mm/Makefile | 1 -
arch/powerpc/mm/book3s64/Makefile | 1 +
arch/powerpc/mm/{ => book3s64}/slice.c | 2 -
arch/powerpc/mm/nohash/mmu_context.c | 9 ----
arch/powerpc/mm/nohash/tlb.c | 4 --
9 files changed, 20 insertions(+), 63 deletions(-)
delete mode 100644 arch/powerpc/include/asm/slice.h
rename arch/powerpc/mm/{ => book3s64}/slice.c (99%)
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index 21f780942911..1c4eebbc69c9 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -18,6 +18,7 @@
* complete pgtable.h but only a portion of it.
*/
#include <asm/book3s/64/pgtable.h>
+#include <asm/book3s/64/slice.h>
#include <asm/task_size_64.h>
#include <asm/cpu_has_feature.h>
diff --git a/arch/powerpc/include/asm/book3s/64/slice.h b/arch/powerpc/include/asm/book3s/64/slice.h
index f0d3194ba41b..5b0f7105bc8b 100644
--- a/arch/powerpc/include/asm/book3s/64/slice.h
+++ b/arch/powerpc/include/asm/book3s/64/slice.h
@@ -2,6 +2,8 @@
#ifndef _ASM_POWERPC_BOOK3S_64_SLICE_H
#define _ASM_POWERPC_BOOK3S_64_SLICE_H
+#ifndef __ASSEMBLY__
+
#define SLICE_LOW_SHIFT 28
#define SLICE_LOW_TOP (0x100000000ul)
#define SLICE_NUM_LOW (SLICE_LOW_TOP >> SLICE_LOW_SHIFT)
@@ -13,4 +15,20 @@
#define SLB_ADDR_LIMIT_DEFAULT DEFAULT_MAP_WINDOW_USER64
+struct mm_struct;
+
+unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
+ unsigned long flags, unsigned int psize,
+ int topdown);
+
+unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr);
+
+void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
+ unsigned long len, unsigned int psize);
+
+void slice_init_new_context_exec(struct mm_struct *mm);
+void slice_setup_new_exec(void);
+
+#endif /* __ASSEMBLY__ */
+
#endif /* _ASM_POWERPC_BOOK3S_64_SLICE_H */
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index 254687258f42..62e0c6f12869 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -329,6 +329,5 @@ static inline unsigned long kaslr_offset(void)
#include <asm-generic/memory_model.h>
#endif /* __ASSEMBLY__ */
-#include <asm/slice.h>
#endif /* _ASM_POWERPC_PAGE_H */
diff --git a/arch/powerpc/include/asm/slice.h b/arch/powerpc/include/asm/slice.h
deleted file mode 100644
index 0bdd9c62eca0..000000000000
--- a/arch/powerpc/include/asm/slice.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_POWERPC_SLICE_H
-#define _ASM_POWERPC_SLICE_H
-
-#ifdef CONFIG_PPC_BOOK3S_64
-#include <asm/book3s/64/slice.h>
-#endif
-
-#ifndef __ASSEMBLY__
-
-struct mm_struct;
-
-#ifdef CONFIG_PPC_MM_SLICES
-
-#ifdef CONFIG_HUGETLB_PAGE
-#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
-#endif
-#define HAVE_ARCH_UNMAPPED_AREA
-#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
-
-unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
- unsigned long flags, unsigned int psize,
- int topdown);
-
-unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr);
-
-void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
- unsigned long len, unsigned int psize);
-
-void slice_init_new_context_exec(struct mm_struct *mm);
-void slice_setup_new_exec(void);
-
-#else /* CONFIG_PPC_MM_SLICES */
-
-static inline void slice_init_new_context_exec(struct mm_struct *mm) {}
-
-static inline unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
-{
- return 0;
-}
-
-#endif /* CONFIG_PPC_MM_SLICES */
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _ASM_POWERPC_SLICE_H */
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index df8172da2301..d4c20484dad9 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += nohash/
obj-$(CONFIG_PPC_BOOK3S_32) += book3s32/
obj-$(CONFIG_PPC_BOOK3S_64) += book3s64/
obj-$(CONFIG_NUMA) += numa.o
-obj-$(CONFIG_PPC_MM_SLICES) += slice.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o
obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o
diff --git a/arch/powerpc/mm/book3s64/Makefile b/arch/powerpc/mm/book3s64/Makefile
index 2d50cac499c5..af2f3e75d458 100644
--- a/arch/powerpc/mm/book3s64/Makefile
+++ b/arch/powerpc/mm/book3s64/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_PPC_RADIX_MMU) += radix_hugetlbpage.o
endif
obj-$(CONFIG_SPAPR_TCE_IOMMU) += iommu_api.o
obj-$(CONFIG_PPC_PKEY) += pkeys.o
+obj-$(CONFIG_PPC_MM_SLICES) += slice.o
# Instrumenting the SLB fault path can lead to duplicate SLB entries
KCOV_INSTRUMENT_slb.o := n
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/book3s64/slice.c
similarity index 99%
rename from arch/powerpc/mm/slice.c
rename to arch/powerpc/mm/book3s64/slice.c
index 8a3ac062b71e..e4382713746d 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/book3s64/slice.c
@@ -692,7 +692,6 @@ void slice_init_new_context_exec(struct mm_struct *mm)
bitmap_fill(mask->high_slices, SLICE_NUM_HIGH);
}
-#ifdef CONFIG_PPC_BOOK3S_64
void slice_setup_new_exec(void)
{
struct mm_struct *mm = current->mm;
@@ -704,7 +703,6 @@ void slice_setup_new_exec(void)
mm_ctx_set_slb_addr_limit(&mm->context, DEFAULT_MAP_WINDOW);
}
-#endif
void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
unsigned long len, unsigned int psize)
diff --git a/arch/powerpc/mm/nohash/mmu_context.c b/arch/powerpc/mm/nohash/mmu_context.c
index 85b048f04c56..ccd5819b1bd9 100644
--- a/arch/powerpc/mm/nohash/mmu_context.c
+++ b/arch/powerpc/mm/nohash/mmu_context.c
@@ -317,15 +317,6 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next,
*/
int init_new_context(struct task_struct *t, struct mm_struct *mm)
{
- /*
- * We have MMU_NO_CONTEXT set to be ~0. Hence check
- * explicitly against context.id == 0. This ensures that we properly
- * initialize context slice details for newly allocated mm's (which will
- * have id == 0) and don't alter context slice inherited via fork (which
- * will have id != 0).
- */
- if (mm->context.id == 0)
- slice_init_new_context_exec(mm);
mm->context.id = MMU_NO_CONTEXT;
mm->context.active = 0;
pte_frag_set(&mm->context, NULL);
diff --git a/arch/powerpc/mm/nohash/tlb.c b/arch/powerpc/mm/nohash/tlb.c
index fd2c77af5c55..7e1e7c3dc66a 100644
--- a/arch/powerpc/mm/nohash/tlb.c
+++ b/arch/powerpc/mm/nohash/tlb.c
@@ -773,9 +773,5 @@ void __init early_init_mmu(void)
#ifdef CONFIG_PPC_47x
early_init_mmu_47x();
#endif
-
-#ifdef CONFIG_PPC_MM_SLICES
- mm_ctx_set_slb_addr_limit(&init_mm.context, SLB_ADDR_LIMIT_DEFAULT);
-#endif
}
#endif /* CONFIG_PPC64 */
--
2.33.1
^ permalink raw reply related
* [PATCH v7 06/14] powerpc/mm: Move vma_mmu_pagesize()
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org, Nicholas Piggin,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
vma_mmu_pagesize() is only required for slices,
otherwise there is a generic weak version doing the
exact same thing.
Move it to slice.c
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
arch/powerpc/mm/hugetlbpage.c | 11 -----------
arch/powerpc/mm/slice.c | 9 +++++++++
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index ddead41e2194..0eec3b61bd13 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -565,17 +565,6 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
}
#endif
-unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
-{
- /* With radix we don't use slice, so derive it from vma*/
- if (IS_ENABLED(CONFIG_PPC_MM_SLICES) && !radix_enabled()) {
- unsigned int psize = get_slice_psize(vma->vm_mm, vma->vm_start);
-
- return 1UL << mmu_psize_to_shift(psize);
- }
- return vma_kernel_pagesize(vma);
-}
-
bool __init arch_hugetlb_valid_size(unsigned long size)
{
int shift = __ffs(size);
diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
index f42711f865f3..8a3ac062b71e 100644
--- a/arch/powerpc/mm/slice.c
+++ b/arch/powerpc/mm/slice.c
@@ -759,4 +759,13 @@ int slice_is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
return !slice_check_range_fits(mm, maskp, addr, len);
}
+
+unsigned long vma_mmu_pagesize(struct vm_area_struct *vma)
+{
+ /* With radix we don't use slice, so derive it from vma*/
+ if (radix_enabled())
+ return vma_kernel_pagesize(vma);
+
+ return 1UL << mmu_psize_to_shift(get_slice_psize(vma->vm_mm, vma->vm_start));
+}
#endif
--
2.33.1
^ permalink raw reply related
* [PATCH v7 03/14] mm: Add len and flags parameters to arch_get_mmap_end()
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, Steve Capper, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Powerpc needs flags and len to make decision on arch_get_mmap_end().
So add them as parameters to arch_get_mmap_end().
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/processor.h | 4 ++--
mm/mmap.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 6f41b65f9962..9ceec2bf4b93 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -91,8 +91,8 @@
#endif /* CONFIG_COMPAT */
#ifndef CONFIG_ARM64_FORCE_52BIT
-#define arch_get_mmap_end(addr) ((addr > DEFAULT_MAP_WINDOW) ? TASK_SIZE :\
- DEFAULT_MAP_WINDOW)
+#define arch_get_mmap_end(addr, len, flags) \
+ (((addr) > DEFAULT_MAP_WINDOW) ? TASK_SIZE : DEFAULT_MAP_WINDOW)
#define arch_get_mmap_base(addr, base) ((addr > DEFAULT_MAP_WINDOW) ? \
base + TASK_SIZE - DEFAULT_MAP_WINDOW :\
diff --git a/mm/mmap.c b/mm/mmap.c
index 7ac6a07ff382..ad48f7af7511 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2113,7 +2113,7 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info)
}
#ifndef arch_get_mmap_end
-#define arch_get_mmap_end(addr) (TASK_SIZE)
+#define arch_get_mmap_end(addr, len, flags) (TASK_SIZE)
#endif
#ifndef arch_get_mmap_base
@@ -2139,7 +2139,7 @@ generic_get_unmapped_area(struct file *filp, unsigned long addr,
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma, *prev;
struct vm_unmapped_area_info info;
- const unsigned long mmap_end = arch_get_mmap_end(addr);
+ const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
if (len > mmap_end - mmap_min_addr)
return -ENOMEM;
@@ -2187,7 +2187,7 @@ generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
struct vm_area_struct *vma, *prev;
struct mm_struct *mm = current->mm;
struct vm_unmapped_area_info info;
- const unsigned long mmap_end = arch_get_mmap_end(addr);
+ const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
/* requested length too big for entire address space */
if (len > mmap_end - mmap_min_addr)
--
2.33.1
^ permalink raw reply related
* [PATCH v7 04/14] mm, hugetlbfs: Allow for "high" userspace addresses
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, Steve Capper, catalin.marinas@arm.com,
Will Deacon, linux-kernel@vger.kernel.org, linux-mm@kvack.org,
stable@vger.kernel.org, akpm@linux-foundation.org,
linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
This is a complement of f6795053dac8 ("mm: mmap: Allow for "high"
userspace addresses") for hugetlb.
This patch adds support for "high" userspace addresses that are
optionally supported on the system and have to be requested via a hint
mechanism ("high" addr parameter to mmap).
Architectures such as powerpc and x86 achieve this by making changes to
their architectural versions of hugetlb_get_unmapped_area() function.
However, arm64 uses the generic version of that function.
So take into account arch_get_mmap_base() and arch_get_mmap_end() in
hugetlb_get_unmapped_area(). To allow that, move those two macros
out of mm/mmap.c into include/linux/sched/mm.h
If these macros are not defined in architectural code then they default
to (TASK_SIZE) and (base) so should not introduce any behavioural
changes to architectures that do not define them.
For the time being, only ARM64 is affected by this change.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Steve Capper <steve.capper@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Fixes: f6795053dac8 ("mm: mmap: Allow for "high" userspace addresses")
Cc: <stable@vger.kernel.org> # 5.0.x
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
---
fs/hugetlbfs/inode.c | 9 +++++----
include/linux/sched/mm.h | 8 ++++++++
mm/mmap.c | 8 --------
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index c7cde4e5924d..a8d3b0899b60 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -205,7 +205,7 @@ hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr,
info.flags = 0;
info.length = len;
info.low_limit = current->mm->mmap_base;
- info.high_limit = TASK_SIZE;
+ info.high_limit = arch_get_mmap_end(addr, len, flags);
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
info.align_offset = 0;
return vm_unmapped_area(&info);
@@ -221,7 +221,7 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
info.length = len;
info.low_limit = max(PAGE_SIZE, mmap_min_addr);
- info.high_limit = current->mm->mmap_base;
+ info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base);
info.align_mask = PAGE_MASK & ~huge_page_mask(h);
info.align_offset = 0;
addr = vm_unmapped_area(&info);
@@ -236,7 +236,7 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
VM_BUG_ON(addr != -ENOMEM);
info.flags = 0;
info.low_limit = current->mm->mmap_base;
- info.high_limit = TASK_SIZE;
+ info.high_limit = arch_get_mmap_end(addr, len, flags);
addr = vm_unmapped_area(&info);
}
@@ -251,6 +251,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
struct hstate *h = hstate_file(file);
+ const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
if (len & ~huge_page_mask(h))
return -EINVAL;
@@ -266,7 +267,7 @@ generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
if (addr) {
addr = ALIGN(addr, huge_page_size(h));
vma = find_vma(mm, addr);
- if (TASK_SIZE - len >= addr &&
+ if (mmap_end - len >= addr &&
(!vma || addr + len <= vm_start_gap(vma)))
return addr;
}
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index 2584f7c13f69..cc9d80bd36d5 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -135,6 +135,14 @@ static inline void mm_update_next_owner(struct mm_struct *mm)
#endif /* CONFIG_MEMCG */
#ifdef CONFIG_MMU
+#ifndef arch_get_mmap_end
+#define arch_get_mmap_end(addr, len, flags) (TASK_SIZE)
+#endif
+
+#ifndef arch_get_mmap_base
+#define arch_get_mmap_base(addr, base) (base)
+#endif
+
extern void arch_pick_mmap_layout(struct mm_struct *mm,
struct rlimit *rlim_stack);
extern unsigned long
diff --git a/mm/mmap.c b/mm/mmap.c
index ad48f7af7511..c773b5ad9a11 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2112,14 +2112,6 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info)
return addr;
}
-#ifndef arch_get_mmap_end
-#define arch_get_mmap_end(addr, len, flags) (TASK_SIZE)
-#endif
-
-#ifndef arch_get_mmap_base
-#define arch_get_mmap_base(addr, base) (base)
-#endif
-
/* Get an address range which is currently unmapped.
* For shmat() with addr=0.
*
--
2.33.1
^ permalink raw reply related
* [PATCH v7 02/14] mm, hugetlbfs: Allow an arch to always use generic versions of get_unmapped_area functions
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org, Nicholas Piggin,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Unlike most architectures, powerpc can only define at runtime
if it is going to use the generic arch_get_unmapped_area() or not.
Today, powerpc has a copy of the generic arch_get_unmapped_area()
because when selection HAVE_ARCH_UNMAPPED_AREA the generic
arch_get_unmapped_area() is not available.
Rename it generic_get_unmapped_area() and make it independent of
HAVE_ARCH_UNMAPPED_AREA.
Do the same for arch_get_unmapped_area_topdown() versus
HAVE_ARCH_UNMAPPED_AREA_TOPDOWN.
Do the same for hugetlb_get_unmapped_area() versus
HAVE_ARCH_HUGETLB_UNMAPPED_AREA.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
---
fs/hugetlbfs/inode.c | 17 +++++++++++++----
include/linux/hugetlb.h | 5 +++++
include/linux/sched/mm.h | 9 +++++++++
mm/mmap.c | 31 ++++++++++++++++++++++++-------
4 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 49d2e686be74..c7cde4e5924d 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -195,7 +195,6 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
* Called under mmap_write_lock(mm).
*/
-#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
static unsigned long
hugetlb_get_unmapped_area_bottomup(struct file *file, unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags)
@@ -244,9 +243,10 @@ hugetlb_get_unmapped_area_topdown(struct file *file, unsigned long addr,
return addr;
}
-static unsigned long
-hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
+unsigned long
+generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
@@ -282,6 +282,15 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
return hugetlb_get_unmapped_area_bottomup(file, addr, len,
pgoff, flags);
}
+
+#ifndef HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+static unsigned long
+hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ return generic_hugetlb_get_unmapped_area(file, addr, len, pgoff, flags);
+}
#endif
static size_t
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 00351ccb49a3..df899d1937ff 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -513,6 +513,11 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
unsigned long flags);
#endif /* HAVE_ARCH_HUGETLB_UNMAPPED_AREA */
+unsigned long
+generic_hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags);
+
/*
* huegtlb page specific state flags. These flags are located in page.private
* of the hugetlb head page. Functions created via the below macros should be
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index aca874d33fe6..2584f7c13f69 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -144,6 +144,15 @@ extern unsigned long
arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags);
+
+unsigned long
+generic_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags);
+unsigned long
+generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags);
#else
static inline void arch_pick_mmap_layout(struct mm_struct *mm,
struct rlimit *rlim_stack) {}
diff --git a/mm/mmap.c b/mm/mmap.c
index bfb0ea164a90..7ac6a07ff382 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2131,10 +2131,10 @@ unsigned long vm_unmapped_area(struct vm_unmapped_area_info *info)
*
* This function "knows" that -ENOMEM has the bits set.
*/
-#ifndef HAVE_ARCH_UNMAPPED_AREA
unsigned long
-arch_get_unmapped_area(struct file *filp, unsigned long addr,
- unsigned long len, unsigned long pgoff, unsigned long flags)
+generic_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma, *prev;
@@ -2164,17 +2164,25 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
info.align_offset = 0;
return vm_unmapped_area(&info);
}
+
+#ifndef HAVE_ARCH_UNMAPPED_AREA
+unsigned long
+arch_get_unmapped_area(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ return generic_get_unmapped_area(filp, addr, len, pgoff, flags);
+}
#endif
/*
* This mmap-allocator allocates new areas top-down from below the
* stack's low limit (the base):
*/
-#ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
unsigned long
-arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
- unsigned long len, unsigned long pgoff,
- unsigned long flags)
+generic_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
{
struct vm_area_struct *vma, *prev;
struct mm_struct *mm = current->mm;
@@ -2222,6 +2230,15 @@ arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
return addr;
}
+
+#ifndef HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
+ unsigned long len, unsigned long pgoff,
+ unsigned long flags)
+{
+ return generic_get_unmapped_area_topdown(filp, addr, len, pgoff, flags);
+}
#endif
unsigned long
--
2.33.1
^ permalink raw reply related
* [PATCH v7 01/14] mm: Allow arch specific arch_randomize_brk() with CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <cover.1642752946.git.christophe.leroy@csgroup.eu>
Commit e7142bf5d231 ("arm64, mm: make randomization selected by
generic topdown mmap layout") introduced a default version of
arch_randomize_brk() provided when
CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT is selected.
powerpc could select CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
but needs to provide its own arch_randomize_brk().
In order to allow that, define generic version of arch_randomize_brk()
as a __weak symbol.
Cc: Alexandre Ghiti <alex@ghiti.fr>
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
mm/util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/util.c b/mm/util.c
index 741ba32a43ac..46d1a2dd7a32 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -344,7 +344,7 @@ unsigned long randomize_stack_top(unsigned long stack_top)
}
#ifdef CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
-unsigned long arch_randomize_brk(struct mm_struct *mm)
+unsigned long __weak arch_randomize_brk(struct mm_struct *mm)
{
/* Is the current task 32bit ? */
if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task())
--
2.33.1
^ permalink raw reply related
* [PATCH v7 00/14] Convert powerpc to default topdown mmap layout
From: Christophe Leroy @ 2022-01-21 8:42 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
alex@ghiti.fr
Cc: will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
akpm@linux-foundation.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
Rebased on top of powerpc/next branch
This series converts powerpc to default topdown mmap layout.
powerpc requires its own arch_get_unmapped_area() only when
slices are needed, which is only for book3s/64. First part of
the series moves slices into book3s/64 specific directories
and cleans up other subarchitectures.
Last part converts to default topdown mmap layout.
A small modification is done to core mm to allow
powerpc to still provide its own arch_randomize_brk()
Another modification is done to core mm to allow powerpc
to use generic versions of get_unmapped_area functions for Radix
while still providing its own implementation for Hash, the
selection between Radix and Hash being doing at runtime.
Last modification to core mm is to give len and flags to
arch_get_mmap_end().
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Changes in v7:
- Taken into account comments from Catalin (patches 3 and 4)
Changes in v6:
- New patch (patch 4) to take arch_get_mmap_base() and arch_get_mmap_end() into account in generic hugetlb_get_unmapped_area()
- Get back arch_randomize_brk() simplification as it relies on default topdown mmap layout.
- Fixed precedence between || and && in powerpc's arch_get_mmap_end() (patch 9)
Changes in v5:
- Added patch 3
- Added arch_get_mmap_base() and arch_get_mmap_end() to patch 7 to better match original powerpc behaviour
- Switched patched 10 and 11 and performed full randomisation in patch 10 just before switching to default implementation, as suggested by Nic.
Changes in v4:
- Move arch_randomize_brk() simplification out of this series
- Add a change to core mm to enable using generic implementation
while providing arch specific one at the same time.
- Reworked radix get_unmapped_area to use generic implementation
- Rebase on top of Nic's series v6
Changes in v3:
- Fixed missing <linux/elf-randomize.h> in last patch
- Added a patch to move SZ_1T out of drivers/pci/controller/pci-xgene.c
Changes in v2:
- Moved patch 4 before patch 2
- Make generic arch_randomize_brk() __weak
- Added patch 9
Christophe Leroy (14):
mm: Allow arch specific arch_randomize_brk() with
CONFIG_ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
mm, hugetlbfs: Allow an arch to always use generic versions of
get_unmapped_area functions
mm: Add len and flags parameters to arch_get_mmap_end()
mm, hugetlbfs: Allow for "high" userspace addresses
sizes.h: Add SZ_1T macro
powerpc/mm: Move vma_mmu_pagesize()
powerpc/mm: Make slice specific to book3s/64
powerpc/mm: Remove CONFIG_PPC_MM_SLICES
powerpc/mm: Use generic_get_unmapped_area() and call it from
arch_get_unmapped_area()
powerpc/mm: Use generic_hugetlb_get_unmapped_area()
powerpc/mm: Move get_unmapped_area functions to slice.c
powerpc/mm: Enable full randomisation of memory mappings
powerpc/mm: Convert to default topdown mmap layout
powerpc: Simplify and move arch_randomize_brk()
arch/arm64/include/asm/processor.h | 4 +-
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/book3s/64/hugetlb.h | 4 -
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 1 +
arch/powerpc/include/asm/book3s/64/mmu.h | 6 -
arch/powerpc/include/asm/book3s/64/slice.h | 24 ++
arch/powerpc/include/asm/hugetlb.h | 2 +-
arch/powerpc/include/asm/paca.h | 7 -
arch/powerpc/include/asm/page.h | 1 -
arch/powerpc/include/asm/processor.h | 2 -
arch/powerpc/include/asm/slice.h | 46 ----
arch/powerpc/include/asm/task_size_64.h | 8 +
arch/powerpc/kernel/paca.c | 5 -
arch/powerpc/kernel/process.c | 41 ---
arch/powerpc/mm/Makefile | 3 +-
arch/powerpc/mm/book3s64/Makefile | 2 +-
arch/powerpc/mm/book3s64/hash_utils.c | 33 ++-
arch/powerpc/mm/book3s64/radix_hugetlbpage.c | 55 ----
arch/powerpc/mm/{ => book3s64}/slice.c | 71 ++++-
arch/powerpc/mm/hugetlbpage.c | 34 ---
arch/powerpc/mm/mmap.c | 256 ------------------
arch/powerpc/mm/nohash/mmu_context.c | 9 -
arch/powerpc/mm/nohash/tlb.c | 4 -
arch/powerpc/platforms/Kconfig.cputype | 4 -
drivers/pci/controller/pci-xgene.c | 1 -
fs/hugetlbfs/inode.c | 26 +-
include/linux/hugetlb.h | 5 +
include/linux/sched/mm.h | 17 ++
include/linux/sizes.h | 2 +
mm/mmap.c | 43 +--
mm/util.c | 2 +-
31 files changed, 185 insertions(+), 535 deletions(-)
delete mode 100644 arch/powerpc/include/asm/slice.h
rename arch/powerpc/mm/{ => book3s64}/slice.c (91%)
delete mode 100644 arch/powerpc/mm/mmap.c
--
2.33.1
^ permalink raw reply
* Re: [PATCH v7 1/7] powerpc/pmem: Restrict papr_scm to P8 and above.
From: Michal Suchánek @ 2022-01-21 8:40 UTC (permalink / raw)
To: Aneesh Kumar K.V
Cc: Jan Kara, linux-nvdimm, Jeff Moyer, oohall, dan.j.williams,
linuxppc-dev
In-Reply-To: <20200701072235.223558-2-aneesh.kumar@linux.ibm.com>
Hello,
On Wed, Jul 01, 2020 at 12:52:29PM +0530, Aneesh Kumar K.V wrote:
> The PAPR based virtualized persistent memory devices are only supported on
> POWER9 and above. In the followup patch, the kernel will switch the persistent
> memory cache flush functions to use a new `dcbf` variant instruction. The new
> instructions even though added in ISA 3.1 works even on P8 and P9 because these
> are implemented as a variant of existing `dcbf` and `hwsync` and on P8 and
> P9 behaves as such.
>
> Considering these devices are only supported on P8 and above, update the driver
> to prevent a P7-compat guest from using persistent memory devices.
>
> We don't update of_pmem driver with the same condition, because, on bare-metal,
> the firmware enables pmem support only on P9 and above. There the kernel depends
> on OPAL firmware to restrict exposing persistent memory related device tree
> entries on older hardware. of_pmem.ko is written without any arch dependency and
> we don't want to add ppc64 specific cpu feature check in of_pmem driver.
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> ---
> arch/powerpc/platforms/pseries/pmem.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/arch/powerpc/platforms/pseries/pmem.c b/arch/powerpc/platforms/pseries/pmem.c
> index f860a897a9e0..2347e1038f58 100644
> --- a/arch/powerpc/platforms/pseries/pmem.c
> +++ b/arch/powerpc/platforms/pseries/pmem.c
> @@ -147,6 +147,12 @@ const struct of_device_id drc_pmem_match[] = {
>
> static int pseries_pmem_init(void)
> {
> + /*
> + * Only supported on POWER8 and above.
> + */
> + if (!cpu_has_feature(CPU_FTR_ARCH_207S))
> + return 0;
> +
This looks superfluous.
The hypervisor is responsible for publishing the pmem in devicetree when
present, kernel is responsible for using it when supported by the
kernel.
Or is there a problem that the flush instruction is not available in P7
compat mode?
Even then volatile regions should still work.
Thanks
Michal
^ permalink raw reply
* [PATCH 3/3] powerpc/lib/sstep: use truncate_if_32bit()
From: Christophe Leroy @ 2022-01-21 8:06 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
In-Reply-To: <6c608fd4795e2d8ea1a0a449405a0087f76d8bb3.1642752375.git.christophe.leroy@csgroup.eu>
Use truncate_if_32bit() when possible instead of open coding.
truncate_if_32bit() returns an unsigned long, so don't use it when
a signed value is expected.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/lib/sstep.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 4aabe3854484..ca38d026fd88 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1065,8 +1065,7 @@ int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
int err;
unsigned long size = l1_dcache_bytes();
- if (!(regs->msr & MSR_64BIT))
- ea &= 0xffffffffUL;
+ ea = truncate_if_32bit(regs->msr, ea);
ea &= ~(size - 1);
if (!address_ok(regs, ea, size))
return -EFAULT;
@@ -1164,10 +1163,8 @@ static nokprobe_inline void add_with_carry(const struct pt_regs *regs,
op->type = COMPUTE + SETREG + SETXER;
op->reg = rd;
op->val = val;
- if (!(regs->msr & MSR_64BIT)) {
- val = (unsigned int) val;
- val1 = (unsigned int) val1;
- }
+ val = truncate_if_32bit(regs->msr, val);
+ val1 = truncate_if_32bit(regs->msr, val1);
op->xerval = regs->xer;
if (val < val1 || (carry_in && val == val1))
op->xerval |= XER_CA;
--
2.33.1
^ permalink raw reply related
* [PATCH 2/3] powerpc/lib/sstep: Remove unneeded #ifdef __powerpc64__
From: Christophe Leroy @ 2022-01-21 8:06 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
In-Reply-To: <6c608fd4795e2d8ea1a0a449405a0087f76d8bb3.1642752375.git.christophe.leroy@csgroup.eu>
MSR_64BIT is always defined, no need to hide code using MSR_64BIT
inside an #ifdef __powerpc64__
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/lib/sstep.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index b7316d697d80..4aabe3854484 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -75,10 +75,8 @@ extern int do_stqcx(unsigned long ea, unsigned long val0, unsigned long val1,
static nokprobe_inline unsigned long truncate_if_32bit(unsigned long msr,
unsigned long val)
{
-#ifdef __powerpc64__
if ((msr & MSR_64BIT) == 0)
val &= 0xffffffffUL;
-#endif
return val;
}
@@ -1067,10 +1065,8 @@ int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
int err;
unsigned long size = l1_dcache_bytes();
-#ifdef __powerpc64__
if (!(regs->msr & MSR_64BIT))
ea &= 0xffffffffUL;
-#endif
ea &= ~(size - 1);
if (!address_ok(regs, ea, size))
return -EFAULT;
@@ -1136,10 +1132,8 @@ static nokprobe_inline void set_cr0(const struct pt_regs *regs,
op->type |= SETCC;
op->ccval = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000);
-#ifdef __powerpc64__
if (!(regs->msr & MSR_64BIT))
val = (int) val;
-#endif
if (val < 0)
op->ccval |= 0x80000000;
else if (val > 0)
@@ -1170,12 +1164,10 @@ static nokprobe_inline void add_with_carry(const struct pt_regs *regs,
op->type = COMPUTE + SETREG + SETXER;
op->reg = rd;
op->val = val;
-#ifdef __powerpc64__
if (!(regs->msr & MSR_64BIT)) {
val = (unsigned int) val;
val1 = (unsigned int) val1;
}
-#endif
op->xerval = regs->xer;
if (val < val1 || (carry_in && val == val1))
op->xerval |= XER_CA;
--
2.33.1
^ permalink raw reply related
* [PATCH 1/3] powerpc/lib/sstep: Use l1_dcache_bytes() instead of opencoding
From: Christophe Leroy @ 2022-01-21 8:06 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
Don't opencode dcache size retrieval based on whether that's ppc32 or ppc64.
Use l1_dcache_bytes()
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/lib/sstep.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index a94b0cd0bdc5..b7316d697d80 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -1065,14 +1065,11 @@ static int __emulate_dcbz(unsigned long ea)
int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
{
int err;
- unsigned long size;
+ unsigned long size = l1_dcache_bytes();
#ifdef __powerpc64__
- size = ppc64_caches.l1d.block_size;
if (!(regs->msr & MSR_64BIT))
ea &= 0xffffffffUL;
-#else
- size = L1_CACHE_BYTES;
#endif
ea &= ~(size - 1);
if (!address_ok(regs, ea, size))
--
2.33.1
^ permalink raw reply related
* [PATCH] powerpc: Use the newly added is_tsk_32bit_task() macro
From: Christophe Leroy @ 2022-01-21 7:58 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman
Cc: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org
Two places deserve using the macro is_tsk_32bit_task() added by
commit 252745240ba0 ("powerpc/audit: Fix syscall_get_arch()")
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
---
arch/powerpc/kernel/ptrace/ptrace-view.c | 2 +-
arch/powerpc/perf/perf_regs.c | 8 +++-----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/kernel/ptrace/ptrace-view.c b/arch/powerpc/kernel/ptrace/ptrace-view.c
index b8be1d6668b5..f15bc78caf71 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-view.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-view.c
@@ -841,7 +841,7 @@ static const struct user_regset_view user_ppc_compat_view = {
const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
- if (IS_ENABLED(CONFIG_PPC64) && test_tsk_thread_flag(task, TIF_32BIT))
+ if (IS_ENABLED(CONFIG_COMPAT) && is_tsk_32bit_task(task))
return &user_ppc_compat_view;
return &user_ppc_native_view;
}
diff --git a/arch/powerpc/perf/perf_regs.c b/arch/powerpc/perf/perf_regs.c
index 51d31b65e423..350dccb0143c 100644
--- a/arch/powerpc/perf/perf_regs.c
+++ b/arch/powerpc/perf/perf_regs.c
@@ -134,12 +134,10 @@ int perf_reg_validate(u64 mask)
u64 perf_reg_abi(struct task_struct *task)
{
-#ifdef CONFIG_PPC64
- if (!test_tsk_thread_flag(task, TIF_32BIT))
- return PERF_SAMPLE_REGS_ABI_64;
+ if (is_tsk_32bit_task(task))
+ return PERF_SAMPLE_REGS_ABI_32;
else
-#endif
- return PERF_SAMPLE_REGS_ABI_32;
+ return PERF_SAMPLE_REGS_ABI_64;
}
void perf_get_regs_user(struct perf_regs *regs_user,
--
2.33.1
^ permalink raw reply related
* Re: [PATCH v7 3/7] powerpc/pmem: Add flush routines using new pmem store and sync instruction
From: Christophe Leroy @ 2022-01-21 7:36 UTC (permalink / raw)
To: Aneesh Kumar K.V, linuxppc-dev, mpe, linux-nvdimm, dan.j.williams
Cc: oohall, Jeff Moyer, msuchanek, Jan Kara
In-Reply-To: <20200701072235.223558-4-aneesh.kumar@linux.ibm.com>
Le 01/07/2020 à 09:22, Aneesh Kumar K.V a écrit :
> Start using dcbstps; phwsync; sequence for flushing persistent memory range.
> The new instructions are implemented as a variant of dcbf and hwsync and on
> P8 and P9 they will be executed as those instructions. We avoid using them on
> older hardware. This helps to avoid difficult to debug bugs.
>
Before this patch, the flush was done for all.
After this patch, IIUC the flush is done only on CPUs having feature
CPU_FTR_ARCH_207S.
What about other CPUs ?
I don't know much about PMEM, my concern is about the UACCESS_FLUSHCACHE
API introduced by commit 6c44741d75a2 ("powerpc/lib: Implement
UACCESS_FLUSHCACHE API")
After your patch, __copy_from_user_flushcache() and memcpy_flushcache()
are not doing cache flush anymore.
Is that intended ?
I'm trying to optimise some ALSA driver that does copy_from_user +
cache_flush for DMA, and I was wondering if using
__copy_from_user_flushcache() was an alternative.
Or is it __copy_from_user_inatomic_nocache() which has to be done for that ?
Thanks
Christophe
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> ---
> arch/powerpc/include/asm/cacheflush.h | 1 +
> arch/powerpc/lib/pmem.c | 50 ++++++++++++++++++++++++---
> 2 files changed, 47 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h
> index de600b915a3c..54764c6e922d 100644
> --- a/arch/powerpc/include/asm/cacheflush.h
> +++ b/arch/powerpc/include/asm/cacheflush.h
> @@ -6,6 +6,7 @@
>
> #include <linux/mm.h>
> #include <asm/cputable.h>
> +#include <asm/cpu_has_feature.h>
>
> #ifdef CONFIG_PPC_BOOK3S_64
> /*
> diff --git a/arch/powerpc/lib/pmem.c b/arch/powerpc/lib/pmem.c
> index 0666a8d29596..5a61aaeb6930 100644
> --- a/arch/powerpc/lib/pmem.c
> +++ b/arch/powerpc/lib/pmem.c
> @@ -9,20 +9,62 @@
>
> #include <asm/cacheflush.h>
>
> +static inline void __clean_pmem_range(unsigned long start, unsigned long stop)
> +{
> + unsigned long shift = l1_dcache_shift();
> + unsigned long bytes = l1_dcache_bytes();
> + void *addr = (void *)(start & ~(bytes - 1));
> + unsigned long size = stop - (unsigned long)addr + (bytes - 1);
> + unsigned long i;
> +
> + for (i = 0; i < size >> shift; i++, addr += bytes)
> + asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory");
> +
> +
> + asm volatile(PPC_PHWSYNC ::: "memory");
> +}
> +
> +static inline void __flush_pmem_range(unsigned long start, unsigned long stop)
> +{
> + unsigned long shift = l1_dcache_shift();
> + unsigned long bytes = l1_dcache_bytes();
> + void *addr = (void *)(start & ~(bytes - 1));
> + unsigned long size = stop - (unsigned long)addr + (bytes - 1);
> + unsigned long i;
> +
> + for (i = 0; i < size >> shift; i++, addr += bytes)
> + asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory");
> +
> +
> + asm volatile(PPC_PHWSYNC ::: "memory");
> +}
> +
> +static inline void clean_pmem_range(unsigned long start, unsigned long stop)
> +{
> + if (cpu_has_feature(CPU_FTR_ARCH_207S))
> + return __clean_pmem_range(start, stop);
> +}
> +
> +static inline void flush_pmem_range(unsigned long start, unsigned long stop)
> +{
> + if (cpu_has_feature(CPU_FTR_ARCH_207S))
> + return __flush_pmem_range(start, stop);
> +}
> +
> /*
> * CONFIG_ARCH_HAS_PMEM_API symbols
> */
> void arch_wb_cache_pmem(void *addr, size_t size)
> {
> unsigned long start = (unsigned long) addr;
> - flush_dcache_range(start, start + size);
> + clean_pmem_range(start, start + size);
> }
> EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
>
> void arch_invalidate_pmem(void *addr, size_t size)
> {
> unsigned long start = (unsigned long) addr;
> - flush_dcache_range(start, start + size);
> + flush_pmem_range(start, start + size);
> }
> EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
>
> @@ -35,7 +77,7 @@ long __copy_from_user_flushcache(void *dest, const void __user *src,
> unsigned long copied, start = (unsigned long) dest;
>
> copied = __copy_from_user(dest, src, size);
> - flush_dcache_range(start, start + size);
> + clean_pmem_range(start, start + size);
>
> return copied;
> }
> @@ -45,7 +87,7 @@ void *memcpy_flushcache(void *dest, const void *src, size_t size)
> unsigned long start = (unsigned long) dest;
>
> memcpy(dest, src, size);
> - flush_dcache_range(start, start + size);
> + clean_pmem_range(start, start + size);
>
> return dest;
> }
^ permalink raw reply
* Re: [PATCH V3 13/17] riscv: compat: signal: Add rt_frame implementation
From: Guo Ren @ 2022-01-21 7:12 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-s390, Guo Ren, gregkh, Drew Fustini, Anup Patel,
Wang Junqiang, the arch/x86 maintainers,
Linux Kernel Mailing List, linux-csky, inux-parisc,
Christoph Hellwig, Palmer Dabbelt, liush, sparclinux, linux-riscv,
open list:BROADCOM NVRAM DRIVER, linuxppc-dev, Christoph Hellwig,
Linux ARM, Wei Fu
In-Reply-To: <CAK8P3a03-3QTC-vxmnbouK7wBd8iunPGZpX0-Jf6ntS1DY0E=w@mail.gmail.com>
On Thu, Jan 20, 2022 at 6:31 PM Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Thu, Jan 20, 2022 at 8:39 AM <guoren@kernel.org> wrote:
> >
> > From: Guo Ren <guoren@linux.alibaba.com>
> >
> > Implement compat_setup_rt_frame for sigcontext save & restore. The
> > main process is the same with signal, but the rv32 pt_regs' size
> > is different from rv64's, so we needs convert them.
> >
> > Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
> > Signed-off-by: Guo Ren <guoren@kernel.org>
> > Cc: Arnd Bergmann <arnd@arndb.de>
>
> I hope someone else can properly review this part, it's not my area
> but it looks complex enough that it could bring subtle bugs.
Here are ltp signal test results:
sigaction01 PASS 0
sigaction02 PASS 0
sigaltstack01 PASS 0
sigaltstack02 PASS 0
sighold02 PASS 0
signal01 PASS 0
signal02 PASS 0
signal03 PASS 0
signal04 PASS 0
signal05 PASS 0
signal06 CONF 32
signalfd01 PASS 0
signalfd4_01 PASS 0
signalfd4_02 PASS 0
sigpending02 PASS 0
sigprocmask01 PASS 0
sigrelse01 PASS 0
sigsuspend01 PASS 0
sigtimedwait01 PASS 0
sigwait01 PASS 0
sigwaitinfo01 CONF 32
>
> Arnd
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
^ permalink raw reply
* Re: [PATCH V3 06/17] riscv: compat: Add basic compat date type implementation
From: Guo Ren @ 2022-01-21 6:59 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-s390, Guo Ren, gregkh, Drew Fustini, Anup Patel,
Wang Junqiang, the arch/x86 maintainers,
Linux Kernel Mailing List, linux-csky, inux-parisc,
Christoph Hellwig, Palmer Dabbelt, liush, sparclinux, linux-riscv,
open list:BROADCOM NVRAM DRIVER, linuxppc-dev, Christoph Hellwig,
Linux ARM, Wei Fu
In-Reply-To: <CAK8P3a00uYPBBphpipBoqCnGFwr_C9vDzS1p1iLN==YTVOARug@mail.gmail.com>
On Thu, Jan 20, 2022 at 5:35 PM Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Thu, Jan 20, 2022 at 8:38 AM <guoren@kernel.org> wrote:
>
> > @@ -0,0 +1,136 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +#ifndef __ASM_COMPAT_H
> > +#define __ASM_COMPAT_H
> > +
> > +#define compat_mode_t compat_mode_t
> > +typedef u16 compat_mode_t;
>
> I think this one is wrong, as rv32 should get the native definition from
>
> include/uapi/asm-generic/posix_types.h:typedef unsigned int __kernel_mode_t;
>
> I think it works if you just remove those two lines. The rest looks good to me.
Yes, you are right. compat_mode_t should be unsigned int.
>
> Arnd
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
^ permalink raw reply
* Re: [PATCH V3 17/17] KVM: compat: riscv: Prevent KVM_COMPAT from being selected
From: Guo Ren @ 2022-01-21 6:35 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-s390, Guo Ren, gregkh, Drew Fustini, Anup Patel,
Wang Junqiang, the arch/x86 maintainers,
Linux Kernel Mailing List, linux-csky, inux-parisc,
Christoph Hellwig, Palmer Dabbelt, liush, sparclinux, linux-riscv,
open list:BROADCOM NVRAM DRIVER, linuxppc-dev, Christoph Hellwig,
Linux ARM, Wei Fu
In-Reply-To: <CAK8P3a1_qwRpfHRyF75WEqfxGxgVnfB15vNS-egQctx7R5-DvA@mail.gmail.com>
On Thu, Jan 20, 2022 at 6:32 PM Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Thu, Jan 20, 2022 at 8:39 AM <guoren@kernel.org> wrote:
> >
> > From: Guo Ren <guoren@linux.alibaba.com>
> >
> > Current riscv doesn't support the 32bit KVM/arm API. Let's make it
> > clear by not selecting KVM_COMPAT.
> >
> > Signed-off-by: Guo Ren <guoren@linux.alibaba.com>
> > ---
> > virt/kvm/Kconfig | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
> > index f4834c20e4a6..a8c5c9f06b3c 100644
> > --- a/virt/kvm/Kconfig
> > +++ b/virt/kvm/Kconfig
> > @@ -53,7 +53,7 @@ config KVM_GENERIC_DIRTYLOG_READ_PROTECT
> >
> > config KVM_COMPAT
> > def_bool y
> > - depends on KVM && COMPAT && !(S390 || ARM64)
> > + depends on KVM && COMPAT && !(S390 || ARM64 || RISCV)
>
> Maybe this should be flipped around into a positive list now?
I think it's another patch to do that. Not in this series.
> The remaining architectures would be mips, powerpc and x86, but it's unclear
> if this actually meant to work on all of them, or any potential ones
> added in the
Yes, it's unclear and arch maintainers need to confirm that.
> future.
>
> Arnd
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
^ permalink raw reply
* Re: [PATCH V3 08/17] riscv: compat: syscall: Add compat_sys_call_table implementation
From: Guo Ren @ 2022-01-21 6:25 UTC (permalink / raw)
To: Arnd Bergmann
Cc: linux-s390, Guo Ren, gregkh, Drew Fustini, Anup Patel,
Wang Junqiang, the arch/x86 maintainers,
Linux Kernel Mailing List, linux-csky, inux-parisc,
Christoph Hellwig, Palmer Dabbelt, liush, sparclinux, linux-riscv,
open list:BROADCOM NVRAM DRIVER, linuxppc-dev, Christoph Hellwig,
Linux ARM, Wei Fu
In-Reply-To: <CAK8P3a0LxB3we9wHOa4OPmNow6wz5NP49zeYhh7QXNv-MiR8UA@mail.gmail.com>
On Thu, Jan 20, 2022 at 10:43 PM Arnd Bergmann <arnd@arndb.de> wrote:
>
> On Thu, Jan 20, 2022 at 8:39 AM <guoren@kernel.org> wrote:
> >
> > /* The array of function pointers for syscalls. */
> > extern void * const sys_call_table[];
> > +#ifdef CONFIG_COMPAT
> > +extern void * const compat_sys_call_table[];
> > +#endif
>
> No need for the #ifdef, the normal convention is to just define the
> extern declaration unconditionally for symbols that may or may not be defined.
Okay
>
> > +COMPAT_SYSCALL_DEFINE3(truncate64, const char __user *, pathname,
> > + arg_u32p(length))
> > +{
> > + return ksys_truncate(pathname, arg_u64(length));
> > +}
>
> Are you sure these are the right calling conventions? According to [1],
> I think the 64-bit argument should be in an aligned pair of registers,
> which means you need an extra pad argument as in the arm64 version
> of these functions. Same for ftruncate64, pread64, pwrite64, and
> readahead.
[1] has abandoned.
See:
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc
Ltp test results:
ftruncate01 PASS 0
ftruncate01_64 PASS 0
ftruncate03 PASS 0
ftruncate03_64 PASS 0
ftruncate04 CONF 32
ftruncate04_64 CONF 32
truncate02 PASS 0
truncate02_64 PASS 0
truncate03 PASS 0
truncate03_64 PASS 0
pread01 PASS 0
pread01_64 PASS 0
pread02 PASS 0
pread02_64 PASS 0
pread03 PASS 0
pread03_64 PASS 0
pwrite01_64 PASS 0
pwrite02_64 PASS 0
pwrite03_64 PASS 0
pwrite04_64 PASS 0
readahead01 PASS 0
readahead02 CONF 32
>
> > +COMPAT_SYSCALL_DEFINE3(ftruncate64, unsigned int, fd, arg_u32p(length))
> > +{
> > + return ksys_ftruncate(fd, arg_u64(length));
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE6(fallocate, int, fd, int, mode,
> > + arg_u32p(offset), arg_u32p(len))
> > +{
> > + return ksys_fallocate(fd, mode, arg_u64(offset), arg_u64(len));
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE5(pread64, unsigned int, fd, char __user *, buf,
> > + size_t, count, arg_u32p(pos))
> > +{
> > + return ksys_pread64(fd, buf, count, arg_u64(pos));
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE5(pwrite64, unsigned int, fd,
> > + const char __user *, buf, size_t, count, arg_u32p(pos))
> > +{
> > + return ksys_pwrite64(fd, buf, count, arg_u64(pos));
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE6(sync_file_range, int, fd, arg_u32p(offset),
> > + arg_u32p(nbytes), unsigned int, flags)
> > +{
> > + return ksys_sync_file_range(fd, arg_u64(offset), arg_u64(nbytes),
> > + flags);
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE4(readahead, int, fd, arg_u32p(offset),
> > + size_t, count)
> > +{
> > + return ksys_readahead(fd, arg_u64(offset), count);
> > +}
> > +
> > +COMPAT_SYSCALL_DEFINE6(fadvise64_64, int, fd, int, advice, arg_u32p(offset),
> > + arg_u32p(len))
> > +{
> > + return ksys_fadvise64_64(fd, arg_u64(offset), arg_u64(len), advice);
> > +}
>
> I still feel like these should be the common implementations next to the
> native handlers inside of an #ifdef CONFIG_COMPAT.
>
> The names clash with the custom versions defined for powerpc and sparc,
> but the duplicates look compatible if you can account for the padded
> argument and the lo/hi order of the pairs, so could just be removed here
> (all other architectures use custom function names instead).
I would try it later.
>
> Arnd
>
> [1] https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
--
Best Regards
Guo Ren
ML: https://lore.kernel.org/linux-csky/
^ permalink raw reply
* [PATCH -v2] powerpc/process, kasan: Silence KASAN warnings in __get_wchan()
From: He Ying @ 2022-01-21 1:44 UTC (permalink / raw)
To: catalin.marinas, mpe, benh, paulus, npiggin, christophe.leroy,
sxwjean, peterz, keescook
Cc: chenjingwen6, huwanming, linuxppc-dev, linux-kernel, heying24
In-Reply-To: <20220119015025.136902-1-heying24@huawei.com>
The following KASAN warning was reported in our kernel.
BUG: KASAN: stack-out-of-bounds in get_wchan+0x188/0x250
Read of size 4 at addr d216f958 by task ps/14437
CPU: 3 PID: 14437 Comm: ps Tainted: G O 5.10.0 #1
Call Trace:
[daa63858] [c0654348] dump_stack+0x9c/0xe4 (unreliable)
[daa63888] [c035cf0c] print_address_description.constprop.3+0x8c/0x570
[daa63908] [c035d6bc] kasan_report+0x1ac/0x218
[daa63948] [c00496e8] get_wchan+0x188/0x250
[daa63978] [c0461ec8] do_task_stat+0xce8/0xe60
[daa63b98] [c0455ac8] proc_single_show+0x98/0x170
[daa63bc8] [c03cab8c] seq_read_iter+0x1ec/0x900
[daa63c38] [c03cb47c] seq_read+0x1dc/0x290
[daa63d68] [c037fc94] vfs_read+0x164/0x510
[daa63ea8] [c03808e4] ksys_read+0x144/0x1d0
[daa63f38] [c005b1dc] ret_from_syscall+0x0/0x38
--- interrupt: c00 at 0x8fa8f4
LR = 0x8fa8cc
The buggy address belongs to the page:
page:98ebcdd2 refcount:0 mapcount:0 mapping:00000000 index:0x2 pfn:0x1216f
flags: 0x0()
raw: 00000000 00000000 01010122 00000000 00000002 00000000 ffffffff 00000000
raw: 00000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
d216f800: 00 00 00 00 00 f1 f1 f1 f1 00 00 00 00 00 00 00
d216f880: f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>d216f900: 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00
^
d216f980: f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00
d216fa00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
After looking into this issue, I find the buggy address belongs
to the task stack region. It seems KASAN has something wrong.
I look into the code of __get_wchan in x86 architecture and
find the same issue has been resolved by the commit
f7d27c35ddff ("x86/mm, kasan: Silence KASAN warnings in get_wchan()").
The solution could be applied to powerpc architecture too.
As Andrey Ryabinin said, get_wchan() is racy by design, it may
access volatile stack of running task, thus it may access
redzone in a stack frame and cause KASAN to warn about this.
Use READ_ONCE_NOCHECK() to silence these warnings.
Reported-by: Wanming Hu <huwanming@huaweil.com>
Signed-off-by: He Ying <heying24@huawei.com>
Signed-off-by: Chen Jingwen <chenjingwen6@huawei.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
---
Changelog:
v2:
* Add missing Reported-by and SoB tags
---
arch/powerpc/kernel/process.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 984813a4d5dc..a75d20f23dac 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -2160,12 +2160,12 @@ static unsigned long ___get_wchan(struct task_struct *p)
return 0;
do {
- sp = *(unsigned long *)sp;
+ sp = READ_ONCE_NOCHECK(*(unsigned long *)sp);
if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD) ||
task_is_running(p))
return 0;
if (count > 0) {
- ip = ((unsigned long *)sp)[STACK_FRAME_LR_SAVE];
+ ip = READ_ONCE_NOCHECK(((unsigned long *)sp)[STACK_FRAME_LR_SAVE]);
if (!in_sched_functions(ip))
return ip;
}
--
2.17.1
^ permalink raw reply related
* [PATCH 2/2] KVM: selftests: Add support for ppc64le
From: Fabiano Rosas @ 2022-01-20 17:01 UTC (permalink / raw)
To: kvm; +Cc: aik, linuxppc-dev, npiggin, paulus, linux-kselftest, pbonzini,
shuah
In-Reply-To: <20220120170109.948681-1-farosas@linux.ibm.com>
This adds the infrastructure for writing tests for the powerpc
platform (Only Radix MMU for now).
This patch also enables two tests:
- a dummy sample test that creates a guest with one vcpu, issues
hypercalls and reads/writes test values from memory.
- the kvm_page_table test, although at this point I'm not using it to
test KVM, but mostly as a way to stress test this code.
$ make -C tools/testing/selftests TARGETS=kvm
$ make -C tools/testing/selftests TARGETS=kvm run_tests
Signed-off-by: Fabiano Rosas <farosas@linux.ibm.com>
---
MAINTAINERS | 3 +
tools/testing/selftests/kvm/.gitignore | 1 +
tools/testing/selftests/kvm/Makefile | 14 +-
.../selftests/kvm/include/kvm_util_base.h | 7 +
.../selftests/kvm/include/ppc64le/processor.h | 43 +++
tools/testing/selftests/kvm/lib/kvm_util.c | 5 +
.../testing/selftests/kvm/lib/powerpc/hcall.S | 6 +
.../selftests/kvm/lib/powerpc/processor.c | 343 ++++++++++++++++++
.../testing/selftests/kvm/lib/powerpc/ucall.c | 67 ++++
.../selftests/kvm/powerpc/sample_test.c | 144 ++++++++
10 files changed, 630 insertions(+), 3 deletions(-)
create mode 100644 tools/testing/selftests/kvm/include/ppc64le/processor.h
create mode 100644 tools/testing/selftests/kvm/lib/powerpc/hcall.S
create mode 100644 tools/testing/selftests/kvm/lib/powerpc/processor.c
create mode 100644 tools/testing/selftests/kvm/lib/powerpc/ucall.c
create mode 100644 tools/testing/selftests/kvm/powerpc/sample_test.c
diff --git a/MAINTAINERS b/MAINTAINERS
index a76e7558b151..15c89d33d584 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10537,6 +10537,9 @@ F: arch/powerpc/include/asm/kvm*
F: arch/powerpc/include/uapi/asm/kvm*
F: arch/powerpc/kernel/kvm*
F: arch/powerpc/kvm/
+F: tools/testing/selftests/kvm/include/ppc64le/
+F: tools/testing/selftests/kvm/lib/powerpc/
+F: tools/testing/selftests/kvm/powerpc/
KERNEL VIRTUAL MACHINE FOR RISC-V (KVM/riscv)
M: Anup Patel <anup@brainfault.org>
diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index 8c129961accf..45ab993e2845 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -46,6 +46,7 @@
/x86_64/xen_vmcall_test
/x86_64/xss_msr_test
/x86_64/vmx_pmu_msrs_test
+/powerpc/sample_test
/access_tracking_perf_test
/demand_paging_test
/dirty_log_test
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 556da71c33b8..5ae27109e9b9 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -17,9 +17,9 @@ KSFT_KHDR_INSTALL := 1
# LINUX_TOOL_ARCH_INCLUDE is set using ARCH variable.
#
# x86_64 targets are named to include x86_64 as a suffix and directories
-# for includes are in x86_64 sub-directory. s390x and aarch64 follow the
-# same convention. "uname -m" doesn't result in the correct mapping for
-# s390x and aarch64.
+# for includes are in x86_64 sub-directory. s390x, aarch64 and ppc64le
+# follow the same convention. "uname -m" doesn't result in the correct
+# mapping for s390x, aarch64 and ppc64le.
#
# No change necessary for x86_64
UNAME_M := $(shell uname -m)
@@ -36,12 +36,17 @@ endif
ifeq ($(ARCH),riscv)
UNAME_M := riscv
endif
+# Set UNAME_M for ppc64le compile/install to work
+ifeq ($(ARCH),powerpc)
+ UNAME_M := ppc64le
+endif
LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/rbtree.c lib/sparsebit.c lib/test_util.c lib/guest_modes.c lib/perf_test_util.c
LIBKVM_x86_64 = lib/x86_64/apic.c lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S
LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c lib/aarch64/handlers.S lib/aarch64/spinlock.c lib/aarch64/gic.c lib/aarch64/gic_v3.c lib/aarch64/vgic.c
LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318_test_handler.c
LIBKVM_riscv = lib/riscv/processor.c lib/riscv/ucall.c
+LIBKVM_ppc64le = lib/powerpc/processor.c lib/powerpc/ucall.c lib/powerpc/hcall.S
TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test
TEST_GEN_PROGS_x86_64 += x86_64/get_msr_index_features
@@ -133,6 +138,9 @@ TEST_GEN_PROGS_riscv += kvm_page_table_test
TEST_GEN_PROGS_riscv += set_memory_region_test
TEST_GEN_PROGS_riscv += kvm_binary_stats_test
+TEST_GEN_PROGS_ppc64le += powerpc/sample_test
+TEST_GEN_PROGS_ppc64le += kvm_page_table_test
+
TEST_GEN_PROGS += $(TEST_GEN_PROGS_$(UNAME_M))
LIBKVM += $(LIBKVM_$(UNAME_M))
diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
index 66775de26952..a930d663fe67 100644
--- a/tools/testing/selftests/kvm/include/kvm_util_base.h
+++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
@@ -54,6 +54,7 @@ enum vm_guest_mode {
VM_MODE_P36V48_16K,
VM_MODE_P36V48_64K,
VM_MODE_P36V47_16K,
+ VM_MODE_P51V52_64K,
NUM_VM_MODES,
};
@@ -87,6 +88,12 @@ extern enum vm_guest_mode vm_mode_default;
#define MIN_PAGE_SHIFT 12U
#define ptes_per_page(page_size) ((page_size) / 8)
+#elif defined(__powerpc__)
+
+#define VM_MODE_DEFAULT VM_MODE_P51V52_64K
+#define MIN_PAGE_SHIFT 16U
+#define ptes_per_page(page_size) ((page_size) / 8)
+
#endif
#define MIN_PAGE_SIZE (1U << MIN_PAGE_SHIFT)
diff --git a/tools/testing/selftests/kvm/include/ppc64le/processor.h b/tools/testing/selftests/kvm/include/ppc64le/processor.h
new file mode 100644
index 000000000000..fbc1332b2b80
--- /dev/null
+++ b/tools/testing/selftests/kvm/include/ppc64le/processor.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * powerpc processor specific defines
+ */
+#ifndef SELFTEST_KVM_PROCESSOR_H
+#define SELFTEST_KVM_PROCESSOR_H
+
+#define PPC_BIT(x) (1ULL << (63 - x))
+
+#define MSR_SF PPC_BIT(0)
+#define MSR_IR PPC_BIT(58)
+#define MSR_DR PPC_BIT(59)
+#define MSR_LE PPC_BIT(63)
+
+#define LPCR_UPRT PPC_BIT(41)
+#define LPCR_EVIRT PPC_BIT(42)
+#define LPCR_HR PPC_BIT(43)
+#define LPCR_GTSE PPC_BIT(53)
+
+#define PATB_GR PPC_BIT(0)
+
+#define PTE_VALID PPC_BIT(0)
+#define PTE_LEAF PPC_BIT(1)
+#define PTE_R PPC_BIT(55)
+#define PTE_C PPC_BIT(56)
+#define PTE_RC (PTE_R | PTE_C)
+#define PTE_READ 0x4
+#define PTE_WRITE 0x2
+#define PTE_EXEC 0x1
+#define PTE_RWX (PTE_READ|PTE_WRITE|PTE_EXEC)
+
+extern uint64_t hcall(uint64_t nr, ...);
+
+static inline uint32_t mfpvr(void)
+{
+ uint32_t pvr;
+
+ asm ("mfpvr %0"
+ : "=r"(pvr));
+ return pvr;
+}
+
+#endif
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index c22a17aac6b0..cc5247c2cfeb 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -205,6 +205,7 @@ const char *vm_guest_mode_string(uint32_t i)
[VM_MODE_P36V48_16K] = "PA-bits:36, VA-bits:48, 16K pages",
[VM_MODE_P36V48_64K] = "PA-bits:36, VA-bits:48, 64K pages",
[VM_MODE_P36V47_16K] = "PA-bits:36, VA-bits:47, 16K pages",
+ [VM_MODE_P51V52_64K] = "PA-bits:51, VA-bits:52, 64K pages",
};
_Static_assert(sizeof(strings)/sizeof(char *) == NUM_VM_MODES,
"Missing new mode strings?");
@@ -230,6 +231,7 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
[VM_MODE_P36V48_16K] = { 36, 48, 0x4000, 14 },
[VM_MODE_P36V48_64K] = { 36, 48, 0x10000, 16 },
[VM_MODE_P36V47_16K] = { 36, 47, 0x4000, 14 },
+ [VM_MODE_P51V52_64K] = { 51, 52, 0x10000, 16 },
};
_Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
"Missing new mode params?");
@@ -331,6 +333,9 @@ struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
case VM_MODE_P44V64_4K:
vm->pgtable_levels = 5;
break;
+ case VM_MODE_P51V52_64K:
+ vm->pgtable_levels = 4;
+ break;
default:
TEST_FAIL("Unknown guest mode, mode: 0x%x", mode);
}
diff --git a/tools/testing/selftests/kvm/lib/powerpc/hcall.S b/tools/testing/selftests/kvm/lib/powerpc/hcall.S
new file mode 100644
index 000000000000..a78b88f3b207
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/powerpc/hcall.S
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+.globl hcall;
+
+hcall:
+ sc 1
+ blr
diff --git a/tools/testing/selftests/kvm/lib/powerpc/processor.c b/tools/testing/selftests/kvm/lib/powerpc/processor.c
new file mode 100644
index 000000000000..2ffd5423a968
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/powerpc/processor.c
@@ -0,0 +1,343 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KVM selftest powerpc library code
+ *
+ * Copyright (C) 2021, IBM Corp.
+ */
+
+#define _GNU_SOURCE
+//#define DEBUG
+
+#include "kvm_util.h"
+#include "../kvm_util_internal.h"
+#include "processor.h"
+
+/*
+ * 2^(12+PRTS) = Process table size
+ *
+ * But the hardware doesn't seem to care, so 0 for now.
+ */
+#define PRTS 0
+#define RTS ((0x5UL << 5) | (0x2UL << 61)) /* 2^(RTS+31) = 2^52 */
+#define RPDS 0xd
+#define RPDB_MASK 0x0fffffffffffff00UL
+#define RPN_MASK 0x01fffffffffff000UL
+
+#define MIN_FRAME_SZ 32
+
+static const int radix_64k_index_sizes[4] = { 5, 9, 9, 13 };
+
+static inline uint64_t mk_pte(uint64_t pte_val)
+{
+ return cpu_to_be64(PTE_VALID | pte_val);
+}
+
+static inline uint64_t get_pte(uint64_t pte)
+{
+ return be64_to_cpu(pte);
+}
+
+static inline uint64_t pte_rpn(uint64_t entry)
+{
+ return get_pte(entry) & RPN_MASK;
+}
+
+static inline uint64_t next_pde(uint64_t entry)
+{
+ return get_pte(entry) & RPDB_MASK;
+}
+
+static inline uint64_t ptrs_per_pgd(int level)
+{
+ return 1UL << radix_64k_index_sizes[level];
+}
+
+static inline uint64_t level_size(int level)
+{
+ return sizeof(vm_paddr_t) << (radix_64k_index_sizes[level] + 3);
+}
+
+static vm_paddr_t alloc_pgd(struct kvm_vm *vm, int level)
+{
+ static vm_paddr_t base;
+ vm_paddr_t addr;
+ uint64_t size = level_size(level);
+
+ if (!base || (base + size) >> vm->page_shift != base >> vm->page_shift)
+ addr = vm_alloc_page_table(vm);
+ else
+ addr = base;
+ base = addr + size;
+
+ return addr;
+}
+
+static vm_paddr_t pgtable_walk(struct kvm_vm *vm, vm_vaddr_t gva, uint64_t gpa,
+ bool alloc)
+{
+ uint64_t index_bits, shift, base, index;
+ uint64_t *ptep, ptep_gpa;
+ int level;
+
+ if (!vm->pgd_created)
+ goto unmapped_gva;
+
+ pr_debug("%s %#lx ", (alloc ? "mapping" : "lookup "), gva);
+
+ base = vm->pgd;
+ shift = vm->va_bits;
+
+ for (level = 3; level >= 0; --level) {
+
+ index_bits = radix_64k_index_sizes[level];
+ shift -= index_bits;
+
+ index = (gva >> shift) & ((1UL << index_bits) - 1);
+ ptep_gpa = base + index * sizeof(*ptep);
+ ptep = addr_gpa2hva(vm, ptep_gpa);
+
+ if (!*ptep) {
+ if (!alloc)
+ goto unmapped_gva;
+ if (level)
+ *ptep = mk_pte(alloc_pgd(vm, level - 1) |
+ radix_64k_index_sizes[level - 1]);
+ }
+
+ if (get_pte(*ptep) & PTE_LEAF)
+ break;
+
+ base = next_pde(*ptep);
+ }
+
+ if (alloc)
+ *ptep = mk_pte(PTE_LEAF | gpa | PTE_RC | PTE_RWX);
+ else
+ gpa = pte_rpn(*ptep);
+
+ pr_debug("-> %#lx pte: %#lx (@%#lx)\n", gpa, get_pte(*ptep), ptep_gpa);
+
+ return gpa | (gva & (vm->page_size - 1));
+
+unmapped_gva:
+ TEST_FAIL("No mapping for vm virtual address, gva: %#lx", gva);
+ exit(1);
+}
+
+void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
+{
+ TEST_ASSERT((vaddr % vm->page_size) == 0,
+ "Virtual address not on page boundary,\n"
+ " vaddr: 0x%lx vm->page_size: 0x%x", vaddr, vm->page_size);
+
+ TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
+ (vaddr >> vm->page_shift)),
+ "Invalid virtual address, vaddr: 0x%lx", vaddr);
+
+ TEST_ASSERT((paddr % vm->page_size) == 0,
+ "Physical address not on page boundary,\n"
+ " paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
+
+ TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
+ "Physical address beyond maximum supported,\n"
+ " paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
+ paddr, vm->max_gfn, vm->page_size);
+
+ TEST_ASSERT(vm->pgd_created, "Page table not created\n");
+
+ pgtable_walk(vm, vaddr, paddr, true);
+}
+
+vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
+{
+ return pgtable_walk(vm, gva, 0, false);
+}
+
+void virt_pgd_alloc(struct kvm_vm *vm)
+{
+ struct kvm_ppc_mmuv3_cfg cfg = { 0 };
+ vm_paddr_t proc_tb;
+ uint64_t *proc_tb_hva;
+
+ if (!kvm_check_cap(KVM_CAP_PPC_MMU_RADIX)) {
+ print_skip("Tests only support Radix MMU");
+ exit(KSFT_SKIP);
+ }
+
+ if (!kvm_check_cap(KVM_CAP_PPC_PAPR)) {
+ print_skip("Tests only support Book3s");
+ exit(KSFT_SKIP);
+ }
+
+ if (vm->pgd_created)
+ return;
+
+ /*
+ * Allocate the process table in guest memory and set the
+ * first doubleword of the pid 0 entry.
+ */
+ proc_tb = vm_alloc_page_table(vm);
+ vm->pgd = vm_alloc_page_table(vm);
+
+ proc_tb_hva = addr_gpa2hva(vm, proc_tb);
+ *proc_tb_hva = cpu_to_be64(RTS | vm->pgd | RPDS);
+
+ pr_debug("process table gpa: %#lx\n", proc_tb);
+ pr_debug("process table hva: %p\n", proc_tb_hva);
+ pr_debug("process table entry 0 dw0: %#lx\n", *proc_tb_hva);
+
+ /* Register the process table with the HV */
+ cfg.process_table = PATB_GR | proc_tb | PRTS;
+ cfg.flags = KVM_PPC_MMUV3_RADIX | KVM_PPC_MMUV3_GTSE;
+
+ pr_debug("MMU config proc table: %#llx\n", cfg.process_table);
+
+ vm_ioctl(vm, KVM_PPC_CONFIGURE_V3_MMU, &cfg);
+ vm->pgd_created = true;
+}
+
+void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code)
+{
+ struct kvm_enable_cap cap = { 0 };
+ struct kvm_regs regs;
+ struct kvm_sregs sregs;
+ vm_vaddr_t stack_vaddr;
+ size_t stack_sz;
+
+ vm_vcpu_add(vm, vcpuid);
+
+ cap.cap = KVM_CAP_PPC_PAPR;
+ vcpu_enable_cap(vm, vcpuid, &cap);
+
+ stack_sz = DEFAULT_STACK_PGS * vm->page_size;
+ stack_vaddr = vm_vaddr_alloc(vm, stack_sz,
+ DEFAULT_GUEST_STACK_VADDR_MIN);
+
+ regs.msr = MSR_SF | MSR_LE;
+ regs.msr |= MSR_IR | MSR_DR;
+ regs.pc = (unsigned long) guest_code;
+ regs.pid = 0;
+ regs.gpr[1] = stack_vaddr + stack_sz - MIN_FRAME_SZ;
+
+ pr_debug("stack - low: %#lx high: %#lx size: %#lx SP: %#llx\n",
+ stack_vaddr, stack_vaddr + stack_sz, stack_sz, regs.gpr[1]);
+
+ vcpu_regs_set(vm, vcpuid, ®s);
+
+ sregs.pvr = mfpvr();
+ vcpu_sregs_set(vm, vcpuid, &sregs);
+
+ if (kvm_check_cap(KVM_CAP_ONE_REG)) {
+ uint64_t lpcr = LPCR_UPRT | LPCR_HR | LPCR_GTSE;
+ struct kvm_one_reg reg = {
+ .id = KVM_REG_PPC_LPCR_64,
+ .addr = (uintptr_t) &lpcr,
+ };
+
+ vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, ®);
+ }
+}
+
+void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
+{
+ va_list ap;
+ struct kvm_regs regs;
+ int i;
+
+ TEST_ASSERT(num >= 1 && num <= 8, "Unsupported number of args,\n"
+ " num: %u\n", num);
+
+ va_start(ap, num);
+ vcpu_regs_get(vm, vcpuid, ®s);
+
+ for (i = 0; i < num; i++)
+ regs.gpr[i + 3] = va_arg(ap, uint64_t);
+
+ vcpu_regs_set(vm, vcpuid, ®s);
+ va_end(ap);
+}
+
+static void pte_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent,
+ uint64_t addr, int level)
+{
+ static const char * const type[] = { "pte", "pmd", "pud", "pgd" };
+ uint64_t pde, *hva;
+
+ if (level < 0)
+ return;
+
+ fprintf(stream, "%*s (%#lx):\n", indent, type[level], addr);
+
+ for (pde = addr; pde < addr + (ptrs_per_pgd(level) * sizeof(vm_paddr_t));
+ pde += sizeof(vm_paddr_t)) {
+
+ hva = addr_gpa2hva(vm, pde);
+ if (!*hva)
+ continue;
+ fprintf(stream, "%*s %#lx: %#lx\n", indent + 1, "", pde,
+ get_pte(*hva));
+ pte_dump(stream, vm, indent + 2, next_pde(*hva), level - 1);
+ }
+}
+
+void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
+{
+ if (!vm->pgd_created)
+ return;
+
+ pte_dump(stream, vm, indent, vm->pgd, 3);
+}
+
+void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid, uint8_t indent)
+{
+ struct kvm_regs regs;
+
+ fprintf(stream, "%*scpuid: %u\n", indent, "", vcpuid);
+
+ vcpu_regs_get(vm, vcpuid, ®s);
+ fprintf(stream, "%*sregs:\n", indent + 2, "");
+
+ fprintf(stream, "%*spc: %#llx\n", indent + 4, "", regs.pc);
+ fprintf(stream, "%*smsr: %#llx\n", indent + 4, "", regs.msr);
+ fprintf(stream, "%*ssrr0: %#llx\n", indent + 4, "", regs.srr0);
+ fprintf(stream, "%*ssrr1: %#llx\n", indent + 4, "", regs.srr1);
+
+ fprintf(stream, "\n%*sr1: %#llx\n", indent + 4, "", regs.gpr[1]);
+ fprintf(stream, "%*sr2: %#llx\n", indent + 4, "", regs.gpr[2]);
+ fprintf(stream, "%*sr3: %#llx\n", indent + 4, "", regs.gpr[3]);
+ fprintf(stream, "%*sr4: %#llx\n", indent + 4, "", regs.gpr[4]);
+
+ if (kvm_check_cap(KVM_CAP_ONE_REG)) {
+ uint64_t lpcr;
+ struct kvm_one_reg reg = {
+ .id = KVM_REG_PPC_LPCR_64,
+ .addr = (uintptr_t) &lpcr,
+ };
+
+ vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, ®);
+ fprintf(stream, "%*slpcr: %#lx\n", indent + 4, "", lpcr);
+ }
+ fprintf(stream, "%*slr: %#llx\n", indent + 4, "", regs.lr);
+}
+
+void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid)
+{
+ struct kvm_run *run;
+
+ run = vcpu_state(vm, vcpuid);
+ if (run) {
+ switch (run->exit_reason) {
+ case KVM_EXIT_PAPR_HCALL:
+ case KVM_EXIT_MMIO:
+ return;
+ default:
+ printf("reason: %s\n",
+ exit_reason_str(run->exit_reason));
+ break;
+ }
+ }
+#ifdef DEBUG
+ vm_dump(stderr, vm, 2);
+#endif
+ TEST_ASSERT(false, "Unhandled exception");
+}
diff --git a/tools/testing/selftests/kvm/lib/powerpc/ucall.c b/tools/testing/selftests/kvm/lib/powerpc/ucall.c
new file mode 100644
index 000000000000..fc76ef796f02
--- /dev/null
+++ b/tools/testing/selftests/kvm/lib/powerpc/ucall.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "kvm_util.h"
+#include "processor.h"
+
+/*
+ * Using this hypercall for now because it is already defined. It is
+ * used by SLOF to ask QEMU to copy memory regions, so it is close
+ * enough for our purposes.
+ */
+#define KVMPPC_H_LOGICAL_MEMOP 0xf001
+
+
+void ucall_init(struct kvm_vm *vm, void *arg)
+{
+}
+
+void ucall_uninit(struct kvm_vm *vm)
+{
+}
+
+static inline int __ucall(uint64_t args)
+{
+ return hcall(KVMPPC_H_LOGICAL_MEMOP, args);
+}
+
+/*
+ * This function runs inside the guest, so avoid optimizations that
+ * could add an indirect call via PLT and disable vector instructions
+ * like the kernel does.
+ */
+__attribute__((optimize(0), target("no-altivec,no-vsx")))
+void ucall(uint64_t cmd, int nargs, ...)
+{
+ struct ucall uc = {
+ .cmd = cmd,
+ };
+ va_list va;
+ int i;
+
+ nargs = nargs <= UCALL_MAX_ARGS ? nargs : UCALL_MAX_ARGS;
+
+ va_start(va, nargs);
+ for (i = 0; i < nargs; ++i)
+ uc.args[i] = va_arg(va, uint64_t);
+ va_end(va);
+
+ __ucall((uint64_t)&uc);
+}
+
+uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
+{
+ struct kvm_run *run = vcpu_state(vm, vcpu_id);
+ struct ucall ucall = {};
+
+ if (uc)
+ memset(uc, 0, sizeof(*uc));
+
+ if (run->exit_reason == KVM_EXIT_PAPR_HCALL &&
+ run->papr_hcall.nr == KVMPPC_H_LOGICAL_MEMOP) {
+ memcpy(&ucall, addr_gva2hva(vm, run->papr_hcall.args[0]),
+ sizeof(ucall));
+ if (uc)
+ memcpy(uc, &ucall, sizeof(ucall));
+ }
+
+ return ucall.cmd;
+}
diff --git a/tools/testing/selftests/kvm/powerpc/sample_test.c b/tools/testing/selftests/kvm/powerpc/sample_test.c
new file mode 100644
index 000000000000..16f0df920d98
--- /dev/null
+++ b/tools/testing/selftests/kvm/powerpc/sample_test.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#define _GNU_SOURCE /* for program_invocation_short_name */
+#include <pthread.h>
+#include <stdio.h>
+#include <signal.h>
+
+#define DEBUG
+#include "kvm_util.h"
+#include "test_util.h"
+#include "processor.h"
+
+#define H_PUT_TERM_CHAR 0x58
+#define TEST_VAL 0x8badf00d
+#define PASS_VAL 0xdeadbeef
+#define FAIL_VAL 0x2badd00d
+
+
+struct kvm_vm *vm;
+
+/*
+ * Call the hypervisor to write a character to the console. KVM does
+ * not handle this hypercall so it goes out to userspace. Which in
+ * this case is the vcpu_worker() below.
+ */
+static inline void put_char(char c)
+{
+ hcall(H_PUT_TERM_CHAR, 0, 1, cpu_to_be64(c));
+}
+
+static void guest_code(uint64_t *ptr, uint64_t val)
+{
+ /*
+ * Test making a hypercall and give a visual indication that
+ * the guest code is running.
+ */
+ put_char('.');
+
+ /* Make sure we can receive values */
+ GUEST_ASSERT(ptr);
+ GUEST_ASSERT(val == TEST_VAL);
+
+ put_char('.');
+
+ /* Read/write to memory */
+ if (*ptr == val)
+ *ptr = PASS_VAL;
+ else
+ *ptr = FAIL_VAL;
+
+ put_char('.');
+
+ /* Signal we're done */
+ GUEST_DONE();
+}
+
+static bool guest_done(struct kvm_vm *vm)
+{
+ struct ucall uc;
+ bool done;
+
+ switch (get_ucall(vm, 0, &uc)) {
+ case UCALL_ABORT:
+ TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0],
+ __FILE__, uc.args[1]);
+ /* not reached */
+ case UCALL_DONE:
+ done = true;
+ break;
+ default:
+ done = false;
+ break;
+ }
+
+ return done;
+}
+
+static void *vcpu_worker(void *data)
+{
+ struct kvm_vm *vm = data;
+ struct kvm_run *run;
+ uint64_t *hva;
+ static uint64_t test_buf = TEST_VAL;
+
+ /* Pass arguments to the guest code */
+ vcpu_args_set(vm, 0, 2, &test_buf, TEST_VAL);
+
+ run = vcpu_state(vm, 0);
+ while (1) {
+ vcpu_run(vm, 0);
+
+ if (guest_done(vm))
+ break;
+
+ switch (run->exit_reason) {
+ case KVM_EXIT_PAPR_HCALL:
+ if (run->papr_hcall.nr == H_PUT_TERM_CHAR) {
+ char c = be64_to_cpu(run->papr_hcall.args[2]);
+
+ pr_debug("%c", c);
+ }
+ break;
+ default:
+ printf("exit reason: %s\n", exit_reason_str(run->exit_reason));
+ break;
+ }
+ }
+
+ hva = addr_gva2hva(vm, (vm_vaddr_t)&test_buf);
+ TEST_ASSERT(*hva != FAIL_VAL,
+ "Guest failed to read test value at gva %p", &test_buf);
+ TEST_ASSERT(*hva == PASS_VAL,
+ "Guest failed to write test value to gva %p", &test_buf);
+
+ pr_debug("PASS\n");
+
+ return NULL;
+}
+
+void dump_vm(int sig)
+{
+ vm_dump(stderr, vm, 2);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ pthread_t vcpu_thread;
+
+ signal(SIGINT, dump_vm);
+
+ /*
+ * Do not buffer stdout so we can implement put_char without
+ * flushing.
+ */
+ setbuf(stdout, NULL);
+
+ vm = vm_create_default(0, 0, guest_code);
+ pthread_create(&vcpu_thread, NULL, vcpu_worker, vm);
+
+ pthread_join(vcpu_thread, NULL);
+ kvm_vm_free(vm);
+
+ return 0;
+}
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox