1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00

Support the CPUID instruction

This commit is contained in:
Achilleas Anagnostopoulos 2017-06-28 20:16:58 +01:00
parent e580dea9d1
commit e4879b9f8a
3 changed files with 55 additions and 0 deletions

View File

@ -1,5 +1,9 @@
package cpu
var (
cpuidFn = ID
)
// EnableInterrupts enables interrupt handling.
func EnableInterrupts()
@ -21,3 +25,16 @@ func ActivePDT() uintptr
// ReadCR2 returns the value stored in the CR2 register.
func ReadCR2() uint64
// ID returns information about the CPU and its features. It
// is implemented as a CPUID instruction with EAX=leaf and
// returns the values in EAX, EBX, ECX and EDX.
func ID(leaf uint32) (uint32, uint32, uint32, uint32)
// IsIntel returns true if the code is running on an Intel processor.
func IsIntel() bool {
_, ebx, ecx, edx := cpuidFn(0)
return ebx == 0x756e6547 && // "Genu"
edx == 0x49656e69 && // "ineI"
ecx == 0x6c65746e // "ntel"
}

View File

@ -31,3 +31,12 @@ TEXT ·ReadCR2(SB),NOSPLIT,$0
MOVQ CR2, AX
MOVQ AX, ret+0(FP)
RET
TEXT ·ID(SB),NOSPLIT,$0
MOVQ leaf+0(FP), AX
CPUID
MOVL AX, ret+0(FP)
MOVL BX, ret+4(FP)
MOVL CX, ret+8(FP)
MOVL DX, ret+12(FP)
RET

View File

@ -0,0 +1,29 @@
package cpu
import "testing"
func TestIsIntel(t *testing.T) {
defer func() {
cpuidFn = ID
}()
specs := []struct {
eax, ebx, ecx, edx uint32
exp bool
}{
// CPUID output from an Intel CPU
{0xd, 0x756e6547, 0x6c65746e, 0x49656e69, true},
// CPUID output from an AMD Athlon CPU
{0x1, 68747541, 0x444d4163, 0x69746e65, false},
}
for specIndex, spec := range specs {
cpuidFn = func(_ uint32) (uint32, uint32, uint32, uint32) {
return spec.eax, spec.ebx, spec.ecx, spec.edx
}
if got := IsIntel(); got != spec.exp {
t.Errorf("[spec %d] expected IsIntel to return %t; got %t", specIndex, spec.exp, got)
}
}
}