diff options
Diffstat (limited to 'platform/linux-generic/odp_system_info.c')
-rw-r--r-- | platform/linux-generic/odp_system_info.c | 382 |
1 files changed, 287 insertions, 95 deletions
diff --git a/platform/linux-generic/odp_system_info.c b/platform/linux-generic/odp_system_info.c index 40ffca078..c31068492 100644 --- a/platform/linux-generic/odp_system_info.c +++ b/platform/linux-generic/odp_system_info.c @@ -1,27 +1,26 @@ -/* Copyright (c) 2013, Linaro Limited - * All rights reserved. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2013-2018 Linaro Limited + * Copyright (c) 2020-2022 Nokia * - * SPDX-License-Identifier: BSD-3-Clause - */ - -/* - * BSD LICENSE - * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. - * All rights reserved. + * Copyright(c) 2010-2014 Intel Corporation + * - lib/eal/common/eal_common_string_fns.c + * - lib/eal/linux/eal_hugepage_info.c */ #include <odp_posix_extensions.h> #include <odp/api/system_info.h> #include <odp/api/version.h> -#include <odp_internal.h> +#include <odp_global_data.h> +#include <odp_sysinfo_internal.h> +#include <odp_init_internal.h> +#include <odp_libconfig_internal.h> #include <odp_debug_internal.h> +#include <odp_config_internal.h> #include <odp/api/align.h> #include <odp/api/cpu.h> + #include <errno.h> -#include <pthread.h> -#include <sched.h> #include <string.h> #include <stdio.h> #include <inttypes.h> @@ -39,19 +38,9 @@ "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size" /* - * Report the number of logical CPUs detected at boot time - */ -static int sysconf_cpu_count(void) -{ - return odp_global_data.num_cpus_installed; -} - -#if defined __x86_64__ || defined __i386__ || defined __OCTEON__ || \ -defined __powerpc__ -/* * Analysis of /sys/devices/system/cpu/ files */ -static int systemcpu_cache_line_size(void) +static int read_cache_line_size(void) { FILE *file; char str[128]; @@ -60,7 +49,9 @@ static int systemcpu_cache_line_size(void) file = fopen(CACHE_LNSZ_FILE, "rt"); if (file == NULL) { /* File not found */ - return 0; + _ODP_WARN("Unable to read host CPU cache line size. " + "Using ODP_CACHE_LINE_SIZE instead.\n"); + return ODP_CACHE_LINE_SIZE; } if (fgets(str, sizeof(str), file) != NULL) { @@ -74,17 +65,6 @@ static int systemcpu_cache_line_size(void) return size; } -#else -/* - * Use dummy data if not available from /sys/devices/system/cpu/ - */ -static int systemcpu_cache_line_size(void) -{ - return 64; -} -#endif - - static uint64_t default_huge_page_size(void) { char str[1024]; @@ -92,16 +72,18 @@ static uint64_t default_huge_page_size(void) FILE *file; file = fopen("/proc/meminfo", "rt"); + if (!file) + return 0; while (fgets(str, sizeof(str), file) != NULL) { if (sscanf(str, "Hugepagesize: %8lu kB", &sz) == 1) { - ODP_DBG("defaut hp size is %" PRIu64 " kB\n", sz); + _ODP_DBG("default hp size is %lu kB\n", sz); fclose(file); return (uint64_t)sz * 1024; } } - ODP_ERR("unable to get default hp size\n"); + _ODP_ERR("unable to get default hp size\n"); fclose(file); return 0; } @@ -227,7 +209,7 @@ static char *get_hugepage_dir(uint64_t hugepage_sz) while (fgets(buf, sizeof(buf), fd)) { if (strsplit(buf, sizeof(buf), tokens, _FIELDNAME_MAX, split_tok) != _FIELDNAME_MAX) { - ODP_ERR("Error parsing %s\n", proc_mounts); + _ODP_ERR("Error parsing %s\n", proc_mounts); break; /* return NULL */ } @@ -241,11 +223,9 @@ static char *get_hugepage_dir(uint64_t hugepage_sz) retval = strdup(tokens[MOUNTPT]); break; } - } - /* there is an explicit page size, so check it */ - else { - pagesz = - str_to_size(&pagesz_str[pagesize_opt_len]); + } else { + /* there is an explicit page size, so check it */ + pagesz = str_to_size(&pagesz_str[pagesize_opt_len]); if (pagesz == hugepage_sz) { retval = strdup(tokens[MOUNTPT]); break; @@ -259,33 +239,61 @@ static char *get_hugepage_dir(uint64_t hugepage_sz) } /* - * Analysis of /sys/devices/system/cpu/ files + * Analysis of /sys/devices/system/cpu/cpu%d/cpufreq/ files */ -static int systemcpu(system_info_t *sysinfo) +static uint64_t read_cpufreq(const char *filename, int id) { - int ret; + char path[256], buffer[256], *endptr = NULL; + FILE *file; + uint64_t ret = 0; - ret = sysconf_cpu_count(); - if (ret == 0) { - ODP_ERR("sysconf_cpu_count failed.\n"); - return -1; - } + snprintf(path, sizeof(path), + "/sys/devices/system/cpu/cpu%d/cpufreq/%s", id, filename); - sysinfo->cpu_count = ret; + file = fopen(path, "r"); + if (file == NULL) + return ret; + if (fgets(buffer, sizeof(buffer), file) != NULL) + ret = strtoull(buffer, &endptr, 0) * 1000; - ret = systemcpu_cache_line_size(); + fclose(file); + + return ret; +} + +static inline uint64_t cpu_hz_current(int id) +{ + uint64_t cur_hz = read_cpufreq("cpuinfo_cur_freq", id); + + if (!cur_hz) + cur_hz = odp_cpu_arch_hz_current(id); + + return cur_hz; +} + +static inline uint64_t cpu_hz_static(int id) +{ + return odp_global_ro.system_info.cpu_hz[id]; +} + +/* + * Analysis of /sys/devices/system/cpu/ files + */ +static int system_cache_line(system_info_t *sysinfo) +{ + int ret; + + ret = read_cache_line_size(); if (ret == 0) { - ODP_ERR("systemcpu_cache_line_size failed.\n"); + _ODP_ERR("read_cache_line_size failed.\n"); return -1; } sysinfo->cache_line_size = ret; - if (ret != ODP_CACHE_LINE_SIZE) { - ODP_ERR("Cache line sizes definitions don't match.\n"); - return -1; - } + if (ret != ODP_CACHE_LINE_SIZE) + _ODP_WARN("Host CPU cache line size and ODP_CACHE_LINE_SIZE don't match.\n"); return 0; } @@ -303,33 +311,103 @@ static int system_hp(hugepage_info_t *hugeinfo) return 0; } +static int read_config_file(void) +{ + const char *str; + int val = 0; + + str = "system.cpu_mhz"; + if (!_odp_libconfig_lookup_int(str, &val)) { + _ODP_ERR("Config option '%s' not found.\n", str); + return -1; + } + odp_global_ro.system_info.default_cpu_hz = (uint64_t)val * 1000000; + + str = "system.cpu_mhz_max"; + if (!_odp_libconfig_lookup_int(str, &val)) { + _ODP_ERR("Config option '%s' not found.\n", str); + return -1; + } + odp_global_ro.system_info.default_cpu_hz_max = (uint64_t)val * 1000000; + + str = "system.cpu_hz_static"; + if (!_odp_libconfig_lookup_int(str, &val)) { + _ODP_ERR("Config option '%s' not found.\n", str); + return -1; + } + odp_global_ro.system_info.cpu_hz_static = !!val; + + return 0; +} + +static void print_compiler_info(void) +{ + _ODP_PRINT("Compiler defines:\n"); + _ODP_PRINT(" __GCC_ATOMIC_LLONG_LOCK_FREE: %d\n", __GCC_ATOMIC_LLONG_LOCK_FREE); + _ODP_PRINT(" __GCC_ATOMIC_LONG_LOCK_FREE: %d\n", __GCC_ATOMIC_LONG_LOCK_FREE); + _ODP_PRINT(" __GCC_ATOMIC_INT_LOCK_FREE: %d\n", __GCC_ATOMIC_INT_LOCK_FREE); + _ODP_PRINT(" __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16: "); +#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16 + _ODP_PRINT("1\n"); +#else + _ODP_PRINT("0\n"); +#endif + _ODP_PRINT("\n"); +} + /* * System info initialisation */ -int odp_system_info_init(void) +int _odp_system_info_init(void) { + int num_cpus; + int i; FILE *file; - memset(&odp_global_data.system_info, 0, sizeof(system_info_t)); + memset(&odp_global_ro.system_info, 0, sizeof(system_info_t)); - odp_global_data.system_info.page_size = ODP_PAGE_SIZE; + odp_global_ro.system_info.page_size = ODP_PAGE_SIZE; - file = fopen("/proc/cpuinfo", "rt"); - if (file == NULL) { - ODP_ERR("Failed to open /proc/cpuinfo\n"); + /* Read default CPU Hz values from config file */ + if (read_config_file()) return -1; - } - cpuinfo_parser(file, &odp_global_data.system_info); + /* Check that CONFIG_NUM_CPU_IDS is large enough */ + num_cpus = get_nprocs_conf(); + if (num_cpus > CONFIG_NUM_CPU_IDS) + _ODP_ERR("Unable to handle all %d " + "CPU IDs. Increase CONFIG_NUM_CPU_IDS value.\n", + num_cpus); - fclose(file); + /* Read and save all CPU frequencies for static mode */ + if (odp_global_ro.system_info.cpu_hz_static) + for (i = 0; i < CONFIG_NUM_CPU_IDS; i++) + odp_global_ro.system_info.cpu_hz[i] = cpu_hz_current(i); - if (systemcpu(&odp_global_data.system_info)) { - ODP_ERR("systemcpu failed\n"); - return -1; + /* By default, read max frequency from a cpufreq file */ + for (i = 0; i < CONFIG_NUM_CPU_IDS; i++) { + uint64_t cpu_hz_max = read_cpufreq("cpuinfo_max_freq", i); + + if (cpu_hz_max) + odp_global_ro.system_info.cpu_hz_max[i] = cpu_hz_max; } - system_hp(&odp_global_data.hugepage_info); + file = fopen("/proc/cpuinfo", "rt"); + if (file != NULL) { + /* Read CPU model, and set max cpu frequency + * if not set from cpufreq. */ + _odp_cpuinfo_parser(file, &odp_global_ro.system_info); + fclose(file); + } else { + _odp_dummy_cpuinfo(&odp_global_ro.system_info); + } + + if (system_cache_line(&odp_global_ro.system_info)) + return -1; + + system_hp(&odp_global_ro.hugepage_info); + + print_compiler_info(); return 0; } @@ -337,9 +415,9 @@ int odp_system_info_init(void) /* * System info termination */ -int odp_system_info_term(void) +int _odp_system_info_term(void) { - free(odp_global_data.hugepage_info.default_huge_page_dir); + free(odp_global_ro.hugepage_info.default_huge_page_dir); return 0; } @@ -351,14 +429,20 @@ int odp_system_info_term(void) */ uint64_t odp_cpu_hz(void) { - int id = sched_getcpu(); + int id = odp_cpu_id(); - return odp_cpu_hz_current(id); + if (odp_global_ro.system_info.cpu_hz_static) + return cpu_hz_static(id); + return cpu_hz_current(id); } uint64_t odp_cpu_hz_id(int id) { - return odp_cpu_hz_current(id); + _ODP_ASSERT(id >= 0 && id < CONFIG_NUM_CPU_IDS); + + if (odp_global_ro.system_info.cpu_hz_static) + return cpu_hz_static(id); + return cpu_hz_current(id); } uint64_t odp_cpu_hz_max(void) @@ -368,20 +452,63 @@ uint64_t odp_cpu_hz_max(void) uint64_t odp_cpu_hz_max_id(int id) { - if (id >= 0 && id < MAX_CPU_NUMBER) - return odp_global_data.system_info.cpu_hz_max[id]; + if (id >= 0 && id < CONFIG_NUM_CPU_IDS) + return odp_global_ro.system_info.cpu_hz_max[id]; else return 0; } uint64_t odp_sys_huge_page_size(void) { - return odp_global_data.hugepage_info.default_huge_page_size; + return odp_global_ro.hugepage_info.default_huge_page_size; +} + +static int pagesz_compare(const void *pagesz1, const void *pagesz2) +{ + const uint64_t val1 = *(const uint64_t *)pagesz1; + const uint64_t val2 = *(const uint64_t *)pagesz2; + + if (val1 < val2) + return -1; + if (val1 > val2) + return 1; + return 0; +} + +int odp_sys_huge_page_size_all(uint64_t size[], int num) +{ + DIR *dir; + struct dirent *entry; + int pagesz_num = 0; + int saved = 0; + + /* See: kernel.org: hugetlbpage.txt */ + dir = opendir("/sys/kernel/mm/hugepages"); + if (!dir) { + _ODP_PRINT("Failed to open /sys/kernel/mm/hugepages: %s\n", strerror(errno)); + return 0; + } + + while ((entry = readdir(dir)) != NULL) { + unsigned long sz; + + if (sscanf(entry->d_name, "hugepages-%8lukB", &sz) == 1) { + if (size != NULL && saved < num) + size[saved++] = sz * 1024; + pagesz_num++; + } + } + closedir(dir); + + if (size != NULL && saved > 1) + qsort(size, saved, sizeof(uint64_t), pagesz_compare); + + return pagesz_num; } uint64_t odp_sys_page_size(void) { - return odp_global_data.system_info.page_size; + return odp_global_ro.system_info.page_size; } const char *odp_cpu_model_str(void) @@ -391,47 +518,112 @@ const char *odp_cpu_model_str(void) const char *odp_cpu_model_str_id(int id) { - if (id >= 0 && id < MAX_CPU_NUMBER) - return odp_global_data.system_info.model_str[id]; + if (id >= 0 && id < CONFIG_NUM_CPU_IDS) + return odp_global_ro.system_info.model_str[id]; else return NULL; } int odp_sys_cache_line_size(void) { - return odp_global_data.system_info.cache_line_size; + return odp_global_ro.system_info.cache_line_size; } int odp_cpu_count(void) { - return odp_global_data.system_info.cpu_count; + return odp_global_ro.num_cpus_installed; +} + +int odp_system_info(odp_system_info_t *info) +{ + system_info_t *sys_info = &odp_global_ro.system_info; + + memset(info, 0, sizeof(odp_system_info_t)); + + info->cpu_arch = sys_info->cpu_arch; + info->cpu_isa_sw = sys_info->cpu_isa_sw; + info->cpu_isa_hw = sys_info->cpu_isa_hw; + + return 0; } void odp_sys_info_print(void) { - int len; + int len, num_cpu; int max_len = 512; + odp_cpumask_t cpumask; + char cpumask_str[ODP_CPUMASK_STR_SIZE]; char str[max_len]; + memset(cpumask_str, 0, sizeof(cpumask_str)); + + num_cpu = odp_cpumask_all_available(&cpumask); + odp_cpumask_to_str(&cpumask, cpumask_str, ODP_CPUMASK_STR_SIZE); + len = snprintf(str, max_len, "\n" "ODP system info\n" "---------------\n" - "ODP API version: %s\n" - "ODP impl name: %s\n" - "CPU model: %s\n" - "CPU freq (hz): %" PRIu64 "\n" - "Cache line size: %i\n" - "CPU count: %i\n" + "ODP API version: %s\n" + "ODP impl name: %s\n" + "ODP impl details: %s\n" + "CPU model: %s\n" + "CPU freq (hz): %" PRIu64 "\n" + "Cache line size: %i\n" + "CPU count: %i\n" + "CPU mask: %s\n" "\n", odp_version_api_str(), odp_version_impl_name(), + odp_version_impl_str(), odp_cpu_model_str(), odp_cpu_hz_max(), odp_sys_cache_line_size(), - odp_cpu_count()); + num_cpu, cpumask_str); str[len] = '\0'; - ODP_PRINT("%s", str); + _ODP_PRINT("%s", str); - sys_info_print_arch(); + _odp_sys_info_print_arch(); +} + +void odp_sys_config_print(void) +{ + /* Print ODP_CONFIG_FILE default and override values */ + if (_odp_libconfig_print()) + _ODP_ERR("Config file print failed\n"); + + _ODP_PRINT("\n\nodp_config_internal.h values:\n" + "-----------------------------\n"); + _ODP_PRINT("CONFIG_NUM_CPU_IDS: %i\n", CONFIG_NUM_CPU_IDS); + _ODP_PRINT("CONFIG_INTERNAL_QUEUES: %i\n", CONFIG_INTERNAL_QUEUES); + _ODP_PRINT("CONFIG_MAX_PLAIN_QUEUES: %i\n", CONFIG_MAX_PLAIN_QUEUES); + _ODP_PRINT("CONFIG_MAX_SCHED_QUEUES: %i\n", CONFIG_MAX_SCHED_QUEUES); + _ODP_PRINT("CONFIG_MAX_QUEUES: %i\n", CONFIG_MAX_QUEUES); + _ODP_PRINT("CONFIG_QUEUE_MAX_ORD_LOCKS: %i\n", CONFIG_QUEUE_MAX_ORD_LOCKS); + _ODP_PRINT("CONFIG_MAX_DMA_SESSIONS: %i\n", CONFIG_MAX_DMA_SESSIONS); + _ODP_PRINT("CONFIG_INTERNAL_STASHES: %i\n", CONFIG_INTERNAL_STASHES); + _ODP_PRINT("CONFIG_MAX_STASHES: %i\n", CONFIG_MAX_STASHES); + _ODP_PRINT("CONFIG_PKTIO_ENTRIES: %i\n", CONFIG_PKTIO_ENTRIES); + _ODP_PRINT("CONFIG_BUFFER_ALIGN_MAX: %i\n", CONFIG_BUFFER_ALIGN_MAX); + _ODP_PRINT("CONFIG_PACKET_HEADROOM: %i\n", CONFIG_PACKET_HEADROOM); + _ODP_PRINT("CONFIG_PACKET_TAILROOM: %i\n", CONFIG_PACKET_TAILROOM); + _ODP_PRINT("CONFIG_PACKET_SEG_SIZE: %i\n", CONFIG_PACKET_SEG_SIZE); + _ODP_PRINT("CONFIG_PACKET_MAX_SEG_LEN: %i\n", CONFIG_PACKET_MAX_SEG_LEN); + _ODP_PRINT("CONFIG_PACKET_SEG_LEN_MIN: %i\n", CONFIG_PACKET_SEG_LEN_MIN); + _ODP_PRINT("CONFIG_PACKET_VECTOR_MAX_SIZE: %i\n", CONFIG_PACKET_VECTOR_MAX_SIZE); + _ODP_PRINT("CONFIG_INTERNAL_SHM_BLOCKS: %i\n", CONFIG_INTERNAL_SHM_BLOCKS); + _ODP_PRINT("CONFIG_SHM_BLOCKS: %i\n", CONFIG_SHM_BLOCKS); + _ODP_PRINT("CONFIG_BURST_SIZE: %i\n", CONFIG_BURST_SIZE); + _ODP_PRINT("CONFIG_INTERNAL_POOLS: %i\n", CONFIG_INTERNAL_POOLS); + _ODP_PRINT("CONFIG_POOLS: %i\n", CONFIG_POOLS); + _ODP_PRINT("CONFIG_POOL_MAX_NUM: %i\n", CONFIG_POOL_MAX_NUM); + _ODP_PRINT("CONFIG_POOL_CACHE_MAX_SIZE: %i\n", CONFIG_POOL_CACHE_MAX_SIZE); + _ODP_PRINT("CONFIG_POOL_STATISTICS: %i\n", CONFIG_POOL_STATISTICS); + _ODP_PRINT("CONFIG_IPSEC_MAX_NUM_SA: %i\n", CONFIG_IPSEC_MAX_NUM_SA); + _ODP_PRINT("CONFIG_TIMER_128BIT_ATOMICS: %i\n", CONFIG_TIMER_128BIT_ATOMICS); + _ODP_PRINT("CONFIG_TIMER_PROFILE_INLINE: %i\n", CONFIG_TIMER_PROFILE_INLINE); + _ODP_PRINT("CONFIG_ML_MAX_MODELS: %i\n", CONFIG_ML_MAX_MODELS); + _ODP_PRINT("CONFIG_ML_MAX_INPUTS: %i\n", CONFIG_ML_MAX_INPUTS); + _ODP_PRINT("CONFIG_ML_MAX_OUTPUTS: %i\n", CONFIG_ML_MAX_OUTPUTS); + _ODP_PRINT("\n"); } |