Skip to content

Commit

Permalink
Add timer to clk module
Browse files Browse the repository at this point in the history
  • Loading branch information
vinc committed Oct 20, 2024
1 parent c1f89f0 commit 3e2a337
Show file tree
Hide file tree
Showing 17 changed files with 78 additions and 58 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn init(boot_info: &'static BootInfo) {
sys::pic::init(); // Enable interrupts
sys::serial::init();
sys::keyboard::init();
sys::time::init();
sys::clk::init();

let v = option_env!("MOROS_VERSION").unwrap_or(env!("CARGO_PKG_VERSION"));
log!("SYS MOROS v{}", v);
Expand Down
4 changes: 2 additions & 2 deletions src/sys/ata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl Bus {
}

fn wait(&mut self, ns: u64) {
sys::time::nanowait(ns);
sys::clk::nanowait(ns);
}

fn clear_interrupt(&mut self) -> u8 {
Expand Down Expand Up @@ -164,7 +164,7 @@ impl Bus {
// Bit 7 => 1
self.drive_register.write(0xA0 | (drive << 4))
}
sys::time::nanowait(400); // Wait at least 400 ns
sys::clk::nanowait(400); // Wait at least 400 ns
self.poll(Status::BSY, false)?;
self.poll(Status::DRQ, false)?;
Ok(())
Expand Down
12 changes: 12 additions & 0 deletions src/sys/clk/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
mod cmos;
mod rtc;
mod sleep;
mod timer;

pub use cmos::CMOS;
pub use rtc::RTC;
pub use sleep::{sleep, nanowait, halt};
pub use timer::{
ticks, time_between_ticks, pit_frequency, set_pit_frequency_divider,
last_rtc_update
};

use rtc::{Interrupt, Register, RTC_CENTURY};
use timer::{rdtsc, CLOCKS_PER_NANOSECOND};

pub fn init() {
timer::init();
}
28 changes: 28 additions & 0 deletions src/sys/clk/sleep.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use crate::sys;

use core::sync::atomic::Ordering;
use x86_64::instructions::interrupts;

pub fn halt() {
let disabled = !interrupts::are_enabled();
interrupts::enable_and_hlt();
if disabled {
interrupts::disable();
}
}

pub fn sleep(seconds: f64) {
let start = sys::clock::uptime();
while sys::clock::uptime() - start < seconds {
halt();
}
}

pub fn nanowait(nanoseconds: u64) {
let start = super::rdtsc();
let clock = super::CLOCKS_PER_NANOSECOND.load(Ordering::Relaxed);
let delta = nanoseconds * clock;
while super::rdtsc() - start < delta {
core::hint::spin_loop();
}
}
43 changes: 12 additions & 31 deletions src/sys/time.rs → src/sys/clk/timer.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::sys;
use crate::sys::clk::CMOS;
use core::hint::spin_loop;
use core::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use x86_64::instructions::interrupts;
use x86_64::instructions::port::Port;
Expand All @@ -15,7 +14,7 @@ const PIT_INTERVAL: f64 = (PIT_DIVIDER as f64) / PIT_FREQUENCY;

static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);
static LAST_RTC_UPDATE: AtomicUsize = AtomicUsize::new(0);
static CLOCKS_PER_NANOSECOND: AtomicU64 = AtomicU64::new(0);
pub static CLOCKS_PER_NANOSECOND: AtomicU64 = AtomicU64::new(0);

pub fn ticks() -> usize {
PIT_TICKS.load(Ordering::Relaxed)
Expand All @@ -29,34 +28,8 @@ pub fn last_rtc_update() -> usize {
LAST_RTC_UPDATE.load(Ordering::Relaxed)
}

pub fn halt() {
let disabled = !interrupts::are_enabled();
interrupts::enable_and_hlt();
if disabled {
interrupts::disable();
}
}

fn rdtsc() -> u64 {
unsafe {
core::arch::x86_64::_mm_lfence();
core::arch::x86_64::_rdtsc()
}
}

pub fn sleep(seconds: f64) {
let start = sys::clock::uptime();
while sys::clock::uptime() - start < seconds {
halt();
}
}

pub fn nanowait(nanoseconds: u64) {
let start = rdtsc();
let delta = nanoseconds * CLOCKS_PER_NANOSECOND.load(Ordering::Relaxed);
while rdtsc() - start < delta {
spin_loop();
}
pub fn pit_frequency() -> f64 {
PIT_FREQUENCY
}

/// The frequency divider must be between 0 and 65535, with 0 acting as 65536
Expand All @@ -75,6 +48,14 @@ pub fn set_pit_frequency_divider(divider: u16, channel: u8) {
});
}

// Read Time Stamp Counter
pub fn rdtsc() -> u64 {
unsafe {
core::arch::x86_64::_mm_lfence();
core::arch::x86_64::_rdtsc()
}
}

pub fn pit_interrupt_handler() {
PIT_TICKS.fetch_add(1, Ordering::Relaxed);
}
Expand All @@ -98,7 +79,7 @@ pub fn init() {
// TSC timmer
let calibration_time = 250_000; // 0.25 seconds
let a = rdtsc();
sleep(calibration_time as f64 / 1e6);
super::sleep(calibration_time as f64 / 1e6);
let b = rdtsc();
CLOCKS_PER_NANOSECOND.store((b - a) / calibration_time, Ordering::Relaxed);
}
6 changes: 3 additions & 3 deletions src/sys/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl FileIO for Uptime {

// NOTE: This clock is monotonic
pub fn uptime() -> f64 {
sys::time::time_between_ticks() * sys::time::ticks() as f64
sys::clk::time_between_ticks() * sys::clk::ticks() as f64
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -103,8 +103,8 @@ pub fn realtime() -> f64 {
+ 60 * rtc.minute as u64
+ rtc.second as u64;

let fract = sys::time::time_between_ticks()
* (sys::time::ticks() - sys::time::last_rtc_update()) as f64;
let fract = sys::clk::time_between_ticks()
* (sys::clk::ticks() - sys::clk::last_rtc_update()) as f64;

(ts as f64) + fract
}
Expand Down
4 changes: 2 additions & 2 deletions src/sys/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ pub fn read_char() -> char {
sys::console::disable_echo();
sys::console::enable_raw();
loop {
sys::time::halt();
sys::clk::halt();
let res = interrupts::without_interrupts(|| {
let mut stdin = STDIN.lock();
if !stdin.is_empty() {
Expand All @@ -160,7 +160,7 @@ pub fn read_char() -> char {

pub fn read_line() -> String {
loop {
sys::time::halt();
sys::clk::halt();
let res = interrupts::without_interrupts(|| {
let mut stdin = STDIN.lock();
match stdin.chars().next_back() {
Expand Down
1 change: 0 additions & 1 deletion src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,4 @@ pub mod process;
pub mod rng;
pub mod serial;
pub mod syscall;
pub mod time;
pub mod vga;
2 changes: 1 addition & 1 deletion src/sys/net/nic/e1000.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ impl Device {
// Reset device
let ctrl = self.read(REG_CTRL);
self.write(REG_CTRL, ctrl | CTRL_RST); // Reset
sys::time::nanowait(500); // TODO: How long should we wait?
sys::clk::nanowait(500); // TODO: How long should we wait?

// Disable interrupts again
self.write(REG_IMC, 0xFFFF);
Expand Down
2 changes: 1 addition & 1 deletion src/sys/net/nic/pcnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ impl Device {

// Wait until init is done
while !self.ports.read_csr_32(0).get_bit(CSR0_IDON) {
sys::time::halt();
sys::clk::halt();
}

// IDON + INTR + INIT
Expand Down
2 changes: 1 addition & 1 deletion src/sys/net/socket/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ fn random_port() -> u16 {
}

fn wait(duration: Duration) {
sys::time::sleep((duration.total_micros() as f64) / 1000000.0);
sys::clk::sleep((duration.total_micros() as f64) / 1000000.0);
}
12 changes: 6 additions & 6 deletions src/sys/net/socket/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl TcpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
}
Ok(())
Expand All @@ -110,7 +110,7 @@ impl TcpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
Ok(())
} else {
Err(())
Expand All @@ -136,7 +136,7 @@ impl TcpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
} else {
Err(())
Expand Down Expand Up @@ -174,7 +174,7 @@ impl FileIO for TcpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
Ok(bytes)
} else {
Expand Down Expand Up @@ -208,7 +208,7 @@ impl FileIO for TcpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
Ok(buf.len())
} else {
Expand All @@ -233,7 +233,7 @@ impl FileIO for TcpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/sys/net/socket/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl UdpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
}
self.remote_endpoint = Some(IpEndpoint::new(addr, port));
Expand Down Expand Up @@ -122,7 +122,7 @@ impl FileIO for UdpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
Ok(bytes)
} else {
Expand Down Expand Up @@ -160,7 +160,7 @@ impl FileIO for UdpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
Ok(buf.len())
} else {
Expand All @@ -185,7 +185,7 @@ impl FileIO for UdpSocket {
if let Some(d) = iface.poll_delay(sys::net::time(), &sockets) {
wait(d);
}
sys::time::halt();
sys::clk::halt();
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/sys/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ pub fn init() {
} else {
log!("RNG RDRAND unavailable");
let mut hasher = Sha256::new();
hasher.update(sys::time::ticks().to_be_bytes());
hasher.update(sys::clk::ticks().to_be_bytes());
hasher.update(sys::clock::realtime().to_be_bytes());
hasher.update(sys::clock::uptime().to_be_bytes());
seed = hasher.finalize().into();
Expand Down
2 changes: 1 addition & 1 deletion src/sys/syscall/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub fn exit(code: ExitCode) -> ExitCode {
}

pub fn sleep(seconds: f64) {
sys::time::sleep(seconds);
sys::clk::sleep(seconds);
}

pub fn delete(path: &str) -> isize {
Expand Down
4 changes: 2 additions & 2 deletions src/usr/beep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use x86_64::instructions::port::Port;
const SPEAKER_PORT: u16 = 0x61;

fn start_sound(freq: f64) {
let divider = (sys::time::PIT_FREQUENCY / freq) as u16;
let divider = (sys::clk::pit_frequency() / freq) as u16;
let channel = 2;
sys::time::set_pit_frequency_divider(divider, channel);
sys::clk::set_pit_frequency_divider(divider, channel);

let mut speaker: Port<u8> = Port::new(SPEAKER_PORT);
let tmp = unsafe { speaker.read() };
Expand Down
2 changes: 1 addition & 1 deletion src/usr/life.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Game {
return;
}
print!("{}", self);
sys::time::sleep(1.0 / self.speed);
sys::clk::sleep(1.0 / self.speed);
if self.is_game_over() {
continue; // Display the screen until ^C is received
}
Expand Down

0 comments on commit 3e2a337

Please sign in to comment.