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 1 : static int __init intel_pconfig_init(void) 41 : { 42 1 : int subleaf; 43 : 44 1 : 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);