Cleanup of graphical debug to allow it to run much earlier

This commit is contained in:
Jeremy Soller
2022-03-01 15:50:26 -07:00
parent ae0d48d9ab
commit 2b5aa1f375
6 changed files with 63 additions and 219 deletions

View File

@@ -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;
}
}

View File

@@ -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)) };
}
}

View File

@@ -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<Option<DebugDisplay>> = 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");
}

View File

@@ -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") _,
);
}

View File

@@ -176,6 +176,36 @@ unsafe fn inner<A: Arch>(
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) {

View File

@@ -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);