@@ -684,40 +684,6 @@ u64 __weak hv_tdx_hypercall(u64 control, u64 param1, u64 param2)
684
684
}
685
685
EXPORT_SYMBOL_GPL (hv_tdx_hypercall );
686
686
687
- /* Convert a hypercall result into a linux-friendly error code. */
688
- int hv_result_to_errno (u64 status )
689
- {
690
- /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
691
- if (unlikely (status == U64_MAX ))
692
- return - EOPNOTSUPP ;
693
- /*
694
- * A failed hypercall is usually only recoverable (or loggable) near
695
- * the call site where the HV_STATUS_* code is known. So the errno
696
- * it gets converted to is not too useful further up the stack.
697
- * Provide a few mappings that could be useful, and revert to -EIO
698
- * as a fallback.
699
- */
700
- switch (hv_result (status )) {
701
- case HV_STATUS_SUCCESS :
702
- return 0 ;
703
- case HV_STATUS_INVALID_HYPERCALL_CODE :
704
- case HV_STATUS_INVALID_HYPERCALL_INPUT :
705
- case HV_STATUS_INVALID_PARAMETER :
706
- case HV_STATUS_INVALID_PARTITION_ID :
707
- case HV_STATUS_INVALID_VP_INDEX :
708
- case HV_STATUS_INVALID_PORT_ID :
709
- case HV_STATUS_INVALID_CONNECTION_ID :
710
- case HV_STATUS_INVALID_LP_INDEX :
711
- case HV_STATUS_INVALID_REGISTER_VALUE :
712
- return - EINVAL ;
713
- case HV_STATUS_INSUFFICIENT_MEMORY :
714
- return - ENOMEM ;
715
- default :
716
- break ;
717
- }
718
- return - EIO ;
719
- }
720
-
721
687
void hv_identify_partition_type (void )
722
688
{
723
689
/* Assume guest role */
@@ -740,3 +706,98 @@ void hv_identify_partition_type(void)
740
706
pr_crit ("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n" );
741
707
}
742
708
}
709
+
710
+ struct hv_status_info {
711
+ char * string ;
712
+ int errno ;
713
+ u16 code ;
714
+ };
715
+
716
+ /*
717
+ * Note on the errno mappings:
718
+ * A failed hypercall is usually only recoverable (or loggable) near
719
+ * the call site where the HV_STATUS_* code is known. So the errno
720
+ * it gets converted to is not too useful further up the stack.
721
+ * Provide a few mappings that could be useful, and revert to -EIO
722
+ * as a fallback.
723
+ */
724
+ static const struct hv_status_info hv_status_infos [] = {
725
+ #define _STATUS_INFO (status , errno ) { #status , (errno ), (status ) }
726
+ _STATUS_INFO (HV_STATUS_SUCCESS , 0 ),
727
+ _STATUS_INFO (HV_STATUS_INVALID_HYPERCALL_CODE , - EINVAL ),
728
+ _STATUS_INFO (HV_STATUS_INVALID_HYPERCALL_INPUT , - EINVAL ),
729
+ _STATUS_INFO (HV_STATUS_INVALID_ALIGNMENT , - EIO ),
730
+ _STATUS_INFO (HV_STATUS_INVALID_PARAMETER , - EINVAL ),
731
+ _STATUS_INFO (HV_STATUS_ACCESS_DENIED , - EIO ),
732
+ _STATUS_INFO (HV_STATUS_INVALID_PARTITION_STATE , - EIO ),
733
+ _STATUS_INFO (HV_STATUS_OPERATION_DENIED , - EIO ),
734
+ _STATUS_INFO (HV_STATUS_UNKNOWN_PROPERTY , - EIO ),
735
+ _STATUS_INFO (HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE , - EIO ),
736
+ _STATUS_INFO (HV_STATUS_INSUFFICIENT_MEMORY , - ENOMEM ),
737
+ _STATUS_INFO (HV_STATUS_INVALID_PARTITION_ID , - EINVAL ),
738
+ _STATUS_INFO (HV_STATUS_INVALID_VP_INDEX , - EINVAL ),
739
+ _STATUS_INFO (HV_STATUS_NOT_FOUND , - EIO ),
740
+ _STATUS_INFO (HV_STATUS_INVALID_PORT_ID , - EINVAL ),
741
+ _STATUS_INFO (HV_STATUS_INVALID_CONNECTION_ID , - EINVAL ),
742
+ _STATUS_INFO (HV_STATUS_INSUFFICIENT_BUFFERS , - EIO ),
743
+ _STATUS_INFO (HV_STATUS_NOT_ACKNOWLEDGED , - EIO ),
744
+ _STATUS_INFO (HV_STATUS_INVALID_VP_STATE , - EIO ),
745
+ _STATUS_INFO (HV_STATUS_NO_RESOURCES , - EIO ),
746
+ _STATUS_INFO (HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED , - EIO ),
747
+ _STATUS_INFO (HV_STATUS_INVALID_LP_INDEX , - EINVAL ),
748
+ _STATUS_INFO (HV_STATUS_INVALID_REGISTER_VALUE , - EINVAL ),
749
+ _STATUS_INFO (HV_STATUS_INVALID_LP_INDEX , - EIO ),
750
+ _STATUS_INFO (HV_STATUS_INVALID_REGISTER_VALUE , - EIO ),
751
+ _STATUS_INFO (HV_STATUS_OPERATION_FAILED , - EIO ),
752
+ _STATUS_INFO (HV_STATUS_TIME_OUT , - EIO ),
753
+ _STATUS_INFO (HV_STATUS_CALL_PENDING , - EIO ),
754
+ _STATUS_INFO (HV_STATUS_VTL_ALREADY_ENABLED , - EIO ),
755
+ #undef _STATUS_INFO
756
+ };
757
+
758
+ static inline const struct hv_status_info * find_hv_status_info (u64 hv_status )
759
+ {
760
+ int i ;
761
+ u16 code = hv_result (hv_status );
762
+
763
+ for (i = 0 ; i < ARRAY_SIZE (hv_status_infos ); ++ i ) {
764
+ const struct hv_status_info * info = & hv_status_infos [i ];
765
+
766
+ if (info -> code == code )
767
+ return info ;
768
+ }
769
+
770
+ return NULL ;
771
+ }
772
+
773
+ /* Convert a hypercall result into a linux-friendly error code. */
774
+ int hv_result_to_errno (u64 status )
775
+ {
776
+ const struct hv_status_info * info ;
777
+
778
+ /* hv_do_hypercall() may return U64_MAX, hypercalls aren't possible */
779
+ if (unlikely (status == U64_MAX ))
780
+ return - EOPNOTSUPP ;
781
+
782
+ info = find_hv_status_info (status );
783
+ if (info )
784
+ return info -> errno ;
785
+
786
+ return - EIO ;
787
+ }
788
+ EXPORT_SYMBOL_GPL (hv_result_to_errno );
789
+
790
+ const char * hv_result_to_string (u64 status )
791
+ {
792
+ const struct hv_status_info * info ;
793
+
794
+ if (unlikely (status == U64_MAX ))
795
+ return "Hypercall page missing!" ;
796
+
797
+ info = find_hv_status_info (status );
798
+ if (info )
799
+ return info -> string ;
800
+
801
+ return "Unknown" ;
802
+ }
803
+ EXPORT_SYMBOL_GPL (hv_result_to_string );
0 commit comments