1
+ #include <stdio.h>
2
+ #include <stdlib.h>
1
3
#include <time.h>
2
4
3
5
#include "utils.h"
22
24
bool boot_complete = false;
23
25
static double scale_factor ;
24
26
27
+ /* for testing */
28
+ uint64_t count = 0 ;
29
+ struct timespec boot_begin , boot_end ;
30
+ double TEST_ns_per_call , TEST_predict_sec ;
31
+
25
32
/* Calculate "x * n / d" without unnecessary overflow or loss of precision.
26
33
*
27
34
* Reference:
@@ -114,14 +121,18 @@ static void measure_bogomips_ns(uint64_t iterations)
114
121
(double ) (elapsed_ns_2 - elapsed_ns_1 ) / (double ) iterations ;
115
122
116
123
/* 'semu_timer_clocksource' is called ~2e8 times per SMP. Each call's
117
- * overhead ~ ns_per_call. The total overhead is ~ ns_per_call * SMP * 2e8.
118
- * That overhead is about 10% of the entire boot, so effectively:
124
+ * overhead ~ ns_per_call. The total overhead is ~ ns_per_call * SMP *
125
+ * 2e8. That overhead is about 10% of the entire boot, so effectively:
119
126
* predict_sec = ns_per_call * SMP * 2e8 * (100%/10%) / 1e9
120
127
* = ns_per_call * SMP * 2.0
121
128
* Then scale_factor = (desired_time) / (predict_sec).
122
129
*/
123
130
const double predict_sec = ns_per_call * SEMU_SMP * 2.0 ;
124
131
scale_factor = SEMU_BOOT_TARGET_TIME / predict_sec ;
132
+
133
+ /* for testing */
134
+ TEST_ns_per_call = ns_per_call ;
135
+ TEST_predict_sec = predict_sec ;
125
136
}
126
137
127
138
/* The main function that returns the "emulated time" in ticks.
@@ -132,6 +143,8 @@ static void measure_bogomips_ns(uint64_t iterations)
132
143
*/
133
144
static uint64_t semu_timer_clocksource (semu_timer_t * timer )
134
145
{
146
+ count ++ ;
147
+
135
148
/* After boot process complete, the timer will switch to real time. Thus,
136
149
* there is an offset between the real time and the emulator time.
137
150
*
@@ -157,8 +170,23 @@ static uint64_t semu_timer_clocksource(semu_timer_t *timer)
157
170
158
171
/* The boot is done => switch to real freq with an offset bridging. */
159
172
if (first_switch ) {
173
+ clock_gettime (CLOCKID , & boot_end );
174
+ double boot_time = (boot_end .tv_sec - boot_begin .tv_sec ) +
175
+ (boot_end .tv_nsec - boot_begin .tv_nsec ) / 1e9 ;
176
+
160
177
first_switch = false;
161
178
offset = (int64_t ) (real_ticks - scaled_ticks );
179
+ printf (
180
+ "\033[1;31m[SEMU LOG]: Boot time: %.5f seconds, called %ld "
181
+ "times semu_timer_total_ticks\033[0m\n" ,
182
+ boot_time , count );
183
+
184
+ printf (
185
+ "\033[1;31m[SEMU LOG]: ns_per_call = %.5f, predict_sec = %.5f, "
186
+ "scale_factor = %.5f\033[0m\n" ,
187
+ TEST_ns_per_call , TEST_predict_sec , scale_factor );
188
+
189
+ exit (0 );
162
190
}
163
191
return (uint64_t ) ((int64_t ) real_ticks - offset );
164
192
@@ -196,6 +224,7 @@ void semu_timer_init(semu_timer_t *timer, uint64_t freq)
196
224
*/
197
225
measure_bogomips_ns (freq );
198
226
227
+ clock_gettime (CLOCKID , & boot_begin );
199
228
timer -> freq = freq ;
200
229
semu_timer_rebase (timer , 0 );
201
230
}
0 commit comments