|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | + |
| 3 | +/* |
| 4 | + * Architecture neutral utility routines for interacting with |
| 5 | + * Hyper-V. This file is specifically for code that must be |
| 6 | + * built-in to the kernel image when CONFIG_HYPERV is set |
| 7 | + * (vs. being in a module) because it is called from architecture |
| 8 | + * specific code under arch/. |
| 9 | + * |
| 10 | + * Copyright (C) 2021, Microsoft, Inc. |
| 11 | + * |
| 12 | + * Author : Michael Kelley <mikelley@microsoft.com> |
| 13 | + */ |
| 14 | + |
| 15 | +#include <linux/types.h> |
| 16 | +#include <linux/export.h> |
| 17 | +#include <linux/bitfield.h> |
| 18 | +#include <asm/hyperv-tlfs.h> |
| 19 | +#include <asm/mshyperv.h> |
| 20 | + |
| 21 | + |
| 22 | +/* Bit mask of the extended capability to query: see HV_EXT_CAPABILITY_xxx */ |
| 23 | +bool hv_query_ext_cap(u64 cap_query) |
| 24 | +{ |
| 25 | + /* |
| 26 | + * The address of the 'hv_extended_cap' variable will be used as an |
| 27 | + * output parameter to the hypercall below and so it should be |
| 28 | + * compatible with 'virt_to_phys'. Which means, it's address should be |
| 29 | + * directly mapped. Use 'static' to keep it compatible; stack variables |
| 30 | + * can be virtually mapped, making them imcompatible with |
| 31 | + * 'virt_to_phys'. |
| 32 | + * Hypercall input/output addresses should also be 8-byte aligned. |
| 33 | + */ |
| 34 | + static u64 hv_extended_cap __aligned(8); |
| 35 | + static bool hv_extended_cap_queried; |
| 36 | + u64 status; |
| 37 | + |
| 38 | + /* |
| 39 | + * Querying extended capabilities is an extended hypercall. Check if the |
| 40 | + * partition supports extended hypercall, first. |
| 41 | + */ |
| 42 | + if (!(ms_hyperv.priv_high & HV_ENABLE_EXTENDED_HYPERCALLS)) |
| 43 | + return false; |
| 44 | + |
| 45 | + /* Extended capabilities do not change at runtime. */ |
| 46 | + if (hv_extended_cap_queried) |
| 47 | + return hv_extended_cap & cap_query; |
| 48 | + |
| 49 | + status = hv_do_hypercall(HV_EXT_CALL_QUERY_CAPABILITIES, NULL, |
| 50 | + &hv_extended_cap); |
| 51 | + |
| 52 | + /* |
| 53 | + * The query extended capabilities hypercall should not fail under |
| 54 | + * any normal circumstances. Avoid repeatedly making the hypercall, on |
| 55 | + * error. |
| 56 | + */ |
| 57 | + hv_extended_cap_queried = true; |
| 58 | + if (!hv_result_success(status)) { |
| 59 | + pr_err("Hyper-V: Extended query capabilities hypercall failed 0x%llx\n", |
| 60 | + status); |
| 61 | + return false; |
| 62 | + } |
| 63 | + |
| 64 | + return hv_extended_cap & cap_query; |
| 65 | +} |
| 66 | +EXPORT_SYMBOL_GPL(hv_query_ext_cap); |
0 commit comments