Re: [PATCH v5 3/5] powerpc/64: make buildable without CONFIG_COMPAT

From: Christophe Leroy
Date: Fri Aug 30 2019 - 02:35:17 EST


On 08/29/2019 10:28 PM, Michal Suchanek wrote:
> There are numerous references to 32bit functions in generic and 64bit
> code so ifdef them out.
>
> Signed-off-by: Michal Suchanek <msuchanek@xxxxxxx>
> ---
> v2:
> - fix 32bit ifdef condition in signal.c
> - simplify the compat ifdef condition in vdso.c - 64bit is redundant
> - simplify the compat ifdef condition in callchain.c - 64bit is redundant
> v3:
> - use IS_ENABLED and maybe_unused where possible
> - do not ifdef declarations
> - clean up Makefile
> v4:
> - further makefile cleanup
> - simplify is_32bit_task conditions
> - avoid ifdef in condition by using return
> v5:
> - avoid unreachable code on 32bit
> - make is_current_64bit constant on !COMPAT
> - add stub perf_callchain_user_32 to avoid some ifdefs
> ---
> arch/powerpc/include/asm/thread_info.h | 4 ++--
> arch/powerpc/kernel/Makefile | 7 +++----
> arch/powerpc/kernel/entry_64.S | 2 ++
> arch/powerpc/kernel/signal.c | 3 +--
> arch/powerpc/kernel/syscall_64.c | 6 ++----
> arch/powerpc/kernel/vdso.c | 5 ++---
> arch/powerpc/perf/callchain.c | 13 +++++++++++--
> 7 files changed, 23 insertions(+), 17 deletions(-)
>
[...]

> diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c
> index c84bbd4298a0..881be5c4e9bb 100644
> --- a/arch/powerpc/perf/callchain.c
> +++ b/arch/powerpc/perf/callchain.c
> @@ -15,7 +15,7 @@
> #include <asm/sigcontext.h>
> #include <asm/ucontext.h>
> #include <asm/vdso.h>
> -#ifdef CONFIG_PPC64
> +#ifdef CONFIG_COMPAT
> #include "../kernel/ppc32.h"
> #endif
> #include <asm/pte-walk.h>
> @@ -291,7 +291,8 @@ static inline int current_is_64bit(void)
> * interrupt stack, and the thread flags don't get copied over
> * from the thread_info on the main stack to the interrupt stack.
> */
> - return !test_ti_thread_flag(task_thread_info(current), TIF_32BIT);
> + return !IS_ENABLED(CONFIG_COMPAT) ||
> + !test_ti_thread_flag(task_thread_info(current), TIF_32BIT);
> }
>
> #else /* CONFIG_PPC64 */
> @@ -341,6 +342,7 @@ static inline int valid_user_sp(unsigned long sp, int is_64)
>
> #endif /* CONFIG_PPC64 */
>
> +#if defined(CONFIG_PPC32) || defined(CONFIG_COMPAT)
> /*
> * Layout for non-RT signal frames
> */
> @@ -482,6 +484,13 @@ static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
> sp = next_sp;
> }
> }
> +#else /* 32bit */
> +static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
> + struct pt_regs *regs)
> +{
> + (void)&read_user_stack_32; /* unused if !COMPAT */

That looks pretty much like a hack.

See possible alternative below.

> +}
> +#endif /* 32bit */
>
> void
> perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
>

---
arch/powerpc/perf/callchain.c | 62 +++++++++++++++++++------------------------
1 file changed, 27 insertions(+), 35 deletions(-)

diff --git a/arch/powerpc/perf/callchain.c b/arch/powerpc/perf/callchain.c
index 881be5c4e9bb..1b169b32776a 100644
--- a/arch/powerpc/perf/callchain.c
+++ b/arch/powerpc/perf/callchain.c
@@ -165,22 +165,6 @@ static int read_user_stack_64(unsigned long __user *ptr, unsigned long *ret)
return read_user_stack_slow(ptr, ret, 8);
}

-static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
-{
- if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) ||
- ((unsigned long)ptr & 3))
- return -EFAULT;
-
- pagefault_disable();
- if (!__get_user_inatomic(*ret, ptr)) {
- pagefault_enable();
- return 0;
- }
- pagefault_enable();
-
- return read_user_stack_slow(ptr, ret, 4);
-}
-
static inline int valid_user_sp(unsigned long sp, int is_64)
{
if (!sp || (sp & 7) || sp > (is_64 ? TASK_SIZE : 0x100000000UL) - 32)
@@ -296,25 +280,10 @@ static inline int current_is_64bit(void)
}

#else /* CONFIG_PPC64 */
-/*
- * On 32-bit we just access the address and let hash_page create a
- * HPTE if necessary, so there is no need to fall back to reading
- * the page tables. Since this is called at interrupt level,
- * do_page_fault() won't treat a DSI as a page fault.
- */
-static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
-{
- int rc;
-
- if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) ||
- ((unsigned long)ptr & 3))
- return -EFAULT;

- pagefault_disable();
- rc = __get_user_inatomic(*ret, ptr);
- pagefault_enable();
-
- return rc;
+static int read_user_stack_slow(void __user *ptr, void *buf, int nb)
+{
+ return 0;
}

static inline void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry,
@@ -344,6 +313,30 @@ static inline int valid_user_sp(unsigned long sp, int is_64)

#if defined(CONFIG_PPC32) || defined(CONFIG_COMPAT)
/*
+ * On 32-bit we just access the address and let hash_page create a
+ * HPTE if necessary, so there is no need to fall back to reading
+ * the page tables. Since this is called at interrupt level,
+ * do_page_fault() won't treat a DSI as a page fault.
+ */
+static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret)
+{
+ int rc;
+
+ if ((unsigned long)ptr > TASK_SIZE - sizeof(unsigned int) ||
+ ((unsigned long)ptr & 3))
+ return -EFAULT;
+
+ pagefault_disable();
+ rc = __get_user_inatomic(*ret, ptr);
+ pagefault_enable();
+
+ if (IS_ENABLED(CONFIG_PPC32) || !rc)
+ return rc;
+
+ return read_user_stack_slow(ptr, ret, 4);
+}
+
+/*
* Layout for non-RT signal frames
*/
struct signal_frame_32 {
@@ -488,7 +481,6 @@ static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
static void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry,
struct pt_regs *regs)
{
- (void)&read_user_stack_32; /* unused if !COMPAT */
}
#endif /* 32bit */

--
2.13.3