Skip to content

Instantly share code, notes, and snippets.

@moson-mo
Created July 3, 2022 09:21
Show Gist options
  • Save moson-mo/f18731cf73203011a279b90230d29362 to your computer and use it in GitHub Desktop.
Save moson-mo/f18731cf73203011a279b90230d29362 to your computer and use it in GitHub Desktop.
Go - Reading/Writing to PCI config registers via sysfs. (example of controlling CPU boosting for a Ryzen mobile processor)
/*
Example of reading/writing to PCI config registers via sysfs.
In this example we write to the SMU (MP1 mailbox) of a Ryzen mobile processor
to modify a setting that controls CPU's boosting behavior.
There are two modes, "power-saving" (which is usually automatically activated when running on battery power)
and "max-performance" (when connected to AC)
See https://github.com/FlyGoat/RyzenAdj/wiki/Renoir-Tuning-Guide#--power-saving-dc-mode-tune-with-boost-delay
for more information.
*/
package main
import (
"encoding/binary"
"fmt"
"os"
)
const (
PCI_DEV_CONFIG_PATH = "/sys/bus/pci/devices/0000:00:00.0/config"
PCI_REG_OFFSET_ADDRESS = 0xB8
PCI_REG_OFFSET_DATA = 0xBC
MP1_MESSAGE_ADDR = 0x3B10528
MP1_RESPONSE_ADDR = 0x3B10564
)
func main() {
writeMP1(MP1_RESPONSE_ADDR, 0x0) // clear response
writeMP1(MP1_MESSAGE_ADDR, 0x11) // performance mode
//writeMP1(MP1_MESSAGE_ADDR, 0x12) // power-saving mode
resp := uint32(0)
for resp == 0 {
resp = readMP1(MP1_RESPONSE_ADDR) // read until we get a response
}
fmt.Printf("DONE - Response code: %d\n", resp)
}
func readMP1(addr uint32) uint32 {
err := writeConfigRegister(PCI_REG_OFFSET_ADDRESS, (addr &^ 0x3))
if err != nil {
panic(err)
}
val, err := readConfigRegister(PCI_REG_OFFSET_DATA)
if err != nil {
panic(err)
}
return val
}
func writeMP1(addr, data uint32) {
err := writeConfigRegister(PCI_REG_OFFSET_ADDRESS, addr)
if err != nil {
panic(err)
}
err = writeConfigRegister(PCI_REG_OFFSET_DATA, data)
if err != nil {
panic(err)
}
}
type barreg struct {
offset int64
*os.File
}
func (r *barreg) Read(b []byte) (int, error) {
return r.ReadAt(b, r.offset)
}
func (r *barreg) Write(b []byte) (int, error) {
return r.WriteAt(b, r.offset)
}
func readConfigRegister(offset int64) (uint32, error) {
f, err := os.Open(PCI_DEV_CONFIG_PATH)
if err != nil {
return 0, err
}
defer f.Close()
var val uint32
err = binary.Read(&barreg{offset: offset, File: f}, binary.LittleEndian, &val)
return val, err
}
func writeConfigRegister(offset int64, val uint32) error {
f, err := os.OpenFile(PCI_DEV_CONFIG_PATH, os.O_WRONLY, 0)
if err != nil {
return err
}
defer f.Close()
err = binary.Write(&barreg{offset: offset, File: f}, binary.LittleEndian, &val)
return err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment