[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] x86/HVM: cancel emulation when register state got altered
commit a141051d7695265c721863dc91a2dc206b9ff5b1 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Thu Apr 23 09:51:18 2020 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu Apr 23 09:51:18 2020 +0200 x86/HVM: cancel emulation when register state got altered Re-execution (after having received data from a device model) relies on the same register state still being in place as it was when the request was first sent to the device model. Therefore vCPU state changes effected by remote sources need to result in no attempt of re-execution. Instead the returned data is to simply be ignored. Note that any such asynchronous state changes happen with the vCPU at least paused (potentially down and/or not marked ->is_initialised), so there's no issue with fiddling with register state behind the actively running emulator's back. Hence the new function doesn't need to synchronize with the core emulation logic. Suggested-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Paul Durrant <pdurrant@xxxxxxxx> --- xen/arch/x86/domctl.c | 6 ++++++ xen/arch/x86/hvm/domain.c | 4 ++++ xen/arch/x86/hvm/emulate.c | 17 +++++++++++++++++ xen/arch/x86/hvm/hvm.c | 10 ++++++++++ xen/arch/x86/hvm/vlapic.c | 3 +++ xen/include/asm-x86/hvm/emulate.h | 1 + xen/include/asm-x86/hvm/hvm.h | 9 ++------- 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index add70126b9..03dffa5ecf 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -21,6 +21,7 @@ #include <xen/iocap.h> #include <xen/paging.h> #include <asm/irq.h> +#include <asm/hvm/emulate.h> #include <asm/hvm/hvm.h> #include <asm/hvm/support.h> #include <asm/processor.h> @@ -1147,11 +1148,16 @@ long arch_do_domctl( else { vcpu_pause(v); + v->arch.xcr0 = _xcr0; v->arch.xcr0_accum = _xcr0_accum; v->arch.nonlazy_xstate_used = _xcr0_accum & XSTATE_NONLAZY; compress_xsave_states(v, _xsave_area, evc->size - PV_XSAVE_HDR_SIZE); + + if ( is_hvm_domain(d) ) + hvmemul_cancel(v); + vcpu_unpause(v); } diff --git a/xen/arch/x86/hvm/domain.c b/xen/arch/x86/hvm/domain.c index 5d5a746a25..8e3375265c 100644 --- a/xen/arch/x86/hvm/domain.c +++ b/xen/arch/x86/hvm/domain.c @@ -22,6 +22,8 @@ #include <xen/paging.h> #include <xen/sched.h> +#include <asm/hvm/emulate.h> + #include <public/hvm/hvm_vcpu.h> static int check_segment(struct segment_register *reg, enum x86_segment seg) @@ -323,6 +325,8 @@ int arch_set_info_hvm_guest(struct vcpu *v, const vcpu_hvm_context_t *ctx) paging_update_paging_modes(v); + hvmemul_cancel(v); + v->is_initialised = 1; set_bit(_VPF_down, &v->pause_flags); diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index d717277b2f..a4185c68cb 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -121,6 +121,23 @@ static const struct hvm_io_handler ioreq_server_handler = { .ops = &ioreq_server_ops }; +/* + * Drop all records of in-flight emulation. This is needed whenever a vCPU's + * register state may have changed behind the emulator's back. + */ +void hvmemul_cancel(struct vcpu *v) +{ + struct hvm_vcpu_io *vio = &v->arch.hvm.hvm_io; + + vio->io_req.state = STATE_IOREQ_NONE; + vio->io_completion = HVMIO_no_completion; + vio->mmio_cache_count = 0; + vio->mmio_insn_bytes = 0; + vio->mmio_access = (struct npfec){}; + vio->mmio_retry = false; + vio->g2m_ioport = NULL; +} + static int hvmemul_do_io( bool_t is_mmio, paddr_t addr, unsigned long *reps, unsigned int size, uint8_t dir, bool_t df, bool_t data_is_addr, uintptr_t data) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 45959d3412..34b39e27df 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -478,6 +478,14 @@ u64 hvm_get_guest_tsc_fixed(struct vcpu *v, uint64_t at_tsc) return tsc + v->arch.hvm.cache_tsc_offset; } +void hvm_set_info_guest(struct vcpu *v) +{ + if ( hvm_funcs.set_info_guest ) + alternative_vcall(hvm_funcs.set_info_guest, v); + + hvmemul_cancel(v); +} + void hvm_migrate_timers(struct vcpu *v) { rtc_migrate_timers(v); @@ -1163,6 +1171,8 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) v->arch.dr6 = ctxt.dr6; v->arch.dr7 = ctxt.dr7; + hvmemul_cancel(v); + /* Auxiliary processors should be woken immediately. */ v->is_initialised = 1; clear_bit(_VPF_down, &v->pause_flags); diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 26726a4312..7b5c633033 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -33,6 +33,7 @@ #include <asm/apic.h> #include <asm/io_apic.h> #include <asm/vpmu.h> +#include <asm/hvm/emulate.h> #include <asm/hvm/hvm.h> #include <asm/hvm/io.h> #include <asm/hvm/support.h> @@ -306,6 +307,8 @@ static void vlapic_init_sipi_one(struct vcpu *target, uint32_t icr) BUG(); } + hvmemul_cancel(target); + vcpu_unpause(target); } diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h index 2bdddef730..a2ad7ff1aa 100644 --- a/xen/include/asm-x86/hvm/emulate.h +++ b/xen/include/asm-x86/hvm/emulate.h @@ -77,6 +77,7 @@ void hvm_emulate_init_per_insn( unsigned int insn_bytes); void hvm_emulate_writeback( struct hvm_emulate_ctxt *hvmemul_ctxt); +void hvmemul_cancel(struct vcpu *v); struct segment_register *hvmemul_get_seg_reg( enum x86_segment seg, struct hvm_emulate_ctxt *hvmemul_ctxt); diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index f283c7d187..1eb377dd82 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -277,6 +277,8 @@ void hvm_get_segment_register(struct vcpu *v, enum x86_segment seg, void hvm_set_segment_register(struct vcpu *v, enum x86_segment seg, struct segment_register *reg); +void hvm_set_info_guest(struct vcpu *v); + bool hvm_set_guest_bndcfgs(struct vcpu *v, u64 val); int hvm_vmexit_cpuid(struct cpu_user_regs *regs, unsigned int inst_len); @@ -545,12 +547,6 @@ static inline unsigned int hvm_get_insn_bytes(struct vcpu *v, uint8_t *buf) ? alternative_call(hvm_funcs.get_insn_bytes, v, buf) : 0); } -static inline void hvm_set_info_guest(struct vcpu *v) -{ - if ( hvm_funcs.set_info_guest ) - alternative_vcall(hvm_funcs.set_info_guest, v); -} - static inline void hvm_invalidate_regs_fields(struct cpu_user_regs *regs) { #ifndef NDEBUG @@ -681,7 +677,6 @@ static inline bool altp2m_vcpu_emulate_ve(struct vcpu *v) */ int hvm_guest_x86_mode(struct vcpu *v); unsigned long hvm_get_shadow_gs_base(struct vcpu *v); -void hvm_set_info_guest(struct vcpu *v); void hvm_cpuid_policy_changed(struct vcpu *v); void hvm_set_tsc_offset(struct vcpu *v, uint64_t offset, uint64_t at_tsc); bool hvm_get_guest_bndcfgs(struct vcpu *v, uint64_t *val); -- generated by git-patchbot for /home/xen/git/xen.git#staging
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |