From faa34a0738456f5328cf99de13622a150042776d Mon Sep 17 00:00:00 2001 From: Chenggang Date: Thu, 13 Sep 2018 21:46:03 -0700 Subject: platform/kvm: Get max vcpu number dynamically by ioctl The old kernel version, such as 4.4, only support 255 vcpus. While gvisor is ran on these kernels, it could panic because the vcpu id and vcpu number beyond max_vcpus. Use ioctl(vmfd, _KVM_CHECK_EXTENSION, _KVM_CAP_MAX_VCPUS) to get max vcpus number dynamically. Change-Id: I50dd859a11b1c2cea854a8e27d4bf11a411aa45c PiperOrigin-RevId: 212929704 --- pkg/sentry/platform/kvm/address_space.go | 29 ++++++++++++----------------- pkg/sentry/platform/kvm/kvm.go | 1 + pkg/sentry/platform/kvm/kvm_const.go | 8 +++++++- pkg/sentry/platform/kvm/machine.go | 30 +++++++++++++++++++++++++++--- 4 files changed, 47 insertions(+), 21 deletions(-) (limited to 'pkg/sentry') diff --git a/pkg/sentry/platform/kvm/address_space.go b/pkg/sentry/platform/kvm/address_space.go index 463617170..c4293c517 100644 --- a/pkg/sentry/platform/kvm/address_space.go +++ b/pkg/sentry/platform/kvm/address_space.go @@ -26,31 +26,26 @@ import ( "gvisor.googlesource.com/gvisor/pkg/sentry/usermem" ) -type vCPUBitArray [(_KVM_NR_VCPUS + 63) / 64]uint64 - // dirtySet tracks vCPUs for invalidation. type dirtySet struct { - vCPUs vCPUBitArray + vCPUs []uint64 } // forEach iterates over all CPUs in the dirty set. func (ds *dirtySet) forEach(m *machine, fn func(c *vCPU)) { - var localSet vCPUBitArray - for index := 0; index < len(ds.vCPUs); index++ { - // Clear the dirty set, copy to the local one. - localSet[index] = atomic.SwapUint64(&ds.vCPUs[index], 0) - } - m.mu.RLock() defer m.mu.RUnlock() - for _, c := range m.vCPUs { - index := uint64(c.id) / 64 - bit := uint64(1) << uint(c.id%64) - - // Call the function if it was set. - if localSet[index]&bit != 0 { - fn(c) + for index := range ds.vCPUs { + mask := atomic.SwapUint64(&ds.vCPUs[index], 0) + if mask != 0 { + for bit := 0; bit < 64; bit++ { + if mask&(1<