mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
133 lines
3.7 KiB
Go
133 lines
3.7 KiB
Go
package goruntime
|
|
|
|
import (
|
|
"testing"
|
|
"unsafe"
|
|
|
|
"github.com/achilleasa/gopher-os/kernel"
|
|
"github.com/achilleasa/gopher-os/kernel/mem"
|
|
"github.com/achilleasa/gopher-os/kernel/mem/pmm"
|
|
"github.com/achilleasa/gopher-os/kernel/mem/vmm"
|
|
)
|
|
|
|
func TestSysReserve(t *testing.T) {
|
|
defer func() {
|
|
earlyReserveRegionFn = vmm.EarlyReserveRegion
|
|
}()
|
|
var reserved bool
|
|
|
|
t.Run("success", func(t *testing.T) {
|
|
specs := []struct {
|
|
reqSize mem.Size
|
|
expRegionSize mem.Size
|
|
}{
|
|
// exact multiple of page size
|
|
{100 << mem.PageShift, 100 << mem.PageShift},
|
|
// size should be rounded up to nearest page size
|
|
{2*mem.PageSize - 1, 2 * mem.PageSize},
|
|
}
|
|
|
|
for specIndex, spec := range specs {
|
|
earlyReserveRegionFn = func(rsvSize mem.Size) (uintptr, *kernel.Error) {
|
|
if rsvSize != spec.expRegionSize {
|
|
t.Errorf("[spec %d] expected reservation size to be %d; got %d", specIndex, spec.expRegionSize, rsvSize)
|
|
}
|
|
|
|
return 0xbadf00d, nil
|
|
}
|
|
|
|
ptr := sysReserve(nil, uintptr(spec.reqSize), &reserved)
|
|
if uintptr(ptr) == 0 {
|
|
t.Errorf("[spec %d] sysReserve returned 0", specIndex)
|
|
continue
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("fail", func(t *testing.T) {
|
|
defer func() {
|
|
if err := recover(); err == nil {
|
|
t.Fatal("expected sysReserve to panic")
|
|
}
|
|
}()
|
|
|
|
earlyReserveRegionFn = func(rsvSize mem.Size) (uintptr, *kernel.Error) {
|
|
return 0, &kernel.Error{Module: "test", Message: "consumed available address space"}
|
|
}
|
|
|
|
sysReserve(nil, uintptr(0xf00), &reserved)
|
|
})
|
|
}
|
|
|
|
func TestSysMap(t *testing.T) {
|
|
defer func() {
|
|
earlyReserveRegionFn = vmm.EarlyReserveRegion
|
|
mapFn = vmm.Map
|
|
}()
|
|
|
|
t.Run("success", func(t *testing.T) {
|
|
specs := []struct {
|
|
reqAddr uintptr
|
|
reqSize mem.Size
|
|
expRsvAddr uintptr
|
|
expMapCallCount int
|
|
}{
|
|
// exact multiple of page size
|
|
{100 << mem.PageShift, 4 * mem.PageSize, 100 << mem.PageShift, 4},
|
|
// address should be rounded up to nearest page size
|
|
{(100 << mem.PageShift) + 1, 4 * mem.PageSize, 101 << mem.PageShift, 4},
|
|
// size should be rounded up to nearest page size
|
|
{1 << mem.PageShift, (4 * mem.PageSize) + 1, 1 << mem.PageShift, 5},
|
|
}
|
|
|
|
for specIndex, spec := range specs {
|
|
var (
|
|
sysStat uint64
|
|
mapCallCount int
|
|
)
|
|
mapFn = func(_ vmm.Page, _ pmm.Frame, flags vmm.PageTableEntryFlag) *kernel.Error {
|
|
expFlags := vmm.FlagPresent | vmm.FlagCopyOnWrite | vmm.FlagNoExecute
|
|
if flags != expFlags {
|
|
t.Errorf("[spec %d] expected map flags to be %d; got %d", specIndex, expFlags, flags)
|
|
}
|
|
mapCallCount++
|
|
return nil
|
|
}
|
|
|
|
rsvPtr := sysMap(unsafe.Pointer(spec.reqAddr), uintptr(spec.reqSize), true, &sysStat)
|
|
if got := uintptr(rsvPtr); got != spec.expRsvAddr {
|
|
t.Errorf("[spec %d] expected mapped address 0x%x; got 0x%x", specIndex, spec.expRsvAddr, got)
|
|
}
|
|
|
|
if mapCallCount != spec.expMapCallCount {
|
|
t.Errorf("[spec %d] expected vmm.Map call count to be %d; got %d", specIndex, spec.expMapCallCount, mapCallCount)
|
|
}
|
|
|
|
if exp := uint64(spec.expMapCallCount << mem.PageShift); sysStat != exp {
|
|
t.Errorf("[spec %d] expected stat counter to be %d; got %d", specIndex, exp, sysStat)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("map fails", func(t *testing.T) {
|
|
mapFn = func(_ vmm.Page, _ pmm.Frame, _ vmm.PageTableEntryFlag) *kernel.Error {
|
|
return &kernel.Error{Module: "test", Message: "map failed"}
|
|
}
|
|
|
|
var sysStat uint64
|
|
if got := sysMap(unsafe.Pointer(uintptr(0xbadf00d)), 1, true, &sysStat); got != unsafe.Pointer(uintptr(0)) {
|
|
t.Fatalf("expected sysMap to return 0x0 if Map returns an error; got 0x%x", uintptr(got))
|
|
}
|
|
})
|
|
|
|
t.Run("panic if not reserved", func(t *testing.T) {
|
|
defer func() {
|
|
if err := recover(); err == nil {
|
|
t.Fatal("expected sysMap to panic")
|
|
}
|
|
}()
|
|
|
|
sysMap(nil, 0, false, nil)
|
|
})
|
|
}
|