Michael Kelley | a4d7e8a | 2021-06-02 14:36:44 -0700 | [diff] [blame^] | 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); |