[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/6] x86emul: generalize wbinvd() hook
> -----Original Message----- > From: Jan Beulich <JBeulich@xxxxxxxx> > Sent: 01 July 2019 12:56 > To: xen-devel@xxxxxxxxxxxxxxxxxxxx > Cc: Andrew Cooper <Andrew.Cooper3@xxxxxxxxxx>; Paul Durrant > <Paul.Durrant@xxxxxxxxxx>; Roger Pau Monne > <roger.pau@xxxxxxxxxx>; Wei Liu <wl@xxxxxxx> > Subject: [PATCH 1/6] x86emul: generalize wbinvd() hook > > The hook is already in use for other purposes, and emulating e.g. > CLFLUSH by issuing WBINVD is, well, not very nice. Rename the hook and > add parameters. Use lighter weight flushing insns when possible in > hvmemul_cache_op(). > > hvmemul_cache_op() treating x86emul_invd the same as x86emul_wbinvd is > to retain original behavior, but I'm not sure this is what we want in > the long run. > > Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> > --- > v2: Use cache_op() as hook name. Convert macros to inline functions in > system.h. Re-base. > --- > I was unsure about PREFETCH* and CLDEMOTE - both are cache management > insns too, but the emulator currently treats them as a NOP without > invoking any hooks. > I was also uncertain about the new cache_flush_permitted() instance - > generally I think it wouldn't be too bad if we allowed line flushes in > all cases, in which case the checks in the ->wbinvd_intercept() handlers > would suffice (as they did until now). > [snip] > --- a/xen/arch/x86/hvm/emulate.c > +++ b/xen/arch/x86/hvm/emulate.c > @@ -25,6 +25,7 @@ > #include <asm/hvm/trace.h> > #include <asm/hvm/support.h> > #include <asm/hvm/svm/svm.h> > +#include <asm/iocap.h> > #include <asm/vm_event.h> > > static void hvmtrace_io_assist(const ioreq_t *p) > @@ -555,16 +556,12 @@ static void *hvmemul_map_linear_addr( > mfn_t *mfn = &hvmemul_ctxt->mfn[0]; > > /* > - * The caller has no legitimate reason for trying a zero-byte write, but > - * all other code here is written to work if the check below was dropped. > - * > - * The maximum write size depends on the number of adjacent mfns[] which > + * The maximum access size depends on the number of adjacent mfns[] which > * can be vmap()'d, accouting for possible misalignment within the > region. > * The higher level emulation callers are responsible for ensuring that > - * mfns[] is large enough for the requested write size. > + * mfns[] is large enough for the requested access size. > */ > - if ( bytes == 0 || > - nr_frames > ARRAY_SIZE(hvmemul_ctxt->mfn) ) > + if ( nr_frames > ARRAY_SIZE(hvmemul_ctxt->mfn) ) > { > ASSERT_UNREACHABLE(); > goto unhandleable; > @@ -669,8 +666,6 @@ static void hvmemul_unmap_linear_addr( > unsigned int i; > mfn_t *mfn = &hvmemul_ctxt->mfn[0]; > > - ASSERT(bytes > 0); > - > if ( nr_frames == 1 ) > unmap_domain_page(mapping); > else > @@ -1473,7 +1468,10 @@ static int hvmemul_write_msr_discard( > return X86EMUL_OKAY; > } > > -static int hvmemul_wbinvd_discard( > +static int hvmemul_cache_op_discard( > + enum x86emul_cache_op op, > + enum x86_segment seg, > + unsigned long offset, > struct x86_emulate_ctxt *ctxt) > { > return X86EMUL_OKAY; > @@ -2149,10 +2147,65 @@ static int hvmemul_write_msr( > return rc; > } > > -static int hvmemul_wbinvd( > +static int hvmemul_cache_op( > + enum x86emul_cache_op op, > + enum x86_segment seg, > + unsigned long offset, > struct x86_emulate_ctxt *ctxt) > { > - alternative_vcall(hvm_funcs.wbinvd_intercept); > + struct hvm_emulate_ctxt *hvmemul_ctxt = > + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); > + unsigned long addr, reps = 1; > + uint32_t pfec = PFEC_page_present; > + int rc; > + void *mapping; > + > + if ( !cache_flush_permitted(current->domain) ) > + return X86EMUL_OKAY; > + > + switch ( op ) > + { > + case x86emul_clflush: > + case x86emul_clflushopt: > + case x86emul_clwb: > + ASSERT(!is_x86_system_segment(seg)); > + > + rc = hvmemul_virtual_to_linear(seg, offset, 0, &reps, > + hvm_access_read, hvmemul_ctxt, &addr); > + if ( rc != X86EMUL_OKAY ) > + break; > + > + if ( hvmemul_ctxt->seg_reg[x86_seg_ss].dpl == 3 ) > + pfec |= PFEC_user_mode; > + > + mapping = hvmemul_map_linear_addr(addr, 0, pfec, hvmemul_ctxt, > + current->arch.hvm.data_cache); > + if ( mapping == ERR_PTR(~X86EMUL_EXCEPTION) ) > + return X86EMUL_EXCEPTION; > + if ( IS_ERR_OR_NULL(mapping) ) > + break; > + > + if ( cpu_has_clflush ) > + { > + if ( op == x86emul_clwb && cpu_has_clwb ) > + clwb(mapping); > + else if ( op == x86emul_clflushopt && cpu_has_clflushopt ) > + clflushopt(mapping); > + else > + clflush(mapping); > + > + hvmemul_unmap_linear_addr(mapping, addr, 0, hvmemul_ctxt); > + break; > + } > + > + hvmemul_unmap_linear_addr(mapping, addr, 0, hvmemul_ctxt); Since the mapping is ditched here, why bother getting one at all in the !cpu_has_clflush case? Are you trying to flush out an error condition that was previously missed? Paul _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |