QEMU源码全解析 —— PCI设备模拟(7)

接前一篇文章:

上一回讲解了pci_edu_realize函数中的pci_register_bar函数,本回开始对于edu设备的MMIO读写函数进行解析。

操作系统与PCI设备交互的主要方式是PIO和MMIO。MMIO虽然是一段内存,但是其没有EPT映射,在虚拟机访问设备的MMIO时,会产生VM Exit;KVM识别此MMIO访问并且将该访问分派到应用层QEMU中;QEMU根据内存虚拟化的步骤进行分派,找到设备注册的MMIO读写回调函数;设备的MMIO读写回调函数根据设备的功能进行模拟,完成模拟之后可能会发送中断到虚拟机中,从而完成一些MMIO访问。

前文书(QEMU源码全解析 —— PCI设备模拟(5))已经讲过,pci_edu_realize函数中调用memory_region_init_io函数,指定其读写函数是edu_mmio_ops。

edu_mmio_ops在hw/misc/edu中初始化,代码如下:

static const MemoryRegionOps edu_mmio_ops = {.read = edu_mmio_read,.write = edu_mmio_write,.endianness = DEVICE_NATIVE_ENDIAN,.valid = {.min_access_size = 4,.max_access_size = 8,},.impl = {.min_access_size = 4,.max_access_size = 8,},};

edu_mmio_ops的类型为MemoryRegionOps,此结构在include/exec/memory.h中定义,代码如下:

typedef struct MemoryRegionOps MemoryRegionOps;

而struct MemoryRegionOps的定义也在include/exec/memory.h中,如下:

/** Memory region callbacks*/
struct MemoryRegionOps {/* Read from the memory region. @addr is relative to @mr; @size is* in bytes. */uint64_t (*read)(void *opaque,hwaddr addr,unsigned size);/* Write to the memory region. @addr is relative to @mr; @size is* in bytes. */void (*write)(void *opaque,hwaddr addr,uint64_t data,unsigned size);MemTxResult (*read_with_attrs)(void *opaque,hwaddr addr,uint64_t *data,unsigned size,MemTxAttrs attrs);MemTxResult (*write_with_attrs)(void *opaque,hwaddr addr,uint64_t data,unsigned size,MemTxAttrs attrs);enum device_endian endianness;/* Guest-visible constraints: */struct {/* If nonzero, specify bounds on access sizes beyond which a machine* check is thrown.*/unsigned min_access_size;unsigned max_access_size;/* If true, unaligned accesses are supported.  Otherwise unaligned* accesses throw machine checks.*/bool unaligned;/** If present, and returns #false, the transaction is not accepted* by the device (and results in machine dependent behaviour such* as a machine check exception).*/bool (*accepts)(void *opaque, hwaddr addr,unsigned size, bool is_write,MemTxAttrs attrs);} valid;/* Internal implementation constraints: */struct {/* If nonzero, specifies the minimum size implemented.  Smaller sizes* will be rounded upwards and a partial result will be returned.*/unsigned min_access_size;/* If nonzero, specifies the maximum size implemented.  Larger sizes* will be done as a series of accesses with smaller sizes.*/unsigned max_access_size;/* If true, unaligned accesses are supported.  Otherwise all accesses* are converted to (possibly multiple) naturally aligned accesses.*/bool unaligned;} impl;
};

其中的read和Write函数分别表示该MMIO的读写回调;endianness表示字节的大小端模式。

以write回调函数为例,

    /* Write to the memory region. @addr is relative to @mr; @size is* in bytes. */void (*write)(void *opaque,hwaddr addr,uint64_t data,unsigned size);
static void edu_mmio_write(void *opaque, hwaddr addr, uint64_t val,unsigned size)

其原型中的opaque表示的是设备的对象;addr表示虚拟机读的地址在该MMIO中的偏移地址;data(val)表示要写入的值;size表示写入值的大小,通常由单字节、双字节、四字节以及八字节。

