* Invalidate guest mappings identified by its vpid from the TLB. */
| 1238 | * Invalidate guest mappings identified by its vpid from the TLB. |
| 1239 | */ |
| 1240 | static __inline void |
| 1241 | vmx_invvpid(struct vmx *vmx, int vcpu, pmap_t pmap, int running) |
| 1242 | { |
| 1243 | struct vmxstate *vmxstate; |
| 1244 | struct invvpid_desc invvpid_desc; |
| 1245 | |
| 1246 | vmxstate = &vmx->state[vcpu]; |
| 1247 | if (vmxstate->vpid == 0) |
| 1248 | return; |
| 1249 | |
| 1250 | if (!running) { |
| 1251 | /* |
| 1252 | * Set the 'lastcpu' to an invalid host cpu. |
| 1253 | * |
| 1254 | * This will invalidate TLB entries tagged with the vcpu's |
| 1255 | * vpid the next time it runs via vmx_set_pcpu_defaults(). |
| 1256 | */ |
| 1257 | vmxstate->lastcpu = NOCPU; |
| 1258 | return; |
| 1259 | } |
| 1260 | |
| 1261 | KASSERT(curthread->td_critnest > 0, ("%s: vcpu %d running outside " |
| 1262 | "critical section", __func__, vcpu)); |
| 1263 | |
| 1264 | /* |
| 1265 | * Invalidate all mappings tagged with 'vpid' |
| 1266 | * |
| 1267 | * We do this because this vcpu was executing on a different host |
| 1268 | * cpu when it last ran. We do not track whether it invalidated |
| 1269 | * mappings associated with its 'vpid' during that run. So we must |
| 1270 | * assume that the mappings associated with 'vpid' on 'curcpu' are |
| 1271 | * stale and invalidate them. |
| 1272 | * |
| 1273 | * Note that we incur this penalty only when the scheduler chooses to |
| 1274 | * move the thread associated with this vcpu between host cpus. |
| 1275 | * |
| 1276 | * Note also that this will invalidate mappings tagged with 'vpid' |
| 1277 | * for "all" EP4TAs. |
| 1278 | */ |
| 1279 | if (atomic_load_long(&pmap->pm_eptgen) == vmx->eptgen[curcpu]) { |
| 1280 | invvpid_desc._res1 = 0; |
| 1281 | invvpid_desc._res2 = 0; |
| 1282 | invvpid_desc.vpid = vmxstate->vpid; |
| 1283 | invvpid_desc.linear_addr = 0; |
| 1284 | invvpid(INVVPID_TYPE_SINGLE_CONTEXT, invvpid_desc); |
| 1285 | vmm_stat_incr(vmx->vm, vcpu, VCPU_INVVPID_DONE, 1); |
| 1286 | } else { |
| 1287 | /* |
| 1288 | * The invvpid can be skipped if an invept is going to |
| 1289 | * be performed before entering the guest. The invept |
| 1290 | * will invalidate combined mappings tagged with |
| 1291 | * 'vmx->eptp' for all vpids. |
| 1292 | */ |
| 1293 | vmm_stat_incr(vmx->vm, vcpu, VCPU_INVVPID_SAVED, 1); |
| 1294 | } |
| 1295 | } |
| 1296 | |
| 1297 | static void |
no test coverage detected