qemu tcg mmp分析

864 /* NOTE: this function can trigger an exception */
 865 /* NOTE2: the returned address is not exactly the physical address: it
 866  * is actually a ram_addr_t (in system mode; the user mode emulation
 867  * version of this function returns a guest virtual address).
 868  */
 869 tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
 870 {
 871     int mmu_idx, index, pd;
 872     void *p;
 873     MemoryRegion *mr;
 874     CPUState *cpu = ENV_GET_CPU(env);
 875     CPUIOTLBEntry *iotlbentry;
 876     hwaddr physaddr;
 877
 878     index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
 879     mmu_idx = cpu_mmu_index(env, true);
 880     if (unlikely(env->tlb_table[mmu_idx][index].addr_code !=
 881                  (addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK)))) {
 882         if (!VICTIM_TLB_HIT(addr_read, addr)) {
 883             tlb_fill(ENV_GET_CPU(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0);
 884         }
 885     }
 886     iotlbentry = &env->iotlb[mmu_idx][index];
 887     pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
 888     mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
 889     if (memory_region_is_unassigned(mr)) {
 890         qemu_mutex_lock_iothread();
 891         if (memory_region_request_mmio_ptr(mr, addr)) {
 892             qemu_mutex_unlock_iothread();
 893             /* A MemoryRegion is potentially added so re-run the
 894              * get_page_addr_code.
 895              */
 896             return get_page_addr_code(env, addr);
 897         }
 898         qemu_mutex_unlock_iothread();
 899
 900         /* Give the new-style cpu_transaction_failed() hook first chance
 901          * to handle this.
 902          * This is not the ideal place to detect and generate CPU
 903          * exceptions for instruction fetch failure (for instance
904          * we don't know the length of the access that the CPU would
 905          * use, and it would be better to go ahead and try the access
 906          * and use the MemTXResult it produced). However it is the
 907          * simplest place we have currently available for the check.
 908          */
 909         physaddr = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
 910         cpu_transaction_failed(cpu, physaddr, addr, 0, MMU_INST_FETCH, mmu_idx,
 911                                iotlbentry->attrs, MEMTX_DECODE_ERROR, 0);
 912
 913         cpu_unassigned_access(cpu, addr, false, true, 0, 4);
 914         /* The CPU's unassigned access hook might have longjumped out
 915          * with an exception. If it didn't (or there was no hook) then
 916          * we can't proceed further.
 917          */
 918         report_bad_exec(cpu, addr);
 919         exit(1);
 920     }
 921     p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
 922     return qemu_ram_addr_from_host_nofail(p);
 923 }

这个函数的参数CPUArchState 为当前cpu的状态,记录了当前cpu的寄存器,tlb等状态。 参数addr为一个虚拟地址,这个函数就是要找到该虚拟地址的对应的主机虚拟地址

转化的过程
guest 虚拟地址(GVD) -> guest 物理地址(GPD) -> host 虚拟地址(HVD)
后面都使用GVD,GPD,HVD代表这三种地址

为什么要这么转化呢, 因为真正的数据存在HVD里面,我们要访问到虚拟机的系统里的数据/代码就是通过HVD。(访问到这些数据,代码就能进行翻译执行了)

878-885行首先在tlb中找到虚拟地址对应的索引(tlb的作用就是缓存虚拟地址->物理地址的映射)如果tlb中没有对应页面的索引,则使用tlb_fill进行填充
888 行找到对应的MemoryRegion。
889-898行如果这个MemoryRegion是为定义的区域,则使用memory_region_request_mmio_ptr来创建该区域。区域创建好后重新使用get_page_addr_code来进行地址转换。
899-919行是异常情况,我们不分析
922行 qemu_ram_addr_from_host_nofail 转换gpa到hpa

发布了113 篇原创文章 · 获赞 22 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/woai110120130/article/details/100626368
mmp