Gexmul虚拟机内存空间原理简述

Gxemul将内存空间分为两部分管理,一部分是物理内存,地址分配到0x00000000,另一部分是device的地址,注册device的时候由device自己指定空间

1 创建物理内存

memory.cc memory_new
{
    初始化物理内存参数
    mem->physical_max = physical_max;
    mem->dev_dyntrans_alignment = 4095;
    创建物理内存
    mem->pagetable = (unsigned char *) mmap(NULL, s,
	    PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
	if (mem->pagetable == NULL) {
		CHECK_ALLOCATION(mem->pagetable = malloc(s));
		memset(mem->pagetable, 0, s);
	}
    
    初始化device可占用的地址空间
    mem->mmap_dev_minaddr = 0xffffffffffffffffULL;
    mem->mmap_dev_maxaddr = 0;
}

2 内存地址转换

?在cpu_new时已经将v2p_translate设置为translate_v2p_mmu3k,translate_v2p_mmu3k在memory_mips.cc中生成?

#define TRANSLATE_ADDRESS        translate_v2p_mmu3k
#define  V2P_MMU3K
#include "memory_mips_v2p.cc"
#undef TRANSLATE_ADDRESS
#undef V2P_MMU3K

int TRANSLATE_ADDRESS(struct cpu *cpu, uint64_t vaddr, uint64_t *return_paddr, int flags)
{
           //获取cpu所在状态
           cp0 = cpu->cd.mips.coproc[0];
           status = cp0->reg[COP0_STATUS];
           if (status & MIPS1_SR_KU_CUR)
                         ksu = KSU_USER;
           else
                         ksu = KSU_KERNEL;
        //32bit判断
        if (x_64 == 0) {
            vaddr = (int32_t) vaddr;
            xuseg_top = 0x7fffffff;
            /*  (Actually useg for R2000/R3000)  */
           }
 
        if (vaddr <= xuseg_top) {
            KUSEG: 低2G必须使用MMU
            use_tlb = 1;
           } else {
               if (ksu == KSU_KERNEL) {
                内核态,直接取低512M
                   /*  kseg0, kseg1:  */
                   if (vaddr >= (uint64_t)0xffffffff80000000ULL &&
                       vaddr <= (uint64_t)0xffffffffbfffffffULL) {
                           *return_paddr = vaddr & 0x1fffffff;
                           return 2;
                   }
                   /*  other segments:  KSEG2 必须使用MMU*/
                   use_tlb = 1;
               } else {
                        不是内核态,但访问了对应的地址,将会产生excption
                        use_tlb = 0;
                 }
           }
           if (use_tlb)
           {
                使用MMU
           }
           
           //内存地址excption
           mips_cpu_exception(cpu, exccode, tlb_refill, vaddr, 0, vaddr_vpn2, vaddr_asid, x_64);
}

3 注册device占用内存空间

device需要内存空间用于安排自己的寄存器和FIFO等

memory.cc memory_device_register
{
    //查找注册的地址是否可用
    for (i=0; i<mem->n_mmapped_devices; i++) {
		if (i == 0 && baseaddr + len <= mem->devices[i].baseaddr)
			newi = i;
		if (i > 0 && baseaddr + len <= mem->devices[i].baseaddr &&
		    baseaddr >= mem->devices[i-1].endaddr)
			newi = i;
		if (i == mem->n_mmapped_devices - 1 &&
		    baseaddr >= mem->devices[i].endaddr)
			newi = i + 1;

		/*  If this is not colliding with device i, then continue:  */
		if (baseaddr + len <= mem->devices[i].baseaddr)
			continue;
		if (baseaddr >= mem->devices[i].endaddr)
			continue;

		fatal("\nERROR! \"%s\" collides with device %i (\"%s\")!\n",
		    device_name, i, mem->devices[i].name);
		exit(1);
	}
    注册device内存空间信息及访问函数
    mem->devices[newi].baseaddr = baseaddr;
    mem->devices[newi].endaddr = baseaddr + len;
    mem->devices[newi].length = len;
    mem->devices[newi].flags = flags;
    mem->devices[newi].dyntrans_data = dyntrans_data;
    mem->devices[newi].dyntrans_write_low = (uint64_t)-1;
    mem->devices[newi].dyntrans_write_high = 0;
    mem->devices[newi].f = f;
    mem->devices[newi].extra = extra;
    mem->devices[newi].m = NULL;
    
    //更新device内存空间范围
    if (baseaddr < mem->mmap_dev_minaddr)
	mem->mmap_dev_minaddr = baseaddr & ~mem->dev_dyntrans_alignment;
    if (baseaddr + len > mem->mmap_dev_maxaddr)
	mem->mmap_dev_maxaddr = (((baseaddr + len) - 1) | mem->dev_dyntrans_alignment) + 1;
}

4 访问内存

mips_memory_rw 由generate_tail.c 自动生成的tmp_mips_tail.c结合mempry_rw.cc产生:

#define MEMORY_RW mips_memory_rw
#define MEM_MIPS
#include "memory_rw.cc"
#undef MEM_MIPS
#undef MEMORY_RW

memory_rw.cc  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int misc_flags)
{
    计算出要访问的物理地址
    cpu->translate_v2p(cpu, vaddr, &paddr,
        (writeflag? FLAG_WRITEFLAG : 0) +
        (no_exceptions? FLAG_NOEXCEPTIONS : 0)
         + (misc_flags & MEMORY_USER_ACCESS)
         + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0))
         if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr)
         {
            属于device的地址,在device中寻找,device地址在memory_device_register已经注册,找到后使用注册的device access函数访问
         }
         
         if (paddr >= mem->physical_max)
         {
            不在物理内存中,属于PROM不做处理
            if ((paddr & 0xffffc00000ULL) == 0x1fc00000) {
                /*  Ok, this is PROM stuff  */
            }
         }
        //转换为虚拟机中的内存地址
        memblock = memory_paddr_to_hostaddr(mem, paddr & ~offset_mask, writeflag);
        
        获取对应数据,并做读写操作
        cpu->update_translation_table
        cpu->invalidate_code_translation
        if (writeflag == MEM_WRITE)
           memcpy(memblock + offset, data, len);
        else
           memcpy(data, memblock + offset, len);
}

