ProcessorInfo.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/StringBuilder.h>
  8. #include <AK/Types.h>
  9. #include <Kernel/Arch/Processor.h>
  10. #include <Kernel/Arch/x86/CPUID.h>
  11. #include <Kernel/Arch/x86/ProcessorInfo.h>
  12. namespace Kernel {
  13. ProcessorInfo::ProcessorInfo(Processor const& processor)
  14. : m_vendor_id_string(build_vendor_id_string())
  15. , m_hypervisor_vendor_id_string(build_hypervisor_vendor_id_string(processor))
  16. , m_brand_string(build_brand_string())
  17. , m_features_string(build_features_string(processor))
  18. {
  19. CPUID cpuid(1);
  20. m_stepping = cpuid.eax() & 0xf;
  21. u32 model = (cpuid.eax() >> 4) & 0xf;
  22. u32 family = (cpuid.eax() >> 8) & 0xf;
  23. m_type = (cpuid.eax() >> 12) & 0x3;
  24. u32 extended_model = (cpuid.eax() >> 16) & 0xf;
  25. u32 extended_family = (cpuid.eax() >> 20) & 0xff;
  26. if (family == 15) {
  27. m_display_family = family + extended_family;
  28. m_display_model = model + (extended_model << 4);
  29. } else if (family == 6) {
  30. m_display_family = family;
  31. m_display_model = model + (extended_model << 4);
  32. } else {
  33. m_display_family = family;
  34. m_display_model = model;
  35. }
  36. }
  37. static void emit_u32(StringBuilder& builder, u32 value)
  38. {
  39. builder.appendff("{:c}{:c}{:c}{:c}",
  40. value & 0xff,
  41. (value >> 8) & 0xff,
  42. (value >> 16) & 0xff,
  43. (value >> 24) & 0xff);
  44. }
  45. NonnullOwnPtr<KString> ProcessorInfo::build_vendor_id_string()
  46. {
  47. CPUID cpuid(0);
  48. StringBuilder builder;
  49. emit_u32(builder, cpuid.ebx());
  50. emit_u32(builder, cpuid.edx());
  51. emit_u32(builder, cpuid.ecx());
  52. // NOTE: This isn't necessarily fixed length and might have null terminators at the end.
  53. return KString::must_create(builder.string_view().trim("\0"sv, TrimMode::Right));
  54. }
  55. NonnullOwnPtr<KString> ProcessorInfo::build_hypervisor_vendor_id_string(Processor const& processor)
  56. {
  57. if (!processor.has_feature(CPUFeature::HYPERVISOR))
  58. return KString::must_create({});
  59. CPUID cpuid(0x40000000);
  60. StringBuilder builder;
  61. emit_u32(builder, cpuid.ebx());
  62. emit_u32(builder, cpuid.ecx());
  63. emit_u32(builder, cpuid.edx());
  64. // NOTE: This isn't necessarily fixed length and might have null terminators at the end.
  65. return KString::must_create(builder.string_view().trim("\0"sv, TrimMode::Right));
  66. }
  67. NonnullOwnPtr<KString> ProcessorInfo::build_brand_string()
  68. {
  69. u32 max_extended_leaf = CPUID(0x80000000).eax();
  70. if (max_extended_leaf < 0x80000004)
  71. return KString::must_create({});
  72. StringBuilder builder;
  73. auto append_brand_string_part_to_builder = [&](u32 i) {
  74. CPUID cpuid(0x80000002 + i);
  75. emit_u32(builder, cpuid.eax());
  76. emit_u32(builder, cpuid.ebx());
  77. emit_u32(builder, cpuid.ecx());
  78. emit_u32(builder, cpuid.edx());
  79. };
  80. append_brand_string_part_to_builder(0);
  81. append_brand_string_part_to_builder(1);
  82. append_brand_string_part_to_builder(2);
  83. // NOTE: This isn't necessarily fixed length and might have null terminators at the end.
  84. return KString::must_create(builder.string_view().trim("\0"sv, TrimMode::Right));
  85. }
  86. NonnullOwnPtr<KString> ProcessorInfo::build_features_string(Processor const& processor)
  87. {
  88. StringBuilder builder;
  89. bool first = true;
  90. for (auto feature = CPUFeature::Type(1u); feature != CPUFeature::__End; feature <<= 1u) {
  91. if (processor.has_feature(feature)) {
  92. if (first)
  93. first = false;
  94. else
  95. MUST(builder.try_append(' '));
  96. MUST(builder.try_append(cpu_feature_to_string_view(feature)));
  97. }
  98. }
  99. return KString::must_create(builder.string_view());
  100. }
  101. }