All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <seanjc@google.com>
To: Maxim Levitsky <mlevitsk@redhat.com>
Cc: kvm@vger.kernel.org, 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>,
	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: Thu, 2 Sep 2021 17:34:50 +0000	[thread overview]
Message-ID: <YTELOvhj5lERBKeC@google.com> (raw)
In-Reply-To: <73f3eff092ca9624ebd55bc02193b39f248c8877.camel@redhat.com>

On Wed, Aug 11, 2021, Maxim Levitsky wrote:
> On Wed, 2021-08-11 at 15:29 +0300, Maxim Levitsky wrote:
> > 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;

Ah, the param is being snapshotted on vCPU creation, hence the writable module
param.  That works, though it'd be better to snapshot it on a per-VM basic, not
per-vCPU, and do so in common x86 code so that the param doesn't need to be
exported.

> > +	for (exc = 0 ; exc < 32 ; exc++) {

for_each_set_bit()

> > +		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)

Maybe add a pr_warn_once() to let the user know they done messed up?

And given that there are already intercepts with undefined behavior, it's probably
best to disallow intercepting anything we aren't 100% postive will be handled
correctly, e.g. intercepting vector 31 is nonsensical at this time.

> > +			continue;
> > +		set_exception_intercept(svm, exc);

...

> > +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;

Might be better to handle this in the x86_exception_has_error_code() path to
avoid confusing readers with respect to exceptions that don't have an error code,
e.g.

	else if (x86_exception_has_error_code(exc)) {
		/* SVM doesn't provide the error code on #DF :-( */
		if (exc == DF_VECTOR)
			kvm_queue_exception_e(vcpu, exc, 0);
		else
			kvm_queue_exception_e(vcpu, exc, svm->vmcb->control.exit_info_1);
	} else {
		...
	}

Alternatively, can we zero svm->vmcb->control.exit_info_1 on #DF to make it more
obvious that SVM leaves stale data in exit_info_1 (assuming that's true)?  E.g.

	...

	if (exc == TS_VECTOR) {
		...
	} else if (x86_exception_has_error_code(exc)) {
		/* SVM doesn't provide the error code on #DF :-( */
		if (exc == DF_VECTOR)
			svm->vmcb->control.exit_info_1 = 0;

		kvm_queue_exception_e(vcpu, exc, svm->vmcb->control.exit_info_1);
	} else {
		...
	}

		
> > +
> > +	if (!(svm->force_intercept_exceptions_mask & (1 << exc)))

BIT(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);

Maybe just disallow intercepting #TS altogether?  Or does this fall into your
Win98 use case? :-)

> > +		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,

This generates a Sparse warning due to the duplicate initializer.  IMO that's a
very good warning as I have zero idea how the compiler actually handles this
particular scenario, e.g. do later entries take priority, is it technically
"undefined" behavior, etc...

arch/x86/kvm/svm/svm.c:3065:10: warning: Initializer entry defined twice
arch/x86/kvm/svm/svm.c:3067:29:   also defined here

I don't have a clever solution though :-(

> > +
> >  	[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)

BIT(bit)

> > +		return;
> > +
> > +	vmcb_clr_intercept(&vmcb->control, INTERCEPT_EXCEPTION_OFFSET + bit);
> >  	recalc_intercepts(svm);
> >  }

  reply	other threads:[~2021-09-02 17:34 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
2021-09-02 17:34     ` Sean Christopherson [this message]
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=YTELOvhj5lERBKeC@google.com \
    --to=seanjc@google.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=mlevitsk@redhat.com \
    --cc=pbonzini@redhat.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.