Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * Intel PCONFIG instruction support. 4 : : * 5 : : * Copyright (C) 2017 Intel Corporation 6 : : * 7 : : * Author: 8 : : * Kirill A. Shutemov <kirill.shutemov@linux.intel.com> 9 : : */ 10 : : 11 : : #include <asm/cpufeature.h> 12 : : #include <asm/intel_pconfig.h> 13 : : 14 : : #define PCONFIG_CPUID 0x1b 15 : : 16 : : #define PCONFIG_CPUID_SUBLEAF_MASK ((1 << 12) - 1) 17 : : 18 : : /* Subleaf type (EAX) for PCONFIG CPUID leaf (0x1B) */ 19 : : enum { 20 : : PCONFIG_CPUID_SUBLEAF_INVALID = 0, 21 : : PCONFIG_CPUID_SUBLEAF_TARGETID = 1, 22 : : }; 23 : : 24 : : /* Bitmask of supported targets */ 25 : : static u64 targets_supported __read_mostly; 26 : : 27 : 0 : int pconfig_target_supported(enum pconfig_target target) 28 : : { 29 : : /* 30 : : * We would need to re-think the implementation once we get > 64 31 : : * PCONFIG targets. Spec allows up to 2^32 targets. 32 : : */ 33 : 0 : BUILD_BUG_ON(PCONFIG_TARGET_NR >= 64); 34 : : 35 [ # # # # ]: 0 : if (WARN_ON_ONCE(target >= 64)) 36 : : return 0; 37 : 0 : return targets_supported & (1ULL << target); 38 : : } 39 : : 40 : 11 : static int __init intel_pconfig_init(void) 41 : : { 42 : 11 : int subleaf; 43 : : 44 [ - + ]: 11 : if (!boot_cpu_has(X86_FEATURE_PCONFIG)) 45 : : return 0; 46 : : 47 : : /* 48 : : * Scan subleafs of PCONFIG CPUID leaf. 49 : : * 50 : : * Subleafs of the same type need not to be consecutive. 51 : : * 52 : : * Stop on the first invalid subleaf type. All subleafs after the first 53 : : * invalid are invalid too. 54 : : */ 55 [ # # ]: 0 : for (subleaf = 0; subleaf < INT_MAX; subleaf++) { 56 : 0 : struct cpuid_regs regs; 57 : : 58 : 0 : cpuid_count(PCONFIG_CPUID, subleaf, 59 : : ®s.eax, ®s.ebx, ®s.ecx, ®s.edx); 60 : : 61 [ # # # ]: 0 : switch (regs.eax & PCONFIG_CPUID_SUBLEAF_MASK) { 62 : 0 : case PCONFIG_CPUID_SUBLEAF_INVALID: 63 : : /* Stop on the first invalid subleaf */ 64 : 0 : goto out; 65 : 0 : case PCONFIG_CPUID_SUBLEAF_TARGETID: 66 : : /* Mark supported PCONFIG targets */ 67 [ # # ]: 0 : if (regs.ebx < 64) 68 : 0 : targets_supported |= (1ULL << regs.ebx); 69 [ # # ]: 0 : if (regs.ecx < 64) 70 : 0 : targets_supported |= (1ULL << regs.ecx); 71 [ # # ]: 0 : if (regs.edx < 64) 72 : 0 : targets_supported |= (1ULL << regs.edx); 73 : : break; 74 : : default: 75 : : /* Unknown CPUID.PCONFIG subleaf: ignore */ 76 : : break; 77 : : } 78 : : } 79 : 0 : out: 80 : : return 0; 81 : : } 82 : : arch_initcall(intel_pconfig_init);