Skip to content

Commit 6582062

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 6582062

File tree

1 file changed

+59
-55
lines changed

1 file changed

+59
-55
lines changed

src/arch/aarch64/kernel/systemtime.rs

Lines changed: 59 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,75 +6,79 @@ use core::str;
66

77
use arm_pl031::Rtc;
88
use hermit_dtb::Dtb;
9+
use hermit_entry::boot_info::PlatformInfo;
910
use hermit_sync::OnceCell;
1011
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};
1112
use time::OffsetDateTime;
1213

1314
use crate::arch::aarch64::mm::paging::{self, BasePageSize, PageSize, PageTableEntryFlags};
1415
use crate::env;
16+
use crate::env::is_uhyve;
1517
use crate::mm::virtualmem;
18+
use crate::syscalls::interfaces::uhyve::uhyve_hypercall;
1619

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

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

77-
BOOT_TIME.set(0).unwrap();
80+
let micros = u64::try_from(boot_time.unix_timestamp_nanos() / 1000).unwrap();
81+
BOOT_TIME.set(micros).unwrap();
7882
}
7983

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

0 commit comments

Comments
 (0)