Commit a9ffde7e authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: system call speedup part 2.

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

System call speedup part 2.
parent 42aef4b0
......@@ -155,9 +155,31 @@ typedef s390_regs elf_gregset_t;
/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
now struct_user_regs, they are different) */
#define ELF_CORE_COPY_REGS(pr_reg, regs) \
memcpy(&pr_reg,regs,sizeof(elf_gregset_t)); \
static inline int dump_regs(struct pt_regs *ptregs, elf_gregset_t *regs)
{
memcpy(&regs->psw, &ptregs->psw, sizeof(regs->psw)+sizeof(regs->gprs));
regs->orig_gpr2 = ptregs->orig_gpr2;
return 1;
}
#define ELF_CORE_COPY_REGS(pr_reg, regs) dump_regs(regs, &pr_reg);
static inline int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
{
dump_regs(__KSTK_PTREGS(tsk), regs);
memcpy(regs->acrs, tsk->thread.acrs, sizeof(regs->acrs));
return 1;
}
#define ELF_CORE_COPY_TASK_REGS(tsk, regs) dump_task_regs(tsk, regs)
static inline int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
{
memcpy(fpregs, &tsk->thread.fp_regs, sizeof(elf_fpregset_t));
return 1;
}
#define ELF_CORE_COPY_FPREGS(tsk, fpregs) dump_task_fpu(tsk, fpregs)
/* This yields a mask that user programs can use to figure out what
......
......@@ -64,7 +64,10 @@
#ifndef __s390x__
#define __LC_KERNEL_STACK 0xC40
#define __LC_ASYNC_STACK 0xC44
#define __LC_THREAD_INFO 0xC44
#define __LC_ASYNC_STACK 0xC48
#define __LC_KERNEL_ASCE 0xC4C
#define __LC_USER_ASCE 0xC50
#define __LC_CPUID 0xC60
#define __LC_CPUADDR 0xC68
#define __LC_IPLDEV 0xC7C
......@@ -73,13 +76,16 @@
#define __LC_INT_CLOCK 0xC98
#else /* __s390x__ */
#define __LC_KERNEL_STACK 0xD40
#define __LC_ASYNC_STACK 0xD48
#define __LC_THREAD_INFO 0xD48
#define __LC_ASYNC_STACK 0xD50
#define __LC_KERNEL_ASCE 0xD58
#define __LC_USER_ASCE 0xD60
#define __LC_CPUID 0xD90
#define __LC_CPUADDR 0xD98
#define __LC_IPLDEV 0xDB8
#define __LC_JIFFY_TIMER 0xDC0
#define __LC_CURRENT 0xDD8
#define __LC_INT_CLOCK 0xDE8
#define __LC_INT_CLOCK 0xDe8
#endif /* __s390x__ */
#define __LC_PANIC_MAGIC 0xE00
......@@ -99,7 +105,6 @@
#include <linux/config.h>
#include <asm/processor.h>
#include <linux/types.h>
#include <asm/atomic.h>
#include <asm/sigp.h>
void restart_int_handler(void);
......@@ -167,9 +172,12 @@ struct _lowcore
/* System info area */
__u32 save_area[16]; /* 0xc00 */
__u32 kernel_stack; /* 0xc40 */
__u32 async_stack; /* 0xc44 */
__u32 thread_info; /* 0xc44 */
__u32 async_stack; /* 0xc48 */
__u32 kernel_asce; /* 0xc4c */
__u32 user_asce; /* 0xc50 */
__u8 pad10[0xc60-0xc54]; /* 0xc54 */
/* entry.S sensitive area start */
__u8 pad10[0xc60-0xc48]; /* 0xc5c */
struct cpuinfo_S390 cpu_data; /* 0xc60 */
__u32 ipl_device; /* 0xc7c */
/* entry.S sensitive area end */
......@@ -245,9 +253,12 @@ struct _lowcore
__u64 save_area[16]; /* 0xc00 */
__u8 pad9[0xd40-0xc80]; /* 0xc80 */
__u64 kernel_stack; /* 0xd40 */
__u64 async_stack; /* 0xd48 */
__u64 thread_info; /* 0xd48 */
__u64 async_stack; /* 0xd50 */
__u64 kernel_asce; /* 0xd58 */
__u64 user_asce; /* 0xd60 */
__u8 pad10[0xd80-0xd68]; /* 0xd68 */
/* entry.S sensitive area start */
__u8 pad10[0xd80-0xd50]; /* 0xd64 */
struct cpuinfo_S390 cpu_data; /* 0xd80 */
__u32 ipl_device; /* 0xdb8 */
__u32 pad11; /* 0xdbc */
......
......@@ -24,22 +24,19 @@ static inline void enter_lazy_tlb(struct mm_struct *mm,
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk)
{
unsigned long pgd;
if (prev != next) {
#ifndef __s390x__
pgd = (__pa(next->pgd)&PAGE_MASK) |
S390_lowcore.user_asce = (__pa(next->pgd)&PAGE_MASK) |
(_SEGMENT_TABLE|USER_STD_MASK);
/* Load page tables */
asm volatile(" lctl 7,7,%0\n" /* secondary space */
" lctl 13,13,%0\n" /* home space */
: : "m" (pgd) );
/* Load home space page table origin. */
asm volatile("lctl 13,13,%0"
: : "m" (S390_lowcore.user_asce) );
#else /* __s390x__ */
pgd = (__pa(next->pgd)&PAGE_MASK) | (_REGION_TABLE|USER_STD_MASK);
/* Load page tables */
asm volatile(" lctlg 7,7,%0\n" /* secondary space */
" lctlg 13,13,%0\n" /* home space */
: : "m" (pgd) );
S390_lowcore.user_asce = (__pa(next->pgd) & PAGE_MASK) |
(_REGION_TABLE|USER_STD_MASK);
/* Load home space page table origin. */
asm volatile("lctlg 13,13,%0"
: : "m" (S390_lowcore.user_asce) );
#endif /* __s390x__ */
}
cpu_set(smp_processor_id(), next->cpu_vm_mask);
......@@ -51,6 +48,7 @@ extern inline void activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
switch_mm(prev, next, current);
set_fs(current->thread.mm_segment);
}
#endif
......@@ -82,10 +82,10 @@ typedef struct {
*/
struct thread_struct {
s390_fp_regs fp_regs;
unsigned int ar2; /* kernel access register 2 */
unsigned int ar4; /* kernel access register 4 */
unsigned int acrs[NUM_ACRS];
unsigned long ksp; /* kernel stack pointer */
unsigned long user_seg; /* HSTD */
mm_segment_t mm_segment;
unsigned long prot_addr; /* address of protection-excep. */
unsigned int error_code; /* error-code of last prog-excep. */
unsigned int trap_no;
......@@ -106,9 +106,10 @@ typedef struct thread_struct thread_struct;
#define INIT_THREAD {{0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, \
{0},{0},{0},{0},{0},{0}}}, \
0, 0, \
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
sizeof(init_stack) + (unsigned long) &init_stack, \
__SWAPPER_PG_DIR, \
{0}, \
0,0,0, \
(per_struct) {{{{0,}}},0,0,0,0,{{0,}}}, \
0, 0 \
......@@ -167,7 +168,7 @@ extern void show_trace(struct task_struct *task, unsigned long *sp);
unsigned long get_wchan(struct task_struct *p);
#define __KSTK_PTREGS(tsk) ((struct pt_regs *) \
(((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)) & -8L))
((unsigned long) tsk->thread_info + THREAD_SIZE - sizeof(struct pt_regs)))
#define KSTK_EIP(tsk) (__KSTK_PTREGS(tsk)->psw.addr)
#define KSTK_ESP(tsk) (__KSTK_PTREGS(tsk)->gprs[15])
......
......@@ -286,10 +286,7 @@ typedef struct
((NEW) & (PSW_MASK_CC|PSW_MASK_PM)))
/*
* The first entries in pt_regs and user_regs_struct
* are common for the two structures. The s390_regs structure
* covers the common parts. It simplifies copying the common part
* between the three structures.
* The s390_regs structure is used to define the elf_gregset_t.
*/
typedef struct
{
......@@ -299,6 +296,7 @@ typedef struct
unsigned long orig_gpr2;
} s390_regs;
#ifdef __KERNEL__
/*
* The pt_regs struct defines the way the registers are stored on
* the stack during a system call.
......@@ -307,11 +305,11 @@ struct pt_regs
{
psw_t psw;
unsigned long gprs[NUM_GPRS];
unsigned int acrs[NUM_ACRS];
unsigned long orig_gpr2;
unsigned short ilc;
unsigned short trap;
} __attribute__ ((packed));
};
#endif
/*
* Now for the program event recording (trace) definitions.
......
......@@ -83,14 +83,33 @@ static inline void restore_fp_regs(s390_fp_regs *fpregs)
: : "a" (fpregs), "m" (*fpregs) );
}
static inline void save_access_regs(unsigned int *acrs)
{
asm volatile ("stam 0,15,0(%0)" : : "a" (acrs) : "memory" );
}
static inline void restore_access_regs(unsigned int *acrs)
{
asm volatile ("lam 0,15,0(%0)" : : "a" (acrs) );
}
#define switch_to(prev,next,last) do { \
if (prev == next) \
break; \
save_fp_regs(&prev->thread.fp_regs); \
restore_fp_regs(&next->thread.fp_regs); \
save_access_regs(&prev->thread.acrs[0]); \
restore_access_regs(&next->thread.acrs[0]); \
prev = __switch_to(prev,next); \
} while (0)
#define prepare_arch_switch(rq, next) do { } while(0)
#define task_running(rq, p) ((rq)->curr == (p))
#define finish_arch_switch(rq, prev) do { \
set_fs(current->thread.mm_segment); \
spin_unlock_irq(&(rq)->lock); \
} while (0)
#define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment