This commit is contained in:
parent
c472ef1e27
commit
34e784ddf7
9 changed files with 98 additions and 37 deletions
|
@ -158,13 +158,15 @@ fn map_range(virt_start: u64, phys_start: u64, size: u64, user: bool, write: boo
|
||||||
map(current_pml4.as_mut().unwrap(), virt_start + i * 0x1000, phys_start + i * 0x1000, user, write, exec, cache_disable);
|
map(current_pml4.as_mut().unwrap(), virt_start + i * 0x1000, phys_start + i * 0x1000, user, write, exec, cache_disable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub unsafe fn map_physical(phys: u64, mut size: u64) -> u64 {
|
pub unsafe fn map_physical(phys: u64, mut size: u64, write_combining: bool) -> u64 {
|
||||||
|
// TODO: Implement WC
|
||||||
let phys_offset = phys % 0x1000;
|
let phys_offset = phys % 0x1000;
|
||||||
let phys_end = (phys + size + 0xfff) / 0x1000 * 0x1000;
|
let phys_end = (phys + size + 0xfff) / 0x1000 * 0x1000;
|
||||||
let phys_start = phys - phys_offset;
|
let phys_start = phys - phys_offset;
|
||||||
size = phys_end - phys_start;
|
size = phys_end - phys_start;
|
||||||
let virt_start = find_free_virt_range(KERNEL_MAPPINGS_START, KERNEL_MAPPINGS_END, size);
|
let virt_start = find_free_virt_range(KERNEL_MAPPINGS_START, KERNEL_MAPPINGS_END, size);
|
||||||
map_range(virt_start, phys_start, size, false, true, false, true);
|
let cache_disable = !write_combining;
|
||||||
|
map_range(virt_start, phys_start, size, false, true, false, cache_disable);
|
||||||
virt_start + phys_offset
|
virt_start + phys_offset
|
||||||
}
|
}
|
||||||
pub unsafe fn unmap_physical(address: u64, size: u64) {
|
pub unsafe fn unmap_physical(address: u64, size: u64) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
|
|
||||||
|
use alloc::vec::Vec;
|
||||||
use embedded_graphics::{
|
use embedded_graphics::{
|
||||||
pixelcolor::Bgr888,
|
pixelcolor::Bgr888,
|
||||||
prelude::{DrawTarget, OriginDimensions, RgbColor, Size},
|
prelude::{DrawTarget, OriginDimensions, RgbColor, Size},
|
||||||
|
@ -7,7 +8,7 @@ use embedded_graphics::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct FramebufferTarget {
|
pub struct FramebufferTarget {
|
||||||
pub framebuffer: *mut u8,
|
pub framebuffer: Vec<u8>,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub stride: usize,
|
pub stride: usize,
|
||||||
|
@ -26,12 +27,10 @@ impl DrawTarget for FramebufferTarget {
|
||||||
if i.0.x < 0 || i.0.x >= self.width as i32 || i.0.y < 0 || i.0.y >= self.height as i32 {
|
if i.0.x < 0 || i.0.x >= self.width as i32 || i.0.y < 0 || i.0.y >= self.height as i32 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let offset = (i.0.y * self.stride as i32 + i.0.x) as isize * 4;
|
let offset = (i.0.y * self.stride as i32 + i.0.x) as usize * 4;
|
||||||
unsafe {
|
self.framebuffer[offset] = i.1.b();
|
||||||
self.framebuffer.offset(offset).write_volatile(i.1.b());
|
self.framebuffer[offset + 1] = i.1.g();
|
||||||
self.framebuffer.offset(offset + 1).write_volatile(i.1.g());
|
self.framebuffer[offset + 2] = i.1.r();
|
||||||
self.framebuffer.offset(offset + 2).write_volatile(i.1.r());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -41,5 +40,3 @@ impl OriginDimensions for FramebufferTarget {
|
||||||
Size::new(self.width as u32, self.height as u32)
|
Size::new(self.width as u32, self.height as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe impl Send for FramebufferTarget {}
|
|
||||||
unsafe impl Sync for FramebufferTarget {}
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ extern "C" fn AcpiOsInstallInterruptHandler(gsi: UINT32, handler: ACPI_OSD_HANDL
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn AcpiOsMapMemory(phys: ACPI_PHYSICAL_ADDRESS, size: ACPI_SIZE) -> *mut c_void {
|
extern "C" fn AcpiOsMapMemory(phys: ACPI_PHYSICAL_ADDRESS, size: ACPI_SIZE) -> *mut c_void {
|
||||||
unsafe {
|
unsafe {
|
||||||
return map_physical(phys, size) as *mut c_void;
|
return map_physical(phys, size, false) as *mut c_void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
|
|
@ -1,23 +1,89 @@
|
||||||
use core::ptr::null_mut;
|
use core::{
|
||||||
|
ptr::null_mut,
|
||||||
|
sync::atomic::{AtomicPtr, AtomicUsize, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
|
use alloc::{string::ToString, vec};
|
||||||
|
use embedded_graphics::{
|
||||||
|
mono_font::{iso_8859_13::FONT_10X20, MonoTextStyle},
|
||||||
|
pixelcolor::Bgr888,
|
||||||
|
prelude::*,
|
||||||
|
text::Text,
|
||||||
|
};
|
||||||
use kernel_common::loader_struct::FramebufferInfo;
|
use kernel_common::loader_struct::FramebufferInfo;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
use crate::{cpu::paging::map_physical, misc::draw_target::FramebufferTarget};
|
use crate::{cpu::paging::map_physical, misc::draw_target::FramebufferTarget};
|
||||||
|
|
||||||
static FRAMEBUFFER: Mutex<FramebufferTarget> = Mutex::new(FramebufferTarget {
|
static FRAMEBUFFER: Mutex<Option<FramebufferTarget>> = Mutex::new(None);
|
||||||
framebuffer: null_mut(),
|
static FRAMEBUFFER_ADDR: AtomicPtr<u8> = AtomicPtr::new(null_mut());
|
||||||
width: 0,
|
static WIDTH: AtomicUsize = AtomicUsize::new(0);
|
||||||
height: 0,
|
static HEIGHT: AtomicUsize = AtomicUsize::new(0);
|
||||||
stride: 0,
|
static CURRENT_X: AtomicUsize = AtomicUsize::new(0);
|
||||||
});
|
static CURRENT_Y: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
fn write_char(x: usize, y: usize, c: char) {
|
||||||
|
let fb = &mut *FRAMEBUFFER.lock();
|
||||||
|
let str = c.to_string();
|
||||||
|
let pos = Point::new(x as i32 * 10 + 9, y as i32 * 20 + 19);
|
||||||
|
let style = MonoTextStyle::new(&FONT_10X20, Bgr888::WHITE);
|
||||||
|
let text = Text::new(&str, pos, style);
|
||||||
|
text.draw(fb.as_mut().unwrap()).unwrap();
|
||||||
|
}
|
||||||
|
fn scroll() {
|
||||||
|
let fb = &mut *FRAMEBUFFER.lock();
|
||||||
|
let fb = fb.as_mut().unwrap();
|
||||||
|
let height = HEIGHT.load(Ordering::SeqCst);
|
||||||
|
let line_size = fb.stride * 20 * 4;
|
||||||
|
fb.framebuffer.copy_within(line_size..line_size * height, 0);
|
||||||
|
fb.framebuffer[line_size * (height - 1)..].fill(0);
|
||||||
|
CURRENT_Y.store(CURRENT_Y.load(Ordering::SeqCst) - 1, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
fn copy_to_fb() {
|
||||||
|
let fb = &mut *FRAMEBUFFER.lock();
|
||||||
|
let fb = fb.as_mut().unwrap();
|
||||||
|
let addr = FRAMEBUFFER_ADDR.load(Ordering::SeqCst);
|
||||||
|
let size = fb.stride * fb.height * 4;
|
||||||
|
unsafe {
|
||||||
|
addr.copy_from_nonoverlapping(fb.framebuffer.as_ptr(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn display_print(str: &str) {
|
||||||
|
let mut current_x = CURRENT_X.load(Ordering::SeqCst);
|
||||||
|
let mut current_y = CURRENT_Y.load(Ordering::SeqCst);
|
||||||
|
let width = WIDTH.load(Ordering::SeqCst);
|
||||||
|
let height = HEIGHT.load(Ordering::SeqCst);
|
||||||
|
for c in str.chars() {
|
||||||
|
if c == '\n' {
|
||||||
|
current_x = 0;
|
||||||
|
current_y += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if current_x == width {
|
||||||
|
current_x = 0;
|
||||||
|
current_y += 1;
|
||||||
|
}
|
||||||
|
if current_y == height {
|
||||||
|
scroll();
|
||||||
|
current_y -= 1;
|
||||||
|
}
|
||||||
|
write_char(current_x, current_y, c);
|
||||||
|
current_x += 1;
|
||||||
|
}
|
||||||
|
CURRENT_X.store(current_x, Ordering::SeqCst);
|
||||||
|
CURRENT_Y.store(current_y, Ordering::SeqCst);
|
||||||
|
copy_to_fb();
|
||||||
|
}
|
||||||
pub fn setup_display(info: FramebufferInfo) {
|
pub fn setup_display(info: FramebufferInfo) {
|
||||||
let addr = unsafe { map_physical(info.address, info.height * info.stride * 4) };
|
let addr = unsafe { map_physical(info.address, info.height * info.stride * 4, true) };
|
||||||
*FRAMEBUFFER.lock() = FramebufferTarget {
|
FRAMEBUFFER_ADDR.store(addr as *mut u8, Ordering::SeqCst);
|
||||||
framebuffer: addr as *mut u8,
|
let fb = vec![0; info.height as usize * info.stride as usize * 4];
|
||||||
|
*FRAMEBUFFER.lock() = Some(FramebufferTarget {
|
||||||
|
framebuffer: fb,
|
||||||
width: info.width as usize,
|
width: info.width as usize,
|
||||||
height: info.height as usize,
|
height: info.height as usize,
|
||||||
stride: info.stride as usize,
|
stride: info.stride as usize,
|
||||||
};
|
});
|
||||||
|
WIDTH.store(info.width as usize / 10 - 1, Ordering::SeqCst);
|
||||||
|
HEIGHT.store(info.height as usize / 20 - 1, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ pub struct EarlyACPIHandler {}
|
||||||
impl AcpiHandler for EarlyACPIHandler {
|
impl AcpiHandler for EarlyACPIHandler {
|
||||||
unsafe fn map_physical_region<T>(&self, phys: usize, size: usize) -> PhysicalMapping<Self, T> {
|
unsafe fn map_physical_region<T>(&self, phys: usize, size: usize) -> PhysicalMapping<Self, T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let virt = map_physical(phys as u64, size as u64);
|
let virt = map_physical(phys as u64, size as u64, false);
|
||||||
return PhysicalMapping::new(phys, NonNull::new(virt as *mut T).unwrap(), size, size, *self);
|
return PhysicalMapping::new(phys, NonNull::new(virt as *mut T).unwrap(), size, size, *self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ pub fn sleep_internal(task: Task) {
|
||||||
}
|
}
|
||||||
pub fn setup_hpet(tables: &AcpiTables<EarlyACPIHandler>) {
|
pub fn setup_hpet(tables: &AcpiTables<EarlyACPIHandler>) {
|
||||||
let hpet_info = HpetInfo::new(tables).unwrap();
|
let hpet_info = HpetInfo::new(tables).unwrap();
|
||||||
let address = unsafe { map_physical(hpet_info.base_address as u64, 0x200) } as *mut u64;
|
let address = unsafe { map_physical(hpet_info.base_address as u64, 0x200, false) } as *mut u64;
|
||||||
ADDRESS.store(address, Ordering::SeqCst);
|
ADDRESS.store(address, Ordering::SeqCst);
|
||||||
let period = unsafe { address.add(REGISTER_CAPABILITIES).read_volatile() >> 32 } as usize;
|
let period = unsafe { address.add(REGISTER_CAPABILITIES).read_volatile() >> 32 } as usize;
|
||||||
PERIOD.store(period, Ordering::SeqCst);
|
PERIOD.store(period, Ordering::SeqCst);
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub fn register_irq_handler(vector: usize, handler: fn()) {
|
||||||
}
|
}
|
||||||
pub fn setup_ioapic(apic_i: u8, phys: u64, gsi_base: u32) {
|
pub fn setup_ioapic(apic_i: u8, phys: u64, gsi_base: u32) {
|
||||||
let apic_i = apic_i as usize;
|
let apic_i = apic_i as usize;
|
||||||
let address = unsafe { map_physical(phys, 0x14) as *mut u32 };
|
let address = unsafe { map_physical(phys, 0x14, false) as *mut u32 };
|
||||||
IOAPICS[apic_i].address.store(address, Ordering::SeqCst);
|
IOAPICS[apic_i].address.store(address, Ordering::SeqCst);
|
||||||
IOAPICS[apic_i].start_gsi.store(gsi_base, Ordering::SeqCst);
|
IOAPICS[apic_i].start_gsi.store(gsi_base, Ordering::SeqCst);
|
||||||
let max_ints = (read_register(apic_i, REGISTER_VERSION) >> 16) & 0xff;
|
let max_ints = (read_register(apic_i, REGISTER_VERSION) >> 16) & 0xff;
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub fn send_eoi() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn setup_lapic(phys: u64) {
|
pub fn setup_lapic(phys: u64) {
|
||||||
let address = unsafe { map_physical(phys, 0x400) as *mut u32 };
|
let address = unsafe { map_physical(phys, 0x400, false) as *mut u32 };
|
||||||
ADDRESS.store(address, Ordering::SeqCst);
|
ADDRESS.store(address, Ordering::SeqCst);
|
||||||
unsafe {
|
unsafe {
|
||||||
BSP_LAPIC_ID.store(address.add(REGISTER_ID).read_volatile() as u8, Ordering::SeqCst);
|
BSP_LAPIC_ID.store(address.add(REGISTER_ID).read_volatile() as u8, Ordering::SeqCst);
|
||||||
|
|
|
@ -3,7 +3,7 @@ use core::{
|
||||||
sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
|
sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::{boxed::Box, sync::Arc};
|
use alloc::{sync::Arc, vec, vec::Vec};
|
||||||
use kernel_common::instructions::hlt;
|
use kernel_common::instructions::hlt;
|
||||||
use spin::Mutex;
|
use spin::Mutex;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub enum TaskState {
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
state: ISRState,
|
state: ISRState,
|
||||||
_kernel_stack: Box<Stack>,
|
_kernel_stack: Vec<u8>,
|
||||||
initial_func: fn(),
|
initial_func: fn(),
|
||||||
pub task_state: TaskState,
|
pub task_state: TaskState,
|
||||||
pub sleep_until_us: usize,
|
pub sleep_until_us: usize,
|
||||||
|
@ -43,17 +43,14 @@ pub struct Task {
|
||||||
const STACK_SIZE: usize = 64 * 1024;
|
const STACK_SIZE: usize = 64 * 1024;
|
||||||
static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2);
|
static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2);
|
||||||
|
|
||||||
#[repr(align(16))]
|
|
||||||
#[repr(C)]
|
|
||||||
struct Stack([u8; STACK_SIZE]);
|
|
||||||
|
|
||||||
pub static CURRENT_TASK: Mutex<Option<Task>> = Mutex::new(None);
|
pub static CURRENT_TASK: Mutex<Option<Task>> = Mutex::new(None);
|
||||||
pub static CURRENT_TASK_LOCK: Spinlock = Spinlock::new();
|
pub static CURRENT_TASK_LOCK: Spinlock = Spinlock::new();
|
||||||
static RFLAGS: AtomicU64 = AtomicU64::new(0);
|
static RFLAGS: AtomicU64 = AtomicU64::new(0);
|
||||||
pub static MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false);
|
pub static MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
pub fn allocate_stack() -> u64 {
|
pub fn allocate_stack() -> u64 {
|
||||||
Box::leak(Box::new(Stack([0; STACK_SIZE]))) as *mut Stack as u64 + STACK_SIZE as u64
|
let stack: Vec<u8> = vec![0; STACK_SIZE];
|
||||||
|
stack.leak().as_mut_ptr() as u64 + STACK_SIZE as u64
|
||||||
}
|
}
|
||||||
pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
|
pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
|
||||||
assert!(CURRENT_TASK_LOCK.is_locked());
|
assert!(CURRENT_TASK_LOCK.is_locked());
|
||||||
|
@ -77,8 +74,7 @@ pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
|
||||||
schedule_timer_interrupt();
|
schedule_timer_interrupt();
|
||||||
}
|
}
|
||||||
pub fn create_task(func: fn()) -> Task {
|
pub fn create_task(func: fn()) -> Task {
|
||||||
let stack = Box::new(Stack([0; STACK_SIZE]));
|
let stack = vec![0; STACK_SIZE];
|
||||||
let stack_address: *const Stack = &*stack;
|
|
||||||
let task = Task {
|
let task = Task {
|
||||||
id: NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst),
|
id: NEXT_TASK_ID.fetch_add(1, Ordering::SeqCst),
|
||||||
state: ISRState {
|
state: ISRState {
|
||||||
|
@ -102,7 +98,7 @@ pub fn create_task(func: fn()) -> Task {
|
||||||
rip: task_entry as u64,
|
rip: task_entry as u64,
|
||||||
cs: 8,
|
cs: 8,
|
||||||
rflags: RFLAGS.load(Ordering::SeqCst),
|
rflags: RFLAGS.load(Ordering::SeqCst),
|
||||||
rsp: stack_address as u64 + STACK_SIZE as u64,
|
rsp: stack.as_ptr() as u64 + STACK_SIZE as u64,
|
||||||
ss: 16,
|
ss: 16,
|
||||||
},
|
},
|
||||||
_kernel_stack: stack,
|
_kernel_stack: stack,
|
||||||
|
|
Loading…
Add table
Reference in a new issue