日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Mips KVM TrapEmulate implemented in Linux

發(fā)布時間:2025/3/15 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mips KVM TrapEmulate implemented in Linux 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

基本原理

Trap&Emulate,即陷入&模擬的方式,是純軟件實現(xiàn)的全虛擬化方案,基本不借助硬件虛擬化功能。本文主要關(guān)注內(nèi)存虛擬化實現(xiàn)中的核心,TLB miss相關(guān)實現(xiàn)。基本原理是:

所有的TLB miss都將導(dǎo)致Guest退出到VMM處理,然后在VMM中進行相應(yīng)模擬。

具體實現(xiàn)原理描述如下:

  • 當(dāng)前內(nèi)核版本(4.9)的實現(xiàn)方式定義了2中TLB:

    • Guest TLB。由Guest OS維護,用于映射GVA->GPA,本質(zhì)為一段內(nèi)存,用于模擬TLB,虛擬TLB,并不真實存在。該TLB不會被Guest OS直接使用,只用于生成Shadow TLB。Guest OS 在維護Guest TLB時,對 TLB 的讀寫指令會被虛擬機管理器(virtual machine monitor, VMM)捕捉并模擬,使 Guest OS 認為成功讀寫了硬件 TLB。
    • Shadow Host TLB,也是Host使用的物理TLB。由VMM(即Host維護)。對于Guest來說,用于映射GVA->HPA,對于Host來說,用于映射HVA->HPA。
  • Guest最終通過Shadow Host TLB中的條目實現(xiàn)GVA到HPA的轉(zhuǎn)換,GPA->HPA的映射通過線性映射表實現(xiàn)。

  • Guest中,任何TLB相關(guān)的操作都將觸發(fā)異常。

