Gxemul 运行原理简述
2019独角兽企业重金招聘Python工程师标准>>>
Gxemul支援ARM,MIPS,PPC内核的虚拟机,这里以oldtestmips机器类型为例,介绍gxemul如何运行
1 主流程,以虚拟机的生命周期简单说明
main.cc main()
{cpu_init(); 初始化CPU模块,注册不同的cpu family函数device_init(); 初始化device模块machine_init(); 初始化machine,注册不同的machine setup函数emul = emul_new(NULL); 创建虚拟机get_cmd_args (argc, argv, emul, &diskimages, &n_diskimages) 解析参数emul_simple_init(emul); 初始化虚拟机emul_run(emul); 运行虚拟机,虚拟机运行后在这个函数内loop执行指令emul_destroy(emul); 删除虚拟机
}
2 初始化CPU
cpu.cc cpu_init
{ADD_ALL_CPU_FAMILIES;
}cpu.cc add_cpu_family(mips_cpu_family_init, ARCH_MIPS);
{res = family_init(fp);
}
对于mips来说family_init就是mips_cpu_family_init,由tmp_mips_tail.cc使用cpu.h的宏CPU_FAMILY_INIT生成,请在tmp_mips_tail.cc是在编译时由generate_tail.c产生
tmp_mips_tail.cc CPU_FAMILY_INIT(mips,"MIPS")
#define CPU_FAMILY_INIT(n,s) int n ## _cpu_family_init( \struct cpu_family *fp) { \/* Fill in the cpu_family struct with valid data for this arch. */ \fp->name = strdup(s); \fp->cpu_new = n ## _cpu_new; \fp->list_available_types = n ## _cpu_list_available_types; \fp->disassemble_instr = n ## _cpu_disassemble_instr; \fp->register_dump = n ## _cpu_register_dump; \fp->dumpinfo = n ## _cpu_dumpinfo; \fp->functioncall_trace = n ## _cpu_functioncall_trace; \fp->tlbdump = n ## _cpu_tlbdump; \fp->init_tables = n ## _cpu_init_tables; \return 1; \
}
展开为:
mips_cpu_family_init(struct cpu_family *)
{fp->name = strdup(“MIPS”);fp->cpu_new = mips _cpu_new;…..fp->init_tables = mips _cpu_init_tables;
}
3 初始化machine
machine.cc machine_init()
{automachine_init()
}automachine.cc automachine_init()
{machine_register_oldtestmips()
}machine_register_oldtestmips()在machine_test.cc 中通过machine.h的宏定义:
#define MACHINE_REGISTER(x) void machine_register_ ## x(void)
MACHINE_REGISTER(oldtestmips)
{MR_DEFAULT(oldtestmips, "Test-machine for MIPS", ARCH_MIPS, MACHINE_TESTMIPS);machine_entry_add_alias(me, "oldtestmips");
}machine.h的宏定义
#define MR_DEFAULT(x,name,arch,type) struct machine_entry \*me = machine_entry_new(name,arch,type); \me->setup = machine_setup_ ## x; \me->set_default_cpu = machine_default_cpu_ ## x; \machine_entry_register(me, arch);展开为:
void machine_register_oldtestmips(void)
{struct machine_entry *me = machine_entry_new("Test-machine for MIPS", ARCH_MIPS, MACHINE_TESTMIPS);me->setup = machine_setup_oldtestmipsme->set_default_cpu = machine_default_cpu_ oldtestmips; machine_entry_register(me, ARCH_MIPS);machine_entry_add_alias(me, "oldtestmips");
}
4 初始化虚拟机
emul.cc emul_simple_init()
{emul_machine_setup(m, extra_argc, extra_argv, 0, NULL);
}emul.cc emul_machine_setup()
{创建系统系统内存machine_memsize_fix(m);memory_amount = (uint64_t)m->physical_ram_in_mb * 1048576;m->memory = memory_new(memory_amount, m->arch);创建cpu管理单元CHECK_ALLOCATION(m->cpus = (struct cpu **) malloc(sizeof(struct cpu *) * m->ncpus));memset(m->cpus, 0, sizeof(struct cpu *) * m->ncpus);m->cpus[i] = cpu_new(m->memory, m, i, m->cpu_name);向系统内存写入随机数cpu->memory_rw(cpu, m->memory, i, data, sizeof(data),MEM_WRITE, CACHE_NONE | NO_EXCEPTIONS | PHYSICAL);添加通用的devicedevice_add(m, device_names[i]);machine设置machine_setup(m);将要运行的文件load进入虚拟机file_load(m, m->memory, name_to_load, &entrypoint, m->arch, &gp, &byte_order, &toc);
}
4.1 创建cpu管理单元
cpu.cc cpu_new
{fp->cpu_new(cpu, mem, machine, cpu_id, cpu_type_name)初始化table,在mips_cpu_family_init中定义为mips_cpu_init_tablesfp->init_tables(cpu);
}
cpu_new在mips_cpu_family_init时已经设置为mips _cpu_new
cpu_mips.cc mips _cpu_new
{设置内存访问函数cpu->memory_rw = mips_memory_rw;设置指令访问函数cpu->run_instr = mips32_run_instr;cpu->instruction_has_delayslot = mips_cpu_instruction_has_delayslot;设置异常中断templ.interrupt_assert = mips_cpu_interrupt_assert;templ.interrupt_deassert = mips_cpu_interrupt_deassert;interrupt_handler_register(&templ);设置cp0/cp1cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);设置虚拟地址到物理地址的转换函数cpu->translate_v2p = translate_v2p_mmu3k;
}
4.2 machine设置
machine.cc machine_setup()
{me->setup(machine, cpu);
}
setup在machine_init的时候注册,oldtestmips对应的是machine_setup_oldtestmips在machine_test.cc 中通过machine.h的宏定义:
#define MACHINE_SETUP(x) void machine_setup_ ## x(struct machine *machine, struct cpu *cpu)
MACHINE_SETUP(oldtestmips)
{device_add(machine, tmpstr); 添加于machine相关的device
}
4.3 load文件到虚拟机内
gxemul可以load各种格式的文件,这里只分析load bin文件的过程
file.cc file_load()
{file_load_raw()
}file_raw.cc file_load_raw
{从脚本中分析出load地址和文件名loadaddr = vaddr = entry = strtoull(filename, NULL, 0);p2 = p+1;打开对应要运行的文件f = fopen(strrchr(filename, ':')+1, "r");读文件并写入到内存中len = fread(buf, 1, to_read, f);m->cpus[0]->memory_rw(m->cpus[0], mem, vaddr, &buf[0], len, MEM_WRITE, NO_EXCEPTIONS);关闭文件fclose(f);
}
5 运行machine
emul.cc emul_run()
{cpu_run_init(emul->machines[j]); 初始化machine内的CPUtimer_start() 启动虚拟机的clock//循环执行while(go){timer_poll();anything = machine_run(emul->machines[j]);if (anything)go = 1;}timer_stop(); 停止虚拟机clockcpu_run_deinit(emul->machines[j]);
}machine.cc machine_run()
{cpus[i]->run_instr(cpus[i]); 执行指令machine->tick_functions.f[te](cpus[0], machine->tick_functions.extra[te]); trick
}
文后话:
gxemul的源代码使用了大量的宏,按照宏的模板生成代码,这可能和作者想通过统一的模板来表示不同的CPU架构,能是代码简洁且模块化强。但是大量的宏降低了代码的可读性。基于同样的原因gxemul针对CPU架构的一些处理代码使用了文件自动生成,阅读的时候也要注意。
转载于:https://my.oschina.net/lgl88911/blog/287766
Gxemul 运行原理简述相关推荐
- 张勋说:简述棒磨机的工作运行原理和磨损机制(图文)
1 棒磨机的工作运行原理 棒磨机采用筒形旋转装置,外沿齿轮传动,两仓,格子型,由给料部.出料部.回转部.传动部 等主要部分组成.中空轴采用铸钢件,内衬可拆换,回转大齿轮釆用铸件滚齿加工,筒体内镶有耐磨 ...
- 【SpringMVC】面试常见问题:总结 SpringMVC 运行原理
请简述SpringMVC 运行原理: 如果在 web.xml 中设置 DispatcherServlet 的 <url-pattern> 为/时, 当用户发起请求, 请求一个控制器, 首先 ...
- ELF PLT Hook 原理简述
[无线平台]ELF PLT Hook 原理简述 简述 Android 是基于Linux的操作系统,因此在Android开发平台上,ELF是原生支持的可执行文件格式:ELF文件格式除了作为可执行文件,还 ...
- Excel阅读模式/聚光灯开发技术之二 超级逐步录入提示功能开发原理简述—— 隐鹤 / HelloWorld...
Excel阅读模式/聚光灯开发技术之二 超级逐步录入提示功能开发原理简述---- 隐鹤 / HelloWorld 1. 引言 自本人第一篇博文"Excel阅读模式/单元格行列指示/聚光灯 ...
- Spark Shuffle运行原理
1.什么是spark shuffle? Shuffle中文意思就是"洗牌",在Spark中Shuffle的目的是为了保证每一个key所对应的value都会汇聚到同一个分区上去聚合和 ...
- Servlet运行原理以及生命周期
Servlet运行原理 Servlet生命周期定义了一个Servlet如何被加载.初始化,以及它怎样接收请求.响应请求,提供服务.在讨论Servlet生命周期之前,先让我们来看一下这几个方法: 1. ...
- ASP.NET运行原理
一个ASP.NET的应用程序是开始于IIS的. 当你请求一个包含ASP.NET应用的网址时,IIS接受到请求(IIS是WEB服务守候进程),IIS收到请求后,会根据请求者请求的主机头或者IP或者端口号 ...
- Linux X Window System运行原理和启动过程
本文主要说明X Window System的基本运行原理,其启动过程,及常见的跨网络运行X Window System. 一) 基本运行原理 X Window System采用C/S结构,但和我们常见 ...
- 10分钟了解Flutter跨平台运行原理!
导语 | 本文将从选型.简介和运行原理三大部分为你介绍Flutter的相关概念,希望能站在框架设计和实现原理的高度,带领大家去理解Flutter区别其他跨平台解决方案的关键所在. 一.为什么选择Flu ...
- spark on yarn 完全分布式_Spark编程笔记(1)-架构基础与运行原理
引言 根据IBM前首席执行官郭士纳的观点,IT领域每隔十五年就会迎来一 次重大变革 .当前我们正处于第三次信息浪潮(2010年前后),物联网.云计算和大数据技术突飞猛进. 信息爆炸是我们当前所需要解决 ...
最新文章
- 没有好看的 Terminal 怎么能够快乐地写代码
- windows server 2003磁盘管理
- android 后台Activity移到前台
- Hadoop 分布式文件系统 - HDFS
- (acm)C++加速输入的几种方法
- 为什么读完博士反而逃离科研?中科院博导:因为我们的科研让人乏味!
- 如何构建可视化的营销数据大屏? 1
- [读后感]Java 控制台执行 Jar 传參的编码问题
- 站在巨人的肩膀上——Linux信号量操作
- 古诗词取名小工具1.0
- fw313r手机登录_迅捷fw326r路由器手机登录
- APISpace 尾号限行API接口 免费好用
- 坚果云服务器地址,坚果云第三方应用授权WebDAV开启方法
- 针对《评人工智能如何走向新阶段》一文,继续发布国内外的跟贴留言466-476条如下:
- 汇编DOS与Windows Masm编译运行代码步骤详解
- Unity打包篇:能够解决Unity打包Gradle遇到的所有问题方法整合!(持续更新中!)
- length()与lengthb()的区别
- 华图教育计算机基础知识,公共基础知识备考:计算机辅助制造
- 小白看了也能搭建物联网项目——物联网开发板——QD-mini板
- 虚函数与纯虚函数以及虚函数表之间的关系
热门文章
- 代码积累与编程能力哪个更重要
- 编译」(compile),与「反编译」(decompile)..哪些语言容易被反编译.
- VSCode : vscode-remote下无法写入文件及linux文件读写权限
- 闭包:学习Javascript闭包(Closure)
- julia: 如何序列化和反序列化?
- 阿里云宗志刚:云网一体,新一代洛神云网络平台
- ZStack跨平台迁移可以如此简单
- 【手势识别】基于matlab PCA+LDA手语检测识别【含Matlab源码 1551期】
- 如何更新计算机的flash player,如何在win7电脑中Adobe Flash Player自动更新?
- html让font居中,用CSS做将如何字体居中?