| 3355 | } |
| 3356 | |
| 3357 | static int |
| 3358 | vmx_setreg(void *arg, int vcpu, int reg, uint64_t val) |
| 3359 | { |
| 3360 | int error, hostcpu, running, shadow; |
| 3361 | uint64_t ctls; |
| 3362 | pmap_t pmap; |
| 3363 | struct vmx *vmx = arg; |
| 3364 | |
| 3365 | running = vcpu_is_running(vmx->vm, vcpu, &hostcpu); |
| 3366 | if (running && hostcpu != curcpu) |
| 3367 | panic("vmx_setreg: %s%d is running", vm_name(vmx->vm), vcpu); |
| 3368 | |
| 3369 | if (reg == VM_REG_GUEST_INTR_SHADOW) |
| 3370 | return (vmx_modify_intr_shadow(vmx, vcpu, running, val)); |
| 3371 | |
| 3372 | if (vmxctx_setreg(&vmx->ctx[vcpu], reg, val) == 0) |
| 3373 | return (0); |
| 3374 | |
| 3375 | /* Do not permit user write access to VMCS fields by offset. */ |
| 3376 | if (reg < 0) |
| 3377 | return (EINVAL); |
| 3378 | |
| 3379 | error = vmcs_setreg(&vmx->vmcs[vcpu], running, reg, val); |
| 3380 | |
| 3381 | if (error == 0) { |
| 3382 | /* |
| 3383 | * If the "load EFER" VM-entry control is 1 then the |
| 3384 | * value of EFER.LMA must be identical to "IA-32e mode guest" |
| 3385 | * bit in the VM-entry control. |
| 3386 | */ |
| 3387 | if ((entry_ctls & VM_ENTRY_LOAD_EFER) != 0 && |
| 3388 | (reg == VM_REG_GUEST_EFER)) { |
| 3389 | vmcs_getreg(&vmx->vmcs[vcpu], running, |
| 3390 | VMCS_IDENT(VMCS_ENTRY_CTLS), &ctls); |
| 3391 | if (val & EFER_LMA) |
| 3392 | ctls |= VM_ENTRY_GUEST_LMA; |
| 3393 | else |
| 3394 | ctls &= ~VM_ENTRY_GUEST_LMA; |
| 3395 | vmcs_setreg(&vmx->vmcs[vcpu], running, |
| 3396 | VMCS_IDENT(VMCS_ENTRY_CTLS), ctls); |
| 3397 | } |
| 3398 | |
| 3399 | shadow = vmx_shadow_reg(reg); |
| 3400 | if (shadow > 0) { |
| 3401 | /* |
| 3402 | * Store the unmodified value in the shadow |
| 3403 | */ |
| 3404 | error = vmcs_setreg(&vmx->vmcs[vcpu], running, |
| 3405 | VMCS_IDENT(shadow), val); |
| 3406 | } |
| 3407 | |
| 3408 | if (reg == VM_REG_GUEST_CR3) { |
| 3409 | /* |
| 3410 | * Invalidate the guest vcpu's TLB mappings to emulate |
| 3411 | * the behavior of updating %cr3. |
| 3412 | * |
| 3413 | * XXX the processor retains global mappings when %cr3 |
| 3414 | * is updated but vmx_invvpid() does not. |
nothing calls this directly
no test coverage detected