topology.c 3.4 KB

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