Skip to content

Commit ba634ed

Browse files
committed
fix(platform/timer): on x86_64, elide usage of asm!() and use _rdtsc() intrinsic
1 parent be63c51 commit ba634ed

3 files changed

Lines changed: 8 additions & 55 deletions

File tree

crates/sprout/src/platform/timer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ pub enum TickFrequency {
1717
/// The platform provides the tick frequency.
1818
Hardware(u64),
1919
/// The tick frequency is measured internally.
20-
Measured(u64, Duration),
20+
Measured(u64),
2121
}
2222

2323
impl TickFrequency {
2424
/// Acquire the tick frequency reported by the platform.
2525
fn ticks(&self) -> u64 {
2626
match self {
2727
TickFrequency::Hardware(frequency) => *frequency,
28-
TickFrequency::Measured(frequency, _) => *frequency,
28+
TickFrequency::Measured(frequency) => *frequency,
2929
}
3030
}
3131

crates/sprout/src/platform/timer/aarch64.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,6 @@ pub fn ticks() -> u64 {
1010
counter
1111
}
1212

13-
/// We can use the actual ticks value as our start value.
14-
pub fn start() -> u64 {
15-
ticks()
16-
}
17-
18-
/// We can use the actual ticks value as our stop value.
19-
pub fn stop() -> u64 {
20-
ticks()
21-
}
22-
2313
/// Our frequency is provided by cntfrq_el0 on the platform.
2414
pub fn frequency() -> TickFrequency {
2515
let frequency: u64;
Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::platform::timer::TickFrequency;
2-
use core::arch::asm;
32
use core::time::Duration;
43

54
/// We will measure the frequency of the timer based on 1000 microseconds.
@@ -8,52 +7,16 @@ const MEASURE_FREQUENCY_DURATION: Duration = Duration::from_micros(1000);
87

98
/// Read the number of ticks from the platform timer.
109
pub fn ticks() -> u64 {
11-
let mut eax: u32;
12-
let mut edx: u32;
13-
14-
unsafe {
15-
asm!("rdtsc", out("eax") eax, out("edx") edx);
16-
}
17-
18-
(edx as u64) << 32 | eax as u64
19-
}
20-
21-
/// Read the starting number of ticks from the platform timer.
22-
pub fn start() -> u64 {
23-
let rax: u64;
24-
unsafe {
25-
asm!(
26-
"mfence",
27-
"lfence",
28-
"rdtsc",
29-
"shl rdx, 32",
30-
"or rax, rdx",
31-
out("rax") rax
32-
);
33-
}
34-
rax
35-
}
36-
37-
/// Read the ending number of ticks from the platform timer.
38-
pub fn stop() -> u64 {
39-
let rax: u64;
40-
unsafe {
41-
asm!(
42-
"rdtsc",
43-
"lfence",
44-
"shl rdx, 32",
45-
"or rax, rdx",
46-
out("rax") rax
47-
);
48-
}
49-
rax
10+
// SAFETY: Reads the platform timer, which is safe in any context.
11+
unsafe { core::arch::x86_64::_rdtsc() }
5012
}
5113

5214
/// Measure the frequency of the platform timer.
15+
/// NOTE: Intentionally, we do not synchronize rdtsc during measurement to match systemd behavior.
5316
fn measure_frequency() -> u64 {
54-
let start = start();
17+
let start = ticks();
5518
uefi::boot::stall(MEASURE_FREQUENCY_DURATION);
56-
let stop = stop();
19+
let stop = ticks();
5720
let elapsed = stop.wrapping_sub(start) as f64;
5821
(elapsed / MEASURE_FREQUENCY_DURATION.as_secs_f64()) as u64
5922
}
@@ -62,5 +25,5 @@ fn measure_frequency() -> u64 {
6225
/// On x86_64, this is slightly expensive, so it should be done once.
6326
pub fn frequency() -> TickFrequency {
6427
let frequency = measure_frequency();
65-
TickFrequency::Measured(frequency, MEASURE_FREQUENCY_DURATION)
28+
TickFrequency::Measured(frequency)
6629
}

0 commit comments

Comments
 (0)