-
Notifications
You must be signed in to change notification settings - Fork 909
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
777048c
commit 575ab46
Showing
20 changed files
with
2,223 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package x86 | ||
|
||
const ( | ||
// CPUID_TIME_STAMP_COUNTER | ||
// EAX Returns processor base frequency information described by the | ||
// type CPUID_PROCESSOR_FREQUENCY_EAX. | ||
// EBX Returns maximum frequency information described by the type | ||
// CPUID_PROCESSOR_FREQUENCY_EBX. | ||
// ECX Returns bus frequency information described by the type | ||
// CPUID_PROCESSOR_FREQUENCY_ECX. | ||
// EDX Reserved. | ||
CPUID_TIME_STAMP_COUNTER = 0x15 | ||
|
||
// CPUID_PROCESSOR_FREQUENCY | ||
// EAX Returns processor base frequency information described by the | ||
// type CPUID_PROCESSOR_FREQUENCY_EAX. | ||
// EBX Returns maximum frequency information described by the type | ||
// CPUID_PROCESSOR_FREQUENCY_EBX. | ||
// ECX Returns bus frequency information described by the type | ||
// CPUID_PROCESSOR_FREQUENCY_ECX. | ||
// EDX Reserved. | ||
CPUID_PROCESSOR_FREQUENCY = 0x16 | ||
) | ||
|
||
//export asmReadRdtsc | ||
func AsmReadRdtsc() uint64 | ||
|
||
//export asmCpuid | ||
func AsmCpuid(index int, registerEax *uint32, registerRbx *uint32, registerEcx *uint32, registerEdx *uint32) | ||
|
||
func InternalGetPerformanceCounterFrequency() uint64 { | ||
return CpuidCoreClockCalculateTscFrequency() | ||
} | ||
|
||
func GetTimeInNanoSecond(ticks uint64) int64 { | ||
frequency := InternalGetPerformanceCounterFrequency() | ||
return ConvertTimeInNanoSecond(frequency, ticks) | ||
} | ||
|
||
func ConvertTimeInNanoSecond(frequency uint64, ticks uint64) int64 { | ||
// Ticks | ||
// Time = --------- x 1,000,000,000 | ||
// Frequency | ||
nanoSeconds := (ticks / frequency) * 1000000000 | ||
remainder := ticks % frequency | ||
|
||
// Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. | ||
// Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, | ||
// i.e. highest bit set in Remainder should <= 33. | ||
// | ||
shift := highBitSet64(remainder) - 32 | ||
if shift < 0 { | ||
shift = 0 | ||
} | ||
remainder = remainder >> shift | ||
frequency = frequency >> shift | ||
nanoSeconds += remainder * 1000000000 / frequency | ||
|
||
return int64(nanoSeconds) | ||
} | ||
|
||
func GetTicksFromNanoSeconds(nano uint64) uint64 { | ||
frequency := InternalGetPerformanceCounterFrequency() | ||
return nano * frequency / 1000000000 | ||
} | ||
|
||
func highBitSet64(operand uint64) int { | ||
if operand == (operand & 0xffffffff) { | ||
return highBitSet32(uint32(operand)) | ||
} | ||
return highBitSet32(uint32(operand>>32)) + 32 | ||
} | ||
|
||
func highBitSet32(operand uint32) int { | ||
if operand == 0 { | ||
return -1 | ||
} | ||
bitIndex := 32 | ||
for operand > 0 { | ||
bitIndex-- | ||
operand <<= 1 | ||
} | ||
return bitIndex | ||
} | ||
|
||
/* | ||
UINT64 | ||
EFIAPI | ||
GetTimeInNanoSecond ( | ||
IN UINT64 Ticks | ||
) | ||
{ | ||
UINT64 Frequency; | ||
UINT64 NanoSeconds; | ||
UINT64 Remainder; | ||
INTN Shift; | ||
Frequency = GetPerformanceCounterProperties (NULL, NULL); | ||
NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u); | ||
// | ||
// Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. | ||
// Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, | ||
// i.e. highest bit set in Remainder should <= 33. | ||
// | ||
Shift = MAX (0, HighBitSet64 (Remainder) - 33); | ||
Remainder = RShiftU64 (Remainder, (UINTN)Shift); | ||
Frequency = RShiftU64 (Frequency, (UINTN)Shift); | ||
NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL); | ||
return NanoSeconds; | ||
} | ||
*/ | ||
|
||
func CpuidCoreClockCalculateTscFrequency() uint64 { | ||
var TscFrequency uint64 | ||
var CoreXtalFrequency uint64 | ||
var RegEax uint32 | ||
var RegEbx uint32 | ||
var RegEcx uint32 | ||
|
||
AsmCpuid(CPUID_TIME_STAMP_COUNTER, &RegEax, &RegEbx, &RegEcx, nil) | ||
|
||
// If EAX or EBX returns 0, the XTAL ratio is not enumerated. | ||
if (RegEax == 0) || (RegEbx == 0) { | ||
return 0 | ||
} | ||
|
||
// If ECX returns 0, the XTAL frequency is not enumerated. | ||
// And PcdCpuCoreCrystalClockFrequency defined should base on processor series. | ||
// | ||
if RegEcx == 0 { | ||
// Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency. | ||
// Intel Xeon Processor Scalable Family with CPUID signature 06_55H = 25000000 (25MHz) | ||
// 6th and 7th generation Intel Core processors and Intel Xeon W Processor Family = 24000000 (24MHz) | ||
// Intel Atom processors based on Goldmont Microarchitecture with CPUID signature 06_5CH = 19200000 (19.2MHz) | ||
CoreXtalFrequency = 24000000 | ||
} else { | ||
CoreXtalFrequency = uint64(RegEcx) | ||
} | ||
|
||
// Calculate TSC frequency = (ECX, Core Xtal Frequency) * EBX/EAX | ||
TscFrequency = ((CoreXtalFrequency * uint64(RegEbx)) + (uint64(RegEax) / 2)) / uint64(RegEax) | ||
return TscFrequency | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
.section .text | ||
|
||
.global asmReadRdtsc | ||
asmReadRdtsc: | ||
rdtsc | ||
shlq $0x20, %rdx | ||
orq %rdx, %rax | ||
ret | ||
|
||
// @param Index The 32-bit value to load into EAX prior to invoking the CPUID | ||
// instruction. | ||
// @param RegisterEax A pointer to the 32-bit EAX value returned by the CPUID | ||
// instruction. This is an optional parameter that may be NULL. | ||
// @param RegisterEbx A pointer to the 32-bit EBX value returned by the CPUID | ||
// instruction. This is an optional parameter that may be NULL. | ||
// @param RegisterEcx A pointer to the 32-bit ECX value returned by the CPUID | ||
// instruction. This is an optional parameter that may be NULL. | ||
// @param RegisterEdx A pointer to the 32-bit EDX value returned by the CPUID | ||
// instruction. This is an optional parameter that may be NULL. | ||
// @return Index. | ||
.global asmCpuid | ||
asmCpuid: | ||
// rcx = Index | ||
// rdx = RegisterEax | ||
// r8 = RegisterEbx | ||
// r9 = RegisterEcx | ||
// rsp + 0x28 = RegisterEdx | ||
pushq %rbx | ||
|
||
mov %ecx, %eax // eax <- index | ||
pushq %rax // save Index on stack | ||
|
||
pushq %rdx // RegisterEax | ||
cpuid | ||
|
||
test %r9, %r9 // RegisterEcx | ||
jz .SkipEcx | ||
mov %ecx, (%r9) | ||
.SkipEcx: | ||
popq %rcx // RegisterEax | ||
jrcxz .SkipEax | ||
mov %eax, (%rcx) | ||
.SkipEax: | ||
mov %r8, %rcx // RegisterEbx | ||
jrcxz .SkipEbx | ||
mov %ebx, (%rcx) | ||
.SkipEbx: | ||
mov 0x38(%rsp), %rcx // 0x28 + 0x10 | ||
jrcxz .SkipEdx | ||
mov %edx, (%rcx) | ||
.SkipEdx: | ||
popq %rax // restore Index to rax as return value | ||
popq %rbx | ||
ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
.section .text | ||
|
||
.global uefiCall0 | ||
uefiCall0: | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
callq *%rcx | ||
movq %rbp, %rsp | ||
popq %rbp | ||
ret | ||
|
||
.global uefiCall1 | ||
uefiCall1: | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
movq %rcx, %rax // rax = fn | ||
movq %rdx, %rcx | ||
callq *%rax | ||
movq %rbp, %rsp | ||
popq %rbp | ||
ret | ||
|
||
.global uefiCall2 | ||
uefiCall2: | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
movq %rcx, %rax // rax = fn | ||
movq %rdx, %rcx | ||
movq %r8, %rdx | ||
callq *%rax | ||
movq %rbp, %rsp | ||
popq %rbp | ||
ret | ||
|
||
.global uefiCall3 | ||
uefiCall3: | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
movq %rcx, %rax // rax = fn | ||
movq %rdx, %rcx | ||
movq %r8, %rdx | ||
movq %r9, %r8 | ||
callq *%rax | ||
movq %rbp, %rsp | ||
popq %rbp | ||
ret | ||
|
||
.global uefiCall4 | ||
uefiCall4: | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
movq %rcx, %rax // rax = fn | ||
movq %rdx, %rcx | ||
movq %r8, %rdx | ||
movq %r9, %r8 | ||
|
||
movq 0x30(%rsp),%r9 // 0x08(return_address) + 0x08(pushq rbp) + 0x20 | ||
|
||
callq *%rax | ||
movq %rbp, %rsp | ||
popq %rbp | ||
ret | ||
|
||
.global uefiCall5 | ||
uefiCall5: | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
movq %rcx, %rax // rax = fn | ||
movq %rdx, %rcx // a | ||
movq %r8, %rdx // b | ||
movq %r9, %r8 // c | ||
movq 0x30(%rbp),%r9 // d | ||
movq 0x38(%rbp),%r10 // e | ||
movq %r10,0x20(%rsp) | ||
callq *%rax | ||
movq %rbp, %rsp | ||
popq %rbp | ||
ret | ||
|
||
.global uefiCall6 | ||
uefiCall6: | ||
pushq %rbp | ||
movq %rsp, %rbp | ||
movq %rcx, %rax // rax = fn | ||
movq %rdx, %rcx // a | ||
movq %r8, %rdx // b | ||
movq %r9, %r8 // c | ||
movq 0x30(%rbp),%r9 // d | ||
movq 0x38(%rbp),%r10 // e | ||
movq %r10,0x20(%rsp) | ||
movq 0x40(%rbp),%r10 // f | ||
movq %r10,0x28(%rsp) | ||
callq *%rax | ||
movq %rbp, %rsp | ||
popq %rbp | ||
ret |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package uefi | ||
|
||
//go:nosplit | ||
//export uefiCall0 | ||
func UefiCall0(fn uintptr) EFI_STATUS | ||
|
||
//go:nosplit | ||
//go:export uefiCall1 | ||
func UefiCall1(fn uintptr, a uintptr) EFI_STATUS | ||
|
||
//go:nosplit | ||
//go:export uefiCall2 | ||
func UefiCall2(fn uintptr, a uintptr, b uintptr) EFI_STATUS | ||
|
||
//go:nosplit | ||
//go:export uefiCall3 | ||
func UefiCall3(fn uintptr, a uintptr, b uintptr, c uintptr) EFI_STATUS | ||
|
||
//go:nosplit | ||
//go:export uefiCall4 | ||
func UefiCall4(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr) EFI_STATUS | ||
|
||
//go:nosplit | ||
//go:export uefiCall5 | ||
func UefiCall5(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr) EFI_STATUS | ||
|
||
//go:nosplit | ||
//go:export uefiCall6 | ||
func UefiCall6(fn uintptr, a uintptr, b uintptr, c uintptr, d uintptr, e uintptr, f uintptr) EFI_STATUS |
Oops, something went wrong.