Cleanup of graphical debug to allow it to run much earlier
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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") _,
|
||||
);
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user