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:
2026-10-27 21:43:24 +01:00
parent 83809bbe94
commit 842d14987c
107 changed files with 771 additions and 647 deletions

View File

@@ -1,29 +1,20 @@
#![no_std]
#![forbid(unsafe_code)]
use hw_virtio::mmio::MmioAccess;
use hw_virtio::queue::{QueueAddrs, VirtioQueue};
use hw_virtio::block::{self, DmaAddrs};
use hw_virtio::mmio::{MmioAccess, Registers};
use hw_virtio::queue::VirtioQueue;
use port_block_device::{BlockDevice, SectorId};
use types::address::{PhysicalAddress, VirtualAddress};
use types::bounded::PageCount;
const MMIO_BASE: usize = 0x20000;
const VQUEUE_VA: usize = 0x21000;
const REQ_HDR_VA: usize = 0x23000;
const MMIO_VA: VirtualAddress = VirtualAddress::from_raw(0x20000);
const VQUEUE_VA: VirtualAddress = VirtualAddress::from_raw(0x21000);
const REQ_HDR_VA: VirtualAddress = VirtualAddress::from_raw(0x23000);
const SECTOR_SIZE: usize = 512;
struct UserMmio;
impl MmioAccess for UserMmio {
fn read(&self, offset: usize) -> u32 {
unsafe { core::ptr::read_volatile((MMIO_BASE + offset) as *const u32) }
}
fn write(&self, offset: usize, val: u32) {
unsafe { core::ptr::write_volatile((MMIO_BASE + offset) as *mut u32, val) }
}
}
pub struct VirtioBlockDevice {
mmio: UserMmio,
mmio: Registers,
queue: VirtioQueue,
dma: DmaAddrs,
sectors: usize,
@@ -33,31 +24,31 @@ impl VirtioBlockDevice {
/// Takes over the virtio block device behind `mmio`. `None` if it is
/// not one or any step fails.
pub fn new(mmio: types::bounded::CapSlot) -> Option<Self> {
libkos::device::map_mmio(mmio, MMIO_BASE).ok()?;
let regs = UserMmio;
let regs = Registers::new(libkos::device::map_mmio(mmio, MMIO_VA).ok()?);
if regs.read(hw_virtio::mmio::REG_MAGIC) != hw_virtio::mmio::MAGIC
|| regs.read(hw_virtio::mmio::REG_DEVICE_ID) != hw_virtio::mmio::DEVICE_ID_BLOCK
{
return None;
}
let vq_pa = libkos::device::dma(2, VQUEUE_VA).ok()?;
let hdr_pa = libkos::device::dma(1, REQ_HDR_VA).ok()?;
hw_virtio::mmio::init_legacy_device(&regs, vq_pa, hw_virtio::queue::QUEUE_SIZE as u32);
let rings = libkos::device::dma(PageCount::new(2)?, VQUEUE_VA).ok()?;
let req = libkos::device::dma(PageCount::new(1)?, REQ_HDR_VA).ok()?;
hw_virtio::mmio::init_legacy_device(&regs, rings.physical, hw_virtio::queue::QUEUE_SIZE as u32);
// Header, status byte and one sector share the request page.
let at = |offset: usize| PhysicalAddress::from_raw(req.physical.raw() + offset);
let dma = DmaAddrs {
header_pa: PhysicalAddress::from_raw(hdr_pa),
header_va: VirtualAddress::from_raw(REQ_HDR_VA),
status_pa: PhysicalAddress::from_raw(hdr_pa + 16),
status_va: VirtualAddress::from_raw(REQ_HDR_VA + 16),
data_pa: PhysicalAddress::from_raw(hdr_pa + 32),
data_va: VirtualAddress::from_raw(REQ_HDR_VA + 32),
header_pa: at(0),
header: req.window.sub(0, 16),
status_pa: at(16),
status: req.window.sub(16, 1),
data_pa: at(32),
data: req.window.sub(32, SECTOR_SIZE),
};
let capacity = regs.read(block::CONFIG_CAPACITY) as u64
| (regs.read(block::CONFIG_CAPACITY + 4) as u64) << 32;
Some(Self {
mmio: UserMmio,
queue: VirtioQueue::new(QueueAddrs::from_base(VQUEUE_VA)),
mmio: regs,
queue: VirtioQueue::new(rings.window),
dma,
sectors: usize::try_from(capacity).ok()?,
})