Skip to content

Commit d274cbe

Browse files
committed
CPU API improvements
1 parent 24d7b73 commit d274cbe

File tree

4 files changed

+44
-13
lines changed

4 files changed

+44
-13
lines changed

Lilu/Headers/kern_cpu.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,10 @@ namespace CPUInfo {
400400
* @param b ebx output pointer (optional)
401401
* @param c ecx output pointer (optional)
402402
* @param d edx output pointer (optional)
403+
*
404+
* @return true if supported
403405
*/
404-
EXPORT void getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b=nullptr, uint32_t *c=nullptr, uint32_t *d=nullptr);
406+
EXPORT bool getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b=nullptr, uint32_t *c=nullptr, uint32_t *d=nullptr);
405407
}
406408

407409
#endif /* kern_cpu_h */

Lilu/Headers/kern_util.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,21 @@ constexpr T getBitField(T so, T hi, T lo) {
414414
return (so & getBitMask(hi, lo)) >> lo;
415415
}
416416

417+
/**
418+
* Set bit field of size sizeof(T)
419+
* Warning, you are suggested to always pass the type explicitly!
420+
*
421+
* @param va value
422+
* @param hi starting high bit
423+
* @param lo ending low bit
424+
*
425+
* @return bit field value
426+
*/
427+
template <typename T>
428+
constexpr T setBitField(T so, T hi, T lo) {
429+
return (so << lo) & getBitMask(hi, lo);
430+
}
431+
417432
/**
418433
* This is an ugly replacement to std::find_if, allowing you
419434
* to check whether a container consists only of value values.

Lilu/Sources/kern_cpu.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,22 @@ static CPUInfo::CpuGeneration currentGeneration = CPUInfo::CpuGeneration::Unknow
1818
static uint32_t currentFamily = 0;
1919
static uint32_t currentModel = 0;
2020
static uint32_t currentStepping = 0;
21+
static uint32_t currentMaxLevel = 0;
22+
static uint32_t currentMaxLevelExt = 0x80000000;
2123

2224
void CPUInfo::loadCpuInformation() {
2325
// Start with detecting CPU vendor
2426
uint32_t b = 0, c = 0, d = 0;
25-
getCpuid(0, 0, nullptr, &b, &c, &d);
27+
getCpuid(0, 0, &currentMaxLevel, &b, &c, &d);
2628
if (b == signature_INTEL_ebx && c == signature_INTEL_ecx && d == signature_INTEL_edx)
2729
currentVendor = CpuVendor::Intel;
2830
else if (b == signature_AMD_ebx && c == signature_AMD_ecx && d == signature_AMD_edx)
2931
currentVendor = CpuVendor::AMD;
3032

31-
// Only do extended model checking on Intel
32-
if (currentVendor != CpuVendor::Intel)
33+
getCpuid(0x80000000, 0, &currentMaxLevelExt);
34+
35+
// Only do extended model checking on Intel or when unsupported.
36+
if (currentVendor != CpuVendor::Intel || currentMaxLevel < 1)
3337
return;
3438

3539
// Detect CPU family and model
@@ -174,6 +178,7 @@ bool CPUInfo::getCpuTopology(CpuTopology &topology) {
174178
topology.logicalCount[topology.packageCount]++;
175179
lcpu = lcpu->next_in_core;
176180
}
181+
core = core->next_in_pkg;
177182
}
178183

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

186-
void CPUInfo::getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
191+
bool CPUInfo::getCpuid(uint32_t no, uint32_t count, uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d) {
187192
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
188-
asm ("xchgq %%rbx, %q1\n"
189-
"cpuid\n"
190-
"xchgq %%rbx, %q1"
191-
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
192-
: "0" (no), "2" (count));
193+
194+
bool supported = (no & 0x80000000) ? currentMaxLevelExt >= no : currentMaxLevel >= no;
195+
196+
// At least pass zeroes on failure
197+
if (supported) {
198+
asm ("xchgq %%rbx, %q1\n"
199+
"cpuid\n"
200+
"xchgq %%rbx, %q1"
201+
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
202+
: "0" (no), "2" (count));
203+
}
193204

194205
if (a) *a = eax;
195206
if (b) *b = ebx;
196207
if (c) *c = ecx;
197208
if (d) *d = edx;
209+
210+
return supported;
198211
}

Lilu/Sources/kern_user.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -660,9 +660,10 @@ bool UserPatcher::loadDyldSharedCacheMapping() {
660660
uint8_t *buffer {nullptr};
661661
size_t bufferSize {0};
662662
uint32_t ebx = 0;
663-
CPUInfo::getCpuid(7, 0, nullptr, &ebx);
664-
if ((ebx & CPUInfo::bit_AVX2) && getKernelVersion() >= KernelVersion::Yosemite)
665-
buffer = FileIO::readFileToBuffer(SharedCacheMapHaswell, bufferSize);
663+
if (CPUInfo::getCpuid(7, 0, nullptr, &ebx)) {
664+
if ((ebx & CPUInfo::bit_AVX2) && getKernelVersion() >= KernelVersion::Yosemite)
665+
buffer = FileIO::readFileToBuffer(SharedCacheMapHaswell, bufferSize);
666+
}
666667

667668
if (!buffer)
668669
buffer = FileIO::readFileToBuffer(SharedCacheMapLegacy, bufferSize);

0 commit comments

Comments
 (0)