On 2/26/2025 3:07 PM, Nuno Das Neves wrote: > Introduce hv_result_to_string() for this purpose. This allows > hypercall failures to be debugged more easily with dmesg. > Let the commit message stand on its own, i.e. state that hv_result_to_string() is introduced to convert hyper-v status codes to string. > Signed-off-by: Nuno Das Neves <nunodasneves@xxxxxxxxxxxxxxxxxxx> > --- > drivers/hv/hv_common.c | 65 ++++++++++++++++++++++++++++++++++ > drivers/hv/hv_proc.c | 13 ++++--- > include/asm-generic/mshyperv.h | 1 + > 3 files changed, 74 insertions(+), 5 deletions(-) > > diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c > index 9804adb4cc56..ce20818688fe 100644 > --- a/drivers/hv/hv_common.c > +++ b/drivers/hv/hv_common.c > @@ -740,3 +740,68 @@ void hv_identify_partition_type(void) > pr_crit("Hyper-V: CONFIG_MSHV_ROOT not enabled!\n"); > } > } > + > +const char *hv_result_to_string(u64 hv_status) > +{ > + switch (hv_result(hv_status)) { > + case HV_STATUS_SUCCESS: > + return "HV_STATUS_SUCCESS"; > + case HV_STATUS_INVALID_HYPERCALL_CODE: > + return "HV_STATUS_INVALID_HYPERCALL_CODE"; > + case HV_STATUS_INVALID_HYPERCALL_INPUT: > + return "HV_STATUS_INVALID_HYPERCALL_INPUT"; > + case HV_STATUS_INVALID_ALIGNMENT: > + return "HV_STATUS_INVALID_ALIGNMENT"; > + case HV_STATUS_INVALID_PARAMETER: > + return "HV_STATUS_INVALID_PARAMETER"; > + case HV_STATUS_ACCESS_DENIED: > + return "HV_STATUS_ACCESS_DENIED"; > + case HV_STATUS_INVALID_PARTITION_STATE: > + return "HV_STATUS_INVALID_PARTITION_STATE"; > + case HV_STATUS_OPERATION_DENIED: > + return "HV_STATUS_OPERATION_DENIED"; > + case HV_STATUS_UNKNOWN_PROPERTY: > + return "HV_STATUS_UNKNOWN_PROPERTY"; > + case HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE: > + return "HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE"; > + case HV_STATUS_INSUFFICIENT_MEMORY: > + return "HV_STATUS_INSUFFICIENT_MEMORY"; > + case HV_STATUS_INVALID_PARTITION_ID: > + return "HV_STATUS_INVALID_PARTITION_ID"; > + case HV_STATUS_INVALID_VP_INDEX: > + return "HV_STATUS_INVALID_VP_INDEX"; > + case HV_STATUS_NOT_FOUND: > + return "HV_STATUS_NOT_FOUND"; > + case HV_STATUS_INVALID_PORT_ID: > + return "HV_STATUS_INVALID_PORT_ID"; > + case HV_STATUS_INVALID_CONNECTION_ID: > + return "HV_STATUS_INVALID_CONNECTION_ID"; > + case HV_STATUS_INSUFFICIENT_BUFFERS: > + return "HV_STATUS_INSUFFICIENT_BUFFERS"; > + case HV_STATUS_NOT_ACKNOWLEDGED: > + return "HV_STATUS_NOT_ACKNOWLEDGED"; > + case HV_STATUS_INVALID_VP_STATE: > + return "HV_STATUS_INVALID_VP_STATE"; > + case HV_STATUS_NO_RESOURCES: > + return "HV_STATUS_NO_RESOURCES"; > + case HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED: > + return "HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED"; > + case HV_STATUS_INVALID_LP_INDEX: > + return "HV_STATUS_INVALID_LP_INDEX"; > + case HV_STATUS_INVALID_REGISTER_VALUE: > + return "HV_STATUS_INVALID_REGISTER_VALUE"; > + case HV_STATUS_OPERATION_FAILED: > + return "HV_STATUS_OPERATION_FAILED"; > + case HV_STATUS_TIME_OUT: > + return "HV_STATUS_TIME_OUT"; > + case HV_STATUS_CALL_PENDING: > + return "HV_STATUS_CALL_PENDING"; > + case HV_STATUS_VTL_ALREADY_ENABLED: > + return "HV_STATUS_VTL_ALREADY_ENABLED"; > + default: > + return "Unknown"; > + }; > + return "Unknown"; Unnecessary extra return since the default case already returns "Unknown" > +} > +EXPORT_SYMBOL_GPL(hv_result_to_string); > + Extra line here ^ > diff --git a/drivers/hv/hv_proc.c b/drivers/hv/hv_proc.c > index 2fae18e4f7d2..8fc30f509fa7 100644 > --- a/drivers/hv/hv_proc.c > +++ b/drivers/hv/hv_proc.c > @@ -87,7 +87,8 @@ int hv_call_deposit_pages(int node, u64 partition_id, u32 num_pages) > page_count, 0, input_page, NULL); > local_irq_restore(flags); > if (!hv_result_success(status)) { > - pr_err("Failed to deposit pages: %lld\n", status); > + pr_err("%s: Failed to deposit pages: %s\n", __func__, > + hv_result_to_string(status)); > ret = hv_result_to_errno(status); > goto err_free_allocations; > } > @@ -137,8 +138,9 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) > > if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) { > if (!hv_result_success(status)) { > - pr_err("%s: cpu %u apic ID %u, %lld\n", __func__, > - lp_index, apic_id, status); > + pr_err("%s: cpu %u apic ID %u, %s\n", > + __func__, lp_index, apic_id, > + hv_result_to_string(status)); > ret = hv_result_to_errno(status); > } > break; > @@ -179,8 +181,9 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) > > if (hv_result(status) != HV_STATUS_INSUFFICIENT_MEMORY) { > if (!hv_result_success(status)) { > - pr_err("%s: vcpu %u, lp %u, %lld\n", __func__, > - vp_index, flags, status); > + pr_err("%s: vcpu %u, lp %u, %s\n", > + __func__, vp_index, flags, > + hv_result_to_string(status)); > ret = hv_result_to_errno(status); > } > break; There are more convertible instances in arch/x86/hyperv/irqdomain.c and drivers/iommu/hyperv-iommu.c > diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h > index b13b0cda4ac8..dc4729dba9ef 100644 > --- a/include/asm-generic/mshyperv.h > +++ b/include/asm-generic/mshyperv.h > @@ -298,6 +298,7 @@ static inline int cpumask_to_vpset_skip(struct hv_vpset *vpset, > return __cpumask_to_vpset(vpset, cpus, func); > } > > +const char *hv_result_to_string(u64 hv_status); > int hv_result_to_errno(u64 status); > void hyperv_report_panic(struct pt_regs *regs, long err, bool in_die); > bool hv_is_hyperv_initialized(void);