Merge patch series "riscv: Introduce compat-mode helpers & improve arch_get_mmap_end()"
authorPalmer Dabbelt <palmer@rivosinc.com>
Wed, 20 Mar 2024 00:09:05 +0000 (17:09 -0700)
committerPalmer Dabbelt <palmer@rivosinc.com>
Wed, 20 Mar 2024 15:56:05 +0000 (08:56 -0700)
Leonardo Bras <leobras@redhat.com> says:

I just saw the opportunity of optimizing the helper is_compat_task() by
introducing a compile-time test, and it made possible to remove some
 #ifdef's without any loss of performance.

I also saw the possibility of removing the direct check of task flags from
general code, and concentrated it in asm/compat.h by creating a few more
helpers, which in the end helped optimize code.

arch_get_mmap_end() just got a simple improvement and some extra docs.

* b4-shazam-merge:
  riscv: Introduce set_compat_task() in asm/compat.h
  riscv: Introduce is_compat_thread() into compat.h
  riscv: add compile-time test into is_compat_task()
  riscv: Replace direct thread flag check with is_compat_task()
  riscv: Improve arch_get_mmap_end() macro

Link: https://lore.kernel.org/r/20240103160024.70305-2-leobras@redhat.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/compat.h
arch/riscv/include/asm/elf.h
arch/riscv/include/asm/pgtable.h
arch/riscv/include/asm/processor.h
arch/riscv/kernel/ptrace.c

index 2ac955b51148f4f12d23c03b42aae76d79b79bed..aa103530a5c83a501ac00c0e00c5e15f8e6a59a9 100644 (file)
 
 static inline int is_compat_task(void)
 {
+       if (!IS_ENABLED(CONFIG_COMPAT))
+               return 0;
+
        return test_thread_flag(TIF_32BIT);
 }
 
+static inline int is_compat_thread(struct thread_info *thread)
+{
+       if (!IS_ENABLED(CONFIG_COMPAT))
+               return 0;
+
+       return test_ti_thread_flag(thread, TIF_32BIT);
+}
+
+static inline void set_compat_task(bool is_compat)
+{
+       if (is_compat)
+               set_thread_flag(TIF_32BIT);
+       else
+               clear_thread_flag(TIF_32BIT);
+}
+
 struct compat_user_regs_struct {
        compat_ulong_t pc;
        compat_ulong_t ra;
index 06c236bfab53b323491ce6ae3bbdbbbcd6206318..c7aea7886d22aaede04dba348c38779f139c31ee 100644 (file)
@@ -53,13 +53,9 @@ extern bool compat_elf_check_arch(Elf32_Ehdr *hdr);
 #define ELF_ET_DYN_BASE                ((DEFAULT_MAP_WINDOW / 3) * 2)
 
 #ifdef CONFIG_64BIT
-#ifdef CONFIG_COMPAT
-#define STACK_RND_MASK         (test_thread_flag(TIF_32BIT) ? \
+#define STACK_RND_MASK         (is_compat_task() ? \
                                 0x7ff >> (PAGE_SHIFT - 12) : \
                                 0x3ffff >> (PAGE_SHIFT - 12))
