diff --git a/pkg/ring0/aarch64.go b/pkg/ring0/aarch64.go index 2c357f59ee..5aa9218fad 100644 --- a/pkg/ring0/aarch64.go +++ b/pkg/ring0/aarch64.go @@ -19,10 +19,16 @@ package ring0 const ( // VirtualAddressBits is fixed at 48. VirtualAddressBits = 48 +) - // PhysicalAddressBits is fixed at 40. - PhysicalAddressBits = 40 +var ( + // PhysicalAddressBits is the number of bits available in the physical + // address space. On ARM64, this is dynamically limited by the host KVM IPA size, + // up to a maximum of 40 bits. + PhysicalAddressBits uintptr = 40 +) +const ( // DAIF bits:debug, sError, IRQ, FIQ. _PSR_D_BIT = 0x00000200 _PSR_A_BIT = 0x00000100 diff --git a/pkg/sentry/platform/kvm/kvm_amd64.go b/pkg/sentry/platform/kvm/kvm_amd64.go index af921c4da8..69e7fb39a6 100644 --- a/pkg/sentry/platform/kvm/kvm_amd64.go +++ b/pkg/sentry/platform/kvm/kvm_amd64.go @@ -248,6 +248,7 @@ func updateGlobalOnce(fd int) error { ring0.Init(cpuid.FeatureSet{ Function: s, }) + initFaultBlocks() physicalInit() return nil } diff --git a/pkg/sentry/platform/kvm/kvm_arm64.go b/pkg/sentry/platform/kvm/kvm_arm64.go index 8a53daf059..999496d223 100644 --- a/pkg/sentry/platform/kvm/kvm_arm64.go +++ b/pkg/sentry/platform/kvm/kvm_arm64.go @@ -20,7 +20,9 @@ package kvm import ( "fmt" + "golang.org/x/sys/unix" "gvisor.dev/gvisor/pkg/abi/linux" + "gvisor.dev/gvisor/pkg/hostsyscall" "gvisor.dev/gvisor/pkg/ring0" "gvisor.dev/gvisor/pkg/sentry/arch" ) @@ -66,7 +68,18 @@ type kvmVcpuEvents struct { // updateGlobalOnce does global initialization. It has to be called only once. func updateGlobalOnce(fd int) error { err := updateSystemValues(int(fd)) + + maxIPA, errno := hostsyscall.RawSyscall(unix.SYS_IOCTL, uintptr(fd), KVM_CHECK_EXTENSION, _KVM_CAP_ARM_VM_IPA_SIZE) + if errno == 0 && maxIPA > 0 { + if maxIPA < 40 { + ring0.PhysicalAddressBits = uintptr(maxIPA) + } else { + ring0.PhysicalAddressBits = 40 + } + } + ring0.Init() + initFaultBlocks() physicalInit() // Explicitly configure address space for 48-bit VA. diff --git a/pkg/sentry/platform/kvm/machine.go b/pkg/sentry/platform/kvm/machine.go index 3f2d770955..5e20421f1b 100644 --- a/pkg/sentry/platform/kvm/machine.go +++ b/pkg/sentry/platform/kvm/machine.go @@ -331,13 +331,9 @@ func newMachine(vm int, config *Config) (*machine, error) { // mmap isn't called frequently, it seems better than the memory and // startup time overhead introduced by mapping the entire address // space. - mapEntireAddressSpace := forceMappingEntireAddressSpace || - runtime.GOARCH != "amd64" + mapEntireAddressSpace := forceMappingEntireAddressSpace || mapEntireAddressSpaceDefault if mapEntireAddressSpace { - // Increase faultBlockSize to be sure that we will not reach the limit. - // faultBlockSize has to equal or less than KVM_MEM_MAX_NR_PAGES. - faultBlockSize = uintptr(1) << 42 - faultBlockMask = ^uintptr(faultBlockSize - 1) + archOverrideFaultBlocks() } else { // Install seccomp rules to trap runtime mmap system calls. They will // be handled by seccompMmapHandler. diff --git a/pkg/sentry/platform/kvm/machine_amd64.go b/pkg/sentry/platform/kvm/machine_amd64.go index 830a543a44..5f54bd09da 100644 --- a/pkg/sentry/platform/kvm/machine_amd64.go +++ b/pkg/sentry/platform/kvm/machine_amd64.go @@ -579,3 +579,17 @@ func (m *machine) getMaxVCPU() { func archPhysicalRegions(physicalRegions []physicalRegion) []physicalRegion { return physicalRegions } + +const mapEntireAddressSpaceDefault = false + +func initFaultBlocks() { + faultBlockSize = uintptr(8 << 30) // 8 GiB + faultBlockMask = ^uintptr(faultBlockSize - 1) +} + +func archOverrideFaultBlocks() { + // Increase faultBlockSize to be sure that we will not reach the limit. + // faultBlockSize has to equal or less than KVM_MEM_MAX_NR_PAGES. + faultBlockSize = uintptr(1) << 42 + faultBlockMask = ^uintptr(faultBlockSize - 1) +} diff --git a/pkg/sentry/platform/kvm/machine_arm64.go b/pkg/sentry/platform/kvm/machine_arm64.go index b9b16252a7..f24a2ab3a6 100644 --- a/pkg/sentry/platform/kvm/machine_arm64.go +++ b/pkg/sentry/platform/kvm/machine_arm64.go @@ -205,3 +205,16 @@ func (m *machine) getMaxVCPU() { } } } + +const mapEntireAddressSpaceDefault = true + +func initFaultBlocks() { + if ring0.PhysicalAddressBits <= 39 { + faultBlockSize = uintptr(1 << 30) // 1 GiB + } else { + faultBlockSize = uintptr(8 << 30) // 8 GiB + } + faultBlockMask = ^uintptr(faultBlockSize - 1) +} + +func archOverrideFaultBlocks() {}