Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/nvmm/x86 Optimize: don't keep a full copy of the gue...
details: https://anonhg.NetBSD.org/src/rev/18bc33899305
branches: trunk
changeset: 838256:18bc33899305
user: maxv <maxv%NetBSD.org@localhost>
date: Tue Jan 08 14:43:18 2019 +0000
description:
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.
diffstat:
sys/dev/nvmm/x86/nvmm_x86_svm.c | 332 ++++++++++++++++++---------------------
1 files changed, 154 insertions(+), 178 deletions(-)
diffs (truncated from 669 to 300 lines):
diff -r 9317c3a6497e -r 18bc33899305 sys/dev/nvmm/x86/nvmm_x86_svm.c
--- a/sys/dev/nvmm/x86/nvmm_x86_svm.c Tue Jan 08 11:36:10 2019 +0000
+++ b/sys/dev/nvmm/x86/nvmm_x86_svm.c Tue Jan 08 14:43:18 2019 +0000
@@ -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 @@
};
struct svm_cpudata {
- /* x64-specific */
- struct nvmm_x64_state state;
-
/* General */
bool shared_asid;
bool tlb_want_flush;
@@ -519,7 +516,7 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
{
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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);
Home |
Main Index |
Thread Index |
Old Index