xref: /qemu/target/s390x/cpu_features.c (revision 6e55b32d)
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,
2216e55b32dSCollin Walling          /* Deprecated on z16 */
2226e55b32dSCollin Walling          S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE,
2236e55b32dSCollin 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