Module Name:    src
Committed By:   maxv
Date:           Tue Jan  8 14:43:18 UTC 2019

Modified Files:
        src/sys/dev/nvmm/x86: nvmm_x86_svm.c

Log Message:
Optimize: don't keep a full copy of the guest state, rather take only what
is needed. This avoids expensive memcpy's.

Also flush the V_TPR as part of the CR-state, because there is CR8 in it.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/nvmm/x86/nvmm_x86_svm.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/nvmm/x86/nvmm_x86_svm.c
diff -u src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.12 src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.13
--- src/sys/dev/nvmm/x86/nvmm_x86_svm.c:1.12	Mon Jan  7 14:08:02 2019
+++ src/sys/dev/nvmm/x86/nvmm_x86_svm.c	Tue Jan  8 14:43:18 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: nvmm_x86_svm.c,v 1.12 2019/01/07 14:08:02 maxv Exp $	*/
+/*	$NetBSD: nvmm_x86_svm.c,v 1.13 2019/01/08 14:43:18 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.12 2019/01/07 14:08:02 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nvmm_x86_svm.c,v 1.13 2019/01/08 14:43:18 maxv Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -499,9 +499,6 @@ static const size_t svm_conf_sizes[NVMM_
 };
 
 struct svm_cpudata {
-	/* x64-specific */
-	struct nvmm_x64_state state;
-
 	/* General */
 	bool shared_asid;
 	bool tlb_want_flush;
