hwcap_linux.mx raw

   1  // Copyright 2019 The Go 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  package cpu
   6  
   7  import (
   8  	"os"
   9  )
  10  
  11  const (
  12  	_AT_HWCAP  = 16
  13  	_AT_HWCAP2 = 26
  14  
  15  	procAuxv = "/proc/self/auxv"
  16  
  17  	uintSize = int(32 << (^uint(0) >> 63))
  18  )
  19  
  20  // For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
  21  // These are initialized in cpu_$GOARCH.go
  22  // and should not be changed after they are initialized.
  23  var hwCap uint
  24  var hwCap2 uint
  25  
  26  func readHWCAP() error {
  27  	// For Go 1.21+, get auxv from the Go runtime.
  28  	if a := getAuxv(); len(a) > 0 {
  29  		for len(a) >= 2 {
  30  			tag, val := a[0], uint(a[1])
  31  			a = a[2:]
  32  			switch tag {
  33  			case _AT_HWCAP:
  34  				hwCap = val
  35  			case _AT_HWCAP2:
  36  				hwCap2 = val
  37  			}
  38  		}
  39  		return nil
  40  	}
  41  
  42  	buf, err := os.ReadFile(procAuxv)
  43  	if err != nil {
  44  		// e.g. on android /proc/self/auxv is not accessible, so silently
  45  		// ignore the error and leave Initialized = false. On some
  46  		// architectures (e.g. arm64) doinit() implements a fallback
  47  		// readout and will set Initialized = true again.
  48  		return err
  49  	}
  50  	bo := hostByteOrder()
  51  	for len(buf) >= 2*(uintSize/8) {
  52  		var tag, val uint
  53  		switch uintSize {
  54  		case 32:
  55  			tag = uint(bo.Uint32(buf[0:]))
  56  			val = uint(bo.Uint32(buf[4:]))
  57  			buf = buf[8:]
  58  		case 64:
  59  			tag = uint(bo.Uint64(buf[0:]))
  60  			val = uint(bo.Uint64(buf[8:]))
  61  			buf = buf[16:]
  62  		}
  63  		switch tag {
  64  		case _AT_HWCAP:
  65  			hwCap = val
  66  		case _AT_HWCAP2:
  67  			hwCap2 = val
  68  		}
  69  	}
  70  	return nil
  71  }
  72