Asterinas 驱动框架

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();
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/865258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

有sdwan可以不用专线吗?sdwan和专线的区别优势

SD-WAN&#xff08;Software-Defined Wide Area Network&#xff0c;软件定义广域网&#xff09;确实可以在很大程度上替代传统的专线连接&#xff0c;尤其是在追求成本效益和网络灵活性的场景下。SD-WAN的核心优势在于其智能化和自动化的能力&#xff0c;这使得它能够优化数据…

华清远见人工智能课程:项目优势助力,学习更高效!

在人工智能飞速发展的今天&#xff0c;学习人工智能成为新的高薪赛道。我们都知道人工智能的学习离不开项目练手&#xff0c;只有通过实际项目的操作&#xff0c;才能真正掌握人工智能的核心技能。但遗憾的是&#xff0c;很多人工智能课程只注重理论知识的传授&#xff0c;缺乏…

本地文件上传Github的方法

本文仅用于个人回忆本地文件上传GitHub方法&#xff0c;使用HTTP上传而不是SSH&#xff0c;其余文件已配置完成&#xff0c;如果你和我一样&#xff0c;那么请往下看&#xff0c;这条博客不说废话。 Step1 选择需要上传的文件&#xff0c;右键选择Git Bash Here Step2 创建一…

GAMES104:04游戏引擎中的渲染系统1:游戏渲染基础-学习笔记

文章目录 概览&#xff1a;游戏引擎中的渲染系统四个课时概览 一&#xff0c;渲染管线流程二&#xff0c;了解GPUSIMD 和 SIMTGPU 架构CPU到GPU的数据传输GPU性能限制 三&#xff0c;可见性Renderable可渲染对象提高渲染效率Visibility Culling 可见性裁剪 四&#xff0c;纹理压…

电路模型和电路定律

电路---为了某种需要由某些电工设备或元件按一定方式组合起来的电流的通路 实际电路的两个作用 1.电能的传输&#xff0c;分配和转换 2.传递和处理信号 电路中的几个基本概念 激励---电源或信号源的电压或电流&#xff0c;也称为输入 响应---由激励在电路各部分产生的电流…

怎么参与场外期权?

今天期权懂带你了解怎么参与场外期权&#xff1f; 目前个人投资者暂时还不能直接参与场外个股期权&#xff0c;因为场外个股期权现在只能机构来进行交易。 所以个人投资者目前只能通过机构通道来进行操作&#xff0c;类似期权懂&#xff0c;找到期权懂经理&#xff0c;然后通…

手机删除的照片怎么找回?3个急救指南,让你重新拥有

一不小心手滑&#xff0c;手机里的几百张珍贵照片就消失了&#xff01;是不是心如刀割&#xff0c;感觉错过了几个亿&#xff1f;手机删除的照片怎么找回&#xff1f;别担心&#xff0c;小菜一碟&#xff0c;恢复照片就像打游戏一样&#xff0c;只要掌握正确的“攻略”&#xf…

AI大模型时代来临:企业如何抢占先机?

AI大模型时代来临:企业如何抢占先机? 2023年,被誉为大模型元年,AI大模型的发展如同一股不可阻挡的潮流,正迅速改变着我们的工作和生活方式。从金融到医疗,从教育到制造业,AI大模型正以其强大的生成能力和智能分析,重塑着行业的未来。 智能化:企业核心能力的转变 企…

世界智能产业博览会开幕 - 天空卫士汽车行业方案入选优秀案例

6月20日&#xff0c;以“智行天下、能动未来”为主题的2024世界智能产业博览会在国家会展中心&#xff08;天津&#xff09;开幕。主席向博览会致贺信并指出&#xff1a;中国高度重视人工智能发展&#xff0c;积极推动互联网、大数据、人工智能和实体经济深度融合&#xff0c;培…

[Python学习篇] Python函数

