mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2026-02-01 15:59:39 +00:00
OcCpuLib: Implement ASM CPU frequency calculation for HSW and lower
This commit is contained in:
parent
cd5bd93932
commit
a62cdf2e26
@ -3,6 +3,7 @@ OpenCore Changelog
|
||||
#### v0.6.7
|
||||
- Fixed ocvalidate return code to be non-zero when issues are found
|
||||
- Added `OEM` values to `PlatformInfo` in `Automatic` mode
|
||||
- Improved CPU frequency calculation on Haswell and earlier
|
||||
|
||||
#### v0.6.6
|
||||
- Added keyboard and pointer entry scroll support in OpenCanopy
|
||||
|
||||
@ -129,15 +129,14 @@ InternalCalculateTSCFromPMTimer (
|
||||
//
|
||||
STATIC UINT64 TSCFrequency = 0;
|
||||
|
||||
UINTN TimerAddr;
|
||||
UINT16 TimerAddr;
|
||||
UINTN VariableSize;
|
||||
UINT64 Tsc0;
|
||||
UINT64 Tsc1;
|
||||
UINT64 TscTicksDelta;
|
||||
UINT32 AcpiTick0;
|
||||
UINT32 AcpiTick1;
|
||||
UINT32 AcpiTicksDelta;
|
||||
UINT32 AcpiTicksTarget;
|
||||
UINT32 TimerResolution;
|
||||
UINT32 AcpiTicksDuration;
|
||||
BOOLEAN HasInterrupts;
|
||||
EFI_TPL PrevTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
@ -169,8 +168,7 @@ InternalCalculateTSCFromPMTimer (
|
||||
}
|
||||
|
||||
if (TSCFrequency == 0) {
|
||||
TimerAddr = InternalGetPmTimerAddr (NULL);
|
||||
TimerResolution = 10;
|
||||
TimerAddr = (UINT16) InternalGetPmTimerAddr (NULL);
|
||||
|
||||
if (TimerAddr != 0) {
|
||||
//
|
||||
@ -187,63 +185,24 @@ InternalCalculateTSCFromPMTimer (
|
||||
// The code below can handle overflow with AcpiTicksTarget of up to 24-bit size,
|
||||
// on both available sizes of ACPI PM Timers (24-bit and 32-bit).
|
||||
//
|
||||
// 357954 clocks of ACPI timer (100ms)
|
||||
// 357954 clocks of ACPI timer (200ms)
|
||||
//
|
||||
AcpiTicksTarget = V_ACPI_TMR_FREQUENCY / TimerResolution;
|
||||
AcpiTicksDuration = V_ACPI_TMR_FREQUENCY / 10;
|
||||
|
||||
//
|
||||
// Disable all events to ensure that nobody interrupts us.
|
||||
//
|
||||
PrevTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
||||
|
||||
AcpiTick0 = IoRead32 (TimerAddr);
|
||||
Tsc0 = AsmReadTsc ();
|
||||
|
||||
do {
|
||||
CpuPause ();
|
||||
|
||||
//
|
||||
// Check how many AcpiTicks have passed since we started.
|
||||
//
|
||||
AcpiTick1 = IoRead32 (TimerAddr);
|
||||
|
||||
if (AcpiTick0 <= AcpiTick1) {
|
||||
//
|
||||
// No overflow.
|
||||
//
|
||||
AcpiTicksDelta = AcpiTick1 - AcpiTick0;
|
||||
} else if (AcpiTick0 - AcpiTick1 <= 0x00FFFFFF) {
|
||||
//
|
||||
// Overflow, 24-bit timer.
|
||||
//
|
||||
AcpiTicksDelta = 0x00FFFFFF - AcpiTick0 + AcpiTick1;
|
||||
} else {
|
||||
//
|
||||
// Overflow, 32-bit timer.
|
||||
//
|
||||
AcpiTicksDelta = MAX_UINT32 - AcpiTick0 + AcpiTick1;
|
||||
}
|
||||
|
||||
//
|
||||
// Keep checking AcpiTicks until target is reached.
|
||||
//
|
||||
} while (AcpiTicksDelta < AcpiTicksTarget);
|
||||
|
||||
Tsc1 = AsmReadTsc ();
|
||||
|
||||
//
|
||||
// On some systems we may end up waiting for notably longer than 100ms,
|
||||
// despite disabling all events. Divide by actual time passed as suggested
|
||||
// by asava's Clover patch r2668.
|
||||
//
|
||||
TSCFrequency = DivU64x32 (
|
||||
MultU64x32 (Tsc1 - Tsc0, V_ACPI_TMR_FREQUENCY), AcpiTicksDelta
|
||||
);
|
||||
|
||||
//
|
||||
// Restore to normal TPL.
|
||||
//
|
||||
HasInterrupts = SaveAndDisableInterrupts ();
|
||||
AsmMeasureTicks (AcpiTicksDuration, TimerAddr, &AcpiTicksDelta, &TscTicksDelta);
|
||||
if (HasInterrupts) {
|
||||
EnableInterrupts ();
|
||||
}
|
||||
gBS->RestoreTPL (PrevTpl);
|
||||
|
||||
TSCFrequency = DivU64x32 (
|
||||
MultU64x32 (TscTicksDelta, V_ACPI_TMR_FREQUENCY), AcpiTicksDelta
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
77
Library/OcCpuLib/Ia32/MeasureTicks.c
Normal file
77
Library/OcCpuLib/Ia32/MeasureTicks.c
Normal file
@ -0,0 +1,77 @@
|
||||
/** @file
|
||||
Copyright (C) 2020, vit9696. All rights reserved.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
**/
|
||||
|
||||
#include "OcCpuInternals.h"
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
AsmMeasureTicks (
|
||||
IN UINT32 AcpiTicksDuration,
|
||||
IN UINT16 TimerAddr,
|
||||
OUT UINT32 *AcpiTicksDelta,
|
||||
OUT UINT64 *TscTicksDelta
|
||||
)
|
||||
{
|
||||
UINT32 AcpiTick0;
|
||||
UINT32 AcpiTick1;
|
||||
UINT32 AcpiCurrentDelta;
|
||||
UINT64 Tsc0;
|
||||
UINT64 Tsc1;
|
||||
|
||||
AcpiTick0 = IoRead32 (TimerAddr);
|
||||
Tsc0 = AsmReadTsc ();
|
||||
|
||||
do {
|
||||
CpuPause ();
|
||||
|
||||
//
|
||||
// Check how many AcpiTicks have passed since we started.
|
||||
//
|
||||
AcpiTick1 = IoRead32 (TimerAddr);
|
||||
|
||||
if (AcpiTick0 <= AcpiTick1) {
|
||||
//
|
||||
// No overflow.
|
||||
//
|
||||
AcpiCurrentDelta = AcpiTick1 - AcpiTick0;
|
||||
} else if (AcpiTick0 - AcpiTick1 <= 0x00FFFFFF) {
|
||||
//
|
||||
// Overflow, 24-bit timer.
|
||||
//
|
||||
AcpiCurrentDelta = 0x00FFFFFF - AcpiTick0 + AcpiTick1;
|
||||
} else {
|
||||
//
|
||||
// Overflow, 32-bit timer.
|
||||
//
|
||||
AcpiCurrentDelta = MAX_UINT32 - AcpiTick0 + AcpiTick1;
|
||||
}
|
||||
|
||||
//
|
||||
// Keep checking AcpiTicks until target is reached.
|
||||
//
|
||||
} while (AcpiCurrentDelta < AcpiTicksDuration);
|
||||
|
||||
Tsc1 = AsmReadTsc ();
|
||||
|
||||
//
|
||||
// On some systems we may end up waiting for notably longer than 100ms,
|
||||
// despite disabling all events. Divide by actual time passed as suggested
|
||||
// by asava's Clover patch r2668.
|
||||
//
|
||||
*TscTicksDelta = Tsc1 - Tsc0;
|
||||
*AcpiTicksDelta = AcpiCurrentDelta;
|
||||
}
|
||||
@ -41,6 +41,23 @@ AsmReadIntelMicrocodeRevision (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Measures TSC and ACPI ticks over specified ACPI tick amount.
|
||||
|
||||
@param[in] AcpiTicksDuration Number of ACPI ticks for calculation.
|
||||
@param[in] TimerAddr ACPI timer address.
|
||||
@param[out] AcpiTicksDelta Reported ACPI ticks delta.
|
||||
@param[out] TscTicksDelta Reported TSC ticks delta.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
AsmMeasureTicks (
|
||||
IN UINT32 AcpiTicksDuration,
|
||||
IN UINT16 TimerAddr,
|
||||
OUT UINT32 *AcpiTicksDelta,
|
||||
OUT UINT64 *TscTicksDelta
|
||||
);
|
||||
|
||||
/**
|
||||
Detect Apple CPU major type.
|
||||
|
||||
|
||||
@ -52,8 +52,10 @@
|
||||
|
||||
[Sources.Ia32]
|
||||
Ia32/Atomic.nasm
|
||||
Ia32/MeasureTicks.c
|
||||
Ia32/Microcode.nasm
|
||||
|
||||
[Sources.X64]
|
||||
X64/Atomic.nasm
|
||||
X64/MeasureTicks.nasm
|
||||
X64/Microcode.nasm
|
||||
|
||||
112
Library/OcCpuLib/X64/MeasureTicks.nasm
Normal file
112
Library/OcCpuLib/X64/MeasureTicks.nasm
Normal file
@ -0,0 +1,112 @@
|
||||
;------------------------------------------------------------------------------
|
||||
; @file
|
||||
; Copyright (C) 2020, vit9696. All rights reserved.
|
||||
;
|
||||
; All rights reserved.
|
||||
;
|
||||
; This program and the accompanying materials
|
||||
; are licensed and made available under the terms and conditions of the BSD License
|
||||
; which accompanies this distribution. The full text of the license may be found at
|
||||
; http://opensource.org/licenses/bsd-license.php
|
||||
;
|
||||
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
BITS 64
|
||||
DEFAULT REL
|
||||
|
||||
SECTION .text
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; VOID
|
||||
; EFIAPI
|
||||
; AsmMeasureTicks (
|
||||
; IN UINT32 AcpiTicksDuration, ///< ecx
|
||||
; IN UINT16 TimerAddr, ///< dx
|
||||
; OUT UINT32 *AcpiTicksDelta, ///< r8
|
||||
; OUT UINT64 *TscTicksDelta ///< r9
|
||||
; );
|
||||
;------------------------------------------------------------------------------
|
||||
global ASM_PFX(AsmMeasureTicks)
|
||||
ASM_PFX(AsmMeasureTicks):
|
||||
; Push preserved registers.
|
||||
push rsi
|
||||
push rdi
|
||||
push rbp
|
||||
push rbx
|
||||
|
||||
; Preserve TimerAddr in r11d as rdtsc overrides edx.
|
||||
mov r11d, edx
|
||||
|
||||
; Read AcpiTicks0 into ebx.
|
||||
in eax, dx
|
||||
mov ebx, eax
|
||||
|
||||
; Read Tsc0 into r10.
|
||||
rdtsc
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
mov r10, rax
|
||||
|
||||
; Store MAX_UINT32 - AcpiTick0 into ebp.
|
||||
mov ebp, ebx
|
||||
not ebp
|
||||
|
||||
; Store MAX_UINT24 - AcpiTick0 into edi.
|
||||
mov edi, 0x00ffffff
|
||||
sub edi, ebx
|
||||
|
||||
CalculationLoop:
|
||||
nop ; or pause.
|
||||
|
||||
; Read AcpiTicks1 into esi.
|
||||
mov edx, r11d
|
||||
in eax, dx
|
||||
mov esi, eax
|
||||
|
||||
; Calculate AcpiTicks0 - AcpiTicks1 into eax.
|
||||
mov eax, ebx
|
||||
sub eax, esi
|
||||
jbe NoOverflow
|
||||
|
||||
; Check for 32-bit overflow.
|
||||
cmp eax, 0x00ffffff
|
||||
ja Overflow32
|
||||
|
||||
Overflow24:
|
||||
; AcpiCurrentDelta (esi) = AcpiTicks1 (esi) + MAX_UINT24 - AcpiTick0 (edi)
|
||||
add esi, edi
|
||||
jmp ContinueLoop
|
||||
|
||||
NoOverflow:
|
||||
; AcpiCurrentDelta (esi) = AcpiTicks1 (esi) - AcpiTicks0 (ebx)
|
||||
sub esi, ebx
|
||||
jmp ContinueLoop
|
||||
|
||||
Overflow32:
|
||||
; AcpiCurrentDelta (esi) = AcpiTicks1 (esi) + MAX_UINT32 - AcpiTick0 (ebp)
|
||||
add esi, ebp
|
||||
|
||||
ContinueLoop:
|
||||
cmp esi, ecx
|
||||
jb CalculationLoop
|
||||
|
||||
; Read Tsc1 into rax.
|
||||
rdtsc
|
||||
shl rdx, 32
|
||||
or rax, rdx
|
||||
|
||||
; Calculate TscDelta into rax.
|
||||
sub rax, r10
|
||||
|
||||
; Store TscDelta and AcpiDelta.
|
||||
mov qword [r9], rax
|
||||
mov dword [r8], esi
|
||||
|
||||
; Pop preserved registers & return.
|
||||
pop rbx
|
||||
pop rbp
|
||||
pop rdi
|
||||
pop rsi
|
||||
ret
|
||||
Loading…
x
Reference in New Issue
Block a user