The branch stable/13 has been updated by jhb:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=20406b29b3ecd14e650ee85291d3977f3bd28432

commit 20406b29b3ecd14e650ee85291d3977f3bd28432
Author:     John Baldwin <[email protected]>
AuthorDate: 2022-11-18 18:04:11 +0000
Commit:     John Baldwin <[email protected]>
CommitDate: 2023-01-26 22:04:30 +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
    
    (cherry picked from commit 58eefc67a1cf16623c23354efd089f65401c0455)
---
 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;

Reply via email to