Asterinas 驱动框架
 总线初始化
 在整个OS初始化的时候:
 Rust
 pub fn init() {
 arch::before_all_init();
 logger::init();
 #[cfg(feature = “intel_tdx”)]
 let td_info = init_tdx().unwrap();
 #[cfg(feature = “intel_tdx”)]
 early_println!(
 “td gpaw: {}, td attributes: {:?}\nTDX guest is initialized”,
 td_info.gpaw,
 td_info.attributes
 );
 vm::heap_allocator::init();
 boot::init();
 vm::init();
 trap::init();
 arch::after_all_init();
 bus::init();
 invoke_ffi_init_funcs();
 }
 先做总线的初始化:
 Rust
 pub fn init() {
 pci::init();
 mmio::init();
 }
 PCI设备
 •PCI总线Bus编号从0到255,每条总线可以挂32个设备,每个设备有8个function。
 Rust
 /// Returns an iterator that enumerates all possible PCI device locations.
 pub fn all() -> impl Iterator<Item = PciDeviceLocation> {
 iter::from_coroutine(|| {
 for bus in Self::MIN_BUS…=Self::MAX_BUS {
 for device in Self::MIN_DEVICE…=Self::MAX_DEVICE {
 for function in Self::MIN_FUNCTION…=Self::MAX_FUNCTION {
 let loc = PciDeviceLocation {
 bus,
 device,
 function,
 };
 yield loc;
 }
 }
 }
 })
 }
 •枚举到PCI总线上的所有可能的设备后,确认设备是否存在:
 Rust
 pub(super) fn new(location: PciDeviceLocation) -> Option {
 if location.read16(0) == 0xFFFF {
 // not exists
 return None;
 }
    let capabilities = Vec::new();let device_id = PciDeviceId::new(location);let bar_manager = BarManager::new(location);let mut device = Self {device_id,location,bar_manager,capabilities,};device.capabilities = Capability::device_capabilities(&mut device);Some(device)
}pub(super) fn bar_manager_mut(&mut self) -> &mut BarManager {&mut self.bar_manager
}pub(super) fn capabilities_mut(&mut self) -> &mut Vec<Capability> {&mut self.capabilities
}
}
•如果设备存在,则在PCI BUS上注册这些设备:
 Rust
 pub(super) fn register_common_device(&mut self, mut common_device: PciCommonDevice) {
 debug!(“Find pci common devices:{:x?}”, common_device);
 let device_id = *common_device.device_id();
 for driver in self.drivers.iter() {
 common_device = match driver.probe(common_device) {
 Ok(device) => {
 debug_assert!(device_id == device.device_id());
 self.devices.push(device);
 return;
 }
 Err((err, common_device)) => {
 if err != BusProbeError::DeviceNotMatch {
 error!(“PCI device construction failed, reason: {:?}”, err);
 }
 debug_assert!(device_id == *common_device.device_id());
 common_device
 }
 };
 }
 self.common_devices.push_back(common_device);
 }
 注意,这个时候应该还没有相应的driver。
MMIO设备
 在MMIO整个地址空间去枚举设备:
 Rust
 iter_range(0xFEB0_0000…0xFEB0_4000);
 判断地址是否有效:
 Rust
 fn iter_range(range: Range) {
 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;
 // Safety: It only read the value and judge if the magic value fit 0x74726976
 let value = unsafe { *(paddr_to_vaddr(current) as *const u32) };
 if value == VIRTIO_MMIO_MAGIC {
 // Safety: It only read the device id
 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();
 // If has two IOApic, then start: 24 (0 in IOApic2), end 47 (23 in IOApic2)
 // If one IOApic, then start: 16, end 23
 io_apic.enable(24 - device_count, handle.clone()).unwrap();
 let device = MmioCommonDevice::new(current, handle);
 lock.register_mmio_device(device);
 }
 }
 }
 •如果有效,首先为设备分配中断号:
 Rust
 let handle = IrqLine::alloc().unwrap();
 •再向申请IOAPIC申请使能:
 Rust
 io_apic.enable(24 - device_count, handle.clone()).unwrap();
 在IOAPIC使能的时候,将设备与中断号做一个绑定关系:
 Rust
 pub fn enable(&mut self, index: u8, irq: IrqLine) -> Result<()> {
 if index >= self.max_redirection_entry() {
 return Err(Error::InvalidArgs);
 }
 let value = self.access.read(Self::TABLE_REG_BASE + 2 * index);
 if value.get_bits(0…8) as u8 != 0 {
 return Err(Error::AccessDenied);
 }
 self.access
 .write(Self::TABLE_REG_BASE + 2 * index, irq.num() as u32);
 self.access.write(Self::TABLE_REG_BASE + 2 * index + 1, 0);
 self.irqs.push(irq);
 Ok(())
 }
 设备在IOAPIC中的地址与中断号绑定起来。
