linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Maxim Levitsky <mlevitsk@redhat.com>
To: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>,
	linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: pbonzini@redhat.com, seanjc@google.com, joro@8bytes.org,
	jon.grimm@amd.com, wei.huang2@amd.com, terry.bowman@amd.com
Subject: Re: [RFCv2 PATCH 08/12] KVM: SVM: Adding support for configuring x2APIC MSRs interception
Date: Thu, 24 Mar 2022 17:19:32 +0200	[thread overview]
Message-ID: <426b70a407b774627187e64b011a64bfb7214b36.camel@redhat.com> (raw)
In-Reply-To: <20220308163926.563994-9-suravee.suthikulpanit@amd.com>

On Tue, 2022-03-08 at 10:39 -0600, Suravee Suthikulpanit wrote:
> When enabling x2APIC virtualization (x2AVIC), the interception of
> x2APIC MSRs must be disabled to let the hardware virtualize guest
> MSR accesses.
> 
> Current implementation keeps track of MSR interception state
> for generic MSRs in the svm_direct_access_msrs array.
> For x2APIC MSRs, introduce direct_access_x2apic_msrs array.
> 
> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> ---
>  arch/x86/kvm/svm/svm.c | 67 +++++++++++++++++++++++++++++++-----------
>  arch/x86/kvm/svm/svm.h |  7 +++++
>  2 files changed, 57 insertions(+), 17 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index 3048f4b758d6..ce3c68a785cf 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -89,7 +89,7 @@ static uint64_t osvw_len = 4, osvw_status;
>  static DEFINE_PER_CPU(u64, current_tsc_ratio);
>  #define TSC_RATIO_DEFAULT	0x0100000000ULL
>  
> -static const struct svm_direct_access_msrs {
> +static struct svm_direct_access_msrs {
>  	u32 index;   /* Index of the MSR */
>  	bool always; /* True if intercept is initially cleared */
>  } direct_access_msrs[MAX_DIRECT_ACCESS_MSRS] = {
> @@ -117,6 +117,9 @@ static const struct svm_direct_access_msrs {
>  	{ .index = MSR_INVALID,				.always = false },
>  };
>  
> +static struct svm_direct_access_msrs
> +direct_access_x2apic_msrs[NUM_DIRECT_ACCESS_X2APIC_MSRS + 1];
> +
>  /*
>   * These 2 parameters are used to config the controls for Pause-Loop Exiting:
>   * pause_filter_count: On processors that support Pause filtering(indicated
> @@ -609,41 +612,42 @@ static int svm_cpu_init(int cpu)
>  
>  }
>  
> -static int direct_access_msr_slot(u32 msr)
> +static int direct_access_msr_slot(u32 msr, struct svm_direct_access_msrs *msrs)
>  {
>  	u32 i;
>  
> -	for (i = 0; direct_access_msrs[i].index != MSR_INVALID; i++)
> -		if (direct_access_msrs[i].index == msr)
> +	for (i = 0; msrs[i].index != MSR_INVALID; i++)
> +		if (msrs[i].index == msr)
>  			return i;
>  
>  	return -ENOENT;
>  }
>  
> -static void set_shadow_msr_intercept(struct kvm_vcpu *vcpu, u32 msr, int read,
> -				     int write)
> +static void set_shadow_msr_intercept(struct kvm_vcpu *vcpu,
> +				     struct svm_direct_access_msrs *msrs, u32 msr,
> +				     int read, void *read_bits,
> +				     int write, void *write_bits)
>  {
> -	struct vcpu_svm *svm = to_svm(vcpu);
> -	int slot = direct_access_msr_slot(msr);direct_access_msrs
> +	int slot = direct_access_msr_slot(msr, msrs);
>  
>  	if (slot == -ENOENT)
>  		return;
>  
>  	/* Set the shadow bitmaps to the desired intercept states */
>  	if (read)
> -		set_bit(slot, svm->shadow_msr_intercept.read);
> +		set_bit(slot, read_bits);
>  	else
> -		clear_bit(slot, svm->shadow_msr_intercept.read);
> +		clear_bit(slot, read_bits);
>  
>  	if (write)
> -		set_bit(slot, svm->shadow_msr_intercept.write);
> +		set_bit(slot, write_bits);
>  	else
> -		clear_bit(slot, svm->shadow_msr_intercept.write);
> +		clear_bit(slot, write_bits);
>  }
>  
> -static bool valid_msr_intercept(u32 index)
> +static bool valid_msr_intercept(u32 index, struct svm_direct_access_msrs *msrs)
>  {
> -	return direct_access_msr_slot(index) != -ENOENT;
> +	return direct_access_msr_slot(index, msrs) != -ENOENT;
>  }
>  
>  static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
> @@ -674,9 +678,12 @@ static void set_msr_interception_bitmap(struct kvm_vcpu *vcpu, u32 *msrpm,
>  
>  	/*
>  	 * If this warning triggers extend the direct_access_msrs list at the
> -	 * beginning of the file
> +	 * beginning of the file. The direct_access_x2apic_msrs is only for
> +	 * x2apic MSRs.
>  	 */
> -	WARN_ON(!valid_msr_intercept(msr));
> +	WARN_ON(!valid_msr_intercept(msr, direct_access_msrs) &&
> +		(boot_cpu_has(X86_FEATURE_X2AVIC) &&
> +		 !valid_msr_intercept(msr, direct_access_x2apic_msrs)));
>  
>  	/* Enforce non allowed MSRs to trap */
>  	if (read && !kvm_msr_allowed(vcpu, msr, KVM_MSR_FILTER_READ))
> @@ -704,7 +711,16 @@ static void set_msr_interception_bitmap(struct kvm_vcpu *vcpu, u32 *msrpm,
>  void set_msr_interception(struct kvm_vcpu *vcpu, u32 *msrpm, u32 msr,
>  			  int read, int write)
>  {
> -	set_shadow_msr_intercept(vcpu, msr, read, write);
> +	struct vcpu_svm *svm = to_svm(vcpu);
> +
> +	if (msr < 0x800 || msr > 0x8ff)
> +		set_shadow_msr_intercept(vcpu, direct_access_msrs, msr,
> +					 read, svm->shadow_msr_intercept.read,
> +					 write, svm->shadow_msr_intercept.write);
> +	else
> +		set_shadow_msr_intercept(vcpu, direct_access_x2apic_msrs, msr,
> +					 read, svm->shadow_x2apic_msr_intercept.read,
> +					 write, svm->shadow_x2apic_msr_intercept.write);
>  	set_msr_interception_bitmap(vcpu, msrpm, msr, read, write);
>  }
>  
> @@ -786,6 +802,22 @@ static void add_msr_offset(u32 offset)
>  	BUG();
>  }
>  
> +static void init_direct_access_x2apic_msrs(void)
> +{
> +	int i;
> +
> +	/* Initialize x2APIC direct_access_x2apic_msrs entries */
> +	for (i = 0; i < NUM_DIRECT_ACCESS_X2APIC_MSRS; i++) {
> +		direct_access_x2apic_msrs[i].index = boot_cpu_has(X86_FEATURE_X2AVIC) ?
> +						  (0x800 + i) : MSR_INVALID;
> +		direct_access_x2apic_msrs[i].always = false;
> +	}
> +
> +	/* Initialize last entry */
> +	direct_access_x2apic_msrs[i].index = MSR_INVALID;
> +	direct_access_x2apic_msrs[i].always = false;
> +}
> +
>  static void init_msrpm_offsets(void)
>  {
>  	int i;
> @@ -4750,6 +4782,7 @@ static __init int svm_hardware_setup(void)
>  	memset(iopm_va, 0xff, PAGE_SIZE * (1 << order));
>  	iopm_base = page_to_pfn(iopm_pages) << PAGE_SHIFT;
>  
> +	init_direct_access_x2apic_msrs();
>  	init_msrpm_offsets();
>  
>  	supported_xcr0 &= ~(XFEATURE_MASK_BNDREGS | XFEATURE_MASK_BNDCSR);
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index b53c83a44ec2..19ad40b8383b 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -29,6 +29,8 @@
>  
>  #define MAX_DIRECT_ACCESS_MSRS	20
>  #define MSRPM_OFFSETS	16
> +#define NUM_DIRECT_ACCESS_X2APIC_MSRS	0x100
> +
>  extern u32 msrpm_offsets[MSRPM_OFFSETS] __read_mostly;
>  extern bool npt_enabled;
>  extern bool intercept_smi;
> @@ -241,6 +243,11 @@ struct vcpu_svm {
>  		DECLARE_BITMAP(write, MAX_DIRECT_ACCESS_MSRS);
>  	} shadow_msr_intercept;
>  
> +	struct {
> +		DECLARE_BITMAP(read, NUM_DIRECT_ACCESS_X2APIC_MSRS);
> +		DECLARE_BITMAP(write, NUM_DIRECT_ACCESS_X2APIC_MSRS);
> +	} shadow_x2apic_msr_intercept;
> +
>  	struct vcpu_sev_es_state sev_es;
>  
>  	bool guest_state_loaded;


I did some homework on this, and it looks mostly correct.

However I do wonder if we need that separation of svm_direct_access_msrs and 
direct_access_x2apic_msrs. I understand the peformance wise, the  
direct_access_msrs will get longer otherwise (but we don't have to allow
all x2apic msr range, but only known x2apic registers which aren't that many).

One of the things that I see that *is* broken (at least in theory) is nesting.

init_msrpm_offsets goes over direct_access_msrs and puts the offsets of corresponding
bits in the hardware msr bitmap into the 'msrpm_offsets'

Then on nested VM entry the nested_svm_vmrun_msrpm uses this list to merge the nested
and host MSR bitmaps.
Without x2apic msrs, this means that if L1 chooses to allow L2 to access its x2apic msrs
it won't work. It is not something that L1 would do often but still allowed to overall.

Honestly we need to write track the nested MSR bitmap to avoid updating it on each VM entry,
then with this hot path eliminated, I don't think there are other places which update
the msr interception often, and thus we could just put the x2apic msrs into the 
direct_access_msrs.

Best regards,
	Maxim Levitsky




  reply	other threads:[~2022-03-24 15:20 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-08 16:39 [RFCv2 PATCH 00/12] Introducing AMD x2APIC Virtualization (x2AVIC) support Suravee Suthikulpanit
2022-03-08 16:39 ` [RFCv2 PATCH 01/12] x86/cpufeatures: Introduce x2AVIC CPUID bit Suravee Suthikulpanit
2022-03-08 16:39 ` [RFCv2 PATCH 02/12] KVM: x86: lapic: Rename [GET/SET]_APIC_DEST_FIELD to [GET/SET]_XAPIC_DEST_FIELD Suravee Suthikulpanit
2022-03-24 10:30   ` Maxim Levitsky
2022-03-08 16:39 ` [RFCv2 PATCH 03/12] KVM: SVM: Detect X2APIC virtualization (x2AVIC) support Suravee Suthikulpanit
2022-03-24 10:53   ` Maxim Levitsky
2022-03-08 16:39 ` [RFCv2 PATCH 04/12] KVM: SVM: Update max number of vCPUs supported for x2AVIC mode Suravee Suthikulpanit
2022-03-24 11:13   ` Maxim Levitsky
2022-03-08 16:39 ` [RFCv2 PATCH 05/12] KVM: SVM: Update avic_kick_target_vcpus to support 32-bit APIC ID Suravee Suthikulpanit
2022-03-24 11:36   ` Maxim Levitsky
2022-03-08 16:39 ` [RFCv2 PATCH 06/12] KVM: SVM: Do not update logical APIC ID table when in x2APIC mode Suravee Suthikulpanit
2022-03-24 11:37   ` Maxim Levitsky
2022-03-08 16:39 ` [RFCv2 PATCH 07/12] KVM: SVM: Introduce helper function kvm_get_apic_id Suravee Suthikulpanit
2022-03-24 14:14   ` Maxim Levitsky
2022-04-05  3:58     ` Suravee Suthikulpanit
2022-04-05  9:36       ` Suravee Suthikulpanit
2022-03-08 16:39 ` [RFCv2 PATCH 08/12] KVM: SVM: Adding support for configuring x2APIC MSRs interception Suravee Suthikulpanit
2022-03-24 15:19   ` Maxim Levitsky [this message]
2022-04-05  1:45     ` Suravee Suthikulpanit
2022-03-08 16:39 ` [RFCv2 PATCH 09/12] KVM: SVM: Refresh AVIC settings when changing APIC mode Suravee Suthikulpanit
2022-03-24 15:35   ` Maxim Levitsky
2022-03-31  4:04     ` Suravee Suthikulpanit
2022-03-08 16:39 ` [RFCv2 PATCH 10/12] KVM: SVM: Introduce helper functions to (de)activate AVIC and x2AVIC Suravee Suthikulpanit
2022-03-24 15:40   ` Maxim Levitsky
2022-03-08 16:39 ` [RFCv2 PATCH 11/12] KVM: SVM: Do not throw warning when calling avic_vcpu_load on a running vcpu Suravee Suthikulpanit
2022-03-24 15:42   ` Maxim Levitsky
2022-03-08 16:39 ` [RFCv2 PATCH 12/12] KVM: SVM: Do not inhibit APICv when x2APIC is present Suravee Suthikulpanit

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=426b70a407b774627187e64b011a64bfb7214b36.camel@redhat.com \
    --to=mlevitsk@redhat.com \
    --cc=jon.grimm@amd.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=suravee.suthikulpanit@amd.com \
    --cc=terry.bowman@amd.com \
    --cc=wei.huang2@amd.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).