18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <string.h> 38c2ecf20Sopenharmony_ci#include <stdlib.h> 48c2ecf20Sopenharmony_ci#include <stdio.h> 58c2ecf20Sopenharmony_ci#include <perf/cpumap.h> 68c2ecf20Sopenharmony_ci#include "cpumap.h" 78c2ecf20Sopenharmony_ci#include "tests.h" 88c2ecf20Sopenharmony_ci#include "session.h" 98c2ecf20Sopenharmony_ci#include "evlist.h" 108c2ecf20Sopenharmony_ci#include "debug.h" 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define TEMPL "/tmp/perf-test-XXXXXX" 148c2ecf20Sopenharmony_ci#define DATA_SIZE 10 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic int get_temp(char *path) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci int fd; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci strcpy(path, TEMPL); 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci fd = mkstemp(path); 238c2ecf20Sopenharmony_ci if (fd < 0) { 248c2ecf20Sopenharmony_ci perror("mkstemp failed"); 258c2ecf20Sopenharmony_ci return -1; 268c2ecf20Sopenharmony_ci } 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci close(fd); 298c2ecf20Sopenharmony_ci return 0; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic int session_write_header(char *path) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci struct perf_session *session; 358c2ecf20Sopenharmony_ci struct perf_data data = { 368c2ecf20Sopenharmony_ci .path = path, 378c2ecf20Sopenharmony_ci .mode = PERF_DATA_MODE_WRITE, 388c2ecf20Sopenharmony_ci }; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci session = perf_session__new(&data, false, NULL); 418c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci session->evlist = perf_evlist__new_default(); 448c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("can't get evlist", session->evlist); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); 478c2ecf20Sopenharmony_ci perf_header__set_feat(&session->header, HEADER_NRCPUS); 488c2ecf20Sopenharmony_ci perf_header__set_feat(&session->header, HEADER_ARCH); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci session->header.data_size += DATA_SIZE; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("failed to write header", 538c2ecf20Sopenharmony_ci !perf_session__write_header(session, session->evlist, data.file.fd, true)); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci evlist__delete(session->evlist); 568c2ecf20Sopenharmony_ci perf_session__delete(session); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic int check_cpu_topology(char *path, struct perf_cpu_map *map) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct perf_session *session; 648c2ecf20Sopenharmony_ci struct perf_data data = { 658c2ecf20Sopenharmony_ci .path = path, 668c2ecf20Sopenharmony_ci .mode = PERF_DATA_MODE_READ, 678c2ecf20Sopenharmony_ci }; 688c2ecf20Sopenharmony_ci int i; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci session = perf_session__new(&data, false, NULL); 718c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* On platforms with large numbers of CPUs process_cpu_topology() 748c2ecf20Sopenharmony_ci * might issue an error while reading the perf.data file section 758c2ecf20Sopenharmony_ci * HEADER_CPU_TOPOLOGY and the cpu_topology_map pointed to by member 768c2ecf20Sopenharmony_ci * cpu is a NULL pointer. 778c2ecf20Sopenharmony_ci * Example: On s390 788c2ecf20Sopenharmony_ci * CPU 0 is on core_id 0 and physical_package_id 6 798c2ecf20Sopenharmony_ci * CPU 1 is on core_id 1 and physical_package_id 3 808c2ecf20Sopenharmony_ci * 818c2ecf20Sopenharmony_ci * Core_id and physical_package_id are platform and architecture 828c2ecf20Sopenharmony_ci * dependend and might have higher numbers than the CPU id. 838c2ecf20Sopenharmony_ci * This actually depends on the configuration. 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * In this case process_cpu_topology() prints error message: 868c2ecf20Sopenharmony_ci * "socket_id number is too big. You may need to upgrade the 878c2ecf20Sopenharmony_ci * perf tool." 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * This is the reason why this test might be skipped. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_ci if (!session->header.env.cpu) 928c2ecf20Sopenharmony_ci return TEST_SKIP; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci for (i = 0; i < session->header.env.nr_cpus_avail; i++) { 958c2ecf20Sopenharmony_ci if (!cpu_map__has(map, i)) 968c2ecf20Sopenharmony_ci continue; 978c2ecf20Sopenharmony_ci pr_debug("CPU %d, core %d, socket %d\n", i, 988c2ecf20Sopenharmony_ci session->header.env.cpu[i].core_id, 998c2ecf20Sopenharmony_ci session->header.env.cpu[i].socket_id); 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci for (i = 0; i < map->nr; i++) { 1038c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Core ID doesn't match", 1048c2ecf20Sopenharmony_ci (session->header.env.cpu[map->map[i]].core_id == (cpu_map__get_core(map, i, NULL) & 0xffff))); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("Socket ID doesn't match", 1078c2ecf20Sopenharmony_ci (session->header.env.cpu[map->map[i]].socket_id == cpu_map__get_socket(map, i, NULL))); 1088c2ecf20Sopenharmony_ci } 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci perf_session__delete(session); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return 0; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciint test__session_topology(struct test *test __maybe_unused, int subtest __maybe_unused) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci char path[PATH_MAX]; 1188c2ecf20Sopenharmony_ci struct perf_cpu_map *map; 1198c2ecf20Sopenharmony_ci int ret = TEST_FAIL; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci TEST_ASSERT_VAL("can't get templ file", !get_temp(path)); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci pr_debug("templ file: %s\n", path); 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci if (session_write_header(path)) 1268c2ecf20Sopenharmony_ci goto free_path; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci map = perf_cpu_map__new(NULL); 1298c2ecf20Sopenharmony_ci if (map == NULL) { 1308c2ecf20Sopenharmony_ci pr_debug("failed to get system cpumap\n"); 1318c2ecf20Sopenharmony_ci goto free_path; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci ret = check_cpu_topology(path, map); 1358c2ecf20Sopenharmony_ci perf_cpu_map__put(map); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cifree_path: 1388c2ecf20Sopenharmony_ci unlink(path); 1398c2ecf20Sopenharmony_ci return ret; 1408c2ecf20Sopenharmony_ci} 141