From nobody Sun May 10 22:40:13 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EEC27C433EF for ; Thu, 21 Apr 2022 16:51:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353034AbiDUQyp (ORCPT ); Thu, 21 Apr 2022 12:54:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35670 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352661AbiDUQym (ORCPT ); Thu, 21 Apr 2022 12:54:42 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE077496BC for ; Thu, 21 Apr 2022 09:51:51 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id z15-20020a25bb0f000000b00613388c7d99so4882657ybg.8 for ; Thu, 21 Apr 2022 09:51:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=IFP8dHfODAcQGiAaeMaPY6n82yRD8VX6rTDaKDuDzEA=; b=p9OLIeRHd/WWFguaSWOzgqSENN+cWNzfUAd9HPgNGe3r/rzFn62/OoDwtSjkoNL78A ec1FiOJ67UPu04RxzQolGEkLPyXnpyCe0vnOnI7vpmfGAz09rvlHWedd6NhgaBBa3ssq KMyBweJ4oUBbuHgwRW3neg+L0xQWZuOpCkrUoB0cb41CA+1R1sLYp/G5QQjrmZ2e4wwp qMBf/Phy4x24C8GsmqaEXK4LsAp3ye7Euya2qnbzoJQF43MAgst27zwKyxVA/i8uJ6fc lhlyS4n20g10s9/31Wru17Ho4nZC3jhQSQNLh4gVscY3ySdyqWwdFXkOcGwmj+nJdXuh GDNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=IFP8dHfODAcQGiAaeMaPY6n82yRD8VX6rTDaKDuDzEA=; b=KGsnuGYlvgoqB2wih2U62TIE5hXbiCVFpJJBBF5h8q53kxmC9f5hmXtEUJyf/9wYrh IjFhx1xmxZFIPot5+WH+O+8Ymp3Qwrp0Yl+o0aavDlRySAr/ThBkpDSx1FhiirFq0aeN +hrFA3knH71GTwg05PRGTOZf9KPjIA4/Cf7M98Y3irw8f52SCQkH7MzJP0JDYH6EGE0M de3E2zyOFKyrPTj/jcpYzJYbfRPcK4zFV72K3crAa+5UwHggSu88B9Cn3Fbhp/Y0hUex RahqbQ/9ZMHhEGnv4GqgN1SwI5QA/9K5x+3UBxUNiTjEDaszF5AFU8iDw0nKfmEqdOb4 GOvA== X-Gm-Message-State: AOAM530QUGYU9YTr3SbcolCQ2KEIH7hrRM7MA5Oo5BP7ySNL6kimgnAU 9Mv0RIFKsujzB4XLRD73Y/UVOo04 X-Google-Smtp-Source: ABdhPJyCWHZngFS/hK6FPiBgDeCIeK3wTfM3o5WOxaOCHNI3yjxGeiEtBjueumJuylGxnBtGQXTymqBx X-Received: from posk.svl.corp.google.com ([2620:15c:2cd:202:af90:3136:42b1:c8e2]) (user=posk job=sendgmr) by 2002:a05:6902:10c2:b0:645:2c6e:b43b with SMTP id w2-20020a05690210c200b006452c6eb43bmr662985ybu.358.1650559910996; Thu, 21 Apr 2022 09:51:50 -0700 (PDT) Date: Thu, 21 Apr 2022 09:51:37 -0700 Message-Id: <20220421165137.306101-1-posk@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.36.0.rc2.479.g8af0fa9b8e-goog Subject: [PATCH] KVM: x86: add HC_VMM_CUSTOM hypercall From: Peter Oskolkov To: Paolo Bonzini , Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel Cc: kvm@vger.kernel.org, Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H . Peter Anvin" , linux-kernel@vger.kernel.org, Paul Turner , Peter Oskolkov , Peter Oskolkov Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow kvm-based VMMs to request KVM to pass a custom vmcall from the guest to the VMM in the host. Quite often, operating systems research projects and/or specialized paravirtualized workloads would benefit from a extra-low-overhead, extra-low-latency guest-host communication channel. With cloud-hypervisor modified to handle the new hypercall (simply return the sum of the received arguments), the following function in guest _userspace_ completes, on average, in 2.5 microseconds (walltime) on a relatively modern Intel Xeon processor: uint64_t hypercall_custom_vmm(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3) { uint64_t ret; asm( "movq $13, %%rax \n\t" // hypercall nr. "movq %[a0], %%rbx \n\t" // a0 "movq %[a1], %%rcx \n\t" // a1 "movq %[a2], %%rdx \n\t" // a2 "movq %[a3], %%rsi \n\t" // a3 "vmcall \n\t" "movq %%rax, %[ret] \n\t" // ret : [ret] "=3Dr"(ret) : [a0] "r"(a0), [a1] "r"(a1), [a2] "r"(a2), [a3] "r"(a3) : "rax", "rbx", "rcx", "rdx", "rsi" ); return ret; } Signed-off-by: Peter Oskolkov --- arch/x86/kvm/x86.c | 28 ++++++++++++++++++++++++++-- include/uapi/linux/kvm_para.h | 1 + 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ab336f7c82e4..343971128da7 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -108,7 +108,8 @@ static u64 __read_mostly efer_reserved_bits =3D ~((u64)= EFER_SCE); =20 static u64 __read_mostly cr4_reserved_bits =3D CR4_RESERVED_BITS; =20 -#define KVM_EXIT_HYPERCALL_VALID_MASK (1 << KVM_HC_MAP_GPA_RANGE) +#define KVM_EXIT_HYPERCALL_VALID_MASK ((1 << KVM_HC_MAP_GPA_RANGE) | \ + (1 << KVM_HC_VMM_CUSTOM)) =20 #define KVM_CAP_PMU_VALID_MASK KVM_PMU_CAP_DISABLE =20 @@ -9207,10 +9208,16 @@ static int complete_hypercall_exit(struct kvm_vcpu = *vcpu) return kvm_skip_emulated_instruction(vcpu); } =20 +static int kvm_allow_hypercall_from_userspace(int nr) +{ + return nr =3D=3D KVM_HC_VMM_CUSTOM; +} + int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) { unsigned long nr, a0, a1, a2, a3, ret; int op_64_bit; + int cpl; =20 if (kvm_xen_hypercall_enabled(vcpu->kvm)) return kvm_xen_hypercall(vcpu); @@ -9235,7 +9242,8 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) a3 &=3D 0xFFFFFFFF; } =20 - if (static_call(kvm_x86_get_cpl)(vcpu) !=3D 0) { + cpl =3D static_call(kvm_x86_get_cpl)(vcpu); + if (cpl !=3D 0 && !kvm_allow_hypercall_from_userspace(nr)) { ret =3D -KVM_EPERM; goto out; } @@ -9294,6 +9302,22 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) vcpu->arch.complete_userspace_io =3D complete_hypercall_exit; return 0; } + case KVM_HC_VMM_CUSTOM: + ret =3D -KVM_ENOSYS; + if (!(vcpu->kvm->arch.hypercall_exit_enabled & (1 << KVM_HC_VMM_CUSTOM))) + break; + + vcpu->run->exit_reason =3D KVM_EXIT_HYPERCALL; + vcpu->run->hypercall.nr =3D KVM_HC_VMM_CUSTOM; + vcpu->run->hypercall.args[0] =3D a0; + vcpu->run->hypercall.args[1] =3D a1; + vcpu->run->hypercall.args[2] =3D a2; + vcpu->run->hypercall.args[3] =3D a3; + vcpu->run->hypercall.args[4] =3D 0; + vcpu->run->hypercall.args[5] =3D cpl; + vcpu->run->hypercall.longmode =3D op_64_bit; + vcpu->arch.complete_userspace_io =3D complete_hypercall_exit; + return 0; default: ret =3D -KVM_ENOSYS; break; diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h index 960c7e93d1a9..8caab28c9025 100644 --- a/include/uapi/linux/kvm_para.h +++ b/include/uapi/linux/kvm_para.h @@ -30,6 +30,7 @@ #define KVM_HC_SEND_IPI 10 #define KVM_HC_SCHED_YIELD 11 #define KVM_HC_MAP_GPA_RANGE 12 +#define KVM_HC_VMM_CUSTOM 13 =20 /* * hypercalls use architecture specific base-commit: 150866cd0ec871c765181d145aa0912628289c8a --=20 2.36.0.rc2.479.g8af0fa9b8e-goog