Skip to content

Commit

Permalink
MN10300: Save frame pointer in thread_info struct rather than global var
Browse files Browse the repository at this point in the history
Save the current exception frame pointer in the thread_info struct rather than
in a global variable as the latter makes SMP tricky, especially when preemption
is also enabled.

This also replaces __frame with current_frame() and rearranges header file
inclusions to make it all compile.

Signed-off-by: David Howells <[email protected]>
Acked-by: Akira Takeuchi <[email protected]>
  • Loading branch information
dhowells committed Oct 27, 2010
1 parent a5e03ca commit 7c7fcf7
Show file tree
Hide file tree
Showing 15 changed files with 76 additions and 146 deletions.
56 changes: 13 additions & 43 deletions arch/mn10300/include/asm/frame.inc
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@
#ifndef __ASM_OFFSETS_H__
#include <asm/asm-offsets.h>
#endif
#ifdef CONFIG_SMP
#include <proc/smp-regs.h>
#endif
#include <asm/thread_info.h>

#define pi break

Expand All @@ -40,27 +38,15 @@
movm [d2,d3,a2,a3,exreg0,exreg1,exother],(sp)
mov sp,fp # FRAME pointer in A3
add -12,sp # allow for calls to be made
#ifdef CONFIG_SMP
#ifdef CONFIG_PREEMPT /* FIXME */
mov epsw,d2
and ~EPSW_IE,epsw
#endif
mov (CPUID),a0
add a0,a0
add a0,a0
mov (___frame,a0),a1
mov a1,(REG_NEXT,fp)
mov fp,(___frame,a0)
#ifdef CONFIG_PREEMPT /* FIXME */
mov d2,epsw
#endif
#else /* CONFIG_SMP */
mov (__frame),a1
mov a1,(REG_NEXT,fp)
mov fp,(__frame)
#endif /* CONFIG_SMP */

and ~EPSW_FE,epsw # disable the FPU inside the kernel
# push the exception frame onto the front of the list
GET_THREAD_INFO a1
mov (TI_frame,a1),a0
mov a0,(REG_NEXT,fp)
mov fp,(TI_frame,a1)

# disable the FPU inside the kernel
and ~EPSW_FE,epsw

# we may be holding current in E2
#ifdef CONFIG_MN10300_CURRENT_IN_E2
Expand All @@ -76,27 +62,11 @@
.macro RESTORE_ALL
# peel back the stack to the calling frame
# - this permits execve() to discard extra frames due to kernel syscalls
#ifdef CONFIG_SMP
#ifdef CONFIG_PREEMPT /* FIXME */
mov epsw,d2
and ~EPSW_IE,epsw
#endif
mov (CPUID),a0
add a0,a0
add a0,a0
mov (___frame,a0),fp
mov fp,sp
mov (REG_NEXT,fp),d0 # userspace has regs->next == 0
mov d0,(___frame,a0)
#ifdef CONFIG_PREEMPT /* FIXME */
mov d2,epsw
#endif
#else /* CONFIG_SMP */
mov (__frame),fp
GET_THREAD_INFO a0
mov (TI_frame,a0),fp
mov fp,sp
mov (REG_NEXT,fp),d0 # userspace has regs->next == 0
mov d0,(__frame)
#endif /* CONFIG_SMP */
mov (REG_NEXT,fp),d0
mov d0,(TI_frame,a0) # userspace has regs->next == 0

#ifndef CONFIG_MN10300_USING_JTAG
mov (REG_EPSW,fp),d0
Expand Down
6 changes: 5 additions & 1 deletion arch/mn10300/include/asm/irq_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
#define ARCH_HAS_OWN_IRQ_REGS

#ifndef __ASSEMBLY__
#define get_irq_regs() (__frame)
static inline __attribute__((const))
struct pt_regs *get_irq_regs(void)
{
return current_frame();
}
#endif

#endif /* _ASM_IRQ_REGS_H */
1 change: 0 additions & 1 deletion arch/mn10300/include/asm/pgalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#ifndef _ASM_PGALLOC_H
#define _ASM_PGALLOC_H

#include <asm/processor.h>
#include <asm/page.h>
#include <linux/threads.h>
#include <linux/mm.h> /* for struct page */
Expand Down
46 changes: 18 additions & 28 deletions arch/mn10300/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@
#ifndef _ASM_PROCESSOR_H
#define _ASM_PROCESSOR_H

#include <linux/threads.h>
#include <linux/thread_info.h>
#include <asm/page.h>
#include <asm/ptrace.h>
#include <asm/cpu-regs.h>
#include <linux/threads.h>
#include <asm/uaccess.h>
#include <asm/current.h>

