diff options
Diffstat (limited to 'arch/s390/include')
173 files changed, 8749 insertions, 5080 deletions
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild index 287d7bbb6d3..57892a8a905 100644 --- a/arch/s390/include/asm/Kbuild +++ b/arch/s390/include/asm/Kbuild @@ -1,15 +1,7 @@ -include include/asm-generic/Kbuild.asm -header-y += chpid.h -header-y += chsc.h -header-y += cmb.h -header-y += dasd.h -header-y += debug.h -header-y += kvm_virtio.h -header-y += monwriter.h -header-y += qeth.h -header-y += schid.h -header-y += tape390.h -header-y += ucontext.h -header-y += vtoc.h -header-y += zcrypt.h + +generic-y += clkdev.h +generic-y += hash.h +generic-y += mcs_spinlock.h +generic-y += preempt.h +generic-y += trace_clock.h diff --git a/arch/s390/include/asm/airq.h b/arch/s390/include/asm/airq.h index 1ac80d6b058..bd93ff6661b 100644 --- a/arch/s390/include/asm/airq.h +++ b/arch/s390/include/asm/airq.h @@ -1,7 +1,5 @@  /* - *  include/asm-s390/airq.h - * - *    Copyright IBM Corp. 2002,2007 + *    Copyright IBM Corp. 2002, 2007   *    Author(s): Ingo Adlung <adlung@de.ibm.com>   *		 Cornelia Huck <cornelia.huck@de.ibm.com>   *		 Arnd Bergmann <arndb@de.ibm.com> @@ -11,9 +9,95 @@  #ifndef _ASM_S390_AIRQ_H  #define _ASM_S390_AIRQ_H -typedef void (*adapter_int_handler_t)(void *, void *); +#include <linux/bit_spinlock.h> -void *s390_register_adapter_interrupt(adapter_int_handler_t, void *, u8); -void s390_unregister_adapter_interrupt(void *, u8); +struct airq_struct { +	struct hlist_node list;		/* Handler queueing. */ +	void (*handler)(struct airq_struct *);	/* Thin-interrupt handler */ +	u8 *lsi_ptr;			/* Local-Summary-Indicator pointer */ +	u8 lsi_mask;			/* Local-Summary-Indicator mask */ +	u8 isc;				/* Interrupt-subclass */ +	u8 flags; +}; + +#define AIRQ_PTR_ALLOCATED	0x01 + +int register_adapter_interrupt(struct airq_struct *airq); +void unregister_adapter_interrupt(struct airq_struct *airq); + +/* Adapter interrupt bit vector */ +struct airq_iv { +	unsigned long *vector;	/* Adapter interrupt bit vector */ +	unsigned long *avail;	/* Allocation bit mask for the bit vector */ +	unsigned long *bitlock;	/* Lock bit mask for the bit vector */ +	unsigned long *ptr;	/* Pointer associated with each bit */ +	unsigned int *data;	/* 32 bit value associated with each bit */ +	unsigned long bits;	/* Number of bits in the vector */ +	unsigned long end;	/* Number of highest allocated bit + 1 */ +	spinlock_t lock;	/* Lock to protect alloc & free */ +}; + +#define AIRQ_IV_ALLOC	1	/* Use an allocation bit mask */ +#define AIRQ_IV_BITLOCK	2	/* Allocate the lock bit mask */ +#define AIRQ_IV_PTR	4	/* Allocate the ptr array */ +#define AIRQ_IV_DATA	8	/* Allocate the data array */ + +struct airq_iv *airq_iv_create(unsigned long bits, unsigned long flags); +void airq_iv_release(struct airq_iv *iv); +unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num); +void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num); +unsigned long airq_iv_scan(struct airq_iv *iv, unsigned long start, +			   unsigned long end); + +static inline unsigned long airq_iv_alloc_bit(struct airq_iv *iv) +{ +	return airq_iv_alloc(iv, 1); +} + +static inline void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) +{ +	airq_iv_free(iv, bit, 1); +} + +static inline unsigned long airq_iv_end(struct airq_iv *iv) +{ +	return iv->end; +} + +static inline void airq_iv_lock(struct airq_iv *iv, unsigned long bit) +{ +	const unsigned long be_to_le = BITS_PER_LONG - 1; +	bit_spin_lock(bit ^ be_to_le, iv->bitlock); +} + +static inline void airq_iv_unlock(struct airq_iv *iv, unsigned long bit) +{ +	const unsigned long be_to_le = BITS_PER_LONG - 1; +	bit_spin_unlock(bit ^ be_to_le, iv->bitlock); +} + +static inline void airq_iv_set_data(struct airq_iv *iv, unsigned long bit, +				    unsigned int data) +{ +	iv->data[bit] = data; +} + +static inline unsigned int airq_iv_get_data(struct airq_iv *iv, +					    unsigned long bit) +{ +	return iv->data[bit]; +} + +static inline void airq_iv_set_ptr(struct airq_iv *iv, unsigned long bit, +				   unsigned long ptr) +{ +	iv->ptr[bit] = ptr; +} + +static inline unsigned long airq_iv_get_ptr(struct airq_iv *iv, +					    unsigned long bit) +{ +	return iv->ptr[bit]; +}  #endif /* _ASM_S390_AIRQ_H */ diff --git a/arch/s390/include/asm/appldata.h b/arch/s390/include/asm/appldata.h index 79283dac828..32a70598715 100644 --- a/arch/s390/include/asm/appldata.h +++ b/arch/s390/include/asm/appldata.h @@ -1,7 +1,5 @@  /* - * include/asm-s390/appldata.h - * - * Copyright (C) IBM Corp. 2006 + * Copyright IBM Corp. 2006   *   * Author(s): Melissa Howland <melissah@us.ibm.com>   */ @@ -72,7 +70,7 @@ static inline int appldata_asm(struct appldata_product_id *id,  	int ry;  	if (!MACHINE_IS_VM) -		return -ENOSYS; +		return -EOPNOTSUPP;  	parm_list.diag = 0xdc;  	parm_list.function = fn;  	parm_list.parlist_length = sizeof(parm_list); diff --git a/arch/s390/include/asm/atomic.h b/arch/s390/include/asm/atomic.h index 76daea11718..fa934fe080c 100644 --- a/arch/s390/include/asm/atomic.h +++ b/arch/s390/include/asm/atomic.h @@ -1,79 +1,131 @@ -#ifndef __ARCH_S390_ATOMIC__ -#define __ARCH_S390_ATOMIC__ -  /* - * Copyright 1999,2009 IBM Corp. + * Copyright IBM Corp. 1999, 2009   * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,   *	      Denis Joseph Barrow,   *	      Arnd Bergmann <arndb@de.ibm.com>,   *   * Atomic operations that C can't guarantee us.   * Useful for resource counting etc. - * s390 uses 'Compare And Swap' for atomicity in SMP enviroment. + * s390 uses 'Compare And Swap' for atomicity in SMP environment.   *   */ +#ifndef __ARCH_S390_ATOMIC__ +#define __ARCH_S390_ATOMIC__ +  #include <linux/compiler.h>  #include <linux/types.h> -#include <asm/system.h> +#include <asm/barrier.h> +#include <asm/cmpxchg.h>  #define ATOMIC_INIT(i)  { (i) } -#define __CS_LOOP(ptr, op_val, op_string) ({				\ +#define __ATOMIC_NO_BARRIER	"\n" + +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES + +#define __ATOMIC_OR	"lao" +#define __ATOMIC_AND	"lan" +#define __ATOMIC_ADD	"laa" +#define __ATOMIC_BARRIER "bcr	14,0\n" + +#define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier)		\ +({									\ +	int old_val;							\ +									\ +	typecheck(atomic_t *, ptr);					\ +	asm volatile(							\ +		__barrier						\ +		op_string "	%0,%2,%1\n"				\ +		__barrier						\ +		: "=d" (old_val), "+Q" ((ptr)->counter)			\ +		: "d" (op_val)						\ +		: "cc", "memory");					\ +	old_val;							\ +}) + +#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ + +#define __ATOMIC_OR	"or" +#define __ATOMIC_AND	"nr" +#define __ATOMIC_ADD	"ar" +#define __ATOMIC_BARRIER "\n" + +#define __ATOMIC_LOOP(ptr, op_val, op_string, __barrier)		\ +({									\  	int old_val, new_val;						\ +									\ +	typecheck(atomic_t *, ptr);					\  	asm volatile(							\  		"	l	%0,%2\n"				\  		"0:	lr	%1,%0\n"				\  		op_string "	%1,%3\n"				\  		"	cs	%0,%1,%2\n"				\  		"	jl	0b"					\ -		: "=&d" (old_val), "=&d" (new_val),			\ -		  "=Q" (((atomic_t *)(ptr))->counter)			\ -		: "d" (op_val),	 "Q" (((atomic_t *)(ptr))->counter)	\ +		: "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\ +		: "d" (op_val)						\  		: "cc", "memory");					\ -	new_val;							\ +	old_val;							\  }) +#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +  static inline int atomic_read(const atomic_t *v)  { -	barrier(); -	return v->counter; +	int c; + +	asm volatile( +		"	l	%0,%1\n" +		: "=d" (c) : "Q" (v->counter)); +	return c;  }  static inline void atomic_set(atomic_t *v, int i)  { -	v->counter = i; -	barrier(); +	asm volatile( +		"	st	%1,%0\n" +		: "=Q" (v->counter) : "d" (i));  }  static inline int atomic_add_return(int i, atomic_t *v)  { -	return __CS_LOOP(v, i, "ar"); +	return __ATOMIC_LOOP(v, i, __ATOMIC_ADD, __ATOMIC_BARRIER) + i;  } -#define atomic_add(_i, _v)		atomic_add_return(_i, _v) -#define atomic_add_negative(_i, _v)	(atomic_add_return(_i, _v) < 0) -#define atomic_inc(_v)			atomic_add_return(1, _v) -#define atomic_inc_return(_v)		atomic_add_return(1, _v) -#define atomic_inc_and_test(_v)		(atomic_add_return(1, _v) == 0) -static inline int atomic_sub_return(int i, atomic_t *v) +static inline void atomic_add(int i, atomic_t *v)  { -	return __CS_LOOP(v, i, "sr"); +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +	if (__builtin_constant_p(i) && (i > -129) && (i < 128)) { +		asm volatile( +			"asi	%0,%1\n" +			: "+Q" (v->counter) +			: "i" (i) +			: "cc", "memory"); +		return; +	} +#endif +	__ATOMIC_LOOP(v, i, __ATOMIC_ADD, __ATOMIC_NO_BARRIER);  } -#define atomic_sub(_i, _v)		atomic_sub_return(_i, _v) + +#define atomic_add_negative(_i, _v)	(atomic_add_return(_i, _v) < 0) +#define atomic_inc(_v)			atomic_add(1, _v) +#define atomic_inc_return(_v)		atomic_add_return(1, _v) +#define atomic_inc_and_test(_v)		(atomic_add_return(1, _v) == 0) +#define atomic_sub(_i, _v)		atomic_add(-(int)(_i), _v) +#define atomic_sub_return(_i, _v)	atomic_add_return(-(int)(_i), _v)  #define atomic_sub_and_test(_i, _v)	(atomic_sub_return(_i, _v) == 0) -#define atomic_dec(_v)			atomic_sub_return(1, _v) +#define atomic_dec(_v)			atomic_sub(1, _v)  #define atomic_dec_return(_v)		atomic_sub_return(1, _v)  #define atomic_dec_and_test(_v)		(atomic_sub_return(1, _v) == 0) -static inline void atomic_clear_mask(unsigned long mask, atomic_t *v) +static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)  { -	__CS_LOOP(v, ~mask, "nr"); +	__ATOMIC_LOOP(v, ~mask, __ATOMIC_AND, __ATOMIC_NO_BARRIER);  } -static inline void atomic_set_mask(unsigned long mask, atomic_t *v) +static inline void atomic_set_mask(unsigned int mask, atomic_t *v)  { -	__CS_LOOP(v, mask, "or"); +	__ATOMIC_LOOP(v, mask, __ATOMIC_OR, __ATOMIC_NO_BARRIER);  }  #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) @@ -82,13 +134,13 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)  {  	asm volatile(  		"	cs	%0,%2,%1" -		: "+d" (old), "=Q" (v->counter) -		: "d" (new), "Q" (v->counter) +		: "+d" (old), "+Q" (v->counter) +		: "d" (new)  		: "cc", "memory");  	return old;  } -static inline int atomic_add_unless(atomic_t *v, int a, int u) +static inline int __atomic_add_unless(atomic_t *v, int a, int u)  {  	int c, old;  	c = atomic_read(v); @@ -100,62 +152,111 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)  			break;  		c = old;  	} -	return c != u; +	return c;  } -#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) -#undef __CS_LOOP +#undef __ATOMIC_LOOP  #define ATOMIC64_INIT(i)  { (i) }  #ifdef CONFIG_64BIT -#define __CSG_LOOP(ptr, op_val, op_string) ({				\ +#define __ATOMIC64_NO_BARRIER	"\n" + +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES + +#define __ATOMIC64_OR	"laog" +#define __ATOMIC64_AND	"lang" +#define __ATOMIC64_ADD	"laag" +#define __ATOMIC64_BARRIER "bcr	14,0\n" + +#define __ATOMIC64_LOOP(ptr, op_val, op_string, __barrier)		\ +({									\ +	long long old_val;						\ +									\ +	typecheck(atomic64_t *, ptr);					\ +	asm volatile(							\ +		__barrier						\ +		op_string "	%0,%2,%1\n"				\ +		__barrier						\ +		: "=d" (old_val), "+Q" ((ptr)->counter)			\ +		: "d" (op_val)						\ +		: "cc", "memory");					\ +	old_val;							\ +}) + +#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ + +#define __ATOMIC64_OR	"ogr" +#define __ATOMIC64_AND	"ngr" +#define __ATOMIC64_ADD	"agr" +#define __ATOMIC64_BARRIER "\n" + +#define __ATOMIC64_LOOP(ptr, op_val, op_string, __barrier)		\ +({									\  	long long old_val, new_val;					\ +									\ +	typecheck(atomic64_t *, ptr);					\  	asm volatile(							\  		"	lg	%0,%2\n"				\  		"0:	lgr	%1,%0\n"				\  		op_string "	%1,%3\n"				\  		"	csg	%0,%1,%2\n"				\  		"	jl	0b"					\ -		: "=&d" (old_val), "=&d" (new_val),			\ -		  "=Q" (((atomic_t *)(ptr))->counter)			\ -		: "d" (op_val),	"Q" (((atomic_t *)(ptr))->counter)	\ +		: "=&d" (old_val), "=&d" (new_val), "+Q" ((ptr)->counter)\ +		: "d" (op_val)						\  		: "cc", "memory");					\ -	new_val;							\ +	old_val;							\  }) +#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +  static inline long long atomic64_read(const atomic64_t *v)  { -	barrier(); -	return v->counter; +	long long c; + +	asm volatile( +		"	lg	%0,%1\n" +		: "=d" (c) : "Q" (v->counter)); +	return c;  }  static inline void atomic64_set(atomic64_t *v, long long i)  { -	v->counter = i; -	barrier(); +	asm volatile( +		"	stg	%1,%0\n" +		: "=Q" (v->counter) : "d" (i));  }  static inline long long atomic64_add_return(long long i, atomic64_t *v)  { -	return __CSG_LOOP(v, i, "agr"); +	return __ATOMIC64_LOOP(v, i, __ATOMIC64_ADD, __ATOMIC64_BARRIER) + i;  } -static inline long long atomic64_sub_return(long long i, atomic64_t *v) +static inline void atomic64_add(long long i, atomic64_t *v)  { -	return __CSG_LOOP(v, i, "sgr"); +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +	if (__builtin_constant_p(i) && (i > -129) && (i < 128)) { +		asm volatile( +			"agsi	%0,%1\n" +			: "+Q" (v->counter) +			: "i" (i) +			: "cc", "memory"); +		return; +	} +#endif +	__ATOMIC64_LOOP(v, i, __ATOMIC64_ADD, __ATOMIC64_NO_BARRIER);  }  static inline void atomic64_clear_mask(unsigned long mask, atomic64_t *v)  { -	__CSG_LOOP(v, ~mask, "ngr"); +	__ATOMIC64_LOOP(v, ~mask, __ATOMIC64_AND, __ATOMIC64_NO_BARRIER);  }  static inline void atomic64_set_mask(unsigned long mask, atomic64_t *v)  { -	__CSG_LOOP(v, mask, "ogr"); +	__ATOMIC64_LOOP(v, mask, __ATOMIC64_OR, __ATOMIC64_NO_BARRIER);  }  #define atomic64_xchg(v, new) (xchg(&((v)->counter), new)) @@ -165,13 +266,13 @@ static inline long long atomic64_cmpxchg(atomic64_t *v,  {  	asm volatile(  		"	csg	%0,%2,%1" -		: "+d" (old), "=Q" (v->counter) -		: "d" (new), "Q" (v->counter) +		: "+d" (old), "+Q" (v->counter) +		: "d" (new)  		: "cc", "memory");  	return old;  } -#undef __CSG_LOOP +#undef __ATOMIC64_LOOP  #else /* CONFIG_64BIT */ @@ -207,8 +308,8 @@ static inline long long atomic64_xchg(atomic64_t *v, long long new)  		"	lm	%0,%N0,%1\n"  		"0:	cds	%0,%2,%1\n"  		"	jl	0b\n" -		: "=&d" (rp_old), "=Q" (v->counter) -		: "d" (rp_new), "Q" (v->counter) +		: "=&d" (rp_old), "+Q" (v->counter) +		: "d" (rp_new)  		: "cc");  	return rp_old.pair;  } @@ -221,8 +322,8 @@ static inline long long atomic64_cmpxchg(atomic64_t *v,  	asm volatile(  		"	cds	%0,%2,%1" -		: "+&d" (rp_old), "=Q" (v->counter) -		: "d" (rp_new), "Q" (v->counter) +		: "+&d" (rp_old), "+Q" (v->counter) +		: "d" (rp_new)  		: "cc");  	return rp_old.pair;  } @@ -239,17 +340,6 @@ static inline long long atomic64_add_return(long long i, atomic64_t *v)  	return new;  } -static inline long long atomic64_sub_return(long long i, atomic64_t *v) -{ -	long long old, new; - -	do { -		old = atomic64_read(v); -		new = old - i; -	} while (atomic64_cmpxchg(v, old, new) != old); -	return new; -} -  static inline void atomic64_set_mask(unsigned long long mask, atomic64_t *v)  {  	long long old, new; @@ -270,9 +360,14 @@ static inline void atomic64_clear_mask(unsigned long long mask, atomic64_t *v)  	} while (atomic64_cmpxchg(v, old, new) != old);  } +static inline void atomic64_add(long long i, atomic64_t *v) +{ +	atomic64_add_return(i, v); +} +  #endif /* CONFIG_64BIT */ -static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u) +static inline int atomic64_add_unless(atomic64_t *v, long long i, long long u)  {  	long long c, old; @@ -280,7 +375,7 @@ static inline int atomic64_add_unless(atomic64_t *v, long long a, long long u)  	for (;;) {  		if (unlikely(c == u))  			break; -		old = atomic64_cmpxchg(v, c, c + a); +		old = atomic64_cmpxchg(v, c, c + i);  		if (likely(old == c))  			break;  		c = old; @@ -305,23 +400,16 @@ static inline long long atomic64_dec_if_positive(atomic64_t *v)  	return dec;  } -#define atomic64_add(_i, _v)		atomic64_add_return(_i, _v)  #define atomic64_add_negative(_i, _v)	(atomic64_add_return(_i, _v) < 0) -#define atomic64_inc(_v)		atomic64_add_return(1, _v) +#define atomic64_inc(_v)		atomic64_add(1, _v)  #define atomic64_inc_return(_v)		atomic64_add_return(1, _v)  #define atomic64_inc_and_test(_v)	(atomic64_add_return(1, _v) == 0) -#define atomic64_sub(_i, _v)		atomic64_sub_return(_i, _v) +#define atomic64_sub_return(_i, _v)	atomic64_add_return(-(long long)(_i), _v) +#define atomic64_sub(_i, _v)		atomic64_add(-(long long)(_i), _v)  #define atomic64_sub_and_test(_i, _v)	(atomic64_sub_return(_i, _v) == 0) -#define atomic64_dec(_v)		atomic64_sub_return(1, _v) +#define atomic64_dec(_v)		atomic64_sub(1, _v)  #define atomic64_dec_return(_v)		atomic64_sub_return(1, _v)  #define atomic64_dec_and_test(_v)	(atomic64_sub_return(1, _v) == 0)  #define atomic64_inc_not_zero(v)	atomic64_add_unless((v), 1, 0) -#define smp_mb__before_atomic_dec()	smp_mb() -#define smp_mb__after_atomic_dec()	smp_mb() -#define smp_mb__before_atomic_inc()	smp_mb() -#define smp_mb__after_atomic_inc()	smp_mb() - -#include <asm-generic/atomic-long.h> -  #endif /* __ARCH_S390_ATOMIC__  */ diff --git a/arch/s390/include/asm/barrier.h b/arch/s390/include/asm/barrier.h new file mode 100644 index 00000000000..19ff956b752 --- /dev/null +++ b/arch/s390/include/asm/barrier.h @@ -0,0 +1,51 @@ +/* + * Copyright IBM Corp. 1999, 2009 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#ifndef __ASM_BARRIER_H +#define __ASM_BARRIER_H + +/* + * Force strict CPU ordering. + * And yes, this is required on UP too when we're talking + * to devices. + */ + +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES +/* Fast-BCR without checkpoint synchronization */ +#define mb() do {  asm volatile("bcr 14,0" : : : "memory"); } while (0) +#else +#define mb() do {  asm volatile("bcr 15,0" : : : "memory"); } while (0) +#endif + +#define rmb()				mb() +#define wmb()				mb() +#define read_barrier_depends()		do { } while(0) +#define smp_mb()			mb() +#define smp_rmb()			rmb() +#define smp_wmb()			wmb() +#define smp_read_barrier_depends()	read_barrier_depends() + +#define smp_mb__before_atomic()		smp_mb() +#define smp_mb__after_atomic()		smp_mb() + +#define set_mb(var, value)		do { var = value; mb(); } while (0) + +#define smp_store_release(p, v)						\ +do {									\ +	compiletime_assert_atomic_type(*p);				\ +	barrier();							\ +	ACCESS_ONCE(*p) = (v);						\ +} while (0) + +#define smp_load_acquire(p)						\ +({									\ +	typeof(*p) ___p1 = ACCESS_ONCE(*p);				\ +	compiletime_assert_atomic_type(*p);				\ +	barrier();							\ +	___p1;								\ +}) + +#endif /* __ASM_BARRIER_H */ diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h index 2e05972c508..52054247767 100644 --- a/arch/s390/include/asm/bitops.h +++ b/arch/s390/include/asm/bitops.h @@ -1,579 +1,397 @@ -#ifndef _S390_BITOPS_H -#define _S390_BITOPS_H -  /* - *  include/asm-s390/bitops.h + *    Copyright IBM Corp. 1999,2013 + * + *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, + * + * The description below was taken in large parts from the powerpc + * bitops header file: + * Within a word, bits are numbered LSB first.  Lot's of places make + * this assumption by directly testing bits with (val & (1<<nr)). + * This can cause confusion for large (> 1 word) bitmaps on a + * big-endian system because, unlike little endian, the number of each + * bit depends on the word size. + * + * The bitop functions are defined to work on unsigned longs, so for an + * s390x system the bits end up numbered: + *   |63..............0|127............64|191...........128|255...........192| + * and on s390: + *   |31.....0|63....32|95....64|127...96|159..128|191..160|223..192|255..224|   * - *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation - *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * There are a few little-endian macros used mostly for filesystem + * bitmaps, these work on similar bit arrays layouts, but + * byte-oriented: + *   |7...0|15...8|23...16|31...24|39...32|47...40|55...48|63...56|   * - *  Derived from "include/asm-i386/bitops.h" - *    Copyright (C) 1992, Linus Torvalds + * The main difference is that bit 3-5 (64b) or 3-4 (32b) in the bit + * number field needs to be reversed compared to the big-endian bit + * fields. This can be achieved by XOR with 0x38 (64b) or 0x18 (32b). + * + * We also have special functions which work with an MSB0 encoding: + * on an s390x system the bits are numbered: + *   |0..............63|64............127|128...........191|192...........255| + * and on s390: + *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255| + * + * The main difference is that bit 0-63 (64b) or 0-31 (32b) in the bit + * number field needs to be reversed compared to the LSB0 encoded bit + * fields. This can be achieved by XOR with 0x3f (64b) or 0x1f (32b).   *   */ -#ifdef __KERNEL__ +#ifndef _S390_BITOPS_H +#define _S390_BITOPS_H  #ifndef _LINUX_BITOPS_H  #error only <linux/bitops.h> can be included directly  #endif +#include <linux/typecheck.h>  #include <linux/compiler.h> +#include <asm/barrier.h> -/* - * 32 bit bitops format: - * bit 0 is the LSB of *addr; bit 31 is the MSB of *addr; - * bit 32 is the LSB of *(addr+4). That combined with the - * big endian byte order on S390 give the following bit - * order in memory: - *    1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 \ - *    0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 - * after that follows the next long with bit numbers - *    3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 - *    2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20 - * The reason for this bit ordering is the fact that - * in the architecture independent code bits operations - * of the form "flags |= (1 << bitnr)" are used INTERMIXED - * with operation of the form "set_bit(bitnr, flags)". - * - * 64 bit bitops format: - * bit 0 is the LSB of *addr; bit 63 is the MSB of *addr; - * bit 64 is the LSB of *(addr+8). That combined with the - * big endian byte order on S390 give the following bit - * order in memory: - *    3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30 - *    2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20 - *    1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10 - *    0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00 - * after that follows the next long with bit numbers - *    7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70 - *    6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60 - *    5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50 - *    4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40 - * The reason for this bit ordering is the fact that - * in the architecture independent code bits operations - * of the form "flags |= (1 << bitnr)" are used INTERMIXED - * with operation of the form "set_bit(bitnr, flags)". - */ - -/* bitmap tables from arch/s390/kernel/bitmap.c */ -extern const char _oi_bitmap[]; -extern const char _ni_bitmap[]; -extern const char _zb_findmap[]; -extern const char _sb_findmap[]; +#define __BITOPS_NO_BARRIER	"\n" -#ifndef __s390x__ +#ifndef CONFIG_64BIT -#define __BITOPS_ALIGN		3 -#define __BITOPS_WORDSIZE	32  #define __BITOPS_OR		"or"  #define __BITOPS_AND		"nr"  #define __BITOPS_XOR		"xr" +#define __BITOPS_BARRIER	"\n" -#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\ +#define __BITOPS_LOOP(__addr, __val, __op_string, __barrier)	\ +({								\ +	unsigned long __old, __new;				\ +								\ +	typecheck(unsigned long *, (__addr));			\  	asm volatile(						\  		"	l	%0,%2\n"			\  		"0:	lr	%1,%0\n"			\  		__op_string "	%1,%3\n"			\  		"	cs	%0,%1,%2\n"			\  		"	jl	0b"				\ -		: "=&d" (__old), "=&d" (__new),			\ -		  "=Q" (*(unsigned long *) __addr)		\ -		: "d" (__val), "Q" (*(unsigned long *) __addr)	\ -		: "cc"); +		: "=&d" (__old), "=&d" (__new), "+Q" (*(__addr))\ +		: "d" (__val)					\ +		: "cc", "memory");				\ +	__old;							\ +}) + +#else /* CONFIG_64BIT */ + +#ifdef CONFIG_HAVE_MARCH_Z196_FEATURES + +#define __BITOPS_OR		"laog" +#define __BITOPS_AND		"lang" +#define __BITOPS_XOR		"laxg" +#define __BITOPS_BARRIER	"bcr	14,0\n" + +#define __BITOPS_LOOP(__addr, __val, __op_string, __barrier)	\ +({								\ +	unsigned long __old;					\ +								\ +	typecheck(unsigned long *, (__addr));			\ +	asm volatile(						\ +		__barrier					\ +		__op_string "	%0,%2,%1\n"			\ +		__barrier					\ +		: "=d" (__old),	"+Q" (*(__addr))		\ +		: "d" (__val)					\ +		: "cc", "memory");				\ +	__old;							\ +}) -#else /* __s390x__ */ +#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ -#define __BITOPS_ALIGN		7 -#define __BITOPS_WORDSIZE	64  #define __BITOPS_OR		"ogr"  #define __BITOPS_AND		"ngr"  #define __BITOPS_XOR		"xgr" +#define __BITOPS_BARRIER	"\n" -#define __BITOPS_LOOP(__old, __new, __addr, __val, __op_string)	\ +#define __BITOPS_LOOP(__addr, __val, __op_string, __barrier)	\ +({								\ +	unsigned long __old, __new;				\ +								\ +	typecheck(unsigned long *, (__addr));			\  	asm volatile(						\  		"	lg	%0,%2\n"			\  		"0:	lgr	%1,%0\n"			\  		__op_string "	%1,%3\n"			\  		"	csg	%0,%1,%2\n"			\  		"	jl	0b"				\ -		: "=&d" (__old), "=&d" (__new),			\ -		  "=Q" (*(unsigned long *) __addr)		\ -		: "d" (__val), "Q" (*(unsigned long *) __addr)	\ -		: "cc"); +		: "=&d" (__old), "=&d" (__new), "+Q" (*(__addr))\ +		: "d" (__val)					\ +		: "cc", "memory");				\ +	__old;							\ +}) -#endif /* __s390x__ */ +#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ -#define __BITOPS_WORDS(bits) (((bits)+__BITOPS_WORDSIZE-1)/__BITOPS_WORDSIZE) -#define __BITOPS_BARRIER() asm volatile("" : : : "memory") +#endif /* CONFIG_64BIT */ -#ifdef CONFIG_SMP -/* - * SMP safe set_bit routine based on compare and swap (CS) - */ -static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr) +#define __BITOPS_WORDS(bits) (((bits) + BITS_PER_LONG - 1) / BITS_PER_LONG) + +static inline unsigned long * +__bitops_word(unsigned long nr, volatile unsigned long *ptr)  { -        unsigned long addr, old, new, mask; - -	addr = (unsigned long) ptr; -	/* calculate address for CS */ -	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; -	/* make OR mask */ -	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1)); -	/* Do the atomic update. */ -	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR); +	unsigned long addr; + +	addr = (unsigned long)ptr + ((nr ^ (nr & (BITS_PER_LONG - 1))) >> 3); +	return (unsigned long *)addr;  } -/* - * SMP safe clear_bit routine based on compare and swap (CS) - */ -static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) +static inline unsigned char * +__bitops_byte(unsigned long nr, volatile unsigned long *ptr)  { -        unsigned long addr, old, new, mask; - -	addr = (unsigned long) ptr; -	/* calculate address for CS */ -	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; -	/* make AND mask */ -	mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1))); -	/* Do the atomic update. */ -	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND); +	return ((unsigned char *)ptr) + ((nr ^ (BITS_PER_LONG - 8)) >> 3);  } -/* - * SMP safe change_bit routine based on compare and swap (CS) - */ -static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr) +static inline void set_bit(unsigned long nr, volatile unsigned long *ptr)  { -        unsigned long addr, old, new, mask; - -	addr = (unsigned long) ptr; -	/* calculate address for CS */ -	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; -	/* make XOR mask */ -	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1)); -	/* Do the atomic update. */ -	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR); +	unsigned long *addr = __bitops_word(nr, ptr); +	unsigned long mask; + +#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES +	if (__builtin_constant_p(nr)) { +		unsigned char *caddr = __bitops_byte(nr, ptr); + +		asm volatile( +			"oi	%0,%b1\n" +			: "+Q" (*caddr) +			: "i" (1 << (nr & 7)) +			: "cc", "memory"); +		return; +	} +#endif +	mask = 1UL << (nr & (BITS_PER_LONG - 1)); +	__BITOPS_LOOP(addr, mask, __BITOPS_OR, __BITOPS_NO_BARRIER);  } -/* - * SMP safe test_and_set_bit routine based on compare and swap (CS) - */ -static inline int -test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr) +static inline void clear_bit(unsigned long nr, volatile unsigned long *ptr)  { -        unsigned long addr, old, new, mask; - -	addr = (unsigned long) ptr; -	/* calculate address for CS */ -	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; -	/* make OR/test mask */ -	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1)); -	/* Do the atomic update. */ -	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_OR); -	__BITOPS_BARRIER(); -	return (old & mask) != 0; +	unsigned long *addr = __bitops_word(nr, ptr); +	unsigned long mask; + +#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES +	if (__builtin_constant_p(nr)) { +		unsigned char *caddr = __bitops_byte(nr, ptr); + +		asm volatile( +			"ni	%0,%b1\n" +			: "+Q" (*caddr) +			: "i" (~(1 << (nr & 7))) +			: "cc", "memory"); +		return; +	} +#endif +	mask = ~(1UL << (nr & (BITS_PER_LONG - 1))); +	__BITOPS_LOOP(addr, mask, __BITOPS_AND, __BITOPS_NO_BARRIER);  } -/* - * SMP safe test_and_clear_bit routine based on compare and swap (CS) - */ -static inline int -test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) +static inline void change_bit(unsigned long nr, volatile unsigned long *ptr)  { -        unsigned long addr, old, new, mask; - -	addr = (unsigned long) ptr; -	/* calculate address for CS */ -	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; -	/* make AND/test mask */ -	mask = ~(1UL << (nr & (__BITOPS_WORDSIZE - 1))); -	/* Do the atomic update. */ -	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_AND); -	__BITOPS_BARRIER(); -	return (old ^ new) != 0; +	unsigned long *addr = __bitops_word(nr, ptr); +	unsigned long mask; + +#ifdef CONFIG_HAVE_MARCH_ZEC12_FEATURES +	if (__builtin_constant_p(nr)) { +		unsigned char *caddr = __bitops_byte(nr, ptr); + +		asm volatile( +			"xi	%0,%b1\n" +			: "+Q" (*caddr) +			: "i" (1 << (nr & 7)) +			: "cc", "memory"); +		return; +	} +#endif +	mask = 1UL << (nr & (BITS_PER_LONG - 1)); +	__BITOPS_LOOP(addr, mask, __BITOPS_XOR, __BITOPS_NO_BARRIER);  } -/* - * SMP safe test_and_change_bit routine based on compare and swap (CS)  - */  static inline int -test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr) +test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)  { -        unsigned long addr, old, new, mask; - -	addr = (unsigned long) ptr; -	/* calculate address for CS */ -	addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; -	/* make XOR/test mask */ -	mask = 1UL << (nr & (__BITOPS_WORDSIZE - 1)); -	/* Do the atomic update. */ -	__BITOPS_LOOP(old, new, addr, mask, __BITOPS_XOR); -	__BITOPS_BARRIER(); +	unsigned long *addr = __bitops_word(nr, ptr); +	unsigned long old, mask; + +	mask = 1UL << (nr & (BITS_PER_LONG - 1)); +	old = __BITOPS_LOOP(addr, mask, __BITOPS_OR, __BITOPS_BARRIER);  	return (old & mask) != 0;  } -#endif /* CONFIG_SMP */ -/* - * fast, non-SMP set_bit routine - */ -static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr) +static inline int +test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned long *addr = __bitops_word(nr, ptr); +	unsigned long old, mask; -	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	asm volatile( -		"	oc	%O0(1,%R0),%1" -		: "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" ); +	mask = ~(1UL << (nr & (BITS_PER_LONG - 1))); +	old = __BITOPS_LOOP(addr, mask, __BITOPS_AND, __BITOPS_BARRIER); +	return (old & ~mask) != 0;  } -static inline void  -__constant_set_bit(const unsigned long nr, volatile unsigned long *ptr) +static inline int +test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned long *addr = __bitops_word(nr, ptr); +	unsigned long old, mask; -	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	*(unsigned char *) addr |= 1 << (nr & 7); +	mask = 1UL << (nr & (BITS_PER_LONG - 1)); +	old = __BITOPS_LOOP(addr, mask, __BITOPS_XOR, __BITOPS_BARRIER); +	return (old & mask) != 0;  } -#define set_bit_simple(nr,addr) \ -(__builtin_constant_p((nr)) ? \ - __constant_set_bit((nr),(addr)) : \ - __set_bit((nr),(addr)) ) - -/* - * fast, non-SMP clear_bit routine - */ -static inline void  -__clear_bit(unsigned long nr, volatile unsigned long *ptr) +static inline void __set_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned char *addr = __bitops_byte(nr, ptr); -	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	asm volatile( -		"	nc	%O0(1,%R0),%1" -		: "=Q" (*(char *) addr) : "Q" (_ni_bitmap[nr & 7]) : "cc" ); +	*addr |= 1 << (nr & 7);  }  static inline void  -__constant_clear_bit(const unsigned long nr, volatile unsigned long *ptr) +__clear_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned char *addr = __bitops_byte(nr, ptr); -	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	*(unsigned char *) addr &= ~(1 << (nr & 7)); +	*addr &= ~(1 << (nr & 7));  } -#define clear_bit_simple(nr,addr) \ -(__builtin_constant_p((nr)) ? \ - __constant_clear_bit((nr),(addr)) : \ - __clear_bit((nr),(addr)) ) - -/*  - * fast, non-SMP change_bit routine  - */  static inline void __change_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned char *addr = __bitops_byte(nr, ptr); -	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	asm volatile( -		"	xc	%O0(1,%R0),%1" -		: "=Q" (*(char *) addr) : "Q" (_oi_bitmap[nr & 7]) : "cc" ); +	*addr ^= 1 << (nr & 7);  } -static inline void  -__constant_change_bit(const unsigned long nr, volatile unsigned long *ptr)  -{ -	unsigned long addr; - -	addr = ((unsigned long) ptr) + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	*(unsigned char *) addr ^= 1 << (nr & 7); -} - -#define change_bit_simple(nr,addr) \ -(__builtin_constant_p((nr)) ? \ - __constant_change_bit((nr),(addr)) : \ - __change_bit((nr),(addr)) ) - -/* - * fast, non-SMP test_and_set_bit routine - */  static inline int -test_and_set_bit_simple(unsigned long nr, volatile unsigned long *ptr) +__test_and_set_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned char *addr = __bitops_byte(nr, ptr);  	unsigned char ch; -	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	ch = *(unsigned char *) addr; -	asm volatile( -		"	oc	%O0(1,%R0),%1" -		: "=Q" (*(char *) addr)	: "Q" (_oi_bitmap[nr & 7]) -		: "cc", "memory"); +	ch = *addr; +	*addr |= 1 << (nr & 7);  	return (ch >> (nr & 7)) & 1;  } -#define __test_and_set_bit(X,Y)		test_and_set_bit_simple(X,Y) -/* - * fast, non-SMP test_and_clear_bit routine - */  static inline int -test_and_clear_bit_simple(unsigned long nr, volatile unsigned long *ptr) +__test_and_clear_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned char *addr = __bitops_byte(nr, ptr);  	unsigned char ch; -	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	ch = *(unsigned char *) addr; -	asm volatile( -		"	nc	%O0(1,%R0),%1" -		: "=Q" (*(char *) addr)	: "Q" (_ni_bitmap[nr & 7]) -		: "cc", "memory"); +	ch = *addr; +	*addr &= ~(1 << (nr & 7));  	return (ch >> (nr & 7)) & 1;  } -#define __test_and_clear_bit(X,Y)	test_and_clear_bit_simple(X,Y) -/* - * fast, non-SMP test_and_change_bit routine - */  static inline int -test_and_change_bit_simple(unsigned long nr, volatile unsigned long *ptr) +__test_and_change_bit(unsigned long nr, volatile unsigned long *ptr)  { -	unsigned long addr; +	unsigned char *addr = __bitops_byte(nr, ptr);  	unsigned char ch; -	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	ch = *(unsigned char *) addr; -	asm volatile( -		"	xc	%O0(1,%R0),%1" -		: "=Q" (*(char *) addr)	: "Q" (_oi_bitmap[nr & 7]) -		: "cc", "memory"); +	ch = *addr; +	*addr ^= 1 << (nr & 7);  	return (ch >> (nr & 7)) & 1;  } -#define __test_and_change_bit(X,Y)	test_and_change_bit_simple(X,Y) - -#ifdef CONFIG_SMP -#define set_bit             set_bit_cs -#define clear_bit           clear_bit_cs -#define change_bit          change_bit_cs -#define test_and_set_bit    test_and_set_bit_cs -#define test_and_clear_bit  test_and_clear_bit_cs -#define test_and_change_bit test_and_change_bit_cs -#else -#define set_bit             set_bit_simple -#define clear_bit           clear_bit_simple -#define change_bit          change_bit_simple -#define test_and_set_bit    test_and_set_bit_simple -#define test_and_clear_bit  test_and_clear_bit_simple -#define test_and_change_bit test_and_change_bit_simple -#endif - -/* - * This routine doesn't need to be atomic. - */ - -static inline int __test_bit(unsigned long nr, const volatile unsigned long *ptr) +static inline int test_bit(unsigned long nr, const volatile unsigned long *ptr)  { -	unsigned long addr; -	unsigned char ch; +	const volatile unsigned char *addr; -	addr = (unsigned long) ptr + ((nr ^ (__BITOPS_WORDSIZE - 8)) >> 3); -	ch = *(volatile unsigned char *) addr; -	return (ch >> (nr & 7)) & 1; -} - -static inline int  -__constant_test_bit(unsigned long nr, const volatile unsigned long *addr) { -    return (((volatile char *) addr) -	    [(nr^(__BITOPS_WORDSIZE-8))>>3] & (1<<(nr&7))) != 0; +	addr = ((const volatile unsigned char *)ptr); +	addr += (nr ^ (BITS_PER_LONG - 8)) >> 3; +	return (*addr >> (nr & 7)) & 1;  } -#define test_bit(nr,addr) \ -(__builtin_constant_p((nr)) ? \ - __constant_test_bit((nr),(addr)) : \ - __test_bit((nr),(addr)) ) -  /* - * Optimized find bit helper functions. + * Functions which use MSB0 bit numbering. + * On an s390x system the bits are numbered: + *   |0..............63|64............127|128...........191|192...........255| + * and on s390: + *   |0.....31|32....63|64....95|96...127|128..159|160..191|192..223|224..255|   */ +unsigned long find_first_bit_inv(const unsigned long *addr, unsigned long size); +unsigned long find_next_bit_inv(const unsigned long *addr, unsigned long size, +				unsigned long offset); -/** - * __ffz_word_loop - find byte offset of first long != -1UL - * @addr: pointer to array of unsigned long - * @size: size of the array in bits - */ -static inline unsigned long __ffz_word_loop(const unsigned long *addr, -					    unsigned long size) -{ -	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; -	unsigned long bytes = 0; - -	asm volatile( -#ifndef __s390x__ -		"	ahi	%1,-1\n" -		"	sra	%1,5\n" -		"	jz	1f\n" -		"0:	c	%2,0(%0,%3)\n" -		"	jne	1f\n" -		"	la	%0,4(%0)\n" -		"	brct	%1,0b\n" -		"1:\n" -#else -		"	aghi	%1,-1\n" -		"	srag	%1,%1,6\n" -		"	jz	1f\n" -		"0:	cg	%2,0(%0,%3)\n" -		"	jne	1f\n" -		"	la	%0,8(%0)\n" -		"	brct	%1,0b\n" -		"1:\n" -#endif -		: "+&a" (bytes), "+&d" (size) -		: "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr) -		: "cc" ); -	return bytes; -} - -/** - * __ffs_word_loop - find byte offset of first long != 0UL - * @addr: pointer to array of unsigned long - * @size: size of the array in bits - */ -static inline unsigned long __ffs_word_loop(const unsigned long *addr, -					    unsigned long size) +static inline void set_bit_inv(unsigned long nr, volatile unsigned long *ptr)  { -	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype; -	unsigned long bytes = 0; - -	asm volatile( -#ifndef __s390x__ -		"	ahi	%1,-1\n" -		"	sra	%1,5\n" -		"	jz	1f\n" -		"0:	c	%2,0(%0,%3)\n" -		"	jne	1f\n" -		"	la	%0,4(%0)\n" -		"	brct	%1,0b\n" -		"1:\n" -#else -		"	aghi	%1,-1\n" -		"	srag	%1,%1,6\n" -		"	jz	1f\n" -		"0:	cg	%2,0(%0,%3)\n" -		"	jne	1f\n" -		"	la	%0,8(%0)\n" -		"	brct	%1,0b\n" -		"1:\n" -#endif -		: "+&a" (bytes), "+&a" (size) -		: "d" (0UL), "a" (addr), "m" (*(addrtype *) addr) -		: "cc" ); -	return bytes; +	return set_bit(nr ^ (BITS_PER_LONG - 1), ptr);  } -/** - * __ffz_word - add number of the first unset bit - * @nr: base value the bit number is added to - * @word: the word that is searched for unset bits - */ -static inline unsigned long __ffz_word(unsigned long nr, unsigned long word) +static inline void clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)  { -#ifdef __s390x__ -	if ((word & 0xffffffff) == 0xffffffff) { -		word >>= 32; -		nr += 32; -	} -#endif -	if ((word & 0xffff) == 0xffff) { -		word >>= 16; -		nr += 16; -	} -	if ((word & 0xff) == 0xff) { -		word >>= 8; -		nr += 8; -	} -	return nr + _zb_findmap[(unsigned char) word]; +	return clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);  } -/** - * __ffs_word - add number of the first set bit - * @nr: base value the bit number is added to - * @word: the word that is searched for set bits - */ -static inline unsigned long __ffs_word(unsigned long nr, unsigned long word) +static inline void __set_bit_inv(unsigned long nr, volatile unsigned long *ptr)  { -#ifdef __s390x__ -	if ((word & 0xffffffff) == 0) { -		word >>= 32; -		nr += 32; -	} -#endif -	if ((word & 0xffff) == 0) { -		word >>= 16; -		nr += 16; -	} -	if ((word & 0xff) == 0) { -		word >>= 8; -		nr += 8; -	} -	return nr + _sb_findmap[(unsigned char) word]; +	return __set_bit(nr ^ (BITS_PER_LONG - 1), ptr);  } - -/** - * __load_ulong_be - load big endian unsigned long - * @p: pointer to array of unsigned long - * @offset: byte offset of source value in the array - */ -static inline unsigned long __load_ulong_be(const unsigned long *p, -					    unsigned long offset) +static inline void __clear_bit_inv(unsigned long nr, volatile unsigned long *ptr)  { -	p = (unsigned long *)((unsigned long) p + offset); -	return *p; +	return __clear_bit(nr ^ (BITS_PER_LONG - 1), ptr);  } -/** - * __load_ulong_le - load little endian unsigned long - * @p: pointer to array of unsigned long - * @offset: byte offset of source value in the array - */ -static inline unsigned long __load_ulong_le(const unsigned long *p, -					    unsigned long offset) +static inline int test_bit_inv(unsigned long nr, +			       const volatile unsigned long *ptr)  { -	unsigned long word; - -	p = (unsigned long *)((unsigned long) p + offset); -#ifndef __s390x__ -	asm volatile( -		"	ic	%0,%O1(%R1)\n" -		"	icm	%0,2,%O1+1(%R1)\n" -		"	icm	%0,4,%O1+2(%R1)\n" -		"	icm	%0,8,%O1+3(%R1)" -		: "=&d" (word) : "Q" (*p) : "cc"); -#else -	asm volatile( -		"	lrvg	%0,%1" -		: "=d" (word) : "m" (*p) ); -#endif -	return word; +	return test_bit(nr ^ (BITS_PER_LONG - 1), ptr);  } -/* - * The various find bit functions. - */ +#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES -/* - * ffz - find first zero in word. - * @word: The word to search +/** + * __flogr - find leftmost one + * @word - The word to search   * - * Undefined if no zero exists, so code should check against ~0UL first. - */ -static inline unsigned long ffz(unsigned long word) -{ -	return __ffz_word(0, word); + * Returns the bit number of the most significant bit set, + * where the most significant bit has bit number 0. + * If no bit is set this function returns 64. + */ +static inline unsigned char __flogr(unsigned long word) +{ +	if (__builtin_constant_p(word)) { +		unsigned long bit = 0; + +		if (!word) +			return 64; +		if (!(word & 0xffffffff00000000UL)) { +			word <<= 32; +			bit += 32; +		} +		if (!(word & 0xffff000000000000UL)) { +			word <<= 16; +			bit += 16; +		} +		if (!(word & 0xff00000000000000UL)) { +			word <<= 8; +			bit += 8; +		} +		if (!(word & 0xf000000000000000UL)) { +			word <<= 4; +			bit += 4; +		} +		if (!(word & 0xc000000000000000UL)) { +			word <<= 2; +			bit += 2; +		} +		if (!(word & 0x8000000000000000UL)) { +			word <<= 1; +			bit += 1; +		} +		return bit; +	} else { +		register unsigned long bit asm("4") = word; +		register unsigned long out asm("5"); + +		asm volatile( +			"       flogr   %[bit],%[bit]\n" +			: [bit] "+d" (bit), [out] "=d" (out) : : "cc"); +		return bit; +	}  }  /** @@ -582,260 +400,83 @@ static inline unsigned long ffz(unsigned long word)   *   * Undefined if no bit exists, so code should check against 0 first.   */ -static inline unsigned long __ffs (unsigned long word) +static inline unsigned long __ffs(unsigned long word)  { -	return __ffs_word(0, word); +	return __flogr(-word & word) ^ (BITS_PER_LONG - 1);  }  /**   * ffs - find first bit set - * @x: the word to search + * @word: the word to search   * - * This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). + * This is defined the same way as the libc and + * compiler builtin ffs routines (man ffs).   */ -static inline int ffs(int x) +static inline int ffs(int word)  { -	if (!x) -		return 0; -	return __ffs_word(1, x); +	unsigned long mask = 2 * BITS_PER_LONG - 1; +	unsigned int val = (unsigned int)word; + +	return (1 + (__flogr(-val & val) ^ (BITS_PER_LONG - 1))) & mask;  }  /** - * find_first_zero_bit - find the first zero bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search + * __fls - find last (most-significant) set bit in a long word + * @word: the word to search   * - * Returns the bit-number of the first zero bit, not the number of the byte - * containing a bit. + * Undefined if no set bit exists, so code should check against 0 first.   */ -static inline unsigned long find_first_zero_bit(const unsigned long *addr, -						unsigned long size) +static inline unsigned long __fls(unsigned long word)  { -	unsigned long bytes, bits; - -        if (!size) -                return 0; -	bytes = __ffz_word_loop(addr, size); -	bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes)); -	return (bits < size) ? bits : size; +	return __flogr(word) ^ (BITS_PER_LONG - 1);  }  /** - * find_first_bit - find the first set bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search + * fls64 - find last set bit in a 64-bit word + * @word: the word to search + * + * This is defined in a similar way as the libc and compiler builtin + * ffsll, but returns the position of the most significant set bit.   * - * Returns the bit-number of the first set bit, not the number of the byte - * containing a bit. + * fls64(value) returns 0 if value is 0 or the position of the last + * set bit if value is nonzero. The last (most significant) bit is + * at position 64.   */ -static inline unsigned long find_first_bit(const unsigned long * addr, -					   unsigned long size) +static inline int fls64(unsigned long word)  { -	unsigned long bytes, bits; +	unsigned long mask = 2 * BITS_PER_LONG - 1; -        if (!size) -                return 0; -	bytes = __ffs_word_loop(addr, size); -	bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes)); -	return (bits < size) ? bits : size; +	return (1 + (__flogr(word) ^ (BITS_PER_LONG - 1))) & mask;  }  /** - * find_next_zero_bit - find the first zero bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -static inline int find_next_zero_bit (const unsigned long * addr, -				      unsigned long size, -				      unsigned long offset) -{ -        const unsigned long *p; -	unsigned long bit, set; - -	if (offset >= size) -		return size; -	bit = offset & (__BITOPS_WORDSIZE - 1); -	offset -= bit; -	size -= offset; -	p = addr + offset / __BITOPS_WORDSIZE; -	if (bit) { -		/* -		 * __ffz_word returns __BITOPS_WORDSIZE -		 * if no zero bit is present in the word. -		 */ -		set = __ffz_word(bit, *p >> bit); -		if (set >= size) -			return size + offset; -		if (set < __BITOPS_WORDSIZE) -			return set + offset; -		offset += __BITOPS_WORDSIZE; -		size -= __BITOPS_WORDSIZE; -		p++; -	} -	return offset + find_first_zero_bit(p, size); -} - -/** - * find_next_bit - find the first set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search + * fls - find last (most-significant) bit set + * @word: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.   */ -static inline int find_next_bit (const unsigned long * addr, -				 unsigned long size, -				 unsigned long offset) +static inline int fls(int word)  { -        const unsigned long *p; -	unsigned long bit, set; - -	if (offset >= size) -		return size; -	bit = offset & (__BITOPS_WORDSIZE - 1); -	offset -= bit; -	size -= offset; -	p = addr + offset / __BITOPS_WORDSIZE; -	if (bit) { -		/* -		 * __ffs_word returns __BITOPS_WORDSIZE -		 * if no one bit is present in the word. -		 */ -		set = __ffs_word(0, *p & (~0UL << bit)); -		if (set >= size) -			return size + offset; -		if (set < __BITOPS_WORDSIZE) -			return set + offset; -		offset += __BITOPS_WORDSIZE; -		size -= __BITOPS_WORDSIZE; -		p++; -	} -	return offset + find_first_bit(p, size); +	return fls64((unsigned int)word);  } -/* - * Every architecture must define this function. It's the fastest - * way of searching a 140-bit bitmap where the first 100 bits are - * unlikely to be set. It's guaranteed that at least one of the 140 - * bits is cleared. - */ -static inline int sched_find_first_bit(unsigned long *b) -{ -	return find_first_bit(b, 140); -} +#else /* CONFIG_HAVE_MARCH_Z9_109_FEATURES */ -#include <asm-generic/bitops/fls.h> +#include <asm-generic/bitops/__ffs.h> +#include <asm-generic/bitops/ffs.h>  #include <asm-generic/bitops/__fls.h> +#include <asm-generic/bitops/fls.h>  #include <asm-generic/bitops/fls64.h> +#endif /* CONFIG_HAVE_MARCH_Z9_109_FEATURES */ + +#include <asm-generic/bitops/ffz.h> +#include <asm-generic/bitops/find.h>  #include <asm-generic/bitops/hweight.h>  #include <asm-generic/bitops/lock.h> - -/* - * ATTENTION: intel byte ordering convention for ext2 and minix !! - * bit 0 is the LSB of addr; bit 31 is the MSB of addr; - * bit 32 is the LSB of (addr+4). - * That combined with the little endian byte order of Intel gives the - * following bit order in memory: - *    07 06 05 04 03 02 01 00 15 14 13 12 11 10 09 08 \ - *    23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24 - */ - -#define ext2_set_bit(nr, addr)       \ -	__test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) -#define ext2_set_bit_atomic(lock, nr, addr)       \ -	test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) -#define ext2_clear_bit(nr, addr)     \ -	__test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) -#define ext2_clear_bit_atomic(lock, nr, addr)     \ -	test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) -#define ext2_test_bit(nr, addr)      \ -	test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr) - -static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size) -{ -	unsigned long bytes, bits; - -        if (!size) -                return 0; -	bytes = __ffz_word_loop(vaddr, size); -	bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes)); -	return (bits < size) ? bits : size; -} - -static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size, -					  unsigned long offset) -{ -        unsigned long *addr = vaddr, *p; -	unsigned long bit, set; - -        if (offset >= size) -                return size; -	bit = offset & (__BITOPS_WORDSIZE - 1); -	offset -= bit; -	size -= offset; -	p = addr + offset / __BITOPS_WORDSIZE; -        if (bit) { -		/* -		 * s390 version of ffz returns __BITOPS_WORDSIZE -		 * if no zero bit is present in the word. -		 */ -		set = __ffz_word(bit, __load_ulong_le(p, 0) >> bit); -		if (set >= size) -			return size + offset; -		if (set < __BITOPS_WORDSIZE) -			return set + offset; -		offset += __BITOPS_WORDSIZE; -		size -= __BITOPS_WORDSIZE; -		p++; -        } -	return offset + ext2_find_first_zero_bit(p, size); -} - -static inline unsigned long ext2_find_first_bit(void *vaddr, -						unsigned long size) -{ -	unsigned long bytes, bits; - -	if (!size) -		return 0; -	bytes = __ffs_word_loop(vaddr, size); -	bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes)); -	return (bits < size) ? bits : size; -} - -static inline int ext2_find_next_bit(void *vaddr, unsigned long size, -				     unsigned long offset) -{ -	unsigned long *addr = vaddr, *p; -	unsigned long bit, set; - -	if (offset >= size) -		return size; -	bit = offset & (__BITOPS_WORDSIZE - 1); -	offset -= bit; -	size -= offset; -	p = addr + offset / __BITOPS_WORDSIZE; -	if (bit) { -		/* -		 * s390 version of ffz returns __BITOPS_WORDSIZE -		 * if no zero bit is present in the word. -		 */ -		set = __ffs_word(0, __load_ulong_le(p, 0) & (~0UL << bit)); -		if (set >= size) -			return size + offset; -		if (set < __BITOPS_WORDSIZE) -			return set + offset; -		offset += __BITOPS_WORDSIZE; -		size -= __BITOPS_WORDSIZE; -		p++; -	} -	return offset + ext2_find_first_bit(p, size); -} - -#include <asm-generic/bitops/minix.h> - -#endif /* __KERNEL__ */ +#include <asm-generic/bitops/sched.h> +#include <asm-generic/bitops/le.h> +#include <asm-generic/bitops/ext2-atomic-setbit.h>  #endif /* _S390_BITOPS_H */ diff --git a/arch/s390/include/asm/bugs.h b/arch/s390/include/asm/bugs.h index 011f1e6a2a6..0f5bd894f4d 100644 --- a/arch/s390/include/asm/bugs.h +++ b/arch/s390/include/asm/bugs.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/bugs.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   *   *  Derived from "include/asm-i386/bugs.h" diff --git a/arch/s390/include/asm/cache.h b/arch/s390/include/asm/cache.h index 24aafa68b64..4d7ccac5fd1 100644 --- a/arch/s390/include/asm/cache.h +++ b/arch/s390/include/asm/cache.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/cache.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *   *  Derived from "include/asm-i386/cache.h"   *    Copyright (C) 1992, Linus Torvalds @@ -13,6 +11,7 @@  #define L1_CACHE_BYTES     256  #define L1_CACHE_SHIFT     8 +#define NET_SKB_PAD	   32  #define __read_mostly __attribute__((__section__(".data..read_mostly"))) diff --git a/arch/s390/include/asm/cacheflush.h b/arch/s390/include/asm/cacheflush.h index 405cc97c624..3e20383d092 100644 --- a/arch/s390/include/asm/cacheflush.h +++ b/arch/s390/include/asm/cacheflush.h @@ -1,32 +1,16 @@  #ifndef _S390_CACHEFLUSH_H  #define _S390_CACHEFLUSH_H -/* Keep includes the same across arches.  */ -#include <linux/mm.h> -  /* Caches aren't brain-dead on the s390. */ -#define flush_cache_all()			do { } while (0) -#define flush_cache_mm(mm)			do { } while (0) -#define flush_cache_dup_mm(mm)			do { } while (0) -#define flush_cache_range(vma, start, end)	do { } while (0) -#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0) -#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0 -#define flush_dcache_page(page)			do { } while (0) -#define flush_dcache_mmap_lock(mapping)		do { } while (0) -#define flush_dcache_mmap_unlock(mapping)	do { } while (0) -#define flush_icache_range(start, end)		do { } while (0) -#define flush_icache_page(vma,pg)		do { } while (0) -#define flush_icache_user_range(vma,pg,adr,len)	do { } while (0) -#define flush_cache_vmap(start, end)		do { } while (0) -#define flush_cache_vunmap(start, end)		do { } while (0) - -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ -	memcpy(dst, src, len) -#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ -	memcpy(dst, src, len) +#include <asm-generic/cacheflush.h>  #ifdef CONFIG_DEBUG_PAGEALLOC  void kernel_map_pages(struct page *page, int numpages, int enable);  #endif +int set_memory_ro(unsigned long addr, int numpages); +int set_memory_rw(unsigned long addr, int numpages); +int set_memory_nx(unsigned long addr, int numpages); +int set_memory_x(unsigned long addr, int numpages); +  #endif /* _S390_CACHEFLUSH_H */ diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index e8501115eca..b80e456d642 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h @@ -1,5 +1,5 @@  /* - * Copyright  IBM Corp. 2002, 2009 + * Copyright IBM Corp. 2002, 2009   *   * Author(s): Arnd Bergmann <arndb@de.ibm.com>   * @@ -11,6 +11,8 @@  #include <linux/device.h>  #include <linux/mod_devicetable.h>  #include <asm/fcx.h> +#include <asm/irq.h> +#include <asm/schid.h>  /* structs from asm/cio.h */  struct irb; @@ -112,7 +114,6 @@ enum uc_todo {  /**   * struct ccw driver - device driver for channel attached devices - * @owner: owning module   * @ids: ids supported by this driver   * @probe: function called on probe   * @remove: function called on remove @@ -128,10 +129,9 @@ enum uc_todo {   * @restore: callback for restoring after hibernation   * @uc_handler: callback for unit check handler   * @driver: embedded device driver structure - * @name: device driver name + * @int_class: interruption class to use for accounting interrupts   */  struct ccw_driver { -	struct module *owner;  	struct ccw_device_id *ids;  	int (*probe) (struct ccw_device *);  	void (*remove) (struct ccw_device *); @@ -147,7 +147,7 @@ struct ccw_driver {  	int (*restore)(struct ccw_device *);  	enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);  	struct device_driver driver; -	char *name; +	enum interruption_class int_class;  };  extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, @@ -204,6 +204,8 @@ int ccw_device_tm_start_timeout(struct ccw_device *, struct tcw *,  			    unsigned long, u8, int);  int ccw_device_tm_intrg(struct ccw_device *cdev); +int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask); +  extern int ccw_device_set_online(struct ccw_device *cdev);  extern int ccw_device_set_offline(struct ccw_device *cdev); @@ -217,13 +219,15 @@ extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *);  #define to_ccwdev(n) container_of(n, struct ccw_device, dev)  #define to_ccwdrv(n) container_of(n, struct ccw_driver, driver) -extern struct ccw_device *ccw_device_probe_console(void); -extern int ccw_device_force_console(void); +extern struct ccw_device *ccw_device_create_console(struct ccw_driver *); +extern void ccw_device_destroy_console(struct ccw_device *); +extern int ccw_device_enable_console(struct ccw_device *); +extern void ccw_device_wait_idle(struct ccw_device *); +extern int ccw_device_force_console(struct ccw_device *);  int ccw_device_siosl(struct ccw_device *); -// FIXME: these have to go -extern int _ccw_device_get_subchannel_number(struct ccw_device *); +extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *); -extern void *ccw_device_get_chp_desc(struct ccw_device *, int); +struct channel_path_desc *ccw_device_get_chp_desc(struct ccw_device *, int);  #endif /* _S390_CCWDEV_H_ */ diff --git a/arch/s390/include/asm/ccwgroup.h b/arch/s390/include/asm/ccwgroup.h index c79c1e787b8..057ce0ca637 100644 --- a/arch/s390/include/asm/ccwgroup.h +++ b/arch/s390/include/asm/ccwgroup.h @@ -6,14 +6,14 @@ struct ccw_driver;  /**   * struct ccwgroup_device - ccw group device - * @creator_id: unique number of the driver   * @state: online/offline state   * @count: number of attached slave devices   * @dev: embedded device structure   * @cdev: variable number of slave devices, allocated as needed + * @ungroup_work: work to be done when a ccwgroup notifier has action + *	type %BUS_NOTIFY_UNBIND_DRIVER   */  struct ccwgroup_device { -	unsigned long creator_id;  	enum {  		CCWGROUP_OFFLINE,  		CCWGROUP_ONLINE, @@ -24,16 +24,13 @@ struct ccwgroup_device {  /* public: */  	unsigned int count;  	struct device	dev; +	struct work_struct ungroup_work;  	struct ccw_device *cdev[0];  };  /**   * struct ccwgroup_driver - driver for ccw group devices - * @owner: driver owner - * @name: driver name - * @max_slaves: maximum number of slave devices - * @driver_id: unique id - * @probe: function called on probe + * @setup: function called during device creation to setup the device   * @remove: function called on remove   * @set_online: function called when device is set online   * @set_offline: function called when device is set offline @@ -46,12 +43,7 @@ struct ccwgroup_device {   * @driver: embedded driver structure   */  struct ccwgroup_driver { -	struct module *owner; -	char *name; -	int max_slaves; -	unsigned long driver_id; - -	int (*probe) (struct ccwgroup_device *); +	int (*setup) (struct ccwgroup_device *);  	void (*remove) (struct ccwgroup_device *);  	int (*set_online) (struct ccwgroup_device *);  	int (*set_offline) (struct ccwgroup_device *); @@ -67,9 +59,11 @@ struct ccwgroup_driver {  extern int  ccwgroup_driver_register   (struct ccwgroup_driver *cdriver);  extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); -int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, -				struct ccw_driver *cdrv, int num_devices, -				const char *buf); +int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv, +			int num_devices, const char *buf); + +extern int ccwgroup_set_online(struct ccwgroup_device *gdev); +extern int ccwgroup_set_offline(struct ccwgroup_device *gdev);  extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);  extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); diff --git a/arch/s390/include/asm/checksum.h b/arch/s390/include/asm/checksum.h index 6c00f6800a3..74036485635 100644 --- a/arch/s390/include/asm/checksum.h +++ b/arch/s390/include/asm/checksum.h @@ -1,18 +1,16 @@ -#ifndef _S390_CHECKSUM_H -#define _S390_CHECKSUM_H -  /* - *  include/asm-s390/checksum.h   *    S390 fast network checksum routines - *    see also arch/S390/lib/checksum.c   *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Ulrich Hild        (first version)   *               Martin Schwidefsky (heavily optimized CKSM version)   *               D.J. Barrow        (third attempt)    */ +#ifndef _S390_CHECKSUM_H +#define _S390_CHECKSUM_H +  #include <asm/uaccess.h>  /* @@ -46,22 +44,15 @@ csum_partial(const void *buff, int len, __wsum sum)   * here even more important to align src and dst on a 32-bit (or even   * better 64-bit) boundary   * - * Copy from userspace and compute checksum.  If we catch an exception - * then zero the rest of the buffer. + * Copy from userspace and compute checksum.   */  static inline __wsum  csum_partial_copy_from_user(const void __user *src, void *dst,                                            int len, __wsum sum,                                            int *err_ptr)  { -	int missing; - -	missing = copy_from_user(dst, src, len); -	if (missing) { -		memset(dst + len - missing, 0, missing); +	if (unlikely(copy_from_user(dst, src, len)))  		*err_ptr = -EFAULT; -	} -		  	return csum_partial(dst, len, sum);  } diff --git a/arch/s390/include/asm/chpid.h b/arch/s390/include/asm/chpid.h index fc71d8a6709..7298eec9854 100644 --- a/arch/s390/include/asm/chpid.h +++ b/arch/s390/include/asm/chpid.h @@ -1,28 +1,24 @@  /* - *  drivers/s390/cio/chpid.h - * - *    Copyright IBM Corp. 2007 + *    Copyright IBM Corp. 2007, 2012   *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>   */ -  #ifndef _ASM_S390_CHPID_H -#define _ASM_S390_CHPID_H _ASM_S390_CHPID_H - -#include <linux/string.h> -#include <linux/types.h> - -#define __MAX_CHPID 255 +#define _ASM_S390_CHPID_H -struct chp_id { -	u8 reserved1; -	u8 cssid; -	u8 reserved2; -	u8 id; -} __attribute__((packed)); - -#ifdef __KERNEL__ +#include <uapi/asm/chpid.h>  #include <asm/cio.h> +struct channel_path_desc { +	u8 flags; +	u8 lsn; +	u8 desc; +	u8 chpid; +	u8 swla; +	u8 zeroes; +	u8 chla; +	u8 chpp; +} __packed; +  static inline void chp_id_init(struct chp_id *chpid)  {  	memset(chpid, 0, sizeof(struct chp_id)); @@ -51,6 +47,4 @@ static inline int chp_id_is_valid(struct chp_id *chpid)  #define chp_id_for_each(c) \  	for (chp_id_init(c); chp_id_is_valid(c); chp_id_next(c)) -#endif /* __KERNEL */ -  #endif /* _ASM_S390_CHPID_H */ diff --git a/arch/s390/include/asm/cio.h b/arch/s390/include/asm/cio.h index e34347d567a..09633920776 100644 --- a/arch/s390/include/asm/cio.h +++ b/arch/s390/include/asm/cio.h @@ -1,7 +1,4 @@  /* - *  include/asm-s390/cio.h - *  include/asm-s390x/cio.h - *   * Common interface for I/O on S/390   */  #ifndef _ASM_S390_CIO_H_ @@ -10,10 +7,10 @@  #include <linux/spinlock.h>  #include <asm/types.h> -#ifdef __KERNEL__ -  #define LPM_ANYPATH 0xff  #define __MAX_CSSID 0 +#define __MAX_SUBCHANNEL 65535 +#define __MAX_SSID 3  #include <asm/scsw.h> @@ -85,6 +82,18 @@ struct erw {  } __attribute__ ((packed));  /** + * struct erw_eadm - EADM Subchannel extended report word + * @b: aob error + * @r: arsb error + */ +struct erw_eadm { +	__u32 : 16; +	__u32 b : 1; +	__u32 r : 1; +	__u32  : 14; +} __packed; + +/**   * struct sublog - subchannel logout area   * @res0: reserved   * @esf: extended status flags @@ -175,15 +184,28 @@ struct esw3 {  } __attribute__ ((packed));  /** + * struct esw_eadm - EADM Subchannel Extended Status Word (ESW) + * @sublog: subchannel logout + * @erw: extended report word + */ +struct esw_eadm { +	__u32 sublog; +	struct erw_eadm erw; +	__u32 : 32; +	__u32 : 32; +	__u32 : 32; +} __packed; + +/**   * struct irb - interruption response block   * @scsw: subchannel status word - * @esw: extened status word, 4 formats + * @esw: extended status word   * @ecw: extended control word   *   * The irb that is handed to the device driver when an interrupt occurs. For   * solicited interrupts, the common I/O layer already performs checks whether   * a field is valid; a field not being valid is always passed as %0. - * If a unit check occured, @ecw may contain sense data; this is retrieved + * If a unit check occurred, @ecw may contain sense data; this is retrieved   * by the common I/O layer itself if the device doesn't support concurrent   * sense (so that the device driver never needs to perform basic sene itself).   * For unsolicited interrupts, the irb is passed as-is (expect for sense data, @@ -196,6 +218,7 @@ struct irb {  		struct esw1 esw1;  		struct esw2 esw2;  		struct esw3 esw3; +		struct esw_eadm eadm;  	} esw;  	__u8   ecw[32];  } __attribute__ ((packed,aligned(4))); @@ -273,8 +296,7 @@ static inline int ccw_dev_id_is_equal(struct ccw_dev_id *dev_id1,  	return 0;  } -extern void wait_cons_dev(void); - +void channel_subsystem_reinit(void);  extern void css_schedule_reprobe(void);  extern void reipl_ccw_dev(struct ccw_dev_id *id); @@ -291,5 +313,3 @@ int chsc_sstpc(void *page, unsigned int op, u16 ctrl);  int chsc_sstpi(void *page, void *result, size_t size);  #endif - -#endif diff --git a/arch/s390/include/asm/clp.h b/arch/s390/include/asm/clp.h new file mode 100644 index 00000000000..a0e71a501f7 --- /dev/null +++ b/arch/s390/include/asm/clp.h @@ -0,0 +1,28 @@ +#ifndef _ASM_S390_CLP_H +#define _ASM_S390_CLP_H + +/* CLP common request & response block size */ +#define CLP_BLK_SIZE			PAGE_SIZE + +struct clp_req_hdr { +	u16 len; +	u16 cmd; +} __packed; + +struct clp_rsp_hdr { +	u16 len; +	u16 rsp; +} __packed; + +/* CLP Response Codes */ +#define CLP_RC_OK			0x0010	/* Command request successfully */ +#define CLP_RC_CMD			0x0020	/* Command code not recognized */ +#define CLP_RC_PERM			0x0030	/* Command not authorized */ +#define CLP_RC_FMT			0x0040	/* Invalid command request format */ +#define CLP_RC_LEN			0x0050	/* Invalid command request length */ +#define CLP_RC_8K			0x0060	/* Command requires 8K LPCB */ +#define CLP_RC_RESNOT0			0x0070	/* Reserved field not zero */ +#define CLP_RC_NODATA			0x0080	/* No data available */ +#define CLP_RC_FC_UNKNOWN		0x0100	/* Function code not recognized */ + +#endif diff --git a/arch/s390/include/asm/cmb.h b/arch/s390/include/asm/cmb.h index 39ae0329479..806eac12e3b 100644 --- a/arch/s390/include/asm/cmb.h +++ b/arch/s390/include/asm/cmb.h @@ -1,61 +1,12 @@  #ifndef S390_CMB_H  #define S390_CMB_H -#include <linux/types.h> +#include <uapi/asm/cmb.h> -/** - * struct cmbdata - channel measurement block data for user space - * @size: size of the stored data - * @elapsed_time: time since last sampling - * @ssch_rsch_count: number of ssch and rsch - * @sample_count: number of samples - * @device_connect_time: time of device connect - * @function_pending_time: time of function pending - * @device_disconnect_time: time of device disconnect - * @control_unit_queuing_time: time of control unit queuing - * @device_active_only_time: time of device active only - * @device_busy_time: time of device busy (ext. format) - * @initial_command_response_time: initial command response time (ext. format) - * - * All values are stored as 64 bit for simplicity, especially - * in 32 bit emulation mode. All time values are normalized to - * nanoseconds. - * Currently, two formats are known, which differ by the size of - * this structure, i.e. the last two members are only set when - * the extended channel measurement facility (first shipped in - * z990 machines) is activated. - * Potentially, more fields could be added, which would result in a - * new ioctl number. - */ -struct cmbdata { -	__u64 size; -	__u64 elapsed_time; - /* basic and exended format: */ -	__u64 ssch_rsch_count; -	__u64 sample_count; -	__u64 device_connect_time; -	__u64 function_pending_time; -	__u64 device_disconnect_time; -	__u64 control_unit_queuing_time; -	__u64 device_active_only_time; - /* extended format only: */ -	__u64 device_busy_time; -	__u64 initial_command_response_time; -}; - -/* enable channel measurement */ -#define BIODASDCMFENABLE	_IO(DASD_IOCTL_LETTER, 32) -/* enable channel measurement */ -#define BIODASDCMFDISABLE	_IO(DASD_IOCTL_LETTER, 33) -/* read channel measurement data */ -#define BIODASDREADALLCMB	_IOWR(DASD_IOCTL_LETTER, 33, struct cmbdata) - -#ifdef __KERNEL__  struct ccw_device;  extern int enable_cmf(struct ccw_device *cdev);  extern int disable_cmf(struct ccw_device *cdev);  extern u64 cmf_read(struct ccw_device *cdev, int index);  extern int cmf_readall(struct ccw_device *cdev, struct cmbdata *data); -#endif /* __KERNEL__ */  #endif /* S390_CMB_H */ diff --git a/arch/s390/include/asm/cmpxchg.h b/arch/s390/include/asm/cmpxchg.h new file mode 100644 index 00000000000..4236408070e --- /dev/null +++ b/arch/s390/include/asm/cmpxchg.h @@ -0,0 +1,304 @@ +/* + * Copyright IBM Corp. 1999, 2011 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, + */ + +#ifndef __ASM_CMPXCHG_H +#define __ASM_CMPXCHG_H + +#include <linux/mmdebug.h> +#include <linux/types.h> +#include <linux/bug.h> + +extern void __xchg_called_with_bad_pointer(void); + +static inline unsigned long __xchg(unsigned long x, void *ptr, int size) +{ +	unsigned long addr, old; +	int shift; + +	switch (size) { +	case 1: +		addr = (unsigned long) ptr; +		shift = (3 ^ (addr & 3)) << 3; +		addr ^= addr & 3; +		asm volatile( +			"	l	%0,%4\n" +			"0:	lr	0,%0\n" +			"	nr	0,%3\n" +			"	or	0,%2\n" +			"	cs	%0,0,%4\n" +			"	jl	0b\n" +			: "=&d" (old), "=Q" (*(int *) addr) +			: "d" ((x & 0xff) << shift), "d" (~(0xff << shift)), +			  "Q" (*(int *) addr) : "memory", "cc", "0"); +		return old >> shift; +	case 2: +		addr = (unsigned long) ptr; +		shift = (2 ^ (addr & 2)) << 3; +		addr ^= addr & 2; +		asm volatile( +			"	l	%0,%4\n" +			"0:	lr	0,%0\n" +			"	nr	0,%3\n" +			"	or	0,%2\n" +			"	cs	%0,0,%4\n" +			"	jl	0b\n" +			: "=&d" (old), "=Q" (*(int *) addr) +			: "d" ((x & 0xffff) << shift), "d" (~(0xffff << shift)), +			  "Q" (*(int *) addr) : "memory", "cc", "0"); +		return old >> shift; +	case 4: +		asm volatile( +			"	l	%0,%3\n" +			"0:	cs	%0,%2,%3\n" +			"	jl	0b\n" +			: "=&d" (old), "=Q" (*(int *) ptr) +			: "d" (x), "Q" (*(int *) ptr) +			: "memory", "cc"); +		return old; +#ifdef CONFIG_64BIT +	case 8: +		asm volatile( +			"	lg	%0,%3\n" +			"0:	csg	%0,%2,%3\n" +			"	jl	0b\n" +			: "=&d" (old), "=m" (*(long *) ptr) +			: "d" (x), "Q" (*(long *) ptr) +			: "memory", "cc"); +		return old; +#endif /* CONFIG_64BIT */ +	} +	__xchg_called_with_bad_pointer(); +	return x; +} + +#define xchg(ptr, x)							  \ +({									  \ +	__typeof__(*(ptr)) __ret;					  \ +	__ret = (__typeof__(*(ptr)))					  \ +		__xchg((unsigned long)(x), (void *)(ptr), sizeof(*(ptr)));\ +	__ret;								  \ +}) + +/* + * Atomic compare and exchange.	 Compare OLD with MEM, if identical, + * store NEW in MEM.  Return the initial value in MEM.	Success is + * indicated by comparing RETURN with OLD. + */ + +#define __HAVE_ARCH_CMPXCHG + +extern void __cmpxchg_called_with_bad_pointer(void); + +static inline unsigned long __cmpxchg(void *ptr, unsigned long old, +				      unsigned long new, int size) +{ +	unsigned long addr, prev, tmp; +	int shift; + +	switch (size) { +	case 1: +		addr = (unsigned long) ptr; +		shift = (3 ^ (addr & 3)) << 3; +		addr ^= addr & 3; +		asm volatile( +			"	l	%0,%2\n" +			"0:	nr	%0,%5\n" +			"	lr	%1,%0\n" +			"	or	%0,%3\n" +			"	or	%1,%4\n" +			"	cs	%0,%1,%2\n" +			"	jnl	1f\n" +			"	xr	%1,%0\n" +			"	nr	%1,%5\n" +			"	jnz	0b\n" +			"1:" +			: "=&d" (prev), "=&d" (tmp), "+Q" (*(int *) addr) +			: "d" ((old & 0xff) << shift), +			  "d" ((new & 0xff) << shift), +			  "d" (~(0xff << shift)) +			: "memory", "cc"); +		return prev >> shift; +	case 2: +		addr = (unsigned long) ptr; +		shift = (2 ^ (addr & 2)) << 3; +		addr ^= addr & 2; +		asm volatile( +			"	l	%0,%2\n" +			"0:	nr	%0,%5\n" +			"	lr	%1,%0\n" +			"	or	%0,%3\n" +			"	or	%1,%4\n" +			"	cs	%0,%1,%2\n" +			"	jnl	1f\n" +			"	xr	%1,%0\n" +			"	nr	%1,%5\n" +			"	jnz	0b\n" +			"1:" +			: "=&d" (prev), "=&d" (tmp), "+Q" (*(int *) addr) +			: "d" ((old & 0xffff) << shift), +			  "d" ((new & 0xffff) << shift), +			  "d" (~(0xffff << shift)) +			: "memory", "cc"); +		return prev >> shift; +	case 4: +		asm volatile( +			"	cs	%0,%3,%1\n" +			: "=&d" (prev), "=Q" (*(int *) ptr) +			: "0" (old), "d" (new), "Q" (*(int *) ptr) +			: "memory", "cc"); +		return prev; +#ifdef CONFIG_64BIT +	case 8: +		asm volatile( +			"	csg	%0,%3,%1\n" +			: "=&d" (prev), "=Q" (*(long *) ptr) +			: "0" (old), "d" (new), "Q" (*(long *) ptr) +			: "memory", "cc"); +		return prev; +#endif /* CONFIG_64BIT */ +	} +	__cmpxchg_called_with_bad_pointer(); +	return old; +} + +#define cmpxchg(ptr, o, n)						 \ +({									 \ +	__typeof__(*(ptr)) __ret;					 \ +	__ret = (__typeof__(*(ptr)))					 \ +		__cmpxchg((ptr), (unsigned long)(o), (unsigned long)(n), \ +			  sizeof(*(ptr)));				 \ +	__ret;								 \ +}) + +#ifdef CONFIG_64BIT +#define cmpxchg64(ptr, o, n)						\ +({									\ +	cmpxchg((ptr), (o), (n));					\ +}) +#else /* CONFIG_64BIT */ +static inline unsigned long long __cmpxchg64(void *ptr, +					     unsigned long long old, +					     unsigned long long new) +{ +	register_pair rp_old = {.pair = old}; +	register_pair rp_new = {.pair = new}; +	unsigned long long *ullptr = ptr; + +	asm volatile( +		"	cds	%0,%2,%1" +		: "+d" (rp_old), "+Q" (*ullptr) +		: "d" (rp_new) +		: "memory", "cc"); +	return rp_old.pair; +} + +#define cmpxchg64(ptr, o, n)				\ +({							\ +	__typeof__(*(ptr)) __ret;			\ +	__ret = (__typeof__(*(ptr)))			\ +		__cmpxchg64((ptr),			\ +			    (unsigned long long)(o),	\ +			    (unsigned long long)(n));	\ +	__ret;						\ +}) +#endif /* CONFIG_64BIT */ + +#define __cmpxchg_double_op(p1, p2, o1, o2, n1, n2, insn)		\ +({									\ +	register __typeof__(*(p1)) __old1 asm("2") = (o1);		\ +	register __typeof__(*(p2)) __old2 asm("3") = (o2);		\ +	register __typeof__(*(p1)) __new1 asm("4") = (n1);		\ +	register __typeof__(*(p2)) __new2 asm("5") = (n2);		\ +	int cc;								\ +	asm volatile(							\ +			insn   " %[old],%[new],%[ptr]\n"		\ +		"	ipm	%[cc]\n"				\ +		"	srl	%[cc],28"				\ +		: [cc] "=d" (cc), [old] "+d" (__old1), "+d" (__old2)	\ +		: [new] "d" (__new1), "d" (__new2),			\ +		  [ptr] "Q" (*(p1)), "Q" (*(p2))			\ +		: "memory", "cc");					\ +	!cc;								\ +}) + +#define __cmpxchg_double_4(p1, p2, o1, o2, n1, n2) \ +	__cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cds") + +#define __cmpxchg_double_8(p1, p2, o1, o2, n1, n2) \ +	__cmpxchg_double_op(p1, p2, o1, o2, n1, n2, "cdsg") + +extern void __cmpxchg_double_called_with_bad_pointer(void); + +#define __cmpxchg_double(p1, p2, o1, o2, n1, n2)			\ +({									\ +	int __ret;							\ +	switch (sizeof(*(p1))) {					\ +	case 4:								\ +		__ret = __cmpxchg_double_4(p1, p2, o1, o2, n1, n2);	\ +		break;							\ +	case 8:								\ +		__ret = __cmpxchg_double_8(p1, p2, o1, o2, n1, n2);	\ +		break;							\ +	default:							\ +		__cmpxchg_double_called_with_bad_pointer();		\ +	}								\ +	__ret;								\ +}) + +#define cmpxchg_double(p1, p2, o1, o2, n1, n2)				\ +({									\ +	__typeof__(p1) __p1 = (p1);					\ +	__typeof__(p2) __p2 = (p2);					\ +	int __ret;							\ +	BUILD_BUG_ON(sizeof(*(p1)) != sizeof(long));			\ +	BUILD_BUG_ON(sizeof(*(p2)) != sizeof(long));			\ +	VM_BUG_ON((unsigned long)((__p1) + 1) != (unsigned long)(__p2));\ +	if (sizeof(long) == 4)						\ +		__ret = __cmpxchg_double_4(__p1, __p2, o1, o2, n1, n2);	\ +	else								\ +		__ret = __cmpxchg_double_8(__p1, __p2, o1, o2, n1, n2);	\ +	__ret;								\ +}) + +#define system_has_cmpxchg_double()	1 + +#include <asm-generic/cmpxchg-local.h> + +static inline unsigned long __cmpxchg_local(void *ptr, +					    unsigned long old, +					    unsigned long new, int size) +{ +	switch (size) { +	case 1: +	case 2: +	case 4: +#ifdef CONFIG_64BIT +	case 8: +#endif +		return __cmpxchg(ptr, old, new, size); +	default: +		return __cmpxchg_local_generic(ptr, old, new, size); +	} + +	return old; +} + +/* + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make + * them available. + */ +#define cmpxchg_local(ptr, o, n)					\ +({									\ +	__typeof__(*(ptr)) __ret;					\ +	__ret = (__typeof__(*(ptr)))					\ +		__cmpxchg_local((ptr), (unsigned long)(o),		\ +				(unsigned long)(n), sizeof(*(ptr)));	\ +	__ret;								\ +}) + +#define cmpxchg64_local(ptr, o, n)	cmpxchg64((ptr), (o), (n)) + +#endif /* __ASM_CMPXCHG_H */ diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index a875c2f542e..d350ed9d0fb 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -7,33 +7,43 @@  #include <linux/sched.h>  #include <linux/thread_info.h> +#define __TYPE_IS_PTR(t) (!__builtin_types_compatible_p(typeof(0?(t)0:0ULL), u64)) + +#define __SC_DELOUSE(t,v) ({ \ +	BUILD_BUG_ON(sizeof(t) > 4 && !__TYPE_IS_PTR(t)); \ +	(t)(__TYPE_IS_PTR(t) ? ((v) & 0x7fffffff) : (v)); \ +}) +  #define PSW32_MASK_PER		0x40000000UL  #define PSW32_MASK_DAT		0x04000000UL  #define PSW32_MASK_IO		0x02000000UL  #define PSW32_MASK_EXT		0x01000000UL  #define PSW32_MASK_KEY		0x00F00000UL +#define PSW32_MASK_BASE		0x00080000UL	/* Always one */  #define PSW32_MASK_MCHECK	0x00040000UL  #define PSW32_MASK_WAIT		0x00020000UL  #define PSW32_MASK_PSTATE	0x00010000UL  #define PSW32_MASK_ASC		0x0000C000UL  #define PSW32_MASK_CC		0x00003000UL  #define PSW32_MASK_PM		0x00000f00UL +#define PSW32_MASK_RI		0x00000080UL + +#define PSW32_MASK_USER		0x0000FF00UL -#define PSW32_ADDR_AMODE31	0x80000000UL +#define PSW32_ADDR_AMODE	0x80000000UL  #define PSW32_ADDR_INSN		0x7FFFFFFFUL -#define PSW32_BASE_BITS		0x00080000UL +#define PSW32_DEFAULT_KEY	(((u32) PAGE_DEFAULT_ACC) << 20)  #define PSW32_ASC_PRIMARY	0x00000000UL  #define PSW32_ASC_ACCREG	0x00004000UL  #define PSW32_ASC_SECONDARY	0x00008000UL  #define PSW32_ASC_HOME		0x0000C000UL -#define PSW32_MASK_MERGE(CURRENT,NEW) \ -	(((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \ -	 ((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM))) - -extern long psw32_user_bits; +#define PSW32_USER_BITS (PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT | \ +			 PSW32_DEFAULT_KEY | PSW32_MASK_BASE | \ +			 PSW32_MASK_MCHECK | PSW32_MASK_PSTATE | \ +			 PSW32_ASC_PRIMARY)  #define COMPAT_USER_HZ		100  #define COMPAT_UTS_MACHINE	"s390\0\0\0\0" @@ -66,6 +76,23 @@ typedef s64		compat_s64;  typedef u32		compat_uint_t;  typedef u32		compat_ulong_t;  typedef u64		compat_u64; +typedef u32		compat_uptr_t; + +typedef struct { +	u32 mask; +	u32 addr; +} __aligned(8) psw_compat_t; + +typedef struct { +	psw_compat_t psw; +	u32 gprs[NUM_GPRS]; +	u32 acrs[NUM_ACRS]; +	u32 orig_gpr2; +} s390_compat_regs; + +typedef struct { +	u32 gprs_high[NUM_GPRS]; +} s390_compat_regs_high;  struct compat_timespec {  	compat_time_t	tv_sec; @@ -121,17 +148,33 @@ struct compat_flock64 {  };  struct compat_statfs { -	s32		f_type; -	s32		f_bsize; -	s32		f_blocks; -	s32		f_bfree; -	s32		f_bavail; -	s32		f_files; -	s32		f_ffree; +	u32		f_type; +	u32		f_bsize; +	u32		f_blocks; +	u32		f_bfree; +	u32		f_bavail; +	u32		f_files; +	u32		f_ffree; +	compat_fsid_t	f_fsid; +	u32		f_namelen; +	u32		f_frsize; +	u32		f_flags; +	u32		f_spare[4]; +}; + +struct compat_statfs64 { +	u32		f_type; +	u32		f_bsize; +	u64		f_blocks; +	u64		f_bfree; +	u64		f_bavail; +	u64		f_files; +	u64		f_ffree;  	compat_fsid_t	f_fsid; -	s32		f_namelen; -	s32		f_frsize; -	s32		f_spare[6]; +	u32		f_namelen; +	u32		f_frsize; +	u32		f_flags; +	u32		f_spare[4];  };  #define COMPAT_RLIM_OLD_INFINITY	0x7fffffff @@ -144,6 +187,79 @@ typedef u32		compat_old_sigset_t;	/* at least 32 bits */  typedef u32		compat_sigset_word; +typedef union compat_sigval { +	compat_int_t	sival_int; +	compat_uptr_t	sival_ptr; +} compat_sigval_t; + +typedef struct compat_siginfo { +	int	si_signo; +	int	si_errno; +	int	si_code; + +	union { +		int _pad[128/sizeof(int) - 3]; + +		/* kill() */ +		struct { +			pid_t	_pid;	/* sender's pid */ +			uid_t	_uid;	/* sender's uid */ +		} _kill; + +		/* POSIX.1b timers */ +		struct { +			compat_timer_t _tid;		/* timer id */ +			int _overrun;			/* overrun count */ +			compat_sigval_t _sigval;	/* same as below */ +			int _sys_private;	/* not to be passed to user */ +		} _timer; + +		/* POSIX.1b signals */ +		struct { +			pid_t			_pid;	/* sender's pid */ +			uid_t			_uid;	/* sender's uid */ +			compat_sigval_t		_sigval; +		} _rt; + +		/* SIGCHLD */ +		struct { +			pid_t			_pid;	/* which child */ +			uid_t			_uid;	/* sender's uid */ +			int			_status;/* exit code */ +			compat_clock_t		_utime; +			compat_clock_t		_stime; +		} _sigchld; + +		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ +		struct { +			__u32	_addr;	/* faulting insn/memory ref. - pointer */ +		} _sigfault; + +		/* SIGPOLL */ +		struct { +			int	_band;	/* POLL_IN, POLL_OUT, POLL_MSG */ +			int	_fd; +		} _sigpoll; +	} _sifields; +} compat_siginfo_t; + +/* + * How these fields are to be accessed. + */ +#define si_pid		_sifields._kill._pid +#define si_uid		_sifields._kill._uid +#define si_status	_sifields._sigchld._status +#define si_utime	_sifields._sigchld._utime +#define si_stime	_sifields._sigchld._stime +#define si_value	_sifields._rt._sigval +#define si_int		_sifields._rt._sigval.sival_int +#define si_ptr		_sifields._rt._sigval.sival_ptr +#define si_addr		_sifields._sigfault._addr +#define si_band		_sifields._sigpoll._band +#define si_fd		_sifields._sigpoll._fd +#define si_tid		_sifields._timer._tid +#define si_overrun	_sifields._timer._overrun +  #define COMPAT_OFF_T_MAX	0x7fffffff  #define COMPAT_LOFF_T_MAX	0x7fffffffffffffffL @@ -153,7 +269,6 @@ typedef u32		compat_sigset_word;   * as pointers because the syscall entry code will have   * appropriately converted them already.   */ -typedef	u32		compat_uptr_t;  static inline void __user *compat_ptr(compat_uptr_t uptr)  { @@ -169,18 +284,9 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)  static inline int is_compat_task(void)  { -	return test_thread_flag(TIF_31BIT); +	return is_32bit_task();  } -#else - -static inline int is_compat_task(void) -{ -	return 0; -} - -#endif -  static inline void __user *arch_compat_alloc_user_space(long len)  {  	unsigned long stack; @@ -191,6 +297,8 @@ static inline void __user *arch_compat_alloc_user_space(long len)  	return (void __user *) (stack - len);  } +#endif +  struct compat_ipc64_perm {  	compat_key_t key;  	__compat_uid32_t uid; diff --git a/arch/s390/include/asm/cpcmd.h b/arch/s390/include/asm/cpcmd.h index 48a9eab1642..3dfadb5d648 100644 --- a/arch/s390/include/asm/cpcmd.h +++ b/arch/s390/include/asm/cpcmd.h @@ -1,8 +1,6 @@  /* - *  arch/s390/kernel/cpcmd.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),   *               Christian Borntraeger (cborntra@de.ibm.com),   */ diff --git a/arch/s390/include/asm/cpu.h b/arch/s390/include/asm/cpu.h index e0b69540216..f5a8e2fcde0 100644 --- a/arch/s390/include/asm/cpu.h +++ b/arch/s390/include/asm/cpu.h @@ -1,5 +1,5 @@  /* - *    Copyright IBM Corp. 2000,2009 + *    Copyright IBM Corp. 2000, 2009   *    Author(s): Hartmut Penner <hp@de.ibm.com>,   *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,   *		 Christian Ehrhardt <ehrhardt@de.ibm.com>, diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h new file mode 100644 index 00000000000..cb700d54bd8 --- /dev/null +++ b/arch/s390/include/asm/cpu_mf.h @@ -0,0 +1,283 @@ +/* + * CPU-measurement facilities + * + *  Copyright IBM Corp. 2012 + *  Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> + *	       Jan Glauber <jang@linux.vnet.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + */ +#ifndef _ASM_S390_CPU_MF_H +#define _ASM_S390_CPU_MF_H + +#include <linux/errno.h> +#include <asm/facility.h> + +#define CPU_MF_INT_SF_IAE	(1 << 31)	/* invalid entry address */ +#define CPU_MF_INT_SF_ISE	(1 << 30)	/* incorrect SDBT entry */ +#define CPU_MF_INT_SF_PRA	(1 << 29)	/* program request alert */ +#define CPU_MF_INT_SF_SACA	(1 << 23)	/* sampler auth. change alert */ +#define CPU_MF_INT_SF_LSDA	(1 << 22)	/* loss of sample data alert */ +#define CPU_MF_INT_CF_CACA	(1 <<  7)	/* counter auth. change alert */ +#define CPU_MF_INT_CF_LCDA	(1 <<  6)	/* loss of counter data alert */ +#define CPU_MF_INT_RI_HALTED	(1 <<  5)	/* run-time instr. halted */ +#define CPU_MF_INT_RI_BUF_FULL	(1 <<  4)	/* run-time instr. program +						   buffer full */ + +#define CPU_MF_INT_CF_MASK	(CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA) +#define CPU_MF_INT_SF_MASK	(CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE|	\ +				 CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA|	\ +				 CPU_MF_INT_SF_LSDA) +#define CPU_MF_INT_RI_MASK	(CPU_MF_INT_RI_HALTED|CPU_MF_INT_RI_BUF_FULL) + +/* CPU measurement facility support */ +static inline int cpum_cf_avail(void) +{ +	return MACHINE_HAS_LPP && test_facility(67); +} + +static inline int cpum_sf_avail(void) +{ +	return MACHINE_HAS_LPP && test_facility(68); +} + + +struct cpumf_ctr_info { +	u16   cfvn; +	u16   auth_ctl; +	u16   enable_ctl; +	u16   act_ctl; +	u16   max_cpu; +	u16   csvn; +	u16   max_cg; +	u16   reserved1; +	u32   reserved2[12]; +} __packed; + +/* QUERY SAMPLING INFORMATION block */ +struct hws_qsi_info_block {	    /* Bit(s) */ +	unsigned int b0_13:14;	    /* 0-13: zeros			 */ +	unsigned int as:1;	    /* 14: basic-sampling authorization	 */ +	unsigned int ad:1;	    /* 15: diag-sampling authorization	 */ +	unsigned int b16_21:6;	    /* 16-21: zeros			 */ +	unsigned int es:1;	    /* 22: basic-sampling enable control */ +	unsigned int ed:1;	    /* 23: diag-sampling enable control	 */ +	unsigned int b24_29:6;	    /* 24-29: zeros			 */ +	unsigned int cs:1;	    /* 30: basic-sampling activation control */ +	unsigned int cd:1;	    /* 31: diag-sampling activation control */ +	unsigned int bsdes:16;	    /* 4-5: size of basic sampling entry */ +	unsigned int dsdes:16;	    /* 6-7: size of diagnostic sampling entry */ +	unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */ +	unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/ +	unsigned long tear;	    /* 24-31: TEAR contents		 */ +	unsigned long dear;	    /* 32-39: DEAR contents		 */ +	unsigned int rsvrd0;	    /* 40-43: reserved			 */ +	unsigned int cpu_speed;     /* 44-47: CPU speed 		 */ +	unsigned long long rsvrd1;  /* 48-55: reserved			 */ +	unsigned long long rsvrd2;  /* 56-63: reserved			 */ +} __packed; + +/* SET SAMPLING CONTROLS request block */ +struct hws_lsctl_request_block { +	unsigned int s:1;	    /* 0: maximum buffer indicator	 */ +	unsigned int h:1;	    /* 1: part. level reserved for VM use*/ +	unsigned long long b2_53:52;/* 2-53: zeros			 */ +	unsigned int es:1;	    /* 54: basic-sampling enable control */ +	unsigned int ed:1;	    /* 55: diag-sampling enable control	 */ +	unsigned int b56_61:6;	    /* 56-61: - zeros			 */ +	unsigned int cs:1;	    /* 62: basic-sampling activation control */ +	unsigned int cd:1;	    /* 63: diag-sampling activation control  */ +	unsigned long interval;     /* 8-15: sampling interval		 */ +	unsigned long tear;	    /* 16-23: TEAR contents		 */ +	unsigned long dear;	    /* 24-31: DEAR contents		 */ +	/* 32-63:							 */ +	unsigned long rsvrd1;	    /* reserved 			 */ +	unsigned long rsvrd2;	    /* reserved 			 */ +	unsigned long rsvrd3;	    /* reserved 			 */ +	unsigned long rsvrd4;	    /* reserved 			 */ +} __packed; + +struct hws_basic_entry { +	unsigned int def:16;	    /* 0-15  Data Entry Format		 */ +	unsigned int R:4;	    /* 16-19 reserved			 */ +	unsigned int U:4;	    /* 20-23 Number of unique instruct.  */ +	unsigned int z:2;	    /* zeros				 */ +	unsigned int T:1;	    /* 26 PSW DAT mode			 */ +	unsigned int W:1;	    /* 27 PSW wait state		 */ +	unsigned int P:1;	    /* 28 PSW Problem state		 */ +	unsigned int AS:2;	    /* 29-30 PSW address-space control	 */ +	unsigned int I:1;	    /* 31 entry valid or invalid	 */ +	unsigned int:16; +	unsigned int prim_asn:16;   /* primary ASN			 */ +	unsigned long long ia;	    /* Instruction Address		 */ +	unsigned long long gpp;     /* Guest Program Parameter		 */ +	unsigned long long hpp;     /* Host Program Parameter		 */ +} __packed; + +struct hws_diag_entry { +	unsigned int def:16;	    /* 0-15  Data Entry Format		 */ +	unsigned int R:14;	    /* 16-19 and 20-30 reserved		 */ +	unsigned int I:1;	    /* 31 entry valid or invalid	 */ +	u8	     data[];	    /* Machine-dependent sample data	 */ +} __packed; + +struct hws_combined_entry { +	struct hws_basic_entry	basic;	/* Basic-sampling data entry */ +	struct hws_diag_entry	diag;	/* Diagnostic-sampling data entry */ +} __packed; + +struct hws_trailer_entry { +	union { +		struct { +			unsigned int f:1;	/* 0 - Block Full Indicator   */ +			unsigned int a:1;	/* 1 - Alert request control  */ +			unsigned int t:1;	/* 2 - Timestamp format	      */ +			unsigned long long:61;	/* 3 - 63: Reserved	      */ +		}; +		unsigned long long flags;	/* 0 - 63: All indicators     */ +	}; +	unsigned long long overflow;	 /* 64 - sample Overflow count	      */ +	unsigned char timestamp[16];	 /* 16 - 31 timestamp		      */ +	unsigned long long reserved1;	 /* 32 -Reserved		      */ +	unsigned long long reserved2;	 /*				      */ +	unsigned long long progusage1;	 /* 48 - reserved for programming use */ +	unsigned long long progusage2;	 /*				      */ +} __packed; + +/* Query counter information */ +static inline int qctri(struct cpumf_ctr_info *info) +{ +	int rc = -EINVAL; + +	asm volatile ( +		"0:	.insn	s,0xb28e0000,%1\n" +		"1:	lhi	%0,0\n" +		"2:\n" +		EX_TABLE(1b, 2b) +		: "+d" (rc), "=Q" (*info)); +	return rc; +} + +/* Load CPU-counter-set controls */ +static inline int lcctl(u64 ctl) +{ +	int cc; + +	asm volatile ( +		"	.insn	s,0xb2840000,%1\n" +		"	ipm	%0\n" +		"	srl	%0,28\n" +		: "=d" (cc) : "m" (ctl) : "cc"); +	return cc; +} + +/* Extract CPU counter */ +static inline int ecctr(u64 ctr, u64 *val) +{ +	register u64 content asm("4") = 0; +	int cc; + +	asm volatile ( +		"	.insn	rre,0xb2e40000,%0,%2\n" +		"	ipm	%1\n" +		"	srl	%1,28\n" +		: "=d" (content), "=d" (cc) : "d" (ctr) : "cc"); +	if (!cc) +		*val = content; +	return cc; +} + +/* Query sampling information */ +static inline int qsi(struct hws_qsi_info_block *info) +{ +	int cc; +	cc = 1; + +	asm volatile( +		"0:	.insn	s,0xb2860000,0(%1)\n" +		"1:	lhi	%0,0\n" +		"2:\n" +		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) +		: "=d" (cc), "+a" (info) +		: "m" (*info) +		: "cc", "memory"); + +	return cc ? -EINVAL : 0; +} + +/* Load sampling controls */ +static inline int lsctl(struct hws_lsctl_request_block *req) +{ +	int cc; + +	cc = 1; +	asm volatile( +		"0:	.insn	s,0xb2870000,0(%1)\n" +		"1:	ipm	%0\n" +		"	srl	%0,28\n" +		"2:\n" +		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b) +		: "+d" (cc), "+a" (req) +		: "m" (*req) +		: "cc", "memory"); + +	return cc ? -EINVAL : 0; +} + +/* Sampling control helper functions */ + +#include <linux/time.h> + +static inline unsigned long freq_to_sample_rate(struct hws_qsi_info_block *qsi, +						unsigned long freq) +{ +	return (USEC_PER_SEC / freq) * qsi->cpu_speed; +} + +static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi, +						unsigned long rate) +{ +	return USEC_PER_SEC * qsi->cpu_speed / rate; +} + +#define SDB_TE_ALERT_REQ_MASK	0x4000000000000000UL +#define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL + +/* Return TOD timestamp contained in an trailer entry */ +static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te) +{ +	/* TOD in STCKE format */ +	if (te->t) +		return *((unsigned long long *) &te->timestamp[1]); + +	/* TOD in STCK format */ +	return *((unsigned long long *) &te->timestamp[0]); +} + +/* Return pointer to trailer entry of an sample data block */ +static inline unsigned long *trailer_entry_ptr(unsigned long v) +{ +	void *ret; + +	ret = (void *) v; +	ret += PAGE_SIZE; +	ret -= sizeof(struct hws_trailer_entry); + +	return (unsigned long *) ret; +} + +/* Return if the entry in the sample data block table (sdbt) + * is a link to the next sdbt */ +static inline int is_link_entry(unsigned long *s) +{ +	return *s & 0x1ul ? 1 : 0; +} + +/* Return pointer to the linked sdbt */ +static inline unsigned long *get_next_sdbt(unsigned long *s) +{ +	return (unsigned long *) (*s & ~0x1ul); +} +#endif /* _ASM_S390_CPU_MF_H */ diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index 40e2ab0fa3f..f65bd363451 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h @@ -1,7 +1,5 @@  /* - *  include/asm-s390/cputime.h - * - *  (C) Copyright IBM Corp. 2004 + *  Copyright IBM Corp. 2004   *   *  Author: Martin Schwidefsky <schwidefsky@de.ibm.com>   */ @@ -14,116 +12,103 @@  #include <linux/spinlock.h>  #include <asm/div64.h> -/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ -typedef unsigned long long cputime_t; -typedef unsigned long long cputime64_t; +/* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ -#ifndef __s390x__ +typedef unsigned long long __nocast cputime_t; +typedef unsigned long long __nocast cputime64_t; -static inline unsigned int -__div(unsigned long long n, unsigned int base) +static inline unsigned long __div(unsigned long long n, unsigned long base)  { +#ifndef CONFIG_64BIT  	register_pair rp;  	rp.pair = n >> 1;  	asm ("dr %0,%1" : "+d" (rp) : "d" (base >> 1));  	return rp.subreg.odd; +#else /* CONFIG_64BIT */ +	return n / base; +#endif /* CONFIG_64BIT */  } -#else /* __s390x__ */ +#define cputime_one_jiffy		jiffies_to_cputime(1) -static inline unsigned int -__div(unsigned long long n, unsigned int base) +/* + * Convert cputime to jiffies and back. + */ +static inline unsigned long cputime_to_jiffies(const cputime_t cputime)  { -	return n / base; +	return __div((__force unsigned long long) cputime, 4096000000ULL / HZ);  } -#endif /* __s390x__ */ +static inline cputime_t jiffies_to_cputime(const unsigned int jif) +{ +	return (__force cputime_t)(jif * (4096000000ULL / HZ)); +} -#define cputime_zero			(0ULL) -#define cputime_one_jiffy		jiffies_to_cputime(1) -#define cputime_max			((~0UL >> 1) - 1) -#define cputime_add(__a, __b)		((__a) +  (__b)) -#define cputime_sub(__a, __b)		((__a) -  (__b)) -#define cputime_div(__a, __n) ({		\ -	unsigned long long __div = (__a);	\ -	do_div(__div,__n);			\ -	__div;					\ -}) -#define cputime_halve(__a)		((__a) >> 1) -#define cputime_eq(__a, __b)		((__a) == (__b)) -#define cputime_gt(__a, __b)		((__a) >  (__b)) -#define cputime_ge(__a, __b)		((__a) >= (__b)) -#define cputime_lt(__a, __b)		((__a) <  (__b)) -#define cputime_le(__a, __b)		((__a) <= (__b)) -#define cputime_to_jiffies(__ct)	(__div((__ct), 4096000000ULL / HZ)) -#define cputime_to_scaled(__ct)		(__ct) -#define jiffies_to_cputime(__hz)	((cputime_t)(__hz) * (4096000000ULL / HZ)) - -#define cputime64_zero			(0ULL) -#define cputime64_add(__a, __b)		((__a) + (__b)) -#define cputime_to_cputime64(__ct)	(__ct) - -static inline u64 -cputime64_to_jiffies64(cputime64_t cputime) -{ -	do_div(cputime, 4096000000ULL / HZ); -	return cputime; +static inline u64 cputime64_to_jiffies64(cputime64_t cputime) +{ +	unsigned long long jif = (__force unsigned long long) cputime; +	do_div(jif, 4096000000ULL / HZ); +	return jif; +} + +static inline cputime64_t jiffies64_to_cputime64(const u64 jif) +{ +	return (__force cputime64_t)(jif * (4096000000ULL / HZ));  }  /*   * Convert cputime to microseconds and back.   */ -static inline unsigned int -cputime_to_usecs(const cputime_t cputime) +static inline unsigned int cputime_to_usecs(const cputime_t cputime)  { -	return cputime_div(cputime, 4096); +	return (__force unsigned long long) cputime >> 12;  } -static inline cputime_t -usecs_to_cputime(const unsigned int m) +static inline cputime_t usecs_to_cputime(const unsigned int m)  { -	return (cputime_t) m * 4096; +	return (__force cputime_t)(m * 4096ULL);  } +#define usecs_to_cputime64(m)		usecs_to_cputime(m) +  /*   * Convert cputime to milliseconds and back.   */ -static inline unsigned int -cputime_to_secs(const cputime_t cputime) +static inline unsigned int cputime_to_secs(const cputime_t cputime)  { -	return __div(cputime, 2048000000) >> 1; +	return __div((__force unsigned long long) cputime, 2048000000) >> 1;  } -static inline cputime_t -secs_to_cputime(const unsigned int s) +static inline cputime_t secs_to_cputime(const unsigned int s)  { -	return (cputime_t) s * 4096000000ULL; +	return (__force cputime_t)(s * 4096000000ULL);  }  /*   * Convert cputime to timespec and back.   */ -static inline cputime_t -timespec_to_cputime(const struct timespec *value) +static inline cputime_t timespec_to_cputime(const struct timespec *value)  { -	return value->tv_nsec * 4096 / 1000 + (u64) value->tv_sec * 4096000000ULL; +	unsigned long long ret = value->tv_sec * 4096000000ULL; +	return (__force cputime_t)(ret + value->tv_nsec * 4096 / 1000);  } -static inline void -cputime_to_timespec(const cputime_t cputime, struct timespec *value) +static inline void cputime_to_timespec(const cputime_t cputime, +				       struct timespec *value)  { -#ifndef __s390x__ +	unsigned long long __cputime = (__force unsigned long long) cputime; +#ifndef CONFIG_64BIT  	register_pair rp; -	rp.pair = cputime >> 1; +	rp.pair = __cputime >> 1;  	asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));  	value->tv_nsec = rp.subreg.even * 1000 / 4096;  	value->tv_sec = rp.subreg.odd;  #else -	value->tv_nsec = (cputime % 4096000000ULL) * 1000 / 4096; -	value->tv_sec = cputime / 4096000000ULL; +	value->tv_nsec = (__cputime % 4096000000ULL) * 1000 / 4096; +	value->tv_sec = __cputime / 4096000000ULL;  #endif  } @@ -132,77 +117,74 @@ cputime_to_timespec(const cputime_t cputime, struct timespec *value)   * Since cputime and timeval have the same resolution (microseconds)   * this is easy.   */ -static inline cputime_t -timeval_to_cputime(const struct timeval *value) +static inline cputime_t timeval_to_cputime(const struct timeval *value)  { -	return value->tv_usec * 4096 + (u64) value->tv_sec * 4096000000ULL; +	unsigned long long ret = value->tv_sec * 4096000000ULL; +	return (__force cputime_t)(ret + value->tv_usec * 4096ULL);  } -static inline void -cputime_to_timeval(const cputime_t cputime, struct timeval *value) +static inline void cputime_to_timeval(const cputime_t cputime, +				      struct timeval *value)  { -#ifndef __s390x__ +	unsigned long long __cputime = (__force unsigned long long) cputime; +#ifndef CONFIG_64BIT  	register_pair rp; -	rp.pair = cputime >> 1; +	rp.pair = __cputime >> 1;  	asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL));  	value->tv_usec = rp.subreg.even / 4096;  	value->tv_sec = rp.subreg.odd;  #else -	value->tv_usec = (cputime % 4096000000ULL) / 4096; -	value->tv_sec = cputime / 4096000000ULL; +	value->tv_usec = (__cputime % 4096000000ULL) / 4096; +	value->tv_sec = __cputime / 4096000000ULL;  #endif  }  /*   * Convert cputime to clock and back.   */ -static inline clock_t -cputime_to_clock_t(cputime_t cputime) +static inline clock_t cputime_to_clock_t(cputime_t cputime)  { -	return cputime_div(cputime, 4096000000ULL / USER_HZ); +	unsigned long long clock = (__force unsigned long long) cputime; +	do_div(clock, 4096000000ULL / USER_HZ); +	return clock;  } -static inline cputime_t -clock_t_to_cputime(unsigned long x) +static inline cputime_t clock_t_to_cputime(unsigned long x)  { -	return (cputime_t) x * (4096000000ULL / USER_HZ); +	return (__force cputime_t)(x * (4096000000ULL / USER_HZ));  }  /*   * Convert cputime64 to clock.   */ -static inline clock_t -cputime64_to_clock_t(cputime64_t cputime) +static inline clock_t cputime64_to_clock_t(cputime64_t cputime)  { -       return cputime_div(cputime, 4096000000ULL / USER_HZ); +	unsigned long long clock = (__force unsigned long long) cputime; +	do_div(clock, 4096000000ULL / USER_HZ); +	return clock;  }  struct s390_idle_data { +	int nohz_delay;  	unsigned int sequence;  	unsigned long long idle_count; -	unsigned long long idle_enter;  	unsigned long long idle_time; -	int nohz_delay; +	unsigned long long clock_idle_enter; +	unsigned long long clock_idle_exit; +	unsigned long long timer_idle_enter; +	unsigned long long timer_idle_exit;  };  DECLARE_PER_CPU(struct s390_idle_data, s390_idle); -void vtime_start_cpu(__u64 int_clock, __u64 enter_timer);  cputime64_t s390_get_idle_time(int cpu);  #define arch_idle_time(cpu) s390_get_idle_time(cpu) -static inline void s390_idle_check(struct pt_regs *regs, __u64 int_clock, -				   __u64 enter_timer) -{ -	if (regs->psw.mask & PSW_MASK_WAIT) -		vtime_start_cpu(int_clock, enter_timer); -} -  static inline int s390_nohz_delay(int cpu)  { -	return per_cpu(s390_idle, cpu).nohz_delay != 0; +	return __get_cpu_var(s390_idle).nohz_delay != 0;  }  #define arch_needs_cpu(cpu) s390_nohz_delay(cpu) diff --git a/arch/s390/include/asm/crw.h b/arch/s390/include/asm/crw.h index 749a97e61be..7c31d3e25cd 100644 --- a/arch/s390/include/asm/crw.h +++ b/arch/s390/include/asm/crw.h @@ -1,6 +1,6 @@  /*   *   Data definitions for channel report processing - *    Copyright IBM Corp. 2000,2009 + *    Copyright IBM Corp. 2000, 2009   *    Author(s): Ingo Adlung <adlung@de.ibm.com>,   *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,   *		 Cornelia Huck <cornelia.huck@de.ibm.com>, diff --git a/arch/s390/include/asm/css_chars.h b/arch/s390/include/asm/css_chars.h new file mode 100644 index 00000000000..09d1dd46bd5 --- /dev/null +++ b/arch/s390/include/asm/css_chars.h @@ -0,0 +1,38 @@ +#ifndef _ASM_CSS_CHARS_H +#define _ASM_CSS_CHARS_H + +#include <linux/types.h> + +struct css_general_char { +	u64 : 12; +	u32 dynio : 1;	 /* bit 12 */ +	u32 : 4; +	u32 eadm : 1;	 /* bit 17 */ +	u32 : 23; +	u32 aif : 1;	 /* bit 41 */ +	u32 : 3; +	u32 mcss : 1;	 /* bit 45 */ +	u32 fcs : 1;	 /* bit 46 */ +	u32 : 1; +	u32 ext_mb : 1;  /* bit 48 */ +	u32 : 7; +	u32 aif_tdd : 1; /* bit 56 */ +	u32 : 1; +	u32 qebsm : 1;	 /* bit 58 */ +	u32 : 8; +	u32 aif_osa : 1; /* bit 67 */ +	u32 : 12; +	u32 eadm_rf : 1; /* bit 80 */ +	u32 : 1; +	u32 cib : 1;	 /* bit 82 */ +	u32 : 5; +	u32 fcx : 1;	 /* bit 88 */ +	u32 : 19; +	u32 alt_ssi : 1; /* bit 108 */ +	u32:1; +	u32 narf:1;	 /* bit 110 */ +} __packed; + +extern struct css_general_char css_general_characteristics; + +#endif diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h new file mode 100644 index 00000000000..31ab9f346d7 --- /dev/null +++ b/arch/s390/include/asm/ctl_reg.h @@ -0,0 +1,82 @@ +/* + * Copyright IBM Corp. 1999, 2009 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#ifndef __ASM_CTL_REG_H +#define __ASM_CTL_REG_H + +#include <linux/bug.h> + +#ifdef CONFIG_64BIT +# define __CTL_LOAD	"lctlg" +# define __CTL_STORE	"stctg" +#else +# define __CTL_LOAD	"lctl" +# define __CTL_STORE	"stctl" +#endif + +#define __ctl_load(array, low, high) {					\ +	typedef struct { char _[sizeof(array)]; } addrtype;		\ +									\ +	BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\ +	asm volatile(							\ +		__CTL_LOAD " %1,%2,%0\n"				\ +		: : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\ +} + +#define __ctl_store(array, low, high) {					\ +	typedef struct { char _[sizeof(array)]; } addrtype;		\ +									\ +	BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\ +	asm volatile(							\ +		__CTL_STORE " %1,%2,%0\n"				\ +		: "=Q" (*(addrtype *)(&array))				\ +		: "i" (low), "i" (high));				\ +} + +static inline void __ctl_set_bit(unsigned int cr, unsigned int bit) +{ +	unsigned long reg; + +	__ctl_store(reg, cr, cr); +	reg |= 1UL << bit; +	__ctl_load(reg, cr, cr); +} + +static inline void __ctl_clear_bit(unsigned int cr, unsigned int bit) +{ +	unsigned long reg; + +	__ctl_store(reg, cr, cr); +	reg &= ~(1UL << bit); +	__ctl_load(reg, cr, cr); +} + +void smp_ctl_set_bit(int cr, int bit); +void smp_ctl_clear_bit(int cr, int bit); + +union ctlreg0 { +	unsigned long val; +	struct { +#ifdef CONFIG_64BIT +		unsigned long	   : 32; +#endif +		unsigned long	   : 3; +		unsigned long lap  : 1; /* Low-address-protection control */ +		unsigned long	   : 4; +		unsigned long edat : 1; /* Enhanced-DAT-enablement control */ +		unsigned long	   : 23; +	}; +}; + +#ifdef CONFIG_SMP +# define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit) +# define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit) +#else +# define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit) +# define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit) +#endif + +#endif /* __ASM_CTL_REG_H */ diff --git a/arch/s390/include/asm/current.h b/arch/s390/include/asm/current.h index 83cf36cde2d..b80941f30df 100644 --- a/arch/s390/include/asm/current.h +++ b/arch/s390/include/asm/current.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/current.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   *   *  Derived from "include/asm-i386/current.h" @@ -11,13 +9,10 @@  #ifndef _S390_CURRENT_H  #define _S390_CURRENT_H -#ifdef __KERNEL__  #include <asm/lowcore.h>  struct task_struct;  #define current ((struct task_struct *const)S390_lowcore.current_task) -#endif -  #endif /* !(_S390_CURRENT_H) */ diff --git a/arch/s390/include/asm/debug.h b/arch/s390/include/asm/debug.h index 18124b75a7a..530c15eb01e 100644 --- a/arch/s390/include/asm/debug.h +++ b/arch/s390/include/asm/debug.h @@ -1,43 +1,16 @@  /* - *  include/asm-s390/debug.h   *   S/390 debug facility   * - *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH, - *                             IBM Corporation + *    Copyright IBM Corp. 1999, 2000   */ -  #ifndef DEBUG_H  #define DEBUG_H -#include <linux/fs.h> - -/* Note: - * struct __debug_entry must be defined outside of #ifdef __KERNEL__  - * in order to allow a user program to analyze the 'raw'-view. - */ - -struct __debug_entry{ -        union { -                struct { -                        unsigned long long clock:52; -                        unsigned long long exception:1; -                        unsigned long long level:3; -                        unsigned long long cpuid:8; -                } fields; - -                unsigned long long stck; -        } id; -        void* caller; -} __attribute__((packed)); - - -#define __DEBUG_FEATURE_VERSION      2  /* version of debug feature */ - -#ifdef __KERNEL__  #include <linux/string.h>  #include <linux/spinlock.h>  #include <linux/kernel.h>  #include <linux/time.h> +#include <uapi/asm/debug.h>  #define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */  #define DEBUG_OFF_LEVEL            -1 /* level where debug is switched off */ @@ -73,7 +46,7 @@ typedef struct debug_info {  	struct dentry* debugfs_entries[DEBUG_MAX_VIEWS];  	struct debug_view* views[DEBUG_MAX_VIEWS];	  	char name[DEBUG_MAX_NAME_LEN]; -	mode_t mode; +	umode_t mode;  } debug_info_t;  typedef int (debug_header_proc_t) (debug_info_t* id, @@ -124,15 +97,21 @@ debug_info_t *debug_register(const char *name, int pages, int nr_areas,                               int buf_size);  debug_info_t *debug_register_mode(const char *name, int pages, int nr_areas, -				  int buf_size, mode_t mode, uid_t uid, +				  int buf_size, umode_t mode, uid_t uid,  				  gid_t gid);  void debug_unregister(debug_info_t* id);  void debug_set_level(debug_info_t* id, int new_level); +void debug_set_critical(void);  void debug_stop_all(void); +static inline bool debug_level_enabled(debug_info_t* id, int level) +{ +	return level <= id->level; +} +  static inline debug_entry_t*  debug_event(debug_info_t* id, int level, void* data, int length)  { @@ -255,5 +234,4 @@ int debug_unregister_view(debug_info_t* id, struct debug_view* view);  #define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER x )  #endif				/* DASD_DEBUG */ -#endif				/* __KERNEL__ */  #endif				/* DEBUG_H */ diff --git a/arch/s390/include/asm/delay.h b/arch/s390/include/asm/delay.h index 8a096b83f51..3f6e4095f47 100644 --- a/arch/s390/include/asm/delay.h +++ b/arch/s390/include/asm/delay.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/delay.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   *   *  Derived from "include/asm-i386/delay.h" @@ -14,10 +12,12 @@  #ifndef _S390_DELAY_H  #define _S390_DELAY_H -extern void __udelay(unsigned long long usecs); -extern void udelay_simple(unsigned long long usecs); -extern void __delay(unsigned long loops); +void __ndelay(unsigned long long nsecs); +void __udelay(unsigned long long usecs); +void udelay_simple(unsigned long long usecs); +void __delay(unsigned long loops); +#define ndelay(n) __ndelay((unsigned long long) (n))  #define udelay(n) __udelay((unsigned long long) (n))  #define mdelay(n) __udelay((unsigned long long) (n) * 1000) diff --git a/arch/s390/include/asm/diag.h b/arch/s390/include/asm/diag.h index 72b2e2f2d32..7e91c58072e 100644 --- a/arch/s390/include/asm/diag.h +++ b/arch/s390/include/asm/diag.h @@ -9,9 +9,22 @@  #define _ASM_S390_DIAG_H  /* - * Diagnose 10: Release pages + * Diagnose 10: Release page range   */ -extern void diag10(unsigned long addr); +static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn) +{ +	unsigned long start_addr, end_addr; + +	start_addr = start_pfn << PAGE_SHIFT; +	end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT; + +	asm volatile( +		"0:	diag	%0,%1,0x10\n" +		"1:\n" +		EX_TABLE(0b, 1b) +		EX_TABLE(1b, 1b) +		: : "a" (start_addr), "a" (end_addr)); +}  /*   * Diagnose 14: Input spool file manipulation diff --git a/arch/s390/include/asm/dis.h b/arch/s390/include/asm/dis.h new file mode 100644 index 00000000000..04a83f5773c --- /dev/null +++ b/arch/s390/include/asm/dis.h @@ -0,0 +1,52 @@ +/* + * Disassemble s390 instructions. + * + * Copyright IBM Corp. 2007 + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#ifndef __ASM_S390_DIS_H__ +#define __ASM_S390_DIS_H__ + +/* Type of operand */ +#define OPERAND_GPR	0x1	/* Operand printed as %rx */ +#define OPERAND_FPR	0x2	/* Operand printed as %fx */ +#define OPERAND_AR	0x4	/* Operand printed as %ax */ +#define OPERAND_CR	0x8	/* Operand printed as %cx */ +#define OPERAND_DISP	0x10	/* Operand printed as displacement */ +#define OPERAND_BASE	0x20	/* Operand printed as base register */ +#define OPERAND_INDEX	0x40	/* Operand printed as index register */ +#define OPERAND_PCREL	0x80	/* Operand printed as pc-relative symbol */ +#define OPERAND_SIGNED	0x100	/* Operand printed as signed value */ +#define OPERAND_LENGTH	0x200	/* Operand printed as length (+1) */ + + +struct s390_operand { +	int bits;		/* The number of bits in the operand. */ +	int shift;		/* The number of bits to shift. */ +	int flags;		/* One bit syntax flags. */ +}; + +struct s390_insn { +	const char name[5]; +	unsigned char opfrag; +	unsigned char format; +}; + + +static inline int insn_length(unsigned char code) +{ +	return ((((int) code + 64) >> 7) + 1) << 1; +} + +void show_code(struct pt_regs *regs); +void print_fn_code(unsigned char *code, unsigned long len); +int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len); +struct s390_insn *find_insn(unsigned char *code); + +static inline int is_known_insn(unsigned char *code) +{ +	return !!find_insn(code); +} + +#endif /* __ASM_S390_DIS_H__ */ diff --git a/arch/s390/include/asm/dma-mapping.h b/arch/s390/include/asm/dma-mapping.h new file mode 100644 index 00000000000..3fbc67d9e19 --- /dev/null +++ b/arch/s390/include/asm/dma-mapping.h @@ -0,0 +1,79 @@ +#ifndef _ASM_S390_DMA_MAPPING_H +#define _ASM_S390_DMA_MAPPING_H + +#include <linux/kernel.h> +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/scatterlist.h> +#include <linux/dma-attrs.h> +#include <linux/dma-debug.h> +#include <linux/io.h> + +#define DMA_ERROR_CODE		(~(dma_addr_t) 0x0) + +extern struct dma_map_ops s390_dma_ops; + +static inline struct dma_map_ops *get_dma_ops(struct device *dev) +{ +	return &s390_dma_ops; +} + +extern int dma_set_mask(struct device *dev, u64 mask); + +static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, +				  enum dma_data_direction direction) +{ +} + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) + +#include <asm-generic/dma-mapping-common.h> + +static inline int dma_supported(struct device *dev, u64 mask) +{ +	struct dma_map_ops *dma_ops = get_dma_ops(dev); + +	if (dma_ops->dma_supported == NULL) +		return 1; +	return dma_ops->dma_supported(dev, mask); +} + +static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size) +{ +	if (!dev->dma_mask) +		return 0; +	return addr + size - 1 <= *dev->dma_mask; +} + +static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ +	struct dma_map_ops *dma_ops = get_dma_ops(dev); + +	debug_dma_mapping_error(dev, dma_addr); +	if (dma_ops->mapping_error) +		return dma_ops->mapping_error(dev, dma_addr); +	return dma_addr == DMA_ERROR_CODE; +} + +static inline void *dma_alloc_coherent(struct device *dev, size_t size, +				       dma_addr_t *dma_handle, gfp_t flag) +{ +	struct dma_map_ops *ops = get_dma_ops(dev); +	void *ret; + +	ret = ops->alloc(dev, size, dma_handle, flag, NULL); +	debug_dma_alloc_coherent(dev, size, *dma_handle, ret); +	return ret; +} + +static inline void dma_free_coherent(struct device *dev, size_t size, +				     void *cpu_addr, dma_addr_t dma_handle) +{ +	struct dma_map_ops *dma_ops = get_dma_ops(dev); + +	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle); +	dma_ops->free(dev, size, cpu_addr, dma_handle, NULL); +} + +#endif /* _ASM_S390_DMA_MAPPING_H */ diff --git a/arch/s390/include/asm/dma.h b/arch/s390/include/asm/dma.h index 7425c6af6cd..bb9bdcd2086 100644 --- a/arch/s390/include/asm/dma.h +++ b/arch/s390/include/asm/dma.h @@ -1,16 +1,19 @@ -/* - *  include/asm-s390/dma.h - * - *  S390 version - */ - -#ifndef _ASM_DMA_H -#define _ASM_DMA_H +#ifndef _ASM_S390_DMA_H +#define _ASM_S390_DMA_H -#include <asm/io.h>		/* need byte IO */ +#include <asm/io.h> +/* + * MAX_DMA_ADDRESS is ambiguous because on s390 its completely unrelated + * to DMA. It _is_ used for the s390 memory zone split at 2GB caused + * by the 31 bit heritage. + */  #define MAX_DMA_ADDRESS         0x80000000 -#define free_dma(x)	do { } while (0) +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy	(0) +#endif -#endif /* _ASM_DMA_H */ +#endif /* _ASM_S390_DMA_H */ diff --git a/arch/s390/include/asm/eadm.h b/arch/s390/include/asm/eadm.h new file mode 100644 index 00000000000..67026300c88 --- /dev/null +++ b/arch/s390/include/asm/eadm.h @@ -0,0 +1,117 @@ +#ifndef _ASM_S390_EADM_H +#define _ASM_S390_EADM_H + +#include <linux/types.h> +#include <linux/device.h> + +struct arqb { +	u64 data; +	u16 fmt:4; +	u16:12; +	u16 cmd_code; +	u16:16; +	u16 msb_count; +	u32 reserved[12]; +} __packed; + +#define ARQB_CMD_MOVE	1 + +struct arsb { +	u16 fmt:4; +	u32:28; +	u8 ef; +	u8:8; +	u8 ecbi; +	u8:8; +	u8 fvf; +	u16:16; +	u8 eqc; +	u32:32; +	u64 fail_msb; +	u64 fail_aidaw; +	u64 fail_ms; +	u64 fail_scm; +	u32 reserved[4]; +} __packed; + +#define EQC_WR_PROHIBIT 22 + +struct msb { +	u8 fmt:4; +	u8 oc:4; +	u8 flags; +	u16:12; +	u16 bs:4; +	u32 blk_count; +	u64 data_addr; +	u64 scm_addr; +	u64:64; +} __packed; + +struct aidaw { +	u8 flags; +	u32 :24; +	u32 :32; +	u64 data_addr; +} __packed; + +#define MSB_OC_CLEAR	0 +#define MSB_OC_READ	1 +#define MSB_OC_WRITE	2 +#define MSB_OC_RELEASE	3 + +#define MSB_FLAG_BNM	0x80 +#define MSB_FLAG_IDA	0x40 + +#define MSB_BS_4K	0 +#define MSB_BS_1M	1 + +#define AOB_NR_MSB	124 + +struct aob { +	struct arqb request; +	struct arsb response; +	struct msb msb[AOB_NR_MSB]; +} __packed __aligned(PAGE_SIZE); + +struct aob_rq_header { +	struct scm_device *scmdev; +	char data[0]; +}; + +struct scm_device { +	u64 address; +	u64 size; +	unsigned int nr_max_block; +	struct device dev; +	struct { +		unsigned int persistence:4; +		unsigned int oper_state:4; +		unsigned int data_state:4; +		unsigned int rank:4; +		unsigned int release:1; +		unsigned int res_id:8; +	} __packed attrs; +}; + +#define OP_STATE_GOOD		1 +#define OP_STATE_TEMP_ERR	2 +#define OP_STATE_PERM_ERR	3 + +enum scm_event {SCM_CHANGE, SCM_AVAIL}; + +struct scm_driver { +	struct device_driver drv; +	int (*probe) (struct scm_device *scmdev); +	int (*remove) (struct scm_device *scmdev); +	void (*notify) (struct scm_device *scmdev, enum scm_event event); +	void (*handler) (struct scm_device *scmdev, void *data, int error); +}; + +int scm_driver_register(struct scm_driver *scmdrv); +void scm_driver_unregister(struct scm_driver *scmdrv); + +int eadm_start_aob(struct aob *aob); +void scm_irq_handler(struct aob *aob, int error); + +#endif /* _ASM_S390_EADM_H */ diff --git a/arch/s390/include/asm/ebcdic.h b/arch/s390/include/asm/ebcdic.h index 7f6f641d32f..c5befc5a3bf 100644 --- a/arch/s390/include/asm/ebcdic.h +++ b/arch/s390/include/asm/ebcdic.h @@ -1,9 +1,8 @@  /* - *  include/asm-s390/ebcdic.h   *    EBCDIC -> ASCII, ASCII -> EBCDIC conversion routines.   *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>   */ diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 354d42616c7..78f4f8711d5 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/elf.h - *   *  S390 version   *   *  Derived from "include/asm-i386/elf.h" @@ -103,15 +101,16 @@  #define HWCAP_S390_HPAGE	128  #define HWCAP_S390_ETF3EH	256  #define HWCAP_S390_HIGH_GPRS	512 +#define HWCAP_S390_TE		1024  /*   * These are used to set parameters in the core dumps.   */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define ELF_CLASS	ELFCLASS32 -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  #define ELF_CLASS	ELFCLASS64 -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  #define ELF_DATA	ELFDATA2MSB  #define ELF_ARCH	EM_S390 @@ -120,6 +119,8 @@   */  #include <asm/ptrace.h> +#include <asm/compat.h> +#include <asm/syscall.h>  #include <asm/user.h>  typedef s390_fp_regs elf_fpregset_t; @@ -129,7 +130,6 @@ typedef s390_fp_regs compat_elf_fpregset_t;  typedef s390_compat_regs compat_elf_gregset_t;  #include <linux/sched.h>	/* for task_struct */ -#include <asm/system.h>		/* for save_access_regs */  #include <asm/mmu_context.h>  #include <asm/vdso.h> @@ -161,7 +161,9 @@ extern unsigned int vdso_enabled;     use of this is to invoke "./ld.so someprog" to test out a new version of     the loader.  We need to make sure that it is out of the way of the program     that it will "exec", and that there is sufficient room for the brk.  */ -#define ELF_ET_DYN_BASE		(STACK_TOP / 3 * 2) + +extern unsigned long randomize_et_dyn(unsigned long base); +#define ELF_ET_DYN_BASE		(randomize_et_dyn(STACK_TOP / 3 * 2))  /* This yields a mask that user programs can use to figure out what     instruction set this CPU supports. */ @@ -180,31 +182,33 @@ extern unsigned long elf_hwcap;  extern char elf_platform[];  #define ELF_PLATFORM (elf_platform) -#ifndef __s390x__ -#define SET_PERSONALITY(ex) set_personality(PER_LINUX) -#else /* __s390x__ */ +#ifndef CONFIG_COMPAT +#define SET_PERSONALITY(ex) \ +do {								\ +	set_personality(PER_LINUX |				\ +		(current->personality & (~PER_MASK)));		\ +	current_thread_info()->sys_call_table = 		\ +		(unsigned long) &sys_call_table;		\ +} while (0) +#else /* CONFIG_COMPAT */  #define SET_PERSONALITY(ex)					\  do {								\  	if (personality(current->personality) != PER_LINUX32)	\ -		set_personality(PER_LINUX);			\ -	if ((ex).e_ident[EI_CLASS] == ELFCLASS32)		\ +		set_personality(PER_LINUX |			\ +			(current->personality & ~PER_MASK));	\ +	if ((ex).e_ident[EI_CLASS] == ELFCLASS32) {		\  		set_thread_flag(TIF_31BIT);			\ -	else							\ +		current_thread_info()->sys_call_table =		\ +			(unsigned long)	&sys_call_table_emu;	\ +	} else {						\  		clear_thread_flag(TIF_31BIT);			\ +		current_thread_info()->sys_call_table =		\ +			(unsigned long) &sys_call_table;	\ +	}							\  } while (0) -#endif /* __s390x__ */ +#endif /* CONFIG_COMPAT */ -/* - * An executable for which elf_read_implies_exec() returns TRUE will - * have the READ_IMPLIES_EXEC personality flag set automatically. - */ -#define elf_read_implies_exec(ex, executable_stack)	\ -({							\ -	if (current->mm->context.noexec &&		\ -	    executable_stack != EXSTACK_DISABLE_X)	\ -		disable_noexec(current->mm, current);	\ -	current->mm->context.noexec == 0;		\ -}) +#define STACK_RND_MASK	0x7ffUL  #define ARCH_DLINFO							    \  do {									    \ @@ -218,4 +222,9 @@ struct linux_binprm;  #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1  int arch_setup_additional_pages(struct linux_binprm *, int); +extern unsigned long arch_randomize_brk(struct mm_struct *mm); +#define arch_randomize_brk arch_randomize_brk + +void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); +  #endif diff --git a/arch/s390/include/asm/etr.h b/arch/s390/include/asm/etr.h index 538e1b36a72..629b79a9316 100644 --- a/arch/s390/include/asm/etr.h +++ b/arch/s390/include/asm/etr.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/etr.h - *   *  Copyright IBM Corp. 2006   *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   */ @@ -142,7 +140,7 @@ struct etr_ptff_qto {  /* Inline assembly helper functions */  static inline int etr_setr(struct etr_eacr *ctrl)  { -	int rc = -ENOSYS; +	int rc = -EOPNOTSUPP;  	asm volatile(  		"	.insn	s,0xb2160000,%1\n" @@ -156,7 +154,7 @@ static inline int etr_setr(struct etr_eacr *ctrl)  /* Stores a format 1 aib with 64 bytes */  static inline int etr_stetr(struct etr_aib *aib)  { -	int rc = -ENOSYS; +	int rc = -EOPNOTSUPP;  	asm volatile(  		"	.insn	s,0xb2170000,%1\n" @@ -171,7 +169,7 @@ static inline int etr_stetr(struct etr_aib *aib)  static inline int etr_steai(struct etr_aib *aib, unsigned int func)  {  	register unsigned int reg0 asm("0") = func; -	int rc = -ENOSYS; +	int rc = -EOPNOTSUPP;  	asm volatile(  		"	.insn	s,0xb2b30000,%1\n" @@ -192,7 +190,7 @@ static inline int etr_ptff(void *ptff_block, unsigned int func)  {  	register unsigned int reg0 asm("0") = func;  	register unsigned long reg1 asm("1") = (unsigned long) ptff_block; -	int rc = -ENOSYS; +	int rc = -EOPNOTSUPP;  	asm volatile(  		"	.word	0x0104\n" diff --git a/arch/s390/include/asm/exec.h b/arch/s390/include/asm/exec.h new file mode 100644 index 00000000000..c4a93d6327f --- /dev/null +++ b/arch/s390/include/asm/exec.h @@ -0,0 +1,12 @@ +/* + * Copyright IBM Corp. 1999, 2009 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#ifndef __ASM_EXEC_H +#define __ASM_EXEC_H + +extern unsigned long arch_align_stack(unsigned long sp); + +#endif /* __ASM_EXEC_H */ diff --git a/arch/s390/include/asm/extmem.h b/arch/s390/include/asm/extmem.h index 33837d75618..6276002d76b 100644 --- a/arch/s390/include/asm/extmem.h +++ b/arch/s390/include/asm/extmem.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390x/extmem.h - *   *  definitions for external memory segment support - *  Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation + *  Copyright IBM Corp. 2003   */  #ifndef _ASM_S390X_DCSS_H diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h new file mode 100644 index 00000000000..0aa6a7ed95a --- /dev/null +++ b/arch/s390/include/asm/facility.h @@ -0,0 +1,67 @@ +/* + * Copyright IBM Corp. 1999, 2009 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#ifndef __ASM_FACILITY_H +#define __ASM_FACILITY_H + +#include <linux/string.h> +#include <linux/preempt.h> +#include <asm/lowcore.h> + +#define MAX_FACILITY_BIT (256*8)	/* stfle_fac_list has 256 bytes */ + +static inline int __test_facility(unsigned long nr, void *facilities) +{ +	unsigned char *ptr; + +	if (nr >= MAX_FACILITY_BIT) +		return 0; +	ptr = (unsigned char *) facilities + (nr >> 3); +	return (*ptr & (0x80 >> (nr & 7))) != 0; +} + +/* + * The test_facility function uses the bit odering where the MSB is bit 0. + * That makes it easier to query facility bits with the bit number as + * documented in the Principles of Operation. + */ +static inline int test_facility(unsigned long nr) +{ +	return __test_facility(nr, &S390_lowcore.stfle_fac_list); +} + +/** + * stfle - Store facility list extended + * @stfle_fac_list: array where facility list can be stored + * @size: size of passed in array in double words + */ +static inline void stfle(u64 *stfle_fac_list, int size) +{ +	unsigned long nr; + +	preempt_disable(); +	asm volatile( +		"	.insn s,0xb2b10000,0(0)\n" /* stfl */ +		"0:\n" +		EX_TABLE(0b, 0b) +		: "+m" (S390_lowcore.stfl_fac_list)); +	nr = 4; /* bytes stored by stfl */ +	memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); +	if (S390_lowcore.stfl_fac_list & 0x01000000) { +		/* More facility bits available with stfle */ +		register unsigned long reg0 asm("0") = size - 1; + +		asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */ +			     : "+d" (reg0) +			     : "a" (stfle_fac_list) +			     : "memory", "cc"); +		nr = (reg0 + 1) * 8; /* # bytes stored by stfle */ +	} +	memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); +	preempt_enable(); +} + +#endif /* __ASM_FACILITY_H */ diff --git a/arch/s390/include/asm/fcx.h b/arch/s390/include/asm/fcx.h index ef617099507..7ecb92b469b 100644 --- a/arch/s390/include/asm/fcx.h +++ b/arch/s390/include/asm/fcx.h @@ -12,9 +12,9 @@  #define TCW_FORMAT_DEFAULT		0  #define TCW_TIDAW_FORMAT_DEFAULT	0 -#define TCW_FLAGS_INPUT_TIDA		1 << (23 - 5) -#define TCW_FLAGS_TCCB_TIDA		1 << (23 - 6) -#define TCW_FLAGS_OUTPUT_TIDA		1 << (23 - 7) +#define TCW_FLAGS_INPUT_TIDA		(1 << (23 - 5)) +#define TCW_FLAGS_TCCB_TIDA		(1 << (23 - 6)) +#define TCW_FLAGS_OUTPUT_TIDA		(1 << (23 - 7))  #define TCW_FLAGS_TIDAW_FORMAT(x)	((x) & 3) << (23 - 9)  #define TCW_FLAGS_GET_TIDAW_FORMAT(x)	(((x) >> (23 - 9)) & 3) @@ -54,11 +54,11 @@ struct tcw {  	u32 intrg;  } __attribute__ ((packed, aligned(64))); -#define TIDAW_FLAGS_LAST		1 << (7 - 0) -#define TIDAW_FLAGS_SKIP		1 << (7 - 1) -#define TIDAW_FLAGS_DATA_INT		1 << (7 - 2) -#define TIDAW_FLAGS_TTIC		1 << (7 - 3) -#define TIDAW_FLAGS_INSERT_CBC		1 << (7 - 4) +#define TIDAW_FLAGS_LAST		(1 << (7 - 0)) +#define TIDAW_FLAGS_SKIP		(1 << (7 - 1)) +#define TIDAW_FLAGS_DATA_INT		(1 << (7 - 2)) +#define TIDAW_FLAGS_TTIC		(1 << (7 - 3)) +#define TIDAW_FLAGS_INSERT_CBC		(1 << (7 - 4))  /**   * struct tidaw - Transport-Indirect-Addressing Word (TIDAW) @@ -106,9 +106,9 @@ struct tsa_ddpc {  	u8 sense[32];  } __attribute__ ((packed)); -#define TSA_INTRG_FLAGS_CU_STATE_VALID		1 << (7 - 0) -#define TSA_INTRG_FLAGS_DEV_STATE_VALID		1 << (7 - 1) -#define TSA_INTRG_FLAGS_OP_STATE_VALID		1 << (7 - 2) +#define TSA_INTRG_FLAGS_CU_STATE_VALID		(1 << (7 - 0)) +#define TSA_INTRG_FLAGS_DEV_STATE_VALID		(1 << (7 - 1)) +#define TSA_INTRG_FLAGS_OP_STATE_VALID		(1 << (7 - 2))  /**   * struct tsa_intrg - Interrogate Transport-Status Area (Intrg. TSA) @@ -140,10 +140,10 @@ struct tsa_intrg {  #define TSB_FORMAT_DDPC		2  #define TSB_FORMAT_INTRG	3 -#define TSB_FLAGS_DCW_OFFSET_VALID	1 << (7 - 0) -#define TSB_FLAGS_COUNT_VALID		1 << (7 - 1) -#define TSB_FLAGS_CACHE_MISS		1 << (7 - 2) -#define TSB_FLAGS_TIME_VALID		1 << (7 - 3) +#define TSB_FLAGS_DCW_OFFSET_VALID	(1 << (7 - 0)) +#define TSB_FLAGS_COUNT_VALID		(1 << (7 - 1)) +#define TSB_FLAGS_CACHE_MISS		(1 << (7 - 2)) +#define TSB_FLAGS_TIME_VALID		(1 << (7 - 3))  #define TSB_FLAGS_FORMAT(x)		((x) & 7)  #define TSB_FORMAT(t)			((t)->flags & 7) @@ -179,9 +179,9 @@ struct tsb {  #define DCW_INTRG_RCQ_PRIMARY		1  #define DCW_INTRG_RCQ_SECONDARY		2 -#define DCW_INTRG_FLAGS_MPM		1 < (7 - 0) -#define DCW_INTRG_FLAGS_PPR		1 < (7 - 1) -#define DCW_INTRG_FLAGS_CRIT		1 < (7 - 2) +#define DCW_INTRG_FLAGS_MPM		(1 << (7 - 0)) +#define DCW_INTRG_FLAGS_PPR		(1 << (7 - 1)) +#define DCW_INTRG_FLAGS_CRIT		(1 << (7 - 2))  /**   * struct dcw_intrg_data - Interrogate DCW data @@ -216,7 +216,7 @@ struct dcw_intrg_data {  	u8  prog_data[0];  } __attribute__ ((packed)); -#define DCW_FLAGS_CC		1 << (7 - 1) +#define DCW_FLAGS_CC		(1 << (7 - 1))  #define DCW_CMD_WRITE		0x01  #define DCW_CMD_READ		0x02 diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index 96c14a9102b..bf246dae136 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h @@ -4,26 +4,23 @@  #ifndef __ASSEMBLY__  extern void _mcount(void); -extern unsigned long ftrace_dyn_func;  struct dyn_arch_ftrace { };  #define MCOUNT_ADDR ((long)_mcount) -#ifdef CONFIG_64BIT -#define MCOUNT_OFFSET_RET 18 -#define MCOUNT_INSN_SIZE  24 -#define MCOUNT_OFFSET	  14 -#else -#define MCOUNT_OFFSET_RET 26 -#define MCOUNT_INSN_SIZE  30 -#define MCOUNT_OFFSET	   8 -#endif  static inline unsigned long ftrace_call_adjust(unsigned long addr)  { -	return addr - MCOUNT_OFFSET; +	return addr;  }  #endif /* __ASSEMBLY__ */ + +#ifdef CONFIG_64BIT +#define MCOUNT_INSN_SIZE  12 +#else +#define MCOUNT_INSN_SIZE  22 +#endif +  #endif /* _ASM_S390_FTRACE_H */ diff --git a/arch/s390/include/asm/futex.h b/arch/s390/include/asm/futex.h index 5c5d02de49e..a4811aa0304 100644 --- a/arch/s390/include/asm/futex.h +++ b/arch/s390/include/asm/futex.h @@ -1,28 +1,63 @@  #ifndef _ASM_S390_FUTEX_H  #define _ASM_S390_FUTEX_H -#ifdef __KERNEL__ - -#include <linux/futex.h>  #include <linux/uaccess.h> +#include <linux/futex.h> +#include <asm/mmu_context.h>  #include <asm/errno.h> -static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr) +#define __futex_atomic_op(insn, ret, oldval, newval, uaddr, oparg)	\ +	asm volatile(							\ +		"   sacf  256\n"					\ +		"0: l     %1,0(%6)\n"					\ +		"1:"insn						\ +		"2: cs    %1,%2,0(%6)\n"				\ +		"3: jl    1b\n"						\ +		"   lhi   %0,0\n"					\ +		"4: sacf  768\n"					\ +		EX_TABLE(0b,4b) EX_TABLE(2b,4b) EX_TABLE(3b,4b)		\ +		: "=d" (ret), "=&d" (oldval), "=&d" (newval),		\ +		  "=m" (*uaddr)						\ +		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\ +		  "m" (*uaddr) : "cc"); + +static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)  {  	int op = (encoded_op >> 28) & 7;  	int cmp = (encoded_op >> 24) & 15;  	int oparg = (encoded_op << 8) >> 20;  	int cmparg = (encoded_op << 20) >> 20; -	int oldval, ret; +	int oldval = 0, newval, ret; +	load_kernel_asce();  	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))  		oparg = 1 << oparg; -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) -		return -EFAULT; -  	pagefault_disable(); -	ret = uaccess.futex_atomic_op(op, uaddr, oparg, &oldval); +	switch (op) { +	case FUTEX_OP_SET: +		__futex_atomic_op("lr %2,%5\n", +				  ret, oldval, newval, uaddr, oparg); +		break; +	case FUTEX_OP_ADD: +		__futex_atomic_op("lr %2,%1\nar %2,%5\n", +				  ret, oldval, newval, uaddr, oparg); +		break; +	case FUTEX_OP_OR: +		__futex_atomic_op("lr %2,%1\nor %2,%5\n", +				  ret, oldval, newval, uaddr, oparg); +		break; +	case FUTEX_OP_ANDN: +		__futex_atomic_op("lr %2,%1\nnr %2,%5\n", +				  ret, oldval, newval, uaddr, oparg); +		break; +	case FUTEX_OP_XOR: +		__futex_atomic_op("lr %2,%1\nxr %2,%5\n", +				  ret, oldval, newval, uaddr, oparg); +		break; +	default: +		ret = -ENOSYS; +	}  	pagefault_enable();  	if (!ret) { @@ -39,14 +74,23 @@ static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)  	return ret;  } -static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, -						int oldval, int newval) +static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +						u32 oldval, u32 newval)  { -	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int))) -		return -EFAULT; +	int ret; -	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval); +	load_kernel_asce(); +	asm volatile( +		"   sacf 256\n" +		"0: cs   %1,%4,0(%5)\n" +		"1: la   %0,0\n" +		"2: sacf 768\n" +		EX_TABLE(0b,2b) EX_TABLE(1b,2b) +		: "=d" (ret), "+d" (oldval), "=m" (*uaddr) +		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr) +		: "cc", "memory"); +	*uval = oldval; +	return ret;  } -#endif /* __KERNEL__ */  #endif /* _ASM_S390_FUTEX_H */ diff --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h index 881d94590ae..b7eabaaeffb 100644 --- a/arch/s390/include/asm/hardirq.h +++ b/arch/s390/include/asm/hardirq.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/hardirq.h - *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999, 2000   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),   *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)   * @@ -18,23 +16,11 @@  #define __ARCH_IRQ_STAT  #define __ARCH_HAS_DO_SOFTIRQ +#define __ARCH_IRQ_EXIT_IRQS_DISABLED -#define HARDIRQ_BITS	8 - -void clock_comparator_work(void); - -static inline unsigned long long local_tick_disable(void) -{ -	unsigned long long old; - -	old = S390_lowcore.clock_comparator; -	S390_lowcore.clock_comparator = -1ULL; -	return old; -} - -static inline void local_tick_enable(unsigned long long comp) +static inline void ack_bad_irq(unsigned int irq)  { -	S390_lowcore.clock_comparator = comp; +	printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);  }  #endif /* __ASM_HARDIRQ_H */ diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h index b56403c2df2..11eae5f55b7 100644 --- a/arch/s390/include/asm/hugetlb.h +++ b/arch/s390/include/asm/hugetlb.h @@ -17,6 +17,9 @@  void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,  		     pte_t *ptep, pte_t pte); +pte_t huge_ptep_get(pte_t *ptep); +pte_t huge_ptep_get_and_clear(struct mm_struct *mm, +			      unsigned long addr, pte_t *ptep);  /*   * If the arch doesn't supply something else, assume that hugepage @@ -33,128 +36,80 @@ static inline int prepare_hugepage_range(struct file *file,  }  #define hugetlb_prefault_arch_hook(mm)		do { } while (0) +#define arch_clear_hugepage_flags(page)		do { } while (0)  int arch_prepare_hugepage(struct page *page);  void arch_release_hugepage(struct page *page); -static inline pte_t huge_pte_wrprotect(pte_t pte) +static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr, +				  pte_t *ptep)  { -	pte_val(pte) |= _PAGE_RO; -	return pte; +	pte_val(*ptep) = _SEGMENT_ENTRY_EMPTY;  } -static inline int huge_pte_none(pte_t pte) +static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, +					 unsigned long address, pte_t *ptep)  { -	return (pte_val(pte) & _SEGMENT_ENTRY_INV) && -		!(pte_val(pte) & _SEGMENT_ENTRY_RO); +	huge_ptep_get_and_clear(vma->vm_mm, address, ptep);  } -static inline pte_t huge_ptep_get(pte_t *ptep) +static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, +					     unsigned long addr, pte_t *ptep, +					     pte_t pte, int dirty)  { -	pte_t pte = *ptep; -	unsigned long mask; - -	if (!MACHINE_HAS_HPAGE) { -		ptep = (pte_t *) (pte_val(pte) & _SEGMENT_ENTRY_ORIGIN); -		if (ptep) { -			mask = pte_val(pte) & -				(_SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO); -			pte = pte_mkhuge(*ptep); -			pte_val(pte) |= mask; -		} +	int changed = !pte_same(huge_ptep_get(ptep), pte); +	if (changed) { +		huge_ptep_get_and_clear(vma->vm_mm, addr, ptep); +		set_huge_pte_at(vma->vm_mm, addr, ptep, pte);  	} -	return pte; +	return changed;  } -static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, -					    unsigned long addr, pte_t *ptep) +static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, +					   unsigned long addr, pte_t *ptep)  { -	pte_t pte = huge_ptep_get(ptep); +	pte_t pte = huge_ptep_get_and_clear(mm, addr, ptep); +	set_huge_pte_at(mm, addr, ptep, pte_wrprotect(pte)); +} -	mm->context.flush_mm = 1; -	pmd_clear((pmd_t *) ptep); -	return pte; +static inline pte_t mk_huge_pte(struct page *page, pgprot_t pgprot) +{ +	return mk_pte(page, pgprot);  } -static inline void __pmd_csp(pmd_t *pmdp) +static inline int huge_pte_none(pte_t pte)  { -	register unsigned long reg2 asm("2") = pmd_val(*pmdp); -	register unsigned long reg3 asm("3") = pmd_val(*pmdp) | -					       _SEGMENT_ENTRY_INV; -	register unsigned long reg4 asm("4") = ((unsigned long) pmdp) + 5; - -	asm volatile( -		"	csp %1,%3" -		: "=m" (*pmdp) -		: "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc"); -	pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY; +	return pte_none(pte);  } -static inline void __pmd_idte(unsigned long address, pmd_t *pmdp) +static inline int huge_pte_write(pte_t pte)  { -	unsigned long sto = (unsigned long) pmdp - -				pmd_index(address) * sizeof(pmd_t); - -	if (!(pmd_val(*pmdp) & _SEGMENT_ENTRY_INV)) { -		asm volatile( -			"	.insn	rrf,0xb98e0000,%2,%3,0,0" -			: "=m" (*pmdp) -			: "m" (*pmdp), "a" (sto), -			  "a" ((address & HPAGE_MASK)) -		); -	} -	pmd_val(*pmdp) = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY; +	return pte_write(pte);  } -static inline void huge_ptep_invalidate(struct mm_struct *mm, -					unsigned long address, pte_t *ptep) +static inline int huge_pte_dirty(pte_t pte)  { -	pmd_t *pmdp = (pmd_t *) ptep; - -	if (!MACHINE_HAS_IDTE) { -		__pmd_csp(pmdp); -		if (mm->context.noexec) { -			pmdp = get_shadow_table(pmdp); -			__pmd_csp(pmdp); -		} -		return; -	} +	return pte_dirty(pte); +} -	__pmd_idte(address, pmdp); -	if (mm->context.noexec) { -		pmdp = get_shadow_table(pmdp); -		__pmd_idte(address, pmdp); -	} -	return; +static inline pte_t huge_pte_mkwrite(pte_t pte) +{ +	return pte_mkwrite(pte);  } -#define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \ -({									    \ -	int __changed = !pte_same(huge_ptep_get(__ptep), __entry);	    \ -	if (__changed) {						    \ -		huge_ptep_invalidate((__vma)->vm_mm, __addr, __ptep);	    \ -		set_huge_pte_at((__vma)->vm_mm, __addr, __ptep, __entry);   \ -	}								    \ -	__changed;							    \ -}) - -#define huge_ptep_set_wrprotect(__mm, __addr, __ptep)			\ -({									\ -	pte_t __pte = huge_ptep_get(__ptep);				\ -	if (pte_write(__pte)) {						\ -		(__mm)->context.flush_mm = 1;				\ -		if (atomic_read(&(__mm)->context.attach_count) > 1 ||	\ -		    (__mm) != current->active_mm)			\ -			huge_ptep_invalidate(__mm, __addr, __ptep);	\ -		set_huge_pte_at(__mm, __addr, __ptep,			\ -				huge_pte_wrprotect(__pte));		\ -	}								\ -}) +static inline pte_t huge_pte_mkdirty(pte_t pte) +{ +	return pte_mkdirty(pte); +} -static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, -					 unsigned long address, pte_t *ptep) +static inline pte_t huge_pte_wrprotect(pte_t pte) +{ +	return pte_wrprotect(pte); +} + +static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)  { -	huge_ptep_invalidate(vma->vm_mm, address, ptep); +	return pte_modify(pte, newprot);  }  #endif /* _ASM_S390_HUGETLB_H */ diff --git a/arch/s390/include/asm/hw_irq.h b/arch/s390/include/asm/hw_irq.h new file mode 100644 index 00000000000..ee96a8b697f --- /dev/null +++ b/arch/s390/include/asm/hw_irq.h @@ -0,0 +1,11 @@ +#ifndef _HW_IRQ_H +#define _HW_IRQ_H + +#include <linux/msi.h> +#include <linux/pci.h> + +void __init init_airq_interrupts(void); +void __init init_cio_interrupts(void); +void __init init_ext_interrupts(void); + +#endif diff --git a/arch/s390/include/asm/idals.h b/arch/s390/include/asm/idals.h index aae276d0038..ea5a6e45fd9 100644 --- a/arch/s390/include/asm/idals.h +++ b/arch/s390/include/asm/idals.h @@ -1,10 +1,9 @@  /*  - * File...........: linux/include/asm-s390x/idals.h   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>   *		    Martin Schwidefsky <schwidefsky@de.ibm.com>   * Bugreports.to..: <Linux390@de.ibm.com> - * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a -  + * Copyright IBM Corp. 2000 + *   * History of changes   * 07/24/00 new file   * 05/04/02 code restructuring. @@ -20,7 +19,7 @@  #include <asm/cio.h>  #include <asm/uaccess.h> -#ifdef __s390x__ +#ifdef CONFIG_64BIT  #define IDA_SIZE_LOG 12 /* 11 for 2k , 12 for 4k */  #else  #define IDA_SIZE_LOG 11 /* 11 for 2k , 12 for 4k */ @@ -33,7 +32,7 @@  static inline int  idal_is_needed(void *vaddr, unsigned int length)  { -#ifdef __s390x__ +#ifdef CONFIG_64BIT  	return ((__pa(vaddr) + length - 1) >> 31) != 0;  #else  	return 0; @@ -78,7 +77,7 @@ static inline unsigned long *idal_create_words(unsigned long *idaws,  static inline int  set_normalized_cda(struct ccw1 * ccw, void *vaddr)  { -#ifdef __s390x__ +#ifdef CONFIG_64BIT  	unsigned int nridaws;  	unsigned long *idal; @@ -105,7 +104,7 @@ set_normalized_cda(struct ccw1 * ccw, void *vaddr)  static inline void  clear_normalized_cda(struct ccw1 * ccw)  { -#ifdef __s390x__ +#ifdef CONFIG_64BIT  	if (ccw->flags & CCW_FLAG_IDA) {  		kfree((void *)(unsigned long) ccw->cda);  		ccw->flags &= ~CCW_FLAG_IDA; @@ -182,7 +181,7 @@ idal_buffer_free(struct idal_buffer *ib)  static inline int  __idal_buffer_is_needed(struct idal_buffer *ib)  { -#ifdef __s390x__ +#ifdef CONFIG_64BIT  	return ib->size > (4096ul << ib->page_order) ||  		idal_is_needed(ib->data[0], ib->size);  #else diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h index b7ff6afc3ca..cd6b9ee7b69 100644 --- a/arch/s390/include/asm/io.h +++ b/arch/s390/include/asm/io.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/io.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   *   *  Derived from "include/asm-i386/io.h" @@ -11,44 +9,64 @@  #ifndef _S390_IO_H  #define _S390_IO_H -#ifdef __KERNEL__ - +#include <linux/kernel.h>  #include <asm/page.h> +#include <asm/pci_io.h> -#define IO_SPACE_LIMIT 0xffffffff +void *xlate_dev_mem_ptr(unsigned long phys); +#define xlate_dev_mem_ptr xlate_dev_mem_ptr +void unxlate_dev_mem_ptr(unsigned long phys, void *addr);  /* - * Change virtual addresses to physical addresses and vv. - * These are pretty trivial + * Convert a virtual cached pointer to an uncached pointer   */ -static inline unsigned long virt_to_phys(volatile void * address) +#define xlate_dev_kmem_ptr(p)	p + +#define IO_SPACE_LIMIT 0 + +#ifdef CONFIG_PCI + +#define ioremap_nocache(addr, size)	ioremap(addr, size) +#define ioremap_wc			ioremap_nocache + +static inline void __iomem *ioremap(unsigned long offset, unsigned long size)  { -	unsigned long real_address; -	asm volatile( -		 "	lra	%0,0(%1)\n" -		 "	jz	0f\n" -		 "	la	%0,0\n" -                 "0:" -		 : "=a" (real_address) : "a" (address) : "cc"); -        return real_address; +	return (void __iomem *) offset;  } -static inline void * phys_to_virt(unsigned long address) +static inline void iounmap(volatile void __iomem *addr)  { -	return (void *) address;  }  /* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access + * s390 needs a private implementation of pci_iomap since ioremap with its + * offset parameter isn't sufficient. That's because BAR spaces are not + * disjunctive on s390 so we need the bar parameter of pci_iomap to find + * the corresponding device and create the mapping cookie.   */ -#define xlate_dev_mem_ptr(p)	__va(p) +#define pci_iomap pci_iomap +#define pci_iounmap pci_iounmap -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p)	p +#define memcpy_fromio(dst, src, count)	zpci_memcpy_fromio(dst, src, count) +#define memcpy_toio(dst, src, count)	zpci_memcpy_toio(dst, src, count) +#define memset_io(dst, val, count)	zpci_memset_io(dst, val, count) + +#define __raw_readb	zpci_read_u8 +#define __raw_readw	zpci_read_u16 +#define __raw_readl	zpci_read_u32 +#define __raw_readq	zpci_read_u64 +#define __raw_writeb	zpci_write_u8 +#define __raw_writew	zpci_write_u16 +#define __raw_writel	zpci_write_u32 +#define __raw_writeq	zpci_write_u64 + +#define readb_relaxed	readb +#define readw_relaxed	readw +#define readl_relaxed	readl +#define readq_relaxed	readq + +#endif /* CONFIG_PCI */ -#endif /* __KERNEL__ */ +#include <asm-generic/io.h>  #endif diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h index 5e95d95450b..2fcccc0c997 100644 --- a/arch/s390/include/asm/ipl.h +++ b/arch/s390/include/asm/ipl.h @@ -7,6 +7,7 @@  #ifndef _ASM_S390_IPL_H  #define _ASM_S390_IPL_H +#include <asm/lowcore.h>  #include <asm/types.h>  #include <asm/cio.h>  #include <asm/setup.h> @@ -86,7 +87,14 @@ struct ipl_parameter_block {   */  extern u32 ipl_flags;  extern u32 dump_prefix_page; -extern unsigned int zfcpdump_prefix_array[]; + +struct dump_save_areas { +	struct save_area **areas; +	int count; +}; + +extern struct dump_save_areas dump_save_areas; +struct save_area *dump_save_area_create(int cpu);  extern void do_reipl(void);  extern void do_halt(void); @@ -167,5 +175,8 @@ enum diag308_rc {  };  extern int diag308(unsigned long subcode, void *addr); +extern void diag308_reset(void); +extern void store_status(void); +extern void lgr_info_log(void);  #endif /* _ASM_S390_IPL_H */ diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index 7da991a858f..c4dd400a279 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h @@ -1,23 +1,109 @@  #ifndef _ASM_IRQ_H  #define _ASM_IRQ_H -#ifdef __KERNEL__ -#include <linux/hardirq.h> +#define EXT_INTERRUPT	1 +#define IO_INTERRUPT	2 +#define THIN_INTERRUPT	3 + +#define NR_IRQS_BASE	4 + +#ifdef CONFIG_PCI_NR_MSI +# define NR_IRQS	(NR_IRQS_BASE + CONFIG_PCI_NR_MSI) +#else +# define NR_IRQS	NR_IRQS_BASE +#endif + +/* This number is used when no interrupt has been assigned */ +#define NO_IRQ		0 + +/* External interruption codes */ +#define EXT_IRQ_INTERRUPT_KEY	0x0040 +#define EXT_IRQ_CLK_COMP	0x1004 +#define EXT_IRQ_CPU_TIMER	0x1005 +#define EXT_IRQ_WARNING_TRACK	0x1007 +#define EXT_IRQ_MALFUNC_ALERT	0x1200 +#define EXT_IRQ_EMERGENCY_SIG	0x1201 +#define EXT_IRQ_EXTERNAL_CALL	0x1202 +#define EXT_IRQ_TIMING_ALERT	0x1406 +#define EXT_IRQ_MEASURE_ALERT	0x1407 +#define EXT_IRQ_SERVICE_SIG	0x2401 +#define EXT_IRQ_CP_SERVICE	0x2603 +#define EXT_IRQ_IUCV		0x4000 -/* - * the definition of irqs has changed in 2.5.46: - * NR_IRQS is no longer the number of i/o - * interrupts (65536), but rather the number - * of interrupt classes (2). - * Only external and i/o interrupts make much sense here (CH). - */ +#ifndef __ASSEMBLY__ + +#include <linux/hardirq.h> +#include <linux/percpu.h> +#include <linux/cache.h> +#include <linux/types.h>  enum interruption_class { -	EXTERNAL_INTERRUPT, -	IO_INTERRUPT, +	IRQEXT_CLK, +	IRQEXT_EXC, +	IRQEXT_EMS, +	IRQEXT_TMR, +	IRQEXT_TLA, +	IRQEXT_PFL, +	IRQEXT_DSD, +	IRQEXT_VRT, +	IRQEXT_SCP, +	IRQEXT_IUC, +	IRQEXT_CMS, +	IRQEXT_CMC, +	IRQEXT_CMR, +	IRQIO_CIO, +	IRQIO_QAI, +	IRQIO_DAS, +	IRQIO_C15, +	IRQIO_C70, +	IRQIO_TAP, +	IRQIO_VMR, +	IRQIO_LCS, +	IRQIO_CLW, +	IRQIO_CTC, +	IRQIO_APB, +	IRQIO_ADM, +	IRQIO_CSC, +	IRQIO_PCI, +	IRQIO_MSI, +	IRQIO_VIR, +	IRQIO_VAI, +	NMI_NMI, +	CPU_RST, +	NR_ARCH_IRQS +}; -	NR_IRQS, +struct irq_stat { +	unsigned int irqs[NR_ARCH_IRQS];  }; -#endif /* __KERNEL__ */ -#endif +DECLARE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat); + +static __always_inline void inc_irq_stat(enum interruption_class irq) +{ +	__get_cpu_var(irq_stat).irqs[irq]++; +} + +struct ext_code { +	unsigned short subcode; +	unsigned short code; +}; + +typedef void (*ext_int_handler_t)(struct ext_code, unsigned int, unsigned long); + +int register_external_irq(u16 code, ext_int_handler_t handler); +int unregister_external_irq(u16 code, ext_int_handler_t handler); + +enum irq_subclass { +	IRQ_SUBCLASS_MEASUREMENT_ALERT = 5, +	IRQ_SUBCLASS_SERVICE_SIGNAL = 9, +}; + +void irq_subclass_register(enum irq_subclass subclass); +void irq_subclass_unregister(enum irq_subclass subclass); + +#define irq_canonicalize(irq)  (irq) + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_IRQ_H */ diff --git a/arch/s390/include/asm/irqflags.h b/arch/s390/include/asm/irqflags.h index 865d6d891ac..37b9091ab8c 100644 --- a/arch/s390/include/asm/irqflags.h +++ b/arch/s390/include/asm/irqflags.h @@ -1,5 +1,5 @@  /* - *    Copyright IBM Corp. 2006,2010 + *    Copyright IBM Corp. 2006, 2010   *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>   */ @@ -29,42 +29,42 @@  })  /* set system mask. */ -static inline void __arch_local_irq_ssm(unsigned long flags) +static inline notrace void __arch_local_irq_ssm(unsigned long flags)  {  	asm volatile("ssm   %0" : : "Q" (flags) : "memory");  } -static inline unsigned long arch_local_save_flags(void) +static inline notrace unsigned long arch_local_save_flags(void)  {  	return __arch_local_irq_stosm(0x00);  } -static inline unsigned long arch_local_irq_save(void) +static inline notrace unsigned long arch_local_irq_save(void)  {  	return __arch_local_irq_stnsm(0xfc);  } -static inline void arch_local_irq_disable(void) +static inline notrace void arch_local_irq_disable(void)  {  	arch_local_irq_save();  } -static inline void arch_local_irq_enable(void) +static inline notrace void arch_local_irq_enable(void)  {  	__arch_local_irq_stosm(0x03);  } -static inline void arch_local_irq_restore(unsigned long flags) +static inline notrace void arch_local_irq_restore(unsigned long flags)  {  	__arch_local_irq_ssm(flags);  } -static inline bool arch_irqs_disabled_flags(unsigned long flags) +static inline notrace bool arch_irqs_disabled_flags(unsigned long flags)  {  	return !(flags & (3UL << (BITS_PER_LONG - 8)));  } -static inline bool arch_irqs_disabled(void) +static inline notrace bool arch_irqs_disabled(void)  {  	return arch_irqs_disabled_flags(arch_local_save_flags());  } diff --git a/arch/s390/include/asm/isc.h b/arch/s390/include/asm/isc.h index 1420a111594..68d7d68300f 100644 --- a/arch/s390/include/asm/isc.h +++ b/arch/s390/include/asm/isc.h @@ -14,9 +14,11 @@  /* Regular I/O interrupts. */  #define IO_SCH_ISC 3			/* regular I/O subchannels */  #define CONSOLE_ISC 1			/* console I/O subchannel */ +#define EADM_SCH_ISC 4			/* EADM subchannels */  #define CHSC_SCH_ISC 7			/* CHSC subchannels */  /* Adapter interrupts. */  #define QDIO_AIRQ_ISC IO_SCH_ISC	/* I/O subchannel in qdio mode */ +#define PCI_ISC 2			/* PCI I/O subchannels */  #define AP_ISC 6			/* adjunct processor (crypto) devices */  /* Functions for registration of I/O interruption subclasses */ diff --git a/arch/s390/include/asm/itcw.h b/arch/s390/include/asm/itcw.h index a9bc5c36b32..fb1bedd3dc0 100644 --- a/arch/s390/include/asm/itcw.h +++ b/arch/s390/include/asm/itcw.h @@ -6,7 +6,7 @@   */  #ifndef _ASM_S390_ITCW_H -#define _ASM_S390_ITCW_H _ASM_S390_ITCW_H +#define _ASM_S390_ITCW_H  #include <linux/types.h>  #include <asm/fcx.h> diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h new file mode 100644 index 00000000000..346b1c85ffb --- /dev/null +++ b/arch/s390/include/asm/jump_label.h @@ -0,0 +1,37 @@ +#ifndef _ASM_S390_JUMP_LABEL_H +#define _ASM_S390_JUMP_LABEL_H + +#include <linux/types.h> + +#define JUMP_LABEL_NOP_SIZE 6 + +#ifdef CONFIG_64BIT +#define ASM_PTR ".quad" +#define ASM_ALIGN ".balign 8" +#else +#define ASM_PTR ".long" +#define ASM_ALIGN ".balign 4" +#endif + +static __always_inline bool arch_static_branch(struct static_key *key) +{ +	asm_volatile_goto("0:	brcl 0,0\n" +		".pushsection __jump_table, \"aw\"\n" +		ASM_ALIGN "\n" +		ASM_PTR " 0b, %l[label], %0\n" +		".popsection\n" +		: : "X" (key) : : label); +	return false; +label: +	return true; +} + +typedef unsigned long jump_label_t; + +struct jump_entry { +	jump_label_t code; +	jump_label_t target; +	jump_label_t key; +}; + +#endif diff --git a/arch/s390/include/asm/kdebug.h b/arch/s390/include/asm/kdebug.h index 40db27cd6e6..5c1abd47612 100644 --- a/arch/s390/include/asm/kdebug.h +++ b/arch/s390/include/asm/kdebug.h @@ -22,6 +22,6 @@ enum die_val {  	DIE_NMI_IPI,  }; -extern void die(const char *, struct pt_regs *, long); +extern void die(struct pt_regs *, const char *);  #endif diff --git a/arch/s390/include/asm/kexec.h b/arch/s390/include/asm/kexec.h index bb729b84a21..694bcd6bd92 100644 --- a/arch/s390/include/asm/kexec.h +++ b/arch/s390/include/asm/kexec.h @@ -1,7 +1,5 @@  /* - * include/asm-s390/kexec.h - * - * (C) Copyright IBM Corp. 2005 + * Copyright IBM Corp. 2005   *   * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>   * @@ -10,10 +8,8 @@  #ifndef _S390_KEXEC_H  #define _S390_KEXEC_H -#ifdef __KERNEL__ -#include <asm/page.h> -#endif  #include <asm/processor.h> +#include <asm/page.h>  /*   * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.   * I.e. Maximum page that is mapped directly into kernel memory, @@ -30,12 +26,36 @@  /* Not more than 2GB */  #define KEXEC_CONTROL_MEMORY_LIMIT (1UL<<31) +/* Maximum address we can use for the crash control pages */ +#define KEXEC_CRASH_CONTROL_MEMORY_LIMIT (-1UL) +  /* Allocate one page for the pdp and the second for the code */  #define KEXEC_CONTROL_PAGE_SIZE 4096 +/* Alignment of crashkernel memory */ +#define KEXEC_CRASH_MEM_ALIGN HPAGE_SIZE +  /* The native architecture */  #define KEXEC_ARCH KEXEC_ARCH_S390 +/* + * Size for s390x ELF notes per CPU + * + * Seven notes plus zero note at the end: prstatus, fpregset, timer, + * tod_cmp, tod_reg, control regs, and prefix + */ +#define KEXEC_NOTE_BYTES \ +	(ALIGN(sizeof(struct elf_note), 4) * 8 + \ +	 ALIGN(sizeof("CORE"), 4) * 7 + \ +	 ALIGN(sizeof(struct elf_prstatus), 4) + \ +	 ALIGN(sizeof(elf_fpregset_t), 4) + \ +	 ALIGN(sizeof(u64), 4) + \ +	 ALIGN(sizeof(u64), 4) + \ +	 ALIGN(sizeof(u32), 4) + \ +	 ALIGN(sizeof(u64) * 16, 4) + \ +	 ALIGN(sizeof(u32), 4) \ +	) +  /* Provide a dummy definition to avoid build failures. */  static inline void crash_setup_regs(struct pt_regs *newregs,  					struct pt_regs *oldregs) { } diff --git a/arch/s390/include/asm/kmap_types.h b/arch/s390/include/asm/kmap_types.h index 94ec3ee0798..0a88622339e 100644 --- a/arch/s390/include/asm/kmap_types.h +++ b/arch/s390/include/asm/kmap_types.h @@ -1,8 +1,6 @@ -#ifdef __KERNEL__  #ifndef _ASM_KMAP_TYPES_H  #define _ASM_KMAP_TYPES_H  #include <asm-generic/kmap_types.h>  #endif -#endif /* __KERNEL__ */ diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h index 330f68caffe..4176dfe0fba 100644 --- a/arch/s390/include/asm/kprobes.h +++ b/arch/s390/include/asm/kprobes.h @@ -17,7 +17,7 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.   * - * Copyright (C) IBM Corporation, 2002, 2006 + * Copyright IBM Corp. 2002, 2006   *   * 2002-Oct	Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel   *		Probes initial implementation ( includes suggestions from @@ -31,7 +31,8 @@  #include <linux/ptrace.h>  #include <linux/percpu.h> -#define  __ARCH_WANT_KPROBES_INSN_SLOT +#define __ARCH_WANT_KPROBES_INSN_SLOT +  struct pt_regs;  struct kprobe; @@ -59,22 +60,11 @@ typedef u16 kprobe_opcode_t;  struct arch_specific_insn {  	/* copy of original instruction */  	kprobe_opcode_t *insn; -	int fixup; -	int ilen; -	int reg;  }; -struct ins_replace_args { -	kprobe_opcode_t *ptr; -	kprobe_opcode_t old; -	kprobe_opcode_t new; -};  struct prev_kprobe {  	struct kprobe *kp;  	unsigned long status; -	unsigned long saved_psw; -	unsigned long kprobe_saved_imask; -	unsigned long kprobe_saved_ctl[3];  };  /* per-cpu kprobe control block */ @@ -82,17 +72,13 @@ struct kprobe_ctlblk {  	unsigned long kprobe_status;  	unsigned long kprobe_saved_imask;  	unsigned long kprobe_saved_ctl[3]; -	struct pt_regs jprobe_saved_regs; -	unsigned long jprobe_saved_r14; -	unsigned long jprobe_saved_r15;  	struct prev_kprobe prev_kprobe; +	struct pt_regs jprobe_saved_regs;  	kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];  };  void arch_remove_kprobe(struct kprobe *p);  void kretprobe_trampoline(void); -int  is_prohibited_opcode(kprobe_opcode_t *instruction); -void get_instruction_type(struct arch_specific_insn *ainsn);  int kprobe_fault_handler(struct pt_regs *regs, int trapnr);  int kprobe_exceptions_notify(struct notifier_block *self, diff --git a/arch/s390/include/asm/kvm.h b/arch/s390/include/asm/kvm.h deleted file mode 100644 index 82b32a100c7..00000000000 --- a/arch/s390/include/asm/kvm.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __LINUX_KVM_S390_H -#define __LINUX_KVM_S390_H -/* - * asm-s390/kvm.h - KVM s390 specific structures and definitions - * - * Copyright IBM Corp. 2008 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License (version 2 only) - * as published by the Free Software Foundation. - * - *    Author(s): Carsten Otte <cotte@de.ibm.com> - *               Christian Borntraeger <borntraeger@de.ibm.com> - */ -#include <linux/types.h> - -#define __KVM_S390 - -/* for KVM_GET_REGS and KVM_SET_REGS */ -struct kvm_regs { -	/* general purpose regs for s390 */ -	__u64 gprs[16]; -}; - -/* for KVM_GET_SREGS and KVM_SET_SREGS */ -struct kvm_sregs { -	__u32 acrs[16]; -	__u64 crs[16]; -}; - -/* for KVM_GET_FPU and KVM_SET_FPU */ -struct kvm_fpu { -	__u32 fpc; -	__u64 fprs[16]; -}; - -struct kvm_debug_exit_arch { -}; - -/* for KVM_SET_GUEST_DEBUG */ -struct kvm_guest_debug_arch { -}; - -#endif diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index cef7dbf69df..4181d7baabb 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -1,7 +1,7 @@  /* - * asm-s390/kvm_host.h - definition for kernel virtual machines on s390 + * definition for kernel virtual machines on s390   * - * Copyright IBM Corp. 2008,2009 + * Copyright IBM Corp. 2008, 2009   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License (version 2 only) @@ -16,38 +16,49 @@  #include <linux/hrtimer.h>  #include <linux/interrupt.h>  #include <linux/kvm_host.h> +#include <linux/kvm.h>  #include <asm/debug.h>  #include <asm/cpu.h> +#include <asm/isc.h>  #define KVM_MAX_VCPUS 64 -#define KVM_MEMORY_SLOTS 32 -/* memory slots that does not exposed to userspace */ -#define KVM_PRIVATE_MEM_SLOTS 4 +#define KVM_USER_MEM_SLOTS 32 + +/* + * These seem to be used for allocating ->chip in the routing table, + * which we don't use. 4096 is an out-of-thin-air value. If we need + * to look at ->chip later on, we'll need to revisit this. + */ +#define KVM_NR_IRQCHIPS 1 +#define KVM_IRQCHIP_NUM_PINS 4096 + +#define SIGP_CTRL_C	0x00800000  struct sca_entry { -	atomic_t scn; +	atomic_t ctrl;  	__u32	reserved;  	__u64	sda;  	__u64	reserved2[2];  } __attribute__((packed)); +union ipte_control { +	unsigned long val; +	struct { +		unsigned long k  : 1; +		unsigned long kh : 31; +		unsigned long kg : 32; +	}; +};  struct sca_block { -	__u64	ipte_control; +	union ipte_control ipte_control;  	__u64	reserved[5];  	__u64	mcn;  	__u64	reserved2;  	struct sca_entry cpu[64];  } __attribute__((packed)); -#define KVM_NR_PAGE_SIZES 2 -#define KVM_HPAGE_GFN_SHIFT(x) (((x) - 1) * 8) -#define KVM_HPAGE_SHIFT(x) (PAGE_SHIFT + KVM_HPAGE_GFN_SHIFT(x)) -#define KVM_HPAGE_SIZE(x) (1UL << KVM_HPAGE_SHIFT(x)) -#define KVM_HPAGE_MASK(x)	(~(KVM_HPAGE_SIZE(x) - 1)) -#define KVM_PAGES_PER_HPAGE(x)	(KVM_HPAGE_SIZE(x) / PAGE_SIZE) - -#define CPUSTAT_HOST       0x80000000 +#define CPUSTAT_STOPPED    0x80000000  #define CPUSTAT_WAIT       0x10000000  #define CPUSTAT_ECALL_PEND 0x08000000  #define CPUSTAT_STOP_INT   0x04000000 @@ -63,23 +74,51 @@ struct sca_block {  #define CPUSTAT_ZARCH      0x00000800  #define CPUSTAT_MCDS       0x00000100  #define CPUSTAT_SM         0x00000080 +#define CPUSTAT_IBS        0x00000040  #define CPUSTAT_G          0x00000008 +#define CPUSTAT_GED        0x00000004  #define CPUSTAT_J          0x00000002  #define CPUSTAT_P          0x00000001  struct kvm_s390_sie_block {  	atomic_t cpuflags;		/* 0x0000 */ -	__u32	prefix;			/* 0x0004 */ -	__u8	reserved8[32];		/* 0x0008 */ +	__u32 : 1;			/* 0x0004 */ +	__u32 prefix : 18; +	__u32 : 13; +	__u8	reserved08[4];		/* 0x0008 */ +#define PROG_IN_SIE (1<<0) +	__u32	prog0c;			/* 0x000c */ +	__u8	reserved10[16];		/* 0x0010 */ +#define PROG_BLOCK_SIE 0x00000001 +	atomic_t prog20;		/* 0x0020 */ +	__u8	reserved24[4];		/* 0x0024 */  	__u64	cputm;			/* 0x0028 */  	__u64	ckc;			/* 0x0030 */  	__u64	epoch;			/* 0x0038 */  	__u8	reserved40[4];		/* 0x0040 */  #define LCTL_CR0	0x8000 +#define LCTL_CR6	0x0200 +#define LCTL_CR9	0x0040 +#define LCTL_CR10	0x0020 +#define LCTL_CR11	0x0010 +#define LCTL_CR14	0x0002  	__u16   lctl;			/* 0x0044 */  	__s16	icpua;			/* 0x0046 */ +#define ICTL_PINT	0x20000000 +#define ICTL_LPSW	0x00400000 +#define ICTL_STCTL	0x00040000 +#define ICTL_ISKE	0x00004000 +#define ICTL_SSKE	0x00002000 +#define ICTL_RRBE	0x00001000 +#define ICTL_TPROT	0x00000200  	__u32	ictl;			/* 0x0048 */  	__u32	eca;			/* 0x004c */ +#define ICPT_INST	0x04 +#define ICPT_PROGI	0x08 +#define ICPT_INSTPROGI	0x0C +#define ICPT_OPEREXC	0x2C +#define ICPT_PARTEXEC	0x38 +#define ICPT_IOINST	0x40  	__u8	icptcode;		/* 0x0050 */  	__u8	reserved51;		/* 0x0051 */  	__u16	ihcpu;			/* 0x0052 */ @@ -89,26 +128,57 @@ struct kvm_s390_sie_block {  	__u32	scaoh;			/* 0x005c */  	__u8	reserved60;		/* 0x0060 */  	__u8	ecb;			/* 0x0061 */ -	__u8	reserved62[2];		/* 0x0062 */ +	__u8    ecb2;                   /* 0x0062 */ +	__u8    reserved63[1];          /* 0x0063 */  	__u32	scaol;			/* 0x0064 */  	__u8	reserved68[4];		/* 0x0068 */  	__u32	todpr;			/* 0x006c */ -	__u8	reserved70[16];		/* 0x0070 */ -	__u64	gmsor;			/* 0x0080 */ -	__u64	gmslm;			/* 0x0088 */ +	__u8	reserved70[32];		/* 0x0070 */  	psw_t	gpsw;			/* 0x0090 */  	__u64	gg14;			/* 0x00a0 */  	__u64	gg15;			/* 0x00a8 */ -	__u8	reservedb0[30];		/* 0x00b0 */ -	__u16   iprcc;			/* 0x00ce */ -	__u8	reservedd0[48];		/* 0x00d0 */ +	__u8	reservedb0[20];		/* 0x00b0 */ +	__u16	extcpuaddr;		/* 0x00c4 */ +	__u16	eic;			/* 0x00c6 */ +	__u32	reservedc8;		/* 0x00c8 */ +	__u16	pgmilc;			/* 0x00cc */ +	__u16	iprcc;			/* 0x00ce */ +	__u32	dxc;			/* 0x00d0 */ +	__u16	mcn;			/* 0x00d4 */ +	__u8	perc;			/* 0x00d6 */ +	__u8	peratmid;		/* 0x00d7 */ +	__u64	peraddr;		/* 0x00d8 */ +	__u8	eai;			/* 0x00e0 */ +	__u8	peraid;			/* 0x00e1 */ +	__u8	oai;			/* 0x00e2 */ +	__u8	armid;			/* 0x00e3 */ +	__u8	reservede4[4];		/* 0x00e4 */ +	__u64	tecmc;			/* 0x00e8 */ +	__u8	reservedf0[16];		/* 0x00f0 */  	__u64	gcr[16];		/* 0x0100 */  	__u64	gbea;			/* 0x0180 */  	__u8	reserved188[24];	/* 0x0188 */  	__u32	fac;			/* 0x01a0 */ -	__u8	reserved1a4[92];	/* 0x01a4 */ +	__u8	reserved1a4[20];	/* 0x01a4 */ +	__u64	cbrlo;			/* 0x01b8 */ +	__u8	reserved1c0[30];	/* 0x01c0 */ +	__u64	pp;			/* 0x01de */ +	__u8	reserved1e6[2];		/* 0x01e6 */ +	__u64	itdba;			/* 0x01e8 */ +	__u8	reserved1f0[16];	/* 0x01f0 */  } __attribute__((packed)); +struct kvm_s390_itdb { +	__u8	data[256]; +} __packed; + +struct sie_page { +	struct kvm_s390_sie_block sie_block; +	__u8 reserved200[1024];		/* 0x0200 */ +	struct kvm_s390_itdb itdb;	/* 0x0600 */ +	__u8 reserved700[2304];		/* 0x0700 */ +} __packed; +  struct kvm_vcpu_stat {  	u32 exit_userspace;  	u32 exit_null; @@ -119,8 +189,11 @@ struct kvm_vcpu_stat {  	u32 exit_instruction;  	u32 instruction_lctl;  	u32 instruction_lctlg; +	u32 instruction_stctl; +	u32 instruction_stctg;  	u32 exit_program_interruption;  	u32 exit_instr_and_program; +	u32 deliver_external_call;  	u32 deliver_emergency_signal;  	u32 deliver_service_signal;  	u32 deliver_virtio_interrupt; @@ -128,52 +201,86 @@ struct kvm_vcpu_stat {  	u32 deliver_prefix_signal;  	u32 deliver_restart_signal;  	u32 deliver_program_int; +	u32 deliver_io_int;  	u32 exit_wait_state; +	u32 instruction_pfmf;  	u32 instruction_stidp;  	u32 instruction_spx;  	u32 instruction_stpx;  	u32 instruction_stap;  	u32 instruction_storage_key; +	u32 instruction_ipte_interlock;  	u32 instruction_stsch;  	u32 instruction_chsc;  	u32 instruction_stsi;  	u32 instruction_stfl; +	u32 instruction_tprot; +	u32 instruction_essa;  	u32 instruction_sigp_sense; +	u32 instruction_sigp_sense_running; +	u32 instruction_sigp_external_call;  	u32 instruction_sigp_emergency;  	u32 instruction_sigp_stop;  	u32 instruction_sigp_arch;  	u32 instruction_sigp_prefix;  	u32 instruction_sigp_restart; +	u32 diagnose_10;  	u32 diagnose_44; +	u32 diagnose_9c;  }; -struct kvm_s390_io_info { -	__u16        subchannel_id;            /* 0x0b8 */ -	__u16        subchannel_nr;            /* 0x0ba */ -	__u32        io_int_parm;              /* 0x0bc */ -	__u32        io_int_word;              /* 0x0c0 */ -}; - -struct kvm_s390_ext_info { -	__u32 ext_params; -	__u64 ext_params2; -}; - -#define PGM_OPERATION            0x01 -#define PGM_PRIVILEGED_OPERATION 0x02 -#define PGM_EXECUTE              0x03 -#define PGM_PROTECTION           0x04 -#define PGM_ADDRESSING           0x05 -#define PGM_SPECIFICATION        0x06 -#define PGM_DATA                 0x07 - -struct kvm_s390_pgm_info { -	__u16 code; -}; - -struct kvm_s390_prefix_info { -	__u32 address; -}; +#define PGM_OPERATION			0x01 +#define PGM_PRIVILEGED_OP		0x02 +#define PGM_EXECUTE			0x03 +#define PGM_PROTECTION			0x04 +#define PGM_ADDRESSING			0x05 +#define PGM_SPECIFICATION		0x06 +#define PGM_DATA			0x07 +#define PGM_FIXED_POINT_OVERFLOW	0x08 +#define PGM_FIXED_POINT_DIVIDE		0x09 +#define PGM_DECIMAL_OVERFLOW		0x0a +#define PGM_DECIMAL_DIVIDE		0x0b +#define PGM_HFP_EXPONENT_OVERFLOW	0x0c +#define PGM_HFP_EXPONENT_UNDERFLOW	0x0d +#define PGM_HFP_SIGNIFICANCE		0x0e +#define PGM_HFP_DIVIDE			0x0f +#define PGM_SEGMENT_TRANSLATION		0x10 +#define PGM_PAGE_TRANSLATION		0x11 +#define PGM_TRANSLATION_SPEC		0x12 +#define PGM_SPECIAL_OPERATION		0x13 +#define PGM_OPERAND			0x15 +#define PGM_TRACE_TABEL			0x16 +#define PGM_SPACE_SWITCH		0x1c +#define PGM_HFP_SQUARE_ROOT		0x1d +#define PGM_PC_TRANSLATION_SPEC		0x1f +#define PGM_AFX_TRANSLATION		0x20 +#define PGM_ASX_TRANSLATION		0x21 +#define PGM_LX_TRANSLATION		0x22 +#define PGM_EX_TRANSLATION		0x23 +#define PGM_PRIMARY_AUTHORITY		0x24 +#define PGM_SECONDARY_AUTHORITY		0x25 +#define PGM_LFX_TRANSLATION		0x26 +#define PGM_LSX_TRANSLATION		0x27 +#define PGM_ALET_SPECIFICATION		0x28 +#define PGM_ALEN_TRANSLATION		0x29 +#define PGM_ALE_SEQUENCE		0x2a +#define PGM_ASTE_VALIDITY		0x2b +#define PGM_ASTE_SEQUENCE		0x2c +#define PGM_EXTENDED_AUTHORITY		0x2d +#define PGM_LSTE_SEQUENCE		0x2e +#define PGM_ASTE_INSTANCE		0x2f +#define PGM_STACK_FULL			0x30 +#define PGM_STACK_EMPTY			0x31 +#define PGM_STACK_SPECIFICATION		0x32 +#define PGM_STACK_TYPE			0x33 +#define PGM_STACK_OPERATION		0x34 +#define PGM_ASCE_TYPE			0x38 +#define PGM_REGION_FIRST_TRANS		0x39 +#define PGM_REGION_SECOND_TRANS		0x3a +#define PGM_REGION_THIRD_TRANS		0x3b +#define PGM_MONITOR			0x40 +#define PGM_PER				0x80 +#define PGM_CRYPTO_OPERATION		0x119  struct kvm_s390_interrupt_info {  	struct list_head list; @@ -182,14 +289,16 @@ struct kvm_s390_interrupt_info {  		struct kvm_s390_io_info io;  		struct kvm_s390_ext_info ext;  		struct kvm_s390_pgm_info pgm; +		struct kvm_s390_emerg_info emerg; +		struct kvm_s390_extcall_info extcall;  		struct kvm_s390_prefix_info prefix; +		struct kvm_s390_mchk_info mchk;  	};  };  /* for local_interrupt.action_flags */  #define ACTION_STORE_ON_STOP		(1<<0)  #define ACTION_STOP_ON_STOP		(1<<1) -#define ACTION_RELOADVCPU_ON_STOP	(1<<2)  struct kvm_s390_local_interrupt {  	spinlock_t lock; @@ -197,7 +306,7 @@ struct kvm_s390_local_interrupt {  	atomic_t active;  	struct kvm_s390_float_interrupt *float_int;  	int timer_due; /* event indicator for waitqueue below */ -	wait_queue_head_t wq; +	wait_queue_head_t *wq;  	atomic_t *cpuflags;  	unsigned int action_bits;  }; @@ -207,36 +316,139 @@ struct kvm_s390_float_interrupt {  	struct list_head list;  	atomic_t active;  	int next_rr_cpu; -	unsigned long idle_mask [(64 + sizeof(long) - 1) / sizeof(long)]; -	struct kvm_s390_local_interrupt *local_int[64]; +	unsigned long idle_mask[BITS_TO_LONGS(KVM_MAX_VCPUS)]; +	unsigned int irq_count; +}; + +struct kvm_hw_wp_info_arch { +	unsigned long addr; +	unsigned long phys_addr; +	int len; +	char *old_data; +}; + +struct kvm_hw_bp_info_arch { +	unsigned long addr; +	int len;  }; +/* + * Only the upper 16 bits of kvm_guest_debug->control are arch specific. + * Further KVM_GUESTDBG flags which an be used from userspace can be found in + * arch/s390/include/uapi/asm/kvm.h + */ +#define KVM_GUESTDBG_EXIT_PENDING 0x10000000 + +#define guestdbg_enabled(vcpu) \ +		(vcpu->guest_debug & KVM_GUESTDBG_ENABLE) +#define guestdbg_sstep_enabled(vcpu) \ +		(vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) +#define guestdbg_hw_bp_enabled(vcpu) \ +		(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP) +#define guestdbg_exit_pending(vcpu) (guestdbg_enabled(vcpu) && \ +		(vcpu->guest_debug & KVM_GUESTDBG_EXIT_PENDING)) + +struct kvm_guestdbg_info_arch { +	unsigned long cr0; +	unsigned long cr9; +	unsigned long cr10; +	unsigned long cr11; +	struct kvm_hw_bp_info_arch *hw_bp_info; +	struct kvm_hw_wp_info_arch *hw_wp_info; +	int nr_hw_bp; +	int nr_hw_wp; +	unsigned long last_bp; +};  struct kvm_vcpu_arch {  	struct kvm_s390_sie_block *sie_block; -	unsigned long	  guest_gprs[16];  	s390_fp_regs      host_fpregs;  	unsigned int      host_acrs[NUM_ACRS];  	s390_fp_regs      guest_fpregs; -	unsigned int      guest_acrs[NUM_ACRS];  	struct kvm_s390_local_interrupt local_int;  	struct hrtimer    ckc_timer;  	struct tasklet_struct tasklet; +	struct kvm_s390_pgm_info pgm;  	union  {  		struct cpuid	cpu_id;  		u64		stidp_data;  	}; +	struct gmap *gmap; +	struct kvm_guestdbg_info_arch guestdbg; +#define KVM_S390_PFAULT_TOKEN_INVALID	(-1UL) +	unsigned long pfault_token; +	unsigned long pfault_select; +	unsigned long pfault_compare;  };  struct kvm_vm_stat {  	u32 remote_tlb_flush;  }; +struct kvm_arch_memory_slot { +}; + +struct s390_map_info { +	struct list_head list; +	__u64 guest_addr; +	__u64 addr; +	struct page *page; +}; + +struct s390_io_adapter { +	unsigned int id; +	int isc; +	bool maskable; +	bool masked; +	bool swap; +	struct rw_semaphore maps_lock; +	struct list_head maps; +	atomic_t nr_maps; +}; + +#define MAX_S390_IO_ADAPTERS ((MAX_ISC + 1) * 8) +#define MAX_S390_ADAPTER_MAPS 256 +  struct kvm_arch{  	struct sca_block *sca;  	debug_info_t *dbf;  	struct kvm_s390_float_interrupt float_int; +	struct kvm_device *flic; +	struct gmap *gmap; +	int css_support; +	int use_irqchip; +	int use_cmma; +	struct s390_io_adapter *adapters[MAX_S390_IO_ADAPTERS]; +	wait_queue_head_t ipte_wq; +	spinlock_t start_stop_lock; +}; + +#define KVM_HVA_ERR_BAD		(-1UL) +#define KVM_HVA_ERR_RO_BAD	(-2UL) + +static inline bool kvm_is_error_hva(unsigned long addr) +{ +	return IS_ERR_VALUE(addr); +} + +#define ASYNC_PF_PER_VCPU	64 +struct kvm_vcpu; +struct kvm_async_pf; +struct kvm_arch_async_pf { +	unsigned long pfault_token;  }; -extern int sie64a(struct kvm_s390_sie_block *, unsigned long *); +bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu); + +void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, +			       struct kvm_async_pf *work); + +void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu, +				     struct kvm_async_pf *work); + +void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, +				 struct kvm_async_pf *work); + +extern int sie64a(struct kvm_s390_sie_block *, u64 *); +extern char sie_exit;  #endif diff --git a/arch/s390/include/asm/kvm_para.h b/arch/s390/include/asm/kvm_para.h index 6964db226f8..e0f842308a6 100644 --- a/arch/s390/include/asm/kvm_para.h +++ b/arch/s390/include/asm/kvm_para.h @@ -1,5 +1,5 @@  /* - * asm-s390/kvm_para.h - definition for paravirtual devices on s390 + * definition for paravirtual devices on s390   *   * Copyright IBM Corp. 2008   * @@ -9,12 +9,6 @@   *   *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>   */ - -#ifndef __S390_KVM_PARA_H -#define __S390_KVM_PARA_H - -#ifdef __KERNEL__ -  /*   * Hypercalls for KVM on s390. The calling convention is similar to the   * s390 ABI, so we use R2-R6 for parameters 1-5. In addition we use R1 @@ -29,6 +23,12 @@   *   * This work is licensed under the terms of the GNU GPL, version 2.   */ +#ifndef __S390_KVM_PARA_H +#define __S390_KVM_PARA_H + +#include <uapi/asm/kvm_para.h> + +  static inline long kvm_hypercall0(unsigned long nr)  { @@ -149,6 +149,9 @@ static inline unsigned int kvm_arch_para_features(void)  	return 0;  } -#endif +static inline bool kvm_check_and_clear_guest_paused(void) +{ +	return false; +}  #endif /* __S390_KVM_PARA_H */ diff --git a/arch/s390/include/asm/linkage.h b/arch/s390/include/asm/linkage.h index 291c2d01c44..fc8a8284778 100644 --- a/arch/s390/include/asm/linkage.h +++ b/arch/s390/include/asm/linkage.h @@ -1,6 +1,9 @@  #ifndef __ASM_LINKAGE_H  #define __ASM_LINKAGE_H -/* Nothing to see here... */ +#include <linux/stringify.h> + +#define __ALIGN .align 4, 0x07 +#define __ALIGN_STR __stringify(__ALIGN)  #endif diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 65e172f8209..4349197ab9d 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -1,5 +1,5 @@  /* - *    Copyright IBM Corp. 1999,2010 + *    Copyright IBM Corp. 1999, 2012   *    Author(s): Hartmut Penner <hp@de.ibm.com>,   *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,   *		 Denis Joseph Barrow, @@ -12,13 +12,6 @@  #include <asm/ptrace.h>  #include <asm/cpu.h> -void restart_int_handler(void); -void ext_int_handler(void); -void system_call(void); -void pgm_check_handler(void); -void mcck_int_handler(void); -void io_int_handler(void); -  #ifdef CONFIG_32BIT  #define LC_ORDER 0 @@ -55,7 +48,7 @@ struct _lowcore {  	psw_t	mcck_new_psw;			/* 0x0070 */  	psw_t	io_new_psw;			/* 0x0078 */  	__u32	ext_params;			/* 0x0080 */ -	__u16	cpu_addr;			/* 0x0084 */ +	__u16	ext_cpu_addr;			/* 0x0084 */  	__u16	ext_int_code;			/* 0x0086 */  	__u16	svc_ilc;			/* 0x0088 */  	__u16	svc_code;			/* 0x008a */ @@ -63,13 +56,14 @@ struct _lowcore {  	__u16	pgm_code;			/* 0x008e */  	__u32	trans_exc_code;			/* 0x0090 */  	__u16	mon_class_num;			/* 0x0094 */ -	__u16	per_perc_atmid;			/* 0x0096 */ +	__u8	per_code;			/* 0x0096 */ +	__u8	per_atmid;			/* 0x0097 */  	__u32	per_address;			/* 0x0098 */  	__u32	monitor_code;			/* 0x009c */  	__u8	exc_access_id;			/* 0x00a0 */  	__u8	per_access_id;			/* 0x00a1 */  	__u8	op_access_id;			/* 0x00a2 */ -	__u8	ar_access_id;			/* 0x00a3 */ +	__u8	ar_mode_id;			/* 0x00a3 */  	__u8	pad_0x00a4[0x00b8-0x00a4];	/* 0x00a4 */  	__u16	subchannel_id;			/* 0x00b8 */  	__u16	subchannel_nr;			/* 0x00ba */ @@ -96,52 +90,61 @@ struct _lowcore {  	__u32	gpregs_save_area[16];		/* 0x0180 */  	__u32	cregs_save_area[16];		/* 0x01c0 */ +	/* Save areas. */ +	__u32	save_area_sync[8];		/* 0x0200 */ +	__u32	save_area_async[8];		/* 0x0220 */ +	__u32	save_area_restart[1];		/* 0x0240 */ + +	/* CPU flags. */ +	__u32	cpu_flags;			/* 0x0244 */ +  	/* Return psws. */ -	__u32	save_area[16];			/* 0x0200 */ -	psw_t	return_psw;			/* 0x0240 */ -	psw_t	return_mcck_psw;		/* 0x0248 */ +	psw_t	return_psw;			/* 0x0248 */ +	psw_t	return_mcck_psw;		/* 0x0250 */  	/* CPU time accounting values */ -	__u64	sync_enter_timer;		/* 0x0250 */ -	__u64	async_enter_timer;		/* 0x0258 */ -	__u64	mcck_enter_timer;		/* 0x0260 */ -	__u64	exit_timer;			/* 0x0268 */ -	__u64	user_timer;			/* 0x0270 */ -	__u64	system_timer;			/* 0x0278 */ -	__u64	steal_timer;			/* 0x0280 */ -	__u64	last_update_timer;		/* 0x0288 */ -	__u64	last_update_clock;		/* 0x0290 */ +	__u64	sync_enter_timer;		/* 0x0258 */ +	__u64	async_enter_timer;		/* 0x0260 */ +	__u64	mcck_enter_timer;		/* 0x0268 */ +	__u64	exit_timer;			/* 0x0270 */ +	__u64	user_timer;			/* 0x0278 */ +	__u64	system_timer;			/* 0x0280 */ +	__u64	steal_timer;			/* 0x0288 */ +	__u64	last_update_timer;		/* 0x0290 */ +	__u64	last_update_clock;		/* 0x0298 */ +	__u64	int_clock;			/* 0x02a0 */ +	__u64	mcck_clock;			/* 0x02a8 */ +	__u64	clock_comparator;		/* 0x02b0 */  	/* Current process. */ -	__u32	current_task;			/* 0x0298 */ -	__u32	thread_info;			/* 0x029c */ -	__u32	kernel_stack;			/* 0x02a0 */ +	__u32	current_task;			/* 0x02b8 */ +	__u32	thread_info;			/* 0x02bc */ +	__u32	kernel_stack;			/* 0x02c0 */ -	/* Interrupt and panic stack. */ -	__u32	async_stack;			/* 0x02a4 */ -	__u32	panic_stack;			/* 0x02a8 */ +	/* Interrupt, panic and restart stack. */ +	__u32	async_stack;			/* 0x02c4 */ +	__u32	panic_stack;			/* 0x02c8 */ +	__u32	restart_stack;			/* 0x02cc */ + +	/* Restart function and parameter. */ +	__u32	restart_fn;			/* 0x02d0 */ +	__u32	restart_data;			/* 0x02d4 */ +	__u32	restart_source;			/* 0x02d8 */  	/* Address space pointer. */ -	__u32	kernel_asce;			/* 0x02ac */ -	__u32	user_asce;			/* 0x02b0 */ -	__u32	user_exec_asce;			/* 0x02b4 */ +	__u32	kernel_asce;			/* 0x02dc */ +	__u32	user_asce;			/* 0x02e0 */ +	__u32	current_pid;			/* 0x02e4 */  	/* SMP info area */ -	__u32	cpu_nr;				/* 0x02b8 */ -	__u32	softirq_pending;		/* 0x02bc */ -	__u32	percpu_offset;			/* 0x02c0 */ -	__u32	ext_call_fast;			/* 0x02c4 */ -	__u64	int_clock;			/* 0x02c8 */ -	__u64	mcck_clock;			/* 0x02d0 */ -	__u64	clock_comparator;		/* 0x02d8 */ -	__u32	machine_flags;			/* 0x02e0 */ -	__u32	ftrace_func;			/* 0x02e4 */ -	__u8	pad_0x02e8[0x0300-0x02e8];	/* 0x02e8 */ - -	/* Interrupt response block */ -	__u8	irb[64];			/* 0x0300 */ - -	__u8	pad_0x0340[0x0e00-0x0340];	/* 0x0340 */ +	__u32	cpu_nr;				/* 0x02e8 */ +	__u32	softirq_pending;		/* 0x02ec */ +	__u32	percpu_offset;			/* 0x02f0 */ +	__u32	machine_flags;			/* 0x02f4 */ +	__u32	ftrace_func;			/* 0x02f8 */ +	__u32	spinlock_lockval;		/* 0x02fc */ + +	__u8	pad_0x0300[0x0e00-0x0300];	/* 0x0300 */  	/*  	 * 0xe00 contains the address of the IPL Parameter Information @@ -150,7 +153,10 @@ struct _lowcore {  	 */  	__u32	ipib;				/* 0x0e00 */  	__u32	ipib_checksum;			/* 0x0e04 */ -	__u8	pad_0x0e08[0x0f00-0x0e08];	/* 0x0e08 */ +	__u32	vmcore_info;			/* 0x0e08 */ +	__u8	pad_0x0e0c[0x0e18-0x0e0c];	/* 0x0e0c */ +	__u32	os_info;			/* 0x0e18 */ +	__u8	pad_0x0e1c[0x0f00-0x0e1c];	/* 0x0e1c */  	/* Extended facility list */  	__u64	stfle_fac_list[32];		/* 0x0f00 */ @@ -182,7 +188,7 @@ struct _lowcore {  	__u32	ipl_parmblock_ptr;		/* 0x0014 */  	__u8	pad_0x0018[0x0080-0x0018];	/* 0x0018 */  	__u32	ext_params;			/* 0x0080 */ -	__u16	cpu_addr;			/* 0x0084 */ +	__u16	ext_cpu_addr;			/* 0x0084 */  	__u16	ext_int_code;			/* 0x0086 */  	__u16	svc_ilc;			/* 0x0088 */  	__u16	svc_code;			/* 0x008a */ @@ -190,12 +196,13 @@ struct _lowcore {  	__u16	pgm_code;			/* 0x008e */  	__u32	data_exc_code;			/* 0x0090 */  	__u16	mon_class_num;			/* 0x0094 */ -	__u16	per_perc_atmid;			/* 0x0096 */ +	__u8	per_code;			/* 0x0096 */ +	__u8	per_atmid;			/* 0x0097 */  	__u64	per_address;			/* 0x0098 */  	__u8	exc_access_id;			/* 0x00a0 */  	__u8	per_access_id;			/* 0x00a1 */  	__u8	op_access_id;			/* 0x00a2 */ -	__u8	ar_access_id;			/* 0x00a3 */ +	__u8	ar_mode_id;			/* 0x00a3 */  	__u8	pad_0x00a4[0x00a8-0x00a4];	/* 0x00a4 */  	__u64	trans_exc_code;			/* 0x00a8 */  	__u64	monitor_code;			/* 0x00b0 */ @@ -227,57 +234,67 @@ struct _lowcore {  	psw_t	mcck_new_psw;			/* 0x01e0 */  	psw_t	io_new_psw;			/* 0x01f0 */ -	/* Entry/exit save area & return psws. */ -	__u64	save_area[16];			/* 0x0200 */ -	psw_t	return_psw;			/* 0x0280 */ -	psw_t	return_mcck_psw;		/* 0x0290 */ +	/* Save areas. */ +	__u64	save_area_sync[8];		/* 0x0200 */ +	__u64	save_area_async[8];		/* 0x0240 */ +	__u64	save_area_restart[1];		/* 0x0280 */ + +	/* CPU flags. */ +	__u64	cpu_flags;			/* 0x0288 */ + +	/* Return psws. */ +	psw_t	return_psw;			/* 0x0290 */ +	psw_t	return_mcck_psw;		/* 0x02a0 */  	/* CPU accounting and timing values. */ -	__u64	sync_enter_timer;		/* 0x02a0 */ -	__u64	async_enter_timer;		/* 0x02a8 */ -	__u64	mcck_enter_timer;		/* 0x02b0 */ -	__u64	exit_timer;			/* 0x02b8 */ -	__u64	user_timer;			/* 0x02c0 */ -	__u64	system_timer;			/* 0x02c8 */ -	__u64	steal_timer;			/* 0x02d0 */ -	__u64	last_update_timer;		/* 0x02d8 */ -	__u64	last_update_clock;		/* 0x02e0 */ +	__u64	sync_enter_timer;		/* 0x02b0 */ +	__u64	async_enter_timer;		/* 0x02b8 */ +	__u64	mcck_enter_timer;		/* 0x02c0 */ +	__u64	exit_timer;			/* 0x02c8 */ +	__u64	user_timer;			/* 0x02d0 */ +	__u64	system_timer;			/* 0x02d8 */ +	__u64	steal_timer;			/* 0x02e0 */ +	__u64	last_update_timer;		/* 0x02e8 */ +	__u64	last_update_clock;		/* 0x02f0 */ +	__u64	int_clock;			/* 0x02f8 */ +	__u64	mcck_clock;			/* 0x0300 */ +	__u64	clock_comparator;		/* 0x0308 */  	/* Current process. */ -	__u64	current_task;			/* 0x02e8 */ -	__u64	thread_info;			/* 0x02f0 */ -	__u64	kernel_stack;			/* 0x02f8 */ +	__u64	current_task;			/* 0x0310 */ +	__u64	thread_info;			/* 0x0318 */ +	__u64	kernel_stack;			/* 0x0320 */ -	/* Interrupt and panic stack. */ -	__u64	async_stack;			/* 0x0300 */ -	__u64	panic_stack;			/* 0x0308 */ +	/* Interrupt, panic and restart stack. */ +	__u64	async_stack;			/* 0x0328 */ +	__u64	panic_stack;			/* 0x0330 */ +	__u64	restart_stack;			/* 0x0338 */ + +	/* Restart function and parameter. */ +	__u64	restart_fn;			/* 0x0340 */ +	__u64	restart_data;			/* 0x0348 */ +	__u64	restart_source;			/* 0x0350 */  	/* Address space pointer. */ -	__u64	kernel_asce;			/* 0x0310 */ -	__u64	user_asce;			/* 0x0318 */ -	__u64	user_exec_asce;			/* 0x0320 */ +	__u64	kernel_asce;			/* 0x0358 */ +	__u64	user_asce;			/* 0x0360 */ +	__u64	current_pid;			/* 0x0368 */  	/* SMP info area */ -	__u32	cpu_nr;				/* 0x0328 */ -	__u32	softirq_pending;		/* 0x032c */ -	__u64	percpu_offset;			/* 0x0330 */ -	__u64	ext_call_fast;			/* 0x0338 */ -	__u64	int_clock;			/* 0x0340 */ -	__u64	mcck_clock;			/* 0x0348 */ -	__u64	clock_comparator;		/* 0x0350 */ -	__u64	vdso_per_cpu_data;		/* 0x0358 */ -	__u64	machine_flags;			/* 0x0360 */ -	__u64	ftrace_func;			/* 0x0368 */ -	__u64	sie_hook;			/* 0x0370 */ -	__u64	cmf_hpp;			/* 0x0378 */ - -	/* Interrupt response block. */ -	__u8	irb[64];			/* 0x0380 */ +	__u32	cpu_nr;				/* 0x0370 */ +	__u32	softirq_pending;		/* 0x0374 */ +	__u64	percpu_offset;			/* 0x0378 */ +	__u64	vdso_per_cpu_data;		/* 0x0380 */ +	__u64	machine_flags;			/* 0x0388 */ +	__u64	ftrace_func;			/* 0x0390 */ +	__u64	gmap;				/* 0x0398 */ +	__u32	spinlock_lockval;		/* 0x03a0 */ +	__u8	pad_0x03a0[0x0400-0x03a4];	/* 0x03a4 */  	/* Per cpu primary space access list */ -	__u32	paste[16];			/* 0x03c0 */ +	__u32	paste[16];			/* 0x0400 */ -	__u8	pad_0x0400[0x0e00-0x0400];	/* 0x0400 */ +	__u8	pad_0x04c0[0x0e00-0x0440];	/* 0x0440 */  	/*  	 * 0xe00 contains the address of the IPL Parameter Information @@ -286,7 +303,10 @@ struct _lowcore {  	 */  	__u64	ipib;				/* 0x0e00 */  	__u32	ipib_checksum;			/* 0x0e08 */ -	__u8	pad_0x0e0c[0x0f00-0x0e0c];	/* 0x0e0c */ +	__u64	vmcore_info;			/* 0x0e0c */ +	__u8	pad_0x0e14[0x0e18-0x0e14];	/* 0x0e14 */ +	__u64	os_info;			/* 0x0e18 */ +	__u8	pad_0x0e20[0x0f00-0x0e20];	/* 0x0e20 */  	/* Extended facility list */  	__u64	stfle_fac_list[32];		/* 0x0f00 */ @@ -310,9 +330,13 @@ struct _lowcore {  	__u8	pad_0x1338[0x1340-0x1338];	/* 0x1338 */  	__u32	access_regs_save_area[16];	/* 0x1340 */  	__u64	cregs_save_area[16];		/* 0x1380 */ +	__u8	pad_0x1400[0x1800-0x1400];	/* 0x1400 */ + +	/* Transaction abort diagnostic block */ +	__u8	pgm_tdb[256];			/* 0x1800 */  	/* align to the top of the prefix area */ -	__u8	pad_0x1400[0x2000-0x1400];	/* 0x1400 */ +	__u8	pad_0x1900[0x2000-0x1900];	/* 0x1900 */  } __packed;  #endif /* CONFIG_32BIT */ diff --git a/arch/s390/include/asm/mathemu.h b/arch/s390/include/asm/mathemu.h index e8dd1ba8edb..614dfaf47f7 100644 --- a/arch/s390/include/asm/mathemu.h +++ b/arch/s390/include/asm/mathemu.h @@ -1,9 +1,8 @@  /* - *  arch/s390/kernel/mathemu.h   *    IEEE floating point emulation.   *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   */ diff --git a/arch/s390/include/asm/mman.h b/arch/s390/include/asm/mman.h index 4e9c8ae0a63..9977e08df5b 100644 --- a/arch/s390/include/asm/mman.h +++ b/arch/s390/include/asm/mman.h @@ -1,19 +1,15 @@  /* - *  include/asm-s390/mman.h - *   *  S390 version   *   *  Derived from "include/asm-i386/mman.h"   */ -  #ifndef __S390_MMAN_H__  #define __S390_MMAN_H__ -#include <asm-generic/mman.h> +#include <uapi/asm/mman.h> -#if defined(__KERNEL__) && !defined(__ASSEMBLY__) && defined(CONFIG_64BIT) -int s390_mmap_check(unsigned long addr, unsigned long len); -#define arch_mmap_check(addr,len,flags)	s390_mmap_check(addr,len) +#if !defined(__ASSEMBLY__) && defined(CONFIG_64BIT) +int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags); +#define arch_mmap_check(addr, len, flags) s390_mmap_check(addr, len, flags)  #endif -  #endif /* __S390_MMAN_H__ */ diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h index 78522cdefdd..a5e656260a7 100644 --- a/arch/s390/include/asm/mmu.h +++ b/arch/s390/include/asm/mmu.h @@ -1,23 +1,42 @@  #ifndef __MMU_H  #define __MMU_H +#include <linux/cpumask.h> +#include <linux/errno.h> +  typedef struct { +	cpumask_t cpu_attach_mask;  	atomic_t attach_count;  	unsigned int flush_mm;  	spinlock_t list_lock; -	struct list_head crst_list;  	struct list_head pgtable_list; +	struct list_head gmap_list;  	unsigned long asce_bits;  	unsigned long asce_limit;  	unsigned long vdso_base; -	int noexec; -	int has_pgste;	 /* The mmu context has extended page tables */ -	int alloc_pgste; /* cloned contexts will have extended page tables */ +	/* The mmu context has extended page tables. */ +	unsigned int has_pgste:1; +	/* The mmu context uses storage keys. */ +	unsigned int use_skey:1;  } mm_context_t;  #define INIT_MM_CONTEXT(name)						      \  	.context.list_lock    = __SPIN_LOCK_UNLOCKED(name.context.list_lock), \ -	.context.crst_list    = LIST_HEAD_INIT(name.context.crst_list),	      \ -	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list), +	.context.pgtable_list = LIST_HEAD_INIT(name.context.pgtable_list),    \ +	.context.gmap_list = LIST_HEAD_INIT(name.context.gmap_list), + +static inline int tprot(unsigned long addr) +{ +	int rc = -EFAULT; + +	asm volatile( +		"	tprot	0(%1),0\n" +		"0:	ipm	%0\n" +		"	srl	%0,28\n" +		"1:\n" +		EX_TABLE(0b,1b) +		: "+d" (rc) : "a" (addr) : "cc"); +	return rc; +}  #endif diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index a6f0e7cc9cd..3815bfea1b2 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/mmu_context.h - *   *  S390 version   *   *  Derived from "include/asm-i386/mmu_context.h" @@ -12,37 +10,20 @@  #include <asm/pgalloc.h>  #include <asm/uaccess.h>  #include <asm/tlbflush.h> -#include <asm-generic/mm_hooks.h> +#include <asm/ctl_reg.h>  static inline int init_new_context(struct task_struct *tsk,  				   struct mm_struct *mm)  { +	cpumask_clear(&mm->context.cpu_attach_mask);  	atomic_set(&mm->context.attach_count, 0);  	mm->context.flush_mm = 0;  	mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;  #ifdef CONFIG_64BIT  	mm->context.asce_bits |= _ASCE_TYPE_REGION3;  #endif -	if (current->mm->context.alloc_pgste) { -		/* -		 * alloc_pgste indicates, that any NEW context will be created -		 * with extended page tables. The old context is unchanged. The -		 * page table allocation and the page table operations will -		 * look at has_pgste to distinguish normal and extended page -		 * tables. The only way to create extended page tables is to -		 * set alloc_pgste and then create a new context (e.g. dup_mm). -		 * The page table allocation is called after init_new_context -		 * and if has_pgste is set, it will create extended page -		 * tables. -		 */ -		mm->context.noexec = 0; -		mm->context.has_pgste = 1; -		mm->context.alloc_pgste = 1; -	} else { -		mm->context.noexec = (user_mode == SECONDARY_SPACE_MODE); -		mm->context.has_pgste = 0; -		mm->context.alloc_pgste = 0; -	} +	mm->context.has_pgste = 0; +	mm->context.use_skey = 0;  	mm->context.asce_limit = STACK_TOP_MAX;  	crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));  	return 0; @@ -50,41 +31,69 @@ static inline int init_new_context(struct task_struct *tsk,  #define destroy_context(mm)             do { } while (0) -#ifndef __s390x__ -#define LCTL_OPCODE "lctl" -#else -#define LCTL_OPCODE "lctlg" -#endif +static inline void set_user_asce(struct mm_struct *mm) +{ +	S390_lowcore.user_asce = mm->context.asce_bits | __pa(mm->pgd); +	if (current->thread.mm_segment.ar4) +		__ctl_load(S390_lowcore.user_asce, 7, 7); +	set_cpu_flag(CIF_ASCE); +} -static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk) +static inline void clear_user_asce(void)  { -	pgd_t *pgd = mm->pgd; - -	S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd); -	if (user_mode != HOME_SPACE_MODE) { -		/* Load primary space page table origin. */ -		pgd = mm->context.noexec ? get_shadow_table(pgd) : pgd; -		S390_lowcore.user_exec_asce = mm->context.asce_bits | __pa(pgd); -		asm volatile(LCTL_OPCODE" 1,1,%0\n" -			     : : "m" (S390_lowcore.user_exec_asce) ); -	} else -		/* Load home space page table origin. */ -		asm volatile(LCTL_OPCODE" 13,13,%0" -			     : : "m" (S390_lowcore.user_asce) ); -	set_fs(current->thread.mm_segment); +	S390_lowcore.user_asce = S390_lowcore.kernel_asce; + +	__ctl_load(S390_lowcore.user_asce, 1, 1); +	__ctl_load(S390_lowcore.user_asce, 7, 7); +} + +static inline void load_kernel_asce(void) +{ +	unsigned long asce; + +	__ctl_store(asce, 1, 1); +	if (asce != S390_lowcore.kernel_asce) +		__ctl_load(S390_lowcore.kernel_asce, 1, 1); +	set_cpu_flag(CIF_ASCE);  }  static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,  			     struct task_struct *tsk)  { -	cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); -	update_mm(next, tsk); -	atomic_dec(&prev->context.attach_count); -	WARN_ON(atomic_read(&prev->context.attach_count) < 0); +	int cpu = smp_processor_id(); + +	if (prev == next) +		return; +	if (MACHINE_HAS_TLB_LC) +		cpumask_set_cpu(cpu, &next->context.cpu_attach_mask); +	/* Clear old ASCE by loading the kernel ASCE. */ +	__ctl_load(S390_lowcore.kernel_asce, 1, 1); +	__ctl_load(S390_lowcore.kernel_asce, 7, 7);  	atomic_inc(&next->context.attach_count); -	/* Check for TLBs not flushed yet */ -	if (next->context.flush_mm) -		__tlb_flush_mm(next); +	atomic_dec(&prev->context.attach_count); +	if (MACHINE_HAS_TLB_LC) +		cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask); +	S390_lowcore.user_asce = next->context.asce_bits | __pa(next->pgd); +} + +#define finish_arch_post_lock_switch finish_arch_post_lock_switch +static inline void finish_arch_post_lock_switch(void) +{ +	struct task_struct *tsk = current; +	struct mm_struct *mm = tsk->mm; + +	load_kernel_asce(); +	if (mm) { +		preempt_disable(); +		while (atomic_read(&mm->context.attach_count) >> 16) +			cpu_relax(); + +		cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); +		if (mm->context.flush_mm) +			__tlb_flush_mm(mm); +		preempt_enable(); +	} +	set_fs(current->thread.mm_segment);  }  #define enter_lazy_tlb(mm,tsk)	do { } while (0) @@ -93,7 +102,22 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,  static inline void activate_mm(struct mm_struct *prev,                                 struct mm_struct *next)  { -        switch_mm(prev, next, current); +	switch_mm(prev, next, current); +	cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); +	set_user_asce(next); +} + +static inline void arch_dup_mmap(struct mm_struct *oldmm, +				 struct mm_struct *mm) +{ +#ifdef CONFIG_64BIT +	if (oldmm->context.asce_limit < mm->context.asce_limit) +		crst_table_downgrade(mm, oldmm->context.asce_limit); +#endif +} + +static inline void arch_exit_mmap(struct mm_struct *mm) +{  }  #endif /* __S390_MMU_CONTEXT_H */ diff --git a/arch/s390/include/asm/module.h b/arch/s390/include/asm/module.h index 1cc1c5af705..df1f861a848 100644 --- a/arch/s390/include/asm/module.h +++ b/arch/s390/include/asm/module.h @@ -1,5 +1,8 @@  #ifndef _ASM_S390_MODULE_H  #define _ASM_S390_MODULE_H + +#include <asm-generic/module.h> +  /*   * This file contains the s390 architecture specific module code.   */ @@ -28,19 +31,4 @@ struct mod_arch_specific  	struct mod_arch_syminfo *syminfo;  }; -#ifdef __s390x__ -#define ElfW(x) Elf64_ ## x -#define ELFW(x) ELF64_ ## x -#else -#define ElfW(x) Elf32_ ## x -#define ELFW(x) ELF32_ ## x -#endif - -#define Elf_Addr ElfW(Addr) -#define Elf_Rela ElfW(Rela) -#define Elf_Shdr ElfW(Shdr) -#define Elf_Sym ElfW(Sym) -#define Elf_Ehdr ElfW(Ehdr) -#define ELF_R_SYM ELFW(R_SYM) -#define ELF_R_TYPE ELFW(R_TYPE)  #endif /* _ASM_S390_MODULE_H */ diff --git a/arch/s390/include/asm/nmi.h b/arch/s390/include/asm/nmi.h index f4b60441adc..35f8ec18561 100644 --- a/arch/s390/include/asm/nmi.h +++ b/arch/s390/include/asm/nmi.h @@ -1,7 +1,7 @@  /*   *   Machine check handler definitions   * - *    Copyright IBM Corp. 2000,2009 + *    Copyright IBM Corp. 2000, 2009   *    Author(s): Ingo Adlung <adlung@de.ibm.com>,   *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,   *		 Cornelia Huck <cornelia.huck@de.ibm.com>, diff --git a/arch/s390/include/asm/os_info.h b/arch/s390/include/asm/os_info.h new file mode 100644 index 00000000000..295f2c4f1c9 --- /dev/null +++ b/arch/s390/include/asm/os_info.h @@ -0,0 +1,49 @@ +/* + * OS info memory interface + * + * Copyright IBM Corp. 2012 + * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com> + */ +#ifndef _ASM_S390_OS_INFO_H +#define _ASM_S390_OS_INFO_H + +#define OS_INFO_VERSION_MAJOR	1 +#define OS_INFO_VERSION_MINOR	1 +#define OS_INFO_MAGIC		0x4f53494e464f535aULL /* OSINFOSZ */ + +#define OS_INFO_VMCOREINFO	0 +#define OS_INFO_REIPL_BLOCK	1 + +struct os_info_entry { +	u64	addr; +	u64	size; +	u32	csum; +} __packed; + +struct os_info { +	u64	magic; +	u32	csum; +	u16	version_major; +	u16	version_minor; +	u64	crashkernel_addr; +	u64	crashkernel_size; +	struct os_info_entry entry[2]; +	u8	reserved[4024]; +} __packed; + +void os_info_init(void); +void os_info_entry_add(int nr, void *ptr, u64 len); +void os_info_crashkernel_add(unsigned long base, unsigned long size); +u32 os_info_csum(struct os_info *os_info); + +#ifdef CONFIG_CRASH_DUMP +void *os_info_old_entry(int nr, unsigned long *size); +int copy_from_oldmem(void *dest, void *src, size_t count); +#else +static inline void *os_info_old_entry(int nr, unsigned long *size) +{ +	return NULL; +} +#endif + +#endif /* _ASM_S390_OS_INFO_H */ diff --git a/arch/s390/include/asm/page.h b/arch/s390/include/asm/page.h index a8729ea7e9a..114258eeaac 100644 --- a/arch/s390/include/asm/page.h +++ b/arch/s390/include/asm/page.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/page.h - *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999, 2000   *    Author(s): Hartmut Penner (hp@de.ibm.com)   */ @@ -32,50 +30,39 @@  #include <asm/setup.h>  #ifndef __ASSEMBLY__ +static inline void storage_key_init_range(unsigned long start, unsigned long end) +{ +#if PAGE_DEFAULT_KEY +	__storage_key_init_range(start, end); +#endif +} +  static inline void clear_page(void *page)  { -	if (MACHINE_HAS_PFMF) { -		asm volatile( -			"	.insn	rre,0xb9af0000,%0,%1" -			: : "d" (0x10000), "a" (page) : "memory", "cc"); -	} else { -		register unsigned long reg1 asm ("1") = 0; -		register void *reg2 asm ("2") = page; -		register unsigned long reg3 asm ("3") = 4096; -		asm volatile( -			"	mvcl	2,0" -			: "+d" (reg2), "+d" (reg3) : "d" (reg1) -			: "memory", "cc"); -	} +	register unsigned long reg1 asm ("1") = 0; +	register void *reg2 asm ("2") = page; +	register unsigned long reg3 asm ("3") = 4096; +	asm volatile( +		"	mvcl	2,0" +		: "+d" (reg2), "+d" (reg3) : "d" (reg1) +		: "memory", "cc");  } +/* + * copy_page uses the mvcl instruction with 0xb0 padding byte in order to + * bypass caches when copying a page. Especially when copying huge pages + * this keeps L1 and L2 data caches alive. + */  static inline void copy_page(void *to, void *from)  { -	if (MACHINE_HAS_MVPG) { -		register unsigned long reg0 asm ("0") = 0; -		asm volatile( -			"	mvpg	%0,%1" -			: : "a" (to), "a" (from), "d" (reg0) -			: "memory", "cc"); -	} else -		asm volatile( -			"	mvc	0(256,%0),0(%1)\n" -			"	mvc	256(256,%0),256(%1)\n" -			"	mvc	512(256,%0),512(%1)\n" -			"	mvc	768(256,%0),768(%1)\n" -			"	mvc	1024(256,%0),1024(%1)\n" -			"	mvc	1280(256,%0),1280(%1)\n" -			"	mvc	1536(256,%0),1536(%1)\n" -			"	mvc	1792(256,%0),1792(%1)\n" -			"	mvc	2048(256,%0),2048(%1)\n" -			"	mvc	2304(256,%0),2304(%1)\n" -			"	mvc	2560(256,%0),2560(%1)\n" -			"	mvc	2816(256,%0),2816(%1)\n" -			"	mvc	3072(256,%0),3072(%1)\n" -			"	mvc	3328(256,%0),3328(%1)\n" -			"	mvc	3584(256,%0),3584(%1)\n" -			"	mvc	3840(256,%0),3840(%1)\n" -			: : "a" (to), "a" (from) : "memory"); +	register void *reg2 asm ("2") = to; +	register unsigned long reg3 asm ("3") = 0x1000; +	register void *reg4 asm ("4") = from; +	register unsigned long reg5 asm ("5") = 0xb0001000; +	asm volatile( +		"	mvcl	2,4" +		: "+d" (reg2), "+d" (reg3), "+d" (reg4), "+d" (reg5) +		: : "memory", "cc");  }  #define clear_user_page(page, vaddr, pg)	clear_page(page) @@ -90,6 +77,7 @@ static inline void copy_page(void *to, void *from)   */  typedef struct { unsigned long pgprot; } pgprot_t; +typedef struct { unsigned long pgste; } pgste_t;  typedef struct { unsigned long pte; } pte_t;  typedef struct { unsigned long pmd; } pmd_t;  typedef struct { unsigned long pud; } pud_t; @@ -97,18 +85,21 @@ typedef struct { unsigned long pgd; } pgd_t;  typedef pte_t *pgtable_t;  #define pgprot_val(x)	((x).pgprot) +#define pgste_val(x)	((x).pgste)  #define pte_val(x)	((x).pte)  #define pmd_val(x)	((x).pmd)  #define pud_val(x)	((x).pud)  #define pgd_val(x)      ((x).pgd) +#define __pgste(x)	((pgste_t) { (x) } )  #define __pte(x)        ((pte_t) { (x) } )  #define __pmd(x)        ((pmd_t) { (x) } ) +#define __pud(x)	((pud_t) { (x) } )  #define __pgd(x)        ((pgd_t) { (x) } )  #define __pgprot(x)     ((pgprot_t) { (x) } ) -static inline void -page_set_storage_key(unsigned long addr, unsigned int skey, int mapped) +static inline void page_set_storage_key(unsigned long addr, +					unsigned char skey, int mapped)  {  	if (!mapped)  		asm volatile(".insn rrf,0xb22b0000,%0,%1,8,0" @@ -117,18 +108,40 @@ page_set_storage_key(unsigned long addr, unsigned int skey, int mapped)  		asm volatile("sske %0,%1" : : "d" (skey), "a" (addr));  } -static inline unsigned int -page_get_storage_key(unsigned long addr) +static inline unsigned char page_get_storage_key(unsigned long addr)  { -	unsigned int skey; +	unsigned char skey; -	asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr), "0" (0)); +	asm volatile("iske %0,%1" : "=d" (skey) : "a" (addr));  	return skey;  } +static inline int page_reset_referenced(unsigned long addr) +{ +	unsigned int ipm; + +	asm volatile( +		"	rrbe	0,%1\n" +		"	ipm	%0\n" +		: "=d" (ipm) : "a" (addr) : "cc"); +	return !!(ipm & 0x20000000); +} + +/* Bits int the storage key */ +#define _PAGE_CHANGED		0x02	/* HW changed bit		*/ +#define _PAGE_REFERENCED	0x04	/* HW referenced bit		*/ +#define _PAGE_FP_BIT		0x08	/* HW fetch protection bit	*/ +#define _PAGE_ACC_BITS		0xf0	/* HW access control bits	*/ +  struct page;  void arch_free_page(struct page *page, int order);  void arch_alloc_page(struct page *page, int order); +void arch_set_page_states(int make_stable); + +static inline int devmem_is_allowed(unsigned long pfn) +{ +	return 0; +}  #define HAVE_ARCH_FREE_PAGE  #define HAVE_ARCH_ALLOC_PAGE diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 42a145c9ddd..c030900320e 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h @@ -1,10 +1,192 @@  #ifndef __ASM_S390_PCI_H  #define __ASM_S390_PCI_H -/* S/390 systems don't have a PCI bus. This file is just here because some stupid .c code - * includes it even if CONFIG_PCI is not set. - */ +/* must be set before including asm-generic/pci.h */  #define PCI_DMA_BUS_IS_PHYS (0) +/* must be set before including pci_clp.h */ +#define PCI_BAR_COUNT	6 -#endif /* __ASM_S390_PCI_H */ +#include <linux/pci.h> +#include <asm-generic/pci.h> +#include <asm-generic/pci-dma-compat.h> +#include <asm/pci_clp.h> +#include <asm/pci_debug.h> +#define PCIBIOS_MIN_IO		0x1000 +#define PCIBIOS_MIN_MEM		0x10000000 + +#define pcibios_assign_all_busses()	(0) + +void __iomem *pci_iomap(struct pci_dev *, int, unsigned long); +void pci_iounmap(struct pci_dev *, void __iomem *); +int pci_domain_nr(struct pci_bus *); +int pci_proc_domain(struct pci_bus *); + +#define ZPCI_BUS_NR			0	/* default bus number */ +#define ZPCI_DEVFN			0	/* default device number */ + +/* PCI Function Controls */ +#define ZPCI_FC_FN_ENABLED		0x80 +#define ZPCI_FC_ERROR			0x40 +#define ZPCI_FC_BLOCKED			0x20 +#define ZPCI_FC_DMA_ENABLED		0x10 + +struct zpci_fmb { +	u32 format	:  8; +	u32 dma_valid	:  1; +	u32		: 23; +	u32 samples; +	u64 last_update; +	/* hardware counters */ +	u64 ld_ops; +	u64 st_ops; +	u64 stb_ops; +	u64 rpcit_ops; +	u64 dma_rbytes; +	u64 dma_wbytes; +	/* software counters */ +	atomic64_t allocated_pages; +	atomic64_t mapped_pages; +	atomic64_t unmapped_pages; +} __packed __aligned(16); + +#define ZPCI_MSI_VEC_BITS	11 +#define ZPCI_MSI_VEC_MAX	(1 << ZPCI_MSI_VEC_BITS) +#define ZPCI_MSI_VEC_MASK	(ZPCI_MSI_VEC_MAX - 1) + +enum zpci_state { +	ZPCI_FN_STATE_RESERVED, +	ZPCI_FN_STATE_STANDBY, +	ZPCI_FN_STATE_CONFIGURED, +	ZPCI_FN_STATE_ONLINE, +	NR_ZPCI_FN_STATES, +}; + +struct zpci_bar_struct { +	struct resource *res;		/* bus resource */ +	u32		val;		/* bar start & 3 flag bits */ +	u16		map_idx;	/* index into bar mapping array */ +	u8		size;		/* order 2 exponent */ +}; + +/* Private data per function */ +struct zpci_dev { +	struct pci_dev	*pdev; +	struct pci_bus	*bus; +	struct list_head entry;		/* list of all zpci_devices, needed for hotplug, etc. */ + +	enum zpci_state state; +	u32		fid;		/* function ID, used by sclp */ +	u32		fh;		/* function handle, used by insn's */ +	u16		vfn;		/* virtual function number */ +	u16		pchid;		/* physical channel ID */ +	u8		pfgid;		/* function group ID */ +	u8		pft;		/* pci function type */ +	u16		domain; + +	u8 pfip[CLP_PFIP_NR_SEGMENTS];	/* pci function internal path */ +	u32 uid;			/* user defined id */ +	u8 util_str[CLP_UTIL_STR_LEN];	/* utility string */ + +	/* IRQ stuff */ +	u64		msi_addr;	/* MSI address */ +	struct airq_iv *aibv;		/* adapter interrupt bit vector */ +	unsigned int	aisb;		/* number of the summary bit */ + +	/* DMA stuff */ +	unsigned long	*dma_table; +	spinlock_t	dma_table_lock; +	int		tlb_refresh; + +	spinlock_t	iommu_bitmap_lock; +	unsigned long	*iommu_bitmap; +	unsigned long	iommu_size; +	unsigned long	iommu_pages; +	unsigned int	next_bit; + +	char res_name[16]; +	struct zpci_bar_struct bars[PCI_BAR_COUNT]; + +	u64		start_dma;	/* Start of available DMA addresses */ +	u64		end_dma;	/* End of available DMA addresses */ +	u64		dma_mask;	/* DMA address space mask */ + +	/* Function measurement block */ +	struct zpci_fmb *fmb; +	u16		fmb_update;	/* update interval */ + +	enum pci_bus_speed max_bus_speed; + +	struct dentry	*debugfs_dev; +	struct dentry	*debugfs_perf; +}; + +static inline bool zdev_enabled(struct zpci_dev *zdev) +{ +	return (zdev->fh & (1UL << 31)) ? true : false; +} + +extern const struct attribute_group *zpci_attr_groups[]; + +/* ----------------------------------------------------------------------------- +  Prototypes +----------------------------------------------------------------------------- */ +/* Base stuff */ +int zpci_create_device(struct zpci_dev *); +int zpci_enable_device(struct zpci_dev *); +int zpci_disable_device(struct zpci_dev *); +void zpci_stop_device(struct zpci_dev *); +int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64); +int zpci_unregister_ioat(struct zpci_dev *, u8); + +/* CLP */ +int clp_scan_pci_devices(void); +int clp_rescan_pci_devices(void); +int clp_rescan_pci_devices_simple(void); +int clp_add_pci_device(u32, u32, int); +int clp_enable_fh(struct zpci_dev *, u8); +int clp_disable_fh(struct zpci_dev *); + +#ifdef CONFIG_PCI +/* Error handling and recovery */ +void zpci_event_error(void *); +void zpci_event_availability(void *); +void zpci_rescan(void); +bool zpci_is_enabled(void); +#else /* CONFIG_PCI */ +static inline void zpci_event_error(void *e) {} +static inline void zpci_event_availability(void *e) {} +static inline void zpci_rescan(void) {} +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_HOTPLUG_PCI_S390 +int zpci_init_slot(struct zpci_dev *); +void zpci_exit_slot(struct zpci_dev *); +#else /* CONFIG_HOTPLUG_PCI_S390 */ +static inline int zpci_init_slot(struct zpci_dev *zdev) +{ +	return 0; +} +static inline void zpci_exit_slot(struct zpci_dev *zdev) {} +#endif /* CONFIG_HOTPLUG_PCI_S390 */ + +/* Helpers */ +struct zpci_dev *get_zdev(struct pci_dev *); +struct zpci_dev *get_zdev_by_fid(u32); + +/* DMA */ +int zpci_dma_init(void); +void zpci_dma_exit(void); + +/* FMB */ +int zpci_fmb_enable_device(struct zpci_dev *); +int zpci_fmb_disable_device(struct zpci_dev *); + +/* Debug */ +int zpci_debug_init(void); +void zpci_debug_exit(void); +void zpci_debug_init_device(struct zpci_dev *); +void zpci_debug_exit_device(struct zpci_dev *); +void zpci_debug_info(struct zpci_dev *, struct seq_file *); + +#endif diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h new file mode 100644 index 00000000000..dd78f92f1cc --- /dev/null +++ b/arch/s390/include/asm/pci_clp.h @@ -0,0 +1,186 @@ +#ifndef _ASM_S390_PCI_CLP_H +#define _ASM_S390_PCI_CLP_H + +#include <asm/clp.h> + +/* + * Call Logical Processor - Command Codes + */ +#define CLP_LIST_PCI		0x0002 +#define CLP_QUERY_PCI_FN	0x0003 +#define CLP_QUERY_PCI_FNGRP	0x0004 +#define CLP_SET_PCI_FN		0x0005 + +/* PCI function handle list entry */ +struct clp_fh_list_entry { +	u16 device_id; +	u16 vendor_id; +	u32 config_state :  1; +	u32		 : 31; +	u32 fid;		/* PCI function id */ +	u32 fh;			/* PCI function handle */ +} __packed; + +#define CLP_RC_SETPCIFN_FH	0x0101	/* Invalid PCI fn handle */ +#define CLP_RC_SETPCIFN_FHOP	0x0102	/* Fn handle not valid for op */ +#define CLP_RC_SETPCIFN_DMAAS	0x0103	/* Invalid DMA addr space */ +#define CLP_RC_SETPCIFN_RES	0x0104	/* Insufficient resources */ +#define CLP_RC_SETPCIFN_ALRDY	0x0105	/* Fn already in requested state */ +#define CLP_RC_SETPCIFN_ERR	0x0106	/* Fn in permanent error state */ +#define CLP_RC_SETPCIFN_RECPND	0x0107	/* Error recovery pending */ +#define CLP_RC_SETPCIFN_BUSY	0x0108	/* Fn busy */ +#define CLP_RC_LISTPCI_BADRT	0x010a	/* Resume token not recognized */ +#define CLP_RC_QUERYPCIFG_PFGID	0x010b	/* Unrecognized PFGID */ + +/* request or response block header length */ +#define LIST_PCI_HDR_LEN	32 + +/* Number of function handles fitting in response block */ +#define CLP_FH_LIST_NR_ENTRIES				\ +	((CLP_BLK_SIZE - 2 * LIST_PCI_HDR_LEN)		\ +		/ sizeof(struct clp_fh_list_entry)) + +#define CLP_SET_ENABLE_PCI_FN	0	/* Yes, 0 enables it */ +#define CLP_SET_DISABLE_PCI_FN	1	/* Yes, 1 disables it */ + +#define CLP_UTIL_STR_LEN	64 +#define CLP_PFIP_NR_SEGMENTS	4 + +/* List PCI functions request */ +struct clp_req_list_pci { +	struct clp_req_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64 reserved1; +	u64 resume_token; +	u64 reserved2; +} __packed; + +/* List PCI functions response */ +struct clp_rsp_list_pci { +	struct clp_rsp_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64 reserved1; +	u64 resume_token; +	u32 reserved2; +	u16 max_fn; +	u8 reserved3; +	u8 entry_size; +	struct clp_fh_list_entry fh_list[CLP_FH_LIST_NR_ENTRIES]; +} __packed; + +/* Query PCI function request */ +struct clp_req_query_pci { +	struct clp_req_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64 reserved1; +	u32 fh;				/* function handle */ +	u32 reserved2; +	u64 reserved3; +} __packed; + +/* Query PCI function response */ +struct clp_rsp_query_pci { +	struct clp_rsp_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64			: 64; +	u16 vfn;			/* virtual fn number */ +	u16			:  7; +	u16 util_str_avail	:  1;	/* utility string available? */ +	u16 pfgid		:  8;	/* pci function group id */ +	u32 fid;			/* pci function id */ +	u8 bar_size[PCI_BAR_COUNT]; +	u16 pchid; +	u32 bar[PCI_BAR_COUNT]; +	u8 pfip[CLP_PFIP_NR_SEGMENTS];	/* pci function internal path */ +	u32			: 24; +	u8 pft;				/* pci function type */ +	u64 sdma;			/* start dma as */ +	u64 edma;			/* end dma as */ +	u32 reserved[11]; +	u32 uid;			/* user defined id */ +	u8 util_str[CLP_UTIL_STR_LEN];	/* utility string */ +} __packed; + +/* Query PCI function group request */ +struct clp_req_query_pci_grp { +	struct clp_req_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64 reserved1; +	u32			: 24; +	u32 pfgid		:  8;	/* function group id */ +	u32 reserved2; +	u64 reserved3; +} __packed; + +/* Query PCI function group response */ +struct clp_rsp_query_pci_grp { +	struct clp_rsp_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64 reserved1; +	u16			:  4; +	u16 noi			: 12;	/* number of interrupts */ +	u8 version; +	u8			:  6; +	u8 frame		:  1; +	u8 refresh		:  1;	/* TLB refresh mode */ +	u16 reserved2; +	u16 mui; +	u64 reserved3; +	u64 dasm;			/* dma address space mask */ +	u64 msia;			/* MSI address */ +	u64 reserved4; +	u64 reserved5; +} __packed; + +/* Set PCI function request */ +struct clp_req_set_pci { +	struct clp_req_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64 reserved1; +	u32 fh;				/* function handle */ +	u16 reserved2; +	u8 oc;				/* operation controls */ +	u8 ndas;			/* number of dma spaces */ +	u64 reserved3; +} __packed; + +/* Set PCI function response */ +struct clp_rsp_set_pci { +	struct clp_rsp_hdr hdr; +	u32 fmt			:  4;	/* cmd request block format */ +	u32			: 28; +	u64 reserved1; +	u32 fh;				/* function handle */ +	u32 reserved3; +	u64 reserved4; +} __packed; + +/* Combined request/response block structures used by clp insn */ +struct clp_req_rsp_list_pci { +	struct clp_req_list_pci request; +	struct clp_rsp_list_pci response; +} __packed; + +struct clp_req_rsp_set_pci { +	struct clp_req_set_pci request; +	struct clp_rsp_set_pci response; +} __packed; + +struct clp_req_rsp_query_pci { +	struct clp_req_query_pci request; +	struct clp_rsp_query_pci response; +} __packed; + +struct clp_req_rsp_query_pci_grp { +	struct clp_req_query_pci_grp request; +	struct clp_rsp_query_pci_grp response; +} __packed; + +#endif diff --git a/arch/s390/include/asm/pci_debug.h b/arch/s390/include/asm/pci_debug.h new file mode 100644 index 00000000000..ac24b26fc06 --- /dev/null +++ b/arch/s390/include/asm/pci_debug.h @@ -0,0 +1,28 @@ +#ifndef _S390_ASM_PCI_DEBUG_H +#define _S390_ASM_PCI_DEBUG_H + +#include <asm/debug.h> + +extern debug_info_t *pci_debug_msg_id; +extern debug_info_t *pci_debug_err_id; + +#define zpci_dbg(imp, fmt, args...)				\ +	debug_sprintf_event(pci_debug_msg_id, imp, fmt, ##args) + +#define zpci_err(text...)							\ +	do {									\ +		char debug_buffer[16];						\ +		snprintf(debug_buffer, 16, text);				\ +		debug_text_event(pci_debug_err_id, 0, debug_buffer);		\ +	} while (0) + +static inline void zpci_err_hex(void *addr, int len) +{ +	while (len > 0) { +		debug_event(pci_debug_err_id, 0, (void *) addr, len); +		len -= pci_debug_err_id->buf_size; +		addr += pci_debug_err_id->buf_size; +	} +} + +#endif diff --git a/arch/s390/include/asm/pci_dma.h b/arch/s390/include/asm/pci_dma.h new file mode 100644 index 00000000000..30b4c179c38 --- /dev/null +++ b/arch/s390/include/asm/pci_dma.h @@ -0,0 +1,196 @@ +#ifndef _ASM_S390_PCI_DMA_H +#define _ASM_S390_PCI_DMA_H + +/* I/O Translation Anchor (IOTA) */ +enum zpci_ioat_dtype { +	ZPCI_IOTA_STO = 0, +	ZPCI_IOTA_RTTO = 1, +	ZPCI_IOTA_RSTO = 2, +	ZPCI_IOTA_RFTO = 3, +	ZPCI_IOTA_PFAA = 4, +	ZPCI_IOTA_IOPFAA = 5, +	ZPCI_IOTA_IOPTO = 7 +}; + +#define ZPCI_IOTA_IOT_ENABLED		0x800UL +#define ZPCI_IOTA_DT_ST			(ZPCI_IOTA_STO	<< 2) +#define ZPCI_IOTA_DT_RT			(ZPCI_IOTA_RTTO << 2) +#define ZPCI_IOTA_DT_RS			(ZPCI_IOTA_RSTO << 2) +#define ZPCI_IOTA_DT_RF			(ZPCI_IOTA_RFTO << 2) +#define ZPCI_IOTA_DT_PF			(ZPCI_IOTA_PFAA << 2) +#define ZPCI_IOTA_FS_4K			0 +#define ZPCI_IOTA_FS_1M			1 +#define ZPCI_IOTA_FS_2G			2 +#define ZPCI_KEY			(PAGE_DEFAULT_KEY << 5) + +#define ZPCI_IOTA_STO_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_ST) +#define ZPCI_IOTA_RTTO_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RT) +#define ZPCI_IOTA_RSTO_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RS) +#define ZPCI_IOTA_RFTO_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_RF) +#define ZPCI_IOTA_RFAA_FLAG	(ZPCI_IOTA_IOT_ENABLED | ZPCI_KEY | ZPCI_IOTA_DT_PF | ZPCI_IOTA_FS_2G) + +/* I/O Region and segment tables */ +#define ZPCI_INDEX_MASK			0x7ffUL + +#define ZPCI_TABLE_TYPE_MASK		0xc +#define ZPCI_TABLE_TYPE_RFX		0xc +#define ZPCI_TABLE_TYPE_RSX		0x8 +#define ZPCI_TABLE_TYPE_RTX		0x4 +#define ZPCI_TABLE_TYPE_SX		0x0 + +#define ZPCI_TABLE_LEN_RFX		0x3 +#define ZPCI_TABLE_LEN_RSX		0x3 +#define ZPCI_TABLE_LEN_RTX		0x3 + +#define ZPCI_TABLE_OFFSET_MASK		0xc0 +#define ZPCI_TABLE_SIZE			0x4000 +#define ZPCI_TABLE_ALIGN		ZPCI_TABLE_SIZE +#define ZPCI_TABLE_ENTRY_SIZE		(sizeof(unsigned long)) +#define ZPCI_TABLE_ENTRIES		(ZPCI_TABLE_SIZE / ZPCI_TABLE_ENTRY_SIZE) + +#define ZPCI_TABLE_BITS			11 +#define ZPCI_PT_BITS			8 +#define ZPCI_ST_SHIFT			(ZPCI_PT_BITS + PAGE_SHIFT) +#define ZPCI_RT_SHIFT			(ZPCI_ST_SHIFT + ZPCI_TABLE_BITS) + +#define ZPCI_RTE_FLAG_MASK		0x3fffUL +#define ZPCI_RTE_ADDR_MASK		(~ZPCI_RTE_FLAG_MASK) +#define ZPCI_STE_FLAG_MASK		0x7ffUL +#define ZPCI_STE_ADDR_MASK		(~ZPCI_STE_FLAG_MASK) + +/* I/O Page tables */ +#define ZPCI_PTE_VALID_MASK		0x400 +#define ZPCI_PTE_INVALID		0x400 +#define ZPCI_PTE_VALID			0x000 +#define ZPCI_PT_SIZE			0x800 +#define ZPCI_PT_ALIGN			ZPCI_PT_SIZE +#define ZPCI_PT_ENTRIES			(ZPCI_PT_SIZE / ZPCI_TABLE_ENTRY_SIZE) +#define ZPCI_PT_MASK			(ZPCI_PT_ENTRIES - 1) + +#define ZPCI_PTE_FLAG_MASK		0xfffUL +#define ZPCI_PTE_ADDR_MASK		(~ZPCI_PTE_FLAG_MASK) + +/* Shared bits */ +#define ZPCI_TABLE_VALID		0x00 +#define ZPCI_TABLE_INVALID		0x20 +#define ZPCI_TABLE_PROTECTED		0x200 +#define ZPCI_TABLE_UNPROTECTED		0x000 + +#define ZPCI_TABLE_VALID_MASK		0x20 +#define ZPCI_TABLE_PROT_MASK		0x200 + +static inline unsigned int calc_rtx(dma_addr_t ptr) +{ +	return ((unsigned long) ptr >> ZPCI_RT_SHIFT) & ZPCI_INDEX_MASK; +} + +static inline unsigned int calc_sx(dma_addr_t ptr) +{ +	return ((unsigned long) ptr >> ZPCI_ST_SHIFT) & ZPCI_INDEX_MASK; +} + +static inline unsigned int calc_px(dma_addr_t ptr) +{ +	return ((unsigned long) ptr >> PAGE_SHIFT) & ZPCI_PT_MASK; +} + +static inline void set_pt_pfaa(unsigned long *entry, void *pfaa) +{ +	*entry &= ZPCI_PTE_FLAG_MASK; +	*entry |= ((unsigned long) pfaa & ZPCI_PTE_ADDR_MASK); +} + +static inline void set_rt_sto(unsigned long *entry, void *sto) +{ +	*entry &= ZPCI_RTE_FLAG_MASK; +	*entry |= ((unsigned long) sto & ZPCI_RTE_ADDR_MASK); +	*entry |= ZPCI_TABLE_TYPE_RTX; +} + +static inline void set_st_pto(unsigned long *entry, void *pto) +{ +	*entry &= ZPCI_STE_FLAG_MASK; +	*entry |= ((unsigned long) pto & ZPCI_STE_ADDR_MASK); +	*entry |= ZPCI_TABLE_TYPE_SX; +} + +static inline void validate_rt_entry(unsigned long *entry) +{ +	*entry &= ~ZPCI_TABLE_VALID_MASK; +	*entry &= ~ZPCI_TABLE_OFFSET_MASK; +	*entry |= ZPCI_TABLE_VALID; +	*entry |= ZPCI_TABLE_LEN_RTX; +} + +static inline void validate_st_entry(unsigned long *entry) +{ +	*entry &= ~ZPCI_TABLE_VALID_MASK; +	*entry |= ZPCI_TABLE_VALID; +} + +static inline void invalidate_table_entry(unsigned long *entry) +{ +	*entry &= ~ZPCI_TABLE_VALID_MASK; +	*entry |= ZPCI_TABLE_INVALID; +} + +static inline void invalidate_pt_entry(unsigned long *entry) +{ +	WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_INVALID); +	*entry &= ~ZPCI_PTE_VALID_MASK; +	*entry |= ZPCI_PTE_INVALID; +} + +static inline void validate_pt_entry(unsigned long *entry) +{ +	WARN_ON_ONCE((*entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID); +	*entry &= ~ZPCI_PTE_VALID_MASK; +	*entry |= ZPCI_PTE_VALID; +} + +static inline void entry_set_protected(unsigned long *entry) +{ +	*entry &= ~ZPCI_TABLE_PROT_MASK; +	*entry |= ZPCI_TABLE_PROTECTED; +} + +static inline void entry_clr_protected(unsigned long *entry) +{ +	*entry &= ~ZPCI_TABLE_PROT_MASK; +	*entry |= ZPCI_TABLE_UNPROTECTED; +} + +static inline int reg_entry_isvalid(unsigned long entry) +{ +	return (entry & ZPCI_TABLE_VALID_MASK) == ZPCI_TABLE_VALID; +} + +static inline int pt_entry_isvalid(unsigned long entry) +{ +	return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID; +} + +static inline int entry_isprotected(unsigned long entry) +{ +	return (entry & ZPCI_TABLE_PROT_MASK) == ZPCI_TABLE_PROTECTED; +} + +static inline unsigned long *get_rt_sto(unsigned long entry) +{ +	return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_RTX) +		? (unsigned long *) (entry & ZPCI_RTE_ADDR_MASK) +		: NULL; +} + +static inline unsigned long *get_st_pto(unsigned long entry) +{ +	return ((entry & ZPCI_TABLE_TYPE_MASK) == ZPCI_TABLE_TYPE_SX) +		? (unsigned long *) (entry & ZPCI_STE_ADDR_MASK) +		: NULL; +} + +/* Prototypes */ +int zpci_dma_init_device(struct zpci_dev *); +void zpci_dma_exit_device(struct zpci_dev *); + +#endif diff --git a/arch/s390/include/asm/pci_insn.h b/arch/s390/include/asm/pci_insn.h new file mode 100644 index 00000000000..649eb62c52b --- /dev/null +++ b/arch/s390/include/asm/pci_insn.h @@ -0,0 +1,86 @@ +#ifndef _ASM_S390_PCI_INSN_H +#define _ASM_S390_PCI_INSN_H + +/* Load/Store status codes */ +#define ZPCI_PCI_ST_FUNC_NOT_ENABLED		4 +#define ZPCI_PCI_ST_FUNC_IN_ERR			8 +#define ZPCI_PCI_ST_BLOCKED			12 +#define ZPCI_PCI_ST_INSUF_RES			16 +#define ZPCI_PCI_ST_INVAL_AS			20 +#define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED	24 +#define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED		28 +#define ZPCI_PCI_ST_2ND_OP_IN_INV_AS		36 +#define ZPCI_PCI_ST_FUNC_NOT_AVAIL		40 +#define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE		44 + +/* Load/Store return codes */ +#define ZPCI_PCI_LS_OK				0 +#define ZPCI_PCI_LS_ERR				1 +#define ZPCI_PCI_LS_BUSY			2 +#define ZPCI_PCI_LS_INVAL_HANDLE		3 + +/* Load/Store address space identifiers */ +#define ZPCI_PCIAS_MEMIO_0			0 +#define ZPCI_PCIAS_MEMIO_1			1 +#define ZPCI_PCIAS_MEMIO_2			2 +#define ZPCI_PCIAS_MEMIO_3			3 +#define ZPCI_PCIAS_MEMIO_4			4 +#define ZPCI_PCIAS_MEMIO_5			5 +#define ZPCI_PCIAS_CFGSPC			15 + +/* Modify PCI Function Controls */ +#define ZPCI_MOD_FC_REG_INT	2 +#define ZPCI_MOD_FC_DEREG_INT	3 +#define ZPCI_MOD_FC_REG_IOAT	4 +#define ZPCI_MOD_FC_DEREG_IOAT	5 +#define ZPCI_MOD_FC_REREG_IOAT	6 +#define ZPCI_MOD_FC_RESET_ERROR	7 +#define ZPCI_MOD_FC_RESET_BLOCK	9 +#define ZPCI_MOD_FC_SET_MEASURE	10 + +/* FIB function controls */ +#define ZPCI_FIB_FC_ENABLED	0x80 +#define ZPCI_FIB_FC_ERROR	0x40 +#define ZPCI_FIB_FC_LS_BLOCKED	0x20 +#define ZPCI_FIB_FC_DMAAS_REG	0x10 + +/* FIB function controls */ +#define ZPCI_FIB_FC_ENABLED	0x80 +#define ZPCI_FIB_FC_ERROR	0x40 +#define ZPCI_FIB_FC_LS_BLOCKED	0x20 +#define ZPCI_FIB_FC_DMAAS_REG	0x10 + +/* Function Information Block */ +struct zpci_fib { +	u32 fmt		:  8;	/* format */ +	u32		: 24; +	u32		: 32; +	u8 fc;			/* function controls */ +	u64		: 56; +	u64 pba;		/* PCI base address */ +	u64 pal;		/* PCI address limit */ +	u64 iota;		/* I/O Translation Anchor */ +	u32		:  1; +	u32 isc		:  3;	/* Interrupt subclass */ +	u32 noi		: 12;	/* Number of interrupts */ +	u32		:  2; +	u32 aibvo	:  6;	/* Adapter interrupt bit vector offset */ +	u32 sum		:  1;	/* Adapter int summary bit enabled */ +	u32		:  1; +	u32 aisbo	:  6;	/* Adapter int summary bit offset */ +	u32		: 32; +	u64 aibv;		/* Adapter int bit vector address */ +	u64 aisb;		/* Adapter int summary bit address */ +	u64 fmb_addr;		/* Function measurement block address and key */ +	u32		: 32; +	u32 gd; +} __packed __aligned(8); + +int zpci_mod_fc(u64 req, struct zpci_fib *fib); +int zpci_refresh_trans(u64 fn, u64 addr, u64 range); +int zpci_load(u64 *data, u64 req, u64 offset); +int zpci_store(u64 data, u64 req, u64 offset); +int zpci_store_block(const u64 *data, u64 req, u64 offset); +void zpci_set_irq_ctrl(u16 ctl, char *unused, u8 isc); + +#endif diff --git a/arch/s390/include/asm/pci_io.h b/arch/s390/include/asm/pci_io.h new file mode 100644 index 00000000000..d194d544d69 --- /dev/null +++ b/arch/s390/include/asm/pci_io.h @@ -0,0 +1,198 @@ +#ifndef _ASM_S390_PCI_IO_H +#define _ASM_S390_PCI_IO_H + +#ifdef CONFIG_PCI + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <asm/pci_insn.h> + +/* I/O Map */ +#define ZPCI_IOMAP_MAX_ENTRIES		0x7fff +#define ZPCI_IOMAP_ADDR_BASE		0x8000000000000000ULL +#define ZPCI_IOMAP_ADDR_IDX_MASK	0x7fff000000000000ULL +#define ZPCI_IOMAP_ADDR_OFF_MASK	0x0000ffffffffffffULL + +struct zpci_iomap_entry { +	u32 fh; +	u8 bar; +}; + +extern struct zpci_iomap_entry *zpci_iomap_start; + +#define ZPCI_IDX(addr)								\ +	(((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> 48) +#define ZPCI_OFFSET(addr)							\ +	((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK) + +#define ZPCI_CREATE_REQ(handle, space, len)					\ +	((u64) handle << 32 | space << 16 | len) + +#define zpci_read(LENGTH, RETTYPE)						\ +static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr)	\ +{										\ +	struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(addr)];	\ +	u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH);		\ +	u64 data;								\ +	int rc;									\ +										\ +	rc = zpci_load(&data, req, ZPCI_OFFSET(addr));				\ +	if (rc)									\ +		data = -1ULL;							\ +	return (RETTYPE) data;							\ +} + +#define zpci_write(LENGTH, VALTYPE)						\ +static inline void zpci_write_##VALTYPE(VALTYPE val,				\ +					const volatile void __iomem *addr)	\ +{										\ +	struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(addr)];	\ +	u64 req = ZPCI_CREATE_REQ(entry->fh, entry->bar, LENGTH);		\ +	u64 data = (VALTYPE) val;						\ +										\ +	zpci_store(data, req, ZPCI_OFFSET(addr));				\ +} + +zpci_read(8, u64) +zpci_read(4, u32) +zpci_read(2, u16) +zpci_read(1, u8) +zpci_write(8, u64) +zpci_write(4, u32) +zpci_write(2, u16) +zpci_write(1, u8) + +static inline int zpci_write_single(u64 req, const u64 *data, u64 offset, u8 len) +{ +	u64 val; + +	switch (len) { +	case 1: +		val = (u64) *((u8 *) data); +		break; +	case 2: +		val = (u64) *((u16 *) data); +		break; +	case 4: +		val = (u64) *((u32 *) data); +		break; +	case 8: +		val = (u64) *((u64 *) data); +		break; +	default: +		val = 0;		/* let FW report error */ +		break; +	} +	return zpci_store(val, req, offset); +} + +static inline int zpci_read_single(u64 req, u64 *dst, u64 offset, u8 len) +{ +	u64 data; +	int cc; + +	cc = zpci_load(&data, req, offset); +	if (cc) +		goto out; + +	switch (len) { +	case 1: +		*((u8 *) dst) = (u8) data; +		break; +	case 2: +		*((u16 *) dst) = (u16) data; +		break; +	case 4: +		*((u32 *) dst) = (u32) data; +		break; +	case 8: +		*((u64 *) dst) = (u64) data; +		break; +	} +out: +	return cc; +} + +static inline int zpci_write_block(u64 req, const u64 *data, u64 offset) +{ +	return zpci_store_block(data, req, offset); +} + +static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max) +{ +	int count = len > max ? max : len, size = 1; + +	while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) { +		dst = dst >> 1; +		src = src >> 1; +		size = size << 1; +	} +	return size; +} + +static inline int zpci_memcpy_fromio(void *dst, +				     const volatile void __iomem *src, +				     unsigned long n) +{ +	struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(src)]; +	u64 req, offset = ZPCI_OFFSET(src); +	int size, rc = 0; + +	while (n > 0) { +		size = zpci_get_max_write_size((u64) src, (u64) dst, n, 8); +		req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size); +		rc = zpci_read_single(req, dst, offset, size); +		if (rc) +			break; +		offset += size; +		dst += size; +		n -= size; +	} +	return rc; +} + +static inline int zpci_memcpy_toio(volatile void __iomem *dst, +				   const void *src, unsigned long n) +{ +	struct zpci_iomap_entry *entry = &zpci_iomap_start[ZPCI_IDX(dst)]; +	u64 req, offset = ZPCI_OFFSET(dst); +	int size, rc = 0; + +	if (!src) +		return -EINVAL; + +	while (n > 0) { +		size = zpci_get_max_write_size((u64) dst, (u64) src, n, 128); +		req = ZPCI_CREATE_REQ(entry->fh, entry->bar, size); + +		if (size > 8) /* main path */ +			rc = zpci_write_block(req, src, offset); +		else +			rc = zpci_write_single(req, src, offset, size); +		if (rc) +			break; +		offset += size; +		src += size; +		n -= size; +	} +	return rc; +} + +static inline int zpci_memset_io(volatile void __iomem *dst, +				 unsigned char val, size_t count) +{ +	u8 *src = kmalloc(count, GFP_KERNEL); +	int rc; + +	if (src == NULL) +		return -ENOMEM; +	memset(src, val, count); + +	rc = zpci_memcpy_toio(dst, src, count); +	kfree(src); +	return rc; +} + +#endif /* CONFIG_PCI */ + +#endif /* _ASM_S390_PCI_IO_H */ diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h index f7ad8719d02..fa91e009745 100644 --- a/arch/s390/include/asm/percpu.h +++ b/arch/s390/include/asm/percpu.h @@ -1,21 +1,190 @@  #ifndef __ARCH_S390_PERCPU__  #define __ARCH_S390_PERCPU__ +#include <linux/preempt.h> +#include <asm/cmpxchg.h> +  /*   * s390 uses its own implementation for per cpu data, the offset of   * the cpu local data area is cached in the cpu's lowcore memory.   */  #define __my_cpu_offset S390_lowcore.percpu_offset +#ifdef CONFIG_64BIT +  /*   * For 64 bit module code, the module may be more than 4G above the   * per cpu area, use weak definitions to force the compiler to   * generate external references.   */ -#if defined(CONFIG_SMP) && defined(__s390x__) && defined(MODULE) +#if defined(CONFIG_SMP) && defined(MODULE)  #define ARCH_NEEDS_WEAK_PER_CPU  #endif +/* + * We use a compare-and-swap loop since that uses less cpu cycles than + * disabling and enabling interrupts like the generic variant would do. + */ +#define arch_this_cpu_to_op_simple(pcp, val, op)			\ +({									\ +	typedef typeof(pcp) pcp_op_T__;					\ +	pcp_op_T__ old__, new__, prev__;				\ +	pcp_op_T__ *ptr__;						\ +	preempt_disable();						\ +	ptr__ = __this_cpu_ptr(&(pcp));					\ +	prev__ = *ptr__;						\ +	do {								\ +		old__ = prev__;						\ +		new__ = old__ op (val);					\ +		prev__ = cmpxchg(ptr__, old__, new__);			\ +	} while (prev__ != old__);					\ +	preempt_enable();						\ +	new__;								\ +}) + +#define this_cpu_add_1(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_add_2(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_and_1(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &) +#define this_cpu_and_2(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &) +#define this_cpu_or_1(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |) +#define this_cpu_or_2(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |) + +#ifndef CONFIG_HAVE_MARCH_Z196_FEATURES + +#define this_cpu_add_4(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_add_8(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) +#define this_cpu_and_4(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &) +#define this_cpu_and_8(pcp, val)	arch_this_cpu_to_op_simple(pcp, val, &) +#define this_cpu_or_4(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |) +#define this_cpu_or_8(pcp, val)		arch_this_cpu_to_op_simple(pcp, val, |) + +#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ + +#define arch_this_cpu_add(pcp, val, op1, op2, szcast)			\ +{									\ +	typedef typeof(pcp) pcp_op_T__; 				\ +	pcp_op_T__ val__ = (val);					\ +	pcp_op_T__ old__, *ptr__;					\ +	preempt_disable();						\ +	ptr__ = __this_cpu_ptr(&(pcp)); 				\ +	if (__builtin_constant_p(val__) &&				\ +	    ((szcast)val__ > -129) && ((szcast)val__ < 128)) {		\ +		asm volatile(						\ +			op2 "   %[ptr__],%[val__]\n"			\ +			: [ptr__] "+Q" (*ptr__) 			\ +			: [val__] "i" ((szcast)val__)			\ +			: "cc");					\ +	} else {							\ +		asm volatile(						\ +			op1 "   %[old__],%[val__],%[ptr__]\n"		\ +			: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)	\ +			: [val__] "d" (val__)				\ +			: "cc");					\ +	}								\ +	preempt_enable();						\ +} + +#define this_cpu_add_4(pcp, val) arch_this_cpu_add(pcp, val, "laa", "asi", int) +#define this_cpu_add_8(pcp, val) arch_this_cpu_add(pcp, val, "laag", "agsi", long) + +#define arch_this_cpu_add_return(pcp, val, op)				\ +({									\ +	typedef typeof(pcp) pcp_op_T__; 				\ +	pcp_op_T__ val__ = (val);					\ +	pcp_op_T__ old__, *ptr__;					\ +	preempt_disable();						\ +	ptr__ = __this_cpu_ptr(&(pcp)); 				\ +	asm volatile(							\ +		op "    %[old__],%[val__],%[ptr__]\n"			\ +		: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)		\ +		: [val__] "d" (val__)					\ +		: "cc");						\ +	preempt_enable();						\ +	old__ + val__;							\ +}) + +#define this_cpu_add_return_4(pcp, val) arch_this_cpu_add_return(pcp, val, "laa") +#define this_cpu_add_return_8(pcp, val) arch_this_cpu_add_return(pcp, val, "laag") + +#define arch_this_cpu_to_op(pcp, val, op)				\ +{									\ +	typedef typeof(pcp) pcp_op_T__; 				\ +	pcp_op_T__ val__ = (val);					\ +	pcp_op_T__ old__, *ptr__;					\ +	preempt_disable();						\ +	ptr__ = __this_cpu_ptr(&(pcp)); 				\ +	asm volatile(							\ +		op "    %[old__],%[val__],%[ptr__]\n"			\ +		: [old__] "=d" (old__), [ptr__] "+Q" (*ptr__)		\ +		: [val__] "d" (val__)					\ +		: "cc");						\ +	preempt_enable();						\ +} + +#define this_cpu_and_4(pcp, val)	arch_this_cpu_to_op(pcp, val, "lan") +#define this_cpu_and_8(pcp, val)	arch_this_cpu_to_op(pcp, val, "lang") +#define this_cpu_or_4(pcp, val)		arch_this_cpu_to_op(pcp, val, "lao") +#define this_cpu_or_8(pcp, val)		arch_this_cpu_to_op(pcp, val, "laog") + +#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ + +#define arch_this_cpu_cmpxchg(pcp, oval, nval)				\ +({									\ +	typedef typeof(pcp) pcp_op_T__;					\ +	pcp_op_T__ ret__;						\ +	pcp_op_T__ *ptr__;						\ +	preempt_disable();						\ +	ptr__ = __this_cpu_ptr(&(pcp));					\ +	ret__ = cmpxchg(ptr__, oval, nval);				\ +	preempt_enable();						\ +	ret__;								\ +}) + +#define this_cpu_cmpxchg_1(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) +#define this_cpu_cmpxchg_2(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) +#define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) +#define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) + +#define arch_this_cpu_xchg(pcp, nval)					\ +({									\ +	typeof(pcp) *ptr__;						\ +	typeof(pcp) ret__;						\ +	preempt_disable();						\ +	ptr__ = __this_cpu_ptr(&(pcp));					\ +	ret__ = xchg(ptr__, nval);					\ +	preempt_enable();						\ +	ret__;								\ +}) + +#define this_cpu_xchg_1(pcp, nval) arch_this_cpu_xchg(pcp, nval) +#define this_cpu_xchg_2(pcp, nval) arch_this_cpu_xchg(pcp, nval) +#define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval) +#define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval) + +#define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2)	\ +({									\ +	typeof(pcp1) o1__ = (o1), n1__ = (n1);				\ +	typeof(pcp2) o2__ = (o2), n2__ = (n2);				\ +	typeof(pcp1) *p1__;						\ +	typeof(pcp2) *p2__;						\ +	int ret__;							\ +	preempt_disable();						\ +	p1__ = __this_cpu_ptr(&(pcp1));					\ +	p2__ = __this_cpu_ptr(&(pcp2));					\ +	ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__);	\ +	preempt_enable();						\ +	ret__;								\ +}) + +#define this_cpu_cmpxchg_double_4 arch_this_cpu_cmpxchg_double +#define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double + +#endif /* CONFIG_64BIT */ +  #include <asm-generic/percpu.h>  #endif /* __ARCH_S390_PERCPU__ */ diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index a75f168d271..159a8ec6da9 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h @@ -1,9 +1,96 @@  /*   * Performance event support - s390 specific definitions.   * - * Copyright 2009 Martin Schwidefsky, IBM Corporation. + * Copyright IBM Corp. 2009, 2013 + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + *	      Hendrik Brueckner <brueckner@linux.vnet.ibm.com>   */ -/* Empty, just to avoid compiling error */ +#ifndef _ASM_S390_PERF_EVENT_H +#define _ASM_S390_PERF_EVENT_H -#define PERF_EVENT_INDEX_OFFSET 0 +#ifdef CONFIG_64BIT + +#include <linux/perf_event.h> +#include <linux/device.h> +#include <asm/cpu_mf.h> + +/* Per-CPU flags for PMU states */ +#define PMU_F_RESERVED			0x1000 +#define PMU_F_ENABLED			0x2000 +#define PMU_F_IN_USE			0x4000 +#define PMU_F_ERR_IBE			0x0100 +#define PMU_F_ERR_LSDA			0x0200 +#define PMU_F_ERR_MASK			(PMU_F_ERR_IBE|PMU_F_ERR_LSDA) + +/* Perf defintions for PMU event attributes in sysfs */ +extern __init const struct attribute_group **cpumf_cf_event_group(void); +extern ssize_t cpumf_events_sysfs_show(struct device *dev, +				       struct device_attribute *attr, +				       char *page); +#define EVENT_VAR(_cat, _name)		event_attr_##_cat##_##_name +#define EVENT_PTR(_cat, _name)		(&EVENT_VAR(_cat, _name).attr.attr) + +#define CPUMF_EVENT_ATTR(cat, name, id)			\ +	PMU_EVENT_ATTR(name, EVENT_VAR(cat, name), id, cpumf_events_sysfs_show) +#define CPUMF_EVENT_PTR(cat, name)	EVENT_PTR(cat, name) + + +/* Perf callbacks */ +struct pt_regs; +extern unsigned long perf_instruction_pointer(struct pt_regs *regs); +extern unsigned long perf_misc_flags(struct pt_regs *regs); +#define perf_misc_flags(regs) perf_misc_flags(regs) + +/* Perf pt_regs extension for sample-data-entry indicators */ +struct perf_sf_sde_regs { +	unsigned char in_guest:1;	  /* guest sample */ +	unsigned long reserved:63;	  /* reserved */ +}; + +/* Perf PMU definitions for the counter facility */ +#define PERF_CPUM_CF_MAX_CTR		256 + +/* Perf PMU definitions for the sampling facility */ +#define PERF_CPUM_SF_MAX_CTR		2 +#define PERF_EVENT_CPUM_SF		0xB0000UL /* Event: Basic-sampling */ +#define PERF_EVENT_CPUM_SF_DIAG		0xBD000UL /* Event: Combined-sampling */ +#define PERF_CPUM_SF_BASIC_MODE		0x0001	  /* Basic-sampling flag */ +#define PERF_CPUM_SF_DIAG_MODE		0x0002	  /* Diagnostic-sampling flag */ +#define PERF_CPUM_SF_MODE_MASK		(PERF_CPUM_SF_BASIC_MODE| \ +					 PERF_CPUM_SF_DIAG_MODE) +#define PERF_CPUM_SF_FULL_BLOCKS	0x0004	  /* Process full SDBs only */ + +#define REG_NONE		0 +#define REG_OVERFLOW		1 +#define OVERFLOW_REG(hwc)	((hwc)->extra_reg.config) +#define SFB_ALLOC_REG(hwc)	((hwc)->extra_reg.alloc) +#define RAWSAMPLE_REG(hwc)	((hwc)->config) +#define TEAR_REG(hwc)		((hwc)->last_tag) +#define SAMPL_RATE(hwc)		((hwc)->event_base) +#define SAMPL_FLAGS(hwc)	((hwc)->config_base) +#define SAMPL_DIAG_MODE(hwc)	(SAMPL_FLAGS(hwc) & PERF_CPUM_SF_DIAG_MODE) +#define SDB_FULL_BLOCKS(hwc)	(SAMPL_FLAGS(hwc) & PERF_CPUM_SF_FULL_BLOCKS) + +/* Structure for sampling data entries to be passed as perf raw sample data + * to user space.  Note that raw sample data must be aligned and, thus, might + * be padded with zeros. + */ +struct sf_raw_sample { +#define SF_RAW_SAMPLE_BASIC	PERF_CPUM_SF_BASIC_MODE +#define SF_RAW_SAMPLE_DIAG	PERF_CPUM_SF_DIAG_MODE +	u64			format; +	u32			 size;	  /* Size of sf_raw_sample */ +	u16			bsdes;	  /* Basic-sampling data entry size */ +	u16			dsdes;	  /* Diagnostic-sampling data entry size */ +	struct hws_basic_entry	basic;	  /* Basic-sampling data entry */ +	struct hws_diag_entry	 diag;	  /* Diagnostic-sampling data entry */ +	u8		    padding[];	  /* Padding to next multiple of 8 */ +} __packed; + +/* Perf hardware reserve and release functions */ +int perf_reserve_sampling(void); +void perf_release_sampling(void); + +#endif /* CONFIG_64BIT */ +#endif /* _ASM_S390_PERF_EVENT_H */ diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 082eb4e50e8..9e18a61d3df 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/pgalloc.h - *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999, 2000   *    Author(s): Hartmut Penner (hp@de.ibm.com)   *               Martin Schwidefsky (schwidefsky@de.ibm.com)   * @@ -17,16 +15,17 @@  #include <linux/gfp.h>  #include <linux/mm.h> -#define check_pgt_cache()	do {} while (0) - -unsigned long *crst_table_alloc(struct mm_struct *, int); +unsigned long *crst_table_alloc(struct mm_struct *);  void crst_table_free(struct mm_struct *, unsigned long *); -void crst_table_free_rcu(struct mm_struct *, unsigned long *); -unsigned long *page_table_alloc(struct mm_struct *); +unsigned long *page_table_alloc(struct mm_struct *, unsigned long);  void page_table_free(struct mm_struct *, unsigned long *); -void page_table_free_rcu(struct mm_struct *, unsigned long *); -void disable_noexec(struct mm_struct *, struct task_struct *); +void page_table_free_rcu(struct mmu_gather *, unsigned long *); + +void page_table_reset_pgste(struct mm_struct *, unsigned long, unsigned long, +			    bool init_skey); +int set_guest_storage_key(struct mm_struct *mm, unsigned long addr, +			  unsigned long key, bool nq);  static inline void clear_table(unsigned long *s, unsigned long val, size_t n)  { @@ -50,12 +49,9 @@ static inline void clear_table(unsigned long *s, unsigned long val, size_t n)  static inline void crst_table_init(unsigned long *crst, unsigned long entry)  {  	clear_table(crst, entry, sizeof(unsigned long)*2048); -	crst = get_shadow_table(crst); -	if (crst) -		clear_table(crst, entry, sizeof(unsigned long)*2048);  } -#ifndef __s390x__ +#ifndef CONFIG_64BIT  static inline unsigned long pgd_entry_type(struct mm_struct *mm)  { @@ -69,12 +65,9 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm)  #define pmd_free(mm, x)				do { } while (0)  #define pgd_populate(mm, pgd, pud)		BUG() -#define pgd_populate_kernel(mm, pgd, pud)	BUG() -  #define pud_populate(mm, pud, pmd)		BUG() -#define pud_populate_kernel(mm, pud, pmd)	BUG() -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  static inline unsigned long pgd_entry_type(struct mm_struct *mm)  { @@ -90,7 +83,7 @@ void crst_table_downgrade(struct mm_struct *, unsigned long limit);  static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)  { -	unsigned long *table = crst_table_alloc(mm, mm->context.noexec); +	unsigned long *table = crst_table_alloc(mm);  	if (table)  		crst_table_init(table, _REGION3_ENTRY_EMPTY);  	return (pud_t *) table; @@ -99,81 +92,61 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)  static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)  { -	unsigned long *table = crst_table_alloc(mm, mm->context.noexec); -	if (table) -		crst_table_init(table, _SEGMENT_ENTRY_EMPTY); +	unsigned long *table = crst_table_alloc(mm); + +	if (!table) +		return NULL; +	crst_table_init(table, _SEGMENT_ENTRY_EMPTY); +	if (!pgtable_pmd_page_ctor(virt_to_page(table))) { +		crst_table_free(mm, table); +		return NULL; +	}  	return (pmd_t *) table;  } -#define pmd_free(mm, pmd) crst_table_free(mm, (unsigned long *) pmd) -static inline void pgd_populate_kernel(struct mm_struct *mm, -				       pgd_t *pgd, pud_t *pud) +static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)  { -	pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud); +	pgtable_pmd_page_dtor(virt_to_page(pmd)); +	crst_table_free(mm, (unsigned long *) pmd);  }  static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)  { -	pgd_populate_kernel(mm, pgd, pud); -	if (mm->context.noexec) { -		pgd = get_shadow_table(pgd); -		pud = get_shadow_table(pud); -		pgd_populate_kernel(mm, pgd, pud); -	} -} - -static inline void pud_populate_kernel(struct mm_struct *mm, -				       pud_t *pud, pmd_t *pmd) -{ -	pud_val(*pud) = _REGION3_ENTRY | __pa(pmd); +	pgd_val(*pgd) = _REGION2_ENTRY | __pa(pud);  }  static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd)  { -	pud_populate_kernel(mm, pud, pmd); -	if (mm->context.noexec) { -		pud = get_shadow_table(pud); -		pmd = get_shadow_table(pmd); -		pud_populate_kernel(mm, pud, pmd); -	} +	pud_val(*pud) = _REGION3_ENTRY | __pa(pmd);  } -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  static inline pgd_t *pgd_alloc(struct mm_struct *mm)  {  	spin_lock_init(&mm->context.list_lock); -	INIT_LIST_HEAD(&mm->context.crst_list);  	INIT_LIST_HEAD(&mm->context.pgtable_list); -	return (pgd_t *) -		crst_table_alloc(mm, user_mode == SECONDARY_SPACE_MODE); +	INIT_LIST_HEAD(&mm->context.gmap_list); +	return (pgd_t *) crst_table_alloc(mm);  }  #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) -static inline void pmd_populate_kernel(struct mm_struct *mm, -				       pmd_t *pmd, pte_t *pte) -{ -	pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte); -} -  static inline void pmd_populate(struct mm_struct *mm,  				pmd_t *pmd, pgtable_t pte)  { -	pmd_populate_kernel(mm, pmd, pte); -	if (mm->context.noexec) { -		pmd = get_shadow_table(pmd); -		pmd_populate_kernel(mm, pmd, pte + PTRS_PER_PTE); -	} +	pmd_val(*pmd) = _SEGMENT_ENTRY + __pa(pte);  } +#define pmd_populate_kernel(mm, pmd, pte) pmd_populate(mm, pmd, pte) +  #define pmd_pgtable(pmd) \  	(pgtable_t)(pmd_val(pmd) & -sizeof(pte_t)*PTRS_PER_PTE)  /*   * page table entry allocation/free routines.   */ -#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm)) -#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm)) +#define pte_alloc_one_kernel(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr)) +#define pte_alloc_one(mm, vmaddr) ((pte_t *) page_table_alloc(mm, vmaddr))  #define pte_free_kernel(mm, pte) page_table_free(mm, (unsigned long *) pte)  #define pte_free(mm, pte) page_table_free(mm, (unsigned long *) pte) diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 02ace3491c5..fcba5e03839 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/pgtable.h - *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999, 2000   *    Author(s): Hartmut Penner (hp@de.ibm.com)   *               Ulrich Weigand (weigand@de.ibm.com)   *               Martin Schwidefsky (schwidefsky@de.ibm.com) @@ -31,20 +29,20 @@  #ifndef __ASSEMBLY__  #include <linux/sched.h>  #include <linux/mm_types.h> -#include <asm/bitops.h> +#include <linux/page-flags.h>  #include <asm/bug.h> -#include <asm/processor.h> +#include <asm/page.h>  extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));  extern void paging_init(void);  extern void vmem_map_init(void); -extern void fault_init(void);  /*   * The S390 doesn't have any external MMU info: the kernel page   * tables contain all the necessary information.   */  #define update_mmu_cache(vma, address, ptep)     do { } while (0) +#define update_mmu_cache_pmd(vma, address, ptep) do { } while (0)  /*   * ZERO_PAGE is a global shared page that is always zero; used @@ -57,17 +55,9 @@ extern unsigned long zero_page_mask;  #define ZERO_PAGE(vaddr) \  	(virt_to_page((void *)(empty_zero_page + \  	 (((unsigned long)(vaddr)) &zero_page_mask)))) +#define __HAVE_COLOR_ZERO_PAGE -#define is_zero_pfn is_zero_pfn -static inline int is_zero_pfn(unsigned long pfn) -{ -	extern unsigned long zero_pfn; -	unsigned long offset_from_zero_pfn = pfn - zero_pfn; -	return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT); -} - -#define my_zero_pfn(addr)	page_to_pfn(ZERO_PAGE(addr)) - +/* TODO: s390 cannot support io_remap_pfn_range... */  #endif /* !__ASSEMBLY__ */  /* @@ -75,15 +65,15 @@ static inline int is_zero_pfn(unsigned long pfn)   * table can map   * PGDIR_SHIFT determines what a third-level page table entry can map   */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  # define PMD_SHIFT	20  # define PUD_SHIFT	20  # define PGDIR_SHIFT	20 -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  # define PMD_SHIFT	20  # define PUD_SHIFT	31  # define PGDIR_SHIFT	42 -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  #define PMD_SIZE        (1UL << PMD_SHIFT)  #define PMD_MASK        (~(PMD_SIZE-1)) @@ -99,13 +89,13 @@ static inline int is_zero_pfn(unsigned long pfn)   * that leads to 1024 pte per pgd   */  #define PTRS_PER_PTE	256 -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define PTRS_PER_PMD	1  #define PTRS_PER_PUD	1 -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  #define PTRS_PER_PMD	2048  #define PTRS_PER_PUD	2048 -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  #define PTRS_PER_PGD	2048  #define FIRST_USER_ADDRESS  0 @@ -121,36 +111,26 @@ static inline int is_zero_pfn(unsigned long pfn)  #ifndef __ASSEMBLY__  /* - * The vmalloc area will always be on the topmost area of the kernel - * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc, - * which should be enough for any sane case. - * By putting vmalloc at the top, we maximise the gap between physical - * memory and vmalloc to catch misplaced memory accesses. As a side - * effect, this also makes sure that 64 bit module code cannot be used - * as system call address. + * The vmalloc and module area will always be on the topmost area of the kernel + * mapping. We reserve 96MB (31bit) / 128GB (64bit) for vmalloc and modules. + * On 64 bit kernels we have a 2GB area at the top of the vmalloc area where + * modules will reside. That makes sure that inter module branches always + * happen without trampolines and in addition the placement within a 2GB frame + * is branch prediction unit friendly.   */ -  extern unsigned long VMALLOC_START; +extern unsigned long VMALLOC_END; +extern struct page *vmemmap; -#ifndef __s390x__ -#define VMALLOC_SIZE	(96UL << 20) -#define VMALLOC_END	0x7e000000UL -#define VMEM_MAP_END	0x80000000UL -#else /* __s390x__ */ -#define VMALLOC_SIZE	(128UL << 30) -#define VMALLOC_END	0x3e000000000UL -#define VMEM_MAP_END	0x40000000000UL -#endif /* __s390x__ */ +#define VMEM_MAX_PHYS ((unsigned long) vmemmap) -/* - * VMEM_MAX_PHYS is the highest physical address that can be added to the 1:1 - * mapping. This needs to be calculated at compile time since the size of the - * VMEM_MAP is static but the size of struct page can change. - */ -#define VMEM_MAX_PAGES	((VMEM_MAP_END - VMALLOC_END) / sizeof(struct page)) -#define VMEM_MAX_PFN	min(VMALLOC_START >> PAGE_SHIFT, VMEM_MAX_PAGES) -#define VMEM_MAX_PHYS	((VMEM_MAX_PFN << PAGE_SHIFT) & ~((16 << 20) - 1)) -#define vmemmap		((struct page *) VMALLOC_END) +#ifdef CONFIG_64BIT +extern unsigned long MODULES_VADDR; +extern unsigned long MODULES_END; +#define MODULES_VADDR	MODULES_VADDR +#define MODULES_END	MODULES_END +#define MODULES_LEN	(1UL << 31) +#endif  /*   * A 31 bit pagetable entry of S390 has following format: @@ -237,76 +217,61 @@ extern unsigned long VMALLOC_START;  /* Hardware bits in the page table entry */  #define _PAGE_CO	0x100		/* HW Change-bit override */ -#define _PAGE_RO	0x200		/* HW read-only bit  */ +#define _PAGE_PROTECT	0x200		/* HW read-only bit  */  #define _PAGE_INVALID	0x400		/* HW invalid bit    */ +#define _PAGE_LARGE	0x800		/* Bit to mark a large pte */  /* Software bits in the page table entry */ -#define _PAGE_SWT	0x001		/* SW pte type bit t */ -#define _PAGE_SWX	0x002		/* SW pte type bit x */ -#define _PAGE_SPECIAL	0x004		/* SW associated with special page */ +#define _PAGE_PRESENT	0x001		/* SW pte present bit */ +#define _PAGE_TYPE	0x002		/* SW pte type bit */ +#define _PAGE_YOUNG	0x004		/* SW pte young bit */ +#define _PAGE_DIRTY	0x008		/* SW pte dirty bit */ +#define _PAGE_READ	0x010		/* SW pte read bit */ +#define _PAGE_WRITE	0x020		/* SW pte write bit */ +#define _PAGE_SPECIAL	0x040		/* SW associated with special page */ +#define _PAGE_UNUSED	0x080		/* SW bit for pgste usage state */  #define __HAVE_ARCH_PTE_SPECIAL  /* Set of bits not changed in pte_modify */ -#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_SPECIAL) - -/* Six different types of pages. */ -#define _PAGE_TYPE_EMPTY	0x400 -#define _PAGE_TYPE_NONE		0x401 -#define _PAGE_TYPE_SWAP		0x403 -#define _PAGE_TYPE_FILE		0x601	/* bit 0x002 is used for offset !! */ -#define _PAGE_TYPE_RO		0x200 -#define _PAGE_TYPE_RW		0x000 -#define _PAGE_TYPE_EX_RO	0x202 -#define _PAGE_TYPE_EX_RW	0x002 - -/* - * Only four types for huge pages, using the invalid bit and protection bit - * of a segment table entry. - */ -#define _HPAGE_TYPE_EMPTY	0x020	/* _SEGMENT_ENTRY_INV */ -#define _HPAGE_TYPE_NONE	0x220 -#define _HPAGE_TYPE_RO		0x200	/* _SEGMENT_ENTRY_RO  */ -#define _HPAGE_TYPE_RW		0x000 +#define _PAGE_CHG_MASK		(PAGE_MASK | _PAGE_SPECIAL | _PAGE_CO | \ +				 _PAGE_DIRTY | _PAGE_YOUNG)  /* - * PTE type bits are rather complicated. handle_pte_fault uses pte_present, - * pte_none and pte_file to find out the pte type WITHOUT holding the page - * table lock. ptep_clear_flush on the other hand uses ptep_clear_flush to - * invalidate a given pte. ipte sets the hw invalid bit and clears all tlbs - * for the page. The page table entry is set to _PAGE_TYPE_EMPTY afterwards. - * This change is done while holding the lock, but the intermediate step - * of a previously valid pte with the hw invalid bit set can be observed by - * handle_pte_fault. That makes it necessary that all valid pte types with - * the hw invalid bit set must be distinguishable from the four pte types - * empty, none, swap and file. + * handle_pte_fault uses pte_present, pte_none and pte_file to find out the + * pte type WITHOUT holding the page table lock. The _PAGE_PRESENT bit + * is used to distinguish present from not-present ptes. It is changed only + * with the page table lock held.   * - *			irxt  ipte  irxt - * _PAGE_TYPE_EMPTY	1000   ->   1000 - * _PAGE_TYPE_NONE	1001   ->   1001 - * _PAGE_TYPE_SWAP	1011   ->   1011 - * _PAGE_TYPE_FILE	11?1   ->   11?1 - * _PAGE_TYPE_RO	0100   ->   1100 - * _PAGE_TYPE_RW	0000   ->   1000 - * _PAGE_TYPE_EX_RO	0110   ->   1110 - * _PAGE_TYPE_EX_RW	0010   ->   1010 + * The following table gives the different possible bit combinations for + * the pte hardware and software bits in the last 12 bits of a pte:   * - * pte_none is true for bits combinations 1000, 1010, 1100, 1110 - * pte_present is true for bits combinations 0000, 0010, 0100, 0110, 1001 - * pte_file is true for bits combinations 1101, 1111 - * swap pte is 1011 and 0001, 0011, 0101, 0111 are invalid. + *				842100000000 + *				000084210000 + *				000000008421 + *				.IR...wrdytp + * empty			.10...000000 + * swap				.10...xxxx10 + * file				.11...xxxxx0 + * prot-none, clean, old	.11...000001 + * prot-none, clean, young	.11...000101 + * prot-none, dirty, old	.10...001001 + * prot-none, dirty, young	.10...001101 + * read-only, clean, old	.11...010001 + * read-only, clean, young	.01...010101 + * read-only, dirty, old	.11...011001 + * read-only, dirty, young	.01...011101 + * read-write, clean, old	.11...110001 + * read-write, clean, young	.01...110101 + * read-write, dirty, old	.10...111001 + * read-write, dirty, young	.00...111101 + * + * pte_present is true for the bit pattern .xx...xxxxx1, (pte & 0x001) == 0x001 + * pte_none    is true for the bit pattern .10...xxxx00, (pte & 0x603) == 0x400 + * pte_file    is true for the bit pattern .11...xxxxx0, (pte & 0x601) == 0x600 + * pte_swap    is true for the bit pattern .10...xxxx10, (pte & 0x603) == 0x402   */ -/* Page status table bits for virtualization */ -#define RCP_PCL_BIT	55 -#define RCP_HR_BIT	54 -#define RCP_HC_BIT	53 -#define RCP_GR_BIT	50 -#define RCP_GC_BIT	49 - -/* User dirty bit for KVM's migration feature */ -#define KVM_UD_BIT	47 - -#ifndef __s390x__ +#ifndef CONFIG_64BIT  /* Bits in the segment table address-space-control-element */  #define _ASCE_SPACE_SWITCH	0x80000000UL	/* space switch event	    */ @@ -316,16 +281,38 @@ extern unsigned long VMALLOC_START;  #define _ASCE_TABLE_LENGTH	0x7f	/* 128 x 64 entries = 8k	    */  /* Bits in the segment table entry */ +#define _SEGMENT_ENTRY_BITS	0x7fffffffUL	/* Valid segment table bits */  #define _SEGMENT_ENTRY_ORIGIN	0x7fffffc0UL	/* page table origin	    */ -#define _SEGMENT_ENTRY_RO	0x200	/* page protection bit		    */ -#define _SEGMENT_ENTRY_INV	0x20	/* invalid segment table entry	    */ +#define _SEGMENT_ENTRY_PROTECT	0x200	/* page protection bit		    */ +#define _SEGMENT_ENTRY_INVALID	0x20	/* invalid segment table entry	    */  #define _SEGMENT_ENTRY_COMMON	0x10	/* common segment bit		    */  #define _SEGMENT_ENTRY_PTL	0x0f	/* page table length		    */ +#define _SEGMENT_ENTRY_NONE	_SEGMENT_ENTRY_PROTECT  #define _SEGMENT_ENTRY		(_SEGMENT_ENTRY_PTL) -#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INV) +#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID) + +/* + * Segment table entry encoding (I = invalid, R = read-only bit): + *		..R...I..... + * prot-none	..1...1..... + * read-only	..1...0..... + * read-write	..0...0..... + * empty	..0...1..... + */ -#else /* __s390x__ */ +/* Page status table bits for virtualization */ +#define PGSTE_ACC_BITS	0xf0000000UL +#define PGSTE_FP_BIT	0x08000000UL +#define PGSTE_PCL_BIT	0x00800000UL +#define PGSTE_HR_BIT	0x00400000UL +#define PGSTE_HC_BIT	0x00200000UL +#define PGSTE_GR_BIT	0x00040000UL +#define PGSTE_GC_BIT	0x00020000UL +#define PGSTE_UC_BIT	0x00008000UL	/* user dirty (migration) */ +#define PGSTE_IN_BIT	0x00004000UL	/* IPTE notify bit */ + +#else /* CONFIG_64BIT */  /* Bits in the segment/region table address-space-control-element */  #define _ASCE_ORIGIN		~0xfffUL/* segment table origin		    */ @@ -342,7 +329,8 @@ extern unsigned long VMALLOC_START;  /* Bits in the region table entry */  #define _REGION_ENTRY_ORIGIN	~0xfffUL/* region/segment table origin	    */ -#define _REGION_ENTRY_INV	0x20	/* invalid region table entry	    */ +#define _REGION_ENTRY_PROTECT	0x200	/* region protection bit	    */ +#define _REGION_ENTRY_INVALID	0x20	/* invalid region table entry	    */  #define _REGION_ENTRY_TYPE_MASK	0x0c	/* region/segment table type mask   */  #define _REGION_ENTRY_TYPE_R1	0x0c	/* region first table type	    */  #define _REGION_ENTRY_TYPE_R2	0x08	/* region second table type	    */ @@ -350,24 +338,70 @@ extern unsigned long VMALLOC_START;  #define _REGION_ENTRY_LENGTH	0x03	/* region third length		    */  #define _REGION1_ENTRY		(_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_LENGTH) -#define _REGION1_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INV) +#define _REGION1_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID)  #define _REGION2_ENTRY		(_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH) -#define _REGION2_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INV) +#define _REGION2_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID)  #define _REGION3_ENTRY		(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH) -#define _REGION3_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV) +#define _REGION3_ENTRY_EMPTY	(_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID) + +#define _REGION3_ENTRY_LARGE	0x400	/* RTTE-format control, large page  */ +#define _REGION3_ENTRY_RO	0x200	/* page protection bit		    */ +#define _REGION3_ENTRY_CO	0x100	/* change-recording override	    */  /* Bits in the segment table entry */ +#define _SEGMENT_ENTRY_BITS	0xfffffffffffffe33UL +#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff1ff33UL +#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address	    */  #define _SEGMENT_ENTRY_ORIGIN	~0x7ffUL/* segment table origin		    */ -#define _SEGMENT_ENTRY_RO	0x200	/* page protection bit		    */ -#define _SEGMENT_ENTRY_INV	0x20	/* invalid segment table entry	    */ +#define _SEGMENT_ENTRY_PROTECT	0x200	/* page protection bit		    */ +#define _SEGMENT_ENTRY_INVALID	0x20	/* invalid segment table entry	    */  #define _SEGMENT_ENTRY		(0) -#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INV) +#define _SEGMENT_ENTRY_EMPTY	(_SEGMENT_ENTRY_INVALID)  #define _SEGMENT_ENTRY_LARGE	0x400	/* STE-format control, large page   */  #define _SEGMENT_ENTRY_CO	0x100	/* change-recording override   */ +#define _SEGMENT_ENTRY_SPLIT	0x001	/* THP splitting bit */ +#define _SEGMENT_ENTRY_YOUNG	0x002	/* SW segment young bit */ +#define _SEGMENT_ENTRY_NONE	_SEGMENT_ENTRY_YOUNG + +/* + * Segment table entry encoding (R = read-only, I = invalid, y = young bit): + *			..R...I...y. + * prot-none, old	..0...1...1. + * prot-none, young	..1...1...1. + * read-only, old	..1...1...0. + * read-only, young	..1...0...1. + * read-write, old	..0...1...0. + * read-write, young	..0...0...1. + * The segment table origin is used to distinguish empty (origin==0) from + * read-write, old segment table entries (origin!=0) + */ -#endif /* __s390x__ */ +#define _SEGMENT_ENTRY_SPLIT_BIT 0	/* THP splitting bit number */ + +/* Set of bits not changed in pmd_modify */ +#define _SEGMENT_CHG_MASK	(_SEGMENT_ENTRY_ORIGIN | _SEGMENT_ENTRY_LARGE \ +				 | _SEGMENT_ENTRY_SPLIT | _SEGMENT_ENTRY_CO) + +/* Page status table bits for virtualization */ +#define PGSTE_ACC_BITS	0xf000000000000000UL +#define PGSTE_FP_BIT	0x0800000000000000UL +#define PGSTE_PCL_BIT	0x0080000000000000UL +#define PGSTE_HR_BIT	0x0040000000000000UL +#define PGSTE_HC_BIT	0x0020000000000000UL +#define PGSTE_GR_BIT	0x0004000000000000UL +#define PGSTE_GC_BIT	0x0002000000000000UL +#define PGSTE_UC_BIT	0x0000800000000000UL	/* user dirty (migration) */ +#define PGSTE_IN_BIT	0x0000400000000000UL	/* IPTE notify bit */ + +#endif /* CONFIG_64BIT */ + +/* Guest Page State used for virtualization */ +#define _PGSTE_GPS_ZERO		0x0000000080000000UL +#define _PGSTE_GPS_USAGE_MASK	0x0000000003000000UL +#define _PGSTE_GPS_USAGE_STABLE 0x0000000000000000UL +#define _PGSTE_GPS_USAGE_UNUSED 0x0000000001000000UL  /*   * A user page table pointer has the space-switch-event bit, the @@ -377,89 +411,77 @@ extern unsigned long VMALLOC_START;  #define _ASCE_USER_BITS		(_ASCE_SPACE_SWITCH | _ASCE_PRIVATE_SPACE | \  				 _ASCE_ALT_EVENT) -/* Bits int the storage key */ -#define _PAGE_CHANGED    0x02          /* HW changed bit                   */ -#define _PAGE_REFERENCED 0x04          /* HW referenced bit                */ -  /*   * Page protection definitions.   */ -#define PAGE_NONE	__pgprot(_PAGE_TYPE_NONE) -#define PAGE_RO		__pgprot(_PAGE_TYPE_RO) -#define PAGE_RW		__pgprot(_PAGE_TYPE_RW) -#define PAGE_EX_RO	__pgprot(_PAGE_TYPE_EX_RO) -#define PAGE_EX_RW	__pgprot(_PAGE_TYPE_EX_RW) - -#define PAGE_KERNEL	PAGE_RW -#define PAGE_COPY	PAGE_RO +#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _PAGE_INVALID) +#define PAGE_READ	__pgprot(_PAGE_PRESENT | _PAGE_READ | \ +				 _PAGE_INVALID | _PAGE_PROTECT) +#define PAGE_WRITE	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ +				 _PAGE_INVALID | _PAGE_PROTECT) + +#define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ +				 _PAGE_YOUNG | _PAGE_DIRTY) +#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ +				 _PAGE_YOUNG | _PAGE_DIRTY) +#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_YOUNG | \ +				 _PAGE_PROTECT)  /* - * Dependent on the EXEC_PROTECT option s390 can do execute protection. - * Write permission always implies read permission. In theory with a - * primary/secondary page table execute only can be implemented but - * it would cost an additional bit in the pte to distinguish all the - * different pte types. To avoid that execute permission currently - * implies read permission as well. + * On s390 the page table entry has an invalid bit and a read-only bit. + * Read permission implies execute permission and write permission + * implies read permission.   */           /*xwr*/  #define __P000	PAGE_NONE -#define __P001	PAGE_RO -#define __P010	PAGE_RO -#define __P011	PAGE_RO -#define __P100	PAGE_EX_RO -#define __P101	PAGE_EX_RO -#define __P110	PAGE_EX_RO -#define __P111	PAGE_EX_RO +#define __P001	PAGE_READ +#define __P010	PAGE_READ +#define __P011	PAGE_READ +#define __P100	PAGE_READ +#define __P101	PAGE_READ +#define __P110	PAGE_READ +#define __P111	PAGE_READ  #define __S000	PAGE_NONE -#define __S001	PAGE_RO -#define __S010	PAGE_RW -#define __S011	PAGE_RW -#define __S100	PAGE_EX_RO -#define __S101	PAGE_EX_RO -#define __S110	PAGE_EX_RW -#define __S111	PAGE_EX_RW +#define __S001	PAGE_READ +#define __S010	PAGE_WRITE +#define __S011	PAGE_WRITE +#define __S100	PAGE_READ +#define __S101	PAGE_READ +#define __S110	PAGE_WRITE +#define __S111	PAGE_WRITE -#ifndef __s390x__ -# define PxD_SHADOW_SHIFT	1 -#else /* __s390x__ */ -# define PxD_SHADOW_SHIFT	2 -#endif /* __s390x__ */ +/* + * Segment entry (large page) protection definitions. + */ +#define SEGMENT_NONE	__pgprot(_SEGMENT_ENTRY_INVALID | \ +				 _SEGMENT_ENTRY_NONE) +#define SEGMENT_READ	__pgprot(_SEGMENT_ENTRY_INVALID | \ +				 _SEGMENT_ENTRY_PROTECT) +#define SEGMENT_WRITE	__pgprot(_SEGMENT_ENTRY_INVALID) -static inline void *get_shadow_table(void *table) +static inline int mm_has_pgste(struct mm_struct *mm)  { -	unsigned long addr, offset; -	struct page *page; - -	addr = (unsigned long) table; -	offset = addr & ((PAGE_SIZE << PxD_SHADOW_SHIFT) - 1); -	page = virt_to_page((void *)(addr ^ offset)); -	return (void *)(addr_t)(page->index ? (page->index | offset) : 0UL); +#ifdef CONFIG_PGSTE +	if (unlikely(mm->context.has_pgste)) +		return 1; +#endif +	return 0;  } -/* - * Certain architectures need to do special things when PTEs - * within a page table are directly modified.  Thus, the following - * hook is made available. - */ -static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, -			      pte_t *ptep, pte_t entry) +static inline int mm_use_skey(struct mm_struct *mm)  { -	*ptep = entry; -	if (mm->context.noexec) { -		if (!(pte_val(entry) & _PAGE_INVALID) && -		    (pte_val(entry) & _PAGE_SWX)) -			pte_val(entry) |= _PAGE_RO; -		else -			pte_val(entry) = _PAGE_TYPE_EMPTY; -		ptep[PTRS_PER_PTE] = entry; -	} +#ifdef CONFIG_PGSTE +	if (mm->context.use_skey) +		return 1; +#endif +	return 0;  }  /*   * pgd/pmd/pte query functions   */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  static inline int pgd_present(pgd_t pgd) { return 1; }  static inline int pgd_none(pgd_t pgd)    { return 0; } @@ -467,9 +489,10 @@ static inline int pgd_bad(pgd_t pgd)     { return 0; }  static inline int pud_present(pud_t pud) { return 1; }  static inline int pud_none(pud_t pud)	 { return 0; } +static inline int pud_large(pud_t pud)	 { return 0; }  static inline int pud_bad(pud_t pud)	 { return 0; } -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  static inline int pgd_present(pgd_t pgd)  { @@ -482,7 +505,7 @@ static inline int pgd_none(pgd_t pgd)  {  	if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2)  		return 0; -	return (pgd_val(pgd) & _REGION_ENTRY_INV) != 0UL; +	return (pgd_val(pgd) & _REGION_ENTRY_INVALID) != 0UL;  }  static inline int pgd_bad(pgd_t pgd) @@ -493,7 +516,7 @@ static inline int pgd_bad(pgd_t pgd)  	 * invalid for either table entry.  	 */  	unsigned long mask = -		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & +		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INVALID &  		~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH;  	return (pgd_val(pgd) & mask) != 0;  } @@ -509,7 +532,14 @@ static inline int pud_none(pud_t pud)  {  	if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3)  		return 0; -	return (pud_val(pud) & _REGION_ENTRY_INV) != 0UL; +	return (pud_val(pud) & _REGION_ENTRY_INVALID) != 0UL; +} + +static inline int pud_large(pud_t pud) +{ +	if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3) +		return 0; +	return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);  }  static inline int pud_bad(pud_t pud) @@ -520,46 +550,105 @@ static inline int pud_bad(pud_t pud)  	 * invalid for either table entry.  	 */  	unsigned long mask = -		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INV & +		~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INVALID &  		~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH;  	return (pud_val(pud) & mask) != 0;  } -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  static inline int pmd_present(pmd_t pmd)  { -	return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL; +	return pmd_val(pmd) != _SEGMENT_ENTRY_INVALID;  }  static inline int pmd_none(pmd_t pmd)  { -	return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; +	return pmd_val(pmd) == _SEGMENT_ENTRY_INVALID; +} + +static inline int pmd_large(pmd_t pmd) +{ +#ifdef CONFIG_64BIT +	return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0; +#else +	return 0; +#endif +} + +static inline int pmd_prot_none(pmd_t pmd) +{ +	return (pmd_val(pmd) & _SEGMENT_ENTRY_INVALID) && +		(pmd_val(pmd) & _SEGMENT_ENTRY_NONE);  }  static inline int pmd_bad(pmd_t pmd)  { -	unsigned long mask = ~_SEGMENT_ENTRY_ORIGIN & ~_SEGMENT_ENTRY_INV; -	return (pmd_val(pmd) & mask) != _SEGMENT_ENTRY; +#ifdef CONFIG_64BIT +	if (pmd_large(pmd)) +		return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0; +#endif +	return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0;  } -static inline int pte_none(pte_t pte) +#define __HAVE_ARCH_PMDP_SPLITTING_FLUSH +extern void pmdp_splitting_flush(struct vm_area_struct *vma, +				 unsigned long addr, pmd_t *pmdp); + +#define  __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS +extern int pmdp_set_access_flags(struct vm_area_struct *vma, +				 unsigned long address, pmd_t *pmdp, +				 pmd_t entry, int dirty); + +#define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH +extern int pmdp_clear_flush_young(struct vm_area_struct *vma, +				  unsigned long address, pmd_t *pmdp); + +#define __HAVE_ARCH_PMD_WRITE +static inline int pmd_write(pmd_t pmd)  { -	return (pte_val(pte) & _PAGE_INVALID) && !(pte_val(pte) & _PAGE_SWT); +	if (pmd_prot_none(pmd)) +		return 0; +	return (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) == 0; +} + +static inline int pmd_young(pmd_t pmd) +{ +	int young = 0; +#ifdef CONFIG_64BIT +	if (pmd_prot_none(pmd)) +		young = (pmd_val(pmd) & _SEGMENT_ENTRY_PROTECT) != 0; +	else +		young = (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0; +#endif +	return young;  }  static inline int pte_present(pte_t pte)  { -	unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT | _PAGE_SWX; -	return (pte_val(pte) & mask) == _PAGE_TYPE_NONE || -		(!(pte_val(pte) & _PAGE_INVALID) && -		 !(pte_val(pte) & _PAGE_SWT)); +	/* Bit pattern: (pte & 0x001) == 0x001 */ +	return (pte_val(pte) & _PAGE_PRESENT) != 0; +} + +static inline int pte_none(pte_t pte) +{ +	/* Bit pattern: pte == 0x400 */ +	return pte_val(pte) == _PAGE_INVALID; +} + +static inline int pte_swap(pte_t pte) +{ +	/* Bit pattern: (pte & 0x603) == 0x402 */ +	return (pte_val(pte) & (_PAGE_INVALID | _PAGE_PROTECT | +				_PAGE_TYPE | _PAGE_PRESENT)) +		== (_PAGE_INVALID | _PAGE_TYPE);  }  static inline int pte_file(pte_t pte)  { -	unsigned long mask = _PAGE_RO | _PAGE_INVALID | _PAGE_SWT; -	return (pte_val(pte) & mask) == _PAGE_TYPE_FILE; +	/* Bit pattern: (pte & 0x601) == 0x600 */ +	return (pte_val(pte) & (_PAGE_INVALID | _PAGE_PROTECT | _PAGE_PRESENT)) +		== (_PAGE_INVALID | _PAGE_PROTECT);  }  static inline int pte_special(pte_t pte) @@ -568,52 +657,228 @@ static inline int pte_special(pte_t pte)  }  #define __HAVE_ARCH_PTE_SAME -#define pte_same(a,b)  (pte_val(a) == pte_val(b)) +static inline int pte_same(pte_t a, pte_t b) +{ +	return pte_val(a) == pte_val(b); +} -static inline void rcp_lock(pte_t *ptep) +static inline pgste_t pgste_get_lock(pte_t *ptep)  { +	unsigned long new = 0;  #ifdef CONFIG_PGSTE -	unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); +	unsigned long old; +  	preempt_disable(); -	while (test_and_set_bit(RCP_PCL_BIT, pgste)) -		; +	asm( +		"	lg	%0,%2\n" +		"0:	lgr	%1,%0\n" +		"	nihh	%0,0xff7f\n"	/* clear PCL bit in old */ +		"	oihh	%1,0x0080\n"	/* set PCL bit in new */ +		"	csg	%0,%1,%2\n" +		"	jl	0b\n" +		: "=&d" (old), "=&d" (new), "=Q" (ptep[PTRS_PER_PTE]) +		: "Q" (ptep[PTRS_PER_PTE]) : "cc", "memory");  #endif +	return __pgste(new);  } -static inline void rcp_unlock(pte_t *ptep) +static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)  {  #ifdef CONFIG_PGSTE -	unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); -	clear_bit(RCP_PCL_BIT, pgste); +	asm( +		"	nihh	%1,0xff7f\n"	/* clear PCL bit */ +		"	stg	%1,%0\n" +		: "=Q" (ptep[PTRS_PER_PTE]) +		: "d" (pgste_val(pgste)), "Q" (ptep[PTRS_PER_PTE]) +		: "cc", "memory");  	preempt_enable();  #endif  } -/* forward declaration for SetPageUptodate in page-flags.h*/ -static inline void page_clear_dirty(struct page *page, int mapped); -#include <linux/page-flags.h> +static inline pgste_t pgste_get(pte_t *ptep) +{ +	unsigned long pgste = 0; +#ifdef CONFIG_PGSTE +	pgste = *(unsigned long *)(ptep + PTRS_PER_PTE); +#endif +	return __pgste(pgste); +} + +static inline void pgste_set(pte_t *ptep, pgste_t pgste) +{ +#ifdef CONFIG_PGSTE +	*(pgste_t *)(ptep + PTRS_PER_PTE) = pgste; +#endif +} -static inline void ptep_rcp_copy(pte_t *ptep) +static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste, +				       struct mm_struct *mm)  {  #ifdef CONFIG_PGSTE -	struct page *page = virt_to_page(pte_val(*ptep)); -	unsigned int skey; -	unsigned long *pgste = (unsigned long *) (ptep + PTRS_PER_PTE); - -	skey = page_get_storage_key(page_to_phys(page)); -	if (skey & _PAGE_CHANGED) { -		set_bit_simple(RCP_GC_BIT, pgste); -		set_bit_simple(KVM_UD_BIT, pgste); +	unsigned long address, bits, skey; + +	if (!mm_use_skey(mm) || pte_val(*ptep) & _PAGE_INVALID) +		return pgste; +	address = pte_val(*ptep) & PAGE_MASK; +	skey = (unsigned long) page_get_storage_key(address); +	bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); +	/* Transfer page changed & referenced bit to guest bits in pgste */ +	pgste_val(pgste) |= bits << 48;		/* GR bit & GC bit */ +	/* Copy page access key and fetch protection bit to pgste */ +	pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT); +	pgste_val(pgste) |= (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56; +#endif +	return pgste; + +} + +static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry, +				 struct mm_struct *mm) +{ +#ifdef CONFIG_PGSTE +	unsigned long address; +	unsigned long nkey; + +	if (!mm_use_skey(mm) || pte_val(entry) & _PAGE_INVALID) +		return; +	VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID)); +	address = pte_val(entry) & PAGE_MASK; +	/* +	 * Set page access key and fetch protection bit from pgste. +	 * The guest C/R information is still in the PGSTE, set real +	 * key C/R to 0. +	 */ +	nkey = (pgste_val(pgste) & (PGSTE_ACC_BITS | PGSTE_FP_BIT)) >> 56; +	nkey |= (pgste_val(pgste) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 48; +	page_set_storage_key(address, nkey, 0); +#endif +} + +static inline pgste_t pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry) +{ +	if ((pte_val(entry) & _PAGE_PRESENT) && +	    (pte_val(entry) & _PAGE_WRITE) && +	    !(pte_val(entry) & _PAGE_INVALID)) { +		if (!MACHINE_HAS_ESOP) { +			/* +			 * Without enhanced suppression-on-protection force +			 * the dirty bit on for all writable ptes. +			 */ +			pte_val(entry) |= _PAGE_DIRTY; +			pte_val(entry) &= ~_PAGE_PROTECT; +		} +		if (!(pte_val(entry) & _PAGE_PROTECT)) +			/* This pte allows write access, set user-dirty */ +			pgste_val(pgste) |= PGSTE_UC_BIT;  	} -	if (skey & _PAGE_REFERENCED) -		set_bit_simple(RCP_GR_BIT, pgste); -	if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { -		SetPageDirty(page); -		set_bit_simple(KVM_UD_BIT, pgste); +	*ptep = entry; +	return pgste; +} + +/** + * struct gmap_struct - guest address space + * @mm: pointer to the parent mm_struct + * @table: pointer to the page directory + * @asce: address space control element for gmap page table + * @crst_list: list of all crst tables used in the guest address space + * @pfault_enabled: defines if pfaults are applicable for the guest + */ +struct gmap { +	struct list_head list; +	struct mm_struct *mm; +	unsigned long *table; +	unsigned long asce; +	void *private; +	struct list_head crst_list; +	bool pfault_enabled; +}; + +/** + * struct gmap_rmap - reverse mapping for segment table entries + * @gmap: pointer to the gmap_struct + * @entry: pointer to a segment table entry + * @vmaddr: virtual address in the guest address space + */ +struct gmap_rmap { +	struct list_head list; +	struct gmap *gmap; +	unsigned long *entry; +	unsigned long vmaddr; +}; + +/** + * struct gmap_pgtable - gmap information attached to a page table + * @vmaddr: address of the 1MB segment in the process virtual memory + * @mapper: list of segment table entries mapping a page table + */ +struct gmap_pgtable { +	unsigned long vmaddr; +	struct list_head mapper; +}; + +/** + * struct gmap_notifier - notify function block for page invalidation + * @notifier_call: address of callback function + */ +struct gmap_notifier { +	struct list_head list; +	void (*notifier_call)(struct gmap *gmap, unsigned long address); +}; + +struct gmap *gmap_alloc(struct mm_struct *mm); +void gmap_free(struct gmap *gmap); +void gmap_enable(struct gmap *gmap); +void gmap_disable(struct gmap *gmap); +int gmap_map_segment(struct gmap *gmap, unsigned long from, +		     unsigned long to, unsigned long len); +int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len); +unsigned long __gmap_translate(unsigned long address, struct gmap *); +unsigned long gmap_translate(unsigned long address, struct gmap *); +unsigned long __gmap_fault(unsigned long address, struct gmap *); +unsigned long gmap_fault(unsigned long address, struct gmap *); +void gmap_discard(unsigned long from, unsigned long to, struct gmap *); +void __gmap_zap(unsigned long address, struct gmap *); +bool gmap_test_and_clear_dirty(unsigned long address, struct gmap *); + + +void gmap_register_ipte_notifier(struct gmap_notifier *); +void gmap_unregister_ipte_notifier(struct gmap_notifier *); +int gmap_ipte_notify(struct gmap *, unsigned long start, unsigned long len); +void gmap_do_ipte_notify(struct mm_struct *, pte_t *); + +static inline pgste_t pgste_ipte_notify(struct mm_struct *mm, +					pte_t *ptep, pgste_t pgste) +{ +#ifdef CONFIG_PGSTE +	if (pgste_val(pgste) & PGSTE_IN_BIT) { +		pgste_val(pgste) &= ~PGSTE_IN_BIT; +		gmap_do_ipte_notify(mm, ptep);  	} -	if (test_and_clear_bit_simple(RCP_HR_BIT, pgste)) -		SetPageReferenced(page);  #endif +	return pgste; +} + +/* + * Certain architectures need to do special things when PTEs + * within a page table are directly modified.  Thus, the following + * hook is made available. + */ +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, +			      pte_t *ptep, pte_t entry) +{ +	pgste_t pgste; + +	if (mm_has_pgste(mm)) { +		pgste = pgste_get_lock(ptep); +		pgste_val(pgste) &= ~_PGSTE_GPS_ZERO; +		pgste_set_key(ptep, pgste, entry, mm); +		pgste = pgste_set_pte(ptep, pgste, entry); +		pgste_set_unlock(ptep, pgste); +	} else { +		if (!(pte_val(entry) & _PAGE_INVALID) && MACHINE_HAS_EDAT1) +			pte_val(entry) |= _PAGE_CO; +		*ptep = entry; +	}  }  /* @@ -622,89 +887,53 @@ static inline void ptep_rcp_copy(pte_t *ptep)   */  static inline int pte_write(pte_t pte)  { -	return (pte_val(pte) & _PAGE_RO) == 0; +	return (pte_val(pte) & _PAGE_WRITE) != 0;  }  static inline int pte_dirty(pte_t pte)  { -	/* A pte is neither clean nor dirty on s/390. The dirty bit -	 * is in the storage key. See page_test_and_clear_dirty for -	 * details. -	 */ -	return 0; +	return (pte_val(pte) & _PAGE_DIRTY) != 0;  }  static inline int pte_young(pte_t pte)  { -	/* A pte is neither young nor old on s/390. The young bit -	 * is in the storage key. See page_test_and_clear_young for -	 * details. -	 */ -	return 0; +	return (pte_val(pte) & _PAGE_YOUNG) != 0; +} + +#define __HAVE_ARCH_PTE_UNUSED +static inline int pte_unused(pte_t pte) +{ +	return pte_val(pte) & _PAGE_UNUSED;  }  /*   * pgd/pmd/pte modification functions   */ -#ifndef __s390x__ - -#define pgd_clear(pgd)		do { } while (0) -#define pud_clear(pud)		do { } while (0) - -#else /* __s390x__ */ - -static inline void pgd_clear_kernel(pgd_t * pgd) +static inline void pgd_clear(pgd_t *pgd)  { +#ifdef CONFIG_64BIT  	if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2)  		pgd_val(*pgd) = _REGION2_ENTRY_EMPTY; +#endif  } -static inline void pgd_clear(pgd_t * pgd) -{ -	pgd_t *shadow = get_shadow_table(pgd); - -	pgd_clear_kernel(pgd); -	if (shadow) -		pgd_clear_kernel(shadow); -} - -static inline void pud_clear_kernel(pud_t *pud) +static inline void pud_clear(pud_t *pud)  { +#ifdef CONFIG_64BIT  	if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)  		pud_val(*pud) = _REGION3_ENTRY_EMPTY; +#endif  } -static inline void pud_clear(pud_t *pud) -{ -	pud_t *shadow = get_shadow_table(pud); - -	pud_clear_kernel(pud); -	if (shadow) -		pud_clear_kernel(shadow); -} - -#endif /* __s390x__ */ - -static inline void pmd_clear_kernel(pmd_t * pmdp) -{ -	pmd_val(*pmdp) = _SEGMENT_ENTRY_EMPTY; -} - -static inline void pmd_clear(pmd_t *pmd) +static inline void pmd_clear(pmd_t *pmdp)  { -	pmd_t *shadow = get_shadow_table(pmd); - -	pmd_clear_kernel(pmd); -	if (shadow) -		pmd_clear_kernel(shadow); +	pmd_val(*pmdp) = _SEGMENT_ENTRY_INVALID;  }  static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)  { -	pte_val(*ptep) = _PAGE_TYPE_EMPTY; -	if (mm->context.noexec) -		pte_val(ptep[PTRS_PER_PTE]) = _PAGE_TYPE_EMPTY; +	pte_val(*ptep) = _PAGE_INVALID;  }  /* @@ -715,54 +944,63 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)  {  	pte_val(pte) &= _PAGE_CHG_MASK;  	pte_val(pte) |= pgprot_val(newprot); +	/* +	 * newprot for PAGE_NONE, PAGE_READ and PAGE_WRITE has the +	 * invalid bit set, clear it again for readable, young pages +	 */ +	if ((pte_val(pte) & _PAGE_YOUNG) && (pte_val(pte) & _PAGE_READ)) +		pte_val(pte) &= ~_PAGE_INVALID; +	/* +	 * newprot for PAGE_READ and PAGE_WRITE has the page protection +	 * bit set, clear it again for writable, dirty pages +	 */ +	if ((pte_val(pte) & _PAGE_DIRTY) && (pte_val(pte) & _PAGE_WRITE)) +		pte_val(pte) &= ~_PAGE_PROTECT;  	return pte;  }  static inline pte_t pte_wrprotect(pte_t pte)  { -	/* Do not clobber _PAGE_TYPE_NONE pages!  */ -	if (!(pte_val(pte) & _PAGE_INVALID)) -		pte_val(pte) |= _PAGE_RO; +	pte_val(pte) &= ~_PAGE_WRITE; +	pte_val(pte) |= _PAGE_PROTECT;  	return pte;  }  static inline pte_t pte_mkwrite(pte_t pte)  { -	pte_val(pte) &= ~_PAGE_RO; +	pte_val(pte) |= _PAGE_WRITE; +	if (pte_val(pte) & _PAGE_DIRTY) +		pte_val(pte) &= ~_PAGE_PROTECT;  	return pte;  }  static inline pte_t pte_mkclean(pte_t pte)  { -	/* The only user of pte_mkclean is the fork() code. -	   We must *not* clear the *physical* page dirty bit -	   just because fork() wants to clear the dirty bit in -	   *one* of the page's mappings.  So we just do nothing. */ +	pte_val(pte) &= ~_PAGE_DIRTY; +	pte_val(pte) |= _PAGE_PROTECT;  	return pte;  }  static inline pte_t pte_mkdirty(pte_t pte)  { -	/* We do not explicitly set the dirty bit because the -	 * sske instruction is slow. It is faster to let the -	 * next instruction set the dirty bit. -	 */ +	pte_val(pte) |= _PAGE_DIRTY; +	if (pte_val(pte) & _PAGE_WRITE) +		pte_val(pte) &= ~_PAGE_PROTECT;  	return pte;  }  static inline pte_t pte_mkold(pte_t pte)  { -	/* S/390 doesn't keep its dirty/referenced bit in the pte. -	 * There is no point in clearing the real referenced bit. -	 */ +	pte_val(pte) &= ~_PAGE_YOUNG; +	pte_val(pte) |= _PAGE_INVALID;  	return pte;  }  static inline pte_t pte_mkyoung(pte_t pte)  { -	/* S/390 doesn't keep its dirty/referenced bit in the pte. -	 * There is no point in setting the real referenced bit. -	 */ +	pte_val(pte) |= _PAGE_YOUNG; +	if (pte_val(pte) & _PAGE_READ) +		pte_val(pte) &= ~_PAGE_INVALID;  	return pte;  } @@ -775,138 +1013,135 @@ static inline pte_t pte_mkspecial(pte_t pte)  #ifdef CONFIG_HUGETLB_PAGE  static inline pte_t pte_mkhuge(pte_t pte)  { -	/* -	 * PROT_NONE needs to be remapped from the pte type to the ste type. -	 * The HW invalid bit is also different for pte and ste. The pte -	 * invalid bit happens to be the same as the ste _SEGMENT_ENTRY_LARGE -	 * bit, so we don't have to clear it. -	 */ -	if (pte_val(pte) & _PAGE_INVALID) { -		if (pte_val(pte) & _PAGE_SWT) -			pte_val(pte) |= _HPAGE_TYPE_NONE; -		pte_val(pte) |= _SEGMENT_ENTRY_INV; -	} -	/* -	 * Clear SW pte bits SWT and SWX, there are no SW bits in a segment -	 * table entry. -	 */ -	pte_val(pte) &= ~(_PAGE_SWT | _PAGE_SWX); -	/* -	 * Also set the change-override bit because we don't need dirty bit -	 * tracking for hugetlbfs pages. -	 */ -	pte_val(pte) |= (_SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_CO); +	pte_val(pte) |= _PAGE_LARGE;  	return pte;  }  #endif -#ifdef CONFIG_PGSTE +static inline void __ptep_ipte(unsigned long address, pte_t *ptep) +{ +	unsigned long pto = (unsigned long) ptep; + +#ifndef CONFIG_64BIT +	/* pto in ESA mode must point to the start of the segment table */ +	pto &= 0x7ffffc00; +#endif +	/* Invalidation + global TLB flush for the pte */ +	asm volatile( +		"	ipte	%2,%3" +		: "=m" (*ptep) : "m" (*ptep), "a" (pto), "a" (address)); +} + +static inline void __ptep_ipte_local(unsigned long address, pte_t *ptep) +{ +	unsigned long pto = (unsigned long) ptep; + +#ifndef CONFIG_64BIT +	/* pto in ESA mode must point to the start of the segment table */ +	pto &= 0x7ffffc00; +#endif +	/* Invalidation + local TLB flush for the pte */ +	asm volatile( +		"	.insn rrf,0xb2210000,%2,%3,0,1" +		: "=m" (*ptep) : "m" (*ptep), "a" (pto), "a" (address)); +} + +static inline void ptep_flush_direct(struct mm_struct *mm, +				     unsigned long address, pte_t *ptep) +{ +	int active, count; + +	if (pte_val(*ptep) & _PAGE_INVALID) +		return; +	active = (mm == current->active_mm) ? 1 : 0; +	count = atomic_add_return(0x10000, &mm->context.attach_count); +	if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active && +	    cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) +		__ptep_ipte_local(address, ptep); +	else +		__ptep_ipte(address, ptep); +	atomic_sub(0x10000, &mm->context.attach_count); +} + +static inline void ptep_flush_lazy(struct mm_struct *mm, +				   unsigned long address, pte_t *ptep) +{ +	int active, count; + +	if (pte_val(*ptep) & _PAGE_INVALID) +		return; +	active = (mm == current->active_mm) ? 1 : 0; +	count = atomic_add_return(0x10000, &mm->context.attach_count); +	if ((count & 0xffff) <= active) { +		pte_val(*ptep) |= _PAGE_INVALID; +		mm->context.flush_mm = 1; +	} else +		__ptep_ipte(address, ptep); +	atomic_sub(0x10000, &mm->context.attach_count); +} +  /* - * Get (and clear) the user dirty bit for a PTE. + * Get (and clear) the user dirty bit for a pte.   */ -static inline int kvm_s390_test_and_clear_page_dirty(struct mm_struct *mm, -						     pte_t *ptep) +static inline int ptep_test_and_clear_user_dirty(struct mm_struct *mm, +						 unsigned long addr, +						 pte_t *ptep)  { +	pgste_t pgste; +	pte_t pte;  	int dirty; -	unsigned long *pgste; -	struct page *page; -	unsigned int skey; - -	if (!mm->context.has_pgste) -		return -EINVAL; -	rcp_lock(ptep); -	pgste = (unsigned long *) (ptep + PTRS_PER_PTE); -	page = virt_to_page(pte_val(*ptep)); -	skey = page_get_storage_key(page_to_phys(page)); -	if (skey & _PAGE_CHANGED) { -		set_bit_simple(RCP_GC_BIT, pgste); -		set_bit_simple(KVM_UD_BIT, pgste); -	} -	if (test_and_clear_bit_simple(RCP_HC_BIT, pgste)) { -		SetPageDirty(page); -		set_bit_simple(KVM_UD_BIT, pgste); + +	if (!mm_has_pgste(mm)) +		return 0; +	pgste = pgste_get_lock(ptep); +	dirty = !!(pgste_val(pgste) & PGSTE_UC_BIT); +	pgste_val(pgste) &= ~PGSTE_UC_BIT; +	pte = *ptep; +	if (dirty && (pte_val(pte) & _PAGE_PRESENT)) { +		pgste = pgste_ipte_notify(mm, ptep, pgste); +		__ptep_ipte(addr, ptep); +		if (MACHINE_HAS_ESOP || !(pte_val(pte) & _PAGE_WRITE)) +			pte_val(pte) |= _PAGE_PROTECT; +		else +			pte_val(pte) |= _PAGE_INVALID; +		*ptep = pte;  	} -	dirty = test_and_clear_bit_simple(KVM_UD_BIT, pgste); -	if (skey & _PAGE_CHANGED) -		page_clear_dirty(page, 1); -	rcp_unlock(ptep); +	pgste_set_unlock(ptep, pgste);  	return dirty;  } -#endif  #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG  static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,  					    unsigned long addr, pte_t *ptep)  { -#ifdef CONFIG_PGSTE -	unsigned long physpage; +	pgste_t pgste; +	pte_t pte;  	int young; -	unsigned long *pgste; -	if (!vma->vm_mm->context.has_pgste) -		return 0; -	physpage = pte_val(*ptep) & PAGE_MASK; -	pgste = (unsigned long *) (ptep + PTRS_PER_PTE); +	if (mm_has_pgste(vma->vm_mm)) { +		pgste = pgste_get_lock(ptep); +		pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste); +	} + +	pte = *ptep; +	ptep_flush_direct(vma->vm_mm, addr, ptep); +	young = pte_young(pte); +	pte = pte_mkold(pte); + +	if (mm_has_pgste(vma->vm_mm)) { +		pgste = pgste_set_pte(ptep, pgste, pte); +		pgste_set_unlock(ptep, pgste); +	} else +		*ptep = pte; -	young = ((page_get_storage_key(physpage) & _PAGE_REFERENCED) != 0); -	rcp_lock(ptep); -	if (young) -		set_bit_simple(RCP_GR_BIT, pgste); -	young |= test_and_clear_bit_simple(RCP_HR_BIT, pgste); -	rcp_unlock(ptep);  	return young; -#endif -	return 0;  }  #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH  static inline int ptep_clear_flush_young(struct vm_area_struct *vma,  					 unsigned long address, pte_t *ptep)  { -	/* No need to flush TLB -	 * On s390 reference bits are in storage key and never in TLB -	 * With virtualization we handle the reference bit, without we -	 * we can simply return */ -#ifdef CONFIG_PGSTE  	return ptep_test_and_clear_young(vma, address, ptep); -#endif -	return 0; -} - -static inline void __ptep_ipte(unsigned long address, pte_t *ptep) -{ -	if (!(pte_val(*ptep) & _PAGE_INVALID)) { -#ifndef __s390x__ -		/* pto must point to the start of the segment table */ -		pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00); -#else -		/* ipte in zarch mode can do the math */ -		pte_t *pto = ptep; -#endif -		asm volatile( -			"	ipte	%2,%3" -			: "=m" (*ptep) : "m" (*ptep), -			  "a" (pto), "a" (address)); -	} -} - -static inline void ptep_invalidate(struct mm_struct *mm, -				   unsigned long address, pte_t *ptep) -{ -	if (mm->context.has_pgste) { -		rcp_lock(ptep); -		__ptep_ipte(address, ptep); -		ptep_rcp_copy(ptep); -		pte_val(*ptep) = _PAGE_TYPE_EMPTY; -		rcp_unlock(ptep); -		return; -	} -	__ptep_ipte(address, ptep); -	pte_val(*ptep) = _PAGE_TYPE_EMPTY; -	if (mm->context.noexec) { -		__ptep_ipte(address, ptep + PTRS_PER_PTE); -		pte_val(*(ptep + PTRS_PER_PTE)) = _PAGE_TYPE_EMPTY; -	}  }  /* @@ -923,24 +1158,89 @@ static inline void ptep_invalidate(struct mm_struct *mm,   * is a nop.   */  #define __HAVE_ARCH_PTEP_GET_AND_CLEAR -#define ptep_get_and_clear(__mm, __address, __ptep)			\ -({									\ -	pte_t __pte = *(__ptep);					\ -	(__mm)->context.flush_mm = 1;					\ -	if (atomic_read(&(__mm)->context.attach_count) > 1 ||		\ -	    (__mm) != current->active_mm)				\ -		ptep_invalidate(__mm, __address, __ptep);		\ -	else								\ -		pte_clear((__mm), (__address), (__ptep));		\ -	__pte;								\ -}) +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, +				       unsigned long address, pte_t *ptep) +{ +	pgste_t pgste; +	pte_t pte; + +	if (mm_has_pgste(mm)) { +		pgste = pgste_get_lock(ptep); +		pgste = pgste_ipte_notify(mm, ptep, pgste); +	} + +	pte = *ptep; +	ptep_flush_lazy(mm, address, ptep); +	pte_val(*ptep) = _PAGE_INVALID; + +	if (mm_has_pgste(mm)) { +		pgste = pgste_update_all(&pte, pgste, mm); +		pgste_set_unlock(ptep, pgste); +	} +	return pte; +} + +#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION +static inline pte_t ptep_modify_prot_start(struct mm_struct *mm, +					   unsigned long address, +					   pte_t *ptep) +{ +	pgste_t pgste; +	pte_t pte; + +	if (mm_has_pgste(mm)) { +		pgste = pgste_get_lock(ptep); +		pgste_ipte_notify(mm, ptep, pgste); +	} + +	pte = *ptep; +	ptep_flush_lazy(mm, address, ptep); + +	if (mm_has_pgste(mm)) { +		pgste = pgste_update_all(&pte, pgste, mm); +		pgste_set(ptep, pgste); +	} +	return pte; +} + +static inline void ptep_modify_prot_commit(struct mm_struct *mm, +					   unsigned long address, +					   pte_t *ptep, pte_t pte) +{ +	pgste_t pgste; + +	if (mm_has_pgste(mm)) { +		pgste = pgste_get(ptep); +		pgste_set_key(ptep, pgste, pte, mm); +		pgste = pgste_set_pte(ptep, pgste, pte); +		pgste_set_unlock(ptep, pgste); +	} else +		*ptep = pte; +}  #define __HAVE_ARCH_PTEP_CLEAR_FLUSH  static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,  				     unsigned long address, pte_t *ptep)  { -	pte_t pte = *ptep; -	ptep_invalidate(vma->vm_mm, address, ptep); +	pgste_t pgste; +	pte_t pte; + +	if (mm_has_pgste(vma->vm_mm)) { +		pgste = pgste_get_lock(ptep); +		pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste); +	} + +	pte = *ptep; +	ptep_flush_direct(vma->vm_mm, address, ptep); +	pte_val(*ptep) = _PAGE_INVALID; + +	if (mm_has_pgste(vma->vm_mm)) { +		if ((pgste_val(pgste) & _PGSTE_GPS_USAGE_MASK) == +		    _PGSTE_GPS_USAGE_UNUSED) +			pte_val(pte) |= _PAGE_UNUSED; +		pgste = pgste_update_all(&pte, pgste, vma->vm_mm); +		pgste_set_unlock(ptep, pgste); +	}  	return pte;  } @@ -953,76 +1253,76 @@ static inline pte_t ptep_clear_flush(struct vm_area_struct *vma,   */  #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL  static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, -					    unsigned long addr, +					    unsigned long address,  					    pte_t *ptep, int full)  { -	pte_t pte = *ptep; +	pgste_t pgste; +	pte_t pte; -	if (full) -		pte_clear(mm, addr, ptep); -	else -		ptep_invalidate(mm, addr, ptep); +	if (!full && mm_has_pgste(mm)) { +		pgste = pgste_get_lock(ptep); +		pgste = pgste_ipte_notify(mm, ptep, pgste); +	} + +	pte = *ptep; +	if (!full) +		ptep_flush_lazy(mm, address, ptep); +	pte_val(*ptep) = _PAGE_INVALID; + +	if (!full && mm_has_pgste(mm)) { +		pgste = pgste_update_all(&pte, pgste, mm); +		pgste_set_unlock(ptep, pgste); +	}  	return pte;  }  #define __HAVE_ARCH_PTEP_SET_WRPROTECT -#define ptep_set_wrprotect(__mm, __addr, __ptep)			\ -({									\ -	pte_t __pte = *(__ptep);					\ -	if (pte_write(__pte)) {						\ -		(__mm)->context.flush_mm = 1;				\ -		if (atomic_read(&(__mm)->context.attach_count) > 1 ||	\ -		    (__mm) != current->active_mm)			\ -			ptep_invalidate(__mm, __addr, __ptep);		\ -		set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte));	\ -	}								\ -}) +static inline pte_t ptep_set_wrprotect(struct mm_struct *mm, +				       unsigned long address, pte_t *ptep) +{ +	pgste_t pgste; +	pte_t pte = *ptep; -#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS -#define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty)	\ -({									\ -	int __changed = !pte_same(*(__ptep), __entry);			\ -	if (__changed) {						\ -		ptep_invalidate((__vma)->vm_mm, __addr, __ptep);	\ -		set_pte_at((__vma)->vm_mm, __addr, __ptep, __entry);	\ -	}								\ -	__changed;							\ -}) +	if (pte_write(pte)) { +		if (mm_has_pgste(mm)) { +			pgste = pgste_get_lock(ptep); +			pgste = pgste_ipte_notify(mm, ptep, pgste); +		} -/* - * Test and clear dirty bit in storage key. - * We can't clear the changed bit atomically. This is a potential - * race against modification of the referenced bit. This function - * should therefore only be called if it is not mapped in any - * address space. - */ -#define __HAVE_ARCH_PAGE_TEST_DIRTY -static inline int page_test_dirty(struct page *page) -{ -	return (page_get_storage_key(page_to_phys(page)) & _PAGE_CHANGED) != 0; -} +		ptep_flush_lazy(mm, address, ptep); +		pte = pte_wrprotect(pte); -#define __HAVE_ARCH_PAGE_CLEAR_DIRTY -static inline void page_clear_dirty(struct page *page, int mapped) -{ -	page_set_storage_key(page_to_phys(page), PAGE_DEFAULT_KEY, mapped); +		if (mm_has_pgste(mm)) { +			pgste = pgste_set_pte(ptep, pgste, pte); +			pgste_set_unlock(ptep, pgste); +		} else +			*ptep = pte; +	} +	return pte;  } -/* - * Test and clear referenced bit in storage key. - */ -#define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG -static inline int page_test_and_clear_young(struct page *page) +#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS +static inline int ptep_set_access_flags(struct vm_area_struct *vma, +					unsigned long address, pte_t *ptep, +					pte_t entry, int dirty)  { -	unsigned long physpage = page_to_phys(page); -	int ccode; +	pgste_t pgste; -	asm volatile( -		"	rrbe	0,%1\n" -		"	ipm	%0\n" -		"	srl	%0,28\n" -		: "=d" (ccode) : "a" (physpage) : "cc" ); -	return ccode & 2; +	if (pte_same(*ptep, entry)) +		return 0; +	if (mm_has_pgste(vma->vm_mm)) { +		pgste = pgste_get_lock(ptep); +		pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste); +	} + +	ptep_flush_direct(vma->vm_mm, address, ptep); + +	if (mm_has_pgste(vma->vm_mm)) { +		pgste = pgste_set_pte(ptep, pgste, entry); +		pgste_set_unlock(ptep, pgste); +	} else +		*ptep = entry; +	return 1;  }  /* @@ -1033,14 +1333,17 @@ static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)  {  	pte_t __pte;  	pte_val(__pte) = physpage + pgprot_val(pgprot); -	return __pte; +	return pte_mkyoung(__pte);  }  static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)  {  	unsigned long physpage = page_to_phys(page); +	pte_t __pte = mk_pte_phys(physpage, pgprot); -	return mk_pte_phys(physpage, pgprot); +	if (pte_write(__pte) && PageDirty(page)) +		__pte = pte_mkdirty(__pte); +	return __pte;  }  #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) @@ -1051,7 +1354,7 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)  #define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))  #define pgd_offset_k(address) pgd_offset(&init_mm, address) -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)  #define pud_deref(pmd) ({ BUG(); 0UL; }) @@ -1060,7 +1363,7 @@ static inline pte_t mk_pte(struct page *page, pgprot_t pgprot)  #define pud_offset(pgd, address) ((pud_t *) pgd)  #define pmd_offset(pud, address) ((pmd_t *) pud + pmd_index(address)) -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  #define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN)  #define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN) @@ -1082,7 +1385,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)  	return pmd + pmd_index(address);  } -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  #define pfn_pte(pfn,pgprot) mk_pte_phys(__pa((pfn) << PAGE_SHIFT),(pgprot))  #define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT) @@ -1096,6 +1399,261 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)  #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)  #define pte_unmap(pte) do { } while (0) +#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE) +static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot) +{ +	/* +	 * pgprot is PAGE_NONE, PAGE_READ, or PAGE_WRITE (see __Pxxx / __Sxxx) +	 * Convert to segment table entry format. +	 */ +	if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE)) +		return pgprot_val(SEGMENT_NONE); +	if (pgprot_val(pgprot) == pgprot_val(PAGE_READ)) +		return pgprot_val(SEGMENT_READ); +	return pgprot_val(SEGMENT_WRITE); +} + +static inline pmd_t pmd_mkyoung(pmd_t pmd) +{ +#ifdef CONFIG_64BIT +	if (pmd_prot_none(pmd)) { +		pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; +	} else { +		pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG; +		pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID; +	} +#endif +	return pmd; +} + +static inline pmd_t pmd_mkold(pmd_t pmd) +{ +#ifdef CONFIG_64BIT +	if (pmd_prot_none(pmd)) { +		pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; +	} else { +		pmd_val(pmd) &= ~_SEGMENT_ENTRY_YOUNG; +		pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID; +	} +#endif +	return pmd; +} + +static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) +{ +	int young; + +	young = pmd_young(pmd); +	pmd_val(pmd) &= _SEGMENT_CHG_MASK; +	pmd_val(pmd) |= massage_pgprot_pmd(newprot); +	if (young) +		pmd = pmd_mkyoung(pmd); +	return pmd; +} + +static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot) +{ +	pmd_t __pmd; +	pmd_val(__pmd) = physpage + massage_pgprot_pmd(pgprot); +	return pmd_mkyoung(__pmd); +} + +static inline pmd_t pmd_mkwrite(pmd_t pmd) +{ +	/* Do not clobber PROT_NONE segments! */ +	if (!pmd_prot_none(pmd)) +		pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; +	return pmd; +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLB_PAGE */ + +static inline void __pmdp_csp(pmd_t *pmdp) +{ +	register unsigned long reg2 asm("2") = pmd_val(*pmdp); +	register unsigned long reg3 asm("3") = pmd_val(*pmdp) | +					       _SEGMENT_ENTRY_INVALID; +	register unsigned long reg4 asm("4") = ((unsigned long) pmdp) + 5; + +	asm volatile( +		"	csp %1,%3" +		: "=m" (*pmdp) +		: "d" (reg2), "d" (reg3), "d" (reg4), "m" (*pmdp) : "cc"); +} + +static inline void __pmdp_idte(unsigned long address, pmd_t *pmdp) +{ +	unsigned long sto; + +	sto = (unsigned long) pmdp - pmd_index(address) * sizeof(pmd_t); +	asm volatile( +		"	.insn	rrf,0xb98e0000,%2,%3,0,0" +		: "=m" (*pmdp) +		: "m" (*pmdp), "a" (sto), "a" ((address & HPAGE_MASK)) +		: "cc" ); +} + +static inline void __pmdp_idte_local(unsigned long address, pmd_t *pmdp) +{ +	unsigned long sto; + +	sto = (unsigned long) pmdp - pmd_index(address) * sizeof(pmd_t); +	asm volatile( +		"	.insn	rrf,0xb98e0000,%2,%3,0,1" +		: "=m" (*pmdp) +		: "m" (*pmdp), "a" (sto), "a" ((address & HPAGE_MASK)) +		: "cc" ); +} + +static inline void pmdp_flush_direct(struct mm_struct *mm, +				     unsigned long address, pmd_t *pmdp) +{ +	int active, count; + +	if (pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID) +		return; +	if (!MACHINE_HAS_IDTE) { +		__pmdp_csp(pmdp); +		return; +	} +	active = (mm == current->active_mm) ? 1 : 0; +	count = atomic_add_return(0x10000, &mm->context.attach_count); +	if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active && +	    cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) +		__pmdp_idte_local(address, pmdp); +	else +		__pmdp_idte(address, pmdp); +	atomic_sub(0x10000, &mm->context.attach_count); +} + +static inline void pmdp_flush_lazy(struct mm_struct *mm, +				   unsigned long address, pmd_t *pmdp) +{ +	int active, count; + +	if (pmd_val(*pmdp) & _SEGMENT_ENTRY_INVALID) +		return; +	active = (mm == current->active_mm) ? 1 : 0; +	count = atomic_add_return(0x10000, &mm->context.attach_count); +	if ((count & 0xffff) <= active) { +		pmd_val(*pmdp) |= _SEGMENT_ENTRY_INVALID; +		mm->context.flush_mm = 1; +	} else if (MACHINE_HAS_IDTE) +		__pmdp_idte(address, pmdp); +	else +		__pmdp_csp(pmdp); +	atomic_sub(0x10000, &mm->context.attach_count); +} + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + +#define __HAVE_ARCH_PGTABLE_DEPOSIT +extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, +				       pgtable_t pgtable); + +#define __HAVE_ARCH_PGTABLE_WITHDRAW +extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp); + +static inline int pmd_trans_splitting(pmd_t pmd) +{ +	return pmd_val(pmd) & _SEGMENT_ENTRY_SPLIT; +} + +static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, +			      pmd_t *pmdp, pmd_t entry) +{ +	if (!(pmd_val(entry) & _SEGMENT_ENTRY_INVALID) && MACHINE_HAS_EDAT1) +		pmd_val(entry) |= _SEGMENT_ENTRY_CO; +	*pmdp = entry; +} + +static inline pmd_t pmd_mkhuge(pmd_t pmd) +{ +	pmd_val(pmd) |= _SEGMENT_ENTRY_LARGE; +	return pmd; +} + +static inline pmd_t pmd_wrprotect(pmd_t pmd) +{ +	/* Do not clobber PROT_NONE segments! */ +	if (!pmd_prot_none(pmd)) +		pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; +	return pmd; +} + +static inline pmd_t pmd_mkdirty(pmd_t pmd) +{ +	/* No dirty bit in the segment table entry. */ +	return pmd; +} + +#define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG +static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma, +					    unsigned long address, pmd_t *pmdp) +{ +	pmd_t pmd; + +	pmd = *pmdp; +	pmdp_flush_direct(vma->vm_mm, address, pmdp); +	*pmdp = pmd_mkold(pmd); +	return pmd_young(pmd); +} + +#define __HAVE_ARCH_PMDP_GET_AND_CLEAR +static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, +				       unsigned long address, pmd_t *pmdp) +{ +	pmd_t pmd = *pmdp; + +	pmdp_flush_direct(mm, address, pmdp); +	pmd_clear(pmdp); +	return pmd; +} + +#define __HAVE_ARCH_PMDP_CLEAR_FLUSH +static inline pmd_t pmdp_clear_flush(struct vm_area_struct *vma, +				     unsigned long address, pmd_t *pmdp) +{ +	return pmdp_get_and_clear(vma->vm_mm, address, pmdp); +} + +#define __HAVE_ARCH_PMDP_INVALIDATE +static inline void pmdp_invalidate(struct vm_area_struct *vma, +				   unsigned long address, pmd_t *pmdp) +{ +	pmdp_flush_direct(vma->vm_mm, address, pmdp); +} + +#define __HAVE_ARCH_PMDP_SET_WRPROTECT +static inline void pmdp_set_wrprotect(struct mm_struct *mm, +				      unsigned long address, pmd_t *pmdp) +{ +	pmd_t pmd = *pmdp; + +	if (pmd_write(pmd)) { +		pmdp_flush_direct(mm, address, pmdp); +		set_pmd_at(mm, address, pmdp, pmd_wrprotect(pmd)); +	} +} + +#define pfn_pmd(pfn, pgprot)	mk_pmd_phys(__pa((pfn) << PAGE_SHIFT), (pgprot)) +#define mk_pmd(page, pgprot)	pfn_pmd(page_to_pfn(page), (pgprot)) + +static inline int pmd_trans_huge(pmd_t pmd) +{ +	return pmd_val(pmd) & _SEGMENT_ENTRY_LARGE; +} + +static inline int has_transparent_hugepage(void) +{ +	return MACHINE_HAS_HPAGE ? 1 : 0; +} + +static inline unsigned long pmd_pfn(pmd_t pmd) +{ +	return pmd_val(pmd) >> PAGE_SHIFT; +} +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +  /*   * 31 bit swap entry format:   * A page-table entry has some bits we have to treat in a special way. @@ -1103,10 +1661,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)   * exception will occur instead of a page translation exception. The   * specifiation exception has the bad habit not to store necessary   * information in the lowcore. - * Bit 21 and bit 22 are the page invalid bit and the page protection - * bit. We set both to indicate a swapped page. - * Bit 30 and 31 are used to distinguish the different page types. For - * a swapped page these bits need to be zero. + * Bits 21, 22, 30 and 31 are used to indicate the page type. + * A swap pte is indicated by bit pattern (pte & 0x603) == 0x402   * This leaves the bits 1-19 and bits 24-29 to store type and offset.   * We use the 5 bits from 25-29 for the type and the 20 bits from 1-19   * plus 24 for the offset. @@ -1120,10 +1676,8 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)   * exception will occur instead of a page translation exception. The   * specifiation exception has the bad habit not to store necessary   * information in the lowcore. - * Bit 53 and bit 54 are the page invalid bit and the page protection - * bit. We set both to indicate a swapped page. - * Bit 62 and 63 are used to distinguish the different page types. For - * a swapped page these bits need to be zero. + * Bits 53, 54, 62 and 63 are used to indicate the page type. + * A swap pte is indicated by bit pattern (pte & 0x603) == 0x402   * This leaves the bits 0-51 and bits 56-61 to store type and offset.   * We use the 5 bits from 57-61 for the type and the 53 bits from 0-51   * plus 56 for the offset. @@ -1131,7 +1685,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)   *  0000000000111111111122222222223333333333444444444455 5555 5 55566 66   *  0123456789012345678901234567890123456789012345678901 2345 6 78901 23   */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define __SWP_OFFSET_MASK (~0UL >> 12)  #else  #define __SWP_OFFSET_MASK (~0UL >> 11) @@ -1140,7 +1694,7 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)  {  	pte_t pte;  	offset &= __SWP_OFFSET_MASK; -	pte_val(pte) = _PAGE_TYPE_SWAP | ((type & 0x1f) << 2) | +	pte_val(pte) = _PAGE_INVALID | _PAGE_TYPE | ((type & 0x1f) << 2) |  		((offset & 1UL) << 7) | ((offset & ~1UL) << 11);  	return pte;  } @@ -1152,18 +1706,18 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)  #define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })  #define __swp_entry_to_pte(x)	((pte_t) { (x).val }) -#ifndef __s390x__ +#ifndef CONFIG_64BIT  # define PTE_FILE_MAX_BITS	26 -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  # define PTE_FILE_MAX_BITS	59 -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  #define pte_to_pgoff(__pte) \  	((((__pte).pte >> 12) << 7) + (((__pte).pte >> 1) & 0x7f))  #define pgoff_to_pte(__off) \  	((pte_t) { ((((__off) & 0x7f) << 1) + (((__off) >> 7) << 12)) \ -		   | _PAGE_TYPE_FILE }) +		   | _PAGE_INVALID | _PAGE_PROTECT })  #endif /* !__ASSEMBLY__ */ @@ -1172,11 +1726,13 @@ static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)  extern int vmem_add_mapping(unsigned long start, unsigned long size);  extern int vmem_remove_mapping(unsigned long start, unsigned long size);  extern int s390_enable_sie(void); +extern void s390_enable_skey(void);  /*   * No page table caches to initialise   */ -#define pgtable_cache_init()	do { } while (0) +static inline void pgtable_cache_init(void) { } +static inline void check_pgt_cache(void) { }  #include <asm-generic/pgtable.h> diff --git a/arch/s390/include/asm/posix_types.h b/arch/s390/include/asm/posix_types.h deleted file mode 100644 index 8cc113f9252..00000000000 --- a/arch/s390/include/asm/posix_types.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - *  include/asm-s390/posix_types.h - * - *  S390 version - * - *  Derived from "include/asm-i386/posix_types.h" - */ - -#ifndef __ARCH_S390_POSIX_TYPES_H -#define __ARCH_S390_POSIX_TYPES_H - -/* - * This file is generally used by user-level software, so you need to - * be a little careful about namespace pollution etc.  Also, we cannot - * assume GCC is being used. - */ - -typedef long            __kernel_off_t; -typedef int             __kernel_pid_t; -typedef unsigned long   __kernel_size_t; -typedef long            __kernel_time_t; -typedef long            __kernel_suseconds_t; -typedef long            __kernel_clock_t; -typedef int		__kernel_timer_t; -typedef int		__kernel_clockid_t; -typedef int             __kernel_daddr_t; -typedef char *          __kernel_caddr_t; -typedef unsigned short	__kernel_uid16_t; -typedef unsigned short	__kernel_gid16_t; - -#ifdef __GNUC__ -typedef long long       __kernel_loff_t; -#endif - -#ifndef __s390x__ - -typedef unsigned long   __kernel_ino_t; -typedef unsigned short  __kernel_mode_t; -typedef unsigned short  __kernel_nlink_t; -typedef unsigned short  __kernel_ipc_pid_t; -typedef unsigned short  __kernel_uid_t; -typedef unsigned short  __kernel_gid_t; -typedef int             __kernel_ssize_t; -typedef int             __kernel_ptrdiff_t; -typedef unsigned int	__kernel_uid32_t; -typedef unsigned int	__kernel_gid32_t; -typedef unsigned short	__kernel_old_uid_t; -typedef unsigned short	__kernel_old_gid_t; -typedef unsigned short	__kernel_old_dev_t; - -#else /* __s390x__ */ - -typedef unsigned int    __kernel_ino_t; -typedef unsigned int    __kernel_mode_t; -typedef unsigned int    __kernel_nlink_t; -typedef int             __kernel_ipc_pid_t; -typedef unsigned int    __kernel_uid_t; -typedef unsigned int    __kernel_gid_t; -typedef long            __kernel_ssize_t; -typedef long            __kernel_ptrdiff_t; -typedef unsigned long   __kernel_sigset_t;      /* at least 32 bits */ -typedef __kernel_uid_t __kernel_old_uid_t; -typedef __kernel_gid_t __kernel_old_gid_t; -typedef __kernel_uid_t __kernel_uid32_t; -typedef __kernel_gid_t __kernel_gid32_t; -typedef unsigned short __kernel_old_dev_t; - -#endif /* __s390x__ */ - -typedef struct { -        int     val[2]; -} __kernel_fsid_t; - - -#ifdef __KERNEL__ - -#undef __FD_SET -static inline void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp) -{ -	unsigned long _tmp = fd / __NFDBITS; -	unsigned long _rem = fd % __NFDBITS; -	fdsetp->fds_bits[_tmp] |= (1UL<<_rem); -} - -#undef __FD_CLR -static inline void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp) -{ -	unsigned long _tmp = fd / __NFDBITS; -	unsigned long _rem = fd % __NFDBITS; -	fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem); -} - -#undef __FD_ISSET -static inline int __FD_ISSET(unsigned long fd, const __kernel_fd_set *fdsetp) -{ -	unsigned long _tmp = fd / __NFDBITS; -	unsigned long _rem = fd % __NFDBITS; -	return (fdsetp->fds_bits[_tmp] & (1UL<<_rem)) != 0; -} - -#undef  __FD_ZERO -#define __FD_ZERO(fdsetp) \ -	((void) memset ((void *) (fdsetp), 0, sizeof (__kernel_fd_set))) - -#endif     /* __KERNEL__ */ - -#endif 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 */ diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index d9d42b1e46f..55d69dd7473 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -1,322 +1,70 @@  /* - *  include/asm-s390/ptrace.h - *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999, 2000   *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)   */ -  #ifndef _S390_PTRACE_H  #define _S390_PTRACE_H -/* - * Offsets in the user_regs_struct. They are used for the ptrace - * system call and in entry.S - */ -#ifndef __s390x__ - -#define PT_PSWMASK  0x00 -#define PT_PSWADDR  0x04 -#define PT_GPR0     0x08 -#define PT_GPR1     0x0C -#define PT_GPR2     0x10 -#define PT_GPR3     0x14 -#define PT_GPR4     0x18 -#define PT_GPR5     0x1C -#define PT_GPR6     0x20 -#define PT_GPR7     0x24 -#define PT_GPR8     0x28 -#define PT_GPR9     0x2C -#define PT_GPR10    0x30 -#define PT_GPR11    0x34 -#define PT_GPR12    0x38 -#define PT_GPR13    0x3C -#define PT_GPR14    0x40 -#define PT_GPR15    0x44 -#define PT_ACR0     0x48 -#define PT_ACR1     0x4C -#define PT_ACR2     0x50 -#define PT_ACR3     0x54 -#define PT_ACR4	    0x58 -#define PT_ACR5	    0x5C -#define PT_ACR6	    0x60 -#define PT_ACR7	    0x64 -#define PT_ACR8	    0x68 -#define PT_ACR9	    0x6C -#define PT_ACR10    0x70 -#define PT_ACR11    0x74 -#define PT_ACR12    0x78 -#define PT_ACR13    0x7C -#define PT_ACR14    0x80 -#define PT_ACR15    0x84 -#define PT_ORIGGPR2 0x88 -#define PT_FPC	    0x90 -/* - * A nasty fact of life that the ptrace api - * only supports passing of longs. - */ -#define PT_FPR0_HI  0x98 -#define PT_FPR0_LO  0x9C -#define PT_FPR1_HI  0xA0 -#define PT_FPR1_LO  0xA4 -#define PT_FPR2_HI  0xA8 -#define PT_FPR2_LO  0xAC -#define PT_FPR3_HI  0xB0 -#define PT_FPR3_LO  0xB4 -#define PT_FPR4_HI  0xB8 -#define PT_FPR4_LO  0xBC -#define PT_FPR5_HI  0xC0 -#define PT_FPR5_LO  0xC4 -#define PT_FPR6_HI  0xC8 -#define PT_FPR6_LO  0xCC -#define PT_FPR7_HI  0xD0 -#define PT_FPR7_LO  0xD4 -#define PT_FPR8_HI  0xD8 -#define PT_FPR8_LO  0XDC -#define PT_FPR9_HI  0xE0 -#define PT_FPR9_LO  0xE4 -#define PT_FPR10_HI 0xE8 -#define PT_FPR10_LO 0xEC -#define PT_FPR11_HI 0xF0 -#define PT_FPR11_LO 0xF4 -#define PT_FPR12_HI 0xF8 -#define PT_FPR12_LO 0xFC -#define PT_FPR13_HI 0x100 -#define PT_FPR13_LO 0x104 -#define PT_FPR14_HI 0x108 -#define PT_FPR14_LO 0x10C -#define PT_FPR15_HI 0x110 -#define PT_FPR15_LO 0x114 -#define PT_CR_9	    0x118 -#define PT_CR_10    0x11C -#define PT_CR_11    0x120 -#define PT_IEEE_IP  0x13C -#define PT_LASTOFF  PT_IEEE_IP -#define PT_ENDREGS  0x140-1 - -#define GPR_SIZE	4 -#define CR_SIZE		4 - -#define STACK_FRAME_OVERHEAD	96	/* size of minimum stack frame */ - -#else /* __s390x__ */ - -#define PT_PSWMASK  0x00 -#define PT_PSWADDR  0x08 -#define PT_GPR0     0x10 -#define PT_GPR1     0x18 -#define PT_GPR2     0x20 -#define PT_GPR3     0x28 -#define PT_GPR4     0x30 -#define PT_GPR5     0x38 -#define PT_GPR6     0x40 -#define PT_GPR7     0x48 -#define PT_GPR8     0x50 -#define PT_GPR9     0x58 -#define PT_GPR10    0x60 -#define PT_GPR11    0x68 -#define PT_GPR12    0x70 -#define PT_GPR13    0x78 -#define PT_GPR14    0x80 -#define PT_GPR15    0x88 -#define PT_ACR0     0x90 -#define PT_ACR1     0x94 -#define PT_ACR2     0x98 -#define PT_ACR3     0x9C -#define PT_ACR4	    0xA0 -#define PT_ACR5	    0xA4 -#define PT_ACR6	    0xA8 -#define PT_ACR7	    0xAC -#define PT_ACR8	    0xB0 -#define PT_ACR9	    0xB4 -#define PT_ACR10    0xB8 -#define PT_ACR11    0xBC -#define PT_ACR12    0xC0 -#define PT_ACR13    0xC4 -#define PT_ACR14    0xC8 -#define PT_ACR15    0xCC -#define PT_ORIGGPR2 0xD0 -#define PT_FPC	    0xD8 -#define PT_FPR0     0xE0 -#define PT_FPR1     0xE8 -#define PT_FPR2     0xF0 -#define PT_FPR3     0xF8 -#define PT_FPR4     0x100 -#define PT_FPR5     0x108 -#define PT_FPR6     0x110 -#define PT_FPR7     0x118 -#define PT_FPR8     0x120 -#define PT_FPR9     0x128 -#define PT_FPR10    0x130 -#define PT_FPR11    0x138 -#define PT_FPR12    0x140 -#define PT_FPR13    0x148 -#define PT_FPR14    0x150 -#define PT_FPR15    0x158 -#define PT_CR_9     0x160 -#define PT_CR_10    0x168 -#define PT_CR_11    0x170 -#define PT_IEEE_IP  0x1A8 -#define PT_LASTOFF  PT_IEEE_IP -#define PT_ENDREGS  0x1B0-1 - -#define GPR_SIZE	8 -#define CR_SIZE		8 +#include <uapi/asm/ptrace.h> -#define STACK_FRAME_OVERHEAD    160      /* size of minimum stack frame */ +#define PIF_SYSCALL		0	/* inside a system call */ +#define PIF_PER_TRAP		1	/* deliver sigtrap on return to user */ -#endif /* __s390x__ */ - -#define NUM_GPRS	16 -#define NUM_FPRS	16 -#define NUM_CRS		16 -#define NUM_ACRS	16 - -#define NUM_CR_WORDS	3 - -#define FPR_SIZE	8 -#define FPC_SIZE	4 -#define FPC_PAD_SIZE	4 /* gcc insists on aligning the fpregs */ -#define ACR_SIZE	4 - - -#define PTRACE_OLDSETOPTIONS         21 +#define _PIF_SYSCALL		(1<<PIF_SYSCALL) +#define _PIF_PER_TRAP		(1<<PIF_PER_TRAP)  #ifndef __ASSEMBLY__ -#include <linux/stddef.h> -#include <linux/types.h> - -typedef union -{ -	float   f; -	double  d; -        __u64   ui; -	struct -	{ -		__u32 hi; -		__u32 lo; -	} fp; -} freg_t; - -typedef struct -{ -	__u32   fpc; -	freg_t  fprs[NUM_FPRS];               -} s390_fp_regs; - -#define FPC_EXCEPTION_MASK      0xF8000000 -#define FPC_FLAGS_MASK          0x00F80000 -#define FPC_DXC_MASK            0x0000FF00 -#define FPC_RM_MASK             0x00000003 -#define FPC_VALID_MASK          0xF8F8FF03 -/* this typedef defines how a Program Status Word looks like */ -typedef struct  -{ -        unsigned long mask; -        unsigned long addr; -} __attribute__ ((aligned(8))) psw_t; - -typedef struct -{ -	__u32	mask; -	__u32	addr; -} __attribute__ ((aligned(8))) psw_compat_t; - -#ifndef __s390x__ - -#define PSW_MASK_PER		0x40000000UL -#define PSW_MASK_DAT		0x04000000UL -#define PSW_MASK_IO		0x02000000UL -#define PSW_MASK_EXT		0x01000000UL -#define PSW_MASK_KEY		0x00F00000UL -#define PSW_MASK_MCHECK		0x00040000UL -#define PSW_MASK_WAIT		0x00020000UL -#define PSW_MASK_PSTATE		0x00010000UL -#define PSW_MASK_ASC		0x0000C000UL -#define PSW_MASK_CC		0x00003000UL -#define PSW_MASK_PM		0x00000F00UL - -#define PSW_ADDR_AMODE		0x80000000UL -#define PSW_ADDR_INSN		0x7FFFFFFFUL - -#define PSW_BASE_BITS		0x00080000UL -#define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 20) - -#define PSW_ASC_PRIMARY		0x00000000UL -#define PSW_ASC_ACCREG		0x00004000UL -#define PSW_ASC_SECONDARY	0x00008000UL -#define PSW_ASC_HOME		0x0000C000UL - -#else /* __s390x__ */ - -#define PSW_MASK_PER		0x4000000000000000UL -#define PSW_MASK_DAT		0x0400000000000000UL -#define PSW_MASK_IO		0x0200000000000000UL -#define PSW_MASK_EXT		0x0100000000000000UL -#define PSW_MASK_KEY		0x00F0000000000000UL -#define PSW_MASK_MCHECK		0x0004000000000000UL -#define PSW_MASK_WAIT		0x0002000000000000UL -#define PSW_MASK_PSTATE		0x0001000000000000UL -#define PSW_MASK_ASC		0x0000C00000000000UL -#define PSW_MASK_CC		0x0000300000000000UL -#define PSW_MASK_PM		0x00000F0000000000UL - -#define PSW_ADDR_AMODE		0x0000000000000000UL -#define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL - -#define PSW_BASE_BITS		0x0000000180000000UL -#define PSW_BASE32_BITS		0x0000000080000000UL -#define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 52) - -#define PSW_ASC_PRIMARY		0x0000000000000000UL -#define PSW_ASC_ACCREG		0x0000400000000000UL -#define PSW_ASC_SECONDARY	0x0000800000000000UL -#define PSW_ASC_HOME		0x0000C00000000000UL - -#endif /* __s390x__ */ - -#ifdef __KERNEL__ -extern long psw_kernel_bits; -extern long psw_user_bits; +#define PSW_KERNEL_BITS	(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_HOME | \ +			 PSW_MASK_EA | PSW_MASK_BA) +#define PSW_USER_BITS	(PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | \ +			 PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK | \ +			 PSW_MASK_PSTATE | PSW_ASC_PRIMARY) + +struct psw_bits { +	unsigned long long	: 1; +	unsigned long long r	: 1; /* PER-Mask */ +	unsigned long long	: 3; +	unsigned long long t	: 1; /* DAT Mode */ +	unsigned long long i	: 1; /* Input/Output Mask */ +	unsigned long long e	: 1; /* External Mask */ +	unsigned long long key	: 4; /* PSW Key */ +	unsigned long long	: 1; +	unsigned long long m	: 1; /* Machine-Check Mask */ +	unsigned long long w	: 1; /* Wait State */ +	unsigned long long p	: 1; /* Problem State */ +	unsigned long long as	: 2; /* Address Space Control */ +	unsigned long long cc	: 2; /* Condition Code */ +	unsigned long long pm	: 4; /* Program Mask */ +	unsigned long long ri	: 1; /* Runtime Instrumentation */ +	unsigned long long	: 6; +	unsigned long long eaba : 2; /* Addressing Mode */  #ifdef CONFIG_64BIT -extern long psw_user32_bits; -#endif +	unsigned long long	: 31; +	unsigned long long ia	: 64;/* Instruction Address */ +#else +	unsigned long long ia	: 31;/* Instruction Address */  #endif +}; -/* This macro merges a NEW PSW mask specified by the user into -   the currently active PSW mask CURRENT, modifying only those -   bits in CURRENT that the user may be allowed to change: this -   is the condition code and the program mask bits.  */ -#define PSW_MASK_MERGE(CURRENT,NEW) \ -	(((CURRENT) & ~(PSW_MASK_CC|PSW_MASK_PM)) | \ -	 ((NEW) & (PSW_MASK_CC|PSW_MASK_PM))) - -/* - * The s390_regs structure is used to define the elf_gregset_t. - */ -typedef struct -{ -	psw_t psw; -	unsigned long gprs[NUM_GPRS]; -	unsigned int  acrs[NUM_ACRS]; -	unsigned long orig_gpr2; -} s390_regs; - -typedef struct -{ -	psw_compat_t	psw; -	__u32		gprs[NUM_GPRS]; -	__u32		acrs[NUM_ACRS]; -	__u32		orig_gpr2; -} s390_compat_regs; +enum { +	PSW_AMODE_24BIT = 0, +	PSW_AMODE_31BIT = 1, +	PSW_AMODE_64BIT = 3 +}; -typedef struct -{ -	__u32		gprs_high[NUM_GPRS]; -} s390_compat_regs_high; +enum { +	PSW_AS_PRIMARY	 = 0, +	PSW_AS_ACCREG	 = 1, +	PSW_AS_SECONDARY = 2, +	PSW_AS_HOME	 = 3 +}; -#ifdef __KERNEL__ +#define psw_bits(__psw) (*({			\ +	typecheck(psw_t, __psw);		\ +	&(*(struct psw_bits *)(&(__psw)));	\ +}))  /*   * The pt_regs struct defines the way the registers are stored on @@ -328,175 +76,91 @@ struct pt_regs  	psw_t psw;  	unsigned long gprs[NUM_GPRS];  	unsigned long orig_gpr2; -	unsigned short ilc; -	unsigned short svcnr; +	unsigned int int_code; +	unsigned int int_parm; +	unsigned long int_parm_long; +	unsigned long flags;  }; -#endif  /* - * Now for the program event recording (trace) definitions. + * Program event recording (PER) register set.   */ -typedef struct -{ -	unsigned long cr[NUM_CR_WORDS]; -} per_cr_words; - -#define PER_EM_MASK 0xE8000000UL - -typedef	struct -{ -#ifdef __s390x__ -	unsigned                       : 32; -#endif /* __s390x__ */ -	unsigned em_branching          : 1; -	unsigned em_instruction_fetch  : 1; -	/* -	 * Switching on storage alteration automatically fixes -	 * the storage alteration event bit in the users std. -	 */ -	unsigned em_storage_alteration : 1; -	unsigned em_gpr_alt_unused     : 1; -	unsigned em_store_real_address : 1; -	unsigned                       : 3; -	unsigned branch_addr_ctl       : 1; -	unsigned                       : 1; -	unsigned storage_alt_space_ctl : 1; -	unsigned                       : 21; -	unsigned long starting_addr; -	unsigned long ending_addr; -} per_cr_bits; - -typedef struct -{ -	unsigned short perc_atmid; -	unsigned long address; -	unsigned char access_id; -} per_lowcore_words; - -typedef struct -{ -	unsigned perc_branching          : 1; -	unsigned perc_instruction_fetch  : 1; -	unsigned perc_storage_alteration : 1; -	unsigned perc_gpr_alt_unused     : 1; -	unsigned perc_store_real_address : 1; -	unsigned                         : 3; -	unsigned atmid_psw_bit_31        : 1; -	unsigned atmid_validity_bit      : 1; -	unsigned atmid_psw_bit_32        : 1; -	unsigned atmid_psw_bit_5         : 1; -	unsigned atmid_psw_bit_16        : 1; -	unsigned atmid_psw_bit_17        : 1; -	unsigned si                      : 2; -	unsigned long address; -	unsigned                         : 4; -	unsigned access_id               : 4; -} per_lowcore_bits; - -typedef struct -{ -	union { -		per_cr_words   words; -		per_cr_bits    bits; -	} control_regs; -	/* -	 * Use these flags instead of setting em_instruction_fetch -	 * directly they are used so that single stepping can be -	 * switched on & off while not affecting other tracing -	 */ -	unsigned  single_step       : 1; -	unsigned  instruction_fetch : 1; -	unsigned                    : 30; -	/* -	 * These addresses are copied into cr10 & cr11 if single -	 * stepping is switched off -	 */ -	unsigned long starting_addr; -	unsigned long ending_addr; -	union { -		per_lowcore_words words; -		per_lowcore_bits  bits; -	} lowcore;  -} per_struct; - -typedef struct -{ -	unsigned int  len; -	unsigned long kernel_addr; -	unsigned long process_addr; -} ptrace_area; +struct per_regs { +	unsigned long control;		/* PER control bits */ +	unsigned long start;		/* PER starting address */ +	unsigned long end;		/* PER ending address */ +};  /* - * S/390 specific non posix ptrace requests. I chose unusual values so - * they are unlikely to clash with future ptrace definitions. + * PER event contains information about the cause of the last PER exception.   */ -#define PTRACE_PEEKUSR_AREA           0x5000 -#define PTRACE_POKEUSR_AREA           0x5001 -#define PTRACE_PEEKTEXT_AREA	      0x5002 -#define PTRACE_PEEKDATA_AREA	      0x5003 -#define PTRACE_POKETEXT_AREA	      0x5004 -#define PTRACE_POKEDATA_AREA 	      0x5005 -#define PTRACE_GET_LAST_BREAK	      0x5006 +struct per_event { +	unsigned short cause;		/* PER code, ATMID and AI */ +	unsigned long address;		/* PER address */ +	unsigned char paid;		/* PER access identification */ +};  /* - * PT_PROT definition is loosely based on hppa bsd definition in - * gdb/hppab-nat.c + * Simplified per_info structure used to decode the ptrace user space ABI.   */ -#define PTRACE_PROT                       21 +struct per_struct_kernel { +	unsigned long cr9;		/* PER control bits */ +	unsigned long cr10;		/* PER starting address */ +	unsigned long cr11;		/* PER ending address */ +	unsigned long bits;		/* Obsolete software bits */ +	unsigned long starting_addr;	/* User specified start address */ +	unsigned long ending_addr;	/* User specified end address */ +	unsigned short perc_atmid;	/* PER trap ATMID */ +	unsigned long address;		/* PER trap instruction address */ +	unsigned char access_id;	/* PER trap access identification */ +}; -typedef enum -{ -	ptprot_set_access_watchpoint, -	ptprot_set_write_watchpoint, -	ptprot_disable_watchpoint -} ptprot_flags; +#define PER_EVENT_MASK			0xEB000000UL + +#define PER_EVENT_BRANCH		0x80000000UL +#define PER_EVENT_IFETCH		0x40000000UL +#define PER_EVENT_STORE			0x20000000UL +#define PER_EVENT_STORE_REAL		0x08000000UL +#define PER_EVENT_TRANSACTION_END	0x02000000UL +#define PER_EVENT_NULLIFICATION		0x01000000UL + +#define PER_CONTROL_MASK		0x00e00000UL -typedef struct +#define PER_CONTROL_BRANCH_ADDRESS	0x00800000UL +#define PER_CONTROL_SUSPENSION		0x00400000UL +#define PER_CONTROL_ALTERATION		0x00200000UL + +static inline void set_pt_regs_flag(struct pt_regs *regs, int flag)  { -	unsigned long lowaddr; -	unsigned long hiaddr; -	ptprot_flags prot; -} ptprot_area;                      +	regs->flags |= (1U << flag); +} -/* Sequence of bytes for breakpoint illegal instruction.  */ -#define S390_BREAKPOINT     {0x0,0x1} -#define S390_BREAKPOINT_U16 ((__u16)0x0001) -#define S390_SYSCALL_OPCODE ((__u16)0x0a00) -#define S390_SYSCALL_SIZE   2 +static inline void clear_pt_regs_flag(struct pt_regs *regs, int flag) +{ +	regs->flags &= ~(1U << flag); +} -/* - * The user_regs_struct defines the way the user registers are - * store on the stack for signal handling. - */ -struct user_regs_struct +static inline int test_pt_regs_flag(struct pt_regs *regs, int flag)  { -	psw_t psw; -	unsigned long gprs[NUM_GPRS]; -	unsigned int  acrs[NUM_ACRS]; -	unsigned long orig_gpr2; -	s390_fp_regs fp_regs; -	/* -	 * These per registers are in here so that gdb can modify them -	 * itself as there is no "official" ptrace interface for hardware -	 * watchpoints. This is the way intel does it. -	 */ -	per_struct per_info; -	unsigned long ieee_instruction_pointer;	/* obsolete, always 0 */ -}; +	return !!(regs->flags & (1U << flag)); +} -#ifdef __KERNEL__  /*   * These are defined as per linux/ptrace.h, which see.   */  #define arch_has_single_step()	(1) -extern void show_regs(struct pt_regs * regs); +#define arch_has_block_step()	(1)  #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)  #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN)  #define user_stack_pointer(regs)((regs)->gprs[15]) -#define regs_return_value(regs)((regs)->gprs[2])  #define profile_pc(regs) instruction_pointer(regs) +static inline long regs_return_value(struct pt_regs *regs) +{ +	return regs->gprs[2]; +} +  int regs_query_register_offset(const char *name);  const char *regs_query_register_name(unsigned int offset);  unsigned long regs_get_register(struct pt_regs *regs, unsigned int offset); @@ -507,7 +171,5 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)  	return regs->gprs[15] & PSW_ADDR_INSN;  } -#endif /* __KERNEL__ */  #endif /* __ASSEMBLY__ */ -  #endif /* _S390_PTRACE_H */ diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 46e96bc1f5a..d786c634e05 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -1,7 +1,5 @@  /* - * linux/include/asm-s390/qdio.h - * - * Copyright 2000,2008 IBM Corp. + * Copyright IBM Corp. 2000, 2008   * Author(s): Utz Bacher <utz.bacher@de.ibm.com>   *	      Jan Glauber <jang@linux.vnet.ibm.com>   * @@ -46,6 +44,8 @@ struct qdesfmt0 {  	u32	 : 16;  } __attribute__ ((packed)); +#define QDR_AC_MULTI_BUFFER_ENABLE 0x01 +  /**   * struct qdr - queue description record (QDR)   * @qfmt: queue format @@ -123,6 +123,40 @@ struct slibe {  };  /** + * struct qaob - queue asynchronous operation block + * @res0: reserved parameters + * @res1: reserved parameter + * @res2: reserved parameter + * @res3: reserved parameter + * @aorc: asynchronous operation return code + * @flags: internal flags + * @cbtbs: control block type + * @sb_count: number of storage blocks + * @sba: storage block element addresses + * @dcount: size of storage block elements + * @user0: user defineable value + * @res4: reserved paramater + * @user1: user defineable value + * @user2: user defineable value + */ +struct qaob { +	u64 res0[6]; +	u8 res1; +	u8 res2; +	u8 res3; +	u8 aorc; +	u8 flags; +	u16 cbtbs; +	u8 sb_count; +	u64 sba[QDIO_MAX_ELEMENTS_PER_BUFFER]; +	u16 dcount[QDIO_MAX_ELEMENTS_PER_BUFFER]; +	u64 user0; +	u64 res4[2]; +	u64 user1; +	u64 user2; +} __attribute__ ((packed, aligned(256))); + +/**   * struct slib - storage list information block (SLIB)   * @nsliba: next SLIB address (if any)   * @sla: SL address @@ -139,110 +173,47 @@ struct slib {  	struct slibe slibe[QDIO_MAX_BUFFERS_PER_Q];  } __attribute__ ((packed, aligned(2048))); -/** - * struct sbal_flags - storage block address list flags - * @last: last entry - * @cont: contiguous storage - * @frag: fragmentation - */ -struct sbal_flags { -	u8	: 1; -	u8 last : 1; -	u8 cont : 1; -	u8	: 1; -	u8 frag : 2; -	u8	: 2; -} __attribute__ ((packed)); +#define SBAL_EFLAGS_LAST_ENTRY		0x40 +#define SBAL_EFLAGS_CONTIGUOUS		0x20 +#define SBAL_EFLAGS_FIRST_FRAG		0x04 +#define SBAL_EFLAGS_MIDDLE_FRAG		0x08 +#define SBAL_EFLAGS_LAST_FRAG		0x0c +#define SBAL_EFLAGS_MASK		0x6f -#define SBAL_FLAGS_FIRST_FRAG		0x04000000UL -#define SBAL_FLAGS_MIDDLE_FRAG		0x08000000UL -#define SBAL_FLAGS_LAST_FRAG		0x0c000000UL -#define SBAL_FLAGS_LAST_ENTRY		0x40000000UL -#define SBAL_FLAGS_CONTIGUOUS		0x20000000UL - -#define SBAL_FLAGS0_DATA_CONTINUATION	0x20UL +#define SBAL_SFLAGS0_PCI_REQ		0x40 +#define SBAL_SFLAGS0_DATA_CONTINUATION	0x20  /* Awesome OpenFCP extensions */ -#define SBAL_FLAGS0_TYPE_STATUS		0x00UL -#define SBAL_FLAGS0_TYPE_WRITE		0x08UL -#define SBAL_FLAGS0_TYPE_READ		0x10UL -#define SBAL_FLAGS0_TYPE_WRITE_READ	0x18UL -#define SBAL_FLAGS0_MORE_SBALS		0x04UL -#define SBAL_FLAGS0_COMMAND		0x02UL -#define SBAL_FLAGS0_LAST_SBAL		0x00UL -#define SBAL_FLAGS0_ONLY_SBAL		SBAL_FLAGS0_COMMAND -#define SBAL_FLAGS0_MIDDLE_SBAL		SBAL_FLAGS0_MORE_SBALS -#define SBAL_FLAGS0_FIRST_SBAL SBAL_FLAGS0_MORE_SBALS | SBAL_FLAGS0_COMMAND -#define SBAL_FLAGS0_PCI			0x40 - -/** - * struct sbal_sbalf_0 - sbal flags for sbale 0 - * @pci: PCI indicator - * @cont: data continuation - * @sbtype: storage-block type (FCP) - */ -struct sbal_sbalf_0 { -	u8	  : 1; -	u8 pci	  : 1; -	u8 cont   : 1; -	u8 sbtype : 2; -	u8	  : 3; -} __attribute__ ((packed)); - -/** - * struct sbal_sbalf_1 - sbal flags for sbale 1 - * @key: storage key - */ -struct sbal_sbalf_1 { -	u8     : 4; -	u8 key : 4; -} __attribute__ ((packed)); - -/** - * struct sbal_sbalf_14 - sbal flags for sbale 14 - * @erridx: error index - */ -struct sbal_sbalf_14 { -	u8	  : 4; -	u8 erridx : 4; -} __attribute__ ((packed)); - -/** - * struct sbal_sbalf_15 - sbal flags for sbale 15 - * @reason: reason for error state - */ -struct sbal_sbalf_15 { -	u8 reason; -} __attribute__ ((packed)); - -/** - * union sbal_sbalf - storage block address list flags - * @i0: sbalf0 - * @i1: sbalf1 - * @i14: sbalf14 - * @i15: sblaf15 - * @value: raw value - */ -union sbal_sbalf { -	struct sbal_sbalf_0  i0; -	struct sbal_sbalf_1  i1; -	struct sbal_sbalf_14 i14; -	struct sbal_sbalf_15 i15; -	u8 value; -}; +#define SBAL_SFLAGS0_TYPE_STATUS	0x00 +#define SBAL_SFLAGS0_TYPE_WRITE		0x08 +#define SBAL_SFLAGS0_TYPE_READ		0x10 +#define SBAL_SFLAGS0_TYPE_WRITE_READ	0x18 +#define SBAL_SFLAGS0_MORE_SBALS		0x04 +#define SBAL_SFLAGS0_COMMAND		0x02 +#define SBAL_SFLAGS0_LAST_SBAL		0x00 +#define SBAL_SFLAGS0_ONLY_SBAL		SBAL_SFLAGS0_COMMAND +#define SBAL_SFLAGS0_MIDDLE_SBAL	SBAL_SFLAGS0_MORE_SBALS +#define SBAL_SFLAGS0_FIRST_SBAL (SBAL_SFLAGS0_MORE_SBALS | SBAL_SFLAGS0_COMMAND)  /**   * struct qdio_buffer_element - SBAL entry - * @flags: flags + * @eflags: SBAL entry flags + * @scount: SBAL count + * @sflags: whole SBAL flags   * @length: length   * @addr: address  */  struct qdio_buffer_element { -	u32 flags; +	u8 eflags; +	/* private: */ +	u8 res1; +	/* public: */ +	u8 scount; +	u8 sflags;  	u32 length;  #ifdef CONFIG_32BIT  	/* private: */ -	void *reserved; +	void *res2;  	/* public: */  #endif  	void *addr; @@ -285,9 +256,43 @@ struct slsb {  	u8 val[QDIO_MAX_BUFFERS_PER_Q];  } __attribute__ ((packed, aligned(256))); +/** + * struct qdio_outbuf_state - SBAL related asynchronous operation information + *   (for communication with upper layer programs) + *   (only required for use with completion queues) + * @flags: flags indicating state of buffer + * @aob: pointer to QAOB used for the particular SBAL + * @user: pointer to upper layer program's state information related to SBAL + *        (stored in user1 data of QAOB) + */ +struct qdio_outbuf_state { +	u8 flags; +	struct qaob *aob; +	void *user; +}; + +#define QDIO_OUTBUF_STATE_FLAG_NONE	0x00 +#define QDIO_OUTBUF_STATE_FLAG_PENDING	0x01 + +#define CHSC_AC1_INITIATE_INPUTQ	0x80 + + +/* qdio adapter-characteristics-1 flag */ +#define AC1_SIGA_INPUT_NEEDED		0x40	/* process input queues */ +#define AC1_SIGA_OUTPUT_NEEDED		0x20	/* process output queues */ +#define AC1_SIGA_SYNC_NEEDED		0x10	/* ask hypervisor to sync */ +#define AC1_AUTOMATIC_SYNC_ON_THININT	0x08	/* set by hypervisor */ +#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI	0x04	/* set by hypervisor */ +#define AC1_SC_QEBSM_AVAILABLE		0x02	/* available for subchannel */ +#define AC1_SC_QEBSM_ENABLED		0x01	/* enabled for subchannel */ + +#define CHSC_AC2_MULTI_BUFFER_AVAILABLE	0x0080 +#define CHSC_AC2_MULTI_BUFFER_ENABLED	0x0040  #define CHSC_AC2_DATA_DIV_AVAILABLE	0x0010  #define CHSC_AC2_DATA_DIV_ENABLED	0x0002 +#define CHSC_AC3_FORMAT2_CQ_AVAILABLE	0x8000 +  struct qdio_ssqd_desc {  	u8 flags;  	u8:8; @@ -306,8 +311,7 @@ struct qdio_ssqd_desc {  	u64 sch_token;  	u8 mro;  	u8 mri; -	u8:8; -	u8 sbalic; +	u16 qdioac3;  	u16:16;  	u8:8;  	u8 mmwc; @@ -319,18 +323,20 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,  			    int, int, unsigned long);  /* qdio errors reported to the upper-layer program */ -#define QDIO_ERROR_SIGA_TARGET			0x02 -#define QDIO_ERROR_SIGA_ACCESS_EXCEPTION	0x10 -#define QDIO_ERROR_SIGA_BUSY			0x20 -#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION	0x40 -#define QDIO_ERROR_SLSB_STATE			0x80 +#define QDIO_ERROR_ACTIVATE			0x0001 +#define QDIO_ERROR_GET_BUF_STATE		0x0002 +#define QDIO_ERROR_SET_BUF_STATE		0x0004 +#define QDIO_ERROR_SLSB_STATE			0x0100 + +#define QDIO_ERROR_FATAL			0x00ff +#define QDIO_ERROR_TEMPORARY			0xff00  /* for qdio_cleanup */  #define QDIO_FLAG_CLEANUP_USING_CLEAR		0x01  #define QDIO_FLAG_CLEANUP_USING_HALT		0x02  /** - * struct qdio_initialize - qdio initalization data + * struct qdio_initialize - qdio initialization data   * @cdev: associated ccw device   * @q_format: queue format   * @adapter_name: name for the adapter @@ -343,13 +349,16 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,   * @no_output_qs: number of output queues   * @input_handler: handler to be called for input queues   * @output_handler: handler to be called for output queues + * @queue_start_poll_array: polling handlers (one per input queue or NULL)   * @int_parm: interruption parameter   * @input_sbal_addr_array:  address of no_input_qs * 128 pointers   * @output_sbal_addr_array: address of no_output_qs * 128 pointers + * @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL)   */  struct qdio_initialize {  	struct ccw_device *cdev;  	unsigned char q_format; +	unsigned char qdr_ac;  	unsigned char adapter_name[8];  	unsigned int qib_param_field_format;  	unsigned char *qib_param_field; @@ -360,12 +369,43 @@ struct qdio_initialize {  	unsigned int no_output_qs;  	qdio_handler_t *input_handler;  	qdio_handler_t *output_handler; -	void (*queue_start_poll) (struct ccw_device *, int, unsigned long); +	void (**queue_start_poll_array) (struct ccw_device *, int, +					  unsigned long); +	int scan_threshold;  	unsigned long int_parm;  	void **input_sbal_addr_array;  	void **output_sbal_addr_array; +	struct qdio_outbuf_state *output_sbal_state_array;  }; +/** + * enum qdio_brinfo_entry_type - type of address entry for qdio_brinfo_desc() + * @l3_ipv6_addr: entry contains IPv6 address + * @l3_ipv4_addr: entry contains IPv4 address + * @l2_addr_lnid: entry contains MAC address and VLAN ID + */ +enum qdio_brinfo_entry_type {l3_ipv6_addr, l3_ipv4_addr, l2_addr_lnid}; + +/** + * struct qdio_brinfo_entry_XXX - Address entry for qdio_brinfo_desc() + * @nit:  Network interface token + * @addr: Address of one of the three types + * + * The struct is passed to the callback function by qdio_brinfo_desc() + */ +struct qdio_brinfo_entry_l3_ipv6 { +	u64 nit; +	struct { unsigned char _s6_addr[16]; } addr; +} __packed; +struct qdio_brinfo_entry_l3_ipv4 { +	u64 nit; +	struct { uint32_t _s_addr; } addr; +} __packed; +struct qdio_brinfo_entry_l2 { +	u64 nit; +	struct { u8 mac[6]; u16 lnid; } addr_lnid; +} __packed; +  #define QDIO_STATE_INACTIVE		0x00000002 /* after qdio_cleanup */  #define QDIO_STATE_ESTABLISHED		0x00000004 /* after qdio_establish */  #define QDIO_STATE_ACTIVE		0x00000008 /* after qdio_activate */ @@ -378,6 +418,7 @@ struct qdio_initialize {  extern int qdio_allocate(struct qdio_initialize *);  extern int qdio_establish(struct qdio_initialize *);  extern int qdio_activate(struct ccw_device *); +extern void qdio_release_aob(struct qaob *);  extern int do_QDIO(struct ccw_device *, unsigned int, int, unsigned int,  		   unsigned int);  extern int qdio_start_irq(struct ccw_device *, int); @@ -386,5 +427,10 @@ extern int qdio_get_next_buffers(struct ccw_device *, int, int *, int *);  extern int qdio_shutdown(struct ccw_device *, int);  extern int qdio_free(struct ccw_device *);  extern int qdio_get_ssqd_desc(struct ccw_device *, struct qdio_ssqd_desc *); +extern int qdio_pnso_brinfo(struct subchannel_id schid, +		int cnc, u16 *response, +		void (*cb)(void *priv, enum qdio_brinfo_entry_type type, +				void *entry), +		void *priv);  #endif /* __QDIO_H__ */ diff --git a/arch/s390/include/asm/reset.h b/arch/s390/include/asm/reset.h index f584f4a5258..804578587a7 100644 --- a/arch/s390/include/asm/reset.h +++ b/arch/s390/include/asm/reset.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/reset.h - *   *    Copyright IBM Corp. 2006   *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>   */ @@ -17,5 +15,5 @@ struct reset_call {  extern void register_reset_call(struct reset_call *reset);  extern void unregister_reset_call(struct reset_call *reset); -extern void s390_reset_system(void); +extern void s390_reset_system(void (*func)(void *), void *data);  #endif /* _ASM_S390_RESET_H */ diff --git a/arch/s390/include/asm/runtime_instr.h b/arch/s390/include/asm/runtime_instr.h new file mode 100644 index 00000000000..830da737ff8 --- /dev/null +++ b/arch/s390/include/asm/runtime_instr.h @@ -0,0 +1,98 @@ +#ifndef _RUNTIME_INSTR_H +#define _RUNTIME_INSTR_H + +#define S390_RUNTIME_INSTR_START	0x1 +#define S390_RUNTIME_INSTR_STOP		0x2 + +struct runtime_instr_cb { +	__u64 buf_current; +	__u64 buf_origin; +	__u64 buf_limit; + +	__u32 valid		: 1; +	__u32 pstate		: 1; +	__u32 pstate_set_buf	: 1; +	__u32 home_space	: 1; +	__u32 altered		: 1; +	__u32			: 3; +	__u32 pstate_sample	: 1; +	__u32 sstate_sample	: 1; +	__u32 pstate_collect	: 1; +	__u32 sstate_collect	: 1; +	__u32			: 1; +	__u32 halted_int	: 1; +	__u32 int_requested	: 1; +	__u32 buffer_full_int	: 1; +	__u32 key		: 4; +	__u32			: 9; +	__u32 rgs		: 3; + +	__u32 mode		: 4; +	__u32 next		: 1; +	__u32 mae		: 1; +	__u32			: 2; +	__u32 call_type_br	: 1; +	__u32 return_type_br	: 1; +	__u32 other_type_br	: 1; +	__u32 bc_other_type	: 1; +	__u32 emit		: 1; +	__u32 tx_abort		: 1; +	__u32			: 2; +	__u32 bp_xn		: 1; +	__u32 bp_xt		: 1; +	__u32 bp_ti		: 1; +	__u32 bp_ni		: 1; +	__u32 suppr_y		: 1; +	__u32 suppr_z		: 1; + +	__u32 dc_miss_extra	: 1; +	__u32 lat_lev_ignore	: 1; +	__u32 ic_lat_lev	: 4; +	__u32 dc_lat_lev	: 4; + +	__u64 reserved1; +	__u64 scaling_factor; +	__u64 rsic; +	__u64 reserved2; +} __packed __aligned(8); + +extern struct runtime_instr_cb runtime_instr_empty_cb; + +static inline void load_runtime_instr_cb(struct runtime_instr_cb *cb) +{ +	asm volatile(".insn	rsy,0xeb0000000060,0,0,%0"	/* LRIC */ +		: : "Q" (*cb)); +} + +static inline void store_runtime_instr_cb(struct runtime_instr_cb *cb) +{ +	asm volatile(".insn	rsy,0xeb0000000061,0,0,%0"	/* STRIC */ +		: "=Q" (*cb) : : "cc"); +} + +static inline void save_ri_cb(struct runtime_instr_cb *cb_prev) +{ +#ifdef CONFIG_64BIT +	if (cb_prev) +		store_runtime_instr_cb(cb_prev); +#endif +} + +static inline void restore_ri_cb(struct runtime_instr_cb *cb_next, +				 struct runtime_instr_cb *cb_prev) +{ +#ifdef CONFIG_64BIT +	if (cb_next) +		load_runtime_instr_cb(cb_next); +	else if (cb_prev) +		load_runtime_instr_cb(&runtime_instr_empty_cb); +#endif +} + +#ifdef CONFIG_64BIT +extern void exit_thread_runtime_instr(void); +#else +static inline void exit_thread_runtime_instr(void) { } +#endif + +#endif /* _RUNTIME_INSTR_H */ diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h index 423fdda2322..487f9b64efb 100644 --- a/arch/s390/include/asm/rwsem.h +++ b/arch/s390/include/asm/rwsem.h @@ -2,10 +2,8 @@  #define _S390_RWSEM_H  /* - *  include/asm-s390/rwsem.h - *   *  S390 version - *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 2002   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   *   *  Based on asm-alpha/semaphore.h and asm-i386/rwsem.h @@ -41,81 +39,21 @@  #error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"  #endif -#ifdef __KERNEL__ - -#include <linux/list.h> -#include <linux/spinlock.h> - -struct rwsem_waiter; - -extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *); -extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *); -extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *); -extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *); -extern struct rw_semaphore *rwsem_downgrade_write(struct rw_semaphore *); - -/* - * the semaphore definition - */ -struct rw_semaphore { -	signed long		count; -	spinlock_t		wait_lock; -	struct list_head	wait_list; -#ifdef CONFIG_DEBUG_LOCK_ALLOC -	struct lockdep_map	dep_map; -#endif -}; - -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define RWSEM_UNLOCKED_VALUE	0x00000000  #define RWSEM_ACTIVE_BIAS	0x00000001  #define RWSEM_ACTIVE_MASK	0x0000ffff  #define RWSEM_WAITING_BIAS	(-0x00010000) -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  #define RWSEM_UNLOCKED_VALUE	0x0000000000000000L  #define RWSEM_ACTIVE_BIAS	0x0000000000000001L  #define RWSEM_ACTIVE_MASK	0x00000000ffffffffL  #define RWSEM_WAITING_BIAS	(-0x0000000100000000L) -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  #define RWSEM_ACTIVE_READ_BIAS	RWSEM_ACTIVE_BIAS  #define RWSEM_ACTIVE_WRITE_BIAS	(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)  /* - * initialisation - */ - -#ifdef CONFIG_DEBUG_LOCK_ALLOC -# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname } -#else -# define __RWSEM_DEP_MAP_INIT(lockname) -#endif - -#define __RWSEM_INITIALIZER(name) \ - { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait.lock), \ -   LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) } - -#define DECLARE_RWSEM(name) \ -	struct rw_semaphore name = __RWSEM_INITIALIZER(name) - -static inline void init_rwsem(struct rw_semaphore *sem) -{ -	sem->count = RWSEM_UNLOCKED_VALUE; -	spin_lock_init(&sem->wait_lock); -	INIT_LIST_HEAD(&sem->wait_list); -} - -extern void __init_rwsem(struct rw_semaphore *sem, const char *name, -			 struct lock_class_key *key); - -#define init_rwsem(sem)				\ -do {						\ -	static struct lock_class_key __key;	\ -						\ -	__init_rwsem((sem), #sem, &__key);	\ -} while (0) - - -/*   * lock for reading   */  static inline void __down_read(struct rw_semaphore *sem) @@ -123,19 +61,19 @@ static inline void __down_read(struct rw_semaphore *sem)  	signed long old, new;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	lr	%1,%0\n"  		"	ahi	%1,%4\n"  		"	cs	%0,%1,%2\n"  		"	jl	0b" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	lgr	%1,%0\n"  		"	aghi	%1,%4\n"  		"	csg	%0,%1,%2\n"  		"	jl	0b" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)  		: "cc", "memory"); @@ -151,7 +89,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)  	signed long old, new;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	ltr	%1,%0\n"  		"	jm	1f\n" @@ -159,7 +97,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)  		"	cs	%0,%1,%2\n"  		"	jl	0b\n"  		"1:" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	ltgr	%1,%0\n"  		"	jm	1f\n" @@ -167,7 +105,7 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)  		"	csg	%0,%1,%2\n"  		"	jl	0b\n"  		"1:" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)  		: "cc", "memory"); @@ -183,19 +121,19 @@ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)  	tmp = RWSEM_ACTIVE_WRITE_BIAS;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	lr	%1,%0\n"  		"	a	%1,%4\n"  		"	cs	%0,%1,%2\n"  		"	jl	0b" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	lgr	%1,%0\n"  		"	ag	%1,%4\n"  		"	csg	%0,%1,%2\n"  		"	jl	0b" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "m" (tmp)  		: "cc", "memory"); @@ -216,19 +154,19 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)  	signed long old;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%1\n"  		"0:	ltr	%0,%0\n"  		"	jnz	1f\n"  		"	cs	%0,%3,%1\n"  		"	jl	0b\n" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%1\n"  		"0:	ltgr	%0,%0\n"  		"	jnz	1f\n"  		"	csg	%0,%3,%1\n"  		"	jl	0b\n" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		"1:"  		: "=&d" (old), "=Q" (sem->count)  		: "Q" (sem->count), "d" (RWSEM_ACTIVE_WRITE_BIAS) @@ -244,19 +182,19 @@ static inline void __up_read(struct rw_semaphore *sem)  	signed long old, new;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	lr	%1,%0\n"  		"	ahi	%1,%4\n"  		"	cs	%0,%1,%2\n"  		"	jl	0b" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	lgr	%1,%0\n"  		"	aghi	%1,%4\n"  		"	csg	%0,%1,%2\n"  		"	jl	0b" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "i" (-RWSEM_ACTIVE_READ_BIAS)  		: "cc", "memory"); @@ -274,19 +212,19 @@ static inline void __up_write(struct rw_semaphore *sem)  	tmp = -RWSEM_ACTIVE_WRITE_BIAS;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	lr	%1,%0\n"  		"	a	%1,%4\n"  		"	cs	%0,%1,%2\n"  		"	jl	0b" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	lgr	%1,%0\n"  		"	ag	%1,%4\n"  		"	csg	%0,%1,%2\n"  		"	jl	0b" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "m" (tmp)  		: "cc", "memory"); @@ -304,19 +242,19 @@ static inline void __downgrade_write(struct rw_semaphore *sem)  	tmp = -RWSEM_WAITING_BIAS;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	lr	%1,%0\n"  		"	a	%1,%4\n"  		"	cs	%0,%1,%2\n"  		"	jl	0b" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	lgr	%1,%0\n"  		"	ag	%1,%4\n"  		"	csg	%0,%1,%2\n"  		"	jl	0b" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "m" (tmp)  		: "cc", "memory"); @@ -332,19 +270,19 @@ static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)  	signed long old, new;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	lr	%1,%0\n"  		"	ar	%1,%4\n"  		"	cs	%0,%1,%2\n"  		"	jl	0b" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	lgr	%1,%0\n"  		"	agr	%1,%4\n"  		"	csg	%0,%1,%2\n"  		"	jl	0b" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "d" (delta)  		: "cc", "memory"); @@ -358,29 +296,23 @@ static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)  	signed long old, new;  	asm volatile( -#ifndef __s390x__ +#ifndef CONFIG_64BIT  		"	l	%0,%2\n"  		"0:	lr	%1,%0\n"  		"	ar	%1,%4\n"  		"	cs	%0,%1,%2\n"  		"	jl	0b" -#else /* __s390x__ */ +#else /* CONFIG_64BIT */  		"	lg	%0,%2\n"  		"0:	lgr	%1,%0\n"  		"	agr	%1,%4\n"  		"	csg	%0,%1,%2\n"  		"	jl	0b" -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  		: "=&d" (old), "=&d" (new), "=Q" (sem->count)  		: "Q" (sem->count), "d" (delta)  		: "cc", "memory");  	return new;  } -static inline int rwsem_is_locked(struct rw_semaphore *sem) -{ -	return (sem->count != 0); -} - -#endif /* __KERNEL__ */  #endif /* _S390_RWSEM_H */ diff --git a/arch/s390/include/asm/s390_ext.h b/arch/s390/include/asm/s390_ext.h deleted file mode 100644 index 1a9307e7084..00000000000 --- a/arch/s390/include/asm/s390_ext.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _S390_EXTINT_H -#define _S390_EXTINT_H - -/* - *  include/asm-s390/s390_ext.h - * - *  S390 version - *    Copyright IBM Corp. 1999,2007 - *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), - *               Martin Schwidefsky (schwidefsky@de.ibm.com) - */ - -#include <linux/types.h> - -typedef void (*ext_int_handler_t)(unsigned int, unsigned int, unsigned long); - -typedef struct ext_int_info_t { -	struct ext_int_info_t *next; -	ext_int_handler_t handler; -	__u16 code; -} ext_int_info_t; - -extern ext_int_info_t *ext_int_hash[]; - -int register_external_interrupt(__u16 code, ext_int_handler_t handler); -int register_early_external_interrupt(__u16 code, ext_int_handler_t handler, -				      ext_int_info_t *info); -int unregister_external_interrupt(__u16 code, ext_int_handler_t handler); -int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler, -					ext_int_info_t *info); - -#endif diff --git a/arch/s390/include/asm/schid.h b/arch/s390/include/asm/schid.h index 3e4d401b4e4..40b47dfa9d6 100644 --- a/arch/s390/include/asm/schid.h +++ b/arch/s390/include/asm/schid.h @@ -1,19 +1,8 @@  #ifndef ASM_SCHID_H  #define ASM_SCHID_H -#include <linux/types.h> - -struct subchannel_id { -	__u32 cssid : 8; -	__u32 : 4; -	__u32 m : 1; -	__u32 ssid : 2; -	__u32 one : 1; -	__u32 sch_no : 16; -} __attribute__ ((packed, aligned(4))); - -#ifdef __KERNEL__  #include <linux/string.h> +#include <uapi/asm/schid.h>  /* Helper function for sane state of pre-allocated subchannel_id. */  static inline void @@ -29,6 +18,4 @@ schid_equal(struct subchannel_id *schid1, struct subchannel_id *schid2)  	return !memcmp(schid1, schid2, sizeof(struct subchannel_id));  } -#endif /* __KERNEL__ */ -  #endif /* ASM_SCHID_H */ diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index fed7bee650a..1aba89b53cb 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/sclp.h - *   *    Copyright IBM Corp. 2007   *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>   */ @@ -10,6 +8,7 @@  #include <linux/types.h>  #include <asm/chpid.h> +#include <asm/cpu.h>  #define SCLP_CHP_INFO_MASK_SIZE		32 @@ -29,7 +28,11 @@ struct sclp_ipl_info {  struct sclp_cpu_entry {  	u8 address; -	u8 reserved0[13]; +	u8 reserved0[2]; +	u8 : 3; +	u8 siif : 1; +	u8 : 4; +	u8 reserved2[10];  	u8 type;  	u8 reserved1;  } __attribute__((packed)); @@ -39,20 +42,30 @@ struct sclp_cpu_info {  	unsigned int standby;  	unsigned int combined;  	int has_cpu_type; -	struct sclp_cpu_entry cpu[255]; +	struct sclp_cpu_entry cpu[MAX_CPU_ADDRESS + 1];  };  int sclp_get_cpu_info(struct sclp_cpu_info *info);  int sclp_cpu_configure(u8 cpu);  int sclp_cpu_deconfigure(u8 cpu); -void sclp_facilities_detect(void);  unsigned long long sclp_get_rnmax(void);  unsigned long long sclp_get_rzm(void); +unsigned int sclp_get_max_cpu(void);  int sclp_sdias_blk_count(void);  int sclp_sdias_copy(void *dest, int blk_num, int nr_blks);  int sclp_chp_configure(struct chp_id chpid);  int sclp_chp_deconfigure(struct chp_id chpid);  int sclp_chp_read_info(struct sclp_chp_info *info);  void sclp_get_ipl_info(struct sclp_ipl_info *info); +bool __init sclp_has_linemode(void); +bool __init sclp_has_vt220(void); +bool sclp_has_sprp(void); +int sclp_pci_configure(u32 fid); +int sclp_pci_deconfigure(u32 fid); +int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); +unsigned long sclp_get_hsa_size(void); +void sclp_early_detect(void); +int sclp_has_siif(void); +unsigned int sclp_get_ibc(void);  #endif /* _ASM_S390_SCLP_H */ diff --git a/arch/s390/include/asm/scsw.h b/arch/s390/include/asm/scsw.h index de389cb54d2..4af99cdaddf 100644 --- a/arch/s390/include/asm/scsw.h +++ b/arch/s390/include/asm/scsw.h @@ -1,7 +1,7 @@  /*   *  Helper functions for scsw access.   * - *    Copyright IBM Corp. 2008,2009 + *    Copyright IBM Corp. 2008, 2012   *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>   */ @@ -9,7 +9,7 @@  #define _ASM_S390_SCSW_H_  #include <linux/types.h> -#include <asm/chsc.h> +#include <asm/css_chars.h>  #include <asm/cio.h>  /** @@ -100,14 +100,46 @@ struct tm_scsw {  } __attribute__ ((packed));  /** + * struct eadm_scsw - subchannel status word for eadm subchannels + * @key: subchannel key + * @eswf: esw format + * @cc: deferred condition code + * @ectl: extended control + * @fctl: function control + * @actl: activity control + * @stctl: status control + * @aob: AOB address + * @dstat: device status + * @cstat: subchannel status + */ +struct eadm_scsw { +	u32 key:4; +	u32:1; +	u32 eswf:1; +	u32 cc:2; +	u32:6; +	u32 ectl:1; +	u32:2; +	u32 fctl:3; +	u32 actl:7; +	u32 stctl:5; +	u32 aob; +	u32 dstat:8; +	u32 cstat:8; +	u32:16; +} __packed; + +/**   * union scsw - subchannel status word   * @cmd: command-mode SCSW   * @tm: transport-mode SCSW + * @eadm: eadm SCSW   */  union scsw {  	struct cmd_scsw cmd;  	struct tm_scsw tm; -} __attribute__ ((packed)); +	struct eadm_scsw eadm; +} __packed;  #define SCSW_FCTL_CLEAR_FUNC	 0x1  #define SCSW_FCTL_HALT_FUNC	 0x2 diff --git a/arch/s390/include/asm/serial.h b/arch/s390/include/asm/serial.h new file mode 100644 index 00000000000..5b3e48ef534 --- /dev/null +++ b/arch/s390/include/asm/serial.h @@ -0,0 +1,6 @@ +#ifndef _ASM_S390_SERIAL_H +#define _ASM_S390_SERIAL_H + +#define BASE_BAUD 0 + +#endif /* _ASM_S390_SERIAL_H */ diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index d5e2ef10537..089a49814c5 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h @@ -1,60 +1,40 @@  /* - *  include/asm-s390/setup.h - *   *  S390 version - *    Copyright IBM Corp. 1999,2010 + *    Copyright IBM Corp. 1999, 2010   */ -  #ifndef _ASM_S390_SETUP_H  #define _ASM_S390_SETUP_H -#define COMMAND_LINE_SIZE	4096 - -#define ARCH_COMMAND_LINE_SIZE	896 +#include <uapi/asm/setup.h> -#ifdef __KERNEL__  #define PARMAREA		0x10400 -#define MEMORY_CHUNKS		256  #ifndef __ASSEMBLY__  #include <asm/lowcore.h>  #include <asm/types.h> -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define IPL_DEVICE        (*(unsigned long *)  (0x10404))  #define INITRD_START      (*(unsigned long *)  (0x1040C))  #define INITRD_SIZE       (*(unsigned long *)  (0x10414)) -#else /* __s390x__ */ +#define OLDMEM_BASE	  (*(unsigned long *)  (0x1041C)) +#define OLDMEM_SIZE	  (*(unsigned long *)  (0x10424)) +#else /* CONFIG_64BIT */  #define IPL_DEVICE        (*(unsigned long *)  (0x10400))  #define INITRD_START      (*(unsigned long *)  (0x10408))  #define INITRD_SIZE       (*(unsigned long *)  (0x10410)) -#endif /* __s390x__ */ +#define OLDMEM_BASE	  (*(unsigned long *)  (0x10418)) +#define OLDMEM_SIZE	  (*(unsigned long *)  (0x10420)) +#endif /* CONFIG_64BIT */  #define COMMAND_LINE      ((char *)            (0x10480)) -#define CHUNK_READ_WRITE 0 -#define CHUNK_READ_ONLY  1 - -struct mem_chunk { -	unsigned long addr; -	unsigned long size; -	int type; -}; - -extern struct mem_chunk memory_chunk[]; -extern unsigned long real_memory_size;  extern int memory_end_set;  extern unsigned long memory_end; +extern unsigned long max_physmem_end; -void detect_memory_layout(struct mem_chunk chunk[]); - -#define PRIMARY_SPACE_MODE	0 -#define ACCESS_REGISTER_MODE	1 -#define SECONDARY_SPACE_MODE	2 -#define HOME_SPACE_MODE		3 - -extern unsigned int user_mode; +extern void detect_memory_memblock(void);  /*   * Machine features detected in head.S @@ -62,50 +42,58 @@ extern unsigned int user_mode;  #define MACHINE_FLAG_VM		(1UL << 0)  #define MACHINE_FLAG_IEEE	(1UL << 1) -#define MACHINE_FLAG_CSP	(1UL << 3) -#define MACHINE_FLAG_MVPG	(1UL << 4) -#define MACHINE_FLAG_DIAG44	(1UL << 5) -#define MACHINE_FLAG_IDTE	(1UL << 6) -#define MACHINE_FLAG_DIAG9C	(1UL << 7) -#define MACHINE_FLAG_MVCOS	(1UL << 8) -#define MACHINE_FLAG_KVM	(1UL << 9) -#define MACHINE_FLAG_HPAGE	(1UL << 10) -#define MACHINE_FLAG_PFMF	(1UL << 11) +#define MACHINE_FLAG_CSP	(1UL << 2) +#define MACHINE_FLAG_MVPG	(1UL << 3) +#define MACHINE_FLAG_DIAG44	(1UL << 4) +#define MACHINE_FLAG_IDTE	(1UL << 5) +#define MACHINE_FLAG_DIAG9C	(1UL << 6) +#define MACHINE_FLAG_KVM	(1UL << 8) +#define MACHINE_FLAG_ESOP	(1UL << 9) +#define MACHINE_FLAG_EDAT1	(1UL << 10) +#define MACHINE_FLAG_EDAT2	(1UL << 11)  #define MACHINE_FLAG_LPAR	(1UL << 12) -#define MACHINE_FLAG_SPP	(1UL << 13) +#define MACHINE_FLAG_LPP	(1UL << 13)  #define MACHINE_FLAG_TOPOLOGY	(1UL << 14) +#define MACHINE_FLAG_TE		(1UL << 15) +#define MACHINE_FLAG_RRBM	(1UL << 16) +#define MACHINE_FLAG_TLB_LC	(1UL << 17)  #define MACHINE_IS_VM		(S390_lowcore.machine_flags & MACHINE_FLAG_VM)  #define MACHINE_IS_KVM		(S390_lowcore.machine_flags & MACHINE_FLAG_KVM)  #define MACHINE_IS_LPAR		(S390_lowcore.machine_flags & MACHINE_FLAG_LPAR)  #define MACHINE_HAS_DIAG9C	(S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C) +#define MACHINE_HAS_ESOP	(S390_lowcore.machine_flags & MACHINE_FLAG_ESOP) +#define MACHINE_HAS_PFMF	MACHINE_HAS_EDAT1 +#define MACHINE_HAS_HPAGE	MACHINE_HAS_EDAT1 -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define MACHINE_HAS_IEEE	(S390_lowcore.machine_flags & MACHINE_FLAG_IEEE)  #define MACHINE_HAS_CSP		(S390_lowcore.machine_flags & MACHINE_FLAG_CSP)  #define MACHINE_HAS_IDTE	(0)  #define MACHINE_HAS_DIAG44	(1)  #define MACHINE_HAS_MVPG	(S390_lowcore.machine_flags & MACHINE_FLAG_MVPG) -#define MACHINE_HAS_MVCOS	(0) -#define MACHINE_HAS_HPAGE	(0) -#define MACHINE_HAS_PFMF	(0) -#define MACHINE_HAS_SPP		(0) +#define MACHINE_HAS_EDAT1	(0) +#define MACHINE_HAS_EDAT2	(0) +#define MACHINE_HAS_LPP		(0)  #define MACHINE_HAS_TOPOLOGY	(0) -#else /* __s390x__ */ +#define MACHINE_HAS_TE		(0) +#define MACHINE_HAS_RRBM	(0) +#define MACHINE_HAS_TLB_LC	(0) +#else /* CONFIG_64BIT */  #define MACHINE_HAS_IEEE	(1)  #define MACHINE_HAS_CSP		(1)  #define MACHINE_HAS_IDTE	(S390_lowcore.machine_flags & MACHINE_FLAG_IDTE)  #define MACHINE_HAS_DIAG44	(S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)  #define MACHINE_HAS_MVPG	(1) -#define MACHINE_HAS_MVCOS	(S390_lowcore.machine_flags & MACHINE_FLAG_MVCOS) -#define MACHINE_HAS_HPAGE	(S390_lowcore.machine_flags & MACHINE_FLAG_HPAGE) -#define MACHINE_HAS_PFMF	(S390_lowcore.machine_flags & MACHINE_FLAG_PFMF) -#define MACHINE_HAS_SPP		(S390_lowcore.machine_flags & MACHINE_FLAG_SPP) +#define MACHINE_HAS_EDAT1	(S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1) +#define MACHINE_HAS_EDAT2	(S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2) +#define MACHINE_HAS_LPP		(S390_lowcore.machine_flags & MACHINE_FLAG_LPP)  #define MACHINE_HAS_TOPOLOGY	(S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY) -#endif /* __s390x__ */ - -#define ZFCPDUMP_HSA_SIZE	(32UL<<20) +#define MACHINE_HAS_TE		(S390_lowcore.machine_flags & MACHINE_FLAG_TE) +#define MACHINE_HAS_RRBM	(S390_lowcore.machine_flags & MACHINE_FLAG_RRBM) +#define MACHINE_HAS_TLB_LC	(S390_lowcore.machine_flags & MACHINE_FLAG_TLB_LC) +#endif /* CONFIG_64BIT */  /*   * Console mode. Override with conmode= @@ -128,19 +116,36 @@ extern char vmpoff_cmd[];  #define NSS_NAME_SIZE	8  extern char kernel_nss_name[]; +#ifdef CONFIG_PFAULT +extern int pfault_init(void); +extern void pfault_fini(void); +#else /* CONFIG_PFAULT */ +#define pfault_init()		({-1;}) +#define pfault_fini()		do { } while (0) +#endif /* CONFIG_PFAULT */ + +extern void cmma_init(void); + +extern void (*_machine_restart)(char *command); +extern void (*_machine_halt)(void); +extern void (*_machine_power_off)(void); +  #else /* __ASSEMBLY__ */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define IPL_DEVICE        0x10404  #define INITRD_START      0x1040C  #define INITRD_SIZE       0x10414 -#else /* __s390x__ */ +#define OLDMEM_BASE	  0x1041C +#define OLDMEM_SIZE	  0x10424 +#else /* CONFIG_64BIT */  #define IPL_DEVICE        0x10400  #define INITRD_START      0x10408  #define INITRD_SIZE       0x10410 -#endif /* __s390x__ */ +#define OLDMEM_BASE	  0x10418 +#define OLDMEM_SIZE	  0x10420 +#endif /* CONFIG_64BIT */  #define COMMAND_LINE      0x10480  #endif /* __ASSEMBLY__ */ -#endif /* __KERNEL__ */  #endif /* _ASM_S390_SETUP_H */ diff --git a/arch/s390/include/asm/sfp-util.h b/arch/s390/include/asm/sfp-util.h index 0addc6466d9..5959bfb3b69 100644 --- a/arch/s390/include/asm/sfp-util.h +++ b/arch/s390/include/asm/sfp-util.h @@ -51,7 +51,7 @@  	wl = __wl;					\  }) -#ifdef __s390x__ +#ifdef CONFIG_64BIT  #define udiv_qrnnd(q, r, n1, n0, d)			\    do { unsigned long __n;				\         unsigned int __r, __d;				\ @@ -72,6 +72,6 @@ extern unsigned long __udiv_qrnnd (unsigned int *, unsigned int,  #define UDIV_NEEDS_NORMALIZATION 0 -#define abort() return 0 +#define abort() BUG()  #define __BYTE_ORDER __BIG_ENDIAN diff --git a/arch/s390/include/asm/shmparam.h b/arch/s390/include/asm/shmparam.h index c2e0c0508e7..e985182738f 100644 --- a/arch/s390/include/asm/shmparam.h +++ b/arch/s390/include/asm/shmparam.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/shmparam.h - *   *  S390 version   *   *  Derived from "include/asm-i386/shmparam.h" diff --git a/arch/s390/include/asm/signal.h b/arch/s390/include/asm/signal.h index cdf5cb2fe03..abf9e573594 100644 --- a/arch/s390/include/asm/signal.h +++ b/arch/s390/include/asm/signal.h @@ -1,22 +1,13 @@  /* - *  include/asm-s390/signal.h - *   *  S390 version   *   *  Derived from "include/asm-i386/signal.h"   */ -  #ifndef _ASMS390_SIGNAL_H  #define _ASMS390_SIGNAL_H -#include <linux/types.h> -#include <linux/time.h> +#include <uapi/asm/signal.h> -/* Avoid too many header ordering problems.  */ -struct siginfo; -struct pt_regs; - -#ifdef __KERNEL__  /* Most things should be clean enough to redefine this at will, if care     is taken to make libc match.  */  #include <asm/sigcontext.h> @@ -30,143 +21,5 @@ typedef struct {          unsigned long sig[_NSIG_WORDS];  } sigset_t; -#else -/* Here we must cater to libcs that poke about in kernel headers.  */ - -#define NSIG            32 -typedef unsigned long sigset_t; - -#endif /* __KERNEL__ */ - -#define SIGHUP           1 -#define SIGINT           2 -#define SIGQUIT          3 -#define SIGILL           4 -#define SIGTRAP          5 -#define SIGABRT          6 -#define SIGIOT           6 -#define SIGBUS           7 -#define SIGFPE           8 -#define SIGKILL          9 -#define SIGUSR1         10 -#define SIGSEGV         11 -#define SIGUSR2         12 -#define SIGPIPE         13 -#define SIGALRM         14 -#define SIGTERM         15 -#define SIGSTKFLT       16 -#define SIGCHLD         17 -#define SIGCONT         18 -#define SIGSTOP         19 -#define SIGTSTP         20 -#define SIGTTIN         21 -#define SIGTTOU         22 -#define SIGURG          23 -#define SIGXCPU         24 -#define SIGXFSZ         25 -#define SIGVTALRM       26 -#define SIGPROF         27 -#define SIGWINCH        28 -#define SIGIO           29 -#define SIGPOLL         SIGIO -/* -#define SIGLOST         29 -*/ -#define SIGPWR          30 -#define SIGSYS		31 -#define SIGUNUSED       31 - -/* These should not be considered constants from userland.  */ -#define SIGRTMIN        32 -#define SIGRTMAX        _NSIG - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP    0x00000001 -#define SA_NOCLDWAIT    0x00000002 -#define SA_SIGINFO      0x00000004 -#define SA_ONSTACK      0x08000000 -#define SA_RESTART      0x10000000 -#define SA_NODEFER      0x40000000 -#define SA_RESETHAND    0x80000000 - -#define SA_NOMASK       SA_NODEFER -#define SA_ONESHOT      SA_RESETHAND - -#define SA_RESTORER     0x04000000 - -/* - * sigaltstack controls - */ -#define SS_ONSTACK      1 -#define SS_DISABLE      2 - -#define MINSIGSTKSZ     2048 -#define SIGSTKSZ        8192 - -#include <asm-generic/signal-defs.h> - -#ifdef __KERNEL__ -struct old_sigaction { -        __sighandler_t sa_handler; -        old_sigset_t sa_mask; -        unsigned long sa_flags; -        void (*sa_restorer)(void); -}; - -struct sigaction { -        __sighandler_t sa_handler; -        unsigned long sa_flags; -        void (*sa_restorer)(void); -        sigset_t sa_mask;               /* mask last for extensibility */ -}; - -struct k_sigaction { -        struct sigaction sa; -}; - -#define ptrace_signal_deliver(regs, cookie) do { } while (0) - -#else -/* Here we must cater to libcs that poke about in kernel headers.  */ - -struct sigaction { -        union { -          __sighandler_t _sa_handler; -          void (*_sa_sigaction)(int, struct siginfo *, void *); -        } _u; -#ifndef __s390x__ /* lovely */ -        sigset_t sa_mask; -        unsigned long sa_flags; -        void (*sa_restorer)(void); -#else  /* __s390x__ */ -        unsigned long sa_flags; -        void (*sa_restorer)(void); -	sigset_t sa_mask; -#endif /* __s390x__ */ -}; - -#define sa_handler      _u._sa_handler -#define sa_sigaction    _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { -        void __user *ss_sp; -        int ss_flags; -        size_t ss_size; -} stack_t; - - +#define __ARCH_HAS_SA_RESTORER  #endif diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h index e3bffd4e2d6..bf9c823d402 100644 --- a/arch/s390/include/asm/sigp.h +++ b/arch/s390/include/asm/sigp.h @@ -1,131 +1,53 @@ -/* - *  Routines and structures for signalling other processors. - * - *    Copyright IBM Corp. 1999,2010 - *    Author(s): Denis Joseph Barrow, - *		 Martin Schwidefsky <schwidefsky@de.ibm.com>, - *		 Heiko Carstens <heiko.carstens@de.ibm.com>, - */ - -#ifndef __ASM_SIGP_H -#define __ASM_SIGP_H - -#include <asm/system.h> - -/* Get real cpu address from logical cpu number. */ -extern unsigned short __cpu_logical_map[]; - -static inline int cpu_logical_map(int cpu) -{ -#ifdef CONFIG_SMP -	return __cpu_logical_map[cpu]; -#else -	return stap(); -#endif -} - -enum { -	sigp_sense = 1, -	sigp_external_call = 2, -	sigp_emergency_signal = 3, -	sigp_start = 4, -	sigp_stop = 5, -	sigp_restart = 6, -	sigp_stop_and_store_status = 9, -	sigp_initial_cpu_reset = 11, -	sigp_cpu_reset = 12, -	sigp_set_prefix = 13, -	sigp_store_status_at_address = 14, -	sigp_store_extended_status_at_address = 15, -	sigp_set_architecture = 18, -	sigp_conditional_emergency_signal = 19, -	sigp_sense_running = 21, -}; - -enum { -	sigp_order_code_accepted = 0, -	sigp_status_stored = 1, -	sigp_busy = 2, -	sigp_not_operational = 3, -}; - -/* - * Definitions for external call. - */ -enum { -	ec_schedule = 0, -	ec_call_function, -	ec_call_function_single, -}; - -/* - * Signal processor. - */ -static inline int raw_sigp(u16 cpu, int order) -{ -	register unsigned long reg1 asm ("1") = 0; -	int ccode; - -	asm volatile( -		"	sigp	%1,%2,0(%3)\n" -		"	ipm	%0\n" -		"	srl	%0,28\n" -		:	"=d"	(ccode) -		: "d" (reg1), "d" (cpu), -		  "a" (order) : "cc" , "memory"); -	return ccode; -} - -/* - * Signal processor with parameter. - */ -static inline int raw_sigp_p(u32 parameter, u16 cpu, int order) -{ -	register unsigned int reg1 asm ("1") = parameter; -	int ccode; - -	asm volatile( -		"	sigp	%1,%2,0(%3)\n" -		"	ipm	%0\n" -		"	srl	%0,28\n" -		: "=d" (ccode) -		: "d" (reg1), "d" (cpu), -		  "a" (order) : "cc" , "memory"); -	return ccode; -} - -/* - * Signal processor with parameter and return status. - */ -static inline int raw_sigp_ps(u32 *status, u32 parm, u16 cpu, int order) +#ifndef __S390_ASM_SIGP_H +#define __S390_ASM_SIGP_H + +/* SIGP order codes */ +#define SIGP_SENSE		      1 +#define SIGP_EXTERNAL_CALL	      2 +#define SIGP_EMERGENCY_SIGNAL	      3 +#define SIGP_START		      4 +#define SIGP_STOP		      5 +#define SIGP_RESTART		      6 +#define SIGP_STOP_AND_STORE_STATUS    9 +#define SIGP_INITIAL_CPU_RESET	     11 +#define SIGP_SET_PREFIX		     13 +#define SIGP_STORE_STATUS_AT_ADDRESS 14 +#define SIGP_SET_ARCHITECTURE	     18 +#define SIGP_COND_EMERGENCY_SIGNAL   19 +#define SIGP_SENSE_RUNNING	     21 + +/* SIGP condition codes */ +#define SIGP_CC_ORDER_CODE_ACCEPTED 0 +#define SIGP_CC_STATUS_STORED	    1 +#define SIGP_CC_BUSY		    2 +#define SIGP_CC_NOT_OPERATIONAL	    3 + +/* SIGP cpu status bits */ + +#define SIGP_STATUS_CHECK_STOP		0x00000010UL +#define SIGP_STATUS_STOPPED		0x00000040UL +#define SIGP_STATUS_EXT_CALL_PENDING	0x00000080UL +#define SIGP_STATUS_INVALID_PARAMETER	0x00000100UL +#define SIGP_STATUS_INCORRECT_STATE	0x00000200UL +#define SIGP_STATUS_NOT_RUNNING		0x00000400UL + +#ifndef __ASSEMBLY__ + +static inline int __pcpu_sigp(u16 addr, u8 order, u32 parm, u32 *status)  {  	register unsigned int reg1 asm ("1") = parm; -	int ccode; +	int cc;  	asm volatile(  		"	sigp	%1,%2,0(%3)\n"  		"	ipm	%0\n"  		"	srl	%0,28\n" -		: "=d" (ccode), "+d" (reg1) -		: "d" (cpu), "a" (order) -		: "cc" , "memory"); -	*status = reg1; -	return ccode; +		: "=d" (cc), "+d" (reg1) : "d" (addr), "a" (order) : "cc"); +	if (status && cc == 1) +		*status = reg1; +	return cc;  } -static inline int sigp(int cpu, int order) -{ -	return raw_sigp(cpu_logical_map(cpu), order); -} - -static inline int sigp_p(u32 parameter, int cpu, int order) -{ -	return raw_sigp_p(parameter, cpu_logical_map(cpu), order); -} - -static inline int sigp_ps(u32 *status, u32 parm, int cpu, int order) -{ -	return raw_sigp_ps(status, parm, cpu_logical_map(cpu), order); -} +#endif /* __ASSEMBLY__ */ -#endif /* __ASM_SIGP_H */ +#endif /* __S390_ASM_SIGP_H */ diff --git a/arch/s390/include/asm/smp.h b/arch/s390/include/asm/smp.h index edc03cb9cd7..4f1307962a9 100644 --- a/arch/s390/include/asm/smp.h +++ b/arch/s390/include/asm/smp.h @@ -1,5 +1,5 @@  /* - *    Copyright IBM Corp. 1999,2009 + *    Copyright IBM Corp. 1999, 2012   *    Author(s): Denis Joseph Barrow,   *		 Martin Schwidefsky <schwidefsky@de.ibm.com>,   *		 Heiko Carstens <heiko.carstens@de.ibm.com>, @@ -7,72 +7,72 @@  #ifndef __ASM_SMP_H  #define __ASM_SMP_H -#ifdef CONFIG_SMP - -#include <asm/system.h>  #include <asm/sigp.h> -extern void machine_restart_smp(char *); -extern void machine_halt_smp(void); -extern void machine_power_off_smp(void); +#ifdef CONFIG_SMP -#define raw_smp_processor_id()	(S390_lowcore.cpu_nr) +#include <asm/lowcore.h> -extern int __cpu_disable (void); -extern void __cpu_die (unsigned int cpu); -extern void cpu_die (void) __attribute__ ((noreturn)); -extern int __cpu_up (unsigned int cpu); +#define raw_smp_processor_id()	(S390_lowcore.cpu_nr)  extern struct mutex smp_cpu_state_mutex; -extern int smp_cpu_polarization[]; + +extern int __cpu_up(unsigned int cpu, struct task_struct *tidle);  extern void arch_send_call_function_single_ipi(int cpu);  extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); -extern struct save_area *zfcpdump_save_areas[NR_CPUS + 1]; +extern void smp_call_online_cpu(void (*func)(void *), void *); +extern void smp_call_ipl_cpu(void (*func)(void *), void *); -extern void smp_switch_to_ipl_cpu(void (*func)(void *), void *); -extern void smp_switch_to_cpu(void (*)(void *), void *, unsigned long sp, -			      int from, int to); -extern void smp_restart_cpu(void); +extern int smp_find_processor_id(u16 address); +extern int smp_store_status(int cpu); +extern int smp_vcpu_scheduled(int cpu); +extern void smp_yield_cpu(int cpu); +extern void smp_yield(void); +extern void smp_cpu_set_polarization(int cpu, int val); +extern int smp_cpu_get_polarization(int cpu); +extern void smp_fill_possible_mask(void); -/* - * returns 1 if (virtual) cpu is scheduled - * returns 0 otherwise - */ -static inline int smp_vcpu_scheduled(int cpu) +#else /* CONFIG_SMP */ + +static inline void smp_call_ipl_cpu(void (*func)(void *), void *data)  { -	u32 status; - -	switch (sigp_ps(&status, 0, cpu, sigp_sense_running)) { -	case sigp_status_stored: -		/* Check for running status */ -		if (status & 0x400) -			return 0; -		break; -	case sigp_not_operational: -		return 0; -	default: -		break; -	} -	return 1; +	func(data);  } -#else /* CONFIG_SMP */ - -static inline void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) +static inline void smp_call_online_cpu(void (*func)(void *), void *data)  {  	func(data);  } -#define smp_vcpu_scheduled	(1) +static inline int smp_find_processor_id(u16 address) { return 0; } +static inline int smp_store_status(int cpu) { return 0; } +static inline int smp_vcpu_scheduled(int cpu) { return 1; } +static inline void smp_yield_cpu(int cpu) { } +static inline void smp_yield(void) { } +static inline void smp_fill_possible_mask(void) { }  #endif /* CONFIG_SMP */ +static inline void smp_stop_cpu(void) +{ +	u16 pcpu = stap(); + +	for (;;) { +		__pcpu_sigp(pcpu, SIGP_STOP, 0, NULL); +		cpu_relax(); +	} +} +  #ifdef CONFIG_HOTPLUG_CPU  extern int smp_rescan_cpus(void); +extern void __noreturn cpu_die(void); +extern void __cpu_die(unsigned int cpu); +extern int __cpu_disable(void);  #else  static inline int smp_rescan_cpus(void) { return 0; } +static inline void cpu_die(void) { }  #endif  #endif /* __ASM_SMP_H */ diff --git a/arch/s390/include/asm/sparsemem.h b/arch/s390/include/asm/sparsemem.h index 545d219e6a2..a60d085ddb4 100644 --- a/arch/s390/include/asm/sparsemem.h +++ b/arch/s390/include/asm/sparsemem.h @@ -4,13 +4,11 @@  #ifdef CONFIG_64BIT  #define SECTION_SIZE_BITS	28 -#define MAX_PHYSADDR_BITS	42 -#define MAX_PHYSMEM_BITS	42 +#define MAX_PHYSMEM_BITS	46  #else  #define SECTION_SIZE_BITS	25 -#define MAX_PHYSADDR_BITS	31  #define MAX_PHYSMEM_BITS	31  #endif /* CONFIG_64BIT */ diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h index 56612fc8186..96879f7ad6d 100644 --- a/arch/s390/include/asm/spinlock.h +++ b/arch/s390/include/asm/spinlock.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/spinlock.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   *   *  Derived from "include/asm-i386/spinlock.h" @@ -13,16 +11,21 @@  #include <linux/smp.h> +#define SPINLOCK_LOCKVAL (S390_lowcore.spinlock_lockval) + +extern int spin_retry; +  static inline int -_raw_compare_and_swap(volatile unsigned int *lock, -		      unsigned int old, unsigned int new) +_raw_compare_and_swap(unsigned int *lock, unsigned int old, unsigned int new)  { +	unsigned int old_expected = old; +  	asm volatile(  		"	cs	%0,%3,%1"  		: "=d" (old), "=Q" (*lock)  		: "0" (old), "d" (new), "Q" (*lock)  		: "cc", "memory" ); -	return old; +	return old == old_expected;  }  /* @@ -34,52 +37,69 @@ _raw_compare_and_swap(volatile unsigned int *lock,   * (the type definitions are in asm/spinlock_types.h)   */ -#define arch_spin_is_locked(x) ((x)->owner_cpu != 0) -#define arch_spin_unlock_wait(lock) \ -	do { while (arch_spin_is_locked(lock)) \ -		 arch_spin_relax(lock); } while (0) +void arch_spin_lock_wait(arch_spinlock_t *); +int arch_spin_trylock_retry(arch_spinlock_t *); +void arch_spin_relax(arch_spinlock_t *); +void arch_spin_lock_wait_flags(arch_spinlock_t *, unsigned long flags); -extern void arch_spin_lock_wait(arch_spinlock_t *); -extern void arch_spin_lock_wait_flags(arch_spinlock_t *, unsigned long flags); -extern int arch_spin_trylock_retry(arch_spinlock_t *); -extern void arch_spin_relax(arch_spinlock_t *lock); +static inline u32 arch_spin_lockval(int cpu) +{ +	return ~cpu; +} -static inline void arch_spin_lock(arch_spinlock_t *lp) +static inline int arch_spin_value_unlocked(arch_spinlock_t lock)  { -	int old; +	return lock.lock == 0; +} -	old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id()); -	if (likely(old == 0)) -		return; -	arch_spin_lock_wait(lp); +static inline int arch_spin_is_locked(arch_spinlock_t *lp) +{ +	return ACCESS_ONCE(lp->lock) != 0;  } -static inline void arch_spin_lock_flags(arch_spinlock_t *lp, -					 unsigned long flags) +static inline int arch_spin_trylock_once(arch_spinlock_t *lp)  { -	int old; +	barrier(); +	return likely(arch_spin_value_unlocked(*lp) && +		      _raw_compare_and_swap(&lp->lock, 0, SPINLOCK_LOCKVAL)); +} -	old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id()); -	if (likely(old == 0)) -		return; -	arch_spin_lock_wait_flags(lp, flags); +static inline int arch_spin_tryrelease_once(arch_spinlock_t *lp) +{ +	return _raw_compare_and_swap(&lp->lock, SPINLOCK_LOCKVAL, 0);  } -static inline int arch_spin_trylock(arch_spinlock_t *lp) +static inline void arch_spin_lock(arch_spinlock_t *lp)  { -	int old; +	if (!arch_spin_trylock_once(lp)) +		arch_spin_lock_wait(lp); +} -	old = _raw_compare_and_swap(&lp->owner_cpu, 0, ~smp_processor_id()); -	if (likely(old == 0)) -		return 1; -	return arch_spin_trylock_retry(lp); +static inline void arch_spin_lock_flags(arch_spinlock_t *lp, +					unsigned long flags) +{ +	if (!arch_spin_trylock_once(lp)) +		arch_spin_lock_wait_flags(lp, flags); +} + +static inline int arch_spin_trylock(arch_spinlock_t *lp) +{ +	if (!arch_spin_trylock_once(lp)) +		return arch_spin_trylock_retry(lp); +	return 1;  }  static inline void arch_spin_unlock(arch_spinlock_t *lp)  { -	_raw_compare_and_swap(&lp->owner_cpu, lp->owner_cpu, 0); +	arch_spin_tryrelease_once(lp);  } -		 + +static inline void arch_spin_unlock_wait(arch_spinlock_t *lock) +{ +	while (arch_spin_is_locked(lock)) +		arch_spin_relax(lock); +} +  /*   * Read-write spinlocks, allowing multiple readers   * but only one writer. @@ -110,42 +130,50 @@ extern void _raw_write_lock_wait(arch_rwlock_t *lp);  extern void _raw_write_lock_wait_flags(arch_rwlock_t *lp, unsigned long flags);  extern int _raw_write_trylock_retry(arch_rwlock_t *lp); +static inline int arch_read_trylock_once(arch_rwlock_t *rw) +{ +	unsigned int old = ACCESS_ONCE(rw->lock); +	return likely((int) old >= 0 && +		      _raw_compare_and_swap(&rw->lock, old, old + 1)); +} + +static inline int arch_write_trylock_once(arch_rwlock_t *rw) +{ +	unsigned int old = ACCESS_ONCE(rw->lock); +	return likely(old == 0 && +		      _raw_compare_and_swap(&rw->lock, 0, 0x80000000)); +} +  static inline void arch_read_lock(arch_rwlock_t *rw)  { -	unsigned int old; -	old = rw->lock & 0x7fffffffU; -	if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old) +	if (!arch_read_trylock_once(rw))  		_raw_read_lock_wait(rw);  }  static inline void arch_read_lock_flags(arch_rwlock_t *rw, unsigned long flags)  { -	unsigned int old; -	old = rw->lock & 0x7fffffffU; -	if (_raw_compare_and_swap(&rw->lock, old, old + 1) != old) +	if (!arch_read_trylock_once(rw))  		_raw_read_lock_wait_flags(rw, flags);  }  static inline void arch_read_unlock(arch_rwlock_t *rw)  { -	unsigned int old, cmp; +	unsigned int old; -	old = rw->lock;  	do { -		cmp = old; -		old = _raw_compare_and_swap(&rw->lock, old, old - 1); -	} while (cmp != old); +		old = ACCESS_ONCE(rw->lock); +	} while (!_raw_compare_and_swap(&rw->lock, old, old - 1));  }  static inline void arch_write_lock(arch_rwlock_t *rw)  { -	if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0)) +	if (!arch_write_trylock_once(rw))  		_raw_write_lock_wait(rw);  }  static inline void arch_write_lock_flags(arch_rwlock_t *rw, unsigned long flags)  { -	if (unlikely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) != 0)) +	if (!arch_write_trylock_once(rw))  		_raw_write_lock_wait_flags(rw, flags);  } @@ -156,18 +184,16 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)  static inline int arch_read_trylock(arch_rwlock_t *rw)  { -	unsigned int old; -	old = rw->lock & 0x7fffffffU; -	if (likely(_raw_compare_and_swap(&rw->lock, old, old + 1) == old)) -		return 1; -	return _raw_read_trylock_retry(rw); +	if (!arch_read_trylock_once(rw)) +		return _raw_read_trylock_retry(rw); +	return 1;  }  static inline int arch_write_trylock(arch_rwlock_t *rw)  { -	if (likely(_raw_compare_and_swap(&rw->lock, 0, 0x80000000) == 0)) -		return 1; -	return _raw_write_trylock_retry(rw); +	if (!arch_write_trylock_once(rw)) +		return _raw_write_trylock_retry(rw); +	return 1;  }  #define arch_read_relax(lock)	cpu_relax() diff --git a/arch/s390/include/asm/spinlock_types.h b/arch/s390/include/asm/spinlock_types.h index 9c76656a0af..b2cd6ff7c2c 100644 --- a/arch/s390/include/asm/spinlock_types.h +++ b/arch/s390/include/asm/spinlock_types.h @@ -6,13 +6,13 @@  #endif  typedef struct { -	volatile unsigned int owner_cpu; +	unsigned int lock;  } __attribute__ ((aligned (4))) arch_spinlock_t; -#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 } +#define __ARCH_SPIN_LOCK_UNLOCKED { .lock = 0, }  typedef struct { -	volatile unsigned int lock; +	unsigned int lock;  } arch_rwlock_t;  #define __ARCH_RW_LOCK_UNLOCKED		{ 0 } diff --git a/arch/s390/include/asm/statfs.h b/arch/s390/include/asm/statfs.h deleted file mode 100644 index 3be7fbd406c..00000000000 --- a/arch/s390/include/asm/statfs.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - *  include/asm-s390/statfs.h - * - *  S390 version - * - *  Derived from "include/asm-i386/statfs.h" - */ - -#ifndef _S390_STATFS_H -#define _S390_STATFS_H - -#ifndef __s390x__ -#include <asm-generic/statfs.h> -#else -/* - * We can't use <asm-generic/statfs.h> because in 64-bit mode - * we mix ints of different sizes in our struct statfs. - */ - -#ifndef __KERNEL_STRICT_NAMES -#include <linux/types.h> -typedef __kernel_fsid_t	fsid_t; -#endif - -struct statfs { -	int  f_type; -	int  f_bsize; -	long f_blocks; -	long f_bfree; -	long f_bavail; -	long f_files; -	long f_ffree; -	__kernel_fsid_t f_fsid; -	int  f_namelen; -	int  f_frsize; -	int  f_flags; -	int  f_spare[4]; -}; - -struct statfs64 { -	int  f_type; -	int  f_bsize; -	long f_blocks; -	long f_bfree; -	long f_bavail; -	long f_files; -	long f_ffree; -	__kernel_fsid_t f_fsid; -	int  f_namelen; -	int  f_frsize; -	int  f_flags; -	int  f_spare[4]; -}; - -struct compat_statfs64 { -	__u32 f_type; -	__u32 f_bsize; -	__u64 f_blocks; -	__u64 f_bfree; -	__u64 f_bavail; -	__u64 f_files; -	__u64 f_ffree; -	__kernel_fsid_t f_fsid; -	__u32 f_namelen; -	__u32 f_frsize; -	__u32 f_flags; -	__u32 f_spare[4]; -}; - -#endif /* __s390x__ */ -#endif diff --git a/arch/s390/include/asm/string.h b/arch/s390/include/asm/string.h index cd0241db5a4..7e2dcd7c57e 100644 --- a/arch/s390/include/asm/string.h +++ b/arch/s390/include/asm/string.h @@ -1,16 +1,12 @@  /* - *  include/asm-s390/string.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),   */  #ifndef _S390_STRING_H_  #define _S390_STRING_H_ -#ifdef __KERNEL__ -  #ifndef _LINUX_TYPES_H  #include <linux/types.h>  #endif @@ -100,7 +96,6 @@ static inline char *strcat(char *dst, const char *src)  static inline char *strcpy(char *dst, const char *src)  { -#if __GNUC__ < 4  	register int r0 asm("0") = 0;  	char *ret = dst; @@ -110,14 +105,10 @@ static inline char *strcpy(char *dst, const char *src)  		: "+&a" (dst), "+&a" (src) : "d" (r0)  		: "cc", "memory");  	return ret; -#else -	return __builtin_strcpy(dst, src); -#endif  }  static inline size_t strlen(const char *s)  { -#if __GNUC__ < 4  	register unsigned long r0 asm("0") = 0;  	const char *tmp = s; @@ -126,9 +117,6 @@ static inline size_t strlen(const char *s)  		"	jo	0b"  		: "+d" (r0), "+a" (tmp) :  : "cc");  	return r0 - (unsigned long) s; -#else -	return __builtin_strlen(s); -#endif  }  static inline size_t strnlen(const char * s, size_t n) @@ -152,6 +140,4 @@ size_t strlen(const char *s);  size_t strnlen(const char * s, size_t n);  #endif /* !IN_ARCH_STRING_C */ -#endif /* __KERNEL__ */ -  #endif /* __S390_STRING_H_ */ diff --git a/arch/s390/include/asm/suspend.h b/arch/s390/include/asm/suspend.h deleted file mode 100644 index dc75c616eaf..00000000000 --- a/arch/s390/include/asm/suspend.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __ASM_S390_SUSPEND_H -#define __ASM_S390_SUSPEND_H - -static inline int arch_prepare_suspend(void) -{ -	return 0; -} - -#endif - diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h new file mode 100644 index 00000000000..18ea9e3f814 --- /dev/null +++ b/arch/s390/include/asm/switch_to.h @@ -0,0 +1,137 @@ +/* + * Copyright IBM Corp. 1999, 2009 + * + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#ifndef __ASM_SWITCH_TO_H +#define __ASM_SWITCH_TO_H + +#include <linux/thread_info.h> +#include <asm/ptrace.h> + +extern struct task_struct *__switch_to(void *, void *); +extern void update_cr_regs(struct task_struct *task); + +static inline int test_fp_ctl(u32 fpc) +{ +	u32 orig_fpc; +	int rc; + +	if (!MACHINE_HAS_IEEE) +		return 0; + +	asm volatile( +		"	efpc    %1\n" +		"	sfpc	%2\n" +		"0:	sfpc	%1\n" +		"	la	%0,0\n" +		"1:\n" +		EX_TABLE(0b,1b) +		: "=d" (rc), "=d" (orig_fpc) +		: "d" (fpc), "0" (-EINVAL)); +	return rc; +} + +static inline void save_fp_ctl(u32 *fpc) +{ +	if (!MACHINE_HAS_IEEE) +		return; + +	asm volatile( +		"       stfpc   %0\n" +		: "+Q" (*fpc)); +} + +static inline int restore_fp_ctl(u32 *fpc) +{ +	int rc; + +	if (!MACHINE_HAS_IEEE) +		return 0; + +	asm volatile( +		"	lfpc    %1\n" +		"0:	la	%0,0\n" +		"1:\n" +		EX_TABLE(0b,1b) +		: "=d" (rc) : "Q" (*fpc), "0" (-EINVAL)); +	return rc; +} + +static inline void save_fp_regs(freg_t *fprs) +{ +	asm volatile("std 0,%0" : "=Q" (fprs[0])); +	asm volatile("std 2,%0" : "=Q" (fprs[2])); +	asm volatile("std 4,%0" : "=Q" (fprs[4])); +	asm volatile("std 6,%0" : "=Q" (fprs[6])); +	if (!MACHINE_HAS_IEEE) +		return; +	asm volatile("std 1,%0" : "=Q" (fprs[1])); +	asm volatile("std 3,%0" : "=Q" (fprs[3])); +	asm volatile("std 5,%0" : "=Q" (fprs[5])); +	asm volatile("std 7,%0" : "=Q" (fprs[7])); +	asm volatile("std 8,%0" : "=Q" (fprs[8])); +	asm volatile("std 9,%0" : "=Q" (fprs[9])); +	asm volatile("std 10,%0" : "=Q" (fprs[10])); +	asm volatile("std 11,%0" : "=Q" (fprs[11])); +	asm volatile("std 12,%0" : "=Q" (fprs[12])); +	asm volatile("std 13,%0" : "=Q" (fprs[13])); +	asm volatile("std 14,%0" : "=Q" (fprs[14])); +	asm volatile("std 15,%0" : "=Q" (fprs[15])); +} + +static inline void restore_fp_regs(freg_t *fprs) +{ +	asm volatile("ld 0,%0" : : "Q" (fprs[0])); +	asm volatile("ld 2,%0" : : "Q" (fprs[2])); +	asm volatile("ld 4,%0" : : "Q" (fprs[4])); +	asm volatile("ld 6,%0" : : "Q" (fprs[6])); +	if (!MACHINE_HAS_IEEE) +		return; +	asm volatile("ld 1,%0" : : "Q" (fprs[1])); +	asm volatile("ld 3,%0" : : "Q" (fprs[3])); +	asm volatile("ld 5,%0" : : "Q" (fprs[5])); +	asm volatile("ld 7,%0" : : "Q" (fprs[7])); +	asm volatile("ld 8,%0" : : "Q" (fprs[8])); +	asm volatile("ld 9,%0" : : "Q" (fprs[9])); +	asm volatile("ld 10,%0" : : "Q" (fprs[10])); +	asm volatile("ld 11,%0" : : "Q" (fprs[11])); +	asm volatile("ld 12,%0" : : "Q" (fprs[12])); +	asm volatile("ld 13,%0" : : "Q" (fprs[13])); +	asm volatile("ld 14,%0" : : "Q" (fprs[14])); +	asm volatile("ld 15,%0" : : "Q" (fprs[15])); +} + +static inline void save_access_regs(unsigned int *acrs) +{ +	typedef struct { int _[NUM_ACRS]; } acrstype; + +	asm volatile("stam 0,15,%0" : "=Q" (*(acrstype *)acrs)); +} + +static inline void restore_access_regs(unsigned int *acrs) +{ +	typedef struct { int _[NUM_ACRS]; } acrstype; + +	asm volatile("lam 0,15,%0" : : "Q" (*(acrstype *)acrs)); +} + +#define switch_to(prev,next,last) do {					\ +	if (prev->mm) {							\ +		save_fp_ctl(&prev->thread.fp_regs.fpc);			\ +		save_fp_regs(prev->thread.fp_regs.fprs);		\ +		save_access_regs(&prev->thread.acrs[0]);		\ +		save_ri_cb(prev->thread.ri_cb);				\ +	}								\ +	if (next->mm) {							\ +		restore_fp_ctl(&next->thread.fp_regs.fpc);		\ +		restore_fp_regs(next->thread.fp_regs.fprs);		\ +		restore_access_regs(&next->thread.acrs[0]);		\ +		restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb);	\ +		update_cr_regs(next);					\ +	}								\ +	prev = __switch_to(prev,next);					\ +} while (0) + +#endif /* __ASM_SWITCH_TO_H */ diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index 5c0246b955d..abad78d5b10 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h @@ -12,7 +12,9 @@  #ifndef _ASM_SYSCALL_H  #define _ASM_SYSCALL_H	1 +#include <uapi/linux/audit.h>  #include <linux/sched.h> +#include <linux/err.h>  #include <asm/ptrace.h>  /* @@ -21,11 +23,13 @@   * type here is what we want [need] for both 32 bit and 64 bit systems.   */  extern const unsigned int sys_call_table[]; +extern const unsigned int sys_call_table_emu[];  static inline long syscall_get_nr(struct task_struct *task,  				  struct pt_regs *regs)  { -	return regs->svcnr ? regs->svcnr : -1; +	return test_pt_regs_flag(regs, PIF_SYSCALL) ? +		(regs->int_code & 0xffff) : -1;  }  static inline void syscall_rollback(struct task_struct *task, @@ -37,7 +41,7 @@ static inline void syscall_rollback(struct task_struct *task,  static inline long syscall_get_error(struct task_struct *task,  				     struct pt_regs *regs)  { -	return (regs->gprs[2] >= -4096UL) ? -regs->gprs[2] : 0; +	return IS_ERR_VALUE(regs->gprs[2]) ? regs->gprs[2] : 0;  }  static inline long syscall_get_return_value(struct task_struct *task, @@ -85,4 +89,12 @@ static inline void syscall_set_arguments(struct task_struct *task,  		regs->orig_gpr2 = args[0];  } +static inline int syscall_get_arch(void) +{ +#ifdef CONFIG_COMPAT +	if (test_tsk_thread_flag(current, TIF_31BIT)) +		return AUDIT_ARCH_S390; +#endif +	return sizeof(long) == 8 ? AUDIT_ARCH_S390X : AUDIT_ARCH_S390; +}  #endif	/* _ASM_SYSCALL_H */ diff --git a/arch/s390/include/asm/sysinfo.h b/arch/s390/include/asm/sysinfo.h index 79d3d6e2e9c..f92428e459f 100644 --- a/arch/s390/include/asm/sysinfo.h +++ b/arch/s390/include/asm/sysinfo.h @@ -1,7 +1,7 @@  /*   * definition for store system information stsi   * - * Copyright IBM Corp. 2001,2008 + * Copyright IBM Corp. 2001, 2008   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of the GNU General Public License (version 2 only) @@ -17,7 +17,10 @@  #include <asm/bitsperlong.h>  struct sysinfo_1_1_1 { -	unsigned short :16; +	unsigned char p:1; +	unsigned char :6; +	unsigned char t:1; +	unsigned char :8;  	unsigned char ccr;  	unsigned char cai;  	char reserved_0[28]; @@ -30,9 +33,14 @@ struct sysinfo_1_1_1 {  	char model[16];  	char model_perm_cap[16];  	char model_temp_cap[16]; -	char model_cap_rating[4]; -	char model_perm_cap_rating[4]; -	char model_temp_cap_rating[4]; +	unsigned int model_cap_rating; +	unsigned int model_perm_cap_rating; +	unsigned int model_temp_cap_rating; +	unsigned char typepct[5]; +	unsigned char reserved_2[3]; +	unsigned int ncr; +	unsigned int npr; +	unsigned int ntr;  };  struct sysinfo_1_2_1 { @@ -47,8 +55,9 @@ struct sysinfo_1_2_2 {  	char format;  	char reserved_0[1];  	unsigned short acc_offset; -	char reserved_1[24]; -	unsigned int secondary_capability; +	char reserved_1[20]; +	unsigned int nominal_cap; +	unsigned int secondary_cap;  	unsigned int capability;  	unsigned short cpus_total;  	unsigned short cpus_configured; @@ -109,6 +118,8 @@ struct sysinfo_3_2_2 {  	char reserved_544[3552];  }; +extern int topology_max_mnest; +  #define TOPOLOGY_CPU_BITS	64  #define TOPOLOGY_NR_MAG		6 @@ -142,21 +153,7 @@ struct sysinfo_15_1_x {  	union topology_entry tle[0];  }; -static inline int stsi(void *sysinfo, int fc, int sel1, int sel2) -{ -	register int r0 asm("0") = (fc << 28) | sel1; -	register int r1 asm("1") = sel2; - -	asm volatile( -		"   stsi 0(%2)\n" -		"0: jz   2f\n" -		"1: lhi  %0,%3\n" -		"2:\n" -		EX_TABLE(0b, 1b) -		: "+d" (r0) : "d" (r1), "a" (sysinfo), "K" (-ENOSYS) -		: "cc", "memory"); -	return r0; -} +int stsi(void *sysinfo, int fc, int sel1, int sel2);  /*   * Service level reporting interface. diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h deleted file mode 100644 index 3ad16dbf622..00000000000 --- a/arch/s390/include/asm/system.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright IBM Corp. 1999, 2009 - * - * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> - */ - -#ifndef __ASM_SYSTEM_H -#define __ASM_SYSTEM_H - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <asm/types.h> -#include <asm/ptrace.h> -#include <asm/setup.h> -#include <asm/processor.h> -#include <asm/lowcore.h> - -#ifdef __KERNEL__ - -struct task_struct; - -extern struct task_struct *__switch_to(void *, void *); - -static inline void save_fp_regs(s390_fp_regs *fpregs) -{ -	asm volatile( -		"	std	0,%O0+8(%R0)\n" -		"	std	2,%O0+24(%R0)\n" -		"	std	4,%O0+40(%R0)\n" -		"	std	6,%O0+56(%R0)" -		: "=Q" (*fpregs) : "Q" (*fpregs)); -	if (!MACHINE_HAS_IEEE) -		return; -	asm volatile( -		"	stfpc	%0\n" -		"	std	1,%O0+16(%R0)\n" -		"	std	3,%O0+32(%R0)\n" -		"	std	5,%O0+48(%R0)\n" -		"	std	7,%O0+64(%R0)\n" -		"	std	8,%O0+72(%R0)\n" -		"	std	9,%O0+80(%R0)\n" -		"	std	10,%O0+88(%R0)\n" -		"	std	11,%O0+96(%R0)\n" -		"	std	12,%O0+104(%R0)\n" -		"	std	13,%O0+112(%R0)\n" -		"	std	14,%O0+120(%R0)\n" -		"	std	15,%O0+128(%R0)\n" -		: "=Q" (*fpregs) : "Q" (*fpregs)); -} - -static inline void restore_fp_regs(s390_fp_regs *fpregs) -{ -	asm volatile( -		"	ld	0,%O0+8(%R0)\n" -		"	ld	2,%O0+24(%R0)\n" -		"	ld	4,%O0+40(%R0)\n" -		"	ld	6,%O0+56(%R0)" -		: : "Q" (*fpregs)); -	if (!MACHINE_HAS_IEEE) -		return; -	asm volatile( -		"	lfpc	%0\n" -		"	ld	1,%O0+16(%R0)\n" -		"	ld	3,%O0+32(%R0)\n" -		"	ld	5,%O0+48(%R0)\n" -		"	ld	7,%O0+64(%R0)\n" -		"	ld	8,%O0+72(%R0)\n" -		"	ld	9,%O0+80(%R0)\n" -		"	ld	10,%O0+88(%R0)\n" -		"	ld	11,%O0+96(%R0)\n" -		"	ld	12,%O0+104(%R0)\n" -		"	ld	13,%O0+112(%R0)\n" -		"	ld	14,%O0+120(%R0)\n" -		"	ld	15,%O0+128(%R0)\n" -		: : "Q" (*fpregs)); -} - -static inline void save_access_regs(unsigned int *acrs) -{ -	asm volatile("stam 0,15,%0" : "=Q" (*acrs)); -} - -static inline void restore_access_regs(unsigned int *acrs) -{ -	asm volatile("lam 0,15,%0" : : "Q" (*acrs)); -} - -#define switch_to(prev,next,last) do {					\ -	if (prev->mm) {							\ -		save_fp_regs(&prev->thread.fp_regs);			\ -		save_access_regs(&prev->thread.acrs[0]);		\ -	}								\ -	if (next->mm) {							\ -		restore_fp_regs(&next->thread.fp_regs);			\ -		restore_access_regs(&next->thread.acrs[0]);		\ -	}								\ -	prev = __switch_to(prev,next);					\ -} while (0) - -extern void account_vtime(struct task_struct *, struct task_struct *); -extern void account_tick_vtime(struct task_struct *); - -#ifdef CONFIG_PFAULT -extern void pfault_irq_init(void); -extern int pfault_init(void); -extern void pfault_fini(void); -#else /* CONFIG_PFAULT */ -#define pfault_irq_init()	do { } while (0) -#define pfault_init()		({-1;}) -#define pfault_fini()		do { } while (0) -#endif /* CONFIG_PFAULT */ - -extern void cmma_init(void); -extern int memcpy_real(void *, void *, size_t); - -#define finish_arch_switch(prev) do {					     \ -	set_fs(current->thread.mm_segment);				     \ -	account_vtime(prev, current);					     \ -} while (0) - -#define nop() asm volatile("nop") - -#define xchg(ptr,x)							  \ -({									  \ -	__typeof__(*(ptr)) __ret;					  \ -	__ret = (__typeof__(*(ptr)))					  \ -		__xchg((unsigned long)(x), (void *)(ptr),sizeof(*(ptr))); \ -	__ret;								  \ -}) - -extern void __xchg_called_with_bad_pointer(void); - -static inline unsigned long __xchg(unsigned long x, void * ptr, int size) -{ -	unsigned long addr, old; -	int shift; - -        switch (size) { -	case 1: -		addr = (unsigned long) ptr; -		shift = (3 ^ (addr & 3)) << 3; -		addr ^= addr & 3; -		asm volatile( -			"	l	%0,%4\n" -			"0:	lr	0,%0\n" -			"	nr	0,%3\n" -			"	or	0,%2\n" -			"	cs	%0,0,%4\n" -			"	jl	0b\n" -			: "=&d" (old), "=Q" (*(int *) addr) -			: "d" (x << shift), "d" (~(255 << shift)), -			  "Q" (*(int *) addr) : "memory", "cc", "0"); -		return old >> shift; -	case 2: -		addr = (unsigned long) ptr; -		shift = (2 ^ (addr & 2)) << 3; -		addr ^= addr & 2; -		asm volatile( -			"	l	%0,%4\n" -			"0:	lr	0,%0\n" -			"	nr	0,%3\n" -			"	or	0,%2\n" -			"	cs	%0,0,%4\n" -			"	jl	0b\n" -			: "=&d" (old), "=Q" (*(int *) addr) -			: "d" (x << shift), "d" (~(65535 << shift)), -			  "Q" (*(int *) addr) : "memory", "cc", "0"); -		return old >> shift; -	case 4: -		asm volatile( -			"	l	%0,%3\n" -			"0:	cs	%0,%2,%3\n" -			"	jl	0b\n" -			: "=&d" (old), "=Q" (*(int *) ptr) -			: "d" (x), "Q" (*(int *) ptr) -			: "memory", "cc"); -		return old; -#ifdef __s390x__ -	case 8: -		asm volatile( -			"	lg	%0,%3\n" -			"0:	csg	%0,%2,%3\n" -			"	jl	0b\n" -			: "=&d" (old), "=m" (*(long *) ptr) -			: "d" (x), "Q" (*(long *) ptr) -			: "memory", "cc"); -		return old; -#endif /* __s390x__ */ -	} -	__xchg_called_with_bad_pointer(); -	return x; -} - -/* - * Atomic compare and exchange.  Compare OLD with MEM, if identical, - * store NEW in MEM.  Return the initial value in MEM.  Success is - * indicated by comparing RETURN with OLD. - */ - -#define __HAVE_ARCH_CMPXCHG 1 - -#define cmpxchg(ptr, o, n)						\ -	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	\ -					(unsigned long)(n), sizeof(*(ptr)))) - -extern void __cmpxchg_called_with_bad_pointer(void); - -static inline unsigned long -__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size) -{ -	unsigned long addr, prev, tmp; -	int shift; - -        switch (size) { -	case 1: -		addr = (unsigned long) ptr; -		shift = (3 ^ (addr & 3)) << 3; -		addr ^= addr & 3; -		asm volatile( -			"	l	%0,%2\n" -			"0:	nr	%0,%5\n" -			"	lr	%1,%0\n" -			"	or	%0,%3\n" -			"	or	%1,%4\n" -			"	cs	%0,%1,%2\n" -			"	jnl	1f\n" -			"	xr	%1,%0\n" -			"	nr	%1,%5\n" -			"	jnz	0b\n" -			"1:" -			: "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) -			: "d" (old << shift), "d" (new << shift), -			  "d" (~(255 << shift)), "Q" (*(int *) ptr) -			: "memory", "cc"); -		return prev >> shift; -	case 2: -		addr = (unsigned long) ptr; -		shift = (2 ^ (addr & 2)) << 3; -		addr ^= addr & 2; -		asm volatile( -			"	l	%0,%2\n" -			"0:	nr	%0,%5\n" -			"	lr	%1,%0\n" -			"	or	%0,%3\n" -			"	or	%1,%4\n" -			"	cs	%0,%1,%2\n" -			"	jnl	1f\n" -			"	xr	%1,%0\n" -			"	nr	%1,%5\n" -			"	jnz	0b\n" -			"1:" -			: "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr) -			: "d" (old << shift), "d" (new << shift), -			  "d" (~(65535 << shift)), "Q" (*(int *) ptr) -			: "memory", "cc"); -		return prev >> shift; -	case 4: -		asm volatile( -			"	cs	%0,%3,%1\n" -			: "=&d" (prev), "=Q" (*(int *) ptr) -			: "0" (old), "d" (new), "Q" (*(int *) ptr) -			: "memory", "cc"); -		return prev; -#ifdef __s390x__ -	case 8: -		asm volatile( -			"	csg	%0,%3,%1\n" -			: "=&d" (prev), "=Q" (*(long *) ptr) -			: "0" (old), "d" (new), "Q" (*(long *) ptr) -			: "memory", "cc"); -		return prev; -#endif /* __s390x__ */ -        } -	__cmpxchg_called_with_bad_pointer(); -	return old; -} - -/* - * Force strict CPU ordering. - * And yes, this is required on UP too when we're talking - * to devices. - * - * This is very similar to the ppc eieio/sync instruction in that is - * does a checkpoint syncronisation & makes sure that  - * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ). - */ - -#define eieio()	asm volatile("bcr 15,0" : : : "memory") -#define SYNC_OTHER_CORES(x)   eieio() -#define mb()    eieio() -#define rmb()   eieio() -#define wmb()   eieio() -#define read_barrier_depends() do { } while(0) -#define smp_mb()       mb() -#define smp_rmb()      rmb() -#define smp_wmb()      wmb() -#define smp_read_barrier_depends()    read_barrier_depends() -#define smp_mb__before_clear_bit()     smp_mb() -#define smp_mb__after_clear_bit()      smp_mb() - - -#define set_mb(var, value)      do { var = value; mb(); } while (0) - -#ifdef __s390x__ - -#define __ctl_load(array, low, high) ({				\ -	typedef struct { char _[sizeof(array)]; } addrtype;	\ -	asm volatile(						\ -		"	lctlg	%1,%2,%0\n"			\ -		: : "Q" (*(addrtype *)(&array)),		\ -		    "i" (low), "i" (high));			\ -	}) - -#define __ctl_store(array, low, high) ({			\ -	typedef struct { char _[sizeof(array)]; } addrtype;	\ -	asm volatile(						\ -		"	stctg	%1,%2,%0\n"			\ -		: "=Q" (*(addrtype *)(&array))			\ -		: "i" (low), "i" (high));			\ -	}) - -#else /* __s390x__ */ - -#define __ctl_load(array, low, high) ({				\ -	typedef struct { char _[sizeof(array)]; } addrtype;	\ -	asm volatile(						\ -		"	lctl	%1,%2,%0\n"			\ -		: : "Q" (*(addrtype *)(&array)),		\ -		    "i" (low), "i" (high));			\ -}) - -#define __ctl_store(array, low, high) ({			\ -	typedef struct { char _[sizeof(array)]; } addrtype;	\ -	asm volatile(						\ -		"	stctl	%1,%2,%0\n"			\ -		: "=Q" (*(addrtype *)(&array))			\ -		: "i" (low), "i" (high));			\ -	}) - -#endif /* __s390x__ */ - -#define __ctl_set_bit(cr, bit) ({	\ -	unsigned long __dummy;		\ -	__ctl_store(__dummy, cr, cr);	\ -	__dummy |= 1UL << (bit);	\ -	__ctl_load(__dummy, cr, cr);	\ -}) - -#define __ctl_clear_bit(cr, bit) ({	\ -	unsigned long __dummy;		\ -	__ctl_store(__dummy, cr, cr);	\ -	__dummy &= ~(1UL << (bit));	\ -	__ctl_load(__dummy, cr, cr);	\ -}) - -#include <linux/irqflags.h> - -#include <asm-generic/cmpxchg-local.h> - -static inline unsigned long __cmpxchg_local(volatile void *ptr, -				      unsigned long old, -				      unsigned long new, int size) -{ -	switch (size) { -	case 1: -	case 2: -	case 4: -#ifdef __s390x__ -	case 8: -#endif -		return __cmpxchg(ptr, old, new, size); -	default: -		return __cmpxchg_local_generic(ptr, old, new, size); -	} - -	return old; -} - -/* - * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make - * them available. - */ -#define cmpxchg_local(ptr, o, n)					\ -	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	\ -			(unsigned long)(n), sizeof(*(ptr)))) -#ifdef __s390x__ -#define cmpxchg64_local(ptr, o, n)					\ -  ({									\ -	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\ -	cmpxchg_local((ptr), (o), (n));					\ -  }) -#else -#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) -#endif - -/* - * 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) -#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK) - -#ifdef CONFIG_SMP - -extern void smp_ctl_set_bit(int cr, int bit); -extern void smp_ctl_clear_bit(int cr, int bit); -#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit) -#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit) - -#else - -#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit) -#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit) - -#endif /* CONFIG_SMP */ - -#define MAX_FACILITY_BIT (256*8)	/* stfle_fac_list has 256 bytes */ - -/* - * The test_facility function uses the bit odering where the MSB is bit 0. - * That makes it easier to query facility bits with the bit number as - * documented in the Principles of Operation. - */ -static inline int test_facility(unsigned long nr) -{ -	unsigned char *ptr; - -	if (nr >= MAX_FACILITY_BIT) -		return 0; -	ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3); -	return (*ptr & (0x80 >> (nr & 7))) != 0; -} - -static inline unsigned short stap(void) -{ -	unsigned short cpu_address; - -	asm volatile("stap %0" : "=m" (cpu_address)); -	return cpu_address; -} - -extern void (*_machine_restart)(char *command); -extern void (*_machine_halt)(void); -extern void (*_machine_power_off)(void); - -#define arch_align_stack(x) (x) - -static inline int tprot(unsigned long addr) -{ -	int rc = -EFAULT; - -	asm volatile( -		"	tprot	0(%1),0\n" -		"0:	ipm	%0\n" -		"	srl	%0,28\n" -		"1:\n" -		EX_TABLE(0b,1b) -		: "+d" (rc) : "a" (addr) : "cc"); -	return rc; -} - -#endif /* __KERNEL__ */ - -#endif diff --git a/arch/s390/include/asm/termios.h b/arch/s390/include/asm/termios.h index bc3a35cefc9..db028d17f06 100644 --- a/arch/s390/include/asm/termios.h +++ b/arch/s390/include/asm/termios.h @@ -1,53 +1,13 @@  /* - *  include/asm-s390/termios.h - *   *  S390 version   *   *  Derived from "include/asm-i386/termios.h"   */ -  #ifndef _S390_TERMIOS_H  #define _S390_TERMIOS_H -#include <asm/termbits.h> -#include <asm/ioctls.h> - -struct winsize { -	unsigned short ws_row; -	unsigned short ws_col; -	unsigned short ws_xpixel; -	unsigned short ws_ypixel; -}; - -#define NCC 8 -struct termio { -	unsigned short c_iflag;		/* input mode flags */ -	unsigned short c_oflag;		/* output mode flags */ -	unsigned short c_cflag;		/* control mode flags */ -	unsigned short c_lflag;		/* local mode flags */ -	unsigned char c_line;		/* line discipline */ -	unsigned char c_cc[NCC];	/* control characters */ -}; +#include <uapi/asm/termios.h> -/* modem lines */ -#define TIOCM_LE	0x001 -#define TIOCM_DTR	0x002 -#define TIOCM_RTS	0x004 -#define TIOCM_ST	0x008 -#define TIOCM_SR	0x010 -#define TIOCM_CTS	0x020 -#define TIOCM_CAR	0x040 -#define TIOCM_RNG	0x080 -#define TIOCM_DSR	0x100 -#define TIOCM_CD	TIOCM_CAR -#define TIOCM_RI	TIOCM_RNG -#define TIOCM_OUT1	0x2000 -#define TIOCM_OUT2	0x4000 -#define TIOCM_LOOP	0x8000 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -#ifdef __KERNEL__  /*	intr=^C		quit=^\		erase=del	kill=^U  	eof=^D		vtime=\0	vmin=\1		sxtc=\0 @@ -62,6 +22,4 @@ struct termio {  #include <asm-generic/termios-base.h> -#endif	/* __KERNEL__ */ -  #endif	/* _S390_TERMIOS_H */ diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 5baf0230b29..b833e9c0bfb 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -1,31 +1,22 @@  /* - *  include/asm-s390/thread_info.h - *   *  S390 version - *    Copyright (C) IBM Corp. 2002,2006 + *    Copyright IBM Corp. 2002, 2006   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   */  #ifndef _ASM_THREAD_INFO_H  #define _ASM_THREAD_INFO_H -#ifdef __KERNEL__ -  /*   * Size of kernel stack for each process   */ -#ifndef __s390x__ +#ifndef CONFIG_64BIT  #define THREAD_ORDER 1  #define ASYNC_ORDER  1 -#else /* __s390x__ */ -#ifndef __SMALL_STACK +#else /* CONFIG_64BIT */  #define THREAD_ORDER 2  #define ASYNC_ORDER  2 -#else -#define THREAD_ORDER 1 -#define ASYNC_ORDER  1 -#endif -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  #define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)  #define ASYNC_SIZE  (PAGE_SIZE << ASYNC_ORDER) @@ -45,9 +36,11 @@ struct thread_info {  	struct task_struct	*task;		/* main task structure */  	struct exec_domain	*exec_domain;	/* execution domain */  	unsigned long		flags;		/* low level flags */ +	unsigned long		sys_call_table;	/* System call table address */  	unsigned int		cpu;		/* current CPU */  	int			preempt_count;	/* 0 => preemptable, <0 => BUG */  	struct restart_block	restart_block; +	unsigned int		system_call;  	__u64			user_timer;  	__u64			system_timer;  	unsigned long		last_break;	/* last breaking-event-address. */ @@ -74,7 +67,7 @@ struct thread_info {  /* how to get the thread information struct from C */  static inline struct thread_info *current_thread_info(void)  { -	return (struct thread_info *)(S390_lowcore.kernel_stack - THREAD_SIZE); +	return (struct thread_info *) S390_lowcore.thread_info;  }  #define THREAD_SIZE_ORDER THREAD_ORDER @@ -84,40 +77,33 @@ static inline struct thread_info *current_thread_info(void)  /*   * thread information flags bit numbers   */ -#define TIF_NOTIFY_RESUME	1	/* callback before returning to user */ -#define TIF_SIGPENDING		2	/* signal pending */ -#define TIF_NEED_RESCHED	3	/* rescheduling necessary */ -#define TIF_RESTART_SVC		4	/* restart svc with new svc number */ -#define TIF_SINGLE_STEP		6	/* deliver sigtrap on return to user */ -#define TIF_MCCK_PENDING	7	/* machine check handling is pending */ -#define TIF_SYSCALL_TRACE	8	/* syscall trace active */ -#define TIF_SYSCALL_AUDIT	9	/* syscall auditing active */ -#define TIF_SECCOMP		10	/* secure computing */ -#define TIF_SYSCALL_TRACEPOINT	11	/* syscall tracepoint instrumentation */ -#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling -					   TIF_NEED_RESCHED */ -#define TIF_31BIT		17	/* 32bit process */ -#define TIF_MEMDIE		18	/* is terminating due to OOM killer */ -#define TIF_RESTORE_SIGMASK	19	/* restore signal mask in do_signal() */ -#define TIF_FREEZE		20	/* thread is freezing for suspend */ +#define TIF_NOTIFY_RESUME	0	/* callback before returning to user */ +#define TIF_SIGPENDING		1	/* signal pending */ +#define TIF_NEED_RESCHED	2	/* rescheduling necessary */ +#define TIF_SYSCALL_TRACE	3	/* syscall trace active */ +#define TIF_SYSCALL_AUDIT	4	/* syscall auditing active */ +#define TIF_SECCOMP		5	/* secure computing */ +#define TIF_SYSCALL_TRACEPOINT	6	/* syscall tracepoint instrumentation */ +#define TIF_31BIT		16	/* 32bit process */ +#define TIF_MEMDIE		17	/* is terminating due to OOM killer */ +#define TIF_RESTORE_SIGMASK	18	/* restore signal mask in do_signal() */ +#define TIF_SINGLE_STEP		19	/* This task is single stepped */ +#define TIF_BLOCK_STEP		20	/* This task is block stepped */  #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME) -#define _TIF_RESTORE_SIGMASK	(1<<TIF_RESTORE_SIGMASK)  #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)  #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED) -#define _TIF_RESTART_SVC	(1<<TIF_RESTART_SVC) -#define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP) -#define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)  #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)  #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)  #define _TIF_SECCOMP		(1<<TIF_SECCOMP)  #define _TIF_SYSCALL_TRACEPOINT	(1<<TIF_SYSCALL_TRACEPOINT) -#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)  #define _TIF_31BIT		(1<<TIF_31BIT) -#define _TIF_FREEZE		(1<<TIF_FREEZE) - -#endif /* __KERNEL__ */ +#define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP) -#define PREEMPT_ACTIVE		0x4000000 +#ifdef CONFIG_64BIT +#define is_32bit_task()		(test_thread_flag(TIF_31BIT)) +#else +#define is_32bit_task()		(1) +#endif  #endif /* _ASM_THREAD_INFO_H */ diff --git a/arch/s390/include/asm/timer.h b/arch/s390/include/asm/timer.h deleted file mode 100644 index 814243cafdf..00000000000 --- a/arch/s390/include/asm/timer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - *  include/asm-s390/timer.h - * - *  (C) Copyright IBM Corp. 2003,2006 - *  Virtual CPU timer - * - *  Author: Jan Glauber (jang@de.ibm.com) - */ - -#ifndef _ASM_S390_TIMER_H -#define _ASM_S390_TIMER_H - -#ifdef __KERNEL__ - -#include <linux/timer.h> - -#define VTIMER_MAX_SLICE (0x7ffffffffffff000LL) - -struct vtimer_list { -	struct list_head entry; - -	int cpu; -	__u64 expires; -	__u64 interval; - -	void (*function)(unsigned long); -	unsigned long data; -}; - -/* the vtimer value will wrap after ca. 71 years */ -struct vtimer_queue { -	struct list_head list; -	spinlock_t lock; -	__u64 timer;		/* last programmed timer */ -	__u64 elapsed;		/* elapsed time of timer expire values */ -	__u64 idle;		/* temp var for idle */ -	int do_spt;		/* =1: reprogram cpu timer in idle */ -}; - -extern void init_virt_timer(struct vtimer_list *timer); -extern void add_virt_timer(void *new); -extern void add_virt_timer_periodic(void *new); -extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); -extern int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires); -extern int del_virt_timer(struct vtimer_list *timer); - -extern void init_cpu_vtimer(void); -extern void vtime_init(void); - -extern void vtime_stop_cpu(void); -extern void vtime_start_leave(void); - -#endif /* __KERNEL__ */ - -#endif /* _ASM_S390_TIMER_H */ diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index 09d345a701d..8beee1cceba 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/timex.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *   *  Derived from "include/asm-i386/timex.h"   *    Copyright (C) 1992, Linus Torvalds @@ -11,11 +9,13 @@  #ifndef _ASM_S390_TIMEX_H  #define _ASM_S390_TIMEX_H +#include <asm/lowcore.h> +  /* The value of the TOD clock for 1.1.1970. */  #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL  /* Inline functions for clock register access. */ -static inline int set_clock(__u64 time) +static inline int set_tod_clock(__u64 time)  {  	int cc; @@ -27,7 +27,7 @@ static inline int set_clock(__u64 time)  	return cc;  } -static inline int store_clock(__u64 *time) +static inline int store_tod_clock(__u64 *time)  {  	int cc; @@ -49,33 +49,57 @@ static inline void store_clock_comparator(__u64 *time)  	asm volatile("stckc %0" : "=Q" (*time));  } +void clock_comparator_work(void); + +static inline unsigned long long local_tick_disable(void) +{ +	unsigned long long old; + +	old = S390_lowcore.clock_comparator; +	S390_lowcore.clock_comparator = -1ULL; +	set_clock_comparator(S390_lowcore.clock_comparator); +	return old; +} + +static inline void local_tick_enable(unsigned long long comp) +{ +	S390_lowcore.clock_comparator = comp; +	set_clock_comparator(S390_lowcore.clock_comparator); +} +  #define CLOCK_TICK_RATE	1193180 /* Underlying HZ */  typedef unsigned long long cycles_t; -static inline unsigned long long get_clock (void) +static inline void get_tod_clock_ext(char clk[16])  { -	unsigned long long clk; +	typedef struct { char _[sizeof(clk)]; } addrtype; -	asm volatile("stck %0" : "=Q" (clk) : : "cc"); -	return clk; +	asm volatile("stcke %0" : "=Q" (*(addrtype *) clk) : : "cc");  } -static inline void get_clock_ext(char *clk) +static inline unsigned long long get_tod_clock(void)  { -	asm volatile("stcke %0" : "=Q" (*clk) : : "cc"); +	unsigned char clk[16]; +	get_tod_clock_ext(clk); +	return *((unsigned long long *)&clk[1]);  } -static inline unsigned long long get_clock_xt(void) +static inline unsigned long long get_tod_clock_fast(void)  { -	unsigned char clk[16]; -	get_clock_ext(clk); -	return *((unsigned long long *)&clk[1]); +#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES +	unsigned long long clk; + +	asm volatile("stckf %0" : "=Q" (clk) : : "cc"); +	return clk; +#else +	return get_tod_clock(); +#endif  }  static inline cycles_t get_cycles(void)  { -	return (cycles_t) get_clock() >> 2; +	return (cycles_t) get_tod_clock() >> 2;  }  int get_sync_clock(unsigned long long *clock); @@ -101,9 +125,37 @@ extern u64 sched_clock_base_cc;   * function, otherwise the returned value is not guaranteed to   * be monotonic.   */ -static inline unsigned long long get_clock_monotonic(void) +static inline unsigned long long get_tod_clock_monotonic(void)  { -	return get_clock_xt() - sched_clock_base_cc; +	return get_tod_clock() - sched_clock_base_cc; +} + +/** + * tod_to_ns - convert a TOD format value to nanoseconds + * @todval: to be converted TOD format value + * Returns: number of nanoseconds that correspond to the TOD format value + * + * Converting a 64 Bit TOD format value to nanoseconds means that the value + * must be divided by 4.096. In order to achieve that we multiply with 125 + * and divide by 512: + * + *    ns = (todval * 125) >> 9; + * + * In order to avoid an overflow with the multiplication we can rewrite this. + * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) + * we end up with + * + *    ns = ((2^32 * th + tl) * 125 ) >> 9; + * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); + * + */ +static inline unsigned long long tod_to_ns(unsigned long long todval) +{ +	unsigned long long ns; + +	ns = ((todval >> 32) << 23) * 125; +	ns += ((todval & 0xffffffff) * 125) >> 9; +	return ns;  }  #endif diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h index f1f644f2240..a25f09fbaf3 100644 --- a/arch/s390/include/asm/tlb.h +++ b/arch/s390/include/asm/tlb.h @@ -22,71 +22,77 @@   */  #include <linux/mm.h> +#include <linux/pagemap.h>  #include <linux/swap.h>  #include <asm/processor.h>  #include <asm/pgalloc.h> -#include <asm/smp.h>  #include <asm/tlbflush.h> -#ifndef CONFIG_SMP -#define TLB_NR_PTRS	1 -#else -#define TLB_NR_PTRS	508 -#endif -  struct mmu_gather {  	struct mm_struct *mm; +	struct mmu_table_batch *batch;  	unsigned int fullmm; -	unsigned int nr_ptes; -	unsigned int nr_pxds; -	void *array[TLB_NR_PTRS]; +	unsigned long start, end;  }; -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); +struct mmu_table_batch { +	struct rcu_head		rcu; +	unsigned int		nr; +	void			*tables[0]; +}; -static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm, -						unsigned int full_mm_flush) -{ -	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); +#define MAX_TABLE_BATCH		\ +	((PAGE_SIZE - sizeof(struct mmu_table_batch)) / sizeof(void *)) + +extern void tlb_table_flush(struct mmu_gather *tlb); +extern void tlb_remove_table(struct mmu_gather *tlb, void *table); +static inline void tlb_gather_mmu(struct mmu_gather *tlb, +				  struct mm_struct *mm, +				  unsigned long start, +				  unsigned long end) +{  	tlb->mm = mm; -	tlb->fullmm = full_mm_flush; -	tlb->nr_ptes = 0; -	tlb->nr_pxds = TLB_NR_PTRS; -	if (tlb->fullmm) -		__tlb_flush_mm(mm); -	return tlb; +	tlb->start = start; +	tlb->end = end; +	tlb->fullmm = !(start | (end+1)); +	tlb->batch = NULL;  } -static inline void tlb_flush_mmu(struct mmu_gather *tlb, -				 unsigned long start, unsigned long end) +static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)  { -	if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pxds < TLB_NR_PTRS)) -		__tlb_flush_mm(tlb->mm); -	while (tlb->nr_ptes > 0) -		page_table_free_rcu(tlb->mm, tlb->array[--tlb->nr_ptes]); -	while (tlb->nr_pxds < TLB_NR_PTRS) -		crst_table_free_rcu(tlb->mm, tlb->array[tlb->nr_pxds++]); +	__tlb_flush_mm_lazy(tlb->mm);  } -static inline void tlb_finish_mmu(struct mmu_gather *tlb, -				  unsigned long start, unsigned long end) +static inline void tlb_flush_mmu_free(struct mmu_gather *tlb)  { -	tlb_flush_mmu(tlb, start, end); +	tlb_table_flush(tlb); +} -	rcu_table_freelist_finish(); -	/* keep the page table cache within bounds */ -	check_pgt_cache(); +static inline void tlb_flush_mmu(struct mmu_gather *tlb) +{ +	tlb_flush_mmu_tlbonly(tlb); +	tlb_flush_mmu_free(tlb); +} -	put_cpu_var(mmu_gathers); +static inline void tlb_finish_mmu(struct mmu_gather *tlb, +				  unsigned long start, unsigned long end) +{ +	tlb_flush_mmu(tlb);  }  /*   * Release the page cache reference for a pte removed by - * tlb_ptep_clear_flush. In both flush modes the tlb fo a page cache page + * tlb_ptep_clear_flush. In both flush modes the tlb for a page cache page   * has already been freed, so just do free_page_and_swap_cache.   */ +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ +	free_page_and_swap_cache(page); +	return 1; /* avoid calling tlb_flush_mmu */ +} +  static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)  {  	free_page_and_swap_cache(page); @@ -99,12 +105,7 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)  static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,  				unsigned long address)  { -	if (!tlb->fullmm) { -		tlb->array[tlb->nr_ptes++] = pte; -		if (tlb->nr_ptes >= tlb->nr_pxds) -			tlb_flush_mmu(tlb, 0, 0); -	} else -		page_table_free(tlb->mm, (unsigned long *) pte); +	page_table_free_rcu(tlb, (unsigned long *) pte);  }  /* @@ -117,15 +118,10 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,  static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,  				unsigned long address)  { -#ifdef __s390x__ +#ifdef CONFIG_64BIT  	if (tlb->mm->context.asce_limit <= (1UL << 31))  		return; -	if (!tlb->fullmm) { -		tlb->array[--tlb->nr_pxds] = pmd; -		if (tlb->nr_ptes >= tlb->nr_pxds) -			tlb_flush_mmu(tlb, 0, 0); -	} else -		crst_table_free(tlb->mm, (unsigned long *) pmd); +	tlb_remove_table(tlb, pmd);  #endif  } @@ -139,21 +135,17 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,  static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,  				unsigned long address)  { -#ifdef __s390x__ +#ifdef CONFIG_64BIT  	if (tlb->mm->context.asce_limit <= (1UL << 42))  		return; -	if (!tlb->fullmm) { -		tlb->array[--tlb->nr_pxds] = pud; -		if (tlb->nr_ptes >= tlb->nr_pxds) -			tlb_flush_mmu(tlb, 0, 0); -	} else -		crst_table_free(tlb->mm, (unsigned long *) pud); +	tlb_remove_table(tlb, pud);  #endif  }  #define tlb_start_vma(tlb, vma)			do { } while (0)  #define tlb_end_vma(tlb, vma)			do { } while (0)  #define tlb_remove_tlb_entry(tlb, ptep, addr)	do { } while (0) +#define tlb_remove_pmd_tlb_entry(tlb, pmdp, addr)	do { } while (0)  #define tlb_migrate_finish(mm)			do { } while (0)  #endif /* _S390_TLB_H */ diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index 29d5d6d4bec..16c9c88658c 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h @@ -7,19 +7,41 @@  #include <asm/pgalloc.h>  /* - * Flush all tlb entries on the local cpu. + * Flush all TLB entries on the local CPU.   */  static inline void __tlb_flush_local(void)  {  	asm volatile("ptlb" : : : "memory");  } -#ifdef CONFIG_SMP  /* - * Flush all tlb entries on all cpus. + * Flush TLB entries for a specific ASCE on all CPUs + */ +static inline void __tlb_flush_idte(unsigned long asce) +{ +	/* Global TLB flush for the mm */ +	asm volatile( +		"	.insn	rrf,0xb98e0000,0,%0,%1,0" +		: : "a" (2048), "a" (asce) : "cc"); +} + +/* + * Flush TLB entries for a specific ASCE on the local CPU   */ +static inline void __tlb_flush_idte_local(unsigned long asce) +{ +	/* Local TLB flush for the mm */ +	asm volatile( +		"	.insn	rrf,0xb98e0000,0,%0,%1,1" +		: : "a" (2048), "a" (asce) : "cc"); +} + +#ifdef CONFIG_SMP  void smp_ptlb_all(void); +/* + * Flush all TLB entries on all CPUs. + */  static inline void __tlb_flush_global(void)  {  	register unsigned long reg2 asm("2"); @@ -27,12 +49,12 @@ static inline void __tlb_flush_global(void)  	register unsigned long reg4 asm("4");  	long dummy; -#ifndef __s390x__ +#ifndef CONFIG_64BIT  	if (!MACHINE_HAS_CSP) {  		smp_ptlb_all();  		return;  	} -#endif /* __s390x__ */ +#endif /* CONFIG_64BIT */  	dummy = 0;  	reg2 = reg3 = 0; @@ -42,64 +64,109 @@ static inline void __tlb_flush_global(void)  		: : "d" (reg2), "d" (reg3), "d" (reg4), "m" (dummy) : "cc" );  } +/* + * Flush TLB entries for a specific mm on all CPUs (in case gmap is used + * this implicates multiple ASCEs!). + */  static inline void __tlb_flush_full(struct mm_struct *mm)  { -	cpumask_t local_cpumask; -  	preempt_disable(); -	/* -	 * If the process only ran on the local cpu, do a local flush. -	 */ -	local_cpumask = cpumask_of_cpu(smp_processor_id()); -	if (cpumask_equal(mm_cpumask(mm), &local_cpumask)) +	atomic_add(0x10000, &mm->context.attach_count); +	if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { +		/* Local TLB flush */  		__tlb_flush_local(); -	else +	} else { +		/* Global TLB flush */  		__tlb_flush_global(); +		/* Reset TLB flush mask */ +		if (MACHINE_HAS_TLB_LC) +			cpumask_copy(mm_cpumask(mm), +				     &mm->context.cpu_attach_mask); +	} +	atomic_sub(0x10000, &mm->context.attach_count);  	preempt_enable();  } + +/* + * Flush TLB entries for a specific ASCE on all CPUs. + */ +static inline void __tlb_flush_asce(struct mm_struct *mm, unsigned long asce) +{ +	int active, count; + +	preempt_disable(); +	active = (mm == current->active_mm) ? 1 : 0; +	count = atomic_add_return(0x10000, &mm->context.attach_count); +	if (MACHINE_HAS_TLB_LC && (count & 0xffff) <= active && +	    cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { +		__tlb_flush_idte_local(asce); +	} else { +		if (MACHINE_HAS_IDTE) +			__tlb_flush_idte(asce); +		else +			__tlb_flush_global(); +		/* Reset TLB flush mask */ +		if (MACHINE_HAS_TLB_LC) +			cpumask_copy(mm_cpumask(mm), +				     &mm->context.cpu_attach_mask); +	} +	atomic_sub(0x10000, &mm->context.attach_count); +	preempt_enable(); +} + +static inline void __tlb_flush_kernel(void) +{ +	if (MACHINE_HAS_IDTE) +		__tlb_flush_idte((unsigned long) init_mm.pgd | +				 init_mm.context.asce_bits); +	else +		__tlb_flush_global(); +}  #else +#define __tlb_flush_global()	__tlb_flush_local()  #define __tlb_flush_full(mm)	__tlb_flush_local() -#endif  /* - * Flush all tlb entries of a page table on all cpus. + * Flush TLB entries for a specific ASCE on all CPUs.   */ -static inline void __tlb_flush_idte(unsigned long asce) +static inline void __tlb_flush_asce(struct mm_struct *mm, unsigned long asce)  { -	asm volatile( -		"	.insn	rrf,0xb98e0000,0,%0,%1,0" -		: : "a" (2048), "a" (asce) : "cc" ); +	if (MACHINE_HAS_TLB_LC) +		__tlb_flush_idte_local(asce); +	else +		__tlb_flush_local();  } +static inline void __tlb_flush_kernel(void) +{ +	if (MACHINE_HAS_TLB_LC) +		__tlb_flush_idte_local((unsigned long) init_mm.pgd | +				       init_mm.context.asce_bits); +	else +		__tlb_flush_local(); +} +#endif +  static inline void __tlb_flush_mm(struct mm_struct * mm)  { -	if (unlikely(cpumask_empty(mm_cpumask(mm)))) -		return;  	/*  	 * If the machine has IDTE we prefer to do a per mm flush  	 * on all cpus instead of doing a local flush if the mm  	 * only ran on the local cpu.  	 */ -	if (MACHINE_HAS_IDTE) { -		if (mm->context.noexec) -			__tlb_flush_idte((unsigned long) -					 get_shadow_table(mm->pgd) | -					 mm->context.asce_bits); -		__tlb_flush_idte((unsigned long) mm->pgd | +	if (MACHINE_HAS_IDTE && list_empty(&mm->context.gmap_list)) +		__tlb_flush_asce(mm, (unsigned long) mm->pgd |  				 mm->context.asce_bits); -		return; -	} -	__tlb_flush_full(mm); +	else +		__tlb_flush_full(mm);  } -static inline void __tlb_flush_mm_cond(struct mm_struct * mm) +static inline void __tlb_flush_mm_lazy(struct mm_struct * mm)  { -	spin_lock(&mm->page_table_lock);  	if (mm->context.flush_mm) {  		__tlb_flush_mm(mm);  		mm->context.flush_mm = 0;  	} -	spin_unlock(&mm->page_table_lock);  }  /* @@ -126,19 +193,19 @@ static inline void __tlb_flush_mm_cond(struct mm_struct * mm)  static inline void flush_tlb_mm(struct mm_struct *mm)  { -	__tlb_flush_mm_cond(mm); +	__tlb_flush_mm_lazy(mm);  }  static inline void flush_tlb_range(struct vm_area_struct *vma,  				   unsigned long start, unsigned long end)  { -	__tlb_flush_mm_cond(vma->vm_mm); +	__tlb_flush_mm_lazy(vma->vm_mm);  }  static inline void flush_tlb_kernel_range(unsigned long start,  					  unsigned long end)  { -	__tlb_flush_mm(&init_mm); +	__tlb_flush_kernel();  }  #endif /* _S390_TLBFLUSH_H */ diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index c5338834ddb..56af53093d2 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h @@ -2,46 +2,52 @@  #define _ASM_S390_TOPOLOGY_H  #include <linux/cpumask.h> -#include <asm/sysinfo.h> -extern unsigned char cpu_core_id[NR_CPUS]; -extern cpumask_t cpu_core_map[NR_CPUS]; - -static inline const struct cpumask *cpu_coregroup_mask(unsigned int cpu) -{ -	return &cpu_core_map[cpu]; -} - -#define topology_core_id(cpu)		(cpu_core_id[cpu]) -#define topology_core_cpumask(cpu)	(&cpu_core_map[cpu]) -#define mc_capable()			(1) +struct sysinfo_15_1_x; +struct cpu;  #ifdef CONFIG_SCHED_BOOK -extern unsigned char cpu_book_id[NR_CPUS]; -extern cpumask_t cpu_book_map[NR_CPUS]; +struct cpu_topology_s390 { +	unsigned short core_id; +	unsigned short socket_id; +	unsigned short book_id; +	cpumask_t core_mask; +	cpumask_t book_mask; +}; -static inline const struct cpumask *cpu_book_mask(unsigned int cpu) -{ -	return &cpu_book_map[cpu]; -} +extern struct cpu_topology_s390 cpu_topology[NR_CPUS]; -#define topology_book_id(cpu)		(cpu_book_id[cpu]) -#define topology_book_cpumask(cpu)	(&cpu_book_map[cpu]) +#define topology_physical_package_id(cpu)	(cpu_topology[cpu].socket_id) +#define topology_core_id(cpu)			(cpu_topology[cpu].core_id) +#define topology_core_cpumask(cpu)		(&cpu_topology[cpu].core_mask) +#define topology_book_id(cpu)			(cpu_topology[cpu].book_id) +#define topology_book_cpumask(cpu)		(&cpu_topology[cpu].book_mask) -#endif /* CONFIG_SCHED_BOOK */ +#define mc_capable() 1 +int topology_cpu_init(struct cpu *);  int topology_set_cpu_management(int fc);  void topology_schedule_update(void);  void store_topology(struct sysinfo_15_1_x *info); +void topology_expect_change(void); +const struct cpumask *cpu_coregroup_mask(int cpu); -#define POLARIZATION_UNKNWN	(-1) +#else /* CONFIG_SCHED_BOOK */ + +static inline void topology_schedule_update(void) { } +static inline int topology_cpu_init(struct cpu *cpu) { return 0; } +static inline void topology_expect_change(void) { } + +#endif /* CONFIG_SCHED_BOOK */ + +#define POLARIZATION_UNKNOWN	(-1)  #define POLARIZATION_HRZ	(0)  #define POLARIZATION_VL		(1)  #define POLARIZATION_VM		(2)  #define POLARIZATION_VH		(3) -#ifdef CONFIG_SMP +#ifdef CONFIG_SCHED_BOOK  void s390_init_cpu_topology(void);  #else  static inline void s390_init_cpu_topology(void) @@ -49,8 +55,6 @@ static inline void s390_init_cpu_topology(void)  };  #endif -#define SD_BOOK_INIT	SD_CPU_INIT -  #include <asm-generic/topology.h>  #endif /* _ASM_S390_TOPOLOGY_H */ diff --git a/arch/s390/include/asm/types.h b/arch/s390/include/asm/types.h index 04d6b95a89c..dccef3ca91f 100644 --- a/arch/s390/include/asm/types.h +++ b/arch/s390/include/asm/types.h @@ -1,44 +1,20 @@  /* - *  include/asm-s390/types.h - *   *  S390 version   *   *  Derived from "include/asm-i386/types.h"   */ -  #ifndef _S390_TYPES_H  #define _S390_TYPES_H -#include <asm-generic/int-ll64.h> - -#ifndef __ASSEMBLY__ - -typedef unsigned short umode_t; - -/* A address type so that arithmetic can be done on it & it can be upgraded to -   64 bit when necessary  -*/ -typedef unsigned long addr_t;  -typedef __signed__ long saddr_t; - -#endif /* __ASSEMBLY__ */ +#include <uapi/asm/types.h>  /*   * These aren't exported outside the kernel to avoid name space clashes   */ -#ifdef __KERNEL__  #ifndef __ASSEMBLY__ -typedef u64 dma64_addr_t; -#ifdef __s390x__ -/* DMA addresses come in 32-bit and 64-bit flavours. */ -typedef u64 dma_addr_t; -#else -typedef u32 dma_addr_t; -#endif - -#ifndef __s390x__ +#ifndef CONFIG_64BIT  typedef union {  	unsigned long long pair;  	struct { @@ -47,7 +23,6 @@ typedef union {  	} subreg;  } register_pair; -#endif /* ! __s390x__   */ +#endif /* ! CONFIG_64BIT   */  #endif /* __ASSEMBLY__  */ -#endif /* __KERNEL__    */  #endif /* _S390_TYPES_H */ diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index d6b1ed0ec52..cd4c68e0398 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/uaccess.h - *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999, 2000   *    Author(s): Hartmut Penner (hp@de.ibm.com),   *               Martin Schwidefsky (schwidefsky@de.ibm.com)   * @@ -16,6 +14,7 @@   */  #include <linux/sched.h>  #include <linux/errno.h> +#include <asm/ctl_reg.h>  #define VERIFY_READ     0  #define VERIFY_WRITE    1 @@ -49,12 +48,18 @@  #define segment_eq(a,b) ((a).ar4 == (b).ar4) - -static inline int __access_ok(const void __user *addr, unsigned long size) +static inline int __range_ok(unsigned long addr, unsigned long size)  {  	return 1;  } -#define access_ok(type,addr,size) __access_ok(addr,size) + +#define __access_ok(addr, size)				\ +({							\ +	__chk_user_ptr(addr);				\ +	__range_ok((unsigned long)(addr), (size));	\ +}) + +#define access_ok(type, addr, size) __access_ok(addr, size)  /*   * The exception table consists of pairs of addresses: the first is the @@ -71,42 +76,104 @@ static inline int __access_ok(const void __user *addr, unsigned long size)  struct exception_table_entry  { -        unsigned long insn, fixup; +	int insn, fixup;  }; -struct uaccess_ops { -	size_t (*copy_from_user)(size_t, const void __user *, void *); -	size_t (*copy_from_user_small)(size_t, const void __user *, void *); -	size_t (*copy_to_user)(size_t, void __user *, const void *); -	size_t (*copy_to_user_small)(size_t, void __user *, const void *); -	size_t (*copy_in_user)(size_t, void __user *, const void __user *); -	size_t (*clear_user)(size_t, void __user *); -	size_t (*strnlen_user)(size_t, const char __user *); -	size_t (*strncpy_from_user)(size_t, const char __user *, char *); -	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old); -	int (*futex_atomic_cmpxchg)(int __user *, int old, int new); -}; +static inline unsigned long extable_insn(const struct exception_table_entry *x) +{ +	return (unsigned long)&x->insn + x->insn; +} + +static inline unsigned long extable_fixup(const struct exception_table_entry *x) +{ +	return (unsigned long)&x->fixup + x->fixup; +} + +#define ARCH_HAS_SORT_EXTABLE +#define ARCH_HAS_SEARCH_EXTABLE + +/** + * __copy_from_user: - Copy a block of data from user space, with less checking. + * @to:   Destination address, in kernel space. + * @from: Source address, in user space. + * @n:	  Number of bytes to copy. + * + * Context: User context only.	This function may sleep. + * + * Copy data from user space to kernel space.  Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + * + * If some data could not be copied, this function will pad the copied + * data to the requested size using zero bytes. + */ +unsigned long __must_check __copy_from_user(void *to, const void __user *from, +					    unsigned long n); + +/** + * __copy_to_user: - Copy a block of data into user space, with less checking. + * @to:   Destination address, in user space. + * @from: Source address, in kernel space. + * @n:	  Number of bytes to copy. + * + * Context: User context only.	This function may sleep. + * + * Copy data from kernel space to user space.  Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be copied. + * On success, this will be zero. + */ +unsigned long __must_check __copy_to_user(void __user *to, const void *from, +					  unsigned long n); -extern struct uaccess_ops uaccess; -extern struct uaccess_ops uaccess_std; -extern struct uaccess_ops uaccess_mvcos; -extern struct uaccess_ops uaccess_mvcos_switch; -extern struct uaccess_ops uaccess_pt; +#define __copy_to_user_inatomic __copy_to_user +#define __copy_from_user_inatomic __copy_from_user -extern int __handle_fault(unsigned long, unsigned long, int); +#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES + +#define __put_get_user_asm(to, from, size, spec)		\ +({								\ +	register unsigned long __reg0 asm("0") = spec;		\ +	int __rc;						\ +								\ +	asm volatile(						\ +		"0:	mvcos	%1,%3,%2\n"			\ +		"1:	xr	%0,%0\n"			\ +		"2:\n"						\ +		".pushsection .fixup, \"ax\"\n"			\ +		"3:	lhi	%0,%5\n"			\ +		"	jg	2b\n"				\ +		".popsection\n"					\ +		EX_TABLE(0b,3b) EX_TABLE(1b,3b)			\ +		: "=d" (__rc), "=Q" (*(to))			\ +		: "d" (size), "Q" (*(from)),			\ +		  "d" (__reg0), "K" (-EFAULT)			\ +		: "cc");					\ +	__rc;							\ +}) -static inline int __put_user_fn(size_t size, void __user *ptr, void *x) +#define __put_user_fn(x, ptr, size) __put_get_user_asm(ptr, x, size, 0x810000UL) +#define __get_user_fn(x, ptr, size) __put_get_user_asm(x, ptr, size, 0x81UL) + +#else /* CONFIG_HAVE_MARCH_Z10_FEATURES */ + +static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size)  { -	size = uaccess.copy_to_user_small(size, ptr, x); -	return size ? -EFAULT : size; +	size = __copy_to_user(ptr, x, size); +	return size ? -EFAULT : 0;  } -static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) +static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size)  { -	size = uaccess.copy_from_user_small(size, ptr, x); -	return size ? -EFAULT : size; +	size = __copy_from_user(x, ptr, size); +	return size ? -EFAULT : 0;  } +#endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */ +  /*   * These are the main single-value transfer routines.  They automatically   * use the right size if we just have the right pointer type. @@ -121,8 +188,8 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)  	case 2:							\  	case 4:							\  	case 8:							\ -		__pu_err = __put_user_fn(sizeof (*(ptr)),	\ -					 ptr, &__x);		\ +		__pu_err = __put_user_fn(&__x, ptr,		\ +					 sizeof(*(ptr)));	\  		break;						\  	default:						\  		__put_user_bad();				\ @@ -138,7 +205,7 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)  }) -extern int __put_user_bad(void) __attribute__((noreturn)); +int __put_user_bad(void) __attribute__((noreturn));  #define __get_user(x, ptr)					\  ({								\ @@ -147,29 +214,29 @@ extern int __put_user_bad(void) __attribute__((noreturn));  	switch (sizeof(*(ptr))) {				\  	case 1: {						\  		unsigned char __x;				\ -		__gu_err = __get_user_fn(sizeof (*(ptr)),	\ -					 ptr, &__x);		\ +		__gu_err = __get_user_fn(&__x, ptr,		\ +					 sizeof(*(ptr)));	\  		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\  		break;						\  	};							\  	case 2: {						\  		unsigned short __x;				\ -		__gu_err = __get_user_fn(sizeof (*(ptr)),	\ -					 ptr, &__x);		\ +		__gu_err = __get_user_fn(&__x, ptr,		\ +					 sizeof(*(ptr)));	\  		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\  		break;						\  	};							\  	case 4: {						\  		unsigned int __x;				\ -		__gu_err = __get_user_fn(sizeof (*(ptr)),	\ -					 ptr, &__x);		\ +		__gu_err = __get_user_fn(&__x, ptr,		\ +					 sizeof(*(ptr)));	\  		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\  		break;						\  	};							\  	case 8: {						\  		unsigned long long __x;				\ -		__gu_err = __get_user_fn(sizeof (*(ptr)),	\ -					 ptr, &__x);		\ +		__gu_err = __get_user_fn(&__x, ptr,		\ +					 sizeof(*(ptr)));	\  		(x) = *(__force __typeof__(*(ptr)) *) &__x;	\  		break;						\  	};							\ @@ -186,38 +253,12 @@ extern int __put_user_bad(void) __attribute__((noreturn));  	__get_user(x, ptr);					\  }) -extern int __get_user_bad(void) __attribute__((noreturn)); +int __get_user_bad(void) __attribute__((noreturn));  #define __put_user_unaligned __put_user  #define __get_user_unaligned __get_user  /** - * __copy_to_user: - Copy a block of data into user space, with less checking. - * @to:   Destination address, in user space. - * @from: Source address, in kernel space. - * @n:    Number of bytes to copy. - * - * Context: User context only.  This function may sleep. - * - * Copy data from kernel space to user space.  Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - */ -static inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) -{ -	if (__builtin_constant_p(n) && (n <= 256)) -		return uaccess.copy_to_user_small(n, to, from); -	else -		return uaccess.copy_to_user(n, to, from); -} - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -/**   * copy_to_user: - Copy a block of data into user space.   * @to:   Destination address, in user space.   * @from: Source address, in kernel space. @@ -234,38 +275,10 @@ static inline unsigned long __must_check  copy_to_user(void __user *to, const void *from, unsigned long n)  {  	might_fault(); -	if (access_ok(VERIFY_WRITE, to, n)) -		n = __copy_to_user(to, from, n); -	return n; +	return __copy_to_user(to, from, n);  } -/** - * __copy_from_user: - Copy a block of data from user space, with less checking. - * @to:   Destination address, in kernel space. - * @from: Source address, in user space. - * @n:    Number of bytes to copy. - * - * Context: User context only.  This function may sleep. - * - * Copy data from user space to kernel space.  Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be copied. - * On success, this will be zero. - * - * If some data could not be copied, this function will pad the copied - * data to the requested size using zero bytes. - */ -static inline unsigned long __must_check -__copy_from_user(void *to, const void __user *from, unsigned long n) -{ -	if (__builtin_constant_p(n) && (n <= 256)) -		return uaccess.copy_from_user_small(n, from, to); -	else -		return uaccess.copy_from_user(n, from, to); -} - -extern void copy_from_user_overflow(void) +void copy_from_user_overflow(void)  #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS  __compiletime_warning("copy_from_user() buffer size is not provably correct")  #endif @@ -297,46 +310,38 @@ copy_from_user(void *to, const void __user *from, unsigned long n)  		copy_from_user_overflow();  		return n;  	} -	if (access_ok(VERIFY_READ, from, n)) -		n = __copy_from_user(to, from, n); -	else -		memset(to, 0, n); -	return n; +	return __copy_from_user(to, from, n);  } -static inline unsigned long __must_check -__copy_in_user(void __user *to, const void __user *from, unsigned long n) -{ -	return uaccess.copy_in_user(n, to, from); -} +unsigned long __must_check +__copy_in_user(void __user *to, const void __user *from, unsigned long n);  static inline unsigned long __must_check  copy_in_user(void __user *to, const void __user *from, unsigned long n)  {  	might_fault(); -	if (__access_ok(from,n) && __access_ok(to,n)) -		n = __copy_in_user(to, from, n); -	return n; +	return __copy_in_user(to, from, n);  }  /*   * Copy a null terminated string from userspace.   */ + +long __strncpy_from_user(char *dst, const char __user *src, long count); +  static inline long __must_check  strncpy_from_user(char *dst, const char __user *src, long count)  { -        long res = -EFAULT;  	might_fault(); -        if (access_ok(VERIFY_READ, src, 1)) -		res = uaccess.strncpy_from_user(count, src, dst); -        return res; +	return __strncpy_from_user(dst, src, count);  } -static inline unsigned long -strnlen_user(const char __user * src, unsigned long n) +unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count); + +static inline unsigned long strnlen_user(const char __user *src, unsigned long n)  {  	might_fault(); -	return uaccess.strnlen_user(n, src); +	return __strnlen_user(src, n);  }  /** @@ -358,20 +363,14 @@ strnlen_user(const char __user * src, unsigned long n)  /*   * Zero Userspace   */ +unsigned long __must_check __clear_user(void __user *to, unsigned long size); -static inline unsigned long __must_check -__clear_user(void __user *to, unsigned long n) -{ -	return uaccess.clear_user(n, to); -} - -static inline unsigned long __must_check -clear_user(void __user *to, unsigned long n) +static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)  {  	might_fault(); -	if (access_ok(VERIFY_WRITE, to, n)) -		n = uaccess.clear_user(n, to); -	return n; +	return __clear_user(to, n);  } +int copy_to_user_real(void __user *dest, void *src, unsigned long count); +  #endif /* __S390_UACCESS_H */ diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 1049ef27c15..65188635355 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h @@ -1,370 +1,13 @@  /* - *  include/asm-s390/unistd.h - *   *  S390 version   *   *  Derived from "include/asm-i386/unistd.h"   */ -  #ifndef _ASM_S390_UNISTD_H_  #define _ASM_S390_UNISTD_H_ -/* - * This file contains the system call numbers. - */ - -#define __NR_exit                 1 -#define __NR_fork                 2 -#define __NR_read                 3 -#define __NR_write                4 -#define __NR_open                 5 -#define __NR_close                6 -#define __NR_restart_syscall	  7 -#define __NR_creat                8 -#define __NR_link                 9 -#define __NR_unlink              10 -#define __NR_execve              11 -#define __NR_chdir               12 -#define __NR_mknod               14 -#define __NR_chmod               15 -#define __NR_lseek               19 -#define __NR_getpid              20 -#define __NR_mount               21 -#define __NR_umount              22 -#define __NR_ptrace              26 -#define __NR_alarm               27 -#define __NR_pause               29 -#define __NR_utime               30 -#define __NR_access              33 -#define __NR_nice                34 -#define __NR_sync                36 -#define __NR_kill                37 -#define __NR_rename              38 -#define __NR_mkdir               39 -#define __NR_rmdir               40 -#define __NR_dup                 41 -#define __NR_pipe                42 -#define __NR_times               43 -#define __NR_brk                 45 -#define __NR_signal              48 -#define __NR_acct                51 -#define __NR_umount2             52 -#define __NR_ioctl               54 -#define __NR_fcntl               55 -#define __NR_setpgid             57 -#define __NR_umask               60 -#define __NR_chroot              61 -#define __NR_ustat               62 -#define __NR_dup2                63 -#define __NR_getppid             64 -#define __NR_getpgrp             65 -#define __NR_setsid              66 -#define __NR_sigaction           67 -#define __NR_sigsuspend          72 -#define __NR_sigpending          73 -#define __NR_sethostname         74 -#define __NR_setrlimit           75 -#define __NR_getrusage           77 -#define __NR_gettimeofday        78 -#define __NR_settimeofday        79 -#define __NR_symlink             83 -#define __NR_readlink            85 -#define __NR_uselib              86 -#define __NR_swapon              87 -#define __NR_reboot              88 -#define __NR_readdir             89 -#define __NR_mmap                90 -#define __NR_munmap              91 -#define __NR_truncate            92 -#define __NR_ftruncate           93 -#define __NR_fchmod              94 -#define __NR_getpriority         96 -#define __NR_setpriority         97 -#define __NR_statfs              99 -#define __NR_fstatfs            100 -#define __NR_socketcall         102 -#define __NR_syslog             103 -#define __NR_setitimer          104 -#define __NR_getitimer          105 -#define __NR_stat               106 -#define __NR_lstat              107 -#define __NR_fstat              108 -#define __NR_lookup_dcookie     110 -#define __NR_vhangup            111 -#define __NR_idle               112 -#define __NR_wait4              114 -#define __NR_swapoff            115 -#define __NR_sysinfo            116 -#define __NR_ipc                117 -#define __NR_fsync              118 -#define __NR_sigreturn          119 -#define __NR_clone              120 -#define __NR_setdomainname      121 -#define __NR_uname              122 -#define __NR_adjtimex           124 -#define __NR_mprotect           125 -#define __NR_sigprocmask        126 -#define __NR_create_module      127 -#define __NR_init_module        128 -#define __NR_delete_module      129 -#define __NR_get_kernel_syms    130 -#define __NR_quotactl           131 -#define __NR_getpgid            132 -#define __NR_fchdir             133 -#define __NR_bdflush            134 -#define __NR_sysfs              135 -#define __NR_personality        136 -#define __NR_afs_syscall        137 /* Syscall for Andrew File System */ -#define __NR_getdents           141 -#define __NR_flock              143 -#define __NR_msync              144 -#define __NR_readv              145 -#define __NR_writev             146 -#define __NR_getsid             147 -#define __NR_fdatasync          148 -#define __NR__sysctl            149 -#define __NR_mlock              150 -#define __NR_munlock            151 -#define __NR_mlockall           152 -#define __NR_munlockall         153 -#define __NR_sched_setparam             154 -#define __NR_sched_getparam             155 -#define __NR_sched_setscheduler         156 -#define __NR_sched_getscheduler         157 -#define __NR_sched_yield                158 -#define __NR_sched_get_priority_max     159 -#define __NR_sched_get_priority_min     160 -#define __NR_sched_rr_get_interval      161 -#define __NR_nanosleep          162 -#define __NR_mremap             163 -#define __NR_query_module       167 -#define __NR_poll               168 -#define __NR_nfsservctl         169 -#define __NR_prctl              172 -#define __NR_rt_sigreturn       173 -#define __NR_rt_sigaction       174 -#define __NR_rt_sigprocmask     175 -#define __NR_rt_sigpending      176 -#define __NR_rt_sigtimedwait    177 -#define __NR_rt_sigqueueinfo    178 -#define __NR_rt_sigsuspend      179 -#define __NR_pread64            180 -#define __NR_pwrite64           181 -#define __NR_getcwd             183 -#define __NR_capget             184 -#define __NR_capset             185 -#define __NR_sigaltstack        186 -#define __NR_sendfile           187 -#define __NR_getpmsg		188 -#define __NR_putpmsg		189 -#define __NR_vfork		190 -#define __NR_pivot_root         217 -#define __NR_mincore            218 -#define __NR_madvise            219 -#define __NR_getdents64		220 -#define __NR_readahead		222 -#define __NR_setxattr		224 -#define __NR_lsetxattr		225 -#define __NR_fsetxattr		226 -#define __NR_getxattr		227 -#define __NR_lgetxattr		228 -#define __NR_fgetxattr		229 -#define __NR_listxattr		230 -#define __NR_llistxattr		231 -#define __NR_flistxattr		232 -#define __NR_removexattr	233 -#define __NR_lremovexattr	234 -#define __NR_fremovexattr	235 -#define __NR_gettid		236 -#define __NR_tkill		237 -#define __NR_futex		238 -#define __NR_sched_setaffinity	239 -#define __NR_sched_getaffinity	240 -#define __NR_tgkill		241 -/* Number 242 is reserved for tux */ -#define __NR_io_setup		243 -#define __NR_io_destroy		244 -#define __NR_io_getevents	245 -#define __NR_io_submit		246 -#define __NR_io_cancel		247 -#define __NR_exit_group		248 -#define __NR_epoll_create	249 -#define __NR_epoll_ctl		250 -#define __NR_epoll_wait		251 -#define __NR_set_tid_address	252 -#define __NR_fadvise64		253 -#define __NR_timer_create	254 -#define __NR_timer_settime	(__NR_timer_create+1) -#define __NR_timer_gettime	(__NR_timer_create+2) -#define __NR_timer_getoverrun	(__NR_timer_create+3) -#define __NR_timer_delete	(__NR_timer_create+4) -#define __NR_clock_settime	(__NR_timer_create+5) -#define __NR_clock_gettime	(__NR_timer_create+6) -#define __NR_clock_getres	(__NR_timer_create+7) -#define __NR_clock_nanosleep	(__NR_timer_create+8) -/* Number 263 is reserved for vserver */ -#define __NR_statfs64		265 -#define __NR_fstatfs64		266 -#define __NR_remap_file_pages	267 -/* Number 268 is reserved for new sys_mbind */ -/* Number 269 is reserved for new sys_get_mempolicy */ -/* Number 270 is reserved for new sys_set_mempolicy */ -#define __NR_mq_open		271 -#define __NR_mq_unlink		272 -#define __NR_mq_timedsend	273 -#define __NR_mq_timedreceive	274 -#define __NR_mq_notify		275 -#define __NR_mq_getsetattr	276 -#define __NR_kexec_load		277 -#define __NR_add_key		278 -#define __NR_request_key	279 -#define __NR_keyctl		280 -#define __NR_waitid		281 -#define __NR_ioprio_set		282 -#define __NR_ioprio_get		283 -#define __NR_inotify_init	284 -#define __NR_inotify_add_watch	285 -#define __NR_inotify_rm_watch	286 -/* Number 287 is reserved for new sys_migrate_pages */ -#define __NR_openat		288 -#define __NR_mkdirat		289 -#define __NR_mknodat		290 -#define __NR_fchownat		291 -#define __NR_futimesat		292 -#define __NR_unlinkat		294 -#define __NR_renameat		295 -#define __NR_linkat		296 -#define __NR_symlinkat		297 -#define __NR_readlinkat		298 -#define __NR_fchmodat		299 -#define __NR_faccessat		300 -#define __NR_pselect6		301 -#define __NR_ppoll		302 -#define __NR_unshare		303 -#define __NR_set_robust_list	304 -#define __NR_get_robust_list	305 -#define __NR_splice		306 -#define __NR_sync_file_range	307 -#define __NR_tee		308 -#define __NR_vmsplice		309 -/* Number 310 is reserved for new sys_move_pages */ -#define __NR_getcpu		311 -#define __NR_epoll_pwait	312 -#define __NR_utimes		313 -#define __NR_fallocate		314 -#define __NR_utimensat		315 -#define __NR_signalfd		316 -#define __NR_timerfd		317 -#define __NR_eventfd		318 -#define __NR_timerfd_create	319 -#define __NR_timerfd_settime	320 -#define __NR_timerfd_gettime	321 -#define __NR_signalfd4		322 -#define __NR_eventfd2		323 -#define __NR_inotify_init1	324 -#define __NR_pipe2		325 -#define __NR_dup3		326 -#define __NR_epoll_create1	327 -#define	__NR_preadv		328 -#define	__NR_pwritev		329 -#define __NR_rt_tgsigqueueinfo	330 -#define __NR_perf_event_open	331 -#define __NR_fanotify_init	332 -#define __NR_fanotify_mark	333 -#define __NR_prlimit64		334 -#define NR_syscalls 335 +#include <uapi/asm/unistd.h> -/*  - * There are some system calls that are not present on 64 bit, some - * have a different name although they do the same (e.g. __NR_chown32 - * is __NR_chown on 64 bit). - */ -#ifndef __s390x__ - -#define __NR_time		 13 -#define __NR_lchown		 16 -#define __NR_setuid		 23 -#define __NR_getuid		 24 -#define __NR_stime		 25 -#define __NR_setgid		 46 -#define __NR_getgid		 47 -#define __NR_geteuid		 49 -#define __NR_getegid		 50 -#define __NR_setreuid		 70 -#define __NR_setregid		 71 -#define __NR_getrlimit		 76 -#define __NR_getgroups		 80 -#define __NR_setgroups		 81 -#define __NR_fchown		 95 -#define __NR_ioperm		101 -#define __NR_setfsuid		138 -#define __NR_setfsgid		139 -#define __NR__llseek		140 -#define __NR__newselect 	142 -#define __NR_setresuid		164 -#define __NR_getresuid		165 -#define __NR_setresgid		170 -#define __NR_getresgid		171 -#define __NR_chown		182 -#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */ -#define __NR_mmap2		192 -#define __NR_truncate64		193 -#define __NR_ftruncate64	194 -#define __NR_stat64		195 -#define __NR_lstat64		196 -#define __NR_fstat64		197 -#define __NR_lchown32		198 -#define __NR_getuid32		199 -#define __NR_getgid32		200 -#define __NR_geteuid32		201 -#define __NR_getegid32		202 -#define __NR_setreuid32		203 -#define __NR_setregid32		204 -#define __NR_getgroups32	205 -#define __NR_setgroups32	206 -#define __NR_fchown32		207 -#define __NR_setresuid32	208 -#define __NR_getresuid32	209 -#define __NR_setresgid32	210 -#define __NR_getresgid32	211 -#define __NR_chown32		212 -#define __NR_setuid32		213 -#define __NR_setgid32		214 -#define __NR_setfsuid32		215 -#define __NR_setfsgid32		216 -#define __NR_fcntl64		221 -#define __NR_sendfile64		223 -#define __NR_fadvise64_64	264 -#define __NR_fstatat64		293 - -#else - -#define __NR_select		142 -#define __NR_getrlimit		191	/* SuS compliant getrlimit */ -#define __NR_lchown  		198 -#define __NR_getuid  		199 -#define __NR_getgid  		200 -#define __NR_geteuid  		201 -#define __NR_getegid  		202 -#define __NR_setreuid  		203 -#define __NR_setregid  		204 -#define __NR_getgroups  	205 -#define __NR_setgroups  	206 -#define __NR_fchown  		207 -#define __NR_setresuid  	208 -#define __NR_getresuid  	209 -#define __NR_setresgid  	210 -#define __NR_getresgid  	211 -#define __NR_chown  		212 -#define __NR_setuid  		213 -#define __NR_setgid  		214 -#define __NR_setfsuid  		215 -#define __NR_setfsgid  		216 -#define __NR_newfstatat		293 - -#endif - -#ifdef __KERNEL__  #ifndef CONFIG_64BIT  #define __IGNORE_select @@ -381,8 +24,8 @@  /* Ignore system calls that are also reachable via sys_socket */  #define __IGNORE_recvmmsg +#define __IGNORE_sendmmsg -#define __ARCH_WANT_IPC_PARSE_VERSION  #define __ARCH_WANT_OLD_READDIR  #define __ARCH_WANT_SYS_ALARM  #define __ARCH_WANT_SYS_GETHOSTNAME @@ -390,6 +33,7 @@  #define __ARCH_WANT_SYS_SIGNAL  #define __ARCH_WANT_SYS_UTIME  #define __ARCH_WANT_SYS_SOCKETCALL +#define __ARCH_WANT_SYS_IPC  #define __ARCH_WANT_SYS_FADVISE64  #define __ARCH_WANT_SYS_GETPGRP  #define __ARCH_WANT_SYS_LLSEEK @@ -399,24 +43,15 @@  #define __ARCH_WANT_SYS_OLDUMOUNT  #define __ARCH_WANT_SYS_SIGPENDING  #define __ARCH_WANT_SYS_SIGPROCMASK -#define __ARCH_WANT_SYS_RT_SIGACTION -#define __ARCH_WANT_SYS_RT_SIGSUSPEND  # ifndef CONFIG_64BIT  #   define __ARCH_WANT_STAT64  #   define __ARCH_WANT_SYS_TIME  # endif  # ifdef CONFIG_COMPAT  #   define __ARCH_WANT_COMPAT_SYS_TIME -#   define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND  # endif +#define __ARCH_WANT_SYS_FORK +#define __ARCH_WANT_SYS_VFORK +#define __ARCH_WANT_SYS_CLONE -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") - -#endif /* __KERNEL__ */  #endif /* _ASM_S390_UNISTD_H_ */ diff --git a/arch/s390/include/asm/user.h b/arch/s390/include/asm/user.h index 1b050e35fdc..6ed1d188633 100644 --- a/arch/s390/include/asm/user.h +++ b/arch/s390/include/asm/user.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/user.h - *   *  S390 version   *   *  Derived from "include/asm-i386/usr.h" diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h index 533f35751ae..bc9746a7d47 100644 --- a/arch/s390/include/asm/vdso.h +++ b/arch/s390/include/asm/vdso.h @@ -1,8 +1,6 @@  #ifndef __S390_VDSO_H__  #define __S390_VDSO_H__ -#ifdef __KERNEL__ -  /* Default link addresses for the vDSOs */  #define VDSO32_LBASE	0  #define VDSO64_LBASE	0 @@ -28,8 +26,9 @@ struct vdso_data {  	__u64 wtom_clock_nsec;		/*				0x28 */  	__u32 tz_minuteswest;		/* Minutes west of Greenwich	0x30 */  	__u32 tz_dsttime;		/* Type of dst correction	0x34 */ -	__u32 ectg_available; -	__u32 ntp_mult;			/* NTP adjusted multiplier	0x3C */ +	__u32 ectg_available;		/* ECTG instruction present	0x38 */ +	__u32 tk_mult;			/* Mult. used for xtime_nsec	0x3c */ +	__u32 tk_shift;			/* Shift used for xtime_nsec	0x40 */  };  struct vdso_per_cpu_data { @@ -40,12 +39,9 @@ struct vdso_per_cpu_data {  extern struct vdso_data *vdso_data;  #ifdef CONFIG_64BIT -int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore); -void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore); +int vdso_alloc_per_cpu(struct _lowcore *lowcore); +void vdso_free_per_cpu(struct _lowcore *lowcore);  #endif  #endif /* __ASSEMBLY__ */ - -#endif /* __KERNEL__ */ -  #endif /* __S390_VDSO_H__ */ diff --git a/arch/s390/include/asm/vga.h b/arch/s390/include/asm/vga.h new file mode 100644 index 00000000000..d375526c261 --- /dev/null +++ b/arch/s390/include/asm/vga.h @@ -0,0 +1,6 @@ +#ifndef _ASM_S390_VGA_H +#define _ASM_S390_VGA_H + +/* Avoid compile errors due to missing asm/vga.h */ + +#endif /* _ASM_S390_VGA_H */ diff --git a/arch/s390/include/asm/vtime.h b/arch/s390/include/asm/vtime.h new file mode 100644 index 00000000000..af9896c53eb --- /dev/null +++ b/arch/s390/include/asm/vtime.h @@ -0,0 +1,7 @@ +#ifndef _S390_VTIME_H +#define _S390_VTIME_H + +#define __ARCH_HAS_VTIME_ACCOUNT +#define __ARCH_HAS_VTIME_TASK_SWITCH + +#endif /* _S390_VTIME_H */ diff --git a/arch/s390/include/asm/vtimer.h b/arch/s390/include/asm/vtimer.h new file mode 100644 index 00000000000..bfe25d513ad --- /dev/null +++ b/arch/s390/include/asm/vtimer.h @@ -0,0 +1,33 @@ +/* + *  Copyright IBM Corp. 2003, 2012 + *  Virtual CPU timer + * + *  Author(s): Jan Glauber <jan.glauber@de.ibm.com> + */ + +#ifndef _ASM_S390_TIMER_H +#define _ASM_S390_TIMER_H + +#define VTIMER_MAX_SLICE (0x7fffffffffffffffULL) + +struct vtimer_list { +	struct list_head entry; +	u64 expires; +	u64 interval; +	void (*function)(unsigned long); +	unsigned long data; +}; + +extern void init_virt_timer(struct vtimer_list *timer); +extern void add_virt_timer(struct vtimer_list *timer); +extern void add_virt_timer_periodic(struct vtimer_list *timer); +extern int mod_virt_timer(struct vtimer_list *timer, u64 expires); +extern int mod_virt_timer_periodic(struct vtimer_list *timer, u64 expires); +extern int del_virt_timer(struct vtimer_list *timer); + +extern void init_cpu_vtimer(void); +extern void vtime_init(void); + +extern void vtime_stop_cpu(void); + +#endif /* _ASM_S390_TIMER_H */ diff --git a/arch/s390/include/uapi/asm/Kbuild b/arch/s390/include/uapi/asm/Kbuild new file mode 100644 index 00000000000..736637363d3 --- /dev/null +++ b/arch/s390/include/uapi/asm/Kbuild @@ -0,0 +1,51 @@ +# UAPI Header export list +include include/uapi/asm-generic/Kbuild.asm + +header-y += auxvec.h +header-y += bitsperlong.h +header-y += byteorder.h +header-y += chpid.h +header-y += chsc.h +header-y += cmb.h +header-y += dasd.h +header-y += debug.h +header-y += errno.h +header-y += fcntl.h +header-y += ioctl.h +header-y += ioctls.h +header-y += ipcbuf.h +header-y += kvm.h +header-y += kvm_para.h +header-y += kvm_virtio.h +header-y += mman.h +header-y += monwriter.h +header-y += msgbuf.h +header-y += param.h +header-y += poll.h +header-y += posix_types.h +header-y += ptrace.h +header-y += qeth.h +header-y += resource.h +header-y += schid.h +header-y += sembuf.h +header-y += setup.h +header-y += shmbuf.h +header-y += sigcontext.h +header-y += siginfo.h +header-y += signal.h +header-y += socket.h +header-y += sockios.h +header-y += sclp_ctl.h +header-y += sie.h +header-y += stat.h +header-y += statfs.h +header-y += swab.h +header-y += tape390.h +header-y += termbits.h +header-y += termios.h +header-y += types.h +header-y += ucontext.h +header-y += unistd.h +header-y += virtio-ccw.h +header-y += vtoc.h +header-y += zcrypt.h diff --git a/arch/s390/include/asm/auxvec.h b/arch/s390/include/uapi/asm/auxvec.h index a1f153e8913..a1f153e8913 100644 --- a/arch/s390/include/asm/auxvec.h +++ b/arch/s390/include/uapi/asm/auxvec.h diff --git a/arch/s390/include/asm/bitsperlong.h b/arch/s390/include/uapi/asm/bitsperlong.h index 6b235aea9c6..6b235aea9c6 100644 --- a/arch/s390/include/asm/bitsperlong.h +++ b/arch/s390/include/uapi/asm/bitsperlong.h diff --git a/arch/s390/include/asm/byteorder.h b/arch/s390/include/uapi/asm/byteorder.h index a332e59e26f..a332e59e26f 100644 --- a/arch/s390/include/asm/byteorder.h +++ b/arch/s390/include/uapi/asm/byteorder.h diff --git a/arch/s390/include/uapi/asm/chpid.h b/arch/s390/include/uapi/asm/chpid.h new file mode 100644 index 00000000000..6b4fb29cc19 --- /dev/null +++ b/arch/s390/include/uapi/asm/chpid.h @@ -0,0 +1,22 @@ +/* + *    Copyright IBM Corp. 2007, 2012 + *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> + */ + +#ifndef _UAPI_ASM_S390_CHPID_H +#define _UAPI_ASM_S390_CHPID_H + +#include <linux/string.h> +#include <linux/types.h> + +#define __MAX_CHPID 255 + +struct chp_id { +	__u8 reserved1; +	__u8 cssid; +	__u8 reserved2; +	__u8 id; +} __attribute__((packed)); + + +#endif /* _UAPI_ASM_S390_CHPID_H */ diff --git a/arch/s390/include/asm/chsc.h b/arch/s390/include/uapi/asm/chsc.h index 4943654ed7f..65dc694725a 100644 --- a/arch/s390/include/asm/chsc.h +++ b/arch/s390/include/uapi/asm/chsc.h @@ -1,7 +1,7 @@  /*   * ioctl interface for /dev/chsc   * - * Copyright 2008 IBM Corp. + * Copyright IBM Corp. 2008, 2012   * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>   */ @@ -9,9 +9,12 @@  #define _ASM_CHSC_H  #include <linux/types.h> +#include <linux/ioctl.h>  #include <asm/chpid.h>  #include <asm/schid.h> +#define CHSC_SIZE 0x1000 +  struct chsc_async_header {  	__u16 length;  	__u16 code; @@ -23,15 +26,24 @@ struct chsc_async_header {  struct chsc_async_area {  	struct chsc_async_header header; -	__u8 data[PAGE_SIZE - 16 /* size of chsc_async_header */]; +	__u8 data[CHSC_SIZE - sizeof(struct chsc_async_header)]; +} __attribute__ ((packed)); + +struct chsc_header { +	__u16 length; +	__u16 code;  } __attribute__ ((packed)); +struct chsc_sync_area { +	struct chsc_header header; +	__u8 data[CHSC_SIZE - sizeof(struct chsc_header)]; +} __attribute__ ((packed));  struct chsc_response_struct {  	__u16 length;  	__u16 code;  	__u32 parms; -	__u8 data[PAGE_SIZE - 8]; +	__u8 data[CHSC_SIZE - 2 * sizeof(__u16) - sizeof(__u32)];  } __attribute__ ((packed));  struct chsc_chp_cd { @@ -124,33 +136,8 @@ struct chsc_cpd_info {  #define CHSC_INFO_CCL _IOWR(CHSC_IOCTL_MAGIC, 0x86, struct chsc_comp_list)  #define CHSC_INFO_CPD _IOWR(CHSC_IOCTL_MAGIC, 0x87, struct chsc_cpd_info)  #define CHSC_INFO_DCAL _IOWR(CHSC_IOCTL_MAGIC, 0x88, struct chsc_dcal) +#define CHSC_START_SYNC _IOWR(CHSC_IOCTL_MAGIC, 0x89, struct chsc_sync_area) +#define CHSC_ON_CLOSE_SET _IOWR(CHSC_IOCTL_MAGIC, 0x8a, struct chsc_async_area) +#define CHSC_ON_CLOSE_REMOVE _IO(CHSC_IOCTL_MAGIC, 0x8b) -#ifdef __KERNEL__ - -struct css_general_char { -	u64 : 12; -	u32 dynio : 1;	 /* bit 12 */ -	u32 : 28; -	u32 aif : 1;	 /* bit 41 */ -	u32 : 3; -	u32 mcss : 1;	 /* bit 45 */ -	u32 fcs : 1;	 /* bit 46 */ -	u32 : 1; -	u32 ext_mb : 1;  /* bit 48 */ -	u32 : 7; -	u32 aif_tdd : 1; /* bit 56 */ -	u32 : 1; -	u32 qebsm : 1;	 /* bit 58 */ -	u32 : 8; -	u32 aif_osa : 1; /* bit 67 */ -	u32 : 14; -	u32 cib : 1;	 /* bit 82 */ -	u32 : 5; -	u32 fcx : 1;	 /* bit 88 */ -	u32 : 7; -}__attribute__((packed)); - -extern struct css_general_char css_general_characteristics; - -#endif /* __KERNEL__ */  #endif diff --git a/arch/s390/include/uapi/asm/cmb.h b/arch/s390/include/uapi/asm/cmb.h new file mode 100644 index 00000000000..0c086d00d89 --- /dev/null +++ b/arch/s390/include/uapi/asm/cmb.h @@ -0,0 +1,53 @@ +#ifndef _UAPIS390_CMB_H +#define _UAPIS390_CMB_H + +#include <linux/types.h> + +/** + * struct cmbdata - channel measurement block data for user space + * @size: size of the stored data + * @elapsed_time: time since last sampling + * @ssch_rsch_count: number of ssch and rsch + * @sample_count: number of samples + * @device_connect_time: time of device connect + * @function_pending_time: time of function pending + * @device_disconnect_time: time of device disconnect + * @control_unit_queuing_time: time of control unit queuing + * @device_active_only_time: time of device active only + * @device_busy_time: time of device busy (ext. format) + * @initial_command_response_time: initial command response time (ext. format) + * + * All values are stored as 64 bit for simplicity, especially + * in 32 bit emulation mode. All time values are normalized to + * nanoseconds. + * Currently, two formats are known, which differ by the size of + * this structure, i.e. the last two members are only set when + * the extended channel measurement facility (first shipped in + * z990 machines) is activated. + * Potentially, more fields could be added, which would result in a + * new ioctl number. + */ +struct cmbdata { +	__u64 size; +	__u64 elapsed_time; + /* basic and exended format: */ +	__u64 ssch_rsch_count; +	__u64 sample_count; +	__u64 device_connect_time; +	__u64 function_pending_time; +	__u64 device_disconnect_time; +	__u64 control_unit_queuing_time; +	__u64 device_active_only_time; + /* extended format only: */ +	__u64 device_busy_time; +	__u64 initial_command_response_time; +}; + +/* enable channel measurement */ +#define BIODASDCMFENABLE	_IO(DASD_IOCTL_LETTER, 32) +/* enable channel measurement */ +#define BIODASDCMFDISABLE	_IO(DASD_IOCTL_LETTER, 33) +/* read channel measurement data */ +#define BIODASDREADALLCMB	_IOWR(DASD_IOCTL_LETTER, 33, struct cmbdata) + +#endif /* _UAPIS390_CMB_H */ diff --git a/arch/s390/include/asm/dasd.h b/arch/s390/include/uapi/asm/dasd.h index b604a9186f8..5812a3b2df9 100644 --- a/arch/s390/include/asm/dasd.h +++ b/arch/s390/include/uapi/asm/dasd.h @@ -1,8 +1,7 @@  /*  - * File...........: linux/drivers/s390/block/dasd.c   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>   * Bugreports.to..: <Linux390@de.ibm.com> - * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + * Copyright IBM Corp. 1999, 2000   * EMC Symmetrix ioctl Copyright EMC Corporation, 2008   * Author.........: Nigel Hislop <hislop_nigel@emc.com>   * @@ -73,6 +72,7 @@ typedef struct dasd_information2_t {   * 0x02: use diag discipline (diag)   * 0x04: set the device initially online (internal use only)   * 0x08: enable ERP related logging + * 0x20: give access to raw eckd data   */  #define DASD_FEATURE_DEFAULT	     0x00  #define DASD_FEATURE_READONLY	     0x01 @@ -80,6 +80,8 @@ typedef struct dasd_information2_t {  #define DASD_FEATURE_INITIAL_ONLINE  0x04  #define DASD_FEATURE_ERPLOG	     0x08  #define DASD_FEATURE_FAILFAST	     0x10 +#define DASD_FEATURE_FAILONSLCK      0x20 +#define DASD_FEATURE_USERAW	     0x40  #define DASD_PARTN_BITS 2 @@ -259,6 +261,10 @@ struct dasd_snid_ioctl_data {  #define BIODASDQUIESCE _IO(DASD_IOCTL_LETTER,6)   /* Resume IO on device */  #define BIODASDRESUME  _IO(DASD_IOCTL_LETTER,7)  +/* Abort all I/O on a device */ +#define BIODASDABORTIO _IO(DASD_IOCTL_LETTER, 240) +/* Allow I/O on a device */ +#define BIODASDALLOWIO _IO(DASD_IOCTL_LETTER, 241)  /* retrieve API version number */ diff --git a/arch/s390/include/uapi/asm/debug.h b/arch/s390/include/uapi/asm/debug.h new file mode 100644 index 00000000000..c59fc79125f --- /dev/null +++ b/arch/s390/include/uapi/asm/debug.h @@ -0,0 +1,34 @@ +/* + *   S/390 debug facility + * + *    Copyright IBM Corp. 1999, 2000 + */ + +#ifndef _UAPIDEBUG_H +#define _UAPIDEBUG_H + +#include <linux/fs.h> + +/* Note: + * struct __debug_entry must be defined outside of #ifdef __KERNEL__  + * in order to allow a user program to analyze the 'raw'-view. + */ + +struct __debug_entry{ +        union { +                struct { +                        unsigned long long clock:52; +                        unsigned long long exception:1; +                        unsigned long long level:3; +                        unsigned long long cpuid:8; +                } fields; + +                unsigned long long stck; +        } id; +        void* caller; +} __attribute__((packed)); + + +#define __DEBUG_FEATURE_VERSION      2  /* version of debug feature */ + +#endif /* _UAPIDEBUG_H */ diff --git a/arch/s390/include/asm/errno.h b/arch/s390/include/uapi/asm/errno.h index e41d5b37c4d..395e97d8005 100644 --- a/arch/s390/include/asm/errno.h +++ b/arch/s390/include/uapi/asm/errno.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/errno.h - *   *  S390 version   *   */ diff --git a/arch/s390/include/asm/fcntl.h b/arch/s390/include/uapi/asm/fcntl.h index 46ab12db573..46ab12db573 100644 --- a/arch/s390/include/asm/fcntl.h +++ b/arch/s390/include/uapi/asm/fcntl.h diff --git a/arch/s390/include/uapi/asm/hypfs.h b/arch/s390/include/uapi/asm/hypfs.h new file mode 100644 index 00000000000..37998b44953 --- /dev/null +++ b/arch/s390/include/uapi/asm/hypfs.h @@ -0,0 +1,25 @@ +/* + * IOCTL interface for hypfs + * + * Copyright IBM Corp. 2013 + * + * Author: Martin Schwidefsky <schwidefsky@de.ibm.com> + */ + +#ifndef _ASM_HYPFS_CTL_H +#define _ASM_HYPFS_CTL_H + +#include <linux/types.h> + +struct hypfs_diag304 { +	__u32	args[2]; +	__u64	data; +	__u64	rc; +} __attribute__((packed)); + +#define HYPFS_IOCTL_MAGIC 0x10 + +#define HYPFS_DIAG304 \ +	_IOWR(HYPFS_IOCTL_MAGIC, 0x20, struct hypfs_diag304) + +#endif diff --git a/arch/s390/include/asm/ioctl.h b/arch/s390/include/uapi/asm/ioctl.h index b279fe06dfe..b279fe06dfe 100644 --- a/arch/s390/include/asm/ioctl.h +++ b/arch/s390/include/uapi/asm/ioctl.h diff --git a/arch/s390/include/asm/ioctls.h b/arch/s390/include/uapi/asm/ioctls.h index 960a4c1ebdf..960a4c1ebdf 100644 --- a/arch/s390/include/asm/ioctls.h +++ b/arch/s390/include/uapi/asm/ioctls.h diff --git a/arch/s390/include/asm/ipcbuf.h b/arch/s390/include/uapi/asm/ipcbuf.h index 37f293d12c8..37f293d12c8 100644 --- a/arch/s390/include/asm/ipcbuf.h +++ b/arch/s390/include/uapi/asm/ipcbuf.h diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h new file mode 100644 index 00000000000..0fc26430a1e --- /dev/null +++ b/arch/s390/include/uapi/asm/kvm.h @@ -0,0 +1,131 @@ +#ifndef __LINUX_KVM_S390_H +#define __LINUX_KVM_S390_H +/* + * KVM s390 specific structures and definitions + * + * Copyright IBM Corp. 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + *    Author(s): Carsten Otte <cotte@de.ibm.com> + *               Christian Borntraeger <borntraeger@de.ibm.com> + */ +#include <linux/types.h> + +#define __KVM_S390 +#define __KVM_HAVE_GUEST_DEBUG + +/* Device control API: s390-specific devices */ +#define KVM_DEV_FLIC_GET_ALL_IRQS	1 +#define KVM_DEV_FLIC_ENQUEUE		2 +#define KVM_DEV_FLIC_CLEAR_IRQS		3 +#define KVM_DEV_FLIC_APF_ENABLE		4 +#define KVM_DEV_FLIC_APF_DISABLE_WAIT	5 +#define KVM_DEV_FLIC_ADAPTER_REGISTER	6 +#define KVM_DEV_FLIC_ADAPTER_MODIFY	7 +/* + * We can have up to 4*64k pending subchannels + 8 adapter interrupts, + * as well as up  to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts. + * There are also sclp and machine checks. This gives us + * sizeof(kvm_s390_irq)*(4*65536+8+64*64+1+1) = 72 * 266250 = 19170000 + * Lets round up to 8192 pages. + */ +#define KVM_S390_MAX_FLOAT_IRQS	266250 +#define KVM_S390_FLIC_MAX_BUFFER	0x2000000 + +struct kvm_s390_io_adapter { +	__u32 id; +	__u8 isc; +	__u8 maskable; +	__u8 swap; +	__u8 pad; +}; + +#define KVM_S390_IO_ADAPTER_MASK 1 +#define KVM_S390_IO_ADAPTER_MAP 2 +#define KVM_S390_IO_ADAPTER_UNMAP 3 + +struct kvm_s390_io_adapter_req { +	__u32 id; +	__u8 type; +	__u8 mask; +	__u16 pad0; +	__u64 addr; +}; + +/* kvm attr_group  on vm fd */ +#define KVM_S390_VM_MEM_CTRL		0 + +/* kvm attributes for mem_ctrl */ +#define KVM_S390_VM_MEM_ENABLE_CMMA	0 +#define KVM_S390_VM_MEM_CLR_CMMA	1 + +/* for KVM_GET_REGS and KVM_SET_REGS */ +struct kvm_regs { +	/* general purpose regs for s390 */ +	__u64 gprs[16]; +}; + +/* for KVM_GET_SREGS and KVM_SET_SREGS */ +struct kvm_sregs { +	__u32 acrs[16]; +	__u64 crs[16]; +}; + +/* for KVM_GET_FPU and KVM_SET_FPU */ +struct kvm_fpu { +	__u32 fpc; +	__u64 fprs[16]; +}; + +#define KVM_GUESTDBG_USE_HW_BP		0x00010000 + +#define KVM_HW_BP			1 +#define KVM_HW_WP_WRITE			2 +#define KVM_SINGLESTEP			4 + +struct kvm_debug_exit_arch { +	__u64 addr; +	__u8 type; +	__u8 pad[7]; /* Should be set to 0 */ +}; + +struct kvm_hw_breakpoint { +	__u64 addr; +	__u64 phys_addr; +	__u64 len; +	__u8 type; +	__u8 pad[7]; /* Should be set to 0 */ +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { +	__u32 nr_hw_bp; +	__u32 pad; /* Should be set to 0 */ +	struct kvm_hw_breakpoint __user *hw_bp; +}; + +#define KVM_SYNC_PREFIX (1UL << 0) +#define KVM_SYNC_GPRS   (1UL << 1) +#define KVM_SYNC_ACRS   (1UL << 2) +#define KVM_SYNC_CRS    (1UL << 3) +/* definition of registers in kvm_run */ +struct kvm_sync_regs { +	__u64 prefix;	/* prefix register */ +	__u64 gprs[16];	/* general purpose registers */ +	__u32 acrs[16];	/* access registers */ +	__u64 crs[16];	/* control registers */ +}; + +#define KVM_REG_S390_TODPR	(KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1) +#define KVM_REG_S390_EPOCHDIFF	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x2) +#define KVM_REG_S390_CPU_TIMER  (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x3) +#define KVM_REG_S390_CLOCK_COMP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x4) +#define KVM_REG_S390_PFTOKEN	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5) +#define KVM_REG_S390_PFCOMPARE	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6) +#define KVM_REG_S390_PFSELECT	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7) +#define KVM_REG_S390_PP		(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x8) +#define KVM_REG_S390_GBEA	(KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x9) +#endif diff --git a/arch/s390/include/uapi/asm/kvm_para.h b/arch/s390/include/uapi/asm/kvm_para.h new file mode 100644 index 00000000000..ff1f4e7b301 --- /dev/null +++ b/arch/s390/include/uapi/asm/kvm_para.h @@ -0,0 +1,11 @@ +/* + * User API definitions for paravirtual devices on s390 + * + * Copyright IBM Corp. 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com> + */ diff --git a/arch/s390/include/asm/kvm_virtio.h b/arch/s390/include/uapi/asm/kvm_virtio.h index 72f614181ef..44a438ca9e7 100644 --- a/arch/s390/include/asm/kvm_virtio.h +++ b/arch/s390/include/uapi/asm/kvm_virtio.h @@ -1,5 +1,5 @@  /* - * kvm_virtio.h - definition for virtio for kvm on s390 + * definition for virtio for kvm on s390   *   * Copyright IBM Corp. 2008   * diff --git a/arch/s390/include/uapi/asm/mman.h b/arch/s390/include/uapi/asm/mman.h new file mode 100644 index 00000000000..de23da1f41b --- /dev/null +++ b/arch/s390/include/uapi/asm/mman.h @@ -0,0 +1,6 @@ +/* + *  S390 version + * + *  Derived from "include/asm-i386/mman.h" + */ +#include <asm-generic/mman.h> diff --git a/arch/s390/include/asm/monwriter.h b/arch/s390/include/uapi/asm/monwriter.h index f0cbf96c52e..f845c8e2f86 100644 --- a/arch/s390/include/asm/monwriter.h +++ b/arch/s390/include/uapi/asm/monwriter.h @@ -1,7 +1,5 @@  /* - * include/asm-s390/monwriter.h - * - * Copyright (C) IBM Corp. 2006 + * Copyright IBM Corp. 2006   * Character device driver for writing z/VM APPLDATA monitor records   * Version 1.0   * Author(s): Melissa Howland <melissah@us.ibm.com> diff --git a/arch/s390/include/asm/msgbuf.h b/arch/s390/include/uapi/asm/msgbuf.h index 1bbdee92792..1bbdee92792 100644 --- a/arch/s390/include/asm/msgbuf.h +++ b/arch/s390/include/uapi/asm/msgbuf.h diff --git a/arch/s390/include/asm/param.h b/arch/s390/include/uapi/asm/param.h index c616821bf2a..c616821bf2a 100644 --- a/arch/s390/include/asm/param.h +++ b/arch/s390/include/uapi/asm/param.h diff --git a/arch/s390/include/asm/poll.h b/arch/s390/include/uapi/asm/poll.h index c98509d3149..c98509d3149 100644 --- a/arch/s390/include/asm/poll.h +++ b/arch/s390/include/uapi/asm/poll.h diff --git a/arch/s390/include/uapi/asm/posix_types.h b/arch/s390/include/uapi/asm/posix_types.h new file mode 100644 index 00000000000..bf2a2ad2f80 --- /dev/null +++ b/arch/s390/include/uapi/asm/posix_types.h @@ -0,0 +1,51 @@ +/* + *  S390 version + * + */ + +#ifndef __ARCH_S390_POSIX_TYPES_H +#define __ARCH_S390_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc.  Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long   __kernel_size_t; +typedef long            __kernel_ssize_t; +#define __kernel_size_t __kernel_size_t + +typedef unsigned short	__kernel_old_dev_t; +#define __kernel_old_dev_t __kernel_old_dev_t + +#ifndef __s390x__ + +typedef unsigned long   __kernel_ino_t; +typedef unsigned short  __kernel_mode_t; +typedef unsigned short  __kernel_ipc_pid_t; +typedef unsigned short  __kernel_uid_t; +typedef unsigned short  __kernel_gid_t; +typedef int             __kernel_ptrdiff_t; + +#else /* __s390x__ */ + +typedef unsigned int    __kernel_ino_t; +typedef unsigned int    __kernel_mode_t; +typedef int             __kernel_ipc_pid_t; +typedef unsigned int    __kernel_uid_t; +typedef unsigned int    __kernel_gid_t; +typedef long            __kernel_ptrdiff_t; +typedef unsigned long   __kernel_sigset_t;      /* at least 32 bits */ + +#endif /* __s390x__ */ + +#define __kernel_ino_t  __kernel_ino_t +#define __kernel_mode_t __kernel_mode_t +#define __kernel_ipc_pid_t __kernel_ipc_pid_t +#define __kernel_uid_t __kernel_uid_t +#define __kernel_gid_t __kernel_gid_t + +#include <asm-generic/posix_types.h> + +#endif diff --git a/arch/s390/include/uapi/asm/ptrace.h b/arch/s390/include/uapi/asm/ptrace.h new file mode 100644 index 00000000000..a150f4fabe4 --- /dev/null +++ b/arch/s390/include/uapi/asm/ptrace.h @@ -0,0 +1,459 @@ +/* + *  S390 version + *    Copyright IBM Corp. 1999, 2000 + *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + */ + +#ifndef _UAPI_S390_PTRACE_H +#define _UAPI_S390_PTRACE_H + +/* + * Offsets in the user_regs_struct. They are used for the ptrace + * system call and in entry.S + */ +#ifndef __s390x__ + +#define PT_PSWMASK  0x00 +#define PT_PSWADDR  0x04 +#define PT_GPR0     0x08 +#define PT_GPR1     0x0C +#define PT_GPR2     0x10 +#define PT_GPR3     0x14 +#define PT_GPR4     0x18 +#define PT_GPR5     0x1C +#define PT_GPR6     0x20 +#define PT_GPR7     0x24 +#define PT_GPR8     0x28 +#define PT_GPR9     0x2C +#define PT_GPR10    0x30 +#define PT_GPR11    0x34 +#define PT_GPR12    0x38 +#define PT_GPR13    0x3C +#define PT_GPR14    0x40 +#define PT_GPR15    0x44 +#define PT_ACR0     0x48 +#define PT_ACR1     0x4C +#define PT_ACR2     0x50 +#define PT_ACR3     0x54 +#define PT_ACR4	    0x58 +#define PT_ACR5	    0x5C +#define PT_ACR6	    0x60 +#define PT_ACR7	    0x64 +#define PT_ACR8	    0x68 +#define PT_ACR9	    0x6C +#define PT_ACR10    0x70 +#define PT_ACR11    0x74 +#define PT_ACR12    0x78 +#define PT_ACR13    0x7C +#define PT_ACR14    0x80 +#define PT_ACR15    0x84 +#define PT_ORIGGPR2 0x88 +#define PT_FPC	    0x90 +/* + * A nasty fact of life that the ptrace api + * only supports passing of longs. + */ +#define PT_FPR0_HI  0x98 +#define PT_FPR0_LO  0x9C +#define PT_FPR1_HI  0xA0 +#define PT_FPR1_LO  0xA4 +#define PT_FPR2_HI  0xA8 +#define PT_FPR2_LO  0xAC +#define PT_FPR3_HI  0xB0 +#define PT_FPR3_LO  0xB4 +#define PT_FPR4_HI  0xB8 +#define PT_FPR4_LO  0xBC +#define PT_FPR5_HI  0xC0 +#define PT_FPR5_LO  0xC4 +#define PT_FPR6_HI  0xC8 +#define PT_FPR6_LO  0xCC +#define PT_FPR7_HI  0xD0 +#define PT_FPR7_LO  0xD4 +#define PT_FPR8_HI  0xD8 +#define PT_FPR8_LO  0XDC +#define PT_FPR9_HI  0xE0 +#define PT_FPR9_LO  0xE4 +#define PT_FPR10_HI 0xE8 +#define PT_FPR10_LO 0xEC +#define PT_FPR11_HI 0xF0 +#define PT_FPR11_LO 0xF4 +#define PT_FPR12_HI 0xF8 +#define PT_FPR12_LO 0xFC +#define PT_FPR13_HI 0x100 +#define PT_FPR13_LO 0x104 +#define PT_FPR14_HI 0x108 +#define PT_FPR14_LO 0x10C +#define PT_FPR15_HI 0x110 +#define PT_FPR15_LO 0x114 +#define PT_CR_9	    0x118 +#define PT_CR_10    0x11C +#define PT_CR_11    0x120 +#define PT_IEEE_IP  0x13C +#define PT_LASTOFF  PT_IEEE_IP +#define PT_ENDREGS  0x140-1 + +#define GPR_SIZE	4 +#define CR_SIZE		4 + +#define STACK_FRAME_OVERHEAD	96	/* size of minimum stack frame */ + +#else /* __s390x__ */ + +#define PT_PSWMASK  0x00 +#define PT_PSWADDR  0x08 +#define PT_GPR0     0x10 +#define PT_GPR1     0x18 +#define PT_GPR2     0x20 +#define PT_GPR3     0x28 +#define PT_GPR4     0x30 +#define PT_GPR5     0x38 +#define PT_GPR6     0x40 +#define PT_GPR7     0x48 +#define PT_GPR8     0x50 +#define PT_GPR9     0x58 +#define PT_GPR10    0x60 +#define PT_GPR11    0x68 +#define PT_GPR12    0x70 +#define PT_GPR13    0x78 +#define PT_GPR14    0x80 +#define PT_GPR15    0x88 +#define PT_ACR0     0x90 +#define PT_ACR1     0x94 +#define PT_ACR2     0x98 +#define PT_ACR3     0x9C +#define PT_ACR4	    0xA0 +#define PT_ACR5	    0xA4 +#define PT_ACR6	    0xA8 +#define PT_ACR7	    0xAC +#define PT_ACR8	    0xB0 +#define PT_ACR9	    0xB4 +#define PT_ACR10    0xB8 +#define PT_ACR11    0xBC +#define PT_ACR12    0xC0 +#define PT_ACR13    0xC4 +#define PT_ACR14    0xC8 +#define PT_ACR15    0xCC +#define PT_ORIGGPR2 0xD0 +#define PT_FPC	    0xD8 +#define PT_FPR0     0xE0 +#define PT_FPR1     0xE8 +#define PT_FPR2     0xF0 +#define PT_FPR3     0xF8 +#define PT_FPR4     0x100 +#define PT_FPR5     0x108 +#define PT_FPR6     0x110 +#define PT_FPR7     0x118 +#define PT_FPR8     0x120 +#define PT_FPR9     0x128 +#define PT_FPR10    0x130 +#define PT_FPR11    0x138 +#define PT_FPR12    0x140 +#define PT_FPR13    0x148 +#define PT_FPR14    0x150 +#define PT_FPR15    0x158 +#define PT_CR_9     0x160 +#define PT_CR_10    0x168 +#define PT_CR_11    0x170 +#define PT_IEEE_IP  0x1A8 +#define PT_LASTOFF  PT_IEEE_IP +#define PT_ENDREGS  0x1B0-1 + +#define GPR_SIZE	8 +#define CR_SIZE		8 + +#define STACK_FRAME_OVERHEAD    160      /* size of minimum stack frame */ + +#endif /* __s390x__ */ + +#define NUM_GPRS	16 +#define NUM_FPRS	16 +#define NUM_CRS		16 +#define NUM_ACRS	16 + +#define NUM_CR_WORDS	3 + +#define FPR_SIZE	8 +#define FPC_SIZE	4 +#define FPC_PAD_SIZE	4 /* gcc insists on aligning the fpregs */ +#define ACR_SIZE	4 + + +#define PTRACE_OLDSETOPTIONS         21 + +#ifndef __ASSEMBLY__ +#include <linux/stddef.h> +#include <linux/types.h> + +typedef union +{ +	float   f; +	double  d; +        __u64   ui; +	struct +	{ +		__u32 hi; +		__u32 lo; +	} fp; +} freg_t; + +typedef struct +{ +	__u32   fpc; +	__u32	pad; +	freg_t  fprs[NUM_FPRS];               +} s390_fp_regs; + +#define FPC_EXCEPTION_MASK      0xF8000000 +#define FPC_FLAGS_MASK          0x00F80000 +#define FPC_DXC_MASK            0x0000FF00 +#define FPC_RM_MASK             0x00000003 + +/* this typedef defines how a Program Status Word looks like */ +typedef struct  +{ +        unsigned long mask; +        unsigned long addr; +} __attribute__ ((aligned(8))) psw_t; + +#ifndef __s390x__ + +#define PSW_MASK_PER		0x40000000UL +#define PSW_MASK_DAT		0x04000000UL +#define PSW_MASK_IO		0x02000000UL +#define PSW_MASK_EXT		0x01000000UL +#define PSW_MASK_KEY		0x00F00000UL +#define PSW_MASK_BASE		0x00080000UL	/* always one */ +#define PSW_MASK_MCHECK		0x00040000UL +#define PSW_MASK_WAIT		0x00020000UL +#define PSW_MASK_PSTATE		0x00010000UL +#define PSW_MASK_ASC		0x0000C000UL +#define PSW_MASK_CC		0x00003000UL +#define PSW_MASK_PM		0x00000F00UL +#define PSW_MASK_RI		0x00000000UL +#define PSW_MASK_EA		0x00000000UL +#define PSW_MASK_BA		0x00000000UL + +#define PSW_MASK_USER		0x0000FF00UL + +#define PSW_ADDR_AMODE		0x80000000UL +#define PSW_ADDR_INSN		0x7FFFFFFFUL + +#define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 20) + +#define PSW_ASC_PRIMARY		0x00000000UL +#define PSW_ASC_ACCREG		0x00004000UL +#define PSW_ASC_SECONDARY	0x00008000UL +#define PSW_ASC_HOME		0x0000C000UL + +#else /* __s390x__ */ + +#define PSW_MASK_PER		0x4000000000000000UL +#define PSW_MASK_DAT		0x0400000000000000UL +#define PSW_MASK_IO		0x0200000000000000UL +#define PSW_MASK_EXT		0x0100000000000000UL +#define PSW_MASK_BASE		0x0000000000000000UL +#define PSW_MASK_KEY		0x00F0000000000000UL +#define PSW_MASK_MCHECK		0x0004000000000000UL +#define PSW_MASK_WAIT		0x0002000000000000UL +#define PSW_MASK_PSTATE		0x0001000000000000UL +#define PSW_MASK_ASC		0x0000C00000000000UL +#define PSW_MASK_CC		0x0000300000000000UL +#define PSW_MASK_PM		0x00000F0000000000UL +#define PSW_MASK_RI		0x0000008000000000UL +#define PSW_MASK_EA		0x0000000100000000UL +#define PSW_MASK_BA		0x0000000080000000UL + +#define PSW_MASK_USER		0x0000FF0180000000UL + +#define PSW_ADDR_AMODE		0x0000000000000000UL +#define PSW_ADDR_INSN		0xFFFFFFFFFFFFFFFFUL + +#define PSW_DEFAULT_KEY		(((unsigned long) PAGE_DEFAULT_ACC) << 52) + +#define PSW_ASC_PRIMARY		0x0000000000000000UL +#define PSW_ASC_ACCREG		0x0000400000000000UL +#define PSW_ASC_SECONDARY	0x0000800000000000UL +#define PSW_ASC_HOME		0x0000C00000000000UL + +#endif /* __s390x__ */ + + +/* + * The s390_regs structure is used to define the elf_gregset_t. + */ +typedef struct +{ +	psw_t psw; +	unsigned long gprs[NUM_GPRS]; +	unsigned int  acrs[NUM_ACRS]; +	unsigned long orig_gpr2; +} s390_regs; + +/* + * Now for the user space program event recording (trace) definitions. + * The following structures are used only for the ptrace interface, don't + * touch or even look at it if you don't want to modify the user-space + * ptrace interface. In particular stay away from it for in-kernel PER. + */ +typedef struct +{ +	unsigned long cr[NUM_CR_WORDS]; +} per_cr_words; + +#define PER_EM_MASK 0xE8000000UL + +typedef	struct +{ +#ifdef __s390x__ +	unsigned                       : 32; +#endif /* __s390x__ */ +	unsigned em_branching          : 1; +	unsigned em_instruction_fetch  : 1; +	/* +	 * Switching on storage alteration automatically fixes +	 * the storage alteration event bit in the users std. +	 */ +	unsigned em_storage_alteration : 1; +	unsigned em_gpr_alt_unused     : 1; +	unsigned em_store_real_address : 1; +	unsigned                       : 3; +	unsigned branch_addr_ctl       : 1; +	unsigned                       : 1; +	unsigned storage_alt_space_ctl : 1; +	unsigned                       : 21; +	unsigned long starting_addr; +	unsigned long ending_addr; +} per_cr_bits; + +typedef struct +{ +	unsigned short perc_atmid; +	unsigned long address; +	unsigned char access_id; +} per_lowcore_words; + +typedef struct +{ +	unsigned perc_branching          : 1; +	unsigned perc_instruction_fetch  : 1; +	unsigned perc_storage_alteration : 1; +	unsigned perc_gpr_alt_unused     : 1; +	unsigned perc_store_real_address : 1; +	unsigned                         : 3; +	unsigned atmid_psw_bit_31        : 1; +	unsigned atmid_validity_bit      : 1; +	unsigned atmid_psw_bit_32        : 1; +	unsigned atmid_psw_bit_5         : 1; +	unsigned atmid_psw_bit_16        : 1; +	unsigned atmid_psw_bit_17        : 1; +	unsigned si                      : 2; +	unsigned long address; +	unsigned                         : 4; +	unsigned access_id               : 4; +} per_lowcore_bits; + +typedef struct +{ +	union { +		per_cr_words   words; +		per_cr_bits    bits; +	} control_regs; +	/* +	 * Use these flags instead of setting em_instruction_fetch +	 * directly they are used so that single stepping can be +	 * switched on & off while not affecting other tracing +	 */ +	unsigned  single_step       : 1; +	unsigned  instruction_fetch : 1; +	unsigned                    : 30; +	/* +	 * These addresses are copied into cr10 & cr11 if single +	 * stepping is switched off +	 */ +	unsigned long starting_addr; +	unsigned long ending_addr; +	union { +		per_lowcore_words words; +		per_lowcore_bits  bits; +	} lowcore;  +} per_struct; + +typedef struct +{ +	unsigned int  len; +	unsigned long kernel_addr; +	unsigned long process_addr; +} ptrace_area; + +/* + * S/390 specific non posix ptrace requests. I chose unusual values so + * they are unlikely to clash with future ptrace definitions. + */ +#define PTRACE_PEEKUSR_AREA           0x5000 +#define PTRACE_POKEUSR_AREA           0x5001 +#define PTRACE_PEEKTEXT_AREA	      0x5002 +#define PTRACE_PEEKDATA_AREA	      0x5003 +#define PTRACE_POKETEXT_AREA	      0x5004 +#define PTRACE_POKEDATA_AREA 	      0x5005 +#define PTRACE_GET_LAST_BREAK	      0x5006 +#define PTRACE_PEEK_SYSTEM_CALL       0x5007 +#define PTRACE_POKE_SYSTEM_CALL	      0x5008 +#define PTRACE_ENABLE_TE	      0x5009 +#define PTRACE_DISABLE_TE	      0x5010 +#define PTRACE_TE_ABORT_RAND	      0x5011 + +/* + * The numbers chosen here are somewhat arbitrary but absolutely MUST + * not overlap with any of the number assigned in <linux/ptrace.h>. + */ +#define PTRACE_SINGLEBLOCK	12	/* resume execution until next branch */ + +/* + * PT_PROT definition is loosely based on hppa bsd definition in + * gdb/hppab-nat.c + */ +#define PTRACE_PROT                       21 + +typedef enum +{ +	ptprot_set_access_watchpoint, +	ptprot_set_write_watchpoint, +	ptprot_disable_watchpoint +} ptprot_flags; + +typedef struct +{ +	unsigned long lowaddr; +	unsigned long hiaddr; +	ptprot_flags prot; +} ptprot_area;                      + +/* Sequence of bytes for breakpoint illegal instruction.  */ +#define S390_BREAKPOINT     {0x0,0x1} +#define S390_BREAKPOINT_U16 ((__u16)0x0001) +#define S390_SYSCALL_OPCODE ((__u16)0x0a00) +#define S390_SYSCALL_SIZE   2 + +/* + * The user_regs_struct defines the way the user registers are + * store on the stack for signal handling. + */ +struct user_regs_struct +{ +	psw_t psw; +	unsigned long gprs[NUM_GPRS]; +	unsigned int  acrs[NUM_ACRS]; +	unsigned long orig_gpr2; +	s390_fp_regs fp_regs; +	/* +	 * These per registers are in here so that gdb can modify them +	 * itself as there is no "official" ptrace interface for hardware +	 * watchpoints. This is the way intel does it. +	 */ +	per_struct per_info; +	unsigned long ieee_instruction_pointer;	/* obsolete, always 0 */ +}; + +#endif /* __ASSEMBLY__ */ + +#endif /* _UAPI_S390_PTRACE_H */ diff --git a/arch/s390/include/asm/qeth.h b/arch/s390/include/uapi/asm/qeth.h index 06cbd1e8c94..3a896cf5258 100644 --- a/arch/s390/include/asm/qeth.h +++ b/arch/s390/include/uapi/asm/qeth.h @@ -1,9 +1,7 @@  /* - * include/asm-s390/qeth.h - *   * ioctl definitions for qeth driver   * - * Copyright (C) 2004 IBM Corporation + * Copyright IBM Corp. 2004   *   * Author(s):	Thomas Spatzier <tspat@de.ibm.com>   * @@ -20,6 +18,7 @@  #define SIOC_QETH_ARP_FLUSH_CACHE       (SIOCDEVPRIVATE + 4)  #define SIOC_QETH_ADP_SET_SNMP_CONTROL  (SIOCDEVPRIVATE + 5)  #define SIOC_QETH_GET_CARD_TYPE         (SIOCDEVPRIVATE + 6) +#define SIOC_QETH_QUERY_OAT		(SIOCDEVPRIVATE + 7)  struct qeth_arp_cache_entry {  	__u8  macaddr[6]; @@ -28,39 +27,70 @@ struct qeth_arp_cache_entry {  	__u8  reserved2[32];  } __attribute__ ((packed)); +enum qeth_arp_ipaddrtype { +	QETHARP_IP_ADDR_V4 = 1, +	QETHARP_IP_ADDR_V6 = 2, +}; +struct qeth_arp_entrytype { +	__u8 mac; +	__u8 ip; +} __attribute__((packed)); + +#define QETH_QARP_MEDIASPECIFIC_BYTES 32 +#define QETH_QARP_MACADDRTYPE_BYTES 1  struct qeth_arp_qi_entry7 { -	__u8 media_specific[32]; -	__u8 macaddr_type; -	__u8 ipaddr_type; +	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; +	struct qeth_arp_entrytype type;  	__u8 macaddr[6];  	__u8 ipaddr[4];  } __attribute__((packed)); +struct qeth_arp_qi_entry7_ipv6 { +	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; +	struct qeth_arp_entrytype type; +	__u8 macaddr[6]; +	__u8 ipaddr[16]; +} __attribute__((packed)); +  struct qeth_arp_qi_entry7_short { -	__u8 macaddr_type; -	__u8 ipaddr_type; +	struct qeth_arp_entrytype type;  	__u8 macaddr[6];  	__u8 ipaddr[4];  } __attribute__((packed)); +struct qeth_arp_qi_entry7_short_ipv6 { +	struct qeth_arp_entrytype type; +	__u8 macaddr[6]; +	__u8 ipaddr[16]; +} __attribute__((packed)); +  struct qeth_arp_qi_entry5 { -	__u8 media_specific[32]; -	__u8 macaddr_type; -	__u8 ipaddr_type; +	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; +	struct qeth_arp_entrytype type;  	__u8 ipaddr[4];  } __attribute__((packed)); +struct qeth_arp_qi_entry5_ipv6 { +	__u8 media_specific[QETH_QARP_MEDIASPECIFIC_BYTES]; +	struct qeth_arp_entrytype type; +	__u8 ipaddr[16]; +} __attribute__((packed)); +  struct qeth_arp_qi_entry5_short { -	__u8 macaddr_type; -	__u8 ipaddr_type; +	struct qeth_arp_entrytype type;  	__u8 ipaddr[4];  } __attribute__((packed)); +struct qeth_arp_qi_entry5_short_ipv6 { +	struct qeth_arp_entrytype type; +	__u8 ipaddr[16]; +} __attribute__((packed));  /*   * can be set by user if no "media specific information" is wanted   * -> saves a lot of space in user space buffer   */  #define QETH_QARP_STRIP_ENTRIES  0x8000 +#define QETH_QARP_WITH_IPV6	 0x4000  #define QETH_QARP_REQUEST_MASK   0x00ff  /* data sent to user space as result of query arp ioctl */ @@ -76,4 +106,10 @@ struct qeth_arp_query_user_data {  	char *entries;  } __attribute__((packed)); +struct qeth_query_oat_data { +	__u32 command; +	__u32 buffer_len; +	__u32 response_len; +	__u64 ptr; +};  #endif /* __ASM_S390_QETH_IOCTL_H__ */ diff --git a/arch/s390/include/asm/resource.h b/arch/s390/include/uapi/asm/resource.h index 366c01de04f..ec23d1c73c9 100644 --- a/arch/s390/include/asm/resource.h +++ b/arch/s390/include/uapi/asm/resource.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/resource.h - *   *  S390 version   *   *  Derived from "include/asm-i386/resources.h" diff --git a/arch/s390/include/uapi/asm/schid.h b/arch/s390/include/uapi/asm/schid.h new file mode 100644 index 00000000000..32f3ab2a820 --- /dev/null +++ b/arch/s390/include/uapi/asm/schid.h @@ -0,0 +1,16 @@ +#ifndef _UAPIASM_SCHID_H +#define _UAPIASM_SCHID_H + +#include <linux/types.h> + +struct subchannel_id { +	__u32 cssid : 8; +	__u32 : 4; +	__u32 m : 1; +	__u32 ssid : 2; +	__u32 one : 1; +	__u32 sch_no : 16; +} __attribute__ ((packed, aligned(4))); + + +#endif /* _UAPIASM_SCHID_H */ diff --git a/arch/s390/include/uapi/asm/sclp_ctl.h b/arch/s390/include/uapi/asm/sclp_ctl.h new file mode 100644 index 00000000000..f2818613ee4 --- /dev/null +++ b/arch/s390/include/uapi/asm/sclp_ctl.h @@ -0,0 +1,24 @@ +/* + * IOCTL interface for SCLP + * + * Copyright IBM Corp. 2012 + * + * Author: Michael Holzheu <holzheu@linux.vnet.ibm.com> + */ + +#ifndef _ASM_SCLP_CTL_H +#define _ASM_SCLP_CTL_H + +#include <linux/types.h> + +struct sclp_ctl_sccb { +	__u32	cmdw; +	__u64	sccb; +} __attribute__((packed)); + +#define SCLP_CTL_IOCTL_MAGIC 0x10 + +#define SCLP_CTL_SCCB \ +	_IOWR(SCLP_CTL_IOCTL_MAGIC, 0x10, struct sclp_ctl_sccb) + +#endif diff --git a/arch/s390/include/asm/sembuf.h b/arch/s390/include/uapi/asm/sembuf.h index 32626b0cac4..32626b0cac4 100644 --- a/arch/s390/include/asm/sembuf.h +++ b/arch/s390/include/uapi/asm/sembuf.h diff --git a/arch/s390/include/uapi/asm/setup.h b/arch/s390/include/uapi/asm/setup.h new file mode 100644 index 00000000000..5a637e3e385 --- /dev/null +++ b/arch/s390/include/uapi/asm/setup.h @@ -0,0 +1,13 @@ +/* + *  S390 version + *    Copyright IBM Corp. 1999, 2010 + */ + +#ifndef _UAPI_ASM_S390_SETUP_H +#define _UAPI_ASM_S390_SETUP_H + +#define COMMAND_LINE_SIZE	4096 + +#define ARCH_COMMAND_LINE_SIZE	896 + +#endif /* _UAPI_ASM_S390_SETUP_H */ diff --git a/arch/s390/include/asm/shmbuf.h b/arch/s390/include/uapi/asm/shmbuf.h index eed2e280ce3..eed2e280ce3 100644 --- a/arch/s390/include/asm/shmbuf.h +++ b/arch/s390/include/uapi/asm/shmbuf.h diff --git a/arch/s390/include/uapi/asm/sie.h b/arch/s390/include/uapi/asm/sie.h new file mode 100644 index 00000000000..5d9cc19462c --- /dev/null +++ b/arch/s390/include/uapi/asm/sie.h @@ -0,0 +1,243 @@ +#ifndef _UAPI_ASM_S390_SIE_H +#define _UAPI_ASM_S390_SIE_H + +#define diagnose_codes						\ +	{ 0x10, "DIAG (0x10) release pages" },			\ +	{ 0x44, "DIAG (0x44) time slice end" },			\ +	{ 0x9c, "DIAG (0x9c) time slice end directed" },	\ +	{ 0x204, "DIAG (0x204) logical-cpu utilization" },	\ +	{ 0x258, "DIAG (0x258) page-reference services" },	\ +	{ 0x308, "DIAG (0x308) ipl functions" },		\ +	{ 0x500, "DIAG (0x500) KVM virtio functions" },		\ +	{ 0x501, "DIAG (0x501) KVM breakpoint" } + +#define sigp_order_codes					\ +	{ 0x01, "SIGP sense" },					\ +	{ 0x02, "SIGP external call" },				\ +	{ 0x03, "SIGP emergency signal" },			\ +	{ 0x05, "SIGP stop" },					\ +	{ 0x06, "SIGP restart" },				\ +	{ 0x09, "SIGP stop and store status" },			\ +	{ 0x0b, "SIGP initial cpu reset" },			\ +	{ 0x0d, "SIGP set prefix" },				\ +	{ 0x0e, "SIGP store status at address" },		\ +	{ 0x12, "SIGP set architecture" },			\ +	{ 0x15, "SIGP sense running" } + +#define icpt_prog_codes						\ +	{ 0x0001, "Prog Operation" },				\ +	{ 0x0002, "Prog Privileged Operation" },		\ +	{ 0x0003, "Prog Execute" },				\ +	{ 0x0004, "Prog Protection" },				\ +	{ 0x0005, "Prog Addressing" },				\ +	{ 0x0006, "Prog Specification" },			\ +	{ 0x0007, "Prog Data" },				\ +	{ 0x0008, "Prog Fixedpoint overflow" },			\ +	{ 0x0009, "Prog Fixedpoint divide" },			\ +	{ 0x000A, "Prog Decimal overflow" },			\ +	{ 0x000B, "Prog Decimal divide" },			\ +	{ 0x000C, "Prog HFP exponent overflow" },		\ +	{ 0x000D, "Prog HFP exponent underflow" },		\ +	{ 0x000E, "Prog HFP significance" },			\ +	{ 0x000F, "Prog HFP divide" },				\ +	{ 0x0010, "Prog Segment translation" },			\ +	{ 0x0011, "Prog Page translation" },			\ +	{ 0x0012, "Prog Translation specification" },		\ +	{ 0x0013, "Prog Special operation" },			\ +	{ 0x0015, "Prog Operand" },				\ +	{ 0x0016, "Prog Trace table" },				\ +	{ 0x0017, "Prog ASNtranslation specification" },	\ +	{ 0x001C, "Prog Spaceswitch event" },			\ +	{ 0x001D, "Prog HFP square root" },			\ +	{ 0x001F, "Prog PCtranslation specification" },		\ +	{ 0x0020, "Prog AFX translation" },			\ +	{ 0x0021, "Prog ASX translation" },			\ +	{ 0x0022, "Prog LX translation" },			\ +	{ 0x0023, "Prog EX translation" },			\ +	{ 0x0024, "Prog Primary authority" },			\ +	{ 0x0025, "Prog Secondary authority" },			\ +	{ 0x0026, "Prog LFXtranslation exception" },		\ +	{ 0x0027, "Prog LSXtranslation exception" },		\ +	{ 0x0028, "Prog ALET specification" },			\ +	{ 0x0029, "Prog ALEN translation" },			\ +	{ 0x002A, "Prog ALE sequence" },			\ +	{ 0x002B, "Prog ASTE validity" },			\ +	{ 0x002C, "Prog ASTE sequence" },			\ +	{ 0x002D, "Prog Extended authority" },			\ +	{ 0x002E, "Prog LSTE sequence" },			\ +	{ 0x002F, "Prog ASTE instance" },			\ +	{ 0x0030, "Prog Stack full" },				\ +	{ 0x0031, "Prog Stack empty" },				\ +	{ 0x0032, "Prog Stack specification" },			\ +	{ 0x0033, "Prog Stack type" },				\ +	{ 0x0034, "Prog Stack operation" },			\ +	{ 0x0039, "Prog Region first translation" },		\ +	{ 0x003A, "Prog Region second translation" },		\ +	{ 0x003B, "Prog Region third translation" },		\ +	{ 0x0040, "Prog Monitor event" },			\ +	{ 0x0080, "Prog PER event" },				\ +	{ 0x0119, "Prog Crypto operation" } + +#define exit_code_ipa0(ipa0, opcode, mnemonic)		\ +	{ (ipa0 << 8 | opcode), #ipa0 " " mnemonic } +#define exit_code(opcode, mnemonic)			\ +	{ opcode, mnemonic } + +#define icpt_insn_codes				\ +	exit_code_ipa0(0x01, 0x01, "PR"),	\ +	exit_code_ipa0(0x01, 0x04, "PTFF"),	\ +	exit_code_ipa0(0x01, 0x07, "SCKPF"),	\ +	exit_code_ipa0(0xAA, 0x00, "RINEXT"),	\ +	exit_code_ipa0(0xAA, 0x01, "RION"),	\ +	exit_code_ipa0(0xAA, 0x02, "TRIC"),	\ +	exit_code_ipa0(0xAA, 0x03, "RIOFF"),	\ +	exit_code_ipa0(0xAA, 0x04, "RIEMIT"),	\ +	exit_code_ipa0(0xB2, 0x02, "STIDP"),	\ +	exit_code_ipa0(0xB2, 0x04, "SCK"),	\ +	exit_code_ipa0(0xB2, 0x05, "STCK"),	\ +	exit_code_ipa0(0xB2, 0x06, "SCKC"),	\ +	exit_code_ipa0(0xB2, 0x07, "STCKC"),	\ +	exit_code_ipa0(0xB2, 0x08, "SPT"),	\ +	exit_code_ipa0(0xB2, 0x09, "STPT"),	\ +	exit_code_ipa0(0xB2, 0x0d, "PTLB"),	\ +	exit_code_ipa0(0xB2, 0x10, "SPX"),	\ +	exit_code_ipa0(0xB2, 0x11, "STPX"),	\ +	exit_code_ipa0(0xB2, 0x12, "STAP"),	\ +	exit_code_ipa0(0xB2, 0x14, "SIE"),	\ +	exit_code_ipa0(0xB2, 0x16, "SETR"),	\ +	exit_code_ipa0(0xB2, 0x17, "STETR"),	\ +	exit_code_ipa0(0xB2, 0x18, "PC"),	\ +	exit_code_ipa0(0xB2, 0x20, "SERVC"),	\ +	exit_code_ipa0(0xB2, 0x28, "PT"),	\ +	exit_code_ipa0(0xB2, 0x29, "ISKE"),	\ +	exit_code_ipa0(0xB2, 0x2a, "RRBE"),	\ +	exit_code_ipa0(0xB2, 0x2b, "SSKE"),	\ +	exit_code_ipa0(0xB2, 0x2c, "TB"),	\ +	exit_code_ipa0(0xB2, 0x2e, "PGIN"),	\ +	exit_code_ipa0(0xB2, 0x2f, "PGOUT"),	\ +	exit_code_ipa0(0xB2, 0x30, "CSCH"),	\ +	exit_code_ipa0(0xB2, 0x31, "HSCH"),	\ +	exit_code_ipa0(0xB2, 0x32, "MSCH"),	\ +	exit_code_ipa0(0xB2, 0x33, "SSCH"),	\ +	exit_code_ipa0(0xB2, 0x34, "STSCH"),	\ +	exit_code_ipa0(0xB2, 0x35, "TSCH"),	\ +	exit_code_ipa0(0xB2, 0x36, "TPI"),	\ +	exit_code_ipa0(0xB2, 0x37, "SAL"),	\ +	exit_code_ipa0(0xB2, 0x38, "RSCH"),	\ +	exit_code_ipa0(0xB2, 0x39, "STCRW"),	\ +	exit_code_ipa0(0xB2, 0x3a, "STCPS"),	\ +	exit_code_ipa0(0xB2, 0x3b, "RCHP"),	\ +	exit_code_ipa0(0xB2, 0x3c, "SCHM"),	\ +	exit_code_ipa0(0xB2, 0x40, "BAKR"),	\ +	exit_code_ipa0(0xB2, 0x48, "PALB"),	\ +	exit_code_ipa0(0xB2, 0x4c, "TAR"),	\ +	exit_code_ipa0(0xB2, 0x50, "CSP"),	\ +	exit_code_ipa0(0xB2, 0x54, "MVPG"),	\ +	exit_code_ipa0(0xB2, 0x58, "BSG"),	\ +	exit_code_ipa0(0xB2, 0x5a, "BSA"),	\ +	exit_code_ipa0(0xB2, 0x5f, "CHSC"),	\ +	exit_code_ipa0(0xB2, 0x74, "SIGA"),	\ +	exit_code_ipa0(0xB2, 0x76, "XSCH"),	\ +	exit_code_ipa0(0xB2, 0x78, "STCKE"),	\ +	exit_code_ipa0(0xB2, 0x7c, "STCKF"),	\ +	exit_code_ipa0(0xB2, 0x7d, "STSI"),	\ +	exit_code_ipa0(0xB2, 0xb0, "STFLE"),	\ +	exit_code_ipa0(0xB2, 0xb1, "STFL"),	\ +	exit_code_ipa0(0xB2, 0xb2, "LPSWE"),	\ +	exit_code_ipa0(0xB2, 0xf8, "TEND"),	\ +	exit_code_ipa0(0xB2, 0xfc, "TABORT"),	\ +	exit_code_ipa0(0xB9, 0x1e, "KMAC"),	\ +	exit_code_ipa0(0xB9, 0x28, "PCKMO"),	\ +	exit_code_ipa0(0xB9, 0x2a, "KMF"),	\ +	exit_code_ipa0(0xB9, 0x2b, "KMO"),	\ +	exit_code_ipa0(0xB9, 0x2d, "KMCTR"),	\ +	exit_code_ipa0(0xB9, 0x2e, "KM"),	\ +	exit_code_ipa0(0xB9, 0x2f, "KMC"),	\ +	exit_code_ipa0(0xB9, 0x3e, "KIMD"),	\ +	exit_code_ipa0(0xB9, 0x3f, "KLMD"),	\ +	exit_code_ipa0(0xB9, 0x8a, "CSPG"),	\ +	exit_code_ipa0(0xB9, 0x8d, "EPSW"),	\ +	exit_code_ipa0(0xB9, 0x8e, "IDTE"),	\ +	exit_code_ipa0(0xB9, 0x8f, "CRDTE"),	\ +	exit_code_ipa0(0xB9, 0x9c, "EQBS"),	\ +	exit_code_ipa0(0xB9, 0xa2, "PTF"),	\ +	exit_code_ipa0(0xB9, 0xab, "ESSA"),	\ +	exit_code_ipa0(0xB9, 0xae, "RRBM"),	\ +	exit_code_ipa0(0xB9, 0xaf, "PFMF"),	\ +	exit_code_ipa0(0xE3, 0x03, "LRAG"),	\ +	exit_code_ipa0(0xE3, 0x13, "LRAY"),	\ +	exit_code_ipa0(0xE3, 0x25, "NTSTG"),	\ +	exit_code_ipa0(0xE5, 0x00, "LASP"),	\ +	exit_code_ipa0(0xE5, 0x01, "TPROT"),	\ +	exit_code_ipa0(0xE5, 0x60, "TBEGIN"),	\ +	exit_code_ipa0(0xE5, 0x61, "TBEGINC"),	\ +	exit_code_ipa0(0xEB, 0x25, "STCTG"),	\ +	exit_code_ipa0(0xEB, 0x2f, "LCTLG"),	\ +	exit_code_ipa0(0xEB, 0x60, "LRIC"),	\ +	exit_code_ipa0(0xEB, 0x61, "STRIC"),	\ +	exit_code_ipa0(0xEB, 0x62, "MRIC"),	\ +	exit_code_ipa0(0xEB, 0x8a, "SQBS"),	\ +	exit_code_ipa0(0xC8, 0x01, "ECTG"),	\ +	exit_code(0x0a, "SVC"),			\ +	exit_code(0x80, "SSM"),			\ +	exit_code(0x82, "LPSW"),		\ +	exit_code(0x83, "DIAG"),		\ +	exit_code(0xae, "SIGP"),		\ +	exit_code(0xac, "STNSM"),		\ +	exit_code(0xad, "STOSM"),		\ +	exit_code(0xb1, "LRA"),			\ +	exit_code(0xb6, "STCTL"),		\ +	exit_code(0xb7, "LCTL"),		\ +	exit_code(0xee, "PLO") + +#define sie_intercept_code					\ +	{ 0x00, "Host interruption" },				\ +	{ 0x04, "Instruction" },				\ +	{ 0x08, "Program interruption" },			\ +	{ 0x0c, "Instruction and program interruption" },	\ +	{ 0x10, "External request" },				\ +	{ 0x14, "External interruption" },			\ +	{ 0x18, "I/O request" },				\ +	{ 0x1c, "Wait state" },					\ +	{ 0x20, "Validity" },					\ +	{ 0x28, "Stop request" },				\ +	{ 0x2c, "Operation exception" },			\ +	{ 0x38, "Partial-execution" },				\ +	{ 0x3c, "I/O interruption" },				\ +	{ 0x40, "I/O instruction" },				\ +	{ 0x48, "Timing subset" } + +/* + * This is the simple interceptable instructions decoder. + * + * It will be used as userspace interface and it can be used in places + * that does not allow to use general decoder functions, + * such as trace events declarations. + * + * Some userspace tools may want to parse this code + * and would be confused by switch(), if() and other statements, + * but they can understand conditional operator. + */ +#define INSN_DECODE_IPA0(ipa0, insn, rshift, mask)		\ +	(insn >> 56) == (ipa0) ?				\ +		((ipa0 << 8) | ((insn >> rshift) & mask)) : + +#define INSN_DECODE(insn) (insn >> 56) + +/* + * The macro icpt_insn_decoder() takes an intercepted instruction + * and returns a key, which can be used to find a mnemonic name + * of the instruction in the icpt_insn_codes table. + */ +#define icpt_insn_decoder(insn)			\ +	INSN_DECODE_IPA0(0x01, insn, 48, 0xff)	\ +	INSN_DECODE_IPA0(0xaa, insn, 48, 0x0f)	\ +	INSN_DECODE_IPA0(0xb2, insn, 48, 0xff)	\ +	INSN_DECODE_IPA0(0xb9, insn, 48, 0xff)	\ +	INSN_DECODE_IPA0(0xe3, insn, 48, 0xff)	\ +	INSN_DECODE_IPA0(0xe5, insn, 48, 0xff)	\ +	INSN_DECODE_IPA0(0xeb, insn, 16, 0xff)	\ +	INSN_DECODE_IPA0(0xc8, insn, 48, 0x0f)	\ +	INSN_DECODE(insn) + +#endif /* _UAPI_ASM_S390_SIE_H */ diff --git a/arch/s390/include/asm/sigcontext.h b/arch/s390/include/uapi/asm/sigcontext.h index aeb6e0b1332..b30de9c01bb 100644 --- a/arch/s390/include/asm/sigcontext.h +++ b/arch/s390/include/uapi/asm/sigcontext.h @@ -1,8 +1,6 @@  /* - *  include/asm-s390/sigcontext.h - *   *  S390 version - *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999, 2000   */  #ifndef _ASM_S390_SIGCONTEXT_H @@ -51,6 +49,7 @@ typedef struct  typedef struct  {  	unsigned int fpc; +	unsigned int pad;  	double   fprs[__NUM_FPRS];  } _s390_fp_regs; diff --git a/arch/s390/include/asm/siginfo.h b/arch/s390/include/uapi/asm/siginfo.h index e0ff1ab054b..91fd3e4b70c 100644 --- a/arch/s390/include/asm/siginfo.h +++ b/arch/s390/include/uapi/asm/siginfo.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/siginfo.h - *   *  S390 version   *   *  Derived from "include/asm-i386/siginfo.h" diff --git a/arch/s390/include/uapi/asm/signal.h b/arch/s390/include/uapi/asm/signal.h new file mode 100644 index 00000000000..2f43cfbf5f1 --- /dev/null +++ b/arch/s390/include/uapi/asm/signal.h @@ -0,0 +1,129 @@ +/* + *  S390 version + * + *  Derived from "include/asm-i386/signal.h" + */ + +#ifndef _UAPI_ASMS390_SIGNAL_H +#define _UAPI_ASMS390_SIGNAL_H + +#include <linux/types.h> +#include <linux/time.h> + +/* Avoid too many header ordering problems.  */ +struct siginfo; +struct pt_regs; + +#ifndef __KERNEL__ +/* Here we must cater to libcs that poke about in kernel headers.  */ + +#define NSIG            32 +typedef unsigned long sigset_t; + +#endif /* __KERNEL__ */ + +#define SIGHUP           1 +#define SIGINT           2 +#define SIGQUIT          3 +#define SIGILL           4 +#define SIGTRAP          5 +#define SIGABRT          6 +#define SIGIOT           6 +#define SIGBUS           7 +#define SIGFPE           8 +#define SIGKILL          9 +#define SIGUSR1         10 +#define SIGSEGV         11 +#define SIGUSR2         12 +#define SIGPIPE         13 +#define SIGALRM         14 +#define SIGTERM         15 +#define SIGSTKFLT       16 +#define SIGCHLD         17 +#define SIGCONT         18 +#define SIGSTOP         19 +#define SIGTSTP         20 +#define SIGTTIN         21 +#define SIGTTOU         22 +#define SIGURG          23 +#define SIGXCPU         24 +#define SIGXFSZ         25 +#define SIGVTALRM       26 +#define SIGPROF         27 +#define SIGWINCH        28 +#define SIGIO           29 +#define SIGPOLL         SIGIO +/* +#define SIGLOST         29 +*/ +#define SIGPWR          30 +#define SIGSYS		31 +#define SIGUNUSED       31 + +/* These should not be considered constants from userland.  */ +#define SIGRTMIN        32 +#define SIGRTMAX        _NSIG + +/* + * SA_FLAGS values: + * + * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_RESTART flag to get restarting signals (which were the default long ago) + * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. + * SA_RESETHAND clears the handler when the signal is delivered. + * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. + * SA_NODEFER prevents the current signal from being masked in the handler. + * + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single + * Unix names RESETHAND and NODEFER respectively. + */ +#define SA_NOCLDSTOP    0x00000001 +#define SA_NOCLDWAIT    0x00000002 +#define SA_SIGINFO      0x00000004 +#define SA_ONSTACK      0x08000000 +#define SA_RESTART      0x10000000 +#define SA_NODEFER      0x40000000 +#define SA_RESETHAND    0x80000000 + +#define SA_NOMASK       SA_NODEFER +#define SA_ONESHOT      SA_RESETHAND + +#define SA_RESTORER     0x04000000 + +#define MINSIGSTKSZ     2048 +#define SIGSTKSZ        8192 + +#include <asm-generic/signal-defs.h> + +#ifndef __KERNEL__ +/* Here we must cater to libcs that poke about in kernel headers.  */ + +struct sigaction { +        union { +          __sighandler_t _sa_handler; +          void (*_sa_sigaction)(int, struct siginfo *, void *); +        } _u; +#ifndef __s390x__ /* lovely */ +        sigset_t sa_mask; +        unsigned long sa_flags; +        void (*sa_restorer)(void); +#else  /* __s390x__ */ +        unsigned long sa_flags; +        void (*sa_restorer)(void); +	sigset_t sa_mask; +#endif /* __s390x__ */ +}; + +#define sa_handler      _u._sa_handler +#define sa_sigaction    _u._sa_sigaction + +#endif /* __KERNEL__ */ + +typedef struct sigaltstack { +        void __user *ss_sp; +        int ss_flags; +        size_t ss_size; +} stack_t; + + +#endif /* _UAPI_ASMS390_SIGNAL_H */ diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/uapi/asm/socket.h index fdff1e995c7..e031332096d 100644 --- a/arch/s390/include/asm/socket.h +++ b/arch/s390/include/uapi/asm/socket.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/socket.h - *   *  S390 version   *   *  Derived from "include/asm-i386/socket.h" @@ -30,7 +28,7 @@  #define SO_PRIORITY	12  #define SO_LINGER	13  #define SO_BSDCOMPAT	14 -/* To add :#define SO_REUSEPORT 15 */ +#define SO_REUSEPORT	15  #define SO_PASSCRED	16  #define SO_PEERCRED	17  #define SO_RCVLOWAT	18 @@ -48,6 +46,7 @@  /* Socket filtering */  #define SO_ATTACH_FILTER        26  #define SO_DETACH_FILTER        27 +#define SO_GET_FILTER		SO_ATTACH_FILTER  #define SO_PEERNAME		28  #define SO_TIMESTAMP		29 @@ -70,4 +69,21 @@  #define SO_RXQ_OVFL             40 +#define SO_WIFI_STATUS		41 +#define SCM_WIFI_STATUS		SO_WIFI_STATUS +#define SO_PEEK_OFF		42 + +/* Instruct lower device to use last 4-bytes of skb data as FCS */ +#define SO_NOFCS		43 + +#define SO_LOCK_FILTER		44 + +#define SO_SELECT_ERR_QUEUE	45 + +#define SO_BUSY_POLL		46 + +#define SO_MAX_PACING_RATE	47 + +#define SO_BPF_EXTENSIONS	48 +  #endif /* _ASM_SOCKET_H */ diff --git a/arch/s390/include/asm/sockios.h b/arch/s390/include/uapi/asm/sockios.h index 6f60eee7324..6f60eee7324 100644 --- a/arch/s390/include/asm/sockios.h +++ b/arch/s390/include/uapi/asm/sockios.h diff --git a/arch/s390/include/asm/stat.h b/arch/s390/include/uapi/asm/stat.h index d92959eebb6..b4ca97d9146 100644 --- a/arch/s390/include/asm/stat.h +++ b/arch/s390/include/uapi/asm/stat.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/stat.h - *   *  S390 version   *   *  Derived from "include/asm-i386/stat.h" diff --git a/arch/s390/include/uapi/asm/statfs.h b/arch/s390/include/uapi/asm/statfs.h new file mode 100644 index 00000000000..471eb09184d --- /dev/null +++ b/arch/s390/include/uapi/asm/statfs.h @@ -0,0 +1,50 @@ +/* + *  S390 version + * + *  Derived from "include/asm-i386/statfs.h" + */ + +#ifndef _S390_STATFS_H +#define _S390_STATFS_H + +/* + * We can't use <asm-generic/statfs.h> because in 64-bit mode + * we mix ints of different sizes in our struct statfs. + */ + +#ifndef __KERNEL_STRICT_NAMES +#include <linux/types.h> +typedef __kernel_fsid_t	fsid_t; +#endif + +struct statfs { +	unsigned int	f_type; +	unsigned int	f_bsize; +	unsigned long	f_blocks; +	unsigned long	f_bfree; +	unsigned long	f_bavail; +	unsigned long	f_files; +	unsigned long	f_ffree; +	__kernel_fsid_t f_fsid; +	unsigned int	f_namelen; +	unsigned int	f_frsize; +	unsigned int	f_flags; +	unsigned int	f_spare[4]; +}; + +struct statfs64 { +	unsigned int	f_type; +	unsigned int	f_bsize; +	unsigned long long f_blocks; +	unsigned long long f_bfree; +	unsigned long long f_bavail; +	unsigned long long f_files; +	unsigned long long f_ffree; +	__kernel_fsid_t f_fsid; +	unsigned int	f_namelen; +	unsigned int	f_frsize; +	unsigned int	f_flags; +	unsigned int	f_spare[4]; +}; + +#endif diff --git a/arch/s390/include/asm/swab.h b/arch/s390/include/uapi/asm/swab.h index 6bdee21c077..da3bfe5cc16 100644 --- a/arch/s390/include/asm/swab.h +++ b/arch/s390/include/uapi/asm/swab.h @@ -2,10 +2,8 @@  #define _S390_SWAB_H  /* - *  include/asm-s390/swab.h - *   *  S390 version - *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + *    Copyright IBM Corp. 1999   *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)   */ @@ -77,7 +75,7 @@ static inline __u16 __arch_swab16p(const __u16 *x)  	asm volatile(  #ifndef __s390x__ -		"	icm	%0,2,%O+1(%R1)\n" +		"	icm	%0,2,%O1+1(%R1)\n"  		"	ic	%0,%1\n"  		: "=&d" (result) : "Q" (*x) : "cc");  #else /* __s390x__ */ diff --git a/arch/s390/include/asm/tape390.h b/arch/s390/include/uapi/asm/tape390.h index 884fba48f1f..b2bc4bab792 100644 --- a/arch/s390/include/asm/tape390.h +++ b/arch/s390/include/uapi/asm/tape390.h @@ -1,10 +1,9 @@  /*************************************************************************   * - * tape390.h   *	   enables user programs to display messages and control encryption   *	   on s390 tape devices   * - *	   Copyright IBM Corp. 2001,2006 + *	   Copyright IBM Corp. 2001, 2006   *	   Author(s): Michael Holzheu <holzheu@de.ibm.com>   *   *************************************************************************/ diff --git a/arch/s390/include/asm/termbits.h b/arch/s390/include/uapi/asm/termbits.h index 71bf6ac6a2b..71bf6ac6a2b 100644 --- a/arch/s390/include/asm/termbits.h +++ b/arch/s390/include/uapi/asm/termbits.h diff --git a/arch/s390/include/uapi/asm/termios.h b/arch/s390/include/uapi/asm/termios.h new file mode 100644 index 00000000000..554f973db1e --- /dev/null +++ b/arch/s390/include/uapi/asm/termios.h @@ -0,0 +1,49 @@ +/* + *  S390 version + * + *  Derived from "include/asm-i386/termios.h" + */ + +#ifndef _UAPI_S390_TERMIOS_H +#define _UAPI_S390_TERMIOS_H + +#include <asm/termbits.h> +#include <asm/ioctls.h> + +struct winsize { +	unsigned short ws_row; +	unsigned short ws_col; +	unsigned short ws_xpixel; +	unsigned short ws_ypixel; +}; + +#define NCC 8 +struct termio { +	unsigned short c_iflag;		/* input mode flags */ +	unsigned short c_oflag;		/* output mode flags */ +	unsigned short c_cflag;		/* control mode flags */ +	unsigned short c_lflag;		/* local mode flags */ +	unsigned char c_line;		/* line discipline */ +	unsigned char c_cc[NCC];	/* control characters */ +}; + +/* modem lines */ +#define TIOCM_LE	0x001 +#define TIOCM_DTR	0x002 +#define TIOCM_RTS	0x004 +#define TIOCM_ST	0x008 +#define TIOCM_SR	0x010 +#define TIOCM_CTS	0x020 +#define TIOCM_CAR	0x040 +#define TIOCM_RNG	0x080 +#define TIOCM_DSR	0x100 +#define TIOCM_CD	TIOCM_CAR +#define TIOCM_RI	TIOCM_RNG +#define TIOCM_OUT1	0x2000 +#define TIOCM_OUT2	0x4000 +#define TIOCM_LOOP	0x8000 + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + + +#endif /* _UAPI_S390_TERMIOS_H */ diff --git a/arch/s390/include/uapi/asm/types.h b/arch/s390/include/uapi/asm/types.h new file mode 100644 index 00000000000..038f2b9178a --- /dev/null +++ b/arch/s390/include/uapi/asm/types.h @@ -0,0 +1,22 @@ +/* + *  S390 version + * + *  Derived from "include/asm-i386/types.h" + */ + +#ifndef _UAPI_S390_TYPES_H +#define _UAPI_S390_TYPES_H + +#include <asm-generic/int-ll64.h> + +#ifndef __ASSEMBLY__ + +/* A address type so that arithmetic can be done on it & it can be upgraded to +   64 bit when necessary  +*/ +typedef unsigned long addr_t;  +typedef __signed__ long saddr_t; + +#endif /* __ASSEMBLY__ */ + +#endif /* _UAPI_S390_TYPES_H */ diff --git a/arch/s390/include/asm/ucontext.h b/arch/s390/include/uapi/asm/ucontext.h index cfb874e66c9..3e077b2a470 100644 --- a/arch/s390/include/asm/ucontext.h +++ b/arch/s390/include/uapi/asm/ucontext.h @@ -1,6 +1,4 @@  /* - *  include/asm-s390/ucontext.h - *   *  S390 version   *   *  Derived from "include/asm-i386/ucontext.h" @@ -18,7 +16,9 @@ struct ucontext_extended {  	struct ucontext  *uc_link;  	stack_t		  uc_stack;  	_sigregs	  uc_mcontext; -	unsigned long	  uc_sigmask[2]; +	sigset_t	  uc_sigmask; +	/* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */ +	unsigned char	  __unused[128 - sizeof(sigset_t)];  	unsigned long	  uc_gprs_high[16];  }; @@ -29,7 +29,9 @@ struct ucontext {  	struct ucontext  *uc_link;  	stack_t		  uc_stack;  	_sigregs          uc_mcontext; -	sigset_t	  uc_sigmask;	/* mask last for extensibility */ +	sigset_t	  uc_sigmask; +	/* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */ +	unsigned char	  __unused[128 - sizeof(sigset_t)];  };  #endif /* !_ASM_S390_UCONTEXT_H */ diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h new file mode 100644 index 00000000000..3802d2d3a18 --- /dev/null +++ b/arch/s390/include/uapi/asm/unistd.h @@ -0,0 +1,378 @@ +/* + *  S390 version + * + *  Derived from "include/asm-i386/unistd.h" + */ + +#ifndef _UAPI_ASM_S390_UNISTD_H_ +#define _UAPI_ASM_S390_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +#define __NR_exit                 1 +#define __NR_fork                 2 +#define __NR_read                 3 +#define __NR_write                4 +#define __NR_open                 5 +#define __NR_close                6 +#define __NR_restart_syscall	  7 +#define __NR_creat                8 +#define __NR_link                 9 +#define __NR_unlink              10 +#define __NR_execve              11 +#define __NR_chdir               12 +#define __NR_mknod               14 +#define __NR_chmod               15 +#define __NR_lseek               19 +#define __NR_getpid              20 +#define __NR_mount               21 +#define __NR_umount              22 +#define __NR_ptrace              26 +#define __NR_alarm               27 +#define __NR_pause               29 +#define __NR_utime               30 +#define __NR_access              33 +#define __NR_nice                34 +#define __NR_sync                36 +#define __NR_kill                37 +#define __NR_rename              38 +#define __NR_mkdir               39 +#define __NR_rmdir               40 +#define __NR_dup                 41 +#define __NR_pipe                42 +#define __NR_times               43 +#define __NR_brk                 45 +#define __NR_signal              48 +#define __NR_acct                51 +#define __NR_umount2             52 +#define __NR_ioctl               54 +#define __NR_fcntl               55 +#define __NR_setpgid             57 +#define __NR_umask               60 +#define __NR_chroot              61 +#define __NR_ustat               62 +#define __NR_dup2                63 +#define __NR_getppid             64 +#define __NR_getpgrp             65 +#define __NR_setsid              66 +#define __NR_sigaction           67 +#define __NR_sigsuspend          72 +#define __NR_sigpending          73 +#define __NR_sethostname         74 +#define __NR_setrlimit           75 +#define __NR_getrusage           77 +#define __NR_gettimeofday        78 +#define __NR_settimeofday        79 +#define __NR_symlink             83 +#define __NR_readlink            85 +#define __NR_uselib              86 +#define __NR_swapon              87 +#define __NR_reboot              88 +#define __NR_readdir             89 +#define __NR_mmap                90 +#define __NR_munmap              91 +#define __NR_truncate            92 +#define __NR_ftruncate           93 +#define __NR_fchmod              94 +#define __NR_getpriority         96 +#define __NR_setpriority         97 +#define __NR_statfs              99 +#define __NR_fstatfs            100 +#define __NR_socketcall         102 +#define __NR_syslog             103 +#define __NR_setitimer          104 +#define __NR_getitimer          105 +#define __NR_stat               106 +#define __NR_lstat              107 +#define __NR_fstat              108 +#define __NR_lookup_dcookie     110 +#define __NR_vhangup            111 +#define __NR_idle               112 +#define __NR_wait4              114 +#define __NR_swapoff            115 +#define __NR_sysinfo            116 +#define __NR_ipc                117 +#define __NR_fsync              118 +#define __NR_sigreturn          119 +#define __NR_clone              120 +#define __NR_setdomainname      121 +#define __NR_uname              122 +#define __NR_adjtimex           124 +#define __NR_mprotect           125 +#define __NR_sigprocmask        126 +#define __NR_create_module      127 +#define __NR_init_module        128 +#define __NR_delete_module      129 +#define __NR_get_kernel_syms    130 +#define __NR_quotactl           131 +#define __NR_getpgid            132 +#define __NR_fchdir             133 +#define __NR_bdflush            134 +#define __NR_sysfs              135 +#define __NR_personality        136 +#define __NR_afs_syscall        137 /* Syscall for Andrew File System */ +#define __NR_getdents           141 +#define __NR_flock              143 +#define __NR_msync              144 +#define __NR_readv              145 +#define __NR_writev             146 +#define __NR_getsid             147 +#define __NR_fdatasync          148 +#define __NR__sysctl            149 +#define __NR_mlock              150 +#define __NR_munlock            151 +#define __NR_mlockall           152 +#define __NR_munlockall         153 +#define __NR_sched_setparam             154 +#define __NR_sched_getparam             155 +#define __NR_sched_setscheduler         156 +#define __NR_sched_getscheduler         157 +#define __NR_sched_yield                158 +#define __NR_sched_get_priority_max     159 +#define __NR_sched_get_priority_min     160 +#define __NR_sched_rr_get_interval      161 +#define __NR_nanosleep          162 +#define __NR_mremap             163 +#define __NR_query_module       167 +#define __NR_poll               168 +#define __NR_nfsservctl         169 +#define __NR_prctl              172 +#define __NR_rt_sigreturn       173 +#define __NR_rt_sigaction       174 +#define __NR_rt_sigprocmask     175 +#define __NR_rt_sigpending      176 +#define __NR_rt_sigtimedwait    177 +#define __NR_rt_sigqueueinfo    178 +#define __NR_rt_sigsuspend      179 +#define __NR_pread64            180 +#define __NR_pwrite64           181 +#define __NR_getcwd             183 +#define __NR_capget             184 +#define __NR_capset             185 +#define __NR_sigaltstack        186 +#define __NR_sendfile           187 +#define __NR_getpmsg		188 +#define __NR_putpmsg		189 +#define __NR_vfork		190 +#define __NR_pivot_root         217 +#define __NR_mincore            218 +#define __NR_madvise            219 +#define __NR_getdents64		220 +#define __NR_readahead		222 +#define __NR_setxattr		224 +#define __NR_lsetxattr		225 +#define __NR_fsetxattr		226 +#define __NR_getxattr		227 +#define __NR_lgetxattr		228 +#define __NR_fgetxattr		229 +#define __NR_listxattr		230 +#define __NR_llistxattr		231 +#define __NR_flistxattr		232 +#define __NR_removexattr	233 +#define __NR_lremovexattr	234 +#define __NR_fremovexattr	235 +#define __NR_gettid		236 +#define __NR_tkill		237 +#define __NR_futex		238 +#define __NR_sched_setaffinity	239 +#define __NR_sched_getaffinity	240 +#define __NR_tgkill		241 +/* Number 242 is reserved for tux */ +#define __NR_io_setup		243 +#define __NR_io_destroy		244 +#define __NR_io_getevents	245 +#define __NR_io_submit		246 +#define __NR_io_cancel		247 +#define __NR_exit_group		248 +#define __NR_epoll_create	249 +#define __NR_epoll_ctl		250 +#define __NR_epoll_wait		251 +#define __NR_set_tid_address	252 +#define __NR_fadvise64		253 +#define __NR_timer_create	254 +#define __NR_timer_settime	(__NR_timer_create+1) +#define __NR_timer_gettime	(__NR_timer_create+2) +#define __NR_timer_getoverrun	(__NR_timer_create+3) +#define __NR_timer_delete	(__NR_timer_create+4) +#define __NR_clock_settime	(__NR_timer_create+5) +#define __NR_clock_gettime	(__NR_timer_create+6) +#define __NR_clock_getres	(__NR_timer_create+7) +#define __NR_clock_nanosleep	(__NR_timer_create+8) +/* Number 263 is reserved for vserver */ +#define __NR_statfs64		265 +#define __NR_fstatfs64		266 +#define __NR_remap_file_pages	267 +/* Number 268 is reserved for new sys_mbind */ +/* Number 269 is reserved for new sys_get_mempolicy */ +/* Number 270 is reserved for new sys_set_mempolicy */ +#define __NR_mq_open		271 +#define __NR_mq_unlink		272 +#define __NR_mq_timedsend	273 +#define __NR_mq_timedreceive	274 +#define __NR_mq_notify		275 +#define __NR_mq_getsetattr	276 +#define __NR_kexec_load		277 +#define __NR_add_key		278 +#define __NR_request_key	279 +#define __NR_keyctl		280 +#define __NR_waitid		281 +#define __NR_ioprio_set		282 +#define __NR_ioprio_get		283 +#define __NR_inotify_init	284 +#define __NR_inotify_add_watch	285 +#define __NR_inotify_rm_watch	286 +/* Number 287 is reserved for new sys_migrate_pages */ +#define __NR_openat		288 +#define __NR_mkdirat		289 +#define __NR_mknodat		290 +#define __NR_fchownat		291 +#define __NR_futimesat		292 +#define __NR_unlinkat		294 +#define __NR_renameat		295 +#define __NR_linkat		296 +#define __NR_symlinkat		297 +#define __NR_readlinkat		298 +#define __NR_fchmodat		299 +#define __NR_faccessat		300 +#define __NR_pselect6		301 +#define __NR_ppoll		302 +#define __NR_unshare		303 +#define __NR_set_robust_list	304 +#define __NR_get_robust_list	305 +#define __NR_splice		306 +#define __NR_sync_file_range	307 +#define __NR_tee		308 +#define __NR_vmsplice		309 +/* Number 310 is reserved for new sys_move_pages */ +#define __NR_getcpu		311 +#define __NR_epoll_pwait	312 +#define __NR_utimes		313 +#define __NR_fallocate		314 +#define __NR_utimensat		315 +#define __NR_signalfd		316 +#define __NR_timerfd		317 +#define __NR_eventfd		318 +#define __NR_timerfd_create	319 +#define __NR_timerfd_settime	320 +#define __NR_timerfd_gettime	321 +#define __NR_signalfd4		322 +#define __NR_eventfd2		323 +#define __NR_inotify_init1	324 +#define __NR_pipe2		325 +#define __NR_dup3		326 +#define __NR_epoll_create1	327 +#define	__NR_preadv		328 +#define	__NR_pwritev		329 +#define __NR_rt_tgsigqueueinfo	330 +#define __NR_perf_event_open	331 +#define __NR_fanotify_init	332 +#define __NR_fanotify_mark	333 +#define __NR_prlimit64		334 +#define __NR_name_to_handle_at	335 +#define __NR_open_by_handle_at	336 +#define __NR_clock_adjtime	337 +#define __NR_syncfs		338 +#define __NR_setns		339 +#define __NR_process_vm_readv	340 +#define __NR_process_vm_writev	341 +#define __NR_s390_runtime_instr 342 +#define __NR_kcmp		343 +#define __NR_finit_module	344 +#define __NR_sched_setattr	345 +#define __NR_sched_getattr	346 +#define __NR_renameat2		347 +#define NR_syscalls 348 + +/*  + * There are some system calls that are not present on 64 bit, some + * have a different name although they do the same (e.g. __NR_chown32 + * is __NR_chown on 64 bit). + */ +#ifndef __s390x__ + +#define __NR_time		 13 +#define __NR_lchown		 16 +#define __NR_setuid		 23 +#define __NR_getuid		 24 +#define __NR_stime		 25 +#define __NR_setgid		 46 +#define __NR_getgid		 47 +#define __NR_geteuid		 49 +#define __NR_getegid		 50 +#define __NR_setreuid		 70 +#define __NR_setregid		 71 +#define __NR_getrlimit		 76 +#define __NR_getgroups		 80 +#define __NR_setgroups		 81 +#define __NR_fchown		 95 +#define __NR_ioperm		101 +#define __NR_setfsuid		138 +#define __NR_setfsgid		139 +#define __NR__llseek		140 +#define __NR__newselect 	142 +#define __NR_setresuid		164 +#define __NR_getresuid		165 +#define __NR_setresgid		170 +#define __NR_getresgid		171 +#define __NR_chown		182 +#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */ +#define __NR_mmap2		192 +#define __NR_truncate64		193 +#define __NR_ftruncate64	194 +#define __NR_stat64		195 +#define __NR_lstat64		196 +#define __NR_fstat64		197 +#define __NR_lchown32		198 +#define __NR_getuid32		199 +#define __NR_getgid32		200 +#define __NR_geteuid32		201 +#define __NR_getegid32		202 +#define __NR_setreuid32		203 +#define __NR_setregid32		204 +#define __NR_getgroups32	205 +#define __NR_setgroups32	206 +#define __NR_fchown32		207 +#define __NR_setresuid32	208 +#define __NR_getresuid32	209 +#define __NR_setresgid32	210 +#define __NR_getresgid32	211 +#define __NR_chown32		212 +#define __NR_setuid32		213 +#define __NR_setgid32		214 +#define __NR_setfsuid32		215 +#define __NR_setfsgid32		216 +#define __NR_fcntl64		221 +#define __NR_sendfile64		223 +#define __NR_fadvise64_64	264 +#define __NR_fstatat64		293 + +#else + +#define __NR_select		142 +#define __NR_getrlimit		191	/* SuS compliant getrlimit */ +#define __NR_lchown  		198 +#define __NR_getuid  		199 +#define __NR_getgid  		200 +#define __NR_geteuid  		201 +#define __NR_getegid  		202 +#define __NR_setreuid  		203 +#define __NR_setregid  		204 +#define __NR_getgroups  	205 +#define __NR_setgroups  	206 +#define __NR_fchown  		207 +#define __NR_setresuid  	208 +#define __NR_getresuid  	209 +#define __NR_setresgid  	210 +#define __NR_getresgid  	211 +#define __NR_chown  		212 +#define __NR_setuid  		213 +#define __NR_setgid  		214 +#define __NR_setfsuid  		215 +#define __NR_setfsgid  		216 +#define __NR_newfstatat		293 + +#endif + +#endif /* _UAPI_ASM_S390_UNISTD_H_ */ diff --git a/arch/s390/include/uapi/asm/virtio-ccw.h b/arch/s390/include/uapi/asm/virtio-ccw.h new file mode 100644 index 00000000000..a9a4ebf79fa --- /dev/null +++ b/arch/s390/include/uapi/asm/virtio-ccw.h @@ -0,0 +1,21 @@ +/* + * Definitions for virtio-ccw devices. + * + * Copyright IBM Corp. 2013 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License (version 2 only) + * as published by the Free Software Foundation. + * + *  Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> + */ +#ifndef __KVM_VIRTIO_CCW_H +#define __KVM_VIRTIO_CCW_H + +/* Alignment of vring buffers. */ +#define KVM_VIRTIO_CCW_RING_ALIGN 4096 + +/* Subcode for diagnose 500 (virtio hypercall). */ +#define KVM_S390_VIRTIO_CCW_NOTIFY 3 + +#endif diff --git a/arch/s390/include/asm/vtoc.h b/arch/s390/include/uapi/asm/vtoc.h index 8406a2b3157..221419de275 100644 --- a/arch/s390/include/asm/vtoc.h +++ b/arch/s390/include/uapi/asm/vtoc.h @@ -1,9 +1,7 @@  /* - * include/asm-s390/vtoc.h - *   * This file contains volume label definitions for DASD devices.   * - * (C) Copyright IBM Corp. 2005 + * Copyright IBM Corp. 2005   *   * Author(s): Volker Sameske <sameske@de.ibm.com>   * diff --git a/arch/s390/include/asm/zcrypt.h b/arch/s390/include/uapi/asm/zcrypt.h index 00d3bbd4411..f2b18eacaca 100644 --- a/arch/s390/include/asm/zcrypt.h +++ b/arch/s390/include/uapi/asm/zcrypt.h @@ -3,7 +3,7 @@   *   *  zcrypt 2.1.0 (user-visible header)   * - *  Copyright (C)  2001, 2006 IBM Corporation + *  Copyright IBM Corp. 2001, 2006   *  Author(s): Robert Burroughs   *	       Eric Rossman (edrossma@us.ibm.com)   * @@ -154,6 +154,67 @@ struct ica_xcRB {  	unsigned short	priority_window;  	unsigned int	status;  } __attribute__((packed)); + +/** + * struct ep11_cprb - EP11 connectivity programming request block + * @cprb_len:		CPRB header length [0x0020] + * @cprb_ver_id:	CPRB version id.   [0x04] + * @pad_000:		Alignment pad bytes + * @flags:		Admin cmd [0x80] or functional cmd [0x00] + * @func_id:		Function id / subtype [0x5434] + * @source_id:		Source id [originator id] + * @target_id:		Target id [usage/ctrl domain id] + * @ret_code:		Return code + * @reserved1:		Reserved + * @reserved2:		Reserved + * @payload_len:	Payload length + */ +struct ep11_cprb { +	uint16_t	cprb_len; +	unsigned char	cprb_ver_id; +	unsigned char	pad_000[2]; +	unsigned char	flags; +	unsigned char	func_id[2]; +	uint32_t	source_id; +	uint32_t	target_id; +	uint32_t	ret_code; +	uint32_t	reserved1; +	uint32_t	reserved2; +	uint32_t	payload_len; +} __attribute__((packed)); + +/** + * struct ep11_target_dev - EP11 target device list + * @ap_id:	AP device id + * @dom_id:	Usage domain id + */ +struct ep11_target_dev { +	uint16_t ap_id; +	uint16_t dom_id; +}; + +/** + * struct ep11_urb - EP11 user request block + * @targets_num:	Number of target adapters + * @targets:		Addr to target adapter list + * @weight:		Level of request priority + * @req_no:		Request id/number + * @req_len:		Request length + * @req:		Addr to request block + * @resp_len:		Response length + * @resp:		Addr to response block + */ +struct ep11_urb { +	uint16_t		targets_num; +	uint64_t		targets; +	uint64_t		weight; +	uint64_t		req_no; +	uint64_t		req_len; +	uint64_t		req; +	uint64_t		resp_len; +	uint64_t		resp; +} __attribute__((packed)); +  #define AUTOSELECT ((unsigned int)0xFFFFFFFF)  #define ZCRYPT_IOCTL_MAGIC 'z' @@ -183,6 +244,9 @@ struct ica_xcRB {   *   ZSECSENDCPRB   *     Send an arbitrary CPRB to a crypto card.   * + *   ZSENDEP11CPRB + *     Send an arbitrary EP11 CPRB to an EP11 coprocessor crypto card. + *   *   Z90STAT_STATUS_MASK   *     Return an 64 element array of unsigned chars for the status of   *     all devices. @@ -256,6 +320,7 @@ struct ica_xcRB {  #define ICARSAMODEXPO	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x05, 0)  #define ICARSACRT	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x06, 0)  #define ZSECSENDCPRB	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x81, 0) +#define ZSENDEP11CPRB	_IOC(_IOC_READ|_IOC_WRITE, ZCRYPT_IOCTL_MAGIC, 0x04, 0)  /* New status calls */  #define Z90STAT_TOTALCOUNT	_IOR(ZCRYPT_IOCTL_MAGIC, 0x40, int)  | 
