]>
Commit | Line | Data |
---|---|---|
78241744 MM |
1 | /* |
2 | * CPU features/facilities for s390x | |
3 | * | |
27e84d4e | 4 | * Copyright IBM Corp. 2016, 2018 |
220ae900 | 5 | * Copyright Red Hat, Inc. 2019 |
78241744 | 6 | * |
220ae900 | 7 | * Author(s): David Hildenbrand <david@redhat.com> |
78241744 MM |
8 | * |
9 | * This work is licensed under the terms of the GNU GPL, version 2 or (at | |
10 | * your option) any later version. See the COPYING file in the top-level | |
11 | * directory. | |
12 | */ | |
13 | ||
14 | #include "qemu/osdep.h" | |
8b3d6cb1 | 15 | #include "qemu/module.h" |
78241744 MM |
16 | #include "cpu_features.h" |
17 | ||
220ae900 DH |
18 | #define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \ |
19 | [S390_FEAT_##_FEAT] = { \ | |
20 | .name = _NAME, \ | |
21 | .type = S390_FEAT_TYPE_##_TYPE, \ | |
22 | .bit = _BIT, \ | |
23 | .desc = _DESC, \ | |
24 | }, | |
25 | static const S390FeatDef s390_features[S390_FEAT_MAX] = { | |
0979ed01 | 26 | #include "cpu_features_def.h.inc" |
78241744 | 27 | }; |
220ae900 | 28 | #undef DEF_FEAT |
78241744 MM |
29 | |
30 | const S390FeatDef *s390_feat_def(S390Feat feat) | |
31 | { | |
32 | return &s390_features[feat]; | |
33 | } | |
34 | ||
35 | S390Feat s390_feat_by_type_and_bit(S390FeatType type, int bit) | |
36 | { | |
37 | S390Feat feat; | |
38 | ||
39 | for (feat = 0; feat < ARRAY_SIZE(s390_features); feat++) { | |
40 | if (s390_features[feat].type == type && | |
41 | s390_features[feat].bit == bit) { | |
42 | return feat; | |
43 | } | |
44 | } | |
45 | return S390_FEAT_MAX; | |
46 | } | |
47 | ||
48 | void s390_init_feat_bitmap(const S390FeatInit init, S390FeatBitmap bitmap) | |
49 | { | |
50 | int i, j; | |
51 | ||
52 | for (i = 0; i < (S390_FEAT_MAX / 64 + 1); i++) { | |
53 | if (init[i]) { | |
54 | for (j = 0; j < 64; j++) { | |
55 | if (init[i] & 1ULL << j) { | |
56 | set_bit(i * 64 + j, bitmap); | |
57 | } | |
58 | } | |
59 | } | |
60 | } | |
61 | } | |
62 | ||
63 | void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, | |
64 | uint8_t *data) | |
65 | { | |
66 | S390Feat feat; | |
67 | int bit_nr; | |
68 | ||
cc18f907 DH |
69 | switch (type) { |
70 | case S390_FEAT_TYPE_STFL: | |
71 | if (test_bit(S390_FEAT_ZARCH, features)) { | |
72 | /* Features that are always active */ | |
3d1cfc3c DH |
73 | set_be_bit(2, data); /* z/Architecture */ |
74 | set_be_bit(138, data); /* Configuration-z-architectural-mode */ | |
cc18f907 DH |
75 | } |
76 | break; | |
77 | case S390_FEAT_TYPE_PTFF: | |
78 | case S390_FEAT_TYPE_KMAC: | |
79 | case S390_FEAT_TYPE_KMC: | |
80 | case S390_FEAT_TYPE_KM: | |
81 | case S390_FEAT_TYPE_KIMD: | |
82 | case S390_FEAT_TYPE_KLMD: | |
83 | case S390_FEAT_TYPE_PCKMO: | |
84 | case S390_FEAT_TYPE_KMCTR: | |
85 | case S390_FEAT_TYPE_KMF: | |
86 | case S390_FEAT_TYPE_KMO: | |
87 | case S390_FEAT_TYPE_PCC: | |
88 | case S390_FEAT_TYPE_PPNO: | |
89 | case S390_FEAT_TYPE_KMA: | |
5dacbe23 | 90 | case S390_FEAT_TYPE_KDSA: |
d220fabf | 91 | case S390_FEAT_TYPE_SORTL: |
afc7b866 | 92 | case S390_FEAT_TYPE_DFLTCC: |
3d1cfc3c | 93 | set_be_bit(0, data); /* query is always available */ |
cc18f907 DH |
94 | break; |
95 | default: | |
96 | break; | |
97 | }; | |
78241744 MM |
98 | |
99 | feat = find_first_bit(features, S390_FEAT_MAX); | |
100 | while (feat < S390_FEAT_MAX) { | |
101 | if (s390_features[feat].type == type) { | |
102 | bit_nr = s390_features[feat].bit; | |
103 | /* big endian on uint8_t array */ | |
3d1cfc3c | 104 | set_be_bit(bit_nr, data); |
78241744 MM |
105 | } |
106 | feat = find_next_bit(features, S390_FEAT_MAX, feat + 1); | |
107 | } | |
108 | } | |
109 | ||
110 | void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type, | |
111 | uint8_t *data) | |
112 | { | |
113 | int nr_bits, le_bit; | |
114 | ||
115 | switch (type) { | |
116 | case S390_FEAT_TYPE_STFL: | |
c547a757 | 117 | nr_bits = 16384; |
78241744 MM |
118 | break; |
119 | case S390_FEAT_TYPE_PLO: | |
d220fabf | 120 | case S390_FEAT_TYPE_SORTL: |
afc7b866 | 121 | case S390_FEAT_TYPE_DFLTCC: |
78241744 MM |
122 | nr_bits = 256; |
123 | break; | |
124 | default: | |
125 | /* all cpu subfunctions have 128 bit */ | |
126 | nr_bits = 128; | |
127 | }; | |
128 | ||
129 | le_bit = find_first_bit((unsigned long *) data, nr_bits); | |
130 | while (le_bit < nr_bits) { | |
131 | /* convert the bit number to a big endian bit nr */ | |
132 | S390Feat feat = s390_feat_by_type_and_bit(type, BE_BIT_NR(le_bit)); | |
133 | /* ignore unknown bits */ | |
134 | if (feat < S390_FEAT_MAX) { | |
135 | set_bit(feat, features); | |
136 | } | |
137 | le_bit = find_next_bit((unsigned long *) data, nr_bits, le_bit + 1); | |
138 | } | |
139 | } | |
140 | ||
8b3d6cb1 | 141 | void s390_feat_bitmap_to_ascii(const S390FeatBitmap features, void *opaque, |
78241744 MM |
142 | void (*fn)(const char *name, void *opaque)) |
143 | { | |
8b3d6cb1 DH |
144 | S390FeatBitmap bitmap, tmp; |
145 | S390FeatGroup group; | |
78241744 MM |
146 | S390Feat feat; |
147 | ||
8b3d6cb1 DH |
148 | bitmap_copy(bitmap, features, S390_FEAT_MAX); |
149 | ||
150 | /* process whole groups first */ | |
151 | for (group = 0; group < S390_FEAT_GROUP_MAX; group++) { | |
152 | const S390FeatGroupDef *def = s390_feat_group_def(group); | |
153 | ||
154 | bitmap_and(tmp, bitmap, def->feat, S390_FEAT_MAX); | |
155 | if (bitmap_equal(tmp, def->feat, S390_FEAT_MAX)) { | |
156 | bitmap_andnot(bitmap, bitmap, def->feat, S390_FEAT_MAX); | |
157 | fn(def->name, opaque); | |
158 | } | |
159 | } | |
160 | ||
161 | /* report leftovers as separate features */ | |
78241744 MM |
162 | feat = find_first_bit(bitmap, S390_FEAT_MAX); |
163 | while (feat < S390_FEAT_MAX) { | |
164 | fn(s390_feat_def(feat)->name, opaque); | |
165 | feat = find_next_bit(bitmap, S390_FEAT_MAX, feat + 1); | |
166 | }; | |
167 | } | |
8b3d6cb1 DH |
168 | |
169 | #define FEAT_GROUP_INIT(_name, _group, _desc) \ | |
170 | { \ | |
171 | .name = _name, \ | |
172 | .desc = _desc, \ | |
173 | .init = { S390_FEAT_GROUP_LIST_ ## _group }, \ | |
174 | } | |
175 | ||
176 | /* indexed by feature group number for easy lookup */ | |
177 | static S390FeatGroupDef s390_feature_groups[] = { | |
178 | FEAT_GROUP_INIT("plo", PLO, "Perform-locked-operation facility"), | |
179 | FEAT_GROUP_INIT("tods", TOD_CLOCK_STEERING, "Tod-clock-steering facility"), | |
180 | FEAT_GROUP_INIT("gen13ptff", GEN13_PTFF, "PTFF enhancements introduced with z13"), | |
181 | FEAT_GROUP_INIT("msa", MSA, "Message-security-assist facility"), | |
182 | FEAT_GROUP_INIT("msa1", MSA_EXT_1, "Message-security-assist-extension 1 facility"), | |
183 | FEAT_GROUP_INIT("msa2", MSA_EXT_2, "Message-security-assist-extension 2 facility"), | |
184 | FEAT_GROUP_INIT("msa3", MSA_EXT_3, "Message-security-assist-extension 3 facility"), | |
185 | FEAT_GROUP_INIT("msa4", MSA_EXT_4, "Message-security-assist-extension 4 facility"), | |
186 | FEAT_GROUP_INIT("msa5", MSA_EXT_5, "Message-security-assist-extension 5 facility"), | |
6da5c593 JH |
187 | FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"), |
188 | FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"), | |
189 | FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"), | |
5dacbe23 CB |
190 | FEAT_GROUP_INIT("msa9", MSA_EXT_9, "Message-security-assist-extension 9 facility"), |
191 | FEAT_GROUP_INIT("msa9_pckmo", MSA_EXT_9_PCKMO, "Message-security-assist-extension 9 PCKMO subfunctions"), | |
ddf5d18a | 192 | FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"), |
d220fabf | 193 | FEAT_GROUP_INIT("esort", ENH_SORT, "Enhanced-sort facility"), |
afc7b866 | 194 | FEAT_GROUP_INIT("deflate", DEFLATE_CONVERSION, "Deflate-conversion facility"), |
8b3d6cb1 DH |
195 | }; |
196 | ||
197 | const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group) | |
198 | { | |
199 | return &s390_feature_groups[group]; | |
200 | } | |
201 | ||
202 | static void init_groups(void) | |
203 | { | |
204 | int i; | |
205 | ||
206 | /* init all bitmaps from gnerated data initially */ | |
207 | for (i = 0; i < ARRAY_SIZE(s390_feature_groups); i++) { | |
208 | s390_init_feat_bitmap(s390_feature_groups[i].init, | |
209 | s390_feature_groups[i].feat); | |
210 | } | |
211 | } | |
212 | ||
213 | type_init(init_groups) |