xref: /openbmc/qemu/target/s390x/cpu_features.c (revision dafec285bdbfe415ac6823abdc510e0b92c3f094)
1  /*
2   * CPU features/facilities for s390x
3   *
4   * Copyright IBM Corp. 2016, 2018
5   * Copyright Red Hat, Inc. 2019
6   *
7   * Author(s): David Hildenbrand <david@redhat.com>
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"
15  #include "qemu/module.h"
16  #include "cpu_features.h"
17  #ifndef CONFIG_USER_ONLY
18  #include "target/s390x/kvm/pv.h"
19  #endif
20  
21  #define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \
22      [S390_FEAT_##_FEAT] = {                        \
23          .name = _NAME,                             \
24          .type = S390_FEAT_TYPE_##_TYPE,            \
25          .bit = _BIT,                               \
26          .desc = _DESC,                             \
27      },
28  static const S390FeatDef s390_features[S390_FEAT_MAX] = {
29      #include "cpu_features_def.h.inc"
30  };
31  #undef DEF_FEAT
32  
s390_feat_def(S390Feat feat)33  const S390FeatDef *s390_feat_def(S390Feat feat)
34  {
35      return &s390_features[feat];
36  }
37  
s390_feat_by_type_and_bit(S390FeatType type,int bit)38  S390Feat s390_feat_by_type_and_bit(S390FeatType type, int bit)
39  {
40      S390Feat feat;
41  
42      for (feat = 0; feat < ARRAY_SIZE(s390_features); feat++) {
43          if (s390_features[feat].type == type &&
44              s390_features[feat].bit == bit) {
45              return feat;
46          }
47      }
48      return S390_FEAT_MAX;
49  }
50  
s390_init_feat_bitmap(const S390FeatInit init,S390FeatBitmap bitmap)51  void s390_init_feat_bitmap(const S390FeatInit init, S390FeatBitmap bitmap)
52  {
53      int i, j;
54  
55      for (i = 0; i < (S390_FEAT_MAX / 64 + 1); i++) {
56          if (init[i]) {
57              for (j = 0; j < 64; j++) {
58                  if (init[i] & 1ULL << j) {
59                      set_bit(i * 64 + j, bitmap);
60                  }
61              }
62          }
63      }
64  }
65  
s390_fill_feat_block(const S390FeatBitmap features,S390FeatType type,uint8_t * data)66  void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type,
67                            uint8_t *data)
68  {
69      S390Feat feat;
70      int bit_nr;
71  
72      switch (type) {
73      case S390_FEAT_TYPE_STFL:
74          if (test_bit(S390_FEAT_ZARCH, features)) {
75              /* Features that are always active */
76              set_be_bit(2, data);   /* z/Architecture */
77              set_be_bit(138, data); /* Configuration-z-architectural-mode */
78          }
79          break;
80      case S390_FEAT_TYPE_PTFF:
81      case S390_FEAT_TYPE_KMAC:
82      case S390_FEAT_TYPE_KMC:
83      case S390_FEAT_TYPE_KM:
84      case S390_FEAT_TYPE_KIMD:
85      case S390_FEAT_TYPE_KLMD:
86      case S390_FEAT_TYPE_PCKMO:
87      case S390_FEAT_TYPE_KMCTR:
88      case S390_FEAT_TYPE_KMF:
89      case S390_FEAT_TYPE_KMO:
90      case S390_FEAT_TYPE_PCC:
91      case S390_FEAT_TYPE_PPNO:
92      case S390_FEAT_TYPE_KMA:
93      case S390_FEAT_TYPE_KDSA:
94      case S390_FEAT_TYPE_SORTL:
95      case S390_FEAT_TYPE_DFLTCC:
96          set_be_bit(0, data); /* query is always available */
97          break;
98      default:
99          break;
100      };
101  
102      feat = find_first_bit(features, S390_FEAT_MAX);
103      while (feat < S390_FEAT_MAX) {
104          if (s390_features[feat].type == type) {
105              bit_nr = s390_features[feat].bit;
106              /* big endian on uint8_t array */
107              set_be_bit(bit_nr, data);
108          }
109          feat = find_next_bit(features, S390_FEAT_MAX, feat + 1);
110      }
111  
112  #ifndef CONFIG_USER_ONLY
113      if (!s390_is_pv()) {
114          return;
115      }
116  
117      /*
118       * Some facilities are not available for CPUs in protected mode:
119       * - All SIE facilities because SIE is not available
120       * - DIAG318
121       *
122       * As VMs can move in and out of protected mode the CPU model
123       * doesn't protect us from that problem because it is only
124       * validated at the start of the VM.
125       */
126      switch (type) {
127      case S390_FEAT_TYPE_SCLP_CPU:
128          clear_be_bit(s390_feat_def(S390_FEAT_SIE_F2)->bit, data);
129          clear_be_bit(s390_feat_def(S390_FEAT_SIE_SKEY)->bit, data);
130          clear_be_bit(s390_feat_def(S390_FEAT_SIE_GPERE)->bit, data);
131          clear_be_bit(s390_feat_def(S390_FEAT_SIE_SIIF)->bit, data);
132          clear_be_bit(s390_feat_def(S390_FEAT_SIE_SIGPIF)->bit, data);
133          clear_be_bit(s390_feat_def(S390_FEAT_SIE_IB)->bit, data);
134          clear_be_bit(s390_feat_def(S390_FEAT_SIE_CEI)->bit, data);
135          break;
136      case S390_FEAT_TYPE_SCLP_CONF_CHAR:
137          clear_be_bit(s390_feat_def(S390_FEAT_SIE_GSLS)->bit, data);
138          clear_be_bit(s390_feat_def(S390_FEAT_HPMA2)->bit, data);
139          clear_be_bit(s390_feat_def(S390_FEAT_SIE_KSS)->bit, data);
140          break;
141      case S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT:
142          clear_be_bit(s390_feat_def(S390_FEAT_SIE_64BSCAO)->bit, data);
143          clear_be_bit(s390_feat_def(S390_FEAT_SIE_CMMA)->bit, data);
144          clear_be_bit(s390_feat_def(S390_FEAT_SIE_PFMFI)->bit, data);
145          clear_be_bit(s390_feat_def(S390_FEAT_SIE_IBS)->bit, data);
146          break;
147      case S390_FEAT_TYPE_SCLP_FAC134:
148          clear_be_bit(s390_feat_def(S390_FEAT_DIAG_318)->bit, data);
149          break;
150      default:
151          return;
152      }
153  #endif
154  }
155  
s390_add_from_feat_block(S390FeatBitmap features,S390FeatType type,uint8_t * data)156  void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type,
157                                uint8_t *data)
158  {
159      int nr_bits, le_bit;
160  
161      switch (type) {
162      case S390_FEAT_TYPE_STFL:
163         nr_bits = 16384;
164         break;
165      case S390_FEAT_TYPE_PLO:
166      case S390_FEAT_TYPE_SORTL:
167      case S390_FEAT_TYPE_DFLTCC:
168         nr_bits = 256;
169         break;
170      default:
171         /* all cpu subfunctions have 128 bit */
172         nr_bits = 128;
173      };
174  
175      le_bit = find_first_bit((unsigned long *) data, nr_bits);
176      while (le_bit < nr_bits) {
177          /* convert the bit number to a big endian bit nr */
178          S390Feat feat = s390_feat_by_type_and_bit(type, BE_BIT_NR(le_bit));
179          /* ignore unknown bits */
180          if (feat < S390_FEAT_MAX) {
181              set_bit(feat, features);
182          }
183          le_bit = find_next_bit((unsigned long *) data, nr_bits, le_bit + 1);
184      }
185  }
186  
s390_feat_bitmap_to_ascii(const S390FeatBitmap features,void * opaque,void (* fn)(const char * name,void * opaque))187  void s390_feat_bitmap_to_ascii(const S390FeatBitmap features, void *opaque,
188                                 void (*fn)(const char *name, void *opaque))
189  {
190      S390FeatBitmap bitmap, tmp;
191      S390FeatGroup group;
192      S390Feat feat;
193  
194      bitmap_copy(bitmap, features, S390_FEAT_MAX);
195  
196      /* process whole groups first */
197      for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
198          const S390FeatGroupDef *def = s390_feat_group_def(group);
199  
200          bitmap_and(tmp, bitmap, def->feat, S390_FEAT_MAX);
201          if (bitmap_equal(tmp, def->feat, S390_FEAT_MAX)) {
202              bitmap_andnot(bitmap, bitmap, def->feat, S390_FEAT_MAX);
203              fn(def->name, opaque);
204          }
205      }
206  
207      /* report leftovers as separate features */
208      feat = find_first_bit(bitmap, S390_FEAT_MAX);
209      while (feat < S390_FEAT_MAX) {
210          fn(s390_feat_def(feat)->name, opaque);
211          feat = find_next_bit(bitmap, S390_FEAT_MAX, feat + 1);
212      };
213  }
214  
s390_get_deprecated_features(S390FeatBitmap features)215  void s390_get_deprecated_features(S390FeatBitmap features)
216  {
217      static const int feats[] = {
218           /* CSSKE is deprecated on newer generations */
219           S390_FEAT_CONDITIONAL_SSKE,
220           S390_FEAT_BPB,
221           /* Deprecated on z16 */
222           S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE,
223           S390_FEAT_TRANSACTIONAL_EXE
224      };
225      int i;
226  
227      for (i = 0; i < ARRAY_SIZE(feats); i++) {
228          set_bit(feats[i], features);
229      }
230  }
231  
232  #define FEAT_GROUP_INIT(_name, _group, _desc)        \
233      {                                                \
234          .name = _name,                               \
235          .desc = _desc,                               \
236          .init = { S390_FEAT_GROUP_LIST_ ## _group }, \
237      }
238  
239  /* indexed by feature group number for easy lookup */
240  static S390FeatGroupDef s390_feature_groups[] = {
241      FEAT_GROUP_INIT("plo", PLO, "Perform-locked-operation facility"),
242      FEAT_GROUP_INIT("tods", TOD_CLOCK_STEERING, "Tod-clock-steering facility"),
243      FEAT_GROUP_INIT("gen13ptff", GEN13_PTFF, "PTFF enhancements introduced with z13"),
244      FEAT_GROUP_INIT("msa", MSA, "Message-security-assist facility"),
245      FEAT_GROUP_INIT("msa1", MSA_EXT_1, "Message-security-assist-extension 1 facility"),
246      FEAT_GROUP_INIT("msa2", MSA_EXT_2, "Message-security-assist-extension 2 facility"),
247      FEAT_GROUP_INIT("msa3", MSA_EXT_3, "Message-security-assist-extension 3 facility"),
248      FEAT_GROUP_INIT("msa4", MSA_EXT_4, "Message-security-assist-extension 4 facility"),
249      FEAT_GROUP_INIT("msa5", MSA_EXT_5, "Message-security-assist-extension 5 facility"),
250      FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"),
251      FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"),
252      FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"),
253      FEAT_GROUP_INIT("msa9", MSA_EXT_9, "Message-security-assist-extension 9 facility"),
254      FEAT_GROUP_INIT("msa9_pckmo", MSA_EXT_9_PCKMO, "Message-security-assist-extension 9 PCKMO subfunctions"),
255      FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"),
256      FEAT_GROUP_INIT("esort", ENH_SORT, "Enhanced-sort facility"),
257      FEAT_GROUP_INIT("deflate", DEFLATE_CONVERSION, "Deflate-conversion facility"),
258  };
259  
s390_feat_group_def(S390FeatGroup group)260  const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group)
261  {
262      return &s390_feature_groups[group];
263  }
264  
init_groups(void)265  static void init_groups(void)
266  {
267      int i;
268  
269      /* init all bitmaps from generated data initially */
270      for (i = 0; i < ARRAY_SIZE(s390_feature_groups); i++) {
271          s390_init_feat_bitmap(s390_feature_groups[i].init,
272                                s390_feature_groups[i].feat);
273      }
274  }
275  
276  type_init(init_groups)
277