From 2b5aa1f375567448f1d8da3803e5b97f2dd85595 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 1 Mar 2022 15:50:26 -0700 Subject: [PATCH] Cleanup of graphical debug to allow it to run much earlier --- src/arch/x86_64/graphical_debug/debug.rs | 26 +--- src/arch/x86_64/graphical_debug/display.rs | 124 +++---------------- src/arch/x86_64/graphical_debug/mod.rs | 47 +------ src/arch/x86_64/graphical_debug/primitive.rs | 39 ------ src/arch/x86_64/rmm.rs | 30 +++++ src/arch/x86_64/start.rs | 16 +-- 6 files changed, 63 insertions(+), 219 deletions(-) delete mode 100644 src/arch/x86_64/graphical_debug/primitive.rs diff --git a/src/arch/x86_64/graphical_debug/debug.rs b/src/arch/x86_64/graphical_debug/debug.rs index 98326a6..052f1bb 100644 --- a/src/arch/x86_64/graphical_debug/debug.rs +++ b/src/arch/x86_64/graphical_debug/debug.rs @@ -21,6 +21,10 @@ impl DebugDisplay { } } + pub fn as_display(&self) -> &Display { + &self.display + } + pub fn into_display(self) -> Display { self.display } @@ -37,38 +41,16 @@ impl DebugDisplay { self.display.scroll(d_y * 16); - self.display.rect( - 0, (self.h - d_y) * 16, - self.w * 8, d_y * 16, - 0x000000 - ); - - self.display.sync( - 0, 0, - self.w * 8, self.h * 16 - ); - self.y = new_y; } if c != '\n' { - self.display.rect( - self.x * 8, self.y * 16, - 8, 16, - 0x000000 - ); - self.display.char( self.x * 8, self.y * 16, c, 0xFFFFFF ); - self.display.sync( - self.x * 8, self.y * 16, - 8, 16 - ); - self.x += 1; } } diff --git a/src/arch/x86_64/graphical_debug/display.rs b/src/arch/x86_64/graphical_debug/display.rs index 4f5ecbf..4f3ff0b 100644 --- a/src/arch/x86_64/graphical_debug/display.rs +++ b/src/arch/x86_64/graphical_debug/display.rs @@ -1,91 +1,32 @@ -use core::alloc::{GlobalAlloc, Layout}; -use core::{cmp, slice}; +use core::{cmp, ptr, slice}; use super::FONT; -use super::primitive::{fast_set32, fast_set64, fast_copy}; /// A display pub struct Display { pub width: usize, pub height: usize, - pub onscreen: &'static mut [u32], - pub offscreen: &'static mut [u32], + pub data: &'static mut [u32], } impl Display { - pub fn new(width: usize, height: usize, onscreen: usize) -> Display { + pub fn new(width: usize, height: usize, data_ptr: *mut u32) -> Display { let size = width * height; - let offscreen = unsafe { crate::ALLOCATOR.alloc(Layout::from_size_align_unchecked(size * 4, 4096)) }; - unsafe { fast_set64(offscreen as *mut u64, 0, size/2) }; + let data = unsafe { + ptr::write_bytes(data_ptr, 0, size); + slice::from_raw_parts_mut(data_ptr, size) + }; Display { - width: width, - height: height, - onscreen: unsafe { slice::from_raw_parts_mut(onscreen as *mut u32, size) }, - offscreen: unsafe { slice::from_raw_parts_mut(offscreen as *mut u32, size) } - } - } - - /// Draw a rectangle - pub fn rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: u32) { - let start_y = cmp::min(self.height, y); - let end_y = cmp::min(self.height, y + h); - - let start_x = cmp::min(self.width, x); - let len = cmp::min(self.width, x + w) - start_x; - - let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; - - let stride = self.width * 4; - - let offset = y * stride + start_x * 4; - offscreen_ptr += offset; - - let mut rows = end_y - start_y; - while rows > 0 { - unsafe { - fast_set32(offscreen_ptr as *mut u32, color, len); - } - offscreen_ptr += stride; - rows -= 1; - } - } - - /// Invert a rectangle - pub fn invert(&mut self, x: usize, y: usize, w: usize, h: usize) { - let start_y = cmp::min(self.height, y); - let end_y = cmp::min(self.height, y + h); - - let start_x = cmp::min(self.width, x); - let len = cmp::min(self.width, x + w) - start_x; - - let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; - - let stride = self.width * 4; - - let offset = y * stride + start_x * 4; - offscreen_ptr += offset; - - let mut rows = end_y - start_y; - while rows > 0 { - let mut row_ptr = offscreen_ptr; - let mut cols = len; - while cols > 0 { - unsafe { - let color = *(row_ptr as *mut u32); - *(row_ptr as *mut u32) = !color; - } - row_ptr += 4; - cols -= 1; - } - offscreen_ptr += stride; - rows -= 1; + width, + height, + data } } /// Draw a character pub fn char(&mut self, x: usize, y: usize, character: char, color: u32) { if x + 8 <= self.width && y + 16 <= self.height { - let mut dst = self.offscreen.as_mut_ptr() as usize + (y * self.width + x) * 4; + let mut dst = self.data.as_mut_ptr() as usize + (y * self.width + x) * 4; let font_i = 16 * (character as usize); if font_i + 16 <= FONT.len() { @@ -105,45 +46,12 @@ impl Display { // Scroll the screen pub fn scroll(&mut self, lines: usize) { let offset = cmp::min(self.height, lines) * self.width; - let size = self.offscreen.len() - offset; + let size = self.data.len() - offset; unsafe { - let to = self.offscreen.as_mut_ptr(); - let from = to.add(offset); - fast_copy(to as *mut u8, from as *const u8, size * 4); - } - } - - /// Copy from offscreen to onscreen - pub fn sync(&mut self, x: usize, y: usize, w: usize, h: usize) { - let start_y = cmp::min(self.height, y); - let end_y = cmp::min(self.height, y + h); - - let start_x = cmp::min(self.width, x); - let len = (cmp::min(self.width, x + w) - start_x) * 4; - - let mut offscreen_ptr = self.offscreen.as_mut_ptr() as usize; - let mut onscreen_ptr = self.onscreen.as_mut_ptr() as usize; - - let stride = self.width * 4; - - let offset = y * stride + start_x * 4; - offscreen_ptr += offset; - onscreen_ptr += offset; - - let mut rows = end_y - start_y; - while rows > 0 { - unsafe { - fast_copy(onscreen_ptr as *mut u8, offscreen_ptr as *const u8, len); - } - offscreen_ptr += stride; - onscreen_ptr += stride; - rows -= 1; + let src = self.data.as_ptr(); + let dst = self.data.as_mut_ptr().add(offset); + ptr::copy(src, dst, size); + ptr::write_bytes(dst, 0, offset); } } } - -impl Drop for Display { - fn drop(&mut self) { - unsafe { crate::ALLOCATOR.dealloc(self.offscreen.as_mut_ptr() as *mut u8, Layout::from_size_align_unchecked(self.offscreen.len() * 4, 4096)) }; - } -} diff --git a/src/arch/x86_64/graphical_debug/mod.rs b/src/arch/x86_64/graphical_debug/mod.rs index ee3d86a..5c411f0 100644 --- a/src/arch/x86_64/graphical_debug/mod.rs +++ b/src/arch/x86_64/graphical_debug/mod.rs @@ -1,24 +1,17 @@ use core::str; use spin::Mutex; -use crate::memory::Frame; -use crate::paging::{ActivePageTable, Page, PageFlags, PhysicalAddress, VirtualAddress}; -use crate::paging::entry::EntryFlags; -use crate::paging::mapper::PageFlushAll; - pub use self::debug::DebugDisplay; use self::display::Display; -use self::primitive::fast_set64; pub mod debug; pub mod display; -pub mod primitive; pub static FONT: &'static [u8] = include_bytes!("../../../../res/unifont.font"); pub static DEBUG_DISPLAY: Mutex> = Mutex::new(None); -pub fn init(active_table: &mut ActivePageTable, env: &[u8]) { +pub fn init(env: &[u8]) { println!("Starting graphical debug"); let mut width = 0; @@ -54,46 +47,16 @@ pub fn init(active_table: &mut ActivePageTable, env: &[u8]) { { let size = width * height * 4; - let onscreen = physbaseptr + crate::PHYS_OFFSET; - { - let flush_all = PageFlushAll::new(); - let start_page = Page::containing_address(VirtualAddress::new(onscreen)); - let end_page = Page::containing_address(VirtualAddress::new(onscreen + size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().data() - crate::PHYS_OFFSET)); - let flags = PageFlags::new().write(true).custom_flag(EntryFlags::HUGE_PAGE.bits(), true); - let result = active_table.map_to(page, frame, flags); - flush_all.consume(result); - } - flush_all.flush(); - } + let virtbaseptr = physbaseptr + crate::PHYS_OFFSET; - unsafe { fast_set64(onscreen as *mut u64, 0, size/8) }; - - let display = Display::new(width, height, onscreen); + let display = Display::new(width, height, virtbaseptr as *mut u32); let debug_display = DebugDisplay::new(display); *DEBUG_DISPLAY.lock() = Some(debug_display); } } -pub fn fini(active_table: &mut ActivePageTable) { - let debug_display_opt = DEBUG_DISPLAY.lock().take(); - if let Some(debug_display) = debug_display_opt { - let display = debug_display.into_display(); - let onscreen = display.onscreen.as_mut_ptr() as usize; - let size = display.onscreen.len() * 4; - //TODO: fix crash if we unmap this memory - if false { - let flush_all = PageFlushAll::new(); - let start_page = Page::containing_address(VirtualAddress::new(onscreen)); - let end_page = Page::containing_address(VirtualAddress::new(onscreen + size - 1)); - for page in Page::range_inclusive(start_page, end_page) { - let (result, _frame) = active_table.unmap_return(page, false); - flush_all.consume(result); - } - flush_all.flush(); - } - } +pub fn fini() { + DEBUG_DISPLAY.lock().take(); println!("Finished graphical debug"); } diff --git a/src/arch/x86_64/graphical_debug/primitive.rs b/src/arch/x86_64/graphical_debug/primitive.rs deleted file mode 100644 index cc69a05..0000000 --- a/src/arch/x86_64/graphical_debug/primitive.rs +++ /dev/null @@ -1,39 +0,0 @@ -#[cfg(target_arch = "x86_64")] -#[inline(always)] -#[cold] -pub unsafe fn fast_copy(dst: *mut u8, src: *const u8, len: usize) { - asm!("cld; rep movsb", - in("rdi") dst as usize, - in("rsi") src as usize, - in("rcx") len, - lateout("rdi") _, - lateout("rsi") _, - lateout("rcx") _, - ); -} - -#[cfg(target_arch = "x86_64")] -#[inline(always)] -#[cold] -pub unsafe fn fast_set32(dst: *mut u32, src: u32, len: usize) { - asm!("cld; rep stosd", - in("rdi") dst as usize, - in("eax") src, - in("rcx") len, - lateout("rdi") _, - lateout("rcx") _, - ); -} - -#[cfg(target_arch = "x86_64")] -#[inline(always)] -#[cold] -pub unsafe fn fast_set64(dst: *mut u64, src: u64, len: usize) { - asm!("cld; rep stosq", - in("rdi") dst as usize, - in("rax") src, - in("rcx") len, - lateout("rdi") _, - lateout("rcx") _, - ); -} diff --git a/src/arch/x86_64/rmm.rs b/src/arch/x86_64/rmm.rs index 328a922..f09af95 100644 --- a/src/arch/x86_64/rmm.rs +++ b/src/arch/x86_64/rmm.rs @@ -176,6 +176,36 @@ unsafe fn inner( flush.ignore(); // Not the active table } + // Ensure graphical debug region remains paged + #[cfg(feature = "graphical_debug")] + { + use super::graphical_debug::DEBUG_DISPLAY; + use super::paging::entry::EntryFlags; + + let (base, size) = if let Some(debug_display) = &*DEBUG_DISPLAY.lock() { + let data = &debug_display.as_display().data; + ( + data.as_ptr() as usize - crate::PHYS_OFFSET, + data.len() * 4 + ) + } else { + (0, 0) + }; + + let pages = (size + A::PAGE_SIZE - 1) / A::PAGE_SIZE; + for i in 0..pages { + let phys = PhysicalAddress::new(base + i * A::PAGE_SIZE); + let virt = A::phys_to_virt(phys); + let flags = PageFlags::new().write(true); + let flush = mapper.map_phys( + virt, + phys, + flags + ).expect("failed to map frame"); + flush.ignore(); // Not the active table + } + } + println!("Table: {:X}", mapper.table().phys().data()); for i in 0..512 { if let Some(entry) = mapper.table().entry(i) { diff --git a/src/arch/x86_64/start.rs b/src/arch/x86_64/start.rs index 508ad80..41e8fb8 100644 --- a/src/arch/x86_64/start.rs +++ b/src/arch/x86_64/start.rs @@ -87,6 +87,13 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { KERNEL_BASE.store(kernel_base, Ordering::SeqCst); KERNEL_SIZE.store(kernel_size, Ordering::SeqCst); + // Convert env to slice + let env = slice::from_raw_parts((env_base + crate::PHYS_OFFSET) as *const u8, env_size); + + // Set up graphical debug + #[cfg(feature="graphical_debug")] + graphical_debug::init(env); + // Initialize logger log::init_logger(|r| { use core::fmt::Write; @@ -156,13 +163,6 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { // Activate memory logging log::init(); - // Convert env to slice - let env = slice::from_raw_parts((env_base + crate::PHYS_OFFSET) as *const u8, env_size); - - // Use graphical debug - #[cfg(feature="graphical_debug")] - graphical_debug::init(&mut active_table, env); - #[cfg(feature = "system76_ec_debug")] device::system76_ec::init(); @@ -185,7 +185,7 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! { // Stop graphical debug #[cfg(feature="graphical_debug")] - graphical_debug::fini(&mut active_table); + graphical_debug::fini(); BSP_READY.store(true, Ordering::SeqCst);