lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <682cefa6-9a74-4b8b-97e2-38a1c58c6e72@amd.com>
Date: Thu, 31 Oct 2024 16:46:32 +0700
From: "Suthikulpanit, Suravee" <suravee.suthikulpanit@....com>
To: linux-kernel@...r.kernel.org, kvm@...r.kernel.org
Cc: seanjc@...gle.com, pbonzini@...hat.com, rkrcmar@...hat.com,
 jon.grimm@....com, santosh.shukla@....com
Subject: Re: [PATCH] KVM: SVM: Increase X2AVIC limit to 4096 vcpus

Hi All,

Any concerns for this patch?

Thanks,
Suravee

On 10/9/2024 12:11 AM, Suravee Suthikulpanit wrote:
> Newer AMD platforms enhance x2AVIC feature to support up to 4096 vcpus.
> This capatility is detected via CPUID_Fn8000000A_ECX[x2AVIC_EXT].
> 
> Modify the SVM driver to check the capability. If detected, extend bitmask
> for guest max physical APIC ID to 0xFFF, increase maximum vcpu index to
> 4095, and increase the size of the Phyical APIC ID table from 4K to 32K in
> order to accommodate up to 4096 entries.
> 
> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@....com>
> ---
>   arch/x86/include/asm/svm.h |  4 ++++
>   arch/x86/kvm/svm/avic.c    | 42 ++++++++++++++++++++++++++------------
>   2 files changed, 33 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/x86/include/asm/svm.h b/arch/x86/include/asm/svm.h
> index 2b59b9951c90..2e9728cec242 100644
> --- a/arch/x86/include/asm/svm.h
> +++ b/arch/x86/include/asm/svm.h
> @@ -268,6 +268,7 @@ enum avic_ipi_failure_cause {
>   };
>   
>   #define AVIC_PHYSICAL_MAX_INDEX_MASK	GENMASK_ULL(8, 0)
> +#define AVIC_PHYSICAL_MAX_INDEX_4K_MASK	GENMASK_ULL(11, 0)
>   
>   /*
>    * For AVIC, the max index allowed for physical APIC ID table is 0xfe (254), as
> @@ -277,11 +278,14 @@ enum avic_ipi_failure_cause {
>   
>   /*
>    * For x2AVIC, the max index allowed for physical APIC ID table is 0x1ff (511).
> + * For extended x2AVIC, the max index allowed for physical APIC ID table is 0xfff (4095).
>    */
>   #define X2AVIC_MAX_PHYSICAL_ID		0x1FFUL
> +#define X2AVIC_MAX_PHYSICAL_ID_4K	0xFFFUL
>   
>   static_assert((AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == AVIC_MAX_PHYSICAL_ID);
>   static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_MAX_PHYSICAL_ID);
> +static_assert((X2AVIC_MAX_PHYSICAL_ID_4K & AVIC_PHYSICAL_MAX_INDEX_4K_MASK) == X2AVIC_MAX_PHYSICAL_ID_4K);
>   
>   #define AVIC_HPA_MASK	~((0xFFFULL << 52) | 0xFFF)
>   
> diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> index 4b74ea91f4e6..fe09e35dad42 100644
> --- a/arch/x86/kvm/svm/avic.c
> +++ b/arch/x86/kvm/svm/avic.c
> @@ -38,9 +38,9 @@
>    * size of the GATag is defined by hardware (32 bits), but is an opaque value
>    * as far as hardware is concerned.
>    */
> -#define AVIC_VCPU_ID_MASK		AVIC_PHYSICAL_MAX_INDEX_MASK
> +#define AVIC_VCPU_ID_MASK		AVIC_PHYSICAL_MAX_INDEX_4K_MASK
>   
> -#define AVIC_VM_ID_SHIFT		HWEIGHT32(AVIC_PHYSICAL_MAX_INDEX_MASK)
> +#define AVIC_VM_ID_SHIFT		HWEIGHT32(AVIC_PHYSICAL_MAX_INDEX_4K_MASK)
>   #define AVIC_VM_ID_MASK			(GENMASK(31, AVIC_VM_ID_SHIFT) >> AVIC_VM_ID_SHIFT)
>   
>   #define AVIC_GATAG_TO_VMID(x)		((x >> AVIC_VM_ID_SHIFT) & AVIC_VM_ID_MASK)
> @@ -73,6 +73,9 @@ static u32 next_vm_id = 0;
>   static bool next_vm_id_wrapped = 0;
>   static DEFINE_SPINLOCK(svm_vm_data_hash_lock);
>   bool x2avic_enabled;
> +static bool x2avic_4k_vcpu_supported;
> +static u64 x2avic_max_physical_id;
> +static u64 avic_physical_max_index_mask;
>   
>   /*
>    * This is a wrapper of struct amd_iommu_ir_data.
> @@ -87,7 +90,7 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
>   	struct vmcb *vmcb = svm->vmcb01.ptr;
>   
>   	vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK);
> -	vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK;
> +	vmcb->control.avic_physical_id &= ~avic_physical_max_index_mask;
>   
>   	vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
>   
> @@ -100,7 +103,7 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
>   	 */
>   	if (x2avic_enabled && apic_x2apic_mode(svm->vcpu.arch.apic)) {
>   		vmcb->control.int_ctl |= X2APIC_MODE_MASK;
> -		vmcb->control.avic_physical_id |= X2AVIC_MAX_PHYSICAL_ID;
> +		vmcb->control.avic_physical_id |= x2avic_max_physical_id;
>   		/* Disabling MSR intercept for x2APIC registers */
>   		svm_set_x2apic_msr_interception(svm, false);
>   	} else {
> @@ -122,7 +125,7 @@ static void avic_deactivate_vmcb(struct vcpu_svm *svm)
>   	struct vmcb *vmcb = svm->vmcb01.ptr;
>   
>   	vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK);
> -	vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK;
> +	vmcb->control.avic_physical_id &= ~avic_physical_max_index_mask;
>   
>   	/*
>   	 * If running nested and the guest uses its own MSR bitmap, there
> @@ -197,13 +200,15 @@ int avic_vm_init(struct kvm *kvm)
>   	struct kvm_svm *k2;
>   	struct page *p_page;
>   	struct page *l_page;
> -	u32 vm_id;
> +	u32 vm_id, entries;
>   
>   	if (!enable_apicv)
>   		return 0;
>   
> -	/* Allocating physical APIC ID table (4KB) */
> -	p_page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO);
> +	/* Allocating physical APIC ID table */
> +	entries = x2avic_max_physical_id + 1;
> +	p_page = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO,
> +			     get_order(sizeof(u64) * entries));
>   	if (!p_page)
>   		goto free_avic;
>   
> @@ -266,7 +271,7 @@ static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
>   	struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
>   
>   	if ((!x2avic_enabled && index > AVIC_MAX_PHYSICAL_ID) ||
> -	    (index > X2AVIC_MAX_PHYSICAL_ID))
> +	    (index > x2avic_max_physical_id))
>   		return NULL;
>   
>   	avic_physical_id_table = page_address(kvm_svm->avic_physical_id_table_page);
> @@ -281,7 +286,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
>   	struct vcpu_svm *svm = to_svm(vcpu);
>   
>   	if ((!x2avic_enabled && id > AVIC_MAX_PHYSICAL_ID) ||
> -	    (id > X2AVIC_MAX_PHYSICAL_ID))
> +	    (id > x2avic_max_physical_id))
>   		return -EINVAL;
>   
>   	if (!vcpu->arch.apic->regs)
> @@ -493,7 +498,7 @@ int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu)
>   	u32 icrh = svm->vmcb->control.exit_info_1 >> 32;
>   	u32 icrl = svm->vmcb->control.exit_info_1;
>   	u32 id = svm->vmcb->control.exit_info_2 >> 32;
> -	u32 index = svm->vmcb->control.exit_info_2 & 0x1FF;
> +	u32 index = svm->vmcb->control.exit_info_2 & avic_physical_max_index_mask;
>   	struct kvm_lapic *apic = vcpu->arch.apic;
>   
>   	trace_kvm_avic_incomplete_ipi(vcpu->vcpu_id, icrh, icrl, id, index);
> @@ -1212,8 +1217,19 @@ bool avic_hardware_setup(void)
>   
>   	/* AVIC is a prerequisite for x2AVIC. */
>   	x2avic_enabled = boot_cpu_has(X86_FEATURE_X2AVIC);
> -	if (x2avic_enabled)
> -		pr_info("x2AVIC enabled\n");
> +	if (x2avic_enabled) {
> +		x2avic_4k_vcpu_supported = !!(cpuid_ecx(0x8000000a) & 0x40);
> +		if (x2avic_4k_vcpu_supported) {
> +			x2avic_max_physical_id = X2AVIC_MAX_PHYSICAL_ID_4K;
> +			avic_physical_max_index_mask = AVIC_PHYSICAL_MAX_INDEX_4K_MASK;
> +		} else {
> +			x2avic_max_physical_id = X2AVIC_MAX_PHYSICAL_ID;
> +			avic_physical_max_index_mask = AVIC_PHYSICAL_MAX_INDEX_MASK;
> +		}
> +
> +		pr_info("x2AVIC enabled%s\n",
> +			x2avic_4k_vcpu_supported ? " (w/ 4K-vcpu)" : "");
> +	}
>   
>   	amd_iommu_register_ga_log_notifier(&avic_ga_log_notifier);
>   

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