Skip to content
Open
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
23 changes: 8 additions & 15 deletions kernel/src/interrupts/irq.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use x86_util::ScopedInterruptDisabler;
use super::pic;

use x86_64::structures::idt::ExceptionStackFrame;
Expand All @@ -9,25 +10,17 @@ pub fn init() {
}

pub fn set_irq_handler(irq: u8, f: Option<fn()>) {
unsafe { asm!("cli"); }
{
let mut irq_map = IRQ_MAP.lock();
irq_map[irq as usize] = f;
}
unsafe { asm!("sti"); }
let _disable_interrupts = ScopedInterruptDisabler::new();
let mut irq_map = IRQ_MAP.lock();

irq_map[irq as usize] = f;
}

fn get_irq_handler(irq: u8) -> Option<fn()> {
let handler;

unsafe { asm!("cli"); }
{
let irq_map = IRQ_MAP.lock();
handler = irq_map[irq as usize];
}
unsafe { asm!("sti"); }
let _disable_interrupts = ScopedInterruptDisabler::new();
let irq_map = IRQ_MAP.lock();

handler
irq_map[irq as usize]
}

fn handle_irq(irq: u8) {
Expand Down
1 change: 1 addition & 0 deletions kernel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#![feature(core_panic_info)]
#![feature(integer_atomics)]
#![feature(lang_items)]
#![feature(optin_builtin_traits)]
#![cfg_attr(not(test), no_std)]

#[cfg(not(test))]
Expand Down
44 changes: 15 additions & 29 deletions kernel/src/rtc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use interrupts;
use x86_util::{inb, outb};
use x86_util::*;

/// Rate controls the interrupt frequency.
/// You can calculate the frequency with `frequency = 32768 >> (rate-1)`.
Expand Down Expand Up @@ -41,14 +41,9 @@ pub fn init() {
}

pub fn get_time() -> RtcTime {
let return_time: RtcTime;
unsafe {
asm!("cli");
let time = TIME.lock();
return_time = *time;
asm!("sti");
}
return_time
let _disable_interrupts = ScopedInterruptDisabler::new();
let time = TIME.lock();
*time
}

/// Handler for the RTC Update Interrupt.
Expand Down Expand Up @@ -90,24 +85,16 @@ fn rtc_interrupt_handler() {

// This is separate from reading the values in order to disable interrupts
// for the least amount of time.
unsafe {
asm!("cli");
}

{
let mut time = TIME.lock();
time.seconds = seconds;
time.minutes = minutes;
time.hours = hours;
time.day_of_week = day_of_week;
time.date_of_month = date_of_month;
time.year = year;
time.count += 1;
}

unsafe {
asm!("sti");
}
let _disable_interrupts = ScopedInterruptDisabler::new();

let mut time = TIME.lock();
time.seconds = seconds;
time.minutes = minutes;
time.hours = hours;
time.day_of_week = day_of_week;
time.date_of_month = date_of_month;
time.year = year;
time.count += 1;
}

/// The values retreived from the RTC might be in BCD format.
Expand All @@ -121,6 +108,7 @@ fn normalize(value: u8, binary_coded_decimal: bool) -> u8 {
}

unsafe fn enable_irq8() {
let _disable_interrupts = ScopedInterruptDisabler::new();
nmi_disable();

// Turn on periodic interrupts to IRQ8.
Expand All @@ -139,11 +127,9 @@ unsafe fn enable_irq8() {
}

unsafe fn nmi_enable() {
asm!("sti");
outb(0x70, inb(0x70) & 0x7F);
}

unsafe fn nmi_disable() {
asm!("cli");
outb(0x70, inb(0x70) | 0x80);
}
31 changes: 31 additions & 0 deletions kernel/src/x86_util.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use x86_64::registers::rflags;

pub unsafe fn outb(port: u16, value: u8) {
asm!("outb %al, %dx" :: "{al}"(value), "{dx}"(port));
}
Expand All @@ -7,3 +9,32 @@ pub unsafe fn inb(port: u16) -> u8 {
asm!("inb %dx, %al" : "={al}"(value) : "{dx}"(port));
value
}

/// Disables interrupts while in scope. When dropped, this resets
/// rflags to their original state.
pub struct ScopedInterruptDisabler {
saved_flags: u64,
}

impl !Send for ScopedInterruptDisabler {}
impl !Sync for ScopedInterruptDisabler {}

impl ScopedInterruptDisabler {
pub fn new() -> ScopedInterruptDisabler {
let saved_flags = rflags::read_raw();

unsafe {
asm!("cli");
}

ScopedInterruptDisabler {
saved_flags: saved_flags,
}
}
}

impl Drop for ScopedInterruptDisabler {
fn drop(&mut self) {
rflags::write_raw(self.saved_flags);
}
}