From 36fde7c7c52bef2c680719778e56761d517e9b3b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Sun, 18 Sep 2016 20:17:08 -0600 Subject: [PATCH] Allow userspace to handle IRQs (WIP). Create basic keyboard handler --- Makefile | 7 +++- arch/x86_64/src/interrupt/irq.rs | 12 ++++--- drivers/ps2d/Cargo.toml | 6 ++++ drivers/ps2d/src/main.rs | 59 ++++++++++++++++++++++++++++++++ kernel/context/memory.rs | 2 +- kernel/scheme/initfs.rs | 3 +- kernel/scheme/irq.rs | 46 +++++++++++++++++-------- kernel/syscall/process.rs | 4 +-- 8 files changed, 115 insertions(+), 24 deletions(-) create mode 100644 drivers/ps2d/Cargo.toml create mode 100644 drivers/ps2d/src/main.rs diff --git a/Makefile b/Makefile index 3c9c5e0..ac98e50 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ clean: cargo clean --manifest-path libstd/Cargo.toml cargo clean --manifest-path init/Cargo.toml cargo clean --manifest-path ion/Cargo.toml + cargo clean --manifest-path drivers/atkbd/Cargo.toml cargo clean --manifest-path drivers/pcid/Cargo.toml rm -rf build @@ -133,4 +134,8 @@ $(BUILD)/pcid: drivers/pcid/Cargo.toml drivers/pcid/src/** $(BUILD)/libstd.rlib $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ strip $@ -$(BUILD)/initfs.rs: $(BUILD)/init $(BUILD)/ion $(BUILD)/pcid +$(BUILD)/ps2d: drivers/ps2d/Cargo.toml drivers/ps2d/src/** $(BUILD)/libstd.rlib + $(CARGO) rustc --manifest-path $< $(CARGOFLAGS) -o $@ + strip $@ + +$(BUILD)/initfs.rs: $(BUILD)/init $(BUILD)/ion $(BUILD)/pcid $(BUILD)/ps2d diff --git a/arch/x86_64/src/interrupt/irq.rs b/arch/x86_64/src/interrupt/irq.rs index a36d019..ec65a20 100644 --- a/arch/x86_64/src/interrupt/irq.rs +++ b/arch/x86_64/src/interrupt/irq.rs @@ -17,6 +17,14 @@ unsafe fn slave_ack() { master_ack(); } +pub unsafe fn acknowledge(irq: usize) { + if irq >= 8 { + slave_ack(); + } else { + master_ack(); + } +} + interrupt!(pit, { COUNTS.lock()[0] += 1; master_ack(); @@ -24,10 +32,6 @@ interrupt!(pit, { interrupt!(keyboard, { COUNTS.lock()[1] += 1; - if let Some(ref mut keyboard) = *PS2_KEYBOARD.lock(){ - keyboard.on_irq(); - } - master_ack(); }); interrupt!(cascade, { diff --git a/drivers/ps2d/Cargo.toml b/drivers/ps2d/Cargo.toml new file mode 100644 index 0000000..f49dee1 --- /dev/null +++ b/drivers/ps2d/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ps2d" +version = "0.1.0" + +[dependencies.syscall] +path = "../../syscall/" diff --git a/drivers/ps2d/src/main.rs b/drivers/ps2d/src/main.rs new file mode 100644 index 0000000..9f45412 --- /dev/null +++ b/drivers/ps2d/src/main.rs @@ -0,0 +1,59 @@ +#![feature(asm)] + +extern crate syscall; + +use std::fs::File; +use std::io::{Read, Write}; +use std::thread; + +use syscall::iopl; + +fn main() { + if true { + unsafe { + iopl(3).expect("pskbd: failed to get I/O permission"); + asm!("cli" :::: "intel", "volatile"); + } + + let mut file = File::open("irq:1").expect("pskbd: failed to open irq:1"); + + println!("pskbd: Reading keyboard IRQs"); + + loop { + let mut irqs = [0; 8]; + file.read(&mut irqs).expect("pskbd: failed to read irq:1"); + + let data: u8; + unsafe { + asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); + } + + println!("pskbd: IRQ {}: {:X}", unsafe { *(irqs.as_ptr() as *const usize) }, data); + + file.write(&irqs).expect("pskbd: failed to write irq:1"); + } + } else { + unsafe { + iopl(3).expect("psmsd: failed to get I/O permission"); + asm!("cli" :::: "intel", "volatile"); + } + + let mut file = File::open("irq:12").expect("psmsd: failed to open irq:12"); + + println!("psmsd: Reading mouse IRQs"); + + loop { + let mut count = [0; 8]; + file.read(&mut count).expect("psmsd: failed to read irq:12"); + + let data: u8; + unsafe { + asm!("in al, dx" : "={al}"(data) : "{dx}"(0x60) : : "intel", "volatile"); + } + + println!("psmsd: IRQ: {:X}", data); + + file.write(&count).expect("psmsd: failed to write irq:12"); + } + } +} diff --git a/kernel/context/memory.rs b/kernel/context/memory.rs index 34e69a3..8f1fecb 100644 --- a/kernel/context/memory.rs +++ b/kernel/context/memory.rs @@ -13,7 +13,7 @@ pub struct Memory { flags: EntryFlags } -#[derive(Debug)] +#[derive(Clone, Debug)] pub enum SharedMemory { Owned(Arc>), Borrowed(Weak>) diff --git a/kernel/scheme/initfs.rs b/kernel/scheme/initfs.rs index 0b15bd2..aa5e7ff 100644 --- a/kernel/scheme/initfs.rs +++ b/kernel/scheme/initfs.rs @@ -21,7 +21,8 @@ impl InitFsScheme { files.insert(b"bin/init", include_bytes!("../../build/userspace/init")); files.insert(b"bin/ion", include_bytes!("../../build/userspace/ion")); files.insert(b"bin/pcid", include_bytes!("../../build/userspace/pcid")); - files.insert(b"etc/init.rc", b"echo testing\ninitfs:bin/pcid\ninitfs:bin/ion"); + files.insert(b"bin/ps2d", include_bytes!("../../build/userspace/ps2d")); + files.insert(b"etc/init.rc", b"echo testing\n#initfs:bin/pcid\ninitfs:bin/ps2d\n#initfs:bin/ion"); InitFsScheme { next_id: 0, diff --git a/kernel/scheme/irq.rs b/kernel/scheme/irq.rs index 9d7d42d..8eee59d 100644 --- a/kernel/scheme/irq.rs +++ b/kernel/scheme/irq.rs @@ -1,6 +1,6 @@ use core::{mem, str}; -use arch::interrupt::irq::COUNTS; +use arch::interrupt::irq::{COUNTS, acknowledge}; use context; use syscall::{Error, Result}; use super::Scheme; @@ -10,7 +10,9 @@ pub struct IrqScheme; impl Scheme for IrqScheme { fn open(&mut self, path: &[u8], _flags: usize) -> Result { let path_str = str::from_utf8(path).or(Err(Error::NoEntry))?; + let id = path_str.parse::().or(Err(Error::NoEntry))?; + if id < COUNTS.lock().len() { Ok(id) } else { @@ -19,35 +21,49 @@ impl Scheme for IrqScheme { } fn dup(&mut self, file: usize) -> Result { - Ok(file) + Err(Error::NotPermitted) } fn read(&mut self, file: usize, buffer: &mut [u8]) -> Result { // Ensures that the length of the buffer is larger than the size of a usize if buffer.len() >= mem::size_of::() { - let current = COUNTS.lock()[file]; + let prev = { COUNTS.lock()[file] }; loop { - let next = COUNTS.lock()[file]; - if next != current { - // Safe if the length of the buffer is larger than the size of a usize - assert!(buffer.len() >= mem::size_of::()); - unsafe { *(buffer.as_mut_ptr() as *mut usize) = next }; - return Ok(mem::size_of::()); - } else { - // Safe if all locks have been dropped - unsafe { context::switch(); } + { + let current = COUNTS.lock()[file]; + if prev != current { + // Safe if the length of the buffer is larger than the size of a usize + assert!(buffer.len() >= mem::size_of::()); + unsafe { *(buffer.as_mut_ptr() as *mut usize) = current; } + return Ok(mem::size_of::()); + } } + + // Safe if all locks have been dropped + unsafe { context::switch(); } } } else { Err(Error::InvalidValue) } } - fn write(&mut self, _file: usize, _buffer: &[u8]) -> Result { - Err(Error::NotPermitted) + fn write(&mut self, file: usize, buffer: &[u8]) -> Result { + if buffer.len() >= mem::size_of::() { + assert!(buffer.len() >= mem::size_of::()); + let prev = unsafe { *(buffer.as_ptr() as *const usize) }; + let current = COUNTS.lock()[file]; + if prev == current { + unsafe { acknowledge(file); } + return Ok(mem::size_of::()); + } else { + return Ok(0); + } + } else { + Err(Error::InvalidValue) + } } - fn fsync(&mut self, file: usize) -> Result<()> { + fn fsync(&mut self, _file: usize) -> Result<()> { Ok(()) } diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs index 383141c..f05271a 100644 --- a/kernel/syscall/process.rs +++ b/kernel/syscall/process.rs @@ -96,11 +96,11 @@ pub fn clone(flags: usize, stack_base: usize) -> Result { if flags & CLONE_VM == CLONE_VM { for memory_shared in context.image.iter() { - image.push(memory_shared.borrow()); + image.push(memory_shared.clone()); } if let Some(ref heap_shared) = context.heap { - heap_option = Some(heap_shared.borrow()); + heap_option = Some(heap_shared.clone()); } } else { for memory_shared in context.image.iter() {