Posts

Showing posts from April, 2016

硬件虛擬化 之VMCS結構

/* VMCS結構: * 1. Guest-state area: //客戶機狀態域(如vmware) , 進入VMM時保存 離開VMM時恢復 Cr0, Cr3, Cr4 Dr7 Rsp, Rip 或對應的32位寄存器 所有段選擇子(包括16位選擇子號,段基址,訪問權限,段大小) GDTR,LDTR 以下MSR: IA32_DEBUGCTL IA32_SYSENTER_CS IA32_SYSENTER_ESP & EIP IA32_PERF_GLOBAL_CTRL IA32_PAT IA32_EFER SMBASE寄存器 Activity State(32bit) //CPU活動狀態 0: Active //活動中 1: HLT //正在執行HLT指令 2: ShutDown //由於3次錯誤,導致關機 3: Wait-for-SIPI //等待主虛擬CPU,發送啟動Startup-IPI Interruptibility State(32bit) //可中斷性狀態 bit[0]: Blocking by STI //表示STI屏蔽目前生效中 bit[1]: Blocking by mov SS //表示MOV SS屏蔽目前生效中 bit[2]: Blocking by SMI //表示SMI屏蔽目前生效中 bit[3]: Blocking by NMI //表示NMI屏蔽目前生效中 bit[31:4]: 0 //保留位, 非零會錯誤 Pending debug Exceptions(64/32bit) bit[3:0]: B3-B0 // 每一位表示對應的斷點狀態, DR7沒有設置為會陷入VMM狀態 bit[11:4]: 保留位 // 清零, 非零則VM entry失敗 bit[12]: enabled bp // 表示最小有一個或多個數據斷點或I/O斷點 斷下 並且他已在DR7激活 bit[14

虛擬化技術(VT) 之 內存虛擬化(待續...)

Image
內存虛擬化 -------------------------------------------- 傳統ia-32 cpu只能支持單次的虛擬地址到物理地址的轉換 但在虛擬機中, 虛擬機的虛擬地址->虛擬機的物理地址(其實也算是虛擬地址)->真正的物理地址 EPT -------------------------------------------- 在原有的CR3頁表地址映射的基礎上, EPT引入了EPT頁表來實現另一次映射 這樣GVA->GPA->HPA就能由硬件實現, 提高效率 為什麼要兩次轉換 如下圖所示... 最重點是因為客戶機的物理地址也是虛擬出來的 1. Guest World GVA -+ | CR3 -+-> PD -> PT -> GPA ------------------------------------- 2. Then when EPT is enabled GPA -+ | EPTP-+-> EPT PML4 -> EPT PDPT -> EPT PDT -> EPT PT -> HPA

虛擬化技術(VT) 之 CPU中斷虛擬化

中斷虛擬化 --------------------------------------------------- 物理CPU外部中斷流程: - I/O設備通過I/O APIC 或PIC 發出中斷請求 - 中斷請求經由PCI總線發送到系統總線, 最後目標CPU的Local APIC 接收中斷 - 最後判斷是否處理中斷 虛擬CPU的模疑流程: - 每個VCPU有對應的虛擬Local APIC用於接收中斷, 及虛擬I/O APIC, 虛擬PIC 用於發送中斷(由VMM維護) - 虛擬設備調用 I/O APIC發送中斷, 挑選出目標的虛擬Local APIC - Local APIC 利用事件注入,將其注入到相應的VCPU 虛擬PIC --------------------------------- IA-32 PIC的ICW1~4 和OCW1~3 都是通過I/O 端口訪問, 即I/O操作, 那vt-x 可以很容易實現虛擬化 具體而言,這些接口是通過I/O端口 0x20 0x21 0xA0 0xA1 來訪問, 因此VMM可以設置VMCS I/O Bitmap相應的位, 使客戶機訪問端口時陷入vmm 陷入VMM後, 按照PIC硬件規範 對這些接口的定義,實現相應的邏輯 例如: OCW1 的功能是用於操作IMR寄存器, 控制指定中斷是否被屏蔽 因此VMM可以分析客戶機的OCW1命令, 判斷出是對哪個中斷進行屏蔽 或者解除屏蔽 VMM繼而在內部邏輯中記錄指定中斷是否被屏蔽, 那下一次虛擬中斷就不會被提交 物理上I/O設備與PIC 是電氣連線 , 但虛擬環境中由於設備和PIC都是虛擬的因而兩者的交互為直接的函數調用 虛擬I/O APIC ------------------------------------------------- PIC是用於單核CPU的, 對於多核CPU 必須通過I/O APIC發送中斷 因此對於多CPU平台, 必須實現I/O APIC 與物理上類似, 虛擬I/O APIC 最後也是提交LAPIC 提交對應中斷 虛擬LAPIC ------------------------------------------------- LAPIC 是CPU上一個內部部份, 負責接受中斷, 此外還

虛擬化技術(VT) 之 虛擬CPU結構VCPU 詳解

CPU虛擬化的實現: 硬件虛擬化使用VCPU描述符來描述虛擬CPU(客戶機, 類似操作系統的PCB) 是一個struct (1) VCPU標示信息: 用於標示VCPU的一些基本屬性,如ID號, 這VCPU屬於哪一個客戶機 (2) 虛擬寄存器信息:虛擬的寄存器資源, 在使用intel VT-x 的情況下, 這些內容包括在vmcs中 (3) VCPU狀態信息: 類似進程狀態信息, 標示vcpu當前所處的狀態 , 例如睡眠,運行, 供調度器使用 (4) 額外寄存器或部件信息: 主要指未包含在VMCS的一些寄存器或CPU部件,如浮點寄存器, LAPIC (5) 其他信息: 用於vmm進行優化,或存儲其他信息 由此可見VCPU可以劃分成兩部份,一個是以VMCS為主由硬件使用和刷新部份, 主要是虛擬寄存器部份, 另一個是除VMCS外,由VMM使用和更新的部份 當VMM創建客戶機時, 首先要為他創建VCPU, 整個客戶機的運行實際上可以看作是VMM調度不同的VCPU運行 VCPU的創建: ---------------------------------------------------------------------------- 由於VCPU實際上是一個結構體, 那它的創建實際上就是分配相應大小的內存空間 VCPU涉及很多信息, 通常為多級結構 如第一級可以是各平台通用的內容, 中間包含一個指針指向第二級 物理CPU被供電以後, 硬件會自動將CPU初始化為指定狀態, VCPU的初始化也是一個類似的過程 將VCPU描述符的各個部份分置成可用的狀態, 通常初始化包含如下內容: (1) 分配VCPU標示: 首先標示VCPU屬於哪個客戶機 (唯一標示) (2) 初始化虛擬寄存器: 指初始化VMCS相關域,通常指CPU當前的值 (3) 初始化VCPU 狀態信息: 設置VCPU在調度前需要配置的必要標誌位 (4) 初始化額外部件: 將未被VMCS包含的虛擬寄存器初始化為物理CPU的值,並配置虛擬LAPIC等部份 (5) 始化化其他信息: 根據VMM的實現初始化VCPU的私有數據 VMCS的創建與初始化: ------------------------------------------------------

虛擬化(VT)技術 之 CPU虛擬化探討

VMX運行模式 只有以下兩種: vmx root狀態 -> vmm運行時的狀態 vmx non-root -> 離開vmm後, 普通CPU的狀態 VMEXIT: 引發VMM的時侯 VMENTRY: 離開VMM的時侯 VMCS: VMCS是指一塊4KB內存, 用於VMEXIT 及VMENTRY切換時 更換CPU狀態 一個CPU只可以綁定一個VMCS 使用VMPTRLD 可以將當前運行這一句的CPU 綁定到對應的VMCS 使用VMCLEAR , 解除綁定現在CPU的VMCS VMCS的變換過程: (1) CPU1 上執行VMCLEAR解除綁定 (2) CPU2 上執行VMPTRLD 綁定新的VMCS VMCS主要偏移: (1) 偏移0 : 是VMCS版本標誌 表示VMCS的數據格式的版本 (2) 偏移4 : VMX中止指示, VMEXIT不成功的時侯產生VMX中止, CPU會在此處存入VMX意外中止的原因 (3) 偏移8 : VMCS數據域,該域的格式是隨著CPU不同而有所變化->具體用偏移0判斷哪一種格式 x86 CPU 提供兩條新引入的匯編指令: VMREAD : 讀取VMCS中 指定的域 VMWRITE : 寫入 中指定的域 VT-x 為VMCS數據域每一個字段也定義了相應的 因此令以上兩條指令成立 具體VMCS數據域包含以下六大信息 (1)客戶機狀態域: 進入VMM時保留, 離開VMM時取回 (2)宿主機狀態域: 進入VMM時取回, 離開VMM時保留 (3)VM-Entry控制域: 控制VM-Entry的過程 (4)VM-Execution控制域: 控制處理器在vmx non-root模式時的行為 (5)VM-Exit控制域: 控制vm-exit的過程 (6)VM-Exit數據域: 提供vm-exit的原因及相關信息, 注意這是只讀(read-only)的 (1) 客戶機狀態域: 用於保存CPU在NON-ROOT模式下的CPU上下文(Context) VM-Entry時會提取恢復到CPU, VM-Exit時會保留 它保存了段寄存器, CR3, IDTR, GDTR等寄存器 CPU通過他們來切換實現客戶機地址空間與VMM地址空間的切換 客戶機狀態域並不包

Windows內核安全之 線程調度

Image
線程一個比較重要的概念是, CPU中永遠調度的是線程, 而不是進程, 而進程的切換完全是源於是否同一個CR3寄存器, 詳見SwapContext的實現 以下先列出KTHREAD對象 內核中對線程優先級(priority) 分別使用0~31表示 實時(Real-time)類別: 16~31 動態(Dynamic)類別: 1~15 系統(System)類別: 0 線程在內核的執行體層(Executable Layer)中 使用以下6種優先級 實時(Realtime) 高(High) 普通之上(Above normal) 普通(normal) 普通之下(Below normal) 低(Low) 執行體層透過一個數組PspPriorityTable 轉換成真正的表示 以下是他們的對應關係 實時(Realtime) 24 高(High) 13 普通之上(Above normal) 10 普通(normal) 8 普通之下(Below normal) 6 低(Low) 4 進程的對象EPROCESS結構中 BasePriority 指定一個進程中所有線程的預設優先級 可以通過KeSetPriorityAndQuantumProcess 或 KeSetBasePriorityThread 函數設置優先級 KTHREAD中的Priority域記錄一個線程當前實際優先級, 他一般是在BasePriority基礎上提升到某個增量 Priority不會超過0~15 內核通過調用KiComputeNewPriority計算並調整非實時的線程優先級 我們可以使用NtSetInformationProcess為進程的基礎優先級進行微調, 所以一條線程在執行體中的值並非數組中指定的值 優先級的提升: ------------- 由於每個線程優先級都有對應的鏈表維護著相同優先級的線程 方便調度 所以優先級的提升, 一定是在加入鏈表之前 內核中不小函數的參數使用KPRIORITY Increment進行提升 如: KeInsertQueueApc KePulseEv