@@ -684,40 +684,6 @@ u64 __weak hv_tdx_hypercall(u64 control, u64 param1, u64 param2)
684684}
685685EXPORT_SYMBOL_GPL (hv_tdx_hypercall );
686686
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-
721687void hv_identify_partition_type (void )
722688{
723689 /* Assume guest role */
@@ -740,3 +706,98 @@ void hv_identify_partition_type(void)
740706 pr_crit ("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n" );
741707 }
742708}
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