|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC v1 7/7] x86/svm: Use the emulator path for VMEXIT_CR*
If the processor has provided extra information, use that to accelerate
the emulator path.
The hvmemul_{read,write}_cr callbacks are used for consistent behaviour
between emulated and fast paths.
Signed-off-by: Ross Lagerwall <ross.lagerwall@xxxxxxxxxx>
---
xen/arch/x86/hvm/emulate.c | 11 ++++++++++
xen/arch/x86/hvm/svm/svm.c | 28 +++++++++-----------------
xen/arch/x86/include/asm/hvm/emulate.h | 7 +++++++
xen/arch/x86/include/asm/hvm/hvm.h | 2 ++
4 files changed, 29 insertions(+), 19 deletions(-)
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 471c032c1e9c..0f7507575884 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -2804,6 +2804,17 @@ static int _hvm_emulate_one(struct hvm_emulate_ctxt
*hvmemul_ctxt,
hvmemul_ctxt->ctxt.retire.hlt = true;
rc = X86EMUL_OKAY;
break;
+ case INSTR_MOV_FROM_CR:
+ case INSTR_MOV_TO_CR:
+ {
+ unsigned long *val = decode_gpr(regs, hvmemul_ctxt->u.cr.gp);
+
+ if ( hvmemul_ctxt->insn == INSTR_MOV_TO_CR )
+ rc = hvmemul_write_cr(hvmemul_ctxt->u.cr.cr, *val,
&hvmemul_ctxt->ctxt);
+ else
+ rc = hvmemul_read_cr(hvmemul_ctxt->u.cr.cr, val,
&hvmemul_ctxt->ctxt);
+ break;
+ }
default:
ASSERT_UNREACHABLE();
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 2d6022d6238c..3ba852f52666 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -1625,22 +1625,6 @@ static void svm_do_nested_pgfault(struct vcpu *v,
domain_crash(v->domain);
}
-static void svm_vmexit_do_cr_access(
- struct vmcb_struct *vmcb, struct cpu_user_regs *regs)
-{
- int gp, cr, dir, rc;
-
- cr = vmcb->exitcode - VMEXIT_CR0_READ;
- dir = (cr > 15);
- cr &= 0xf;
- gp = vmcb->ei.mov_cr.gpr;
-
- rc = dir ? hvm_mov_to_cr(cr, gp) : hvm_mov_from_cr(cr, gp);
-
- if ( rc == X86EMUL_OKAY )
- __update_guest_eip(regs, vmcb->nextrip - vmcb->rip);
-}
-
static void svm_dr_access(struct vcpu *v, struct cpu_user_regs *regs)
{
struct vmcb_struct *vmcb = vcpu_nestedhvm(v).nv_n1vmcx;
@@ -2869,10 +2853,16 @@ void asmlinkage svm_vmexit_handler(void)
case VMEXIT_CR0_READ ... VMEXIT_CR15_READ:
case VMEXIT_CR0_WRITE ... VMEXIT_CR15_WRITE:
+ hvm_emulate_init_once(&ctxt, x86_insn_is_cr_access, "CR access", regs);
+
if ( cpu_has_svm_decode && vmcb->ei.mov_cr.mov_insn )
- svm_vmexit_do_cr_access(vmcb, regs);
- else if ( !hvm_emulate_one_insn(x86_insn_is_cr_access, "CR access") )
- hvm_inject_hw_exception(X86_EXC_GP, 0);
+ {
+ ctxt.u.cr.cr = vmcb->exitcode - VMEXIT_CR0_READ;
+ ctxt.insn = (ctxt.u.cr.cr > 15) ? INSTR_MOV_TO_CR :
INSTR_MOV_FROM_CR;
+ ctxt.u.cr.cr = ctxt.u.cr.cr & 0xf;
+ ctxt.u.cr.gp = vmcb->ei.mov_cr.gpr;
+ }
+ svm_emulate_one(&ctxt);
break;
case VMEXIT_INVLPG:
diff --git a/xen/arch/x86/include/asm/hvm/emulate.h
b/xen/arch/x86/include/asm/hvm/emulate.h
index 1e626f8af8f2..3661ca28d6f4 100644
--- a/xen/arch/x86/include/asm/hvm/emulate.h
+++ b/xen/arch/x86/include/asm/hvm/emulate.h
@@ -56,6 +56,13 @@ struct hvm_emulate_ctxt {
unsigned int insn;
unsigned int insn_len;
+
+ union {
+ struct {
+ int cr;
+ int gp;
+ } cr;
+ } u;
};
enum emul_kind {
diff --git a/xen/arch/x86/include/asm/hvm/hvm.h
b/xen/arch/x86/include/asm/hvm/hvm.h
index a9b64814ca71..7732217e279a 100644
--- a/xen/arch/x86/include/asm/hvm/hvm.h
+++ b/xen/arch/x86/include/asm/hvm/hvm.h
@@ -879,6 +879,8 @@ static inline void hvm_sync_pir_to_irr(struct vcpu *v)
#define INSTR_RDTSC INSTR_ENC(X86EMUL_OPC(0x0f, 0x31), 0)
#define INSTR_RDMSR INSTR_ENC(X86EMUL_OPC(0x0f, 0x32), 0)
#define INSTR_CPUID INSTR_ENC(X86EMUL_OPC(0x0f, 0xa2), 0)
+#define INSTR_MOV_FROM_CR INSTR_ENC(X86EMUL_OPC(0x0f, 0x20), 0)
+#define INSTR_MOV_TO_CR INSTR_ENC(X86EMUL_OPC(0x0f, 0x22), 0)
#else /* CONFIG_HVM */
--
2.53.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |