lkml.org 
[lkml]   [2023]   [Aug]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 2/9] x86/hyperv: Support hypercalls for fully enlightened TDX guests
    Date
    A fully enlightened TDX guest on Hyper-V (i.e. without the paravisor) only
    uses the GHCI call rather than hv_hypercall_pg.

    In hv_do_hypercall(), Hyper-V requires that the input/output addresses
    must have the cc_mask.

    Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
    Reviewed-by: Michael Kelley <mikelley@microsoft.com>
    Signed-off-by: Dexuan Cui <decui@microsoft.com>
    ---
    arch/x86/hyperv/hv_init.c | 8 ++++++++
    arch/x86/hyperv/ivm.c | 17 +++++++++++++++++
    arch/x86/include/asm/mshyperv.h | 15 +++++++++++++++
    drivers/hv/hv_common.c | 10 ++++++++--
    include/asm-generic/mshyperv.h | 1 +
    5 files changed, 49 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
    index 547ebf6a03bc9..d8ea54663113c 100644
    --- a/arch/x86/hyperv/hv_init.c
    +++ b/arch/x86/hyperv/hv_init.c
    @@ -481,6 +481,10 @@ void __init hyperv_init(void)
    /* Hyper-V requires to write guest os id via ghcb in SNP IVM. */
    hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id);

    + /* A TDX guest uses the GHCI call rather than hv_hypercall_pg. */
    + if (hv_isolation_type_tdx())
    + goto skip_hypercall_pg_init;
    +
    hv_hypercall_pg = __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START,
    VMALLOC_END, GFP_KERNEL, PAGE_KERNEL_ROX,
    VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
    @@ -520,6 +524,7 @@ void __init hyperv_init(void)
    wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
    }

    +skip_hypercall_pg_init:
    /*
    * hyperv_init() is called before LAPIC is initialized: see
    * apic_intr_mode_init() -> x86_platform.apic_post_init() and
    @@ -647,6 +652,9 @@ bool hv_is_hyperv_initialized(void)
    if (x86_hyper_type != X86_HYPER_MS_HYPERV)
    return false;

    + /* A TDX guest uses the GHCI call rather than hv_hypercall_pg. */
    + if (hv_isolation_type_tdx())
    + return true;
    /*
    * Verify that earlier initialization succeeded by checking
    * that the hypercall page is setup
    diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
    index d4aafe8b6b50d..5792cddea4914 100644
    --- a/arch/x86/hyperv/ivm.c
    +++ b/arch/x86/hyperv/ivm.c
    @@ -533,3 +533,20 @@ bool hv_isolation_type_tdx(void)
    {
    return static_branch_unlikely(&isolation_type_tdx);
    }
    +
    +#ifdef CONFIG_INTEL_TDX_GUEST
    +
    +u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2)
    +{
    + struct tdx_hypercall_args args = { };
    +
    + args.r10 = control;
    + args.rdx = param1;
    + args.r8 = param2;
    +
    + (void)__tdx_hypercall_ret(&args);
    +
    + return args.r11;
    +}
    +
    +#endif
    diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
    index 83fc3a79f1557..4c68564a165e5 100644
    --- a/arch/x86/include/asm/mshyperv.h
    +++ b/arch/x86/include/asm/mshyperv.h
    @@ -61,7 +61,12 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 acpi_id);
    int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags);

    bool hv_isolation_type_tdx(void);
    +u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2);

    +/*
    + * If the hypercall involves no input or output parameters, the hypervisor
    + * ignores the corresponding GPA pointer.
    + */
    static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
    {
    u64 input_address = input ? virt_to_phys(input) : 0;
    @@ -69,6 +74,10 @@ static inline u64 hv_do_hypercall(u64 control, void *input, void *output)
    u64 hv_status;

    #ifdef CONFIG_X86_64
    + if (hv_isolation_type_tdx())
    + return hv_tdx_hypercall(control,
    + cc_mkdec(input_address),
    + cc_mkdec(output_address));
    if (!hv_hypercall_pg)
    return U64_MAX;

    @@ -112,6 +121,9 @@ static inline u64 _hv_do_fast_hypercall8(u64 control, u64 input1)
    u64 hv_status;

    #ifdef CONFIG_X86_64
    + if (hv_isolation_type_tdx())
    + return hv_tdx_hypercall(control, input1, 0);
    +
    {
    __asm__ __volatile__("mov %[thunk_target], %%r8\n"
    ALTERNATIVE(CALL_NOSPEC, "vmmcall", X86_FEATURE_SEV_ES)
    @@ -158,6 +170,9 @@ static inline u64 _hv_do_fast_hypercall16(u64 control, u64 input1, u64 input2)
    u64 hv_status;

    #ifdef CONFIG_X86_64
    + if (hv_isolation_type_tdx())
    + return hv_tdx_hypercall(control, input1, input2);
    +
    {
    __asm__ __volatile__("mov %[output], %%r8\n"
    ALTERNATIVE(CALL_NOSPEC, "vmmcall", X86_FEATURE_SEV_ES)
    diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c
    index da3307533f4d7..897bbb96f4118 100644
    --- a/drivers/hv/hv_common.c
    +++ b/drivers/hv/hv_common.c
    @@ -381,10 +381,10 @@ int hv_common_cpu_init(unsigned int cpu)
    *outputarg = (char *)(*inputarg) + HV_HYP_PAGE_SIZE;
    }

    - if (hv_isolation_type_en_snp()) {
    + if (hv_isolation_type_en_snp() || hv_isolation_type_tdx()) {
    ret = set_memory_decrypted((unsigned long)*inputarg, pgcount);
    if (ret) {
    - kfree(*inputarg);
    + /* It may be unsafe to free *inputarg */
    *inputarg = NULL;
    return ret;
    }
    @@ -567,3 +567,9 @@ u64 __weak hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_s
    return HV_STATUS_INVALID_PARAMETER;
    }
    EXPORT_SYMBOL_GPL(hv_ghcb_hypercall);
    +
    +u64 __weak hv_tdx_hypercall(u64 control, u64 param1, u64 param2)
    +{
    + return HV_STATUS_INVALID_PARAMETER;
    +}
    +EXPORT_SYMBOL_GPL(hv_tdx_hypercall);
    diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
    index c5e657c3cdf4c..30fa75facd784 100644
    --- a/include/asm-generic/mshyperv.h
    +++ b/include/asm-generic/mshyperv.h
    @@ -283,6 +283,7 @@ enum hv_isolation_type hv_get_isolation_type(void);
    bool hv_is_isolation_supported(void);
    bool hv_isolation_type_snp(void);
    u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
    +u64 hv_tdx_hypercall(u64 control, u64 param1, u64 param2);
    void hyperv_cleanup(void);
    bool hv_query_ext_cap(u64 cap_query);
    void hv_setup_dma_ops(struct device *dev, bool coherent);
    --
    2.25.1
    \
     
     \ /
      Last update: 2023-08-12 00:22    [W:7.166 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site