@@ -30,6 +30,7 @@ typedef enum {
3030 SYZOS_API_NESTED_CREATE_VM = 301 ,
3131 SYZOS_API_NESTED_LOAD_CODE = 302 ,
3232 SYZOS_API_NESTED_VMLAUNCH = 303 ,
33+ SYZOS_API_NESTED_VMRESUME = 304 ,
3334 SYZOS_API_STOP , // Must be the last one
3435} syzos_api_id ;
3536
@@ -102,6 +103,7 @@ GUEST_CODE static void guest_handle_enable_nested(struct api_call_1* cmd, uint64
102103GUEST_CODE static void guest_handle_nested_create_vm (struct api_call_1 * cmd , uint64 cpu_id );
103104GUEST_CODE static void guest_handle_nested_load_code (struct api_call_nested_load_code * cmd , uint64 cpu_id );
104105GUEST_CODE static void guest_handle_nested_vmlaunch (struct api_call_1 * cmd , uint64 cpu_id );
106+ GUEST_CODE static void guest_handle_nested_vmresume (struct api_call_1 * cmd , uint64 cpu_id );
105107
106108typedef enum {
107109 UEXIT_END = (uint64 )- 1 ,
@@ -208,6 +210,9 @@ guest_main(uint64 size, uint64 cpu)
208210 } else if (call == SYZOS_API_NESTED_VMLAUNCH ) {
209211 // Launch the nested VM.
210212 guest_handle_nested_vmlaunch ((struct api_call_1 * )cmd , cpu );
213+ } else if (call == SYZOS_API_NESTED_VMRESUME ) {
214+ // Resume a nested VM.
215+ guest_handle_nested_vmresume ((struct api_call_1 * )cmd , cpu );
211216 }
212217 addr += cmd -> size ;
213218 size -= cmd -> size ;
@@ -733,6 +738,7 @@ GUEST_CODE static noinline void init_vmcs_control_fields(uint64 cpu_id, uint64 v
733738// Common L2 exit reasons for Intel and AMD.
734739typedef enum {
735740 SYZOS_NESTED_EXIT_REASON_HLT = 1 ,
741+ SYZOS_NESTED_EXIT_REASON_INVD = 2 ,
736742 SYZOS_NESTED_EXIT_REASON_UNKNOWN = 0xFF ,
737743} syz_nested_exit_reason ;
738744
@@ -748,22 +754,37 @@ GUEST_CODE static void guest_uexit_l2(uint64 exit_reason, syz_nested_exit_reason
748754 }
749755}
750756
751- GUEST_CODE static syz_nested_exit_reason map_intel_exit_reason (uint64 reason )
757+ #define EXIT_REASON_HLT 0xc
758+ #define EXIT_REASON_INVD 0xd
759+
760+ GUEST_CODE static syz_nested_exit_reason map_intel_exit_reason (uint64 basic_reason )
752761{
753- volatile uint64 basic_reason = reason & 0xFFFF ;
754- // EXIT_REASON_HLT.
755- if (basic_reason == 0xc )
762+ // Disable optimizations.
763+ volatile uint64 reason = basic_reason ;
764+ if (reason == EXIT_REASON_HLT )
756765 return SYZOS_NESTED_EXIT_REASON_HLT ;
766+ if (reason == EXIT_REASON_INVD )
767+ return SYZOS_NESTED_EXIT_REASON_INVD ;
757768 return SYZOS_NESTED_EXIT_REASON_UNKNOWN ;
758769}
759770
771+ GUEST_CODE static void advance_l2_rip_intel (uint64 basic_reason )
772+ {
773+ if (basic_reason == EXIT_REASON_INVD ) {
774+ uint64 rip = vmread (VMCS_GUEST_RIP );
775+ vmwrite (VMCS_GUEST_RIP , rip + 2 );
776+ }
777+ }
778+
760779// This function is called from inline assembly.
761780__attribute__((used ))
762781GUEST_CODE static void
763782nested_vm_exit_handler_intel (uint64 exit_reason , struct l2_guest_regs * regs )
764783{
765- syz_nested_exit_reason mapped_reason = map_intel_exit_reason (exit_reason );
784+ uint64 basic_reason = exit_reason & 0xFFFF ;
785+ syz_nested_exit_reason mapped_reason = map_intel_exit_reason (basic_reason );
766786 guest_uexit_l2 (exit_reason , mapped_reason , CPU_VENDOR_INTEL );
787+ advance_l2_rip_intel (basic_reason );
767788}
768789
769790extern char after_vmentry_label ;
@@ -810,20 +831,36 @@ __attribute__((naked)) GUEST_CODE static void nested_vm_exit_handler_intel_asm(v
810831 [vm_exit_reason ] "i" (VMCS_VM_EXIT_REASON ) : "memory" , "cc" , "rbx" , "rdi" , "rsi" );
811832}
812833
813- GUEST_CODE static syz_nested_exit_reason map_amd_exit_reason (uint64 reason )
834+ #define VMEXIT_INVD 0x76
835+ #define VMEXIT_HLT 0x78
836+
837+ GUEST_CODE static syz_nested_exit_reason map_amd_exit_reason (uint64 basic_reason )
814838{
815- volatile uint64 basic_reason = reason & 0xFFFF ;
816- // #VMEXIT_HLT.
817- if (basic_reason == 0x78 )
839+ // Disable optimizations.
840+ volatile uint64 reason = basic_reason ;
841+ if (reason == VMEXIT_HLT )
818842 return SYZOS_NESTED_EXIT_REASON_HLT ;
843+ if (reason == VMEXIT_INVD )
844+ return SYZOS_NESTED_EXIT_REASON_INVD ;
819845 return SYZOS_NESTED_EXIT_REASON_UNKNOWN ;
820846}
821847
848+ GUEST_CODE static void advance_l2_rip_amd (uint64 basic_reason , uint64 cpu_id , uint64 vm_id )
849+ {
850+ if (basic_reason == VMEXIT_INVD ) {
851+ uint64 vmcb_addr = X86_SYZOS_ADDR_VMCS_VMCB (cpu_id , vm_id );
852+ uint64 rip = vmcb_read64 ((volatile uint8 * )vmcb_addr , VMCB_GUEST_RIP );
853+ vmcb_write64 (vmcb_addr , VMCB_GUEST_RIP , rip + 2 );
854+ }
855+ }
856+
822857__attribute__((used )) GUEST_CODE static void
823858nested_vm_exit_handler_amd (uint64 exit_reason , uint64 cpu_id , uint64 vm_id )
824859{
825- syz_nested_exit_reason mapped_reason = map_amd_exit_reason (exit_reason );
860+ volatile uint64 basic_reason = exit_reason & 0xFFFF ;
861+ syz_nested_exit_reason mapped_reason = map_amd_exit_reason (basic_reason );
826862 guest_uexit_l2 (exit_reason , mapped_reason , CPU_VENDOR_AMD );
863+ advance_l2_rip_amd (basic_reason , cpu_id , vm_id );
827864}
828865
829866GUEST_CODE static noinline void init_vmcs_host_state (void )
@@ -1011,7 +1048,7 @@ GUEST_CODE static noinline void init_vmcb_guest_state(uint64 cpu_id, uint64 vm_i
10111048 vmcb_write32 (vmcb_addr , VMCB_GUEST_IDTR_LIM , idtr .limit );
10121049
10131050 // Setup VMCB Control Fields.
1014- vmcb_write32 (vmcb_addr , VMCB_CTRL_INTERCEPT_VEC3 , VMCB_CTRL_INTERCEPT_HLT );
1051+ vmcb_write32 (vmcb_addr , VMCB_CTRL_INTERCEPT_VEC3 , VMCB_CTRL_INTERCEPT_VEC3_ALL );
10151052 vmcb_write32 (vmcb_addr , VMCB_CTRL_INTERCEPT_VEC4 , VMCB_CTRL_INTERCEPT_VEC4_ALL );
10161053
10171054 // Enable Nested Paging (NPT):
@@ -1078,9 +1115,8 @@ guest_handle_nested_load_code(struct api_call_nested_load_code* cmd, uint64 cpu_
10781115}
10791116
10801117GUEST_CODE static noinline void
1081- guest_handle_nested_vmentry_intel (struct api_call_1 * cmd , uint64 cpu_id , bool is_launch )
1118+ guest_handle_nested_vmentry_intel (uint64 vm_id , uint64 cpu_id , bool is_launch )
10821119{
1083- uint64 vm_id = cmd -> arg ;
10841120 uint64 vmx_error_code = 0 ;
10851121 uint8 fail_flag = 0 ; // Will be 1 if EITHER CF or ZF is set
10861122
@@ -1149,19 +1185,24 @@ guest_run_amd_vm(uint64 cpu_id, uint64 vm_id)
11491185}
11501186
11511187GUEST_CODE static noinline void
1152- guest_handle_nested_vmlaunch_amd (struct api_call_1 * cmd , uint64 cpu_id , uint64 vm_id )
1188+ guest_handle_nested_vmlaunch (struct api_call_1 * cmd , uint64 cpu_id )
11531189{
1154- guest_run_amd_vm (cpu_id , vm_id );
1190+ uint64 vm_id = cmd -> arg ;
1191+ if (get_cpu_vendor () == CPU_VENDOR_INTEL ) {
1192+ guest_handle_nested_vmentry_intel (vm_id , cpu_id , true);
1193+ } else {
1194+ guest_run_amd_vm (cpu_id , vm_id );
1195+ }
11551196}
11561197
11571198GUEST_CODE static noinline void
1158- guest_handle_nested_vmlaunch (struct api_call_1 * cmd , uint64 cpu_id )
1199+ guest_handle_nested_vmresume (struct api_call_1 * cmd , uint64 cpu_id )
11591200{
11601201 uint64 vm_id = cmd -> arg ;
11611202 if (get_cpu_vendor () == CPU_VENDOR_INTEL ) {
1162- guest_handle_nested_vmentry_intel (cmd , cpu_id , true );
1203+ guest_handle_nested_vmentry_intel (vm_id , cpu_id , false );
11631204 } else {
1164- guest_handle_nested_vmlaunch_amd ( cmd , cpu_id , vm_id );
1205+ guest_run_amd_vm ( cpu_id , vm_id );
11651206 }
11661207}
11671208
0 commit comments