最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

深入解析Linux虛擬化KVM-Qemu分析之KVM源碼

2023-01-03 17:38 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿


說明:

  1. KVM版本:5.9.1

  2. QEMU版本:5.0.0

  3. 工具:Source Insight 3.5, Visio

  4. 文章同步在博客園:https://www.cnblogs.com/LoyenWang/

1. 概述

  • 從本文開始將開始source code的系列分析了;

  • KVM作為內(nèi)核模塊,可以認(rèn)為是一個(gè)中間層,向上對(duì)接用戶的控制,向下對(duì)接不同架構(gòu)的硬件虛擬化支持;

  • 本文主要介紹體系架構(gòu)初始化部分,以及向上的框架;

圖片

2. KVM初始化

  • 貝多芬曾經(jīng)說過,一旦你找到了代碼的入口,你就扼住了軟件的咽喉;

  • 我們的故事,從module_init(arm_init)開始,代碼路徑:arch/arm64/kvm/arm.c;

老規(guī)矩,先來一張圖(圖片中涉及到的紅色框函數(shù),都是會(huì)展開描述的):

圖片
  • 內(nèi)核的功能模塊,基本上的套路就是:1)完成模塊初始化,向系統(tǒng)注冊(cè);2)響應(yīng)各類請(qǐng)求,這種請(qǐng)求可能來自用戶態(tài),也可能來自異常響應(yīng)等;

  • kvm的初始化,在kvm_init中完成,既包含了體系結(jié)構(gòu)相關(guān)的初始化設(shè)置,也包含了各類回調(diào)函數(shù)的設(shè)置,資源分配,以及設(shè)備注冊(cè)等,只有當(dāng)初始化完成后,才能響應(yīng)各類請(qǐng)求,比如創(chuàng)建虛擬機(jī)等;

    1. 回調(diào)函數(shù)設(shè)置:cpuhp_setup_state_nocall與CPU的熱插拔相關(guān),register_reboot_notifer與系統(tǒng)的重啟相關(guān),register_syscore_ops與系統(tǒng)的休眠喚醒相關(guān),而這幾個(gè)模塊的回調(diào)函數(shù),最終都會(huì)去調(diào)用體系結(jié)構(gòu)相關(guān)的函數(shù)去打開或關(guān)閉Hypervisor

    2. 資源分配:kmem_cache_create_usercopykvm_async_pf_init都是創(chuàng)建slab緩存,用于內(nèi)核對(duì)象的分配;

    3. kvm_vfio_ops_initVFIO是一個(gè)可以安全將設(shè)備I/O、中斷、DMA導(dǎo)出到用戶空間的框架,后續(xù)在將IO虛擬化時(shí)再深入分析;

  • 圖片中紅色的兩個(gè)函數(shù),是本文分析的內(nèi)容,其中kvm_arch_init與前文ARMv8硬件虛擬化支持緊密相關(guān),而misc_register與上層操作緊密相關(guān);


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【749907784】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ? ?

2.1?kvm_arch_init

  • It's a big topic, I'll try to put it in a nutshell.

  • 這部分內(nèi)容,設(shè)計(jì)ARMv8體系結(jié)構(gòu),建議先閱讀《Linux虛擬化KVM-Qemu分析(二)之ARMv8虛擬化》;

  • 紅色框的函數(shù)是需要進(jìn)一步展開講述的;

圖片
  • is_hyp_mode_available用于判斷ARMv8的Hyp模式是否可用,實(shí)際是通過判斷__boot_cpu_mode的值來完成,該值是在arch/arm64/kernel/head.S中定義,在啟動(dòng)階段會(huì)設(shè)置該值:

圖片
  • is_kernel_in_hyp_mode,通過讀取ARMv8的CurrentEL,判斷是否為CurrentEL_EL2;

  • ARM架構(gòu)中,SVE的實(shí)現(xiàn)要求VHE也要實(shí)現(xiàn),這個(gè)可以從arch/arm64/Kconfig中看到,SVE的模塊編譯:depends on !KVM || ARM64_VHE。SVE(scalable vector extension),是AArch64下一代的SIMD(single instruction multiple data)指令集,用于加速高性能計(jì)算。其中SIMD如下:

圖片
  • init_common_resources,用于設(shè)置IPA的地址范圍,將其限制在系統(tǒng)能支持的物理地址范圍之內(nèi)。stage 2頁表依賴于stage 1頁表代碼,需要遵循一個(gè)條件:Stage 1的頁表級(jí)數(shù) >=?Stage 2的頁表級(jí)數(shù);