/* Forward declaration, a strange C thing */
struct task_struct;
Expand Down Expand Up @@ -83,10 +86,6 @@ extern void dodgy_tsc(void);
*/
#define TASK_UNMAPPED_BASE 0x30000000

typedef struct {
unsigned long seg;
} mm_segment_t;

struct fpu_state_struct {
unsigned long fs[32]; /* fpu registers */
unsigned long fpcr; /* fpu control register */
Expand All @@ -99,7 +98,6 @@ struct thread_struct {
unsigned long a3; /* kernel FP */
unsigned long wchan;
unsigned long usp;
struct pt_regs *frame;
unsigned long fpu_flags;
#define THREAD_USING_FPU 0x00000001 /* T if this task is using the FPU */
#define THREAD_HAS_FPU 0x00000002 /* T if this task owns the FPU right now */
Expand All @@ -113,7 +111,6 @@ struct thread_struct {
.sp = 0, \
.a3 = 0, \
.wchan = 0, \
.frame = NULL, \
}

#define INIT_MMAP \
Expand All @@ -125,27 +122,20 @@ struct thread_struct {
* - need to discard the frame stacked by the kernel thread invoking the execve
* syscall (see RESTORE_ALL macro)
*/
#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) /* FIXME */
#define start_thread(regs, new_pc, new_sp) do { \
int cpu; \
preempt_disable(); \
cpu = CPUID; \
set_fs(USER_DS); \
___frame[cpu] = current->thread.uregs; \
___frame[cpu]->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;\
___frame[cpu]->pc = new_pc; \
___frame[cpu]->sp = new_sp; \
preempt_enable(); \
} while (0)
#else /* CONFIG_SMP && CONFIG_PREEMPT */
#define start_thread(regs, new_pc, new_sp) do { \
set_fs(USER_DS); \
__frame = current->thread.uregs; \
__frame->epsw = EPSW_nSL | EPSW_IE | EPSW_IM; \
__frame->pc = new_pc; \
__frame->sp = new_sp; \
} while (0)
#endif /* CONFIG_SMP && CONFIG_PREEMPT */
static inline void start_thread(struct pt_regs *regs,
unsigned long new_pc, unsigned long new_sp)
{
struct thread_info *ti = current_thread_info();
struct pt_regs *frame0;
set_fs(USER_DS);

frame0 = thread_info_to_uregs(ti);
frame0->epsw = EPSW_nSL | EPSW_IE | EPSW_IM;
frame0->pc = new_pc;
frame0->sp = new_sp;
ti->frame = frame0;
}


/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);
Expand Down
6 changes: 0 additions & 6 deletions arch/mn10300/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ struct pt_regs {

#ifdef __KERNEL__

#ifdef CONFIG_SMP
extern struct pt_regs *___frame[]; /* current frame pointer */
#else
extern struct pt_regs *__frame; /* current frame pointer */
#endif

#define user_mode(regs) (((regs)->epsw & EPSW_nSL) == EPSW_nSL)
#define instruction_pointer(regs) ((regs)->pc)
#define user_stack_pointer(regs) ((regs)->sp)
Expand Down
13 changes: 0 additions & 13 deletions arch/mn10300/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,6 @@ extern int __cpu_disable(void);
extern void __cpu_die(unsigned int cpu);
#endif /* CONFIG_HOTPLUG_CPU */

#ifdef CONFIG_PREEMPT /* FIXME */
#define __frame \
({ \
struct pt_regs *f; \
preempt_disable(); \
f = ___frame[CPUID]; \
preempt_enable(); \
f; \
})
#else
#define __frame ___frame[CPUID]
#endif

#endif /* __ASSEMBLY__ */
#else /* CONFIG_SMP */
#ifndef __ASSEMBLY__
Expand Down
18 changes: 14 additions & 4 deletions arch/mn10300/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@

#include <asm/page.h>

#ifndef __ASSEMBLY__
#include <asm/processor.h>
#endif

#define PREEMPT_ACTIVE 0x10000000

#ifdef CONFIG_4KSTACKS
Expand All @@ -38,10 +34,14 @@
* must also be changed
*/
#ifndef __ASSEMBLY__
typedef struct {
unsigned long seg;
} mm_segment_t;

struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
struct pt_regs *frame; /* current exception frame */
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
__s32 preempt_count; /* 0 => preemptable, <0 => BUG */
Expand All @@ -55,6 +55,10 @@ struct thread_info {
__u8 supervisor_stack[0];
};

#define thread_info_to_uregs(ti) \
((struct pt_regs *) \
((unsigned long)ti + THREAD_SIZE - sizeof(struct pt_regs)))

#else /* !__ASSEMBLY__ */

#ifndef __ASM_OFFSETS_H__
Expand Down Expand Up @@ -102,6 +106,12 @@ struct thread_info *current_thread_info(void)
return ti;
}

