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

     1  /*
     2  Copyright 2021 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 sst
    18  
    19  import (
    20  	"fmt"
    21  	stdlog "log"
    22  	"os"
    23  
    24  	grclog "github.com/intel/goresctrl/pkg/log"
    25  	goresctrlpath "github.com/intel/goresctrl/pkg/path"
    26  	"github.com/intel/goresctrl/pkg/utils"
    27  )
    28  
    29  // SstPackageInfo contains status of Intel Speed Select Technologies (SST)
    30  // for one CPU package
    31  type SstPackageInfo struct {
    32  	// Package related to this SST info
    33  	pkg *cpuPackageInfo
    34  
    35  	// Gereric PP info
    36  	PPSupported    bool
    37  	PPLocked       bool
    38  	PPVersion      int
    39  	PPCurrentLevel int
    40  	PPMaxLevel     int
    41  
    42  	// Information about the currently active PP level
    43  	CPSupported bool
    44  	CPEnabled   bool
    45  	CPPriority  CPPriorityType
    46  	BFSupported bool
    47  	BFEnabled   bool
    48  	BFCores     utils.IDSet
    49  	TFSupported bool
    50  	TFEnabled   bool
    51  
    52  	ClosInfo    [NumClos]SstClosInfo
    53  	ClosCPUInfo ClosCPUSet
    54  }
    55  
    56  // NumClos is the number of CLOSes suported by SST-CP
    57  const NumClos = 4
    58  
    59  // SstClosInfo contains parameters of one CLOS of SST-CP
    60  type SstClosInfo struct {
    61  	EPP                  int
    62  	ProportionalPriority int
    63  	MinFreq              int
    64  	MaxFreq              int
    65  	DesiredFreq          int
    66  }
    67  
    68  // CPPriorityType denotes the type CLOS priority ordering used in SST-CP
    69  type CPPriorityType int
    70  
    71  const (
    72  	Proportional CPPriorityType = 0
    73  	Ordered      CPPriorityType = 1
    74  )
    75  
    76  // ClosCPUSet contains mapping from Clos id to a set of CPU ids
    77  type ClosCPUSet map[int]utils.IDSet
    78  
    79  var sstlog grclog.Logger = grclog.NewLoggerWrapper(stdlog.New(os.Stderr, "[ sst ] ", 0))
    80  
    81  func isstDevPath() string { return goresctrlpath.Path("dev/isst_interface") }
    82  
    83  // SstSupported returns true if Intel Speed Select Technologies (SST) is supported
    84  // by the system and can be interfaced via the Linux kernel device
    85  func SstSupported() bool {
    86  	devPath := isstDevPath()
    87  	if _, err := os.Stat(devPath); err != nil {
    88  		if !os.IsNotExist(err) {
    89  			sstlog.Warnf("failed to access sst device %q: %v", devPath, err)
    90  		} else {
    91  			sstlog.Debugf("sst device %q does not exist", devPath)
    92  		}
    93  		return false
    94  	}
    95  	return true
    96  }
    97  
    98  // Check that a list of CPUs belong to a given package
    99  func CheckPackageCpus(info *SstPackageInfo, cpus utils.IDSet) bool {
   100  	return info.pkg.hasCpus(cpus)
   101  }
   102  
   103  // GetPackageInfo returns information of those packages given as a parameter
   104  // or all if none given.
   105  func GetPackageInfo(pkgs ...int) (map[int]*SstPackageInfo, error) {
   106  	var numPkgs int
   107  	var pkglist []int
   108  
   109  	// Get topology information from sysfs
   110  	packages, err := getOnlineCpuPackages()
   111  	if err != nil {
   112  		return nil, fmt.Errorf("failed to determine cpu topology: %w", err)
   113  	}
   114  
   115  	if len(pkgs) == 0 {
   116  		for i := range packages {
   117  			pkglist = append(pkglist, i)
   118  		}
   119  	} else {
   120  		for _, i := range pkgs {
   121  			if _, ok := packages[i]; !ok {
   122  				return nil, fmt.Errorf("cpu package %d not present", i)
   123  			} else {
   124  				pkglist = append(pkglist, i)
   125  			}
   126  		}
   127  	}
   128  
   129  	numPkgs = len(pkglist)
   130  	infomap := make(map[int]*SstPackageInfo, numPkgs)
   131  
   132  	for _, i := range pkglist {
   133  		info, err := getSinglePackageInfo(packages[i])
   134  		if err != nil {
   135  			return nil, err
   136  		}
   137  
   138  		infomap[i] = &info
   139  	}
   140  
   141  	return infomap, nil
   142  }
   143  
   144  // getSinglePackageInfo returns information of the SST configuration of one cpu
   145  // package.
   146  func getSinglePackageInfo(pkg *cpuPackageInfo) (SstPackageInfo, error) {
   147  	info := SstPackageInfo{}
   148  
   149  	cpu := pkg.cpus[0] // We just need to pass one logical cpu from the pkg as an arg
   150  
   151  	var rsp uint32
   152  	var err error
   153  
   154  	// Read perf-profile feature info
   155  	if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_GET_LEVELS_INFO, 0, 0); err != nil {
   156  		return info, fmt.Errorf("failed to read SST PP info: %v", err)
   157  	}
   158  	info.PPSupported = getBits(rsp, 31, 31) != 0
   159  	info.PPLocked = getBits(rsp, 24, 24) != 0
   160  	info.PPCurrentLevel = int(getBits(rsp, 16, 23))
   161  	info.PPMaxLevel = int(getBits(rsp, 8, 15))
   162  	info.PPVersion = int(getBits(rsp, 0, 7))
   163  	info.pkg = pkg
   164  
   165  	// Forget about older hw with partial/convoluted support
   166  	if info.PPVersion < 3 {
   167  		sstlog.Infof("SST PP version %d (less than 3), giving up...")
   168  		return info, nil
   169  	}
   170  
   171  	// Read the status of currently active perf-profile
   172  	if !info.PPSupported {
   173  		sstlog.Debugf("SST PP feature not supported, only profile level %d is valid", info.PPCurrentLevel)
   174  	}
   175  
   176  	if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_CONTROL, 0, uint32(info.PPCurrentLevel)); err != nil {
   177  		return info, fmt.Errorf("failed to read SST BF/TF status: %v", err)
   178  	}
   179  
   180  	info.BFSupported = isBitSet(rsp, 1)
   181  	info.BFEnabled = isBitSet(rsp, 17)
   182  
   183  	info.TFSupported = isBitSet(rsp, 0)
   184  	info.TFEnabled = isBitSet(rsp, 16)
   185  
   186  	// Read base-frequency info
   187  	if info.BFSupported {
   188  		info.BFCores = utils.IDSet{}
   189  
   190  		punitCoreIDs := make(map[utils.ID]utils.IDSet, len(pkg.cpus))
   191  		var maxPunitCore utils.ID
   192  		for _, id := range pkg.cpus {
   193  			pc, err := punitCPU(id)
   194  			if err != nil {
   195  				return info, err
   196  			}
   197  			punitCore := pc >> 1
   198  			if _, ok := punitCoreIDs[punitCore]; !ok {
   199  				punitCoreIDs[punitCore] = utils.IDSet{}
   200  			}
   201  			punitCoreIDs[punitCore].Add(id)
   202  			if punitCore > maxPunitCore {
   203  				maxPunitCore = punitCore
   204  			}
   205  		}
   206  
   207  		// Read out core masks in batches of 32 (32 bits per response)
   208  		for i := 0; i <= int(maxPunitCore)/32; i++ {
   209  			if rsp, err = sendMboxCmd(cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_CORE_MASK_INFO, 0, uint32(info.PPCurrentLevel+(i<<8))); err != nil {
   210  				return info, fmt.Errorf("failed to read SST BF core mask (#%d): %v", i, err)
   211  			}
   212  			for bit := 0; bit < 32; bit++ {
   213  				if isBitSet(rsp, uint32(bit)) {
   214  					info.BFCores.Add(punitCoreIDs[utils.ID(i*32+bit)].Members()...)
   215  				}
   216  			}
   217  		}
   218  	}
   219  
   220  	// Read core-power feature info
   221  	if rsp, err = sendMboxCmd(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0); err != nil {
   222  		return info, fmt.Errorf("failed to read SST CP info: %v", err)
   223  	}
   224  
   225  	info.CPSupported = isBitSet(rsp, 0)
   226  	info.CPEnabled = isBitSet(rsp, 16)
   227  
   228  	if info.CPSupported {
   229  		if rsp, err = sendMboxCmd(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0); err != nil {
   230  			return info, fmt.Errorf("failed to read SST CP status: %v", err)
   231  		}
   232  
   233  		info.CPPriority = CPPriorityType(getBits(rsp, 2, 2))
   234  		info.ClosCPUInfo = make(map[int]utils.IDSet, NumClos)
   235  
   236  		for i := 0; i < NumClos; i++ {
   237  			if rsp, err = sendClosCmd(cpu, CLOS_PM_CLOS, uint32(i), 0); err != nil {
   238  				return info, fmt.Errorf("failed to read SST CLOS #%d info: %v", i, err)
   239  			}
   240  
   241  			info.ClosInfo[i] = SstClosInfo{
   242  				EPP:                  int(getBits(rsp, 0, 3)),
   243  				ProportionalPriority: int(getBits(rsp, 4, 7)),
   244  				MinFreq:              int(getBits(rsp, 8, 15)),
   245  				MaxFreq:              int(getBits(rsp, 16, 23)),
   246  				DesiredFreq:          int(getBits(rsp, 24, 31)),
   247  			}
   248  		}
   249  
   250  		for _, id := range pkg.cpus {
   251  			closId, err := GetCPUClosID(id)
   252  			if err != nil {
   253  				continue
   254  			}
   255  
   256  			if info.ClosCPUInfo[closId] == nil {
   257  				info.ClosCPUInfo[closId] = utils.NewIDSet(id)
   258  			} else {
   259  				info.ClosCPUInfo[closId].Add(id)
   260  			}
   261  		}
   262  	}
   263  
   264  	return info, nil
   265  }
   266  
   267  func getPunitCoreId(cpu utils.ID) (uint32, error) {
   268  	p, err := punitCPU(cpu)
   269  	if err != nil {
   270  		return 0, err
   271  	}
   272  	punitCore := uint32(p) >> 1
   273  
   274  	return punitCore, nil
   275  }
   276  
   277  // GetCPUClosID returns the SST-CP CLOS id that a cpu is associated with.
   278  func GetCPUClosID(cpu utils.ID) (int, error) {
   279  	punitCore, err := getPunitCoreId(cpu)
   280  	if err != nil {
   281  		return -1, fmt.Errorf("invalid core id %d for cpu %d: %v", punitCore, cpu, err)
   282  	}
   283  
   284  	rsp, err := sendClosCmd(cpu, CLOS_PQR_ASSOC, punitCore, 0)
   285  	if err != nil {
   286  		return -1, fmt.Errorf("failed to read CLOS number of cpu %d: %v", cpu, err)
   287  	}
   288  	return int(getBits(rsp, 16, 17)), nil
   289  }
   290  
   291  func getBits(val, i, j uint32) uint32 {
   292  	lsb := i
   293  	msb := j
   294  	if i > j {
   295  		lsb = j
   296  		msb = i
   297  	}
   298  	return (val >> lsb) & ((1 << (msb - lsb + 1)) - 1)
   299  }
   300  
   301  func isBitSet(val, n uint32) bool {
   302  	return val&(1<<n) != 0
   303  }
   304  
   305  func setBit(val, n uint32) uint32 {
   306  	return val | (1 << n)
   307  }
   308  
   309  func clearBit(val, n uint32) uint32 {
   310  	return val &^ (1 << n)
   311  }
   312  
   313  func setBFStatus(info *SstPackageInfo, status bool) error {
   314  	rsp, err := sendMboxCmd(info.pkg.cpus[0], CONFIG_TDP, CONFIG_TDP_GET_TDP_CONTROL, 0, uint32(info.PPCurrentLevel))
   315  	if err != nil {
   316  		return fmt.Errorf("failed to read SST status: %w", err)
   317  	}
   318  
   319  	req := clearBit(rsp, 17)
   320  	if status {
   321  		req = setBit(rsp, 17)
   322  	}
   323  
   324  	if _, err = sendMboxCmd(info.pkg.cpus[0], CONFIG_TDP, CONFIG_TDP_SET_TDP_CONTROL, 0, req); err != nil {
   325  		return fmt.Errorf("failed to enable SST %s: %w", "BF", err)
   326  	}
   327  
   328  	info.BFEnabled = status
   329  
   330  	return nil
   331  }
   332  
   333  func setScalingMin2CPUInfoMax(info *SstPackageInfo) error {
   334  	for _, cpu := range info.pkg.cpus {
   335  		err := setCPUScalingMin2CPUInfoMaxFreq(cpu)
   336  		if err != nil {
   337  			return err
   338  		}
   339  	}
   340  
   341  	return nil
   342  }
   343  
   344  func enableBF(info *SstPackageInfo) error {
   345  	if !info.BFSupported {
   346  		return fmt.Errorf("SST BF not supported")
   347  	}
   348  
   349  	if err := setBFStatus(info, true); err != nil {
   350  		return err
   351  	}
   352  
   353  	if err := setScalingMin2CPUInfoMax(info); err != nil {
   354  		return err
   355  	}
   356  
   357  	return nil
   358  }
   359  
   360  // EnableBF enables SST-BF and sets it up properly
   361  func EnableBF(pkgs ...int) error {
   362  	if !isHWPEnabled() {
   363  		return fmt.Errorf("HWP is not enabled")
   364  	}
   365  
   366  	info, err := GetPackageInfo(pkgs...)
   367  	if err != nil {
   368  		return err
   369  	}
   370  
   371  	for _, i := range info {
   372  		err = enableBF(i)
   373  		if err != nil {
   374  			// Ignore but log error as there might be packages in the
   375  			// user supplied list that do not exists
   376  			sstlog.Errorf("sst-bf : %w", err)
   377  		}
   378  	}
   379  
   380  	return nil
   381  }
   382  
   383  func setScalingMin2CPUInfoMin(info *SstPackageInfo) error {
   384  	for _, cpu := range info.pkg.cpus {
   385  		err := setCPUScalingMin2CPUInfoMinFreq(cpu)
   386  		if err != nil {
   387  			return err
   388  		}
   389  	}
   390  
   391  	return nil
   392  }
   393  
   394  func disableBF(info *SstPackageInfo) error {
   395  	if !info.BFSupported {
   396  		return fmt.Errorf("SST BF not supported")
   397  	}
   398  
   399  	if err := setBFStatus(info, false); err != nil {
   400  		return err
   401  	}
   402  
   403  	if err := setScalingMin2CPUInfoMin(info); err != nil {
   404  		return err
   405  	}
   406  
   407  	return nil
   408  }
   409  
   410  // DisableBF disables SST-BF and clears things properly
   411  func DisableBF(pkgs ...int) error {
   412  	info, err := GetPackageInfo(pkgs...)
   413  	if err != nil {
   414  		return err
   415  	}
   416  
   417  	for _, i := range info {
   418  		err = disableBF(i)
   419  		if err != nil {
   420  			// Ignore but log error as there might be packages in the
   421  			// user supplied list that do not exists
   422  			sstlog.Errorf("sst-bf : %w", err)
   423  		}
   424  	}
   425  
   426  	return nil
   427  }
   428  
   429  func sendClosCmd(cpu utils.ID, subCmd uint16, parameter uint32, reqData uint32) (uint32, error) {
   430  	var id, offset uint32
   431  
   432  	switch subCmd {
   433  	case CLOS_PQR_ASSOC:
   434  		id = parameter & 0xff // core id
   435  		offset = PQR_ASSOC_OFFSET
   436  	case CLOS_PM_CLOS:
   437  		id = parameter & 0x03 // clos id
   438  		offset = PM_CLOS_OFFSET
   439  	case CLOS_STATUS:
   440  		fallthrough
   441  	default:
   442  		return 0, nil
   443  	}
   444  
   445  	return sendMMIOCmd(cpu, (id<<2)+offset, reqData, isBitSet(parameter, MBOX_CMD_WRITE_BIT))
   446  }
   447  
   448  func saveClos(closInfo *SstClosInfo, cpu utils.ID, clos int) error {
   449  	req := closInfo.EPP & 0x0f
   450  	req |= (closInfo.ProportionalPriority & 0x0f) << 4
   451  	req |= (closInfo.MinFreq & 0xff) << 8
   452  	req |= (closInfo.MaxFreq & 0xff) << 16
   453  	req |= (closInfo.DesiredFreq & 0xff) << 24
   454  
   455  	param := setBit(uint32(clos), MBOX_CMD_WRITE_BIT)
   456  
   457  	if _, err := sendClosCmd(cpu, CLOS_PM_CLOS, param, uint32(req)); err != nil {
   458  		return fmt.Errorf("failed to save Clos: %v", err)
   459  	}
   460  
   461  	return nil
   462  }
   463  
   464  func associate2Clos(cpu utils.ID, clos int) error {
   465  	coreId, err := getPunitCoreId(cpu)
   466  	if err != nil {
   467  		return fmt.Errorf("invalid core id %d for cpu %d: %v", coreId, cpu, err)
   468  	}
   469  
   470  	req := (clos & 0x03) << 16
   471  	param := setBit(coreId, MBOX_CMD_WRITE_BIT)
   472  
   473  	if _, err := sendClosCmd(cpu, CLOS_PQR_ASSOC, param, uint32(req)); err != nil {
   474  		return fmt.Errorf("failed to associate cpu %d to clos %d: %v", cpu, clos, err)
   475  	}
   476  
   477  	return nil
   478  }
   479  
   480  func writePMConfig(info *SstPackageInfo, cpu utils.ID, enable bool) (uint32, error) {
   481  	var req uint32
   482  
   483  	if enable {
   484  		req = setBit(0, 16)
   485  	}
   486  
   487  	if _, err := sendMboxCmd(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req); err != nil {
   488  		return 0, fmt.Errorf("failed to set SST-CP status: %v", err)
   489  	}
   490  
   491  	rsp, err := sendMboxCmd(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0)
   492  	if err != nil {
   493  		return 0, fmt.Errorf("failed to get SST-CP status: %v", err)
   494  	}
   495  
   496  	return rsp, nil
   497  }
   498  
   499  func writeClosPmQosConfig(info *SstPackageInfo, cpu utils.ID, enable bool) error {
   500  	var req uint32
   501  
   502  	param := setBit(0, MBOX_CMD_WRITE_BIT)
   503  
   504  	if enable {
   505  		req = setBit(0, 1)
   506  
   507  		if info.CPPriority > 0 {
   508  			req = setBit(req, 2)
   509  		}
   510  	}
   511  
   512  	if _, err := sendMboxCmd(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, param, req); err != nil {
   513  		return fmt.Errorf("failed to set SST-CP status: %v", err)
   514  	}
   515  
   516  	return nil
   517  }
   518  
   519  func enableCP(info *SstPackageInfo, cpu utils.ID) (uint32, error) {
   520  	if err := writeClosPmQosConfig(info, cpu, true); err != nil {
   521  		return 0, fmt.Errorf("Cannot set Clos status: %v", err)
   522  	}
   523  
   524  	return writePMConfig(info, cpu, true)
   525  }
   526  
   527  func disableCP(info *SstPackageInfo, cpu utils.ID) (uint32, error) {
   528  	if err := writeClosPmQosConfig(info, cpu, false); err != nil {
   529  		return 0, fmt.Errorf("Cannot set Clos status: %v", err)
   530  	}
   531  
   532  	return writePMConfig(info, cpu, false)
   533  }
   534  
   535  func setDefaultClosParam(info *SstPackageInfo, cpu utils.ID) error {
   536  	defaultConfig := &SstClosInfo{MaxFreq: 255}
   537  
   538  	for clos := 0; clos < 4; clos++ {
   539  		if err := saveClos(defaultConfig, cpu, clos); err != nil {
   540  			return err
   541  		}
   542  	}
   543  
   544  	return nil
   545  }
   546  
   547  func assignCPU2Clos(info *SstPackageInfo, clos int) error {
   548  	sstlog.Debugf("Setting Clos %d for cpus %v\n", clos, info.ClosCPUInfo[clos].Members())
   549  
   550  	for _, cpu := range info.ClosCPUInfo[clos].Members() {
   551  		if err := associate2Clos(cpu, clos); err != nil {
   552  			return fmt.Errorf("failed to associate cpu %d to clos %d: %v", cpu, clos, err)
   553  		}
   554  	}
   555  
   556  	return nil
   557  }
   558  
   559  // ConfigureCP will allow caller to configure CPUs to various Clos.
   560  func ConfigureCP(info *SstPackageInfo, priority int, cpu2clos *ClosCPUSet) error {
   561  	if priority < 0 || priority > 1 {
   562  		return fmt.Errorf("Invalid CP priority value %d (valid 0 or 1)", priority)
   563  	}
   564  
   565  	if info.ClosCPUInfo == nil {
   566  		info.ClosCPUInfo = make(map[int]utils.IDSet, len(*cpu2clos))
   567  	}
   568  
   569  	for clos, cpus := range *cpu2clos {
   570  		info.ClosCPUInfo[clos] = cpus.Clone()
   571  
   572  		// Remove the CPU from other Clos if found
   573  		for i := 0; i < NumClos; i++ {
   574  			if i == clos {
   575  				continue
   576  			}
   577  
   578  			for id := range cpus {
   579  				info.ClosCPUInfo[i].Del(id)
   580  			}
   581  		}
   582  
   583  		if err := assignCPU2Clos(info, clos); err != nil {
   584  			return err
   585  		}
   586  	}
   587  
   588  	info.CPPriority = CPPriorityType(priority)
   589  
   590  	return nil
   591  }
   592  
   593  // ClosSetup stores the user supplied Clos information into punit
   594  func ClosSetup(info *SstPackageInfo, clos int, closInfo *SstClosInfo) error {
   595  	if clos < 0 || clos >= NumClos {
   596  		return fmt.Errorf("Invalid Clos value (%d)", clos)
   597  	}
   598  
   599  	if closInfo.MinFreq < 0 || closInfo.MinFreq > 255 {
   600  		return fmt.Errorf("Invalid min freq (%d)", closInfo.MinFreq)
   601  	}
   602  
   603  	if closInfo.MaxFreq < 0 || closInfo.MaxFreq > 255 {
   604  		return fmt.Errorf("Invalid max freq (%d)", closInfo.MaxFreq)
   605  	}
   606  
   607  	if closInfo.MinFreq > closInfo.MaxFreq {
   608  		return fmt.Errorf("Min freq %d must be smaller than max freq %d", closInfo.MinFreq, closInfo.MaxFreq)
   609  	}
   610  
   611  	if closInfo.DesiredFreq < 0 || closInfo.DesiredFreq > 255 {
   612  		return fmt.Errorf("Invalid value %d for desired freq", closInfo.DesiredFreq)
   613  	}
   614  
   615  	if closInfo.EPP < 0 || closInfo.EPP > 15 {
   616  		return fmt.Errorf("Invalid value %d for EPP", closInfo.EPP)
   617  	}
   618  
   619  	if closInfo.ProportionalPriority < 0 || closInfo.ProportionalPriority > 15 {
   620  		return fmt.Errorf("Invalid value %d for proportionalPriority", closInfo.ProportionalPriority)
   621  	}
   622  
   623  	info.ClosInfo[clos] = *closInfo
   624  
   625  	return saveClos(&info.ClosInfo[clos], info.pkg.cpus[0], clos)
   626  }
   627  
   628  // ResetCPConfig will bring the system to a known state. This means that all
   629  // CLOS groups are reset to their default values, all package cores are assigned to
   630  // CLOS group 0 and ordered priority mode is enabled.
   631  func ResetCPConfig() error {
   632  	infomap, err := GetPackageInfo()
   633  	if err != nil {
   634  		return err
   635  	}
   636  
   637  	for _, info := range infomap {
   638  		for _, cpu := range info.pkg.cpus {
   639  			if info.pkg.cpus[0] == cpu {
   640  				if err := setDefaultClosParam(info, cpu); err != nil {
   641  					return err
   642  				}
   643  			}
   644  
   645  			if err := associate2Clos(cpu, 0); err != nil {
   646  				return fmt.Errorf("failed to associate cpu %d to clos %d: %w", cpu, 0, err)
   647  			}
   648  		}
   649  	}
   650  
   651  	return nil
   652  }
   653  
   654  // EnableCP enables SST-CP feature
   655  func EnableCP(info *SstPackageInfo) error {
   656  	if !info.CPSupported {
   657  		return fmt.Errorf("SST CP not supported")
   658  	}
   659  
   660  	if len(info.ClosCPUInfo) == 0 {
   661  		return fmt.Errorf("failed to enable CP: Clos to CPU mapping missing")
   662  	}
   663  
   664  	rsp, err := enableCP(info, info.pkg.cpus[0])
   665  	if err != nil {
   666  		return fmt.Errorf("failed to enable SST-CP: %v", err)
   667  	}
   668  
   669  	info.CPSupported = isBitSet(rsp, 0)
   670  	info.CPEnabled = isBitSet(rsp, 16)
   671  
   672  	return nil
   673  }
   674  
   675  // DisableCP disables SST-CP feature
   676  func DisableCP(info *SstPackageInfo) error {
   677  	if !info.CPSupported {
   678  		return fmt.Errorf("SST CP not supported")
   679  	}
   680  
   681  	if info.TFEnabled {
   682  		return fmt.Errorf("SST TF still enabled, disable it first.")
   683  	}
   684  
   685  	rsp, err := disableCP(info, info.pkg.cpus[0])
   686  	if err != nil {
   687  		return fmt.Errorf("failed to disable SST-CP: %v", err)
   688  	}
   689  
   690  	info.CPSupported = isBitSet(rsp, 0)
   691  	info.CPEnabled = isBitSet(rsp, 16)
   692  
   693  	return nil
   694  }