Drivers: hv: hv_common: use meaningful errnos for hypercall statuses#146
Drivers: hv: hv_common: use meaningful errnos for hypercall statuses#146hargar19 wants to merge 1 commit into
Conversation
Several HV_STATUS_* codes were collapsed to -EIO in commit 3817854 ("hyperv: Log hypercall status codes as strings") when hv_result_to_errno() was converted from a switch statement to a table-driven lookup. The change was a side-effect of consolidating string/errno mappings into one place; the commit message focused on adding hv_status_printk() for debugging. The previous OOT helper hv_status_to_errno() (in v6.12) preserved more meaningful errnos for several codes that have natural POSIX counterparts. The collapse-to-EIO loses information at call sites that key behavior on the converted errno (for example mshv_vtl_configure_reg_page() whitelists -EINVAL/-EACCES to fall back gracefully when the host refuses to install the register-page overlay; with -EIO that call site now hits a BUG()). Restore the semantically meaningful mappings for the affected statuses: HV_STATUS_ACCESS_DENIED -EIO -> -EACCES HV_STATUS_OPERATION_DENIED -EIO -> -EACCES HV_STATUS_UNKNOWN_PROPERTY -EIO -> -EINVAL HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGE -EIO -> -EINVAL HV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTED -EIO -> -EOPNOTSUPP EACCES is the canonical errno for permission denied, EINVAL for invalid argument, and EOPNOTSUPP for unsupported operations. These mappings match both their <errno.h> definitions and the established meanings in the OOT v6.12 helper. Also drop two duplicate _STATUS_INFO() rows for HV_STATUS_INVALID_LP_INDEX and HV_STATUS_INVALID_REGISTER_VALUE that were leftover from the original table conversion. find_hv_status_info() is first-match-wins so the dead rows were not reachable, but they are confusing on review. Impact analysis --------------- The change only matters at sites that distinguish between specific errnos (e.g. `ret == -EIO` vs `ret == -EACCES`). To confirm safety, the entire kernel tree was audited for equality comparisons against any of the affected errnos in Hyper-V-touching code: $ git grep -nE '(ret|status|err|rc|r)[[:space:]]*==[[:space:]]*\ -(EACCES|EBADFD|ENOTRECOVERABLE|EOPNOTSUPP|EIO|EINVAL|ENOMEM)' \ -- drivers/hv/ arch/x86/hyperv/ arch/arm64/hyperv/ \ drivers/iommu/hyperv-iommu.c Results in Hyper-V code: drivers/hv/hv_balloon.c: ret == -EEXIST | ret == -EAGAIN (not in table) drivers/hv/mshv_eventfd.c: ret == -EAGAIN (not in table) drivers/hv/connection.c: ret == -ETIMEDOUT (not in table) drivers/hv/mshv_vtl_main.c: ret == -EINVAL || ret == -EACCES (the consumer this patch fixes) No other in-tree code path inspects -EOPNOTSUPP, -EACCES, -EINVAL or -EIO from a hypercall result to make a behavioral decision. The remaining HV_STATUS_* codes that 3817854 mapped to -EIO are therefore left as -EIO; nothing keys behavior off the distinction today. Signed-off-by: Hardik Garg <hargar@microsoft.com>
There was a problem hiding this comment.
Pull request overview
This PR restores more semantically meaningful Linux errno mappings for specific Hyper-V hypercall status codes in hv_result_to_errno() by adjusting the hv_status_infos[] lookup table, and removes unreachable duplicate table rows introduced during the earlier table conversion.
Changes:
- Map
HV_STATUS_ACCESS_DENIED/HV_STATUS_OPERATION_DENIEDto-EACCESinstead of-EIO. - Map
HV_STATUS_UNKNOWN_PROPERTY/HV_STATUS_PROPERTY_VALUE_OUT_OF_RANGEto-EINVALinstead of-EIO, andHV_STATUS_PROCESSOR_FEATURE_NOT_SUPPORTEDto-EOPNOTSUPP. - Remove duplicate (dead)
_STATUS_INFO()entries forHV_STATUS_INVALID_LP_INDEXandHV_STATUS_INVALID_REGISTER_VALUE.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Why arm VM fails on v6.18 but not v6.12: The bug surface: same hypercall, same response, same hardware
This is a benign per-VP policy denial — the host supports the register-page feature in principle, but refuses the install on this configuration. The register page is an optional performance optimization (lets user-mode skip a hypercall for some VP register accesses); kernels are expected to fall back gracefully. v6.12: failure handled gracefully The caller mshv_vtl_configure_reg_page() (drivers/hv/mshv_vtl_main.c) whitelists exactly this: So Kernel boots normally. The host's denial is logged and ignored, hypercall-based path takes over. v6.18: same response, but mapped to Result: HV_STATUS_ACCESS_DENIED is now mapped to -EIO, the whitelist misses it, and the code hits BUG():
Diagnostic instrumentation confirming the diagnosis v6.12 (boots): v6.18 (crashes pre-patch): Identical hypercall, identical raw hypervisor response (0x6), different errno → different kernel reaction. Impact analysis for this change:The change only matters at sites that distinguish between specific errnos (e.g. ret == -EIO vs ret == -EACCES). To confirm safety, the entire kernel tree was audited for equality comparisons against any of the affected errnos in Hyper-V-touching code: Results in Hyper-V code:
No other in-tree code path inspects -EOPNOTSUPP, -EACCES, -EINVAL or -EIO from a hypercall result to make a behavioral decision. The remaining HV_STATUS_* codes that 3817854 mapped to -EIO are therefore left as -EIO; nothing keys behavior off the distinction today. |
|
Change LGTM, have we run Sashiko or AI agent on this? Nit, subject: s/"Drivers: hv: hv_common:"/Drivers: hv:" |
namancse
left a comment
There was a problem hiding this comment.
No issues with Sashiko, Opus 4.7.
saurabh-sengar
left a comment
There was a problem hiding this comment.
LGTM, please make sure we do proper testing
Several HV_STATUS_* codes were collapsed to -EIO in commit 3817854 ("hyperv: Log hypercall status codes as strings") when hv_result_to_errno() was converted from a switch statement to a table-driven lookup. The change was a side-effect of consolidating string/errno mappings into one place; the commit message focused on adding hv_status_printk() for debugging.
The previous mapping in hv_status_to_errno() (used in OHCL v6.12 and earlier) preserved more meaningful errnos for several codes that have natural POSIX counterparts. The collapse to -EIO loses information at call sites that key behavior on the converted errno (for example mshv_vtl_configure_reg_page() whitelists -EINVAL/-EACCES to fall back gracefully when the host refuses to install the register-page overlay; with -EIO that call site now hits a BUG()).
Restore the semantically meaningful mappings for the affected statuses:
EACCES is the canonical errno for permission denied, EINVAL for invalid argument, and EOPNOTSUPP for unsupported operations. These mappings match both their <errno.h> definitions and the established meanings in the v6.12 mapping.
Also drop two duplicate _STATUS_INFO() rows for HV_STATUS_INVALID_LP_INDEX and HV_STATUS_INVALID_REGISTER_VALUE that were leftover from the original table conversion.
Signed-off-by: Hardik Garg hargar@microsoft.com