mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Merge pull request #37 from achilleasa/support-cpuid-and-implement-port-rw-helpers
Support CPUID and implement port R/W asm helpers
This commit is contained in:
commit
dd63b23246
@ -1,5 +1,9 @@
|
|||||||
package cpu
|
package cpu
|
||||||
|
|
||||||
|
var (
|
||||||
|
cpuidFn = ID
|
||||||
|
)
|
||||||
|
|
||||||
// EnableInterrupts enables interrupt handling.
|
// EnableInterrupts enables interrupt handling.
|
||||||
func EnableInterrupts()
|
func EnableInterrupts()
|
||||||
|
|
||||||
@ -21,3 +25,34 @@ func ActivePDT() uintptr
|
|||||||
|
|
||||||
// ReadCR2 returns the value stored in the CR2 register.
|
// ReadCR2 returns the value stored in the CR2 register.
|
||||||
func ReadCR2() uint64
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
// PortWriteByte writes a uint8 value to the requested port.
|
||||||
|
func PortWriteByte(port uint16, val uint8)
|
||||||
|
|
||||||
|
// PortWriteWord writes a uint16 value to the requested port.
|
||||||
|
func PortWriteWord(port uint16, val uint16)
|
||||||
|
|
||||||
|
// PortWriteDword writes a uint32 value to the requested port.
|
||||||
|
func PortWriteDword(port uint16, val uint32)
|
||||||
|
|
||||||
|
// PortReadByte reads a uint8 value from the requested port.
|
||||||
|
func PortReadByte(port uint16) uint8
|
||||||
|
|
||||||
|
// PortReadWord reads a uint16 value from the requested port.
|
||||||
|
func PortReadWord(port uint16) uint16
|
||||||
|
|
||||||
|
// PortReadDword reads a uint32 value from the requested port.
|
||||||
|
func PortReadDword(port uint16) uint32
|
||||||
|
@ -31,3 +31,50 @@ TEXT ·ReadCR2(SB),NOSPLIT,$0
|
|||||||
MOVQ CR2, AX
|
MOVQ CR2, AX
|
||||||
MOVQ AX, ret+0(FP)
|
MOVQ AX, ret+0(FP)
|
||||||
RET
|
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
|
||||||
|
|
||||||
|
TEXT ·PortWriteByte(SB),NOSPLIT,$0
|
||||||
|
MOVW port+0(FP), DX
|
||||||
|
MOVB val+0(FP), AX
|
||||||
|
BYTE $0xee // out al, dx
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·PortWriteWord(SB),NOSPLIT,$0
|
||||||
|
MOVW port+0(FP), DX
|
||||||
|
MOVW val+0(FP), AX
|
||||||
|
BYTE $0x66
|
||||||
|
BYTE $0xef // out ax, dx
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·PortWriteDword(SB),NOSPLIT,$0
|
||||||
|
MOVW port+0(FP), DX
|
||||||
|
MOVL val+0(FP), AX
|
||||||
|
BYTE $0xef // out eax, dx
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·PortReadByte(SB),NOSPLIT,$0
|
||||||
|
MOVW port+0(FP), DX
|
||||||
|
BYTE $0xec // in al, dx
|
||||||
|
MOVB AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·PortReadWord(SB),NOSPLIT,$0
|
||||||
|
MOVW port+0(FP), DX
|
||||||
|
BYTE $0x66
|
||||||
|
BYTE $0xed // in ax, dx
|
||||||
|
MOVW AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·PortReadDword(SB),NOSPLIT,$0
|
||||||
|
MOVW port+0(FP), DX
|
||||||
|
BYTE $0xed // in eax, dx
|
||||||
|
MOVL AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
29
src/gopheros/kernel/cpu/cpu_amd64_test.go
Normal file
29
src/gopheros/kernel/cpu/cpu_amd64_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user