Skip to content

Commit 60e7106

Browse files
committed
using bootinfo to determine the boot time
On aarch64, uhyve doesn't support the ARM PrimeCell Real Time Clock(PL031). To detemine the unix timestamp, the kernel uses bootinfo to determine the boot timne
1 parent 393f6a1 commit 60e7106

File tree

1 file changed

+58
-59
lines changed

1 file changed

+58
-59
lines changed

src/arch/aarch64/kernel/systemtime.rs

Lines changed: 58 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,79 @@
1-
#![allow(unused)]
2-
31
use alloc::vec::Vec;
4-
use core::arch::asm;
52
use core::str;
63

74
use arm_pl031::Rtc;
85
use hermit_dtb::Dtb;
6+
use hermit_entry::boot_info::PlatformInfo;
97
use hermit_sync::OnceCell;
10-
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};
8+
use memory_addresses::arch::aarch64::PhysAddr;
119
use time::OffsetDateTime;
1210

1311
use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
1412
use crate::env;
1513
use crate::mm::virtualmem;
1614

17-
static RTC_PL031: OnceCell<Rtc> = OnceCell::new();
1815
static BOOT_TIME: OnceCell<u64> = OnceCell::new();
1916

2017
pub fn init() {
21-
let dtb = unsafe {
22-
Dtb::from_raw(core::ptr::with_exposed_provenance(
23-
env::boot_info().hardware_info.device_tree.unwrap().get() as usize,
24-
))
25-
.expect(".dtb file has invalid header")
26-
};
27-
28-
for node in dtb.enum_subnodes("/") {
29-
let parts: Vec<_> = node.split('@').collect();
30-
31-
if let Some(compatible) = dtb.get_property(parts.first().unwrap(), "compatible") {
32-
if str::from_utf8(compatible).unwrap().contains("pl031") {
33-
let reg = dtb.get_property(parts.first().unwrap(), "reg").unwrap();
34-
let (slice, residual_slice) = reg.split_at(core::mem::size_of::<u64>());
35-
let addr = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
36-
let (slice, _residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
37-
let size = u64::from_be_bytes(slice.try_into().unwrap());
38-
39-
debug!("Found RTC at {addr:p} (size {size:#X})");
40-
41-
let pl031_address = virtualmem::allocate_aligned(
42-
size.try_into().unwrap(),
43-
BasePageSize::SIZE.try_into().unwrap(),
44-
)
45-
.unwrap();
46-
47-
let mut flags = PageTableEntryFlags::empty();
48-
flags.device().writable().execute_disable();
49-
paging::map::<BasePageSize>(
50-
pl031_address,
51-
addr,
52-
(size / BasePageSize::SIZE).try_into().unwrap(),
53-
flags,
54-
);
55-
56-
debug!("Mapping RTC to virtual address {pl031_address:p}");
57-
58-
let rtc = unsafe { Rtc::new(pl031_address.as_mut_ptr()) };
59-
let boot_time =
60-
OffsetDateTime::from_unix_timestamp(rtc.get_unix_timestamp().into()).unwrap();
61-
info!("Hermit booted on {boot_time}");
62-
63-
let micros = u64::try_from(boot_time.unix_timestamp_nanos() / 1000).unwrap();
64-
let current_ticks = super::processor::get_timer_ticks();
65-
66-
assert!(
67-
BOOT_TIME.set(micros - current_ticks).is_err(),
68-
"Unable to set BOOT_TIME"
69-
);
70-
assert!(RTC_PL031.set(rtc).is_err(), "Unable to set RTC_PL031");
71-
72-
return;
18+
let boot_time = match env::boot_info().platform_info {
19+
PlatformInfo::Uhyve { boot_time, .. } => boot_time,
20+
_ => {
21+
let mut offset = OffsetDateTime::UNIX_EPOCH;
22+
let dtb = unsafe {
23+
Dtb::from_raw(core::ptr::with_exposed_provenance(
24+
env::boot_info().hardware_info.device_tree.unwrap().get() as usize,
25+
))
26+
.expect(".dtb file has invalid header")
27+
};
28+
29+
for node in dtb.enum_subnodes("/") {
30+
let parts: Vec<_> = node.split('@').collect();
31+
32+
if let Some(compatible) = dtb.get_property(parts.first().unwrap(), "compatible") {
33+
if str::from_utf8(compatible).unwrap().contains("pl031") {
34+
let reg = dtb.get_property(parts.first().unwrap(), "reg").unwrap();
35+
let (slice, residual_slice) = reg.split_at(core::mem::size_of::<u64>());
36+
let addr = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
37+
let (slice, _residual_slice) =
38+
residual_slice.split_at(core::mem::size_of::<u64>());
39+
let size = u64::from_be_bytes(slice.try_into().unwrap());
40+
41+
debug!("Found RTC at {addr:p} (size {size:#X})");
42+
43+
let pl031_address = virtualmem::allocate_aligned(
44+
size.try_into().unwrap(),
45+
BasePageSize::SIZE.try_into().unwrap(),
46+
)
47+
.unwrap();
48+
49+
let mut flags = PageTableEntryFlags::empty();
50+
flags.device().writable().execute_disable();
51+
paging::map::<BasePageSize>(
52+
pl031_address,
53+
addr,
54+
(size / BasePageSize::SIZE).try_into().unwrap(),
55+
flags,
56+
);
57+
58+
debug!("Mapping RTC to virtual address {pl031_address:p}");
59+
60+
let rtc = unsafe { Rtc::new(pl031_address.as_mut_ptr()) };
61+
offset =
62+
OffsetDateTime::from_unix_timestamp(rtc.get_unix_timestamp().into())
63+
.unwrap();
64+
65+
break;
66+
}
67+
}
7368
}
69+
70+
offset
7471
}
75-
}
72+
};
73+
info!("Hermit booted on {boot_time}");
7674

77-
BOOT_TIME.set(0).unwrap();
75+
let micros = u64::try_from(boot_time.unix_timestamp_nanos() / 1000).unwrap();
76+
BOOT_TIME.set(micros).unwrap();
7877
}
7978

8079
/// Returns the current time in microseconds since UNIX epoch.

0 commit comments

Comments
 (0)