f-stack/dpdk/lib/eal/riscv/include/rte_cycles.h

102 lines
2.3 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2015 Cavium, Inc
* Copyright(c) 2022 StarFive
* Copyright(c) 2022 SiFive
* Copyright(c) 2022 Semihalf
*/
#ifndef RTE_CYCLES_RISCV_H
#define RTE_CYCLES_RISCV_H
#ifdef __cplusplus
extern "C" {
#endif
#include "generic/rte_cycles.h"
#ifndef RTE_RISCV_RDTSC_USE_HPM
#define RTE_RISCV_RDTSC_USE_HPM 0
#endif
/** Read wall time counter */
static __rte_always_inline uint64_t
__rte_riscv_rdtime(void)
{
uint64_t tsc;
asm volatile("csrr %0, time" : "=r" (tsc) : : "memory");
return tsc;
}
/** Read wall time counter ensuring no re-ordering */
static __rte_always_inline uint64_t
__rte_riscv_rdtime_precise(void)
{
asm volatile("fence" : : : "memory");
return __rte_riscv_rdtime();
}
/** Read hart cycle counter */
static __rte_always_inline uint64_t
__rte_riscv_rdcycle(void)
{
uint64_t tsc;
asm volatile("csrr %0, cycle" : "=r" (tsc) : : "memory");
return tsc;
}
/** Read hart cycle counter ensuring no re-ordering */
static __rte_always_inline uint64_t
__rte_riscv_rdcycle_precise(void)
{
asm volatile("fence" : : : "memory");
return __rte_riscv_rdcycle();
}
/**
* Read the time base register.
*
* @return
* The time base for this lcore.
*/
static __rte_always_inline uint64_t
rte_rdtsc(void)
{
/**
* By default TIME userspace counter is used. It is stable and shared
* across cores. Although it's frequency may not be enough for all
* applications.
*/
if (!RTE_RISCV_RDTSC_USE_HPM)
return __rte_riscv_rdtime();
/**
* Alternatively HPM's CYCLE counter may be used. However this counter
* is not guaranteed by ISA to either be stable frequency or always
* enabled for userspace access (it may trap to kernel or firmware,
* though as of Linux kernel 5.13 it doesn't).
* It is also highly probable that values of this counter are not
* synchronized across cores. Therefore if it is to be used as a timer,
* it can only be used in the scope of a single core.
*/
return __rte_riscv_rdcycle();
}
static inline uint64_t
rte_rdtsc_precise(void)
{
if (!RTE_RISCV_RDTSC_USE_HPM)
return __rte_riscv_rdtime_precise();
return __rte_riscv_rdcycle_precise();
}
static __rte_always_inline uint64_t
rte_get_tsc_cycles(void)
{
return rte_rdtsc();
}
#ifdef __cplusplus
}
#endif
#endif /* RTE_CYCLES_RISCV_H */