Re: git: 58eefc67a1cf - main - vmm vmx: Allocate vpids on demand as each vCPU is initialized.

From: FreeBSD User <freebsd_at_walstatt-de.de>
Date: Fri, 18 Nov 2022 19:25:07 UTC
Am Fri, 18 Nov 2022 18:26:49 GMT
John Baldwin <jhb@FreeBSD.org> schrieb:

> The branch main has been updated by jhb:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=58eefc67a1cf16623c23354efd089f65401c0455
> 
> commit 58eefc67a1cf16623c23354efd089f65401c0455
> Author:     John Baldwin <jhb@FreeBSD.org>
> AuthorDate: 2022-11-18 18:04:11 +0000
> Commit:     John Baldwin <jhb@FreeBSD.org>
> CommitDate: 2022-11-18 18:25:38 +0000
> 
>     vmm vmx: Allocate vpids on demand as each vCPU is initialized.
>     
>     Compared to the previous version this does mean that if the system as
>     a whole runs out of dedicated vPIDs you might end up with some vCPUs
>     within a single VM using dedicated vPIDs and others using shared
>     vPIDs, but this should not break anything.
>     
>     Reviewed by:    corvink, markj
>     Differential Revision:  https://reviews.freebsd.org/D37169
> ---
>  sys/amd64/vmm/intel/vmx.c | 47 +++++++++++++++++------------------------------
>  sys/amd64/vmm/intel/vmx.h |  1 -
>  2 files changed, 17 insertions(+), 31 deletions(-)
> 
> diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
> index 9db638fd858e..52573416ded7 100644
> --- a/sys/amd64/vmm/intel/vmx.c
> +++ b/sys/amd64/vmm/intel/vmx.c
> @@ -527,36 +527,25 @@ vpid_free(int vpid)
>  		free_unr(vpid_unr, vpid);
>  }
>  
> -static void
> -vpid_alloc(uint16_t *vpid, int num)
> +static uint16_t
> +vpid_alloc(int vcpuid)
>  {
> -	int i, x;
> -
> -	if (num <= 0 || num > VM_MAXCPU)
> -		panic("invalid number of vpids requested: %d", num);
> +	int x;
>  
>  	/*
>  	 * If the "enable vpid" execution control is not enabled then the
>  	 * VPID is required to be 0 for all vcpus.
>  	 */
> -	if ((procbased_ctls2 & PROCBASED2_ENABLE_VPID) == 0) {
> -		for (i = 0; i < num; i++)
> -			vpid[i] = 0;
> -		return;
> -	}
> +	if ((procbased_ctls2 & PROCBASED2_ENABLE_VPID) == 0)
> +		return (0);
>  
>  	/*
> -	 * Allocate a unique VPID for each vcpu from the unit number allocator.
> +	 * Try to allocate a unique VPID for each from the unit number
> +	 * allocator.
>  	 */
> -	for (i = 0; i < num; i++) {
> -		x = alloc_unr(vpid_unr);
> -		if (x == -1)
> -			break;
> -		else
> -			vpid[i] = x;
> -	}
> +	x = alloc_unr(vpid_unr);
>  
> -	if (i < num) {
> +	if (x == -1) {
>  		atomic_add_int(&vpid_alloc_failed, 1);
>  
>  		/*
> @@ -570,12 +559,10 @@ vpid_alloc(uint16_t *vpid, int num)
>  		 * It is still sub-optimal because the invvpid will invalidate
>  		 * combined mappings for a particular VPID across all EP4TAs.
>  		 */
> -		while (i-- > 0)
> -			vpid_free(vpid[i]);
> -
> -		for (i = 0; i < num; i++)
> -			vpid[i] = i + 1;
> +		return (vcpuid + 1);
>  	}
> +
> +	return (x);
>  }
>  
>  static void
> @@ -1035,7 +1022,6 @@ vmx_init(struct vm *vm, pmap_t pmap)
>  {
>  	int error;
>  	struct vmx *vmx;
> -	uint16_t maxcpus = vm_get_maxcpus(vm);
>  
>  	vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO);
>  	vmx->vm = vm;
> @@ -1096,8 +1082,6 @@ vmx_init(struct vm *vm, pmap_t pmap)
>  	    ((cap_rdpid || cap_rdtscp) && guest_msr_ro(vmx, MSR_TSC_AUX)))
>  		panic("vmx_init: error setting guest msr access");
>  
> -	vpid_alloc(vmx->vpids, maxcpus);
> -
>  	if (virtual_interrupt_delivery) {
>  		error = vm_map_mmio(vm, DEFAULT_APIC_BASE, PAGE_SIZE,
>  		    APIC_ACCESS_ADDRESS);
> @@ -1116,8 +1100,11 @@ vmx_vcpu_init(void *vmi, struct vcpu *vcpu1, int vcpuid)
>  	struct vmcs *vmcs;
>  	struct vmx_vcpu *vcpu;
>  	uint32_t exc_bitmap;
> +	uint16_t vpid;
>  	int error;
>  
> +	vpid = vpid_alloc(vcpuid);
> +
>  	vcpu = malloc(sizeof(*vcpu), M_VMX, M_WAITOK | M_ZERO);
>  	vcpu->vmx = vmx;
>  	vcpu->vcpu = vcpu1;
> @@ -1156,7 +1143,7 @@ vmx_vcpu_init(void *vmi, struct vcpu *vcpu1, int vcpuid)
>  	error += vmwrite(VMCS_EXIT_CTLS, exit_ctls);
>  	error += vmwrite(VMCS_ENTRY_CTLS, entry_ctls);
>  	error += vmwrite(VMCS_MSR_BITMAP, vtophys(vmx->msr_bitmap));
> -	error += vmwrite(VMCS_VPID, vmx->vpids[vcpuid]);
> +	error += vmwrite(VMCS_VPID, vpid);
>  
>  	if (guest_l1d_flush && !guest_l1d_flush_sw) {
>  		vmcs_write(VMCS_ENTRY_MSR_LOAD, pmap_kextract(
> @@ -1204,7 +1191,7 @@ vmx_vcpu_init(void *vmi, struct vcpu *vcpu1, int vcpuid)
>  
>  	vcpu->state.nextrip = ~0;
>  	vcpu->state.lastcpu = NOCPU;
> -	vcpu->state.vpid = vmx->vpids[vcpuid];
> +	vcpu->state.vpid = vpid;
>  
>  	/*
>  	 * Set up the CR0/4 shadows, and init the read shadow
> diff --git a/sys/amd64/vmm/intel/vmx.h b/sys/amd64/vmm/intel/vmx.h
> index e91675b62800..ad172073b03f 100644
> --- a/sys/amd64/vmm/intel/vmx.h
> +++ b/sys/amd64/vmm/intel/vmx.h
> @@ -147,7 +147,6 @@ struct vmx {
>  	uint64_t	eptp;
>  	long		eptgen[MAXCPU];		/* cached pmap->pm_eptgen */
>  	pmap_t		pmap;
> -	uint16_t	vpids[VM_MAXCPU];
>  };
>  
>  extern bool vmx_have_msr_tsc_aux;
> 

Buildworld bails out on vmx.c:

[...]
/usr/src/sys/amd64/vmm/intel/vmx.c:1023:6: error: variable 'error' set but not used
[-Werror,-Wunused-but-set-variable] int error;

-- 
O. Hartmann