// SPDX-License-Identifier: GPL-2.0 /* * Architecture neutral utility routines for interacting with * Hyper-V. This file is specifically for code that must be * built-in to the kernel image when CONFIG_HYPERV is set * (vs. being in a module) because it is called from architecture * specific code under arch/. * * Copyright (C) 2021, Microsoft, Inc. * * Author : Michael Kelley */ #include #include #include #include #include /* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */ bool hv_query_ext_cap(u64 cap_query) { /* * The address of the 'hv_extended_cap' variable will be used as an * output parameter to the hypercall below and so it should be * compatible with 'virt_to_phys'. Which means, it's address should be * directly mapped. Use 'static' to keep it compatible; stack variables * can be virtually mapped, making them imcompatible with * 'virt_to_phys'. * Hypercall input/output addresses should also be 8-byte aligned. */ static u64 hv_extended_cap __aligned(8); static bool hv_extended_cap_queried; u64 status; /* * Querying extended capabilities is an extended hypercall. Check if the * partition supports extended hypercall, first. */ if (!(ms_hyperv.priv_high & HV_ENABLE_EXTENDED_HYPERCALLS)) return false; /* Extended capabilities do not change at runtime. */ if (hv_extended_cap_queried) return hv_extended_cap & cap_query; status = hv_do_hypercall(HV_EXT_CALL_QUERY_CAPABILITIES, NULL, &hv_extended_cap); /* * The query extended capabilities hypercall should not fail under * any normal circumstances. Avoid repeatedly making the hypercall, on * error. */ hv_extended_cap_queried = true; if (!hv_result_success(status)) { pr_err("Hyper-V: Extended query capabilities hypercall failed 0x%llx\n", status); return false; } return hv_extended_cap & cap_query; } EXPORT_SYMBOL_GPL(hv_query_ext_cap);