Re: [PATCH] KVM: VMX: unify VMX instruction error reporting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, May 04, 2022, Jim Mattson wrote:
> From: David Matlack <dmatlack@xxxxxxxxxx>
> 
> Include the value of the "VM-instruction error" field from the current
> VMCS (if any) in the error message whenever a VMX instruction (other
> than VMREAD) fails. Previously, this field was only reported for
> VMWRITE errors.

Eh, this is pointless for INVVPID and INVEPT, they both have a single error
reason.  VMCLEAR is slightly less pointless, but printing the PA will most likely
make the error reason superfluous.  Ditto for VMPTRLD.

I'm not strictly opposed to printing the error info, but it's not a clear cut win
versus the added risk of blowing up the VMREAD (which is a tiny risk, but non-zero).
And, if we want to do this for everything, then we might as well do it for VMREAD
too.

To reduce the risk of blowing up the host and play nice with VMREAD, what about
adding a dedicated "safe" helper to read VM_INSTRUCTION_ERROR for the error
handlers?  Then modify this patch to go on top...

Compile tested only (I can fully test later today).

--
From: Sean Christopherson <seanjc@xxxxxxxxxx>
Date: Thu, 5 May 2022 08:19:58 -0700
Subject: [PATCH] KVM: VMX: Add a dedicated "safe" helper for
 VMREAD(VM_INSTRUCTION_ERROR)

Add a fully "safe" helper to do VMREAD(VM_INSTRUCTION_ERROR) so that VMX
instruction error handlers, e.g. for VMPTRLD, VMREAD itself, etc..., can
get and print the extra error information without the risk of triggering
kvm_spurious_fault() or an infinite loop (in the VMREAD case).

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 arch/x86/kvm/vmx/vmx.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 26ec9b814651..14ac7b8b0723 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -373,6 +373,26 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var);

 void vmx_vmexit(void);

+static u32 vmread_vm_instruction_error_safe(void)
+{
+	unsigned long value;
+
+	asm volatile("1: vmread %1, %0\n\t"
+		     "ja 3f\n\t"
+
+		     /* VMREAD failed or faulted, clear the return value. */
+		     "2:\n\t"
+		     "xorl %k0, %k0\n\t"
+		     "3:\n\t"
+
+		     _ASM_EXTABLE(1b, 2b)
+
+		     : "=&r"(value)
+		     : "r"((unsigned long)VM_INSTRUCTION_ERROR)
+		     : "cc");
+	return value;
+}
+
 #define vmx_insn_failed(fmt...)		\
 do {					\
 	WARN_ONCE(1, fmt);		\
@@ -390,7 +410,7 @@ asmlinkage void vmread_error(unsigned long field, bool fault)
 noinline void vmwrite_error(unsigned long field, unsigned long value)
 {
 	vmx_insn_failed("kvm: vmwrite failed: field=%lx val=%lx err=%d\n",
-			field, value, vmcs_read32(VM_INSTRUCTION_ERROR));
+			field, value, vmread_vm_instruction_error_safe());
 }

 noinline void vmclear_error(struct vmcs *vmcs, u64 phys_addr)

base-commit: 68973d7fff6d23ae4d05708db429c56e50d377e5
--




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux