Documentation ¶
Overview ¶
Package pagetables provides a generic implementation of pagetables.
The core functions must be safe to call from a nosplit context. Furthermore, this pagetables implementation goes to lengths to ensure that all functions are free from runtime allocation. Calls to NewPTEs/FreePTEs may be made during walks, but these can be cached elsewhere if required.
Index ¶
- type Allocator
- type MapOpts
- type PCIDs
- type PTE
- type PTEs
- type PageTables
- func (p *PageTables) CR3(noFlush bool, pcid uint16) uint64
- func (p *PageTables) Init(allocator Allocator)
- func (p *PageTables) InitArch(allocator Allocator)
- func (p *PageTables) IsEmpty(addr hostarch.Addr, length uintptr) bool
- func (p *PageTables) Lookup(addr hostarch.Addr, findFirst bool) (virtual hostarch.Addr, physical, size uintptr, opts MapOpts)
- func (p *PageTables) Map(addr hostarch.Addr, length uintptr, opts MapOpts, physical uintptr) bool
- func (p *PageTables) MarkReadOnlyShared()
- func (p *PageTables) Unmap(addr hostarch.Addr, length uintptr) bool
- type RuntimeAllocator
- func (r *RuntimeAllocator) Drain()
- func (r *RuntimeAllocator) FreePTEs(ptes *PTEs)
- func (r *RuntimeAllocator) Init()
- func (r *RuntimeAllocator) LookupPTEs(physical uintptr) *PTEs
- func (r *RuntimeAllocator) NewPTEs() *PTEs
- func (r *RuntimeAllocator) PhysicalFor(ptes *PTEs) uintptr
- func (r *RuntimeAllocator) Recycle()
- type Visitor
- type Walker
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Allocator ¶
type Allocator interface { // NewPTEs returns a new set of PTEs and their physical address. NewPTEs() *PTEs // PhysicalFor gives the physical address for a set of PTEs. PhysicalFor(ptes *PTEs) uintptr // LookupPTEs looks up PTEs by physical address. LookupPTEs(physical uintptr) *PTEs // FreePTEs marks a set of PTEs a freed, although they may not be available // for use again until Recycle is called, below. FreePTEs(ptes *PTEs) // Recycle makes freed PTEs available for use again. Recycle() }
Allocator is used to allocate and map PTEs.
Note that allocators may be called concurrently.
type MapOpts ¶
type MapOpts struct { // AccessType defines permissions. AccessType hostarch.AccessType // Global indicates the page is globally accessible. Global bool // User indicates the page is a user page. User bool }
MapOpts are x86 options.
type PCIDs ¶
type PCIDs struct {
// contains filtered or unexported fields
}
PCIDs is a simple PCID database.
This is not protected by locks and is thus suitable for use only with a single CPU at a time.
func NewPCIDs ¶
NewPCIDs returns a new PCID database.
start is the first index to assign. Typically this will be one, as the zero pcid will always be flushed on transition (see pagetables_x86.go). This may be more than one if specific PCIDs are reserved.
Nil is returned iff the start and size are out of range.
func (*PCIDs) Assign ¶
func (p *PCIDs) Assign(pt *PageTables) (uint16, bool)
Assign assigns a PCID to the given PageTables.
This may overwrite any previous assignment provided. If this in the case, true is returned to indicate that the PCID should be flushed.
func (*PCIDs) Drop ¶
func (p *PCIDs) Drop(pt *PageTables)
Drop drops references to a set of page tables.
type PTE ¶
type PTE uintptr
PTE is a page table entry.
type PageTables ¶
type PageTables struct { // Allocator is used to allocate nodes. Allocator Allocator // contains filtered or unexported fields }
PageTables is a set of page tables.
func NewWithUpper ¶
func NewWithUpper(a Allocator, upperSharedPageTables *PageTables, upperStart uintptr) *PageTables
NewWithUpper returns new PageTables.
upperSharedPageTables are used for mapping the upper of addresses, starting at upperStart. These pageTables should not be touched (as invalidations may be incorrect) after they are passed as an upperSharedPageTables. Only when all dependent PageTables are gone may they be used. The intenteded use case is for kernel page tables, which are static and fixed.
Precondition: upperStart must be between canonical ranges. Precondition: upperStart must be pgdSize aligned. precondition: upperSharedPageTables must be marked read-only shared.
func (*PageTables) CR3 ¶
func (p *PageTables) CR3(noFlush bool, pcid uint16) uint64
CR3 returns the CR3 value for these tables.
This may be called in interrupt contexts. A PCID of zero always implies a flush and should be passed when PCIDs are not enabled. See pcids_x86.go for more information.
func (*PageTables) Init ¶
func (p *PageTables) Init(allocator Allocator)
Init initializes a set of PageTables.
+checkescape:hard,stack
func (*PageTables) InitArch ¶
func (p *PageTables) InitArch(allocator Allocator)
InitArch does some additional initialization related to the architecture.
+checkescape:hard,stack
func (*PageTables) IsEmpty ¶
func (p *PageTables) IsEmpty(addr hostarch.Addr, length uintptr) bool
IsEmpty checks if the given range is empty.
Precondition: addr & length must be page-aligned.
+checkescape:hard,stack
func (*PageTables) Lookup ¶
func (p *PageTables) Lookup(addr hostarch.Addr, findFirst bool) (virtual hostarch.Addr, physical, size uintptr, opts MapOpts)
Lookup returns the physical address for the given virtual address.
If findFirst is true, then the next valid address after addr is returned. If findFirst is false, then only a mapping for addr will be returned.
Note that if size is zero, then no matching entry was found.
+checkescape:hard,stack
func (*PageTables) Map ¶
Map installs a mapping with the given physical address.
True is returned iff there was a previous mapping in the range.
Precondition: addr & length must be page-aligned, their sum must not overflow.
+checkescape:hard,stack
func (*PageTables) MarkReadOnlyShared ¶
func (p *PageTables) MarkReadOnlyShared()
MarkReadOnlyShared marks the pagetables read-only and can be shared.
It is usually used on the pagetables that are used as the upper
type RuntimeAllocator ¶
type RuntimeAllocator struct {
// contains filtered or unexported fields
}
RuntimeAllocator is a trivial allocator.
func NewRuntimeAllocator ¶
func NewRuntimeAllocator() *RuntimeAllocator
NewRuntimeAllocator returns an allocator that uses runtime allocation.
func (*RuntimeAllocator) FreePTEs ¶
func (r *RuntimeAllocator) FreePTEs(ptes *PTEs)
FreePTEs implements Allocator.FreePTEs.
func (*RuntimeAllocator) Init ¶
func (r *RuntimeAllocator) Init()
Init initializes a RuntimeAllocator.
func (*RuntimeAllocator) LookupPTEs ¶
func (r *RuntimeAllocator) LookupPTEs(physical uintptr) *PTEs
LookupPTEs implements Allocator.LookupPTEs.
func (*RuntimeAllocator) NewPTEs ¶
func (r *RuntimeAllocator) NewPTEs() *PTEs
NewPTEs implements Allocator.NewPTEs.
Note that the "physical" address here is actually the virtual address of the PTEs structure. The entries are tracked only to avoid garbage collection.
This is guaranteed not to split as long as the pool is sufficiently full.
func (*RuntimeAllocator) PhysicalFor ¶
func (r *RuntimeAllocator) PhysicalFor(ptes *PTEs) uintptr
PhysicalFor returns the physical address for the given PTEs.
func (*RuntimeAllocator) Recycle ¶
func (r *RuntimeAllocator) Recycle()
Recycle returns freed pages to the pool.