xref: /dpdk/lib/eal/riscv/rte_cycles.c (revision ae67895b507bb6af22263c79ba0d5c374b396485)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2015 Cavium, Inc
3  * Copyright(c) 2022 StarFive
4  * Copyright(c) 2022 SiFive
5  * Copyright(c) 2022 Semihalf
6  */
7 
8 #include <stdio.h>
9 
10 #include "eal_private.h"
11 #include "rte_byteorder.h"
12 #include "rte_cycles.h"
13 #include "rte_log.h"
14 
15 /** Read generic counter frequency */
16 static uint64_t
__rte_riscv_timefrq(void)17 __rte_riscv_timefrq(void)
18 {
19 #define TIMEBASE_FREQ_SIZE	8
20 	if (RTE_RISCV_TIME_FREQ > 0)
21 		return RTE_RISCV_TIME_FREQ;
22 	uint8_t buf[TIMEBASE_FREQ_SIZE];
23 	ssize_t cnt;
24 	FILE *file;
25 
26 	file = fopen("/proc/device-tree/cpus/timebase-frequency", "rb");
27 	if (!file)
28 		goto fail;
29 
30 	cnt = fread(buf, 1, TIMEBASE_FREQ_SIZE, file);
31 	fclose(file);
32 	switch (cnt) {
33 	case 8:
34 		return rte_be_to_cpu_64(*(uint64_t *)buf);
35 	case 4:
36 		return rte_be_to_cpu_32(*(uint32_t *)buf);
37 	default:
38 		break;
39 	}
40 fail:
41 	EAL_LOG(WARNING, "Unable to read timebase-frequency from FDT.");
42 	return 0;
43 }
44 
45 uint64_t
get_tsc_freq_arch(void)46 get_tsc_freq_arch(void)
47 {
48 	EAL_LOG(NOTICE, "TSC using RISC-V %s.",
49 		RTE_RISCV_RDTSC_USE_HPM ? "rdcycle" : "rdtime");
50 	if (!RTE_RISCV_RDTSC_USE_HPM)
51 		return __rte_riscv_timefrq();
52 #define CYC_PER_1MHZ 1E6
53 	/*
54 	 * Use real time clock to estimate current cycle frequency
55 	 */
56 	uint64_t ticks, frq;
57 	uint64_t start_ticks, cur_ticks;
58 	uint64_t start_cycle, end_cycle;
59 
60 	/* Do not proceed unless clock frequency can be obtained. */
61 	frq = __rte_riscv_timefrq();
62 	if (!frq)
63 		return 0;
64 
65 	/* Number of ticks for 1/10 second */
66 	ticks = frq / 10;
67 
68 	start_ticks = __rte_riscv_rdtime_precise();
69 	start_cycle = rte_rdtsc_precise();
70 	do {
71 		cur_ticks = __rte_riscv_rdtime();
72 	} while ((cur_ticks - start_ticks) < ticks);
73 	end_cycle = rte_rdtsc_precise();
74 
75 	/* Adjust the cycles to next 1Mhz */
76 	return RTE_ALIGN_MUL_CEIL((end_cycle - start_cycle) * 10, CYC_PER_1MHZ);
77 }
78