arm-cpu-features.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * Arm CPU feature test cases
  3. *
  4. * Copyright (c) 2019 Red Hat Inc.
  5. * Authors:
  6. * Andrew Jones <drjones@redhat.com>
  7. *
  8. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  9. * See the COPYING file in the top-level directory.
  10. */
  11. #include "qemu/osdep.h"
  12. #include "qemu/bitops.h"
  13. #include "libqtest.h"
  14. #include "qapi/qmp/qdict.h"
  15. #include "qapi/qmp/qjson.h"
  16. /*
  17. * We expect the SVE max-vq to be 16. Also it must be <= 64
  18. * for our test code, otherwise 'vls' can't just be a uint64_t.
  19. */
  20. #define SVE_MAX_VQ 16
  21. #define MACHINE "-machine virt,gic-version=max,accel=tcg "
  22. #define MACHINE_KVM "-machine virt,gic-version=max,accel=kvm:tcg "
  23. #define QUERY_HEAD "{ 'execute': 'query-cpu-model-expansion', " \
  24. " 'arguments': { 'type': 'full', "
  25. #define QUERY_TAIL "}}"
  26. static bool kvm_enabled(QTestState *qts)
  27. {
  28. QDict *resp, *qdict;
  29. bool enabled;
  30. resp = qtest_qmp(qts, "{ 'execute': 'query-kvm' }");
  31. g_assert(qdict_haskey(resp, "return"));
  32. qdict = qdict_get_qdict(resp, "return");
  33. g_assert(qdict_haskey(qdict, "enabled"));
  34. enabled = qdict_get_bool(qdict, "enabled");
  35. qobject_unref(resp);
  36. return enabled;
  37. }
  38. static QDict *do_query_no_props(QTestState *qts, const char *cpu_type)
  39. {
  40. return qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s }"
  41. QUERY_TAIL, cpu_type);
  42. }
  43. static QDict *do_query(QTestState *qts, const char *cpu_type,
  44. const char *fmt, ...)
  45. {
  46. QDict *resp;
  47. if (fmt) {
  48. QDict *args;
  49. va_list ap;
  50. va_start(ap, fmt);
  51. args = qdict_from_vjsonf_nofail(fmt, ap);
  52. va_end(ap);
  53. resp = qtest_qmp(qts, QUERY_HEAD "'model': { 'name': %s, "
  54. "'props': %p }"
  55. QUERY_TAIL, cpu_type, args);
  56. } else {
  57. resp = do_query_no_props(qts, cpu_type);
  58. }
  59. return resp;
  60. }
  61. static const char *resp_get_error(QDict *resp)
  62. {
  63. QDict *qdict;
  64. g_assert(resp);
  65. qdict = qdict_get_qdict(resp, "error");
  66. if (qdict) {
  67. return qdict_get_str(qdict, "desc");
  68. }
  69. return NULL;
  70. }
  71. #define assert_error(qts, cpu_type, expected_error, fmt, ...) \
  72. ({ \
  73. QDict *_resp; \
  74. const char *_error; \
  75. \
  76. _resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \
  77. g_assert(_resp); \
  78. _error = resp_get_error(_resp); \
  79. g_assert(_error); \
  80. g_assert(g_str_equal(_error, expected_error)); \
  81. qobject_unref(_resp); \
  82. })
  83. static bool resp_has_props(QDict *resp)
  84. {
  85. QDict *qdict;
  86. g_assert(resp);
  87. if (!qdict_haskey(resp, "return")) {
  88. return false;
  89. }
  90. qdict = qdict_get_qdict(resp, "return");
  91. if (!qdict_haskey(qdict, "model")) {
  92. return false;
  93. }
  94. qdict = qdict_get_qdict(qdict, "model");
  95. return qdict_haskey(qdict, "props");
  96. }
  97. static QDict *resp_get_props(QDict *resp)
  98. {
  99. QDict *qdict;
  100. g_assert(resp);
  101. g_assert(resp_has_props(resp));
  102. qdict = qdict_get_qdict(resp, "return");
  103. qdict = qdict_get_qdict(qdict, "model");
  104. qdict = qdict_get_qdict(qdict, "props");
  105. return qdict;
  106. }
  107. static bool resp_get_feature(QDict *resp, const char *feature)
  108. {
  109. QDict *props;
  110. g_assert(resp);
  111. g_assert(resp_has_props(resp));
  112. props = resp_get_props(resp);
  113. g_assert(qdict_get(props, feature));
  114. return qdict_get_bool(props, feature);
  115. }
  116. #define assert_has_feature(qts, cpu_type, feature) \
  117. ({ \
  118. QDict *_resp = do_query_no_props(qts, cpu_type); \
  119. g_assert(_resp); \
  120. g_assert(resp_has_props(_resp)); \
  121. g_assert(qdict_get(resp_get_props(_resp), feature)); \
  122. qobject_unref(_resp); \
  123. })
  124. #define assert_has_not_feature(qts, cpu_type, feature) \
  125. ({ \
  126. QDict *_resp = do_query_no_props(qts, cpu_type); \
  127. g_assert(_resp); \
  128. g_assert(!resp_has_props(_resp) || \
  129. !qdict_get(resp_get_props(_resp), feature)); \
  130. qobject_unref(_resp); \
  131. })
  132. static void assert_type_full(QTestState *qts)
  133. {
  134. const char *error;
  135. QDict *resp;
  136. resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', "
  137. "'arguments': { 'type': 'static', "
  138. "'model': { 'name': 'foo' }}}");
  139. g_assert(resp);
  140. error = resp_get_error(resp);
  141. g_assert(error);
  142. g_assert(g_str_equal(error,
  143. "The requested expansion type is not supported"));
  144. qobject_unref(resp);
  145. }
  146. static void assert_bad_props(QTestState *qts, const char *cpu_type)
  147. {
  148. const char *error;
  149. QDict *resp;
  150. resp = qtest_qmp(qts, "{ 'execute': 'query-cpu-model-expansion', "
  151. "'arguments': { 'type': 'full', "
  152. "'model': { 'name': %s, "
  153. "'props': false }}}",
  154. cpu_type);
  155. g_assert(resp);
  156. error = resp_get_error(resp);
  157. g_assert(error);
  158. g_assert(g_str_equal(error,
  159. "Invalid parameter type for 'props', expected: dict"));
  160. qobject_unref(resp);
  161. }
  162. static uint64_t resp_get_sve_vls(QDict *resp)
  163. {
  164. QDict *props;
  165. const QDictEntry *e;
  166. uint64_t vls = 0;
  167. int n = 0;
  168. g_assert(resp);
  169. g_assert(resp_has_props(resp));
  170. props = resp_get_props(resp);
  171. for (e = qdict_first(props); e; e = qdict_next(props, e)) {
  172. if (strlen(e->key) > 3 && !strncmp(e->key, "sve", 3) &&
  173. g_ascii_isdigit(e->key[3])) {
  174. char *endptr;
  175. int bits;
  176. bits = g_ascii_strtoll(&e->key[3], &endptr, 10);
  177. if (!bits || *endptr != '\0') {
  178. continue;
  179. }
  180. if (qdict_get_bool(props, e->key)) {
  181. vls |= BIT_ULL((bits / 128) - 1);
  182. }
  183. ++n;
  184. }
  185. }
  186. g_assert(n == SVE_MAX_VQ);
  187. return vls;
  188. }
  189. #define assert_sve_vls(qts, cpu_type, expected_vls, fmt, ...) \
  190. ({ \
  191. QDict *_resp = do_query(qts, cpu_type, fmt, ##__VA_ARGS__); \
  192. g_assert(_resp); \
  193. g_assert(resp_has_props(_resp)); \
  194. g_assert(resp_get_sve_vls(_resp) == expected_vls); \
  195. qobject_unref(_resp); \
  196. })
  197. static void sve_tests_default(QTestState *qts, const char *cpu_type)
  198. {
  199. /*
  200. * With no sve-max-vq or sve<N> properties on the command line
  201. * the default is to have all vector lengths enabled. This also
  202. * tests that 'sve' is 'on' by default.
  203. */
  204. assert_sve_vls(qts, cpu_type, BIT_ULL(SVE_MAX_VQ) - 1, NULL);
  205. /* With SVE off, all vector lengths should also be off. */
  206. assert_sve_vls(qts, cpu_type, 0, "{ 'sve': false }");
  207. /* With SVE on, we must have at least one vector length enabled. */
  208. assert_error(qts, cpu_type, "cannot disable sve128", "{ 'sve128': false }");
  209. /* Basic enable/disable tests. */
  210. assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve384': true }");
  211. assert_sve_vls(qts, cpu_type, ((BIT_ULL(SVE_MAX_VQ) - 1) & ~BIT_ULL(2)),
  212. "{ 'sve384': false }");
  213. /*
  214. * ---------------------------------------------------------------------
  215. * power-of-two(vq) all-power- can can
  216. * of-two(< vq) enable disable
  217. * ---------------------------------------------------------------------
  218. * vq < max_vq no MUST* yes yes
  219. * vq < max_vq yes MUST* yes no
  220. * ---------------------------------------------------------------------
  221. * vq == max_vq n/a MUST* yes** yes**
  222. * ---------------------------------------------------------------------
  223. * vq > max_vq n/a no no yes
  224. * vq > max_vq n/a yes yes yes
  225. * ---------------------------------------------------------------------
  226. *
  227. * [*] "MUST" means this requirement must already be satisfied,
  228. * otherwise 'max_vq' couldn't itself be enabled.
  229. *
  230. * [**] Not testable with the QMP interface, only with the command line.
  231. */
  232. /* max_vq := 8 */
  233. assert_sve_vls(qts, cpu_type, 0x8b, "{ 'sve1024': true }");
  234. /* max_vq := 8, vq < max_vq, !power-of-two(vq) */
  235. assert_sve_vls(qts, cpu_type, 0x8f,
  236. "{ 'sve1024': true, 'sve384': true }");
  237. assert_sve_vls(qts, cpu_type, 0x8b,
  238. "{ 'sve1024': true, 'sve384': false }");
  239. /* max_vq := 8, vq < max_vq, power-of-two(vq) */
  240. assert_sve_vls(qts, cpu_type, 0x8b,
  241. "{ 'sve1024': true, 'sve256': true }");
  242. assert_error(qts, cpu_type, "cannot disable sve256",
  243. "{ 'sve1024': true, 'sve256': false }");
  244. /* max_vq := 3, vq > max_vq, !all-power-of-two(< vq) */
  245. assert_error(qts, cpu_type, "cannot disable sve512",
  246. "{ 'sve384': true, 'sve512': false, 'sve640': true }");
  247. /*
  248. * We can disable power-of-two vector lengths when all larger lengths
  249. * are also disabled. We only need to disable the power-of-two length,
  250. * as all non-enabled larger lengths will then be auto-disabled.
  251. */
  252. assert_sve_vls(qts, cpu_type, 0x7, "{ 'sve512': false }");
  253. /* max_vq := 3, vq > max_vq, all-power-of-two(< vq) */
  254. assert_sve_vls(qts, cpu_type, 0x1f,
  255. "{ 'sve384': true, 'sve512': true, 'sve640': true }");
  256. assert_sve_vls(qts, cpu_type, 0xf,
  257. "{ 'sve384': true, 'sve512': true, 'sve640': false }");
  258. }
  259. static void sve_tests_sve_max_vq_8(const void *data)
  260. {
  261. QTestState *qts;
  262. qts = qtest_init(MACHINE "-cpu max,sve-max-vq=8");
  263. assert_sve_vls(qts, "max", BIT_ULL(8) - 1, NULL);
  264. /*
  265. * Disabling the max-vq set by sve-max-vq is not allowed, but
  266. * of course enabling it is OK.
  267. */
  268. assert_error(qts, "max", "cannot disable sve1024", "{ 'sve1024': false }");
  269. assert_sve_vls(qts, "max", 0xff, "{ 'sve1024': true }");
  270. /*
  271. * Enabling anything larger than max-vq set by sve-max-vq is not
  272. * allowed, but of course disabling everything larger is OK.
  273. */
  274. assert_error(qts, "max", "cannot enable sve1152", "{ 'sve1152': true }");
  275. assert_sve_vls(qts, "max", 0xff, "{ 'sve1152': false }");
  276. /*
  277. * We can enable/disable non power-of-two lengths smaller than the
  278. * max-vq set by sve-max-vq, but, while we can enable power-of-two
  279. * lengths, we can't disable them.
  280. */
  281. assert_sve_vls(qts, "max", 0xff, "{ 'sve384': true }");
  282. assert_sve_vls(qts, "max", 0xfb, "{ 'sve384': false }");
  283. assert_sve_vls(qts, "max", 0xff, "{ 'sve256': true }");
  284. assert_error(qts, "max", "cannot disable sve256", "{ 'sve256': false }");
  285. qtest_quit(qts);
  286. }
  287. static void sve_tests_sve_off(const void *data)
  288. {
  289. QTestState *qts;
  290. qts = qtest_init(MACHINE "-cpu max,sve=off");
  291. /* SVE is off, so the map should be empty. */
  292. assert_sve_vls(qts, "max", 0, NULL);
  293. /* The map stays empty even if we turn lengths off. */
  294. assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
  295. /* It's an error to enable lengths when SVE is off. */
  296. assert_error(qts, "max", "cannot enable sve128", "{ 'sve128': true }");
  297. /* With SVE re-enabled we should get all vector lengths enabled. */
  298. assert_sve_vls(qts, "max", BIT_ULL(SVE_MAX_VQ) - 1, "{ 'sve': true }");
  299. /* Or enable SVE with just specific vector lengths. */
  300. assert_sve_vls(qts, "max", 0x3,
  301. "{ 'sve': true, 'sve128': true, 'sve256': true }");
  302. qtest_quit(qts);
  303. }
  304. static void sve_tests_sve_off_kvm(const void *data)
  305. {
  306. QTestState *qts;
  307. qts = qtest_init(MACHINE_KVM "-cpu max,sve=off");
  308. /*
  309. * We don't know if this host supports SVE so we don't
  310. * attempt to test enabling anything. We only test that
  311. * everything is disabled (as it should be with sve=off)
  312. * and that using sve<N>=off to explicitly disable vector
  313. * lengths is OK too.
  314. */
  315. assert_sve_vls(qts, "max", 0, NULL);
  316. assert_sve_vls(qts, "max", 0, "{ 'sve128': false }");
  317. qtest_quit(qts);
  318. }
  319. static void test_query_cpu_model_expansion(const void *data)
  320. {
  321. QTestState *qts;
  322. qts = qtest_init(MACHINE "-cpu max");
  323. /* Test common query-cpu-model-expansion input validation */
  324. assert_type_full(qts);
  325. assert_bad_props(qts, "max");
  326. assert_error(qts, "foo", "The CPU type 'foo' is not a recognized "
  327. "ARM CPU type", NULL);
  328. assert_error(qts, "max", "Parameter 'not-a-prop' is unexpected",
  329. "{ 'not-a-prop': false }");
  330. assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
  331. /* Test expected feature presence/absence for some cpu types */
  332. assert_has_feature(qts, "max", "pmu");
  333. assert_has_feature(qts, "cortex-a15", "pmu");
  334. assert_has_not_feature(qts, "cortex-a15", "aarch64");
  335. if (g_str_equal(qtest_get_arch(), "aarch64")) {
  336. assert_has_feature(qts, "max", "aarch64");
  337. assert_has_feature(qts, "max", "sve");
  338. assert_has_feature(qts, "max", "sve128");
  339. assert_has_feature(qts, "cortex-a57", "pmu");
  340. assert_has_feature(qts, "cortex-a57", "aarch64");
  341. sve_tests_default(qts, "max");
  342. /* Test that features that depend on KVM generate errors without. */
  343. assert_error(qts, "max",
  344. "'aarch64' feature cannot be disabled "
  345. "unless KVM is enabled and 32-bit EL1 "
  346. "is supported",
  347. "{ 'aarch64': false }");
  348. }
  349. qtest_quit(qts);
  350. }
  351. static void test_query_cpu_model_expansion_kvm(const void *data)
  352. {
  353. QTestState *qts;
  354. qts = qtest_init(MACHINE_KVM "-cpu max");
  355. /*
  356. * These tests target the 'host' CPU type, so KVM must be enabled.
  357. */
  358. if (!kvm_enabled(qts)) {
  359. qtest_quit(qts);
  360. return;
  361. }
  362. if (g_str_equal(qtest_get_arch(), "aarch64")) {
  363. bool kvm_supports_sve;
  364. char max_name[8], name[8];
  365. uint32_t max_vq, vq;
  366. uint64_t vls;
  367. QDict *resp;
  368. char *error;
  369. assert_has_feature(qts, "host", "aarch64");
  370. assert_has_feature(qts, "host", "pmu");
  371. assert_error(qts, "cortex-a15",
  372. "We cannot guarantee the CPU type 'cortex-a15' works "
  373. "with KVM on this host", NULL);
  374. assert_has_feature(qts, "host", "sve");
  375. resp = do_query_no_props(qts, "host");
  376. kvm_supports_sve = resp_get_feature(resp, "sve");
  377. vls = resp_get_sve_vls(resp);
  378. qobject_unref(resp);
  379. if (kvm_supports_sve) {
  380. g_assert(vls != 0);
  381. max_vq = 64 - __builtin_clzll(vls);
  382. sprintf(max_name, "sve%d", max_vq * 128);
  383. /* Enabling a supported length is of course fine. */
  384. assert_sve_vls(qts, "host", vls, "{ %s: true }", max_name);
  385. /* Get the next supported length smaller than max-vq. */
  386. vq = 64 - __builtin_clzll(vls & ~BIT_ULL(max_vq - 1));
  387. if (vq) {
  388. /*
  389. * We have at least one length smaller than max-vq,
  390. * so we can disable max-vq.
  391. */
  392. assert_sve_vls(qts, "host", (vls & ~BIT_ULL(max_vq - 1)),
  393. "{ %s: false }", max_name);
  394. /*
  395. * Smaller, supported vector lengths cannot be disabled
  396. * unless all larger, supported vector lengths are also
  397. * disabled.
  398. */
  399. sprintf(name, "sve%d", vq * 128);
  400. error = g_strdup_printf("cannot disable %s", name);
  401. assert_error(qts, "host", error,
  402. "{ %s: true, %s: false }",
  403. max_name, name);
  404. g_free(error);
  405. }
  406. /*
  407. * The smallest, supported vector length is required, because
  408. * we need at least one vector length enabled.
  409. */
  410. vq = __builtin_ffsll(vls);
  411. sprintf(name, "sve%d", vq * 128);
  412. error = g_strdup_printf("cannot disable %s", name);
  413. assert_error(qts, "host", error, "{ %s: false }", name);
  414. g_free(error);
  415. /* Get an unsupported length. */
  416. for (vq = 1; vq <= max_vq; ++vq) {
  417. if (!(vls & BIT_ULL(vq - 1))) {
  418. break;
  419. }
  420. }
  421. if (vq <= SVE_MAX_VQ) {
  422. sprintf(name, "sve%d", vq * 128);
  423. error = g_strdup_printf("cannot enable %s", name);
  424. assert_error(qts, "host", error, "{ %s: true }", name);
  425. g_free(error);
  426. }
  427. } else {
  428. g_assert(vls == 0);
  429. }
  430. } else {
  431. assert_has_not_feature(qts, "host", "aarch64");
  432. assert_has_not_feature(qts, "host", "pmu");
  433. assert_has_not_feature(qts, "host", "sve");
  434. }
  435. qtest_quit(qts);
  436. }
  437. int main(int argc, char **argv)
  438. {
  439. g_test_init(&argc, &argv, NULL);
  440. qtest_add_data_func("/arm/query-cpu-model-expansion",
  441. NULL, test_query_cpu_model_expansion);
  442. /*
  443. * For now we only run KVM specific tests with AArch64 QEMU in
  444. * order avoid attempting to run an AArch32 QEMU with KVM on
  445. * AArch64 hosts. That won't work and isn't easy to detect.
  446. */
  447. if (g_str_equal(qtest_get_arch(), "aarch64")) {
  448. qtest_add_data_func("/arm/kvm/query-cpu-model-expansion",
  449. NULL, test_query_cpu_model_expansion_kvm);
  450. }
  451. if (g_str_equal(qtest_get_arch(), "aarch64")) {
  452. qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-max-vq-8",
  453. NULL, sve_tests_sve_max_vq_8);
  454. qtest_add_data_func("/arm/max/query-cpu-model-expansion/sve-off",
  455. NULL, sve_tests_sve_off);
  456. qtest_add_data_func("/arm/kvm/query-cpu-model-expansion/sve-off",
  457. NULL, sve_tests_sve_off_kvm);
  458. }
  459. return g_test_run();
  460. }