diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/s390/crypto/crypt_s390.h | 2 | ||||
| -rw-r--r-- | arch/s390/include/asm/lowcore.h | 11 | ||||
| -rw-r--r-- | arch/s390/include/asm/system.h | 33 | ||||
| -rw-r--r-- | arch/s390/kernel/early.c | 40 | ||||
| -rw-r--r-- | arch/s390/kernel/setup.c | 19 | ||||
| -rw-r--r-- | arch/s390/kernel/smp.c | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/topology.c | 5 | ||||
| -rw-r--r-- | arch/s390/kernel/vdso.c | 6 | ||||
| -rw-r--r-- | arch/s390/kvm/kvm-s390.c | 2 | ||||
| -rw-r--r-- | arch/s390/kvm/priv.c | 4 | ||||
| -rw-r--r-- | arch/s390/mm/fault.c | 7 | 
11 files changed, 65 insertions, 66 deletions
| diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index 0ef9829f2ad6..7ee9a1b4ad9f 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h @@ -297,7 +297,7 @@ static inline int crypt_s390_func_available(int func)  	int ret;  	/* check if CPACF facility (bit 17) is available */ -	if (!(stfl() & 1ULL << (31 - 17))) +	if (!test_facility(17))  		return 0;  	switch (func & CRYPT_S390_OP_MASK) { diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index 0f97ef2d92ac..65e172f8209d 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h @@ -150,9 +150,10 @@ struct _lowcore {  	 */  	__u32	ipib;				/* 0x0e00 */  	__u32	ipib_checksum;			/* 0x0e04 */ +	__u8	pad_0x0e08[0x0f00-0x0e08];	/* 0x0e08 */ -	/* Align to the top 1k of prefix area */ -	__u8	pad_0x0e08[0x1000-0x0e08];	/* 0x0e08 */ +	/* Extended facility list */ +	__u64	stfle_fac_list[32];		/* 0x0f00 */  } __packed;  #else /* CONFIG_32BIT */ @@ -285,7 +286,11 @@ struct _lowcore {  	 */  	__u64	ipib;				/* 0x0e00 */  	__u32	ipib_checksum;			/* 0x0e08 */ -	__u8	pad_0x0e0c[0x11b8-0x0e0c];	/* 0x0e0c */ +	__u8	pad_0x0e0c[0x0f00-0x0e0c];	/* 0x0e0c */ + +	/* Extended facility list */ +	__u64	stfle_fac_list[32];		/* 0x0f00 */ +	__u8	pad_0x1000[0x11b8-0x1000];	/* 0x1000 */  	/* 64 bit extparam used for pfault/diag 250: defined by architecture */  	__u64	ext_params2;			/* 0x11B8 */ diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index 3c079dd5ee79..3ad16dbf622e 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h @@ -420,30 +420,21 @@ extern void smp_ctl_clear_bit(int cr, int bit);  #endif /* CONFIG_SMP */ -static inline unsigned int stfl(void) -{ -	asm volatile( -		"	.insn	s,0xb2b10000,0(0)\n" /* stfl */ -		"0:\n" -		EX_TABLE(0b,0b)); -	return S390_lowcore.stfl_fac_list; -} +#define MAX_FACILITY_BIT (256*8)	/* stfle_fac_list has 256 bytes */ -static inline int __stfle(unsigned long long *list, int doublewords) +/* + * 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)  { -	typedef struct { unsigned long long _[doublewords]; } addrtype; -	register unsigned long __nr asm("0") = doublewords - 1; - -	asm volatile(".insn s,0xb2b00000,%0" /* stfle */ -		     : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); -	return __nr + 1; -} +	unsigned char *ptr; -static inline int stfle(unsigned long long *list, int doublewords) -{ -	if (!(stfl() & (1UL << 24))) -		return -EOPNOTSUPP; -	return __stfle(list, doublewords); +	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) diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 0badc6344eb4..d2455d44d99a 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c @@ -256,13 +256,35 @@ static noinline __init void setup_lowcore_early(void)  	s390_base_pgm_handler_fn = early_pgm_check_handler;  } +static noinline __init void setup_facility_list(void) +{ +	unsigned long nr; + +	S390_lowcore.stfl_fac_list = 0; +	asm volatile( +		"	.insn	s,0xb2b10000,0(0)\n" /* stfl */ +		"0:\n" +		EX_TABLE(0b,0b) : "=m" (S390_lowcore.stfl_fac_list)); +	memcpy(&S390_lowcore.stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); +	nr = 4;				/* # bytes stored by stfl */ +	if (test_facility(7)) { +		/* More facility bits available with stfle */ +		register unsigned long reg0 asm("0") = MAX_FACILITY_BIT/64 - 1; +		asm volatile(".insn s,0xb2b00000,%0" /* stfle */ +			     : "=m" (S390_lowcore.stfle_fac_list), "+d" (reg0) +			     : : "cc"); +		nr = (reg0 + 1) * 8;	/* # bytes stored by stfle */ +	} +	memset((char *) S390_lowcore.stfle_fac_list + nr, 0, +	       MAX_FACILITY_BIT/8 - nr); +} +  static noinline __init void setup_hpage(void)  {  #ifndef CONFIG_DEBUG_PAGEALLOC  	unsigned int facilities; -	facilities = stfl(); -	if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29))) +	if (!test_facility(2) || !test_facility(8))  		return;  	S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE;  	__ctl_set_bit(0, 23); @@ -356,18 +378,13 @@ static __init void detect_diag44(void)  static __init void detect_machine_facilities(void)  {  #ifdef CONFIG_64BIT -	unsigned int facilities; -	unsigned long long facility_bits; - -	facilities = stfl(); -	if (facilities & (1 << 28)) +	if (test_facility(3))  		S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; -	if (facilities & (1 << 23)) +	if (test_facility(8))  		S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; -	if (facilities & (1 << 4)) +	if (test_facility(27))  		S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; -	if ((stfle(&facility_bits, 1) > 0) && -	    (facility_bits & (1ULL << (63 - 40)))) +	if (test_facility(40))  		S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;  #endif  } @@ -448,6 +465,7 @@ void __init startup_init(void)  	lockdep_off();  	sort_main_extable();  	setup_lowcore_early(); +	setup_facility_list();  	detect_machine_type();  	ipl_update_parameters();  	setup_boot_command_line(); diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 9071e984dcf1..e3ceb911dc75 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -409,6 +409,9 @@ setup_lowcore(void)  	lc->current_task = (unsigned long) init_thread_union.thread_info.task;  	lc->thread_info = (unsigned long) &init_thread_union;  	lc->machine_flags = S390_lowcore.machine_flags; +	lc->stfl_fac_list = S390_lowcore.stfl_fac_list; +	memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list, +	       MAX_FACILITY_BIT/8);  #ifndef CONFIG_64BIT  	if (MACHINE_HAS_IEEE) {  		lc->extended_save_area_addr = (__u32) @@ -675,12 +678,9 @@ setup_memory(void)  static void __init setup_hwcaps(void)  {  	static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; -	unsigned long long facility_list_extended; -	unsigned int facility_list;  	struct cpuid cpu_id;  	int i; -	facility_list = stfl();  	/*  	 * The store facility list bits numbers as found in the principles  	 * of operation are numbered with bit 1UL<<31 as number 0 to @@ -700,11 +700,10 @@ static void __init setup_hwcaps(void)  	 *   HWCAP_S390_ETF3EH bit 8 (22 && 30).  	 */  	for (i = 0; i < 6; i++) -		if (facility_list & (1UL << (31 - stfl_bits[i]))) +		if (test_facility(stfl_bits[i]))  			elf_hwcap |= 1UL << i; -	if ((facility_list & (1UL << (31 - 22))) -	    && (facility_list & (1UL << (31 - 30)))) +	if (test_facility(22) && test_facility(30))  		elf_hwcap |= HWCAP_S390_ETF3EH;  	/* @@ -720,12 +719,8 @@ static void __init setup_hwcaps(void)  	 * translated to:  	 *   HWCAP_S390_DFP bit 6 (42 && 44).  	 */ -	if ((elf_hwcap & (1UL << 2)) && -	    __stfle(&facility_list_extended, 1) > 0) { -		if ((facility_list_extended & (1ULL << (63 - 42))) -		    && (facility_list_extended & (1ULL << (63 - 44)))) -			elf_hwcap |= HWCAP_S390_DFP; -	} +	if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) +		elf_hwcap |= HWCAP_S390_DFP;  	/*  	 * Huge page support HWCAP_S390_HPAGE is bit 7. diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 354589d096b1..94cf510b8fe1 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -594,6 +594,8 @@ int __cpuinit __cpu_up(unsigned int cpu)  	cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce;  	cpu_lowcore->machine_flags = S390_lowcore.machine_flags;  	cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; +	memcpy(cpu_lowcore->stfle_fac_list, S390_lowcore.stfle_fac_list, +	       MAX_FACILITY_BIT/8);  	eieio();  	while (sigp(cpu, sigp_restart) == sigp_busy) diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index eb0bc4752ae8..91fb66baa50b 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -351,13 +351,10 @@ static void alloc_masks(struct tl_info *info, struct mask_info *mask, int offset  void __init s390_init_cpu_topology(void)  { -	unsigned long long facility_bits;  	struct tl_info *info;  	int i; -	if (stfle(&facility_bits, 1) <= 0) -		return; -	if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61))) +	if (!test_facility(2) || !test_facility(11))  		return;  	machine_has_topology = 1; diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 6b83870507d5..e3150dd2fe74 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c @@ -84,11 +84,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data;   */  static void vdso_init_data(struct vdso_data *vd)  { -	unsigned int facility_list; - -	facility_list = stfl(); -	vd->ectg_available = -		user_mode != HOME_SPACE_MODE && (facility_list & 1); +	vd->ectg_available = user_mode != HOME_SPACE_MODE && test_facility(31);  }  #ifdef CONFIG_64BIT diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 76482b65ba3e..985d825494f1 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -740,7 +740,7 @@ static int __init kvm_s390_init(void)  		kvm_exit();  		return -ENOMEM;  	} -	stfle(facilities, 1); +	memcpy(facilities, S390_lowcore.stfle_fac_list, 16);  	facilities[0] &= 0xff00fff3f47c0000ULL;  	return 0;  } diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index 44205507717c..9194a4b52b22 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c @@ -154,12 +154,12 @@ static int handle_chsc(struct kvm_vcpu *vcpu)  static int handle_stfl(struct kvm_vcpu *vcpu)  { -	unsigned int facility_list = stfl(); +	unsigned int facility_list;  	int rc;  	vcpu->stat.instruction_stfl++;  	/* only pass the facility bits, which we can handle */ -	facility_list &= 0xff00fff3; +	facility_list = S390_lowcore.stfl_fac_list & 0xff00fff3;  	rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),  			   &facility_list, sizeof(facility_list)); diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index b4aad0c1f562..fe5701e9efbf 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -56,12 +56,7 @@ static unsigned long store_indication;  void fault_init(void)  { -	unsigned long long facility_list[2]; - -	if (stfle(facility_list, 2) < 2) -		return; -	if ((facility_list[0] & (1ULL << 61)) && -	    (facility_list[1] & (1ULL << 52))) +	if (test_facility(2) && test_facility(75))  		store_indication = 0xc00;  } | 
