intel_pconfig.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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 <[email protected]>
  9. */
  10. #include <asm/cpufeature.h>
  11. #include <asm/intel_pconfig.h>
  12. #define PCONFIG_CPUID 0x1b
  13. #define PCONFIG_CPUID_SUBLEAF_MASK ((1 << 12) - 1)
  14. /* Subleaf type (EAX) for PCONFIG CPUID leaf (0x1B) */
  15. enum {
  16. PCONFIG_CPUID_SUBLEAF_INVALID = 0,
  17. PCONFIG_CPUID_SUBLEAF_TARGETID = 1,
  18. };
  19. /* Bitmask of supported targets */
  20. static u64 targets_supported __read_mostly;
  21. int pconfig_target_supported(enum pconfig_target target)
  22. {
  23. /*
  24. * We would need to re-think the implementation once we get > 64
  25. * PCONFIG targets. Spec allows up to 2^32 targets.
  26. */
  27. BUILD_BUG_ON(PCONFIG_TARGET_NR >= 64);
  28. if (WARN_ON_ONCE(target >= 64))
  29. return 0;
  30. return targets_supported & (1ULL << target);
  31. }
  32. static int __init intel_pconfig_init(void)
  33. {
  34. int subleaf;
  35. if (!boot_cpu_has(X86_FEATURE_PCONFIG))
  36. return 0;
  37. /*
  38. * Scan subleafs of PCONFIG CPUID leaf.
  39. *
  40. * Subleafs of the same type need not to be consecutive.
  41. *
  42. * Stop on the first invalid subleaf type. All subleafs after the first
  43. * invalid are invalid too.
  44. */
  45. for (subleaf = 0; subleaf < INT_MAX; subleaf++) {
  46. struct cpuid_regs regs;
  47. cpuid_count(PCONFIG_CPUID, subleaf,
  48. &regs.eax, &regs.ebx, &regs.ecx, &regs.edx);
  49. switch (regs.eax & PCONFIG_CPUID_SUBLEAF_MASK) {
  50. case PCONFIG_CPUID_SUBLEAF_INVALID:
  51. /* Stop on the first invalid subleaf */
  52. goto out;
  53. case PCONFIG_CPUID_SUBLEAF_TARGETID:
  54. /* Mark supported PCONFIG targets */
  55. if (regs.ebx < 64)
  56. targets_supported |= (1ULL << regs.ebx);
  57. if (regs.ecx < 64)
  58. targets_supported |= (1ULL << regs.ecx);
  59. if (regs.edx < 64)
  60. targets_supported |= (1ULL << regs.edx);
  61. break;
  62. default:
  63. /* Unknown CPUID.PCONFIG subleaf: ignore */
  64. break;
  65. }
  66. }
  67. out:
  68. return 0;
  69. }
  70. arch_initcall(intel_pconfig_init);