@@ -519,7 +516,7 @@ struct svm_cpudata {
 	paddr_t msrbm_pa;
 
 	/* Host state */
-	uint64_t xcr0;
+	uint64_t hxcr0;
 	uint64_t star;
 	uint64_t lstar;
 	uint64_t cstar;
@@ -533,6 +530,9 @@ struct svm_cpudata {
 	bool nmi_window_exit;
 
 	/* Guest state */
+	uint64_t gxcr0;
+	uint64_t gprs[NVMM_X64_NGPR];
+	uint64_t drs[NVMM_X64_NDR];
 	uint64_t tsc_offset;
 	struct xsave_header gfpu __aligned(16);
 };
@@ -564,7 +564,8 @@ svm_vmcb_cache_update(struct vmcb *vmcb,
 	}
 	if (flags & NVMM_X64_STATE_CRS) {
 		vmcb->ctrl.vmcb_clean &=
-		    ~(VMCB_CTRL_VMCB_CLEAN_CR | VMCB_CTRL_VMCB_CLEAN_CR2);
+		    ~(VMCB_CTRL_VMCB_CLEAN_CR | VMCB_CTRL_VMCB_CLEAN_CR2 |
+		      VMCB_CTRL_VMCB_CLEAN_TPR);
 	}
 	if (flags & NVMM_X64_STATE_DRS) {
 		vmcb->ctrl.vmcb_clean &= ~VMCB_CTRL_VMCB_CLEAN_DR;
@@ -755,12 +756,11 @@ static void
 svm_inkernel_handle_cpuid(struct nvmm_cpu *vcpu, uint64_t eax, uint64_t ecx)
 {
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *state = &cpudata->state;
 
 	switch (eax) {
 	case 0x00000001: /* APIC number in RBX. The rest is tunable. */
-		state->gprs[NVMM_X64_GPR_RBX] &= ~CPUID_LOCAL_APIC_ID;
-		state->gprs[NVMM_X64_GPR_RBX] |= __SHIFTIN(vcpu->cpuid,
+		cpudata->gprs[NVMM_X64_GPR_RBX] &= ~CPUID_LOCAL_APIC_ID;
+		cpudata->gprs[NVMM_X64_GPR_RBX] |= __SHIFTIN(vcpu->cpuid,
 		    CPUID_LOCAL_APIC_ID);
 		break;
 	case 0x0000000D: /* FPU description. Not tunable. */
@@ -768,22 +768,22 @@ svm_inkernel_handle_cpuid(struct nvmm_cp
 			break;
 		}
 		cpudata->vmcb->state.rax = svm_xcr0_mask & 0xFFFFFFFF;
-		if (state->crs[NVMM_X64_CR_XCR0] & XCR0_SSE) {
-			state->gprs[NVMM_X64_GPR_RBX] = sizeof(struct fxsave);
+		if (cpudata->gxcr0 & XCR0_SSE) {
+			cpudata->gprs[NVMM_X64_GPR_RBX] = sizeof(struct fxsave);
 		} else {
-			state->gprs[NVMM_X64_GPR_RBX] = sizeof(struct save87);
+			cpudata->gprs[NVMM_X64_GPR_RBX] = sizeof(struct save87);
 		}
-		state->gprs[NVMM_X64_GPR_RBX] += 64; /* XSAVE header */
-		state->gprs[NVMM_X64_GPR_RCX] = sizeof(struct fxsave);
-		state->gprs[NVMM_X64_GPR_RDX] = svm_xcr0_mask >> 32;
+		cpudata->gprs[NVMM_X64_GPR_RBX] += 64; /* XSAVE header */
+		cpudata->gprs[NVMM_X64_GPR_RCX] = sizeof(struct fxsave);
+		cpudata->gprs[NVMM_X64_GPR_RDX] = svm_xcr0_mask >> 32;
 		break;
 	case 0x40000000:
-		memcpy(&state->gprs[NVMM_X64_GPR_RBX], "___ ", 4);
-		memcpy(&state->gprs[NVMM_X64_GPR_RCX], "NVMM", 4);
-		memcpy(&state->gprs[NVMM_X64_GPR_RDX], " ___", 4);
+		memcpy(&cpudata->gprs[NVMM_X64_GPR_RBX], "___ ", 4);
+		memcpy(&cpudata->gprs[NVMM_X64_GPR_RCX], "NVMM", 4);
+		memcpy(&cpudata->gprs[NVMM_X64_GPR_RDX], " ___", 4);
 		break;
 	case 0x80000001: /* No SVM in ECX. The rest is tunable. */
-		state->gprs[NVMM_X64_GPR_RCX] &= ~CPUID_SVM;
+		cpudata->gprs[NVMM_X64_GPR_RCX] &= ~CPUID_SVM;
 		break;
 	default:
 		break;
@@ -796,20 +796,19 @@ svm_exit_cpuid(struct nvmm_machine *mach
 {
 	struct svm_machdata *machdata = mach->machdata;
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *state = &cpudata->state;
 	struct nvmm_x86_conf_cpuid *cpuid;
 	uint64_t eax, ecx;
 	u_int descs[4];
 	size_t i;
 
 	eax = cpudata->vmcb->state.rax;
-	ecx = state->gprs[NVMM_X64_GPR_RCX];
+	ecx = cpudata->gprs[NVMM_X64_GPR_RCX];
 	x86_cpuid2(eax, ecx, descs);
 
 	cpudata->vmcb->state.rax = descs[0];
-	state->gprs[NVMM_X64_GPR_RBX] = descs[1];
-	state->gprs[NVMM_X64_GPR_RCX] = descs[2];
-	state->gprs[NVMM_X64_GPR_RDX] = descs[3];
+	cpudata->gprs[NVMM_X64_GPR_RBX] = descs[1];
+	cpudata->gprs[NVMM_X64_GPR_RCX] = descs[2];
+	cpudata->gprs[NVMM_X64_GPR_RDX] = descs[3];
 
 	for (i = 0; i < SVM_NCPUIDS; i++) {
 		cpuid = &machdata->cpuid[i];
@@ -822,15 +821,15 @@ svm_exit_cpuid(struct nvmm_machine *mach
 
 		/* del */
 		cpudata->vmcb->state.rax &= ~cpuid->del.eax;
-		state->gprs[NVMM_X64_GPR_RBX] &= ~cpuid->del.ebx;
-		state->gprs[NVMM_X64_GPR_RCX] &= ~cpuid->del.ecx;
-		state->gprs[NVMM_X64_GPR_RDX] &= ~cpuid->del.edx;
+		cpudata->gprs[NVMM_X64_GPR_RBX] &= ~cpuid->del.ebx;
+		cpudata->gprs[NVMM_X64_GPR_RCX] &= ~cpuid->del.ecx;
+		cpudata->gprs[NVMM_X64_GPR_RDX] &= ~cpuid->del.edx;
 
 		/* set */
 		cpudata->vmcb->state.rax |= cpuid->set.eax;
-		state->gprs[NVMM_X64_GPR_RBX] |= cpuid->set.ebx;
-		state->gprs[NVMM_X64_GPR_RCX] |= cpuid->set.ecx;
-		state->gprs[NVMM_X64_GPR_RDX] |= cpuid->set.edx;
+		cpudata->gprs[NVMM_X64_GPR_RBX] |= cpuid->set.ebx;
+		cpudata->gprs[NVMM_X64_GPR_RCX] |= cpuid->set.ecx;
+		cpudata->gprs[NVMM_X64_GPR_RDX] |= cpuid->set.edx;
 
 		break;
 	}
@@ -936,7 +935,6 @@ svm_inkernel_handle_msr(struct nvmm_mach
     struct nvmm_exit *exit)
 {
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *state = &cpudata->state;
 	uint64_t val;
 	size_t i;
 
@@ -945,13 +943,13 @@ svm_inkernel_handle_msr(struct nvmm_mach
 		if (exit->u.msr.msr == MSR_CR_PAT) {
 			val = cpudata->vmcb->state.g_pat;
 			cpudata->vmcb->state.rax = (val & 0xFFFFFFFF);
-			state->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
+			cpudata->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
 			goto handled;
 		}
 		if (exit->u.msr.msr == MSR_NB_CFG) {
 			val = NB_CFG_INITAPICCPUIDLO;
 			cpudata->vmcb->state.rax = (val & 0xFFFFFFFF);
-			state->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
+			cpudata->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
 			goto handled;
 		}
 		for (i = 0; i < __arraycount(msr_ignore_list); i++) {
@@ -959,7 +957,7 @@ svm_inkernel_handle_msr(struct nvmm_mach
 				continue;
 			val = 0;
 			cpudata->vmcb->state.rax = (val & 0xFFFFFFFF);
-			state->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
+			cpudata->gprs[NVMM_X64_GPR_RDX] = (val >> 32);
 			goto handled;
 		}
 		break;
@@ -1000,7 +998,6 @@ svm_exit_msr(struct nvmm_machine *mach, 
     struct nvmm_exit *exit)
 {
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *state = &cpudata->state;
 	uint64_t info = cpudata->vmcb->ctrl.exitinfo1;
 
 	if (info == 0) {
@@ -1009,11 +1006,11 @@ svm_exit_msr(struct nvmm_machine *mach, 
 		exit->u.msr.type = NVMM_EXIT_MSR_WRMSR;
 	}
 
-	exit->u.msr.msr = state->gprs[NVMM_X64_GPR_RCX];
+	exit->u.msr.msr = cpudata->gprs[NVMM_X64_GPR_RCX];
 
 	if (info == 1) {
 		uint64_t rdx, rax;
-		rdx = state->gprs[NVMM_X64_GPR_RDX];
+		rdx = cpudata->gprs[NVMM_X64_GPR_RDX];
 		rax = cpudata->vmcb->state.rax;
 		exit->u.msr.val = (rdx << 32) | (rax & 0xFFFFFFFF);
 	} else {
@@ -1062,16 +1059,15 @@ svm_exit_xsetbv(struct nvmm_machine *mac
     struct nvmm_exit *exit)
 {
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *state = &cpudata->state;
 	struct vmcb *vmcb = cpudata->vmcb;
 	uint64_t val;
 
 	exit->reason = NVMM_EXIT_NONE;
 
-	val = (state->gprs[NVMM_X64_GPR_RDX] << 32) |
+	val = (cpudata->gprs[NVMM_X64_GPR_RDX] << 32) |
 	    (vmcb->state.rax & 0xFFFFFFFF);
 
-	if (__predict_false(state->gprs[NVMM_X64_GPR_RCX] != 0)) {
+	if (__predict_false(cpudata->gprs[NVMM_X64_GPR_RCX] != 0)) {
 		goto error;
 	} else if (__predict_false(vmcb->state.cpl != 0)) {
 		goto error;
@@ -1081,7 +1077,7 @@ svm_exit_xsetbv(struct nvmm_machine *mac
 		goto error;
 	}
 
-	state->crs[NVMM_X64_CR_XCR0] = val;
+	cpudata->gxcr0 = val;
 
 	cpudata->vmcb->state.rip = cpudata->vmcb->ctrl.nrip;
 	return;
@@ -1096,8 +1092,8 @@ svm_vcpu_guest_fpu_enter(struct nvmm_cpu
 	struct svm_cpudata *cpudata = vcpu->cpudata;
 
 	if (x86_xsave_features != 0) {
-		cpudata->xcr0 = rdxcr(0);
-		wrxcr(0, cpudata->state.crs[NVMM_X64_CR_XCR0]);
+		cpudata->hxcr0 = rdxcr(0);
+		wrxcr(0, cpudata->gxcr0);
 	}
 
 	cpudata->ts_set = (rcr0() & CR0_TS) != 0;
@@ -1119,8 +1115,8 @@ svm_vcpu_guest_fpu_leave(struct nvmm_cpu
 	}
 
 	if (x86_xsave_features != 0) {
-		cpudata->state.crs[NVMM_X64_CR_XCR0] = rdxcr(0);
-		wrxcr(0, cpudata->xcr0);
+		cpudata->gxcr0 = rdxcr(0);
+		wrxcr(0, cpudata->hxcr0);
 	}
 }
 
@@ -1128,26 +1124,24 @@ static void
 svm_vcpu_guest_dbregs_enter(struct nvmm_cpu *vcpu)
 {
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *state = &cpudata->state;
 
 	x86_dbregs_save(curlwp);
 
-	ldr0(state->drs[NVMM_X64_DR_DR0]);
-	ldr1(state->drs[NVMM_X64_DR_DR1]);
-	ldr2(state->drs[NVMM_X64_DR_DR2]);
-	ldr3(state->drs[NVMM_X64_DR_DR3]);
+	ldr0(cpudata->drs[NVMM_X64_DR_DR0]);
+	ldr1(cpudata->drs[NVMM_X64_DR_DR1]);
+	ldr2(cpudata->drs[NVMM_X64_DR_DR2]);
+	ldr3(cpudata->drs[NVMM_X64_DR_DR3]);
 }
 
 static void
 svm_vcpu_guest_dbregs_leave(struct nvmm_cpu *vcpu)
 {
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *state = &cpudata->state;
 
-	state->drs[NVMM_X64_DR_DR0] = rdr0();
-	state->drs[NVMM_X64_DR_DR1] = rdr1();
-	state->drs[NVMM_X64_DR_DR2] = rdr2();
-	state->drs[NVMM_X64_DR_DR3] = rdr3();
+	cpudata->drs[NVMM_X64_DR_DR0] = rdr0();
+	cpudata->drs[NVMM_X64_DR_DR1] = rdr1();
+	cpudata->drs[NVMM_X64_DR_DR2] = rdr2();
+	cpudata->drs[NVMM_X64_DR_DR3] = rdr3();
 
 	x86_dbregs_restore(curlwp);
 }
@@ -1216,7 +1210,7 @@ svm_vcpu_run(struct nvmm_machine *mach, 
 	while (1) {
 		s = splhigh();
 		svm_vcpu_guest_fpu_enter(vcpu);
-		svm_vmrun(cpudata->vmcb_pa, cpudata->state.gprs);
+		svm_vmrun(cpudata->vmcb_pa, cpudata->gprs);
 		svm_vcpu_guest_fpu_leave(vcpu);
 		splx(s);
 
@@ -1703,28 +1697,27 @@ svm_vcpu_getstate_seg(struct nvmm_x64_st
 	seg->base = vseg->base;
 }
 
-static bool
-svm_state_tlb_flush(struct nvmm_x64_state *cstate,
-    struct nvmm_x64_state *nstate, uint64_t flags)
+static inline bool
+svm_state_tlb_flush(struct vmcb *vmcb, struct nvmm_x64_state *state,
+    uint64_t flags)
 {
 	if (flags & NVMM_X64_STATE_CRS) {
-		if ((cstate->crs[NVMM_X64_CR_CR0] ^
-		     nstate->crs[NVMM_X64_CR_CR0]) & CR0_TLB_FLUSH) {
+		if ((vmcb->state.cr0 ^
+		     state->crs[NVMM_X64_CR_CR0]) & CR0_TLB_FLUSH) {
 			return true;
 		}
-		if (cstate->crs[NVMM_X64_CR_CR3] !=
-		    nstate->crs[NVMM_X64_CR_CR3]) {
+		if (vmcb->state.cr3 != state->crs[NVMM_X64_CR_CR3]) {
 			return true;
 		}
-		if ((cstate->crs[NVMM_X64_CR_CR4] ^
-		     nstate->crs[NVMM_X64_CR_CR4]) & CR4_TLB_FLUSH) {
+		if ((vmcb->state.cr4 ^
+		     state->crs[NVMM_X64_CR_CR4]) & CR4_TLB_FLUSH) {
 			return true;
 		}
 	}
 
 	if (flags & NVMM_X64_STATE_MSRS) {
-		if ((cstate->msrs[NVMM_X64_MSR_EFER] ^
-		     nstate->msrs[NVMM_X64_MSR_EFER]) & EFER_TLB_FLUSH) {
+		if ((vmcb->state.efer ^
+		     state->msrs[NVMM_X64_MSR_EFER]) & EFER_TLB_FLUSH) {
 			return true;
 		}
 	}
@@ -1735,130 +1728,121 @@ svm_state_tlb_flush(struct nvmm_x64_stat
 static void
 svm_vcpu_setstate(struct nvmm_cpu *vcpu, void *data, uint64_t flags)
 {
+	struct nvmm_x64_state *state = (struct nvmm_x64_state *)data;
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *cstate = &cpudata->state;
-	struct nvmm_x64_state *nstate = (struct nvmm_x64_state *)data;
 	struct vmcb *vmcb = cpudata->vmcb;
 	struct fxsave *fpustate;
 
-	if (svm_state_tlb_flush(cstate, nstate, flags)) {
+	if (svm_state_tlb_flush(vmcb, state, flags)) {
 		cpudata->tlb_want_flush = true;
 	}
 
 	if (flags & NVMM_X64_STATE_SEGS) {
-		memcpy(cstate->segs, nstate->segs, sizeof(nstate->segs));
-
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_CS],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_CS],
 		    &vmcb->state.cs);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_DS],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_DS],
 		    &vmcb->state.ds);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_ES],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_ES],
 		    &vmcb->state.es);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_FS],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_FS],
 		    &vmcb->state.fs);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_GS],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_GS],
 		    &vmcb->state.gs);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_SS],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_SS],
 		    &vmcb->state.ss);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_GDT],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_GDT],
 		    &vmcb->state.gdt);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_IDT],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_IDT],
 		    &vmcb->state.idt);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_LDT],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_LDT],
 		    &vmcb->state.ldt);
-		svm_vcpu_setstate_seg(&cstate->segs[NVMM_X64_SEG_TR],
+		svm_vcpu_setstate_seg(&state->segs[NVMM_X64_SEG_TR],
 		    &vmcb->state.tr);
 	}
 
+	CTASSERT(sizeof(cpudata->gprs) == sizeof(state->gprs));
 	if (flags & NVMM_X64_STATE_GPRS) {
-		memcpy(cstate->gprs, nstate->gprs, sizeof(nstate->gprs));
+		memcpy(cpudata->gprs, state->gprs, sizeof(state->gprs));
 
-		vmcb->state.rip = cstate->gprs[NVMM_X64_GPR_RIP];
-		vmcb->state.rsp = cstate->gprs[NVMM_X64_GPR_RSP];
-		vmcb->state.rax = cstate->gprs[NVMM_X64_GPR_RAX];
-		vmcb->state.rflags = cstate->gprs[NVMM_X64_GPR_RFLAGS];
+		vmcb->state.rip = state->gprs[NVMM_X64_GPR_RIP];
+		vmcb->state.rsp = state->gprs[NVMM_X64_GPR_RSP];
+		vmcb->state.rax = state->gprs[NVMM_X64_GPR_RAX];
+		vmcb->state.rflags = state->gprs[NVMM_X64_GPR_RFLAGS];
 	}
 
 	if (flags & NVMM_X64_STATE_CRS) {
-		memcpy(cstate->crs, nstate->crs, sizeof(nstate->crs));
-
-		vmcb->state.cr0 = cstate->crs[NVMM_X64_CR_CR0];
-		vmcb->state.cr2 = cstate->crs[NVMM_X64_CR_CR2];
-		vmcb->state.cr3 = cstate->crs[NVMM_X64_CR_CR3];
-		vmcb->state.cr4 = cstate->crs[NVMM_X64_CR_CR4];
+		vmcb->state.cr0 = state->crs[NVMM_X64_CR_CR0];
+		vmcb->state.cr2 = state->crs[NVMM_X64_CR_CR2];
+		vmcb->state.cr3 = state->crs[NVMM_X64_CR_CR3];
+		vmcb->state.cr4 = state->crs[NVMM_X64_CR_CR4];
 
 		vmcb->ctrl.v &= ~VMCB_CTRL_V_TPR;
-		vmcb->ctrl.v |= __SHIFTIN(cstate->crs[NVMM_X64_CR_CR8],
+		vmcb->ctrl.v |= __SHIFTIN(state->crs[NVMM_X64_CR_CR8],
 		    VMCB_CTRL_V_TPR);
 
 		/* Clear unsupported XCR0 bits, set mandatory X87 bit. */
 		if (svm_xcr0_mask != 0) {
-			cstate->crs[NVMM_X64_CR_XCR0] &= svm_xcr0_mask;
-			cstate->crs[NVMM_X64_CR_XCR0] |= XCR0_X87;
+			cpudata->gxcr0 = state->crs[NVMM_X64_CR_XCR0];
+			cpudata->gxcr0 &= svm_xcr0_mask;
+			cpudata->gxcr0 |= XCR0_X87;
 		} else {
-			cstate->crs[NVMM_X64_CR_XCR0] = 0;
+			cpudata->gxcr0 = 0;
 		}
 	}
 
+	CTASSERT(sizeof(cpudata->drs) == sizeof(state->drs));
 	if (flags & NVMM_X64_STATE_DRS) {
-		memcpy(cstate->drs, nstate->drs, sizeof(nstate->drs));
+		memcpy(cpudata->drs, state->drs, sizeof(state->drs));
 
-		vmcb->state.dr6 = cstate->drs[NVMM_X64_DR_DR6];
-		vmcb->state.dr7 = cstate->drs[NVMM_X64_DR_DR7];
+		vmcb->state.dr6 = state->drs[NVMM_X64_DR_DR6];
+		vmcb->state.dr7 = state->drs[NVMM_X64_DR_DR7];
 	}
 
 	if (flags & NVMM_X64_STATE_MSRS) {
-		memcpy(cstate->msrs, nstate->msrs, sizeof(nstate->msrs));
-
 		/* Bit EFER_SVME is mandatory. */
-		cstate->msrs[NVMM_X64_MSR_EFER] |= EFER_SVME;
+		vmcb->state.efer = state->msrs[NVMM_X64_MSR_EFER] | EFER_SVME;
 
-		vmcb->state.efer = cstate->msrs[NVMM_X64_MSR_EFER];
-		vmcb->state.star = cstate->msrs[NVMM_X64_MSR_STAR];
-		vmcb->state.lstar = cstate->msrs[NVMM_X64_MSR_LSTAR];
-		vmcb->state.cstar = cstate->msrs[NVMM_X64_MSR_CSTAR];
-		vmcb->state.sfmask = cstate->msrs[NVMM_X64_MSR_SFMASK];
+		vmcb->state.star = state->msrs[NVMM_X64_MSR_STAR];
+		vmcb->state.lstar = state->msrs[NVMM_X64_MSR_LSTAR];
+		vmcb->state.cstar = state->msrs[NVMM_X64_MSR_CSTAR];
+		vmcb->state.sfmask = state->msrs[NVMM_X64_MSR_SFMASK];
 		vmcb->state.kernelgsbase =
-		    cstate->msrs[NVMM_X64_MSR_KERNELGSBASE];
+		    state->msrs[NVMM_X64_MSR_KERNELGSBASE];
 		vmcb->state.sysenter_cs =
-		    cstate->msrs[NVMM_X64_MSR_SYSENTER_CS];
+		    state->msrs[NVMM_X64_MSR_SYSENTER_CS];
 		vmcb->state.sysenter_esp =
-		    cstate->msrs[NVMM_X64_MSR_SYSENTER_ESP];
+		    state->msrs[NVMM_X64_MSR_SYSENTER_ESP];
 		vmcb->state.sysenter_eip =
-		    cstate->msrs[NVMM_X64_MSR_SYSENTER_EIP];
-		vmcb->state.g_pat = cstate->msrs[NVMM_X64_MSR_PAT];
+		    state->msrs[NVMM_X64_MSR_SYSENTER_EIP];
+		vmcb->state.g_pat = state->msrs[NVMM_X64_MSR_PAT];
 	}
 
 	if (flags & NVMM_X64_STATE_MISC) {
-		memcpy(cstate->misc, nstate->misc, sizeof(nstate->misc));
-
-		vmcb->state.cpl = cstate->misc[NVMM_X64_MISC_CPL];
+		vmcb->state.cpl = state->misc[NVMM_X64_MISC_CPL];
 
-		if (cstate->misc[NVMM_X64_MISC_INT_SHADOW]) {
+		if (state->misc[NVMM_X64_MISC_INT_SHADOW]) {
 			vmcb->ctrl.intr |= VMCB_CTRL_INTR_SHADOW;
 		} else {
 			vmcb->ctrl.intr &= ~VMCB_CTRL_INTR_SHADOW;
 		}
 
-		if (cstate->misc[NVMM_X64_MISC_INT_WINDOW_EXIT]) {
+		if (state->misc[NVMM_X64_MISC_INT_WINDOW_EXIT]) {
 			svm_event_waitexit_enable(vcpu, false);
 		} else {
 			svm_event_waitexit_disable(vcpu, false);
 		}
 
-		if (cstate->misc[NVMM_X64_MISC_NMI_WINDOW_EXIT]) {
+		if (state->misc[NVMM_X64_MISC_NMI_WINDOW_EXIT]) {
 			svm_event_waitexit_enable(vcpu, true);
 		} else {
 			svm_event_waitexit_disable(vcpu, true);
 		}
 	}
 
-	CTASSERT(sizeof(cpudata->gfpu.xsh_fxsave) == sizeof(cstate->fpu));
+	CTASSERT(sizeof(cpudata->gfpu.xsh_fxsave) == sizeof(state->fpu));
 	if (flags & NVMM_X64_STATE_FPU) {
-		memcpy(&cstate->fpu, &nstate->fpu, sizeof(nstate->fpu));
-
-		memcpy(cpudata->gfpu.xsh_fxsave, &cstate->fpu,
-		    sizeof(cstate->fpu));
+		memcpy(cpudata->gfpu.xsh_fxsave, &state->fpu,
+		    sizeof(state->fpu));
 
 		fpustate = (struct fxsave *)cpudata->gfpu.xsh_fxsave;
 		fpustate->fx_mxcsr_mask &= x86_fpu_mxcsr_mask;
@@ -1871,104 +1855,96 @@ svm_vcpu_setstate(struct nvmm_cpu *vcpu,
 static void
 svm_vcpu_getstate(struct nvmm_cpu *vcpu, void *data, uint64_t flags)
 {
+	struct nvmm_x64_state *state = (struct nvmm_x64_state *)data;
 	struct svm_cpudata *cpudata = vcpu->cpudata;
-	struct nvmm_x64_state *cstate = &cpudata->state;
-	struct nvmm_x64_state *nstate = (struct nvmm_x64_state *)data;
 	struct vmcb *vmcb = cpudata->vmcb;
 
 	if (flags & NVMM_X64_STATE_SEGS) {
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_CS],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_CS],
 		    &vmcb->state.cs);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_DS],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_DS],
 		    &vmcb->state.ds);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_ES],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_ES],
 		    &vmcb->state.es);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_FS],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_FS],
 		    &vmcb->state.fs);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_GS],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_GS],
 		    &vmcb->state.gs);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_SS],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_SS],
 		    &vmcb->state.ss);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_GDT],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_GDT],
 		    &vmcb->state.gdt);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_IDT],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_IDT],
 		    &vmcb->state.idt);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_LDT],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_LDT],
 		    &vmcb->state.ldt);
