topology.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <perf/cpumap.h>
  6. #include "cpumap.h"
  7. #include "tests.h"
  8. #include "session.h"
  9. #include "evlist.h"
  10. #include "debug.h"
  11. #include <linux/err.h>
  12. #define TEMPL "/tmp/perf-test-XXXXXX"
  13. #define DATA_SIZE 10
  14. static int get_temp(char *path)
  15. {
  16. int fd;
  17. strcpy(path, TEMPL);
  18. fd = mkstemp(path);
  19. if (fd < 0) {
  20. perror("mkstemp failed");
  21. return -1;
  22. }
  23. close(fd);
  24. return 0;
  25. }
  26. static int session_write_header(char *path)
  27. {
  28. struct perf_session *session;
  29. struct perf_data data = {
  30. .path = path,
  31. .mode = PERF_DATA_MODE_WRITE,
  32. };
  33. session = perf_session__new(&data, false, NULL);
  34. TEST_ASSERT_VAL("can't get session", !IS_ERR(session));
  35. session->evlist = perf_evlist__new_default();
  36. TEST_ASSERT_VAL("can't get evlist", session->evlist);
  37. perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
  38. perf_header__set_feat(&session->header, HEADER_NRCPUS);
  39. perf_header__set_feat(&session->header, HEADER_ARCH);
  40. session->header.data_size += DATA_SIZE;
  41. TEST_ASSERT_VAL("failed to write header",
  42. !perf_session__write_header(session, session->evlist, data.file.fd, true));
  43. evlist__delete(session->evlist);
  44. perf_session__delete(session);
  45. return 0;
  46. }
  47. static int check_cpu_topology(char *path, struct perf_cpu_map *map)
  48. {
  49. struct perf_session *session;
  50. struct perf_data data = {
  51. .path = path,
  52. .mode = PERF_DATA_MODE_READ,
  53. };
  54. int i;
  55. session = perf_session__new(&data, false, NULL);
  56. TEST_ASSERT_VAL("can't get session", !IS_ERR(session));
  57. /* On platforms with large numbers of CPUs process_cpu_topology()
  58. * might issue an error while reading the perf.data file section
  59. * HEADER_CPU_TOPOLOGY and the cpu_topology_map pointed to by member
  60. * cpu is a NULL pointer.
  61. * Example: On s390
  62. * CPU 0 is on core_id 0 and physical_package_id 6
  63. * CPU 1 is on core_id 1 and physical_package_id 3
  64. *
  65. * Core_id and physical_package_id are platform and architecture
  66. * dependend and might have higher numbers than the CPU id.
  67. * This actually depends on the configuration.
  68. *
  69. * In this case process_cpu_topology() prints error message:
  70. * "socket_id number is too big. You may need to upgrade the
  71. * perf tool."
  72. *
  73. * This is the reason why this test might be skipped.
  74. */
  75. if (!session->header.env.cpu)
  76. return TEST_SKIP;
  77. for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
  78. if (!cpu_map__has(map, i))
  79. continue;
  80. pr_debug("CPU %d, core %d, socket %d\n", i,
  81. session->header.env.cpu[i].core_id,
  82. session->header.env.cpu[i].socket_id);
  83. }
  84. for (i = 0; i < map->nr; i++) {
  85. TEST_ASSERT_VAL("Core ID doesn't match",
  86. (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff)));
  87. TEST_ASSERT_VAL("Socket ID doesn't match",
  88. (session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL)));
  89. }
  90. perf_session__delete(session);
  91. return 0;
  92. }
  93. int test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused)
  94. {
  95. char path[PATH_MAX];
  96. struct perf_cpu_map *map;
  97. int ret = TEST_FAIL;
  98. TEST_ASSERT_VAL("can't get templ file", !get_temp(path));
  99. pr_debug("templ file: %s\n", path);
  100. if (session_write_header(path))
  101. goto free_path;
  102. map = perf_cpu_map__new(NULL);
  103. if (map == NULL) {
  104. pr_debug("failed to get system cpumap\n");
  105. goto free_path;
  106. }
  107. ret = check_cpu_topology(path, map);
  108. perf_cpu_map__put(map);
  109. free_path:
  110. unlink(path);
  111. return ret;
  112. }