eal/riscv: support RISC-V architecture
[dpdk.git] / lib / eal / riscv / rte_cycles.c
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
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         RTE_LOG(WARNING, EAL, "Unable to read timebase-frequency from FDT.\n");
42         return 0;
43 }
44
45 uint64_t
46 get_tsc_freq_arch(void)
47 {
48         RTE_LOG(NOTICE, EAL, "TSC using RISC-V %s.\n",
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 }