diff options
author | Chenggang <chenggang.qcg@alibaba-inc.com> | 2018-09-13 21:46:03 -0700 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2018-09-13 21:47:11 -0700 |
commit | faa34a0738456f5328cf99de13622a150042776d (patch) | |
tree | 72f2aaac72df21efac1c4ce55d6a711ae0a7d296 /pkg/sentry/platform/kvm/machine.go | |
parent | 29a7271f5da9fdb7b4a9a6c9ea61421ce6844a73 (diff) |
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
Diffstat (limited to 'pkg/sentry/platform/kvm/machine.go')
-rw-r--r-- | pkg/sentry/platform/kvm/machine.go | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/pkg/sentry/platform/kvm/machine.go b/pkg/sentry/platform/kvm/machine.go index 68e099d1b..9f60b6b31 100644 --- a/pkg/sentry/platform/kvm/machine.go +++ b/pkg/sentry/platform/kvm/machine.go @@ -22,6 +22,7 @@ import ( "syscall" "gvisor.googlesource.com/gvisor/pkg/atomicbitops" + "gvisor.googlesource.com/gvisor/pkg/log" "gvisor.googlesource.com/gvisor/pkg/sentry/platform/procid" "gvisor.googlesource.com/gvisor/pkg/sentry/platform/ring0" "gvisor.googlesource.com/gvisor/pkg/sentry/platform/ring0/pagetables" @@ -55,6 +56,12 @@ type machine struct { // // These are populated dynamically. vCPUs map[uint64]*vCPU + + // vCPUsByID are the machine vCPUs, can be indexed by the vCPU's ID. + vCPUsByID map[int]*vCPU + + // maxVCPUs is the maximum number of vCPUs supported by the machine. + maxVCPUs int } const ( @@ -135,6 +142,7 @@ func (m *machine) newVCPU() *vCPU { c.CPU.Init(&m.kernel) c.CPU.KernelSyscall = bluepillSyscall c.CPU.KernelException = bluepillException + m.vCPUsByID[c.id] = c // Ensure the signal mask is correct. if err := c.setSignalMask(); err != nil { @@ -160,14 +168,23 @@ func (m *machine) newVCPU() *vCPU { func newMachine(vm int) (*machine, error) { // Create the machine. m := &machine{ - fd: vm, - vCPUs: make(map[uint64]*vCPU), + fd: vm, + vCPUs: make(map[uint64]*vCPU), + vCPUsByID: make(map[int]*vCPU), } m.available.L = &m.mu m.kernel.Init(ring0.KernelOpts{ PageTables: pagetables.New(newAllocator()), }) + maxVCPUs, _, errno := syscall.RawSyscall(syscall.SYS_IOCTL, uintptr(m.fd), _KVM_CHECK_EXTENSION, _KVM_CAP_MAX_VCPUS) + if errno != 0 { + m.maxVCPUs = _KVM_NR_VCPUS + } else { + m.maxVCPUs = int(maxVCPUs) + } + log.Debugf("The maximum number of vCPUs is %d.", m.maxVCPUs) + // Apply the physical mappings. Note that these mappings may point to // guest physical addresses that are not actually available. These // physical pages are mapped on demand, see kernel_unsafe.go. @@ -315,7 +332,7 @@ func (m *machine) Get() *vCPU { } // Create a new vCPU (maybe). - if len(m.vCPUs) < _KVM_NR_VCPUS { + if len(m.vCPUs) < m.maxVCPUs { c := m.newVCPU() c.lock() m.vCPUs[tid] = c @@ -365,6 +382,13 @@ func (m *machine) Put(c *vCPU) { m.available.Signal() } +// newDirtySet returns a new dirty set. +func (m *machine) newDirtySet() *dirtySet { + return &dirtySet{ + vCPUs: make([]uint64, (m.maxVCPUs+63)/64, (m.maxVCPUs+63)/64), + } +} + // lock marks the vCPU as in user mode. // // This should only be called directly when known to be safe, i.e. when |