All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maxim Levitsky <mlevitsk@redhat.com>
To: kvm@vger.kernel.org
Cc: Kieran Bingham <kbingham@kernel.org>,
	Jan Kiszka <jan.kiszka@siemens.com>,
	Andrew Jones <drjones@redhat.com>,
	Jonathan Corbet <corbet@lwn.net>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	Sean Christopherson <seanjc@google.com>,
	Ingo Molnar <mingo@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	"maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)"
	<x86@kernel.org>, Johannes Berg <johannes.berg@intel.com>,
	Wanpeng Li <wanpengli@tencent.com>,
	"H. Peter Anvin" <hpa@zytor.com>, Jessica Yu <jeyu@kernel.org>,
	Jim Mattson <jmattson@google.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Joerg Roedel <joro@8bytes.org>,
	Yang Weijiang <weijiang.yang@intel.com>,
	linux-kernel@vger.kernel.org, Borislav Petkov <bp@alien8.de>,
	"open list:KERNEL SELFTEST FRAMEWORK" 
	<linux-kselftest@vger.kernel.org>,
	"open list:DOCUMENTATION" <linux-doc@vger.kernel.org>,
	Shuah Khan <shuah@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: Re: [PATCH v3 3/6] KVM: SVM: implement force_intercept_exceptions_mask
Date: Wed, 11 Aug 2021 17:26:40 +0300	[thread overview]
Message-ID: <73f3eff092ca9624ebd55bc02193b39f248c8877.camel@redhat.com> (raw)
In-Reply-To: <20210811122927.900604-4-mlevitsk@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 7280 bytes --]