-		svm_vcpu_getstate_seg(&cstate->segs[NVMM_X64_SEG_TR],
+		svm_vcpu_getstate_seg(&state->segs[NVMM_X64_SEG_TR],
 		    &vmcb->state.tr);
-
-		memcpy(nstate->segs, cstate->segs, sizeof(cstate->segs));
 	}
 
+	CTASSERT(sizeof(cpudata->gprs) == sizeof(state->gprs));
 	if (flags & NVMM_X64_STATE_GPRS) {
-		cstate->gprs[NVMM_X64_GPR_RIP] = vmcb->state.rip;
-		cstate->gprs[NVMM_X64_GPR_RSP] = vmcb->state.rsp;
-		cstate->gprs[NVMM_X64_GPR_RAX] = vmcb->state.rax;
-		cstate->gprs[NVMM_X64_GPR_RFLAGS] = vmcb->state.rflags;
+		memcpy(state->gprs, cpudata->gprs, sizeof(state->gprs));
 
-		memcpy(nstate->gprs, cstate->gprs, sizeof(cstate->gprs));
+		state->gprs[NVMM_X64_GPR_RIP] = vmcb->state.rip;
+		state->gprs[NVMM_X64_GPR_RSP] = vmcb->state.rsp;
+		state->gprs[NVMM_X64_GPR_RAX] = vmcb->state.rax;
+		state->gprs[NVMM_X64_GPR_RFLAGS] = vmcb->state.rflags;
 	}
 
 	if (flags & NVMM_X64_STATE_CRS) {
-		cstate->crs[NVMM_X64_CR_CR0] = vmcb->state.cr0;
-		cstate->crs[NVMM_X64_CR_CR2] = vmcb->state.cr2;
-		cstate->crs[NVMM_X64_CR_CR3] = vmcb->state.cr3;
-		cstate->crs[NVMM_X64_CR_CR4] = vmcb->state.cr4;
-		cstate->crs[NVMM_X64_CR_CR8] = __SHIFTOUT(vmcb->ctrl.v,
+		state->crs[NVMM_X64_CR_CR0] = vmcb->state.cr0;
+		state->crs[NVMM_X64_CR_CR2] = vmcb->state.cr2;
+		state->crs[NVMM_X64_CR_CR3] = vmcb->state.cr3;
+		state->crs[NVMM_X64_CR_CR4] = vmcb->state.cr4;
+		state->crs[NVMM_X64_CR_CR8] = __SHIFTOUT(vmcb->ctrl.v,
 		    VMCB_CTRL_V_TPR);
-
-		memcpy(nstate->crs, cstate->crs, sizeof(cstate->crs));
+		state->crs[NVMM_X64_CR_XCR0] = cpudata->gxcr0;
 	}
 
+	CTASSERT(sizeof(cpudata->drs) == sizeof(state->drs));
 	if (flags & NVMM_X64_STATE_DRS) {
-		cstate->drs[NVMM_X64_DR_DR6] = vmcb->state.dr6;
-		cstate->drs[NVMM_X64_DR_DR7] = vmcb->state.dr7;
+		memcpy(state->drs, cpudata->drs, sizeof(state->drs));
 
-		memcpy(nstate->drs, cstate->drs, sizeof(cstate->drs));
+		state->drs[NVMM_X64_DR_DR6] = vmcb->state.dr6;
+		state->drs[NVMM_X64_DR_DR7] = vmcb->state.dr7;
 	}
 
 	if (flags & NVMM_X64_STATE_MSRS) {
-		cstate->msrs[NVMM_X64_MSR_EFER] = vmcb->state.efer;
-		cstate->msrs[NVMM_X64_MSR_STAR] = vmcb->state.star;
-		cstate->msrs[NVMM_X64_MSR_LSTAR] = vmcb->state.lstar;
-		cstate->msrs[NVMM_X64_MSR_CSTAR] = vmcb->state.cstar;
-		cstate->msrs[NVMM_X64_MSR_SFMASK] = vmcb->state.sfmask;
-		cstate->msrs[NVMM_X64_MSR_KERNELGSBASE] =
+		state->msrs[NVMM_X64_MSR_EFER] = vmcb->state.efer;
+		state->msrs[NVMM_X64_MSR_STAR] = vmcb->state.star;
+		state->msrs[NVMM_X64_MSR_LSTAR] = vmcb->state.lstar;
+		state->msrs[NVMM_X64_MSR_CSTAR] = vmcb->state.cstar;
+		state->msrs[NVMM_X64_MSR_SFMASK] = vmcb->state.sfmask;
+		state->msrs[NVMM_X64_MSR_KERNELGSBASE] =
 		    vmcb->state.kernelgsbase;
-		cstate->msrs[NVMM_X64_MSR_SYSENTER_CS] =
+		state->msrs[NVMM_X64_MSR_SYSENTER_CS] =
 		    vmcb->state.sysenter_cs;
-		cstate->msrs[NVMM_X64_MSR_SYSENTER_ESP] =
+		state->msrs[NVMM_X64_MSR_SYSENTER_ESP] =
 		    vmcb->state.sysenter_esp;
-		cstate->msrs[NVMM_X64_MSR_SYSENTER_EIP] =
+		state->msrs[NVMM_X64_MSR_SYSENTER_EIP] =
 		    vmcb->state.sysenter_eip;
-		cstate->msrs[NVMM_X64_MSR_PAT] = vmcb->state.g_pat;
-
-		memcpy(nstate->msrs, cstate->msrs, sizeof(cstate->msrs));
+		state->msrs[NVMM_X64_MSR_PAT] = vmcb->state.g_pat;
 
 		/* Hide SVME. */
-		nstate->msrs[NVMM_X64_MSR_EFER] &= ~EFER_SVME;
+		state->msrs[NVMM_X64_MSR_EFER] &= ~EFER_SVME;
 	}
 
 	if (flags & NVMM_X64_STATE_MISC) {
-		cstate->misc[NVMM_X64_MISC_CPL] = vmcb->state.cpl;
+		state->misc[NVMM_X64_MISC_CPL] = vmcb->state.cpl;
 
-		cstate->misc[NVMM_X64_MISC_INT_SHADOW] =
+		state->misc[NVMM_X64_MISC_INT_SHADOW] =
 		    (vmcb->ctrl.intr & VMCB_CTRL_INTR_SHADOW) != 0;
-		cstate->misc[NVMM_X64_MISC_INT_WINDOW_EXIT] =
+		state->misc[NVMM_X64_MISC_INT_WINDOW_EXIT] =
 		    cpudata->int_window_exit;
-		cstate->misc[NVMM_X64_MISC_NMI_WINDOW_EXIT] =
+		state->misc[NVMM_X64_MISC_NMI_WINDOW_EXIT] =
 		    cpudata->nmi_window_exit;
-
-		memcpy(nstate->misc, cstate->misc, sizeof(cstate->misc));
 	}
 
-	CTASSERT(sizeof(cpudata->gfpu.xsh_fxsave) == sizeof(cstate->fpu));
+	CTASSERT(sizeof(cpudata->gfpu.xsh_fxsave) == sizeof(state->fpu));
 	if (flags & NVMM_X64_STATE_FPU) {
-		memcpy(&cstate->fpu, cpudata->gfpu.xsh_fxsave,
-		    sizeof(cstate->fpu));
-
-		memcpy(&nstate->fpu, &cstate->fpu, sizeof(cstate->fpu));
+		memcpy(&state->fpu, cpudata->gfpu.xsh_fxsave,
+		    sizeof(state->fpu));
 	}
 }
 

Reply via email to