mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
kvm/arm: calculate virtual-to-physical mappings only once
This commit is contained in:
committed by
Andrei Vagin
parent
c1a726e8c5
commit
981111a9ee
@@ -192,6 +192,10 @@ func (m *machine) newVCPU() *vCPU {
|
||||
return c // Done.
|
||||
}
|
||||
|
||||
// readOnlyGuestRegions contains regions that have to be mapped read-only into
|
||||
// the guest physical address space. Right now, it is used on arm64 only.
|
||||
var readOnlyGuestRegions []region
|
||||
|
||||
// newMachine returns a new VM context.
|
||||
func newMachine(vm int) (*machine, error) {
|
||||
// Create the machine.
|
||||
@@ -241,32 +245,11 @@ func newMachine(vm int) (*machine, error) {
|
||||
return true // Keep iterating.
|
||||
})
|
||||
|
||||
var physicalRegionsReadOnly []physicalRegion
|
||||
var physicalRegionsAvailable []physicalRegion
|
||||
|
||||
physicalRegionsReadOnly = rdonlyRegionsForSetMem()
|
||||
physicalRegionsAvailable = availableRegionsForSetMem()
|
||||
|
||||
// Map all read-only regions.
|
||||
for _, r := range physicalRegionsReadOnly {
|
||||
m.mapPhysical(r.physical, r.length, physicalRegionsReadOnly, _KVM_MEM_READONLY)
|
||||
}
|
||||
|
||||
// Ensure that the currently mapped virtual regions are actually
|
||||
// available in the VM. Note that this doesn't guarantee no future
|
||||
// faults, however it should guarantee that everything is available to
|
||||
// ensure successful vCPU entry.
|
||||
applyVirtualRegions(func(vr virtualRegion) {
|
||||
if excludeVirtualRegion(vr) {
|
||||
return // skip region.
|
||||
}
|
||||
|
||||
for _, r := range physicalRegionsReadOnly {
|
||||
if vr.virtual == r.virtual {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
mapRegion := func(vr region, flags uint32) {
|
||||
for virtual := vr.virtual; virtual < vr.virtual+vr.length; {
|
||||
physical, length, ok := translateToPhysical(virtual)
|
||||
if !ok {
|
||||
@@ -280,9 +263,26 @@ func newMachine(vm int) (*machine, error) {
|
||||
}
|
||||
|
||||
// Ensure the physical range is mapped.
|
||||
m.mapPhysical(physical, length, physicalRegionsAvailable, _KVM_MEM_FLAGS_NONE)
|
||||
m.mapPhysical(physical, length, physicalRegions, flags)
|
||||
virtual += length
|
||||
}
|
||||
}
|
||||
|
||||
for _, vr := range(readOnlyGuestRegions) {
|
||||
mapRegion(vr, _KVM_MEM_READONLY)
|
||||
}
|
||||
|
||||
applyVirtualRegions(func(vr virtualRegion) {
|
||||
if excludeVirtualRegion(vr) {
|
||||
return // skip region.
|
||||
}
|
||||
for _, r := range readOnlyGuestRegions {
|
||||
if vr.virtual == r.virtual {
|
||||
return
|
||||
}
|
||||
}
|
||||
mapRegion(vr.region, 0)
|
||||
|
||||
})
|
||||
|
||||
// Initialize architecture state.
|
||||
|
||||
@@ -522,3 +522,7 @@ func (m *machine) getNewVCPU() *vCPU {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func archPhysicalRegions(physicalRegions []physicalRegion) ([]physicalRegion) {
|
||||
return physicalRegions
|
||||
}
|
||||
|
||||
@@ -110,18 +110,128 @@ func rdonlyRegionsForSetMem() (phyRegions []physicalRegion) {
|
||||
return phyRegions
|
||||
}
|
||||
|
||||
// Get all available physicalRegions.
|
||||
func availableRegionsForSetMem() (phyRegions []physicalRegion) {
|
||||
var excludeRegions []region
|
||||
// archPhysicalRegions fills readOnlyGuestRegions and allocates separate
|
||||
// physical regions form them.
|
||||
func archPhysicalRegions(physicalRegions []physicalRegion) ([]physicalRegion) {
|
||||
applyVirtualRegions(func(vr virtualRegion) {
|
||||
if excludeVirtualRegion(vr) {
|
||||
return // skip region.
|
||||
}
|
||||
if !vr.accessType.Write {
|
||||
excludeRegions = append(excludeRegions, vr.region)
|
||||
readOnlyGuestRegions = append(readOnlyGuestRegions, vr.region)
|
||||
}
|
||||
})
|
||||
|
||||
phyRegions = computePhysicalRegions(excludeRegions)
|
||||
rdRegions := readOnlyGuestRegions[:]
|
||||
|
||||
return phyRegions
|
||||
// Add an unreachable region.
|
||||
rdRegions = append(rdRegions, region {
|
||||
virtual: 0xffffffffffffffff,
|
||||
length: 0,
|
||||
})
|
||||
|
||||
var regions []physicalRegion
|
||||
addValidRegion := func(r *physicalRegion, virtual, length uintptr) {
|
||||
if length == 0 {
|
||||
return
|
||||
}
|
||||
regions = append(regions, physicalRegion {
|
||||
region: region{
|
||||
virtual: virtual,
|
||||
length: length,
|
||||
},
|
||||
physical: r.physical + (virtual - r.virtual),
|
||||
})
|
||||
}
|
||||
i := 0
|
||||
for _, pr := range(physicalRegions) {
|
||||
start := pr.virtual
|
||||
end := pr.virtual + pr.length
|
||||
for start < end {
|
||||
rdRegion := rdRegions[i]
|
||||
rdStart := rdRegion.virtual
|
||||
rdEnd := rdRegion.virtual + rdRegion.length
|
||||
if rdEnd <= start {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if rdStart > start {
|
||||
newEnd := rdStart
|
||||
if end < rdStart {
|
||||
newEnd = end
|
||||
}
|
||||
addValidRegion(&pr, start, newEnd - start)
|
||||
start = rdStart
|
||||
continue
|
||||
}
|
||||
if rdEnd < end {
|
||||
addValidRegion(&pr, start, rdEnd - start)
|
||||
start = rdEnd
|
||||
continue
|
||||
}
|
||||
addValidRegion(&pr, start, end - start)
|
||||
start = end
|
||||
}
|
||||
}
|
||||
|
||||
return regions
|
||||
}
|
||||
|
||||
// Get all available physicalRegions.
|
||||
func availableRegionsForSetMem() ([]physicalRegion) {
|
||||
var excludedRegions []region
|
||||
applyVirtualRegions(func(vr virtualRegion) {
|
||||
if !vr.accessType.Write {
|
||||
excludedRegions = append(excludedRegions, vr.region)
|
||||
}
|
||||
})
|
||||
|
||||
// Add an unreachable region.
|
||||
excludedRegions = append(excludedRegions, region {
|
||||
virtual: 0xffffffffffffffff,
|
||||
length: 0,
|
||||
})
|
||||
|
||||
var regions []physicalRegion
|
||||
addValidRegion := func(r *physicalRegion, virtual, length uintptr) {
|
||||
if length == 0 {
|
||||
return
|
||||
}
|
||||
regions = append(regions, physicalRegion {
|
||||
region: region{
|
||||
virtual: virtual,
|
||||
length: length,
|
||||
},
|
||||
physical: r.physical + (virtual - r.virtual),
|
||||
})
|
||||
}
|
||||
i := 0
|
||||
for _, pr := range(physicalRegions) {
|
||||
start := pr.virtual
|
||||
end := pr.virtual + pr.length
|
||||
for start < end {
|
||||
er := excludedRegions[i]
|
||||
excludeEnd := er.virtual + er.length
|
||||
excludeStart := er.virtual
|
||||
if excludeEnd < start {
|
||||
i++
|
||||
continue
|
||||
}
|
||||
if excludeStart < start {
|
||||
start = excludeEnd
|
||||
i++
|
||||
continue
|
||||
}
|
||||
rend := excludeStart
|
||||
if rend > end {
|
||||
rend = end
|
||||
}
|
||||
addValidRegion(&pr, start, rend - start)
|
||||
start = excludeEnd
|
||||
}
|
||||
}
|
||||
|
||||
return regions
|
||||
}
|
||||
|
||||
// nonCanonical generates a canonical address return.
|
||||
|
||||
@@ -168,6 +168,9 @@ func computePhysicalRegions(excludedRegions []region) (physicalRegions []physica
|
||||
}
|
||||
addValidRegion(lastExcludedEnd, ring0.MaximumUserAddress-lastExcludedEnd)
|
||||
|
||||
// Do arch-specific actions on physical regions.
|
||||
physicalRegions = archPhysicalRegions(physicalRegions)
|
||||
|
||||
// Dump our all physical regions.
|
||||
for _, r := range physicalRegions {
|
||||
log.Infof("physicalRegion: virtual [%x,%x) => physical [%x,%x)",
|
||||
|
||||
Reference in New Issue
Block a user