edu_mmio_write函数同样在hw/misc/edu.c中,代码如下:

static void edu_mmio_write(void *opaque, hwaddr addr, uint64_t val,unsigned size)
{EduState *edu = opaque;if (addr < 0x80 && size != 4) {return;}if (addr >= 0x80 && size != 4 && size != 8) {return;}switch (addr) {case 0x04:edu->addr4 = ~val;break;case 0x08:if (qatomic_read(&edu->status) & EDU_STATUS_COMPUTING) {break;}/* EDU_STATUS_COMPUTING cannot go 0->1 concurrently, because it is only* set in this function and it is under the iothread mutex.*/qemu_mutex_lock(&edu->thr_mutex);edu->fact = val;qatomic_or(&edu->status, EDU_STATUS_COMPUTING);qemu_cond_signal(&edu->thr_cond);qemu_mutex_unlock(&edu->thr_mutex);break;case 0x20:if (val & EDU_STATUS_IRQFACT) {qatomic_or(&edu->status, EDU_STATUS_IRQFACT);/* Order check of the COMPUTING flag after setting IRQFACT.  */smp_mb__after_rmw();} else {qatomic_and(&edu->status, ~EDU_STATUS_IRQFACT);}break;case 0x60:edu_raise_irq(edu, val);break;case 0x64:edu_lower_irq(edu, val);break;case 0x80:dma_rw(edu, true, &val, &edu->dma.src, false);break;case 0x88:dma_rw(edu, true, &val, &edu->dma.dst, false);break;case 0x90:dma_rw(edu, true, &val, &edu->dma.cnt, false);break;case 0x98:if (!(val & EDU_DMA_RUN)) {break;}dma_rw(edu, true, &val, &edu->dma.cmd, true);break;}
}

edu_mmio_write函数展示了一个虚拟机在写设备MMIO地址时QEMU中设备模拟的典型行为。

(1)首先,需要检查读写地址以及大小是否在范围之内。代码片段如下:

    if (addr < 0x80 && size != 4) {return;}if (addr >= 0x80 && size != 4 && size != 8) {return;}

(2)然后,根据具体的地址来进行适当的行为。

这些行为可以是简单地设置一个值,如这里的写0x04地址,代码片段如下:

    case 0x04:edu->addr4 = ~val;break;

也可以是将中断设置为高电平(写0x60地址)或者设置为低电平(写0x64地址),代码片段如下:

    case 0x60:edu_raise_irq(edu, val);break;case 0x64:edu_lower_irq(edu, val);break;

还可以是通过dma读写设备虚拟机的物理地址(写0x80地址),代码片段如下:

    case 0x80:dma_rw(edu, true, &val, &edu->dma.src, false);break;

对于read回调函数,也是类似的机制。这里仅给出edu_mmio_read函数源码,在hw/misc/edu.c中,代码如下:

static uint64_t edu_mmio_read(void *opaque, hwaddr addr, unsigned size)
{EduState *edu = opaque;uint64_t val = ~0ULL;if (addr < 0x80 && size != 4) {return val;}if (addr >= 0x80 && size != 4 && size != 8) {return val;}switch (addr) {case 0x00:val = 0x010000edu;break;case 0x04:val = edu->addr4;break;case 0x08:qemu_mutex_lock(&edu->thr_mutex);val = edu->fact;qemu_mutex_unlock(&edu->thr_mutex);break;case 0x20:val = qatomic_read(&edu->status);break;case 0x24:val = edu->irq_status;break;case 0x80:dma_rw(edu, false, &val, &edu->dma.src, false);break;case 0x88:dma_rw(edu, false, &val, &edu->dma.dst, false);break;case 0x90:dma_rw(edu, false, &val, &edu->dma.cnt, false);break;case 0x98:dma_rw(edu, false, &val, &edu->dma.cmd, false);break;}return val;
}