On Wed, 2021-08-11 at 15:29 +0300, Maxim Levitsky wrote:
> Currently #TS interception is only done once.
> Also exception interception is not enabled for SEV guests.
> 
> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> ---
>  arch/x86/include/asm/kvm_host.h |  2 +
>  arch/x86/kvm/svm/svm.c          | 70 +++++++++++++++++++++++++++++++++
>  arch/x86/kvm/svm/svm.h          |  6 ++-
>  arch/x86/kvm/x86.c              |  5 ++-
>  4 files changed, 80 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 20daaf67a5bf..72fe03506018 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -1690,6 +1690,8 @@ int kvm_emulate_rdpmc(struct kvm_vcpu *vcpu);
>  void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr);
>  void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
>  void kvm_queue_exception_p(struct kvm_vcpu *vcpu, unsigned nr, unsigned long payload);
> +void kvm_queue_exception_e_p(struct kvm_vcpu *vcpu, unsigned nr,
> +			     u32 error_code, unsigned long payload);
>  void kvm_requeue_exception(struct kvm_vcpu *vcpu, unsigned nr);
>  void kvm_requeue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, u32 error_code);
>  void kvm_inject_page_fault(struct kvm_vcpu *vcpu, struct x86_exception *fault);
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index e45259177009..19f54b07161a 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -233,6 +233,8 @@ static const u32 msrpm_ranges[] = {0, 0xc0000000, 0xc0010000};
>  #define MSRS_RANGE_SIZE 2048
>  #define MSRS_IN_RANGE (MSRS_RANGE_SIZE * 8 / 2)
>  
> +static int svm_handle_invalid_exit(struct kvm_vcpu *vcpu, u64 exit_code);
> +
>  u32 svm_msrpm_offset(u32 msr)
>  {
>  	u32 offset;
> @@ -1153,6 +1155,22 @@ static void svm_recalc_instruction_intercepts(struct kvm_vcpu *vcpu,
>  	}
>  }
>  
> +static void svm_init_force_exceptions_intercepts(struct vcpu_svm *svm)
> +{
> +	int exc;
> +
> +	svm->force_intercept_exceptions_mask = force_intercept_exceptions_mask;
> +	for (exc = 0 ; exc < 32 ; exc++) {
> +		if (!(svm->force_intercept_exceptions_mask & (1 << exc)))
> +			continue;
> +
> +		/* Those are defined to have undefined behavior in the SVM spec */
> +		if (exc != 2 && exc != 9)
> +			continue;
> +		set_exception_intercept(svm, exc);

I made a mistake here, during one of the refactoring I think, after I finished
testing this througfully, and I noticed it now while looking again
at the code.

I attached a fix for this, and I also tested more carefully that the
feature works with selftests, kvm unit tests and by booting few VMs.

Best regards,
	Maxim Levitsky

> +	}
> +}
> +
>  static void init_vmcb(struct kvm_vcpu *vcpu)
>  {
>  	struct vcpu_svm *svm = to_svm(vcpu);
> @@ -1304,6 +1322,9 @@ static void init_vmcb(struct kvm_vcpu *vcpu)
>  
>  	enable_gif(svm);
>  
> +	if (!sev_es_guest(vcpu->kvm))
> +		svm_init_force_exceptions_intercepts(svm);
> +
>  }
>  
>  static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
> @@ -1892,6 +1913,17 @@ static int pf_interception(struct kvm_vcpu *vcpu)
>  	u64 fault_address = svm->vmcb->control.exit_info_2;
>  	u64 error_code = svm->vmcb->control.exit_info_1;
>  
> +	if ((svm->force_intercept_exceptions_mask & (1 << PF_VECTOR)))
> +		if (npt_enabled && !vcpu->arch.apf.host_apf_flags) {
> +			/* If the #PF was only intercepted for debug, inject
> +			 * it directly to the guest, since the kvm's mmu code
> +			 * is not ready to deal with such page faults.
> +			 */
> +			kvm_queue_exception_e_p(vcpu, PF_VECTOR,
> +						error_code, fault_address);
> +			return 1;
> +		}
> +
>  	return kvm_handle_page_fault(vcpu, error_code, fault_address,
>  			static_cpu_has(X86_FEATURE_DECODEASSISTS) ?
>  			svm->vmcb->control.insn_bytes : NULL,
> @@ -1967,6 +1999,40 @@ static int ac_interception(struct kvm_vcpu *vcpu)
>  	return 1;
>  }
>  
> +static int gen_exc_interception(struct kvm_vcpu *vcpu)
> +{
> +	/*
> +	 * Generic exception intercept handler which forwards a guest exception
> +	 * as-is to the guest.
> +	 * For exceptions that don't have a special intercept handler.
> +	 *
> +	 * Used only for 'force_intercept_exceptions_mask' KVM debug feature.
> +	 */
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +	int exc = svm->vmcb->control.exit_code - SVM_EXIT_EXCP_BASE;
> +
> +	/* SVM doesn't provide us with an error code for the #DF */
> +	u32 err_code = exc == DF_VECTOR ? 0 : svm->vmcb->control.exit_info_1;
> +
> +	if (!(svm->force_intercept_exceptions_mask & (1 << exc)))
> +		return svm_handle_invalid_exit(vcpu, svm->vmcb->control.exit_code);
> +
> +	if (exc == TS_VECTOR) {
> +		/*
> +		 * SVM doesn't provide us with an error code to be able to
> +		 * re-inject the #TS exception, so just disable its
> +		 * intercept, and let the guest re-execute the instruction.
> +		 */
> +		vmcb_clr_intercept(&svm->vmcb01.ptr->control,
> +				   INTERCEPT_EXCEPTION_OFFSET + TS_VECTOR);
> +		recalc_intercepts(svm);
> +	} else if (x86_exception_has_error_code(exc))
> +		kvm_queue_exception_e(vcpu, exc, err_code);
> +	else
> +		kvm_queue_exception(vcpu, exc);
> +	return 1;
> +}
> +
>  static bool is_erratum_383(void)
>  {
>  	int err, i;
> @@ -3065,6 +3131,10 @@ static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
>  	[SVM_EXIT_WRITE_DR5]			= dr_interception,
>  	[SVM_EXIT_WRITE_DR6]			= dr_interception,
>  	[SVM_EXIT_WRITE_DR7]			= dr_interception,
> +
> +	[SVM_EXIT_EXCP_BASE ...
> +	SVM_EXIT_EXCP_BASE + 31]		= gen_exc_interception,
> +
>  	[SVM_EXIT_EXCP_BASE + DB_VECTOR]	= db_interception,
>  	[SVM_EXIT_EXCP_BASE + BP_VECTOR]	= bp_interception,
>  	[SVM_EXIT_EXCP_BASE + UD_VECTOR]	= ud_interception,
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 524d943f3efc..187ada7c5b03 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -196,6 +196,7 @@ struct vcpu_svm {
>  	bool ghcb_sa_free;
>  
>  	bool guest_state_loaded;
> +	u32 force_intercept_exceptions_mask;
>  };
>  
>  struct svm_cpu_data {
> @@ -351,8 +352,11 @@ static inline void clr_exception_intercept(struct vcpu_svm *svm, u32 bit)
>  	struct vmcb *vmcb = svm->vmcb01.ptr;
>  
>  	WARN_ON_ONCE(bit >= 32);
> -	vmcb_clr_intercept(&vmcb->control, INTERCEPT_EXCEPTION_OFFSET + bit);
>  
> +	if ((1 << bit) & svm->force_intercept_exceptions_mask)
> +		return;
> +
> +	vmcb_clr_intercept(&vmcb->control, INTERCEPT_EXCEPTION_OFFSET + bit);
>  	recalc_intercepts(svm);
>  }
>  
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 092e2fad3c0d..e5c7b8fa1f7f 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -695,12 +695,13 @@ void kvm_queue_exception_p(struct kvm_vcpu *vcpu, unsigned nr,
>  }
>  EXPORT_SYMBOL_GPL(kvm_queue_exception_p);
>  
> -static void kvm_queue_exception_e_p(struct kvm_vcpu *vcpu, unsigned nr,
> -				    u32 error_code, unsigned long payload)
> +void kvm_queue_exception_e_p(struct kvm_vcpu *vcpu, unsigned nr,
> +			     u32 error_code, unsigned long payload)
>  {
>  	kvm_multiple_exception(vcpu, nr, true, error_code,
>  			       true, payload, false);
>  }
> +EXPORT_SYMBOL_GPL(kvm_queue_exception_e_p);
>  
>  int kvm_complete_insn_gp(struct kvm_vcpu *vcpu, int err)
>  {


[-- Attachment #2: 0001-KVM-x86-fix-for-force_intercept_exceptions_mask.patch --]
[-- Type: text/x-patch, Size: 770 bytes --]

From 2bdf847f9991f5be1bdb3a47c0e796af935bdb3f Mon Sep 17 00:00:00 2001
From: Maxim Levitsky <mlevitsk@redhat.com>
Date: Wed, 11 Aug 2021 17:02:14 +0300
Subject: [PATCH] KVM: x86: fix for force_intercept_exceptions_mask

---
 arch/x86/kvm/svm/svm.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 6f17569fd5c8..85e5a93fa79a 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1166,8 +1166,7 @@ static void svm_init_force_exceptions_intercepts(struct vcpu_svm *svm)
 
 		/* Those are defined to have undefined behavior in the SVM spec */
 		if (exc != 2 && exc != 9)
-			continue;
-		set_exception_intercept(svm, exc);
+			set_exception_intercept(svm, exc);
 	}
 }
 
-- 
2.26.3


  reply	other threads:[~2021-08-11 14:27 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-11 12:29 [PATCH v3 0/6] KVM: my debug patch queue Maxim Levitsky
2021-08-11 12:29 ` [PATCH v3 1/6] KVM: SVM: split svm_handle_invalid_exit Maxim Levitsky
2021-08-11 12:29 ` [PATCH v3 2/6] KVM: x86: add force_intercept_exceptions_mask Maxim Levitsky
2021-09-02 16:56   ` Sean Christopherson
2022-02-08 14:34     ` Maxim Levitsky
2022-03-08 23:37       ` Sean Christopherson
2022-03-09 12:31         ` Maxim Levitsky
2022-03-09 14:03           ` Paolo Bonzini
2022-03-09 15:40             ` Sean Christopherson
2021-08-11 12:29 ` [PATCH v3 3/6] KVM: SVM: implement force_intercept_exceptions_mask Maxim Levitsky
2021-08-11 14:26   ` Maxim Levitsky [this message]
2021-09-02 17:34     ` Sean Christopherson
2022-02-08 14:35       ` Maxim Levitsky
2021-08-11 12:29 ` [PATCH v3 4/6] scripts/gdb: rework lx-symbols gdb script Maxim Levitsky
2021-08-11 12:29 ` [PATCH v3 5/6] KVM: x86: implement KVM_GUESTDBG_BLOCKIRQ Maxim Levitsky
2021-08-11 12:29 ` [PATCH v3 6/6] KVM: selftests: test KVM_GUESTDBG_BLOCKIRQ Maxim Levitsky
2021-09-06 11:20   ` Paolo Bonzini
2021-09-06 21:03     ` Maxim Levitsky
2021-11-01 15:43     ` Vitaly Kuznetsov
2021-11-01 16:19       ` Maxim Levitsky
2021-11-01 23:21         ` Sean Christopherson
2021-11-02 10:46           ` Vitaly Kuznetsov
2021-11-02 15:53             ` Sean Christopherson
2021-11-02 16:18               ` Vitaly Kuznetsov
2021-11-02 18:45                 ` Sean Christopherson
2021-11-03  9:04                   ` Maxim Levitsky
2021-11-03  9:29                     ` [PATCH] KVM: x86: inhibit APICv when KVM_GUESTDBG_BLOCKIRQ active Maxim Levitsky
2021-11-03  9:31                       ` Maxim Levitsky
2021-08-11 13:10 ` [PATCH v3 0/6] KVM: my debug patch queue Paolo Bonzini
2021-08-11 13:22   ` Maxim Levitsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=73f3eff092ca9624ebd55bc02193b39f248c8877.camel@redhat.com \
    --to=mlevitsk@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=bp@alien8.de \
    --cc=corbet@lwn.net \
    --cc=drjones@redhat.com \
    --cc=hpa@zytor.com \
    --cc=jan.kiszka@siemens.com \
    --cc=jeyu@kernel.org \
    --cc=jmattson@google.com \
    --cc=johannes.berg@intel.com \
    --cc=joro@8bytes.org \
    --cc=kbingham@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=shuah@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=vkuznets@redhat.com \
    --cc=wanpengli@tencent.com \
    --cc=weijiang.yang@intel.com \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.