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. 张勋说:简述棒磨机的工作运行原理和磨损机制(图文)

    1 棒磨机的工作运行原理 棒磨机采用筒形旋转装置,外沿齿轮传动,两仓,格子型,由给料部.出料部.回转部.传动部 等主要部分组成.中空轴采用铸钢件,内衬可拆换,回转大齿轮釆用铸件滚齿加工,筒体内镶有耐磨 ...

  2. 【SpringMVC】面试常见问题:总结 SpringMVC 运行原理

    请简述SpringMVC 运行原理: 如果在 web.xml 中设置 DispatcherServlet 的 <url-pattern> 为/时, 当用户发起请求, 请求一个控制器, 首先 ...

  3. ELF PLT Hook 原理简述

    [无线平台]ELF PLT Hook 原理简述 简述 Android 是基于Linux的操作系统,因此在Android开发平台上,ELF是原生支持的可执行文件格式:ELF文件格式除了作为可执行文件,还 ...

  4. Excel阅读模式/聚光灯开发技术之二 超级逐步录入提示功能开发原理简述—— 隐鹤 / HelloWorld...

    Excel阅读模式/聚光灯开发技术之二 超级逐步录入提示功能开发原理简述---- 隐鹤  /  HelloWorld 1. 引言 自本人第一篇博文"Excel阅读模式/单元格行列指示/聚光灯 ...

  5. Spark Shuffle运行原理

    1.什么是spark shuffle? Shuffle中文意思就是"洗牌",在Spark中Shuffle的目的是为了保证每一个key所对应的value都会汇聚到同一个分区上去聚合和 ...

  6. Servlet运行原理以及生命周期

    Servlet运行原理 Servlet生命周期定义了一个Servlet如何被加载.初始化,以及它怎样接收请求.响应请求,提供服务.在讨论Servlet生命周期之前,先让我们来看一下这几个方法: 1. ...

  7. ASP.NET运行原理

    一个ASP.NET的应用程序是开始于IIS的. 当你请求一个包含ASP.NET应用的网址时,IIS接受到请求(IIS是WEB服务守候进程),IIS收到请求后,会根据请求者请求的主机头或者IP或者端口号 ...

  8. Linux X Window System运行原理和启动过程

    本文主要说明X Window System的基本运行原理,其启动过程,及常见的跨网络运行X Window System. 一) 基本运行原理 X Window System采用C/S结构,但和我们常见 ...

  9. 10分钟了解Flutter跨平台运行原理!

    导语 | 本文将从选型.简介和运行原理三大部分为你介绍Flutter的相关概念,希望能站在框架设计和实现原理的高度,带领大家去理解Flutter区别其他跨平台解决方案的关键所在. 一.为什么选择Flu ...

  10. spark on yarn 完全分布式_Spark编程笔记(1)-架构基础与运行原理

    引言 根据IBM前首席执行官郭士纳的观点,IT领域每隔十五年就会迎来一 次重大变革 .当前我们正处于第三次信息浪潮(2010年前后),物联网.云计算和大数据技术突飞猛进. 信息爆炸是我们当前所需要解决 ...

最新文章

  1. 没有好看的 Terminal 怎么能够快乐地写代码
  2. windows server 2003磁盘管理
  3. android 后台Activity移到前台
  4. Hadoop 分布式文件系统 - HDFS
  5. (acm)C++加速输入的几种方法
  6. 为什么读完博士反而逃离科研?中科院博导:因为我们的科研让人乏味!
  7. 如何构建可视化的营销数据大屏? 1
  8. [读后感]Java 控制台执行 Jar 传參的编码问题
  9. 站在巨人的肩膀上——Linux信号量操作
  10. 古诗词取名小工具1.0
  11. fw313r手机登录_迅捷fw326r路由器手机登录
  12. APISpace 尾号限行API接口 免费好用
  13. 坚果云服务器地址,坚果云第三方应用授权WebDAV开启方法
  14. 针对《评人工智能如何走向新阶段》一文,继续发布国内外的跟贴留言466-476条如下:
  15. 汇编DOS与Windows Masm编译运行代码步骤详解
  16. Unity打包篇:能够解决Unity打包Gradle遇到的所有问题方法整合!(持续更新中!)
  17. length()与lengthb()的区别
  18. 华图教育计算机基础知识,公共基础知识备考:计算机辅助制造
  19. 小白看了也能搭建物联网项目——物联网开发板——QD-mini板
  20. 虚函数与纯虚函数以及虚函数表之间的关系

热门文章

  1. 代码积累与编程能力哪个更重要
  2. 编译」(compile),与「反编译」(decompile)..哪些语言容易被反编译.
  3. VSCode : vscode-remote下无法写入文件及linux文件读写权限
  4. 闭包:学习Javascript闭包(Closure)
  5. julia: 如何序列化和反序列化?
  6. 阿里云宗志刚:云网一体,新一代洛神云网络平台
  7. ZStack跨平台迁移可以如此简单
  8. 【手势识别】基于matlab PCA+LDA手语检测识别【含Matlab源码 1551期】
  9. 如何更新计算机的flash player,如何在win7电脑中Adobe Flash Player自动更新?
  10. html让font居中,用CSS做将如何字体居中?