•分配MmioCommonDevice:
 Rust
 let device = MmioCommonDevice::new(current, handle);
 •确定设备的IoMem:
 Rust
 let io_mem = unsafe { IoMem::new(paddr…paddr + 0x200) };
 let res: MmioCommonDevice = Self {
 io_mem,
 irq: handle,
 };
 •注册这些设备:
 Rust
 pub(super) fn register_mmio_device(&mut self, mut mmio_device: MmioCommonDevice) {
 let device_id = mmio_device.device_id();
 for driver in self.drivers.iter() {
 mmio_device = match driver.probe(mmio_device) {
 Ok(device) => {
 debug_assert!(device_id == device.device_id());
 self.devices.push(device);
 return;
 }
 Err((err, common_device)) => {
 if err != BusProbeError::DeviceNotMatch {
 error!(“MMIO device construction failed, reason: {:?}”, err);
 }
 debug_assert!(device_id == common_device.device_id());
 common_device
 }
 };
 }
 self.common_devices.push_back(mmio_device);
 }
 同理,这个时候应该还没有相应的driver。
驱动初始化
 在virtio的component的初始化中:
 Rust
 fn virtio_component_init() -> Result<(), ComponentInitError> {
 // Find all devices and register them to the corresponding crate
 transport::init();
 首先调用了 transport::init();
 Rust
 pub fn init() {
 virtio_pci_init();
 virtio_mmio_init();
 }
 然后分别注册了PCI driver 与MMIO driver:
 Rust
 pub fn virtio_pci_init() {
 VIRTIO_PCI_DRIVER.call_once(|| Arc::new(VirtioPciDriver::new()));
 PCI_BUS
 .lock()
 .register_driver(VIRTIO_PCI_DRIVER.get().unwrap().clone());
 }
Rust
 pub fn virtio_mmio_init() {
 VIRTIO_MMIO_DRIVER.call_once(|| Arc::new(VirtioMmioDriver::new()));
 MMIO_BUS
 .lock()
 .register_driver(VIRTIO_MMIO_DRIVER.get().unwrap().clone());
 }
为device 分配transport:
 Rust
 pub fn register_driver(&mut self, driver: Arc) {
 debug!(“Register driver:{:#x?}”, driver);
 let length = self.common_devices.len();
 for i in (0…length).rev() {
 let common_device = self.common_devices.pop_front().unwrap();
 let device_id = common_device.device_id();
 let device: MmioCommonDevice = match driver.probe(common_device) {
 Ok(device) => {
 debug_assert!(device_id == device.device_id());
 self.devices.push(device);
 continue;
 }
 Err((err, device)) => {
 if err != BusProbeError::DeviceNotMatch {
 error!(“MMIO device construction failed, reason: {:?}”, err);
 }
 debug_assert!(device_id == device.device_id());
 device
 }
 };
 self.common_devices.push_back(device);
 }
 self.drivers.push(driver);
 }
Rust
impl MmioDriver for VirtioMmioDriver {
 fn probe(
 &self,
 device: MmioCommonDevice,
 ) -> Result<Arc, (BusProbeError, MmioCommonDevice)> {
 let device = VirtioMmioTransport::new(device);
 let mmio_device = device.mmio_device().clone();
 self.devices.lock().push(device);
 Ok(mmio_device)
 }
 }
中断响应流程
 设置中断响应函数,在trapframe中,为255个中断号设置中断响应函数:
 Rust
 pub fn init() {
 extern “C” {
 #[link_name = “__vectors”]
 static VECTORS: [extern “C” fn(); 256];
 }
let idt = Box::leak(Box::new(InterruptDescriptorTable::new()));
// let idt = sidt().base;
let entries: &'static mut [Entry<HandlerFunc>; 256] =unsafe { core::mem::transmute_copy(&idt) };
for i in 0..256 {let opt = entries[i].set_handler_fn(unsafe { core::mem::transmute(VECTORS[i]) });// Enable user space `int3` and `into`if i == 3 || i == 4 {opt.set_privilege_level(PrivilegeLevel::Ring3);}
}
idt.load();
}
 其中VECTORS函数数组被定义在:
 Rust
 .global __vectors
 __vectors:
 .quad vector0
 .quad vector1
 .quad vector2
 .quad vector3
 .quad vector4
 .quad vector5
 .quad vector6
 .quad vector7
 .quad vector8
 .quad vector9
 .quad vector10
 .quad vector11
 .quad vector12
 .quad vector13
 .quad vector14
 .quad vector15
 .quad vector16
 .quad vector17
 .quad vector18
 .quad vector19
数组每个成员函数:
 Rust
 .section .text
 vector0:
 push 0
 push 0
 jmp __alltraps
 vector1:
 push 0
 push 1
 jmp __alltraps
 vector2:
 push 0
 push 2
 jmp __alltraps
 vector3:
 push 0
 push 3
 jmp __alltraps
 vector4:
 push 0
 push 4
 jmp __alltraps
 vector5:
 push 0
 push 5
 jmp __alltraps
 vector6:
 push 0
 push 6
 jmp __alltraps
 vector7:
 push 0
 push 7
 jmp __alltraps
 vector8:
 push 8
 jmp __alltraps
将中断响应函数组装载进IDT寄存器:
 Rust
 pub unsafe fn lidt(idt: &DescriptorTablePointer) {
 unsafe {
 asm!(“lidt [{}]”, in(reg) idt, options(readonly, nostack, preserves_flags));
 }
 }
 因此每个中断号上有中断信号时候都会跳进__alltraps函数:
 Rust
 text
 .global __alltraps
 __alltraps:
 push rax
/*
kernel stack:
- ptr to GeneralRegs
- ss
- rsp
- rflags
- cs
- rip
- error code
- trap num
- rax
*/
mov ax, [rsp + 4*8]     # load cs
and ax, 0x3             # test
jz __from_kernel        # continue trap
Rust
 __from_kernel:
 pop rax
 push 0
 push r15
 push r14
 push r13
 push r12
 push r11
 push r10
 push r9
 push r8
 lea r8, [rsp + 13*8]
 push r8 # push rsp
 push rbp
 push rdi
 push rsi
 push rdx
 push rcx
 push rbx
 push rax
mov rdi, rsp
call trap_handler
trap_handler函数在aster-frame中被实现:
 Rust
 extern “sysv64” fn trap_handler(f: &mut TrapFrame) {
 if CpuException::is_cpu_exception(f.trap_num as u16) {
 #[cfg(feature = “intel_tdx”)]
 if f.trap_num as u16 == 20 {
 let ve_info = tdcall::get_veinfo().expect(“#VE handler: fail to get VE info\n”);
 handle_virtual_exception(f, &ve_info);
 return;
 }
 panic!(“cannot handle kernel cpu fault now, information:{:#x?}”, f);
 } else {
 call_irq_callback_functions(f);
 }
 }
 调用注册进中断的的回调响应函数中处理,根据中断号找到对应的中断,再查到对应的中断回调函数。
 Rust
 pub(crate) fn call_irq_callback_functions(trap_frame: &TrapFrame) {
 let irq_line = IRQ_LIST.get().unwrap().get(trap_frame.trap_num).unwrap();
 let callback_functions = irq_line.callback_list();
 for callback_function in callback_functions.iter() {
 callback_function.call(trap_frame);
 }
 if !CpuException::is_cpu_exception(trap_frame.trap_num as u16) {
 crate::arch::interrupts_ack();
 }
 }