@@ -32,7 +32,7 @@ use super::vmcs::{
3232use crate :: LinuxContext ;
3333use crate :: page_table:: GuestPageTable64 ;
3434use crate :: page_table:: GuestPageWalkInfo ;
35- use crate :: segmentation:: Segment ;
35+ use crate :: segmentation:: { Segment , SegmentAccessRights } ;
3636use crate :: xstate:: XState ;
3737use crate :: { msr:: Msr , regs:: GeneralRegisters } ;
3838
@@ -70,11 +70,13 @@ pub struct VmxVcpu<H: AxVCpuHal> {
7070 cur_xstate : XState ,
7171 entry : Option < GuestPhysAddr > ,
7272 ept_root : Option < HostPhysAddr > ,
73+
74+ id : usize ,
7375}
7476
7577impl < H : AxVCpuHal > VmxVcpu < H > {
7678 /// Create a new [`VmxVcpu`].
77- pub fn new ( ) -> AxResult < Self > {
79+ pub fn new ( id : usize ) -> AxResult < Self > {
7880 let vcpu = Self {
7981 guest_regs : GeneralRegisters :: default ( ) ,
8082 host_stack_top : 0 ,
@@ -88,6 +90,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
8890 cur_xstate : XState :: new ( ) ,
8991 entry : None ,
9092 ept_root : None ,
93+ id,
9194 } ;
9295 debug ! ( "[HV] created VmxVcpu(vmcs: {:#x})" , vcpu. vmcs. phys_addr( ) , ) ;
9396 Ok ( vcpu)
@@ -543,6 +546,11 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
543546 } } ;
544547 }
545548
549+ debug ! (
550+ "setup_vmcs_guest_from_ctx: CS access rights: {:?}" ,
551+ linux. cs. access_rights
552+ ) ;
553+
546554 set_guest_segment ! ( linux. es, ES ) ;
547555 set_guest_segment ! ( linux. cs, CS ) ;
548556 set_guest_segment ! ( linux. ss, SS ) ;
@@ -764,33 +772,42 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
764772 Ok ( ( ) )
765773 }
766774
767- fn load_vmcs_guest ( & self , linux : & mut LinuxContext ) {
768- linux. rip = VmcsGuestNW :: RIP . read ( ) . unwrap ( ) as _ ;
769- linux. rsp = VmcsGuestNW :: RSP . read ( ) . unwrap ( ) as _ ;
770- linux. cr0 = Cr0Flags :: from_bits_truncate ( VmcsGuestNW :: CR0 . read ( ) . unwrap ( ) as _ ) ;
771- linux. cr3 = VmcsGuestNW :: CR3 . read ( ) . unwrap ( ) as _ ;
772- linux. cr4 = Cr4Flags :: from_bits_truncate ( VmcsGuestNW :: CR4 . read ( ) . unwrap ( ) as _ ) ;
773-
774- linux. es . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: ES_SELECTOR . read ( ) . unwrap ( ) ) ;
775- linux. cs . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: CS_SELECTOR . read ( ) . unwrap ( ) ) ;
776- linux. ss . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: SS_SELECTOR . read ( ) . unwrap ( ) ) ;
777- linux. ds . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: DS_SELECTOR . read ( ) . unwrap ( ) ) ;
778- linux. fs . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: FS_SELECTOR . read ( ) . unwrap ( ) ) ;
779- linux. fs . base = VmcsGuestNW :: FS_BASE . read ( ) . unwrap ( ) as _ ;
780- linux. gs . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: GS_SELECTOR . read ( ) . unwrap ( ) ) ;
781- linux. gs . base = VmcsGuestNW :: GS_BASE . read ( ) . unwrap ( ) as _ ;
782- linux. tss . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: TR_SELECTOR . read ( ) . unwrap ( ) ) ;
783-
784- linux. gdt . base = VirtAddr :: new ( VmcsGuestNW :: GDTR_BASE . read ( ) . unwrap ( ) as _ ) ;
785- linux. gdt . limit = VmcsGuest32 :: GDTR_LIMIT . read ( ) . unwrap ( ) as _ ;
786- linux. idt . base = VirtAddr :: new ( VmcsGuestNW :: IDTR_BASE . read ( ) . unwrap ( ) as _ ) ;
787- linux. idt . limit = VmcsGuest32 :: IDTR_LIMIT . read ( ) . unwrap ( ) as _ ;
788-
789- linux. ia32_sysenter_cs = VmcsGuest32 :: IA32_SYSENTER_CS . read ( ) . unwrap ( ) as _ ; // 0x174
790- linux. ia32_sysenter_esp = VmcsGuestNW :: IA32_SYSENTER_ESP . read ( ) . unwrap ( ) as _ ; // 0x178
791- linux. ia32_sysenter_eip = VmcsGuestNW :: IA32_SYSENTER_EIP . read ( ) . unwrap ( ) as _ ; // 0x17a
775+ fn load_vmcs_guest ( & self , linux : & mut LinuxContext ) -> AxResult {
776+ linux. rip = VmcsGuestNW :: RIP . read ( ) ? as _ ;
777+ linux. rsp = VmcsGuestNW :: RSP . read ( ) ? as _ ;
778+ linux. cr0 = Cr0Flags :: from_bits_truncate ( VmcsGuestNW :: CR0 . read ( ) ? as _ ) ;
779+ linux. cr3 = VmcsGuestNW :: CR3 . read ( ) ? as _ ;
780+ linux. cr4 = Cr4Flags :: from_bits_truncate ( VmcsGuestNW :: CR4 . read ( ) ? as _ ) ;
781+
782+ linux. es . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: ES_SELECTOR . read ( ) ?) ;
783+
784+ linux. cs . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: CS_SELECTOR . read ( ) ?) ;
785+ // CS:
786+ // If the Type is 9 or 11 (non-conforming code segment), the DPL must equal the DPL in the access-rights field for SS.
787+ linux. cs . access_rights =
788+ SegmentAccessRights :: from_bits_truncate ( VmcsGuest32 :: CS_ACCESS_RIGHTS . read ( ) ?) ;
789+ linux. ss . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: SS_SELECTOR . read ( ) ?) ;
790+ linux. ss . access_rights =
791+ SegmentAccessRights :: from_bits_truncate ( VmcsGuest32 :: SS_ACCESS_RIGHTS . read ( ) ?) ;
792+
793+ linux. ds . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: DS_SELECTOR . read ( ) ?) ;
794+ linux. fs . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: FS_SELECTOR . read ( ) ?) ;
795+ linux. fs . base = VmcsGuestNW :: FS_BASE . read ( ) ? as _ ;
796+ linux. gs . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: GS_SELECTOR . read ( ) ?) ;
797+ linux. gs . base = VmcsGuestNW :: GS_BASE . read ( ) ? as _ ;
798+ linux. tss . selector = SegmentSelector :: from_raw ( VmcsGuest16 :: TR_SELECTOR . read ( ) ?) ;
799+
800+ linux. gdt . base = VirtAddr :: new ( VmcsGuestNW :: GDTR_BASE . read ( ) ? as _ ) ;
801+ linux. gdt . limit = VmcsGuest32 :: GDTR_LIMIT . read ( ) ? as _ ;
802+ linux. idt . base = VirtAddr :: new ( VmcsGuestNW :: IDTR_BASE . read ( ) ? as _ ) ;
803+ linux. idt . limit = VmcsGuest32 :: IDTR_LIMIT . read ( ) ? as _ ;
804+
805+ linux. ia32_sysenter_cs = VmcsGuest32 :: IA32_SYSENTER_CS . read ( ) ? as _ ; // 0x174
806+ linux. ia32_sysenter_esp = VmcsGuestNW :: IA32_SYSENTER_ESP . read ( ) ? as _ ; // 0x178
807+ linux. ia32_sysenter_eip = VmcsGuestNW :: IA32_SYSENTER_EIP . read ( ) ? as _ ; // 0x17a
792808
793809 linux. load_guest_regs ( self . regs ( ) ) ;
810+ Ok ( ( ) )
794811 }
795812
796813 fn get_paging_level ( & self ) -> usize {
@@ -1260,6 +1277,33 @@ fn get_tr_base(tr: SegmentSelector, gdt: &DescriptorTablePointer<u64>) -> u64 {
12601277impl < H : AxVCpuHal > Debug for VmxVcpu < H > {
12611278 fn fmt ( & self , f : & mut Formatter ) -> Result {
12621279 ( || -> AxResult < Result > {
1280+ let cs_selector = SegmentSelector :: from_raw ( VmcsGuest16 :: CS_SELECTOR . read ( ) ?) ;
1281+ let cs_access_rights_raw = VmcsGuest32 :: CS_ACCESS_RIGHTS . read ( ) ?;
1282+ let cs_access_rights = SegmentAccessRights :: from_bits_truncate ( cs_access_rights_raw) ;
1283+ let ss_selector = SegmentSelector :: from_raw ( VmcsGuest16 :: SS_SELECTOR . read ( ) ?) ;
1284+ let ss_access_rights_raw = VmcsGuest32 :: SS_ACCESS_RIGHTS . read ( ) ?;
1285+ let ss_access_rights = SegmentAccessRights :: from_bits_truncate ( ss_access_rights_raw) ;
1286+ let ds_selector = SegmentSelector :: from_raw ( VmcsGuest16 :: DS_SELECTOR . read ( ) ?) ;
1287+ let ds_access_rights =
1288+ SegmentAccessRights :: from_bits_truncate ( VmcsGuest32 :: DS_ACCESS_RIGHTS . read ( ) ?) ;
1289+ let fs_selector = SegmentSelector :: from_raw ( VmcsGuest16 :: FS_SELECTOR . read ( ) ?) ;
1290+ let fs_access_rights =
1291+ SegmentAccessRights :: from_bits_truncate ( VmcsGuest32 :: FS_ACCESS_RIGHTS . read ( ) ?) ;
1292+ let gs_selector = SegmentSelector :: from_raw ( VmcsGuest16 :: GS_SELECTOR . read ( ) ?) ;
1293+ let gs_access_rights =
1294+ SegmentAccessRights :: from_bits_truncate ( VmcsGuest32 :: GS_ACCESS_RIGHTS . read ( ) ?) ;
1295+ let tr_selector = SegmentSelector :: from_raw ( VmcsGuest16 :: TR_SELECTOR . read ( ) ?) ;
1296+ let tr_access_rights =
1297+ SegmentAccessRights :: from_bits_truncate ( VmcsGuest32 :: TR_ACCESS_RIGHTS . read ( ) ?) ;
1298+ let gdt_base = VirtAddr :: new ( VmcsGuestNW :: GDTR_BASE . read ( ) ? as _ ) ;
1299+ let gdt_limit = VmcsGuest32 :: GDTR_LIMIT . read ( ) ?;
1300+ let idt_base = VirtAddr :: new ( VmcsGuestNW :: IDTR_BASE . read ( ) ? as _ ) ;
1301+ let idt_limit = VmcsGuest32 :: IDTR_LIMIT . read ( ) ?;
1302+
1303+ let ia32_sysenter_cs = VmcsGuest32 :: IA32_SYSENTER_CS . read ( ) ?;
1304+ let ia32_sysenter_esp = VmcsGuestNW :: IA32_SYSENTER_ESP . read ( ) ?;
1305+ let ia32_sysenter_eip = VmcsGuestNW :: IA32_SYSENTER_EIP . read ( ) ?;
1306+
12631307 Ok ( f. debug_struct ( "VmxVcpu" )
12641308 . field ( "guest_regs" , & self . guest_regs )
12651309 . field ( "rip" , & VmcsGuestNW :: RIP . read ( ) ?)
@@ -1268,29 +1312,53 @@ impl<H: AxVCpuHal> Debug for VmxVcpu<H> {
12681312 . field ( "cr0" , & VmcsGuestNW :: CR0 . read ( ) ?)
12691313 . field ( "cr3" , & VmcsGuestNW :: CR3 . read ( ) ?)
12701314 . field ( "cr4" , & VmcsGuestNW :: CR4 . read ( ) ?)
1271- . field ( "cs" , & VmcsGuest16 :: CS_SELECTOR . read ( ) ?)
1315+ . field ( "cs_base" , & VmcsGuestNW :: CS_BASE . read ( ) ?)
1316+ . field ( "cs_selector" , & cs_selector)
1317+ . field ( "cs_access_rights" , & cs_access_rights)
1318+ . field ( "cs_access_rights_raw" , & cs_access_rights_raw)
1319+ . field ( "ss_base" , & VmcsGuestNW :: SS_BASE . read ( ) ?)
1320+ . field ( "ss_selector" , & ss_selector)
1321+ . field ( "ss_access_rights_raw" , & ss_access_rights_raw)
1322+ . field ( "ss_access_rights" , & ss_access_rights)
1323+ . field ( "ds_base" , & VmcsGuestNW :: DS_BASE . read ( ) ?)
1324+ . field ( "ds_selector" , & ds_selector)
1325+ . field ( "ds_access_rights" , & ds_access_rights)
12721326 . field ( "fs_base" , & VmcsGuestNW :: FS_BASE . read ( ) ?)
1327+ . field ( "fs_selector" , & fs_selector)
1328+ . field ( "fs_access_rights" , & fs_access_rights)
12731329 . field ( "gs_base" , & VmcsGuestNW :: GS_BASE . read ( ) ?)
1274- . field ( "tss" , & VmcsGuest16 :: TR_SELECTOR . read ( ) ?)
1330+ . field ( "gs_selector" , & gs_selector)
1331+ . field ( "gs_access_rights" , & gs_access_rights)
1332+ . field ( "tr_selector" , & tr_selector)
1333+ . field ( "tr_access_rights" , & tr_access_rights)
1334+ . field ( "gdt_base" , & gdt_base)
1335+ . field ( "gdt_limit" , & gdt_limit)
1336+ . field ( "idt_base" , & idt_base)
1337+ . field ( "idt_limit" , & idt_limit)
1338+ . field ( "ia32_sysenter_cs" , & ia32_sysenter_cs)
1339+ . field ( "ia32_sysenter_esp" , & ia32_sysenter_esp)
1340+ . field ( "ia32_sysenter_eip" , & ia32_sysenter_eip)
12751341 . finish ( ) )
12761342 } ) ( )
12771343 . unwrap ( )
12781344 }
12791345}
12801346
12811347impl < H : AxVCpuHal > AxArchVCpu for VmxVcpu < H > {
1282- type CreateConfig = ( ) ;
1348+ type CreateConfig = usize ;
12831349
12841350 type SetupConfig = ( ) ;
12851351
12861352 type HostContext = crate :: context:: LinuxContext ;
12871353
1288- fn new ( _config : Self :: CreateConfig ) -> AxResult < Self > {
1289- Self :: new ( )
1354+ fn new ( id : Self :: CreateConfig ) -> AxResult < Self > {
1355+ Self :: new ( id )
12901356 }
12911357
12921358 fn load_context ( & self , config : & mut Self :: HostContext ) -> AxResult {
1293- self . load_vmcs_guest ( config) ;
1359+ info ! ( "Loading context {:#x?}" , self ) ;
1360+
1361+ self . load_vmcs_guest ( config) ?;
12941362 Ok ( ( ) )
12951363 }
12961364
@@ -1315,8 +1383,23 @@ impl<H: AxVCpuHal> AxArchVCpu for VmxVcpu<H> {
13151383 }
13161384
13171385 fn run ( & mut self ) -> AxResult < AxVCpuExitReason > {
1386+ if self . id == 3 {
1387+ warn ! ( "Instance vcpu run {:#x?}" , self ) ;
1388+ }
1389+
13181390 match self . inner_run ( ) {
13191391 Some ( exit_info) => Ok ( if exit_info. entry_failure {
1392+ match exit_info. exit_reason {
1393+ VmxExitReason :: INVALID_GUEST_STATE
1394+ | VmxExitReason :: MCE_DURING_VMENTRY
1395+ | VmxExitReason :: MSR_LOAD_FAIL => { }
1396+ _ => {
1397+ error ! ( "Invalid exit reasion when entry failure: {:#x?}" , exit_info) ;
1398+ }
1399+ } ;
1400+
1401+ warn ! ( "VMX entry failure: {:#x?}" , exit_info) ;
1402+
13201403 AxVCpuExitReason :: FailEntry {
13211404 // Todo: get `hardware_entry_failure_reason` somehow.
13221405 hardware_entry_failure_reason : 0 ,
0 commit comments