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")]
|
||||
pub use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64 as FRAME_ALLOCATOR;
|
||||
|
||||
use crate::{driver::timer::TIMER, util::serial_print};
|
||||
use alloc::string::ToString;
|
||||
use core::{alloc::GlobalAlloc, arch::asm, sync::atomic::Ordering};
|
||||
use crate::driver::timer::TIMER;
|
||||
use core::{alloc::GlobalAlloc, arch::asm};
|
||||
use limine::response::{HhdmResponse, MemoryMapResponse};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::arch::x86_64::{
|
||||
elf::run_elf_x86_64,
|
||||
heap::ALLOCATOR,
|
||||
init::init_x86_64,
|
||||
paging::{FRAME_ALLOCATOR_X86_64, XunilFrameAllocator},
|
||||
usermode::enter_usermode_x86_64,
|
||||
elf::run_elf_x86_64, heap::ALLOCATOR, init::init_x86_64, usermode::enter_usermode_x86_64,
|
||||
};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use x86_64::structures::paging::OffsetPageTable;
|
||||
@@ -21,7 +16,7 @@ use x86_64::structures::paging::OffsetPageTable;
|
||||
pub fn init<'a>(
|
||||
hhdm_response: &HhdmResponse,
|
||||
memory_map_response: &'a MemoryMapResponse,
|
||||
) -> (OffsetPageTable<'static>) {
|
||||
) -> OffsetPageTable<'static> {
|
||||
return init_x86_64(hhdm_response, memory_map_response);
|
||||
}
|
||||
|
||||
@@ -51,11 +46,10 @@ pub fn idle() {
|
||||
}
|
||||
|
||||
pub fn sleep(ticks: u64) {
|
||||
// let start = TIMER.now();
|
||||
// while start.ticks_since() < ticks {
|
||||
// serial_print(start.ticks_since().to_string().as_str());
|
||||
// core::hint::spin_loop();
|
||||
// }
|
||||
let start = TIMER.now();
|
||||
while start.ticks_since() < ticks {
|
||||
idle();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn infinite_idle() -> ! {
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
use alloc::vec::Vec;
|
||||
use x86_64::{
|
||||
VirtAddr,
|
||||
structures::paging::{
|
||||
FrameAllocator, Mapper, OffsetPageTable, Page, PageTableFlags, PhysFrame, Size4KiB,
|
||||
},
|
||||
structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::{
|
||||
arch::FRAME_ALLOCATOR,
|
||||
x86_64::{paging::XunilFrameAllocator, usermode::enter_usermode_x86_64},
|
||||
},
|
||||
task::{process::Process, scheduler::SCHEDULER},
|
||||
};
|
||||
use crate::{arch::arch::FRAME_ALLOCATOR, task::scheduler::SCHEDULER};
|
||||
|
||||
pub fn run_elf_x86_64(entry_point: *const u8, heap_base: u64) {
|
||||
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::util::{Locked, serial_print};
|
||||
use crate::arch::x86_64::paging::FRAME_ALLOCATOR_X86_64;
|
||||
use crate::util::Locked;
|
||||
use core::{
|
||||
alloc::{GlobalAlloc, Layout},
|
||||
ptr::null_mut,
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::{
|
||||
mouse::setup_mouse,
|
||||
},
|
||||
driver::mouse::MOUSE,
|
||||
util::serial_print,
|
||||
};
|
||||
use limine::response::{HhdmResponse, MemoryMapResponse};
|
||||
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")]
|
||||
use crate::arch::x86_64::{
|
||||
heap::init_heap,
|
||||
paging::{FRAME_ALLOCATOR_X86_64, XunilFrameAllocator, initialize_paging},
|
||||
paging::{FRAME_ALLOCATOR_X86_64, initialize_paging},
|
||||
};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use x86_64::{VirtAddr, structures::paging::OffsetPageTable};
|
||||
@@ -61,6 +60,7 @@ pub fn init_x86_64<'a>(
|
||||
load_gdt_x86_64();
|
||||
|
||||
unsafe {
|
||||
// setup SSE (SIMD = Single Instruction, Multiple Data)
|
||||
let mut cr0 = Cr0::read();
|
||||
cr0.remove(Cr0Flags::EMULATE_COPROCESSOR);
|
||||
cr0.insert(Cr0Flags::MONITOR_COPROCESSOR);
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
use crate::{
|
||||
arch::x86_64::{gdt, mouse::mouse_interrupt},
|
||||
driver::{
|
||||
keyboard::{KEYBOARD_STATE, KeyboardEvent},
|
||||
mouse::MOUSE,
|
||||
timer::TIMER,
|
||||
},
|
||||
driver::{keyboard::process_keyboard_event, mouse::MOUSE, timer::TIMER},
|
||||
println,
|
||||
util::serial_print,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use pc_keyboard::DecodedKey;
|
||||
use pic8259::ChainedPics;
|
||||
use spin::Mutex;
|
||||
use x86_64::{
|
||||
@@ -19,8 +13,8 @@ use x86_64::{
|
||||
structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode},
|
||||
};
|
||||
|
||||
pub const PIC_1_OFFSET: u8 = 32;
|
||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
|
||||
pub const PIC_1_OFFSET: u8 = 32; // master
|
||||
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; // slave
|
||||
|
||||
pub static PICS: Mutex<ChainedPics> =
|
||||
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) {
|
||||
let mut port = Port::new(0x60);
|
||||
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) {
|
||||
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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
process_keyboard_event(scancode);
|
||||
|
||||
unsafe {
|
||||
PICS.lock()
|
||||
@@ -175,6 +157,7 @@ unsafe extern "C" fn syscall_interrupt_handler() {
|
||||
"push rdi",
|
||||
"push rax",
|
||||
"sub rsp, 8",
|
||||
"sti", // allow IRQ interrupts
|
||||
"mov rcx, rdx", // arg2
|
||||
"mov rdx, rsi", // arg1
|
||||
"mov rsi, rdi", // arg0
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use alloc::string::ToString;
|
||||
use spin::mutex::Mutex;
|
||||
use x86_64::{
|
||||
PhysAddr, VirtAddr,
|
||||
@@ -8,7 +7,7 @@ use x86_64::{
|
||||
|
||||
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 {
|
||||
let (level_4_table, _) = Cr3::read();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use core::ptr::null;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use x86_64::structures::paging::OffsetPageTable;
|
||||
|
||||
use crate::driver::{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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},
|
||||
};
|
||||
|
||||
|
||||
@@ -80,9 +80,9 @@ impl Framebuffer {
|
||||
let w = core::cmp::min(src_width, self.width);
|
||||
|
||||
for y in 0..h {
|
||||
let src_row = src_ptr.add(y * src_width);
|
||||
let dst_row = self.back_buffer.as_mut_ptr().add(y * self.pitch);
|
||||
core::ptr::copy_nonoverlapping(src_row, dst_row, w);
|
||||
let src_row = unsafe { src_ptr.add(y * src_width) };
|
||||
let dst_row = unsafe { self.back_buffer.as_mut_ptr().add(y * self.pitch) };
|
||||
unsafe { core::ptr::copy_nonoverlapping(src_row, dst_row, w) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,35 +1,79 @@
|
||||
use alloc::collections::VecDeque;
|
||||
use lazy_static::lazy_static;
|
||||
use pc_keyboard::{HandleControl, Keyboard, ScancodeSet1, layouts};
|
||||
use pc_keyboard::{DecodedKey, HandleControl, KeyState, Keyboard, ScancodeSet2, layouts};
|
||||
use spin::mutex::Mutex;
|
||||
use x86_64::instructions::interrupts::without_interrupts;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum KeyboardEvent {
|
||||
Unicode(char),
|
||||
RawKey(pc_keyboard::KeyCode),
|
||||
use crate::task::scheduler::SCHEDULER;
|
||||
|
||||
#[repr(C)]
|
||||
#[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 keyboard: Keyboard<layouts::Us104Key, ScancodeSet1>,
|
||||
pub event_queue: VecDeque<KeyboardEvent>,
|
||||
}
|
||||
impl KeyboardState {
|
||||
pub fn new() -> KeyboardState {
|
||||
KeyboardState {
|
||||
keyboard: Keyboard::new(
|
||||
ScancodeSet1::new(),
|
||||
layouts::Us104Key,
|
||||
HandleControl::Ignore,
|
||||
),
|
||||
event_queue: VecDeque::new(),
|
||||
pub fn process_keyboard_event(scancode: u8) {
|
||||
let mut keyboard = without_interrupts(|| KEYBOARD.lock());
|
||||
|
||||
let scheduler = without_interrupts(|| SCHEDULER.lock());
|
||||
let pid = scheduler.current_process;
|
||||
|
||||
if pid < 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
drop(scheduler);
|
||||
|
||||
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
|
||||
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,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
pub static KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet2>> = Mutex::new(Keyboard::new(
|
||||
ScancodeSet2::new(),
|
||||
layouts::Us104Key,
|
||||
HandleControl::Ignore,
|
||||
));
|
||||
|
||||
@@ -16,7 +16,7 @@ pub struct ConsoleWriter<'a> {
|
||||
impl Write for ConsoleWriter<'_> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
serial_print(s);
|
||||
self.console.render_text(self.fb, s, 2, false);
|
||||
// self.console.render_text(self.fb, s, 2, false);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ use core::{
|
||||
ptr::null_mut,
|
||||
};
|
||||
|
||||
use alloc::string::ToString;
|
||||
use x86_64::{
|
||||
VirtAddr,
|
||||
instructions::interrupts::without_interrupts,
|
||||
structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB},
|
||||
};
|
||||
|
||||
@@ -13,11 +13,13 @@ use crate::{
|
||||
arch::arch::{FRAME_ALLOCATOR, get_allocator, infinite_idle, sleep},
|
||||
driver::{
|
||||
graphics::{framebuffer::with_framebuffer, primitives::rectangle_filled},
|
||||
keyboard::KeyboardEvent,
|
||||
timer::TIMER,
|
||||
},
|
||||
mm::usercopy::copy_to_user,
|
||||
print, println,
|
||||
task::scheduler::SCHEDULER,
|
||||
util::{align_up, serial_print},
|
||||
util::align_up,
|
||||
};
|
||||
|
||||
const READ: usize = 0;
|
||||
@@ -41,10 +43,11 @@ const UNLINK: usize = 87;
|
||||
const GETDENTS64: usize = 217;
|
||||
const CLOCK_GETTIME: usize = 228;
|
||||
const EXIT_GROUP: usize = 231;
|
||||
const KBD_READ: usize = 666;
|
||||
const SLEEP: usize = 909090; // zzz haha
|
||||
const DRAW_PIXEL: usize = 5555;
|
||||
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 {
|
||||
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) };
|
||||
}
|
||||
|
||||
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 {
|
||||
let mut scheduler = SCHEDULER.lock();
|
||||
let scheduler = without_interrupts(|| SCHEDULER.lock());
|
||||
if scheduler.current_process == -1 {
|
||||
return -1;
|
||||
}
|
||||
@@ -91,7 +126,7 @@ pub unsafe fn sbrk(increment: isize) -> isize {
|
||||
|
||||
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
||||
return SCHEDULER
|
||||
.with_process(pid as u64, |mut process| {
|
||||
.with_process(pid as u64, |process| {
|
||||
let (heap_end, heap_base, stack_top) =
|
||||
(process.heap_end, process.heap_base, process.stack_top);
|
||||
|
||||
@@ -161,7 +196,7 @@ pub unsafe extern "C" fn syscall_dispatch(
|
||||
arg2: isize,
|
||||
) -> isize {
|
||||
match num {
|
||||
BRK => sbrk(arg0),
|
||||
BRK => unsafe { sbrk(arg0) },
|
||||
WRITE => {
|
||||
let buf_ptr = arg1 as *const u8;
|
||||
let len = arg2 as usize;
|
||||
@@ -185,10 +220,6 @@ pub unsafe extern "C" fn syscall_dispatch(
|
||||
with_framebuffer(|fb| fb.swap());
|
||||
infinite_idle();
|
||||
}
|
||||
67 => {
|
||||
println!("{:?}", arg1);
|
||||
0
|
||||
}
|
||||
SLEEP => {
|
||||
sleep(arg0 as u64);
|
||||
0
|
||||
@@ -201,12 +232,13 @@ pub unsafe extern "C" fn syscall_dispatch(
|
||||
0
|
||||
}
|
||||
DRAW_BUFFER => {
|
||||
with_framebuffer(|mut fb| {
|
||||
fb.load_from_ptr(arg0 as *const u32, arg1 as usize, arg2 as usize);
|
||||
with_framebuffer(|fb| {
|
||||
unsafe { fb.load_from_ptr(arg0 as *const u32, arg1 as usize, arg2 as usize) };
|
||||
fb.swap();
|
||||
});
|
||||
0
|
||||
}
|
||||
KBD_READ => kbd_read(arg0 as *mut KeyboardEvent, arg1),
|
||||
FRAMEBUFFER_SWAP => {
|
||||
with_framebuffer(|fb| {
|
||||
fb.swap();
|
||||
|
||||
@@ -3,8 +3,6 @@ use core::{
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
};
|
||||
|
||||
use crate::util::serial_print;
|
||||
|
||||
pub static TIMER: Timer = Timer::new();
|
||||
|
||||
pub struct Timer {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#![no_main]
|
||||
#![feature(abi_x86_interrupt)]
|
||||
#![feature(str_from_raw_parts)]
|
||||
#![allow(warnings)]
|
||||
extern crate alloc;
|
||||
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::timer::TIMER;
|
||||
use crate::userspace_stub::userspace_init;
|
||||
use crate::util::serial_print;
|
||||
/// Sets the base revision to the latest revision supported by the crate.
|
||||
/// See specification for further info.
|
||||
/// 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},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
arch::{arch::FRAME_ALLOCATOR, x86_64::paging::XunilFrameAllocator},
|
||||
driver::syscall::memset,
|
||||
};
|
||||
use crate::arch::arch::FRAME_ALLOCATOR;
|
||||
|
||||
pub struct AddressSpace {
|
||||
cr3_frame: PhysFrame<Size4KiB>,
|
||||
@@ -24,7 +21,7 @@ impl AddressSpace {
|
||||
core::ptr::write_bytes(new_pml4_ptr, 0, 512);
|
||||
}
|
||||
|
||||
let (cur_pml4, pml4_flags) = Cr3::read();
|
||||
let (cur_pml4, _) = Cr3::read();
|
||||
|
||||
unsafe {
|
||||
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 virtual_addr = VirtAddr::new(addr);
|
||||
let level_4_table: *mut PageTable = virtual_addr.as_mut_ptr();
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
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,
|
||||
Running,
|
||||
Blocked,
|
||||
@@ -10,10 +12,10 @@ enum ProcessState {
|
||||
pub struct Process {
|
||||
pub pid: u64,
|
||||
pub state: ProcessState,
|
||||
// cpu_ctx: &[u8],
|
||||
pub stack_top: u64,
|
||||
pub heap_base: u64,
|
||||
pub heap_end: u64,
|
||||
pub kbd_buffer: Vec<KeyboardEvent>,
|
||||
pub address_space: AddressSpace,
|
||||
pub user_entry: u64,
|
||||
}
|
||||
@@ -33,6 +35,7 @@ impl Process {
|
||||
state: ProcessState::Ready,
|
||||
heap_base,
|
||||
heap_end,
|
||||
kbd_buffer: Vec::new(),
|
||||
address_space,
|
||||
user_entry,
|
||||
})
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
use alloc::collections::btree_map::BTreeMap;
|
||||
use lazy_static::lazy_static;
|
||||
use x86_64::instructions::interrupts::without_interrupts;
|
||||
|
||||
use crate::{
|
||||
arch::{arch::enter_usermode, x86_64::paging::XunilFrameAllocator},
|
||||
task::process::Process,
|
||||
util::Locked,
|
||||
};
|
||||
use crate::{arch::arch::enter_usermode, task::process::Process, util::Locked};
|
||||
|
||||
pub struct Scheduler {
|
||||
pub processes: BTreeMap<u64, Process>,
|
||||
@@ -25,7 +21,7 @@ impl Scheduler {
|
||||
|
||||
impl Locked<Scheduler> {
|
||||
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;
|
||||
guard.next_pid += 1;
|
||||
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) {
|
||||
let mut guard = self.lock();
|
||||
let mut guard = without_interrupts(|| self.lock());
|
||||
let stack_top = guard.processes[&pid].stack_top;
|
||||
guard.current_process = pid as i64;
|
||||
|
||||
@@ -48,7 +44,7 @@ impl Locked<Scheduler> {
|
||||
where
|
||||
F: FnOnce(&mut Process) -> R,
|
||||
{
|
||||
let mut guard = self.lock();
|
||||
let mut guard = without_interrupts(|| self.lock());
|
||||
let process = guard.processes.get_mut(&index)?;
|
||||
Some(f(process))
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ use alloc::string::ToString;
|
||||
use x86_64::structures::paging::OffsetPageTable;
|
||||
|
||||
use crate::{
|
||||
arch::{
|
||||
arch::{FRAME_ALLOCATOR, run_elf, sleep},
|
||||
x86_64::paging::XunilFrameAllocator,
|
||||
},
|
||||
arch::arch::{run_elf, sleep},
|
||||
driver::{
|
||||
elf::loader::load_file,
|
||||
graphics::{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "../src/stdio.h"
|
||||
#include "../../libxunil/include/stdio.h"
|
||||
|
||||
void _start() {
|
||||
write(0, "Hello, World!", 13);
|
||||
int main(int argc, char **argv) {
|
||||
printf("%s\n", "Hello, world!");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user