From 7477f99d05f845f7663467c6db3c333e56969f83 Mon Sep 17 00:00:00 2001 From: Benjamin Lamowski Date: Wed, 19 Oct 2022 16:25:55 +0200 Subject: [PATCH] base-hw: x86: detect CPU Vendor and SVM support Ref #4826 --- .../src/core/spec/x86_64/platform_support.cc | 2 +- .../base-hw/src/include/hw/spec/x86_64/cpu.h | 12 +++ .../src/include/hw/spec/x86_64/x86_64.h | 81 ++++++++++++++++++- 3 files changed, 93 insertions(+), 2 deletions(-) diff --git a/repos/base-hw/src/core/spec/x86_64/platform_support.cc b/repos/base-hw/src/core/spec/x86_64/platform_support.cc index 0aba3437ca..7b3d97cece 100644 --- a/repos/base-hw/src/core/spec/x86_64/platform_support.cc +++ b/repos/base-hw/src/core/spec/x86_64/platform_support.cc @@ -54,7 +54,7 @@ void Platform::_init_additional_platform_info(Xml_generator &xml) }); xml.node("hardware", [&] () { xml.node("features", [&] () { - xml.attribute("svm", false); + xml.attribute("svm", Hw::Virtualization_support::has_svm()); xml.attribute("vmx", false); }); }); diff --git a/repos/base-hw/src/include/hw/spec/x86_64/cpu.h b/repos/base-hw/src/include/hw/spec/x86_64/cpu.h index 130adf1079..2063527fb4 100644 --- a/repos/base-hw/src/include/hw/spec/x86_64/cpu.h +++ b/repos/base-hw/src/include/hw/spec/x86_64/cpu.h @@ -104,10 +104,22 @@ struct Hw::X86_64_cpu }; ); + X86_64_MSR_REGISTER(Amd_vm_cr, 0xC0010114, + struct Svmdis : Bitfield< 4, 1> { }; /* SVM disabled */ + ); + + X86_64_CPUID_REGISTER(Cpuid_0_ebx, 0, ebx); + X86_64_CPUID_REGISTER(Cpuid_0_ecx, 0, ecx); + X86_64_CPUID_REGISTER(Cpuid_0_edx, 0, edx); + X86_64_CPUID_REGISTER(Cpuid_1_edx, 1, edx, struct Pat : Bitfield<16, 1> { }; ); + X86_64_CPUID_REGISTER(Cpuid_80000001_ecx, 0x80000001, ecx, + struct Svm : Bitfield<2, 1> { }; + ); + Suspend_type suspend; }; diff --git a/repos/base-hw/src/include/hw/spec/x86_64/x86_64.h b/repos/base-hw/src/include/hw/spec/x86_64/x86_64.h index 19f4a399e9..37468a7266 100644 --- a/repos/base-hw/src/include/hw/spec/x86_64/x86_64.h +++ b/repos/base-hw/src/include/hw/spec/x86_64/x86_64.h @@ -14,10 +14,15 @@ #ifndef _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ #define _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ +#include #include #include -namespace Hw { struct Cpu_memory_map; } +namespace Hw { + struct Cpu_memory_map; + struct Virtualization_support; + class Vendor; +} struct Hw::Cpu_memory_map @@ -35,4 +40,78 @@ struct Hw::Cpu_memory_map } }; +struct Hw::Vendor +{ +private: + static constexpr char const *const vendor_string[] = { + "GenuineIntel", + "AuthenticAMD", + "KVMKVMKVM", + "Microsoft Hv", + "VMwareVMware", + "XenVMMXenVMM" + "Unknown", + }; + +public: + enum Vendor_id { + INTEL, + AMD, + KVM, + MICROSOFT, + VMWARE, + XEN, + UNKNOWN, + }; + + static Vendor_id get_vendor_id() + { + using Cpu = Hw::X86_64_cpu; + using Genode::uint32_t; + + uint32_t ebx = static_cast(Cpu::Cpuid_0_ebx::read()); + uint32_t ecx = static_cast(Cpu::Cpuid_0_ecx::read()); + uint32_t edx = static_cast(Cpu::Cpuid_0_edx::read()); + + Genode::size_t v; + for (v = 0; v <= Vendor_id::UNKNOWN; ++v) + if (*reinterpret_cast(vendor_string[v] + + 0) == ebx && + *reinterpret_cast(vendor_string[v] + + 4) == edx && + *reinterpret_cast(vendor_string[v] + + 8) == ecx) + break; + + return Vendor_id(v); + } +}; + +struct Hw::Virtualization_support +{ + using Cpu = Hw::X86_64_cpu; + static bool has_svm() + { + /* + * Check for vendor because the CPUID bit checked for SVM is reserved + * on Intel. + */ + if (Hw::Vendor::get_vendor_id() != Hw::Vendor::AMD) + return false; + + Hw::X86_64_cpu::Cpuid_80000001_ecx::access_t cpuid_svm = + Hw::X86_64_cpu::Cpuid_80000001_ecx::read(); + + if (Hw::X86_64_cpu::Cpuid_80000001_ecx::Svm::get(cpuid_svm) != 0) { + Hw::X86_64_cpu::Amd_vm_cr::access_t amd_vm_cr = + Hw::X86_64_cpu::Amd_vm_cr::read(); + + if (Hw::X86_64_cpu::Amd_vm_cr::Svmdis::get(amd_vm_cr) == 0) + return true; + } + + return false; + } +}; + #endif /* _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ */