github.com/intel/goresctrl@v0.5.0/pkg/utils/sysfs.go (about)

     1  /*
     2  Copyright 2022 Intel Corporation
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package utils
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"strconv"
    23  	"strings"
    24  
    25  	goresctrlpath "github.com/intel/goresctrl/pkg/path"
    26  )
    27  
    28  const (
    29  	SysfsUncoreBasepath = "sys/devices/system/cpu/intel_uncore_frequency"
    30  	SysfsCpuBasepath    = "sys/devices/system/cpu"
    31  )
    32  
    33  func setCPUFreqValue(cpu ID, setting string, value int) error {
    34  	return writeFileInt(cpuFreqPath(cpu, setting), value)
    35  }
    36  
    37  // GetCPUFreqValue returns information of the currently used CPU frequency
    38  func GetCPUFreqValue(cpu ID, setting string) (int, error) {
    39  	raw, err := os.ReadFile(cpuFreqPath(cpu, setting))
    40  	if err != nil {
    41  		return 0, err
    42  	}
    43  
    44  	value, err := strconv.Atoi(strings.TrimSpace(string(raw)))
    45  	if err != nil {
    46  		return 0, err
    47  	}
    48  
    49  	return value, nil
    50  }
    51  
    52  func cpuFreqPath(cpu ID, setting string) string {
    53  	return goresctrlpath.Path(SysfsCpuBasepath, fmt.Sprintf("cpu%d", cpu), "cpufreq", setting)
    54  }
    55  
    56  // SetCPUScalingMinFreq sets the scaling_min_freq value of a given CPU
    57  func SetCPUScalingMinFreq(cpu ID, freq int) error {
    58  	return setCPUFreqValue(cpu, "scaling_min_freq", freq)
    59  }
    60  
    61  // SetCPUScalingMaxFreq sets the scaling_max_freq value of a given CPU
    62  func SetCPUScalingMaxFreq(cpu ID, freq int) error {
    63  	return setCPUFreqValue(cpu, "scaling_max_freq", freq)
    64  }
    65  
    66  // SetCPUsScalingMinFreq sets the scaling_min_freq value of a given set of CPUs
    67  func SetCPUsScalingMinFreq(cpus []ID, freq int) error {
    68  	for _, cpu := range cpus {
    69  		if err := SetCPUScalingMinFreq(cpu, freq); err != nil {
    70  			return err
    71  		}
    72  	}
    73  
    74  	return nil
    75  }
    76  
    77  // SetCPUsScalingMaxFreq sets the scaling_max_freq value of a given set of CPUs
    78  func SetCPUsScalingMaxFreq(cpus []ID, freq int) error {
    79  	for _, cpu := range cpus {
    80  		if err := SetCPUScalingMaxFreq(cpu, freq); err != nil {
    81  			return err
    82  		}
    83  	}
    84  
    85  	return nil
    86  }
    87  
    88  // UncoreFreqAvailable returns true if the uncore frequency control functions are available.
    89  func UncoreFreqAvailable() bool {
    90  	_, err := os.Stat(goresctrlpath.Path(SysfsUncoreBasepath))
    91  	return err == nil
    92  }
    93  
    94  // SetUncoreMinFreq sets the minimum uncore frequency of a CPU die. Frequency is specified in kHz.
    95  func SetUncoreMinFreq(pkg, die ID, freqKhz int) error {
    96  	return setUncoreFreqValue(pkg, die, "min_freq_khz", freqKhz)
    97  }
    98  
    99  // SetUncoreMaxFreq sets the maximum uncore frequency of a CPU die. Frequency is specified in kHz.
   100  func SetUncoreMaxFreq(pkg, die ID, freqKhz int) error {
   101  	return setUncoreFreqValue(pkg, die, "max_freq_khz", freqKhz)
   102  }
   103  
   104  func uncoreFreqPath(pkg, die ID, attribute string) string {
   105  	return goresctrlpath.Path(SysfsUncoreBasepath, fmt.Sprintf("package_%02d_die_%02d", pkg, die), attribute)
   106  }
   107  
   108  func getUncoreFreqValue(pkg, die ID, attribute string) (int, error) {
   109  	return readFileInt(uncoreFreqPath(pkg, die, attribute))
   110  }
   111  
   112  func setUncoreFreqValue(pkg, die ID, attribute string, value int) error {
   113  	// Bounds checking
   114  	if hwMinFreq, err := getUncoreFreqValue(pkg, die, "initial_min_freq_khz"); err != nil {
   115  		return err
   116  	} else if value < hwMinFreq {
   117  		value = hwMinFreq
   118  	}
   119  	if hwMaxFreq, err := getUncoreFreqValue(pkg, die, "initial_max_freq_khz"); err != nil {
   120  		return err
   121  	} else if value > hwMaxFreq {
   122  		value = hwMaxFreq
   123  	}
   124  
   125  	return writeFileInt(uncoreFreqPath(pkg, die, attribute), value)
   126  }
   127  
   128  func writeFileInt(path string, value int) error {
   129  	return os.WriteFile(path, []byte(strconv.Itoa(value)), 0644)
   130  }
   131  
   132  func readFileInt(path string) (int, error) {
   133  	data, err := os.ReadFile(path)
   134  	if err != nil {
   135  		return 0, err
   136  	}
   137  	i, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 32)
   138  	return int(i), err
   139  }