fix: GPU display at correct resolution, clean up diagnostics

- Add GET_DISPLAY_INFO command to query QEMU's preferred resolution
  (was hardcoded 640x480, QEMU wanted 1280x800)
- Allocate framebuffer matching actual display dimensions
- Remove debug diagnostic output from display server and snake
This commit is contained in:
2026-10-19 00:24:37 +02:00
parent f5ac7189a9
commit 68849f698b
3 changed files with 60 additions and 20 deletions

View File

@@ -13,10 +13,8 @@ const VQUEUE_VA: usize = 0x21000;
const CMDBUF_VA: usize = 0x23000; const CMDBUF_VA: usize = 0x23000;
const PHYSINFO_VA: usize = 0x24000; const PHYSINFO_VA: usize = 0x24000;
const FB_VA: usize = 0x100000; const FB_VA: usize = 0x100000;
const FB_WIDTH: Dimension = Dimension::new(640); const DEFAULT_WIDTH: Dimension = Dimension::new(640);
const FB_HEIGHT: Dimension = Dimension::new(480); const DEFAULT_HEIGHT: Dimension = Dimension::new(480);
const FB_BPP: usize = 4;
const FB_PAGES: usize = (FB_WIDTH.raw() as usize * FB_HEIGHT.raw() as usize * FB_BPP + 4095) / 4096;
pub fn configure(uart: &Uart, display_pid: ProcessId) { pub fn configure(uart: &Uart, display_pid: ProcessId) {
let gpu = match VirtioGpu::probe() { let gpu = match VirtioGpu::probe() {
@@ -38,8 +36,36 @@ pub fn configure(uart: &Uart, display_pid: ProcessId) {
let cmd_phys = mmu::allocator::alloc_zeroed_page(); let cmd_phys = mmu::allocator::alloc_zeroed_page();
map_page(pt, CMDBUF_VA, cmd_phys); map_page(pt, CMDBUF_VA, cmd_phys);
let fb_phys = alloc_contiguous(FB_PAGES); gpu.init_device(vq_phys);
map_range(pt, FB_VA, fb_phys, FB_PAGES);
let queue = hw_virtio::queue::VirtioQueue::new(
hw_virtio::queue::QueueAddrs::from_base(vq_phys),
);
let dma = hw_virtio::gpu::GpuDmaAddrs {
cmd_pa: types::address::PhysicalAddress::from_raw(cmd_phys),
cmd_va: types::address::VirtualAddress::from_raw(cmd_phys),
resp_pa: types::address::PhysicalAddress::from_raw(cmd_phys + 512),
};
use hw_virtio::mmio::MmioAccess;
let (width, height) = match hw_virtio::gpu::get_display_info(gpu.mmio(), &queue, &dma) {
Some((w, h)) => {
uart.write_str("k-os: GPU display: ");
uart.write_dec(w as usize);
uart.put_char(b'x');
uart.write_dec(h as usize);
uart.put_char(b'\n');
(Dimension::new(w as u16), Dimension::new(h as u16))
}
None => {
uart.write_str("k-os: GPU display: using default 640x480\n");
(DEFAULT_WIDTH, DEFAULT_HEIGHT)
}
};
let fb_pages = (width.raw() as usize * height.raw() as usize * 4 + 4095) / 4096;
let fb_phys = alloc_contiguous(fb_pages);
map_range(pt, FB_VA, fb_phys, fb_pages);
let info_phys = mmu::allocator::alloc_zeroed_page(); let info_phys = mmu::allocator::alloc_zeroed_page();
map_page(pt, PHYSINFO_VA, info_phys); map_page(pt, PHYSINFO_VA, info_phys);
@@ -48,12 +74,11 @@ pub fn configure(uart: &Uart, display_pid: ProcessId) {
core::ptr::write_volatile(info, cmd_phys as u64); core::ptr::write_volatile(info, cmd_phys as u64);
core::ptr::write_volatile(info.add(1), (cmd_phys + 512) as u64); core::ptr::write_volatile(info.add(1), (cmd_phys + 512) as u64);
core::ptr::write_volatile(info.add(2), fb_phys as u64); core::ptr::write_volatile(info.add(2), fb_phys as u64);
core::ptr::write_volatile(info.add(3), FB_WIDTH.raw() as u64); core::ptr::write_volatile(info.add(3), width.raw() as u64);
core::ptr::write_volatile(info.add(4), FB_HEIGHT.raw() as u64); core::ptr::write_volatile(info.add(4), height.raw() as u64);
} }
gpu.init_device(vq_phys); if gpu.setup_framebuffer(cmd_phys, vq_phys, fb_phys, width, height) {
if gpu.setup_framebuffer(cmd_phys, vq_phys, fb_phys, FB_WIDTH, FB_HEIGHT) {
uart.write_str("k-os: VirtIO GPU configured\n"); uart.write_str("k-os: VirtIO GPU configured\n");
} else { } else {
uart.write_str("k-os: VirtIO GPU setup failed (display will be headless)\n"); uart.write_str("k-os: VirtIO GPU setup failed (display will be headless)\n");

View File

@@ -14,7 +14,7 @@ use display_server::protocol::DisplayRequest;
const INPUT_EP: CapSlot = CapSlot::const_new(0); const INPUT_EP: CapSlot = CapSlot::const_new(0);
const DISPLAY_EP: CapSlot = CapSlot::const_new(1); const DISPLAY_EP: CapSlot = CapSlot::const_new(1);
const TICK_DELAY: u64 = 2_000_000; const TICK_DELAY: u64 = 5_000_000;
const MAX_RENDER_CMDS: usize = 140; const MAX_RENDER_CMDS: usize = 140;
fn display_send(req: &DisplayRequest) { fn display_send(req: &DisplayRequest) {
@@ -50,20 +50,17 @@ extern "C" fn main() {
} }
flush(); flush();
wait_tick();
handle_input(&mut snake);
snake.tick();
if snake.state() == GameState::GameOver { if snake.state() == GameState::GameOver {
let gw = renderer::grid_pixel_width(); let gw = renderer::grid_pixel_width();
let gh = renderer::grid_pixel_height(); let gh = renderer::grid_pixel_height();
draw_rect(gw / 2 - 60, gh / 2 - 12, 120, 24, 0xFF800000); draw_rect(gw / 2 - 60, gh / 2 - 12, 120, 24, 0xFFCC0000);
flush(); flush();
loop { syscall::yield_now(); }
let end = Ticks::from_raw(syscall::get_time().raw() + 50_000_000);
while syscall::get_time().raw() < end.raw() { syscall::yield_now(); }
return;
} }
wait_tick();
handle_input(&mut snake);
snake.tick();
} }
} }

View File

@@ -83,6 +83,24 @@ fn write_cmd_header(cmd_va: VirtualAddress, cmd_type: u32) {
} }
} }
pub fn get_display_info(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs) -> Option<(u32, u32)> {
write_cmd_header(dma.cmd_va, 0x0100);
let descs = [
Descriptor { addr: dma.cmd_pa.raw() as u64, len: 24, writable: false },
Descriptor { addr: dma.resp_pa.raw() as u64, len: 408, writable: true },
];
if !queue.submit(mmio, &descs) { return None; }
unsafe {
let resp = dma.resp_pa.raw() as usize;
let resp_va = dma.cmd_va.raw() + 512;
let resp_type = core::ptr::read_volatile(resp_va as *const u32);
if resp_type != 0x1101 { return None; }
let w = core::ptr::read_volatile((resp_va + 24 + 8) as *const u32);
let h = core::ptr::read_volatile((resp_va + 24 + 12) as *const u32);
if w > 0 && h > 0 { Some((w, h)) } else { None }
}
}
fn submit_cmd(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, cmd_len: u32) -> bool { fn submit_cmd(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, cmd_len: u32) -> bool {
let descs = [ let descs = [
Descriptor { addr: dma.cmd_pa.raw() as u64, len: cmd_len, writable: false }, Descriptor { addr: dma.cmd_pa.raw() as u64, len: cmd_len, writable: false },