github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/hostcpu/hostcpu.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package hostcpu provides utilities for working with CPU information provided
    16  // by a host Linux kernel.
    17  package hostcpu
    18  
    19  import (
    20  	"fmt"
    21  	"io/ioutil"
    22  	"strconv"
    23  	"strings"
    24  	"unicode"
    25  )
    26  
    27  // GetCPU returns the caller's current CPU number, without using the Linux VDSO
    28  // (which is not available to the sentry) or the getcpu(2) system call (which
    29  // is relatively slow).
    30  func GetCPU() uint32
    31  
    32  // MaxPossibleCPU returns the highest possible CPU number, which is guaranteed
    33  // not to change for the lifetime of the host kernel.
    34  func MaxPossibleCPU() (uint32, error) {
    35  	const path = "/sys/devices/system/cpu/possible"
    36  	data, err := ioutil.ReadFile(path)
    37  	if err != nil {
    38  		return 0, err
    39  	}
    40  	str := string(data)
    41  	// Linux: drivers/base/cpu.c:show_cpus_attr() =>
    42  	// include/linux/cpumask.h:cpumask_print_to_pagebuf() =>
    43  	// lib/bitmap.c:bitmap_print_to_pagebuf()
    44  	i, err := maxValueInLinuxBitmap(str)
    45  	if err != nil {
    46  		return 0, fmt.Errorf("invalid %s (%q): %v", path, str, err)
    47  	}
    48  	return uint32(i), nil
    49  }
    50  
    51  // maxValueInLinuxBitmap returns the maximum value specified in str, which is a
    52  // string emitted by Linux's lib/bitmap.c:bitmap_print_to_pagebuf(list=true).
    53  func maxValueInLinuxBitmap(str string) (uint64, error) {
    54  	str = strings.TrimSpace(str)
    55  	// Find the last decimal number in str.
    56  	idx := strings.LastIndexFunc(str, func(c rune) bool {
    57  		return !unicode.IsDigit(c)
    58  	})
    59  	if idx != -1 {
    60  		str = str[idx+1:]
    61  	}
    62  	i, err := strconv.ParseUint(str, 10, 64)
    63  	if err != nil {
    64  		return 0, err
    65  	}
    66  	return i, nil
    67  }