mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-04-25 11:49:03 +02:00
Add correct sleep which works now because interrupts are re-enabled
using sti in syscalls, remove a bunch of old imports and code, move keyboard scancode handling to keyboard.rs, add a new KeyboardEvent based layout where press/release and unicode is handled, add a kbd_read syscall which writes kbd events to a userspace buffer, add a usercopy file which provides safe copying functions to userspace
This commit is contained in:
Binary file not shown.
@@ -1,18 +1,13 @@
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64 as FRAME_ALLOCATOR;
|
pub use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64 as FRAME_ALLOCATOR;
|
||||||
|
|
||||||
use crate::{driver::timer::TIMER, util::serial_print};
|
use crate::driver::timer::TIMER;
|
||||||
use alloc::string::ToString;
|
use core::{alloc::GlobalAlloc, arch::asm};
|
||||||
use core::{alloc::GlobalAlloc, arch::asm, sync::atomic::Ordering};
|
|
||||||
use limine::response::{HhdmResponse, MemoryMapResponse};
|
use limine::response::{HhdmResponse, MemoryMapResponse};
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86_64::{
|
use crate::arch::x86_64::{
|
||||||
elf::run_elf_x86_64,
|
elf::run_elf_x86_64, heap::ALLOCATOR, init::init_x86_64, usermode::enter_usermode_x86_64,
|
||||||
heap::ALLOCATOR,
|
|
||||||
init::init_x86_64,
|
|
||||||
paging::{FRAME_ALLOCATOR_X86_64, XunilFrameAllocator},
|
|
||||||
usermode::enter_usermode_x86_64,
|
|
||||||
};
|
};
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::structures::paging::OffsetPageTable;
|
use x86_64::structures::paging::OffsetPageTable;
|
||||||
@@ -21,7 +16,7 @@ use x86_64::structures::paging::OffsetPageTable;
|
|||||||
pub fn init<'a>(
|
pub fn init<'a>(
|
||||||
hhdm_response: &HhdmResponse,
|
hhdm_response: &HhdmResponse,
|
||||||
memory_map_response: &'a MemoryMapResponse,
|
memory_map_response: &'a MemoryMapResponse,
|
||||||
) -> (OffsetPageTable<'static>) {
|
) -> OffsetPageTable<'static> {
|
||||||
return init_x86_64(hhdm_response, memory_map_response);
|
return init_x86_64(hhdm_response, memory_map_response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,11 +46,10 @@ pub fn idle() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(ticks: u64) {
|
pub fn sleep(ticks: u64) {
|
||||||
// let start = TIMER.now();
|
let start = TIMER.now();
|
||||||
// while start.ticks_since() < ticks {
|
while start.ticks_since() < ticks {
|
||||||
// serial_print(start.ticks_since().to_string().as_str());
|
idle();
|
||||||
// core::hint::spin_loop();
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn infinite_idle() -> ! {
|
pub fn infinite_idle() -> ! {
|
||||||
|
|||||||
@@ -1,18 +1,10 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
structures::paging::{
|
structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB},
|
||||||
FrameAllocator, Mapper, OffsetPageTable, Page, PageTableFlags, PhysFrame, Size4KiB,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{arch::arch::FRAME_ALLOCATOR, task::scheduler::SCHEDULER};
|
||||||
arch::{
|
|
||||||
arch::FRAME_ALLOCATOR,
|
|
||||||
x86_64::{paging::XunilFrameAllocator, usermode::enter_usermode_x86_64},
|
|
||||||
},
|
|
||||||
task::{process::Process, scheduler::SCHEDULER},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn run_elf_x86_64(entry_point: *const u8, heap_base: u64) {
|
pub fn run_elf_x86_64(entry_point: *const u8, heap_base: u64) {
|
||||||
let stack_base: u64 = 0x0000_7fff_0000_0000;
|
let stack_base: u64 = 0x0000_7fff_0000_0000;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::arch::x86_64::paging::{FRAME_ALLOCATOR_X86_64, XunilFrameAllocator};
|
use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64;
|
||||||
use crate::util::{Locked, serial_print};
|
use crate::util::Locked;
|
||||||
use core::{
|
use core::{
|
||||||
alloc::{GlobalAlloc, Layout},
|
alloc::{GlobalAlloc, Layout},
|
||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use crate::{
|
|||||||
mouse::setup_mouse,
|
mouse::setup_mouse,
|
||||||
},
|
},
|
||||||
driver::mouse::MOUSE,
|
driver::mouse::MOUSE,
|
||||||
util::serial_print,
|
|
||||||
};
|
};
|
||||||
use limine::response::{HhdmResponse, MemoryMapResponse};
|
use limine::response::{HhdmResponse, MemoryMapResponse};
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
@@ -23,7 +22,7 @@ const PIT_DIVISOR: u16 = (1_193_182_u32 / TIMER_PRECISION_HZ) as u16;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use crate::arch::x86_64::{
|
use crate::arch::x86_64::{
|
||||||
heap::init_heap,
|
heap::init_heap,
|
||||||
paging::{FRAME_ALLOCATOR_X86_64, XunilFrameAllocator, initialize_paging},
|
paging::{FRAME_ALLOCATOR_X86_64, initialize_paging},
|
||||||
};
|
};
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use x86_64::{VirtAddr, structures::paging::OffsetPageTable};
|
use x86_64::{VirtAddr, structures::paging::OffsetPageTable};
|
||||||
@@ -61,6 +60,7 @@ pub fn init_x86_64<'a>(
|
|||||||
load_gdt_x86_64();
|
load_gdt_x86_64();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
// setup SSE (SIMD = Single Instruction, Multiple Data)
|
||||||
let mut cr0 = Cr0::read();
|
let mut cr0 = Cr0::read();
|
||||||
cr0.remove(Cr0Flags::EMULATE_COPROCESSOR);
|
cr0.remove(Cr0Flags::EMULATE_COPROCESSOR);
|
||||||
cr0.insert(Cr0Flags::MONITOR_COPROCESSOR);
|
cr0.insert(Cr0Flags::MONITOR_COPROCESSOR);
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
arch::x86_64::{gdt, mouse::mouse_interrupt},
|
arch::x86_64::{gdt, mouse::mouse_interrupt},
|
||||||
driver::{
|
driver::{keyboard::process_keyboard_event, mouse::MOUSE, timer::TIMER},
|
||||||
keyboard::{KEYBOARD_STATE, KeyboardEvent},
|
|
||||||
mouse::MOUSE,
|
|
||||||
timer::TIMER,
|
|
||||||
},
|
|
||||||
println,
|
println,
|
||||||
util::serial_print,
|
|
||||||
};
|
};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use pc_keyboard::DecodedKey;
|
|
||||||
use pic8259::ChainedPics;
|
use pic8259::ChainedPics;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
@@ -19,8 +13,8 @@ use x86_64::{
|
|||||||
structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PIC_1_OFFSET: u8 = 32;
|
pub const PIC_1_OFFSET: u8 = 32; // master
|
||||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; // slave
|
||||||
|
|
||||||
pub static PICS: Mutex<ChainedPics> =
|
pub static PICS: Mutex<ChainedPics> =
|
||||||
Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
|
||||||
@@ -134,20 +128,8 @@ extern "x86-interrupt" fn mouse_interrupt_handler(_stack_frame: InterruptStackFr
|
|||||||
pub extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
pub extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStackFrame) {
|
||||||
let mut port = Port::new(0x60);
|
let mut port = Port::new(0x60);
|
||||||
let scancode: u8 = unsafe { port.read() };
|
let scancode: u8 = unsafe { port.read() };
|
||||||
let mut keyboard_state = KEYBOARD_STATE.lock();
|
|
||||||
|
|
||||||
if let Ok(Some(key_event)) = keyboard_state.keyboard.add_byte(scancode) {
|
process_keyboard_event(scancode);
|
||||||
if let Some(key) = keyboard_state.keyboard.process_keyevent(key_event) {
|
|
||||||
match key {
|
|
||||||
DecodedKey::Unicode(character) => keyboard_state
|
|
||||||
.event_queue
|
|
||||||
.push_back(KeyboardEvent::Unicode(character)),
|
|
||||||
DecodedKey::RawKey(key) => keyboard_state
|
|
||||||
.event_queue
|
|
||||||
.push_back(KeyboardEvent::RawKey(key)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
PICS.lock()
|
PICS.lock()
|
||||||
@@ -175,6 +157,7 @@ unsafe extern "C" fn syscall_interrupt_handler() {
|
|||||||
"push rdi",
|
"push rdi",
|
||||||
"push rax",
|
"push rax",
|
||||||
"sub rsp, 8",
|
"sub rsp, 8",
|
||||||
|
"sti", // allow IRQ interrupts
|
||||||
"mov rcx, rdx", // arg2
|
"mov rcx, rdx", // arg2
|
||||||
"mov rdx, rsi", // arg1
|
"mov rdx, rsi", // arg1
|
||||||
"mov rsi, rdi", // arg0
|
"mov rsi, rdi", // arg0
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use alloc::string::ToString;
|
|
||||||
use spin::mutex::Mutex;
|
use spin::mutex::Mutex;
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
PhysAddr, VirtAddr,
|
PhysAddr, VirtAddr,
|
||||||
@@ -8,7 +7,7 @@ use x86_64::{
|
|||||||
|
|
||||||
use limine::memory_map::{Entry, EntryType};
|
use limine::memory_map::{Entry, EntryType};
|
||||||
|
|
||||||
use crate::util::{align_up, serial_print};
|
use crate::util::align_up;
|
||||||
|
|
||||||
unsafe fn active_level_4_table(mem_offset: VirtAddr) -> &'static mut PageTable {
|
unsafe fn active_level_4_table(mem_offset: VirtAddr) -> &'static mut PageTable {
|
||||||
let (level_4_table, _) = Cr3::read();
|
let (level_4_table, _) = Cr3::read();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use core::ptr::null;
|
use core::ptr::null;
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
|
||||||
use x86_64::structures::paging::OffsetPageTable;
|
use x86_64::structures::paging::OffsetPageTable;
|
||||||
|
|
||||||
use crate::driver::{
|
use crate::driver::{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::driver::elf::{
|
use crate::driver::elf::{
|
||||||
header::{Elf64Ehdr, Elf64Rel, Elf64Rela, Elf64Shdr, R_X86_64_64},
|
header::{Elf64Ehdr, Elf64Rel, Elf64Shdr, R_X86_64_64},
|
||||||
section::{elf_get_symval, elf_section},
|
section::{elf_get_symval, elf_section},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -80,9 +80,9 @@ impl Framebuffer {
|
|||||||
let w = core::cmp::min(src_width, self.width);
|
let w = core::cmp::min(src_width, self.width);
|
||||||
|
|
||||||
for y in 0..h {
|
for y in 0..h {
|
||||||
let src_row = src_ptr.add(y * src_width);
|
let src_row = unsafe { src_ptr.add(y * src_width) };
|
||||||
let dst_row = self.back_buffer.as_mut_ptr().add(y * self.pitch);
|
let dst_row = unsafe { self.back_buffer.as_mut_ptr().add(y * self.pitch) };
|
||||||
core::ptr::copy_nonoverlapping(src_row, dst_row, w);
|
unsafe { core::ptr::copy_nonoverlapping(src_row, dst_row, w) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,79 @@
|
|||||||
use alloc::collections::VecDeque;
|
use pc_keyboard::{DecodedKey, HandleControl, KeyState, Keyboard, ScancodeSet2, layouts};
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use pc_keyboard::{HandleControl, Keyboard, ScancodeSet1, layouts};
|
|
||||||
use spin::mutex::Mutex;
|
use spin::mutex::Mutex;
|
||||||
|
use x86_64::instructions::interrupts::without_interrupts;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
use crate::task::scheduler::SCHEDULER;
|
||||||
pub enum KeyboardEvent {
|
|
||||||
Unicode(char),
|
#[repr(C)]
|
||||||
RawKey(pc_keyboard::KeyCode),
|
#[derive(Clone, Debug, Copy, Default)]
|
||||||
|
pub struct KeyboardEvent {
|
||||||
|
pub state: u8,
|
||||||
|
pub _pad1: u8,
|
||||||
|
pub key: u16,
|
||||||
|
pub mods: u16,
|
||||||
|
pub _pad2: u16,
|
||||||
|
pub unicode: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct KeyboardState {
|
pub fn process_keyboard_event(scancode: u8) {
|
||||||
pub keyboard: Keyboard<layouts::Us104Key, ScancodeSet1>,
|
let mut keyboard = without_interrupts(|| KEYBOARD.lock());
|
||||||
pub event_queue: VecDeque<KeyboardEvent>,
|
|
||||||
|
let scheduler = without_interrupts(|| SCHEDULER.lock());
|
||||||
|
let pid = scheduler.current_process;
|
||||||
|
|
||||||
|
if pid < 0 {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
impl KeyboardState {
|
|
||||||
pub fn new() -> KeyboardState {
|
drop(scheduler);
|
||||||
KeyboardState {
|
|
||||||
keyboard: Keyboard::new(
|
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||||
ScancodeSet1::new(),
|
let keycode = key_event.code;
|
||||||
|
let keystate = key_event.state;
|
||||||
|
if let Some(key) = keyboard.process_keyevent(key_event) {
|
||||||
|
match key {
|
||||||
|
DecodedKey::Unicode(character) => {
|
||||||
|
SCHEDULER.with_process(pid as u64, |process| {
|
||||||
|
process.kbd_buffer.push(KeyboardEvent {
|
||||||
|
state: if keystate == KeyState::Down { 1 } else { 0 },
|
||||||
|
_pad1: 0,
|
||||||
|
key: keycode as u16,
|
||||||
|
mods: 0,
|
||||||
|
_pad2: 0,
|
||||||
|
unicode: character as u32,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
DecodedKey::RawKey(_) => {
|
||||||
|
SCHEDULER.with_process(pid as u64, |process| {
|
||||||
|
process.kbd_buffer.push(KeyboardEvent {
|
||||||
|
state: if keystate == KeyState::Down { 1 } else { 0 },
|
||||||
|
_pad1: 0,
|
||||||
|
key: keycode as u16,
|
||||||
|
mods: 0,
|
||||||
|
_pad2: 0,
|
||||||
|
unicode: 0,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SCHEDULER.with_process(pid as u64, |process| {
|
||||||
|
process.kbd_buffer.push(KeyboardEvent {
|
||||||
|
state: if keystate == KeyState::Down { 1 } else { 0 },
|
||||||
|
_pad1: 0,
|
||||||
|
key: keycode as u16,
|
||||||
|
mods: 0,
|
||||||
|
_pad2: 0,
|
||||||
|
unicode: 0,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet2>> = Mutex::new(Keyboard::new(
|
||||||
|
ScancodeSet2::new(),
|
||||||
layouts::Us104Key,
|
layouts::Us104Key,
|
||||||
HandleControl::Ignore,
|
HandleControl::Ignore,
|
||||||
),
|
));
|
||||||
event_queue: VecDeque::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref KEYBOARD_STATE: Mutex<KeyboardState> = Mutex::new(KeyboardState::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop_event() -> Option<KeyboardEvent> {
|
|
||||||
KEYBOARD_STATE.lock().event_queue.pop_front()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub struct ConsoleWriter<'a> {
|
|||||||
impl Write for ConsoleWriter<'_> {
|
impl Write for ConsoleWriter<'_> {
|
||||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
serial_print(s);
|
serial_print(s);
|
||||||
self.console.render_text(self.fb, s, 2, false);
|
// self.console.render_text(self.fb, s, 2, false);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ use core::{
|
|||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::string::ToString;
|
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
VirtAddr,
|
VirtAddr,
|
||||||
|
instructions::interrupts::without_interrupts,
|
||||||
structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB},
|
structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -13,11 +13,13 @@ use crate::{
|
|||||||
arch::arch::{FRAME_ALLOCATOR, get_allocator, infinite_idle, sleep},
|
arch::arch::{FRAME_ALLOCATOR, get_allocator, infinite_idle, sleep},
|
||||||
driver::{
|
driver::{
|
||||||
graphics::{framebuffer::with_framebuffer, primitives::rectangle_filled},
|
graphics::{framebuffer::with_framebuffer, primitives::rectangle_filled},
|
||||||
|
keyboard::KeyboardEvent,
|
||||||
timer::TIMER,
|
timer::TIMER,
|
||||||
},
|
},
|
||||||
|
mm::usercopy::copy_to_user,
|
||||||
print, println,
|
print, println,
|
||||||
task::scheduler::SCHEDULER,
|
task::scheduler::SCHEDULER,
|
||||||
util::{align_up, serial_print},
|
util::align_up,
|
||||||
};
|
};
|
||||||
|
|
||||||
const READ: usize = 0;
|
const READ: usize = 0;
|
||||||
@@ -41,10 +43,11 @@ const UNLINK: usize = 87;
|
|||||||
const GETDENTS64: usize = 217;
|
const GETDENTS64: usize = 217;
|
||||||
const CLOCK_GETTIME: usize = 228;
|
const CLOCK_GETTIME: usize = 228;
|
||||||
const EXIT_GROUP: usize = 231;
|
const EXIT_GROUP: usize = 231;
|
||||||
|
const KBD_READ: usize = 666;
|
||||||
const SLEEP: usize = 909090; // zzz haha
|
const SLEEP: usize = 909090; // zzz haha
|
||||||
const DRAW_PIXEL: usize = 5555;
|
const DRAW_PIXEL: usize = 5555;
|
||||||
const FRAMEBUFFER_SWAP: usize = 6666;
|
const FRAMEBUFFER_SWAP: usize = 6666;
|
||||||
pub const DRAW_BUFFER: usize = 7777;
|
const DRAW_BUFFER: usize = 7777;
|
||||||
|
|
||||||
pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
|
pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
|
||||||
let align = if align < 1 {
|
let align = if align < 1 {
|
||||||
@@ -81,8 +84,40 @@ pub unsafe fn memset(ptr: *mut u8, val: u8, count: usize) {
|
|||||||
unsafe { core::ptr::write_bytes(ptr, val, count) };
|
unsafe { core::ptr::write_bytes(ptr, val, count) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize {
|
||||||
|
if max_events <= 0 || user_ptr.is_null() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pid = without_interrupts(|| {
|
||||||
|
let scheduler = SCHEDULER.lock();
|
||||||
|
scheduler.current_process
|
||||||
|
});
|
||||||
|
|
||||||
|
if pid < 0 {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCHEDULER
|
||||||
|
.with_process(pid as u64, |process| {
|
||||||
|
let to_copy = (max_events as usize).min(process.kbd_buffer.len());
|
||||||
|
if let Ok(_) = copy_to_user(
|
||||||
|
&mut process.address_space.mapper,
|
||||||
|
user_ptr as *mut u8,
|
||||||
|
process.kbd_buffer.as_ptr() as *const u8,
|
||||||
|
to_copy * size_of::<KeyboardEvent>(),
|
||||||
|
) {
|
||||||
|
process.kbd_buffer.drain(0..to_copy);
|
||||||
|
return to_copy as isize;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.unwrap_or(-1);
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn sbrk(increment: isize) -> isize {
|
pub unsafe fn sbrk(increment: isize) -> isize {
|
||||||
let mut scheduler = SCHEDULER.lock();
|
let scheduler = without_interrupts(|| SCHEDULER.lock());
|
||||||
if scheduler.current_process == -1 {
|
if scheduler.current_process == -1 {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -91,7 +126,7 @@ pub unsafe fn sbrk(increment: isize) -> isize {
|
|||||||
|
|
||||||
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
||||||
return SCHEDULER
|
return SCHEDULER
|
||||||
.with_process(pid as u64, |mut process| {
|
.with_process(pid as u64, |process| {
|
||||||
let (heap_end, heap_base, stack_top) =
|
let (heap_end, heap_base, stack_top) =
|
||||||
(process.heap_end, process.heap_base, process.stack_top);
|
(process.heap_end, process.heap_base, process.stack_top);
|
||||||
|
|
||||||
@@ -161,7 +196,7 @@ pub unsafe extern "C" fn syscall_dispatch(
|
|||||||
arg2: isize,
|
arg2: isize,
|
||||||
) -> isize {
|
) -> isize {
|
||||||
match num {
|
match num {
|
||||||
BRK => sbrk(arg0),
|
BRK => unsafe { sbrk(arg0) },
|
||||||
WRITE => {
|
WRITE => {
|
||||||
let buf_ptr = arg1 as *const u8;
|
let buf_ptr = arg1 as *const u8;
|
||||||
let len = arg2 as usize;
|
let len = arg2 as usize;
|
||||||
@@ -185,10 +220,6 @@ pub unsafe extern "C" fn syscall_dispatch(
|
|||||||
with_framebuffer(|fb| fb.swap());
|
with_framebuffer(|fb| fb.swap());
|
||||||
infinite_idle();
|
infinite_idle();
|
||||||
}
|
}
|
||||||
67 => {
|
|
||||||
println!("{:?}", arg1);
|
|
||||||
0
|
|
||||||
}
|
|
||||||
SLEEP => {
|
SLEEP => {
|
||||||
sleep(arg0 as u64);
|
sleep(arg0 as u64);
|
||||||
0
|
0
|
||||||
@@ -201,12 +232,13 @@ pub unsafe extern "C" fn syscall_dispatch(
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
DRAW_BUFFER => {
|
DRAW_BUFFER => {
|
||||||
with_framebuffer(|mut fb| {
|
with_framebuffer(|fb| {
|
||||||
fb.load_from_ptr(arg0 as *const u32, arg1 as usize, arg2 as usize);
|
unsafe { fb.load_from_ptr(arg0 as *const u32, arg1 as usize, arg2 as usize) };
|
||||||
fb.swap();
|
fb.swap();
|
||||||
});
|
});
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
KBD_READ => kbd_read(arg0 as *mut KeyboardEvent, arg1),
|
||||||
FRAMEBUFFER_SWAP => {
|
FRAMEBUFFER_SWAP => {
|
||||||
with_framebuffer(|fb| {
|
with_framebuffer(|fb| {
|
||||||
fb.swap();
|
fb.swap();
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ use core::{
|
|||||||
sync::atomic::{AtomicU64, Ordering},
|
sync::atomic::{AtomicU64, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::util::serial_print;
|
|
||||||
|
|
||||||
pub static TIMER: Timer = Timer::new();
|
pub static TIMER: Timer = Timer::new();
|
||||||
|
|
||||||
pub struct Timer {
|
pub struct Timer {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
#![feature(str_from_raw_parts)]
|
#![feature(str_from_raw_parts)]
|
||||||
#![allow(warnings)]
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
@@ -24,7 +23,6 @@ use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer};
|
|||||||
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
|
use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console};
|
||||||
use crate::driver::timer::TIMER;
|
use crate::driver::timer::TIMER;
|
||||||
use crate::userspace_stub::userspace_init;
|
use crate::userspace_stub::userspace_init;
|
||||||
use crate::util::serial_print;
|
|
||||||
/// Sets the base revision to the latest revision supported by the crate.
|
/// Sets the base revision to the latest revision supported by the crate.
|
||||||
/// See specification for further info.
|
/// See specification for further info.
|
||||||
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
|
/// Be sure to mark all limine requests with #[used], otherwise they may be removed by the compiler.
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ use x86_64::{
|
|||||||
structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB},
|
structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::arch::arch::FRAME_ALLOCATOR;
|
||||||
arch::{arch::FRAME_ALLOCATOR, x86_64::paging::XunilFrameAllocator},
|
|
||||||
driver::syscall::memset,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct AddressSpace {
|
pub struct AddressSpace {
|
||||||
cr3_frame: PhysFrame<Size4KiB>,
|
cr3_frame: PhysFrame<Size4KiB>,
|
||||||
@@ -24,7 +21,7 @@ impl AddressSpace {
|
|||||||
core::ptr::write_bytes(new_pml4_ptr, 0, 512);
|
core::ptr::write_bytes(new_pml4_ptr, 0, 512);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (cur_pml4, pml4_flags) = Cr3::read();
|
let (cur_pml4, _) = Cr3::read();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let cur_pml4_ptr =
|
let cur_pml4_ptr =
|
||||||
@@ -38,7 +35,7 @@ impl AddressSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut mapper = unsafe {
|
let mapper = unsafe {
|
||||||
let addr = frame_allocator.hhdm_offset + new_pml4.start_address().as_u64();
|
let addr = frame_allocator.hhdm_offset + new_pml4.start_address().as_u64();
|
||||||
let virtual_addr = VirtAddr::new(addr);
|
let virtual_addr = VirtAddr::new(addr);
|
||||||
let level_4_table: *mut PageTable = virtual_addr.as_mut_ptr();
|
let level_4_table: *mut PageTable = virtual_addr.as_mut_ptr();
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
pub mod address_space;
|
pub mod address_space;
|
||||||
|
pub mod usercopy;
|
||||||
|
|||||||
39
kernel/src/mm/usercopy.rs
Normal file
39
kernel/src/mm/usercopy.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
use x86_64::{
|
||||||
|
VirtAddr,
|
||||||
|
structures::paging::{OffsetPageTable, PageTableFlags, Translate, mapper::TranslateResult},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn copy_to_user(
|
||||||
|
mapper: &mut OffsetPageTable,
|
||||||
|
buf: *mut u8,
|
||||||
|
src: *const u8,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<(), isize> {
|
||||||
|
let start = buf as u64;
|
||||||
|
let end = start + len as u64;
|
||||||
|
let mut page_addr = start & !0xFFF;
|
||||||
|
|
||||||
|
while page_addr < end {
|
||||||
|
let translate_result = mapper.translate(VirtAddr::new(page_addr));
|
||||||
|
#[allow(non_shorthand_field_patterns)]
|
||||||
|
if let TranslateResult::Mapped {
|
||||||
|
frame: _,
|
||||||
|
offset: _,
|
||||||
|
flags: flags,
|
||||||
|
} = translate_result
|
||||||
|
{
|
||||||
|
if flags.contains(PageTableFlags::USER_ACCESSIBLE)
|
||||||
|
&& flags.contains(PageTableFlags::WRITABLE)
|
||||||
|
{
|
||||||
|
} else {
|
||||||
|
return Err(-13);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(-1);
|
||||||
|
}
|
||||||
|
page_addr += 0x1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { core::ptr::copy_nonoverlapping(src, buf, len) };
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::{arch::x86_64::paging::XunilFrameAllocator, mm::address_space::AddressSpace};
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
enum ProcessState {
|
use crate::{driver::keyboard::KeyboardEvent, mm::address_space::AddressSpace};
|
||||||
|
|
||||||
|
pub enum ProcessState {
|
||||||
Ready,
|
Ready,
|
||||||
Running,
|
Running,
|
||||||
Blocked,
|
Blocked,
|
||||||
@@ -10,10 +12,10 @@ enum ProcessState {
|
|||||||
pub struct Process {
|
pub struct Process {
|
||||||
pub pid: u64,
|
pub pid: u64,
|
||||||
pub state: ProcessState,
|
pub state: ProcessState,
|
||||||
// cpu_ctx: &[u8],
|
|
||||||
pub stack_top: u64,
|
pub stack_top: u64,
|
||||||
pub heap_base: u64,
|
pub heap_base: u64,
|
||||||
pub heap_end: u64,
|
pub heap_end: u64,
|
||||||
|
pub kbd_buffer: Vec<KeyboardEvent>,
|
||||||
pub address_space: AddressSpace,
|
pub address_space: AddressSpace,
|
||||||
pub user_entry: u64,
|
pub user_entry: u64,
|
||||||
}
|
}
|
||||||
@@ -33,6 +35,7 @@ impl Process {
|
|||||||
state: ProcessState::Ready,
|
state: ProcessState::Ready,
|
||||||
heap_base,
|
heap_base,
|
||||||
heap_end,
|
heap_end,
|
||||||
|
kbd_buffer: Vec::new(),
|
||||||
address_space,
|
address_space,
|
||||||
user_entry,
|
user_entry,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
use alloc::collections::btree_map::BTreeMap;
|
use alloc::collections::btree_map::BTreeMap;
|
||||||
use lazy_static::lazy_static;
|
use x86_64::instructions::interrupts::without_interrupts;
|
||||||
|
|
||||||
use crate::{
|
use crate::{arch::arch::enter_usermode, task::process::Process, util::Locked};
|
||||||
arch::{arch::enter_usermode, x86_64::paging::XunilFrameAllocator},
|
|
||||||
task::process::Process,
|
|
||||||
util::Locked,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Scheduler {
|
pub struct Scheduler {
|
||||||
pub processes: BTreeMap<u64, Process>,
|
pub processes: BTreeMap<u64, Process>,
|
||||||
@@ -25,7 +21,7 @@ impl Scheduler {
|
|||||||
|
|
||||||
impl Locked<Scheduler> {
|
impl Locked<Scheduler> {
|
||||||
pub fn spawn_process(&self, entry_point: u64, stack_top: u64, heap_base: u64) -> Option<u64> {
|
pub fn spawn_process(&self, entry_point: u64, stack_top: u64, heap_base: u64) -> Option<u64> {
|
||||||
let mut guard = self.lock();
|
let mut guard = without_interrupts(|| self.lock());
|
||||||
let pid = guard.next_pid;
|
let pid = guard.next_pid;
|
||||||
guard.next_pid += 1;
|
guard.next_pid += 1;
|
||||||
let process = Process::new(pid, entry_point, stack_top, heap_base, heap_base)?;
|
let process = Process::new(pid, entry_point, stack_top, heap_base, heap_base)?;
|
||||||
@@ -35,7 +31,7 @@ impl Locked<Scheduler> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_process(&self, pid: u64, entry_point: *const u8) {
|
pub fn run_process(&self, pid: u64, entry_point: *const u8) {
|
||||||
let mut guard = self.lock();
|
let mut guard = without_interrupts(|| self.lock());
|
||||||
let stack_top = guard.processes[&pid].stack_top;
|
let stack_top = guard.processes[&pid].stack_top;
|
||||||
guard.current_process = pid as i64;
|
guard.current_process = pid as i64;
|
||||||
|
|
||||||
@@ -48,7 +44,7 @@ impl Locked<Scheduler> {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&mut Process) -> R,
|
F: FnOnce(&mut Process) -> R,
|
||||||
{
|
{
|
||||||
let mut guard = self.lock();
|
let mut guard = without_interrupts(|| self.lock());
|
||||||
let process = guard.processes.get_mut(&index)?;
|
let process = guard.processes.get_mut(&index)?;
|
||||||
Some(f(process))
|
Some(f(process))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ use alloc::string::ToString;
|
|||||||
use x86_64::structures::paging::OffsetPageTable;
|
use x86_64::structures::paging::OffsetPageTable;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
arch::{
|
arch::arch::{run_elf, sleep},
|
||||||
arch::{FRAME_ALLOCATOR, run_elf, sleep},
|
|
||||||
x86_64::paging::XunilFrameAllocator,
|
|
||||||
},
|
|
||||||
driver::{
|
driver::{
|
||||||
elf::loader::load_file,
|
elf::loader::load_file,
|
||||||
graphics::{
|
graphics::{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "../src/stdio.h"
|
#include "../../libxunil/include/stdio.h"
|
||||||
|
|
||||||
void _start() {
|
int main(int argc, char **argv) {
|
||||||
write(0, "Hello, World!", 13);
|
printf("%s\n", "Hello, world!");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user