欲知后事如何,且看下回分解。

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

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

相关文章

Smallpdf扫描、转换、压缩、编辑、签名PDF

【应用名称】&#xff1a;Smallpdf: 扫描、转换、压缩、编辑、签名PDF 【适用平台】&#xff1a;#Android 【软件标签】&#xff1a;#Smallpdf 【应用版本】&#xff1a;1.71.0 【应用大小】&#xff1a;150MB 【软件说明】&#xff1a;通过 Smallpdf&#xff0c;您可以&…

数据结构 模拟实现二叉树(孩子表示法)

目录 一、二叉树的简单概念 &#xff08;1&#xff09;关于树的一些概念 &#xff08;2&#xff09;二叉树的一些概念及性质 定义二叉树的代码&#xff1a; 二、二叉树的方法实现 &#xff08;1&#xff09;createTree &#xff08;2&#xff09;preOrder &#xff08;…

资源三号03星-立体测绘卫星星座

资源三号03星作为我国民用高分辨率立体测图卫星资源三号系列的第三颗卫星&#xff0c;在资源三号02星技术状态的基础上进行了继承和适当优化&#xff0c;设计寿命由资源三号02星的5年延长至8年&#xff0c;星上搭载了三线阵立体测绘相机、多光谱相机和业务化应用的激光测高仪&a…

【模型评估 07】过拟合与欠拟合

在模型评估与调整的过程中&#xff0c;我们往往会遇到“过拟合”或“欠拟合”的情况。如何有效地识别“过拟合”和“欠拟合”现象&#xff0c;并有针对性地进行模型调整&#xff0c;是不断改进机器学习模型的关键。特别是在实际项目中&#xff0c;采用多种方法、从多个角度降低…

C#使用CryptoStream类加密和解密字符串

目录 一、CrytoStream的加密方法 二、CrytoStream的解密方法 三、实例 1.源码Form1.cs 2.类库Encrypt.cs 3.生成效果 在使用CryptoStream前要先引用命名空间using System.Security.Cryptography。 一、CrytoStream的加密方法 记住&#xff0c;不能再使用DESCryptoServi…

DrGraph原理示教 - OpenCV 4 功能 - 边界填充

今天简单来看一下OpenCV中的边界填充 param src Source image. param dst Destination image of the same type as src and the size Size(src.colsleftright, src.rowstopbottom) . param top the top pixels param bottom the bottom pixels param left the left pixels par…

Photoshop 2024 (PS2024) v25 直装版 支持win/mac版

Photoshop 2024 提供了多种创意工具&#xff0c;如画笔、铅笔、涂鸦和渐变等&#xff0c;用户可以通过这些工具来创建独特和令人印象深刻的设计效果。增强的云同步&#xff1a;通过 Adobe Creative Cloud&#xff0c;用户可以方便地将他们的工作从一个设备无缝同步到另一个设备…

STM32L051使用HAL库操作实例(14)- ADC采集电压

目录 一、前言 二、ADC外设简要说明 三、STM32CubeMX配置&#xff08;本文使用的STM32CubeMX版本为6.1.2&#xff09; 1.MCU选型 2.时钟使能 3.外部时钟配置 4.串口配置 5.ADC引脚配置 6.配置STM32CubeMX生成工程文件 7.点击GENERATE CODE生成工程文件 四、工程源码 …

Python基础知识:整理13 利用pyecharts生成折线图

首先需要安装第三方包pyecharts 1 基础折线图 # 导包&#xff0c;导入Line功能构建折线图对象 from pyecharts.charts import Line # 折线图 from pyecharts.options import TitleOpts # 标题 from pyecharts.options import LegendOpts # 图例 from pyecharts.options im…

mp4文件全部转换为mp3

