github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/smn/main.go (about)

     1  // Copyright 2012-2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // smn: read or write registers in the System Management Network on AMD cpus
     6  //
     7  // Synopsis:
     8  //
     9  //	snm [0 or more addresses]
    10  //
    11  // N.B. having no addresses is an easy way to see if you can
    12  // access PCI at all.
    13  //
    14  // Description:
    15  //
    16  //	read and write System Management Network registers
    17  //
    18  // Options:
    19  //
    20  //	-s: device glob in the form tttt:bb:dd.fn with * as needed
    21  //	-n: number of 32-bit words to dump.
    22  //	-v: 32-bit value to write
    23  //	-w: write the value to the register(s)
    24  package main
    25  
    26  import (
    27  	"flag"
    28  	"fmt"
    29  	"log"
    30  	"strconv"
    31  	"strings"
    32  
    33  	"github.com/mvdan/u-root-coreutils/pkg/pci"
    34  )
    35  
    36  // Index/Data register pairs, as, e.g., cf8/cfc for PCI,
    37  // are known to be a terrible idea, from almost any point of view.
    38  // It took years to kill them on regular PCI.
    39  // AMD brought them back for the SMN. Bummer.
    40  const (
    41  	regIndex = 0xa0
    42  	regData  = 0xa4
    43  )
    44  
    45  var (
    46  	devs  = flag.String("s", "0000:00:00.0", "Glob for northbridge")
    47  	n     = flag.Uint("n", 1, "Number 32-bit words to dump/set")
    48  	val   = flag.Uint64("v", 0, "Val to set on write")
    49  	write = flag.Bool("w", false, "Write a value")
    50  )
    51  
    52  func usage() {
    53  	log.Fatal("Usage: smn [-w] [-d glob] address [# 32-words to read | 32-bit value to write]")
    54  }
    55  
    56  func main() {
    57  	flag.Parse()
    58  	r, err := pci.NewBusReader(strings.Split(*devs, ",")...)
    59  	if err != nil {
    60  		log.Fatalf("%v", err)
    61  	}
    62  
    63  	d, err := r.Read()
    64  	if err != nil {
    65  		log.Fatalf("Read: %v", err)
    66  	}
    67  
    68  	a := flag.Args()
    69  	if uint32(*val>>32) != 0 {
    70  		log.Fatalf("Value:%#x is not a 32-bit number", *val)
    71  	}
    72  	for i := range a {
    73  		addr, err := strconv.ParseUint(a[i], 16, 32)
    74  		if err != nil {
    75  			log.Fatal(err)
    76  		}
    77  		switch *write {
    78  		case true:
    79  			if err := d.WriteConfigRegister(regIndex, 32, addr); err != nil {
    80  				log.Fatal(err)
    81  			}
    82  			if err := d.WriteConfigRegister(regData, 32, *val); err != nil {
    83  				log.Fatal(err)
    84  			}
    85  		case false:
    86  			for i := addr; i < addr+uint64(*n); i += 4 {
    87  				if err := d.WriteConfigRegister(regIndex, 32, i); err != nil {
    88  					log.Fatal(err)
    89  				}
    90  				// SMN data is 32 bits!
    91  				dat, err := d.ReadConfigRegister(regData, 32)
    92  				if err != nil {
    93  					log.Fatal(err)
    94  				}
    95  				fmt.Printf("%#x:", i)
    96  				for i := range dat {
    97  					fmt.Printf("%s:%#x,", d[i].Addr, dat[i])
    98  				}
    99  				fmt.Println()
   100  			}
   101  		}
   102  	}
   103  }