#pragma GCC pop_options
#endif /* defined(__i386__) || defined(__x86_64__) */
+
+#ifdef __s390__
+
+struct facilityList {
+ uint64_t bits[4];
+};
+
+struct queryResult {
+ uint64_t bits[2];
+};
+
+struct facilityList stfle(void)
+ __asm__(GOSYM_PREFIX "internal..z2fcpu.stfle")
+ __attribute__((no_split_stack));
+
+struct facilityList stfle(void) {
+ struct facilityList ret;
+ __asm__ ("la %%r1, %[ret]\t\n"
+ "lghi %%r0, 3\t\n" // last doubleword index to store
+ "xc 0(32,%%r1), 0(%%r1)\t\n" // clear 4 doublewords (32 bytes)
+ ".long 0xb2b01000\t\n" // store facility list extended (STFLE)
+ :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+ return ret;
+}
+
+struct queryResult kmQuery(void)
+ __asm__(GOSYM_PREFIX "internal..z2fcpu.kmQuery")
+ __attribute__((no_split_stack));
+
+struct queryResult kmQuery() {
+ struct queryResult ret;
+
+ __asm__ ("lghi %%r0, 0\t\n" // set function code to 0 (KM-Query)
+ "la %%r1, %[ret]\t\n"
+ ".long 0xb92e0024\t\n" // cipher message (KM)
+ :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+ return ret;
+}
+
+struct queryResult kmcQuery(void)
+ __asm__(GOSYM_PREFIX "internal..z2fcpu.kmcQuery")
+ __attribute__((no_split_stack));
+
+struct queryResult kmcQuery() {
+ struct queryResult ret;
+
+ __asm__ ("lghi %%r0, 0\t\n" // set function code to 0 (KMC-Query)
+ "la %%r1, %[ret]\t\n"
+ ".long 0xb92f0024\t\n" // cipher message with chaining (KMC)
+ :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+ return ret;
+}
+
+struct queryResult kmctrQuery(void)
+ __asm__(GOSYM_PREFIX "internal..z2fcpu.kmctrQuery")
+ __attribute__((no_split_stack));
+
+struct queryResult kmctrQuery() {
+ struct queryResult ret;
+
+ __asm__ ("lghi %%r0, 0\t\n" // set function code to 0 (KMCTR-Query)
+ "la %%r1, %[ret]\t\n"
+ ".long 0xb92d4024\t\n" // cipher message with counter (KMCTR)
+ :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+ return ret;
+}
+
+struct queryResult kmaQuery(void)
+ __asm__(GOSYM_PREFIX "internal..z2fcpu.kmaQuery")
+ __attribute__((no_split_stack));
+
+struct queryResult kmaQuery() {
+ struct queryResult ret;
+
+ __asm__ ("lghi %%r0, 0\t\n" // set function code to 0 (KMA-Query)
+ "la %%r1, %[ret]\t\n"
+ ".long 0xb9296024\t\n" // cipher message with authentication (KMA)
+ :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+ return ret;
+}
+
+struct queryResult kimdQuery(void)
+ __asm__(GOSYM_PREFIX "internal..z2fcpu.kimdQuery")
+ __attribute__((no_split_stack));
+
+struct queryResult kimdQuery() {
+ struct queryResult ret;
+
+ __asm__ ("lghi %%r0, 0\t\n" // set function code to 0 (KIMD-Query)
+ "la %%r1, %[ret]\t\n"
+ ".long 0xb93e0024\t\n" // compute intermediate message digest (KIMD)
+ :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+ return ret;
+}
+
+struct queryResult klmdQuery(void)
+ __asm__(GOSYM_PREFIX "internal..z2fcpu.klmdQuery")
+ __attribute__((no_split_stack));
+
+struct queryResult klmdQuery() {
+ struct queryResult ret;
+
+ __asm__ ("lghi %%r0, 0\t\n" // set function code to 0 (KLMD-Query)
+ "la %%r1, %[ret]\t\n"
+ ".long 0xb93f0024\t\n" // compute last message digest (KLMD)
+ :[ret] "=Q" (ret) : : "r0", "r1", "cc");
+
+ return ret;
+}
+
+#endif /* defined(__s390__) */
// 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 { 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") }
+func stfle() facilityList
+func kmQuery() queryResult
+func kmcQuery() queryResult
+func kmctrQuery() queryResult
+func kmaQuery() queryResult
+func kimdQuery() queryResult
+func klmdQuery() queryResult
func doinit() {
options = []option{
aes := []function{aes128, aes192, aes256}
facilities := stfle()
- S390X.HasZArch = facilities.Has(zarch)
- S390X.HasSTFLE = facilities.Has(stflef)
- S390X.HasLDisp = facilities.Has(ldisp)
- S390X.HasEImm = facilities.Has(eimm)
- S390X.HasDFP = facilities.Has(dfp)
- S390X.HasETF3Enhanced = facilities.Has(etf3eh)
- S390X.HasMSA = facilities.Has(msa)
-
if S390X.HasMSA {
// cipher message
km, kmc := kmQuery(), kmcQuery()
const (
// bit masks taken from bits/hwcap.h
- _HWCAP_S390_VX = 2048 // vector facility
+ _HWCAP_S390_ZARCH = 2
+ _HWCAP_S390_STFLE = 4
+ _HWCAP_S390_MSA = 8
+ _HWCAP_S390_LDISP = 16
+ _HWCAP_S390_EIMM = 32
+ _HWCAP_S390_DFP = 64
+ _HWCAP_S390_ETF3EH = 256
+ _HWCAP_S390_VX = 2048 // vector facility
)
func archauxv(tag, val uintptr) {
switch tag {
case _AT_HWCAP: // CPU capability bit flags
+ cpu.S390X.HasZArch = val&_HWCAP_S390_ZARCH != 0
+ cpu.S390X.HasSTFLE = val&_HWCAP_S390_STFLE != 0
+ cpu.S390X.HasMSA = val&_HWCAP_S390_MSA != 0
+ cpu.S390X.HasLDisp = val&_HWCAP_S390_LDISP != 0
+ cpu.S390X.HasEImm = val&_HWCAP_S390_EIMM != 0
+ cpu.S390X.HasDFP = val&_HWCAP_S390_DFP != 0
+ cpu.S390X.HasETF3Enhanced = val&_HWCAP_S390_ETF3EH != 0
cpu.S390X.HasVX = val&_HWCAP_S390_VX != 0
}
}