-#else
-#define STACK_RND_MASK         (0x3ffff >> (PAGE_SHIFT - 12))
-#endif
 #endif
 
 /*
@@ -139,10 +135,7 @@ do {                                                       \
 #ifdef CONFIG_COMPAT
 
 #define SET_PERSONALITY(ex)                                    \
-do {    if ((ex).e_ident[EI_CLASS] == ELFCLASS32)              \
-               set_thread_flag(TIF_32BIT);                     \
-       else                                                    \
-               clear_thread_flag(TIF_32BIT);                   \
+do {   set_compat_task((ex).e_ident[EI_CLASS] == ELFCLASS32);  \
        if (personality(current->personality) != PER_LINUX32)   \
                set_personality(PER_LINUX |                     \
                        (current->personality & (~PER_MASK)));  \
index 3e9177f40c68408e6923bfef769ddf4ef6c26637..9c45810806ff410daa8a726e732d7b60065e6c97 100644 (file)
 #define VA_USER_SV48 (UL(1) << (VA_BITS_SV48 - 1))
 #define VA_USER_SV57 (UL(1) << (VA_BITS_SV57 - 1))
 
-#ifdef CONFIG_COMPAT
 #define MMAP_VA_BITS_64 ((VA_BITS >= VA_BITS_SV48) ? VA_BITS_SV48 : VA_BITS)
 #define MMAP_MIN_VA_BITS_64 (VA_BITS_SV39)
 #define MMAP_VA_BITS (is_compat_task() ? VA_BITS_SV32 : MMAP_VA_BITS_64)
 #define MMAP_MIN_VA_BITS (is_compat_task() ? VA_BITS_SV32 : MMAP_MIN_VA_BITS_64)
-#else
-#define MMAP_VA_BITS ((VA_BITS >= VA_BITS_SV48) ? VA_BITS_SV48 : VA_BITS)
-#define MMAP_MIN_VA_BITS (VA_BITS_SV39)
-#endif /* CONFIG_COMPAT */
-
 #else
 #include <asm/pgtable-32.h>
 #endif /* CONFIG_64BIT */
@@ -877,8 +871,8 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
 #define TASK_SIZE_MIN  (PGDIR_SIZE_L3 * PTRS_PER_PGD / 2)
 
 #ifdef CONFIG_COMPAT
-#define TASK_SIZE_32   (_AC(0x80000000, UL))
-#define TASK_SIZE      (test_thread_flag(TIF_32BIT) ? \
+#define TASK_SIZE_32   (_AC(0x80000000, UL) - PAGE_SIZE)
+#define TASK_SIZE      (is_compat_task() ? \
                         TASK_SIZE_32 : TASK_SIZE_64)
 #else
 #define TASK_SIZE      TASK_SIZE_64
index 0d13b4497b01745a467f580b6a2dd52b274de206..0faf5f161f1e4957b4cbeac63cf4d69c4dbd55e6 100644 (file)
 
 #include <asm/ptrace.h>
 
+/*
+ * addr is a hint to the maximum userspace address that mmap should provide, so
+ * this macro needs to return the largest address space available so that
+ * mmap_end < addr, being mmap_end the top of that address space.
+ * See Documentation/arch/riscv/vm-layout.rst for more details.
+ */
 #define arch_get_mmap_end(addr, len, flags)                    \
 ({                                                             \
        unsigned long mmap_end;                                 \
        typeof(addr) _addr = (addr);                            \
-       if ((_addr) == 0 ||                                     \
-           (IS_ENABLED(CONFIG_COMPAT) && is_compat_task()) ||  \
+       if ((_addr) == 0 || is_compat_task() ||                 \
            ((_addr + len) > BIT(VA_BITS - 1)))                 \
                mmap_end = STACK_TOP_MAX;                       \
        else                                                    \
@@ -33,8 +38,7 @@
        typeof(addr) _addr = (addr);                            \
        typeof(base) _base = (base);                            \
        unsigned long rnd_gap = DEFAULT_MAP_WINDOW - (_base);   \
-       if ((_addr) == 0 ||                                     \
-           (IS_ENABLED(CONFIG_COMPAT) && is_compat_task()) ||  \
+       if ((_addr) == 0 || is_compat_task() ||                 \
            ((_addr + len) > BIT(VA_BITS - 1)))                 \
                mmap_base = (_base);                            \
        else                                                    \
index e8515aa9d80bf82fd6ff2598664b9fe18a6b1de3..92731ff8c79ad02b6f3db9375b84635d3ea13f41 100644 (file)
@@ -377,14 +377,14 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
        return ret;
 }
+#else
+static const struct user_regset_view compat_riscv_user_native_view = {};
 #endif /* CONFIG_COMPAT */
 
 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
 {
-#ifdef CONFIG_COMPAT
-       if (test_tsk_thread_flag(task, TIF_32BIT))
+       if (is_compat_thread(&task->thread_info))
                return &compat_riscv_user_native_view;
        else
-#endif
                return &riscv_user_native_view;
 }