From patchwork Fri Jul 22 23:02:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Vagin X-Patchwork-Id: 12926966 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 3CECCC43334 for ; Fri, 22 Jul 2022 23:02:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236679AbiGVXC4 (ORCPT ); Fri, 22 Jul 2022 19:02:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52266 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229572AbiGVXCx (ORCPT ); Fri, 22 Jul 2022 19:02:53 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EE87285FAF for ; Fri, 22 Jul 2022 16:02:51 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-2eb7d137101so49444257b3.12 for ; Fri, 22 Jul 2022 16:02:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=FiHaCQhNDin1qEUasBSBeGavty7GfFuR81E7xhz62HI=; b=c1rAayLK7iuzyanIxPd2s407NjMvZS1gAWHbj2TnvKwoSzsJmhT2/rBhCxrzweD5bv goe/abBy7tIHD2PSW9W9YnBYWHFtXFPEamWfSvSBZq2LF7vTzdC7PyirE6re1S8KkYnZ 1AJn7Tt3KERZ2wW11owVtqmqOZlc0m6dMwpkpTXh+j1tK0hRBz29NOXYSq0Ytm9thELs gN8CHKC3AqZVebQZ86fJSV7cGNQw6305dLKxSNP9nt7krqnR1itpC6y2U7KVV1R8MlAy e73WJF8p/Qw4XVS91CV+aHr0vsi6LVWd59DTfIH6QGon7pVTvQDEz98LU2Oh2LHM2NzL fBvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=FiHaCQhNDin1qEUasBSBeGavty7GfFuR81E7xhz62HI=; b=Te73zh1jTFFdr9Mg/NqGf3WBF377SNL3pUuXM/qRBE0eZeFOxXpH4DYoYgHbJE/qI7 sO2RS1KJ9zS/z21Qdj0Ng/XI6lEKdnUbkn93eDDFwyL5J+tS+GanMXTm7WpWFmCNvScp QZ6IWXwe0zUZ0q5SYcDuPad+hXIFaOXmrOgIyJZWW+vNYsqtvWdChXw7KmzTmN+IKeRS TV0Z0XsenY6f7km4jCiwyJn9u15gnlnRkbXJK7MgVxPrIXS17bjm+8I25GJfkm1Qutz8 zm0YvKfo/vglSMhGdXAIwytPTHghrsk63U68eGI7xz6noVHUAmxahAOMr5lkzlNKGh9g vQYQ== X-Gm-Message-State: AJIora9w+cB9McEPPgyXsnWVufw977hCYm1qw4BG9rLzJ0XKTjKODaLz N+ardgqSZMOgDZb0vk4R92ePjN24uuM= X-Google-Smtp-Source: AGRyM1t+zExx1lMHouATchHS9iV5z5PPTi5UzQWlQv/TLkhoMSChcKNIDdA7jkdLJ9eLFt4X/Rtsejoq1PI= X-Received: from avagin.kir.corp.google.com ([2620:15c:29:204:5863:d08b:b2f8:4a3e]) (user=avagin job=sendgmr) by 2002:a25:7e42:0:b0:670:9c92:d1ab with SMTP id z63-20020a257e42000000b006709c92d1abmr1933632ybc.638.1658530971110; Fri, 22 Jul 2022 16:02:51 -0700 (PDT) Date: Fri, 22 Jul 2022 16:02:37 -0700 In-Reply-To: <20220722230241.1944655-1-avagin@google.com> Message-Id: <20220722230241.1944655-2-avagin@google.com> Mime-Version: 1.0 References: <20220722230241.1944655-1-avagin@google.com> X-Mailer: git-send-email 2.37.1.359.gd136c6c3e2-goog Subject: [PATCH 1/5] kernel: add a new helper to execute system calls from kernel code From: Andrei Vagin To: Paolo Bonzini Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Andrei Vagin , Sean Christopherson , Wanpeng Li , Vitaly Kuznetsov , Jianfeng Tan , Adin Scannell , Konstantin Bogomolov , Etienne Perot Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org This helper will be used to implement a kvm hypercall to call host system calls. The new helper executes seccomp rules and calls trace_sys_{enter,exit} hooks. But it intentionally doesn't call ptrace hooks because calling syscalls are not linked with the current process state. Signed-off-by: Andrei Vagin --- arch/x86/entry/common.c | 50 ++++++++++++++++++++++++++++++++++ arch/x86/include/asm/syscall.h | 1 + 2 files changed, 51 insertions(+) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 6c2826417b33..7f4c172a9a4e 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_XEN_PV #include @@ -37,6 +38,55 @@ #ifdef CONFIG_X86_64 +/* + * do_ksyscall_64 executes a system call. This helper can be used from the + * kernel code. + */ +bool do_ksyscall_64(int nr, struct pt_regs *regs) +{ + struct task_struct *task = current; + unsigned long work = READ_ONCE(current_thread_info()->syscall_work); + /* + * Convert negative numbers to very high and thus out of range + * numbers for comparisons. + */ + unsigned int unr = nr; + +#ifdef CONFIG_IA32_EMULATION + if (task->thread_info.status & TS_COMPAT) + return false; +#endif + + if (work & SYSCALL_WORK_SECCOMP) { + struct seccomp_data sd; + unsigned long args[6]; + + sd.nr = nr; + sd.arch = AUDIT_ARCH_X86_64; + syscall_get_arguments(task, regs, args); + sd.args[0] = args[0]; + sd.args[1] = args[1]; + sd.args[2] = args[2]; + sd.args[3] = args[3]; + sd.args[4] = args[4]; + sd.args[5] = args[5]; + sd.instruction_pointer = regs->ip; + if (__secure_computing(&sd) == -1) + return false; + } + + if (likely(unr >= NR_syscalls)) + return false; + + unr = array_index_nospec(unr, NR_syscalls); + + trace_sys_enter(regs, unr); + regs->ax = sys_call_table[unr](regs); + trace_sys_exit(regs, syscall_get_return_value(task, regs)); + return true; +} +EXPORT_SYMBOL_GPL(do_ksyscall_64); + static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) { /* diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 5b85987a5e97..6cde1ddeb50b 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -126,6 +126,7 @@ static inline int syscall_get_arch(struct task_struct *task) ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; } +bool do_ksyscall_64(int nr, struct pt_regs *regs); void do_syscall_64(struct pt_regs *regs, int nr); void do_int80_syscall_32(struct pt_regs *regs); long do_fast_syscall_32(struct pt_regs *regs); From patchwork Fri Jul 22 23:02:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Vagin X-Patchwork-Id: 12926967 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 74B8AC433EF for ; Fri, 22 Jul 2022 23:02:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236932AbiGVXC5 (ORCPT ); Fri, 22 Jul 2022 19:02:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52314 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236563AbiGVXCz (ORCPT ); Fri, 22 Jul 2022 19:02:55 -0400 Received: from mail-pf1-x44a.google.com (mail-pf1-x44a.google.com [IPv6:2607:f8b0:4864:20::44a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2FF587C21 for ; Fri, 22 Jul 2022 16:02:53 -0700 (PDT) Received: by mail-pf1-x44a.google.com with SMTP id e21-20020aa78c55000000b00528c6cca624so2402353pfd.3 for ; Fri, 22 Jul 2022 16:02:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=PKYAm/0aV3bhWo2rNA4kUnanHN9tpgw1D3TRbQRB/9o=; b=lRI5e0Ox5A5pJzsc8ceHqeriWk/S0n2o4DRYoy+eweCV0NrV2mSJaSneriBwNeCzSl EjNuI6u8Lw0Mg0RRaQbudLHcxikI0qQXRNUZFovHPMTpsiTrd6OgMcQEwuhNQRa9pEJN Dw4byaxIfon3dRpoBFL9/ccN8ggLzT235AHW65DMUaTfodhQcOltUccfwqJhjpTE03VG B4q+0lnOiALPxjpgtnBUhGwOSn2u66VCnbw/quRPfH74J04tQk8H1W3qBxsNynCXNw7s Ftjgj57ImdzNUgt/DUFUhV92yk2DtAV4LuhOx6dSSlWkSn+hZnHA9h5sy9BnuKPHgo7O vYtQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=PKYAm/0aV3bhWo2rNA4kUnanHN9tpgw1D3TRbQRB/9o=; b=n3k/Mnz07vKBsrtjtzEUte4V0Lw2JDIfSR61/Ry+W6g+ApaLMulFY7omddcKsC+uRU e0oiLtJK3xI0xPVi7sPFMAecwdXlgzXt/SVU4FnpvYvC/2ONpAmLxNDjOSjkTr6h4baa udNMXTC+0Kn9MWjS8omjryoPqh1QpM6ugrJkssFCf37abgaJG7ik1nev/y2fkcotXKEs QyFWaF8rJACWv8uAGEjtn9b/NgpFB3sXN7Ua+jj9E79baAcX6Ru+8q0GoAzvyd5in9NS Bsd9bx9iJWBTYJzo8RNzH7rUOfMfasEZ+kRI9NEwgTyGuyA5nZi1U7R/B6ncCoJJfQtR vqTw== X-Gm-Message-State: AJIora/7HOds5C6l/YQ9of08IBcfg6LIGf4MxcXY/tkbTQGXzmNb505e FQ3Dq7ImdqHe+wDngYZaqhEiMYNL3Gs= X-Google-Smtp-Source: AGRyM1twrLBpGr4Rz+bwCq0sU1u6HXMQYaN9Ydo7etaUWvEkYD6SXH+Pv7yJf/rikB6rcJ4tVIjl8xKA39o= X-Received: from avagin.kir.corp.google.com ([2620:15c:29:204:5863:d08b:b2f8:4a3e]) (user=avagin job=sendgmr) by 2002:a17:903:11c9:b0:16b:8293:c599 with SMTP id q9-20020a17090311c900b0016b8293c599mr1695061plh.136.1658530973354; Fri, 22 Jul 2022 16:02:53 -0700 (PDT) Date: Fri, 22 Jul 2022 16:02:38 -0700 In-Reply-To: <20220722230241.1944655-1-avagin@google.com> Message-Id: <20220722230241.1944655-3-avagin@google.com> Mime-Version: 1.0 References: <20220722230241.1944655-1-avagin@google.com> X-Mailer: git-send-email 2.37.1.359.gd136c6c3e2-goog Subject: [PATCH 2/5] kvm/x86: add controls to enable/disable paravirtualized system calls From: Andrei Vagin To: Paolo Bonzini Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Andrei Vagin , Sean Christopherson , Wanpeng Li , Vitaly Kuznetsov , Jianfeng Tan , Adin Scannell , Konstantin Bogomolov , Etienne Perot Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The following change will add a new hypercall to execute host syscalls. This hypercall is helpful for user-mode kernel solutions such as gVisor that needs to manage multiple address spaces. The new hypercall is a backdoor for most KVM users, so it must be disabled by default. This change introduces a new capability that has to be set to enable the hypercall. There is another standard way to allow hypercalls by using KVM_SET_CPUID2. It isn't suitable in this case because one of the common ways of using it is to request all available features (KVM_GET_SUPPORTED_CPUID) and let them all together. In this case, it is a hard requirement that the new hypercall can be enabled only intentionally. Signed-off-by: Andrei Vagin --- arch/x86/include/uapi/asm/kvm_para.h | 3 +++ arch/x86/kvm/cpuid.c | 25 +++++++++++++++++++++++++ arch/x86/kvm/cpuid.h | 8 +++++++- arch/x86/kvm/x86.c | 4 ++++ include/uapi/linux/kvm.h | 1 + 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h index 6e64b27b2c1e..84ad13ffc23c 100644 --- a/arch/x86/include/uapi/asm/kvm_para.h +++ b/arch/x86/include/uapi/asm/kvm_para.h @@ -37,6 +37,9 @@ #define KVM_FEATURE_HC_MAP_GPA_RANGE 16 #define KVM_FEATURE_MIGRATION_CONTROL 17 +/* Features that are not controlled by KVM_SET_CPUID2. */ +#define KVM_FEATURE_PV_HOST_SYSCALL 31 + #define KVM_HINTS_REALTIME 0 /* The last 8 bits are used to indicate how to interpret the flags field diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index de6d44e07e34..4fdfe9409506 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -104,6 +104,10 @@ static int kvm_check_cpuid(struct kvm_vcpu *vcpu, return -EINVAL; } + best = cpuid_entry2_find(entries, nent, KVM_CPUID_FEATURES, 0); + if (best && (best->eax & (1<arch.pv_cpuid.enforce) + return -EINVAL; + + best = kvm_find_cpuid_entry(vcpu, KVM_CPUID_FEATURES, 0); + if (!best) + return -EINVAL; + + if (set) + best->eax |= 1 << KVM_FEATURE_PV_HOST_SYSCALL; + else + best->eax &= ~(1 << KVM_FEATURE_PV_HOST_SYSCALL); + + kvm_update_pv_runtime(vcpu); + + return 0; +} + void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) { __kvm_update_cpuid_runtime(vcpu, vcpu->arch.cpuid_entries, vcpu->arch.cpuid_nent); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 8a770b481d9d..80721093b82b 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -219,10 +219,16 @@ static __always_inline void kvm_cpu_cap_check_and_set(unsigned int x86_feature) static __always_inline bool guest_pv_has(struct kvm_vcpu *vcpu, unsigned int kvm_feature) { - if (!vcpu->arch.pv_cpuid.enforce) + if (!vcpu->arch.pv_cpuid.enforce) { + if (kvm_feature == KVM_FEATURE_PV_HOST_SYSCALL) + return false; + return true; + } return vcpu->arch.pv_cpuid.features & (1u << kvm_feature); } +int kvm_vcpu_pv_set_host_syscall(struct kvm_vcpu *vcpu, bool set); + #endif diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e5fa335a4ea7..19e634768161 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5306,6 +5306,10 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, kvm_update_pv_runtime(vcpu); return 0; + + case KVM_CAP_PV_HOST_SYSCALL: + return kvm_vcpu_pv_set_host_syscall(vcpu, cap->args[0]); + default: return -EINVAL; } diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 860f867c50c0..89ed59d13877 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -1157,6 +1157,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_VM_TSC_CONTROL 214 #define KVM_CAP_SYSTEM_EVENT_DATA 215 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216 +#define KVM_CAP_PV_HOST_SYSCALL 217 #ifdef KVM_CAP_IRQ_ROUTING From patchwork Fri Jul 22 23:02:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrei Vagin X-Patchwork-Id: 12926968 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 640AFC433EF for ; Fri, 22 Jul 2022 23:03:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236514AbiGVXC7 (ORCPT ); Fri, 22 Jul 2022 19:02:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52266 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236724AbiGVXC4 (ORCPT ); Fri, 22 Jul 2022 19:02:56 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9FBE8C5B2 for ; Fri, 22 Jul 2022 16:02:55 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id p10-20020a170902e74a00b0016c3f3acb51so3281966plf.16 for ; Fri, 22 Jul 2022 16:02:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=93pRDb/hhCi6rn7HrzOWCC1IRMMdq/ahH9HJBQp/dJg=; b=EUvosg4JwWCErsar9boMExIxd60trxESqOUvfC4H7XMTC55998ES0+6EaKk32Yx4YJ BOBys09yAI3hZK/BjMEiyUcHPvh3D/BXi7DAVvAtcpu2eWLQZ0YkhcHrVH3zSNksmjKa cuVHaBmIQBHZpy4oogMHMpxdPNPhaxDBwnziDcvMiUoorLSx2LhPnOt7FYv6EaWca+ez Y/FTlRddDDLDb7zJzq6+XHgGQXg+9b5hiVjj/0Fcy3KETz7WmM8GLsLL1ztkAz95DHtj eIAqRvf41WwdGlp4bo6xZeEhzPCDhUlTAQhDeVquikPqpyxtqTg+RZbFo4aaTuztDRD/ 9F6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=93pRDb/hhCi6rn7HrzOWCC1IRMMdq/ahH9HJBQp/dJg=; b=P229tOFWLsWrsm0cl/S+dy9/fuyYcnf3aIpUfCxyBUEEqwA3Ozu9AalpLu1QiTBUH9 E4SevuLTLZ5YHl2L2a+1UHePNBXelEqBDff0OENjoD94dq1MjnXakq+V0nYkEMVWkFjm zFpQat8HFNpn3Ml1VpPTe7DRvLyyjeSG0mi3jDNZ04RoOYvPEkw2BAmbWlGgUJ5HrDzM xjZzbBaOPcqJQ1vWD+p47m8mQ8OsSGDUyu2CxWOJd92eqNWLatZN+BCTfvoJI6dQozxv wIic+sPhy+0IXv4fL+hoePcwmarDlUez588zRKAfnDr+TuYqBTsk6v1pxLNDggKeyQFb MYKQ== X-Gm-Message-State: AJIora9PxA/6V2/Mkq5nIAUjHtZ+NmsdH4zpvbf3xL9KdS6H1innytPb J6gKy4daO/AnQZOgK5Zt9JWrW2XwpH8= X-Google-Smtp-Source: AGRyM1tuB8T8+TDU+/wEL8IXih3eYVfU3anj1QMIw6F2QkJkLQSIMsTOL2fMQGKvm9YOxs+SKE2f668OjKA= X-Received: from avagin.kir.corp.google.com ([2620:15c:29:204:5863:d08b:b2f8:4a3e]) (user=avagin job=sendgmr) by 2002:a17:902:cf0e:b0:16d:2517:845 with SMTP id i14-20020a170902cf0e00b0016d25170845mr1737227plg.62.1658530975445; Fri, 22 Jul 2022 16:02:55 -0700 (PDT) Date: Fri, 22 Jul 2022 16:02:39 -0700 In-Reply-To: <20220722230241.1944655-1-avagin@google.com> Message-Id: <20220722230241.1944655-4-avagin@google.com> Mime-Version: 1.0 References: <20220722230241.1944655-1-avagin@google.com> X-Mailer: git-send-email 2.37.1.359.gd136c6c3e2-goog Subject: [PATCH 3/5] KVM/x86: add a new hypercall to execute host system calls. From: Andrei Vagin To: Paolo Bonzini Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Andrei Vagin , Sean Christopherson , Wanpeng Li , Vitaly Kuznetsov , Jianfeng Tan , Adin Scannell , Konstantin Bogomolov , Etienne Perot Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org There is a class of applications that use KVM to manage multiple address spaces rather than use it as an isolation boundary. In all other terms, they are normal processes that execute system calls, handle signals, etc. Currently, each time when such a process needs to interact with the operation system, it has to switch to host and back to guest. Such entire switches are expensive and significantly increase the overhead of system calls. The new hypercall reduces this overhead by more than two times. The new hypercall allows to execute host system calls. As for native calls, seccomp filters are executed before calls. It takes one argument that is a pointer to a pt_regs structure in the host address space. It provides registers to execute a system call according to the calling convention. Arguments are passed in %rdi, %rsi, %rdx, %r10, %r8 and %r9 and then a return code is stored in %rax.  The hypercall returns 0 if a system call has been executed. Otherwise, it returns an error code. Signed-off-by: Andrei Vagin --- Documentation/virt/kvm/x86/hypercalls.rst | 18 +++++++++++++ arch/x86/kvm/x86.c | 33 +++++++++++++++++++++++ include/uapi/linux/kvm_para.h | 1 + 3 files changed, 52 insertions(+) diff --git a/Documentation/virt/kvm/x86/hypercalls.rst b/Documentation/virt/kvm/x86/hypercalls.rst index e56fa8b9cfca..eb18f2128bfe 100644 --- a/Documentation/virt/kvm/x86/hypercalls.rst +++ b/Documentation/virt/kvm/x86/hypercalls.rst @@ -190,3 +190,21 @@ the KVM_CAP_EXIT_HYPERCALL capability. Userspace must enable that capability before advertising KVM_FEATURE_HC_MAP_GPA_RANGE in the guest CPUID. In addition, if the guest supports KVM_FEATURE_MIGRATION_CONTROL, userspace must also set up an MSR filter to process writes to MSR_KVM_MIGRATION_CONTROL. + +9. KVM_HC_HOST_SYSCALL +--------------------- +:Architecture: x86 +:Status: active +:Purpose: Execute a specified system call. + +- a0: pointer to a pt_regs structure in the host addess space. + +This hypercall lets a guest to execute host system calls. The first and only +argument represents process registers that are used as input and output +parameters. + +Returns 0 if the requested syscall has been executed. Otherwise, it returns an +error code. + +**Implementation note**: The KVM_CAP_PV_HOST_SYSCALL capability has to be set +to use this hypercall. diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 19e634768161..aa54e180c9d4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -81,6 +81,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include "trace.h" @@ -9253,6 +9254,27 @@ static int complete_hypercall_exit(struct kvm_vcpu *vcpu) return kvm_skip_emulated_instruction(vcpu); } +static int kvm_pv_host_syscall(unsigned long a0) +{ + struct pt_regs pt_regs = {}; + unsigned long sysno; + + if (copy_from_user(&pt_regs, (void *)a0, sizeof(pt_regs))) + return -EFAULT; + + sysno = pt_regs.ax; + pt_regs.orig_ax = pt_regs.ax; + pt_regs.ax = -ENOSYS; + + do_ksyscall_64(sysno, &pt_regs); + + pt_regs.orig_ax = -1; + if (copy_to_user((void *)a0, &pt_regs, sizeof(pt_regs))) + return -EFAULT; + + return 0; +} + int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) { unsigned long nr, a0, a1, a2, a3, ret; @@ -9318,6 +9340,7 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) kvm_sched_yield(vcpu, a0); ret = 0; break; + case KVM_HC_MAP_GPA_RANGE: { u64 gpa = a0, npages = a1, attrs = a2; @@ -9340,6 +9363,16 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) vcpu->arch.complete_userspace_io = complete_hypercall_exit; return 0; } + + case KVM_HC_HOST_SYSCALL: + if (!guest_pv_has(vcpu, KVM_FEATURE_PV_HOST_SYSCALL)) + break; + + kvm_vcpu_srcu_read_unlock(vcpu); + ret = kvm_pv_host_syscall(a0); + kvm_vcpu_srcu_read_lock(vcpu); + break; + default: ret = -KVM_ENOSYS; break; diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h index 960c7e93d1a9..3fcfb3241f35 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_HOST_SYSCALL 13 /* * hypercalls use architecture specific From patchwork Fri Jul 22 23:02:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Vagin X-Patchwork-Id: 12926969 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 E6B88C433EF for ; Fri, 22 Jul 2022 23:03:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237081AbiGVXDE (ORCPT ); Fri, 22 Jul 2022 19:03:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236831AbiGVXDC (ORCPT ); Fri, 22 Jul 2022 19:03:02 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 80BAF8C774 for ; Fri, 22 Jul 2022 16:02:58 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id 81-20020a630054000000b0041978b2aa9eso2911991pga.9 for ; Fri, 22 Jul 2022 16:02:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=eFGhzQ9ieMwuMtkU6aZcvdfyIrCCb4Zx8OPekzscmEA=; b=Rj7cNuRUCpucaVioPmXIiaEJWvYU48FgfQkcqWs9BdTDYt6d2xNZVgJ8i05utO5yBA ZqMtib1JRFofx7GuAYB0jClC6Z/GPrAXxXWySG4lG13dtHH0IPj1LlXEUQfm5j160iXS oNDnAdmcLQHunEE4rblSfzNusIGuJJUplpLPYBgPrLuNss0LZFpEk7mHbkYrpzQLn65F yqi5Icj2pEBTjOTFIsLYXrl8+a46/LOnPDZr/Pt5fOYRNsd+iVCQQNdNPQAxrV0u9EON L2Mt20reNxYUDOMIE9FjYFFrCRhKPuHXfbEEZ1HSRskhR5YDguJUb+SR+9FJ6Xo0lbPw p8DQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=eFGhzQ9ieMwuMtkU6aZcvdfyIrCCb4Zx8OPekzscmEA=; b=mz34MYNvSiIW907iioBqk60Oag591xvi2r/nSTaey+62pUzlhvQXqLsH/ypA62jrUv i4BIiAjaRbCsKL9knSCXd2uAdv9Xjq2VEn+rQO8k3J/TWtq1LivzlK23Zba53QObFLop UnWguR4ozXcoHvHMj9xslKWP/5mauzwU9MqZDXGLG5VprqvUhIAhHseM43AdlbLC8UO7 DSemBi1q9bjlFoAvrnxUUC8isfUE/U9BZGVJtiBJbZjd7haDkzAlHob7jKMqXYPrzbNn L+/W+G703Y++2N7SfmVnMLKFCNFRVfjvDCOnf8FJgGxpcAN8Q32AZUP2Kix5z+vKf5+B NLVA== X-Gm-Message-State: AJIora8epBOBQpmZG/1MxqXja6q3Hq9HTE1BxkGv5yWfJs22xkk/n9EE 6luh51hg+9U/UNrset0CwV/xQi6YP24= X-Google-Smtp-Source: AGRyM1vHj3Wp6OStOx4/akn2IlWiLgNBGkbbYAibl24DPkdzM2wkiTjgHa/vb1rt6Jr8P9Yq76tjVz4UjsU= X-Received: from avagin.kir.corp.google.com ([2620:15c:29:204:5863:d08b:b2f8:4a3e]) (user=avagin job=sendgmr) by 2002:a17:90a:73ca:b0:1f2:2989:b92d with SMTP id n10-20020a17090a73ca00b001f22989b92dmr1934085pjk.182.1658530977975; Fri, 22 Jul 2022 16:02:57 -0700 (PDT) Date: Fri, 22 Jul 2022 16:02:40 -0700 In-Reply-To: <20220722230241.1944655-1-avagin@google.com> Message-Id: <20220722230241.1944655-5-avagin@google.com> Mime-Version: 1.0 References: <20220722230241.1944655-1-avagin@google.com> X-Mailer: git-send-email 2.37.1.359.gd136c6c3e2-goog Subject: [PATCH 4/5] selftests/kvm/x86_64: set rax before vmcall From: Andrei Vagin To: Paolo Bonzini Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Andrei Vagin , Sean Christopherson , Wanpeng Li , Vitaly Kuznetsov , Jianfeng Tan , Adin Scannell , Konstantin Bogomolov , Etienne Perot Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org kvm_hypercall has to place the hypercall number in rax. Trace events show that kvm_pv_test doesn't work properly: kvm_pv_test-53132: kvm_hypercall: nr 0x0 a0 0x0 a1 0x0 a2 0x0 a3 0x0 kvm_pv_test-53132: kvm_hypercall: nr 0x0 a0 0x0 a1 0x0 a2 0x0 a3 0x0 kvm_pv_test-53132: kvm_hypercall: nr 0x0 a0 0x0 a1 0x0 a2 0x0 a3 0x0 With this change, it starts working as expected: kvm_pv_test-54285: kvm_hypercall: nr 0x5 a0 0x0 a1 0x0 a2 0x0 a3 0x0 kvm_pv_test-54285: kvm_hypercall: nr 0xa a0 0x0 a1 0x0 a2 0x0 a3 0x0 kvm_pv_test-54285: kvm_hypercall: nr 0xb a0 0x0 a1 0x0 a2 0x0 a3 0x0 Signed-off-by: Andrei Vagin --- tools/testing/selftests/kvm/lib/x86_64/processor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c index ead7011ee8f6..5d85e1c021da 100644 --- a/tools/testing/selftests/kvm/lib/x86_64/processor.c +++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c @@ -1422,7 +1422,7 @@ uint64_t kvm_hypercall(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, asm volatile("vmcall" : "=a"(r) - : "b"(a0), "c"(a1), "d"(a2), "S"(a3)); + : "a"(nr), "b"(a0), "c"(a1), "d"(a2), "S"(a3)); return r; } From patchwork Fri Jul 22 23:02:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Vagin X-Patchwork-Id: 12926970 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 0004BC43334 for ; Fri, 22 Jul 2022 23:03:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232679AbiGVXDT (ORCPT ); Fri, 22 Jul 2022 19:03:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52598 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237040AbiGVXDD (ORCPT ); Fri, 22 Jul 2022 19:03:03 -0400 Received: from mail-pl1-x649.google.com (mail-pl1-x649.google.com [IPv6:2607:f8b0:4864:20::649]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7A358A896E for ; Fri, 22 Jul 2022 16:03:00 -0700 (PDT) Received: by mail-pl1-x649.google.com with SMTP id p10-20020a170902e74a00b0016c3f3acb51so3282066plf.16 for ; Fri, 22 Jul 2022 16:03:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=ohjmvic4E29z52GxL81iJJ/NoT9cQn3Y4MQIK9DNO8c=; b=NUPStMJh9IgIejquXH41dWpPzb0keBnwKYv/YW8pfw5tOHeupTpouxU7AoPrEITB+l vNcaNvL+2+sjkec80bqYbPcI9dy4syJ0u7saxw8sIFI6mmNy68pkpcr/P3WesShFzO6/ 3QCbtoKA8mfc2zzeMa7JVT75czfnmJejoWd2iIGQiYUGJWQfXX6ahwwZoyd3PpJQ2hS8 N/BGy3AwdK+1zeIIPoghK96lusqX0lMGsYPJoOybcjl2A+VUVjVr4JRgoAhKz1DElQHO GJoToXM2Q9s9MWEmr3E5U/MdvlCXqTBRWfscu+Dqkuwf+lreJM5wnjvyb/Jc4jYcoHzv NLTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=ohjmvic4E29z52GxL81iJJ/NoT9cQn3Y4MQIK9DNO8c=; b=q2S9w42OQ8iBUi5Gt1pEpfINt3NyptISatwKqQKq7rsnRVuq8KjQDlsGGaWWTAaIX/ jFzOgAkLVo/8jmGDWu7NMK35xNiju7OJyKxrVljyQbwuwv0Zq18fyxxymkbjXtvrIFlR phBIMO9eLmqLRzVZh2wk6ebFRWOsv0Udlw2q23DuMvc6r9+lL3uTX3YYpJ9T7Q9eQHDh 6sXgz1WrxVD+u5BC1GF8p+71ACF72BvEg+n2YubQGxCTL6UjNayrT0En2mL4/Ix2rrzd T2Agbwu5MPs0fvz7jCKX4xJP4b0gZDE2X4ReFL3xtgoBJHPBUua4OuTczI0LBUMTOjuu 0tnw== X-Gm-Message-State: AJIora+7y4vkwrbr2h6KLOwUpFnVDgm0/80OLrV88y7VBdL2f50RVavh WSKU7MaMVIS5aw9IT9mbYT8xsEJCQdg= X-Google-Smtp-Source: AGRyM1vzNfKx1ntihwPeEq0EYbJkTHi1QJ88thF08Vd6neFyCEJbIjBBCh8im7RSQIkoT/hFtNaXPTG+FJo= X-Received: from avagin.kir.corp.google.com ([2620:15c:29:204:5863:d08b:b2f8:4a3e]) (user=avagin job=sendgmr) by 2002:a05:6a00:17aa:b0:52a:e94b:67e5 with SMTP id s42-20020a056a0017aa00b0052ae94b67e5mr2199067pfg.76.1658530980244; Fri, 22 Jul 2022 16:03:00 -0700 (PDT) Date: Fri, 22 Jul 2022 16:02:41 -0700 In-Reply-To: <20220722230241.1944655-1-avagin@google.com> Message-Id: <20220722230241.1944655-6-avagin@google.com> Mime-Version: 1.0 References: <20220722230241.1944655-1-avagin@google.com> X-Mailer: git-send-email 2.37.1.359.gd136c6c3e2-goog Subject: [PATCH 5/5] selftests/kvm/x86_64: add tests for KVM_HC_HOST_SYSCALL From: Andrei Vagin To: Paolo Bonzini Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org, Andrei Vagin , Sean Christopherson , Wanpeng Li , Vitaly Kuznetsov , Jianfeng Tan , Adin Scannell , Konstantin Bogomolov , Etienne Perot Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org * check that syscall are executed. * check that non-existing syscalls return ENOSYS. Signed-off-by: Andrei Vagin --- 0000-kvm-host-syscall.patch | 7 + tools/testing/selftests/kvm/.gitignore | 1 + tools/testing/selftests/kvm/Makefile | 1 + .../selftests/kvm/include/x86_64/processor.h | 4 + .../kvm/x86_64/kvm_pv_syscall_test.c | 145 ++++++++++++++++++ 5 files changed, 158 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/kvm_pv_syscall_test.c diff --git a/0000-kvm-host-syscall.patch b/0000-kvm-host-syscall.patch index 364db7471abc..653430d57c62 100644 --- a/0000-kvm-host-syscall.patch +++ b/0000-kvm-host-syscall.patch @@ -57,6 +57,13 @@ In the Google kernel, we have a kvm-like subsystem designed especially for gVisor. This change is the first step of integrating it into the KVM code base and making it available to all Linux users. +Cc: Paolo Bonzini +Cc: Sean Christopherson +Cc: Wanpeng Li +Cc: Vitaly Kuznetsov +Cc: Jianfeng Tan +Cc: Adin Scannell + Andrei Vagin (5): kernel: add a new helper to execute system calls from kernel code kvm: add controls to enable/disable paravirtualized system calls diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore index 4509a3a7eeae..57d39fec6fdd 100644 --- a/tools/testing/selftests/kvm/.gitignore +++ b/tools/testing/selftests/kvm/.gitignore @@ -21,6 +21,7 @@ /x86_64/get_msr_index_features /x86_64/kvm_clock_test /x86_64/kvm_pv_test +/x86_64/kvm_pv_syscall_test /x86_64/hyperv_clock /x86_64/hyperv_cpuid /x86_64/hyperv_features diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 22423c871ed6..e6459f3e5318 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -82,6 +82,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/hyperv_features TEST_GEN_PROGS_x86_64 += x86_64/hyperv_svm_test TEST_GEN_PROGS_x86_64 += x86_64/kvm_clock_test TEST_GEN_PROGS_x86_64 += x86_64/kvm_pv_test +TEST_GEN_PROGS_x86_64 += x86_64/kvm_pv_syscall_test TEST_GEN_PROGS_x86_64 += x86_64/mmio_warning_test TEST_GEN_PROGS_x86_64 += x86_64/mmu_role_test TEST_GEN_PROGS_x86_64 += x86_64/platform_info_test diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h index 6ce185449259..4503e9556279 100644 --- a/tools/testing/selftests/kvm/include/x86_64/processor.h +++ b/tools/testing/selftests/kvm/include/x86_64/processor.h @@ -17,6 +17,7 @@ #include "../kvm_util.h" +#ifndef X86_EFLAGS_FIXED #define X86_EFLAGS_FIXED (1u << 1) #define X86_CR4_VME (1ul << 0) @@ -40,6 +41,7 @@ #define X86_CR4_SMEP (1ul << 20) #define X86_CR4_SMAP (1ul << 21) #define X86_CR4_PKE (1ul << 22) +#endif /* CPUID.1.ECX */ #define CPUID_VMX (1ul << 5) @@ -503,6 +505,7 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) /* * Basic CPU control in CR0 */ +#ifndef X86_CR0_PE #define X86_CR0_PE (1UL<<0) /* Protection Enable */ #define X86_CR0_MP (1UL<<1) /* Monitor Coprocessor */ #define X86_CR0_EM (1UL<<2) /* Emulation */ @@ -514,6 +517,7 @@ void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) #define X86_CR0_NW (1UL<<29) /* Not Write-through */ #define X86_CR0_CD (1UL<<30) /* Cache Disable */ #define X86_CR0_PG (1UL<<31) /* Paging */ +#endif #define XSTATE_XTILE_CFG_BIT 17 #define XSTATE_XTILE_DATA_BIT 18 diff --git a/tools/testing/selftests/kvm/x86_64/kvm_pv_syscall_test.c b/tools/testing/selftests/kvm/x86_64/kvm_pv_syscall_test.c new file mode 100644 index 000000000000..601f84b11711 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/kvm_pv_syscall_test.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020, Google LLC. + * + * Tests for KVM paravirtual feature disablement + */ +#include +#include +#include +#include + +#include + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +struct pt_regs regs_dup = { + .rax = __NR_dup, + .rdi = -1, +}; + +struct pt_regs regs_nosys = { + .rax = -1, +}; + +struct hcall_data { + const char *name; + struct pt_regs *regs; + long ret; +}; + +#define TEST_HCALL(hc) { .nr = hc, .name = #hc } +#define UCALL_PR_HCALL 0xdeadc0de +#define PR_HCALL(hc) ucall(UCALL_PR_HCALL, 1, hc) + +/* + * KVM hypercalls to test. Expect -KVM_ENOSYS when called, as the corresponding + * features have been cleared in KVM_CPUID_FEATURES. + */ +static struct hcall_data hcalls_to_test[] = { + {.name = "dup", .regs = ®s_dup, .ret = -EBADF}, + {.name = "enosys", .regs = ®s_nosys, .ret = -ENOSYS}, +}; + +static void test_hcall(struct hcall_data *hc) +{ + uint64_t r; + + PR_HCALL(hc); + r = kvm_hypercall(KVM_HC_HOST_SYSCALL, (unsigned long)hc->regs, 0, 0, 0); + GUEST_ASSERT(r == 0); +} + +static void guest_main(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hcalls_to_test); i++) + test_hcall(&hcalls_to_test[i]); + + GUEST_DONE(); +} + +static void pr_hcall(struct ucall *uc) +{ + struct hcall_data *hc = (struct hcall_data *)uc->args[0]; + + pr_info("testing hcall: %s\n", hc->name); +} + +static void handle_abort(struct ucall *uc) +{ + TEST_FAIL("%s at %s:%ld", (const char *)uc->args[0], + __FILE__, uc->args[1]); +} + +#define VCPU_ID 0 + +static void enter_guest(struct kvm_vm *vm) +{ + struct kvm_run *run; + struct ucall uc; + int r, i; + + run = vcpu_state(vm, VCPU_ID); + + while (true) { + r = _vcpu_run(vm, VCPU_ID); + TEST_ASSERT(!r, "vcpu_run failed: %d\n", r); + TEST_ASSERT(run->exit_reason == KVM_EXIT_IO, + "unexpected exit reason: %u (%s)", + run->exit_reason, exit_reason_str(run->exit_reason)); + + switch (get_ucall(vm, VCPU_ID, &uc)) { + case UCALL_PR_HCALL: + pr_hcall(&uc); + break; + case UCALL_ABORT: + handle_abort(&uc); + return; + case UCALL_DONE: + goto out; + } + } + +out: + for (i = 0; i < ARRAY_SIZE(hcalls_to_test); i++) { + struct hcall_data *hc = &hcalls_to_test[i]; + + TEST_ASSERT(hc->ret == hc->regs->rax, "%s: ret %ld (expected %ld)", + hc->name, hc->ret, hc->regs->rax); + } +} + +int main(void) +{ + struct kvm_enable_cap cap = {0}; + struct kvm_cpuid2 *best; + struct kvm_vm *vm; + + if (!kvm_check_cap(KVM_CAP_ENFORCE_PV_FEATURE_CPUID)) { + pr_info("will skip kvm paravirt restriction tests.\n"); + return 0; + } + + vm = vm_create_default(VCPU_ID, 0, guest_main); + + cap.cap = KVM_CAP_ENFORCE_PV_FEATURE_CPUID; + cap.args[0] = 1; + vcpu_enable_cap(vm, VCPU_ID, &cap); + + best = kvm_get_supported_cpuid(); + vcpu_set_cpuid(vm, VCPU_ID, best); + + cap.cap = KVM_CAP_PV_HOST_SYSCALL; + cap.args[0] = 1; + vcpu_enable_cap(vm, VCPU_ID, &cap); + + vm_init_descriptor_tables(vm); + vcpu_init_descriptor_tables(vm, VCPU_ID); + + enter_guest(vm); + kvm_vm_free(vm); +}