mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
132 lines
4.4 KiB
Go
132 lines
4.4 KiB
Go
package allocator
|
|
|
|
import (
|
|
"testing"
|
|
"unsafe"
|
|
|
|
"github.com/achilleasa/gopher-os/kernel/driver/video/console"
|
|
"github.com/achilleasa/gopher-os/kernel/hal"
|
|
"github.com/achilleasa/gopher-os/kernel/hal/multiboot"
|
|
)
|
|
|
|
func TestBootMemoryAllocator(t *testing.T) {
|
|
multiboot.SetInfoPtr(uintptr(unsafe.Pointer(&multibootMemoryMap[0])))
|
|
|
|
specs := []struct {
|
|
kernelStart, kernelEnd uintptr
|
|
expAllocCount uint64
|
|
}{
|
|
{
|
|
// the kernel is loaded in a reserved memory region
|
|
0xa0000,
|
|
0xa0000,
|
|
// region 1 extents get rounded to [0, 9f000] and provides 159 frames [0 to 158]
|
|
// region 1 uses the original extents [100000 - 7fe0000] and provides 32480 frames [256-32735]
|
|
159 + 32480,
|
|
},
|
|
{
|
|
// the kernel is loaded at the beginning of region 1 taking 2.5 pages
|
|
0x0,
|
|
0x2800,
|
|
// region 1 extents get rounded to [0, 9f000] and provides 159 frames [0 to 158]; out of these
|
|
// frames 0,1 and 2 (round up kernel end) are used by the kernel
|
|
// region 1 uses the original extents [100000 - 7fe0000] and provides 32480 frames [256-32735]
|
|
159 - 3 + 32480,
|
|
},
|
|
{
|
|
// the kernel is loaded at the end of region 1 taking 2.5 pages
|
|
0x9c800,
|
|
0x9f000,
|
|
// region 1 extents get rounded to [0, 9f000] and provides 159 frames [0 to 158]; out of these
|
|
// frames 156,157 and 158 (round down kernel start) are used by the kernel
|
|
// region 1 uses the original extents [100000 - 7fe0000] and provides 32480 frames [256-32735]
|
|
159 - 3 + 32480,
|
|
},
|
|
{
|
|
// the kernel (after rounding) uses the entire region 1
|
|
0x123,
|
|
0x9fc00,
|
|
// region 1 extents get rounded to [0, 9f000] and provides 159 frames [0 to 158]; all are used
|
|
// by the kernel
|
|
// region 1 uses the original extents [100000 - 7fe0000] and provides 32480 frames [256-32735]
|
|
32480,
|
|
},
|
|
{
|
|
// the kernel is loaded at region 2 start + 2K taking 1.5 pages
|
|
0x100800,
|
|
0x102000,
|
|
// region 1 extents get rounded to [0, 9f000] and provides 159 frames [0 to 158]
|
|
// region 1 uses the original extents [100000 - 7fe0000] and provides 32480 frames [256-32735];
|
|
// out of these frames 256 (kernel start rounded down) and 257 is used by the kernel
|
|
159 + 32480 - 2,
|
|
},
|
|
}
|
|
|
|
var alloc bootMemAllocator
|
|
for specIndex, spec := range specs {
|
|
alloc.allocCount = 0
|
|
alloc.lastAllocFrame = 0
|
|
alloc.init(spec.kernelStart, spec.kernelEnd)
|
|
|
|
for {
|
|
frame, err := alloc.AllocFrame()
|
|
if err != nil {
|
|
if err == errBootAllocOutOfMemory {
|
|
break
|
|
}
|
|
t.Errorf("[spec %d] [frame %d] unexpected allocator error: %v", specIndex, alloc.allocCount, err)
|
|
break
|
|
}
|
|
|
|
if frame != alloc.lastAllocFrame {
|
|
t.Errorf("[spec %d] [frame %d] expected allocated frame to be %d; got %d", specIndex, alloc.allocCount, alloc.lastAllocFrame, frame)
|
|
}
|
|
|
|
if !frame.Valid() {
|
|
t.Errorf("[spec %d] [frame %d] expected IsValid() to return true", specIndex, alloc.allocCount)
|
|
}
|
|
}
|
|
|
|
if alloc.allocCount != spec.expAllocCount {
|
|
t.Errorf("[spec %d] expected allocator to allocate %d frames; allocated %d", specIndex, spec.expAllocCount, alloc.allocCount)
|
|
}
|
|
}
|
|
}
|
|
|
|
var (
|
|
// A dump of multiboot data when running under qemu containing only the
|
|
// memory region tag. The dump encodes the following available memory
|
|
// regions:
|
|
// [ 0 - 9fc00] length: 654336
|
|
// [100000 - 7fe0000] length: 133038080
|
|
multibootMemoryMap = []byte{
|
|
72, 5, 0, 0, 0, 0, 0, 0,
|
|
6, 0, 0, 0, 160, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 9, 0, 0, 0, 0, 0,
|
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 252, 9, 0, 0, 0, 0, 0,
|
|
0, 4, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
|
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0,
|
|
0, 0, 238, 7, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 254, 7, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
|
|
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252, 255, 0, 0, 0, 0,
|
|
0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
|
|
9, 0, 0, 0, 212, 3, 0, 0, 24, 0, 0, 0, 40, 0, 0, 0,
|
|
21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, 0, 0,
|
|
1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 16, 0, 0, 16, 0, 0,
|
|
24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
}
|
|
)
|
|
|
|
func mockTTY() []byte {
|
|
// Mock a tty to handle early.Printf output
|
|
mockConsoleFb := make([]byte, 160*25)
|
|
mockConsole := &console.Ega{}
|
|
mockConsole.Init(80, 25, uintptr(unsafe.Pointer(&mockConsoleFb[0])))
|
|
hal.ActiveTerminal.AttachTo(mockConsole)
|
|
|
|
return mockConsoleFb
|
|
}
|