@@ -32,7 +32,7 @@ use super::vmcs::{
32
32
use crate :: LinuxContext ;
33
33
use crate :: page_table:: GuestPageTable64 ;
34
34
use crate :: page_table:: GuestPageWalkInfo ;
35
- use crate :: segmentation:: Segment ;
35
+ use crate :: segmentation:: { Segment , SegmentAccessRights } ;
36
36
use crate :: xstate:: XState ;
37
37
use crate :: { msr:: Msr , regs:: GeneralRegisters } ;
38
38
@@ -70,11 +70,13 @@ pub struct VmxVcpu<H: AxVCpuHal> {
70
70
cur_xstate : XState ,
71
71
entry : Option < GuestPhysAddr > ,
72
72
ept_root : Option < HostPhysAddr > ,
73
+
74
+ id : usize ,
73
75
}
74
76
75
77
impl < H : AxVCpuHal > VmxVcpu < H > {
76
78
/// Create a new [`VmxVcpu`].
77
- pub fn new ( ) -> AxResult < Self > {
79
+ pub fn new ( id : usize ) -> AxResult < Self > {
78
80
let vcpu = Self {
79
81
guest_regs : GeneralRegisters :: default ( ) ,
80
82
host_stack_top : 0 ,
@@ -88,6 +90,7 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
88
90
cur_xstate : XState :: new ( ) ,
89
91
entry : None ,
90
92
ept_root : None ,
93
+ id,
91
94
} ;
92
95
debug ! ( "[HV] created VmxVcpu(vmcs: {:#x})" , vcpu. vmcs. phys_addr( ) , ) ;
93
96
Ok ( vcpu)
@@ -543,6 +546,11 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
543
546
} } ;
544
547
}
545
548
549
+ debug ! (
550
+ "setup_vmcs_guest_from_ctx: CS access rights: {:?}" ,
551
+ linux. cs. access_rights
552
+ ) ;
553
+
546
554
set_guest_segment ! ( linux. es, ES ) ;
547
555
set_guest_segment ! ( linux. cs, CS ) ;
548
556
set_guest_segment ! ( linux. ss, SS ) ;
@@ -764,33 +772,42 @@ impl<H: AxVCpuHal> VmxVcpu<H> {
764
772
Ok ( ( ) )
765
773
}
766
774
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
792
808
793
809
linux. load_guest_regs ( self . regs ( ) ) ;
810
+ Ok ( ( ) )
794
811
}
795
812
796
813
fn get_paging_level ( & self ) -> usize {
@@ -1260,6 +1277,33 @@ fn get_tr_base(tr: SegmentSelector, gdt: &DescriptorTablePointer<u64>) -> u64 {
1260
1277
impl < H : AxVCpuHal > Debug for VmxVcpu < H > {
1261
1278
fn fmt ( & self , f : & mut Formatter ) -> Result {
1262
1279
( || -> 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
+
1263
1307
Ok ( f. debug_struct ( "VmxVcpu" )
1264
1308
. field ( "guest_regs" , & self . guest_regs )
1265
1309
. field ( "rip" , & VmcsGuestNW :: RIP . read ( ) ?)
@@ -1268,29 +1312,53 @@ impl<H: AxVCpuHal> Debug for VmxVcpu<H> {
1268
1312
. field ( "cr0" , & VmcsGuestNW :: CR0 . read ( ) ?)
1269
1313
. field ( "cr3" , & VmcsGuestNW :: CR3 . read ( ) ?)
1270
1314
. 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)
1272
1326
. field ( "fs_base" , & VmcsGuestNW :: FS_BASE . read ( ) ?)
1327
+ . field ( "fs_selector" , & fs_selector)
1328
+ . field ( "fs_access_rights" , & fs_access_rights)
1273
1329
. 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)
1275
1341
. finish ( ) )
1276
1342
} ) ( )
1277
1343
. unwrap ( )
1278
1344
}
1279
1345
}
1280
1346
1281
1347
impl < H : AxVCpuHal > AxArchVCpu for VmxVcpu < H > {
1282
- type CreateConfig = ( ) ;
1348
+ type CreateConfig = usize ;
1283
1349
1284
1350
type SetupConfig = ( ) ;
1285
1351
1286
1352
type HostContext = crate :: context:: LinuxContext ;
1287
1353
1288
- fn new ( _config : Self :: CreateConfig ) -> AxResult < Self > {
1289
- Self :: new ( )
1354
+ fn new ( id : Self :: CreateConfig ) -> AxResult < Self > {
1355
+ Self :: new ( id )
1290
1356
}
1291
1357
1292
1358
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) ?;
1294
1362
Ok ( ( ) )
1295
1363
}
1296
1364
@@ -1315,8 +1383,23 @@ impl<H: AxVCpuHal> AxArchVCpu for VmxVcpu<H> {
1315
1383
}
1316
1384
1317
1385
fn run ( & mut self ) -> AxResult < AxVCpuExitReason > {
1386
+ if self . id == 3 {
1387
+ warn ! ( "Instance vcpu run {:#x?}" , self ) ;
1388
+ }
1389
+
1318
1390
match self . inner_run ( ) {
1319
1391
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
+
1320
1403
AxVCpuExitReason :: FailEntry {
1321
1404
// Todo: get `hardware_entry_failure_reason` somehow.
1322
1405
hardware_entry_failure_reason : 0 ,
0 commit comments