From 9200aaf9f7d71075bd59cf096a6101c732605512 Mon Sep 17 00:00:00 2001 From: Markus Lehtonen Date: Mon, 14 Sep 2026 09:57:38 +0300 Subject: [PATCH] sst: fix usage of unsafe.Pointer Fix usage if unsafe.Pointer with the ioctl calls. We converted a unsafe.Pointer to uintptr (a plain integer) early on, which opened the possibility for the garbage collector to move/invalidate the value before the syscall was finished. The syscall case is explicitly mentioned in the unsafe.Pointer documentation, see usage patter (4) in: https://pkg.go.dev/unsafe#Pointer Signed-off-by: Markus Lehtonen --- pkg/sst/internal/isst/isst.go | 12 ++++++------ pkg/sst/internal/isst/msr.go | 2 +- pkg/sst/internal/tpmi/tpmi.go | 36 +++++++++++++++++------------------ 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pkg/sst/internal/isst/isst.go b/pkg/sst/internal/isst/isst.go index c144618..9b8d151 100644 --- a/pkg/sst/internal/isst/isst.go +++ b/pkg/sst/internal/isst/isst.go @@ -38,14 +38,14 @@ func SetLogger(l *slog.Logger) { log = l } func DevPath() string { return goresctrlpath.Path("dev/isst_interface") } // Ioctl executes an ioctl on the linux isst_if device driver. -func Ioctl(ioctl uintptr, req uintptr) error { +func Ioctl(ioctl uintptr, req unsafe.Pointer) error { devPath := DevPath() f, err := os.Open(devPath) if err != nil { return fmt.Errorf("failed to open isst device %q: %v", devPath, err) } defer f.Close() //nolint:errcheck - if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(f.Fd()), ioctl, req); errno != 0 { + if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), ioctl, uintptr(req)); errno != 0 { return errno } return nil @@ -79,7 +79,7 @@ func getCPUMapping(cpu uint16) (uint16, error) { Cmd_count: 1, Cpu_map: [1]CPUMap{{Logical_cpu: uint32(cpu)}}, } - if err := Ioctl(ISST_IF_GET_PHY_ID, uintptr(unsafe.Pointer(&req))); err != nil { + if err := Ioctl(ISST_IF_GET_PHY_ID, unsafe.Pointer(&req)); err != nil { return 0, fmt.Errorf("failed to get CPU mapping for cpu %d: %v", cpu, err) } return uint16(req.Cpu_map[0].Physical_cpu), nil @@ -98,7 +98,7 @@ func SendMboxCmd(cpu uint16, cmd uint16, subCmd uint16, parameter uint32, reqDat }}, } log.Debug("MBOX SEND", "cpu", cpu, "cmd", cmd, "subCmd", subCmd, SlogHex("data", reqData)) - if err := Ioctl(ISST_IF_MBOX_COMMAND, uintptr(unsafe.Pointer(&req))); err != nil { + if err := Ioctl(ISST_IF_MBOX_COMMAND, unsafe.Pointer(&req)); err != nil { return 0, fmt.Errorf("mbox command failed with %v", err) } log.Debug("MBOX RECV", SlogHex("data", req.Mbox_cmd[0].Resp_data)) @@ -121,7 +121,7 @@ func SendMMIOCmd(cpu uint16, reg uint32, value uint32, doWrite bool) (uint32, er }}, } log.Debug("MMIO SEND", "cpu", cpu, "reg", reg, SlogHex("data", value), "write", doWrite) - if err := Ioctl(ISST_IF_IO_CMD, uintptr(unsafe.Pointer(&req))); err != nil { + if err := Ioctl(ISST_IF_IO_CMD, unsafe.Pointer(&req)); err != nil { return 0, fmt.Errorf("MMIO command failed with %v", err) } log.Debug("MMIO RECV", SlogHex("data", req.Io_reg[0].Value)) @@ -136,7 +136,7 @@ func SlogHex(key string, val uint32) slog.Attr { // GetPlatformAPIVersion gets the ISST API version. func GetPlatformAPIVersion() (int, error) { var info PlatformInfo - if err := Ioctl(ISST_IF_GET_PLATFORM_INFO, uintptr(unsafe.Pointer(&info))); err != nil { + if err := Ioctl(ISST_IF_GET_PLATFORM_INFO, unsafe.Pointer(&info)); err != nil { return 0, fmt.Errorf("failed to get ISST platform info: %w", err) } return int(info.Api_version), nil diff --git a/pkg/sst/internal/isst/msr.go b/pkg/sst/internal/isst/msr.go index 6385026..1e7ab16 100644 --- a/pkg/sst/internal/isst/msr.go +++ b/pkg/sst/internal/isst/msr.go @@ -37,7 +37,7 @@ func SendMSRCmd(cpu uint16, msr uint64, write bool, data *uint64) error { Data: *data, }}, } - if err := Ioctl(ISST_IF_MSR_COMMAND, uintptr(unsafe.Pointer(&req))); err != nil { + if err := Ioctl(ISST_IF_MSR_COMMAND, unsafe.Pointer(&req)); err != nil { return fmt.Errorf("MSR 0x%x command for cpu %d: %w", msr, cpu, err) } *data = req.Msr_cmd[0].Data diff --git a/pkg/sst/internal/tpmi/tpmi.go b/pkg/sst/internal/tpmi/tpmi.go index c01254a..9edaf5d 100644 --- a/pkg/sst/internal/tpmi/tpmi.go +++ b/pkg/sst/internal/tpmi/tpmi.go @@ -30,7 +30,7 @@ const numClos = 4 // GetSocketPunits returns the valid TPMI power domain (punit) indices for a socket. func GetSocketPunits(socketID uint8) ([]uint8, error) { req := isst.TpmiInstanceCount{Socket_id: socketID} - if err := isst.Ioctl(isst.ISST_IF_COUNT_TPMI_INSTANCES, uintptr(unsafe.Pointer(&req))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_COUNT_TPMI_INSTANCES, unsafe.Pointer(&req)); err != nil { return nil, fmt.Errorf("ISST_IF_COUNT_TPMI_INSTANCES for socket %d: %w", socketID, err) } if req.Valid_mask == 0 { @@ -64,7 +64,7 @@ func GetPunitCoreID(cpu uint16) (uint16, error) { // PPGetPerfLevels reads performance level info for a punit. func PPGetPerfLevels(socketID, punitID uint8) (isst.PerfLevelInfo, error) { info := isst.PerfLevelInfo{Socket_id: socketID, Power_domain_id: punitID} - if err := isst.Ioctl(isst.ISST_IF_PERF_LEVELS, uintptr(unsafe.Pointer(&info))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_PERF_LEVELS, unsafe.Pointer(&info)); err != nil { return isst.PerfLevelInfo{}, fmt.Errorf("ISST_IF_PERF_LEVELS for socket %d punit %d: %w", socketID, punitID, err) } return info, nil @@ -81,7 +81,7 @@ func CPSetState(socketID, punitID uint8, enable bool, priority uint8) error { if enable { cpState.Enable = 1 } - if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, uintptr(unsafe.Pointer(&cpState))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, unsafe.Pointer(&cpState)); err != nil { return fmt.Errorf("ISST_IF_CORE_POWER_STATE set for socket %d punit %d: %w", socketID, punitID, err) } return nil @@ -90,12 +90,12 @@ func CPSetState(socketID, punitID uint8, enable bool, priority uint8) error { // CPSetPriorityType updates the CP priority type for one punit, preserving the current enable state. func CPSetPriorityType(socketID, punitID uint8, priority uint8) error { cpState := isst.CorePower{Socket_id: socketID, Power_domain_id: punitID} - if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, uintptr(unsafe.Pointer(&cpState))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, unsafe.Pointer(&cpState)); err != nil { return fmt.Errorf("ISST_IF_CORE_POWER_STATE for socket %d punit %d: %w", socketID, punitID, err) } cpState.Get_set = 1 cpState.Priority_type = priority - if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, uintptr(unsafe.Pointer(&cpState))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, unsafe.Pointer(&cpState)); err != nil { return fmt.Errorf("ISST_IF_CORE_POWER_STATE set for socket %d punit %d: %w", socketID, punitID, err) } return nil @@ -113,7 +113,7 @@ func CPGetPriorityType(socketID, punitID uint8) (uint8, error) { // CPGetState reads the SST-CP state for a punit. func CPGetState(socketID, punitID uint8) (isst.CorePower, error) { cpState := isst.CorePower{Socket_id: socketID, Power_domain_id: punitID} - if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, uintptr(unsafe.Pointer(&cpState))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CORE_POWER_STATE, unsafe.Pointer(&cpState)); err != nil { return isst.CorePower{}, fmt.Errorf("ISST_IF_CORE_POWER_STATE for socket %d punit %d: %w", socketID, punitID, err) } return cpState, nil @@ -131,7 +131,7 @@ func ClosSetParam(socketID, punitID, clos, proportional uint8, minFreq, maxFreq Min_freq_mhz: minFreq, Max_freq_mhz: maxFreq, } - if err := isst.Ioctl(isst.ISST_IF_CLOS_PARAM, uintptr(unsafe.Pointer(¶m))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CLOS_PARAM, unsafe.Pointer(¶m)); err != nil { return fmt.Errorf("ISST_IF_CLOS_PARAM set for clos %d punit %d: %w", clos, punitID, err) } return nil @@ -144,7 +144,7 @@ func ClosGetParam(socketID, punitID, closIdx uint8) (isst.ClosParam, error) { Power_domain_id: punitID, Clos: closIdx, } - if err := isst.Ioctl(isst.ISST_IF_CLOS_PARAM, uintptr(unsafe.Pointer(&closParam))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CLOS_PARAM, unsafe.Pointer(&closParam)); err != nil { return isst.ClosParam{}, fmt.Errorf("ISST_IF_CLOS_PARAM for clos %d punit %d: %w", closIdx, punitID, err) } return closParam, nil @@ -173,7 +173,7 @@ func ClosAssociate(socketID, punitID uint8, punitCoreID uint16, clos uint8) erro Clos: uint16(clos), }}, } - if err := isst.Ioctl(isst.ISST_IF_CLOS_ASSOC, uintptr(unsafe.Pointer(&req))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CLOS_ASSOC, unsafe.Pointer(&req)); err != nil { return fmt.Errorf("ISST_IF_CLOS_ASSOC set for socket %d punit %d core %d clos %d: %w", socketID, punitID, punitCoreID, clos, err) } return nil @@ -190,7 +190,7 @@ func GetCPUClosID(socketID, punitID uint8, punitCoreID uint16) (uint8, error) { Logical_cpu: punitCoreID, }}, } - if err := isst.Ioctl(isst.ISST_IF_CLOS_ASSOC, uintptr(unsafe.Pointer(&req))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_CLOS_ASSOC, unsafe.Pointer(&req)); err != nil { return 0, fmt.Errorf("ISST_IF_CLOS_ASSOC for socket %d punit %d core %d: %w", socketID, punitID, punitCoreID, err) } return uint8(req.Assoc_info[0].Clos), nil @@ -199,7 +199,7 @@ func GetCPUClosID(socketID, punitID uint8, punitCoreID uint16) (uint8, error) { // BFSetStatus enables or disables SST-BF for one punit, preserving the current TF state. func BFSetStatus(socketID, punitID uint8, enable bool) error { perfInfo := isst.PerfLevelInfo{Socket_id: socketID, Power_domain_id: punitID} - if err := isst.Ioctl(isst.ISST_IF_PERF_LEVELS, uintptr(unsafe.Pointer(&perfInfo))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_PERF_LEVELS, unsafe.Pointer(&perfInfo)); err != nil { return fmt.Errorf("ISST_IF_PERF_LEVELS for socket %d punit %d: %w", socketID, punitID, err) } feature := perfInfo.Feature_state & 0x02 // preserve TF bit @@ -207,7 +207,7 @@ func BFSetStatus(socketID, punitID uint8, enable bool) error { feature |= 0x01 } ctrl := isst.PerfFeatureControl{Socket_id: socketID, Power_domain_id: punitID, Feature: feature} - if err := isst.Ioctl(isst.ISST_IF_PERF_SET_FEATURE, uintptr(unsafe.Pointer(&ctrl))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_PERF_SET_FEATURE, unsafe.Pointer(&ctrl)); err != nil { return fmt.Errorf("ISST_IF_PERF_SET_FEATURE (BF=%v) for socket %d punit %d: %w", enable, socketID, punitID, err) } return nil @@ -221,7 +221,7 @@ func BFGetCoreMask(socketID, punitID, level uint8) (uint64, error) { Level: level, Punit_cpu_map: 1, } - if err := isst.Ioctl(isst.ISST_IF_GET_BASE_FREQ_CPU_MASK, uintptr(unsafe.Pointer(&cpuMask))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_GET_BASE_FREQ_CPU_MASK, unsafe.Pointer(&cpuMask)); err != nil { return 0, fmt.Errorf("ISST_IF_GET_BASE_FREQ_CPU_MASK for socket %d punit %d: %w", socketID, punitID, err) } return cpuMask.Mask, nil @@ -231,7 +231,7 @@ func BFGetCoreMask(socketID, punitID, level uint8) (uint64, error) { // preserving the current BF state. func TFSetStatus(socketID, punitID uint8, enable bool) error { perfInfo := isst.PerfLevelInfo{Socket_id: socketID, Power_domain_id: punitID} - if err := isst.Ioctl(isst.ISST_IF_PERF_LEVELS, uintptr(unsafe.Pointer(&perfInfo))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_PERF_LEVELS, unsafe.Pointer(&perfInfo)); err != nil { return fmt.Errorf("ISST_IF_PERF_LEVELS for socket %d punit %d: %w", socketID, punitID, err) } feature := perfInfo.Feature_state & 0x01 // preserve BF bit @@ -239,7 +239,7 @@ func TFSetStatus(socketID, punitID uint8, enable bool) error { feature |= 0x02 } ctrl := isst.PerfFeatureControl{Socket_id: socketID, Power_domain_id: punitID, Feature: feature} - if err := isst.Ioctl(isst.ISST_IF_PERF_SET_FEATURE, uintptr(unsafe.Pointer(&ctrl))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_PERF_SET_FEATURE, unsafe.Pointer(&ctrl)); err != nil { return fmt.Errorf("ISST_IF_PERF_SET_FEATURE (TF=%v) for socket %d punit %d: %w", enable, socketID, punitID, err) } return nil @@ -253,7 +253,7 @@ func PerfLevelGetCPUMask(socketID, punitID, level uint8) (uint64, error) { Level: level, Punit_cpu_map: 1, } - if err := isst.Ioctl(isst.ISST_IF_GET_PERF_LEVEL_CPU_MASK, uintptr(unsafe.Pointer(&cpuMask))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_GET_PERF_LEVEL_CPU_MASK, unsafe.Pointer(&cpuMask)); err != nil { return 0, fmt.Errorf("ISST_IF_GET_PERF_LEVEL_CPU_MASK for socket %d punit %d level %d: %w", socketID, punitID, level, err) } return cpuMask.Mask, nil @@ -262,7 +262,7 @@ func PerfLevelGetCPUMask(socketID, punitID, level uint8) (uint64, error) { // BFGetInfo reads SST-BF frequency info for a performance level. func BFGetInfo(socketID, punitID, level uint8) (isst.BaseFreqInfo, error) { info := isst.BaseFreqInfo{Socket_id: socketID, Power_domain_id: punitID, Level: uint16(level)} - if err := isst.Ioctl(isst.ISST_IF_GET_BASE_FREQ_INFO, uintptr(unsafe.Pointer(&info))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_GET_BASE_FREQ_INFO, unsafe.Pointer(&info)); err != nil { return isst.BaseFreqInfo{}, fmt.Errorf("ISST_IF_GET_BASE_FREQ_INFO for socket %d punit %d level %d: %w", socketID, punitID, level, err) } return info, nil @@ -271,7 +271,7 @@ func BFGetInfo(socketID, punitID, level uint8) (isst.BaseFreqInfo, error) { // TFGetInfo reads SST-TF frequency info for a performance level. func TFGetInfo(socketID, punitID, level uint8) (isst.TurboFreqInfo, error) { info := isst.TurboFreqInfo{Socket_id: socketID, Power_domain_id: punitID, Level: uint16(level)} - if err := isst.Ioctl(isst.ISST_IF_GET_TURBO_FREQ_INFO, uintptr(unsafe.Pointer(&info))); err != nil { + if err := isst.Ioctl(isst.ISST_IF_GET_TURBO_FREQ_INFO, unsafe.Pointer(&info)); err != nil { return isst.TurboFreqInfo{}, fmt.Errorf("ISST_IF_GET_TURBO_FREQ_INFO for socket %d punit %d level %d: %w", socketID, punitID, level, err) } return info, nil