Archives
在LDD3上有一个例子,代码如下:
1: /* Wait for space for writing; caller must hold device semaphore. On
2: * error the semaphore will be released before returning. */
3: static int scull_getwritespace(struct scull_pipe *dev, struct file *filp)
4: {
5:
6: while (spacefree(dev) == 0)
7: { /* [...]
讨论见这里:http://lists.gnu.org/archive/html/qemu-devel/2006-11/msg00144.html
Fabrice 的回复:http://lists.gnu.org/archive/html/qemu-devel/2006-11/msg00149.html
这里还有qemu 中3D加速的讨论:http://www.mail-archive.com/qemu-devel@nongnu.org/msg15702.html
上一篇文章中,介绍了如何在google code中使用Git svn。现在又有了新问题。比如项目qemu-omap3是想往开源项目qemu中增加一个新的功能。qemu-omap3的项目hosting是在google code上面,使用Git svn来管理。而qemu在http://repo.or.cz/w/qemu.git,使用Git来管理。
为了开发qemu-omap3,需要从某一天的qemu中拿下来所有的源码,然后在这个基础上进行开发。但问题在于qemu的开发也同时在进行。这就需要qemu-omap3中的代码能保持和qemu中的同步。也就是说,我的需求如下:
1. 使用git svn来管理qemu-omap3
2. 能得到最新的qemu的代码
3. 最新的qemu的代码不影响我的qemu-omap3
之前解决的方法是定期从qemu中拿下所有的源码,然后在qemu-omap3中建立一个branch,然后拷贝过去,进行merage。这个过程比较繁琐。
实际上,可以通过git remote命令来增加一个新的remote repo。
git remote add qemu http://repo.or.cz/r/qemu.git
git fetch qemu
这会在git中自动建立一个branch qemu并且会将所有的qemu中的branch等全部放到qemu下。下面是目前我的branch。
kill-bill:/home/root/sdc/qemu/qemu-omap/svn# git-branch -a * master qemu/master qemu/svn/perso qemu/svn/tags/initial [...]
x-load本质是一个U-BOOT的精简版。为什么需要x-load这个玩意呢,而不是直接用u-boot呢?那是因为U-boot太大了,塞不进内部的RAM?那为啥要把X-LOAD塞进内部的RAM,而不是load到外部的RAM呢?
问题就在这里了。当OMAP3530上电的时候,memory controller还没有初始化,怎么去读写外部的RAM呢?必须要有人能先初始化memory controller啊。任务就交给x-Load了。它必须负责初始化外部的RAM控制器,把u-boot从NAND或者MMC中读出到外部RAM,然后跳到u-boot的入口处执行。
问题又来了,那么x-load又是由谁来load的呢?OMAP3530里面带了一个内部RAM,大小为64K。当OMAP3530上电后,会从NAND Flash或者MMC中读取x-load到内部的RAM。然后执行x-load,x-load然后执行上面所说的任务,最后把控制入口交给u-boot。
要编译x-load,先安装toolchain。然后
In file include/configs/omap3530beagle.h
/* For X-loader to be flashed on to NAND disable the below macro */ //#define CFG_CMD_MMC Comiple the x-loader as shown below make CROSS_COMPILE=arm-none-linux-gnueabi- distclean make CROSS_COMPILE=arm-none-linux-gnueabi- omap3530beagle_config [...]
相比sf,googlecode的使用更加简单和方便。虽然在功能方面没有sf多,但是对于一个开源项目来说,基本上够用了。google code的功能有wiki,下载,svn,issue report。最近googlecode的svn中又增加了一个code review的功能,也就是说别人可以浏览SVN中代码并且留下comment。详细见google的介绍:http://code.google.com/p/support/wiki/CodeReviews
虽然google提供的SVN功能不错,但是我喜欢在本地用GIT来管理我的代码。之前我的使用方法是用svn co下来一份代码,然后git建一个本地仓库,所有的代码修改log都进入本地仓库。当完成一个功能后,用svn commit进googlecode。这样做的缺点在于本地git的log不能反应到svn中。也就是说svn中的log信息都是比较粗线条的,不能很细化的反应项目的变化情况。
于是就需要请出我们今天的主角:git-svn。首先在ubuntu中安装它。
sudo apt-get install git-svn
安装完以后,需要checkout出google code svn中的东西来。
git-svn clone https://omap3emu.googlecode.com/svn -T trunk -b branches -t tags
这会在本地生成一个文件夹svn。里面就是google code svn中的东西。请记住,GIT的远端仓库和本地目录都是在一起的。我们来看一下目前的GIT仓库中有哪些branch。
目前以shared source发布的device emulator的版本是v1,我手头的版本也就是这个版本。在MSDN的这篇文章中,Barry给出了device emulator的V2版本对于V1的改进的地方。通过这些改进,模拟速度的提升达到40%!
1. TLB 查找的优化
我们知道在带有MMU的ARM中,当访问memory的时候,需要先将虚拟地址转换成物理地址。这涉及到查TLB和页表的过程。如果能在TLB中找到表项,则不用去页表中进行查找。
在V1中,实现了TLB的查找。整个TLB的表项有64个。在硬件实现中,TLB的查找是并行的,而对于emulator来说,查找是线性的。最坏的情况需要遍历整个64个entry。因此,如果能够快速的寻找到TLB表项,无疑对于性能是一个很大的帮助。
根据程序的memory访问具有相关性(locality)的特点(也就是说,下一次访问的memory地址和上一次访问的memory地址不会相差太远),因此,在进行TLB查找的时候,总是从上一次查找成功的那个TLB Slot开始查找,而不是从TLB 表项0开始查找。
但这仍然有一个问题,最坏的情况下,仍然是线性搜索64个entry。V2做了一个改进,将线性的搜索变为hash搜索。这样,在最坏的情况下,不用遍历整个64个entry。不过具体的hash算法并没有给出。
2. Interrupt polling
这个也比较有意思。对于emulator来说,interrupt的产生是异步的,因此emulator是需要不断polling interrupt的状态。如果有interrupt pending,必须修改guest的PC,使得guest跳到异常处理程序的地方继续执行。
根据我之前开发emulator的经验,会在emulator的JIT生成的X86汇编中阶段性的去polling interrupt的状态。比如
if (g_fInterruptPending) {
SimulateHardwareInterrupt();
}
也就是说,JIT生成的X86代码需要非常多的MOV/CMP/BRANCH的序列。而在V2中,将interrupt polling 改成
void SimulateHardwareInterruptIfPending(void)
{ /* note: no code here */
}
这个函数是一个空函数。让有中断产生的时候,会patch这个函数,将这个函数变成RET到中断处理函数的地址。 这样就可以省掉MOV/CMP/BRANCH的序列。其实还可以减少translated后的代码大小。
3. 优化memcpy和memset.
emulator能识别出guest的memcpy和memset,把它变成手工优化的X86代码。
如何识别memcpy和memset,没有讲明。我想应该和所使用的 libc库以及compiler有关。
4. 窥孔优化
对IR进行窥孔优化。
str r0, [sp+10]
ldr r3, [sp+10]
变成
str r0, [sp+10]
mov r0, r3
5. 一次尽可能多的去ARM指令
也就是一次去指令的时候,至少应该可以取1K的指令。而不用每一次取指令的时候都去跑完整个memory load(guest虚拟地址->TLB->[页表->]guest物理地址->host虚拟地址->取指令)的整个过程。这个优化方法在dynamips和virtualmips中也有应用。
6. Reduce x86 processor stalls due to mixed code and data
这个应该是X86处理器相关的。不具体介绍了。
其实这些优化方面都不是很难,但是取得的性能提升确实显著的:40%。看来我要多学学怎么用工具来寻找程序的瓶颈,如何去优化。特别对于emulator来说,性能是非常非常关键的。
计划一个新的项目omap3emu:OMAP3的emulator。
等会等会,怎么又要做一个emulator啊?现在的emulator已经够多的了。
确实。qemu,skyeye,armware都有非常不错的ARM支持。其中以qemu的支持最为广泛。那么为什么还需要omap3emu呢?
1. 虽然已经有蛮多的ARM Emulator,但是,还没有能模拟ARM V7架构的Opensource的emulator。
2. 在上一篇文章中也提到,通过这个模拟器,可以进一步熟悉了解ARM的体系结构,为Lguest移植到ARM打下基础。我认为,学习一个新的体系结构最好的方法就是写一个emulator。
3. QEMU的执行速度虽然很快,但是由于其采用了JIT的方法来生成代码,导致不能了解每一步的代码执行情况,或者说debug的时候,比较困难。而 omap3emu打算先提供一个step by step的解释型的执行引擎,虽然很慢,但是对于调试emulator本身和上面的软件都是比较方便的。
4. 打算通过这个omap3emu来验证<虚拟机-系统与进程的通用平台>中介绍的各种优化方法到底有多大的用途,能获得多大的性能提升。在目前硬件发展越来越快的今天,也许其中所介绍的优化方法已经不再适用。
5. omap3emu作为移植lguest到OMAP3上面的前期工具。
6. 3D虚拟化方面的尝试。目前,多数的Emulator对于显卡的处理方式多为模拟。尝试采用虚拟化的方式来加速emulator中guest的3D/2D应用。 GUEST 3D/2D Application -- 虚拟化 -- host的3D加速。
omap3emu需要能在Linux和XP上运行,采用SDL作为LCD的模拟。编译系统采用scons。
编译器: Linux:gcc XP: VS2008 Express edition
项目的主页在googlecode上面。
目前的重点还是放在了qemu-omap3上面。从头开始做omap3emu 所需要的时间/精力太大。不是我目前能承受的。
最近几天一直在分析device emulator的源代码(采用Share Source发布)。为了看一下其运行的效果,因此打算编译运行device emulator。
首先下载device emulator。 下载地址
在device emulator的doc中给出了编译的方法。
首先需要下载 zlib-1.2.3,解压后放到features\zlib中,然后下载 libpng 1.2.8,解压到 features\libpng中。
推荐的编译环境是vs2005。编译的过程很简单,图形化的用户界面。编译完成后会在release中生成DeviceEmulator.exe。
下载 Windows Mobile 5.0 Emulator Images for Smartphone,用MSI文件提取器提出其中的BIN文件。文件在目录 Windows Mobile 5_EXT\Windows Mobile 5.0 Emulator Images for Smartphone - CHS\Deviceemulation\0804下。分别为 SP_CHS_GSM_QVGA_VR.bin和SP_CHS_GSM_VR.bin。搞不清楚这个两个文件有什么区别。
1. qemu
http://bellard.org/qemu/
首先当然是大名鼎鼎的qemu了。Qemu目前能支持的指令集包括ARM/MIPS/PPC/X86等等。最新的版本是发布于2008年1月6日的0.9.1。对于ARM来说,目前的SVN的版本中(2008-10-07)支持的SOC/machine包括:
integratorcp: ARM Integrator/CP (ARM926EJ-S)
versatilepb: ARM Versatile/PB (ARM926EJ-S)
versatileab: ARM Versatile/AB (ARM926EJ-S)
realview: ARM RealView Emulation Baseboard (ARM926EJ-S)
akita: Akita PDA (PXA270)
spitz: Spitz PDA (PXA270)
borzoi: Borzoi PDA (PXA270)
terrier: Terrier PDA (PXA270)
cheetah: Palm Tungsten|E aka. Cheetah PDA (OMAP310)
n800: Nokia N800 tablet aka. RX-34 (OMAP2420)
n810: Nokia N810 tablet aka. RX-44 [...]
写一个 from emulation to virtualization 的文章的计划很早就在我的大脑中盘旋。可是要写这样的一个文章,需要比较深的积累。
之前在尝试移植lguest到MIPS平台,虽然后来放弃了这个努力,但是仍然积累了一些经验。同时也明白,要想写一个virtualization之类的东西,对于ARM/MIPS的深刻了解是必不可少的。
在选择ARM还是MIPS作为文章的平台上,一直在考虑和权衡。最终还是选择ARM。这是因为(1)我想做的是嵌入式的virtualization,而 ARM又是嵌入式和手持设备中使用最为广泛的平台。(2)我对ARM平台还不是非常了解,而借此机会,可以深刻了解ARM平台。而不仅仅把自己局限在 MIPS平台上。从目前我了解的情况来看,MIPS相比ARM比较简单。而ARM的设计更为复杂,也更为灵活。不仅仅是单纯的RISC的理念。
为了实现这个目标,大约分为以下几个步骤进行。
写一个解释型的ARM SOC的模拟器。目标:深刻理解ARM结构
验证书上所提到的emulation的优化方法进行优化,得出每一种优化的效率。并做整理。作为短期目标的文章发布。
JIT。目标是移植一个通用的JIT框架。从ARM->中间表示->优化->host。而这一部分也可以写一些文章。
移植lguest到ARM中。在这一过程中,需要权衡每一种设计方案,比较在ARM中设计虚拟化和X86的不同。
在lguest中运行一些benchmark,看看有哪些可以优化的地方。
仿照INTEL VT对ARM的指令集进行扩展
由于实现的模拟器的作用是用来作为example,因此,该模拟器的结构不要太复杂,代码量不要太大。基本上在1W行以内( 不包括JIT部分)。
模拟器的SOC初步定为OMAP3系列。原因在于有良好的文档和工具。模拟的板子为beagle borad,以后可以加入V哥的OPENOMAP。DSP扩展和3D加速的模拟作为低优先级任务。
整个计划的时间大约在6个月左右。也就是2008-10到2009-3月左右。
Recent Comments