static inline __attribute__((const))
struct pt_regs *current_frame(void)
{
return current_thread_info()->frame;
}

/* how to get the current stack pointer from C */
static inline unsigned long current_stack_pointer(void)
{
Expand Down
4 changes: 1 addition & 3 deletions arch/mn10300/include/asm/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
/*
* User space memory access functions
*/
#include <linux/sched.h>
#include <linux/thread_info.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/errno.h>

#define VERIFY_READ 0
Expand All @@ -29,7 +28,6 @@
*
* For historical reasons, these macros are grossly misnamed.
*/

#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })

#define KERNEL_XDS MAKE_MM_SEG(0xBFFFFFFF)
Expand Down
2 changes: 1 addition & 1 deletion arch/mn10300/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void foo(void)

OFFSET(TI_task, thread_info, task);
OFFSET(TI_exec_domain, thread_info, exec_domain);
OFFSET(TI_frame, thread_info, frame);
OFFSET(TI_flags, thread_info, flags);
OFFSET(TI_cpu, thread_info, cpu);
OFFSET(TI_preempt_count, thread_info, preempt_count);
Expand Down Expand Up @@ -66,7 +67,6 @@ void foo(void)
OFFSET(THREAD_SP, thread_struct, sp);
OFFSET(THREAD_A3, thread_struct, a3);
OFFSET(THREAD_USP, thread_struct, usp);
OFFSET(THREAD_FRAME, thread_struct, frame);
#ifdef CONFIG_FPU
OFFSET(THREAD_FPU_FLAGS, thread_struct, fpu_flags);
OFFSET(THREAD_FPU_STATE, thread_struct, fpu_state);
Expand Down
2 changes: 1 addition & 1 deletion arch/mn10300/kernel/mn10300-watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void __init watchdog_go(void)
static void watchdog_dump_register(void *dummy)
{
printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
show_registers(__frame);
show_registers(current_frame());
}
#endif

Expand Down
20 changes: 11 additions & 9 deletions arch/mn10300/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ int copy_thread(unsigned long clone_flags,
unsigned long c_usp, unsigned long ustk_size,
struct task_struct *p, struct pt_regs *kregs)
{
struct thread_info *ti = task_thread_info(p);
struct pt_regs *c_uregs, *c_kregs, *uregs;
unsigned long c_ksp;

Expand All @@ -248,7 +249,7 @@ int copy_thread(unsigned long clone_flags,

/* the new TLS pointer is passed in as arg #5 to sys_clone() */
if (clone_flags & CLONE_SETTLS)
c_uregs->e2 = __frame->d3;
c_uregs->e2 = current_frame()->d3;

/* set up the return kernel frame if called from kernel_thread() */
c_kregs = c_uregs;
Expand All @@ -266,7 +267,7 @@ int copy_thread(unsigned long clone_flags,
}

/* set up things up so the scheduler can start the new task */
p->thread.frame = c_kregs;
ti->frame = c_kregs;
p->thread.a3 = (unsigned long) c_kregs;
p->thread.sp = c_ksp;
p->thread.pc = (unsigned long) ret_from_fork;
Expand All @@ -278,25 +279,26 @@ int copy_thread(unsigned long clone_flags,

/*
* clone a process
* - tlsptr is retrieved by copy_thread() from __frame->d3
* - tlsptr is retrieved by copy_thread() from current_frame()->d3
*/
asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
int __user *parent_tidptr, int __user *child_tidptr,
int __user *tlsptr)
{
return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0,
parent_tidptr, child_tidptr);
return do_fork(clone_flags, newsp ?: current_frame()->sp,
current_frame(), 0, parent_tidptr, child_tidptr);
}

asmlinkage long sys_fork(void)
{
return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL);
return do_fork(SIGCHLD, current_frame()->sp,
current_frame(), 0, NULL, NULL);
}

asmlinkage long sys_vfork(void)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame,
0, NULL, NULL);
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
current_frame(), 0, NULL, NULL);
}

asmlinkage long sys_execve(const char __user *name,
Expand All @@ -310,7 +312,7 @@ asmlinkage long sys_execve(const char __user *name,
error = PTR_ERR(filename);
if (IS_ERR(filename))
return error;
error = do_execve(filename, argv, envp, __frame);
error = do_execve(filename, argv, envp, current_frame());
putname(filename);
return error;
}
Expand Down
Loading

0 comments on commit 7c7fcf7

Please sign in to comment.