1
0
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:
Achilleas Anagnostopoulos 2017-06-14 17:09:05 +01:00
parent dbdf686d27
commit 1c3bfcd58d
2 changed files with 64 additions and 0 deletions

View 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
}

View 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)
}
}