137 lines
3.8 KiB
Go
137 lines
3.8 KiB
Go
/*
|
|
Copyright 2022 Intel Corporation
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
SysfsUncoreBasepath = "/sys/devices/system/cpu/intel_uncore_frequency/"
|
|
)
|
|
|
|
func setCPUFreqValue(cpu ID, setting string, value int) error {
|
|
path := fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/%s", cpu, setting)
|
|
return writeFileInt(path, value)
|
|
}
|
|
|
|
// GetCPUFreqValue returns information of the currently used CPU frequency
|
|
func GetCPUFreqValue(cpu ID, setting string) (int, error) {
|
|
str := fmt.Sprintf("/sys/devices/system/cpu/cpu%d/cpufreq/%s", cpu, setting)
|
|
|
|
raw, err := ioutil.ReadFile(str)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
value, err := strconv.Atoi(strings.TrimSpace(string(raw)))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
// SetCPUScalingMinFreq sets the scaling_min_freq value of a given CPU
|
|
func SetCPUScalingMinFreq(cpu ID, freq int) error {
|
|
return setCPUFreqValue(cpu, "scaling_min_freq", freq)
|
|
}
|
|
|
|
// SetCPUScalingMaxFreq sets the scaling_max_freq value of a given CPU
|
|
func SetCPUScalingMaxFreq(cpu ID, freq int) error {
|
|
return setCPUFreqValue(cpu, "scaling_max_freq", freq)
|
|
}
|
|
|
|
// SetCPUsScalingMinFreq sets the scaling_min_freq value of a given set of CPUs
|
|
func SetCPUsScalingMinFreq(cpus []ID, freq int) error {
|
|
for _, cpu := range cpus {
|
|
if err := SetCPUScalingMinFreq(cpu, freq); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetCPUsScalingMaxFreq sets the scaling_max_freq value of a given set of CPUs
|
|
func SetCPUsScalingMaxFreq(cpus []ID, freq int) error {
|
|
for _, cpu := range cpus {
|
|
if err := SetCPUScalingMaxFreq(cpu, freq); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// UncoreFreqAvailable returns true if the uncore frequency control functions are available.
|
|
func UncoreFreqAvailable() bool {
|
|
_, err := os.Stat(SysfsUncoreBasepath)
|
|
return err == nil
|
|
}
|
|
|
|
// SetUncoreMinFreq sets the minimum uncore frequency of a CPU die. Frequency is specified in kHz.
|
|
func SetUncoreMinFreq(pkg, die ID, freqKhz int) error {
|
|
return setUncoreFreqValue(pkg, die, "min_freq_khz", freqKhz)
|
|
}
|
|
|
|
// SetUncoreMaxFreq sets the maximum uncore frequency of a CPU die. Frequency is specified in kHz.
|
|
func SetUncoreMaxFreq(pkg, die ID, freqKhz int) error {
|
|
return setUncoreFreqValue(pkg, die, "max_freq_khz", freqKhz)
|
|
}
|
|
|
|
func uncoreFreqPath(pkg, die ID, attribute string) string {
|
|
return fmt.Sprintf(SysfsUncoreBasepath+"package_%02d_die_%02d/%s", pkg, die, attribute)
|
|
}
|
|
|
|
func getUncoreFreqValue(pkg, die ID, attribute string) (int, error) {
|
|
return readFileInt(uncoreFreqPath(pkg, die, attribute))
|
|
}
|
|
|
|
func setUncoreFreqValue(pkg, die ID, attribute string, value int) error {
|
|
// Bounds checking
|
|
if hwMinFreq, err := getUncoreFreqValue(pkg, die, "initial_min_freq_khz"); err != nil {
|
|
return err
|
|
} else if value < hwMinFreq {
|
|
value = hwMinFreq
|
|
}
|
|
if hwMaxFreq, err := getUncoreFreqValue(pkg, die, "initial_max_freq_khz"); err != nil {
|
|
return err
|
|
} else if value > hwMaxFreq {
|
|
value = hwMaxFreq
|
|
}
|
|
|
|
return writeFileInt(uncoreFreqPath(pkg, die, attribute), value)
|
|
}
|
|
|
|
func writeFileInt(path string, value int) error {
|
|
return ioutil.WriteFile(path, []byte(strconv.Itoa(value)), 0644)
|
|
}
|
|
|
|
func readFileInt(path string) (int, error) {
|
|
data, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
i, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 32)
|
|
return int(i), err
|
|
}
|