Gexmul虚拟机内存空间原理简述

时间: 2024-10-04 08:45:29

Gexmul虚拟机内存空间原理简述的相关文章

Java虚拟机内存管理原理基础入门

Jdk:Java程序设计语言.Java虚拟机.Java API类库. Jdk是用于支持Java程序开发的最小环境. Jre:Java API类库中的Java SE API子集.Java虚拟机. Jre是支持Java程序运行的标准环境. Program Counter Register:较小的内存空间,可以看作当前线程所执行的字节码的行号指示器.是唯一一个Java虚拟机规范中没有规定OutOfMemoryError的区域. VM Stack:生命周期和线程相同,它描述了Java方法执行的内存模型:

打包apk java 虚拟机内存不足

解决方案:在android->sdk->build-tools-android-version 中有个 dx.bat dx.bat --dex 命令的dx.bat脚本有这样一句代码 REM By default, give dx a max heap size of 1 gig and a stack size of 1meg. rem This can be overridden by using "-JXmx..." and "-JXss..." o

JVM工作原理 - 内存空间

大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) ,   VM Stack(虚拟机栈,也有翻译成JAVA 方法栈的),Native Method Stack  ( 本地方法栈 ),其中Method Area 和  Heap 是线程共享的  ,VM Stack,Native Method Stack  和Program Counter Register  是非线程共享的.为什

java内存空间简述

JVM的内存空间: 1. 寄存器 (Registers):最快的保存区域,位于处理器内部,由编译器分配.主要作用是记录当前线程所执行的字节码的行号.字节码解释器工作时就是通过改变当前线程的程序计数器选取下一条字节码指令来工作.任何分支.循环.方法调用.判断.异常处理.线程等待以及恢复线程.递归等都是通过这个计数器来完成.为了多线程的实现,每条线程都会有独立的程序计数器来记录当前指令的行号,以使得线程等待结束后能恢复到正确的位置执行.这块内存也被称为"线程私有"的内存.如果调用的方法是n

java中JVM虚拟机内存模型详细说明

java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03|  分类: JAVA |  标签:java  jvm  堆内存  虚拟机  |举报|字号 订阅 JVM的内部结构如下图: 一个优秀Java程序员,必须了解Java内存模型.GC工作原理,以及如何优化GC的性能.与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能提高整个应用程序的性能. 本文将从JVM内存模型.GC工作原理,以及GC的几个关键问题进行探讨,从

探秘Java虚拟机——内存管理与垃圾回收

详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt106 1.Java虚拟机运行时的数据区 2.常用的内存区域调节参数 -Xms:初始堆大小,默认为物理内存的1/64(<1GB):默认(MinHeapFreeRatio参数可以调整)空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制 -Xmx:最大堆大小,默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小

erlang虚拟机代码执行原理

erlang是开源的,很多人都研究过源代码.但是,从erlang代码到c代码,这是个不小的跨度,而且代码也比较复杂.所以这里,我利用一些时间,整理下erlang代码的执行过程,从erlang代码编译过程,到代码执行过程做讲解,然后重点讲下虚拟机执行代码的原理.将本篇文章,献给所有喜欢erlang的人. erlang代码编译过程 erlang对开发者是友好的,从erlang程序文件编译成能被erlang虚拟机识别的beam文件,在这个编译过程还对开发者暴露中间代码.借助这个中间代码,我们就可以逐步

【转】java虚拟机内存原型

本文主要通过分析Java内存分配的栈.堆以以及常量池详细的讲解了其的工作原理. 一.java虚拟机内存原型 寄存器:我们在程序中无法控制栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中堆:存放用new产生的数据静态域:存放在对象中用static定义的静态成员常量池:存放常量非RAM存储:硬盘等永久存储空间. 二.常量池(constant pool) 常量池指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据.除了包含代码中所定义的各种基本类型(如int.

转 Linux内存管理原理

Linux内存管理原理 在用户态,内核态逻辑地址专指下文说的线性偏移前的地址Linux内核虚拟3.伙伴算法和slab分配器 16个页面RAM因为最大连续内存大小为16个页面 页面最多16个页面,所以16/2order(0)bimap有8个bit位两个页框page1 与page2组成与两个页框page3 与page4组成,这两个块之间有一个bit位 order(1)bimap有4个bit位order(2)bimap有4个bit位的2个页面分配过程 当我们需要order(1)的空闲页面块时,orde