minimal_rt/arch/x86_64/
hypercall.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Hypercall architecture-dependent infrastructure.
5//!
6//! The hypercall ABI for x64 is well documented in the TLFS.
7
8unsafe extern "C" {
9    /// The hypercall page. The actual hypercall page must be mapped on top of
10    /// this page before it is used.
11    pub static mut HYPERCALL_PAGE: [u8; 4096];
12}
13
14core::arch::global_asm! {
15    r#"
16.globl HYPERCALL_PAGE
17.align 4096
18HYPERCALL_PAGE:
19    ud2
20    .skip 4094, 0xcc
21"#,
22}
23
24/// Invokes a standard hypercall, or a fast hypercall with at most two input
25/// words and zero output words.
26///
27/// # Safety
28/// The caller must ensure the hypercall is safe to issue, and that the
29/// input/output pages are not being concurrently used elsewhere. For fast
30/// hypercalls, the caller must ensure that there are no output words so that
31/// there is no register corruption.
32pub unsafe fn invoke_hypercall(
33    control: hvdef::hypercall::Control,
34    input_gpa_or_fast1: u64,
35    output_gpa_or_fast2: u64,
36) -> hvdef::hypercall::HypercallOutput {
37    let output: u64;
38    // SAFETY: the caller guarantees the safety of this operation.
39    unsafe {
40        core::arch::asm! {
41            "call {hypercall_page}",
42            hypercall_page = sym HYPERCALL_PAGE,
43            inout("rcx") u64::from(control) => _,
44            in("rdx") input_gpa_or_fast1,
45            in("r8") output_gpa_or_fast2,
46            out("rax") output,
47        }
48    }
49    output.into()
50}