#![allow(dead_code)]
pub mod bus;
pub mod common_device;
use alloc::vec::Vec;
use core::ops::Range;
#[cfg(feature = "intel_tdx")]
use ::tdx_guest::tdx_is_enabled;
use log::debug;
use self::bus::MmioBus;
#[cfg(feature = "intel_tdx")]
use crate::arch::tdx_guest;
use crate::{
arch::kernel::IO_APIC, bus::mmio::common_device::MmioCommonDevice, mm::paddr_to_vaddr,
sync::SpinLock, trap::IrqLine,
};
const VIRTIO_MMIO_MAGIC: u32 = 0x74726976;
pub static MMIO_BUS: SpinLock<MmioBus> = SpinLock::new(MmioBus::new());
static IRQS: SpinLock<Vec<IrqLine>> = SpinLock::new(Vec::new());
pub(crate) fn init() {
#[cfg(feature = "intel_tdx")]
if tdx_is_enabled() {
unsafe {
tdx_guest::unprotect_gpa_range(0xFEB0_0000, 4).unwrap();
}
}
iter_range(0xFEB0_0000..0xFEB0_4000);
}
fn iter_range(range: Range<usize>) {
debug!("[Virtio]: Iter MMIO range:{:x?}", range);
let mut current = range.end;
let mut lock = MMIO_BUS.lock();
let io_apics = IO_APIC.get().unwrap();
let is_ioapic2 = io_apics.len() == 2;
let mut io_apic = if is_ioapic2 {
io_apics.get(1).unwrap().lock()
} else {
io_apics.first().unwrap().lock()
};
let mut device_count = 0;
while current > range.start {
current -= 0x100;
let value = unsafe { *(paddr_to_vaddr(current) as *const u32) };
if value == VIRTIO_MMIO_MAGIC {
let device_id = unsafe { *(paddr_to_vaddr(current + 8) as *const u32) };
device_count += 1;
if device_id == 0 {
continue;
}
let handle = IrqLine::alloc().unwrap();
io_apic.enable(24 - device_count, handle.clone()).unwrap();
let device = MmioCommonDevice::new(current, handle);
lock.register_mmio_device(device);
}
}
}