xtensa: fix MAKE_PC_FROM_RA second argument
authorMax Filippov <jcmvbkbc@gmail.com>
Sat, 17 Feb 2024 13:15:42 +0000 (05:15 -0800)
committerMax Filippov <jcmvbkbc@gmail.com>
Wed, 3 Apr 2024 02:42:35 +0000 (19:42 -0700)
Xtensa has two-argument MAKE_PC_FROM_RA macro to convert a0 to an actual
return address because when windowed ABI is used call{,x}{4,8,12}
opcodes stuff encoded window size into the top 2 bits of the register
that becomes a return address in the called function. Second argument of
that macro is supposed to be an address having these 2 topmost bits set
correctly, but the comment suggested that that could be the stack
address. However the stack doesn't have to be in the same 1GByte region
as the code, especially in noMMU XIP configurations.

Fix the comment and use either _text or regs->pc as the second argument
for the MAKE_PC_FROM_RA macro.

Cc: stable@vger.kernel.org
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/ptrace.h
arch/xtensa/kernel/process.c
arch/xtensa/kernel/stacktrace.c

index d008a153a2b9f7a9782b5874643f2d5a3741e995..7ed1a2085bd72883025c7de7d0d028ab077cc56c 100644 (file)
 #define MAKE_RA_FOR_CALL(ra,ws)   (((ra) & 0x3fffffff) | (ws) << 30)
 
 /* Convert return address to a valid pc
- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ * Note: 'text' is the address within the same 1GB range as the ra
  */
-#define MAKE_PC_FROM_RA(ra,sp)    (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
+#define MAKE_PC_FROM_RA(ra, text) (((ra) & 0x3fffffff) | ((unsigned long)(text) & 0xc0000000))
 
 #elif defined(__XTENSA_CALL0_ABI__)
 
 #define MAKE_RA_FOR_CALL(ra, ws)   (ra)
 
 /* Convert return address to a valid pc
- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ * Note: 'text' is not used as 'ra' is always the full address
  */
-#define MAKE_PC_FROM_RA(ra, sp)    (ra)
+#define MAKE_PC_FROM_RA(ra, text)  (ra)
 
 #else
 #error Unsupported Xtensa ABI
index a270467556dc84df2c6ceb0786acee3669a059f8..86c70117371bb7cc022b0793f0a4eb8ef834bc63 100644 (file)
@@ -87,7 +87,7 @@ struct pt_regs {
 # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
 # define instruction_pointer(regs) ((regs)->pc)
 # define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
-                                              (regs)->areg[1]))
+                                              (regs)->pc))
 
 # ifndef CONFIG_SMP
 #  define profile_pc(regs) instruction_pointer(regs)
index a815577d25fd02f3b267359d923cb83aae512c3d..7bd66677f7b6de58d0a1bda1b414ebc622dce962 100644 (file)
@@ -47,6 +47,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/regs.h>
 #include <asm/hw_breakpoint.h>
+#include <asm/sections.h>
 #include <asm/traps.h>
 
 extern void ret_from_fork(void);
@@ -380,7 +381,7 @@ unsigned long __get_wchan(struct task_struct *p)
        int count = 0;
 
        sp = p->thread.sp;
-       pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
+       pc = MAKE_PC_FROM_RA(p->thread.ra, _text);
 
        do {
                if (sp < stack_page + sizeof(struct task_struct) ||
@@ -392,7 +393,7 @@ unsigned long __get_wchan(struct task_struct *p)
 
                /* Stack layout: sp-4: ra, sp-3: sp' */
 
-               pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp);
+               pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), _text);
                sp = SPILL_SLOT(sp, 1);
        } while (count++ < 16);
        return 0;
index 831ffb648bda7e160408fd97530eddee760c27fc..ed324fdf2a2f9124527a5514ce14ac731996a2ad 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/stacktrace.h>
 
 #include <asm/ftrace.h>
+#include <asm/sections.h>
 #include <asm/stacktrace.h>
 #include <asm/traps.h>
 #include <linux/uaccess.h>
@@ -189,7 +190,7 @@ void walk_stackframe(unsigned long *sp,
                if (a1 <= (unsigned long)sp)
                        break;
 
-               frame.pc = MAKE_PC_FROM_RA(a0, a1);
+               frame.pc = MAKE_PC_FROM_RA(a0, _text);
                frame.sp = a1;
 
                if (fn(&frame, data))