2.1.1?init_hyp_mode

圖片
  • 放眼望去,init_hyp_mode解決的問題就是各種映射,最終都會(huì)調(diào)用到__create_hyp_mappings,先來解決這個(gè)映射問題:

圖片
  • 看過之前內(nèi)存管理子系統(tǒng)的同學(xué),應(yīng)該熟悉這個(gè)頁表映射建立的過程,基本的流程是給定一個(gè)虛擬地址區(qū)間和物理地址,然后從pgd開始逐級(jí)往下去建立映射。ARMv8架構(gòu)在實(shí)際映射過程中,P4D這一級(jí)頁表并沒有使用。

讓我們繼續(xù)回到init_hyp_mode的正題上來,這個(gè)函數(shù)完成了PGD頁表的分配,完成了IDMAP代碼段的映射,完成了其他各種段的映射,完成了異常向量表的映射,等等。此外,再補(bǔ)充幾點(diǎn)內(nèi)容:

  1. ARMv8異常向量表

圖片
  • ARMv8架構(gòu)的AArch64執(zhí)行態(tài)中,每種EL都有16個(gè)entry,分為四類:Synchronous,IRQ,F(xiàn)IQ,SError。以系統(tǒng)啟動(dòng)時(shí)設(shè)置hypervisor的異常向量表__hyp_stub_vectors為例:

圖片
  • 當(dāng)從不同的Exception Level觸發(fā)異常時(shí),根據(jù)執(zhí)行狀態(tài),去選擇對(duì)應(yīng)的handler處理,比如上圖中只有el1_sync有效,也就是在EL1狀態(tài)觸發(fā)EL2時(shí)跳轉(zhuǎn)到該函數(shù);

  1. pushsection/popsection

  • init_hyp_mode函數(shù)中,完成各種段的映射,段的定義放置在vmlinux.lds.S中,比如hyp.idmap.text

圖片
  • 可以通過pushsection/popsection來在目標(biāo)文件中來添加一個(gè)段,并指定段的屬性,比如"ax"代表可分配和可執(zhí)行,這個(gè)在匯編代碼中經(jīng)常用到,比如hyp-init.S中,會(huì)將代碼都放置在hyp.idmap.text中:

圖片
  • 除了pushsection/popsection外,通過#define __hyp_text __section(.hyp.text) notrace __noscs的形式也能將代碼放置在指定的段中;

  1. Hypervisor相關(guān)寄存器

  • 講幾個(gè)關(guān)鍵的相關(guān)寄存器:1)sctlr_el2(System Control Register):可以用于控制EL2的MMU和Cache相關(guān)操作;2)ttbr0_el2(Translation Table Base Register 0):用于存放頁表的基地址,上文中提到分配的hyp_pgd就需要設(shè)置到該寄存器中;3)vbar_el2(Vector Base Address Register):用于存放異常向量表的基地址;

我們需要先明確幾點(diǎn):

  1. Hyp模式下要執(zhí)行的代碼,需要先建立起映射;

  2. 映射IDMAP代碼段和其他代碼段,明確這些段中都有哪些函數(shù),這個(gè)可以通過pushsection/popsection以及__hyp_text宏可以看出來;

  3. 最終的目標(biāo)是需要建立好頁表映射,并安裝好異常向量表;

貌似內(nèi)容比較零碎,最終的串聯(lián)與謎題留在下一小節(jié)來解答。

2.1.2?init_subsystems

先看一下函數(shù)的調(diào)用流程:

圖片
  • VGIC,timer,以及電源管理相關(guān)模塊在本文中暫且不深入分析了,本節(jié)主要關(guān)心cpu_hyp_reinit的功能;

  • 綠色框中的函數(shù),會(huì)陷入到EL2進(jìn)行執(zhí)行;

看圖中有好幾次異常向量表的設(shè)置,此外,還有頁表基地址、棧頁的獲取與設(shè)置等,結(jié)合上一小節(jié)的各類映射,是不是已經(jīng)有點(diǎn)迷糊了,下邊這張圖會(huì)將這些內(nèi)容串聯(lián)起來:

圖片
  • 在整個(gè)異常向量表創(chuàng)建的過程中,涉及到三個(gè)向量表:__hyp_stub_vectors,__kvm_hyp_init,?__kvm_call_hyp,這些代碼都是匯編實(shí)現(xiàn);

  • 在系統(tǒng)啟動(dòng)過程中(arch/arm64/kernel/head.S),調(diào)用到el2_setup函數(shù),在該函數(shù)中設(shè)置了一個(gè)臨時(shí)的異常向量表,也就是先打一個(gè)樁,這個(gè)從名字也可以看出來,該異常向量表中僅實(shí)現(xiàn)了el2_synchandler處理函數(shù),可以應(yīng)對(duì)兩種異常:1)設(shè)置新的異常向量表;2)重置異常向量表,也就是設(shè)置回__hyp_stub_vectors

  • kvm初始化時(shí),調(diào)用了__hyp_set_vectors來設(shè)置新的異常向量表:__kvm_hyp_init。這個(gè)向量表中只實(shí)現(xiàn)了__do_hyp_init的處理函數(shù),也就是只能用來對(duì)Hyp模式進(jìn)行初始化。上文提到過idmap段,這個(gè)代碼就放置在idmap段,以前分析內(nèi)存管理子系統(tǒng)時(shí)也提到過idmap,為什么需要這個(gè)呢?idmap: identity map,也就是物理地址和虛擬地址是一一映射的,防止MMU在使能前后代碼不能執(zhí)行;

  • __kvm_call_hyp函數(shù),用于在Hyp模式下執(zhí)行指定的函數(shù),在cpu_hyp_reinit函數(shù)中調(diào)用了該函數(shù),傳遞的參數(shù)包括了新的異常向量表地址,頁表基地址,Hyp的棧地址,per-CPU偏移等,最終會(huì)調(diào)用__do_hyp_init函數(shù)完成相應(yīng)的設(shè)置。

到此,頁表和異常向量表的設(shè)置算是完成了。

2.2?misc_register

misc_register用于注冊(cè)字符設(shè)備驅(qū)動(dòng),在kvm_init函數(shù)中調(diào)用此函數(shù)完成注冊(cè),以便上層應(yīng)用程序來使用kvm模塊

圖片
  • 字符設(shè)備的注冊(cè)分為三級(jí),分別代表kvm,?vm,?vcpu,上層最終使用底層的服務(wù)都是通過ioctl函數(shù)來操作;

  • kvm:代表kvm內(nèi)核模塊,可以通過kvm_dev_ioctl來管理kvm版本信息,以及vm的創(chuàng)建等;

  • vm:虛擬機(jī)實(shí)例,可以通過kvm_vm_ioctl函數(shù)來創(chuàng)建vcpu,設(shè)置內(nèi)存區(qū)間,分配中斷等;

  • vcpu:代表虛擬的CPU,可以通過kvm_vcpu_ioctl來啟動(dòng)或暫停CPU的運(yùn)行,設(shè)置vcpu的寄存器等;

Qemu的使用為例:

  1. 打開/dev/kvm設(shè)備文件;

  2. ioctl(xx, KVM_CREATE_VM, xx)創(chuàng)建虛擬機(jī)對(duì)象;

  3. ioctl(xx, KVM_CREATE_VCPU, xx)為虛擬機(jī)創(chuàng)建vcpu對(duì)象;

  4. ioctl(xx, KVM_RUN, xx)讓vcpu運(yùn)行起來;

3. 總結(jié)

本文主要從兩個(gè)方向來介紹了kvm_init

  1. 底層的體系結(jié)構(gòu)相關(guān)的初始化,主要涉及的就是EL2的相關(guān)設(shè)置,比如各個(gè)段的映射,異常向量表的安裝,頁表基地址的設(shè)置等,當(dāng)把這些準(zhǔn)備工作做完后,才能在硬件上去支持虛擬化的服務(wù)請(qǐng)求;

  2. 字符設(shè)備注冊(cè),設(shè)置好各類ioctl的函數(shù),上層應(yīng)用程序可以通過字符設(shè)備文件,來操作底層的kvm模塊。

原文作者:LoyenWang





深入解析Linux虛擬化KVM-Qemu分析之KVM源碼的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
宁晋县| 仁怀市| 新乡市| 青铜峡市| 平定县| 托克托县| 长沙县| 永德县| 武隆县| 鄂州市| 潼南县| 泰宁县| 山东| 商洛市| 崇信县| 岚皋县| 汉川市| 怀化市| 始兴县| 陆川县| 揭西县| 宜阳县| 济阳县| 峨山| 崇左市| 巴南区| 鄂尔多斯市| 天峻县| 巫溪县| 丘北县| 土默特右旗| 开远市| 江口县| 巴林右旗| 阜平县| 宜阳县| 云安县| 镇赉县| 方城县| 枣强县| 嘉兴市|