diff options
Diffstat (limited to 'arch/s390/include/asm/processor.h')
| -rw-r--r-- | arch/s390/include/asm/processor.h | 231 | 
1 files changed, 158 insertions, 73 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 8d6f8716957..6f02d452bbe 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/processor.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Hartmut Penner (hp@de.ibm.com),   *               Martin Schwidefsky (schwidefsky@de.ibm.com)   * @@ -13,13 +11,38 @@  #ifndef __ASM_S390_PROCESSOR_H  #define __ASM_S390_PROCESSOR_H +#define CIF_MCCK_PENDING	0	/* machine check handling is pending */ +#define CIF_ASCE		1	/* user asce needs fixup / uaccess */ + +#define _CIF_MCCK_PENDING	(1<<CIF_MCCK_PENDING) +#define _CIF_ASCE		(1<<CIF_ASCE) + + +#ifndef __ASSEMBLY__ +  #include <linux/linkage.h> +#include <linux/irqflags.h>  #include <asm/cpu.h>  #include <asm/page.h>  #include <asm/ptrace.h>  #include <asm/setup.h> +#include <asm/runtime_instr.h> + +static inline void set_cpu_flag(int flag) +{ +	S390_lowcore.cpu_flags |= (1U << flag); +} + +static inline void clear_cpu_flag(int flag) +{ +	S390_lowcore.cpu_flags &= ~(1U << flag); +} + +static inline int test_cpu_flag(int flag) +{ +	return !!(S390_lowcore.cpu_flags & (1U << flag)); +} -#ifdef __KERNEL__  /*   * Default implementation of macro that returns current   * instruction pointer ("program counter"). @@ -32,38 +55,36 @@ static inline void get_cpu_id(struct cpuid *ptr)  }  extern void s390_adjust_jiffies(void); -extern void print_cpu_info(void); -extern int get_cpu_capability(unsigned int *); +extern const struct seq_operations cpuinfo_op; +extern int sysctl_ieee_emulation_warnings; +extern void execve_tail(void);  /*   * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit.   */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define TASK_SIZE		(1UL << 31) +#define TASK_MAX_SIZE		(1UL << 31)  #define TASK_UNMAPPED_BASE	(1UL << 30) -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  #define TASK_SIZE_OF(tsk)	((tsk)->mm->context.asce_limit)  #define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_31BIT) ? \  					(1UL << 30) : (1UL << 41))  #define TASK_SIZE		TASK_SIZE_OF(current) +#define TASK_MAX_SIZE		(1UL << 53) -#endif /* __s390x__ */ - -#ifdef __KERNEL__ +#endif /* CONFIG_64BIT */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define STACK_TOP		(1UL << 31)  #define STACK_TOP_MAX		(1UL << 31) -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  #define STACK_TOP		(1UL << (test_thread_flag(TIF_31BIT) ? 31:42))  #define STACK_TOP_MAX		(1UL << 42) -#endif /* __s390x__ */ - - -#endif +#endif /* CONFIG_64BIT */  #define HAVE_ARCH_PICK_MMAP_LAYOUT @@ -79,13 +100,32 @@ struct thread_struct {  	unsigned int  acrs[NUM_ACRS];          unsigned long ksp;              /* kernel stack pointer             */  	mm_segment_t mm_segment; -        unsigned long prot_addr;        /* address of protection-excep.     */ -        unsigned int trap_no; -        per_struct per_info; +	unsigned long gmap_addr;	/* address of last gmap fault. */ +	unsigned int gmap_pfault;	/* signal of a pending guest pfault */ +	struct per_regs per_user;	/* User specified PER registers */ +	struct per_event per_event;	/* Cause of the last PER trap */ +	unsigned long per_flags;	/* Flags to control debug behavior */          /* pfault_wait is used to block the process on a pfault event */  	unsigned long pfault_wait; +	struct list_head list; +	/* cpu runtime instrumentation */ +	struct runtime_instr_cb *ri_cb; +	int ri_signum; +#ifdef CONFIG_64BIT +	unsigned char trap_tdb[256];	/* Transaction abort diagnose block */ +#endif  }; +/* Flag to disable transactions. */ +#define PER_FLAG_NO_TE			1UL +/* Flag to enable random transaction aborts. */ +#define PER_FLAG_TE_ABORT_RAND		2UL +/* Flag to specify random transaction abort mode: + * - abort each transaction at a random instruction before TEND if set. + * - abort random transactions at a random instruction if cleared. + */ +#define PER_FLAG_TE_ABORT_RAND_TEND	4UL +  typedef struct thread_struct thread_struct;  /* @@ -116,19 +156,19 @@ struct stack_frame {  /*   * Do necessary setup to start up a new thread.   */ -#define start_thread(regs, new_psw, new_stackp) do {		\ -	set_fs(USER_DS);					\ -	regs->psw.mask	= psw_user_bits;			\ -	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;		\ -	regs->gprs[15]	= new_stackp;				\ +#define start_thread(regs, new_psw, new_stackp) do {			\ +	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_EA | PSW_MASK_BA;	\ +	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\ +	regs->gprs[15]	= new_stackp;					\ +	execve_tail();							\  } while (0) -#define start_thread31(regs, new_psw, new_stackp) do {		\ -	set_fs(USER_DS);					\ -	regs->psw.mask	= psw_user32_bits;			\ -	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;		\ -	regs->gprs[15]	= new_stackp;				\ -	crst_table_downgrade(current->mm, 1UL << 31);		\ +#define start_thread31(regs, new_psw, new_stackp) do {			\ +	regs->psw.mask	= PSW_USER_BITS | PSW_MASK_BA;			\ +	regs->psw.addr	= new_psw | PSW_ADDR_AMODE;			\ +	regs->gprs[15]	= new_stackp;					\ +	crst_table_downgrade(current->mm, 1UL << 31);			\ +	execve_tail();							\  } while (0)  /* Forward declaration, a strange C thing */ @@ -136,31 +176,37 @@ struct task_struct;  struct mm_struct;  struct seq_file; +#ifdef CONFIG_64BIT +extern void show_cacheinfo(struct seq_file *m); +#else +static inline void show_cacheinfo(struct seq_file *m) { } +#endif +  /* Free all resources held by a thread. */  extern void release_thread(struct task_struct *); -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - -/* Prepare to copy thread state - unlazy all lazy status */ -#define prepare_to_copy(tsk)	do { } while (0)  /*   * Return saved PC of a blocked thread.   */  extern unsigned long thread_saved_pc(struct task_struct *t); -/* - * Print register of task into buffer. Used in fs/proc/array.c. - */ -extern void task_show_regs(struct seq_file *m, struct task_struct *task); - -extern void show_code(struct pt_regs *regs); -  unsigned long get_wchan(struct task_struct *p);  #define task_pt_regs(tsk) ((struct pt_regs *) \          (task_stack_page(tsk) + THREAD_SIZE) - 1)  #define KSTK_EIP(tsk)	(task_pt_regs(tsk)->psw.addr)  #define KSTK_ESP(tsk)	(task_pt_regs(tsk)->gprs[15]) +/* Has task runtime instrumentation enabled ? */ +#define is_ri_task(tsk) (!!(tsk)->thread.ri_cb) + +static inline unsigned short stap(void) +{ +	unsigned short cpu_address; + +	asm volatile("stap %0" : "=m" (cpu_address)); +	return cpu_address; +} +  /*   * Give up the time slice of the virtual PU.   */ @@ -171,6 +217,8 @@ static inline void cpu_relax(void)  	barrier();  } +#define arch_mutex_cpu_relax()  barrier() +  static inline void psw_set_key(unsigned int key)  {  	asm volatile("spka 0(%0)" : : "d" (key)); @@ -181,7 +229,7 @@ static inline void psw_set_key(unsigned int key)   */  static inline void __load_psw(psw_t psw)  { -#ifndef __s390x__ +#ifndef CONFIG_64BIT  	asm volatile("lpsw  %0" : : "Q" (psw) : "cc");  #else  	asm volatile("lpswe %0" : : "Q" (psw) : "cc"); @@ -192,7 +240,6 @@ static inline void __load_psw(psw_t psw)   * Set PSW mask to specified value, while leaving the   * PSW addr pointing to the next instruction.   */ -  static inline void __load_psw_mask (unsigned long mask)  {  	unsigned long addr; @@ -200,7 +247,7 @@ static inline void __load_psw_mask (unsigned long mask)  	psw.mask = mask; -#ifndef __s390x__ +#ifndef CONFIG_64BIT  	asm volatile(  		"	basr	%0,0\n"  		"0:	ahi	%0,1f-0b\n" @@ -208,41 +255,52 @@ static inline void __load_psw_mask (unsigned long mask)  		"	lpsw	%1\n"  		"1:"  		: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc"); -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  	asm volatile(  		"	larl	%0,1f\n"  		"	stg	%0,%O1+8(%R1)\n"  		"	lpswe	%1\n"  		"1:"  		: "=&d" (addr), "=Q" (psw) : "Q" (psw) : "memory", "cc"); -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  } -  +  /* - * Function to stop a processor until an interruption occurred + * Rewind PSW instruction address by specified number of bytes.   */ -static inline void enabled_wait(void) +static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)  { -	__load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT | -			PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY); -} +#ifndef CONFIG_64BIT +	if (psw.addr & PSW_ADDR_AMODE) +		/* 31 bit mode */ +		return (psw.addr - ilc) | PSW_ADDR_AMODE; +	/* 24 bit mode */ +	return (psw.addr - ilc) & ((1UL << 24) - 1); +#else +	unsigned long mask; +	mask = (psw.mask & PSW_MASK_EA) ? -1UL : +	       (psw.mask & PSW_MASK_BA) ? (1UL << 31) - 1 : +					  (1UL << 24) - 1; +	return (psw.addr - ilc) & mask; +#endif +} +   /*   * Function to drop a processor into disabled wait state   */ - -static inline void ATTRIB_NORET disabled_wait(unsigned long code) +static inline void __noreturn disabled_wait(unsigned long code)  {          unsigned long ctl_buf;          psw_t dw_psw; -        dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; +	dw_psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;          dw_psw.addr = code;          /*            * Store status and then load disabled wait psw,           * the processor is dead afterwards           */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  	asm volatile(  		"	stctl	0,0,0(%2)\n"  		"	ni	0(%2),0xef\n"	/* switch off protection */ @@ -261,7 +319,7 @@ static inline void ATTRIB_NORET disabled_wait(unsigned long code)  		"	lpsw	0(%1)"  		: "=m" (ctl_buf)  		: "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc"); -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  	asm volatile(  		"	stctg	0,0,0(%2)\n"  		"	ni	4(%2),0xef\n"	/* switch off protection */ @@ -294,11 +352,26 @@ static inline void ATTRIB_NORET disabled_wait(unsigned long code)  		"	lpswe	0(%1)"  		: "=m" (ctl_buf)  		: "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0", "1"); -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  	while (1);  }  /* + * Use to set psw mask except for the first byte which + * won't be changed by this function. + */ +static inline void +__set_psw_mask(unsigned long mask) +{ +	__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8))); +} + +#define local_mcck_enable() \ +	__set_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT | PSW_MASK_MCHECK) +#define local_mcck_disable() \ +	__set_psw_mask(PSW_KERNEL_BITS | PSW_MASK_DAT) + +/*   * Basic Machine Check/Program Check Handler.   */ @@ -312,23 +385,35 @@ extern void (*s390_base_ext_handler_fn)(void);  #define ARCH_LOW_ADDRESS_LIMIT	0x7fffffffUL -#endif +extern int memcpy_real(void *, void *, size_t); +extern void memcpy_absolute(void *, void *, size_t); + +#define mem_assign_absolute(dest, val) {			\ +	__typeof__(dest) __tmp = (val);				\ +								\ +	BUILD_BUG_ON(sizeof(__tmp) != sizeof(val));		\ +	memcpy_absolute(&(dest), &__tmp, sizeof(__tmp));	\ +}  /*   * Helper macro for exception table entries   */ -#ifndef __s390x__ -#define EX_TABLE(_fault,_target)			\ -	".section __ex_table,\"a\"\n"			\ -	"	.align 4\n"				\ -	"	.long  " #_fault "," #_target "\n"	\ -	".previous\n" -#else -#define EX_TABLE(_fault,_target)			\ -	".section __ex_table,\"a\"\n"			\ -	"	.align 8\n"				\ -	"	.quad  " #_fault "," #_target "\n"	\ +#define EX_TABLE(_fault, _target)	\ +	".section __ex_table,\"a\"\n"	\ +	".align	4\n"			\ +	".long	(" #_fault ") - .\n"	\ +	".long	(" #_target ") - .\n"	\  	".previous\n" -#endif -#endif                                 /* __ASM_S390_PROCESSOR_H           */ +#else /* __ASSEMBLY__ */ + +#define EX_TABLE(_fault, _target)	\ +	.section __ex_table,"a"	;	\ +	.align	4 ;			\ +	.long	(_fault) - . ;		\ +	.long	(_target) - . ;		\ +	.previous + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_S390_PROCESSOR_H */  | 
