On Fri, 17 Mar 2017 05:03:44 -0600 "Jan Beulich" <jbeul...@suse.com> wrote:
> >>> On 10.03.17 at 16:50, <ito...@bitdefender.com> wrote: > > --- a/xen/arch/x86/hvm/hvm.c > > +++ b/xen/arch/x86/hvm/hvm.c > > @@ -3645,6 +3645,41 @@ gp_fault: > > return X86EMUL_EXCEPTION; > > } > > > > +int hvm_descriptor_access_intercept(uint64_t exit_info, uint64_t > > exit_qualification, > > + uint8_t descriptor, bool_t is_write) > > bool (also elsewhere) Ok. > > +{ > > + struct vcpu *v = current; > > + struct domain *d = v->domain; > > curr and currd respectively. Ok. > > + struct hvm_emulate_ctxt ctxt = {}; > > Please move this into the more narrow scope it's needed in. Ok. > > + int rc; > > + > > + if ( d->arch.monitor.descriptor_access_enabled ) > > + { > > + ASSERT(v->arch.vm_event); > > + hvm_monitor_descriptor_access(exit_info, exit_qualification, > > descriptor, is_write); > > + } > > + else > > + { > > + hvm_emulate_init_once(&ctxt, NULL, guest_cpu_user_regs()); > > + rc = hvm_emulate_one(&ctxt); > > + switch ( rc ) > > + { > > + case X86EMUL_UNHANDLEABLE: > > + hvm_inject_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC); > > Is #UD the right exception here? In fact, is delivering an exception > sensible in this case at all? Possibly not; it's how that case is handled elsewhere. For the given set of instructions at least, X86EMUL_UNHANDLEABLE should only be returnable due to some internal bug/error (e.g. invalid/unknown HVMCOPY_* constant returned by hvm_fetch_from_guest_linear() or an invalid selector passed to ->write_segment() etc.); what would be the best way to handle that case? > > @@ -3369,6 +3384,33 @@ static void vmx_handle_xrstors(void) > > domain_crash(current->domain); > > } > > > > +static void vmx_handle_descriptor_access(uint32_t exit_reason) > > +{ > > + uint8_t instr_id; > > + uint64_t instr_info; > > + uint64_t exit_qualification; > > + uint8_t descriptor = VM_EVENT_DESC_INVALID; > > + > > + __vmread(EXIT_QUALIFICATION, &exit_qualification); > > + __vmread(VMX_INSTRUCTION_INFO, &instr_info); > > + > > + instr_id = (instr_info >> 28) & 3; /* Instruction identity: bits 29:28 > > */ > > + > > + if ( exit_reason == EXIT_REASON_ACCESS_GDTR_OR_IDTR ) > > + if ( instr_id & 1 ) > > + descriptor = VM_EVENT_DESC_IDTR; > > + else > > + descriptor = VM_EVENT_DESC_GDTR; > > + else > > + if ( instr_id & 1 ) > > + descriptor = VM_EVENT_DESC_TR; > > + else > > + descriptor = VM_EVENT_DESC_LDTR; > > Please use conditional expressions instead of if/else in such cases. Ok. > > + hvm_descriptor_access_intercept(instr_info, exit_qualification, > > descriptor, > > + instr_id >= 2); > > instr_id & 2 (to be consistent with the other code. But anyway, even > better would be to use manifest constants instead of all these literal > numbers. (instr_id & 2) makes sense, but the 1 & 2 literals are unnamed criteria inferred from the encoding to simplify the code, they don't have an explicit meaning (at least in the Intel docs). > > @@ -444,6 +445,7 @@ int hvm_event_needs_reinjection(uint8_t type, uint8_t > > vector); > > uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2); > > > > void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable); > > +void hvm_set_descriptor_access_exiting(struct domain *d, bool_t enable); > > Dead declaration. It somehow got away from a previous (internal) version of the patch; it will be removed. > > --- a/xen/include/asm-x86/monitor.h > > +++ b/xen/include/asm-x86/monitor.h > > @@ -77,6 +77,7 @@ static inline uint32_t > > arch_monitor_get_capabilities(struct domain *d) > > (1U << XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST) | > > (1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) | > > (1U << XEN_DOMCTL_MONITOR_EVENT_CPUID) | > > + (1U << XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS) | > > (1U << XEN_DOMCTL_MONITOR_EVENT_INTERRUPT); > > If I was the maintainer of this code, I'd ask for the elements to > remain ordered numerically, i.e. matching ... > > > --- a/xen/include/public/domctl.h > > +++ b/xen/include/public/domctl.h > > @@ -1087,6 +1087,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t); > > #define XEN_DOMCTL_MONITOR_EVENT_CPUID 6 > > #define XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL 7 > > #define XEN_DOMCTL_MONITOR_EVENT_INTERRUPT 8 > > +#define XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS 9 > > ... the sequence here. Ok. > > @@ -259,6 +261,24 @@ struct vm_event_mov_to_msr { > > uint64_t value; > > }; > > > > +#define VM_EVENT_DESC_INVALID 0 > > What is this good for? The default (uninitialized) value is given a semantic of "invalid" to make potential problems due to incorrectly / incompletely initialized or corrupted data more obvious (I assume the .pad* fields are checked to be 0 for the same reason). > Jan Thank you for the review; pending further feedback on the X86EMUL_UNHANDLEABLE case I'll post an updated patch. -- Vlad-Ioan TOPAN Linux Kernel Development Lead Bitdefender _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org https://lists.xen.org/xen-devel