base-hw: x86: detect CPU Vendor and SVM support

Ref #4826
This commit is contained in:
Benjamin Lamowski 2022-10-19 16:25:55 +02:00 committed by Christian Helmuth
parent 6ca7119267
commit 7477f99d05
3 changed files with 93 additions and 2 deletions

View File

@ -54,7 +54,7 @@ void Platform::_init_additional_platform_info(Xml_generator &xml)
}); });
xml.node("hardware", [&] () { xml.node("hardware", [&] () {
xml.node("features", [&] () { xml.node("features", [&] () {
xml.attribute("svm", false); xml.attribute("svm", Hw::Virtualization_support::has_svm());
xml.attribute("vmx", false); xml.attribute("vmx", false);
}); });
}); });

View File

@ -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, X86_64_CPUID_REGISTER(Cpuid_1_edx, 1, edx,
struct Pat : Bitfield<16, 1> { }; struct Pat : Bitfield<16, 1> { };
); );
X86_64_CPUID_REGISTER(Cpuid_80000001_ecx, 0x80000001, ecx,
struct Svm : Bitfield<2, 1> { };
);
Suspend_type suspend; Suspend_type suspend;
}; };

View File

@ -14,10 +14,15 @@
#ifndef _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ #ifndef _SRC__LIB__HW__SPEC__X86_64__X86_64_H_
#define _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ #define _SRC__LIB__HW__SPEC__X86_64__X86_64_H_
#include <base/log.h>
#include <base/stdint.h> #include <base/stdint.h>
#include <hw/spec/x86_64/cpu.h> #include <hw/spec/x86_64/cpu.h>
namespace Hw { struct Cpu_memory_map; } namespace Hw {
struct Cpu_memory_map;
struct Virtualization_support;
class Vendor;
}
struct Hw::Cpu_memory_map 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<uint32_t>(Cpu::Cpuid_0_ebx::read());
uint32_t ecx = static_cast<uint32_t>(Cpu::Cpuid_0_ecx::read());
uint32_t edx = static_cast<uint32_t>(Cpu::Cpuid_0_edx::read());
Genode::size_t v;
for (v = 0; v <= Vendor_id::UNKNOWN; ++v)
if (*reinterpret_cast<uint32_t const *>(vendor_string[v] +
0) == ebx &&
*reinterpret_cast<uint32_t const *>(vendor_string[v] +
4) == edx &&
*reinterpret_cast<uint32_t const *>(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_ */ #endif /* _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ */