diff options
Diffstat (limited to 'arch/s390/include/asm/system.h')
-rw-r--r-- | arch/s390/include/asm/system.h | 51 |
1 files changed, 22 insertions, 29 deletions
diff --git a/arch/s390/include/asm/system.h b/arch/s390/include/asm/system.h index 1f2ebc4afd82..3ad16dbf622e 100644 --- a/arch/s390/include/asm/system.h +++ b/arch/s390/include/asm/system.h | |||
@@ -85,14 +85,16 @@ static inline void restore_access_regs(unsigned int *acrs) | |||
85 | asm volatile("lam 0,15,%0" : : "Q" (*acrs)); | 85 | asm volatile("lam 0,15,%0" : : "Q" (*acrs)); |
86 | } | 86 | } |
87 | 87 | ||
88 | #define switch_to(prev,next,last) do { \ | 88 | #define switch_to(prev,next,last) do { \ |
89 | if (prev == next) \ | 89 | if (prev->mm) { \ |
90 | break; \ | 90 | save_fp_regs(&prev->thread.fp_regs); \ |
91 | save_fp_regs(&prev->thread.fp_regs); \ | 91 | save_access_regs(&prev->thread.acrs[0]); \ |
92 | restore_fp_regs(&next->thread.fp_regs); \ | 92 | } \ |
93 | save_access_regs(&prev->thread.acrs[0]); \ | 93 | if (next->mm) { \ |
94 | restore_access_regs(&next->thread.acrs[0]); \ | 94 | restore_fp_regs(&next->thread.fp_regs); \ |
95 | prev = __switch_to(prev,next); \ | 95 | restore_access_regs(&next->thread.acrs[0]); \ |
96 | } \ | ||
97 | prev = __switch_to(prev,next); \ | ||
96 | } while (0) | 98 | } while (0) |
97 | 99 | ||
98 | extern void account_vtime(struct task_struct *, struct task_struct *); | 100 | extern void account_vtime(struct task_struct *, struct task_struct *); |
@@ -418,30 +420,21 @@ extern void smp_ctl_clear_bit(int cr, int bit); | |||
418 | 420 | ||
419 | #endif /* CONFIG_SMP */ | 421 | #endif /* CONFIG_SMP */ |
420 | 422 | ||
421 | static inline unsigned int stfl(void) | 423 | #define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ |
422 | { | ||
423 | asm volatile( | ||
424 | " .insn s,0xb2b10000,0(0)\n" /* stfl */ | ||
425 | "0:\n" | ||
426 | EX_TABLE(0b,0b)); | ||
427 | return S390_lowcore.stfl_fac_list; | ||
428 | } | ||
429 | 424 | ||
430 | static inline int __stfle(unsigned long long *list, int doublewords) | 425 | /* |
426 | * The test_facility function uses the bit odering where the MSB is bit 0. | ||
427 | * That makes it easier to query facility bits with the bit number as | ||
428 | * documented in the Principles of Operation. | ||
429 | */ | ||
430 | static inline int test_facility(unsigned long nr) | ||
431 | { | 431 | { |
432 | typedef struct { unsigned long long _[doublewords]; } addrtype; | 432 | unsigned char *ptr; |
433 | register unsigned long __nr asm("0") = doublewords - 1; | ||
434 | |||
435 | asm volatile(".insn s,0xb2b00000,%0" /* stfle */ | ||
436 | : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); | ||
437 | return __nr + 1; | ||
438 | } | ||
439 | 433 | ||
440 | static inline int stfle(unsigned long long *list, int doublewords) | 434 | if (nr >= MAX_FACILITY_BIT) |
441 | { | 435 | return 0; |
442 | if (!(stfl() & (1UL << 24))) | 436 | ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3); |
443 | return -EOPNOTSUPP; | 437 | return (*ptr & (0x80 >> (nr & 7))) != 0; |
444 | return __stfle(list, doublewords); | ||
445 | } | 438 | } |
446 | 439 | ||
447 | static inline unsigned short stap(void) | 440 | static inline unsigned short stap(void) |