Unverified Commit f8d9ec29 authored by cuisongliu's avatar cuisongliu Committed by GitHub
Browse files

Merge pull request #256 from cuisongliu/feature/ssh

支持实时输出日志
parents 2968ef33 822f81cc
Showing with 389 additions and 67 deletions
+389 -67
......@@ -3,7 +3,7 @@ module github.com/fanux/sealos
go 1.13
require (
github.com/cuisongliu/sshcmd v0.0.0-20200324171807-1615e61773b1
github.com/cuisongliu/sshcmd v1.5.1
github.com/fanux/lvscare v0.0.0-00010101000000-000000000000
github.com/fanux/sealgate v0.0.5
github.com/mitchellh/go-homedir v1.1.0
......
......@@ -31,8 +31,8 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cuisongliu/sshcmd v0.0.0-20200324171807-1615e61773b1 h1:VhGG7tHUJ8sud9OgypR5VmiUrsWB+kq7h/ivOf1Tfyg=
github.com/cuisongliu/sshcmd v0.0.0-20200324171807-1615e61773b1/go.mod h1:jAEBZhFW5kNey9B+59lR8mfQaCQsyp8b8QaI7RhESxE=
github.com/cuisongliu/sshcmd v1.5.1 h1:Kj0CMKsSJ4WuBIYSviM46picbCc2/AJRtFBJM9yns+U=
github.com/cuisongliu/sshcmd v1.5.1/go.mod h1:8KeK/STl5TGGMBZrgfFwHOOMNbiwuGXdB9fx/pUD+/4=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
......@@ -274,8 +274,9 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
......
......@@ -110,7 +110,7 @@ func (s *SealosClean) cleanNode(node string) {
if len(MasterIPs) > 0 {
hostname := isHostName(MasterIPs[0], node)
cmd := "kubectl delete node %s"
SSHConfig.Cmd(MasterIPs[0], fmt.Sprintf(cmd, strings.TrimSpace(hostname)))
_ = SSHConfig.CmdAsync(MasterIPs[0], fmt.Sprintf(cmd, strings.TrimSpace(hostname)))
}
}
}
......@@ -124,7 +124,7 @@ func (s *SealosClean) cleanMaster(master string) {
if len(MasterIPs) > 0 {
hostname := isHostName(MasterIPs[0], master)
cmd := "kubectl delete node %s"
SSHConfig.Cmd(MasterIPs[0], fmt.Sprintf(cmd, strings.TrimSpace(hostname)))
_ = SSHConfig.CmdAsync(MasterIPs[0], fmt.Sprintf(cmd, strings.TrimSpace(hostname)))
}
//清空所有的nodes的数据
yaml := ipvs.LvsStaticPodYaml(VIP, MasterIPs, "")
......@@ -133,8 +133,8 @@ func (s *SealosClean) cleanMaster(master string) {
wg.Add(1)
go func(node string) {
defer wg.Done()
SSHConfig.Cmd(node, "rm -rf /etc/kubernetes/manifests/kube-sealyun-lvscare*")
SSHConfig.Cmd(node, "echo \""+yaml+"\" > /etc/kubernetes/manifests/kube-sealyun-lvscare.yaml")
_ = SSHConfig.CmdAsync(node, "rm -rf /etc/kubernetes/manifests/kube-sealyun-lvscare*")
_ = SSHConfig.CmdAsync(node, "echo \""+yaml+"\" > /etc/kubernetes/manifests/kube-sealyun-lvscare.yaml")
}(node)
}
wg.Wait()
......@@ -143,19 +143,19 @@ func (s *SealosClean) cleanMaster(master string) {
func clean(host string) {
cmd := "kubeadm reset -f && modprobe -r ipip && lsmod"
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
cmd = "rm -rf ~/.kube/ && rm -rf /etc/kubernetes/"
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
cmd = "rm -rf /etc/systemd/system/kubelet.service.d && rm -rf /etc/systemd/system/kubelet.service"
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
cmd = "rm -rf /usr/bin/kube* && rm -rf /usr/bin/crictl"
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
cmd = "rm -rf /etc/cni && rm -rf /opt/cni"
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
cmd = "rm -rf /var/lib/etcd && rm -rf /var/etcd"
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
cmd = fmt.Sprintf("sed -i \"/%s/d\" /etc/hosts ", ApiServer)
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
cmd = fmt.Sprint("rm -rf ~/kube")
SSHConfig.Cmd(host, cmd)
_ = SSHConfig.CmdAsync(host, cmd)
}
......@@ -26,7 +26,7 @@ func SendPackage(location string, hosts []string, dst, hook string) {
wm.Add(1)
go func(host string) {
defer wm.Done()
SSHConfig.Cmd(host, mkDstDir)
_ = SSHConfig.CmdAsync(host, mkDstDir)
logger.Debug("[%s]please wait for mkDstDir", host)
if SSHConfig.IsFilExist(host, fullPath) {
logger.Warn("[%s]SendPackage: file is exist", host)
......@@ -39,7 +39,7 @@ func SendPackage(location string, hosts []string, dst, hook string) {
}
if hook != "" {
logger.Debug("[%s]please wait for hook", host)
SSHConfig.Cmd(host, hook)
_ = SSHConfig.CmdAsync(host, hook)
}
}(host)
}
......
......@@ -58,13 +58,13 @@ func (s *SealosInstaller) KubeadmConfigInstall() {
templateData = string(TemplateFromTemplateContent(string(fileData)))
}
cmd := "echo \"" + templateData + "\" > /root/kubeadm-config.yaml"
SSHConfig.Cmd(s.Masters[0], cmd)
_ = SSHConfig.CmdAsync(s.Masters[0], cmd)
}
//InstallMaster0 is
func (s *SealosInstaller) InstallMaster0() {
cmd := fmt.Sprintf("echo %s %s >> /etc/hosts", IpFormat(s.Masters[0]), ApiServer)
SSHConfig.Cmd(s.Masters[0], cmd)
_ = SSHConfig.CmdAsync(s.Masters[0], cmd)
cmd = s.Command(Version, InitMaster)
......@@ -85,9 +85,9 @@ func (s *SealosInstaller) InstallMaster0() {
//cmd = `kubectl apply -f /root/kube/conf/net/calico.yaml || true`
netyaml := net.NewNetwork(Network, net.MetaData{
Interface: Interface,
CIDR: PodCIDR,
IPIP:IPIP,
MTU: MTU,
CIDR: PodCIDR,
IPIP: IPIP,
MTU: MTU,
}).Manifests("")
logger.Info("calico yaml is : \n", netyaml)
......
......@@ -196,5 +196,5 @@ func (r *RunOnMaster) Run(config SealConfig, url, pkgName string) {
func CmdWorkSpace(node, cmd, workdir string) {
command := fmt.Sprintf("cd %s && %s", workdir, cmd)
SSHConfig.Cmd(node, command)
_ = SSHConfig.CmdAsync(node, command)
}
......@@ -79,14 +79,14 @@ func (s *SealosInstaller) JoinMasters(masters []string) {
cmd := s.Command(Version, JoinMaster)
for _, master := range masters {
cmdHosts := fmt.Sprintf("echo %s %s >> /etc/hosts", IpFormat(s.Masters[0]), ApiServer)
SSHConfig.Cmd(master, cmdHosts)
SSHConfig.Cmd(master, cmd)
_ = SSHConfig.CmdAsync(master, cmdHosts)
_ = SSHConfig.CmdAsync(master, cmd)
cmdHosts = fmt.Sprintf(`sed "s/%s/%s/g" -i /etc/hosts`, IpFormat(s.Masters[0]), IpFormat(master))
SSHConfig.Cmd(master, cmdHosts)
_ = SSHConfig.CmdAsync(master, cmdHosts)
copyk8sConf := `mkdir -p /root/.kube && cp -i /etc/kubernetes/admin.conf /root/.kube/config`
SSHConfig.Cmd(master, copyk8sConf)
_ = SSHConfig.CmdAsync(master, copyk8sConf)
cleaninstall := `rm -rf /root/kube`
SSHConfig.Cmd(master, cleaninstall)
_ = SSHConfig.CmdAsync(master, cleaninstall)
}
}
......@@ -97,22 +97,22 @@ func (s *SealosInstaller) JoinNodes() {
for _, master := range s.Masters {
masters += fmt.Sprintf(" --rs %s:6443", IpFormat(master))
}
ipvsCmd := fmt.Sprintf("sealos ipvs --vs %s:6443 %s --health-path /healthz --health-schem https --run-once",VIP, masters)
ipvsCmd := fmt.Sprintf("sealos ipvs --vs %s:6443 %s --health-path /healthz --health-schem https --run-once", VIP, masters)
for _, node := range s.Nodes {
wg.Add(1)
go func(node string) {
defer wg.Done()
cmdHosts := fmt.Sprintf("echo %s %s >> /etc/hosts", VIP, ApiServer)
SSHConfig.Cmd(node, cmdHosts)
SSHConfig.Cmd(node,ipvsCmd) // create ipvs rules before we join node
_ = SSHConfig.CmdAsync(node, cmdHosts)
_ = SSHConfig.CmdAsync(node, ipvsCmd) // create ipvs rules before we join node
cmd := s.Command(Version, JoinNode)
//create lvscare static pod
yaml := ipvs.LvsStaticPodYaml(VIP,MasterIPs,"")
SSHConfig.Cmd(node,fmt.Sprintf("echo \"%s\" > /etc/kubernetes/manifests/kube-sealyun-lvscare.yaml", yaml))
SSHConfig.Cmd(node, cmd)
yaml := ipvs.LvsStaticPodYaml(VIP, MasterIPs, "")
_ = SSHConfig.CmdAsync(node, fmt.Sprintf("echo \"%s\" > /etc/kubernetes/manifests/kube-sealyun-lvscare.yaml", yaml))
_ = SSHConfig.CmdAsync(node, cmd)
cleaninstall := `rm -rf /root/kube`
SSHConfig.Cmd(node, cleaninstall)
_ = SSHConfig.CmdAsync(node, cleaninstall)
}(node)
}
......@@ -126,8 +126,8 @@ func (s *SealosInstaller) lvscare() {
go func(node string) {
defer wg.Done()
yaml := ipvs.LvsStaticPodYaml(VIP, MasterIPs, "")
SSHConfig.Cmd(node, "rm -rf /etc/kubernetes/manifests/kube-sealyun-lvscare*")
SSHConfig.Cmd(node, "echo \""+yaml+"\" > /etc/kubernetes/manifests/kube-sealyun-lvscare.yaml")
_ = SSHConfig.CmdAsync(node, "rm -rf /etc/kubernetes/manifests/kube-sealyun-lvscare*")
_ = SSHConfig.CmdAsync(node, "echo \""+yaml+"\" > /etc/kubernetes/manifests/kube-sealyun-lvscare.yaml")
}(node)
}
......
......@@ -16,7 +16,7 @@ func Cmd(name string, arg ...string) {
cmd.Stdout = os.Stdout
err := cmd.Run()
if err != nil {
logger.Error("os call error.", err)
logger.Error("[os]os call error.", err)
}
}
......@@ -30,7 +30,7 @@ func CmdToString(name string, arg ...string) string {
cmd.Stderr = &b
err := cmd.Run()
if err != nil {
logger.Error("os call error.", err)
logger.Error("[os]os call error.", err)
return ""
}
return b.String()
......
......@@ -27,7 +27,7 @@ func LoggerFileSize(filename string, size int) {
}
lengthFloat := float64(lengthByte)
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", lengthFloat/oneMBByte), 64)
logger.Alert("[%s]transfer total size is: %.2f%s", filename, value, "MB")
logger.Alert("[os][%s]transfer total size is: %.2f%s", filename, value, "MB")
}
}
}
......@@ -44,7 +44,7 @@ func IsFilExist(filepath string) bool {
count, err := strconv.Atoi(strings.TrimSpace(data))
defer func() {
if r := recover(); r != nil {
logger.Error("[%s]RemoteFilExist:%s", filepath, err)
logger.Error("[os][%s]RemoteFilExist:%s", filepath, err)
}
}()
if err != nil {
......
......@@ -19,17 +19,17 @@ func (ss *SSH) CopyForMD5(host, localFilePath, remoteFilePath, md5 string) bool
if md5 == "" {
md5 = md5sum.FromLocal(localFilePath)
}
logger.Debug("source file md5 value is %s", md5)
logger.Debug("[ssh]source file md5 value is %s", md5)
ss.Copy(host, localFilePath, remoteFilePath)
remoteMD5 := ss.Md5Sum(host, remoteFilePath)
logger.Debug("host: %s , remote md5: %s", host, remoteMD5)
logger.Debug("[ssh]host: %s , remote md5: %s", host, remoteMD5)
remoteMD5 = strings.TrimSpace(remoteMD5)
md5 = strings.TrimSpace(md5)
if remoteMD5 == md5 {
logger.Info("md5 validate true")
logger.Info("[ssh]md5 validate true")
return true
}
logger.Error("md5 validate false")
logger.Error("[ssh]md5 validate false")
return false
}
func (ss *SSH) Md5Sum(host, remoteFilePath string) string {
......@@ -43,7 +43,7 @@ func (ss *SSH) Copy(host, localFilePath, remoteFilePath string) {
sftpClient, err := ss.sftpConnect(host)
defer func() {
if r := recover(); r != nil {
logger.Error("[%s]scpCopy: %s", host, err)
logger.Error("[ssh][%s]scpCopy: %s", host, err)
}
}()
if err != nil {
......@@ -53,7 +53,7 @@ func (ss *SSH) Copy(host, localFilePath, remoteFilePath string) {
srcFile, err := os.Open(localFilePath)
defer func() {
if r := recover(); r != nil {
logger.Error("[%s]scpCopy: %s", host, err)
logger.Error("[ssh][%s]scpCopy: %s", host, err)
}
}()
if err != nil {
......@@ -64,7 +64,7 @@ func (ss *SSH) Copy(host, localFilePath, remoteFilePath string) {
dstFile, err := sftpClient.Create(remoteFilePath)
defer func() {
if r := recover(); r != nil {
logger.Error("[%s]scpCopy: %s", host, err)
logger.Error("[ssh][%s]scpCopy: %s", host, err)
}
}()
if err != nil {
......@@ -80,7 +80,7 @@ func (ss *SSH) Copy(host, localFilePath, remoteFilePath string) {
}
length, _ := dstFile.Write(buf[0:n])
totalMB += length / oneMBByte
logger.Alert("[%s]transfer total size is: %d%s", host, totalMB, "MB")
logger.Alert("[ssh][%s]transfer total size is: %d%s", host, totalMB, "MB")
}
}
......
package sshutil
import (
"bufio"
"github.com/wonderivan/logger"
"strings"
)
//Cmd is in host exec cmd
func (ss *SSH) Cmd(host string, cmd string) []byte {
logger.Info("[%s]exec cmd is : %s", host, cmd)
logger.Info("[ssh][%s]exec cmd is : %s", host, cmd)
session, err := ss.Connect(host)
defer func() {
if r := recover(); r != nil {
logger.Error("[%s]Error create ssh session failed,%s", host, err)
logger.Error("[ssh][%s]Error create ssh session failed,%s", host, err)
}
}()
if err != nil {
panic(1)
}
defer session.Close()
b, err := session.CombinedOutput(cmd)
logger.Debug("[%s]command result is: %s", host, string(b))
logger.Debug("[ssh][%s]command result is: %s", host, string(b))
defer func() {
if r := recover(); r != nil {
logger.Error("[%s]Error exec command failed: %s", host, err)
logger.Error("[ssh][%s]Error exec command failed: %s", host, err)
}
}()
if err != nil {
......@@ -32,6 +32,39 @@ func (ss *SSH) Cmd(host string, cmd string) []byte {
return b
}
func (ss *SSH) CmdAsync(host string, cmd string) error {
logger.Info("[ssh][%s]exec cmd is : %s", host, cmd)
session, err := ss.Connect(host)
if err != nil {
logger.Error("[ssh][%s]Error create ssh session failed,%s", host, err)
return err
}
defer session.Close()
stdout, err := session.StdoutPipe()
if err != nil {
logger.Error("[ssh][%s]Unable to request StdoutPipe(): %s", host, err)
return err
}
if err := session.Start(cmd); err != nil {
logger.Error("[ssh][%s]Unable to execute command: %s", host, err)
return err
}
done := make(chan bool, 1)
go func() {
for {
r := bufio.NewReader(stdout)
line, _, err := r.ReadLine()
if line == nil || err != nil {
done <- true
} else {
logger.Info("[ssh][%s]: %s", host, line)
}
}
}()
<-done
return nil
}
//CmdToString is in host exec cmd and replace to spilt str
func (ss *SSH) CmdToString(host, cmd, spilt string) string {
data := ss.Cmd(host, cmd)
......
package sshutil
import (
"bytes"
"fmt"
"github.com/wonderivan/logger"
"path"
......@@ -28,7 +27,7 @@ func (ss *SSH) LoggerFileSize(host, filename string, size int) {
}
lengthFloat := float64(lengthByte)
value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", lengthFloat/oneMBByte), 64)
logger.Alert("[%s]transfer total size is: %.2f%s", host, value, "MB")
logger.Alert("[ssh][%s]transfer total size is: %.2f%s", host, value, "MB")
}
}
}
......@@ -39,14 +38,15 @@ func (ss *SSH) IsFilExist(host, remoteFilePath string) bool {
// ls -l | grep aa | wc -l
remoteFileName := path.Base(remoteFilePath) // aa
remoteFileDirName := path.Dir(remoteFilePath)
remoteFileCommand := fmt.Sprintf("ls -l %s | grep %s | wc -l", remoteFileDirName, remoteFileName)
data := bytes.Replace(ss.Cmd(host, remoteFileCommand), []byte("\r"), []byte(""), -1)
data = bytes.Replace(data, []byte("\n"), []byte(""), -1)
//it's bug: if file is aa.bak, `ls -l | grep aa | wc -l` is 1 ,should use `ll aa 2>/dev/null |wc -l`
//remoteFileCommand := fmt.Sprintf("ls -l %s| grep %s | grep -v grep |wc -l", remoteFileDirName, remoteFileName)
remoteFileCommand := fmt.Sprintf("ls -l %s/%s 2>/dev/null |wc -l", remoteFileDirName, remoteFileName)
count, err := strconv.Atoi(string(data))
data := ss.CmdToString(host, remoteFileCommand, " ")
count, err := strconv.Atoi(strings.TrimSpace(data))
defer func() {
if r := recover(); r != nil {
logger.Error("[%s]RemoteFilExist:%s", host, err)
logger.Error("[ssh][%s]RemoteFilExist:%s", host, err)
}
}()
if err != nil {
......
......@@ -5,26 +5,56 @@
package cpu
import (
"encoding/binary"
"runtime"
)
// byteOrder is a subset of encoding/binary.ByteOrder.
type byteOrder interface {
Uint32([]byte) uint32
Uint64([]byte) uint64
}
type littleEndian struct{}
type bigEndian struct{}
func (littleEndian) Uint32(b []byte) uint32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
func (littleEndian) Uint64(b []byte) uint64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}
func (bigEndian) Uint32(b []byte) uint32 {
_ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
return uint32(b[3]) | uint32(b[2])<<8 | uint32(b[1])<<16 | uint32(b[0])<<24
}
func (bigEndian) Uint64(b []byte) uint64 {
_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808
return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
}
// hostByteOrder returns binary.LittleEndian on little-endian machines and
// binary.BigEndian on big-endian machines.
func hostByteOrder() binary.ByteOrder {
func hostByteOrder() byteOrder {
switch runtime.GOARCH {
case "386", "amd64", "amd64p32",
"arm", "arm64",
"mipsle", "mips64le", "mips64p32le",
"ppc64le",
"riscv", "riscv64":
return binary.LittleEndian
return littleEndian{}
case "armbe", "arm64be",
"mips", "mips64", "mips64p32",
"ppc", "ppc64",
"s390", "s390x",
"sparc", "sparc64":
return binary.BigEndian
return bigEndian{}
}
panic("unknown architecture")
}
......@@ -78,6 +78,42 @@ var ARM64 struct {
_ CacheLinePad
}
// ARM contains the supported CPU features of the current ARM (32-bit) platform.
// All feature flags are false if:
// 1. the current platform is not arm, or
// 2. the current operating system is not Linux.
var ARM struct {
_ CacheLinePad
HasSWP bool // SWP instruction support
HasHALF bool // Half-word load and store support
HasTHUMB bool // ARM Thumb instruction set
Has26BIT bool // Address space limited to 26-bits
HasFASTMUL bool // 32-bit operand, 64-bit result multiplication support
HasFPA bool // Floating point arithmetic support
HasVFP bool // Vector floating point support
HasEDSP bool // DSP Extensions support
HasJAVA bool // Java instruction set
HasIWMMXT bool // Intel Wireless MMX technology support
HasCRUNCH bool // MaverickCrunch context switching and handling
HasTHUMBEE bool // Thumb EE instruction set
HasNEON bool // NEON instruction set
HasVFPv3 bool // Vector floating point version 3 support
HasVFPv3D16 bool // Vector floating point version 3 D8-D15
HasTLS bool // Thread local storage support
HasVFPv4 bool // Vector floating point version 4 support
HasIDIVA bool // Integer divide instruction support in ARM mode
HasIDIVT bool // Integer divide instruction support in Thumb mode
HasVFPD32 bool // Vector floating point version 3 D15-D31
HasLPAE bool // Large Physical Address Extensions
HasEVTSTRM bool // Event stream support
HasAES bool // AES hardware implementation
HasPMULL bool // Polynomial multiplication instruction set
HasSHA1 bool // SHA1 hardware implementation
HasSHA2 bool // SHA2 hardware implementation
HasCRC32 bool // CRC32 hardware implementation
_ CacheLinePad
}
// PPC64 contains the supported CPU features of the current ppc64/ppc64le platforms.
// If the current platform is not ppc64/ppc64le then all feature flags are false.
//
......
......@@ -6,4 +6,35 @@ package cpu
const cacheLineSize = 32
func doinit() {}
// HWCAP/HWCAP2 bits.
// These are specific to Linux.
const (
hwcap_SWP = 1 << 0
hwcap_HALF = 1 << 1
hwcap_THUMB = 1 << 2
hwcap_26BIT = 1 << 3
hwcap_FAST_MULT = 1 << 4
hwcap_FPA = 1 << 5
hwcap_VFP = 1 << 6
hwcap_EDSP = 1 << 7
hwcap_JAVA = 1 << 8
hwcap_IWMMXT = 1 << 9
hwcap_CRUNCH = 1 << 10
hwcap_THUMBEE = 1 << 11
hwcap_NEON = 1 << 12
hwcap_VFPv3 = 1 << 13
hwcap_VFPv3D16 = 1 << 14
hwcap_TLS = 1 << 15
hwcap_VFPv4 = 1 << 16
hwcap_IDIVA = 1 << 17
hwcap_IDIVT = 1 << 18
hwcap_VFPD32 = 1 << 19
hwcap_LPAE = 1 << 20
hwcap_EVTSTRM = 1 << 21
hwcap2_AES = 1 << 0
hwcap2_PMULL = 1 << 1
hwcap2_SHA1 = 1 << 2
hwcap2_SHA2 = 1 << 3
hwcap2_CRC32 = 1 << 4
)
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cpu
import "runtime"
const cacheLineSize = 64
func init() {
switch runtime.GOOS {
case "android", "darwin":
// Android and iOS don't seem to allow reading these registers.
// Fake the minimal features expected by
// TestARM64minimalFeatures.
ARM64.HasASIMD = true
ARM64.HasFP = true
case "linux":
doinit()
default:
readARM64Registers()
}
}
func readARM64Registers() {
Initialized = true
// ID_AA64ISAR0_EL1
isar0 := getisar0()
switch extractBits(isar0, 4, 7) {
case 1:
ARM64.HasAES = true
case 2:
ARM64.HasAES = true
ARM64.HasPMULL = true
}
switch extractBits(isar0, 8, 11) {
case 1:
ARM64.HasSHA1 = true
}
switch extractBits(isar0, 12, 15) {
case 1:
ARM64.HasSHA2 = true
case 2:
ARM64.HasSHA2 = true
ARM64.HasSHA512 = true
}
switch extractBits(isar0, 16, 19) {
case 1:
ARM64.HasCRC32 = true
}
switch extractBits(isar0, 20, 23) {
case 2:
ARM64.HasATOMICS = true
}
switch extractBits(isar0, 28, 31) {
case 1:
ARM64.HasASIMDRDM = true
}
switch extractBits(isar0, 32, 35) {
case 1:
ARM64.HasSHA3 = true
}
switch extractBits(isar0, 36, 39) {
case 1:
ARM64.HasSM3 = true
}
switch extractBits(isar0, 40, 43) {
case 1:
ARM64.HasSM4 = true
}
switch extractBits(isar0, 44, 47) {
case 1:
ARM64.HasASIMDDP = true
}
// ID_AA64ISAR1_EL1
isar1 := getisar1()
switch extractBits(isar1, 0, 3) {
case 1:
ARM64.HasDCPOP = true
}
switch extractBits(isar1, 12, 15) {
case 1:
ARM64.HasJSCVT = true
}
switch extractBits(isar1, 16, 19) {
case 1:
ARM64.HasFCMA = true
}
switch extractBits(isar1, 20, 23) {
case 1:
ARM64.HasLRCPC = true
}
// ID_AA64PFR0_EL1
pfr0 := getpfr0()
switch extractBits(pfr0, 16, 19) {
case 0:
ARM64.HasFP = true
case 1:
ARM64.HasFP = true
ARM64.HasFPHP = true
}
switch extractBits(pfr0, 20, 23) {
case 0:
ARM64.HasASIMD = true
case 1:
ARM64.HasASIMD = true
ARM64.HasASIMDHP = true
}
switch extractBits(pfr0, 32, 35) {
case 1:
ARM64.HasSVE = true
}
}
func extractBits(data uint64, start, end uint) uint {
return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
}
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo
#include "textflag.h"
// func getisar0() uint64
TEXT ·getisar0(SB),NOSPLIT,$0-8
// get Instruction Set Attributes 0 into x0
// mrs x0, ID_AA64ISAR0_EL1 = d5380600
WORD $0xd5380600
MOVD R0, ret+0(FP)
RET
// func getisar1() uint64
TEXT ·getisar1(SB),NOSPLIT,$0-8
// get Instruction Set Attributes 1 into x0
// mrs x0, ID_AA64ISAR1_EL1 = d5380620
WORD $0xd5380620
MOVD R0, ret+0(FP)
RET
// func getpfr0() uint64
TEXT ·getpfr0(SB),NOSPLIT,$0-8
// get Processor Feature Register 0 into x0
// mrs x0, ID_AA64PFR0_EL1 = d5380400
WORD $0xd5380400
MOVD R0, ret+0(FP)
RET
// Copyright 2018 The Go Authors. All rights reserved.
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "textflag.h"
// +build !gccgo
TEXT ·getprocaddress(SB),NOSPLIT,$0
B syscall·getprocaddress(SB)
package cpu
TEXT ·loadlibrary(SB),NOSPLIT,$0
B syscall·loadlibrary(SB)
func getisar0() uint64
func getisar1() uint64
func getpfr0() uint64
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build gccgo
package cpu
func getisar0() uint64 { return 0 }
func getisar1() uint64 { return 0 }
func getpfr0() uint64 { return 0 }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment