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
This commit is contained in:
John Baldwin
2022-11-18 10:04:11 -08:00
parent 3f0f4b1598
commit 58eefc67a1
2 changed files with 17 additions and 31 deletions
+17 -30
View File
@@ -527,36 +527,25 @@ vpid_free(int vpid)
free_unr(vpid_unr, vpid); free_unr(vpid_unr, vpid);
} }
static void static uint16_t
vpid_alloc(uint16_t *vpid, int num) vpid_alloc(int vcpuid)
{ {
int i, x; int x;
if (num <= 0 || num > VM_MAXCPU)
panic("invalid number of vpids requested: %d", num);
/* /*
* If the "enable vpid" execution control is not enabled then the * If the "enable vpid" execution control is not enabled then the
* VPID is required to be 0 for all vcpus. * VPID is required to be 0 for all vcpus.
*/ */
if ((procbased_ctls2 & PROCBASED2_ENABLE_VPID) == 0) { if ((procbased_ctls2 & PROCBASED2_ENABLE_VPID) == 0)
for (i = 0; i < num; i++) return (0);
vpid[i] = 0;
return;
}
/* /*
* 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);
x = alloc_unr(vpid_unr);
if (x == -1)
break;
else
vpid[i] = x;
}
if (i < num) { if (x == -1) {
atomic_add_int(&vpid_alloc_failed, 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 * It is still sub-optimal because the invvpid will invalidate
* combined mappings for a particular VPID across all EP4TAs. * combined mappings for a particular VPID across all EP4TAs.
*/ */
while (i-- > 0) return (vcpuid + 1);
vpid_free(vpid[i]);
for (i = 0; i < num; i++)
vpid[i] = i + 1;
} }
return (x);
} }
static void static void
@@ -1035,7 +1022,6 @@ vmx_init(struct vm *vm, pmap_t pmap)
{ {
int error; int error;
struct vmx *vmx; struct vmx *vmx;
uint16_t maxcpus = vm_get_maxcpus(vm);
vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO); vmx = malloc(sizeof(struct vmx), M_VMX, M_WAITOK | M_ZERO);
vmx->vm = vm; 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))) ((cap_rdpid || cap_rdtscp) && guest_msr_ro(vmx, MSR_TSC_AUX)))
panic("vmx_init: error setting guest msr access"); panic("vmx_init: error setting guest msr access");
vpid_alloc(vmx->vpids, maxcpus);
if (virtual_interrupt_delivery) { if (virtual_interrupt_delivery) {
error = vm_map_mmio(vm, DEFAULT_APIC_BASE, PAGE_SIZE, error = vm_map_mmio(vm, DEFAULT_APIC_BASE, PAGE_SIZE,
APIC_ACCESS_ADDRESS); APIC_ACCESS_ADDRESS);
@@ -1116,8 +1100,11 @@ vmx_vcpu_init(void *vmi, struct vcpu *vcpu1, int vcpuid)
struct vmcs *vmcs; struct vmcs *vmcs;
struct vmx_vcpu *vcpu; struct vmx_vcpu *vcpu;
uint32_t exc_bitmap; uint32_t exc_bitmap;
uint16_t vpid;
int error; int error;
vpid = vpid_alloc(vcpuid);
vcpu = malloc(sizeof(*vcpu), M_VMX, M_WAITOK | M_ZERO); vcpu = malloc(sizeof(*vcpu), M_VMX, M_WAITOK | M_ZERO);
vcpu->vmx = vmx; vcpu->vmx = vmx;
vcpu->vcpu = vcpu1; 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_EXIT_CTLS, exit_ctls);
error += vmwrite(VMCS_ENTRY_CTLS, entry_ctls); error += vmwrite(VMCS_ENTRY_CTLS, entry_ctls);
error += vmwrite(VMCS_MSR_BITMAP, vtophys(vmx->msr_bitmap)); 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) { if (guest_l1d_flush && !guest_l1d_flush_sw) {
vmcs_write(VMCS_ENTRY_MSR_LOAD, pmap_kextract( 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.nextrip = ~0;
vcpu->state.lastcpu = NOCPU; 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 * Set up the CR0/4 shadows, and init the read shadow
-1
View File
@@ -147,7 +147,6 @@ struct vmx {
uint64_t eptp; uint64_t eptp;
long eptgen[MAXCPU]; /* cached pmap->pm_eptgen */ long eptgen[MAXCPU]; /* cached pmap->pm_eptgen */
pmap_t pmap; pmap_t pmap;
uint16_t vpids[VM_MAXCPU];
}; };
extern bool vmx_have_msr_tsc_aux; extern bool vmx_have_msr_tsc_aux;