lkml.org 
[lkml]   [2021]   [Jul]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 06/13] HV: Add ghcb hvcall support for SNP VM
    Date
    From: Tianyu Lan <Tianyu.Lan@microsoft.com>

    Hyper-V provides ghcb hvcall to handle VMBus
    HVCALL_SIGNAL_EVENT and HVCALL_POST_MESSAGE
    msg in SNP Isolation VM. Add such support.

    Signed-off-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
    ---
    arch/x86/hyperv/ivm.c | 42 +++++++++++++++++++++++++++++++++
    arch/x86/include/asm/mshyperv.h | 1 +
    drivers/hv/connection.c | 6 ++++-
    drivers/hv/hv.c | 8 ++++++-
    include/asm-generic/mshyperv.h | 29 +++++++++++++++++++++++
    5 files changed, 84 insertions(+), 2 deletions(-)

    diff --git a/arch/x86/hyperv/ivm.c b/arch/x86/hyperv/ivm.c
    index 9c30d5bb7b64..13bab7f07085 100644
    --- a/arch/x86/hyperv/ivm.c
    +++ b/arch/x86/hyperv/ivm.c
    @@ -15,6 +15,48 @@
    #include <asm/io.h>
    #include <asm/mshyperv.h>

    +u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size)
    +{
    + union hv_ghcb *hv_ghcb;
    + void **ghcb_base;
    + unsigned long flags;
    +
    + if (!ms_hyperv.ghcb_base)
    + return -EFAULT;
    +
    + WARN_ON(in_nmi());
    +
    + local_irq_save(flags);
    + ghcb_base = (void **)this_cpu_ptr(ms_hyperv.ghcb_base);
    + hv_ghcb = (union hv_ghcb *)*ghcb_base;
    + if (!hv_ghcb) {
    + local_irq_restore(flags);
    + return -EFAULT;
    + }
    +
    + memset(hv_ghcb, 0x00, HV_HYP_PAGE_SIZE);
    + hv_ghcb->ghcb.protocol_version = 1;
    + hv_ghcb->ghcb.ghcb_usage = 1;
    +
    + hv_ghcb->hypercall.outputgpa = (u64)output;
    + hv_ghcb->hypercall.hypercallinput.asuint64 = 0;
    + hv_ghcb->hypercall.hypercallinput.callcode = control;
    +
    + if (input_size)
    + memcpy(hv_ghcb->hypercall.hypercalldata, input, input_size);
    +
    + VMGEXIT();
    +
    + hv_ghcb->ghcb.ghcb_usage = 0xffffffff;
    + memset(hv_ghcb->ghcb.save.valid_bitmap, 0,
    + sizeof(hv_ghcb->ghcb.save.valid_bitmap));
    +
    + local_irq_restore(flags);
    +
    + return hv_ghcb->hypercall.hypercalloutput.callstatus;
    +}
    +EXPORT_SYMBOL_GPL(hv_ghcb_hypercall);
    +
    void hv_ghcb_msr_write(u64 msr, u64 value)
    {
    union hv_ghcb *hv_ghcb;
    diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
    index 3c0cafdf7309..8bf26e6e7055 100644
    --- a/arch/x86/include/asm/mshyperv.h
    +++ b/arch/x86/include/asm/mshyperv.h
    @@ -254,6 +254,7 @@ void hv_sint_rdmsrl_ghcb(u64 msr, u64 *value);
    void hv_signal_eom_ghcb(void);
    void hv_ghcb_msr_write(u64 msr, u64 value);
    void hv_ghcb_msr_read(u64 msr, u64 *value);
    +u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);

    #define hv_get_synint_state_ghcb(int_num, val) \
    hv_sint_rdmsrl_ghcb(HV_X64_MSR_SINT0 + int_num, val)
    diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
    index 5e479d54918c..6d315c1465e0 100644
    --- a/drivers/hv/connection.c
    +++ b/drivers/hv/connection.c
    @@ -447,6 +447,10 @@ void vmbus_set_event(struct vmbus_channel *channel)

    ++channel->sig_events;

    - hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
    + if (hv_isolation_type_snp())
    + hv_ghcb_hypercall(HVCALL_SIGNAL_EVENT, &channel->sig_event,
    + NULL, sizeof(u64));
    + else
    + hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
    }
    EXPORT_SYMBOL_GPL(vmbus_set_event);
    diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
    index 59f7173c4d9f..e5c9fc467893 100644
    --- a/drivers/hv/hv.c
    +++ b/drivers/hv/hv.c
    @@ -98,7 +98,13 @@ int hv_post_message(union hv_connection_id connection_id,
    aligned_msg->payload_size = payload_size;
    memcpy((void *)aligned_msg->payload, payload, payload_size);

    - status = hv_do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL);
    + if (hv_isolation_type_snp())
    + status = hv_ghcb_hypercall(HVCALL_POST_MESSAGE,
    + (void *)aligned_msg, NULL,
    + sizeof(struct hv_input_post_message));
    + else
    + status = hv_do_hypercall(HVCALL_POST_MESSAGE,
    + aligned_msg, NULL);

    /* Preemption must remain disabled until after the hypercall
    * so some other thread can't get scheduled onto this cpu and
    diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h
    index b0cfc25dffaa..317d2a8d9700 100644
    --- a/include/asm-generic/mshyperv.h
    +++ b/include/asm-generic/mshyperv.h
    @@ -31,6 +31,35 @@

    union hv_ghcb {
    struct ghcb ghcb;
    + struct {
    + u64 hypercalldata[509];
    + u64 outputgpa;
    + union {
    + union {
    + struct {
    + u32 callcode : 16;
    + u32 isfast : 1;
    + u32 reserved1 : 14;
    + u32 isnested : 1;
    + u32 countofelements : 12;
    + u32 reserved2 : 4;
    + u32 repstartindex : 12;
    + u32 reserved3 : 4;
    + };
    + u64 asuint64;
    + } hypercallinput;
    + union {
    + struct {
    + u16 callstatus;
    + u16 reserved1;
    + u32 elementsprocessed : 12;
    + u32 reserved2 : 20;
    + };
    + u64 asunit64;
    + } hypercalloutput;
    + };
    + u64 reserved2;
    + } hypercall;
    } __packed __aligned(PAGE_SIZE);

    struct ms_hyperv_info {
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-07-28 16:54    [W:4.087 / U:0.844 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site