qemu源码解析【04】qom实例

目录

  • qemu源码解析【04】qom实例
    • 1. type_init()宏
    • 2. type_register_static()宏
    • 3. arm_sbcon_i2c_init()何时被qemu系统调用

qemu源码解析【04】qom实例

  • qemu源码解析【总目录】

  • 继续分析arm_sbcon_i2c实例,代码从行尾往上逐步分析

#include "qemu/osdep.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#include "hw/registerfields.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "qom/object.h"REG32(CONTROL_GET, 0)
REG32(CONTROL_SET, 0)
REG32(CONTROL_CLR, 4)#define SCL BIT(0)
#define SDA BIT(1)static uint64_t arm_sbcon_i2c_read(void *opaque, hwaddr offset,unsigned size)
{ArmSbconI2CState *s = opaque;switch (offset) {case A_CONTROL_SET:return (s->out & 1) | (s->in << 1);default:qemu_log_mask(LOG_GUEST_ERROR,"%s: Bad offset 0x%x\n", __func__, (int)offset);return -1;}
}static void arm_sbcon_i2c_write(void *opaque, hwaddr offset,uint64_t value, unsigned size)
{ArmSbconI2CState *s = opaque;switch (offset) {case A_CONTROL_SET:s->out |= value & 3;break;case A_CONTROL_CLR:s->out &= ~value;break;default:qemu_log_mask(LOG_GUEST_ERROR,"%s: Bad offset 0x%x\n", __func__, (int)offset);}bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & SCL) != 0);s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0);
}static const MemoryRegionOps arm_sbcon_i2c_ops = {.read = arm_sbcon_i2c_read,.write = arm_sbcon_i2c_write,.endianness = DEVICE_NATIVE_ENDIAN,
};static void arm_sbcon_i2c_init(Object *obj)
{DeviceState *dev = DEVICE(obj);ArmSbconI2CState *s = ARM_SBCON_I2C(obj);SysBusDevice *sbd = SYS_BUS_DEVICE(obj);I2CBus *bus;bus = i2c_init_bus(dev, "i2c");bitbang_i2c_init(&s->bitbang, bus);memory_region_init_io(&s->iomem, obj, &arm_sbcon_i2c_ops, s,"arm_sbcon_i2c", 0x1000);sysbus_init_mmio(sbd, &s->iomem);
}static const TypeInfo arm_sbcon_i2c_info = {.name          = TYPE_ARM_SBCON_I2C,.parent        = TYPE_SYS_BUS_DEVICE,.instance_size = sizeof(ArmSbconI2CState),.instance_init = arm_sbcon_i2c_init,
};static void arm_sbcon_i2c_register_types(void)
{type_register_static(&arm_sbcon_i2c_info);
}type_init(arm_sbcon_i2c_register_types)

1. type_init()宏

  • 注意到上述代码最后一行,有个type_init()宏,这个宏用来注册qemu代码中,所有的qom类型
  • 将这个宏简单展开,可以得到如下函数:
static ModuleTypeList *find_type(module_init_type type)
{init_lists();return &init_type_list[type];
}void register_module_init(void (*fn)(void), MODULE_INIT_QOM)
{ModuleEntry *e;ModuleTypeList *l;e = g_malloc0(sizeof(*e));e->init = fn;e->type = MODULE_INIT_QOM;l = find_type(type);QTAILQ_INSERT_TAIL(l, e, node);
}
  • 不难看出,qemu中维护了一个全局列表ModuleTypeList * init_type_list[8],用来存放所有类型的初始化接口。qom类型位于init_type_list[MODULE_INIT_QOM]这个节点上
  • 所有qom类型经过注册之后,可以得到以下的链表:
    在这里插入图片描述
  • qemu系统启动时,对于qom类型,会逐个执行init_type_list[MODULE_INIT_QOM]列表上,所有的init入口函数,从而完成所有qom类型的初始化
  • 对于arm_sbcon_i2c这个实例,也就是执行arm_sbcon_i2c_register_types()入口函数

2. type_register_static()宏

  • 对于arm_sbcon_i2c这个实例,它的初始化入口函数arm_sbcon_i2c_register_types(),只有一行代码:
static void arm_sbcon_i2c_register_types(void)
{type_register_static(&arm_sbcon_i2c_info);
}
  • 将这个宏定义简单展开,可以得到
