diff options
| author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2010-10-25 10:10:51 -0400 |
|---|---|---|
| committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2010-10-25 10:10:21 -0400 |
| commit | 14375bc4eb8dd0fb0e765390650564c35bb31068 (patch) | |
| tree | 27200620658245c582ee9497fc969a082b304cab | |
| parent | eca577ef5989d25dedc6b0fae3c4622ceaee8005 (diff) | |
[S390] cleanup facility list handling
Store the facility list once at system startup with stfl/stfle and
reuse the result for all facility tests.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -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 | ||||
| -rw-r--r-- | drivers/s390/crypto/ap_bus.c | 9 |
12 files changed, 66 insertions, 74 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) | |||
| 297 | int ret; | 297 | int ret; |
| 298 | 298 | ||
| 299 | /* check if CPACF facility (bit 17) is available */ | 299 | /* check if CPACF facility (bit 17) is available */ |
| 300 | if (!(stfl() & 1ULL << (31 - 17))) | 300 | if (!test_facility(17)) |
| 301 | return 0; | 301 | return 0; |
| 302 | 302 | ||
| 303 | switch (func & CRYPT_S390_OP_MASK) { | 303 | 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 { | |||
| 150 | */ | 150 | */ |
| 151 | __u32 ipib; /* 0x0e00 */ | 151 | __u32 ipib; /* 0x0e00 */ |
| 152 | __u32 ipib_checksum; /* 0x0e04 */ | 152 | __u32 ipib_checksum; /* 0x0e04 */ |
| 153 | __u8 pad_0x0e08[0x0f00-0x0e08]; /* 0x0e08 */ | ||
| 153 | 154 | ||
| 154 | /* Align to the top 1k of prefix area */ | 155 | /* Extended facility list */ |
| 155 | __u8 pad_0x0e08[0x1000-0x0e08]; /* 0x0e08 */ | 156 | __u64 stfle_fac_list[32]; /* 0x0f00 */ |
| 156 | } __packed; | 157 | } __packed; |
| 157 | 158 | ||
| 158 | #else /* CONFIG_32BIT */ | 159 | #else /* CONFIG_32BIT */ |
| @@ -285,7 +286,11 @@ struct _lowcore { | |||
| 285 | */ | 286 | */ |
| 286 | __u64 ipib; /* 0x0e00 */ | 287 | __u64 ipib; /* 0x0e00 */ |
| 287 | __u32 ipib_checksum; /* 0x0e08 */ | 288 | __u32 ipib_checksum; /* 0x0e08 */ |
| 288 | __u8 pad_0x0e0c[0x11b8-0x0e0c]; /* 0x0e0c */ | 289 | __u8 pad_0x0e0c[0x0f00-0x0e0c]; /* 0x0e0c */ |
| 290 | |||
| 291 | /* Extended facility list */ | ||
| 292 | __u64 stfle_fac_list[32]; /* 0x0f00 */ | ||
| 293 | __u8 pad_0x1000[0x11b8-0x1000]; /* 0x1000 */ | ||
| 289 | 294 | ||
| 290 | /* 64 bit extparam used for pfault/diag 250: defined by architecture */ | 295 | /* 64 bit extparam used for pfault/diag 250: defined by architecture */ |
| 291 | __u64 ext_params2; /* 0x11B8 */ | 296 | __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); | |||
| 420 | 420 | ||
| 421 | #endif /* CONFIG_SMP */ | 421 | #endif /* CONFIG_SMP */ |
| 422 | 422 | ||
| 423 | static inline unsigned int stfl(void) | 423 | #define MAX_FACILITY_BIT (256*8) /* stfle_fac_list has 256 bytes */ |
| 424 | { | ||
| 425 | asm volatile( | ||
| 426 | " .insn s,0xb2b10000,0(0)\n" /* stfl */ | ||
| 427 | "0:\n" | ||
| 428 | EX_TABLE(0b,0b)); | ||
| 429 | return S390_lowcore.stfl_fac_list; | ||
| 430 | } | ||
| 431 | 424 | ||
| 432 | 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) | ||
| 433 | { | 431 | { |
| 434 | typedef struct { unsigned long long _[doublewords]; } addrtype; | 432 | unsigned char *ptr; |
| 435 | register unsigned long __nr asm("0") = doublewords - 1; | ||
| 436 | |||
| 437 | asm volatile(".insn s,0xb2b00000,%0" /* stfle */ | ||
| 438 | : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc"); | ||
| 439 | return __nr + 1; | ||
| 440 | } | ||
| 441 | 433 | ||
| 442 | static inline int stfle(unsigned long long *list, int doublewords) | 434 | if (nr >= MAX_FACILITY_BIT) |
| 443 | { | 435 | return 0; |
| 444 | if (!(stfl() & (1UL << 24))) | 436 | ptr = (unsigned char *) &S390_lowcore.stfle_fac_list + (nr >> 3); |
| 445 | return -EOPNOTSUPP; | 437 | return (*ptr & (0x80 >> (nr & 7))) != 0; |
| 446 | return __stfle(list, doublewords); | ||
| 447 | } | 438 | } |
| 448 | 439 | ||
| 449 | static inline unsigned short stap(void) | 440 | 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) | |||
| 256 | s390_base_pgm_handler_fn = early_pgm_check_handler; | 256 | s390_base_pgm_handler_fn = early_pgm_check_handler; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | static noinline __init void setup_facility_list(void) | ||
| 260 | { | ||
| 261 | unsigned long nr; | ||
| 262 | |||
| 263 | S390_lowcore.stfl_fac_list = 0; | ||
| 264 | asm volatile( | ||
| 265 | " .insn s,0xb2b10000,0(0)\n" /* stfl */ | ||
| 266 | "0:\n" | ||
| 267 | EX_TABLE(0b,0b) : "=m" (S390_lowcore.stfl_fac_list)); | ||
| 268 | memcpy(&S390_lowcore.stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); | ||
| 269 | nr = 4; /* # bytes stored by stfl */ | ||
| 270 | if (test_facility(7)) { | ||
| 271 | /* More facility bits available with stfle */ | ||
| 272 | register unsigned long reg0 asm("0") = MAX_FACILITY_BIT/64 - 1; | ||
| 273 | asm volatile(".insn s,0xb2b00000,%0" /* stfle */ | ||
| 274 | : "=m" (S390_lowcore.stfle_fac_list), "+d" (reg0) | ||
| 275 | : : "cc"); | ||
| 276 | nr = (reg0 + 1) * 8; /* # bytes stored by stfle */ | ||
| 277 | } | ||
| 278 | memset((char *) S390_lowcore.stfle_fac_list + nr, 0, | ||
| 279 | MAX_FACILITY_BIT/8 - nr); | ||
| 280 | } | ||
| 281 | |||
| 259 | static noinline __init void setup_hpage(void) | 282 | static noinline __init void setup_hpage(void) |
| 260 | { | 283 | { |
| 261 | #ifndef CONFIG_DEBUG_PAGEALLOC | 284 | #ifndef CONFIG_DEBUG_PAGEALLOC |
| 262 | unsigned int facilities; | 285 | unsigned int facilities; |
| 263 | 286 | ||
| 264 | facilities = stfl(); | 287 | if (!test_facility(2) || !test_facility(8)) |
| 265 | if (!(facilities & (1UL << 23)) || !(facilities & (1UL << 29))) | ||
| 266 | return; | 288 | return; |
| 267 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; | 289 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; |
| 268 | __ctl_set_bit(0, 23); | 290 | __ctl_set_bit(0, 23); |
| @@ -356,18 +378,13 @@ static __init void detect_diag44(void) | |||
| 356 | static __init void detect_machine_facilities(void) | 378 | static __init void detect_machine_facilities(void) |
| 357 | { | 379 | { |
| 358 | #ifdef CONFIG_64BIT | 380 | #ifdef CONFIG_64BIT |
| 359 | unsigned int facilities; | 381 | if (test_facility(3)) |
| 360 | unsigned long long facility_bits; | ||
| 361 | |||
| 362 | facilities = stfl(); | ||
| 363 | if (facilities & (1 << 28)) | ||
| 364 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; | 382 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; |
| 365 | if (facilities & (1 << 23)) | 383 | if (test_facility(8)) |
| 366 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; | 384 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; |
| 367 | if (facilities & (1 << 4)) | 385 | if (test_facility(27)) |
| 368 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; | 386 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; |
| 369 | if ((stfle(&facility_bits, 1) > 0) && | 387 | if (test_facility(40)) |
| 370 | (facility_bits & (1ULL << (63 - 40)))) | ||
| 371 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; | 388 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; |
| 372 | #endif | 389 | #endif |
| 373 | } | 390 | } |
| @@ -448,6 +465,7 @@ void __init startup_init(void) | |||
| 448 | lockdep_off(); | 465 | lockdep_off(); |
| 449 | sort_main_extable(); | 466 | sort_main_extable(); |
| 450 | setup_lowcore_early(); | 467 | setup_lowcore_early(); |
| 468 | setup_facility_list(); | ||
| 451 | detect_machine_type(); | 469 | detect_machine_type(); |
| 452 | ipl_update_parameters(); | 470 | ipl_update_parameters(); |
| 453 | setup_boot_command_line(); | 471 | 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) | |||
| 409 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; | 409 | lc->current_task = (unsigned long) init_thread_union.thread_info.task; |
| 410 | lc->thread_info = (unsigned long) &init_thread_union; | 410 | lc->thread_info = (unsigned long) &init_thread_union; |
| 411 | lc->machine_flags = S390_lowcore.machine_flags; | 411 | lc->machine_flags = S390_lowcore.machine_flags; |
| 412 | lc->stfl_fac_list = S390_lowcore.stfl_fac_list; | ||
| 413 | memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list, | ||
| 414 | MAX_FACILITY_BIT/8); | ||
| 412 | #ifndef CONFIG_64BIT | 415 | #ifndef CONFIG_64BIT |
| 413 | if (MACHINE_HAS_IEEE) { | 416 | if (MACHINE_HAS_IEEE) { |
| 414 | lc->extended_save_area_addr = (__u32) | 417 | lc->extended_save_area_addr = (__u32) |
| @@ -675,12 +678,9 @@ setup_memory(void) | |||
| 675 | static void __init setup_hwcaps(void) | 678 | static void __init setup_hwcaps(void) |
| 676 | { | 679 | { |
| 677 | static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; | 680 | static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 }; |
| 678 | unsigned long long facility_list_extended; | ||
| 679 | unsigned int facility_list; | ||
| 680 | struct cpuid cpu_id; | 681 | struct cpuid cpu_id; |
| 681 | int i; | 682 | int i; |
| 682 | 683 | ||
| 683 | facility_list = stfl(); | ||
| 684 | /* | 684 | /* |
| 685 | * The store facility list bits numbers as found in the principles | 685 | * The store facility list bits numbers as found in the principles |
| 686 | * of operation are numbered with bit 1UL<<31 as number 0 to | 686 | * of operation are numbered with bit 1UL<<31 as number 0 to |
| @@ -700,11 +700,10 @@ static void __init setup_hwcaps(void) | |||
| 700 | * HWCAP_S390_ETF3EH bit 8 (22 && 30). | 700 | * HWCAP_S390_ETF3EH bit 8 (22 && 30). |
| 701 | */ | 701 | */ |
| 702 | for (i = 0; i < 6; i++) | 702 | for (i = 0; i < 6; i++) |
| 703 | if (facility_list & (1UL << (31 - stfl_bits[i]))) | 703 | if (test_facility(stfl_bits[i])) |
| 704 | elf_hwcap |= 1UL << i; | 704 | elf_hwcap |= 1UL << i; |
| 705 | 705 | ||
| 706 | if ((facility_list & (1UL << (31 - 22))) | 706 | if (test_facility(22) && test_facility(30)) |
| 707 | && (facility_list & (1UL << (31 - 30)))) | ||
| 708 | elf_hwcap |= HWCAP_S390_ETF3EH; | 707 | elf_hwcap |= HWCAP_S390_ETF3EH; |
| 709 | 708 | ||
| 710 | /* | 709 | /* |
| @@ -720,12 +719,8 @@ static void __init setup_hwcaps(void) | |||
| 720 | * translated to: | 719 | * translated to: |
| 721 | * HWCAP_S390_DFP bit 6 (42 && 44). | 720 | * HWCAP_S390_DFP bit 6 (42 && 44). |
| 722 | */ | 721 | */ |
| 723 | if ((elf_hwcap & (1UL << 2)) && | 722 | if ((elf_hwcap & (1UL << 2)) && test_facility(42) && test_facility(44)) |
| 724 | __stfle(&facility_list_extended, 1) > 0) { | 723 | elf_hwcap |= HWCAP_S390_DFP; |
| 725 | if ((facility_list_extended & (1ULL << (63 - 42))) | ||
| 726 | && (facility_list_extended & (1ULL << (63 - 44)))) | ||
| 727 | elf_hwcap |= HWCAP_S390_DFP; | ||
| 728 | } | ||
| 729 | 724 | ||
| 730 | /* | 725 | /* |
| 731 | * Huge page support HWCAP_S390_HPAGE is bit 7. | 726 | * 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) | |||
| 594 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; | 594 | cpu_lowcore->kernel_asce = S390_lowcore.kernel_asce; |
| 595 | cpu_lowcore->machine_flags = S390_lowcore.machine_flags; | 595 | cpu_lowcore->machine_flags = S390_lowcore.machine_flags; |
| 596 | cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; | 596 | cpu_lowcore->ftrace_func = S390_lowcore.ftrace_func; |
| 597 | memcpy(cpu_lowcore->stfle_fac_list, S390_lowcore.stfle_fac_list, | ||
| 598 | MAX_FACILITY_BIT/8); | ||
| 597 | eieio(); | 599 | eieio(); |
| 598 | 600 | ||
| 599 | while (sigp(cpu, sigp_restart) == sigp_busy) | 601 | 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 | |||
| 351 | 351 | ||
| 352 | void __init s390_init_cpu_topology(void) | 352 | void __init s390_init_cpu_topology(void) |
| 353 | { | 353 | { |
| 354 | unsigned long long facility_bits; | ||
| 355 | struct tl_info *info; | 354 | struct tl_info *info; |
| 356 | int i; | 355 | int i; |
| 357 | 356 | ||
| 358 | if (stfle(&facility_bits, 1) <= 0) | 357 | if (!test_facility(2) || !test_facility(11)) |
| 359 | return; | ||
| 360 | if (!(facility_bits & (1ULL << 52)) || !(facility_bits & (1ULL << 61))) | ||
| 361 | return; | 358 | return; |
| 362 | machine_has_topology = 1; | 359 | machine_has_topology = 1; |
| 363 | 360 | ||
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; | |||
| 84 | */ | 84 | */ |
| 85 | static void vdso_init_data(struct vdso_data *vd) | 85 | static void vdso_init_data(struct vdso_data *vd) |
| 86 | { | 86 | { |
| 87 | unsigned int facility_list; | 87 | vd->ectg_available = user_mode != HOME_SPACE_MODE && test_facility(31); |
| 88 | |||
| 89 | facility_list = stfl(); | ||
| 90 | vd->ectg_available = | ||
| 91 | user_mode != HOME_SPACE_MODE && (facility_list & 1); | ||
| 92 | } | 88 | } |
| 93 | 89 | ||
| 94 | #ifdef CONFIG_64BIT | 90 | #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) | |||
| 740 | kvm_exit(); | 740 | kvm_exit(); |
| 741 | return -ENOMEM; | 741 | return -ENOMEM; |
| 742 | } | 742 | } |
| 743 | stfle(facilities, 1); | 743 | memcpy(facilities, S390_lowcore.stfle_fac_list, 16); |
| 744 | facilities[0] &= 0xff00fff3f47c0000ULL; | 744 | facilities[0] &= 0xff00fff3f47c0000ULL; |
| 745 | return 0; | 745 | return 0; |
| 746 | } | 746 | } |
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) | |||
| 154 | 154 | ||
| 155 | static int handle_stfl(struct kvm_vcpu *vcpu) | 155 | static int handle_stfl(struct kvm_vcpu *vcpu) |
| 156 | { | 156 | { |
| 157 | unsigned int facility_list = stfl(); | 157 | unsigned int facility_list; |
| 158 | int rc; | 158 | int rc; |
| 159 | 159 | ||
| 160 | vcpu->stat.instruction_stfl++; | 160 | vcpu->stat.instruction_stfl++; |
| 161 | /* only pass the facility bits, which we can handle */ | 161 | /* only pass the facility bits, which we can handle */ |
| 162 | facility_list &= 0xff00fff3; | 162 | facility_list = S390_lowcore.stfl_fac_list & 0xff00fff3; |
| 163 | 163 | ||
| 164 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), | 164 | rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list), |
| 165 | &facility_list, sizeof(facility_list)); | 165 | &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; | |||
| 56 | 56 | ||
| 57 | void fault_init(void) | 57 | void fault_init(void) |
| 58 | { | 58 | { |
| 59 | unsigned long long facility_list[2]; | 59 | if (test_facility(2) && test_facility(75)) |
| 60 | |||
| 61 | if (stfle(facility_list, 2) < 2) | ||
| 62 | return; | ||
| 63 | if ((facility_list[0] & (1ULL << 61)) && | ||
| 64 | (facility_list[1] & (1ULL << 52))) | ||
| 65 | store_indication = 0xc00; | 60 | store_indication = 0xc00; |
| 66 | } | 61 | } |
| 67 | 62 | ||
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 91c6028d7b74..8fd8c62455e9 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
| @@ -154,14 +154,7 @@ static inline int ap_instructions_available(void) | |||
| 154 | */ | 154 | */ |
| 155 | static int ap_interrupts_available(void) | 155 | static int ap_interrupts_available(void) |
| 156 | { | 156 | { |
| 157 | unsigned long long facility_bits[2]; | 157 | return test_facility(1) && test_facility(2); |
| 158 | |||
| 159 | if (stfle(facility_bits, 2) <= 1) | ||
| 160 | return 0; | ||
| 161 | if (!(facility_bits[0] & (1ULL << 61)) || | ||
| 162 | !(facility_bits[1] & (1ULL << 62))) | ||
| 163 | return 0; | ||
| 164 | return 1; | ||
| 165 | } | 158 | } |
| 166 | 159 | ||
| 167 | /** | 160 | /** |