问题 今天突发奇想&#xff0c;想把mp4视频转换为mp3来收听&#xff0c;于是想到了ffmpeg工具 步骤 安装ffmpeg环境 要在 Windows 上配置 FFmpeg 环境&#xff0c;你可以按照以下步骤进行操作&#xff1a; 下载 FFmpeg&#xff1a; 首先&#xff0c;你需要下载 FFmpeg 的 W…

一个成功的camera案例:ros2+gazebo+摄像头

各位看&#xff1a;随着大物体的移动&#xff0c;在涉嫌头的位置也发生了改变-----右上角那个/camera的位置也变了 右上角那个是摄像头图案&#xff0c;以下是仓库链接&#xff1a; ros-ign-gazebo-camera: https://github.com/arashsm79/ros-ign-gazebo-camera.git一个ros2摄…

初识物联网

1&#xff1a;什么是IOT&#xff1a; 物联网的英文名称是Internet of Things。IoT则是Internet of Things的缩写。因此, 物联网 IoT。 通俗地说&#xff0c;物联网是互联网的一种拓展。我们知道互联网是由无数的计算机和智能手机交错连接而编织成的一张网。而正是有了像NodeM…

Spring Cloud + Vue前后端分离-第12章 通用权限设计

源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第12章 通用权限设计 这一章我们不依赖第三方框架&#xff0c;我会从权限相关表的设计&#xff0c;到权限的配置&#xff0c;到权限的拦截&#xff0c;带大家一步一步的做出…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《考虑新能源配网三相不平衡治理的电动汽车充电策略》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 这个标题表明研究着重于开发一种电动汽车充电策略&#xff0c;该策略考虑了在新能源配电网络中存在的三相不平衡问题。解读如下&#xff1a; 电动汽车充…

Typora上传图片失败PicGo

起初我是在Typora中点击一键上传图片&#xff0c;结果如下&#xff0c;报错。可是我找了半天也没错啊。 最后发现原来是一个图片的命名问题&#xff0c;名字太过于复杂&#xff0c;PicGo识别不出&#xff0c;一个图片报错导致其它也上传不了。 我把它复制到其它文件夹之后&…

【QUARTZ】springboot+quartz动态配置定时任务

Quartz 介绍 Quartz 定时任务可分为Trigger&#xff08;触发器&#xff09;、Job&#xff08;任务&#xff09;和Scheduler&#xff08;调度器&#xff09;&#xff0c;定时任务的逻辑大体为&#xff1a;创建触发器和任务&#xff0c;并将其加入到调度器中&#xff0c;如下图所…

webpack原理和逆向实战

文章目录 什么是webpackwebpack基本原理webpack代码分析webpack代码抠取webpack全模块自吐webpack自动扣取总结 什么是webpack webpack是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)&#xff0c;负责分析翻译压缩打包代码。 上面的官网的一张示例图。 web…

大数据实时抓取软件:Maxwell学习网站的高效框架!

介绍&#xff1a;Maxwell是由美国Zendesk开源的&#xff0c;使用Java编写的MySQL实时抓取软件。它能够实时读取MySQL的二进制日志&#xff08;Binlog&#xff09;&#xff0c;并将这些信息生成为JSON格式的消息。进一步地&#xff0c;Maxwell将这些消息作为生产者发送给Kafka、…

Springboot项目Nacos做配置中心

Springboot项目Nacos做配置中心 说明安装2.Springboot整合使用Nacos3.问题处理 说明 文档参考 Nacos Spring Boot 安装 查看nacos镜像 docker search nacos 下载镜像 docker pull nacos/nacos-server启动naocs镜像 docker run --env MODEstandalone --name nacos -d -p 8…

Abaqus2023安装下载教程

用钢铁意志&#xff0c;成就不平凡的人生。 今天博主整理了一下Abaqus2023安装下载教程&#xff0c;希望大家学习。 安装之前请关闭电脑所有杀毒软件和防火墙&#xff0c;并保证计算机名不是中文&#xff01;&#xff01;&#xff01;&#xff01; 1.首先创建一个用于Abaqus…