static TypeImpl *type_register_internal(const TypeInfo *info)
{TypeImpl *ti;// 检测一下成员name是否合法if (!type_name_is_valid(info->name)) {fprintf(stderr, "Registering '%s' with illegal type name\n", info->name);abort();}// 根据传入的TypeInfo类型,生成对应的TypeImpl类型ti = type_new(info);// 将新生成的TypeImpl类型,添加到全局的hash表中assert(!enumerating_types);g_hash_table_insert(type_table_get(), (void *)ti->name, ti);return ti;
}
  • 上述的代码注释已经写清楚了,我们在arm_sbcon_i2c.c中生成了一个TypeInfo类型,然后用这个宏生成对应的TypeImpl类型,基本上两个结构体的成员差不多。然后将这个TypeImpl数据添加到全局的hash表中

3. arm_sbcon_i2c_init()何时被qemu系统调用

  • 简单分析了一下,针对这个arm_sbcon_i2c实例,arm_sbcon_i2c_init()的调用层级如以下所示:
  • system/main.c,main()函数
  • system/vl.c,qemu_init()函数
  • system/vl.c,qemu_create_machine()函数
  • qom/object.c,object_new_with_class()函数
  • qom/object.c,object_new_with_type()函数
  • qom/object.c,object_initialize_with_type()函数
  • qom/object.c,object_init_with_type()函数,这个函数正式调用每个hash表节点的初始化函数,并且还带了一个递归逻辑,循环初始化父类型:
static void object_init_with_type(Object *obj, TypeImpl *ti)
{if (type_has_parent(ti)) {object_init_with_type(obj, type_get_parent(ti));}if (ti->instance_init) {ti->instance_init(obj);}
}

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

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

相关文章

【潜意识Java】蓝桥杯算法有关的动态规划求解背包问题

目录 背包问题简介 问题描述 输入&#xff1a; 输出&#xff1a; 动态规划解法 动态规划状态转移 代码实现 代码解释 动态规划的时间复杂度 例子解析 输出&#xff1a; 总结 作者我蓝桥杯&#xff1a;2023第十四届蓝桥杯国赛C/C大学B组一等奖&#xff0c;所以请听我…

【C++】抽象之神:类和对象(中)万字详解

Hi&#xff0c;朋友们&#xff0c;好久不见 我们上次学到了C类和对象&#xff08;上&#xff09;&#xff0c;感觉那难度还行&#xff0c;能接受&#xff0c;但这次的类和对象&#xff08;中&#xff09;&#xff0c;一开始真是让我觉得脑子转不动的无力感&#xff0c;难呐&am…

C++手动实现一个HashMap

1.HashMap原理 参考我的博客&#xff1a;https://blog.csdn.net/Revendell/article/details/110009858 开链法&#xff1a;STL的hashtable便是采用开链法解决冲突。这种做法是在每一个表格元素中维护一个list&#xff1a;散列函数为我们分配某一个list&#xff0c;然后我们在…

【Linux】深入理解进程信号机制:信号的产生、捕获与阻塞

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 时间不语&#xff0c;却回答了所有问题 目录 &#x1f4da;前言 &#x1f4da;一、信号的本质 &#x1f4d6;1.异步通信 &#x1f4d6;2.信…

sql server 数据库还原,和数据检查

右键数据库选择还原&#xff0c; 还原的备份文件必须选择在本地的文件&#xff08;远程文件没有试过&#xff09;还原数据库名字可以修改&#xff0c;然后file选择中有个2个目录data file 的目录 &#xff0c;和log data 的目录都可以重新选择还原到的新的目录&#xff0c;不要…

v31蓝牙信标方案

革新点 带蜂鸣器功能 容易安装和移动 多彩均匀明显的指示灯 长电池寿命&#xff0c;常规使用1-2年 自带1个按键 钮扣电池组供电 产品概述 电子标签拣货系统是一组安装在货架储位上的电子设备&#xff0c;通过计算机与软件的控制&#xff0c;藉由指示灯或数字显示作为辅助…

内存中优雅的csv对象(Python)

磁盘*.csv文件是文本&#xff0c;以行结构的二维list是内存中的“csv”。 (笔记模板由python脚本于2024年12月18日 10:15:23创建&#xff0c;本篇笔记适合学习过list、panda的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&…

OpenGL —— 2.6.1、绘制一个正方体并贴图渲染颜色(附源码,glfw+glad)

源码效果 C++源码 纹理图片 需下载stb_image.h这个解码图片的库,该库只有一个头文件。 具体代码: vertexShader.glsl #version

H5 中 van-popup 的使用以及题目的切换

H5 中 van-popup 的使用以及题目的切换 在移动端开发中&#xff0c;弹窗组件是一个常见的需求。vant 是一个轻量、可靠的移动端 Vue 组件库&#xff0c;其中的 van-popup 组件可以方便地实现弹窗效果。本文将介绍如何使用 van-popup 实现题目详情的弹窗展示&#xff0c;并实现…