Guest OS做訪存操作時有如下幾中情況發(fā)生:

  • Shadow Host TLB(即硬件TLB)中剛好有該GVA到HPA的映射,此時不會發(fā)生異常,硬件TLB直接翻譯地址,正常訪問。
  • 如果硬件TLB中不存在相應(yīng)映射條目,觸發(fā)TLB Miss異常。此時退出到VMM中進行處理。
    • VMM先遍歷Guest TLB,如果找到相應(yīng)條目,則將Guest TLB中翻譯后的GPA轉(zhuǎn)換為HPA,然后填入Shadow Host TLB(硬件TLB),并返回Guest OS繼續(xù)運行。
    • 如果Guest TLB中沒有找到,則向Guest OS中注入TLB Load/Store異常(由Guest OS負責(zé)重填Guest TLB),然后填入Shadow Host TLB(硬件TLB),并返回Guest OS繼續(xù)運行。
    • 當(dāng)Guest得到調(diào)度運行時,TLB Load/Store異常(General異常)入口,最終會進入page fault相關(guān)流程,完成Guest TLB重填。
    • 重填TLB時,會調(diào)用類似TLBWR之類的之令,此時會再次觸發(fā)VM-Exit,VMM通過捕獲該異常,其中填入虛擬的Guest TLB、flust相應(yīng)的Shadow Host TLB條目,然后返回Guest OS繼續(xù)執(zhí)行。
  • 代碼實現(xiàn)

    kvm_mips_handle_tlbmiss

    tlbmiss異常通用入口,在如下兩種情況下發(fā)生:

  • TLB Entry在Guest TLB和shadow host TLB中都不存在。這種情況下,將相應(yīng)異常注入Guest中,由Guest自己處理。
  • TLB Entry在Guest TLB中存在,但在shadow host TLB中不存在。這種情況下,由VMM根據(jù)Guest TLB中的相應(yīng)Entry填充shadow host TLB。
  • 主要處理邏輯:

    • 查找Guest TLB中是否存在相應(yīng)entry;
    • 如果存在,則調(diào)用kvm_mips_handle_mapped_seg_tlb_fault填充shadow Host TLB(即物理TLB);
    • 如果不存在,則根據(jù)exccode向Guest中注入相應(yīng)的異常,比如TLB miss load異常,接口如kvm_mips_emulate_tlbmiss_ld。

    具體代碼實現(xiàn)如下:

    enum emulation_result kvm_mips_handle_tlbmiss(u32 cause,u32 *opc,struct kvm_run *run,struct kvm_vcpu *vcpu) {enum emulation_result er = EMULATE_DONE;/* 讀取異常類型碼 */u32 exccode = (cause >> CAUSEB_EXCCODE) & 0x1f;/* 獲取發(fā)送tlbmiss的地址,為GVA地址 */unsigned long va = vcpu->arch.host_cp0_badvaddr;int index;kvm_debug("kvm_mips_handle_tlbmiss: badvaddr: %#lx\n",vcpu->arch.host_cp0_badvaddr);/** KVM would not have got the exception if this entry was valid in the* shadow host TLB. Check the Guest TLB, if the entry is not there then* send the guest an exception. The guest exc handler should then inject* an entry into the guest TLB.*//* 查找Guest TLB(本質(zhì)為一段內(nèi)存,虛擬TLB,并不真實存在),確認是否存在 */index = kvm_mips_guest_tlb_lookup(vcpu,(va & VPN2_MASK) |(kvm_read_c0_guest_entryhi(vcpu->arch.cop0) &KVM_ENTRYHI_ASID));/* 不存在 */if (index < 0) {/* 根據(jù)異常類型碼向Guest中注入不同的異常 */if (exccode == EXCCODE_TLBL) {/* TLB load異常 */er = kvm_mips_emulate_tlbmiss_ld(cause, opc, run, vcpu);} else if (exccode == EXCCODE_TLBS) {/* TLB set異常 */er = kvm_mips_emulate_tlbmiss_st(cause, opc, run, vcpu);} else {kvm_err("%s: invalid exc code: %d\n", __func__,exccode);er = EMULATE_FAIL;}} else {/* 如果在guest TLB中找到相應(yīng)條目 *//* 獲取相應(yīng)條目 */struct kvm_mips_tlb *tlb = &vcpu->arch.guest_tlb[index];/** Check if the entry is valid, if not then setup a TLB invalid* exception to the guest*//* 檢查條目是否可用,不可用,則再注入TLB相應(yīng)異常 */if (!TLB_IS_VALID(*tlb, va)) {if (exccode == EXCCODE_TLBL) {er = kvm_mips_emulate_tlbinv_ld(cause, opc, run,vcpu);} else if (exccode == EXCCODE_TLBS) {er = kvm_mips_emulate_tlbinv_st(cause, opc, run,vcpu);} else {kvm_err("%s: invalid exc code: %d\n", __func__,exccode);er = EMULATE_FAIL;}} else { /* 條目可用,則填充Host TLB */kvm_debug("Injecting hi: %#lx, lo0: %#lx, lo1: %#lx into shadow host TLB\n",tlb->tlb_hi, tlb->tlb_lo[0], tlb->tlb_lo[1]);/** OK we have a Guest TLB entry, now inject it into the* shadow host TLB*//* Host TLB的實際填充操作在kvm_mips_handle_mapped_seg_tlb_fault函數(shù)中完成*/if (kvm_mips_handle_mapped_seg_tlb_fault(vcpu, tlb)) {kvm_err("%s: handling mapped seg tlb fault for %lx, index: %u, vcpu: %p, ASID: %#lx\n",__func__, va, index, vcpu,read_c0_entryhi());er = EMULATE_FAIL;}}}return er;}

    kvm_mips_emulate_tlbmiss_ld

    實現(xiàn)向Guest中注入TLB load異常,本質(zhì)為:

    設(shè)置CP0 Status中的ST0_EXL,然后將PC指向General異常的處理入口,Guest得到調(diào)度即可直接跳轉(zhuǎn)到異常入口執(zhí)行,實現(xiàn)異常注入。

    enum emulation_result kvm_mips_emulate_tlbinv_ld(u32 cause,u32 *opc,struct kvm_run *run,struct kvm_vcpu *vcpu) {struct mips_coproc *cop0 = vcpu->arch.cop0;struct kvm_vcpu_arch *arch = &vcpu->arch;unsigned long entryhi =(vcpu->arch.host_cp0_badvaddr & VPN2_MASK) |(kvm_read_c0_guest_entryhi(cop0) & KVM_ENTRYHI_ASID);/** 讀取Guest C0中Status寄存器,判斷ST0_EXL(標(biāo)識當(dāng)前是否已經(jīng)處于異常狀態(tài),* 如果已經(jīng)是,且再次觸發(fā)tlbmiss異常,此時不會重入,而會觸發(fā)General異常,* 即TLB load異常,也可以理解成X86中的缺頁異常),如果沒有設(shè)置,則需要進行* 相應(yīng)設(shè)置,以便能向Guest中注入TLB load異常 */if ((kvm_read_c0_guest_status(cop0) & ST0_EXL) == 0) {/* save old pc */kvm_write_c0_guest_epc(cop0, arch->pc);/* 設(shè)置ST0_EXL標(biāo)記 */kvm_set_c0_guest_status(cop0, ST0_EXL);if (cause & CAUSEF_BD)kvm_set_c0_guest_cause(cop0, CAUSEF_BD);elsekvm_clear_c0_guest_cause(cop0, CAUSEF_BD);kvm_debug("[EXL == 0] delivering TLB INV @ pc %#lx\n",arch->pc);/* set pc to the exception entry point *//** 設(shè)置當(dāng)前的PC指針指向General異常的處理入口,這樣,當(dāng)Guest得到調(diào)度* 時,就能直接進入General異常處理流程中,其中會最終走到page fault* 相關(guān)流程,之前的文章中有相應(yīng)的原理描述*/arch->pc = KVM_GUEST_KSEG0 + 0x180;} else {/* 如果已經(jīng)設(shè)置了ST0_EXL標(biāo)記,則直接修改PC指針即可 */kvm_debug("[EXL == 1] delivering TLB MISS @ pc %#lx\n",arch->pc);arch->pc = KVM_GUEST_KSEG0 + 0x180;}/* 寫入EXCCODE為TLBL */kvm_change_c0_guest_cause(cop0, (0xff),(EXCCODE_TLBL << CAUSEB_EXCCODE));/* setup badvaddr, context and entryhi registers for the guest */kvm_write_c0_guest_badvaddr(cop0, vcpu->arch.host_cp0_badvaddr);/* XXXKYMA: is the context register used by linux??? */kvm_write_c0_guest_entryhi(cop0, entryhi);/* Blow away the shadow host TLBs */kvm_mips_flush_host_tlb(1);return EMULATE_DONE; }

    kvm_mips_handle_mapped_seg_tlb_fault

    主要完成任務(wù):根據(jù)Guest TLB中的entry,填充Host TLB中相應(yīng)條目。

    int kvm_mips_handle_mapped_seg_tlb_fault(struct kvm_vcpu *vcpu,struct kvm_mips_tlb *tlb) {unsigned long entryhi = 0, entrylo0 = 0, entrylo1 = 0;struct kvm *kvm = vcpu->kvm;kvm_pfn_t pfn0, pfn1;gfn_t gfn0, gfn1;long tlb_lo[2];int ret;tlb_lo[0] = tlb->tlb_lo[0];tlb_lo[1] = tlb->tlb_lo[1];/** The commpage address must not be mapped to anything else if the guest* TLB contains entries nearby, or commpage accesses will break.*/if (!((tlb->tlb_hi ^ KVM_GUEST_COMMPAGE_ADDR) &VPN2_MASK & (PAGE_MASK << 1)))tlb_lo[(KVM_GUEST_COMMPAGE_ADDR >> PAGE_SHIFT) & 1] = 0;/* 獲取gfn */gfn0 = mips3_tlbpfn_to_paddr(tlb_lo[0]) >> PAGE_SHIFT;gfn1 = mips3_tlbpfn_to_paddr(tlb_lo[1]) >> PAGE_SHIFT;if (gfn0 >= kvm->arch.guest_pmap_npages ||gfn1 >= kvm->arch.guest_pmap_npages) {kvm_err("%s: Invalid gfn: [%#llx, %#llx], EHi: %#lx\n",__func__, gfn0, gfn1, tlb->tlb_hi);kvm_mips_dump_guest_tlbs(vcpu);return -1;}/** 建立gfn和pfn的映射關(guān)系,本質(zhì)是通memslot中獲取對應(yīng)關(guān)系,然后設(shè)置guest_pmap線性* 映射數(shù)組,后面使用*/if (kvm_mips_map_page(kvm, gfn0) < 0)return -1;if (kvm_mips_map_page(kvm, gfn1) < 0)return -1;/* 獲取pfn */pfn0 = kvm->arch.guest_pmap[gfn0];pfn1 = kvm->arch.guest_pmap[gfn1];/* Get attributes from the Guest TLB *//* 從Guest TLB中獲取entrylo0、entrylo1、entryhi等關(guān)鍵信息,以便于后續(xù)將其寫入Host TLB */entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) |((_page_cachable_default >> _CACHE_SHIFT) << ENTRYLO_C_SHIFT) |(tlb_lo[0] & ENTRYLO_D) |(tlb_lo[0] & ENTRYLO_V);entrylo1 = mips3_paddr_to_tlbpfn(pfn1 << PAGE_SHIFT) |((_page_cachable_default >> _CACHE_SHIFT) << ENTRYLO_C_SHIFT) |(tlb_lo[1] & ENTRYLO_D) |(tlb_lo[1] & ENTRYLO_V);kvm_debug("@ %#lx tlb_lo0: 0x%08lx tlb_lo1: 0x%08lx\n", vcpu->arch.pc,tlb->tlb_lo[0], tlb->tlb_lo[1]);preempt_disable();entryhi = (tlb->tlb_hi & VPN2_MASK) | (KVM_GUEST_KERNEL_MODE(vcpu) ?kvm_mips_get_kernel_asid(vcpu) :kvm_mips_get_user_asid(vcpu));/* 將TLB Entry信息寫入Host TLB,即物理TLB */ret = kvm_mips_host_tlb_write(vcpu, entryhi, entrylo0, entrylo1,tlb->tlb_mask);preempt_enable();return ret; }

    kvm_mips_map_page

    建立gfn和pfn的映射關(guān)系,本質(zhì)是通memslot中獲取對應(yīng)關(guān)系,然后設(shè)置guest_pmap線性映射數(shù)組

    static int kvm_mips_map_page(struct kvm *kvm, gfn_t gfn) {int srcu_idx, err = 0;kvm_pfn_t pfn;/* 已經(jīng)存在映射 */if (kvm->arch.guest_pmap[gfn] != KVM_INVALID_PAGE)return 0;srcu_idx = srcu_read_lock(&kvm->srcu);/* 將gfn轉(zhuǎn)換為pfn,通過memslot實現(xiàn),kvm標(biāo)準(zhǔn)接口 */pfn = gfn_to_pfn(kvm, gfn);if (is_error_noslot_pfn(pfn)) {kvm_err("Couldn't get pfn for gfn %#llx!\n", gfn);err = -EFAULT;goto out;}/* 填入映射關(guān)系 */kvm->arch.guest_pmap[gfn] = pfn; out:srcu_read_unlock(&kvm->srcu, srcu_idx);return err; } 原文地址: https://happyseeker.github.io/kernel/2017/01/11/Mips-KVM-Trap&E-implement.html

    總結(jié)

    以上是生活随笔為你收集整理的Mips KVM TrapEmulate implemented in Linux的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 丰满少妇在线观看网站 | av手机 | 91午夜免费视频 | 国产精品久久久99 | 久久九九免费视频 | 99国产精品久久久久久久 | 新狠狠干 | 午夜影院 | 波多野结衣在线免费观看视频 | 最好看的mv中文字幕国语电影 | 亚洲九色 | 播五月婷婷 | 臭脚猛1s民工调教奴粗口视频 | 亚洲永久精品一区二区 | 国产激情无套内精对白视频 | 善良的公与媳hd中文字 | 国产哺乳奶水91在线播放 | 少妇一级淫片免费看 | 久久av高潮av无码av喷吹 | 亚洲欧美自拍另类 | 中文字幕激情视频 | 国产毛片电影 | 尤物网在线 | 男女日批视频 | 日韩免费av一区 | 色版视频在线观看 | 久久精品在线免费观看 | 九九黄色片| 国产微拍一区 | 免费看黄色片的网站 | 91天堂视频 | 亚洲欧美精品suv | 日韩精品无码一区二区三区 | 成年人在线免费观看 | 美女视频在线观看免费 | 精品人妻无码一区二区三 | 小泽玛利亚一区二区三区视频 | av中文字幕网站 | 天天躁日日躁狠狠躁av麻豆男男 | 4hu最新网址 | 亚洲AV成人精品 | 国产精品日韩在线观看 | 我我色综合| 亚洲图片欧美在线 | a级片在线看| 亚洲精品成人区在线观看 | 亚洲伦理网站 | 成年人黄色免费视频 | 97自拍视频在线 | 亚洲人人爽 | 理论片一区 | 永久免费看mv网站入口亚洲 | 欧美亚洲二区 | 国产精品无码网站 | 国内特级毛片 | 成人综合av | 高清视频一区二区 | av在线二区 | 超碰狠狠干 | 国产精品免费无遮挡无码永久视频 | 国产裸体永久免费视频网站 | 欧美一级淫片免费视频黄 | 最新国产拍偷乱偷精品 | 久久精品网 | 国产成人精品一区二区三区视频 | 精品乱子伦一区二区三区 | 免费视频福利 | 大香焦久久 | 日韩色婷婷 | 日韩成人av网站 | 香蕉视频亚洲一级 | 亚洲第一欧美 | 久久av一区二区三区 | 亚洲AV成人无码电影在线观看 | 在线久| 一本色道久久88综合日韩精品 | 天天干夜夜操 | 色婷婷免费视频 | 成人高潮片免费网站 | 总裁憋尿呻吟双腿大开憋尿 | 超碰加勒比 | 一区二区在线观看免费 | 日韩精品视频在线看 | 中文字幕第22页 | 911精品国产一区二区在线 | 亚洲少妇中文字幕 | 尹人香蕉网 | 国产精品成人免费视频 | 亚洲无限看 | 另类一区 | 13日本xxxxxⅹxxx20| 欧美午夜精品久久久久久人妖 | av首页在线 | 国产特黄毛片 | 伊人久久青青 | 国产v综合v亚洲欧美久久 | 国产色图片 | 91亚洲国产成人久久精品麻豆 | 九色蝌蚪9l视频蝌蚪9l视频 |