refactor: unsafe only in adapter + libkos; forbid(unsafe_code) everywhere else; libkos Window (volatile, bounds-checked MMIO/DMA/shared mem), entry!, thread::spawn; MapRegion returns pages; kernel const-built (with_cores/install_platform); newtype addrs
This commit is contained in:
@@ -1,103 +1,83 @@
|
||||
use crate::mmio::MmioAccess;
|
||||
use crate::queue::{Descriptor, VirtioQueue};
|
||||
use types::address::{PhysicalAddress, VirtualAddress};
|
||||
use libkos::Window;
|
||||
use types::address::PhysicalAddress;
|
||||
use types::display::Dimension;
|
||||
|
||||
/// The command page: commands go out from its start, responses come back
|
||||
/// at `RESPONSE`.
|
||||
pub struct GpuDmaAddrs {
|
||||
pub cmd_pa: PhysicalAddress,
|
||||
pub cmd_va: VirtualAddress,
|
||||
pub cmd: Window,
|
||||
pub resp_pa: PhysicalAddress,
|
||||
}
|
||||
|
||||
pub const RESPONSE: usize = 512;
|
||||
|
||||
pub fn create_2d(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, width: Dimension, height: Dimension) -> bool {
|
||||
write_cmd_header(dma.cmd_va, 0x0101);
|
||||
unsafe {
|
||||
let p = dma.cmd_va.raw() as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, resource_id);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, 1);
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, width.raw() as u32);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, height.raw() as u32);
|
||||
}
|
||||
write_cmd_header(&dma.cmd, 0x0101);
|
||||
dma.cmd.write(24, resource_id);
|
||||
dma.cmd.write(28, 1u32);
|
||||
dma.cmd.write(32, width.raw() as u32);
|
||||
dma.cmd.write(36, height.raw() as u32);
|
||||
submit_cmd(mmio, queue, dma, 40)
|
||||
}
|
||||
|
||||
pub fn attach_backing(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, fb_pa: PhysicalAddress, fb_size: u32) -> bool {
|
||||
write_cmd_header(dma.cmd_va, 0x0106);
|
||||
unsafe {
|
||||
let p = dma.cmd_va.raw() as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, resource_id);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, 1);
|
||||
core::ptr::write_volatile(p.add(32) as *mut u64, fb_pa.raw() as u64);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u32, fb_size);
|
||||
}
|
||||
write_cmd_header(&dma.cmd, 0x0106);
|
||||
dma.cmd.write(24, resource_id);
|
||||
dma.cmd.write(28, 1u32);
|
||||
dma.cmd.write(32, fb_pa.raw() as u64 as u64);
|
||||
dma.cmd.write(40, fb_size);
|
||||
submit_cmd(mmio, queue, dma, 48)
|
||||
}
|
||||
|
||||
pub fn set_scanout(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, scanout_id: u32, resource_id: u32, width: Dimension, height: Dimension) -> bool {
|
||||
write_cmd_header(dma.cmd_va, 0x0103);
|
||||
unsafe {
|
||||
let p = dma.cmd_va.raw() as *mut u8;
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, width.raw() as u32);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, height.raw() as u32);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u32, scanout_id);
|
||||
core::ptr::write_volatile(p.add(44) as *mut u32, resource_id);
|
||||
}
|
||||
write_cmd_header(&dma.cmd, 0x0103);
|
||||
dma.cmd.write(32, width.raw() as u32);
|
||||
dma.cmd.write(36, height.raw() as u32);
|
||||
dma.cmd.write(40, scanout_id);
|
||||
dma.cmd.write(44, resource_id);
|
||||
submit_cmd(mmio, queue, dma, 48)
|
||||
}
|
||||
|
||||
pub fn transfer_to_host(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, x: u32, y: u32, w: u32, h: u32) -> bool {
|
||||
write_cmd_header(dma.cmd_va, 0x0105);
|
||||
unsafe {
|
||||
let p = dma.cmd_va.raw() as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, x);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, y);
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, w);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, h);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u64, 0);
|
||||
core::ptr::write_volatile(p.add(48) as *mut u32, resource_id);
|
||||
}
|
||||
write_cmd_header(&dma.cmd, 0x0105);
|
||||
dma.cmd.write(24, x);
|
||||
dma.cmd.write(28, y);
|
||||
dma.cmd.write(32, w);
|
||||
dma.cmd.write(36, h);
|
||||
dma.cmd.write(40, 0u64);
|
||||
dma.cmd.write(48, resource_id);
|
||||
submit_cmd(mmio, queue, dma, 56)
|
||||
}
|
||||
|
||||
pub fn resource_flush(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, resource_id: u32, x: u32, y: u32, w: u32, h: u32) -> bool {
|
||||
write_cmd_header(dma.cmd_va, 0x0104);
|
||||
unsafe {
|
||||
let p = dma.cmd_va.raw() as *mut u8;
|
||||
core::ptr::write_volatile(p.add(24) as *mut u32, x);
|
||||
core::ptr::write_volatile(p.add(28) as *mut u32, y);
|
||||
core::ptr::write_volatile(p.add(32) as *mut u32, w);
|
||||
core::ptr::write_volatile(p.add(36) as *mut u32, h);
|
||||
core::ptr::write_volatile(p.add(40) as *mut u32, resource_id);
|
||||
}
|
||||
write_cmd_header(&dma.cmd, 0x0104);
|
||||
dma.cmd.write(24, x);
|
||||
dma.cmd.write(28, y);
|
||||
dma.cmd.write(32, w);
|
||||
dma.cmd.write(36, h);
|
||||
dma.cmd.write(40, resource_id);
|
||||
submit_cmd(mmio, queue, dma, 48)
|
||||
}
|
||||
|
||||
fn write_cmd_header(cmd_va: VirtualAddress, cmd_type: u32) {
|
||||
unsafe {
|
||||
let p = cmd_va.raw() as *mut u8;
|
||||
// Volatile so the device sees the zeros.
|
||||
for i in 0..128 {
|
||||
core::ptr::write_volatile((p as *mut u32).add(i), 0);
|
||||
}
|
||||
core::ptr::write_volatile(p as *mut u32, cmd_type);
|
||||
}
|
||||
fn write_cmd_header(cmd: &Window, cmd_type: u32) {
|
||||
cmd.fill_u32(0, 128, 0);
|
||||
cmd.write(0, cmd_type);
|
||||
}
|
||||
|
||||
pub fn get_display_info(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs) -> Option<(u32, u32)> {
|
||||
write_cmd_header(dma.cmd_va, 0x0100);
|
||||
write_cmd_header(&dma.cmd, 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_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 }
|
||||
}
|
||||
if dma.cmd.read::<u32>(RESPONSE) != 0x1101 { return None; }
|
||||
let w: u32 = dma.cmd.read(RESPONSE + 24 + 8);
|
||||
let h: u32 = dma.cmd.read(RESPONSE + 24 + 12);
|
||||
if w > 0 && h > 0 { Some((w, h)) } else { None }
|
||||
}
|
||||
|
||||
fn submit_cmd(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, cmd_len: u32) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user