1 /*
2  * Copyright (c) 2020 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/arch/x86/arch.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys_clock.h>
10 #include <zephyr/timing/timing.h>
11 #include <zephyr/app_memory/app_memdomain.h>
12 
K_APP_BMEM(z_libc_partition)13 K_APP_BMEM(z_libc_partition) static uint64_t tsc_freq;
14 
15 void arch_timing_x86_init(void)
16 {
17 	uint32_t cyc_start, cyc_end;
18 	uint64_t tsc_start, tsc_end;
19 	uint64_t cyc_freq = sys_clock_hw_cycles_per_sec();
20 	uint64_t dcyc, dtsc;
21 
22 	do {
23 		cyc_start = k_cycle_get_32();
24 		tsc_start = z_tsc_read();
25 
26 		k_busy_wait(10 * USEC_PER_MSEC);
27 
28 		cyc_end = k_cycle_get_32();
29 		tsc_end = z_tsc_read();
30 
31 		/*
32 		 * cycles are in 32-bit, and delta must be
33 		 * calculated in 32-bit precision. Or it would be
34 		 * wrapping around in 64-bit.
35 		 */
36 		dcyc = (uint32_t)cyc_end - (uint32_t)cyc_start;
37 		dtsc = tsc_end - tsc_start;
38 	} while ((dcyc == 0) || (dtsc == 0));
39 
40 	tsc_freq = (cyc_freq * dtsc) / dcyc;
41 }
42 
arch_timing_x86_freq_get(void)43 uint64_t arch_timing_x86_freq_get(void)
44 {
45 	return tsc_freq;
46 }
47 
arch_timing_init(void)48 void arch_timing_init(void)
49 {
50 	arch_timing_x86_init();
51 }
52 
arch_timing_start(void)53 void arch_timing_start(void)
54 {
55 }
56 
arch_timing_stop(void)57 void arch_timing_stop(void)
58 {
59 }
60 
arch_timing_counter_get(void)61 timing_t arch_timing_counter_get(void)
62 {
63 	return z_tsc_read();
64 }
65 
arch_timing_cycles_get(volatile timing_t * const start,volatile timing_t * const end)66 uint64_t arch_timing_cycles_get(volatile timing_t *const start,
67 				volatile timing_t *const end)
68 {
69 	return (*end - *start);
70 }
71 
72 
arch_timing_freq_get(void)73 uint64_t arch_timing_freq_get(void)
74 {
75 	return arch_timing_x86_freq_get();
76 }
77 
arch_timing_cycles_to_ns(uint64_t cycles)78 uint64_t arch_timing_cycles_to_ns(uint64_t cycles)
79 {
80 	return ((cycles) * NSEC_PER_SEC / tsc_freq);
81 }
82 
arch_timing_cycles_to_ns_avg(uint64_t cycles,uint32_t count)83 uint64_t arch_timing_cycles_to_ns_avg(uint64_t cycles, uint32_t count)
84 {
85 	return arch_timing_cycles_to_ns(cycles) / count;
86 }
87 
arch_timing_freq_get_mhz(void)88 uint32_t arch_timing_freq_get_mhz(void)
89 {
90 	return (uint32_t)(arch_timing_freq_get() / 1000000U);
91 }
92