Metaploit-永恒之蓝漏洞利用

1&#xff1a;Metaploit介绍   本次测试主要是利用永恒之蓝漏洞对windows7进行控制利用&#xff0c;掌握Metaploit工具的使用&#xff0c;知道永恒之蓝的漏洞利用原理。永恒之蓝是在Windows的SMB服务处理SMB v1请求时发生的漏洞&#xff0c;这个漏洞导致攻击者在目标系统上可…

FPGA高速下载器SZ901

SZ901基于AMD(Xilinx) Virtual Cable协议. 本设备使用千兆网络接口。基于此接口,本设备可以同时支持多达四路FPGA板卡同时调试,每组相互独立,互不干扰。 特点 1,支持JTAG 速度最高53Mb/s&#xff0c;电压范围1.2-3.3V,最高支持200cm排线 2,支持4路JTAG独立使用 3,支持多路…

【递归,搜索与回溯算法】穷举 vs 暴搜 vs 深搜 vs 回溯 vs 剪枝算法入门专题详解

前言 什么是回溯算法&#xff1f; 回溯算法是一种经典的递归算法&#xff0c;通常用于解决组合问题、排列问题和搜索问题等。 回溯算法的基本思想 从一个初始状态开始&#xff0c;按照一定的规则向前搜索&#xff0c;当搜索到某个状态无法前进时&#xff0c;回退…

设计模式之桥接模式:抽象与实现之间的分离艺术

~犬&#x1f4f0;余~ “我欲贱而贵&#xff0c;愚而智&#xff0c;贫而富&#xff0c;可乎&#xff1f; 曰&#xff1a;其唯学乎” 桥接模式概述与角色组成 想象一下你家里的电视遥控器&#xff0c;无论是索尼还是三星的电视机&#xff0c;遥控器的按键功能都差不多&#xff1…

ASRPRO学习笔记一之语音模型位置和语音替换

一、语音替换的步骤 1、扬声器录音 打开GoldWave,点击工具栏中的蓝色控制属性按钮&#xff0c;点击设备&#xff0c;选择扬声器&#xff0c;点击ok。打开电脑上的网易云音乐&#xff0c;点击红色的录制按钮&#xff0c;开始录制音乐&#xff0c;在网易云音乐上点击播放音乐,录…

多因子认证 (Multi-factor authentication, MFA)

多因子认证 (MFA) 是一种思想&#xff0c;而UsernamePassword&#xff0c;OTP等是具体的认证手段。多因子认证就是将这些认证手段结合。 目录 什么是MFAMFA的作用MFA的实际应用 认证认证 (Authentication, AuthN) 因素常见的认证 (Authentication, AuthN) 类型密码认证无密码认…

内存压缩禁用设置

设置禁用内存压缩功能 1、“Win”“X”键→“A”键 2、如果输入“Get-MMAgent”并按“Enter”键&#xff0c;则可以从“MemoryCompression”中检查内存压缩功能的状态。 True启用&#xff0c;False禁用 3、要禁用内存压缩功能&#xff0c;请输入“Disable-MMAgent -mc”并…

素数回文数的个数

素数回文数的个数 C语言代码C 代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 求11到n之间&#xff08;包括n&#xff09;&#xff0c;既是素数又是回文数的整数有多少个。 输入 一个大于11小于1000的整数n。 输出…

QT网络(一):主机信息查询

网络简介 在QT中进行网络通信可以使用QT提供的Qt Network模块&#xff0c;该模块提供了用于编写TCP/IP网络应用程序的各种类&#xff0c;如用于TCP通信的QTcpSocket和 QTcpServer&#xff0c;用于 UDP 通信的 QUdpSocket&#xff0c;还有用于网络承载管理的类&#xff0c;以及…

Flutter Navigator2.0的原理和Web端实践

01 背景与动机 在Navigator 2.0推出之前&#xff0c;Flutter主要通过Navigator 1.0和其提供的 API&#xff08;如push(), pop(), pushNamed()等&#xff09;来管理页面路由。然而&#xff0c;Navigator 1.0存在一些局限性&#xff0c;如难以实现复杂的页面操作&#xff08;如移…

如何在谷歌浏览器中开启安全浏览

在数字化时代&#xff0c;网络安全变得愈发重要。作为全球最受欢迎的网络浏览器之一&#xff0c;谷歌浏览器提供了多种功能来保护用户的在线安全。本文将详细介绍如何在谷歌浏览器中开启安全浏览&#xff0c;并额外提供一些有用的页面滚动设置、地址栏快捷搜索和跟踪防护的相关…