/* * arch/x86/hvm/vm_event.c * * HVM vm_event handling routines * * Copyright (c) 2004, Intel Corporation. * Copyright (c) 2005, International Business Machines Corporation. * Copyright (c) 2008, Citrix Systems, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; If not, see . */ #include #include #include #include #include static void hvm_vm_event_set_registers(const struct vcpu *v) { ASSERT(v == current); if ( unlikely(v->arch.vm_event->set_gprs) ) { struct cpu_user_regs *regs = guest_cpu_user_regs(); regs->rax = v->arch.vm_event->gprs.rax; regs->rbx = v->arch.vm_event->gprs.rbx; regs->rcx = v->arch.vm_event->gprs.rcx; regs->rdx = v->arch.vm_event->gprs.rdx; regs->rsp = v->arch.vm_event->gprs.rsp; regs->rbp = v->arch.vm_event->gprs.rbp; regs->rsi = v->arch.vm_event->gprs.rsi; regs->rdi = v->arch.vm_event->gprs.rdi; regs->r8 = v->arch.vm_event->gprs.r8; regs->r9 = v->arch.vm_event->gprs.r9; regs->r10 = v->arch.vm_event->gprs.r10; regs->r11 = v->arch.vm_event->gprs.r11; regs->r12 = v->arch.vm_event->gprs.r12; regs->r13 = v->arch.vm_event->gprs.r13; regs->r14 = v->arch.vm_event->gprs.r14; regs->r15 = v->arch.vm_event->gprs.r15; regs->rflags = v->arch.vm_event->gprs.rflags; regs->rip = v->arch.vm_event->gprs.rip; v->arch.vm_event->set_gprs = false; } } void hvm_vm_event_do_resume(struct vcpu *v) { struct monitor_write_data *w; ASSERT(v->arch.vm_event); hvm_vm_event_set_registers(v); w = &v->arch.vm_event->write_data; if ( unlikely(v->arch.vm_event->emulate_flags) ) { enum emul_kind kind = EMUL_KIND_NORMAL; /* * Please observe the order here to match the flag descriptions * provided in public/vm_event.h */ if ( v->arch.vm_event->emulate_flags & VM_EVENT_FLAG_SET_EMUL_READ_DATA ) kind = EMUL_KIND_SET_CONTEXT_DATA; else if ( v->arch.vm_event->emulate_flags & VM_EVENT_FLAG_EMULATE_NOWRITE ) kind = EMUL_KIND_NOWRITE; else if ( v->arch.vm_event->emulate_flags & VM_EVENT_FLAG_SET_EMUL_INSN_DATA ) kind = EMUL_KIND_SET_CONTEXT_INSN; hvm_emulate_one_vm_event(kind, TRAP_invalid_op, X86_EVENT_NO_EC); v->arch.vm_event->emulate_flags = 0; } if ( unlikely(w->do_write.cr0) ) { if ( hvm_set_cr0(w->cr0, false) == X86EMUL_EXCEPTION ) hvm_inject_hw_exception(TRAP_gp_fault, 0); w->do_write.cr0 = 0; } if ( unlikely(w->do_write.cr4) ) { if ( hvm_set_cr4(w->cr4, false) == X86EMUL_EXCEPTION ) hvm_inject_hw_exception(TRAP_gp_fault, 0); w->do_write.cr4 = 0; } if ( unlikely(w->do_write.cr3) ) { if ( hvm_set_cr3(w->cr3, w->cr3_noflush, false) == X86EMUL_EXCEPTION ) hvm_inject_hw_exception(TRAP_gp_fault, 0); w->do_write.cr3 = 0; } if ( unlikely(w->do_write.msr) ) { if ( hvm_msr_write_intercept(w->msr, w->value, false) == X86EMUL_EXCEPTION ) hvm_inject_hw_exception(TRAP_gp_fault, 0); w->do_write.msr = 0; } vm_event_sync_event(v, false); } /* * Local variables: * mode: C * c-file-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */