RISC-V: Stop relying on GCC's register allocator's hueristics
GCC allows users to hint to the register allocation that a variable should be placed in a register by using a syntax along the lines of function(...) { register long in_REG __asm__("REG"); } We've abused this a bit throughout the RISC-V port to access fixed registers directly as C variables. In practice it's never going to blow up because GCC isn't going to allocate these registers, but it's not a well defined syntax so we really shouldn't be relying upon this. Luckily there is a very similar but well defined syntax that allows us to still access these registers directly as C variables, which is to simply declare the register variables globally. For fixed variables this doesn't change the ABI. LLVM disallows this ambiguous syntax, so this isn't just strictly a formatting change. Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
This commit is contained in:
parent
064223b947
commit
52e7c52d2d
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
struct task_struct;
|
struct task_struct;
|
||||||
|
|
||||||
|
register struct task_struct *riscv_current_is_tp __asm__("tp");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This only works because "struct thread_info" is at offset 0 from "struct
|
* This only works because "struct thread_info" is at offset 0 from "struct
|
||||||
* task_struct". This constraint seems to be necessary on other architectures
|
* task_struct". This constraint seems to be necessary on other architectures
|
||||||
|
@ -26,8 +28,7 @@ struct task_struct;
|
||||||
*/
|
*/
|
||||||
static __always_inline struct task_struct *get_current(void)
|
static __always_inline struct task_struct *get_current(void)
|
||||||
{
|
{
|
||||||
register struct task_struct *tp __asm__("tp");
|
return riscv_current_is_tp;
|
||||||
return tp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define current get_current()
|
#define current get_current()
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <asm/switch_to.h>
|
#include <asm/switch_to.h>
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
|
|
||||||
|
unsigned long gp_in_global __asm__("gp");
|
||||||
|
|
||||||
extern asmlinkage void ret_from_fork(void);
|
extern asmlinkage void ret_from_fork(void);
|
||||||
extern asmlinkage void ret_from_kernel_thread(void);
|
extern asmlinkage void ret_from_kernel_thread(void);
|
||||||
|
|
||||||
|
@ -107,9 +109,8 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
|
||||||
/* p->thread holds context to be restored by __switch_to() */
|
/* p->thread holds context to be restored by __switch_to() */
|
||||||
if (unlikely(p->flags & PF_KTHREAD)) {
|
if (unlikely(p->flags & PF_KTHREAD)) {
|
||||||
/* Kernel thread */
|
/* Kernel thread */
|
||||||
const register unsigned long gp __asm__ ("gp");
|
|
||||||
memset(childregs, 0, sizeof(struct pt_regs));
|
memset(childregs, 0, sizeof(struct pt_regs));
|
||||||
childregs->gp = gp;
|
childregs->gp = gp_in_global;
|
||||||
/* Supervisor/Machine, irqs on: */
|
/* Supervisor/Machine, irqs on: */
|
||||||
childregs->status = SR_PP | SR_PIE;
|
childregs->status = SR_PP | SR_PIE;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ struct stackframe {
|
||||||
unsigned long ra;
|
unsigned long ra;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
register unsigned long sp_in_global __asm__("sp");
|
||||||
|
|
||||||
void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
||||||
bool (*fn)(unsigned long, void *), void *arg)
|
bool (*fn)(unsigned long, void *), void *arg)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +31,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
|
||||||
sp = user_stack_pointer(regs);
|
sp = user_stack_pointer(regs);
|
||||||
pc = instruction_pointer(regs);
|
pc = instruction_pointer(regs);
|
||||||
} else if (task == NULL || task == current) {
|
} else if (task == NULL || task == current) {
|
||||||
const register unsigned long current_sp __asm__ ("sp");
|
const register unsigned long current_sp = sp_in_global;
|
||||||
fp = (unsigned long)__builtin_frame_address(0);
|
fp = (unsigned long)__builtin_frame_address(0);
|
||||||
sp = current_sp;
|
sp = current_sp;
|
||||||
pc = (unsigned long)walk_stackframe;
|
pc = (unsigned long)walk_stackframe;
|
||||||
|
@ -73,8 +75,7 @@ static void notrace walk_stackframe(struct task_struct *task,
|
||||||
sp = user_stack_pointer(regs);
|
sp = user_stack_pointer(regs);
|
||||||
pc = instruction_pointer(regs);
|
pc = instruction_pointer(regs);
|
||||||
} else if (task == NULL || task == current) {
|
} else if (task == NULL || task == current) {
|
||||||
const register unsigned long current_sp __asm__ ("sp");
|
sp = sp_in_global;
|
||||||
sp = current_sp;
|
|
||||||
pc = (unsigned long)walk_stackframe;
|
pc = (unsigned long)walk_stackframe;
|
||||||
} else {
|
} else {
|
||||||
/* task blocked in __switch_to */
|
/* task blocked in __switch_to */
|
||||||
|
|
Loading…
Reference in New Issue