@@ -2352,24 +2352,29 @@ static void sev_es_sync_from_ghcb(struct vcpu_svm *svm)
23522352 memset (ghcb -> save .valid_bitmap , 0 , sizeof (ghcb -> save .valid_bitmap ));
23532353}
23542354
2355- static int sev_es_validate_vmgexit (struct vcpu_svm * svm )
2355+ static bool sev_es_validate_vmgexit (struct vcpu_svm * svm )
23562356{
23572357 struct kvm_vcpu * vcpu ;
23582358 struct ghcb * ghcb ;
2359- u64 exit_code = 0 ;
2359+ u64 exit_code ;
2360+ u64 reason ;
23602361
23612362 ghcb = svm -> sev_es .ghcb ;
23622363
2363- /* Only GHCB Usage code 0 is supported */
2364- if (ghcb -> ghcb_usage )
2365- goto vmgexit_err ;
2366-
23672364 /*
2368- * Retrieve the exit code now even though is may not be marked valid
2365+ * Retrieve the exit code now even though it may not be marked valid
23692366 * as it could help with debugging.
23702367 */
23712368 exit_code = ghcb_get_sw_exit_code (ghcb );
23722369
2370+ /* Only GHCB Usage code 0 is supported */
2371+ if (ghcb -> ghcb_usage ) {
2372+ reason = GHCB_ERR_INVALID_USAGE ;
2373+ goto vmgexit_err ;
2374+ }
2375+
2376+ reason = GHCB_ERR_MISSING_INPUT ;
2377+
23732378 if (!ghcb_sw_exit_code_is_valid (ghcb ) ||
23742379 !ghcb_sw_exit_info_1_is_valid (ghcb ) ||
23752380 !ghcb_sw_exit_info_2_is_valid (ghcb ))
@@ -2448,30 +2453,34 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
24482453 case SVM_VMGEXIT_UNSUPPORTED_EVENT :
24492454 break ;
24502455 default :
2456+ reason = GHCB_ERR_INVALID_EVENT ;
24512457 goto vmgexit_err ;
24522458 }
24532459
2454- return 0 ;
2460+ return true ;
24552461
24562462vmgexit_err :
24572463 vcpu = & svm -> vcpu ;
24582464
2459- if (ghcb -> ghcb_usage ) {
2465+ if (reason == GHCB_ERR_INVALID_USAGE ) {
24602466 vcpu_unimpl (vcpu , "vmgexit: ghcb usage %#x is not valid\n" ,
24612467 ghcb -> ghcb_usage );
2468+ } else if (reason == GHCB_ERR_INVALID_EVENT ) {
2469+ vcpu_unimpl (vcpu , "vmgexit: exit code %#llx is not valid\n" ,
2470+ exit_code );
24622471 } else {
2463- vcpu_unimpl (vcpu , "vmgexit: exit reason %#llx is not valid\n" ,
2472+ vcpu_unimpl (vcpu , "vmgexit: exit code %#llx input is not valid\n" ,
24642473 exit_code );
24652474 dump_ghcb (svm );
24662475 }
24672476
2468- vcpu -> run -> exit_reason = KVM_EXIT_INTERNAL_ERROR ;
2469- vcpu -> run -> internal . suberror = KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON ;
2470- vcpu -> run -> internal . ndata = 2 ;
2471- vcpu -> run -> internal . data [ 0 ] = exit_code ;
2472- vcpu -> run -> internal . data [ 1 ] = vcpu -> arch . last_vmentry_cpu ;
2477+ /* Clear the valid entries fields */
2478+ memset ( ghcb -> save . valid_bitmap , 0 , sizeof ( ghcb -> save . valid_bitmap )) ;
2479+
2480+ ghcb_set_sw_exit_info_1 ( ghcb , 2 ) ;
2481+ ghcb_set_sw_exit_info_2 ( ghcb , reason ) ;
24732482
2474- return - EINVAL ;
2483+ return false ;
24752484}
24762485
24772486void sev_es_unmap_ghcb (struct vcpu_svm * svm )
@@ -2530,7 +2539,7 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu)
25302539}
25312540
25322541#define GHCB_SCRATCH_AREA_LIMIT (16ULL * PAGE_SIZE)
2533- static int setup_vmgexit_scratch (struct vcpu_svm * svm , bool sync , u64 len )
2542+ static bool setup_vmgexit_scratch (struct vcpu_svm * svm , bool sync , u64 len )
25342543{
25352544 struct vmcb_control_area * control = & svm -> vmcb -> control ;
25362545 struct ghcb * ghcb = svm -> sev_es .ghcb ;
@@ -2541,14 +2550,14 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
25412550 scratch_gpa_beg = ghcb_get_sw_scratch (ghcb );
25422551 if (!scratch_gpa_beg ) {
25432552 pr_err ("vmgexit: scratch gpa not provided\n" );
2544- return - EINVAL ;
2553+ goto e_scratch ;
25452554 }
25462555
25472556 scratch_gpa_end = scratch_gpa_beg + len ;
25482557 if (scratch_gpa_end < scratch_gpa_beg ) {
25492558 pr_err ("vmgexit: scratch length (%#llx) not valid for scratch address (%#llx)\n" ,
25502559 len , scratch_gpa_beg );
2551- return - EINVAL ;
2560+ goto e_scratch ;
25522561 }
25532562
25542563 if ((scratch_gpa_beg & PAGE_MASK ) == control -> ghcb_gpa ) {
@@ -2566,7 +2575,7 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
25662575 scratch_gpa_end > ghcb_scratch_end ) {
25672576 pr_err ("vmgexit: scratch area is outside of GHCB shared buffer area (%#llx - %#llx)\n" ,
25682577 scratch_gpa_beg , scratch_gpa_end );
2569- return - EINVAL ;
2578+ goto e_scratch ;
25702579 }
25712580
25722581 scratch_va = (void * )svm -> sev_es .ghcb ;
@@ -2579,18 +2588,18 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
25792588 if (len > GHCB_SCRATCH_AREA_LIMIT ) {
25802589 pr_err ("vmgexit: scratch area exceeds KVM limits (%#llx requested, %#llx limit)\n" ,
25812590 len , GHCB_SCRATCH_AREA_LIMIT );
2582- return - EINVAL ;
2591+ goto e_scratch ;
25832592 }
25842593 scratch_va = kvzalloc (len , GFP_KERNEL_ACCOUNT );
25852594 if (!scratch_va )
2586- return - ENOMEM ;
2595+ goto e_scratch ;
25872596
25882597 if (kvm_read_guest (svm -> vcpu .kvm , scratch_gpa_beg , scratch_va , len )) {
25892598 /* Unable to copy scratch area from guest */
25902599 pr_err ("vmgexit: kvm_read_guest for scratch area failed\n" );
25912600
25922601 kvfree (scratch_va );
2593- return - EFAULT ;
2602+ goto e_scratch ;
25942603 }
25952604
25962605 /*
@@ -2606,7 +2615,13 @@ static int setup_vmgexit_scratch(struct vcpu_svm *svm, bool sync, u64 len)
26062615 svm -> sev_es .ghcb_sa = scratch_va ;
26072616 svm -> sev_es .ghcb_sa_len = len ;
26082617
2609- return 0 ;
2618+ return true;
2619+
2620+ e_scratch :
2621+ ghcb_set_sw_exit_info_1 (ghcb , 2 );
2622+ ghcb_set_sw_exit_info_2 (ghcb , GHCB_ERR_INVALID_SCRATCH_AREA );
2623+
2624+ return false;
26102625}
26112626
26122627static void set_ghcb_msr_bits (struct vcpu_svm * svm , u64 value , u64 mask ,
@@ -2657,7 +2672,7 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
26572672
26582673 ret = svm_invoke_exit_handler (vcpu , SVM_EXIT_CPUID );
26592674 if (!ret ) {
2660- ret = - EINVAL ;
2675+ /* Error, keep GHCB MSR value as-is */
26612676 break ;
26622677 }
26632678
@@ -2693,10 +2708,13 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
26932708 GHCB_MSR_TERM_REASON_POS );
26942709 pr_info ("SEV-ES guest requested termination: %#llx:%#llx\n" ,
26952710 reason_set , reason_code );
2696- fallthrough ;
2711+
2712+ ret = - EINVAL ;
2713+ break ;
26972714 }
26982715 default :
2699- ret = - EINVAL ;
2716+ /* Error, keep GHCB MSR value as-is */
2717+ break ;
27002718 }
27012719
27022720 trace_kvm_vmgexit_msr_protocol_exit (svm -> vcpu .vcpu_id ,
@@ -2720,14 +2738,18 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
27202738
27212739 if (!ghcb_gpa ) {
27222740 vcpu_unimpl (vcpu , "vmgexit: GHCB gpa is not set\n" );
2723- return - EINVAL ;
2741+
2742+ /* Without a GHCB, just return right back to the guest */
2743+ return 1 ;
27242744 }
27252745
27262746 if (kvm_vcpu_map (vcpu , ghcb_gpa >> PAGE_SHIFT , & svm -> sev_es .ghcb_map )) {
27272747 /* Unable to map GHCB from guest */
27282748 vcpu_unimpl (vcpu , "vmgexit: error mapping GHCB [%#llx] from guest\n" ,
27292749 ghcb_gpa );
2730- return - EINVAL ;
2750+
2751+ /* Without a GHCB, just return right back to the guest */
2752+ return 1 ;
27312753 }
27322754
27332755 svm -> sev_es .ghcb = svm -> sev_es .ghcb_map .hva ;
@@ -2737,18 +2759,17 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
27372759
27382760 exit_code = ghcb_get_sw_exit_code (ghcb );
27392761
2740- ret = sev_es_validate_vmgexit (svm );
2741- if (ret )
2742- return ret ;
2762+ if (!sev_es_validate_vmgexit (svm ))
2763+ return 1 ;
27432764
27442765 sev_es_sync_from_ghcb (svm );
27452766 ghcb_set_sw_exit_info_1 (ghcb , 0 );
27462767 ghcb_set_sw_exit_info_2 (ghcb , 0 );
27472768
2769+ ret = 1 ;
27482770 switch (exit_code ) {
27492771 case SVM_VMGEXIT_MMIO_READ :
2750- ret = setup_vmgexit_scratch (svm , true, control -> exit_info_2 );
2751- if (ret )
2772+ if (!setup_vmgexit_scratch (svm , true, control -> exit_info_2 ))
27522773 break ;
27532774
27542775 ret = kvm_sev_es_mmio_read (vcpu ,
@@ -2757,8 +2778,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
27572778 svm -> sev_es .ghcb_sa );
27582779 break ;
27592780 case SVM_VMGEXIT_MMIO_WRITE :
2760- ret = setup_vmgexit_scratch (svm , false, control -> exit_info_2 );
2761- if (ret )
2781+ if (!setup_vmgexit_scratch (svm , false, control -> exit_info_2 ))
27622782 break ;
27632783
27642784 ret = kvm_sev_es_mmio_write (vcpu ,
@@ -2787,14 +2807,10 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
27872807 default :
27882808 pr_err ("svm: vmgexit: unsupported AP jump table request - exit_info_1=%#llx\n" ,
27892809 control -> exit_info_1 );
2790- ghcb_set_sw_exit_info_1 (ghcb , 1 );
2791- ghcb_set_sw_exit_info_2 (ghcb ,
2792- X86_TRAP_UD |
2793- SVM_EVTINJ_TYPE_EXEPT |
2794- SVM_EVTINJ_VALID );
2810+ ghcb_set_sw_exit_info_1 (ghcb , 2 );
2811+ ghcb_set_sw_exit_info_2 (ghcb , GHCB_ERR_INVALID_INPUT );
27952812 }
27962813
2797- ret = 1 ;
27982814 break ;
27992815 }
28002816 case SVM_VMGEXIT_UNSUPPORTED_EVENT :
@@ -2814,7 +2830,6 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
28142830{
28152831 int count ;
28162832 int bytes ;
2817- int r ;
28182833
28192834 if (svm -> vmcb -> control .exit_info_2 > INT_MAX )
28202835 return - EINVAL ;
@@ -2823,9 +2838,8 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
28232838 if (unlikely (check_mul_overflow (count , size , & bytes )))
28242839 return - EINVAL ;
28252840
2826- r = setup_vmgexit_scratch (svm , in , bytes );
2827- if (r )
2828- return r ;
2841+ if (!setup_vmgexit_scratch (svm , in , bytes ))
2842+ return 1 ;
28292843
28302844 return kvm_sev_es_string_io (& svm -> vcpu , size , port , svm -> sev_es .ghcb_sa ,
28312845 count , in );
0 commit comments