Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add rtc support #155

Merged
merged 4 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion api/arceos_api/src/imp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@ mod stdio {
}
}

mod time {
pub use axhal::time::{
monotonic_time as ax_monotonic_time, wall_time as ax_wall_time, TimeValue as AxTimeValue,
};
}

pub use self::mem::*;
pub use self::stdio::*;
pub use self::task::*;
pub use self::time::*;

pub use axhal::misc::terminate as ax_terminate;
pub use axhal::time::{current_time as ax_current_time, TimeValue as AxTimeValue};
pub use axio::PollState as AxPollState;
6 changes: 4 additions & 2 deletions api/arceos_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ pub mod time {
}

define_api! {
/// Returns the current clock time.
pub fn ax_current_time() -> AxTimeValue;
/// Returns the time elapsed since system boot.
pub fn ax_monotonic_time() -> AxTimeValue;
/// Returns the time elapsed since epoch, also known as realtime.
pub fn ax_wall_time() -> AxTimeValue;
}
}

Expand Down
1 change: 1 addition & 0 deletions api/arceos_posix_api/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ typedef struct {{
"aibuf",
];
let allow_vars = [
"CLOCK_.*",
"O_.*",
"AF_.*",
"SOCK_.*",
Expand Down
1 change: 1 addition & 0 deletions api/arceos_posix_api/ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <netinet/in.h>
#include <pthread.h>
#include <stddef.h>
#include <time.h>
#include <sys/epoll.h>
#include <sys/resource.h>
#include <sys/select.h>
Expand Down
8 changes: 4 additions & 4 deletions api/arceos_posix_api/src/imp/io_mpx/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use alloc::sync::Arc;
use core::{ffi::c_int, time::Duration};

use axerrno::{LinuxError, LinuxResult};
use axhal::time::current_time;
use axhal::time::wall_time;
use axsync::Mutex;

use crate::ctypes;
Expand Down Expand Up @@ -184,8 +184,8 @@ pub unsafe fn sys_epoll_wait(
return Err(LinuxError::EINVAL);
}
let events = unsafe { core::slice::from_raw_parts_mut(events, maxevents as usize) };
let deadline = (!timeout.is_negative())
.then(|| current_time() + Duration::from_millis(timeout as u64));
let deadline =
(!timeout.is_negative()).then(|| wall_time() + Duration::from_millis(timeout as u64));
let epoll_instance = EpollInstance::from_fd(epfd)?;
loop {
#[cfg(feature = "net")]
Expand All @@ -195,7 +195,7 @@ pub unsafe fn sys_epoll_wait(
return Ok(events_num as c_int);
}

if deadline.map_or(false, |ddl| current_time() >= ddl) {
if deadline.map_or(false, |ddl| wall_time() >= ddl) {
debug!(" timeout!");
return Ok(0);
}
Expand Down
6 changes: 3 additions & 3 deletions api/arceos_posix_api/src/imp/io_mpx/select.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::ffi::c_int;

use axerrno::{LinuxError, LinuxResult};
use axhal::time::current_time;
use axhal::time::wall_time;

use crate::{ctypes, imp::fd_ops::get_file_like};

Expand Down Expand Up @@ -124,7 +124,7 @@ pub unsafe fn sys_select(
return Err(LinuxError::EINVAL);
}
let nfds = (nfds as usize).min(FD_SETSIZE);
let deadline = unsafe { timeout.as_ref().map(|t| current_time() + (*t).into()) };
let deadline = unsafe { timeout.as_ref().map(|t| wall_time() + (*t).into()) };
let fd_sets = FdSets::from(nfds, readfds, writefds, exceptfds);

unsafe {
Expand All @@ -141,7 +141,7 @@ pub unsafe fn sys_select(
return Ok(res);
}

if deadline.map_or(false, |ddl| current_time() >= ddl) {
if deadline.map_or(false, |ddl| wall_time() >= ddl) {
debug!(" timeout!");
return Ok(0);
}
Expand Down
16 changes: 12 additions & 4 deletions api/arceos_posix_api/src/imp/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use core::ffi::{c_int, c_long};
use core::time::Duration;

use crate::ctypes;
use crate::ctypes::{CLOCK_MONOTONIC, CLOCK_REALTIME};

impl From<ctypes::timespec> for Duration {
fn from(ts: ctypes::timespec) -> Self {
Expand Down Expand Up @@ -35,12 +36,19 @@ impl From<Duration> for ctypes::timeval {
}

/// Get clock time since booting
pub unsafe fn sys_clock_gettime(_clk: ctypes::clockid_t, ts: *mut ctypes::timespec) -> c_int {
pub unsafe fn sys_clock_gettime(clk: ctypes::clockid_t, ts: *mut ctypes::timespec) -> c_int {
syscall_body!(sys_clock_gettime, {
if ts.is_null() {
return Err(LinuxError::EFAULT);
}
let now = axhal::time::current_time().into();
let now = match clk as u32 {
CLOCK_REALTIME => axhal::time::wall_time().into(),
CLOCK_MONOTONIC => axhal::time::monotonic_time().into(),
_ => {
warn!("Called sys_clock_gettime for unsupported clock {}", clk);
return Err(LinuxError::EINVAL);
}
};
unsafe { *ts = now };
debug!("sys_clock_gettime: {}.{:09}s", now.tv_sec, now.tv_nsec);
Ok(0)
Expand All @@ -63,14 +71,14 @@ pub unsafe fn sys_nanosleep(req: *const ctypes::timespec, rem: *mut ctypes::time
Duration::from(*req)
};

let now = axhal::time::current_time();
let now = axhal::time::monotonic_time();

#[cfg(feature = "multitask")]
axtask::sleep(dur);
#[cfg(not(feature = "multitask"))]
axhal::time::busy_wait(dur);

let after = axhal::time::current_time();
let after = axhal::time::monotonic_time();
let actual = after - now;

if let Some(diff) = dur.checked_sub(actual) {
Expand Down
3 changes: 3 additions & 0 deletions api/axfeat/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ net = ["alloc", "paging", "axdriver/virtio-net", "dep:axnet", "axruntime/net"]
# Display
display = ["alloc", "paging", "axdriver/virtio-gpu", "dep:axdisplay", "axruntime/display"]

# Real Time Clock (RTC) Driver.
rtc = ["axhal/rtc", "axruntime/rtc"]

# Device drivers
bus-mmio = ["axdriver?/bus-mmio"]
bus-pci = ["axdriver?/bus-pci"]
Expand Down
2 changes: 1 addition & 1 deletion doc/apps_sleep.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ graph TD;
S-->arg["libax::time::Duration::from_secs()"]
arg-->argA["libax::time::Duration::new(secs)"]

S-->A["axhal::time::current_time()"]
S-->A["axhal::time::wall_time()"]
A-->AA["axhal::time::TimeValue::from_nanos()"]

S-->B["axtask::run_queue::AxRunQueue::sleep_until()"]
Expand Down
4 changes: 4 additions & 0 deletions modules/axhal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ fp_simd = []
paging = ["axalloc", "page_table"]
irq = []
tls = ["alloc"]
rtc = ["x86_rtc", "riscv_goldfish", "arm_pl031"]
default = []

[dependencies]
Expand All @@ -42,16 +43,19 @@ x86 = "0.52"
x86_64 = "0.15"
x2apic = "0.4"
raw-cpuid = "11.0"
x86_rtc = { version = "0.1.1", optional = true }

[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
riscv = "0.11"
sbi-rt = { version = "0.0.3", features = ["legacy"] }
riscv_goldfish = { version = "0.1.1", optional = true }

[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64-cpu = "9.4"
tock-registers = "0.8"
arm_gic = { path = "../../crates/arm_gic" }
arm_pl011 = { path = "../../crates/arm_pl011" }
arm_pl031 = { version = "0.1.1", optional = true }
dw_apb_uart = { path = "../../crates/dw_apb_uart" }

[build-dependencies]
Expand Down
27 changes: 26 additions & 1 deletion modules/axhal/src/platform/aarch64_common/generic_timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use tock_registers::interfaces::{Readable, Writeable};

static mut CNTPCT_TO_NANOS_RATIO: Ratio = Ratio::zero();
static mut NANOS_TO_CNTPCT_RATIO: Ratio = Ratio::zero();
/// RTC wall time offset in nanoseconds at monotonic time base.
static mut RTC_EPOCHOFFSET_NANOS: u64 = 0;

/// Returns the current clock time in hardware ticks.
#[inline]
Expand All @@ -25,9 +27,14 @@ pub fn nanos_to_ticks(nanos: u64) -> u64 {
unsafe { NANOS_TO_CNTPCT_RATIO.mul_trunc(nanos) }
}

/// Return epoch offset in nanoseconds (wall time offset to monotonic clock start).
pub fn epochoffset_nanos() -> u64 {
unsafe { RTC_EPOCHOFFSET_NANOS }
}

/// Set a one-shot timer.
///
/// A timer interrupt will be triggered at the given deadline (in nanoseconds).
/// A timer interrupt will be triggered at the specified monotonic time deadline (in nanoseconds).
#[cfg(feature = "irq")]
pub fn set_oneshot_timer(deadline_ns: u64) {
let cnptct = CNTPCT_EL0.get();
Expand All @@ -48,6 +55,24 @@ pub(crate) fn init_early() {
CNTPCT_TO_NANOS_RATIO = Ratio::new(crate::time::NANOS_PER_SEC as u32, freq as u32);
NANOS_TO_CNTPCT_RATIO = CNTPCT_TO_NANOS_RATIO.inverse();
}

// Make sure `RTC_PADDR` is valid in platform config file.
#[cfg(feature = "rtc")]
if axconfig::RTC_PADDR != 0 {
use crate::mem::phys_to_virt;
use arm_pl031::Rtc;
use memory_addr::PhysAddr;

const PL031_BASE: PhysAddr = PhysAddr::from(axconfig::RTC_PADDR);
// Get the current time in microseconds since the epoch (1970-01-01) from the aarch64 pl031 RTC.
// Subtract the timer ticks to get the actual time when ArceOS was booted.
let epoch_time_nanos =
Rtc::new(phys_to_virt(PL031_BASE).as_usize()).get_unix_timestamp() * 1_000_000_000;

unsafe {
RTC_EPOCHOFFSET_NANOS = epoch_time_nanos - ticks_to_nanos(current_ticks());
}
}
}

pub(crate) fn init_percpu() {
Expand Down
7 changes: 6 additions & 1 deletion modules/axhal/src/platform/dummy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ pub mod time {

/// Set a one-shot timer.
///
/// A timer interrupt will be triggered at the given deadline (in nanoseconds).
/// A timer interrupt will be triggered at the specified monotonic time deadline (in nanoseconds).
pub fn set_oneshot_timer(deadline_ns: u64) {}

/// Return epoch offset in nanoseconds (wall time offset to monotonic clock start).
pub fn epochoffset_nanos() -> u64 {
0
}
}

#[cfg(feature = "irq")]
Expand Down
4 changes: 4 additions & 0 deletions modules/axhal/src/platform/riscv64_qemu_virt/boot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ static mut BOOT_STACK: [u8; TASK_STACK_SIZE] = [0; TASK_STACK_SIZE];
static mut BOOT_PT_SV39: [u64; 512] = [0; 512];

unsafe fn init_boot_page_table() {
// 0x0000_0000..0x4000_0000, VRWX_GAD, 1G block
BOOT_PT_SV39[0] = (0x80000 << 10) | 0xef;
// 0x8000_0000..0xc000_0000, VRWX_GAD, 1G block
BOOT_PT_SV39[2] = (0x80000 << 10) | 0xef;
// 0xffff_ffc0_0000_0000..0xffff_ffc0_4000_0000, VRWX_GAD, 1G block
BOOT_PT_SV39[0x100] = (0x80000 << 10) | 0xef;
// 0xffff_ffc0_8000_0000..0xffff_ffc0_c000_0000, VRWX_GAD, 1G block
BOOT_PT_SV39[0x102] = (0x80000 << 10) | 0xef;
}
Expand Down
1 change: 1 addition & 0 deletions modules/axhal/src/platform/riscv64_qemu_virt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ unsafe extern "C" fn rust_entry(cpu_id: usize, dtb: usize) {
crate::mem::clear_bss();
crate::cpu::init_primary(cpu_id);
crate::arch::set_trap_vector_base(trap_vector_base as usize);
self::time::init_early();
rust_main(cpu_id, dtb);
}

Expand Down
Loading
Loading