FreeBSD/sys/amd64/vmm/amd/vmcb.c
/*
 * Write to segment selector, control and general purpose register of VMCB.
 */
Write to segment selector, control and general purpose register of VMCB.
Write to segment selector control and general purpose register of VMCB .
int
vmcb_write(struct svm_softc *sc, int vcpu, int ident, uint64_t val)
{
	struct vmcb *vmcb;
	struct vmcb_state *state;
	struct vmcb_segment *seg;
	int err, dirtyseg;
	vmcb = svm_get_vmcb(sc, vcpu);
	state = &vmcb->state;
	dirtyseg = 0;
	err = 0;
	if (VMCB_ACCESS_OK(ident))
		return (vmcb_access(sc, vcpu, 1, ident, &val));
	switch (ident) {
	case VM_REG_GUEST_CR0:
		state->cr0 = val;
		svm_set_dirty(sc, vcpu, VMCB_CACHE_CR);
		break;
	case VM_REG_GUEST_CR2:
		state->cr2 = val;
		svm_set_dirty(sc, vcpu, VMCB_CACHE_CR2);
		break;
	case VM_REG_GUEST_CR3:
		state->cr3 = val;
		svm_set_dirty(sc, vcpu, VMCB_CACHE_CR);
		break;
	case VM_REG_GUEST_CR4:
		state->cr4 = val;
		svm_set_dirty(sc, vcpu, VMCB_CACHE_CR);
		break;
	case VM_REG_GUEST_DR7:
		state->dr7 = val;
		break;
	case VM_REG_GUEST_EFER:
		state->efer = val | EFER_SVM;
		svm_set_dirty(sc, vcpu, VMCB_CACHE_CR);
		break;
	case VM_REG_GUEST_RAX:
		state->rax = val;
		break;
	case VM_REG_GUEST_RFLAGS:
		state->rflags = val;
		break;
	case VM_REG_GUEST_RIP:
		state->rip = val;
		break;
	case VM_REG_GUEST_RSP:
		state->rsp = val;
		break;
	case VM_REG_GUEST_CS:
	case VM_REG_GUEST_DS:
	case VM_REG_GUEST_ES:
	case VM_REG_GUEST_SS:
		dirtyseg = 1;		
	case VM_REG_GUEST_FS:
	case VM_REG_GUEST_GS:
	case VM_REG_GUEST_LDTR:
	case VM_REG_GUEST_TR:
		seg = vmcb_segptr(vmcb, ident);
		KASSERT(seg != NULL, ("%s: unable to get segment %d from VMCB",
		    __func__, ident));
		seg->selector = val;
		if (dirtyseg)
			svm_set_dirty(sc, vcpu, VMCB_CACHE_SEG);
		break;
	case VM_REG_GUEST_GDTR:
	case VM_REG_GUEST_IDTR:
		err = EINVAL;
		break;
	default:
		err = EINVAL;
		break;
	}
	return (err);
}
int vmcb_write ( struct svm_softc * sc , int vcpu , int ident , uint64_t val ) { struct vmcb * vmcb ; struct vmcb_state * state ; struct vmcb_segment * seg ; int err , dirtyseg ; vmcb = svm_get_vmcb ( sc , vcpu ) ; state = & vmcb -> state ; dirtyseg = 0 ; err = 0 ; if ( VMCB_ACCESS_OK ( ident ) ) return ( vmcb_access ( sc , vcpu , 1 , ident , & val ) ) ; switch ( ident ) { case VM_REG_GUEST_CR0 : state -> cr0 = val ; svm_set_dirty ( sc , vcpu , VMCB_CACHE_CR ) ; break ; case VM_REG_GUEST_CR2 : state -> cr2 = val ; svm_set_dirty ( sc , vcpu , VMCB_CACHE_CR2 ) ; break ; case VM_REG_GUEST_CR3 : state -> cr3 = val ; svm_set_dirty ( sc , vcpu , VMCB_CACHE_CR ) ; break ; case VM_REG_GUEST_CR4 : state -> cr4 = val ; svm_set_dirty ( sc , vcpu , VMCB_CACHE_CR ) ; break ; case VM_REG_GUEST_DR7 : state -> dr7 = val ; break ; case VM_REG_GUEST_EFER : state -> efer = val | EFER_SVM ; svm_set_dirty ( sc , vcpu , VMCB_CACHE_CR ) ; break ; case VM_REG_GUEST_RAX : state -> rax = val ; break ; case VM_REG_GUEST_RFLAGS : state -> rflags = val ; break ; case VM_REG_GUEST_RIP : state -> rip = val ; break ; case VM_REG_GUEST_RSP : state -> rsp = val ; break ; case VM_REG_GUEST_CS : case VM_REG_GUEST_DS : case VM_REG_GUEST_ES : case VM_REG_GUEST_SS : dirtyseg = 1 ; case VM_REG_GUEST_FS : case VM_REG_GUEST_GS : case VM_REG_GUEST_LDTR : case VM_REG_GUEST_TR : seg = vmcb_segptr ( vmcb , ident ) ; KASSERT ( seg != NULL , ( " " , __func__ , ident ) ) ; seg -> selector = val ; if ( dirtyseg ) svm_set_dirty ( sc , vcpu , VMCB_CACHE_SEG ) ; break ; case VM_REG_GUEST_GDTR : case VM_REG_GUEST_IDTR : err = EINVAL ; break ; default : err = EINVAL ; break ; } return ( err ) ; }
Write to segment selector, control and general purpose register of VMCB.
Write to segment selector control and general purpose register of VMCB .
/* EFER_SVM must always be set when the guest is executing */ /* FALLTHROUGH */ /* GDTR and IDTR don't have segment selectors */