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