From: NIIBE Y. <gn...@m1...> - 2002-03-05 09:07:08
|
Follow up to 2.5.4. Introducing thread_info structure. Will come correspoinding change of entry.S... Note that we won't have addr_limit member for thread_info. This should be fit in a cache line (or it's better), and SH-3 has only has 16-byte. 2002-03-05 NIIBE Yutaka <gn...@m1...> * arch/sh/kernel/fpu.c (save_fpu, ieee_fpe_handler, do_fpu_state_restore): Use set_tsk_thread_flag and clear_tsk_thread_flag. * arch/sh/kernel/process.c (print_syscall): Removed. * include/asm-sh/processor.h (thread_saved_pc): Follow the change of API (argument type). (THREAD_SIZE): Removed from here (will be in thread_info.h). (alloc_task_struct, free_task_struct, get_task_struct, init_task, init_stack): Removed. (unlazy_fpu, clear_fpu): Use test_tsk_thread_flag and clear_tsk_thread_flag. * include/asm-sh/uaccess.h (KERN_ADDR_LIMIT, USER_ADDR_LIMIT): New macros. (KERNEL_DS, USER_DS): Use KERN_ADDR_LIMIT, USER_ADDR_LIMIT. (get_fs, set_fs): New functions using thread flag. (__addr_ok, __range_ok): Use get_fs().seg. * include/asm-sh/thread_info.h: New file. Index: arch/sh/kernel/fpu.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/fpu.c,v retrieving revision 1.3 diff -u -3 -p -r1.3 fpu.c --- arch/sh/kernel/fpu.c 1 Mar 2002 01:55:10 -0000 1.3 +++ arch/sh/kernel/fpu.c 5 Mar 2002 09:01:58 -0000 @@ -67,7 +67,7 @@ save_fpu(struct task_struct *tsk) "r" (FPSCR_INIT) : "memory"); - clear_thread_flag(TIF_USEDFPU); + clear_tsk_thread_flag(tsk, TIF_USEDFPU); release_fpu(); } @@ -260,7 +260,7 @@ ieee_fpe_handler (struct pt_regs *regs) ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); grab_fpu(); restore_fpu(tsk); - set_thread_flag(TIF_USEDFPU); + set_tsk_thread_flag(tsk, TIF_USEDFPU); } else { tsk->thread.trap_no = 11; tsk->thread.error_code = 0; @@ -310,5 +310,5 @@ do_fpu_state_restore(unsigned long r4, u fpu_init(); tsk->used_math = 1; } - set_thread_flag(TIF_USEDFPU); + set_tsk_thread_flag(tsk, TIF_USEDFPU); } Index: arch/sh/kernel/process.c =================================================================== RCS file: /cvsroot/linuxsh/linux/arch/sh/kernel/process.c,v retrieving revision 1.4 diff -u -3 -p -r1.4 process.c --- arch/sh/kernel/process.c 24 Jan 2002 11:22:36 -0000 1.4 +++ arch/sh/kernel/process.c 5 Mar 2002 09:01:58 -0000 @@ -355,17 +355,6 @@ unsigned long get_wchan(struct task_stru return pc; } -asmlinkage void print_syscall(int x) -{ - unsigned long flags, sr; - asm("stc sr, %0": "=r" (sr)); - save_and_cli(flags); - printk("%c: %c %c, %c: SYSCALL\n", (x&63)+32, - (current->flags&PF_USEDFPU)?'C':' ', - (init_task.flags&PF_USEDFPU)?'K':' ', (sr&SR_FD)?' ':'F'); - restore_flags(flags); -} - asmlinkage void break_point_trap(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) Index: include/asm-sh/processor.h =================================================================== RCS file: /cvsroot/linuxsh/linux/include/asm-sh/processor.h,v retrieving revision 1.2 diff -u -3 -p -r1.2 processor.h --- include/asm-sh/processor.h 29 Dec 2001 06:50:38 -0000 1.2 +++ include/asm-sh/processor.h 5 Mar 2002 09:01:58 -0000 @@ -182,17 +182,17 @@ static __inline__ void grab_fpu(void) extern void save_fpu(struct task_struct *__tsk); -#define unlazy_fpu(tsk) do { \ - if ((tsk)->flags & PF_USEDFPU) { \ - save_fpu(tsk); \ - } \ +#define unlazy_fpu(tsk) do { \ + if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ + save_fpu(tsk); \ + } \ } while (0) -#define clear_fpu(tsk) do { \ - if ((tsk)->flags & PF_USEDFPU) { \ - (tsk)->flags &= ~PF_USEDFPU; \ - release_fpu(); \ - } \ +#define clear_fpu(tsk) do { \ + if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ + clear_tsk_thread_flag(tsk, TIF_USEDFPU); \ + release_fpu(); \ + } \ } while (0) /* Double presision, NANS as NANS, rounding to nearest, no exceptions */ @@ -204,23 +204,15 @@ extern void save_fpu(struct task_struct /* * Return saved PC of a blocked thread. */ -static __inline__ unsigned long thread_saved_pc(struct thread_struct *t) +static __inline__ unsigned long thread_saved_pc(struct task_struct *tsk) { - return t->pc; + return tsk->thread->pc; } extern unsigned long get_wchan(struct task_struct *p); #define KSTK_EIP(tsk) ((tsk)->thread.pc) #define KSTK_ESP(tsk) ((tsk)->thread.sp) - -#define THREAD_SIZE (2*PAGE_SIZE) -extern struct task_struct * alloc_task_struct(void); -extern void free_task_struct(struct task_struct *); -#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) - -#define init_task (init_task_union.task) -#define init_stack (init_task_union.stack) #define cpu_relax() do { } while (0) Index: include/asm-sh/thread_info.h =================================================================== RCS file: include/asm-sh/thread_info.h diff -N include/asm-sh/thread_info.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ include/asm-sh/thread_info.h 5 Mar 2002 09:01:58 -0000 @@ -0,0 +1,110 @@ +#ifndef __ASM_SH_THREAD_INFO_H +#define __ASM_SH_THREAD_INFO_H + +/* SuperH version + * Copyright (C) 2002 Niibe Yutaka + * + * The copyright of original i386 version is: + * + * Copyright (C) 2002 David Howells (dho...@re...) + * - Incorporating suggestions made by Linus Torvalds and Dave Miller + */ + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ +#include <asm/processor.h> +#endif + +/* + * low level task data that entry.S needs immediate access to + * - this struct should fit entirely inside of one cache line + * - this struct shares the supervisor stack pages + * - if the contents of this structure are changed, the assembly constants must also be changed + */ +#ifndef __ASSEMBLY__ +struct thread_info { + struct task_struct *task; /* main task structure */ + struct exec_domain *exec_domain; /* execution domain */ + __u32 flags; /* low level flags */ + __s32 preempt_count; /* 0 => preemptable, <0 => BUG */ + + __u8 supervisor_stack[0]; +}; + +#else /* !__ASSEMBLY__ */ + +/* offsets into the thread_info struct for assembly code access */ +#define TI_TASK 0x00000000 +#define TI_EXEC_DOMAIN 0x00000004 +#define TI_FLAGS 0x00000008 +#define TI_PRE_COUNT 0x0000000c + +#endif + +/* + * macros/functions for gaining access to the thread information structure + */ +#ifndef __ASSEMBLY__ +#define INIT_THREAD_INFO(tsk) \ +{ \ + task: &tsk, \ + exec_domain: &default_exec_domain, \ + flags: 0, \ + preempt_count: 0, \ +} + +#define init_thread_info (init_thread_union.thread_info) +#define init_stack (init_thread_union.stack) + +/* how to get the thread information struct from C */ +static inline struct thread_info *current_thread_info(void) +{ + struct thread_info *ti; + __asm__("stc r7_bank, %0" : "=r" (ti)); + return ti; +} + +/* thread information allocation */ +#define THREAD_SIZE (2*PAGE_SIZE) +#define alloc_thread_info() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) +#define free_thread_info(ti) free_pages((unsigned long) (ti), 1) +#define get_thread_info(ti) get_task_struct((ti)->task) +#define put_thread_info(ti) put_task_struct((ti)->task) + +#else /* !__ASSEMBLY__ */ + +/* how to get the thread information struct from ASM */ +#define GET_THREAD_INFO(reg) \ + stc r7_bank, reg + +#endif + +/* + * thread information flags + * - these are process state flags that various assembly files may need to access + * - pending work-to-be-done flags are in LSW + * - other flags in MSW + */ +#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */ +#define TIF_SIGPENDING 2 /* signal pending */ +#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ +#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ +#define TIF_USERSPACE 18 /* true if FS sets userspace */ + +#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) +#define _TIF_SIGPENDING (1<<TIF_SIGPENDING) +#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) +#define _TIF_USEDFPU (1<<TIF_USEDFPU) +#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) +#define _TIF_USERSPACE (1<<TIF_USERSPACE) + +#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ +#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ + +#endif /* __KERNEL__ */ + +#endif /* __ASM_SH_THREAD_INFO_H */ Index: include/asm-sh/uaccess.h =================================================================== RCS file: /cvsroot/linuxsh/linux/include/asm-sh/uaccess.h,v retrieving revision 1.3 diff -u -3 -p -r1.3 uaccess.h --- include/asm-sh/uaccess.h 1 Mar 2002 01:55:10 -0000 1.3 +++ include/asm-sh/uaccess.h 5 Mar 2002 09:01:58 -0000 @@ -28,16 +28,33 @@ #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) -#define USER_DS MAKE_MM_SEG(0x80000000) +#define KERN_ADDR_LIMIT 0xFFFFFFFF +#define USER_ADDR_LIMIT 0x80000000 + +#define KERNEL_DS MAKE_MM_SEG(KERN_ADDR_LIMIT) +#define USER_DS MAKE_MM_SEG(USER_ADDR_LIMIT) #define get_ds() (KERNEL_DS) -#define get_fs() (current_thread_info()->addr_limit) -#define set_fs(x) (current_thread_info()->addr_limit=(x)) + +static inline mm_segment_t get_fs(void) +{ + if (test_thread_flag(TIF_USERSPACE)) + return USER_DS; + else + return KERNEL_DS; +} + +static inline void set_fs(mm_segment_t s) +{ + if (s.seg == USER_ADDR_LIMIT) + set_thread_flag(TIF_USERSPACE); + else + clear_thread_flag(TIF_USERSPACE); +} #define segment_eq(a,b) ((a).seg == (b).seg) -#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) +#define __addr_ok(addr) ((unsigned long)(addr) < (get_fs().seg)) /* * Uhhuh, this needs 33-bit arithmetic. We have a carry.. @@ -49,7 +66,7 @@ unsigned long flag,sum; \ __asm__("clrt; addc %3, %1; movt %0; cmp/hi %4, %1; rotcl %0" \ :"=&r" (flag), "=r" (sum) \ - :"1" (addr), "r" ((int)(size)), "r" (current_thread_info()->addr_limit.seg) \ + :"1" (addr), "r" ((int)(size)), "r" (get_fs().seg) \ :"t"); \ flag; }) |