From nobody Mon Nov 25 04:31:31 2024 Received: from mail-vs1-f45.google.com (mail-vs1-f45.google.com [209.85.217.45]) (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 034E31946DF for ; Wed, 30 Oct 2024 03:35:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.217.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259323; cv=none; b=oGXm6blOc4BqgknOcwXTpV+NoVkANhMkeOj8dL74rjddyygs033PMnsYByG4DMpNlw9ZiIVMioNoLqvKKr4btqepIGliE5dXOUQU9lnELRGIwr4SSoE8ogH9eNafKlgNkgZeenA6ZoMdA6v1awKP1GxhhH3u/PXrqZe2vNu5D0Y= 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.45 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-f45.google.com with SMTP id ada2fe7eead31-4a47d70cd8aso1947139137.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=cou2ChYextFRXiF6Ak8TmdiKDqlaF/LMzzj8OzAKNNAQm25tt7fQMThb2sqBeYBFD0 2mVHJ5Qp/lTc+LcPt15RvThhQ49m63tyi1vHshzvmDkcJT3rDd4r7h5B/FTVRKxup8yF YXqqm2mWg+k1wv/85j2HTH50gSgFxKTe7794nGY80KPvBmrS1s0KERleou6zyYkxutKP 4r8tYL0Hn8BjvZX4ZpXlNW6dd9iTzGnWceqeE3LEVUDSDVgF7Mz5/3DLZbxx2dQ8n2aW 6cfinj3rUg7JXw9FSdQpRpZQqU1WugcLRzVx+ni3WJkaOUrxYT3Bl8yTVCa0ix3OGsUC 3f9Q== X-Forwarded-Encrypted: i=1; AJvYcCX3hlqMc4f/KPWNznF2yy2h3nBVQCYXFarWYqbir6y9kpuO92Nn444G0guxdYwahJMDpmGrcd17Xzza9kk=@vger.kernel.org X-Gm-Message-State: AOJu0YwyhZHElhsS2SyB6ZpgJGre/eJZE/XKOEEjB5T2ncteeIdxfhki XPkKXO/BsagGufNiPGTA1dfSRDpMhAcW0Y3+0oXokHd/kBqjwIWKkiN7JIElbg== 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-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 o= r L2 guest depending on which executed at the time of an exit. Userspace must take care to differentiate between these cases. =20 +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. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.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; =20 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 x8= 6_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 =3D=3D VMWARE_PORT_VMPORT) || (port =3D=3D VMWARE_PORT_VMRPC))) return true; =20 @@ -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=3D0. */ - if (enable_vmware_backdoor && is_vmware_backdoor_pmc(rcx)) + if (kvm_vmware_backdoor_enabled(ctxt->vcpu) && + is_vmware_backdoor_pmc(rcx)) return X86EMUL_CONTINUE; =20 /* 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); =20 /* @@ -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); =20 svm_set_intercept(svm, INTERCEPT_INTR); @@ -2401,7 +2401,7 @@ static int gp_interception(struct kvm_vcpu *vcpu) opcode =3D svm_instr_opcode(vcpu); =20 if (opcode =3D=3D NONE_SVM_INSTR) { - if (!enable_vmware_backdoor) + if (!kvm_vmware_backdoor_enabled(vcpu)) goto reinject; =20 /* 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 |=3D (1u << GP_VECTOR); if ((vcpu->guest_debug & (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) =3D=3D @@ -5249,7 +5249,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) error_code =3D vmcs_read32(VM_EXIT_INTR_ERROR_CODE); =20 if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) { - WARN_ON_ONCE(!enable_vmware_backdoor); + WARN_ON_ONCE(!kvm_vmware_backdoor_enabled(vcpu)); =20 /* * 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, lon= g 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 =3D 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 =3D -EINVAL; + if (cap->args[0] & ~1) + break; + mutex_lock(&kvm->lock); + if (!kvm->created_vcpus) { + kvm->arch.vmware_backdoor_enabled =3D cap->args[0]; + r =3D 0; + } + mutex_unlock(&kvm->lock); + break; default: r =3D -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 =3D true; kvm->arch.enable_pmu =3D enable_pmu; =20 + kvm->arch.vmware_backdoor_enabled =3D enable_vmware_backdoor; + #if IS_ENABLED(CONFIG_HYPERV) spin_lock_init(&kvm->arch.hv_root_tdp_lock); kvm->arch.hv_root_tdp =3D 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) =20 extern unsigned int min_timer_period_us; =20 -extern bool enable_vmware_backdoor; - extern int pi_inject_timer; =20 extern bool report_ignored_msrs; =20 extern bool eager_page_split; =20 +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 =20 struct kvm_irq_routing_irqchip { __u32 irqchip; --=20 2.43.0 From nobody Mon Nov 25 04:31:31 2024 Received: from mail-qt1-f178.google.com (mail-qt1-f178.google.com [209.85.160.178]) (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 090E61991DA for ; Wed, 30 Oct 2024 03:35:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259327; cv=none; b=kvJsWdLwKvMz4Z21Hkizsf3zC45mt/TeFe24MtX9P9GZ2piWVw/7PsN7ihu8GNVC6NXbH0lgSB3Z/Ki4AKkR64h9ce42UezgLteVRWjfeeebb9SF0ONZgEFFO6AuO4SAdcBMsETvSdoFv6DLcujgmcEaY843xhoBhG2Zm7KS3ts= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259327; c=relaxed/simple; bh=Kgs+eWx7o2g2fh3PL6R26a4Wy9eDpiLIOtdgqULaC2k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nudeWJzPfOS0ZBe8C/EKXm4sSCw2n9O1vzutUV/uZfzPnCHQSNucrnMAt+73uV7K3qvqaDV+2VWlfg2wj7A2NN81DE6xoU5xkkffJWv0WLd11uhZ8DJUK6/F7szgu6JutXcstLRPeJ6sdA+F4nir+zzr78hF3CFoypOzOUeUGzU= 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.178 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-f178.google.com with SMTP id d75a77b69052e-460c2418e37so45886381cf.0 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=ILH6UNKdoKuWAVT8HukrLRYgAoWOWXcMoTUA7C0YNQKl02PvX1og5KoEoMi2cef/+t C57vibGzREdhpq1VU5iICmrJWy7WEmKbioOiCWrpNRqGMTOozDOWkSOYFtZ++iJKH0K6 37cUsl5kQPvheaIkMMsRmBdZEu1Sqlg0SPeWCyVlpocLx2aq/F1jAG4eilXgvHpAT7y6 LgL0exwey2RdSJvaR886wdD9AKekZcnKraHkx3FwGlAEsYi0IigQslOXohbMt9RP9Ujo XvmRjsshTXTUveY6Dgn37XcWUfixu91mfsS0BNGdadmQDAfVaFEaqnpryeV88Tej9fLR DO7A== X-Forwarded-Encrypted: i=1; AJvYcCXYEJLWRyR7g1YrbYYLtZoGveNF+G4MgDiLU/3YzXxvudRmr2OSng0qrPKVIQIcANdh1vIwogJU2xZhAtU=@vger.kernel.org X-Gm-Message-State: AOJu0Yz59T8TnpXItVCeU4W+Xj1C4XGedrpSJ3U9QMX5AgZyelAaArZ4 16Xt0ER//W14niJP8kHzMji4mIAVvtYcrBccZw1ymKzpYGFkcoC+0ak+zAxjhA== 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-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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:: =20 For KVM_EXIT_IO, KVM_EXIT_MMIO, KVM_EXIT_OSI, KVM_EXIT_PAPR, KVM_EXI= T_XEN, - KVM_EXIT_EPR, KVM_EXIT_X86_RDMSR and KVM_EXIT_X86_WRMSR the correspo= nding - operations are complete (and guest state is consistent) only after u= serspace - 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_X8= 6_WRMSR + the corresponding operations are complete (and guest state is consis= tent) + only after userspace has re-entered the kernel with KVM_RUN. The ker= nel + side will first finish incomplete operations and then check for pend= ing + signals. =20 The pending state of the operation is not preserved in state which is visible to userspace, thus userspace should ensure that the operatio= n is @@ -8201,6 +8202,38 @@ default value for it is set via the kvm.enable_vmwar= e_backdoor kernel parameter (false when not set). Must be set before any VCPUs have been created. =20 +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. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_hos= t.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; =20 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, lon= g 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 =3D 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 =3D -EINVAL; + if (cap->args[0] & ~1) + break; + kvm->arch.vmware_hypercall_enabled =3D cap->args[0]; + r =3D 0; + break; default: r =3D -EINVAL; break; @@ -10127,6 +10135,28 @@ static int complete_hypercall_exit(struct kvm_vcpu= *vcpu) return kvm_skip_emulated_instruction(vcpu); } =20 +static int kvm_vmware_hypercall(struct kvm_vcpu *vcpu) +{ + struct kvm_run *run =3D vcpu->run; + bool is_64_bit =3D is_64_bit_hypercall(vcpu); + u64 mask =3D is_64_bit ? U64_MAX : U32_MAX; + + vcpu->run->hypercall.flags =3D is_64_bit ? KVM_EXIT_HYPERCALL_LONG_MODE := 0; + run->hypercall.nr =3D kvm_rax_read(vcpu) & mask; + run->hypercall.args[0] =3D kvm_rbx_read(vcpu) & mask; + run->hypercall.args[1] =3D kvm_rcx_read(vcpu) & mask; + run->hypercall.args[2] =3D kvm_rdx_read(vcpu) & mask; + run->hypercall.args[3] =3D kvm_rsi_read(vcpu) & mask; + run->hypercall.args[4] =3D kvm_rdi_read(vcpu) & mask; + run->hypercall.args[5] =3D kvm_rbp_read(vcpu) & mask; + run->hypercall.ret =3D kvm_x86_call(get_cpl)(vcpu); + + run->exit_reason =3D KVM_EXIT_HYPERCALL; + vcpu->arch.complete_userspace_io =3D 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; =20 + if (vcpu->kvm->arch.vmware_hypercall_enabled) + return kvm_vmware_hypercall(vcpu); + if (kvm_xen_hypercall_enabled(vcpu->kvm)) return kvm_xen_hypercall(vcpu); =20 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 =20 struct kvm_irq_routing_irqchip { __u32 irqchip; --=20 2.43.0 From nobody Mon Nov 25 04:31:31 2024 Received: from mail-qt1-f172.google.com (mail-qt1-f172.google.com [209.85.160.172]) (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 1A0C91993BD for ; Wed, 30 Oct 2024 03:35:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259326; cv=none; b=GMewA8G2aT/tN64VtkB7FGt4fMCZjJBBEeX9zTrOaTCbyzHE5tyHI6wwmL7PZKpx/FeX3k/Wlz0sHdLLB98qE2YTWSXh+9N12ZCucIqf72pD0Am3rb2Pr5zwpxJQPCcO3omdLOqEztvWQT7kkOm2dxLIk5MT8W/yaZJX1OLCByY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1730259326; c=relaxed/simple; bh=IpK3iCKepmRoHoRT3dTc56O3/n6KoDfaNOMfErPW1c8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=HUJp/XQTtPzt6zmIeU56IyorqQbk99oq1CU8pKtsJvz22JiCYxysANgTUjqmG4KlOe0t3/i25VvE/TSdtigQziuyF4sBz1I5yA2KgMMDbl56PGpd//2n07ts3mgvdeve7WF5VuT3ObWgTiisyqa33AxEBjltfbYEQbApiXt+goY= 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.172 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-f172.google.com with SMTP id d75a77b69052e-460ad0440ddso44299551cf.3 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=Yd/Okr8EdyJnBopM/txW99/YFiE8HtWA1YQQevhEUfUlwvUFcNmBye/usyBuJzOmOr 0vVlEXYOLmgs1di2Yt+Qzn47kbi8AkZC2x5pyFzGhRyBHa9kHOE6Hq7e3orW33sCJnQO IyrnfMcraLAdOokStuGO5DMxbL66Pr0Ic3ybLkURO802sH+Z71l1dorHcLYj8uCmJHNz UgbskDsNu5vP7oVFO7hOLJx5hFweh4dpAuD8S54S53N6YKSvtSURG4S/3aeFYAR03cy4 kXFK7BTuKAGhnQ1DGJ1F+DHHedkMIQVbK/ZKtg/t+v/1U61dnTdOkU2uOwerWPitLZIy MGxQ== X-Forwarded-Encrypted: i=1; AJvYcCXjqlC8W127TPrTRg91J09X5bsiJkULSabmTdpEy705kB1w5TQ7lOdNu/tXvnTB3u0RPOgdkIFM7TqvJns=@vger.kernel.org X-Gm-Message-State: AOJu0YyRHKeclwBXRbcHVGCKLTJtuvcthbPgr8M5z6ZdOM65LFts7pK4 TxXSSksfAggqF1x1/SV1/CvPqJA+PoeUS++/2uzJg5s0omlKqJ5zxVGiSfmcGA== 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-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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_tes= t.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 =20 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 +=3D x86_64/sync_regs_test TEST_GEN_PROGS_x86_64 +=3D x86_64/ucna_injection_test TEST_GEN_PROGS_x86_64 +=3D x86_64/userspace_io_test TEST_GEN_PROGS_x86_64 +=3D x86_64/userspace_msr_exit_test +TEST_GEN_PROGS_x86_64 +=3D x86_64/vmware_hypercall_test TEST_GEN_PROGS_x86_64 +=3D x86_64/vmx_apic_access_test TEST_GEN_PROGS_x86_64 +=3D x86_64/vmx_close_while_nested_test TEST_GEN_PROGS_x86_64 +=3D x86_64/vmx_dirty_log_test diff --git a/tools/testing/selftests/kvm/x86_64/vmware_hypercall_test.c b/t= ools/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 + * =E2=80=9CBroadcom=E2=80=9D refers to Broadcom Inc. and/or its subsidiar= ies. + * + * Based on: + * xen_vmcall_test.c + * + * Copyright =C2=A9 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 =3D ARGVALUE(1); + unsigned long rbx =3D ARGVALUE(2); + unsigned long rcx =3D ARGVALUE(3); + unsigned long rdx =3D ARGVALUE(4); + unsigned long rsi =3D ARGVALUE(5); + unsigned long rdi =3D ARGVALUE(6); + register unsigned long rbp __asm__("rbp") =3D ARGVALUE(7); + + __asm__ __volatile__("vmcall" : + "=3Da"(rax), "=3Db"(rbx), "=3Dc"(rcx), "=3Dd"(rdx), + "=3DS"(rsi), "=3DD"(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 =3D vm_create_with_one_vcpu(&vcpu, guest_code); + + vm_enable_cap(vm, KVM_CAP_X86_VMWARE_HYPERCALL, 1); + + for (;;) { + struct kvm_run *run =3D vcpu->run; + struct ucall uc; + + vcpu_run(vcpu); + + if (run->exit_reason =3D=3D 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 =3D RETVALUE(1); + vcpu_regs_get(vcpu, ®s); + regs.rbx =3D RETVALUE(2); + regs.rcx =3D RETVALUE(3); + regs.rdx =3D RETVALUE(4); + regs.rdi =3D RETVALUE(5); + regs.rsi =3D 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; +} --=20 2.43.0