mirror of https://github.com/F-Stack/f-stack.git
102 lines
2.3 KiB
C
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 */
|