From 7b53c8dbaef3e559b6de799d8858382b57b9a65f Mon Sep 17 00:00:00 2001 From: jharper5 Date: Wed, 28 Jun 2023 17:20:07 -0700 Subject: [PATCH] Add active idle values to uncore table --- .gitignore | 1 + go.work | 1 + go.work.sum | 17 ++- src/Makefile | 22 ++-- src/collector/collector_linux.go | 2 +- .../resources/collector_reports.yaml.tmpl | 14 +++ src/pkg/msr/msr.go | 43 +++++++ src/pkg/msr/msr_test.go | 11 ++ src/reporter/report.go | 2 +- src/reporter/report_tables.go | 4 + src/reporter/source.go | 22 ++++ src/wrmsr/go.mod | 7 ++ src/wrmsr/main.go | 115 ++++++++++++++++++ 13 files changed, 247 insertions(+), 14 deletions(-) create mode 100644 src/wrmsr/go.mod create mode 100644 src/wrmsr/main.go diff --git a/.gitignore b/.gitignore index 9a2f19e..2185dcc 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ src/collector/collector src/collector/collector.exe src/collector/collector_arm64 src/rdmsr/rdmsr +src/wrmsr/wrmsr src/msrbusy/msrbusy src/calcfreq/calcfreq # src diff --git a/go.work b/go.work index 5d5c8a1..84713b1 100644 --- a/go.work +++ b/go.work @@ -5,6 +5,7 @@ use ./src/msrbusy use ./src/orchestrator use ./src/rdmsr use ./src/reporter +use ./src/wrmsr use ./src/pkg/commandfile use ./src/pkg/core use ./src/pkg/cpu diff --git a/go.work.sum b/go.work.sum index 1870b55..4dea408 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,13 +1,22 @@ +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/xuri/excelize/v2 v2.7.0 h1:Hri/czwyRCW6f6zrCDWXcXKshlq4xAZNpNOpdfnFhEw= github.com/xuri/excelize/v2 v2.7.0/go.mod h1:ebKlRoS+rGyLMyUx3ErBECXs/HNYqyj+PbkkKRK5vSI= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/src/Makefile b/src/Makefile index b05b236..3d2e853 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,9 +10,9 @@ VERSION_NUMBER := $(shell cat ${VERSION_FILE}) VERSION := $(VERSION_NUMBER)_$(COMMIT_DATE)_$(COMMIT_ID) default: check orchestrator -.PHONY: default test check format_check format linux-source collector reporter orchestrator rdmsr msrbusy reset clean tools libs async-profiler calcfreq cpuid dmidecode ethtool fio flamegraph ipmitool lshw lspci mlc perf spectre-meltdown-checker sshpass stress-ng sysstat turbostat oss-source +.PHONY: default test check format_check format linux-source collector reporter orchestrator rdmsr wrmsr msrbusy reset clean tools libs async-profiler calcfreq cpuid dmidecode ethtool fio flamegraph ipmitool lshw lspci mlc perf spectre-meltdown-checker sshpass stress-ng sysstat turbostat oss-source -collector_tools: async-profiler calcfreq cpuid dmidecode ethtool fio flamegraph ipmitool lshw lspci mlc msrbusy perf rdmsr spectre-meltdown-checker stress-ng sysstat turbostat +collector_tools: async-profiler calcfreq cpuid dmidecode ethtool fio flamegraph ipmitool lshw lspci mlc msrbusy perf rdmsr wrmsr spectre-meltdown-checker stress-ng sysstat turbostat test: cd pkg/commandfile && go test -v -vet=all . @@ -25,6 +25,7 @@ test: cd collector && go test -v -vet=all . cd reporter && go test -v -vet=all . cd rdmsr && go test -v -vet=all . + cd wrmsr && go test -v -vet=all . cd msrbusy && go test -v -vet=all . format: @@ -45,20 +46,23 @@ orchestrator: sshpass reporter collector collector-deps cp reporter/reporter orchestrator/resources/ cp collector/collector orchestrator/resources/ cp collector/collector_arm64 orchestrator/resources/ - cd orchestrator && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -X main.gVersion=$(VERSION)' -o orchestrator + cd orchestrator && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '-s -w -X main.gVersion=$(VERSION)' -o orchestrator collector: - cd collector && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -X main.gVersion=$(VERSION)' -o collector - cd collector && CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags '-s -w -X main.gVersion=$(VERSION)' -o collector_arm64 + cd collector && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '-s -w -X main.gVersion=$(VERSION)' -o collector + cd collector && CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -v -ldflags '-s -w -X main.gVersion=$(VERSION)' -o collector_arm64 reporter: - cd reporter && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -X main.gVersion=$(VERSION)' -o reporter + cd reporter && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '-s -w -X main.gVersion=$(VERSION)' -o reporter rdmsr: - cd rdmsr && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -X main.gVersion=$(VERSION)' -o rdmsr + cd rdmsr && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '-s -w -X main.gVersion=$(VERSION)' -o rdmsr + +wrmsr: + cd wrmsr && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '-s -w -X main.gVersion=$(VERSION)' -o wrmsr msrbusy: - cd msrbusy && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w -X main.gVersion=$(VERSION)' -o msrbusy + cd msrbusy && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -v -ldflags '-s -w -X main.gVersion=$(VERSION)' -o msrbusy async-profiler: ifeq ("$(wildcard async-profiler)","") @@ -232,6 +236,7 @@ collector-deps-amd64: collector_tools cp -R async-profiler $(TMPDIR) cp flamegraph/stackcollapse-perf.pl $(TMPDIR) cp rdmsr/rdmsr $(TMPDIR) + cp wrmsr/wrmsr $(TMPDIR) cp spectre-meltdown-checker/spectre-meltdown-checker.sh $(TMPDIR) cp stress-ng/stress-ng $(TMPDIR) cp sysstat/mpstat $(TMPDIR) @@ -271,6 +276,7 @@ clean: rm -f orchestrator/resources/reporter rm -f orchestrator/resources/sshpass rm -f rdmsr/rdmsr + rm -f wrmsr/wrmsr rm -f msrbusy/msrbusy reset: diff --git a/src/collector/collector_linux.go b/src/collector/collector_linux.go index c788322..8ec7334 100644 --- a/src/collector/collector_linux.go +++ b/src/collector/collector_linux.go @@ -37,7 +37,7 @@ func runCommand(label string, command string, superuser bool, superuserPassword if binPath != "" { path := getUserPath() newPath := fmt.Sprintf("%s%c%s", binPath, os.PathListSeparator, path) - cmdWithPath = fmt.Sprintf("PATH=\"%s\" %s", newPath, cmdWithPath) + cmdWithPath = fmt.Sprintf("PATH=\"%s\"\n%s", newPath, command) } if superuser { return runSuperUserCommand(cmdWithPath, superuserPassword, timeout) diff --git a/src/orchestrator/resources/collector_reports.yaml.tmpl b/src/orchestrator/resources/collector_reports.yaml.tmpl index 7fca2f8..0c92a9a 100644 --- a/src/orchestrator/resources/collector_reports.yaml.tmpl +++ b/src/orchestrator/resources/collector_reports.yaml.tmpl @@ -191,6 +191,20 @@ commands: superuser: true modprobe: msr parallel: true + - label: active idle utilization point + command: |- + wrmsr 0xb0 0x80000694 # must write this value to this MSR before reading 0xb1 + rdmsr -f 15:8 0xb1 # ACTIVE IDLE - UTILIZATION POINT + superuser: true + modprobe: msr + parallel: true + - label: active idle mesh frequency + command: |- + wrmsr 0xb0 0x80000694 # must write this value to this MSR before reading 0xb1 + rdmsr -f 7:0 0xb1 # ACTIVE IDLE - MESH FREQUENCY + superuser: true + modprobe: msr + parallel: true - label: ipmitool sel time get command: LC_ALL=C ipmitool sel time get superuser: true diff --git a/src/pkg/msr/msr.go b/src/pkg/msr/msr.go index 92e290d..769eeb0 100644 --- a/src/pkg/msr/msr.go +++ b/src/pkg/msr/msr.go @@ -127,6 +127,25 @@ func (msr *MSR) read(reg uint64, fileName string, bytes int) (val uint64, err er return } +func (msr *MSR) write(reg uint64, fileName string, bytes int, val uint64) (err error) { + f, err := os.OpenFile(fileName, os.O_RDWR, 0644) + if err != nil { + return + } + defer f.Close() + buf := make([]byte, 0, 8) + buf = binary.LittleEndian.AppendUint64(buf, val) + written, err := f.WriteAt(buf, int64(reg)) + if err != nil { + return + } + if written != bytes { + err = fmt.Errorf("didn't write intended number of bytes: %d,%d", bytes, written) + return + } + return +} + // SetBitRange filters bits for subsequent calls to Read* functions func (msr *MSR) SetBitRange(highBit int, lowBit int) (err error) { if lowBit >= highBit { @@ -160,6 +179,19 @@ func (msr *MSR) ReadAll(reg uint64) (out []uint64, err error) { return } +// WriteAll writes the given value to all cores at the given register offset +func (msr *MSR) WriteAll(reg uint64, val uint64) (err error) { + fileNames := msr.getMSRFileNames(-1, false) + for _, fileName := range fileNames { + var val uint64 + err = msr.write(reg, fileName, 8, val) + if err != nil { + return + } + } + return +} + // ReadOne returns the register value for the specified core func (msr *MSR) ReadOne(reg uint64, core int) (out uint64, err error) { fileNames := msr.getMSRFileNames(core, false) @@ -171,6 +203,17 @@ func (msr *MSR) ReadOne(reg uint64, core int) (out uint64, err error) { return } +// WriteOne writes the given value to the the specified core at the given register offset +func (msr *MSR) WriteOne(reg uint64, core int, val uint64) (err error) { + fileNames := msr.getMSRFileNames(core, false) + if len(fileNames) != 1 { + err = fmt.Errorf("did not find filenames for msr,core: %d, %d", reg, core) + return + } + err = msr.write(reg, fileNames[0], 8, val) + return +} + // ReadPackages returns the specified register value for each package (CPU/Socket) func (msr *MSR) ReadPackages(reg uint64) (out []uint64, err error) { fileNames := msr.getMSRFileNames(-1, true) diff --git a/src/pkg/msr/msr_test.go b/src/pkg/msr/msr_test.go index 05fb152..0637e50 100644 --- a/src/pkg/msr/msr_test.go +++ b/src/pkg/msr/msr_test.go @@ -66,6 +66,17 @@ func TestReadOne(t *testing.T) { } } +func TestWriteOne(t *testing.T) { + msr, err := NewMSR() + if err != nil { + t.Fatal(err) + } + err = msr.WriteOne(0xB0, 0, 0x80000694) + if err != nil { + t.Fatal(err) + } +} + func TestReadAll(t *testing.T) { msr, err := NewMSR() if err != nil { diff --git a/src/reporter/report.go b/src/reporter/report.go index 800b331..92ffeeb 100644 --- a/src/reporter/report.go +++ b/src/reporter/report.go @@ -43,9 +43,9 @@ func NewConfigurationReport(sources []*Source, cpusInfo *cpu.CPU) (report *Repor newISATable(sources, CPUCategory), newAcceleratorTable(sources, CPUCategory), newFeatureTable(sources, CPUCategory), - newUncoreTable(sources, CPUCategory), newPowerTable(sources, Power), + newUncoreTable(sources, Power), }..., ) diff --git a/src/reporter/report_tables.go b/src/reporter/report_tables.go index ef564a0..c4c8d88 100644 --- a/src/reporter/report_tables.go +++ b/src/reporter/report_tables.go @@ -672,12 +672,16 @@ func newUncoreTable(sources []*Source, category TableCategory) (table *Table) { "CHA Count", "Minimum Frequency", "Maximum Frequency", + "Active Idle Frequency", + "Active Idle Utilization Point", }, Values: [][]string{ { source.getCHACount(), source.getUncoreMinFrequency(), source.getUncoreMaxFrequency(), + source.getActiveIdleFrequency(), + source.getActiveIdleUtilizationPoint(), }, }, } diff --git a/src/reporter/source.go b/src/reporter/source.go index 72a7fb9..1f60657 100644 --- a/src/reporter/source.go +++ b/src/reporter/source.go @@ -425,6 +425,28 @@ func (s *Source) getNUMACPUList() (val string) { return } +func (s *Source) getActiveIdleFrequency() (val string) { + hex := s.getCommandOutputLine("active idle mesh frequency") + if hex != "" { + parsed, err := strconv.ParseInt(hex, 16, 64) + if err == nil { + val = fmt.Sprintf("%.1fGHz", float64(parsed)/10) + } + } + return +} + +func (s *Source) getActiveIdleUtilizationPoint() (val string) { + hex := s.getCommandOutputLine("active idle utilization point") + if hex != "" { + parsed, err := strconv.ParseInt(hex, 16, 64) + if err == nil { + val = fmt.Sprintf("%d", parsed) + } + } + return +} + func (s *Source) getUncoreMaxFrequency() (val string) { hex := s.getCommandOutputLine("uncore max frequency") if hex != "" && hex != "0" { diff --git a/src/wrmsr/go.mod b/src/wrmsr/go.mod new file mode 100644 index 0000000..8818de2 --- /dev/null +++ b/src/wrmsr/go.mod @@ -0,0 +1,7 @@ +module intel.com/svr-info/wrmsr/v2 + +go 1.20 + +replace intel.com/svr-info/pkg/msr => ../pkg/msr + +require intel.com/svr-info/pkg/msr v0.0.0-00010101000000-000000000000 diff --git a/src/wrmsr/main.go b/src/wrmsr/main.go new file mode 100644 index 0000000..1048208 --- /dev/null +++ b/src/wrmsr/main.go @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2023 Intel Corporation + * SPDX-License-Identifier: MIT + */ +package main + +import ( + "flag" + "fmt" + "os" + "path/filepath" + "strconv" + + "intel.com/svr-info/pkg/msr" +) + +type CmdLineArgs struct { + help bool + version bool + all bool + processor int + msr uint64 + val uint64 +} + +// globals +var ( + gVersion string = "dev" // build overrides this, see makefile + gCmdLineArgs CmdLineArgs +) + +func showUsage() { + appName := filepath.Base(os.Args[0]) + fmt.Fprintf(os.Stderr, "Usage: %s msr value\n", appName) + fmt.Fprintf(os.Stderr, "Example: %s -p 1 0x123 0xabc\n", appName) + flag.PrintDefaults() +} + +func showVersion() { + fmt.Println(gVersion) +} + +func init() { + // init command line flags + flag.Usage = func() { showUsage() } // override default usage output + flag.BoolVar(&gCmdLineArgs.help, "h", false, "Print this usage message.") + flag.BoolVar(&gCmdLineArgs.version, "v", false, "Print program version.") + flag.BoolVar(&gCmdLineArgs.all, "a", false, "Write for all processors.") + flag.IntVar(&gCmdLineArgs.processor, "p", 0, "Select processor number. Default 0.") + flag.Parse() + if gCmdLineArgs.help || gCmdLineArgs.version { + return + } + // positional arg + if flag.NArg() < 2 { + flag.Usage() + os.Exit(1) + } else { + msrHex := flag.Arg(0) + if len(msrHex) > 2 && msrHex[:2] == "0x" { + msrHex = msrHex[2:] + } + msr, err := strconv.ParseInt(msrHex, 16, 0) + if err != nil { + fmt.Fprintf(os.Stderr, "Could not parse provided msr address: %v\n", err) + showUsage() + os.Exit(1) + } + gCmdLineArgs.msr = uint64(msr) + + valHex := flag.Arg(1) + if len(valHex) > 2 && valHex[:2] == "0x" { + valHex = valHex[2:] + } + val, err := strconv.ParseInt(valHex, 16, 0) + if err != nil { + fmt.Fprintf(os.Stderr, "Could not parse provided msr value: %v\n", err) + showUsage() + os.Exit(1) + } + gCmdLineArgs.val = uint64(val) + } +} + +func mainReturnWithCode() int { + if gCmdLineArgs.help { + showUsage() + return 0 + } + if gCmdLineArgs.version { + showVersion() + return 0 + } + msrWriter, err := msr.NewMSR() + if err != nil { + fmt.Fprintln(os.Stderr, err) + return 1 + } + if gCmdLineArgs.all { + err = msrWriter.WriteAll(gCmdLineArgs.msr, gCmdLineArgs.val) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return 1 + } + } else { + err := msrWriter.WriteOne(gCmdLineArgs.msr, gCmdLineArgs.processor, gCmdLineArgs.val) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return 1 + } + } + return 0 +} + +func main() { os.Exit(mainReturnWithCode()) }