@ -0,0 +1,22 @@ | |||
// Copyright 2019 The Gitea Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package integrations | |||
import ( | |||
"net/http" | |||
"testing" | |||
"github.com/stretchr/testify/assert" | |||
) | |||
func TestCORSNotSet(t *testing.T) { | |||
prepareTestEnv(t) | |||
req := NewRequestf(t, "GET", "/api/v1/version") | |||
session := loginUser(t, "user2") | |||
resp := session.MakeRequest(t, req, http.StatusOK) | |||
assert.Equal(t, resp.Code, http.StatusOK) | |||
corsHeader := resp.Header().Get("Access-Control-Allow-Origin") | |||
assert.Equal(t, corsHeader, "", "Access-Control-Allow-Origin: generated header should match") // header not set | |||
} |
@ -0,0 +1,41 @@ | |||
// Copyright 2019 The Gitea Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package setting | |||
import ( | |||
"time" | |||
"code.gitea.io/gitea/modules/log" | |||
"github.com/go-macaron/cors" | |||
) | |||
var ( | |||
// CORSConfig defines CORS settings | |||
CORSConfig cors.Options | |||
// EnableCORS defines whether CORS settings is enabled or not | |||
EnableCORS bool | |||
) | |||
func newCORSService() { | |||
sec := Cfg.Section("cors") | |||
// Check cors setting. | |||
EnableCORS = sec.Key("ENABLED").MustBool(false) | |||
maxAge := sec.Key("MAX_AGE").MustDuration(10 * time.Minute) | |||
CORSConfig = cors.Options{ | |||
Scheme: sec.Key("SCHEME").String(), | |||
AllowDomain: sec.Key("ALLOW_DOMAIN").String(), | |||
AllowSubdomain: sec.Key("ALLOW_SUBDOMAIN").MustBool(), | |||
Methods: sec.Key("METHODS").Strings(","), | |||
MaxAgeSeconds: int(maxAge.Seconds()), | |||
AllowCredentials: sec.Key("ALLOW_CREDENTIALS").MustBool(), | |||
} | |||
if EnableCORS { | |||
log.Info("CORS Service Enabled") | |||
} | |||
} |
@ -0,0 +1,8 @@ | |||
module github.com/Unknwon/com | |||
require ( | |||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect | |||
github.com/jtolds/gls v4.2.1+incompatible // indirect | |||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 // indirect | |||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c | |||
) |
@ -0,0 +1,8 @@ | |||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= | |||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | |||
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= | |||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | |||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= | |||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | |||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= | |||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= |
@ -0,0 +1,12 @@ | |||
# Binaries for programs and plugins | |||
*.exe | |||
*.exe~ | |||
*.dll | |||
*.so | |||
*.dylib | |||
# Test binary, build with `go test -c` | |||
*.test | |||
# Output of the go coverage tool, specifically when used with LiteIDE | |||
*.out |
@ -0,0 +1,201 @@ | |||
Apache License | |||
Version 2.0, January 2004 | |||
http://www.apache.org/licenses/ | |||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |||
1. Definitions. | |||
"License" shall mean the terms and conditions for use, reproduction, | |||
and distribution as defined by Sections 1 through 9 of this document. | |||
"Licensor" shall mean the copyright owner or entity authorized by | |||
the copyright owner that is granting the License. | |||
"Legal Entity" shall mean the union of the acting entity and all | |||
other entities that control, are controlled by, or are under common | |||
control with that entity. For the purposes of this definition, | |||
"control" means (i) the power, direct or indirect, to cause the | |||
direction or management of such entity, whether by contract or | |||
otherwise, or (ii) ownership of fifty percent (50%) or more of the | |||
outstanding shares, or (iii) beneficial ownership of such entity. | |||
"You" (or "Your") shall mean an individual or Legal Entity | |||
exercising permissions granted by this License. | |||
"Source" form shall mean the preferred form for making modifications, | |||
including but not limited to software source code, documentation | |||
source, and configuration files. | |||
"Object" form shall mean any form resulting from mechanical | |||
transformation or translation of a Source form, including but | |||
not limited to compiled object code, generated documentation, | |||
and conversions to other media types. | |||
"Work" shall mean the work of authorship, whether in Source or | |||
Object form, made available under the License, as indicated by a | |||
copyright notice that is included in or attached to the work | |||
(an example is provided in the Appendix below). | |||
"Derivative Works" shall mean any work, whether in Source or Object | |||
form, that is based on (or derived from) the Work and for which the | |||
editorial revisions, annotations, elaborations, or other modifications | |||
represent, as a whole, an original work of authorship. For the purposes | |||
of this License, Derivative Works shall not include works that remain | |||
separable from, or merely link (or bind by name) to the interfaces of, | |||
the Work and Derivative Works thereof. | |||
"Contribution" shall mean any work of authorship, including | |||
the original version of the Work and any modifications or additions | |||
to that Work or Derivative Works thereof, that is intentionally | |||
submitted to Licensor for inclusion in the Work by the copyright owner | |||
or by an individual or Legal Entity authorized to submit on behalf of | |||
the copyright owner. For the purposes of this definition, "submitted" | |||
means any form of electronic, verbal, or written communication sent | |||
to the Licensor or its representatives, including but not limited to | |||
communication on electronic mailing lists, source code control systems, | |||
and issue tracking systems that are managed by, or on behalf of, the | |||
Licensor for the purpose of discussing and improving the Work, but | |||
excluding communication that is conspicuously marked or otherwise | |||
designated in writing by the copyright owner as "Not a Contribution." | |||
"Contributor" shall mean Licensor and any individual or Legal Entity | |||
on behalf of whom a Contribution has been received by Licensor and | |||
subsequently incorporated within the Work. | |||
2. Grant of Copyright License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
copyright license to reproduce, prepare Derivative Works of, | |||
publicly display, publicly perform, sublicense, and distribute the | |||
Work and such Derivative Works in Source or Object form. | |||
3. Grant of Patent License. Subject to the terms and conditions of | |||
this License, each Contributor hereby grants to You a perpetual, | |||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |||
(except as stated in this section) patent license to make, have made, | |||
use, offer to sell, sell, import, and otherwise transfer the Work, | |||
where such license applies only to those patent claims licensable | |||
by such Contributor that are necessarily infringed by their | |||
Contribution(s) alone or by combination of their Contribution(s) | |||
with the Work to which such Contribution(s) was submitted. If You | |||
institute patent litigation against any entity (including a | |||
cross-claim or counterclaim in a lawsuit) alleging that the Work | |||
or a Contribution incorporated within the Work constitutes direct | |||
or contributory patent infringement, then any patent licenses | |||
granted to You under this License for that Work shall terminate | |||
as of the date such litigation is filed. | |||
4. Redistribution. You may reproduce and distribute copies of the | |||
Work or Derivative Works thereof in any medium, with or without | |||
modifications, and in Source or Object form, provided that You | |||
meet the following conditions: | |||
(a) You must give any other recipients of the Work or | |||
Derivative Works a copy of this License; and | |||
(b) You must cause any modified files to carry prominent notices | |||
stating that You changed the files; and | |||
(c) You must retain, in the Source form of any Derivative Works | |||
that You distribute, all copyright, patent, trademark, and | |||
attribution notices from the Source form of the Work, | |||
excluding those notices that do not pertain to any part of | |||
the Derivative Works; and | |||
(d) If the Work includes a "NOTICE" text file as part of its | |||
distribution, then any Derivative Works that You distribute must | |||
include a readable copy of the attribution notices contained | |||
within such NOTICE file, excluding those notices that do not | |||
pertain to any part of the Derivative Works, in at least one | |||
of the following places: within a NOTICE text file distributed | |||
as part of the Derivative Works; within the Source form or | |||
documentation, if provided along with the Derivative Works; or, | |||
within a display generated by the Derivative Works, if and | |||
wherever such third-party notices normally appear. The contents | |||
of the NOTICE file are for informational purposes only and | |||
do not modify the License. You may add Your own attribution | |||
notices within Derivative Works that You distribute, alongside | |||
or as an addendum to the NOTICE text from the Work, provided | |||
that such additional attribution notices cannot be construed | |||
as modifying the License. | |||
You may add Your own copyright statement to Your modifications and | |||
may provide additional or different license terms and conditions | |||
for use, reproduction, or distribution of Your modifications, or | |||
for any such Derivative Works as a whole, provided Your use, | |||
reproduction, and distribution of the Work otherwise complies with | |||
the conditions stated in this License. | |||
5. Submission of Contributions. Unless You explicitly state otherwise, | |||
any Contribution intentionally submitted for inclusion in the Work | |||
by You to the Licensor shall be under the terms and conditions of | |||
this License, without any additional terms or conditions. | |||
Notwithstanding the above, nothing herein shall supersede or modify | |||
the terms of any separate license agreement you may have executed | |||
with Licensor regarding such Contributions. | |||
6. Trademarks. This License does not grant permission to use the trade | |||
names, trademarks, service marks, or product names of the Licensor, | |||
except as required for reasonable and customary use in describing the | |||
origin of the Work and reproducing the content of the NOTICE file. | |||
7. Disclaimer of Warranty. Unless required by applicable law or | |||
agreed to in writing, Licensor provides the Work (and each | |||
Contributor provides its Contributions) on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |||
implied, including, without limitation, any warranties or conditions | |||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |||
PARTICULAR PURPOSE. You are solely responsible for determining the | |||
appropriateness of using or redistributing the Work and assume any | |||
risks associated with Your exercise of permissions under this License. | |||
8. Limitation of Liability. In no event and under no legal theory, | |||
whether in tort (including negligence), contract, or otherwise, | |||
unless required by applicable law (such as deliberate and grossly | |||
negligent acts) or agreed to in writing, shall any Contributor be | |||
liable to You for damages, including any direct, indirect, special, | |||
incidental, or consequential damages of any character arising as a | |||
result of this License or out of the use or inability to use the | |||
Work (including but not limited to damages for loss of goodwill, | |||
work stoppage, computer failure or malfunction, or any and all | |||
other commercial damages or losses), even if such Contributor | |||
has been advised of the possibility of such damages. | |||
9. Accepting Warranty or Additional Liability. While redistributing | |||
the Work or Derivative Works thereof, You may choose to offer, | |||
and charge a fee for, acceptance of support, warranty, indemnity, | |||
or other liability obligations and/or rights consistent with this | |||
License. However, in accepting such obligations, You may act only | |||
on Your own behalf and on Your sole responsibility, not on behalf | |||
of any other Contributor, and only if You agree to indemnify, | |||
defend, and hold each Contributor harmless for any liability | |||
incurred by, or claims asserted against, such Contributor by reason | |||
of your accepting any such warranty or additional liability. | |||
END OF TERMS AND CONDITIONS | |||
APPENDIX: How to apply the Apache License to your work. | |||
To apply the Apache License to your work, attach the following | |||
boilerplate notice, with the fields enclosed by brackets "[]" | |||
replaced with your own identifying information. (Don't include | |||
the brackets!) The text should be enclosed in the appropriate | |||
comment syntax for the file format. We also recommend that a | |||
file or class name and description of purpose be included on the | |||
same "printed page" as the copyright notice for easier | |||
identification within third-party archives. | |||
Copyright [yyyy] [name of copyright owner] | |||
Licensed under the Apache License, Version 2.0 (the "License"); | |||
you may not use this file except in compliance with the License. | |||
You may obtain a copy of the License at | |||
http://www.apache.org/licenses/LICENSE-2.0 | |||
Unless required by applicable law or agreed to in writing, software | |||
distributed under the License is distributed on an "AS IS" BASIS, | |||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
See the License for the specific language governing permissions and | |||
limitations under the License. |
@ -0,0 +1,2 @@ | |||
# cors | |||
Package cors is a middleware that handles CORS requests & headers for Macaron. |
@ -0,0 +1,139 @@ | |||
package cors | |||
import ( | |||
"fmt" | |||
"log" | |||
"net/http" | |||
"net/url" | |||
"strconv" | |||
"strings" | |||
macaron "gopkg.in/macaron.v1" | |||
) | |||
const _VERSION = "0.1.0" | |||
func Version() string { | |||
return _VERSION | |||
} | |||
// Options represents a struct for specifying configuration options for the CORS middleware. | |||
type Options struct { | |||
Section string | |||
Scheme string | |||
AllowDomain string | |||
AllowSubdomain bool | |||
Methods []string | |||
MaxAgeSeconds int | |||
AllowCredentials bool | |||
} | |||
func prepareOptions(options []Options) Options { | |||
var opt Options | |||
if len(options) > 0 { | |||
opt = options[0] | |||
} | |||
if len(opt.Section) == 0 { | |||
opt.Section = "cors" | |||
} | |||
sec := macaron.Config().Section(opt.Section) | |||
if len(opt.Scheme) == 0 { | |||
opt.Scheme = sec.Key("SCHEME").MustString("http") | |||
} | |||
if len(opt.AllowDomain) == 0 { | |||
opt.AllowDomain = sec.Key("ALLOW_DOMAIN").MustString("*") | |||
} | |||
if !opt.AllowSubdomain { | |||
opt.AllowSubdomain = sec.Key("ALLOW_SUBDOMAIN").MustBool(false) | |||
} | |||
if len(opt.Methods) == 0 { | |||
opt.Methods = sec.Key("METHODS").Strings(",") | |||
if len(opt.Methods) == 0 { | |||
opt.Methods = []string{ | |||
http.MethodGet, | |||
http.MethodHead, | |||
http.MethodPost, | |||
http.MethodPut, | |||
http.MethodPatch, | |||
http.MethodDelete, | |||
http.MethodOptions, | |||
} | |||
} | |||
} | |||
if opt.MaxAgeSeconds <= 0 { | |||
// cache options response for 600 secs | |||
// ref: https://stackoverflow.com/questions/54300997/is-it-possible-to-cache-http-options-response?noredirect=1#comment95790277_54300997 | |||
// ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age | |||
opt.MaxAgeSeconds = sec.Key("MAX_AGE_SECONDS").MustInt(600) | |||
} | |||
if !opt.AllowCredentials { | |||
opt.AllowCredentials = sec.Key("ALLOW_CREDENTIALS").MustBool(true) | |||
} | |||
return opt | |||
} | |||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin | |||
// https://fetch.spec.whatwg.org/#cors-protocol-and-credentials | |||
// For requests without credentials, the server may specify "*" as a wildcard, thereby allowing any origin to access the resource. | |||
func CORS(options ...Options) macaron.Handler { | |||
opt := prepareOptions(options) | |||
return func(ctx *macaron.Context, log *log.Logger) { | |||
reqOptions := ctx.Req.Method == http.MethodOptions | |||
headers := map[string]string{ | |||
"access-control-allow-methods": strings.Join(opt.Methods, ","), | |||
"access-control-allow-headers": ctx.Req.Header.Get("access-control-request-headers"), | |||
"access-control-max-age": strconv.Itoa(opt.MaxAgeSeconds), | |||
} | |||
if opt.AllowDomain == "*" { | |||
headers["access-control-allow-origin"] = "*" | |||
} else if opt.AllowDomain != "" { | |||
origin := ctx.Req.Header.Get("Origin") | |||
if reqOptions && origin == "" { | |||
respErrorf(ctx, log, http.StatusBadRequest, "missing origin header in CORS request") | |||
return | |||
} | |||
u, err := url.Parse(origin) | |||
if err != nil { | |||
respErrorf(ctx, log, http.StatusBadRequest, "Failed to parse CORS origin header. Reason: %v", err) | |||
return | |||
} | |||
ok := u.Hostname() == opt.AllowDomain || | |||
(opt.AllowSubdomain && strings.HasSuffix(u.Hostname(), "."+opt.AllowDomain)) | |||
if ok { | |||
u.Scheme = opt.Scheme | |||
headers["access-control-allow-origin"] = u.String() | |||
headers["access-control-allow-credentials"] = strconv.FormatBool(opt.AllowCredentials) | |||
headers["vary"] = "Origin" | |||
} | |||
if reqOptions && !ok { | |||
respErrorf(ctx, log, http.StatusBadRequest, "CORS request from prohibited domain %v", origin) | |||
return | |||
} | |||
} | |||
ctx.Resp.Before(func(w macaron.ResponseWriter) { | |||
for k, v := range headers { | |||
w.Header().Set(k, v) | |||
} | |||
}) | |||
if reqOptions { | |||
ctx.Status(200) // return response | |||
} | |||
} | |||
} | |||
func respErrorf(ctx *macaron.Context, log *log.Logger, statusCode int, format string, a ...interface{}) { | |||
msg := fmt.Sprintf(format, a...) | |||
log.Println(msg) | |||
ctx.WriteHeader(statusCode) | |||
_, err := ctx.Write([]byte(msg)) | |||
if err != nil { | |||
panic(err) | |||
} | |||
return | |||
} |
@ -0,0 +1,11 @@ | |||
module github.com/go-macaron/cors | |||
go 1.12 | |||
require ( | |||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755 // indirect | |||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 // indirect | |||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 // indirect | |||
gopkg.in/ini.v1 v1.42.0 // indirect | |||
gopkg.in/macaron.v1 v1.3.2 | |||
) |
@ -0,0 +1,19 @@ | |||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755 h1:1B7wb36fHLSwZfHg6ngZhhtIEHQjiC5H4p7qQGBEffg= | |||
github.com/Unknwon/com v0.0.0-20190321035513-0fed4efef755/go.mod h1:voKvFVpXBJxdIPeqjoJuLK+UVcRlo/JLjeToGxPYu68= | |||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191 h1:NjHlg70DuOkcAMqgt0+XA+NHwtu66MkTVVgR4fFWbcI= | |||
github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191/go.mod h1:VFI2o2q9kYsC4o7VP1HrEVosiZZTd+MVT3YZx4gqvJw= | |||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= | |||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | |||
github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= | |||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | |||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY= | |||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | |||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpkel/udgjbwB5Lktg9BtvJSh2DT0Hi6LPSyI2w= | |||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= | |||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk= | |||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= | |||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||
gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk= | |||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= | |||
gopkg.in/macaron.v1 v1.3.2 h1:AvWIaPmwBUA87/OWzePkoxeaw6YJWDfBt1pDFPBnLf8= | |||
gopkg.in/macaron.v1 v1.3.2/go.mod h1:PrsiawTWAGZs6wFbT5hlr7SQ2Ns9h7cUVtcUu4lQOVo= |
@ -0,0 +1,308 @@ | |||
// Copyright 2018 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 go1.11 | |||
// +build !gccgo,!appengine | |||
#include "textflag.h" | |||
#define NUM_ROUNDS 10 | |||
// func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) | |||
TEXT ·xorKeyStreamVX(SB), NOSPLIT, $0 | |||
MOVD dst+0(FP), R1 | |||
MOVD src+24(FP), R2 | |||
MOVD src_len+32(FP), R3 | |||
MOVD key+48(FP), R4 | |||
MOVD nonce+56(FP), R6 | |||
MOVD counter+64(FP), R7 | |||
MOVD $·constants(SB), R10 | |||
MOVD $·incRotMatrix(SB), R11 | |||
MOVW (R7), R20 | |||
AND $~255, R3, R13 | |||
ADD R2, R13, R12 // R12 for block end | |||
AND $255, R3, R13 | |||
loop: | |||
MOVD $NUM_ROUNDS, R21 | |||
VLD1 (R11), [V30.S4, V31.S4] | |||
// load contants | |||
// VLD4R (R10), [V0.S4, V1.S4, V2.S4, V3.S4] | |||
WORD $0x4D60E940 | |||
// load keys | |||
// VLD4R 16(R4), [V4.S4, V5.S4, V6.S4, V7.S4] | |||
WORD $0x4DFFE884 | |||
// VLD4R 16(R4), [V8.S4, V9.S4, V10.S4, V11.S4] | |||
WORD $0x4DFFE888 | |||
SUB $32, R4 | |||
// load counter + nonce | |||
// VLD1R (R7), [V12.S4] | |||
WORD $0x4D40C8EC | |||
// VLD3R (R6), [V13.S4, V14.S4, V15.S4] | |||
WORD $0x4D40E8CD | |||
// update counter | |||
VADD V30.S4, V12.S4, V12.S4 | |||
chacha: | |||
// V0..V3 += V4..V7 | |||
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 16) | |||
VADD V0.S4, V4.S4, V0.S4 | |||
VADD V1.S4, V5.S4, V1.S4 | |||
VADD V2.S4, V6.S4, V2.S4 | |||
VADD V3.S4, V7.S4, V3.S4 | |||
VEOR V12.B16, V0.B16, V12.B16 | |||
VEOR V13.B16, V1.B16, V13.B16 | |||
VEOR V14.B16, V2.B16, V14.B16 | |||
VEOR V15.B16, V3.B16, V15.B16 | |||
VREV32 V12.H8, V12.H8 | |||
VREV32 V13.H8, V13.H8 | |||
VREV32 V14.H8, V14.H8 | |||
VREV32 V15.H8, V15.H8 | |||
// V8..V11 += V12..V15 | |||
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 12) | |||
VADD V8.S4, V12.S4, V8.S4 | |||
VADD V9.S4, V13.S4, V9.S4 | |||
VADD V10.S4, V14.S4, V10.S4 | |||
VADD V11.S4, V15.S4, V11.S4 | |||
VEOR V8.B16, V4.B16, V16.B16 | |||
VEOR V9.B16, V5.B16, V17.B16 | |||
VEOR V10.B16, V6.B16, V18.B16 | |||
VEOR V11.B16, V7.B16, V19.B16 | |||
VSHL $12, V16.S4, V4.S4 | |||
VSHL $12, V17.S4, V5.S4 | |||
VSHL $12, V18.S4, V6.S4 | |||
VSHL $12, V19.S4, V7.S4 | |||
VSRI $20, V16.S4, V4.S4 | |||
VSRI $20, V17.S4, V5.S4 | |||
VSRI $20, V18.S4, V6.S4 | |||
VSRI $20, V19.S4, V7.S4 | |||
// V0..V3 += V4..V7 | |||
// V12..V15 <<<= ((V12..V15 XOR V0..V3), 8) | |||
VADD V0.S4, V4.S4, V0.S4 | |||
VADD V1.S4, V5.S4, V1.S4 | |||
VADD V2.S4, V6.S4, V2.S4 | |||
VADD V3.S4, V7.S4, V3.S4 | |||
VEOR V12.B16, V0.B16, V12.B16 | |||
VEOR V13.B16, V1.B16, V13.B16 | |||
VEOR V14.B16, V2.B16, V14.B16 | |||
VEOR V15.B16, V3.B16, V15.B16 | |||
VTBL V31.B16, [V12.B16], V12.B16 | |||
VTBL V31.B16, [V13.B16], V13.B16 | |||
VTBL V31.B16, [V14.B16], V14.B16 | |||
VTBL V31.B16, [V15.B16], V15.B16 | |||
// V8..V11 += V12..V15 | |||
// V4..V7 <<<= ((V4..V7 XOR V8..V11), 7) | |||
VADD V12.S4, V8.S4, V8.S4 | |||
VADD V13.S4, V9.S4, V9.S4 | |||
VADD V14.S4, V10.S4, V10.S4 | |||
VADD V15.S4, V11.S4, V11.S4 | |||
VEOR V8.B16, V4.B16, V16.B16 | |||
VEOR V9.B16, V5.B16, V17.B16 | |||
VEOR V10.B16, V6.B16, V18.B16 | |||
VEOR V11.B16, V7.B16, V19.B16 | |||
VSHL $7, V16.S4, V4.S4 | |||
VSHL $7, V17.S4, V5.S4 | |||
VSHL $7, V18.S4, V6.S4 | |||
VSHL $7, V19.S4, V7.S4 | |||
VSRI $25, V16.S4, V4.S4 | |||
VSRI $25, V17.S4, V5.S4 | |||
VSRI $25, V18.S4, V6.S4 | |||
VSRI $25, V19.S4, V7.S4 | |||
// V0..V3 += V5..V7, V4 | |||
// V15,V12-V14 <<<= ((V15,V12-V14 XOR V0..V3), 16) | |||
VADD V0.S4, V5.S4, V0.S4 | |||
VADD V1.S4, V6.S4, V1.S4 | |||
VADD V2.S4, V7.S4, V2.S4 | |||
VADD V3.S4, V4.S4, V3.S4 | |||
VEOR V15.B16, V0.B16, V15.B16 | |||
VEOR V12.B16, V1.B16, V12.B16 | |||
VEOR V13.B16, V2.B16, V13.B16 | |||
VEOR V14.B16, V3.B16, V14.B16 | |||
VREV32 V12.H8, V12.H8 | |||
VREV32 V13.H8, V13.H8 | |||
VREV32 V14.H8, V14.H8 | |||
VREV32 V15.H8, V15.H8 | |||
// V10 += V15; V5 <<<= ((V10 XOR V5), 12) | |||
// ... | |||
VADD V15.S4, V10.S4, V10.S4 | |||
VADD V12.S4, V11.S4, V11.S4 | |||
VADD V13.S4, V8.S4, V8.S4 | |||
VADD V14.S4, V9.S4, V9.S4 | |||
VEOR V10.B16, V5.B16, V16.B16 | |||
VEOR V11.B16, V6.B16, V17.B16 | |||
VEOR V8.B16, V7.B16, V18.B16 | |||
VEOR V9.B16, V4.B16, V19.B16 | |||
VSHL $12, V16.S4, V5.S4 | |||
VSHL $12, V17.S4, V6.S4 | |||
VSHL $12, V18.S4, V7.S4 | |||
VSHL $12, V19.S4, V4.S4 | |||
VSRI $20, V16.S4, V5.S4 | |||
VSRI $20, V17.S4, V6.S4 | |||
VSRI $20, V18.S4, V7.S4 | |||
VSRI $20, V19.S4, V4.S4 | |||
// V0 += V5; V15 <<<= ((V0 XOR V15), 8) | |||
// ... | |||
VADD V5.S4, V0.S4, V0.S4 | |||
VADD V6.S4, V1.S4, V1.S4 | |||
VADD V7.S4, V2.S4, V2.S4 | |||
VADD V4.S4, V3.S4, V3.S4 | |||
VEOR V0.B16, V15.B16, V15.B16 | |||
VEOR V1.B16, V12.B16, V12.B16 | |||
VEOR V2.B16, V13.B16, V13.B16 | |||
VEOR V3.B16, V14.B16, V14.B16 | |||
VTBL V31.B16, [V12.B16], V12.B16 | |||
VTBL V31.B16, [V13.B16], V13.B16 | |||
VTBL V31.B16, [V14.B16], V14.B16 | |||
VTBL V31.B16, [V15.B16], V15.B16 | |||
// V10 += V15; V5 <<<= ((V10 XOR V5), 7) | |||
// ... | |||
VADD V15.S4, V10.S4, V10.S4 | |||
VADD V12.S4, V11.S4, V11.S4 | |||
VADD V13.S4, V8.S4, V8.S4 | |||
VADD V14.S4, V9.S4, V9.S4 | |||
VEOR V10.B16, V5.B16, V16.B16 | |||
VEOR V11.B16, V6.B16, V17.B16 | |||
VEOR V8.B16, V7.B16, V18.B16 | |||
VEOR V9.B16, V4.B16, V19.B16 | |||
VSHL $7, V16.S4, V5.S4 | |||
VSHL $7, V17.S4, V6.S4 | |||
VSHL $7, V18.S4, V7.S4 | |||
VSHL $7, V19.S4, V4.S4 | |||
VSRI $25, V16.S4, V5.S4 | |||
VSRI $25, V17.S4, V6.S4 | |||
VSRI $25, V18.S4, V7.S4 | |||
VSRI $25, V19.S4, V4.S4 | |||
SUB $1, R21 | |||
CBNZ R21, chacha | |||
// VLD4R (R10), [V16.S4, V17.S4, V18.S4, V19.S4] | |||
WORD $0x4D60E950 | |||
// VLD4R 16(R4), [V20.S4, V21.S4, V22.S4, V23.S4] | |||
WORD $0x4DFFE894 | |||
VADD V30.S4, V12.S4, V12.S4 | |||
VADD V16.S4, V0.S4, V0.S4 | |||
VADD V17.S4, V1.S4, V1.S4 | |||
VADD V18.S4, V2.S4, V2.S4 | |||
VADD V19.S4, V3.S4, V3.S4 | |||
// VLD4R 16(R4), [V24.S4, V25.S4, V26.S4, V27.S4] | |||
WORD $0x4DFFE898 | |||
// restore R4 | |||
SUB $32, R4 | |||
// load counter + nonce | |||
// VLD1R (R7), [V28.S4] | |||
WORD $0x4D40C8FC | |||
// VLD3R (R6), [V29.S4, V30.S4, V31.S4] | |||
WORD $0x4D40E8DD | |||
VADD V20.S4, V4.S4, V4.S4 | |||
VADD V21.S4, V5.S4, V5.S4 | |||
VADD V22.S4, V6.S4, V6.S4 | |||
VADD V23.S4, V7.S4, V7.S4 | |||
VADD V24.S4, V8.S4, V8.S4 | |||
VADD V25.S4, V9.S4, V9.S4 | |||
VADD V26.S4, V10.S4, V10.S4 | |||
VADD V27.S4, V11.S4, V11.S4 | |||
VADD V28.S4, V12.S4, V12.S4 | |||
VADD V29.S4, V13.S4, V13.S4 | |||
VADD V30.S4, V14.S4, V14.S4 | |||
VADD V31.S4, V15.S4, V15.S4 | |||
VZIP1 V1.S4, V0.S4, V16.S4 | |||
VZIP2 V1.S4, V0.S4, V17.S4 | |||
VZIP1 V3.S4, V2.S4, V18.S4 | |||
VZIP2 V3.S4, V2.S4, V19.S4 | |||
VZIP1 V5.S4, V4.S4, V20.S4 | |||
VZIP2 V5.S4, V4.S4, V21.S4 | |||
VZIP1 V7.S4, V6.S4, V22.S4 | |||
VZIP2 V7.S4, V6.S4, V23.S4 | |||
VZIP1 V9.S4, V8.S4, V24.S4 | |||
VZIP2 V9.S4, V8.S4, V25.S4 | |||
VZIP1 V11.S4, V10.S4, V26.S4 | |||
VZIP2 V11.S4, V10.S4, V27.S4 | |||
VZIP1 V13.S4, V12.S4, V28.S4 | |||
VZIP2 V13.S4, V12.S4, V29.S4 | |||
VZIP1 V15.S4, V14.S4, V30.S4 | |||
VZIP2 V15.S4, V14.S4, V31.S4 | |||
VZIP1 V18.D2, V16.D2, V0.D2 | |||
VZIP2 V18.D2, V16.D2, V4.D2 | |||
VZIP1 V19.D2, V17.D2, V8.D2 | |||
VZIP2 V19.D2, V17.D2, V12.D2 | |||
VLD1.P 64(R2), [V16.B16, V17.B16, V18.B16, V19.B16] | |||
VZIP1 V22.D2, V20.D2, V1.D2 | |||
VZIP2 V22.D2, V20.D2, V5.D2 | |||
VZIP1 V23.D2, V21.D2, V9.D2 | |||
VZIP2 V23.D2, V21.D2, V13.D2 | |||
VLD1.P 64(R2), [V20.B16, V21.B16, V22.B16, V23.B16] | |||
VZIP1 V26.D2, V24.D2, V2.D2 | |||
VZIP2 V26.D2, V24.D2, V6.D2 | |||
VZIP1 V27.D2, V25.D2, V10.D2 | |||
VZIP2 V27.D2, V25.D2, V14.D2 | |||
VLD1.P 64(R2), [V24.B16, V25.B16, V26.B16, V27.B16] | |||
VZIP1 V30.D2, V28.D2, V3.D2 | |||
VZIP2 V30.D2, V28.D2, V7.D2 | |||
VZIP1 V31.D2, V29.D2, V11.D2 | |||
VZIP2 V31.D2, V29.D2, V15.D2 | |||
VLD1.P 64(R2), [V28.B16, V29.B16, V30.B16, V31.B16] | |||
VEOR V0.B16, V16.B16, V16.B16 | |||
VEOR V1.B16, V17.B16, V17.B16 | |||
VEOR V2.B16, V18.B16, V18.B16 | |||
VEOR V3.B16, V19.B16, V19.B16 | |||
VST1.P [V16.B16, V17.B16, V18.B16, V19.B16], 64(R1) | |||
VEOR V4.B16, V20.B16, V20.B16 | |||
VEOR V5.B16, V21.B16, V21.B16 | |||
VEOR V6.B16, V22.B16, V22.B16 | |||
VEOR V7.B16, V23.B16, V23.B16 | |||
VST1.P [V20.B16, V21.B16, V22.B16, V23.B16], 64(R1) | |||
VEOR V8.B16, V24.B16, V24.B16 | |||
VEOR V9.B16, V25.B16, V25.B16 | |||
VEOR V10.B16, V26.B16, V26.B16 | |||
VEOR V11.B16, V27.B16, V27.B16 | |||
VST1.P [V24.B16, V25.B16, V26.B16, V27.B16], 64(R1) | |||
VEOR V12.B16, V28.B16, V28.B16 | |||
VEOR V13.B16, V29.B16, V29.B16 | |||
VEOR V14.B16, V30.B16, V30.B16 | |||
VEOR V15.B16, V31.B16, V31.B16 | |||
VST1.P [V28.B16, V29.B16, V30.B16, V31.B16], 64(R1) | |||
ADD $4, R20 | |||
MOVW R20, (R7) // update counter | |||
CMP R2, R12 | |||
BGT loop | |||
RET | |||
DATA ·constants+0x00(SB)/4, $0x61707865 | |||
DATA ·constants+0x04(SB)/4, $0x3320646e | |||
DATA ·constants+0x08(SB)/4, $0x79622d32 | |||
DATA ·constants+0x0c(SB)/4, $0x6b206574 | |||
GLOBL ·constants(SB), NOPTR|RODATA, $32 | |||
DATA ·incRotMatrix+0x00(SB)/4, $0x00000000 | |||
DATA ·incRotMatrix+0x04(SB)/4, $0x00000001 | |||
DATA ·incRotMatrix+0x08(SB)/4, $0x00000002 | |||
DATA ·incRotMatrix+0x0c(SB)/4, $0x00000003 | |||
DATA ·incRotMatrix+0x10(SB)/4, $0x02010003 | |||
DATA ·incRotMatrix+0x14(SB)/4, $0x06050407 | |||
DATA ·incRotMatrix+0x18(SB)/4, $0x0A09080B | |||
DATA ·incRotMatrix+0x1c(SB)/4, $0x0E0D0C0F | |||
GLOBL ·incRotMatrix(SB), NOPTR|RODATA, $32 |
@ -0,0 +1,31 @@ | |||
// Copyright 2018 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 go1.11 | |||
// +build !gccgo | |||
package chacha20 | |||
const ( | |||
haveAsm = true | |||
bufSize = 256 | |||
) | |||
//go:noescape | |||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32) | |||
func (c *Cipher) xorKeyStreamAsm(dst, src []byte) { | |||
if len(src) >= bufSize { | |||
xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter) | |||
} | |||
if len(src)%bufSize != 0 { | |||
i := len(src) - len(src)%bufSize | |||
c.buf = [bufSize]byte{} | |||
copy(c.buf[:], src[i:]) | |||
xorKeyStreamVX(c.buf[:], c.buf[:], &c.key, &c.nonce, &c.counter) | |||
c.len = bufSize - copy(dst[i:], c.buf[:len(src)%bufSize]) | |||
} | |||
} |
@ -0,0 +1,11 @@ | |||
// Copyright 2018 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 !amd64 gccgo appengine | |||
package poly1305 | |||
type mac struct{ macGeneric } | |||
func newMAC(key *[32]byte) mac { return mac{newMACGeneric(key)} } |
@ -0,0 +1,30 @@ | |||
// 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 ( | |||
"encoding/binary" | |||
"runtime" | |||
) | |||
// hostByteOrder returns binary.LittleEndian on little-endian machines and | |||
// binary.BigEndian on big-endian machines. | |||
func hostByteOrder() binary.ByteOrder { | |||
switch runtime.GOARCH { | |||
case "386", "amd64", "amd64p32", | |||
"arm", "arm64", | |||
"mipsle", "mips64le", "mips64p32le", | |||
"ppc64le", | |||
"riscv", "riscv64": | |||
return binary.LittleEndian | |||
case "armbe", "arm64be", | |||
"mips", "mips64", "mips64p32", | |||
"ppc", "ppc64", | |||
"s390", "s390x", | |||
"sparc", "sparc64": | |||
return binary.BigEndian | |||
} | |||
panic("unknown architecture") | |||
} |
@ -0,0 +1,126 @@ | |||
// Copyright 2018 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 implements processor feature detection for | |||
// various CPU architectures. | |||
package cpu | |||
// Initialized reports whether the CPU features were initialized. | |||
// | |||
// For some GOOS/GOARCH combinations initialization of the CPU features depends | |||
// on reading an operating specific file, e.g. /proc/self/auxv on linux/arm | |||
// Initialized will report false if reading the file fails. | |||
var Initialized bool | |||
// CacheLinePad is used to pad structs to avoid false sharing. | |||
type CacheLinePad struct{ _ [cacheLineSize]byte } | |||
// X86 contains the supported CPU features of the | |||
// current X86/AMD64 platform. If the current platform | |||
// is not X86/AMD64 then all feature flags are false. | |||
// | |||
// X86 is padded to avoid false sharing. Further the HasAVX | |||
// and HasAVX2 are only set if the OS supports XMM and YMM | |||
// registers in addition to the CPUID feature bit being set. | |||
var X86 struct { | |||
_ CacheLinePad | |||
HasAES bool // AES hardware implementation (AES NI) | |||
HasADX bool // Multi-precision add-carry instruction extensions | |||
HasAVX bool // Advanced vector extension | |||
HasAVX2 bool // Advanced vector extension 2 | |||
HasBMI1 bool // Bit manipulation instruction set 1 | |||
HasBMI2 bool // Bit manipulation instruction set 2 | |||
HasERMS bool // Enhanced REP for MOVSB and STOSB | |||
HasFMA bool // Fused-multiply-add instructions | |||
HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. | |||
HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM | |||
HasPOPCNT bool // Hamming weight instruction POPCNT. | |||
HasRDRAND bool // RDRAND instruction (on-chip random number generator) | |||
HasRDSEED bool // RDSEED instruction (on-chip random number generator) | |||
HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) | |||
HasSSE3 bool // Streaming SIMD extension 3 | |||
HasSSSE3 bool // Supplemental streaming SIMD extension 3 | |||
HasSSE41 bool // Streaming SIMD extension 4 and 4.1 | |||
HasSSE42 bool // Streaming SIMD extension 4 and 4.2 | |||
_ CacheLinePad | |||
} | |||
// ARM64 contains the supported CPU features of the | |||
// current ARMv8(aarch64) platform. If the current platform | |||
// is not arm64 then all feature flags are false. | |||
var ARM64 struct { | |||
_ CacheLinePad | |||
HasFP bool // Floating-point instruction set (always available) | |||
HasASIMD bool // Advanced SIMD (always available) | |||
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 | |||
HasATOMICS bool // Atomic memory operation instruction set | |||
HasFPHP bool // Half precision floating-point instruction set | |||
HasASIMDHP bool // Advanced SIMD half precision instruction set | |||
HasCPUID bool // CPUID identification scheme registers | |||
HasASIMDRDM bool // Rounding double multiply add/subtract instruction set | |||
HasJSCVT bool // Javascript conversion from floating-point to integer | |||
HasFCMA bool // Floating-point multiplication and addition of complex numbers | |||
HasLRCPC bool // Release Consistent processor consistent support | |||
HasDCPOP bool // Persistent memory support | |||
HasSHA3 bool // SHA3 hardware implementation | |||
HasSM3 bool // SM3 hardware implementation | |||
HasSM4 bool // SM4 hardware implementation | |||
HasASIMDDP bool // Advanced SIMD double precision instruction set | |||
HasSHA512 bool // SHA512 hardware implementation | |||
HasSVE bool // Scalable Vector Extensions | |||
HasASIMDFHM bool // Advanced SIMD multiplication FP16 to FP32 | |||
_ 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. | |||
// | |||
// For ppc64/ppc64le, it is safe to check only for ISA level starting on ISA v3.00, | |||
// since there are no optional categories. There are some exceptions that also | |||
// require kernel support to work (DARN, SCV), so there are feature bits for | |||
// those as well. The minimum processor requirement is POWER8 (ISA 2.07). | |||
// The struct is padded to avoid false sharing. | |||
var PPC64 struct { | |||
_ CacheLinePad | |||
HasDARN bool // Hardware random number generator (requires kernel enablement) | |||
HasSCV bool // Syscall vectored (requires kernel enablement) | |||
IsPOWER8 bool // ISA v2.07 (POWER8) | |||
IsPOWER9 bool // ISA v3.00 (POWER9) | |||
_ CacheLinePad | |||
} | |||
// S390X contains the supported CPU features of the current IBM Z | |||
// (s390x) platform. If the current platform is not IBM Z then all | |||
// feature flags are false. | |||
// | |||
// S390X is padded to avoid false sharing. Further HasVX is only set | |||
// if the OS supports vector registers in addition to the STFLE | |||
// feature bit being set. | |||
var S390X struct { | |||
_ CacheLinePad | |||
HasZARCH bool // z/Architecture mode is active [mandatory] | |||
HasSTFLE bool // store facility list extended | |||
HasLDISP bool // long (20-bit) displacements | |||
HasEIMM bool // 32-bit immediates | |||
HasDFP bool // decimal floating point | |||
HasETF3EH bool // ETF-3 enhanced | |||
HasMSA bool // message security assist (CPACF) | |||
HasAES bool // KM-AES{128,192,256} functions | |||
HasAESCBC bool // KMC-AES{128,192,256} functions | |||
HasAESCTR bool // KMCTR-AES{128,192,256} functions | |||
HasAESGCM bool // KMA-GCM-AES{128,192,256} functions | |||
HasGHASH bool // KIMD-GHASH function | |||
HasSHA1 bool // K{I,L}MD-SHA-1 functions | |||
HasSHA256 bool // K{I,L}MD-SHA-256 functions | |||
HasSHA512 bool // K{I,L}MD-SHA-512 functions | |||
HasSHA3 bool // K{I,L}MD-SHA3-{224,256,384,512} and K{I,L}MD-SHAKE-{128,256} functions | |||
HasVX bool // vector facility | |||
HasVXE bool // vector-enhancements facility 1 | |||
_ CacheLinePad | |||
} |
@ -0,0 +1,30 @@ | |||
// 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 aix,ppc64 | |||
package cpu | |||
import "golang.org/x/sys/unix" | |||
const cacheLineSize = 128 | |||
const ( | |||
// getsystemcfg constants | |||
_SC_IMPL = 2 | |||
_IMPL_POWER8 = 0x10000 | |||
_IMPL_POWER9 = 0x20000 | |||
) | |||
func init() { | |||
impl := unix.Getsystemcfg(_SC_IMPL) | |||
if impl&_IMPL_POWER8 != 0 { | |||
PPC64.IsPOWER8 = true | |||
} | |||
if impl&_IMPL_POWER9 != 0 { | |||
PPC64.IsPOWER9 = true | |||
} | |||
Initialized = true | |||
} |
@ -0,0 +1,9 @@ | |||
// Copyright 2018 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 | |||
const cacheLineSize = 32 | |||
func doinit() {} |
@ -0,0 +1,21 @@ | |||
// 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 | |||
// haveAsmFunctions reports whether the other functions in this file can | |||
// be safely called. | |||
func haveAsmFunctions() bool { return true } | |||
// The following feature detection functions are defined in cpu_s390x.s. | |||
// They are likely to be expensive to call so the results should be cached. | |||
func stfle() facilityList | |||
func kmQuery() queryResult | |||
func kmcQuery() queryResult | |||
func kmctrQuery() queryResult | |||
func kmaQuery() queryResult | |||
func kimdQuery() queryResult | |||
func klmdQuery() queryResult |
@ -0,0 +1,16 @@ | |||
// Copyright 2018 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 386 amd64 amd64p32 | |||
// +build !gccgo | |||
package cpu | |||
// cpuid is implemented in cpu_x86.s for gc compiler | |||
// and in cpu_gccgo.c for gccgo. | |||
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) | |||
// xgetbv with ecx = 0 is implemented in cpu_x86.s for gc compiler | |||
// and in cpu_gccgo.c for gccgo. | |||
func xgetbv() (eax, edx uint32) |
@ -0,0 +1,43 @@ | |||
// Copyright 2018 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 386 amd64 amd64p32 | |||
// +build gccgo | |||
#include <cpuid.h> | |||
#include <stdint.h> | |||
// Need to wrap __get_cpuid_count because it's declared as static. | |||
int | |||
gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, | |||
uint32_t *eax, uint32_t *ebx, | |||
uint32_t *ecx, uint32_t *edx) | |||
{ | |||
return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); | |||
} | |||
// xgetbv reads the contents of an XCR (Extended Control Register) | |||
// specified in the ECX register into registers EDX:EAX. | |||
// Currently, the only supported value for XCR is 0. | |||
// | |||
// TODO: Replace with a better alternative: | |||
// | |||
// #include <xsaveintrin.h> | |||
// | |||
// #pragma GCC target("xsave") | |||
// | |||
// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { | |||
// unsigned long long x = _xgetbv(0); | |||
// *eax = x & 0xffffffff; | |||
// *edx = (x >> 32) & 0xffffffff; | |||
// } | |||
// | |||
// Note that _xgetbv is defined starting with GCC 8. | |||
void | |||
gccgoXgetbv(uint32_t *eax, uint32_t *edx) | |||
{ | |||
__asm(" xorl %%ecx, %%ecx\n" | |||
" xgetbv" | |||
: "=a"(*eax), "=d"(*edx)); | |||
} |
@ -0,0 +1,26 @@ | |||
// Copyright 2018 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 386 amd64 amd64p32 | |||
// +build gccgo | |||
package cpu | |||
//extern gccgoGetCpuidCount | |||
func gccgoGetCpuidCount(eaxArg, ecxArg uint32, eax, ebx, ecx, edx *uint32) | |||
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) { | |||
var a, b, c, d uint32 | |||
gccgoGetCpuidCount(eaxArg, ecxArg, &a, &b, &c, &d) | |||
return a, b, c, d | |||
} | |||
//extern gccgoXgetbv | |||
func gccgoXgetbv(eax, edx *uint32) | |||
func xgetbv() (eax, edx uint32) { | |||
var a, d uint32 | |||
gccgoXgetbv(&a, &d) | |||
return a, d | |||
} |
@ -0,0 +1,22 @@ | |||
// 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 | |||
// haveAsmFunctions reports whether the other functions in this file can | |||
// be safely called. | |||
func haveAsmFunctions() bool { return false } | |||
// TODO(mundaym): the following feature detection functions are currently | |||
// stubs. See https://golang.org/cl/162887 for how to fix this. | |||
// They are likely to be expensive to call so the results should be cached. | |||
func stfle() facilityList { panic("not implemented for gccgo") } | |||
func kmQuery() queryResult { panic("not implemented for gccgo") } | |||
func kmcQuery() queryResult { panic("not implemented for gccgo") } | |||
func kmctrQuery() queryResult { panic("not implemented for gccgo") } | |||
func kmaQuery() queryResult { panic("not implemented for gccgo") } | |||
func kimdQuery() queryResult { panic("not implemented for gccgo") } | |||
func klmdQuery() queryResult { panic("not implemented for gccgo") } |
@ -0,0 +1,59 @@ | |||
// Copyright 2018 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 !amd64,!amd64p32,!386 | |||
package cpu | |||
import ( | |||
"io/ioutil" | |||
) | |||
const ( | |||
_AT_HWCAP = 16 | |||
_AT_HWCAP2 = 26 | |||
procAuxv = "/proc/self/auxv" | |||
uintSize = int(32 << (^uint(0) >> 63)) | |||
) | |||
// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2 | |||
// These are initialized in cpu_$GOARCH.go | |||
// and should not be changed after they are initialized. | |||
var hwCap uint | |||
var hwCap2 uint | |||
func init() { | |||
buf, err := ioutil.ReadFile(procAuxv) | |||
if err != nil { | |||
// e.g. on android /proc/self/auxv is not accessible, so silently | |||
// ignore the error and leave Initialized = false | |||
return | |||
} | |||
bo := hostByteOrder() | |||
for len(buf) >= 2*(uintSize/8) { | |||
var tag, val uint | |||
switch uintSize { | |||
case 32: | |||
tag = uint(bo.Uint32(buf[0:])) | |||
val = uint(bo.Uint32(buf[4:])) | |||
buf = buf[8:] | |||
case 64: | |||
tag = uint(bo.Uint64(buf[0:])) | |||
val = uint(bo.Uint64(buf[8:])) | |||
buf = buf[16:] | |||
} | |||
switch tag { | |||
case _AT_HWCAP: | |||
hwCap = val | |||
case _AT_HWCAP2: | |||
hwCap2 = val | |||
} | |||
} | |||
doinit() | |||
Initialized = true | |||
} |
@ -0,0 +1,67 @@ | |||
// Copyright 2018 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 | |||
const cacheLineSize = 64 | |||
// HWCAP/HWCAP2 bits. These are exposed by Linux. | |||
const ( | |||
hwcap_FP = 1 << 0 | |||
hwcap_ASIMD = 1 << 1 | |||
hwcap_EVTSTRM = 1 << 2 | |||
hwcap_AES = 1 << 3 | |||
hwcap_PMULL = 1 << 4 | |||
hwcap_SHA1 = 1 << 5 | |||
hwcap_SHA2 = 1 << 6 | |||
hwcap_CRC32 = 1 << 7 | |||
hwcap_ATOMICS = 1 << 8 | |||
hwcap_FPHP = 1 << 9 | |||
hwcap_ASIMDHP = 1 << 10 | |||
hwcap_CPUID = 1 << 11 | |||
hwcap_ASIMDRDM = 1 << 12 | |||
hwcap_JSCVT = 1 << 13 | |||
hwcap_FCMA = 1 << 14 | |||
hwcap_LRCPC = 1 << 15 | |||
hwcap_DCPOP = 1 << 16 | |||
hwcap_SHA3 = 1 << 17 | |||
hwcap_SM3 = 1 << 18 | |||
hwcap_SM4 = 1 << 19 | |||
hwcap_ASIMDDP = 1 << 20 | |||
hwcap_SHA512 = 1 << 21 | |||
hwcap_SVE = 1 << 22 | |||
hwcap_ASIMDFHM = 1 << 23 | |||
) | |||
func doinit() { | |||
// HWCAP feature bits | |||
ARM64.HasFP = isSet(hwCap, hwcap_FP) | |||
ARM64.HasASIMD = isSet(hwCap, hwcap_ASIMD) | |||
ARM64.HasEVTSTRM = isSet(hwCap, hwcap_EVTSTRM) | |||
ARM64.HasAES = isSet(hwCap, hwcap_AES) | |||
ARM64.HasPMULL = isSet(hwCap, hwcap_PMULL) | |||
ARM64.HasSHA1 = isSet(hwCap, hwcap_SHA1) | |||
ARM64.HasSHA2 = isSet(hwCap, hwcap_SHA2) | |||
ARM64.HasCRC32 = isSet(hwCap, hwcap_CRC32) | |||
ARM64.HasATOMICS = isSet(hwCap, hwcap_ATOMICS) | |||
ARM64.HasFPHP = isSet(hwCap, hwcap_FPHP) | |||
ARM64.HasASIMDHP = isSet(hwCap, hwcap_ASIMDHP) | |||
ARM64.HasCPUID = isSet(hwCap, hwcap_CPUID) | |||
ARM64.HasASIMDRDM = isSet(hwCap, hwcap_ASIMDRDM) | |||
ARM64.HasJSCVT = isSet(hwCap, hwcap_JSCVT) | |||
ARM64.HasFCMA = isSet(hwCap, hwcap_FCMA) | |||
ARM64.HasLRCPC = isSet(hwCap, hwcap_LRCPC) | |||
ARM64.HasDCPOP = isSet(hwCap, hwcap_DCPOP) | |||
ARM64.HasSHA3 = isSet(hwCap, hwcap_SHA3) | |||
ARM64.HasSM3 = isSet(hwCap, hwcap_SM3) | |||
ARM64.HasSM4 = isSet(hwCap, hwcap_SM4) | |||
ARM64.HasASIMDDP = isSet(hwCap, hwcap_ASIMDDP) | |||
ARM64.HasSHA512 = isSet(hwCap, hwcap_SHA512) | |||
ARM64.HasSVE = isSet(hwCap, hwcap_SVE) | |||
ARM64.HasASIMDFHM = isSet(hwCap, hwcap_ASIMDFHM) | |||
} | |||
func isSet(hwc uint, value uint) bool { | |||
return hwc&value != 0 | |||
} |
@ -0,0 +1,33 @@ | |||
// Copyright 2018 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 linux | |||
// +build ppc64 ppc64le | |||
package cpu | |||
const cacheLineSize = 128 | |||
// HWCAP/HWCAP2 bits. These are exposed by the kernel. | |||
const ( | |||
// ISA Level | |||
_PPC_FEATURE2_ARCH_2_07 = 0x80000000 | |||
_PPC_FEATURE2_ARCH_3_00 = 0x00800000 | |||
// CPU features | |||
_PPC_FEATURE2_DARN = 0x00200000 | |||
_PPC_FEATURE2_SCV = 0x00100000 | |||
) | |||
func doinit() { | |||
// HWCAP2 feature bits | |||
PPC64.IsPOWER8 = isSet(hwCap2, _PPC_FEATURE2_ARCH_2_07) | |||
PPC64.IsPOWER9 = isSet(hwCap2, _PPC_FEATURE2_ARCH_3_00) | |||
PPC64.HasDARN = isSet(hwCap2, _PPC_FEATURE2_DARN) | |||
PPC64.HasSCV = isSet(hwCap2, _PPC_FEATURE2_SCV) | |||
} | |||
func isSet(hwc uint, value uint) bool { | |||
return hwc&value != 0 | |||
} |
@ -0,0 +1,161 @@ | |||
// 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 | |||
const cacheLineSize = 256 | |||
const ( | |||
// bit mask values from /usr/include/bits/hwcap.h | |||
hwcap_ZARCH = 2 | |||
hwcap_STFLE = 4 | |||
hwcap_MSA = 8 | |||
hwcap_LDISP = 16 | |||
hwcap_EIMM = 32 | |||
hwcap_DFP = 64 | |||
hwcap_ETF3EH = 256 | |||
hwcap_VX = 2048 | |||
hwcap_VXE = 8192 | |||
) | |||
// bitIsSet reports whether the bit at index is set. The bit index | |||
// is in big endian order, so bit index 0 is the leftmost bit. | |||
func bitIsSet(bits []uint64, index uint) bool { | |||
return bits[index/64]&((1<<63)>>(index%64)) != 0 | |||
} | |||
// function is the code for the named cryptographic function. | |||
type function uint8 | |||
const ( | |||
// KM{,A,C,CTR} function codes | |||
aes128 function = 18 // AES-128 | |||
aes192 function = 19 // AES-192 | |||
aes256 function = 20 // AES-256 | |||
// K{I,L}MD function codes | |||
sha1 function = 1 // SHA-1 | |||
sha256 function = 2 // SHA-256 | |||
sha512 function = 3 // SHA-512 | |||
sha3_224 function = 32 // SHA3-224 | |||
sha3_256 function = 33 // SHA3-256 | |||
sha3_384 function = 34 // SHA3-384 | |||
sha3_512 function = 35 // SHA3-512 | |||
shake128 function = 36 // SHAKE-128 | |||
shake256 function = 37 // SHAKE-256 | |||
// KLMD function codes | |||
ghash function = 65 // GHASH | |||
) | |||
// queryResult contains the result of a Query function | |||
// call. Bits are numbered in big endian order so the | |||
// leftmost bit (the MSB) is at index 0. | |||
type queryResult struct { | |||
bits [2]uint64 | |||
} | |||
// Has reports whether the given functions are present. | |||
func (q *queryResult) Has(fns ...function) bool { | |||
if len(fns) == 0 { | |||
panic("no function codes provided") | |||
} | |||
for _, f := range fns { | |||
if !bitIsSet(q.bits[:], uint(f)) { | |||
return false | |||
} | |||
} | |||
return true | |||
} | |||
// facility is a bit index for the named facility. | |||
type facility uint8 | |||
const ( | |||
// cryptography facilities | |||
msa4 facility = 77 // message-security-assist extension 4 | |||
msa8 facility = 146 // message-security-assist extension 8 | |||
) | |||
// facilityList contains the result of an STFLE call. | |||
// Bits are numbered in big endian order so the | |||
// leftmost bit (the MSB) is at index 0. | |||
type facilityList struct { | |||
bits [4]uint64 | |||
} | |||
// Has reports whether the given facilities are present. | |||
func (s *facilityList) Has(fs ...facility) bool { | |||
if len(fs) == 0 { | |||
panic("no facility bits provided") | |||
} | |||
for _, f := range fs { | |||
if !bitIsSet(s.bits[:], uint(f)) { | |||
return false | |||
} | |||
} | |||
return true | |||
} | |||
func doinit() { | |||
// test HWCAP bit vector | |||
has := func(featureMask uint) bool { | |||
return hwCap&featureMask == featureMask | |||
} | |||
// mandatory | |||
S390X.HasZARCH = has(hwcap_ZARCH) | |||
// optional | |||
S390X.HasSTFLE = has(hwcap_STFLE) | |||
S390X.HasLDISP = has(hwcap_LDISP) | |||
S390X.HasEIMM = has(hwcap_EIMM) | |||
S390X.HasETF3EH = has(hwcap_ETF3EH) | |||
S390X.HasDFP = has(hwcap_DFP) | |||
S390X.HasMSA = has(hwcap_MSA) | |||
S390X.HasVX = has(hwcap_VX) | |||
if S390X.HasVX { | |||
S390X.HasVXE = has(hwcap_VXE) | |||
} | |||
// We need implementations of stfle, km and so on | |||
// to detect cryptographic features. | |||
if !haveAsmFunctions() { | |||
return | |||
} | |||
// optional cryptographic functions | |||
if S390X.HasMSA { | |||
aes := []function{aes128, aes192, aes256} | |||
// cipher message | |||
km, kmc := kmQuery(), kmcQuery() | |||
S390X.HasAES = km.Has(aes...) | |||
S390X.HasAESCBC = kmc.Has(aes...) | |||
if S390X.HasSTFLE { | |||
facilities := stfle() | |||
if facilities.Has(msa4) { | |||
kmctr := kmctrQuery() | |||
S390X.HasAESCTR = kmctr.Has(aes...) | |||
} | |||
if facilities.Has(msa8) { | |||
kma := kmaQuery() | |||
S390X.HasAESGCM = kma.Has(aes...) | |||
} | |||
} | |||
// compute message digest | |||
kimd := kimdQuery() // intermediate (no padding) | |||
klmd := klmdQuery() // last (padding) | |||
S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) | |||
S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) | |||
S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) | |||
S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist | |||
sha3 := []function{ | |||
sha3_224, sha3_256, sha3_384, sha3_512, | |||
shake128, shake256, | |||
} | |||
S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) | |||
} | |||
} |
@ -0,0 +1,11 @@ | |||
// Copyright 2018 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 mips64 mips64le | |||
package cpu | |||
const cacheLineSize = 32 | |||
func doinit() {} |
@ -0,0 +1,11 @@ | |||
// Copyright 2018 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 mips mipsle | |||
package cpu | |||
const cacheLineSize = 32 | |||
func doinit() {} |
@ -0,0 +1,11 @@ | |||
// 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 !linux,arm64 | |||
package cpu | |||
const cacheLineSize = 64 | |||
func doinit() {} |
@ -0,0 +1,57 @@ | |||
// 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 stfle() facilityList | |||
TEXT ·stfle(SB), NOSPLIT|NOFRAME, $0-32 | |||
MOVD $ret+0(FP), R1 | |||
MOVD $3, R0 // last doubleword index to store | |||
XC $32, (R1), (R1) // clear 4 doublewords (32 bytes) | |||
WORD $0xb2b01000 // store facility list extended (STFLE) | |||
RET | |||
// func kmQuery() queryResult | |||
TEXT ·kmQuery(SB), NOSPLIT|NOFRAME, $0-16 | |||
MOVD $0, R0 // set function code to 0 (KM-Query) | |||
MOVD $ret+0(FP), R1 // address of 16-byte return value | |||
WORD $0xB92E0024 // cipher message (KM) | |||
RET | |||
// func kmcQuery() queryResult | |||
TEXT ·kmcQuery(SB), NOSPLIT|NOFRAME, $0-16 | |||
MOVD $0, R0 // set function code to 0 (KMC-Query) | |||
MOVD $ret+0(FP), R1 // address of 16-byte return value | |||
WORD $0xB92F0024 // cipher message with chaining (KMC) | |||
RET | |||
// func kmctrQuery() queryResult | |||
TEXT ·kmctrQuery(SB), NOSPLIT|NOFRAME, $0-16 | |||
MOVD $0, R0 // set function code to 0 (KMCTR-Query) | |||
MOVD $ret+0(FP), R1 // address of 16-byte return value | |||
WORD $0xB92D4024 // cipher message with counter (KMCTR) | |||
RET | |||
// func kmaQuery() queryResult | |||
TEXT ·kmaQuery(SB), NOSPLIT|NOFRAME, $0-16 | |||
MOVD $0, R0 // set function code to 0 (KMA-Query) | |||
MOVD $ret+0(FP), R1 // address of 16-byte return value | |||
WORD $0xb9296024 // cipher message with authentication (KMA) | |||
RET | |||
// func kimdQuery() queryResult | |||
TEXT ·kimdQuery(SB), NOSPLIT|NOFRAME, $0-16 | |||
MOVD $0, R0 // set function code to 0 (KIMD-Query) | |||
MOVD $ret+0(FP), R1 // address of 16-byte return value | |||
WORD $0xB93E0024 // compute intermediate message digest (KIMD) | |||
RET | |||
// func klmdQuery() queryResult | |||
TEXT ·klmdQuery(SB), NOSPLIT|NOFRAME, $0-16 | |||
MOVD $0, R0 // set function code to 0 (KLMD-Query) | |||
MOVD $ret+0(FP), R1 // address of 16-byte return value | |||
WORD $0xB93F0024 // compute last message digest (KLMD) | |||
RET |
@ -0,0 +1,15 @@ | |||
// 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 wasm | |||
package cpu | |||
// We're compiling the cpu package for an unknown (software-abstracted) CPU. | |||
// Make CacheLinePad an empty struct and hope that the usual struct alignment | |||
// rules are good enough. | |||
const cacheLineSize = 0 | |||
func doinit() {} |
@ -0,0 +1,59 @@ | |||
// Copyright 2018 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 386 amd64 amd64p32 | |||
package cpu | |||
const cacheLineSize = 64 | |||
func init() { | |||
Initialized = true | |||
maxID, _, _, _ := cpuid(0, 0) | |||
if maxID < 1 { | |||
return | |||
} | |||
_, _, ecx1, edx1 := cpuid(1, 0) | |||
X86.HasSSE2 = isSet(26, edx1) | |||
X86.HasSSE3 = isSet(0, ecx1) | |||
X86.HasPCLMULQDQ = isSet(1, ecx1) | |||
X86.HasSSSE3 = isSet(9, ecx1) | |||
X86.HasFMA = isSet(12, ecx1) | |||
X86.HasSSE41 = isSet(19, ecx1) | |||
X86.HasSSE42 = isSet(20, ecx1) | |||
X86.HasPOPCNT = isSet(23, ecx1) | |||
X86.HasAES = isSet(25, ecx1) | |||
X86.HasOSXSAVE = isSet(27, ecx1) | |||
X86.HasRDRAND = isSet(30, ecx1) | |||
osSupportsAVX := false | |||
// For XGETBV, OSXSAVE bit is required and sufficient. | |||
if X86.HasOSXSAVE { | |||
eax, _ := xgetbv() | |||
// Check if XMM and YMM registers have OS support. | |||
osSupportsAVX = isSet(1, eax) && isSet(2, eax) | |||
} | |||
X86.HasAVX = isSet(28, ecx1) && osSupportsAVX | |||
if maxID < 7 { | |||
return | |||
} | |||
_, ebx7, _, _ := cpuid(7, 0) | |||
X86.HasBMI1 = isSet(3, ebx7) | |||
X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX | |||
X86.HasBMI2 = isSet(8, ebx7) | |||
X86.HasERMS = isSet(9, ebx7) | |||
X86.HasRDSEED = isSet(18, ebx7) | |||
X86.HasADX = isSet(19, ebx7) | |||
} | |||
func isSet(bitpos uint, value uint32) bool { | |||
return value&(1<<bitpos) != 0 | |||
} |
@ -0,0 +1,27 @@ | |||
// Copyright 2018 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 386 amd64 amd64p32 | |||
// +build !gccgo | |||
#include "textflag.h" | |||
// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32) | |||
TEXT ·cpuid(SB), NOSPLIT, $0-24 | |||
MOVL eaxArg+0(FP), AX | |||
MOVL ecxArg+4(FP), CX | |||
CPUID | |||
MOVL AX, eax+8(FP) | |||
MOVL BX, ebx+12(FP) | |||
MOVL CX, ecx+16(FP) | |||
MOVL DX, edx+20(FP) | |||
RET | |||
// func xgetbv() (eax, edx uint32) | |||
TEXT ·xgetbv(SB),NOSPLIT,$0-8 | |||
MOVL $0, CX | |||
XGETBV | |||
MOVL AX, eax+0(FP) | |||
MOVL DX, edx+4(FP) | |||
RET |