-
Notifications
You must be signed in to change notification settings - Fork 0
/
ch03.xml
154 lines (144 loc) · 9.55 KB
/
ch03.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="ch03">
<title>Runtime features</title>
<para><indexterm><primary>Feature detection</primary></indexterm><indexterm><primary>Feature detection</primary><secondary>AIX</secondary></indexterm>Runtime feature detections allows code to switch to a faster implementation when the hardware permits. This chapter shows you how to determine POWER8 cryptography availability at runtime on AIX and Linux PowerPC platforms.</para>
<section id="feature_strategy">
<title>Strategy</title>
<para>The strategy to detect availability of in-core cryptography on POWER processors is check for ISA 2.07 or above. Cryptography is an ISA 2.07 and POWER8 requirement, and the cryptography support cannot be disgorged.</para>
<para>AIX systems should check for POWER8. AIX does not provide separate bits for AES, SHA and polynomial multiplies. The ISA level signals the availability of the cryptography on AIX. Linux supplies separate bits for ISA 2.07 and vector cryptography, but you only need to check the ISA level.</para>
<para>There is no need to perform <systemitem>SIGILL</systemitem> probes on AIX or newer Linux systems. If you are using older versions of Glibc or Linux kernel then you may have to fallback to <systemitem>SIGILL</systemitem> probes. Older versions include Glibc 2.24 and Linux kernel 4.08 (and earlier).</para>
</section>
<section id="feature_aix">
<title>AIX features</title>
<para><indexterm><primary>Feature detection</primary><secondary>AIX</secondary></indexterm>The AIX system header <systemitem><systemcfg.h></systemitem> defines the <systemitem>_system_configuration</systemitem> structure that identifies system characteristics. The header also provides macros to access various fields of the structure. Runtime code to perform the POWER8 cryptography check should look similar to below.</para>
<programlisting><?code-font-size 75% ?><indexterm><primary>__power_7_andup</primary></indexterm><indexterm><primary>__power_8_andup</primary></indexterm>#include <sys/systemcfg.h>
#ifndef __power_7_andup
# define __power_7_andup() 0
#endif
#ifndef __power_8_andup
# define __power_8_andup() 0
#endif
bool HasPower7()
{
if (__power_7_andup() != 0)
return true;
return false;
}
bool HasPower8()
{
if (__power_8_andup() != 0)
return true;
return false;
}
bool HasCrypto()
{
if (__power_8_andup() != 0)
return true;
return false;
}
</programlisting>
<para><indexterm><primary>__power_vsx</primary></indexterm>You <emphasis>should not</emphasis> use the <systemitem>__power_vsx()</systemitem> macro to detect in-core cryptography availability. Though cryptography is implemented in the VSX unit, the VSX unit is available in POWER7 and above.</para>
<para>OpenSSL uses the following on AIX to test for cryptography availability in <ulink url="https://github.com/openssl/openssl/blob/master/crypto/ppccap.c"><systemitem>crypto/ppccap.c</systemitem></ulink>. The project effectively re-implements the <systemitem>__power_8_andup()</systemitem> macro.</para>
<programlisting><?code-font-size 75% ?><indexterm><primary>__power_set</primary></indexterm>/* POWER8 and later */
if (__power_set(0xffffffffU<<16))
OPENSSL_ppccap_P |= PPC_CRYPTO207;
</programlisting>
</section>
<section id="feature_linux">
<title>Linux features</title>
<para><indexterm><primary>Feature detection</primary><secondary>Linux</secondary></indexterm><indexterm><primary>Glibc</primary></indexterm>Some versions of Glibc and the kernel provide ELF auxiliary vectors with system information. <systemitem>AT_HWCAP2</systemitem> will show the <systemitem>vcrypto</systemitem> flag when in-core cryptography is available. This is guaranteed for the following little-endian Linux distributions:</para>
<itemizedlist spacing="compact">
<listitem>
<para>Ubuntu 14.04 and later</para>
</listitem>
<listitem>
<para>SLES 12 and later</para>
</listitem>
<listitem>
<para>RHEL 7 and later</para>
</listitem>
</itemizedlist>
<para><indexterm><primary>LD_SHOW_AUXV</primary></indexterm>Below is a screen capture using the loader's diagnostics to print the auxiliary vector for the <systemitem>/bin/true</systemitem> program on <systemitem>gcc112</systemitem>.</para>
<screen>$ LD_SHOW_AUXV=1 /bin/true
AT_DCACHEBSIZE: 0x80
AT_ICACHEBSIZE: 0x80
AT_UCACHEBSIZE: 0x0
AT_SYSINFO_EHDR: 0x3fff877c0000
AT_HWCAP: ppcle true_le archpmu vsx arch_2_06 dfp ic_snoop
smt mmu fpu altivec ppc64 ppc32
AT_PAGESZ: 65536
AT_CLKTCK: 100
AT_PHDR: 0x10000040
AT_PHENT: 56
AT_PHNUM: 9
AT_BASE: 0x3fff877e0000
AT_FLAGS: 0x0
AT_ENTRY: 0x1000145c
AT_UID: 10455
AT_EUID: 10455
AT_GID: 10455
AT_EGID: 10455
AT_SECURE: 0
AT_RANDOM: 0x3fffeaeaa872
AT_HWCAP2: vcrypto tar isel ebb dscr htm arch_2_07
AT_EXECFN: /bin/true
AT_PLATFORM: power8
AT_BASE_PLATFORM:power8
</screen>
<para><indexterm><primary>Feature detection</primary><secondary>Glibc</secondary></indexterm>Linux systems with Glibc version 2.16 can use <systemitem>getauxval</systemitem> to determine CPU features. However, defines like <systemitem>PPC_FEATURE2_ARCH_2_07</systemitem> and <systemitem>PPC_FEATURE2_VEC_CRYPTO</systemitem> require Glibc 2.24. Runtime code to perform the check should look similar to below. The defines below were taken from the Linux kernel's <ulink url="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/powerpc/include/asm/cputable.h">cputable.h</ulink>.</para>
<programlisting><?code-font-size 75% ?><indexterm><primary>getauxval</primary></indexterm><indexterm><primary>AT_HWCAP</primary></indexterm><indexterm><primary>AT_HWCAP2</primary></indexterm><indexterm><primary>PPC_FEATURE_HAS_ALTIVEC</primary></indexterm><indexterm><primary>PPC_FEATURE_ARCH_2_06</primary></indexterm><indexterm><primary>PPC_FEATURE2_ARCH_2_07</primary></indexterm><indexterm><primary>PPC_FEATURE2_ARCH_3_00</primary></indexterm><indexterm><primary>PPC_FEATURE2_VEC_CRYPTO</primary></indexterm>#ifndef AT_HWCAP
# define AT_HWCAP 16
#endif
#ifndef AT_HWCAP2
# define AT_HWCAP2 26
#endif
#ifndef PPC_FEATURE_ARCH_2_06
# define PPC_FEATURE_ARCH_2_06 0x00000100
#endif
#ifndef PPC_FEATURE2_ARCH_2_07
# define PPC_FEATURE2_ARCH_2_07 0x80000000
#endif
#ifndef PPC_FEATURE2_VEC_CRYPTO
# define PPC_FEATURE2_VEC_CRYPTO 0x02000000
#endif
bool HasPower7()
{
if (getauxval(AT_HWCAP) & PPC_FEATURE_ARCH_2_06 != 0)
return true;
return false;
}
bool HasPower8()
{
if (getauxval(AT_HWCAP2) & PPC_FEATURE2_ARCH_2_07 != 0)
return true;
return false;
}
bool HasCrypto()
{
if (getauxval(AT_HWCAP2) & PPC_FEATURE2_VEC_CRYPTO != 0)
return true;
return false;
}
</programlisting>
</section>
<section id="feature_cache_size">
<title>L1 Data Cache</title>
<para><indexterm><primary>L1 data cache</primary></indexterm>The L1 data cache line size is an important security parameter that can be used to avoid leaking information through timing attacks. IBM POWER System S822, like <systemitem>gcc112</systemitem> and <systemitem>gcc119</systemitem>, have a 128-byte L1 data cache line size.</para>
<para><indexterm><primary>L1 data cache</primary><secondary>AIX</secondary></indexterm><systemitem>gcc119</systemitem> runs AIX and L1 data cache line size can be queried as shown below.</para>
<programlisting><?code-font-size 75% ?><indexterm><primary>getsystemcfg</primary></indexterm><indexterm><primary>SC_L1C_DLS</primary></indexterm>#include <sys/systemcfg.h>
int cacheLineSize = getsystemcfg(SC_L1C_DLS);
if (cacheLineSize) <= 0)
cacheLineSize = DEFAULT_L1_CACHE_LINE_SIZE;
</programlisting>
<para><indexterm><primary>L1 data cache</primary><secondary>Linux</secondary></indexterm><systemitem>gcc112</systemitem> runs Linux and L1 data cache line size can be queried as shown below. However, the call requires Glibc 2.26 and Linux kernel 4.10.</para>
<programlisting><?code-font-size 75% ?><indexterm><primary>sysconf</primary></indexterm><indexterm><primary>_SC_LEVEL1_DCACHE_LINESIZE</primary></indexterm>#include <unistd.h>
int cacheLineSize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
if (cacheLineSize) <= 0)
cacheLineSize = DEFAULT_L1_CACHE_LINE_SIZE;
</programlisting>
<para>It is important to check the return value from <systemitem>sysconf</systemitem> on Linux. CentOS 7.4 on <systemitem>gcc112</systemitem> returns 0 for the query because Glibc is version 2.17 and the Linux kernel is version 3.10. In addition to -1, you should consider a return value of 0 as failure.</para>
<para>You should have a fallback strategy that includes a sane default set for <systemitem>DEFAULT_L1_CACHE_LINE_SIZE</systemitem> because Glibc does not return a failure. On 32-bit systems you can usually use 32-bytes as a default, and on 64-bit systems you can usually use 64-bytes as a default.</para>
<para>Returning success with a value of 0 for an unimplemented <systemitem>sysconf</systemitem> parameter appears to be a Glibc bug. Also see <ulink url="https://lists.centos.org/pipermail/centos/2017-September/166236.html">sysconf and _SC_LEVEL1_DCACHE_LINESIZE returns 0?</ulink> on the CentOS mailing list and <ulink url="https://bugs.centos.org/view.php?id=14599">Issue 14599: sysconf(_SC_LEVEL1_DCACHE_LINESIZE) returns 0 instead of 128</ulink> in the CentOS issue tracker.</para>
</section>
</chapter>