From patchwork Wed Oct 30 03:34:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13855884 Received: from mail-vs1-f46.google.com (mail-vs1-f46.google.com [209.85.217.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 06461194A73 for ; Wed, 30 Oct 2024 03:35:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.217.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259323; cv=none; b=fva623b/Ct8PsKgNnnAXPL8X35OmKvs2xJgNpbn81FEUQfaCgKNl9nWhw8RNg3KkqIezHYp5G5Msrh3AYM6yW0aYx96DZWFw6KeUy8UEDLf7JaRGfOJx8MF+HkJ50b15TnO6z2Io8mVE8xy4THLQwAjFtY06H5H2OTIkudQXfPg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259323; c=relaxed/simple; bh=Bf8atWoT1AgbKzljqD4YpHmghXSVbfevIZjTTADfkuM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jK7LL4p7sSbQhpZzp0moB39CkxzBTvN1HSypFlXcQDX/kQQ083kYaPNKI5hh595YNA+LiYEn2esjbIS61RR3VAorHVCZF0bwyOPKFzjbF/zKo91EHzOdOUlI+CfSVGX7cMorWx1CtJqeQ8mgLA4camxJy/MkbJU2YaDPoC62iJE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=fhAcneuK; arc=none smtp.client-ip=209.85.217.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="fhAcneuK" Received: by mail-vs1-f46.google.com with SMTP id ada2fe7eead31-4a47d70cd8aso1947135137.1 for ; Tue, 29 Oct 2024 20:35:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1730259320; x=1730864120; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yXSF2eEHg6CQZsZauUAKPc3+lZzOLUOLy+73Zovk/II=; b=fhAcneuK+f0ngG3926ADrrLAQAYOPbg7wlUAZNdUWAZm+X2UrCS17ZEFCcjvdxBLgC K8FvoJ33U2ylciSwUFDhm9RuDPnpf5cFZGpJbsMS5HQWTAhfWUTwQpOxIOBPF/ok5rzT SHFI9IYDMS1KIu9NLaQ58rZ0uLVjz017eoLo4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730259320; x=1730864120; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yXSF2eEHg6CQZsZauUAKPc3+lZzOLUOLy+73Zovk/II=; b=rMyh0cXxTESLblrwOOfMsRcmtHm9kdqtrGLax9oGcwE8Kbs2oJ9dB4GoIsWDh3wliD D8ZinHl0z0DHCSoF7rdVFZbx52+tu15RM3DvmOhqsuhy7zKFuVaZLr3m9uK8BwthbZN5 vKSP2lknsap3B2FAVq1y+ky6C3HoFOX/k+zDfxe5PXoCkrWUdIxMzpcP/3PjFmHQm3dY ahgoxP9qTm7tuEu6tRAA+2X+ea3Uq7EPFDb/kUAMZfOI4Q7Y1JjoU1DnMUo1LjycmM9d ziS9+anDnnccR/fhEkkvzohY3sekAY6fhs9+LXbz2iMlB+NcgEynPOA/de78hIUvN3zj vyPA== X-Forwarded-Encrypted: i=1; AJvYcCVwcaHZn4sK8c104nI+Tzb0ewwbyfEvF4DRG7yEiKWkgTX/jTl3nmQO9cHK5AJu79ATDYwyHhPKevsYB8PX5Ac=@vger.kernel.org X-Gm-Message-State: AOJu0Yx0nsavDRuhkm2UWGFwNE/6hCvR3Ts63MPB0SWXRlRP7ncbVBN2 IcvTrQjaBA0aUKCYPOx0H0IvvOYc8OFAi7YvteRxUCSuyiI/olKSlSqTgWyRig== X-Google-Smtp-Source: AGHT+IGZpRhflFNaUw8TMKAPrDYokmZ7cw+TYThiu0Fvr4MS0wJ34OSWBafYUwebIo7ai1SLq3TcAg== X-Received: by 2002:a05:6102:3a09:b0:4a4:6098:1fec with SMTP id ada2fe7eead31-4a8cfb25a8emr13741342137.2.1730259319648; Tue, 29 Oct 2024 20:35:19 -0700 (PDT) Received: from localhost.localdomain ([192.19.144.250]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-461323a4840sm51015561cf.86.2024.10.29.20.35.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Oct 2024 20:35:19 -0700 (PDT) From: Zack Rusin To: kvm@vger.kernel.org Cc: Zack Rusin , Doug Covelli , Paolo Bonzini , Jonathan Corbet , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Namhyung Kim , Arnaldo Carvalho de Melo , Isaku Yamahata , Joel Stanley , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH 1/3] KVM: x86: Allow enabling of the vmware backdoor via a cap Date: Tue, 29 Oct 2024 23:34:07 -0400 Message-ID: <20241030033514.1728937-2-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030033514.1728937-1-zack.rusin@broadcom.com> References: <20241030033514.1728937-1-zack.rusin@broadcom.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Allow enabling of the vmware backdoor on a per-vm basis. The vmware backdoor could only be enabled systemwide via the kernel parameter kvm.enable_vmware_backdoor which required modifying the kernels boot parameters. Add the KVM_CAP_X86_VMWARE_BACKDOOR cap that enables the backdoor at the hypervisor level and allows setting it on a per-vm basis. The default is whatever kvm.enable_vmware_backdoor was set to, which by default is false. Signed-off-by: Zack Rusin Cc: Doug Covelli Cc: Paolo Bonzini Cc: Jonathan Corbet Cc: Sean Christopherson Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: x86@kernel.org Cc: "H. Peter Anvin" Cc: Shuah Khan Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Isaku Yamahata Cc: Joel Stanley Cc: Zack Rusin Cc: kvm@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org --- Documentation/virt/kvm/api.rst | 15 +++++++++++++++ arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/emulate.c | 5 +++-- arch/x86/kvm/svm/svm.c | 6 +++--- arch/x86/kvm/vmx/vmx.c | 4 ++-- arch/x86/kvm/x86.c | 14 ++++++++++++++ arch/x86/kvm/x86.h | 7 +++++-- include/uapi/linux/kvm.h | 1 + 8 files changed, 44 insertions(+), 9 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index b3be87489108..33ef3cc785e4 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -8186,6 +8186,21 @@ KVM exits with the register state of either the L1 or L2 guest depending on which executed at the time of an exit. Userspace must take care to differentiate between these cases. +7.37 KVM_CAP_X86_VMWARE_BACKDOOR +-------------------------------- + +:Architectures: x86 +:Parameters: args[0] whether the feature should be enabled or not +:Returns: 0 on success. + +The presence of this capability indicates that KVM supports +enabling of the VMware backdoor via the enable cap interface. + +When enabled KVM will support VMware backdoor PV interface. The +default value for it is set via the kvm.enable_vmware_backdoor +kernel parameter (false when not set). Must be set before any +VCPUs have been created. + 8. Other capabilities. ====================== diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4a68cb3eba78..7fcf185e337f 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1403,6 +1403,7 @@ struct kvm_arch { #ifdef CONFIG_KVM_XEN struct kvm_xen xen; #endif + bool vmware_backdoor_enabled; bool backwards_tsc_observed; bool boot_vcpu_runs_old_kvmclock; diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index e72aed25d721..8aee73f9a560 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2563,7 +2563,7 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt, * VMware allows access to these ports even if denied * by TSS I/O permission bitmap. Mimic behavior. */ - if (enable_vmware_backdoor && + if (kvm_vmware_backdoor_enabled(ctxt->vcpu) && ((port == VMWARE_PORT_VMPORT) || (port == VMWARE_PORT_VMRPC))) return true; @@ -3917,7 +3917,8 @@ static int check_rdpmc(struct x86_emulate_ctxt *ctxt) * VMware allows access to these Pseduo-PMCs even when read via RDPMC * in Ring3 when CR4.PCE=0. */ - if (enable_vmware_backdoor && is_vmware_backdoor_pmc(rcx)) + if (kvm_vmware_backdoor_enabled(ctxt->vcpu) && + is_vmware_backdoor_pmc(rcx)) return X86EMUL_CONTINUE; /* diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 5ab2c92c7331..a55655337cfa 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -314,7 +314,7 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) svm_leave_nested(vcpu); svm_set_gif(svm, true); /* #GP intercept is still needed for vmware backdoor */ - if (!enable_vmware_backdoor) + if (!kvm_vmware_backdoor_enabled(vcpu)) clr_exception_intercept(svm, GP_VECTOR); /* @@ -1262,7 +1262,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu) * We intercept those #GP and allow access to them anyway * as VMware does. */ - if (enable_vmware_backdoor) + if (kvm_vmware_backdoor_enabled(vcpu)) set_exception_intercept(svm, GP_VECTOR); svm_set_intercept(svm, INTERCEPT_INTR); @@ -2401,7 +2401,7 @@ static int gp_interception(struct kvm_vcpu *vcpu) opcode = svm_instr_opcode(vcpu); if (opcode == NONE_SVM_INSTR) { - if (!enable_vmware_backdoor) + if (!kvm_vmware_backdoor_enabled(vcpu)) goto reinject; /* diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 733a0c45d1a6..6b874c629b82 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -885,7 +885,7 @@ void vmx_update_exception_bitmap(struct kvm_vcpu *vcpu) * We intercept those #GP and allow access to them anyway * as VMware does. */ - if (enable_vmware_backdoor) + if (kvm_vmware_backdoor_enabled(vcpu)) eb |= (1u << GP_VECTOR); if ((vcpu->guest_debug & (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) == @@ -5249,7 +5249,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE); if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) { - WARN_ON_ONCE(!enable_vmware_backdoor); + WARN_ON_ONCE(!kvm_vmware_backdoor_enabled(vcpu)); /* * VMware backdoor emulation on #GP interception only handles diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c983c8e434b8..d7071907d6a5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4688,6 +4688,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_IRQFD_RESAMPLE: case KVM_CAP_MEMORY_FAULT_INFO: case KVM_CAP_X86_GUEST_MODE: + case KVM_CAP_X86_VMWARE_BACKDOOR: r = 1; break; case KVM_CAP_PRE_FAULT_MEMORY: @@ -6772,6 +6773,17 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, mutex_unlock(&kvm->lock); break; } + case KVM_CAP_X86_VMWARE_BACKDOOR: + r = -EINVAL; + if (cap->args[0] & ~1) + break; + mutex_lock(&kvm->lock); + if (!kvm->created_vcpus) { + kvm->arch.vmware_backdoor_enabled = cap->args[0]; + r = 0; + } + mutex_unlock(&kvm->lock); + break; default: r = -EINVAL; break; @@ -12685,6 +12697,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm->arch.guest_can_read_msr_platform_info = true; kvm->arch.enable_pmu = enable_pmu; + kvm->arch.vmware_backdoor_enabled = enable_vmware_backdoor; + #if IS_ENABLED(CONFIG_HYPERV) spin_lock_init(&kvm->arch.hv_root_tdp_lock); kvm->arch.hv_root_tdp = INVALID_PAGE; diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 50596f6f8320..ae278a48566a 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -376,14 +376,17 @@ static inline bool kvm_mpx_supported(void) extern unsigned int min_timer_period_us; -extern bool enable_vmware_backdoor; - extern int pi_inject_timer; extern bool report_ignored_msrs; extern bool eager_page_split; +static inline bool kvm_vmware_backdoor_enabled(struct kvm_vcpu *vcpu) +{ + return vcpu->kvm->arch.vmware_backdoor_enabled; +} + static inline void kvm_pr_unimpl_wrmsr(struct kvm_vcpu *vcpu, u32 msr, u64 data) { if (report_ignored_msrs) diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 637efc055145..c7b5f1c2ee1c 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -933,6 +933,7 @@ struct kvm_enable_cap { #define KVM_CAP_PRE_FAULT_MEMORY 236 #define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237 #define KVM_CAP_X86_GUEST_MODE 238 +#define KVM_CAP_X86_VMWARE_BACKDOOR 239 struct kvm_irq_routing_irqchip { __u32 irqchip; From patchwork Wed Oct 30 03:34:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13855885 Received: from mail-qt1-f175.google.com (mail-qt1-f175.google.com [209.85.160.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EF7D61991D4 for ; Wed, 30 Oct 2024 03:35:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259325; cv=none; b=E9xe9ckU93V/2KLO7c1neTCNq5BRePSz7DnFOICRBowVd0wNPemUrxdNqkJpNAsQTRn5X7Shq9HDUNfri2e0P7QsKeSwoCHDSjK05Iovh2xWLA8/f3wmBbRroPrjmrZ4/nuAeqAbznQV1HrcyGyGKnx4utX/9xS3QNJbKbzSRss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259325; c=relaxed/simple; bh=Kgs+eWx7o2g2fh3PL6R26a4Wy9eDpiLIOtdgqULaC2k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ld5lN4z1GcARKYsrd6UtU6dDUIVwy06usiG7Im+MrOc6kfP+k9LiOZkPrbO1vcJa9O0V9k8kEabaplx5pOSWfS9aiyN3yObYwSyDO0K553KWiEN5Q3OS2xX4PUxZwMNgN+rzuoQ8XxZl6VAbZKNBox21mnaWivuOQ7N1gbzCgLk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=QfxcA08N; arc=none smtp.client-ip=209.85.160.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="QfxcA08N" Received: by mail-qt1-f175.google.com with SMTP id d75a77b69052e-460ace055d8so42902581cf.1 for ; Tue, 29 Oct 2024 20:35:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1730259321; x=1730864121; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=m3GKYnVa/shm5to0559XXaPhB1/FWLLgFQ/uN05I12o=; b=QfxcA08NC0NnIPbqn9DVA/38nFNZzTKKpKCKt8Emp9n/FKloM2jTvqKc26Csu2p61k IL4irsUiyk/cR/HhtuOIyrpnph4+XeCUPfQfYuArPbuZe9lF5CRvcnb9fQzT+C+p2XAk 2vBV6EyTXPWKmQ0TS8AdRjpDoYFgP2a2/XrfM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730259321; x=1730864121; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=m3GKYnVa/shm5to0559XXaPhB1/FWLLgFQ/uN05I12o=; b=KY7gJm1tzPlp6yLWEZ2/YSfeFUT4rymxis1jgMawBJjbp2mS0q0YXNTTzziDdQJwIN 3IJQFqnyumzHhWGaoAig31faOnukHhWD4QCDDti4SNPursoP8W+PfDvFT1+5KWTK+C8f 0/I+picNWHipHS3u2E5saQP9IaHWFPJg2wBkaZKn0QdhNHlV+jcYKazVfCI65J7Z6oyY kKCYlkC+0dHkd2USB77e0aVgOz5gvFvqTB90kgCX7ehHDL0ucV68EYv81hqtxz3e3rZw 2C4sTXr+waCnZlRcRWSfiDcpMOLdbPEI+117ok1sbMD7vLGXf+vnLUaHFWIDZ4FFRvt6 f5Kw== X-Forwarded-Encrypted: i=1; AJvYcCVBcOAOXJcfTuTT53b93wTqtfRiFz7l1YYKz9RZrEn6FlpNHyWOJpiZjvHCpTWZ1ScVGu3gnGmk3+e/XBVwh3A=@vger.kernel.org X-Gm-Message-State: AOJu0YzfE8QMvhn4yER+H9EUvp5cHJBNZu3wK3FNcpaqijno7CPknzeV u+Z945lD61KoAzsQtzOspfNNrlSLzduLEGOOPPRUlwUyIf0s09kmMs6K8KYl1Q== X-Google-Smtp-Source: AGHT+IEem11ygHxVK51cRhrQxNiN0xVSQYe3RjjvoZI4dUIf0yRjgNEKPfSjst7O5GbzSQBBOQwR/g== X-Received: by 2002:a05:622a:1184:b0:45f:bc9e:c69c with SMTP id d75a77b69052e-4613bfd417dmr199820411cf.7.1730259320884; Tue, 29 Oct 2024 20:35:20 -0700 (PDT) Received: from localhost.localdomain ([192.19.144.250]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-461323a4840sm51015561cf.86.2024.10.29.20.35.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Oct 2024 20:35:20 -0700 (PDT) From: Zack Rusin To: kvm@vger.kernel.org Cc: Zack Rusin , Doug Covelli , Paolo Bonzini , Jonathan Corbet , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Namhyung Kim , Arnaldo Carvalho de Melo , Isaku Yamahata , Joel Stanley , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH 2/3] KVM: x86: Add support for VMware guest specific hypercalls Date: Tue, 29 Oct 2024 23:34:08 -0400 Message-ID: <20241030033514.1728937-3-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030033514.1728937-1-zack.rusin@broadcom.com> References: <20241030033514.1728937-1-zack.rusin@broadcom.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 VMware products handle hypercalls in userspace. Give KVM the ability to run VMware guests unmodified by fowarding all hypercalls to the userspace. Enabling of the KVM_CAP_X86_VMWARE_HYPERCALL_ENABLE capability turns the feature on - it's off by default. This allows vmx's built on top of KVM to support VMware specific hypercalls. Signed-off-by: Zack Rusin Cc: Doug Covelli Cc: Paolo Bonzini Cc: Jonathan Corbet Cc: Sean Christopherson Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: x86@kernel.org Cc: "H. Peter Anvin" Cc: Shuah Khan Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Isaku Yamahata Cc: Joel Stanley Cc: Zack Rusin Cc: kvm@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org --- Documentation/virt/kvm/api.rst | 41 +++++++++++++++++++++++++++++---- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/x86.c | 33 ++++++++++++++++++++++++++ include/uapi/linux/kvm.h | 1 + 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst index 33ef3cc785e4..5a8c7922f64f 100644 --- a/Documentation/virt/kvm/api.rst +++ b/Documentation/virt/kvm/api.rst @@ -6601,10 +6601,11 @@ to the byte array. .. note:: For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR, KVM_EXIT_XEN, - KVM_EXIT_EPR, KVM_EXIT_X86_RDMSR and KVM_EXIT_X86_WRMSR the corresponding - operations are complete (and guest state is consistent) only after userspace - has re-entered the kernel with KVM_RUN. The kernel side will first finish - incomplete operations and then check for pending signals. + KVM_EXIT_EPR, KVM_EXIT_HYPERCALL, KVM_EXIT_X86_RDMSR and KVM_EXIT_X86_WRMSR + the corresponding operations are complete (and guest state is consistent) + only after userspace has re-entered the kernel with KVM_RUN. The kernel + side will first finish incomplete operations and then check for pending + signals. The pending state of the operation is not preserved in state which is visible to userspace, thus userspace should ensure that the operation is @@ -8201,6 +8202,38 @@ default value for it is set via the kvm.enable_vmware_backdoor kernel parameter (false when not set). Must be set before any VCPUs have been created. +7.38 KVM_CAP_X86_VMWARE_HYPERCALL +--------------------------------- + +:Architectures: x86 +:Parameters: args[0] whether the feature should be enabled or not +:Returns: 0 on success. + +Capability allows userspace to handle hypercalls. When enabled +whenever the vcpu has executed a VMCALL(Intel) or a VMMCALL(AMD) +instruction kvm will exit to userspace with KVM_EXIT_HYPERCALL. + +On exit the hypercall structure of the kvm_run structure will +look as follows: + +:: + /* KVM_EXIT_HYPERCALL */ + struct { + __u64 nr; // rax + __u64 args[6]; // rbx, rcx, rdx, rsi, rdi, rbp + __u64 ret; // cpl, whatever userspace + // sets this to on return will be + // written to the rax + __u64 flags; // KVM_EXIT_HYPERCALL_LONG_MODE if + // the hypercall was executed in + // 64bit mode, 0 otherwise + } hypercall; + +Except when running in compatibility mode with VMware hypervisors +userspace handling of hypercalls is discouraged. To implement +such functionality, use KVM_EXIT_IO (x86) or KVM_EXIT_MMIO +(all except s390). + 8. Other capabilities. ====================== diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 7fcf185e337f..7fbb11682517 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1404,6 +1404,7 @@ struct kvm_arch { struct kvm_xen xen; #endif bool vmware_backdoor_enabled; + bool vmware_hypercall_enabled; bool backwards_tsc_observed; bool boot_vcpu_runs_old_kvmclock; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d7071907d6a5..b676c54266e7 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4689,6 +4689,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_MEMORY_FAULT_INFO: case KVM_CAP_X86_GUEST_MODE: case KVM_CAP_X86_VMWARE_BACKDOOR: + case KVM_CAP_X86_VMWARE_HYPERCALL: r = 1; break; case KVM_CAP_PRE_FAULT_MEMORY: @@ -6784,6 +6785,13 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm, } mutex_unlock(&kvm->lock); break; + case KVM_CAP_X86_VMWARE_HYPERCALL: + r = -EINVAL; + if (cap->args[0] & ~1) + break; + kvm->arch.vmware_hypercall_enabled = cap->args[0]; + r = 0; + break; default: r = -EINVAL; break; @@ -10127,6 +10135,28 @@ static int complete_hypercall_exit(struct kvm_vcpu *vcpu) return kvm_skip_emulated_instruction(vcpu); } +static int kvm_vmware_hypercall(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run = vcpu->run; + bool is_64_bit = is_64_bit_hypercall(vcpu); + u64 mask = is_64_bit ? U64_MAX : U32_MAX; + + vcpu->run->hypercall.flags = is_64_bit ? KVM_EXIT_HYPERCALL_LONG_MODE : 0; + run->hypercall.nr = kvm_rax_read(vcpu) & mask; + run->hypercall.args[0] = kvm_rbx_read(vcpu) & mask; + run->hypercall.args[1] = kvm_rcx_read(vcpu) & mask; + run->hypercall.args[2] = kvm_rdx_read(vcpu) & mask; + run->hypercall.args[3] = kvm_rsi_read(vcpu) & mask; + run->hypercall.args[4] = kvm_rdi_read(vcpu) & mask; + run->hypercall.args[5] = kvm_rbp_read(vcpu) & mask; + run->hypercall.ret = kvm_x86_call(get_cpl)(vcpu); + + run->exit_reason = KVM_EXIT_HYPERCALL; + vcpu->arch.complete_userspace_io = complete_hypercall_exit; + + return 0; +} + unsigned long __kvm_emulate_hypercall(struct kvm_vcpu *vcpu, unsigned long nr, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, @@ -10225,6 +10255,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) int op_64_bit; int cpl; + if (vcpu->kvm->arch.vmware_hypercall_enabled) + return kvm_vmware_hypercall(vcpu); + if (kvm_xen_hypercall_enabled(vcpu->kvm)) return kvm_xen_hypercall(vcpu); diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index c7b5f1c2ee1c..4c2cc6ed29a0 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -934,6 +934,7 @@ struct kvm_enable_cap { #define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237 #define KVM_CAP_X86_GUEST_MODE 238 #define KVM_CAP_X86_VMWARE_BACKDOOR 239 +#define KVM_CAP_X86_VMWARE_HYPERCALL 240 struct kvm_irq_routing_irqchip { __u32 irqchip; From patchwork Wed Oct 30 03:34:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13855886 Received: from mail-qt1-f180.google.com (mail-qt1-f180.google.com [209.85.160.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12C611993B7 for ; Wed, 30 Oct 2024 03:35:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259325; cv=none; b=oFnk5Qb1fdi/vfH9L6JxhuZuZHdhPU+KjOKqY4urUH5rDI53s3CyvatkvKFox+b33lRM4t2baRlTBcSnk38tFiQeXlYJkvV/eflzO6z9fSgvDAESZRulLyyWjRb41BApJ62bUXydBjOq/qxpBYleYf/5tIyLc4eGhqz8yZ8PQns= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259325; c=relaxed/simple; bh=IpK3iCKepmRoHoRT3dTc56O3/n6KoDfaNOMfErPW1c8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ONJCokrGzMqCYFfYzUwhdWyBRAiJYC4WzuyZ+jjvCBnvQE79prXWv8CUfiMbpv7Ob4nlYSbI+IJU1xGe436hOUKswhT+PEcrcuRAxbR0DyhzfsBQJ87xTMw9SnutHix8TLYMu8hGnOthT3y/hkjIdDRWxlf0PKSXhQM/4V43mo8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com; spf=fail smtp.mailfrom=broadcom.com; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b=J99NGQ6J; arc=none smtp.client-ip=209.85.160.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=broadcom.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=broadcom.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=broadcom.com header.i=@broadcom.com header.b="J99NGQ6J" Received: by mail-qt1-f180.google.com with SMTP id d75a77b69052e-4608e389407so76289741cf.2 for ; Tue, 29 Oct 2024 20:35:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1730259322; x=1730864122; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=BPCD1LndjblnaQOLlh+NJCoCkXHp7fNk6gTan5Du7Vo=; b=J99NGQ6J4vvrrX8IMJWw8lFG4zcxI8atJ/mG7h2zdxsOEBbekMFxFHmD7BcstIwXDb +F/b9Jl12rsLYvfjaaTetmLTEpjcn++3qVepPxh+uVN+VTZHIRxO2FqZWw9I9sOImVms BIzvLH8aYfjLTLHh3NnofvFjIZRF4Ytmkwhrw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730259322; x=1730864122; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BPCD1LndjblnaQOLlh+NJCoCkXHp7fNk6gTan5Du7Vo=; b=EK/ILGvCxSW19rZHYoSnLHXHONiwVkk/qkDzsBdqTNZGWNO+NSrFNO/wVuNhqDDI5p 9MXLkuXKLaUp/QYz+QpWDUH8Jc3A5YkzrTuxFVfUXbYPf35Y5eDN6IGmkHv/J9Y+6fZN ZY1RhvPhOyn4Po6Ikxo9pIzC8tzay9YzKDrq+ksFiR2P5VEqgg41ui8NkQTVYSv7Zrdd 293x0vfE0IFGYkm3tKV+uniSNNIJKywrRoz5ql1+MstZn3eFdhRNmkS8gv9Tt/AOp/tZ xgOzEn+UerQvJZfCGb5Lq3vNb7F8HN7N+We1tg0Qvk/sqm6HSLSzlUaJMILIFKWIPnmb BUKg== X-Forwarded-Encrypted: i=1; AJvYcCWBf1DLPt4ap5nCoFWZNHdGsvN89bHW0D+CDf1u6YFBzQxWnpmSfQkOU/riOOsBNfZVFLkk4JeetT6BbyoZsgw=@vger.kernel.org X-Gm-Message-State: AOJu0YyxO+qynxzTIR5TAMEGPJwrDgN+0J05HLBg2FAOYd0YG/OE7fMl sH7glGnXf2F5Ys+xCOkJIuTbtvNOTo7RFzqCWtVWDltcRjxfSLA0yv47J+8dUg== X-Google-Smtp-Source: AGHT+IGvqvrGUPIW3W466krAijES6+oygZ/+5sDNjWbmWwE75flUdG/mkbK2Qqi4HXz/VvGz42EwRw== X-Received: by 2002:a05:622a:181c:b0:45e:fbd1:9890 with SMTP id d75a77b69052e-4613bfc868bmr200791401cf.8.1730259321901; Tue, 29 Oct 2024 20:35:21 -0700 (PDT) Received: from localhost.localdomain ([192.19.144.250]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-461323a4840sm51015561cf.86.2024.10.29.20.35.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Oct 2024 20:35:21 -0700 (PDT) From: Zack Rusin To: kvm@vger.kernel.org Cc: Zack Rusin , Doug Covelli , Paolo Bonzini , Jonathan Corbet , Sean Christopherson , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Namhyung Kim , Arnaldo Carvalho de Melo , Isaku Yamahata , Joel Stanley , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH 3/3] KVM: selftests: x86: Add a test for KVM_CAP_X86_VMWARE_HYPERCALL Date: Tue, 29 Oct 2024 23:34:09 -0400 Message-ID: <20241030033514.1728937-4-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241030033514.1728937-1-zack.rusin@broadcom.com> References: <20241030033514.1728937-1-zack.rusin@broadcom.com> Precedence: bulk X-Mailing-List: linux-kselftest@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add a testcase to exercise KVM_CAP_X86_VMWARE_HYPERCALL and validate that KVM exits to userspace on hypercalls and registers are correctly preserved. Signed-off-by: Zack Rusin Cc: Doug Covelli Cc: Paolo Bonzini Cc: Jonathan Corbet Cc: Sean Christopherson Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: x86@kernel.org Cc: "H. Peter Anvin" Cc: Shuah Khan Cc: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Isaku Yamahata Cc: Joel Stanley Cc: Zack Rusin Cc: kvm@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linux-kselftest@vger.kernel.org --- tools/include/uapi/linux/kvm.h | 2 + tools/testing/selftests/kvm/Makefile | 1 + .../kvm/x86_64/vmware_hypercall_test.c | 108 ++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 tools/testing/selftests/kvm/x86_64/vmware_hypercall_test.c diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index 637efc055145..4c2cc6ed29a0 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -933,6 +933,8 @@ struct kvm_enable_cap { #define KVM_CAP_PRE_FAULT_MEMORY 236 #define KVM_CAP_X86_APIC_BUS_CYCLES_NS 237 #define KVM_CAP_X86_GUEST_MODE 238 +#define KVM_CAP_X86_VMWARE_BACKDOOR 239 +#define KVM_CAP_X86_VMWARE_HYPERCALL 240 struct kvm_irq_routing_irqchip { __u32 irqchip; diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index 48d32c5aa3eb..fa538d01249b 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -103,6 +103,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test TEST_GEN_PROGS_x86_64 += x86_64/ucna_injection_test TEST_GEN_PROGS_x86_64 += x86_64/userspace_io_test TEST_GEN_PROGS_x86_64 += x86_64/userspace_msr_exit_test +TEST_GEN_PROGS_x86_64 += x86_64/vmware_hypercall_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_apic_access_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_close_while_nested_test TEST_GEN_PROGS_x86_64 += x86_64/vmx_dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/vmware_hypercall_test.c b/tools/testing/selftests/kvm/x86_64/vmware_hypercall_test.c new file mode 100644 index 000000000000..0600919ecec8 --- /dev/null +++ b/tools/testing/selftests/kvm/x86_64/vmware_hypercall_test.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * vmware_hypercall_test + * + * Copyright (c) 2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * Based on: + * xen_vmcall_test.c + * + * Copyright © 2020 Amazon.com, Inc. or its affiliates. + * + * VMware hypercall testing + */ + +#include "test_util.h" +#include "kvm_util.h" +#include "processor.h" + +#define ARGVALUE(x) (0xdeadbeef5a5a0000UL + (x)) +#define RETVALUE(x) (0xcafef00dfbfbffffUL + (x)) + +static void guest_code(void) +{ + unsigned long rax = ARGVALUE(1); + unsigned long rbx = ARGVALUE(2); + unsigned long rcx = ARGVALUE(3); + unsigned long rdx = ARGVALUE(4); + unsigned long rsi = ARGVALUE(5); + unsigned long rdi = ARGVALUE(6); + register unsigned long rbp __asm__("rbp") = ARGVALUE(7); + + __asm__ __volatile__("vmcall" : + "=a"(rax), "=b"(rbx), "=c"(rcx), "=d"(rdx), + "=S"(rsi), "=D"(rdi) : + "a"(rax), "b"(rbx), "c"(rcx), "d"(rdx), + "S"(rsi), "D"(rdi), "r"(rbp)); + GUEST_ASSERT_EQ(rax, RETVALUE(1)); + GUEST_ASSERT_EQ(rbx, RETVALUE(2)); + GUEST_ASSERT_EQ(rcx, RETVALUE(3)); + GUEST_ASSERT_EQ(rdx, RETVALUE(4)); + GUEST_ASSERT_EQ(rdi, RETVALUE(5)); + GUEST_ASSERT_EQ(rsi, RETVALUE(6)); + GUEST_DONE(); +} + +int main(int argc, char *argv[]) +{ + struct kvm_vcpu *vcpu; + struct kvm_vm *vm; + + if (!kvm_check_cap(KVM_CAP_X86_VMWARE_HYPERCALL)) { + print_skip("KVM_CAP_X86_VMWARE_HYPERCALL not available"); + exit(KSFT_SKIP); + } + + vm = vm_create_with_one_vcpu(&vcpu, guest_code); + + vm_enable_cap(vm, KVM_CAP_X86_VMWARE_HYPERCALL, 1); + + for (;;) { + struct kvm_run *run = vcpu->run; + struct ucall uc; + + vcpu_run(vcpu); + + if (run->exit_reason == KVM_EXIT_HYPERCALL) { + struct kvm_regs regs; + + TEST_ASSERT_EQ(run->hypercall.ret, 0); + TEST_ASSERT_EQ(run->hypercall.longmode, 1); + TEST_ASSERT_EQ(run->hypercall.nr, ARGVALUE(1)); + TEST_ASSERT_EQ(run->hypercall.args[0], ARGVALUE(2)); + TEST_ASSERT_EQ(run->hypercall.args[1], ARGVALUE(3)); + TEST_ASSERT_EQ(run->hypercall.args[2], ARGVALUE(4)); + TEST_ASSERT_EQ(run->hypercall.args[3], ARGVALUE(5)); + TEST_ASSERT_EQ(run->hypercall.args[4], ARGVALUE(6)); + TEST_ASSERT_EQ(run->hypercall.args[5], ARGVALUE(7)); + + run->hypercall.ret = RETVALUE(1); + vcpu_regs_get(vcpu, ®s); + regs.rbx = RETVALUE(2); + regs.rcx = RETVALUE(3); + regs.rdx = RETVALUE(4); + regs.rdi = RETVALUE(5); + regs.rsi = RETVALUE(6); + vcpu_regs_set(vcpu, ®s); + continue; + } + + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); + + switch (get_ucall(vcpu, &uc)) { + case UCALL_ABORT: + REPORT_GUEST_ASSERT(uc); + /* NOT REACHED */ + case UCALL_SYNC: + break; + case UCALL_DONE: + goto done; + default: + TEST_FAIL("Unknown ucall 0x%lx.", uc.cmd); + } + } +done: + kvm_vm_free(vm); + return 0; +}