mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
Implement early virtual address space reservation helper
Function EarlyReserveRegion reserves contiguous virtual address space regions beginning at the end of the available kernel space and moving towards lower virtual addresses. The only state that is tracked by this function is the last allocated virtual page address which is adjusted after each reservation request. Starting at the end of the kernel address space ensures that we will not step on the virtual addresses used by the kernel code and data sections.
This commit is contained in:
parent
dbdf686d27
commit
1c3bfcd58d
35
kernel/mem/vmm/addr_space.go
Normal file
35
kernel/mem/vmm/addr_space.go
Normal file
@ -0,0 +1,35 @@
|
||||
package vmm
|
||||
|
||||
import (
|
||||
"github.com/achilleasa/gopher-os/kernel"
|
||||
"github.com/achilleasa/gopher-os/kernel/mem"
|
||||
)
|
||||
|
||||
var (
|
||||
// earlyReserveLastUsed tracks the last reserved page address and is
|
||||
// decreased after each allocation request. Initially, it points to
|
||||
// tempMappingAddr which coincides with the end of the kernel address
|
||||
// space.
|
||||
earlyReserveLastUsed = tempMappingAddr
|
||||
|
||||
errEarlyReserveNoSpace = &kernel.Error{Module: "early_reserve", Message: "remaining virtual address space not large enough to satisfy reservation request"}
|
||||
)
|
||||
|
||||
// EarlyReserveRegion reserves a page-aligned contiguous virtual memory region
|
||||
// with the requested size in the kernel address space and returns its virtual
|
||||
// address. If size is not a multiple of mem.PageSize it will be automatically
|
||||
// rounded up.
|
||||
//
|
||||
// This function allocates regions starting at the end of the kernel address
|
||||
// space. It should only be used during the early stages of kernel initialization.
|
||||
func EarlyReserveRegion(size mem.Size) (uintptr, *kernel.Error) {
|
||||
size = (size + (mem.PageSize - 1)) & ^(mem.PageSize - 1)
|
||||
|
||||
// reserving a region of the requested size will cause an underflow
|
||||
if uintptr(size) > earlyReserveLastUsed {
|
||||
return 0, errEarlyReserveNoSpace
|
||||
}
|
||||
|
||||
earlyReserveLastUsed -= uintptr(size)
|
||||
return earlyReserveLastUsed, nil
|
||||
}
|
29
kernel/mem/vmm/addr_space_test.go
Normal file
29
kernel/mem/vmm/addr_space_test.go
Normal file
@ -0,0 +1,29 @@
|
||||
package vmm
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEarlyReserveAmd64(t *testing.T) {
|
||||
if runtime.GOARCH != "amd64" {
|
||||
t.Skip("test requires amd64 runtime; skipping")
|
||||
}
|
||||
|
||||
defer func(origLastUsed uintptr) {
|
||||
earlyReserveLastUsed = origLastUsed
|
||||
}(earlyReserveLastUsed)
|
||||
|
||||
earlyReserveLastUsed = 4096
|
||||
next, err := EarlyReserveRegion(42)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if exp := uintptr(0); next != exp {
|
||||
t.Fatal("expected reservation request to be rounded to nearest page")
|
||||
}
|
||||
|
||||
if _, err = EarlyReserveRegion(1); err != errEarlyReserveNoSpace {
|
||||
t.Fatalf("expected to get errEarlyReserveNoSpace; got %v", err)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user