/*- * BSD LICENSE * * Copyright(c) 2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include "eal_private.h" static unsigned int rte_cpu_get_model(uint32_t fam_mod_step) { uint32_t family, model, ext_model; family = (fam_mod_step >> 8) & 0xf; model = (fam_mod_step >> 4) & 0xf; if (family == 6 || family == 15) { ext_model = (fam_mod_step >> 16) & 0xf; model += (ext_model << 4); } return model; } static int32_t rdmsr(int msr, uint64_t *val) { #ifdef RTE_EXEC_ENV_LINUXAPP int fd; int ret; fd = open("/dev/cpu/0/msr", O_RDONLY); if (fd < 0) return fd; ret = pread(fd, val, sizeof(uint64_t), msr); close(fd); return ret; #else RTE_SET_USED(msr); RTE_SET_USED(val); return -1; #endif } static uint32_t check_model_wsm_nhm(uint8_t model) { switch (model) { /* Westmere */ case 0x25: case 0x2C: case 0x2F: /* Nehalem */ case 0x1E: case 0x1F: case 0x1A: case 0x2E: return 1; } return 0; } static uint32_t check_model_gdm_dnv(uint8_t model) { switch (model) { /* Goldmont */ case 0x5C: /* Denverton */ case 0x5F: return 1; } return 0; } uint64_t get_tsc_freq_arch(void) { uint64_t tsc_hz = 0; uint32_t a, b, c, d, maxleaf; uint8_t mult, model; int32_t ret; /* * Time Stamp Counter and Nominal Core Crystal Clock * Information Leaf */ maxleaf = __get_cpuid_max(0, NULL); if (maxleaf >= 0x15) { __cpuid(0x15, a, b, c, d); /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */ if (b && c) return c * (b / a); } __cpuid(0x1, a, b, c, d); model = rte_cpu_get_model(a); if (check_model_wsm_nhm(model)) mult = 133; else if ((c & bit_AVX) || check_model_gdm_dnv(model)) mult = 100; else return 0; ret = rdmsr(0xCE, &tsc_hz); if (ret < 0) return 0; return ((tsc_hz >> 8) & 0xff) * mult * 1E6; }