1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * CPU features/facilities for s390x
3fcf5ef2aSThomas Huth *
427e84d4eSChristian Borntraeger * Copyright IBM Corp. 2016, 2018
5220ae900SDavid Hildenbrand * Copyright Red Hat, Inc. 2019
6fcf5ef2aSThomas Huth *
7220ae900SDavid Hildenbrand * Author(s): David Hildenbrand <david@redhat.com>
8fcf5ef2aSThomas Huth *
9fcf5ef2aSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or (at
10fcf5ef2aSThomas Huth * your option) any later version. See the COPYING file in the top-level
11fcf5ef2aSThomas Huth * directory.
12fcf5ef2aSThomas Huth */
13fcf5ef2aSThomas Huth
14fcf5ef2aSThomas Huth #include "qemu/osdep.h"
15fcf5ef2aSThomas Huth #include "qemu/module.h"
16fcf5ef2aSThomas Huth #include "cpu_features.h"
173ea7e312SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
18f5f9c6eaSPhilippe Mathieu-Daudé #include "target/s390x/kvm/pv.h"
193ea7e312SPhilippe Mathieu-Daudé #endif
20fcf5ef2aSThomas Huth
21220ae900SDavid Hildenbrand #define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \
22220ae900SDavid Hildenbrand [S390_FEAT_##_FEAT] = { \
23220ae900SDavid Hildenbrand .name = _NAME, \
24220ae900SDavid Hildenbrand .type = S390_FEAT_TYPE_##_TYPE, \
25220ae900SDavid Hildenbrand .bit = _BIT, \
26220ae900SDavid Hildenbrand .desc = _DESC, \
27220ae900SDavid Hildenbrand },
28220ae900SDavid Hildenbrand static const S390FeatDef s390_features[S390_FEAT_MAX] = {
290979ed01SPaolo Bonzini #include "cpu_features_def.h.inc"
30fcf5ef2aSThomas Huth };
31220ae900SDavid Hildenbrand #undef DEF_FEAT
32fcf5ef2aSThomas Huth
s390_feat_def(S390Feat feat)33fcf5ef2aSThomas Huth const S390FeatDef *s390_feat_def(S390Feat feat)
34fcf5ef2aSThomas Huth {
35fcf5ef2aSThomas Huth return &s390_features[feat];
36fcf5ef2aSThomas Huth }
37fcf5ef2aSThomas Huth
s390_feat_by_type_and_bit(S390FeatType type,int bit)38fcf5ef2aSThomas Huth S390Feat s390_feat_by_type_and_bit(S390FeatType type, int bit)
39fcf5ef2aSThomas Huth {
40fcf5ef2aSThomas Huth S390Feat feat;
41fcf5ef2aSThomas Huth
42fcf5ef2aSThomas Huth for (feat = 0; feat < ARRAY_SIZE(s390_features); feat++) {
43fcf5ef2aSThomas Huth if (s390_features[feat].type == type &&
44fcf5ef2aSThomas Huth s390_features[feat].bit == bit) {
45fcf5ef2aSThomas Huth return feat;
46fcf5ef2aSThomas Huth }
47fcf5ef2aSThomas Huth }
48fcf5ef2aSThomas Huth return S390_FEAT_MAX;
49fcf5ef2aSThomas Huth }
50fcf5ef2aSThomas Huth
s390_init_feat_bitmap(const S390FeatInit init,S390FeatBitmap bitmap)51fcf5ef2aSThomas Huth void s390_init_feat_bitmap(const S390FeatInit init, S390FeatBitmap bitmap)
52fcf5ef2aSThomas Huth {
53fcf5ef2aSThomas Huth int i, j;
54fcf5ef2aSThomas Huth
55fcf5ef2aSThomas Huth for (i = 0; i < (S390_FEAT_MAX / 64 + 1); i++) {
56fcf5ef2aSThomas Huth if (init[i]) {
57fcf5ef2aSThomas Huth for (j = 0; j < 64; j++) {
58fcf5ef2aSThomas Huth if (init[i] & 1ULL << j) {
59fcf5ef2aSThomas Huth set_bit(i * 64 + j, bitmap);
60fcf5ef2aSThomas Huth }
61fcf5ef2aSThomas Huth }
62fcf5ef2aSThomas Huth }
63fcf5ef2aSThomas Huth }
64fcf5ef2aSThomas Huth }
65fcf5ef2aSThomas Huth
s390_fill_feat_block(const S390FeatBitmap features,S390FeatType type,uint8_t * data)66fcf5ef2aSThomas Huth void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type,
67fcf5ef2aSThomas Huth uint8_t *data)
68fcf5ef2aSThomas Huth {
69fcf5ef2aSThomas Huth S390Feat feat;
70fcf5ef2aSThomas Huth int bit_nr;
71fcf5ef2aSThomas Huth
72cc18f907SDavid Hildenbrand switch (type) {
73cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_STFL:
74cc18f907SDavid Hildenbrand if (test_bit(S390_FEAT_ZARCH, features)) {
75075e52b8SJason J. Herne /* Features that are always active */
763d1cfc3cSDavid Hildenbrand set_be_bit(2, data); /* z/Architecture */
773d1cfc3cSDavid Hildenbrand set_be_bit(138, data); /* Configuration-z-architectural-mode */
78fcf5ef2aSThomas Huth }
79cc18f907SDavid Hildenbrand break;
80cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_PTFF:
81cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KMAC:
82cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KMC:
83cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KM:
84cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KIMD:
85cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KLMD:
86cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_PCKMO:
87cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KMCTR:
88cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KMF:
89cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KMO:
90cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_PCC:
91cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_PPNO:
92cc18f907SDavid Hildenbrand case S390_FEAT_TYPE_KMA:
935dacbe23SChristian Borntraeger case S390_FEAT_TYPE_KDSA:
94d220fabfSChristian Borntraeger case S390_FEAT_TYPE_SORTL:
95afc7b866SChristian Borntraeger case S390_FEAT_TYPE_DFLTCC:
963d1cfc3cSDavid Hildenbrand set_be_bit(0, data); /* query is always available */
97cc18f907SDavid Hildenbrand break;
98cc18f907SDavid Hildenbrand default:
99cc18f907SDavid Hildenbrand break;
100cc18f907SDavid Hildenbrand };
101fcf5ef2aSThomas Huth
102fcf5ef2aSThomas Huth feat = find_first_bit(features, S390_FEAT_MAX);
103fcf5ef2aSThomas Huth while (feat < S390_FEAT_MAX) {
104fcf5ef2aSThomas Huth if (s390_features[feat].type == type) {
105fcf5ef2aSThomas Huth bit_nr = s390_features[feat].bit;
106fcf5ef2aSThomas Huth /* big endian on uint8_t array */
1073d1cfc3cSDavid Hildenbrand set_be_bit(bit_nr, data);
108fcf5ef2aSThomas Huth }
109fcf5ef2aSThomas Huth feat = find_next_bit(features, S390_FEAT_MAX, feat + 1);
110fcf5ef2aSThomas Huth }
1113ded270aSJanosch Frank
1123ea7e312SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
11310248418SJanosch Frank if (!s390_is_pv()) {
11410248418SJanosch Frank return;
11510248418SJanosch Frank }
11610248418SJanosch Frank
11710248418SJanosch Frank /*
11810248418SJanosch Frank * Some facilities are not available for CPUs in protected mode:
11910248418SJanosch Frank * - All SIE facilities because SIE is not available
12010248418SJanosch Frank * - DIAG318
12110248418SJanosch Frank *
12210248418SJanosch Frank * As VMs can move in and out of protected mode the CPU model
12310248418SJanosch Frank * doesn't protect us from that problem because it is only
12410248418SJanosch Frank * validated at the start of the VM.
12510248418SJanosch Frank */
12610248418SJanosch Frank switch (type) {
12710248418SJanosch Frank case S390_FEAT_TYPE_SCLP_CPU:
12810248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_F2)->bit, data);
12910248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_SKEY)->bit, data);
13010248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_GPERE)->bit, data);
13110248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_SIIF)->bit, data);
13210248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_SIGPIF)->bit, data);
13310248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_IB)->bit, data);
13410248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_CEI)->bit, data);
13510248418SJanosch Frank break;
13610248418SJanosch Frank case S390_FEAT_TYPE_SCLP_CONF_CHAR:
13710248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_GSLS)->bit, data);
13810248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_HPMA2)->bit, data);
13910248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_KSS)->bit, data);
14010248418SJanosch Frank break;
14110248418SJanosch Frank case S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT:
14210248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_64BSCAO)->bit, data);
14310248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_CMMA)->bit, data);
14410248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_PFMFI)->bit, data);
14510248418SJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_SIE_IBS)->bit, data);
14610248418SJanosch Frank break;
14710248418SJanosch Frank case S390_FEAT_TYPE_SCLP_FAC134:
1483ded270aSJanosch Frank clear_be_bit(s390_feat_def(S390_FEAT_DIAG_318)->bit, data);
14910248418SJanosch Frank break;
15010248418SJanosch Frank default:
15110248418SJanosch Frank return;
1523ded270aSJanosch Frank }
1533ea7e312SPhilippe Mathieu-Daudé #endif
154fcf5ef2aSThomas Huth }
155fcf5ef2aSThomas Huth
s390_add_from_feat_block(S390FeatBitmap features,S390FeatType type,uint8_t * data)156fcf5ef2aSThomas Huth void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type,
157fcf5ef2aSThomas Huth uint8_t *data)
158fcf5ef2aSThomas Huth {
159fcf5ef2aSThomas Huth int nr_bits, le_bit;
160fcf5ef2aSThomas Huth
161fcf5ef2aSThomas Huth switch (type) {
162fcf5ef2aSThomas Huth case S390_FEAT_TYPE_STFL:
163c547a757SDavid Hildenbrand nr_bits = 16384;
164fcf5ef2aSThomas Huth break;
165fcf5ef2aSThomas Huth case S390_FEAT_TYPE_PLO:
166d220fabfSChristian Borntraeger case S390_FEAT_TYPE_SORTL:
167afc7b866SChristian Borntraeger case S390_FEAT_TYPE_DFLTCC:
168fcf5ef2aSThomas Huth nr_bits = 256;
169fcf5ef2aSThomas Huth break;
170fcf5ef2aSThomas Huth default:
171fcf5ef2aSThomas Huth /* all cpu subfunctions have 128 bit */
172fcf5ef2aSThomas Huth nr_bits = 128;
173fcf5ef2aSThomas Huth };
174fcf5ef2aSThomas Huth
175fcf5ef2aSThomas Huth le_bit = find_first_bit((unsigned long *) data, nr_bits);
176fcf5ef2aSThomas Huth while (le_bit < nr_bits) {
177fcf5ef2aSThomas Huth /* convert the bit number to a big endian bit nr */
178fcf5ef2aSThomas Huth S390Feat feat = s390_feat_by_type_and_bit(type, BE_BIT_NR(le_bit));
179fcf5ef2aSThomas Huth /* ignore unknown bits */
180fcf5ef2aSThomas Huth if (feat < S390_FEAT_MAX) {
181fcf5ef2aSThomas Huth set_bit(feat, features);
182fcf5ef2aSThomas Huth }
183fcf5ef2aSThomas Huth le_bit = find_next_bit((unsigned long *) data, nr_bits, le_bit + 1);
184fcf5ef2aSThomas Huth }
185fcf5ef2aSThomas Huth }
186fcf5ef2aSThomas Huth
s390_feat_bitmap_to_ascii(const S390FeatBitmap features,void * opaque,void (* fn)(const char * name,void * opaque))187fcf5ef2aSThomas Huth void s390_feat_bitmap_to_ascii(const S390FeatBitmap features, void *opaque,
188fcf5ef2aSThomas Huth void (*fn)(const char *name, void *opaque))
189fcf5ef2aSThomas Huth {
190fcf5ef2aSThomas Huth S390FeatBitmap bitmap, tmp;
191fcf5ef2aSThomas Huth S390FeatGroup group;
192fcf5ef2aSThomas Huth S390Feat feat;
193fcf5ef2aSThomas Huth
194fcf5ef2aSThomas Huth bitmap_copy(bitmap, features, S390_FEAT_MAX);
195fcf5ef2aSThomas Huth
196fcf5ef2aSThomas Huth /* process whole groups first */
197fcf5ef2aSThomas Huth for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
198fcf5ef2aSThomas Huth const S390FeatGroupDef *def = s390_feat_group_def(group);
199fcf5ef2aSThomas Huth
200fcf5ef2aSThomas Huth bitmap_and(tmp, bitmap, def->feat, S390_FEAT_MAX);
201fcf5ef2aSThomas Huth if (bitmap_equal(tmp, def->feat, S390_FEAT_MAX)) {
202fcf5ef2aSThomas Huth bitmap_andnot(bitmap, bitmap, def->feat, S390_FEAT_MAX);
203fcf5ef2aSThomas Huth fn(def->name, opaque);
204fcf5ef2aSThomas Huth }
205fcf5ef2aSThomas Huth }
206fcf5ef2aSThomas Huth
207fcf5ef2aSThomas Huth /* report leftovers as separate features */
208fcf5ef2aSThomas Huth feat = find_first_bit(bitmap, S390_FEAT_MAX);
209fcf5ef2aSThomas Huth while (feat < S390_FEAT_MAX) {
210fcf5ef2aSThomas Huth fn(s390_feat_def(feat)->name, opaque);
211fcf5ef2aSThomas Huth feat = find_next_bit(bitmap, S390_FEAT_MAX, feat + 1);
212fcf5ef2aSThomas Huth };
213fcf5ef2aSThomas Huth }
214fcf5ef2aSThomas Huth
s390_get_deprecated_features(S390FeatBitmap features)2158aa2211eSCollin Walling void s390_get_deprecated_features(S390FeatBitmap features)
2168aa2211eSCollin Walling {
2178aa2211eSCollin Walling static const int feats[] = {
2188aa2211eSCollin Walling /* CSSKE is deprecated on newer generations */
2198aa2211eSCollin Walling S390_FEAT_CONDITIONAL_SSKE,
2208aa2211eSCollin Walling S390_FEAT_BPB,
221*6e55b32dSCollin Walling /* Deprecated on z16 */
222*6e55b32dSCollin Walling S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE,
223*6e55b32dSCollin Walling S390_FEAT_TRANSACTIONAL_EXE
2248aa2211eSCollin Walling };
2258aa2211eSCollin Walling int i;
2268aa2211eSCollin Walling
2278aa2211eSCollin Walling for (i = 0; i < ARRAY_SIZE(feats); i++) {
2288aa2211eSCollin Walling set_bit(feats[i], features);
2298aa2211eSCollin Walling }
2308aa2211eSCollin Walling }
2318aa2211eSCollin Walling
232fcf5ef2aSThomas Huth #define FEAT_GROUP_INIT(_name, _group, _desc) \
233fcf5ef2aSThomas Huth { \
234fcf5ef2aSThomas Huth .name = _name, \
235fcf5ef2aSThomas Huth .desc = _desc, \
236fcf5ef2aSThomas Huth .init = { S390_FEAT_GROUP_LIST_ ## _group }, \
237fcf5ef2aSThomas Huth }
238fcf5ef2aSThomas Huth
239fcf5ef2aSThomas Huth /* indexed by feature group number for easy lookup */
240fcf5ef2aSThomas Huth static S390FeatGroupDef s390_feature_groups[] = {
241fcf5ef2aSThomas Huth FEAT_GROUP_INIT("plo", PLO, "Perform-locked-operation facility"),
242fcf5ef2aSThomas Huth FEAT_GROUP_INIT("tods", TOD_CLOCK_STEERING, "Tod-clock-steering facility"),
243fcf5ef2aSThomas Huth FEAT_GROUP_INIT("gen13ptff", GEN13_PTFF, "PTFF enhancements introduced with z13"),
244fcf5ef2aSThomas Huth FEAT_GROUP_INIT("msa", MSA, "Message-security-assist facility"),
245fcf5ef2aSThomas Huth FEAT_GROUP_INIT("msa1", MSA_EXT_1, "Message-security-assist-extension 1 facility"),
246fcf5ef2aSThomas Huth FEAT_GROUP_INIT("msa2", MSA_EXT_2, "Message-security-assist-extension 2 facility"),
247fcf5ef2aSThomas Huth FEAT_GROUP_INIT("msa3", MSA_EXT_3, "Message-security-assist-extension 3 facility"),
248fcf5ef2aSThomas Huth FEAT_GROUP_INIT("msa4", MSA_EXT_4, "Message-security-assist-extension 4 facility"),
249fcf5ef2aSThomas Huth FEAT_GROUP_INIT("msa5", MSA_EXT_5, "Message-security-assist-extension 5 facility"),
2506da5c593SJason J. Herne FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"),
2516da5c593SJason J. Herne FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"),
2526da5c593SJason J. Herne FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"),
2535dacbe23SChristian Borntraeger FEAT_GROUP_INIT("msa9", MSA_EXT_9, "Message-security-assist-extension 9 facility"),
2545dacbe23SChristian Borntraeger FEAT_GROUP_INIT("msa9_pckmo", MSA_EXT_9_PCKMO, "Message-security-assist-extension 9 PCKMO subfunctions"),
255ddf5d18aSCollin Walling FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"),
256d220fabfSChristian Borntraeger FEAT_GROUP_INIT("esort", ENH_SORT, "Enhanced-sort facility"),
257afc7b866SChristian Borntraeger FEAT_GROUP_INIT("deflate", DEFLATE_CONVERSION, "Deflate-conversion facility"),
258fcf5ef2aSThomas Huth };
259fcf5ef2aSThomas Huth
s390_feat_group_def(S390FeatGroup group)260fcf5ef2aSThomas Huth const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group)
261fcf5ef2aSThomas Huth {
262fcf5ef2aSThomas Huth return &s390_feature_groups[group];
263fcf5ef2aSThomas Huth }
264fcf5ef2aSThomas Huth
init_groups(void)265fcf5ef2aSThomas Huth static void init_groups(void)
266fcf5ef2aSThomas Huth {
267fcf5ef2aSThomas Huth int i;
268fcf5ef2aSThomas Huth
269cced0d65SMichael Tokarev /* init all bitmaps from generated data initially */
270fcf5ef2aSThomas Huth for (i = 0; i < ARRAY_SIZE(s390_feature_groups); i++) {
271fcf5ef2aSThomas Huth s390_init_feat_bitmap(s390_feature_groups[i].init,
272fcf5ef2aSThomas Huth s390_feature_groups[i].feat);
273fcf5ef2aSThomas Huth }
274fcf5ef2aSThomas Huth }
275fcf5ef2aSThomas Huth
276fcf5ef2aSThomas Huth type_init(init_groups)
277