定义函数 语法&#xff1a;使用关键字 def def 函数名(参数): 代码1 代码2 ...... 调用函数 语法&#xff1a; 函数名(参数) 注意&#xff1a;不同的需求&#xff0c;参数可有可无。在Python中&#xff0c;函数必须先定义后使用 示例&#xff1a; # 定义函数 d…

csdn如何建立专栏,并且把已发布的文章,放到专栏里

不会在csdn上建立专栏&#xff0c;管理自己的博客&#xff1f; 建立了专栏&#xff0c;不知道该怎么放入文章&#xff1f; 本文将一步步带你解决这些问题。 我是蚊子码农&#xff0c;欢迎各位的点赞、关注和收藏&#xff0c;有了你们的激励&#xff0c;我会带来更好的作品。…

聚焦 Navicat 17 新特性 | 让用户界面交互更丝滑

随着 Navicat 17 的发布&#xff0c;引起业界热烈反响和深入讨论。早前&#xff0c;我们介绍了 Navicat 17 《模型设计创新与优化​​​​​​​》与《查询与配置》的新特性。此外&#xff0c;Navicat 在用户界面交互方面进行了显著优化&#xff0c;新增了一系列实用的功能&…

《后端程序猿 · 基于 Lettuce 实现缓存容错策略》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;如需交流&#xff…

机器学习辅助的乙醇浓度检测

目录 1.为什么要机器学习 2. 神经网络一般组成 3.BP神经网络工作过程 4.评价指标 5.实操代码 1.为什么要用机器学习 人工分析大量的谐振模式&#xff0c;建立各种WGM的响应与未知目标之间的关系&#xff0c;是一个很大的挑战。机器学习(ML)能够自行识别全谱的全部特征。作为…

如何在Lazada平台快速出单?测评助力商家突破销量瓶颈

Lazada在短短的几年里已经发展成了东南亚地区最大的在线购物网站之一 &#xff0c;很多商家也想要在这样一个大的跨境平台上发展。那么&#xff0c;对于希望在Lazada平台上大展拳脚的商家而言&#xff0c;出单是否容易呢? ​一、Lazada出单容易吗? Lazada出单的难易程度并非…

漫步5G-A City,一份独属于上海的浪漫

作家亨利詹姆斯曾写道&#xff0c;“城市漫步&#xff0c;让我接触到了这个世界上最好的东西”。 用漫无目的地行走&#xff0c;来体验和观察一座城市&#xff0c;上海凭借丰富多元的文化特质&#xff0c;成为citywalk这种浪漫生活方式的流行地。 无论你是漫步在美术馆、画廊林…

数据抓取技术在视频内容监控与快速读取中的应用

引言 在数字化时代&#xff0c;视频内容的快速读取和监控对于内容提供商来说至关重要。思通数科的OPEN-SPIDER抓取技术为这一需求提供了高效的解决方案。 OPEN-SPIDER技术概述 OPEN-SPIDER是思通数科开发的一种先进的数据抓取技术&#xff0c;它能够&#xff1a; - 高效地从各…

Stable Diffusion【基础篇】:降噪强度(denoising strength)

提到降噪强度&#xff08;denoising strength&#xff09;&#xff0c;大家一定不会陌生&#xff0c;这个参数是图生图中最关键的参数之一。今天在Stable Diffusion Art网站看到一篇介绍降噪强度&#xff08;denoising strength&#xff09;的文章&#xff08;地址&#xff1a;…

从hugging face 下模型

支持国内下载hugging face 的东西 下模型权重 model_id 是红色圈复制的 代码 记得设置下载的存储位置 import os from pathlib import Path from huggingface_hub import hf_hub_download from huggingface_hub import snapshot_downloadmodel_id"llava-hf/llava-v1…

【Python机器学习】模型评估与改进——二分类指标

目录 1、错误类型 2、不平衡数据集 3、混淆矩阵 与精度的关系。 准确率、召回率与f-分数 分类报告 4、考虑不确定性 5、准确率-召回率曲线 6、受试者工作特征&#xff08;ROC&#xff09;与AUC 二分类可能是实践中最常见的机器学习应用&#xff0c;也是概念最简单的应…