Skip to content

Commit

Permalink
CPU API improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
vit9696 committed Aug 11, 2018
1 parent 24d7b73 commit d274cbe
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 13 deletions.
4 changes: 3 additions & 1 deletion Lilu/Headers/kern_cpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,10 @@ namespace CPUInfo {
* @param b ebx output pointer (optional)
* @param c ecx output pointer (optional)
* @param d edx output pointer (optional)
*
* @return true if supported
*/
EXPORT void getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b=nullptr, uint32_t *c=nullptr, uint32_t *d=nullptr);
EXPORT bool getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b=nullptr, uint32_t *c=nullptr, uint32_t *d=nullptr);
}

#endif /* kern_cpu_h */
15 changes: 15 additions & 0 deletions Lilu/Headers/kern_util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,21 @@ constexpr T getBitField(T so, T hi, T lo) {
return (so & getBitMask(hi, lo)) >> lo;
}

/**
* Set bit field of size sizeof(T)
* Warning, you are suggested to always pass the type explicitly!
*
* @param va value
* @param hi starting high bit
* @param lo ending low bit
*
* @return bit field value
*/
template <typename T>
constexpr T setBitField(T so, T hi, T lo) {
return (so << lo) & getBitMask(hi, lo);
}

/**
* This is an ugly replacement to std::find_if, allowing you
* to check whether a container consists only of value values.
Expand Down
31 changes: 22 additions & 9 deletions Lilu/Sources/kern_cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,22 @@ static CPUInfo::CpuGeneration currentGeneration = CPUInfo::CpuGeneration::Unknow
static uint32_t currentFamily = 0;
static uint32_t currentModel = 0;
static uint32_t currentStepping = 0;
static uint32_t currentMaxLevel = 0;
static uint32_t currentMaxLevelExt = 0x80000000;

void CPUInfo::loadCpuInformation() {
// Start with detecting CPU vendor
uint32_t b = 0, c = 0, d = 0;
getCpuid(0, 0, nullptr, &b, &c, &d);
getCpuid(0, 0, &currentMaxLevel, &b, &c, &d);
if (b == signature_INTEL_ebx && c == signature_INTEL_ecx && d == signature_INTEL_edx)
currentVendor = CpuVendor::Intel;
else if (b == signature_AMD_ebx && c == signature_AMD_ecx && d == signature_AMD_edx)
currentVendor = CpuVendor::AMD;

// Only do extended model checking on Intel
if (currentVendor != CpuVendor::Intel)
getCpuid(0x80000000, 0, &currentMaxLevelExt);

// Only do extended model checking on Intel or when unsupported.
if (currentVendor != CpuVendor::Intel || currentMaxLevel < 1)
return;

// Detect CPU family and model
Expand Down Expand Up @@ -174,6 +178,7 @@ bool CPUInfo::getCpuTopology(CpuTopology &topology) {
topology.logicalCount[topology.packageCount]++;
lcpu = lcpu->next_in_core;
}
core = core->next_in_pkg;
}

topology.packageCount++;
Expand All @@ -183,16 +188,24 @@ bool CPUInfo::getCpuTopology(CpuTopology &topology) {
return true;
}

void CPUInfo::getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
bool CPUInfo::getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
asm ("xchgq %%rbx, %q1\n"
"cpuid\n"
"xchgq %%rbx, %q1"
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
: "0" (no), "2" (count));

bool supported = (no & 0x80000000) ? currentMaxLevelExt >= no : currentMaxLevel >= no;

// At least pass zeroes on failure
if (supported) {
asm ("xchgq %%rbx, %q1\n"
"cpuid\n"
"xchgq %%rbx, %q1"
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
: "0" (no), "2" (count));
}

if (a) *a = eax;
if (b) *b = ebx;
if (c) *c = ecx;
if (d) *d = edx;

return supported;
}
7 changes: 4 additions & 3 deletions Lilu/Sources/kern_user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,9 +660,10 @@ bool UserPatcher::loadDyldSharedCacheMapping() {
uint8_t *buffer {nullptr};
size_t bufferSize {0};
uint32_t ebx = 0;
CPUInfo::getCpuid(7, 0, nullptr, &ebx);
if ((ebx & CPUInfo::bit_AVX2) && getKernelVersion() >= KernelVersion::Yosemite)
buffer = FileIO::readFileToBuffer(SharedCacheMapHaswell, bufferSize);
if (CPUInfo::getCpuid(7, 0, nullptr, &ebx)) {
if ((ebx & CPUInfo::bit_AVX2) && getKernelVersion() >= KernelVersion::Yosemite)
buffer = FileIO::readFileToBuffer(SharedCacheMapHaswell, bufferSize);
}

if (!buffer)
buffer = FileIO::readFileToBuffer(SharedCacheMapLegacy, bufferSize);
Expand Down

0 comments on commit d274cbe

Please sign in to comment.