12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779 |
- use core::intrinsics::likely;
- use core::intrinsics::unlikely;
- use core::sync::atomic::{AtomicBool, Ordering};
- use exit::VmxExitHandlers;
- use log::debug;
- use log::error;
- use log::warn;
- use x86_64::registers::control::Cr3Flags;
- use x86_64::structures::paging::PhysFrame;
- use crate::arch::process::table::USER_DS;
- use crate::arch::vm::mmu::kvm_mmu::KvmMmu;
- use crate::arch::vm::uapi::kvm_exit;
- use crate::arch::vm::uapi::{
- AC_VECTOR, BP_VECTOR, DB_VECTOR, GP_VECTOR, MC_VECTOR, NM_VECTOR, PF_VECTOR, UD_VECTOR,
- };
- use crate::arch::vm::vmx::vmcs::VmcsIntrHelper;
- use crate::libs::spinlock::SpinLockGuard;
- use crate::mm::VirtAddr;
- use crate::process::ProcessManager;
- use crate::virt::vm::kvm_host::vcpu::GuestDebug;
- use crate::{
- arch::{
- vm::{
- asm::KvmX86Asm,
- kvm_host::{vcpu::VirtCpuRequest, X86KvmArch},
- vmx::vmcs::vmx_area,
- },
- CurrentIrqArch, MMArch, VirtCpuArch,
- },
- exception::InterruptArch,
- libs::spinlock::SpinLock,
- mm::{
- percpu::{PerCpu, PerCpuVar},
- MemoryManagementArch,
- },
- smp::{core::smp_get_processor_id, cpu::ProcessorId},
- virt::vm::{kvm_dev::kvm_init, kvm_host::vcpu::VirtCpu, user_api::UapiKvmSegment},
- };
- use alloc::{alloc::Global, boxed::Box, collections::LinkedList, sync::Arc, vec::Vec};
- use asm::VMX_EPTP_AD_ENABLE_BIT;
- use asm::VMX_EPTP_MT_WB;
- use asm::VMX_EPTP_PWL_4;
- use asm::VMX_EPTP_PWL_5;
- use bitfield_struct::bitfield;
- use bitmap::{traits::BitMapOps, AllocBitmap};
- use raw_cpuid::CpuId;
- use system_error::SystemError;
- use x86::controlregs::{cr2, cr2_write};
- use x86::dtables::ldtr;
- use x86::msr::wrmsr;
- use x86::segmentation::load_ds;
- use x86::segmentation::load_es;
- use x86::segmentation::{ds, es, fs, gs};
- use x86::vmx::vmcs::ro;
- use x86::{
- bits64::rflags::RFlags,
- controlregs::{cr0, cr4, Cr0, Cr4, Xcr0},
- msr::{self, rdmsr},
- segmentation::{self},
- vmx::vmcs::{
- control::{
- self, EntryControls, ExitControls, PinbasedControls, PrimaryControls, SecondaryControls,
- },
- guest, host,
- },
- };
- use x86_64::registers::control::Cr3;
- use x86_64::{instructions::tables::sidt, registers::control::EferFlags};
- use crate::{
- arch::{
- vm::{vmx::vmcs::feat::VmxFeat, x86_kvm_manager_mut, McgCap},
- KvmArch,
- },
- libs::rwlock::RwLock,
- virt::vm::kvm_host::Vm,
- };
- use self::exit::ExitFastpathCompletion;
- use self::exit::VmxExitReason;
- use self::exit::VmxExitReasonBasic;
- use self::vmcs::LoadedVmcs;
- use self::{
- capabilities::{ProcessorTraceMode, VmcsConfig, VmxCapability},
- vmcs::{
- current_loaded_vmcs_list_mut, current_vmcs, current_vmcs_mut, ControlsType,
- LockedLoadedVmcs, VMControlStructure, VmxMsrBitmapAccess, VmxMsrBitmapAction,
- PERCPU_LOADED_VMCS_LIST, PERCPU_VMCS, VMXAREA,
- },
- };
- use super::asm::IntrInfo;
- use super::asm::SegmentCacheField;
- use super::kvm_host::vcpu::KvmIntrType;
- use super::kvm_host::RMODE_TSS_SIZE;
- use super::x86_kvm_ops;
- use super::{
- asm::{VcpuSegment, VmxAsm, VmxMsrEntry},
- init_kvm_arch,
- kvm_host::{KvmFunc, KvmInitFunc, KvmIrqChipMode, KvmReg, MsrFilterType, NotifyVmExitFlags},
- x86_kvm_manager, KvmArchManager,
- };
- pub mod asm;
- pub mod capabilities;
- pub mod ept;
- pub mod exit;
- pub mod vmcs;
- extern "C" {
- fn vmx_vmexit();
- }
- pub struct VmxKvmInitFunc;
- impl VmxKvmInitFunc {
- pub fn setup_per_cpu(&self) {
- let mut vmcs_areas = Vec::new();
- vmcs_areas.resize(PerCpu::MAX_CPU_NUM as usize, VMControlStructure::new());
- unsafe { VMXAREA = PerCpuVar::new(vmcs_areas) };
- let mut percpu_current_vmcs = Vec::new();
- percpu_current_vmcs.resize(PerCpu::MAX_CPU_NUM as usize, None);
- unsafe { PERCPU_VMCS = PerCpuVar::new(percpu_current_vmcs) }
- let mut percpu_loaded_vmcs_lists = Vec::new();
- percpu_loaded_vmcs_lists.resize(PerCpu::MAX_CPU_NUM as usize, LinkedList::new());
- unsafe { PERCPU_LOADED_VMCS_LIST = PerCpuVar::new(percpu_loaded_vmcs_lists) }
- }
- }
- impl KvmInitFunc for VmxKvmInitFunc {
- #[allow(clippy::borrow_interior_mutable_const)]
- #[inline(never)]
- fn hardware_setup(&self) -> Result<(), SystemError> {
- let idt = sidt();
- let cpuid = CpuId::new();
- let cpu_extend_feature = cpuid
- .get_extended_processor_and_feature_identifiers()
- .ok_or(SystemError::ENOSYS)?;
- let mut vmx_init: Box<Vmx> = unsafe {
- Box::try_new_zeroed_in(Global)
- .map_err(|_| SystemError::ENOMEM)?
- .assume_init()
- };
- vmx_init.init();
- vmx_init.host_idt_base = idt.base.as_u64();
- Vmx::set_up_user_return_msrs();
- Vmx::setup_vmcs_config(&mut vmx_init.vmcs_config, &mut vmx_init.vmx_cap)?;
- let manager = x86_kvm_manager_mut();
- let kvm_cap = &mut manager.kvm_caps;
- if vmx_init.has_mpx() {
- kvm_cap.supported_xcr0 &= !(Xcr0::XCR0_BNDREG_STATE | Xcr0::XCR0_BNDCSR_STATE);
- }
- // 判断是否启用vpid
- if !vmx_init.has_vpid()
- || !vmx_init.has_invvpid()
- || !vmx_init.has_invvpid_single()
- || !vmx_init.has_invvpid_global()
- {
- vmx_init.enable_vpid = false;
- }
- if !vmx_init.has_ept()
- || !vmx_init.has_ept_4levels()
- || !vmx_init.has_ept_mt_wb()
- || !vmx_init.has_invept_global()
- {
- vmx_init.enable_ept = false;
- }
- // 是否启用了 EPT 并且检查 CPU 是否支持 Execute Disable(NX)功能
- // Execute Disable 是一种 CPU 功能,可以防止代码在数据内存区域上执行
- if !vmx_init.enable_ept && !cpu_extend_feature.has_execute_disable() {
- error!("[KVM] NX (Execute Disable) not supported");
- return Err(SystemError::ENOSYS);
- }
- if !vmx_init.has_ept_ad_bits() || !vmx_init.enable_ept {
- vmx_init.enable_ept_ad = false;
- }
- if !vmx_init.has_unrestricted_guest() || !vmx_init.enable_ept {
- vmx_init.enable_unrestricted_guest = false;
- }
- if !vmx_init.has_flexproirity() {
- vmx_init.enable_flexpriority = false;
- }
- if !vmx_init.has_virtual_nmis() {
- vmx_init.enable_vnmi = false;
- }
- if !vmx_init.has_encls_vmexit() {
- vmx_init.enable_sgx = false;
- }
- if !vmx_init.enable_flexpriority {
- VmxKvmFunc::CONFIG.write().have_set_apic_access_page_addr = false;
- }
- if !vmx_init.has_tpr_shadow() {
- VmxKvmFunc::CONFIG.write().have_update_cr8_intercept = false;
- }
- // TODO:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/kvm/vmx/vmx.c#8501 - 8513
- if !vmx_init.has_ple() {
- vmx_init.ple_gap = 0;
- vmx_init.ple_window = 0;
- vmx_init.ple_window_grow = 0;
- vmx_init.ple_window_max = 0;
- vmx_init.ple_window_shrink = 0;
- }
- if !vmx_init.has_apicv() {
- vmx_init.enable_apicv = false;
- }
- if !vmx_init.enable_apicv {
- // TODO: 设置sync_pir_to_irr
- }
- if !vmx_init.enable_apicv || !vmx_init.has_ipiv() {
- vmx_init.enable_ipiv = false;
- }
- if vmx_init.has_tsc_scaling() {
- kvm_cap.has_tsc_control = true;
- }
- kvm_cap.max_tsc_scaling_ratio = 0xffffffffffffffff;
- kvm_cap.tsc_scaling_ratio_frac_bits = 48;
- kvm_cap.has_bus_lock_exit = vmx_init.has_bus_lock_detection();
- kvm_cap.has_notify_vmexit = vmx_init.has_notify_vmexit();
- // vmx_init.vpid_bitmap.lock().set_all(false);
- if vmx_init.enable_ept {
- // TODO: mmu_set_ept_masks
- warn!("mmu_set_ept_masks TODO!");
- }
- warn!("vmx_setup_me_spte_mask TODO!");
- KvmMmu::kvm_configure_mmu(
- vmx_init.enable_ept,
- 0,
- vmx_init.get_max_ept_level(),
- vmx_init.ept_cap_to_lpage_level(),
- );
- if !vmx_init.enable_ept || !vmx_init.enable_ept_ad || !vmx_init.has_pml() {
- vmx_init.enable_pml = false;
- }
- if !vmx_init.enable_pml {
- // TODO: Set cpu dirty log size
- }
- if !vmx_init.has_preemption_timer() {
- vmx_init.enable_preemption_timer = false;
- }
- if vmx_init.enable_preemption_timer {
- // TODO
- }
- if !vmx_init.enable_preemption_timer {
- // TODO
- }
- kvm_cap
- .supported_mce_cap
- .insert(McgCap::MCG_LMCE_P | McgCap::MCG_CMCI_P);
- // TODO: pt_mode
- // TODO: setup_default_sgx_lepubkeyhash
- // TODO: nested
- // TODO: vmx_set_cpu_caps
- init_vmx(vmx_init);
- self.setup_per_cpu();
- warn!("hardware setup finish");
- Ok(())
- }
- fn handle_intel_pt_intr(&self) -> u32 {
- todo!()
- }
- fn runtime_funcs(&self) -> &'static dyn super::kvm_host::KvmFunc {
- &VmxKvmFunc
- }
- }
- #[derive(Debug)]
- pub struct VmxKvmFunc;
- pub struct VmxKvmFuncConfig {
- pub have_set_apic_access_page_addr: bool,
- pub have_update_cr8_intercept: bool,
- }
- impl VmxKvmFunc {
- #[allow(clippy::declare_interior_mutable_const)]
- pub const CONFIG: RwLock<VmxKvmFuncConfig> = RwLock::new(VmxKvmFuncConfig {
- have_set_apic_access_page_addr: true,
- have_update_cr8_intercept: true,
- });
- pub fn vcpu_load_vmcs(
- vcpu: &mut VirtCpu,
- cpu: ProcessorId,
- _buddy: Option<Arc<LockedLoadedVmcs>>,
- ) {
- let vmx = vcpu.vmx();
- let already_loaded = vmx.loaded_vmcs.lock().cpu == cpu;
- if !already_loaded {
- Self::loaded_vmcs_clear(&vmx.loaded_vmcs);
- let _irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
- current_loaded_vmcs_list_mut().push_back(vmx.loaded_vmcs.clone());
- }
- if let Some(prev) = current_vmcs() {
- let vmcs = vmx.loaded_vmcs.lock().vmcs.clone();
- if !Arc::ptr_eq(&vmcs, prev) {
- VmxAsm::vmcs_load(vmcs.phys_addr());
- *current_vmcs_mut() = Some(vmcs);
- // TODO:buddy barrier?
- }
- } else {
- let vmcs = vmx.loaded_vmcs.lock().vmcs.clone();
- VmxAsm::vmcs_load(vmcs.phys_addr());
- *current_vmcs_mut() = Some(vmcs);
- // TODO:buddy barrier?
- }
- if !already_loaded {
- let mut pseudo_descriptpr: x86::dtables::DescriptorTablePointer<u64> =
- Default::default();
- unsafe {
- x86::dtables::sgdt(&mut pseudo_descriptpr);
- };
- vmx.loaded_vmcs.lock().cpu = cpu;
- let id = vmx.loaded_vmcs.lock().vmcs.lock().revision_id();
- debug!(
- "revision_id {id} req {:?}",
- VirtCpuRequest::KVM_REQ_TLB_FLUSH
- );
- vcpu.request(VirtCpuRequest::KVM_REQ_TLB_FLUSH);
- VmxAsm::vmx_vmwrite(
- host::TR_BASE,
- KvmX86Asm::get_segment_base(
- pseudo_descriptpr.base,
- pseudo_descriptpr.limit,
- unsafe { x86::task::tr().bits() },
- ),
- );
- VmxAsm::vmx_vmwrite(host::GDTR_BASE, pseudo_descriptpr.base as usize as u64);
- VmxAsm::vmx_vmwrite(host::IA32_SYSENTER_ESP, unsafe {
- rdmsr(msr::IA32_SYSENTER_ESP)
- });
- }
- }
- pub fn loaded_vmcs_clear(loaded_vmcs: &Arc<LockedLoadedVmcs>) {
- let mut guard = loaded_vmcs.lock();
- if guard.cpu == ProcessorId::INVALID {
- return;
- }
- if guard.cpu == smp_get_processor_id() {
- if let Some(vmcs) = current_vmcs() {
- if Arc::ptr_eq(vmcs, &guard.vmcs) {
- *current_vmcs_mut() = None;
- }
- }
- VmxAsm::vmclear(guard.vmcs.phys_addr());
- if let Some(shadow) = &guard.shadow_vmcs {
- if guard.launched {
- VmxAsm::vmclear(shadow.phys_addr());
- }
- }
- let _ = current_loaded_vmcs_list_mut().extract_if(|x| Arc::ptr_eq(x, loaded_vmcs));
- guard.cpu = ProcessorId::INVALID;
- guard.launched = false;
- } else {
- // 交由对应cpu处理
- todo!()
- }
- }
- pub fn seg_setup(&self, seg: VcpuSegment) {
- let seg_field = &KVM_VMX_SEGMENT_FIELDS[seg as usize];
- VmxAsm::vmx_vmwrite(seg_field.selector, 0);
- VmxAsm::vmx_vmwrite(seg_field.base, 0);
- VmxAsm::vmx_vmwrite(seg_field.limit, 0xffff);
- let mut ar = 0x93;
- if seg == VcpuSegment::CS {
- ar |= 0x08;
- }
- VmxAsm::vmx_vmwrite(seg_field.ar_bytes, ar);
- }
- }
- impl KvmFunc for VmxKvmFunc {
- fn name(&self) -> &'static str {
- "VMX"
- }
- fn hardware_enable(&self) -> Result<(), SystemError> {
- let vmcs = vmx_area().get().as_ref();
- debug!("vmcs idx {}", vmcs.abort);
- let phys_addr =
- unsafe { MMArch::virt_2_phys(VirtAddr::new(vmcs as *const _ as usize)).unwrap() };
- // TODO: intel_pt_handle_vmx(1);
- VmxAsm::kvm_cpu_vmxon(phys_addr)?;
- Ok(())
- }
- fn vm_init(&self) -> X86KvmArch {
- let vmx_init = vmx_info();
- let mut arch = X86KvmArch::default();
- if vmx_init.ple_gap == 0 {
- arch.pause_in_guest = true;
- }
- return arch;
- }
- fn vcpu_create(&self, vcpu: &mut VirtCpu, vm: &Vm) {
- VmxVCpuPriv::init(vcpu, vm);
- }
- fn vcpu_load(&self, vcpu: &mut VirtCpu, cpu: crate::smp::cpu::ProcessorId) {
- Self::vcpu_load_vmcs(vcpu, cpu, None);
- // TODO: vmx_vcpu_pi_load
- }
- fn cache_reg(&self, vcpu: &mut VirtCpuArch, reg: KvmReg) {
- vcpu.mark_register_available(reg);
- match reg {
- KvmReg::VcpuRegsRsp => {
- vcpu.regs[reg as usize] = VmxAsm::vmx_vmread(guest::RSP);
- }
- KvmReg::VcpuRegsRip => {
- vcpu.regs[reg as usize] = VmxAsm::vmx_vmread(guest::RIP);
- }
- // VCPU_EXREG_PDPTR
- KvmReg::NrVcpuRegs => {
- if vmx_info().enable_ept {
- todo!()
- }
- }
- KvmReg::VcpuExregCr0 => {
- let guest_owned = vcpu.cr0_guest_owned_bits;
- vcpu.cr0.remove(guest_owned);
- vcpu.cr0.insert(
- Cr0::from_bits_truncate(VmxAsm::vmx_vmread(guest::CR0) as usize) & guest_owned,
- );
- }
- KvmReg::VcpuExregCr3 => {
- //当拦截CR3加载时(例如用于影子分页),KVM(Kernel-based Virtual Machine)的CR3会被加载到硬件中,而不是客户机的CR3。
- //暂时先直接读寄存器
- vcpu.cr3 = VmxAsm::vmx_vmread(guest::CR3);
- //todo!()
- }
- KvmReg::VcpuExregCr4 => {
- let guest_owned = vcpu.cr4_guest_owned_bits;
- vcpu.cr4.remove(guest_owned);
- vcpu.cr4.insert(
- Cr4::from_bits_truncate(VmxAsm::vmx_vmread(guest::CR4) as usize) & guest_owned,
- );
- }
- _ => {
- todo!()
- }
- }
- }
- fn apicv_pre_state_restore(&self, _vcpu: &mut VirtCpu) {
- // https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/kvm/vmx/vmx.c#6924
- // TODO: pi
- // todo!()
- }
- fn set_msr(&self, vcpu: &mut VirtCpu, msr: super::asm::MsrData) -> Result<(), SystemError> {
- let vmx = vcpu.vmx_mut();
- let msr_index = msr.index;
- let data = msr.data;
- match msr_index {
- msr::IA32_EFER => {
- todo!("IA32_EFER")
- }
- msr::IA32_FS_BASE => {
- todo!("IA32_FS_BASE")
- }
- msr::IA32_GS_BASE => {
- todo!("IA32_GS_BASE")
- }
- msr::IA32_KERNEL_GSBASE => {
- todo!("IA32_KERNEL_GSBASE")
- }
- 0x000001c4 => {
- todo!("MSR_IA32_XFD")
- }
- msr::IA32_SYSENTER_CS => {
- todo!("IA32_SYSENTER_CS")
- }
- msr::IA32_SYSENTER_EIP => {
- todo!("IA32_SYSENTER_EIP")
- }
- msr::IA32_SYSENTER_ESP => {
- todo!("IA32_SYSENTER_ESP")
- }
- msr::IA32_DEBUGCTL => {
- todo!("IA32_DEBUGCTL")
- }
- msr::MSR_C1_PMON_EVNT_SEL0 => {
- todo!("MSR_IA32_BNDCFGS")
- }
- 0xe1 => {
- todo!("MSR_IA32_UMWAIT_CONTROL ")
- }
- 0x48 => {
- todo!("MSR_IA32_SPEC_CTRL")
- }
- msr::MSR_IA32_TSX_CTRL => {
- todo!("MSR_IA32_TSX_CTRL")
- }
- msr::IA32_PAT => {
- todo!("IA32_PAT")
- }
- 0x4d0 => {
- todo!("MSR_IA32_MCG_EXT_CTL")
- }
- msr::IA32_FEATURE_CONTROL => {
- todo!("IA32_FEATURE_CONTROL")
- }
- 0x8c..=0x8f => {
- todo!("MSR_IA32_SGXLEPUBKEYHASH0 ... MSR_IA32_SGXLEPUBKEYHASH3 {msr_index}")
- }
- msr::IA32_VMX_BASIC..=msr::IA32_VMX_VMFUNC => {
- todo!("msr::IA32_VMX_BASIC..=msr::IA32_VMX_VMFUNC")
- }
- msr::MSR_IA32_RTIT_CTL => {
- todo!("MSR_IA32_RTIT_CTL")
- }
- msr::MSR_IA32_RTIT_STATUS => {
- todo!("MSR_IA32_RTIT_STATUS")
- }
- msr::MSR_IA32_RTIT_OUTPUT_BASE => {
- todo!("MSR_IA32_RTIT_OUTPUT_BASE")
- }
- 0x572 => {
- todo!("MSR_IA32_RTIT_CR3_MATCH")
- }
- msr::MSR_IA32_RTIT_OUTPUT_MASK_PTRS => {
- todo!("MSR_IA32_RTIT_OUTPUT_MASK_PTRS")
- }
- msr::MSR_IA32_ADDR0_START..=msr::MSR_IA32_ADDR3_END => {
- todo!("msr::MSR_IA32_ADDR0_START..=msr::MSR_IA32_ADDR3_END")
- }
- msr::MSR_PERF_CAPABILITIES => {
- todo!("MSR_PERF_CAPABILITIES")
- }
- _ => {
- let uret_msr = vmx.find_uret_msr(msr_index);
- if let Some((idx, _msr)) = uret_msr {
- vmx.set_guest_uret_msr(idx, data)?;
- vmx.set_uret_msr(msr_index, data);
- } else {
- vcpu.arch.set_msr_common(&msr);
- };
- }
- }
- if msr_index == 0x10a {
- // MSR_IA32_ARCH_CAPABILITIES
- todo!()
- }
- Ok(())
- }
- fn vcpu_reset(&self, vcpu: &mut VirtCpu, vm: &Vm, init_event: bool) {
- if !init_event {
- vmx_info_mut().vmx_reset_vcpu(vcpu, vm)
- }
- vcpu.kvm_set_cr8(0);
- let vmx = vcpu.vmx_mut();
- vmx.rmode.vm86_active = false;
- vmx.spec_ctrl = 0;
- vmx.msr_ia32_umwait_control = 0;
- vmx.hv_deadline_tsc = u64::MAX;
- vmx.segment_cache_clear();
- vcpu.arch.mark_register_available(KvmReg::VcpuExregSegments);
- self.seg_setup(VcpuSegment::CS);
- VmxAsm::vmx_vmwrite(guest::CS_SELECTOR, 0xf000);
- VmxAsm::vmx_vmwrite(guest::CS_BASE, 0xffff0000);
- self.seg_setup(VcpuSegment::DS);
- self.seg_setup(VcpuSegment::ES);
- self.seg_setup(VcpuSegment::FS);
- self.seg_setup(VcpuSegment::GS);
- self.seg_setup(VcpuSegment::SS);
- VmxAsm::vmx_vmwrite(guest::TR_SELECTOR, 0);
- VmxAsm::vmx_vmwrite(guest::TR_BASE, 0);
- VmxAsm::vmx_vmwrite(guest::TR_LIMIT, 0xffff);
- VmxAsm::vmx_vmwrite(guest::TR_ACCESS_RIGHTS, 0x008b);
- VmxAsm::vmx_vmwrite(guest::LDTR_SELECTOR, 0);
- VmxAsm::vmx_vmwrite(guest::LDTR_BASE, 0);
- VmxAsm::vmx_vmwrite(guest::LDTR_LIMIT, 0xffff);
- VmxAsm::vmx_vmwrite(guest::LDTR_ACCESS_RIGHTS, 0x00082);
- VmxAsm::vmx_vmwrite(guest::GDTR_BASE, 0);
- VmxAsm::vmx_vmwrite(guest::GDTR_LIMIT, 0xffff);
- VmxAsm::vmx_vmwrite(guest::IDTR_BASE, 0);
- VmxAsm::vmx_vmwrite(guest::IDTR_LIMIT, 0xffff);
- VmxAsm::vmx_vmwrite(guest::ACTIVITY_STATE, 0);
- VmxAsm::vmx_vmwrite(guest::INTERRUPTIBILITY_STATE, 0);
- VmxAsm::vmx_vmwrite(guest::PENDING_DBG_EXCEPTIONS, 0);
- if x86_kvm_manager().mpx_supported() {
- VmxAsm::vmx_vmwrite(guest::IA32_BNDCFGS_FULL, 0);
- }
- VmxAsm::vmx_vmwrite(control::VMENTRY_INTERRUPTION_INFO_FIELD, 0);
- vcpu.request(VirtCpuRequest::MAKE_KVM_REQ_APIC_PAGE_RELOAD);
- vmx_info().vpid_sync_context(vcpu.vmx().vpid);
- warn!("TODO: vmx_update_fb_clear_dis");
- }
- fn set_rflags(&self, vcpu: &mut VirtCpu, mut rflags: x86::bits64::rflags::RFlags) {
- if vcpu.is_unrestricted_guest() {
- vcpu.arch.mark_register_available(KvmReg::VcpuExregRflags);
- vcpu.vmx_mut().rflags = rflags;
- VmxAsm::vmx_vmwrite(guest::RFLAGS, rflags.bits());
- return;
- }
- let old_rflags = self.get_rflags(vcpu);
- let vmx = vcpu.vmx_mut();
- vmx.rflags = rflags;
- if vmx.rmode.vm86_active {
- vmx.rmode.save_rflags = rflags;
- rflags.insert(RFlags::FLAGS_IOPL3 | RFlags::FLAGS_VM);
- }
- VmxAsm::vmx_vmwrite(guest::RFLAGS, rflags.bits());
- if (old_rflags ^ vmx.rflags).contains(RFlags::FLAGS_VM) {
- let emulation_required = vmx_info().emulation_required(vcpu);
- vcpu.vmx_mut().emulation_required = emulation_required;
- }
- }
- fn set_cr0(&self, vm: &Vm, vcpu: &mut VirtCpu, cr0: x86::controlregs::Cr0) {
- let old_cr0_pg = vcpu.arch.read_cr0_bits(Cr0::CR0_ENABLE_PAGING);
- let mut hw_cr0 = cr0 & (!(Cr0::CR0_NOT_WRITE_THROUGH | Cr0::CR0_CACHE_DISABLE));
- if vmx_info().enable_unrestricted_guest {
- hw_cr0.insert(Cr0::CR0_NUMERIC_ERROR);
- } else {
- hw_cr0
- .insert(Cr0::CR0_NUMERIC_ERROR | Cr0::CR0_ENABLE_PAGING | Cr0::CR0_PROTECTED_MODE);
- if !vmx_info().enable_ept {
- hw_cr0.insert(Cr0::CR0_WRITE_PROTECT);
- }
- if vcpu.vmx().rmode.vm86_active && cr0.contains(Cr0::CR0_PROTECTED_MODE) {
- vmx_info().enter_pmode(vcpu);
- }
- if !vcpu.vmx().rmode.vm86_active && !cr0.contains(Cr0::CR0_PROTECTED_MODE) {
- vmx_info().enter_rmode(vcpu, vm);
- }
- }
- VmxAsm::vmx_vmwrite(control::CR0_READ_SHADOW, cr0.bits() as u64);
- VmxAsm::vmx_vmwrite(guest::CR0, hw_cr0.bits() as u64);
- vcpu.arch.cr0 = cr0;
- vcpu.arch.mark_register_available(KvmReg::VcpuExregCr0);
- if vcpu.arch.efer.contains(EferFlags::LONG_MODE_ENABLE) {
- if old_cr0_pg.is_empty() && cr0.contains(Cr0::CR0_ENABLE_PAGING) {
- todo!("enter lmode todo");
- } else if !old_cr0_pg.is_empty() && !cr0.contains(Cr0::CR0_ENABLE_PAGING) {
- todo!("exit lmode todo");
- }
- }
- if vmx_info().enable_ept && !vmx_info().enable_unrestricted_guest {
- todo!()
- }
- vcpu.vmx_mut().emulation_required = vmx_info().emulation_required(vcpu);
- }
- fn set_cr4(&self, vcpu: &mut VirtCpu, cr4_flags: x86::controlregs::Cr4) {
- let old_cr4 = vcpu.arch.read_cr4_bits(Cr4::all());
- let mut hw_cr4 = (unsafe { cr4() } & Cr4::CR4_ENABLE_MACHINE_CHECK)
- | (cr4_flags & (!Cr4::CR4_ENABLE_MACHINE_CHECK));
- if vmx_info().enable_unrestricted_guest {
- hw_cr4.insert(Cr4::CR4_ENABLE_VMX);
- } else if vcpu.vmx().rmode.vm86_active {
- hw_cr4.insert(Cr4::CR4_ENABLE_PAE | Cr4::CR4_ENABLE_VMX | Cr4::CR4_ENABLE_VME);
- } else {
- hw_cr4.insert(Cr4::CR4_ENABLE_PAE | Cr4::CR4_ENABLE_VMX);
- }
- if vmx_info().vmx_umip_emulated() {
- if cr4_flags.contains(Cr4::CR4_ENABLE_UMIP) {
- vcpu.vmx().loaded_vmcs().controls_set(
- ControlsType::SecondaryExec,
- SecondaryControls::DTABLE_EXITING.bits() as u64,
- );
- hw_cr4.remove(Cr4::CR4_ENABLE_UMIP);
- } else if !vcpu.arch.is_guest_mode() {
- vcpu.vmx().loaded_vmcs().controls_clearbit(
- ControlsType::SecondaryExec,
- SecondaryControls::DTABLE_EXITING.bits() as u64,
- );
- }
- }
- vcpu.arch.cr4 = cr4_flags;
- vcpu.arch.mark_register_available(KvmReg::VcpuExregCr4);
- if !vmx_info().enable_unrestricted_guest {
- if vmx_info().enable_ept {
- if vcpu.arch.read_cr0_bits(Cr0::CR0_ENABLE_PAGING).is_empty() {
- hw_cr4.remove(Cr4::CR4_ENABLE_PAE);
- hw_cr4.insert(Cr4::CR4_ENABLE_PSE);
- } else if !cr4_flags.contains(Cr4::CR4_ENABLE_PAE) {
- hw_cr4.remove(Cr4::CR4_ENABLE_PAE);
- }
- }
- if vcpu.arch.read_cr0_bits(Cr0::CR0_ENABLE_PAGING).is_empty() {
- hw_cr4.remove(
- Cr4::CR4_ENABLE_SMEP | Cr4::CR4_ENABLE_SMAP | Cr4::CR4_ENABLE_PROTECTION_KEY,
- );
- }
- }
- VmxAsm::vmx_vmwrite(control::CR4_READ_SHADOW, cr4_flags.bits() as u64);
- VmxAsm::vmx_vmwrite(guest::CR4, hw_cr4.bits() as u64);
- if (cr4_flags ^ old_cr4).contains(Cr4::CR4_ENABLE_OS_XSAVE | Cr4::CR4_ENABLE_PROTECTION_KEY)
- {
- // TODO: update_cpuid_runtime
- }
- }
- fn set_efer(&self, vcpu: &mut VirtCpu, efer: x86_64::registers::control::EferFlags) {
- if vcpu.vmx().find_uret_msr(msr::IA32_EFER).is_none() {
- return;
- }
- vcpu.arch.efer = efer;
- if efer.contains(EferFlags::LONG_MODE_ACTIVE) {
- vcpu.vmx().loaded_vmcs().controls_setbit(
- ControlsType::VmEntry,
- EntryControls::IA32E_MODE_GUEST.bits().into(),
- );
- } else {
- vcpu.vmx().loaded_vmcs().controls_clearbit(
- ControlsType::VmEntry,
- EntryControls::IA32E_MODE_GUEST.bits().into(),
- );
- }
- vmx_info().setup_uret_msrs(vcpu);
- }
- fn update_exception_bitmap(&self, vcpu: &mut VirtCpu) {
- let mut eb = (1u32 << PF_VECTOR)
- | (1 << UD_VECTOR)
- | (1 << MC_VECTOR)
- | (1 << DB_VECTOR)
- | (1 << AC_VECTOR);
- if vmx_info().enable_vmware_backdoor {
- eb |= 1 << GP_VECTOR;
- }
- if vcpu.guest_debug & (GuestDebug::ENABLE | GuestDebug::USE_SW_BP)
- == (GuestDebug::ENABLE | GuestDebug::USE_SW_BP)
- {
- eb |= 1 << BP_VECTOR;
- }
- if vcpu.vmx().rmode.vm86_active {
- eb = !0;
- }
- if !vmx_info().vmx_need_pf_intercept(vcpu) {
- eb &= !(1 << PF_VECTOR);
- }
- if vcpu.arch.is_guest_mode() {
- todo!()
- } else {
- let mut mask = PageFaultErr::empty();
- let mut match_code = PageFaultErr::empty();
- if vmx_info().enable_ept && (eb & (1 << PF_VECTOR) != 0) {
- mask = PageFaultErr::PFERR_PRESENT | PageFaultErr::PFERR_RSVD;
- match_code = PageFaultErr::PFERR_PRESENT;
- }
- VmxAsm::vmx_vmwrite(control::PAGE_FAULT_ERR_CODE_MASK, mask.bits);
- VmxAsm::vmx_vmwrite(control::PAGE_FAULT_ERR_CODE_MATCH, match_code.bits);
- }
- if vcpu.arch.xfd_no_write_intercept {
- eb |= 1 << NM_VECTOR;
- }
- VmxAsm::vmx_vmwrite(control::EXCEPTION_BITMAP, eb as u64);
- }
- fn has_emulated_msr(&self, msr: u32) -> bool {
- match msr {
- msr::IA32_SMBASE => {
- return vmx_info().enable_unrestricted_guest
- || vmx_info().emulate_invalid_guest_state;
- }
- msr::IA32_VMX_BASIC..=msr::IA32_VMX_VMFUNC => {
- return vmx_info().nested;
- }
- 0xc001011f | 0xc0000104 => {
- // MSR_AMD64_VIRT_SPEC_CTRL | MSR_AMD64_TSC_RATIO
- return false;
- }
- _ => {
- return true;
- }
- }
- }
- fn get_msr_feature(&self, msr: &mut super::asm::VmxMsrEntry) -> bool {
- match msr.index {
- msr::IA32_VMX_BASIC..=msr::IA32_VMX_VMFUNC => {
- if !vmx_info().nested {
- return false;
- }
- match vmx_info().vmcs_config.nested.get_vmx_msr(msr.index) {
- Some(data) => {
- msr.data = data;
- return true;
- }
- None => {
- return false;
- }
- }
- }
- _ => {
- return false;
- }
- }
- }
- fn get_rflags(&self, vcpu: &mut VirtCpu) -> x86::bits64::rflags::RFlags {
- if !vcpu.arch.is_register_available(KvmReg::VcpuExregRflags) {
- vcpu.arch.mark_register_available(KvmReg::VcpuExregRflags);
- let mut rflags = RFlags::from_bits_truncate(VmxAsm::vmx_vmread(guest::RFLAGS));
- if vcpu.vmx_mut().rmode.vm86_active {
- rflags.remove(RFlags::FLAGS_IOPL3 | RFlags::FLAGS_VM);
- let save_rflags = vcpu.vmx_mut().rmode.save_rflags;
- rflags.insert(save_rflags & !(RFlags::FLAGS_IOPL3 | RFlags::FLAGS_VM));
- }
- vcpu.vmx_mut().rflags = rflags;
- }
- return vcpu.vmx_mut().rflags;
- }
- fn vcpu_precreate(&self, vm: &mut Vm) -> Result<(), SystemError> {
- if vm.arch.irqchip_mode != KvmIrqChipMode::None || !vmx_info().enable_ipiv {
- return Ok(());
- }
- let kvm_vmx = vm.kvm_vmx_mut();
- if kvm_vmx.pid_table.is_some() {
- return Ok(());
- }
- kvm_vmx.pid_table = Some(unsafe { Box::new_zeroed().assume_init() });
- Ok(())
- }
- fn set_segment(&self, vcpu: &mut VirtCpu, var: &mut UapiKvmSegment, seg: VcpuSegment) {
- vcpu.vmx_mut().emulation_required = vmx_info().emulation_required(vcpu);
- *var = vmx_info()._vmx_set_segment(vcpu, *var, seg);
- }
- fn get_segment(
- &self,
- vcpu: &mut VirtCpu,
- var: UapiKvmSegment,
- seg: VcpuSegment,
- ) -> UapiKvmSegment {
- return vmx_info().vmx_get_segment(vcpu, var, seg);
- }
- fn get_idt(&self, _vcpu: &mut VirtCpu, dt: &mut x86::dtables::DescriptorTablePointer<u8>) {
- dt.limit = VmxAsm::vmx_vmread(guest::IDTR_LIMIT) as u16;
- dt.base = VmxAsm::vmx_vmread(guest::IDTR_BASE) as usize as *const _;
- }
- fn set_idt(&self, _vcpu: &mut VirtCpu, dt: &x86::dtables::DescriptorTablePointer<u8>) {
- VmxAsm::vmx_vmwrite(guest::IDTR_LIMIT, dt.limit as u64);
- VmxAsm::vmx_vmwrite(guest::IDTR_BASE, dt.base as usize as u64);
- }
- fn get_gdt(&self, _vcpu: &mut VirtCpu, dt: &mut x86::dtables::DescriptorTablePointer<u8>) {
- dt.limit = VmxAsm::vmx_vmread(guest::GDTR_LIMIT) as u16;
- dt.base = VmxAsm::vmx_vmread(guest::GDTR_BASE) as usize as *const _;
- }
- fn set_gdt(&self, _vcpu: &mut VirtCpu, dt: &x86::dtables::DescriptorTablePointer<u8>) {
- VmxAsm::vmx_vmwrite(guest::GDTR_LIMIT, dt.limit as u64);
- VmxAsm::vmx_vmwrite(guest::GDTR_BASE, dt.base as usize as u64);
- }
- fn is_vaild_cr0(&self, vcpu: &VirtCpu, _cr0: Cr0) -> bool {
- if vcpu.arch.is_guest_mode() {
- todo!()
- }
- // TODO: 判断vmx->nested->vmxon
- true
- }
- fn is_vaild_cr4(&self, vcpu: &VirtCpu, cr4: Cr4) -> bool {
- if cr4.contains(Cr4::CR4_ENABLE_VMX) && vcpu.arch.is_smm() {
- return false;
- }
- // TODO: 判断vmx->nested->vmxon
- return true;
- }
- fn post_set_cr3(&self, _vcpu: &VirtCpu, _cr3: u64) {
- // Do Nothing
- }
- fn vcpu_run(&self, vcpu: &mut VirtCpu) -> ExitFastpathCompletion {
- if unlikely(vmx_info().enable_vnmi && vcpu.vmx().loaded_vmcs().soft_vnmi_blocked) {
- todo!()
- }
- if unlikely(vcpu.vmx().emulation_required) {
- todo!()
- }
- if vcpu.vmx().ple_window_dirty {
- vcpu.vmx_mut().ple_window_dirty = false;
- VmxAsm::vmx_vmwrite(control::PLE_WINDOW, vcpu.vmx().ple_window as u64);
- }
- if vcpu.arch.is_register_dirty(KvmReg::VcpuRegsRsp) {
- VmxAsm::vmx_vmwrite(guest::RSP, vcpu.arch.regs[KvmReg::VcpuRegsRsp as usize]);
- }
- if vcpu.arch.is_register_dirty(KvmReg::VcpuRegsRip) {
- VmxAsm::vmx_vmwrite(guest::RIP, vcpu.arch.regs[KvmReg::VcpuRegsRip as usize]);
- }
- vcpu.arch.clear_dirty();
- let cr3: (PhysFrame, Cr3Flags) = Cr3::read();
- if unlikely(cr3 != vcpu.vmx().loaded_vmcs().host_state.cr3) {
- let cr3_combined: u64 =
- (cr3.0.start_address().as_u64() & 0xFFFF_FFFF_FFFF_F000) | (cr3.1.bits() & 0xFFF);
- VmxAsm::vmx_vmwrite(host::CR3, cr3_combined);
- vcpu.vmx().loaded_vmcs().host_state.cr3 = cr3;
- }
- let cr4 = unsafe { cr4() };
- if unlikely(cr4 != vcpu.vmx().loaded_vmcs().host_state.cr4) {
- VmxAsm::vmx_vmwrite(host::CR4, cr4.bits() as u64);
- vcpu.vmx().loaded_vmcs().host_state.cr4 = cr4;
- }
- // TODO: set_debugreg
- if vcpu.guest_debug.contains(GuestDebug::SINGLESTEP) {
- todo!()
- }
- vcpu.load_guest_xsave_state();
- // TODO: pt_guest_enter
- // TODO: atomic_switch_perf_msrs
- if vmx_info().enable_preemption_timer {
- // todo!()
- warn!("vmx_update_hv_timer TODO");
- }
- Vmx::vmx_vcpu_enter_exit(vcpu, vcpu.vmx().vmx_vcpu_run_flags());
- unsafe {
- load_ds(USER_DS);
- load_es(USER_DS);
- };
- // TODO: pt_guest_exit
- // TODO: kvm_load_host_xsave_state
- if vcpu.arch.is_guest_mode() {
- todo!()
- }
- if unlikely(vcpu.vmx().fail != 0) {
- return ExitFastpathCompletion::None;
- }
- if unlikely(
- vcpu.vmx().exit_reason.basic()
- == VmxExitReasonBasic::VM_ENTRY_FAILURE_MACHINE_CHECK_EVENT as u16,
- ) {
- todo!()
- }
- if unlikely(vcpu.vmx().exit_reason.failed_vmentry()) {
- return ExitFastpathCompletion::None;
- }
- vcpu.vmx().loaded_vmcs().launched = true;
- // TODO: 处理中断
- if vcpu.arch.is_guest_mode() {
- return ExitFastpathCompletion::None;
- }
- return Vmx::vmx_exit_handlers_fastpath(vcpu);
- }
- fn prepare_switch_to_guest(&self, vcpu: &mut VirtCpu) {
- // let cpu = smp_get_processor_id();
- let vmx = vcpu.vmx_mut();
- vmx.req_immediate_exit = false;
- if !vmx.guest_uret_msrs_loaded {
- vmx.guest_uret_msrs_loaded = true;
- for (idx, msr) in vmx.guest_uret_msrs.iter().enumerate() {
- if msr.load_into_hardware {
- x86_kvm_manager().kvm_set_user_return_msr(idx, msr.data, msr.mask);
- }
- }
- }
- // TODO: nested
- if vmx.guest_state_loaded {
- return;
- }
- // fixme: 这里读的是当前cpu的gsbase,正确安全做法应该为将gsbase设置为percpu变量
- let gs_base = unsafe { rdmsr(msr::IA32_KERNEL_GSBASE) };
- let current = ProcessManager::current_pcb();
- let mut pcb_arch = current.arch_info_irqsave();
- let fs_sel = fs().bits();
- let gs_sel = gs().bits();
- unsafe {
- pcb_arch.save_fsbase();
- pcb_arch.save_gsbase();
- }
- let fs_base = pcb_arch.fsbase();
- vmx.msr_host_kernel_gs_base = pcb_arch.gsbase() as u64;
- unsafe { wrmsr(msr::IA32_KERNEL_GSBASE, vmx.msr_guest_kernel_gs_base) };
- let mut loaded_vmcs = vmx.loaded_vmcs();
- let host_state = &mut loaded_vmcs.host_state;
- host_state.ldt_sel = unsafe { ldtr() }.bits();
- host_state.ds_sel = ds().bits();
- host_state.es_sel = es().bits();
- host_state.set_host_fsgs(fs_sel, gs_sel, fs_base, gs_base as usize);
- drop(loaded_vmcs);
- vmx.guest_state_loaded = true;
- }
- fn flush_tlb_all(&self, vcpu: &mut VirtCpu) {
- if vmx_info().enable_ept {
- VmxAsm::ept_sync_global();
- } else if vmx_info().has_invvpid_global() {
- VmxAsm::sync_vcpu_global();
- } else {
- VmxAsm::sync_vcpu_single(vcpu.vmx().vpid);
- // TODO: 嵌套:VmxAsm::sync_vcpu_single(vcpu.vmx().nested.vpid02);
- }
- }
- fn handle_exit_irqoff(&self, vcpu: &mut VirtCpu) {
- if vcpu.vmx().emulation_required {
- return;
- }
- let basic = VmxExitReasonBasic::from(vcpu.vmx().exit_reason.basic());
- if basic == VmxExitReasonBasic::EXTERNAL_INTERRUPT {
- Vmx::handle_external_interrupt_irqoff(vcpu);
- } else if basic == VmxExitReasonBasic::EXCEPTION_OR_NMI {
- //todo!()
- }
- }
- fn handle_exit(
- //vmx_handle_exit
- &self,
- vcpu: &mut VirtCpu,
- vm: &Vm,
- fastpath: ExitFastpathCompletion,
- ) -> Result<i32, SystemError> {
- let r = vmx_info().vmx_handle_exit(vcpu, vm, fastpath);
- if vcpu.vmx().exit_reason.bus_lock_detected() {
- todo!()
- }
- r
- }
- fn load_mmu_pgd(&self, vcpu: &mut VirtCpu, _vm: &Vm, root_hpa: u64, root_level: u32) {
- let guest_cr3;
- let eptp;
- if vmx_info().enable_ept {
- eptp = vmx_info().construct_eptp(vcpu, root_hpa, root_level);
- VmxAsm::vmx_vmwrite(control::EPTP_FULL, eptp);
- if !vmx_info().enable_unrestricted_guest
- && !vcpu.arch.cr0.contains(Cr0::CR0_ENABLE_PAGING)
- {
- todo!()
- } else if vcpu.arch.is_register_dirty(KvmReg::VcpuExregCr3) {
- guest_cr3 = vcpu.arch.cr3;
- debug!("load_mmu_pgd: guest_cr3 = {:#x}", guest_cr3);
- } else {
- return;
- }
- } else {
- todo!();
- }
- vcpu.load_pdptrs();
- VmxAsm::vmx_vmwrite(guest::CR3, guest_cr3);
- }
- }
- static mut VMX: Option<Vmx> = None;
- #[inline]
- pub fn vmx_info() -> &'static Vmx {
- unsafe { VMX.as_ref().unwrap() }
- }
- #[inline]
- pub fn vmx_info_mut() -> &'static mut Vmx {
- unsafe { VMX.as_mut().unwrap() }
- }
- #[inline(never)]
- pub fn init_vmx(vmx: Box<Vmx>) {
- static INIT_ONCE: AtomicBool = AtomicBool::new(false);
- if INIT_ONCE
- .compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
- .is_ok()
- {
- unsafe { VMX = Some(*vmx) };
- } else {
- panic!("init_vmx can only be called once");
- }
- }
- #[derive(Debug)]
- pub struct Vmx {
- pub host_idt_base: u64,
- pub vmcs_config: VmcsConfig,
- pub vmx_cap: VmxCapability,
- pub vpid_bitmap: SpinLock<AllocBitmap>,
- pub enable_vpid: bool,
- pub enable_ept: bool,
- pub enable_ept_ad: bool,
- pub enable_unrestricted_guest: bool,
- pub emulate_invalid_guest_state: bool,
- pub enable_flexpriority: bool,
- pub enable_vnmi: bool,
- pub enable_sgx: bool,
- pub enable_apicv: bool,
- pub enable_ipiv: bool,
- pub enable_pml: bool,
- pub enable_preemption_timer: bool,
- pub enable_vmware_backdoor: bool,
- pub nested: bool,
- pub ple_gap: u32,
- pub ple_window: u32,
- pub ple_window_grow: u32,
- pub ple_window_max: u32,
- pub ple_window_shrink: u32,
- pub pt_mode: ProcessorTraceMode,
- }
- impl Vmx {
- fn init(&mut self) {
- let mut bitmap = AllocBitmap::new(1 << 16);
- // 0为vpid的非法值
- bitmap.set(0, true);
- self.host_idt_base = Default::default();
- self.vmcs_config = Default::default();
- self.vmx_cap = Default::default();
- self.vpid_bitmap = SpinLock::new(bitmap);
- self.enable_vpid = true;
- self.enable_ept = true;
- self.enable_ept_ad = true;
- self.enable_unrestricted_guest = true;
- self.enable_flexpriority = true;
- self.enable_vnmi = true;
- self.enable_sgx = true;
- self.ple_gap = 128;
- self.ple_window = 4096;
- self.ple_window_grow = 2;
- self.ple_window_max = u32::MAX;
- self.ple_window_shrink = 0;
- self.enable_apicv = true;
- self.enable_ipiv = true;
- self.enable_pml = true;
- self.enable_preemption_timer = true;
- self.pt_mode = ProcessorTraceMode::System;
- self.emulate_invalid_guest_state = true;
- // 目前先不管嵌套虚拟化,后续再实现
- self.nested = false;
- self.enable_vmware_backdoor = false;
- }
- /*
- * Internal error codes that are used to indicate that MSR emulation encountered
- * an error that should result in #GP in the guest, unless userspace
- * handles it.
- */
- #[allow(dead_code)]
- pub const KVM_MSR_RET_INVALID: u32 = 2; /* in-kernel MSR emulation #GP condition */
- #[allow(dead_code)]
- pub const KVM_MSR_RET_FILTERED: u32 = 3; /* #GP due to userspace MSR filter */
- pub const MAX_POSSIBLE_PASSTHROUGH_MSRS: usize = 16;
- pub const VMX_POSSIBLE_PASSTHROUGH_MSRS: [u32; Self::MAX_POSSIBLE_PASSTHROUGH_MSRS] = [
- 0x48, // MSR_IA32_SPEC_CTRL
- 0x49, // MSR_IA32_PRED_CMD
- 0x10b, // MSR_IA32_FLUSH_CMD
- msr::IA32_TIME_STAMP_COUNTER,
- msr::IA32_FS_BASE,
- msr::IA32_GS_BASE,
- msr::IA32_KERNEL_GSBASE,
- 0x1c4, // MSR_IA32_XFD
- 0x1c5, // MSR_IA32_XFD_ERR
- msr::IA32_SYSENTER_CS,
- msr::IA32_SYSENTER_ESP,
- msr::IA32_SYSENTER_EIP,
- msr::MSR_CORE_C1_RESIDENCY,
- msr::MSR_CORE_C3_RESIDENCY,
- msr::MSR_CORE_C6_RESIDENCY,
- msr::MSR_CORE_C7_RESIDENCY,
- ];
- /// ### 查看CPU是否支持虚拟化
- #[allow(dead_code)]
- pub fn check_vmx_support() -> bool {
- let cpuid = CpuId::new();
- // Check to see if CPU is Intel (“GenuineIntel”).
- if let Some(vi) = cpuid.get_vendor_info() {
- if vi.as_str() != "GenuineIntel" {
- return false;
- }
- }
- // Check processor supports for Virtual Machine Extension (VMX) technology
- // CPUID.1:ECX.VMX[bit 5] = 1 (Intel Manual: 24.6 Discovering Support for VMX)
- if let Some(fi) = cpuid.get_feature_info() {
- if !fi.has_vmx() {
- return false;
- }
- }
- return true;
- }
- #[inline(never)]
- pub fn set_up_user_return_msrs() {
- const VMX_URET_MSRS_LIST: &[u32] = &[
- msr::IA32_FMASK,
- msr::IA32_LSTAR,
- msr::IA32_CSTAR,
- msr::IA32_EFER,
- msr::IA32_TSC_AUX,
- msr::IA32_STAR,
- // 这个寄存器会出错<,先注释掉
- // MSR_IA32_TSX_CTRL,
- ];
- let manager = x86_kvm_manager_mut();
- for msr in VMX_URET_MSRS_LIST {
- manager.add_user_return_msr(*msr);
- }
- }
- /// 初始化设置vmcs的config
- #[inline(never)]
- pub fn setup_vmcs_config(
- vmcs_config: &mut VmcsConfig,
- vmx_cap: &mut VmxCapability,
- ) -> Result<(), SystemError> {
- const VMCS_ENTRY_EXIT_PAIRS: &[VmcsEntryExitPair] = &[
- VmcsEntryExitPair::new(
- EntryControls::LOAD_IA32_PERF_GLOBAL_CTRL,
- ExitControls::LOAD_IA32_PERF_GLOBAL_CTRL,
- ),
- VmcsEntryExitPair::new(EntryControls::LOAD_IA32_PAT, ExitControls::LOAD_IA32_PAT),
- VmcsEntryExitPair::new(EntryControls::LOAD_IA32_EFER, ExitControls::LOAD_IA32_EFER),
- VmcsEntryExitPair::new(
- EntryControls::LOAD_IA32_BNDCFGS,
- ExitControls::CLEAR_IA32_BNDCFGS,
- ),
- VmcsEntryExitPair::new(
- EntryControls::LOAD_IA32_RTIT_CTL,
- ExitControls::CLEAR_IA32_RTIT_CTL,
- ),
- ];
- let mut cpu_based_exec_control = VmxFeat::adjust_primary_controls()?;
- let mut cpu_based_2nd_exec_control =
- if cpu_based_exec_control.contains(PrimaryControls::SECONDARY_CONTROLS) {
- VmxFeat::adjust_secondary_controls()?
- } else {
- SecondaryControls::empty()
- };
- if cpu_based_2nd_exec_control.contains(SecondaryControls::VIRTUALIZE_APIC) {
- cpu_based_exec_control.remove(PrimaryControls::USE_TPR_SHADOW)
- }
- if !cpu_based_exec_control.contains(PrimaryControls::USE_TPR_SHADOW) {
- cpu_based_2nd_exec_control.remove(
- SecondaryControls::VIRTUALIZE_APIC_REGISTER
- | SecondaryControls::VIRTUALIZE_X2APIC
- | SecondaryControls::VIRTUAL_INTERRUPT_DELIVERY,
- )
- }
- let cap = unsafe { rdmsr(msr::IA32_VMX_EPT_VPID_CAP) };
- vmx_cap.set_val_from_msr_val(cap);
- // 不支持ept但是读取到了值
- if !cpu_based_2nd_exec_control.contains(SecondaryControls::ENABLE_EPT)
- && !vmx_cap.ept.is_empty()
- {
- warn!("EPT CAP should not exist if not support. 1-setting enable EPT VM-execution control");
- return Err(SystemError::EIO);
- }
- if !cpu_based_2nd_exec_control.contains(SecondaryControls::ENABLE_VPID)
- && !vmx_cap.vpid.is_empty()
- {
- warn!("VPID CAP should not exist if not support. 1-setting enable VPID VM-execution control");
- return Err(SystemError::EIO);
- }
- let cpuid = CpuId::new();
- let cpu_extend_feat = cpuid
- .get_extended_feature_info()
- .ok_or(SystemError::ENOSYS)?;
- if !cpu_extend_feat.has_sgx() {
- cpu_based_2nd_exec_control.remove(SecondaryControls::ENCLS_EXITING);
- }
- let cpu_based_3rd_exec_control = 0;
- // if cpu_based_exec_control.contains(SecondaryControls::TERTIARY_CONTROLS) {
- // // Self::adjust_vmx_controls64(VmxFeature::IPI_VIRT, IA32_CTLS3)
- // todo!()
- // } else {
- // 0
- // };
- let vmxexit_control = VmxFeat::adjust_exit_controls()?;
- let pin_based_exec_control = VmxFeat::adjust_pin_based_controls()?;
- // TODO: broken timer?
- // https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/kvm/vmx/vmx.c#2676
- let vmentry_control = VmxFeat::adjust_entry_controls()?;
- for pair in VMCS_ENTRY_EXIT_PAIRS {
- let n_ctrl = pair.entry;
- let x_ctrl = pair.exit;
- // if !(vmentry_control.bits() & n_ctrl.bits) == !(vmxexit_control.bits() & x_ctrl.bits) {
- // continue;
- // }
- if (vmentry_control.contains(n_ctrl)) == (vmxexit_control.contains(x_ctrl)) {
- continue;
- }
- warn!(
- "Inconsistent VM-Entry/VM-Exit pair, entry = {:?}, exit = {:?}",
- vmentry_control & n_ctrl,
- vmxexit_control & x_ctrl,
- );
- return Err(SystemError::EIO);
- }
- let basic = unsafe { rdmsr(msr::IA32_VMX_BASIC) };
- let vmx_msr_high = (basic >> 32) as u32;
- let vmx_msr_low = basic as u32;
- // 64位cpu,VMX_BASIC[48] == 0
- if vmx_msr_high & (1 << 16) != 0 {
- return Err(SystemError::EIO);
- }
- // 判断是否为写回(WB)
- if (vmx_msr_high >> 18) & 15 != 6 {
- return Err(SystemError::EIO);
- }
- let misc_msr = unsafe { rdmsr(msr::IA32_VMX_MISC) };
- vmcs_config.size = vmx_msr_high & 0x1fff;
- vmcs_config.basic_cap = vmx_msr_high & !0x1fff;
- vmcs_config.revision_id = vmx_msr_low;
- vmcs_config.pin_based_exec_ctrl = pin_based_exec_control;
- vmcs_config.cpu_based_exec_ctrl = cpu_based_exec_control;
- vmcs_config.cpu_based_2nd_exec_ctrl = cpu_based_2nd_exec_control;
- vmcs_config.cpu_based_3rd_exec_ctrl = cpu_based_3rd_exec_control;
- vmcs_config.vmentry_ctrl = vmentry_control;
- vmcs_config.vmexit_ctrl = vmxexit_control;
- vmcs_config.misc = misc_msr;
- Ok(())
- }
- fn adjust_vmx_controls(ctl_min: u32, ctl_opt: u32, msr: u32) -> Result<u32, SystemError> {
- let mut ctl = ctl_min | ctl_opt;
- let val = unsafe { rdmsr(msr) };
- let low = val as u32;
- let high = (val >> 32) as u32;
- ctl &= high;
- ctl |= low;
- if ctl_min & !ctl != 0 {
- return Err(SystemError::EIO);
- }
- return Ok(ctl);
- }
- #[allow(dead_code)]
- fn adjust_vmx_controls64(ctl_opt: u32, msr: u32) -> u32 {
- let allow = unsafe { rdmsr(msr) } as u32;
- ctl_opt & allow
- }
- pub fn alloc_vpid(&self) -> Option<usize> {
- if !self.enable_vpid {
- return None;
- }
- let mut bitmap_guard = self.vpid_bitmap.lock();
- let idx = bitmap_guard.first_false_index();
- if let Some(idx) = idx {
- bitmap_guard.set(idx, true);
- }
- return idx;
- }
- #[allow(dead_code)]
- pub fn free_vpid(&self, vpid: Option<usize>) {
- if !self.enable_vpid || vpid.is_none() {
- return;
- }
- self.vpid_bitmap.lock().set(vpid.unwrap(), false);
- }
- pub fn is_valid_passthrough_msr(msr: u32) -> bool {
- match msr {
- 0x800..0x8ff => {
- // x2Apic msr寄存器
- return true;
- }
- msr::MSR_IA32_RTIT_STATUS
- | msr::MSR_IA32_RTIT_OUTPUT_BASE
- | msr::MSR_IA32_RTIT_OUTPUT_MASK_PTRS
- | msr::MSR_IA32_CR3_MATCH
- | msr::MSR_LBR_SELECT
- | msr::MSR_LASTBRANCH_TOS => {
- return true;
- }
- msr::MSR_IA32_ADDR0_START..msr::MSR_IA32_ADDR3_END => {
- return true;
- }
- 0xdc0..0xddf => {
- // MSR_LBR_INFO_0 ... MSR_LBR_INFO_0 + 31
- return true;
- }
- 0x680..0x69f => {
- // MSR_LBR_NHM_FROM ... MSR_LBR_NHM_FROM + 31
- return true;
- }
- 0x6c0..0x6df => {
- // MSR_LBR_NHM_TO ... MSR_LBR_NHM_TO + 31
- return true;
- }
- 0x40..0x48 => {
- // MSR_LBR_CORE_FROM ... MSR_LBR_CORE_FROM + 8
- return true;
- }
- 0x60..0x68 => {
- // MSR_LBR_CORE_TO ... MSR_LBR_CORE_TO + 8
- return true;
- }
- _ => {
- return Self::possible_passthrough_msr_slot(msr).is_some();
- }
- }
- }
- pub fn vpid_sync_context(&self, vpid: u16) {
- if self.has_invvpid_single() {
- VmxAsm::sync_vcpu_single(vpid);
- } else if vpid != 0 {
- VmxAsm::sync_vcpu_global();
- }
- }
- pub fn possible_passthrough_msr_slot(msr: u32) -> Option<usize> {
- for (idx, val) in Self::VMX_POSSIBLE_PASSTHROUGH_MSRS.iter().enumerate() {
- if *val == msr {
- return Some(idx);
- }
- }
- return None;
- }
- pub fn tdp_enabled(&self) -> bool {
- self.enable_ept
- }
- fn setup_l1d_flush(&self) {
- // TODO:先这样写
- *L1TF_VMX_MITIGATION.write() = VmxL1dFlushState::NotRequired;
- }
- pub fn construct_eptp(&self, vcpu: &mut VirtCpu, root_hpa: u64, root_level: u32) -> u64 {
- let mut eptp = VMX_EPTP_MT_WB;
- eptp |= if root_level == 5 {
- VMX_EPTP_PWL_5
- } else {
- VMX_EPTP_PWL_4
- };
- if self.enable_ept_ad && !vcpu.arch.is_guest_mode() {
- eptp |= VMX_EPTP_AD_ENABLE_BIT;
- }
- eptp |= root_hpa;
- return eptp;
- }
- fn vmx_reset_vcpu(&mut self, vcpu: &mut VirtCpu, vm: &Vm) {
- self.init_vmcs(vcpu, vm);
- if self.nested {
- todo!()
- }
- // TODO: vcpu_setup_sgx_lepubkeyhash
- // TODO: nested
- vcpu.arch.microcode_version = 0x100000000;
- let vmx = vcpu.vmx_mut();
- vmx.msr_ia32_feature_control_valid_bits = 1 << 0;
- vmx.post_intr_desc.control.set_nv(0xf2);
- vmx.post_intr_desc.control.set_sn(true);
- }
- fn init_vmcs(&mut self, vcpu: &mut VirtCpu, vm: &Vm) {
- let kvm_vmx = vm.kvm_vmx();
- if vmx_info().nested {
- todo!()
- }
- if vmx_info().has_msr_bitmap() {
- debug!(
- "msr_bitmap addr 0x{:x}",
- vcpu.vmx().vmcs01.lock().msr_bitmap.phys_addr() as u64
- );
- VmxAsm::vmx_vmwrite(
- control::MSR_BITMAPS_ADDR_FULL,
- vcpu.vmx().vmcs01.lock().msr_bitmap.phys_addr() as u64,
- )
- }
- VmxAsm::vmx_vmwrite(guest::LINK_PTR_FULL, u64::MAX);
- let mut loaded_vmcs = vcpu.vmx().loaded_vmcs.lock();
- loaded_vmcs.controls_set(
- ControlsType::Pin,
- self.get_pin_based_exec_controls(vcpu).bits() as u64,
- );
- loaded_vmcs.controls_set(
- ControlsType::Exec,
- self.get_exec_controls(vcpu, &vm.arch).bits() as u64,
- );
- if self.has_sceondary_exec_ctrls() {
- loaded_vmcs.controls_set(
- ControlsType::SecondaryExec,
- self.get_secondary_exec_controls(vcpu, vm).bits() as u64,
- )
- }
- if self.has_tertiary_exec_ctrls() {
- todo!()
- }
- drop(loaded_vmcs);
- if self.enable_apicv && vcpu.arch.lapic_in_kernel() {
- VmxAsm::vmx_vmwrite(control::EOI_EXIT0_FULL, 0);
- VmxAsm::vmx_vmwrite(control::EOI_EXIT1_FULL, 0);
- VmxAsm::vmx_vmwrite(control::EOI_EXIT2_FULL, 0);
- VmxAsm::vmx_vmwrite(control::EOI_EXIT3_FULL, 0);
- VmxAsm::vmx_vmwrite(guest::INTERRUPT_STATUS, 0);
- VmxAsm::vmx_vmwrite(control::POSTED_INTERRUPT_NOTIFICATION_VECTOR, 0xf2);
- VmxAsm::vmx_vmwrite(control::POSTED_INTERRUPT_DESC_ADDR_FULL, unsafe {
- MMArch::virt_2_phys(VirtAddr::new(
- &vcpu.vmx().post_intr_desc as *const _ as usize,
- ))
- .unwrap()
- .data() as u64
- })
- }
- if self.enable_apicv && vcpu.arch.lapic_in_kernel() {
- // PID_POINTER_TABLE
- VmxAsm::vmx_vmwrite(0x2042, unsafe {
- MMArch::virt_2_phys(VirtAddr::new(kvm_vmx.pid_table().as_ptr() as usize))
- .unwrap()
- .data() as u64
- });
- // LAST_PID_POINTER_INDEX
- VmxAsm::vmx_vmwrite(0x08, vm.arch.max_vcpu_ids as u64 - 1);
- }
- if !vm.arch.pause_in_guest {
- VmxAsm::vmx_vmwrite(control::PLE_GAP, self.ple_gap as u64);
- vcpu.vmx_mut().ple_window = self.ple_window;
- vcpu.vmx_mut().ple_window_dirty = true;
- }
- if vm
- .arch
- .notify_vmexit_flags
- .contains(NotifyVmExitFlags::KVM_X86_NOTIFY_VMEXIT_ENABLED)
- {
- // NOTIFY_WINDOW
- VmxAsm::vmx_vmwrite(0x4024, vm.arch.notify_window as u64);
- }
- VmxAsm::vmx_vmwrite(control::PAGE_FAULT_ERR_CODE_MASK, 0);
- VmxAsm::vmx_vmwrite(control::PAGE_FAULT_ERR_CODE_MATCH, 0);
- VmxAsm::vmx_vmwrite(control::CR3_TARGET_COUNT, 0);
- VmxAsm::vmx_vmwrite(host::FS_SELECTOR, 0);
- VmxAsm::vmx_vmwrite(host::GS_SELECTOR, 0);
- self.set_constant_host_state(vcpu);
- VmxAsm::vmx_vmwrite(host::FS_BASE, 0);
- VmxAsm::vmx_vmwrite(host::GS_BASE, 0);
- if self.has_vmfunc() {
- VmxAsm::vmx_vmwrite(control::VM_FUNCTION_CONTROLS_FULL, 0);
- }
- VmxAsm::vmx_vmwrite(control::VMEXIT_MSR_STORE_COUNT, 0);
- VmxAsm::vmx_vmwrite(control::VMEXIT_MSR_LOAD_COUNT, 0);
- VmxAsm::vmx_vmwrite(control::VMEXIT_MSR_LOAD_ADDR_FULL, unsafe {
- MMArch::virt_2_phys(VirtAddr::new(
- vcpu.vmx().msr_autoload.host.val.as_ptr() as *const _ as usize,
- ))
- .unwrap()
- .data() as u64
- });
- VmxAsm::vmx_vmwrite(control::VMENTRY_MSR_LOAD_COUNT, 0);
- VmxAsm::vmx_vmwrite(control::VMENTRY_MSR_LOAD_ADDR_FULL, unsafe {
- MMArch::virt_2_phys(VirtAddr::new(
- vcpu.vmx().msr_autoload.guest.val.as_ptr() as usize
- ))
- .unwrap()
- .data() as u64
- });
- if self
- .vmcs_config
- .vmentry_ctrl
- .contains(EntryControls::LOAD_IA32_PAT)
- {
- VmxAsm::vmx_vmwrite(guest::IA32_PAT_FULL, vcpu.arch.pat) //todo
- }
- let mut loaded_vmcs = vcpu.vmx().loaded_vmcs.lock();
- loaded_vmcs.controls_set(
- ControlsType::VmExit,
- self.get_vmexit_controls().bits() as u64,
- );
- loaded_vmcs.controls_set(
- ControlsType::VmEntry,
- self.get_vmentry_controls().bits() as u64,
- );
- drop(loaded_vmcs);
- vcpu.arch.cr0_guest_owned_bits = self.l1_guest_owned_cr0_bits();
- VmxAsm::vmx_vmwrite(
- control::CR0_GUEST_HOST_MASK,
- (!vcpu.arch.cr0_guest_owned_bits).bits() as u64,
- );
- self.set_cr4_guest_host_mask(&mut vcpu.arch);
- if vcpu.vmx().vpid != 0 {
- VmxAsm::vmx_vmwrite(control::VPID, vcpu.vmx().vpid as u64);
- }
- if self.has_xsaves() {
- VmxAsm::vmx_vmwrite(control::XSS_EXITING_BITMAP_FULL, 0);
- }
- if self.enable_pml {
- VmxAsm::vmx_vmwrite(control::PML_ADDR_FULL, unsafe {
- MMArch::virt_2_phys(VirtAddr::new(vcpu.vmx().pml_pg.as_ref().as_ptr() as usize))
- .unwrap()
- .data() as u64
- });
- VmxAsm::vmx_vmwrite(guest::PML_INDEX, VmxVCpuPriv::PML_ENTITY_NUM as u64 - 1);
- }
- // TODO: vmx_write_encls_bitmap
- if self.pt_mode == ProcessorTraceMode::HostGuest {
- todo!()
- }
- VmxAsm::vmx_vmwrite(guest::IA32_SYSENTER_CS, 0);
- VmxAsm::vmx_vmwrite(guest::IA32_SYSENTER_ESP, 0);
- VmxAsm::vmx_vmwrite(guest::IA32_SYSENTER_EIP, 0);
- VmxAsm::vmx_vmwrite(guest::IA32_DEBUGCTL_FULL, 0);
- if self.has_tpr_shadow() {
- VmxAsm::vmx_vmwrite(control::VIRT_APIC_ADDR_FULL, 0);
- if vcpu.arch.lapic_in_kernel() {
- VmxAsm::vmx_vmwrite(control::VIRT_APIC_ADDR_FULL, unsafe {
- MMArch::virt_2_phys(VirtAddr::new(vcpu.arch.lapic().regs.as_ptr() as usize))
- .unwrap()
- .data() as u64
- });
- }
- VmxAsm::vmx_vmwrite(control::TPR_THRESHOLD, 0);
- }
- self.setup_uret_msrs(vcpu);
- }
- /// 打印VMCS信息用于debug
- pub fn dump_vmcs(&self, vcpu: &VirtCpu) {
- let vmentry_ctl = unsafe {
- EntryControls::from_bits_unchecked(self.vmread(control::VMENTRY_CONTROLS) as u32)
- };
- let vmexit_ctl = unsafe {
- ExitControls::from_bits_unchecked(self.vmread(control::VMEXIT_CONTROLS) as u32)
- };
- let cpu_based_exec_ctl = PrimaryControls::from_bits_truncate(
- self.vmread(control::PRIMARY_PROCBASED_EXEC_CONTROLS) as u32,
- );
- let pin_based_exec_ctl = PinbasedControls::from_bits_truncate(
- self.vmread(control::PINBASED_EXEC_CONTROLS) as u32,
- );
- // let cr4 = Cr4::from_bits_truncate(self.vmread(guest::CR4) as usize);
- let secondary_exec_control = if self.has_sceondary_exec_ctrls() {
- unsafe {
- SecondaryControls::from_bits_unchecked(
- self.vmread(control::SECONDARY_PROCBASED_EXEC_CONTROLS) as u32,
- )
- }
- } else {
- SecondaryControls::empty()
- };
- if self.has_tertiary_exec_ctrls() {
- todo!()
- }
- error!(
- "VMCS addr: 0x{:x}, last attempted VM-entry on CPU {:?}",
- vcpu.vmx().loaded_vmcs().vmcs.lock().as_ref() as *const _ as usize,
- vcpu.arch.last_vmentry_cpu
- );
- error!("--- GUEST STATE ---");
- error!(
- "CR0: actual = 0x{:x}, shadow = 0x{:x}, gh_mask = 0x{:x}",
- self.vmread(guest::CR0),
- self.vmread(control::CR0_READ_SHADOW),
- self.vmread(control::CR0_GUEST_HOST_MASK)
- );
- error!(
- "CR4: actual = 0x{:x}, shadow = 0x{:x}, gh_mask = 0x{:x}",
- self.vmread(guest::CR4),
- self.vmread(control::CR4_READ_SHADOW),
- self.vmread(control::CR4_GUEST_HOST_MASK)
- );
- error!("CR3: actual = 0x{:x}", self.vmread(guest::CR3));
- if self.has_ept() {
- error!(
- "PDPTR0 = 0x{:x}, PDPTR1 = 0x{:x}",
- self.vmread(guest::PDPTE0_FULL),
- self.vmread(guest::PDPTE1_FULL)
- );
- error!(
- "PDPTR2 = 0x{:x}, PDPTR3 = 0x{:x}",
- self.vmread(guest::PDPTE2_FULL),
- self.vmread(guest::PDPTE3_FULL)
- );
- }
- error!(
- "RSP = 0x{:x}, RIP = 0x{:x}",
- self.vmread(guest::RSP),
- self.vmread(guest::RIP)
- );
- error!(
- "RFLAGS = 0x{:x}, DR7 = 0x{:x}",
- self.vmread(guest::RFLAGS),
- self.vmread(guest::DR7)
- );
- error!(
- "Sysenter RSP = 0x{:x}, CS:RIP = 0x{:x}:0x{:x}",
- self.vmread(guest::IA32_SYSENTER_ESP),
- self.vmread(guest::IA32_SYSENTER_CS),
- self.vmread(guest::IA32_SYSENTER_EIP),
- );
- self.dump_sel("CS: ", guest::CS_SELECTOR);
- self.dump_sel("DS: ", guest::DS_SELECTOR);
- self.dump_sel("SS: ", guest::SS_SELECTOR);
- self.dump_sel("ES: ", guest::ES_SELECTOR);
- self.dump_sel("FS: ", guest::FS_SELECTOR);
- self.dump_sel("GS: ", guest::GS_SELECTOR);
- self.dump_dtsel("GDTR: ", guest::GDTR_LIMIT);
- self.dump_sel("LDTR: ", guest::LDTR_SELECTOR);
- self.dump_dtsel("IDTR: ", guest::IDTR_LIMIT);
- self.dump_sel("TR: ", guest::TR_SELECTOR);
- let efer_slot = vcpu
- .vmx()
- .msr_autoload
- .guest
- .find_loadstore_msr_slot(msr::IA32_EFER);
- if vmentry_ctl.contains(EntryControls::LOAD_IA32_EFER) {
- error!("EFER = 0x{:x}", self.vmread(guest::IA32_EFER_FULL));
- } else if let Some(slot) = efer_slot {
- error!(
- "EFER = 0x{:x} (autoload)",
- vcpu.vmx().msr_autoload.guest.val[slot].data
- );
- } else if vmentry_ctl.contains(EntryControls::IA32E_MODE_GUEST) {
- error!(
- "EFER = 0x{:x} (effective)",
- vcpu.arch.efer | (EferFlags::LONG_MODE_ACTIVE | EferFlags::LONG_MODE_ENABLE)
- );
- } else {
- error!(
- "EFER = 0x{:x} (effective)",
- vcpu.arch.efer & !(EferFlags::LONG_MODE_ACTIVE | EferFlags::LONG_MODE_ENABLE)
- );
- }
- if vmentry_ctl.contains(EntryControls::LOAD_IA32_PAT) {
- error!("PAT = 0x{:x}", self.vmread(guest::IA32_PAT_FULL));
- }
- error!(
- "DebugCtl = 0x{:x}, DebugExceptions = 0x{:x}",
- self.vmread(guest::IA32_DEBUGCTL_FULL),
- self.vmread(guest::PENDING_DBG_EXCEPTIONS)
- );
- if self.has_load_perf_global_ctrl()
- && vmentry_ctl.contains(EntryControls::LOAD_IA32_PERF_GLOBAL_CTRL)
- {
- error!(
- "PerfGlobCtl = 0x{:x}",
- self.vmread(guest::IA32_PERF_GLOBAL_CTRL_FULL)
- );
- }
- if vmentry_ctl.contains(EntryControls::LOAD_IA32_BNDCFGS) {
- error!("BndCfgS = 0x{:x}", self.vmread(guest::IA32_BNDCFGS_FULL));
- }
- error!(
- "Interruptibility = 0x{:x}, ActivityState = 0x{:x}",
- self.vmread(guest::INTERRUPT_STATUS),
- self.vmread(guest::ACTIVITY_STATE)
- );
- if secondary_exec_control.contains(SecondaryControls::VIRTUAL_INTERRUPT_DELIVERY) {
- error!(
- "InterruptStatus = 0x{:x}",
- self.vmread(guest::INTERRUPT_STATUS)
- );
- }
- if self.vmread(control::VMENTRY_MSR_LOAD_COUNT) > 0 {
- self.dump_msrs("guest autoload", &vcpu.vmx().msr_autoload.guest);
- }
- if self.vmread(control::VMEXIT_MSR_LOAD_COUNT) > 0 {
- self.dump_msrs("guest autostore", &vcpu.vmx().msr_autostore);
- }
- error!("\n--- HOST STATE ---");
- error!(
- "RIP = 0x{:x}, RSP = 0x{:x}",
- self.vmread(host::RIP),
- self.vmread(host::RSP)
- );
- error!(
- "CS = 0x{:x}, SS = 0x{:x}, DS = 0x{:x}, ES = 0x{:x}, FS = 0x{:x}, GS = 0x{:x}, TR = 0x{:x}",
- self.vmread(host::CS_SELECTOR),
- self.vmread(host::SS_SELECTOR),
- self.vmread(host::DS_SELECTOR),
- self.vmread(host::ES_SELECTOR),
- self.vmread(host::FS_SELECTOR),
- self.vmread(host::GS_SELECTOR),
- self.vmread(host::TR_SELECTOR)
- );
- error!(
- "FSBase = 0x{:x}, GSBase = 0x{:x}, TRBase = 0x{:x}",
- self.vmread(host::FS_BASE),
- self.vmread(host::GS_BASE),
- self.vmread(host::TR_BASE),
- );
- error!(
- "GDTBase = 0x{:x}, IDTBase = 0x{:x}",
- self.vmread(host::GDTR_BASE),
- self.vmread(host::IDTR_BASE),
- );
- error!(
- "CR0 = 0x{:x}, CR3 = 0x{:x}, CR4 = 0x{:x}",
- self.vmread(host::CR0),
- self.vmread(host::CR3),
- self.vmread(host::CR4),
- );
- error!(
- "Sysenter RSP = 0x{:x}, CS:RIP=0x{:x}:0x{:x}",
- self.vmread(host::IA32_SYSENTER_ESP),
- self.vmread(host::IA32_SYSENTER_CS),
- self.vmread(host::IA32_SYSENTER_EIP),
- );
- if vmexit_ctl.contains(ExitControls::LOAD_IA32_EFER) {
- error!("EFER = 0x{:x}", self.vmread(host::IA32_EFER_FULL));
- }
- if vmexit_ctl.contains(ExitControls::LOAD_IA32_PAT) {
- error!("PAT = 0x{:x}", self.vmread(host::IA32_PAT_FULL));
- }
- if self.has_load_perf_global_ctrl()
- && vmexit_ctl.contains(ExitControls::LOAD_IA32_PERF_GLOBAL_CTRL)
- {
- error!(
- "PerfGlobCtl = 0x{:x}",
- self.vmread(host::IA32_PERF_GLOBAL_CTRL_FULL)
- );
- }
- if self.vmread(control::VMEXIT_MSR_LOAD_COUNT) > 0 {
- self.dump_msrs("host autoload", &vcpu.vmx().msr_autoload.host);
- }
- error!("\n--- CONTROL STATE ---");
- error!(
- "\nCPUBased = {:?},\nSecondaryExec = 0x{:x},\nTertiaryExec = 0(Unused)",
- cpu_based_exec_ctl, secondary_exec_control,
- );
- error!(
- "\nPinBased = {:?},\nEntryControls = {:?},\nExitControls = {:?}",
- pin_based_exec_ctl, vmentry_ctl, vmexit_ctl,
- );
- error!(
- "ExceptionBitmap = 0x{:x}, PFECmask = 0x{:x}, PFECmatch = 0x{:x}",
- self.vmread(control::EXCEPTION_BITMAP),
- self.vmread(control::PAGE_FAULT_ERR_CODE_MASK),
- self.vmread(control::PAGE_FAULT_ERR_CODE_MATCH),
- );
- error!(
- "VMEntry: intr_info = 0x{:x}, errcode = 0x{:x}, ilen = 0x{:x}",
- self.vmread(control::VMENTRY_INTERRUPTION_INFO_FIELD),
- self.vmread(control::VMENTRY_EXCEPTION_ERR_CODE),
- self.vmread(control::VMENTRY_INSTRUCTION_LEN),
- );
- error!(
- "VMExit: intr_info = 0x{:x}, errcode = 0x{:x}, ilen = 0x{:x}",
- self.vmread(ro::VMEXIT_INSTRUCTION_INFO),
- self.vmread(ro::VMEXIT_INTERRUPTION_ERR_CODE),
- self.vmread(ro::VMEXIT_INSTRUCTION_LEN),
- );
- error!(
- " reason = 0x{:x}, qualification = 0x{:x}",
- self.vmread(ro::EXIT_REASON),
- self.vmread(ro::EXIT_QUALIFICATION),
- );
- error!(
- "IDTVectoring: info = 0x{:x}, errcode = 0x{:x}",
- self.vmread(ro::IDT_VECTORING_INFO),
- self.vmread(ro::IDT_VECTORING_ERR_CODE),
- );
- error!("TSC Offset = 0x{:x}", self.vmread(control::TSC_OFFSET_FULL));
- if secondary_exec_control.contains(SecondaryControls::USE_TSC_SCALING) {
- error!(
- "TSC Multiplier = 0x{:x}",
- self.vmread(control::TSC_MULTIPLIER_FULL)
- );
- }
- if cpu_based_exec_ctl.contains(PrimaryControls::USE_TPR_SHADOW) {
- if secondary_exec_control.contains(SecondaryControls::VIRTUAL_INTERRUPT_DELIVERY) {
- let status = self.vmread(guest::INTERRUPT_STATUS);
- error!("SVI|RVI = 0x{:x}|0x{:x}", status >> 8, status & 0xff);
- }
- error!(
- "TPR Threshold = 0x{:x}",
- self.vmread(control::TPR_THRESHOLD)
- );
- if secondary_exec_control.contains(SecondaryControls::VIRTUALIZE_APIC) {
- error!(
- "APIC-access addr = 0x{:x}",
- self.vmread(control::APIC_ACCESS_ADDR_FULL)
- );
- }
- error!(
- "virt-APIC addr = 0x{:x}",
- self.vmread(control::VIRT_APIC_ADDR_FULL)
- );
- }
- if pin_based_exec_ctl.contains(PinbasedControls::POSTED_INTERRUPTS) {
- error!(
- "PostedIntrVec = 0x{:x}",
- self.vmread(control::POSTED_INTERRUPT_NOTIFICATION_VECTOR)
- );
- }
- if secondary_exec_control.contains(SecondaryControls::ENABLE_EPT) {
- error!("EPT pointer = 0x{:x}", self.vmread(control::EPTP_FULL));
- }
- if secondary_exec_control.contains(SecondaryControls::PAUSE_LOOP_EXITING) {
- error!(
- "PLE Gap = 0x{:x}, Window = 0x{:x}",
- self.vmread(control::PLE_GAP),
- self.vmread(control::PLE_WINDOW)
- );
- }
- if secondary_exec_control.contains(SecondaryControls::ENABLE_VPID) {
- error!("Virtual processor ID = 0x{:x}", self.vmread(control::VPID));
- }
- }
- pub fn dump_sel(&self, name: &'static str, sel: u32) {
- error!(
- "{name} sel = 0x{:x}, attr = 0x{:x}, limit = 0x{:x}, base = 0x{:x}",
- self.vmread(sel),
- self.vmread(sel + guest::ES_ACCESS_RIGHTS - guest::ES_SELECTOR),
- self.vmread(sel + guest::ES_LIMIT - guest::ES_SELECTOR),
- self.vmread(sel + guest::ES_BASE - guest::ES_SELECTOR),
- );
- }
- pub fn dump_dtsel(&self, name: &'static str, limit: u32) {
- error!(
- "{name} limit = 0x{:x}, base = 0x{:x}",
- self.vmread(limit),
- self.vmread(limit + guest::GDTR_BASE - guest::GDTR_LIMIT)
- );
- }
- pub fn dump_msrs(&self, name: &'static str, msr: &VmxMsrs) {
- error!("MSR {name}:");
- for (idx, msr) in msr.val.iter().enumerate() {
- error!("{idx}: msr = 0x{:x}, value = 0x{:x}", msr.index, msr.data);
- }
- }
- #[inline]
- pub fn vmread(&self, field: u32) -> u64 {
- VmxAsm::vmx_vmread(field)
- }
- fn setup_uret_msrs(&self, vcpu: &mut VirtCpu) {
- // 是否加载syscall相关msr
- let load_syscall_msrs =
- vcpu.arch.is_long_mode() && vcpu.arch.efer.contains(EferFlags::SYSTEM_CALL_EXTENSIONS);
- self.setup_uret_msr(vcpu, msr::IA32_STAR, load_syscall_msrs);
- self.setup_uret_msr(vcpu, msr::IA32_LSTAR, load_syscall_msrs);
- self.setup_uret_msr(vcpu, msr::IA32_FMASK, load_syscall_msrs);
- let load_efer = self.update_transition_efer(vcpu);
- self.setup_uret_msr(vcpu, msr::IA32_EFER, load_efer);
- // TODO: MSR_TSC_AUX
- self.setup_uret_msr(
- vcpu,
- msr::MSR_IA32_TSX_CTRL,
- CpuId::default()
- .get_extended_feature_info()
- .unwrap()
- .has_rtm(),
- );
- vcpu.vmx_mut().guest_uret_msrs_loaded = false;
- }
- fn setup_uret_msr(&self, vcpu: &mut VirtCpu, msr: u32, load_into_hardware: bool) {
- let uret_msr = vcpu.vmx_mut().find_uret_msr_mut(msr);
- if let Some((_idx, msr)) = uret_msr {
- msr.load_into_hardware = load_into_hardware;
- }
- }
- fn update_transition_efer(&self, vcpu: &mut VirtCpu) -> bool {
- let mut guest_efer = vcpu.arch.efer;
- let mut ignore_efer = EferFlags::empty();
- if !self.enable_ept {
- guest_efer.insert(EferFlags::NO_EXECUTE_ENABLE);
- }
- ignore_efer.insert(EferFlags::SYSTEM_CALL_EXTENSIONS);
- ignore_efer.insert(EferFlags::LONG_MODE_ACTIVE | EferFlags::LONG_MODE_ENABLE);
- if guest_efer.contains(EferFlags::LONG_MODE_ACTIVE) {
- ignore_efer.remove(EferFlags::SYSTEM_CALL_EXTENSIONS);
- }
- if self.has_load_ia32_efer()
- || (self.enable_ept
- && (vcpu.arch.efer ^ x86_kvm_manager().host_efer)
- .contains(EferFlags::NO_EXECUTE_ENABLE))
- {
- if !guest_efer.contains(EferFlags::LONG_MODE_ACTIVE) {
- guest_efer.remove(EferFlags::LONG_MODE_ENABLE);
- }
- if guest_efer != x86_kvm_manager().host_efer {
- vcpu.vmx_mut().add_atomic_switch_msr(
- msr::IA32_EFER,
- guest_efer.bits(),
- x86_kvm_manager().host_efer.bits(),
- false,
- );
- } else {
- vcpu.vmx_mut().clear_atomic_switch_msr(msr::IA32_EFER);
- }
- return false;
- }
- let idx = x86_kvm_manager().find_user_return_msr_idx(msr::IA32_EFER);
- if let Some(i) = idx {
- vcpu.vmx_mut().clear_atomic_switch_msr(msr::IA32_EFER);
- guest_efer.remove(ignore_efer);
- guest_efer.insert(x86_kvm_manager().host_efer & ignore_efer);
- vcpu.vmx_mut().guest_uret_msrs[i].data = guest_efer.bits();
- vcpu.vmx_mut().guest_uret_msrs[i].mask = (!ignore_efer).bits();
- return true;
- } else {
- return false;
- }
- }
- fn set_cr4_guest_host_mask(&self, arch: &mut VirtCpuArch) {
- arch.cr4_guest_owned_bits =
- x86_kvm_manager().possible_cr4_guest & (!arch.cr4_guest_rsvd_bits);
- if !self.enable_ept {
- arch.cr4_guest_owned_bits
- .remove(x86_kvm_manager().cr4_tlbflush_bits);
- arch.cr4_guest_owned_bits
- .remove(x86_kvm_manager().cr4_pdptr_bits);
- }
- if arch.is_guest_mode() {
- // 嵌套todo
- todo!()
- }
- VmxAsm::vmx_vmwrite(
- control::CR4_GUEST_HOST_MASK,
- (!arch.cr4_guest_owned_bits).bits() as u64,
- );
- }
- fn l1_guest_owned_cr0_bits(&self) -> Cr0 {
- let mut cr0 = x86_kvm_manager().possible_cr0_guest;
- if !self.enable_ept {
- cr0.remove(Cr0::CR0_WRITE_PROTECT)
- }
- return cr0;
- }
- /// 设置在guest生命周期中host不变的部分
- fn set_constant_host_state(&self, vcpu: &mut VirtCpu) {
- let loaded_vmcs_host_state = &mut vcpu.vmx().loaded_vmcs.lock().host_state;
- VmxAsm::vmx_vmwrite(host::CR0, unsafe { cr0() }.bits() as u64);
- let cr3: (PhysFrame, Cr3Flags) = Cr3::read();
- let cr3_combined: u64 =
- (cr3.0.start_address().as_u64() & 0xFFFF_FFFF_FFFF_F000) | (cr3.1.bits() & 0xFFF);
- VmxAsm::vmx_vmwrite(host::CR3, cr3_combined);
- loaded_vmcs_host_state.cr3 = cr3;
- let cr4 = unsafe { cr4() };
- VmxAsm::vmx_vmwrite(host::CR4, cr4.bits() as u64);
- loaded_vmcs_host_state.cr4 = cr4;
- VmxAsm::vmx_vmwrite(
- host::CS_SELECTOR,
- (segmentation::cs().bits() & (!0x07)).into(),
- );
- VmxAsm::vmx_vmwrite(host::DS_SELECTOR, 0);
- VmxAsm::vmx_vmwrite(host::ES_SELECTOR, 0);
- VmxAsm::vmx_vmwrite(
- host::SS_SELECTOR,
- (segmentation::ds().bits() & (!0x07)).into(),
- );
- VmxAsm::vmx_vmwrite(
- host::TR_SELECTOR,
- (unsafe { x86::task::tr().bits() } & (!0x07)).into(),
- );
- VmxAsm::vmx_vmwrite(host::IDTR_BASE, self.host_idt_base);
- VmxAsm::vmx_vmwrite(host::RIP, vmx_vmexit as usize as u64);
- let val = unsafe { rdmsr(msr::IA32_SYSENTER_CS) };
- // low32
- VmxAsm::vmx_vmwrite(host::IA32_SYSENTER_CS, (val << 32) >> 32);
- // VmxAsm::vmx_vmwrite(host::IA32_SYSENTER_ESP, 0);
- let tmp = unsafe { rdmsr(msr::IA32_SYSENTER_EIP) };
- VmxAsm::vmx_vmwrite(host::IA32_SYSENTER_EIP, (tmp << 32) >> 32);
- if self
- .vmcs_config
- .vmexit_ctrl
- .contains(ExitControls::LOAD_IA32_PAT)
- {
- VmxAsm::vmx_vmwrite(host::IA32_PAT_FULL, unsafe { rdmsr(msr::IA32_PAT) });
- }
- if self.has_load_ia32_efer() {
- VmxAsm::vmx_vmwrite(
- host::IA32_EFER_FULL,
- x86_kvm_manager().host_efer.bits() as u64,
- );
- }
- }
- fn get_pin_based_exec_controls(&self, vcpu: &VirtCpu) -> PinbasedControls {
- let mut ctrls = self.vmcs_config.pin_based_exec_ctrl;
- if !vcpu.arch.vcpu_apicv_active() {
- ctrls.remove(PinbasedControls::POSTED_INTERRUPTS);
- }
- if !self.enable_vnmi {
- ctrls.remove(PinbasedControls::VIRTUAL_NMIS);
- }
- if !self.enable_preemption_timer {
- ctrls.remove(PinbasedControls::VMX_PREEMPTION_TIMER);
- }
- return ctrls;
- }
- fn get_exec_controls(&self, vcpu: &VirtCpu, vmarch: &KvmArch) -> PrimaryControls {
- let mut ctrls = self.vmcs_config.cpu_based_exec_ctrl;
- ctrls.remove(
- PrimaryControls::RDTSC_EXITING
- | PrimaryControls::USE_IO_BITMAPS
- | PrimaryControls::MONITOR_TRAP_FLAG
- | PrimaryControls::PAUSE_EXITING,
- );
- ctrls.remove(
- PrimaryControls::NMI_WINDOW_EXITING | PrimaryControls::INTERRUPT_WINDOW_EXITING,
- );
- ctrls.remove(PrimaryControls::MOV_DR_EXITING);
- if vcpu.arch.lapic_in_kernel() && self.has_tpr_shadow() {
- ctrls.remove(PrimaryControls::USE_TPR_SHADOW);
- }
- if ctrls.contains(PrimaryControls::USE_TPR_SHADOW) {
- ctrls.remove(PrimaryControls::CR8_LOAD_EXITING | PrimaryControls::CR8_STORE_EXITING);
- } else {
- ctrls.insert(PrimaryControls::CR8_LOAD_EXITING | PrimaryControls::CR8_STORE_EXITING);
- }
- if self.enable_ept {
- ctrls.remove(
- PrimaryControls::CR3_LOAD_EXITING
- | PrimaryControls::CR3_STORE_EXITING
- | PrimaryControls::INVLPG_EXITING,
- );
- }
- if vmarch.mwait_in_guest {
- ctrls.remove(PrimaryControls::MWAIT_EXITING | PrimaryControls::MONITOR_EXITING);
- }
- if vmarch.hlt_in_guest {
- ctrls.remove(PrimaryControls::HLT_EXITING);
- }
- return ctrls;
- }
- fn get_secondary_exec_controls(&mut self, vcpu: &VirtCpu, vm: &Vm) -> SecondaryControls {
- let mut ctrls = self.vmcs_config.cpu_based_2nd_exec_ctrl;
- if self.pt_mode == ProcessorTraceMode::System {
- ctrls.remove(
- SecondaryControls::INTEL_PT_GUEST_PHYSICAL | SecondaryControls::CONCEAL_VMX_FROM_PT,
- );
- }
- if !(self.enable_flexpriority && vcpu.arch.lapic_in_kernel()) {
- ctrls.remove(SecondaryControls::VIRTUALIZE_APIC)
- }
- if vcpu.vmx().vpid == 0 {
- ctrls.remove(SecondaryControls::ENABLE_VPID);
- }
- if !self.enable_ept {
- ctrls.remove(SecondaryControls::ENABLE_EPT);
- self.enable_unrestricted_guest = false;
- }
- if !self.enable_unrestricted_guest {
- ctrls.remove(SecondaryControls::UNRESTRICTED_GUEST);
- }
- if vm.arch.pause_in_guest {
- ctrls.remove(SecondaryControls::PAUSE_LOOP_EXITING);
- }
- if !vcpu.arch.vcpu_apicv_active() {
- ctrls.remove(
- SecondaryControls::VIRTUALIZE_APIC_REGISTER
- | SecondaryControls::VIRTUAL_INTERRUPT_DELIVERY,
- );
- }
- ctrls.remove(SecondaryControls::VIRTUALIZE_X2APIC);
- ctrls.remove(SecondaryControls::ENABLE_VM_FUNCTIONS);
- ctrls.remove(SecondaryControls::DTABLE_EXITING);
- ctrls.remove(SecondaryControls::VMCS_SHADOWING);
- if !self.enable_pml || vm.nr_memslots_dirty_logging == 0 {
- ctrls.remove(SecondaryControls::ENABLE_PML);
- }
- // TODO: vmx_adjust_sec_exec_feature
- if self.has_rdtscp() {
- warn!("adjust RDTSCP todo!");
- // todo!()
- }
- return ctrls;
- }
- fn get_vmexit_controls(&self) -> ExitControls {
- let mut ctrls = self.vmcs_config.vmexit_ctrl;
- ctrls.remove(
- ExitControls::SAVE_IA32_PAT
- | ExitControls::SAVE_IA32_EFER
- | ExitControls::SAVE_VMX_PREEMPTION_TIMER,
- );
- if self.pt_mode == ProcessorTraceMode::System {
- ctrls.remove(ExitControls::CONCEAL_VMX_FROM_PT | ExitControls::CLEAR_IA32_RTIT_CTL);
- }
- // todo: cpu_has_perf_global_ctrl_bug
- ctrls.remove(ExitControls::LOAD_IA32_PERF_GLOBAL_CTRL | ExitControls::LOAD_IA32_EFER);
- ctrls
- }
- fn get_vmentry_controls(&self) -> EntryControls {
- let mut ctrls = self.vmcs_config.vmentry_ctrl;
- if self.pt_mode == ProcessorTraceMode::System {
- ctrls.remove(EntryControls::CONCEAL_VMX_FROM_PT | EntryControls::LOAD_IA32_RTIT_CTL);
- }
- ctrls.remove(
- EntryControls::LOAD_IA32_PERF_GLOBAL_CTRL
- | EntryControls::LOAD_IA32_EFER
- | EntryControls::IA32E_MODE_GUEST,
- );
- // todo: cpu_has_perf_global_ctrl_bug
- ctrls
- }
- pub fn emulation_required(&self, vcpu: &mut VirtCpu) -> bool {
- return self.emulate_invalid_guest_state && !self.guest_state_valid(vcpu);
- }
- pub fn guest_state_valid(&self, vcpu: &mut VirtCpu) -> bool {
- return vcpu.is_unrestricted_guest() || self.__guest_state_valid(vcpu);
- }
- pub fn __guest_state_valid(&self, vcpu: &mut VirtCpu) -> bool {
- if vcpu.arch.is_portected_mode()
- || x86_kvm_ops().get_rflags(vcpu).contains(RFlags::FLAGS_VM)
- {
- if !self.rmode_segment_valid(vcpu, VcpuSegment::CS) {
- return false;
- }
- if !self.rmode_segment_valid(vcpu, VcpuSegment::SS) {
- return false;
- }
- if !self.rmode_segment_valid(vcpu, VcpuSegment::DS) {
- return false;
- }
- if !self.rmode_segment_valid(vcpu, VcpuSegment::ES) {
- return false;
- }
- if !self.rmode_segment_valid(vcpu, VcpuSegment::FS) {
- return false;
- }
- if !self.rmode_segment_valid(vcpu, VcpuSegment::GS) {
- return false;
- }
- } else {
- todo!("protected mode guest state checks todo");
- }
- return true;
- }
- pub fn vmx_get_segment(
- &self,
- vcpu: &mut VirtCpu,
- mut var: UapiKvmSegment,
- seg: VcpuSegment,
- ) -> UapiKvmSegment {
- if vcpu.vmx().rmode.vm86_active && seg != VcpuSegment::LDTR {
- var = vcpu.vmx().rmode.segs[seg as usize];
- if seg == VcpuSegment::TR || var.selector == Vmx::vmx_read_guest_seg_selector(vcpu, seg)
- {
- return var;
- }
- var.base = Vmx::vmx_read_guest_seg_base(vcpu, seg);
- var.selector = Vmx::vmx_read_guest_seg_selector(vcpu, seg);
- return var;
- }
- var.base = Vmx::vmx_read_guest_seg_base(vcpu, seg);
- var.limit = Vmx::vmx_read_guest_seg_limit(vcpu, seg);
- var.selector = Vmx::vmx_read_guest_seg_selector(vcpu, seg);
- let ar = Vmx::vmx_read_guest_seg_ar(vcpu, seg);
- var.unusable = ((ar >> 16) & 1) as u8;
- var.type_ = (ar & 15) as u8;
- var.s = ((ar >> 4) & 1) as u8;
- var.dpl = ((ar >> 5) & 3) as u8;
- var.present = !var.unusable;
- var.avl = ((ar >> 12) & 1) as u8;
- var.l = ((ar >> 13) & 1) as u8;
- var.db = ((ar >> 14) & 1) as u8;
- var.g = ((ar >> 15) & 1) as u8;
- return var;
- }
- pub fn _vmx_set_segment(
- &self,
- vcpu: &mut VirtCpu,
- mut var: UapiKvmSegment,
- seg: VcpuSegment,
- ) -> UapiKvmSegment {
- let sf = &KVM_VMX_SEGMENT_FIELDS[seg as usize];
- vcpu.vmx_mut().segment_cache_clear();
- if vcpu.vmx().rmode.vm86_active && seg != VcpuSegment::LDTR {
- vcpu.vmx_mut().rmode.segs[seg as usize] = var;
- if seg == VcpuSegment::TR {
- VmxAsm::vmx_vmwrite(sf.selector, var.selector as u64);
- } else if var.s != 0 {
- Vmx::fix_rmode_seg(seg, &vcpu.vmx().rmode.segs[seg as usize]);
- }
- return var;
- }
- VmxAsm::vmx_vmwrite(sf.base, var.base);
- VmxAsm::vmx_vmwrite(sf.limit, var.limit as u64);
- VmxAsm::vmx_vmwrite(sf.selector, var.selector as u64);
- if vcpu.is_unrestricted_guest() && seg != VcpuSegment::LDTR {
- var.type_ |= 0x1;
- }
- VmxAsm::vmx_vmwrite(sf.ar_bytes, var.vmx_segment_access_rights() as u64);
- return var;
- }
- pub fn rmode_segment_valid(&self, vcpu: &mut VirtCpu, seg: VcpuSegment) -> bool {
- let mut var = UapiKvmSegment::default();
- var = self.vmx_get_segment(vcpu, var, seg);
- var.dpl = 0x3;
- if seg == VcpuSegment::CS {
- var.type_ = 0x3;
- }
- let ar = var.vmx_segment_access_rights();
- if var.base != ((var.selector as u64) << 4) {
- return false;
- }
- if var.limit != 0xffff {
- return false;
- }
- if ar != 0xf3 {
- return false;
- }
- true
- }
- pub fn fix_rmode_seg(seg: VcpuSegment, save: &UapiKvmSegment) {
- let sf = &KVM_VMX_SEGMENT_FIELDS[seg as usize];
- let mut var = *save;
- var.dpl = 0x3;
- if seg == VcpuSegment::CS {
- var.type_ = 0x3;
- }
- if !vmx_info().emulate_invalid_guest_state {
- var.selector = (var.base >> 4) as u16;
- var.base &= 0xffff0;
- var.limit = 0xffff;
- var.g = 0;
- var.db = 0;
- var.present = 1;
- var.s = 1;
- var.l = 0;
- var.unusable = 0;
- var.type_ = 0x3;
- var.avl = 0;
- if save.base & 0xf != 0 {
- warn!("segment base is not paragraph aligned when entering protected mode (seg={seg:?})");
- }
- }
- VmxAsm::vmx_vmwrite(sf.selector, var.selector as u64);
- VmxAsm::vmx_vmwrite(sf.base, var.base);
- VmxAsm::vmx_vmwrite(sf.limit, var.limit as u64);
- VmxAsm::vmx_vmwrite(sf.ar_bytes, var.vmx_segment_access_rights() as u64);
- }
- pub fn fix_pmode_seg(
- &self,
- vcpu: &mut VirtCpu,
- seg: VcpuSegment,
- mut save: UapiKvmSegment,
- ) -> UapiKvmSegment {
- if self.emulate_invalid_guest_state {
- if seg == VcpuSegment::CS || seg == VcpuSegment::SS {
- save.selector &= !0x3;
- }
- save.dpl = (save.selector & 0x3) as u8;
- save.s = 1;
- }
- self._vmx_set_segment(vcpu, save, seg);
- return save;
- }
- pub fn enter_pmode(&self, vcpu: &mut VirtCpu) {
- self.get_segment_with_rmode(vcpu, VcpuSegment::ES);
- self.get_segment_with_rmode(vcpu, VcpuSegment::DS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::FS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::GS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::SS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::CS);
- vcpu.vmx_mut().rmode.vm86_active = false;
- self.set_segment_with_rmode(vcpu, VcpuSegment::TR);
- let mut flags = RFlags::from_bits_truncate(VmxAsm::vmx_vmread(guest::RFLAGS));
- flags.remove(RFlags::FLAGS_IOPL3 | RFlags::FLAGS_VM);
- flags.insert(vcpu.vmx().rmode.save_rflags & (RFlags::FLAGS_IOPL3 | RFlags::FLAGS_VM));
- VmxAsm::vmx_vmwrite(guest::RFLAGS, flags.bits());
- let cr4 = (Cr4::from_bits_truncate(VmxAsm::vmx_vmread(guest::CR4) as usize)
- & (!Cr4::CR4_ENABLE_VME))
- | (Cr4::from_bits_truncate(VmxAsm::vmx_vmread(control::CR4_READ_SHADOW) as usize)
- & Cr4::CR4_ENABLE_VME);
- VmxAsm::vmx_vmwrite(guest::CR4, cr4.bits() as u64);
- VmxKvmFunc.update_exception_bitmap(vcpu);
- self.fix_pmode_seg_with_rmode(vcpu, VcpuSegment::CS);
- self.fix_pmode_seg_with_rmode(vcpu, VcpuSegment::SS);
- self.fix_pmode_seg_with_rmode(vcpu, VcpuSegment::ES);
- self.fix_pmode_seg_with_rmode(vcpu, VcpuSegment::DS);
- self.fix_pmode_seg_with_rmode(vcpu, VcpuSegment::FS);
- self.fix_pmode_seg_with_rmode(vcpu, VcpuSegment::GS);
- }
- fn fix_pmode_seg_with_rmode(&self, vcpu: &mut VirtCpu, seg: VcpuSegment) {
- let segment = vcpu.vmx().rmode.segs[seg as usize];
- vcpu.vmx_mut().rmode.segs[seg as usize] = self.fix_pmode_seg(vcpu, seg, segment);
- }
- fn get_segment_with_rmode(&self, vcpu: &mut VirtCpu, seg: VcpuSegment) {
- let segment = vcpu.vmx().rmode.segs[seg as usize];
- vcpu.vmx_mut().rmode.segs[seg as usize] = self.vmx_get_segment(vcpu, segment, seg);
- }
- fn set_segment_with_rmode(&self, vcpu: &mut VirtCpu, seg: VcpuSegment) {
- let segment = vcpu.vmx().rmode.segs[seg as usize];
- vcpu.vmx_mut().rmode.segs[seg as usize] = self._vmx_set_segment(vcpu, segment, seg);
- }
- pub fn enter_rmode(&self, vcpu: &mut VirtCpu, vm: &Vm) {
- let kvm_vmx = vm.kvm_vmx();
- self.get_segment_with_rmode(vcpu, VcpuSegment::TR);
- self.get_segment_with_rmode(vcpu, VcpuSegment::ES);
- self.get_segment_with_rmode(vcpu, VcpuSegment::DS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::FS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::GS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::SS);
- self.get_segment_with_rmode(vcpu, VcpuSegment::CS);
- vcpu.vmx_mut().rmode.vm86_active = true;
- vcpu.vmx_mut().segment_cache_clear();
- VmxAsm::vmx_vmwrite(guest::TR_BASE, kvm_vmx.tss_addr as u64);
- VmxAsm::vmx_vmwrite(guest::TR_LIMIT, RMODE_TSS_SIZE as u64 - 1);
- VmxAsm::vmx_vmwrite(guest::TR_ACCESS_RIGHTS, 0x008b);
- let mut flags = RFlags::from_bits_truncate(VmxAsm::vmx_vmread(guest::RFLAGS));
- vcpu.vmx_mut().rmode.save_rflags = flags;
- flags.insert(RFlags::FLAGS_IOPL3 | RFlags::FLAGS_VM);
- VmxAsm::vmx_vmwrite(guest::RFLAGS, flags.bits());
- VmxAsm::vmx_vmwrite(
- guest::CR4,
- VmxAsm::vmx_vmread(guest::CR4) | Cr4::CR4_ENABLE_VME.bits() as u64,
- );
- VmxKvmFunc.update_exception_bitmap(vcpu);
- self.fix_rmode_seg_with_rmode(vcpu, VcpuSegment::SS);
- self.fix_rmode_seg_with_rmode(vcpu, VcpuSegment::CS);
- self.fix_rmode_seg_with_rmode(vcpu, VcpuSegment::ES);
- self.fix_rmode_seg_with_rmode(vcpu, VcpuSegment::DS);
- self.fix_rmode_seg_with_rmode(vcpu, VcpuSegment::GS);
- self.fix_rmode_seg_with_rmode(vcpu, VcpuSegment::FS);
- }
- fn fix_rmode_seg_with_rmode(&self, vcpu: &VirtCpu, seg: VcpuSegment) {
- Vmx::fix_rmode_seg(seg, &vcpu.vmx().rmode.segs[seg as usize]);
- }
- pub fn vmx_read_guest_seg_ar(vcpu: &mut VirtCpu, seg: VcpuSegment) -> u32 {
- if !Vmx::vmx_segment_cache_test_set(vcpu, seg, SegmentCacheField::AR) {
- vcpu.vmx_mut().segment_cache.seg[seg as usize].ar =
- VmxAsm::vmx_vmread(KVM_VMX_SEGMENT_FIELDS[seg as usize].ar_bytes) as u32;
- }
- return vcpu.vmx().segment_cache.seg[seg as usize].ar;
- }
- pub fn vmx_read_guest_seg_selector(vcpu: &mut VirtCpu, seg: VcpuSegment) -> u16 {
- if !Vmx::vmx_segment_cache_test_set(vcpu, seg, SegmentCacheField::SEL) {
- vcpu.vmx_mut().segment_cache.seg[seg as usize].selector =
- VmxAsm::vmx_vmread(KVM_VMX_SEGMENT_FIELDS[seg as usize].selector) as u16;
- }
- return vcpu.vmx().segment_cache.seg[seg as usize].selector;
- }
- pub fn vmx_read_guest_seg_base(vcpu: &mut VirtCpu, seg: VcpuSegment) -> u64 {
- if !Vmx::vmx_segment_cache_test_set(vcpu, seg, SegmentCacheField::BASE) {
- vcpu.vmx_mut().segment_cache.seg[seg as usize].base =
- VmxAsm::vmx_vmread(KVM_VMX_SEGMENT_FIELDS[seg as usize].base);
- }
- return vcpu.vmx().segment_cache.seg[seg as usize].base;
- }
- pub fn vmx_read_guest_seg_limit(vcpu: &mut VirtCpu, seg: VcpuSegment) -> u32 {
- if !Vmx::vmx_segment_cache_test_set(vcpu, seg, SegmentCacheField::LIMIT) {
- vcpu.vmx_mut().segment_cache.seg[seg as usize].limit =
- VmxAsm::vmx_vmread(KVM_VMX_SEGMENT_FIELDS[seg as usize].limit) as u32;
- }
- return vcpu.vmx().segment_cache.seg[seg as usize].limit;
- }
- fn vmx_segment_cache_test_set(
- vcpu: &mut VirtCpu,
- seg: VcpuSegment,
- field: SegmentCacheField,
- ) -> bool {
- let mask = 1u32 << (seg as usize * SegmentCacheField::NR as usize + field as usize);
- if !vcpu.arch.is_register_available(KvmReg::VcpuExregSegments) {
- vcpu.arch.mark_register_available(KvmReg::VcpuExregSegments);
- vcpu.vmx_mut().segment_cache_clear();
- }
- let ret = vcpu.vmx().segment_cache.bitmask & mask;
- vcpu.vmx_mut().segment_cache.bitmask |= mask;
- return ret != 0;
- }
- pub fn vmx_vcpu_enter_exit(vcpu: &mut VirtCpu, flags: VmxRunFlag) {
- // TODO: vmx_l1d_should_flush and mmio_stale_data_clear
- // TODO: vmx_disable_fb_clear
- if vcpu.arch.cr2 != unsafe { cr2() } as u64 {
- unsafe { cr2_write(vcpu.arch.cr2) };
- }
- let fail =
- unsafe { __vmx_vcpu_run(vcpu.vmx(), vcpu.arch.regs.as_ptr(), flags.bits as u32) };
- vcpu.vmx_mut().fail = fail as u8;
- vcpu.arch.cr2 = unsafe { cr2() } as u64;
- vcpu.arch.regs_avail.set_all(true);
- // 这些寄存器需要更新缓存
- for reg_idx in Vmx::VMX_REGS_LAZY_LOAD_SET {
- vcpu.arch.regs_avail.set(*reg_idx, false);
- }
- vcpu.vmx_mut().idt_vectoring_info = IntrInfo::empty();
- // TODO: enable_fb_clear
- if unlikely(vcpu.vmx().fail != 0) {
- vcpu.vmx_mut().exit_reason = VmxExitReason::from(0xdead);
- return;
- }
- vcpu.vmx_mut().exit_reason =
- VmxExitReason::from(VmxAsm::vmx_vmread(ro::EXIT_REASON) as u32);
- if likely(!vcpu.vmx().exit_reason.failed_vmentry()) {
- vcpu.vmx_mut().idt_vectoring_info =
- IntrInfo::from_bits_truncate(VmxAsm::vmx_vmread(ro::IDT_VECTORING_INFO) as u32);
- }
- if VmxExitReasonBasic::from(vcpu.vmx().exit_reason.basic())
- == VmxExitReasonBasic::EXCEPTION_OR_NMI
- && VmcsIntrHelper::is_nmi(&Vmx::vmx_get_intr_info(vcpu))
- {
- todo!()
- }
- }
- fn vmx_get_intr_info(vcpu: &mut VirtCpu) -> IntrInfo {
- if !vcpu
- .arch
- .test_and_mark_available(KvmReg::VcpuExregExitInfo2)
- {
- vcpu.vmx_mut().exit_intr_info = IntrInfo::from_bits_truncate(VmxAsm::vmx_vmread(
- ro::VMEXIT_INTERRUPTION_INFO,
- ) as u32);
- }
- return vcpu.vmx_mut().exit_intr_info;
- }
- pub fn vmx_exit_handlers_fastpath(vcpu: &mut VirtCpu) -> ExitFastpathCompletion {
- match VmxExitReasonBasic::from(vcpu.vmx().exit_reason.basic()) {
- VmxExitReasonBasic::WRMSR => {
- todo!()
- }
- VmxExitReasonBasic::VMX_PREEMPTION_TIMER_EXPIRED => {
- todo!()
- }
- _ => ExitFastpathCompletion::None,
- }
- }
- pub fn vmx_handle_exit(
- &self,
- vcpu: &mut VirtCpu,
- vm: &Vm,
- exit_fastpath: ExitFastpathCompletion,
- ) -> Result<i32, SystemError> {
- let exit_reason = vcpu.vmx().exit_reason;
- // self.dump_vmcs(vcpu);
- {
- let reason = self.vmread(ro::EXIT_REASON);
- debug!("vm_exit reason 0x{:x}\n", reason);
- }
- let unexpected_vmexit = |vcpu: &mut VirtCpu| -> Result<i32, SystemError> {
- error!("vmx: unexpected exit reason {:?}\n", exit_reason);
- self.dump_vmcs(vcpu);
- let cpu = vcpu.arch.last_vmentry_cpu.into() as u64;
- let run = vcpu.kvm_run_mut();
- run.exit_reason = kvm_exit::KVM_EXIT_INTERNAL_ERROR;
- unsafe {
- run.__bindgen_anon_1.internal.ndata = 2;
- run.__bindgen_anon_1.internal.data[0] = Into::<u32>::into(exit_reason) as u64;
- run.__bindgen_anon_1.internal.data[1] = cpu;
- }
- return Ok(0);
- };
- let vectoring_info = vcpu.vmx().idt_vectoring_info;
- if self.enable_pml && !vcpu.arch.is_guest_mode() {
- todo!()
- }
- if vcpu.arch.is_guest_mode() {
- if exit_reason.basic() == VmxExitReasonBasic::PML_FULL as u16 {
- return unexpected_vmexit(vcpu);
- }
- todo!()
- }
- if vcpu.vmx().emulation_required {
- todo!()
- }
- if exit_reason.failed_vmentry() {
- self.dump_vmcs(vcpu);
- todo!()
- }
- if unlikely(vcpu.vmx().fail != 0) {
- self.dump_vmcs(vcpu);
- todo!()
- }
- let basic = VmxExitReasonBasic::from(exit_reason.basic());
- if vectoring_info.contains(IntrInfo::INTR_INFO_VALID_MASK)
- && basic != VmxExitReasonBasic::EXCEPTION_OR_NMI
- && basic != VmxExitReasonBasic::EPT_VIOLATION
- && basic != VmxExitReasonBasic::PML_FULL
- && basic != VmxExitReasonBasic::APIC_ACCESS
- && basic != VmxExitReasonBasic::TASK_SWITCH
- && basic != VmxExitReasonBasic::NOTIFY
- {
- todo!()
- }
- if unlikely(!self.enable_pml && vcpu.vmx().loaded_vmcs().soft_vnmi_blocked) {
- todo!()
- }
- if exit_fastpath != ExitFastpathCompletion::None {
- return Err(SystemError::EINVAL);
- }
- match VmxExitHandlers::try_handle_exit(
- vcpu,
- vm,
- VmxExitReasonBasic::from(exit_reason.basic()),
- ) {
- Some(Ok(r)) => {
- debug!("vmx: handled exit return {:?}\n", r);
- return Ok(r);
- }
- Some(Err(_)) | None => unexpected_vmexit(vcpu),
- }
- }
- #[allow(unreachable_code)]
- pub fn handle_external_interrupt_irqoff(vcpu: &mut VirtCpu) {
- let intr_info = Vmx::vmx_get_intr_info(vcpu);
- let _vector = intr_info & IntrInfo::INTR_INFO_VECTOR_MASK;
- // let desc = vmx_info().host_idt_base + vector.bits() as u64;
- if !VmcsIntrHelper::is_external_intr(&intr_info) {
- error!("unexpected VM-Exit interrupt info: {:?}", intr_info);
- return;
- }
- vcpu.arch.kvm_before_interrupt(KvmIntrType::Irq);
- // TODO
- warn!("handle_external_interrupt_irqoff TODO");
- vcpu.arch.kvm_after_interrupt();
- vcpu.arch.at_instruction_boundary = true;
- }
- /// 需要在缓存中更新的寄存器集。此处未列出的其他寄存器在 VM 退出后立即同步到缓存。
- pub const VMX_REGS_LAZY_LOAD_SET: &'static [usize] = &[
- KvmReg::VcpuRegsRip as usize,
- KvmReg::VcpuRegsRsp as usize,
- KvmReg::VcpuExregRflags as usize,
- KvmReg::NrVcpuRegs as usize,
- KvmReg::VcpuExregSegments as usize,
- KvmReg::VcpuExregCr0 as usize,
- KvmReg::VcpuExregCr3 as usize,
- KvmReg::VcpuExregCr4 as usize,
- KvmReg::VcpuExregExitInfo1 as usize,
- KvmReg::VcpuExregExitInfo2 as usize,
- ];
- }
- extern "C" {
- /// #[allow(improper_ctypes)]因为只需要在内部调用而无需与C交互
- #[allow(improper_ctypes)]
- fn __vmx_vcpu_run(vmx: &VmxVCpuPriv, regs: *const u64, flags: u32) -> i32;
- }
- struct VmcsEntryExitPair {
- entry: EntryControls,
- exit: ExitControls,
- }
- impl VmcsEntryExitPair {
- pub const fn new(entry: EntryControls, exit: ExitControls) -> Self {
- Self { entry, exit }
- }
- }
- #[derive(Debug, Default)]
- #[repr(C, align(64))]
- pub struct PostedIntrDesc {
- pir: [u32; 8],
- control: PostedIntrDescControl,
- // 保留位
- rsvd: [u32; 6],
- }
- #[bitfield(u64)]
- pub struct PostedIntrDescControl {
- #[bits(1)]
- on: bool,
- #[bits(1)]
- sn: bool,
- #[bits(14)]
- rsvd_1: u16,
- nv: u8,
- rsvd_2: u8,
- ndst: u32,
- }
- #[derive(Debug, Default, Clone, Copy)]
- pub struct VmxUretMsr {
- load_into_hardware: bool,
- data: u64,
- mask: u64,
- }
- #[derive(Debug, Default)]
- pub struct VmxMsrs {
- nr: usize,
- val: [VmxMsrEntry; Self::MAX_NR_LOADSTORE_MSRS],
- }
- impl VmxMsrs {
- pub const MAX_NR_LOADSTORE_MSRS: usize = 8;
- pub fn find_loadstore_msr_slot(&self, msr: u32) -> Option<usize> {
- return (0..self.nr).find(|&i| self.val[i].index == msr);
- }
- }
- #[derive(Debug, Default)]
- pub struct VmxMsrAutoLoad {
- guest: VmxMsrs,
- host: VmxMsrs,
- }
- #[derive(Debug)]
- pub struct VmxRMode {
- pub vm86_active: bool,
- pub save_rflags: RFlags,
- pub segs: [UapiKvmSegment; 8],
- }
- impl Default for VmxRMode {
- fn default() -> Self {
- Self {
- vm86_active: false,
- save_rflags: RFlags::empty(),
- segs: [UapiKvmSegment::default(); 8],
- }
- }
- }
- #[derive(Debug, Clone, Copy, Default)]
- pub struct VmxSaveSegment {
- selector: u16,
- base: u64,
- limit: u32,
- ar: u32,
- }
- #[derive(Debug, Default)]
- pub struct VmxSegmentCache {
- pub bitmask: u32,
- pub seg: [VmxSaveSegment; 8],
- }
- #[derive(Debug)]
- #[allow(dead_code)]
- pub struct VmxVCpuPriv {
- vpid: u16,
- fail: u8,
- exit_reason: VmxExitReason,
- exit_intr_info: IntrInfo,
- idt_vectoring_info: IntrInfo,
- vmcs01: Arc<LockedLoadedVmcs>,
- loaded_vmcs: Arc<LockedLoadedVmcs>,
- guest_uret_msrs: [VmxUretMsr; KvmArchManager::KVM_MAX_NR_USER_RETURN_MSRS],
- guest_uret_msrs_loaded: bool,
- post_intr_desc: PostedIntrDesc,
- shadow_msr_intercept_read: AllocBitmap,
- shadow_msr_intercept_write: AllocBitmap,
- msr_ia32_feature_control: u64,
- msr_ia32_feature_control_valid_bits: u64,
- msr_host_kernel_gs_base: u64,
- msr_guest_kernel_gs_base: u64,
- emulation_required: bool,
- rflags: RFlags,
- ple_window: u32,
- ple_window_dirty: bool,
- msr_autoload: VmxMsrAutoLoad,
- msr_autostore: VmxMsrs,
- pml_pg: Box<[u8; MMArch::PAGE_SIZE]>,
- rmode: VmxRMode,
- spec_ctrl: u64,
- msr_ia32_umwait_control: u32,
- hv_deadline_tsc: u64,
- segment_cache: VmxSegmentCache,
- req_immediate_exit: bool,
- guest_state_loaded: bool,
- exit_qualification: u64, //暂时不知道用处fztodo
- }
- #[derive(Debug, Default)]
- #[allow(dead_code)]
- pub struct KvmVmx {
- tss_addr: usize,
- ept_identity_pagetable_done: bool,
- ept_identity_map_addr: u64,
- pid_table: Option<Box<[u64; MMArch::PAGE_SIZE]>>,
- }
- impl KvmVmx {
- pub fn pid_table(&self) -> &[u64; MMArch::PAGE_SIZE] {
- self.pid_table.as_ref().unwrap().as_ref()
- }
- }
- impl VmxVCpuPriv {
- pub const PML_ENTITY_NUM: usize = 512;
- pub fn loaded_vmcs(&self) -> SpinLockGuard<LoadedVmcs> {
- self.loaded_vmcs.lock()
- }
- /// 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/kvm/vmx/vmx.c#7452
- pub fn init(vcpu: &mut VirtCpu, vm: &Vm) {
- let vmcs = LockedLoadedVmcs::new();
- // TODO: 改堆分配
- let mut vmx = Self {
- vpid: 0,
- fail: 0,
- vmcs01: vmcs.clone(),
- loaded_vmcs: vmcs,
- guest_uret_msrs: [VmxUretMsr::default(); KvmArchManager::KVM_MAX_NR_USER_RETURN_MSRS],
- shadow_msr_intercept_read: AllocBitmap::new(16),
- shadow_msr_intercept_write: AllocBitmap::new(16),
- post_intr_desc: PostedIntrDesc::default(),
- ple_window: 0,
- ple_window_dirty: false,
- msr_autoload: VmxMsrAutoLoad::default(),
- pml_pg: unsafe { Box::new_zeroed().assume_init() },
- guest_uret_msrs_loaded: false,
- msr_ia32_feature_control: 0,
- msr_ia32_feature_control_valid_bits: 0,
- rmode: VmxRMode::default(),
- spec_ctrl: 0,
- msr_ia32_umwait_control: 0,
- hv_deadline_tsc: u64::MAX,
- segment_cache: VmxSegmentCache::default(),
- emulation_required: false,
- rflags: RFlags::empty(),
- req_immediate_exit: false,
- guest_state_loaded: false,
- msr_host_kernel_gs_base: 0,
- msr_guest_kernel_gs_base: 0,
- idt_vectoring_info: IntrInfo::empty(),
- exit_reason: VmxExitReason::new(),
- exit_intr_info: IntrInfo::empty(),
- msr_autostore: VmxMsrs::default(),
- exit_qualification: 0, //fztodo
- };
- vmx.vpid = vmx_info().alloc_vpid().unwrap_or_default() as u16;
- for i in 0..x86_kvm_manager().kvm_uret_msrs_list.len() {
- vmx.guest_uret_msrs[i].mask = u64::MAX;
- }
- if CpuId::new().get_extended_feature_info().unwrap().has_rtm() {
- let tsx_ctrl = vmx.find_uret_msr_mut(msr::MSR_IA32_TSX_CTRL);
- if let Some((_idx, tsx_ctrl)) = tsx_ctrl {
- // Disable TSX enumeration
- tsx_ctrl.mask = !(1 << 1);
- }
- }
- vmx.shadow_msr_intercept_read.set_all(true);
- vmx.shadow_msr_intercept_write.set_all(true);
- let arch = &vm.arch;
- vmx.disable_intercept_for_msr(arch, msr::IA32_TIME_STAMP_COUNTER, MsrType::READ);
- vmx.disable_intercept_for_msr(arch, msr::IA32_FS_BASE, MsrType::RW);
- vmx.disable_intercept_for_msr(arch, msr::IA32_GS_BASE, MsrType::RW);
- vmx.disable_intercept_for_msr(arch, msr::IA32_KERNEL_GSBASE, MsrType::RW);
- vmx.disable_intercept_for_msr(arch, msr::IA32_SYSENTER_CS, MsrType::RW);
- vmx.disable_intercept_for_msr(arch, msr::IA32_SYSENTER_ESP, MsrType::RW);
- vmx.disable_intercept_for_msr(arch, msr::IA32_SYSENTER_EIP, MsrType::RW);
- if arch.pause_in_guest {
- vmx.disable_intercept_for_msr(arch, msr::MSR_CORE_C1_RESIDENCY, MsrType::READ);
- vmx.disable_intercept_for_msr(arch, msr::MSR_CORE_C3_RESIDENCY, MsrType::READ);
- vmx.disable_intercept_for_msr(arch, msr::MSR_CORE_C6_RESIDENCY, MsrType::READ);
- vmx.disable_intercept_for_msr(arch, msr::MSR_CORE_C7_RESIDENCY, MsrType::READ);
- }
- if vmx_info().enable_flexpriority && vcpu.arch.lapic_in_kernel() {
- todo!()
- }
- if vmx_info().enable_ept && !vmx_info().enable_unrestricted_guest {
- todo!()
- }
- if vcpu.arch.lapic_in_kernel() && vmx_info().enable_ipiv {
- todo!()
- }
- // 初始化vmx私有信息
- vcpu.private = Some(vmx);
- }
- pub fn find_uret_msr(&self, msr: u32) -> Option<(usize, &VmxUretMsr)> {
- let idx = x86_kvm_manager().find_user_return_msr_idx(msr);
- if let Some(index) = idx {
- return Some((index, &self.guest_uret_msrs[index]));
- } else {
- return None;
- }
- }
- fn set_uret_msr(&mut self, msr: u32, data: u64) {
- if let Some((_idx, msr)) = self.find_uret_msr_mut(msr) {
- msr.data = data;
- }
- }
- pub fn find_uret_msr_mut(&mut self, msr: u32) -> Option<(usize, &mut VmxUretMsr)> {
- let idx = x86_kvm_manager().find_user_return_msr_idx(msr);
- if let Some(index) = idx {
- return Some((index, &mut self.guest_uret_msrs[index]));
- } else {
- return None;
- }
- }
- fn set_guest_uret_msr(&mut self, slot: usize, data: u64) -> Result<(), SystemError> {
- let msr = &mut self.guest_uret_msrs[slot];
- if msr.load_into_hardware {
- x86_kvm_manager().kvm_set_user_return_msr(slot, data, msr.mask);
- }
- msr.data = data;
- Ok(())
- }
- /// ## 禁用对特定的 MSR 的拦截
- fn disable_intercept_for_msr(&mut self, arch: &KvmArch, msr: u32, mut msr_type: MsrType) {
- if !vmx_info().has_msr_bitmap() {
- return;
- }
- let msr_bitmap = &mut self.vmcs01.lock().msr_bitmap;
- // TODO: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/kvm/vmx/vmx.c#3974
- // 嵌套vmx处理
- if Vmx::is_valid_passthrough_msr(msr) {
- if let Some(idx) = Vmx::possible_passthrough_msr_slot(msr) {
- if msr_type.contains(MsrType::READ) {
- self.shadow_msr_intercept_read.set(idx, false);
- }
- if msr_type.contains(MsrType::WRITE) {
- self.shadow_msr_intercept_write.set(idx, false);
- }
- }
- }
- if msr_type.contains(MsrType::READ)
- && !arch.msr_allowed(msr, MsrFilterType::KVM_MSR_FILTER_READ)
- {
- msr_bitmap.ctl(msr, VmxMsrBitmapAction::Set, VmxMsrBitmapAccess::Read);
- msr_type.remove(MsrType::READ);
- }
- if msr_type.contains(MsrType::WRITE)
- && !arch.msr_allowed(msr, MsrFilterType::KVM_MSR_FILTER_WRITE)
- {
- msr_bitmap.ctl(msr, VmxMsrBitmapAction::Set, VmxMsrBitmapAccess::Write);
- msr_type.remove(MsrType::WRITE);
- }
- if msr_type.contains(MsrType::READ) {
- msr_bitmap.ctl(msr, VmxMsrBitmapAction::Clear, VmxMsrBitmapAccess::Read);
- }
- if msr_type.contains(MsrType::WRITE) {
- msr_bitmap.ctl(msr, VmxMsrBitmapAction::Clear, VmxMsrBitmapAccess::Write);
- }
- }
- #[inline]
- pub fn segment_cache_clear(&mut self) {
- self.segment_cache.bitmask = 0;
- }
- pub fn clear_atomic_switch_msr(&mut self, msr: u32) {
- match msr {
- msr::IA32_EFER => {
- if vmx_info().has_load_ia32_efer() {
- self.clear_stomic_switch_msr_special(
- EntryControls::LOAD_IA32_EFER.bits().into(),
- ExitControls::LOAD_IA32_EFER.bits().into(),
- );
- return;
- }
- }
- msr::MSR_PERF_GLOBAL_CTRL => {
- if vmx_info().has_load_perf_global_ctrl() {
- self.clear_stomic_switch_msr_special(
- EntryControls::LOAD_IA32_PERF_GLOBAL_CTRL.bits().into(),
- ExitControls::LOAD_IA32_PERF_GLOBAL_CTRL.bits().into(),
- );
- return;
- }
- }
- _ => {}
- }
- let m = &mut self.msr_autoload;
- let i = m.guest.find_loadstore_msr_slot(msr);
- if let Some(i) = i {
- m.guest.nr -= 1;
- m.guest.val[i] = m.guest.val[m.guest.nr];
- VmxAsm::vmx_vmwrite(control::VMENTRY_MSR_LOAD_COUNT, m.guest.nr as u64);
- }
- let i = m.host.find_loadstore_msr_slot(msr);
- if let Some(i) = i {
- m.host.nr -= 1;
- m.host.val[i] = m.host.val[m.host.nr];
- VmxAsm::vmx_vmwrite(control::VMEXIT_MSR_LOAD_COUNT, m.host.nr as u64);
- }
- }
- fn clear_stomic_switch_msr_special(&self, entry: u64, exit: u64) {
- let mut guard = self.loaded_vmcs.lock();
- guard.controls_clearbit(ControlsType::VmEntry, entry);
- guard.controls_clearbit(ControlsType::VmExit, exit);
- }
- pub fn add_atomic_switch_msr(
- &mut self,
- msr: u32,
- guest_val: u64,
- host_val: u64,
- entry_only: bool,
- ) {
- match msr {
- msr::IA32_EFER => {
- if vmx_info().has_load_ia32_efer() {
- self.add_atomic_switch_msr_special(
- EntryControls::LOAD_IA32_EFER.bits() as u64,
- ExitControls::LOAD_IA32_EFER.bits() as u64,
- guest::IA32_EFER_FULL,
- host::IA32_EFER_FULL,
- guest_val,
- host_val,
- );
- return;
- }
- }
- msr::MSR_PERF_GLOBAL_CTRL => {
- if vmx_info().has_load_perf_global_ctrl() {
- self.add_atomic_switch_msr_special(
- EntryControls::LOAD_IA32_PERF_GLOBAL_CTRL.bits().into(),
- ExitControls::LOAD_IA32_PERF_GLOBAL_CTRL.bits().into(),
- guest::IA32_PERF_GLOBAL_CTRL_FULL,
- host::IA32_PERF_GLOBAL_CTRL_FULL,
- guest_val,
- host_val,
- );
- return;
- }
- }
- msr::MSR_PEBS_ENABLE => {
- unsafe { wrmsr(msr::MSR_PEBS_ENABLE, 0) };
- }
- _ => {}
- }
- let m = &mut self.msr_autoload;
- let i = m.guest.find_loadstore_msr_slot(msr);
- let j = if !entry_only {
- m.host.find_loadstore_msr_slot(msr)
- } else {
- Some(0)
- };
- if (i.is_none() && m.guest.nr == VmxMsrs::MAX_NR_LOADSTORE_MSRS)
- || (j.is_none() && m.host.nr == VmxMsrs::MAX_NR_LOADSTORE_MSRS)
- {
- warn!("Not enough msr switch entries. Can't add msr 0x{:x}", msr);
- return;
- }
- let i = if let Some(i) = i {
- i
- } else {
- m.guest.nr += 1;
- VmxAsm::vmx_vmwrite(control::VMENTRY_MSR_LOAD_COUNT, m.guest.nr as u64);
- m.guest.nr
- };
- m.guest.val[i].index = msr;
- m.guest.val[i].data = guest_val;
- if entry_only {
- return;
- }
- let j = if let Some(j) = j {
- j
- } else {
- m.host.nr += 1;
- VmxAsm::vmx_vmwrite(control::VMEXIT_MSR_LOAD_COUNT, m.host.nr as u64);
- m.host.nr
- };
- m.host.val[j].index = msr;
- m.host.val[j].data = host_val;
- }
- fn add_atomic_switch_msr_special(
- &self,
- entry: u64,
- exit: u64,
- guest_val_vmcs: u32,
- host_val_vmcs: u32,
- guest_val: u64,
- host_val: u64,
- ) {
- VmxAsm::vmx_vmwrite(guest_val_vmcs, guest_val);
- if host_val_vmcs != host::IA32_EFER_FULL {
- VmxAsm::vmx_vmwrite(host_val_vmcs, host_val);
- }
- let mut guard = self.loaded_vmcs.lock();
- guard.controls_setbit(ControlsType::VmEntry, entry);
- guard.controls_setbit(ControlsType::VmExit, exit);
- }
- pub fn vmx_vcpu_run_flags(&self) -> VmxRunFlag {
- let mut flags = VmxRunFlag::empty();
- if self.loaded_vmcs().launched {
- flags.insert(VmxRunFlag::VMRESUME);
- }
- // MSR_IA32_SPEC_CTRL
- if !self.loaded_vmcs().msr_write_intercepted(0x48) {
- flags.insert(VmxRunFlag::SAVE_SPEC_CTRL);
- }
- flags
- }
- pub fn get_exit_qual(&self) -> u64 {
- self.exit_qualification
- }
- pub fn vmread_exit_qual(&mut self) {
- self.exit_qualification = VmxAsm::vmx_vmread(ro::EXIT_QUALIFICATION);
- }
- }
- bitflags! {
- pub struct MsrType: u8 {
- const READ = 1;
- const WRITE = 2;
- const RW = 3;
- }
- //https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/include/asm/kvm_host.h#249
- pub struct PageFaultErr: u64 {
- const PFERR_PRESENT = 1 << 0;
- const PFERR_WRITE = 1 << 1;
- const PFERR_USER = 1 << 2;
- const PFERR_RSVD = 1 << 3;
- const PFERR_FETCH = 1 << 4;
- const PFERR_PK = 1 << 5;
- const PFERR_SGX = 1 << 15;
- const PFERR_GUEST_FINAL = 1 << 32;
- const PFERR_GUEST_PAGE = 1 << 33;
- const PFERR_IMPLICIT_ACCESS = 1 << 48;
- }
- pub struct VmxRunFlag: u8 {
- const VMRESUME = 1 << 0;
- const SAVE_SPEC_CTRL = 1 << 1;
- }
- }
- #[derive(Debug, PartialEq)]
- #[allow(dead_code)]
- pub enum VmxL1dFlushState {
- Auto,
- Never,
- Cond,
- Always,
- EptDisabled,
- NotRequired,
- }
- #[derive(Debug, PartialEq)]
- pub struct VmxSegmentField {
- selector: u32,
- base: u32,
- limit: u32,
- ar_bytes: u32,
- }
- //fix
- pub const KVM_VMX_SEGMENT_FIELDS: &[VmxSegmentField] = &[
- // ES
- VmxSegmentField {
- selector: guest::ES_SELECTOR,
- base: guest::ES_BASE,
- limit: guest::ES_LIMIT,
- ar_bytes: guest::ES_ACCESS_RIGHTS,
- },
- // CS
- VmxSegmentField {
- selector: guest::CS_SELECTOR,
- base: guest::CS_BASE,
- limit: guest::CS_LIMIT,
- ar_bytes: guest::CS_ACCESS_RIGHTS,
- },
- // SS
- VmxSegmentField {
- selector: guest::SS_SELECTOR,
- base: guest::SS_BASE,
- limit: guest::SS_LIMIT,
- ar_bytes: guest::SS_ACCESS_RIGHTS,
- },
- // DS
- VmxSegmentField {
- selector: guest::DS_SELECTOR,
- base: guest::DS_BASE,
- limit: guest::DS_LIMIT,
- ar_bytes: guest::DS_ACCESS_RIGHTS,
- },
- // FS
- VmxSegmentField {
- selector: guest::FS_SELECTOR,
- base: guest::FS_BASE,
- limit: guest::FS_LIMIT,
- ar_bytes: guest::FS_ACCESS_RIGHTS,
- },
- // GS
- VmxSegmentField {
- selector: guest::GS_SELECTOR,
- base: guest::GS_BASE,
- limit: guest::GS_LIMIT,
- ar_bytes: guest::GS_ACCESS_RIGHTS,
- },
- // TR
- VmxSegmentField {
- selector: guest::TR_SELECTOR,
- base: guest::TR_BASE,
- limit: guest::TR_LIMIT,
- ar_bytes: guest::TR_ACCESS_RIGHTS,
- },
- // LDTR
- VmxSegmentField {
- selector: guest::LDTR_SELECTOR,
- base: guest::LDTR_BASE,
- limit: guest::LDTR_LIMIT,
- ar_bytes: guest::LDTR_ACCESS_RIGHTS,
- },
- ];
- pub static L1TF_VMX_MITIGATION: RwLock<VmxL1dFlushState> = RwLock::new(VmxL1dFlushState::Auto);
- pub fn vmx_init() -> Result<(), SystemError> {
- let cpuid = CpuId::new();
- let cpu_feat = cpuid.get_feature_info().ok_or_else(|| {
- log::warn!("Failed to get CPU feature info, perhaps not AMD or Intel CPU");
- SystemError::ENOSYS
- })?;
- if !cpu_feat.has_vmx() {
- log::warn!("VMX not supported or enabled");
- return Err(SystemError::ENOSYS);
- }
- init_kvm_arch();
- x86_kvm_manager_mut().vendor_init(&VmxKvmInitFunc)?;
- vmx_info().setup_l1d_flush();
- kvm_init()?;
- Ok(())
- }
- #[no_mangle]
- unsafe extern "C" fn vmx_update_host_rsp(vcpu_vmx: &VmxVCpuPriv, host_rsp: usize) {
- warn!("vmx_update_host_rsp");
- let mut guard = vcpu_vmx.loaded_vmcs.lock();
- if unlikely(host_rsp != guard.host_state.rsp) {
- guard.host_state.rsp = host_rsp;
- VmxAsm::vmx_vmwrite(host::RSP, host_rsp as u64);
- }
- }
- #[no_mangle]
- unsafe extern "C" fn vmx_spec_ctrl_restore_host(_vcpu_vmx: &VmxVCpuPriv, _flags: u32) {
- // TODO
- warn!("vmx_spec_ctrl_restore_host todo!");
- }
|