From: Julian Seward Date: Thu, 4 Sep 2014 10:59:50 +0000 (+0000) Subject: Add support for Xen hypercalls used by libvmi. Patch from Antony Saba X-Git-Tag: svn/VALGRIND_3_10_0~56 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a4830754d0474adf41c382844af703a047cd89be;p=thirdparty%2Fvalgrind.git Add support for Xen hypercalls used by libvmi. Patch from Antony Saba (antony.saba@fireeye.com). First of two patches from #337740. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14453 --- diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 0ba00d7cb9..f65ba12a4e 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -186,7 +186,7 @@ PRE(memory_op) PRE_MEM_READ("XENMEM_add_to_physmap gpfn", (Addr)&arg->gpfn, sizeof(arg->gpfn)); break; - }; + } case VKI_XENMEM_remove_from_physmap: { struct vki_xen_remove_from_physmap *arg = @@ -195,12 +195,24 @@ PRE(memory_op) (Addr)&arg->domid, sizeof(arg->domid)); PRE_MEM_READ("XENMEM_remove_from_physmap gpfn", (Addr)&arg->gpfn, sizeof(arg->gpfn)); + break; } case VKI_XENMEM_get_sharing_freed_pages: case VKI_XENMEM_get_sharing_shared_pages: break; + case VKI_XENMEM_access_op: { + struct vki_xen_mem_event_op *arg = + (struct vki_xen_mem_event_op *)ARG2; + PRE_MEM_READ("XENMEM_access_op domid", + (Addr)&arg->domain, sizeof(arg->domain)); + PRE_MEM_READ("XENMEM_access_op op", + (Addr)&arg->op, sizeof(arg->op)); + PRE_MEM_READ("XENMEM_access_op gfn", + (Addr)&arg->gfn, sizeof(arg->gfn)); + break; + } default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_memory_op", ARG1); @@ -619,6 +631,26 @@ PRE(domctl) domctl->u.hvmcontext.size); break; + case VKI_XEN_DOMCTL_gethvmcontext_partial: + __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, type); + __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, instance); + __PRE_XEN_DOMCTL_READ(gethvmcontext_partial, hvmcontext_partial, buffer); + + switch (domctl->u.hvmcontext_partial.type) { + case VKI_HVM_SAVE_CODE(CPU): + if ( domctl->u.hvmcontext_partial.buffer.p ) + PRE_MEM_WRITE("XEN_DOMCTL_gethvmcontext_partial *buffer", + (Addr)domctl->u.hvmcontext_partial.buffer.p, + VKI_HVM_SAVE_LENGTH(CPU)); + break; + default: + bad_subop(tid, layout, arrghs, status, flags, + "__HYPERVISOR_domctl_gethvmcontext_partial type", + domctl->u.hvmcontext_partial.type); + break; + } + break; + case VKI_XEN_DOMCTL_max_mem: PRE_XEN_DOMCTL_READ(max_mem, max_memkb); break; @@ -634,6 +666,12 @@ PRE(domctl) __PRE_XEN_DOMCTL_READ(settscinfo, tsc_info, info.elapsed_nsec); break; + case VKI_XEN_DOMCTL_ioport_permission: + PRE_XEN_DOMCTL_READ(ioport_permission, first_port); + PRE_XEN_DOMCTL_READ(ioport_permission, nr_ports); + PRE_XEN_DOMCTL_READ(ioport_permission, allow_access); + break; + case VKI_XEN_DOMCTL_hypercall_init: PRE_XEN_DOMCTL_READ(hypercall_init, gmfn); break; @@ -773,6 +811,20 @@ PRE(domctl) PRE_XEN_DOMCTL_READ(cacheflush, nr_pfns); break; + case VKI_XEN_DOMCTL_set_access_required: + PRE_XEN_DOMCTL_READ(access_required, access_required); + break; + + case VKI_XEN_DOMCTL_mem_event_op: + PRE_XEN_DOMCTL_READ(mem_event_op, op); + PRE_XEN_DOMCTL_READ(mem_event_op, mode); + break; + + case VKI_XEN_DOMCTL_debug_op: + PRE_XEN_DOMCTL_READ(debug_op, op); + PRE_XEN_DOMCTL_READ(debug_op, vcpu); + break; + default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl", domctl->cmd); @@ -827,6 +879,34 @@ PRE(hvm_op) PRE_XEN_HVMOP_READ(set_mem_type, first_pfn); break; + case VKI_XEN_HVMOP_set_mem_access: + PRE_XEN_HVMOP_READ(set_mem_access, domid); + PRE_XEN_HVMOP_READ(set_mem_access, hvmmem_access); + PRE_XEN_HVMOP_READ(set_mem_access, first_pfn); + /* if default access */ + if ( ((vki_xen_hvm_set_mem_access_t*)arg)->first_pfn != ~0ULL) + PRE_XEN_HVMOP_READ(set_mem_access, nr); + break; + + case VKI_XEN_HVMOP_get_mem_access: + PRE_XEN_HVMOP_READ(get_mem_access, domid); + PRE_XEN_HVMOP_READ(get_mem_access, pfn); + + PRE_MEM_WRITE("XEN_HVMOP_get_mem_access *hvmmem_access", + (Addr)&(((vki_xen_hvm_get_mem_access_t*)arg)->hvmmem_access), + sizeof(vki_uint16_t)); + break; + + case VKI_XEN_HVMOP_inject_trap: + PRE_XEN_HVMOP_READ(inject_trap, domid); + PRE_XEN_HVMOP_READ(inject_trap, vcpuid); + PRE_XEN_HVMOP_READ(inject_trap, vector); + PRE_XEN_HVMOP_READ(inject_trap, type); + PRE_XEN_HVMOP_READ(inject_trap, error_code); + PRE_XEN_HVMOP_READ(inject_trap, insn_len); + PRE_XEN_HVMOP_READ(inject_trap, cr2); + break; + default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_hvm_op", op); @@ -900,6 +980,7 @@ POST(memory_op) case VKI_XENMEM_claim_pages: case VKI_XENMEM_maximum_gpfn: case VKI_XENMEM_remove_from_physmap: + case VKI_XENMEM_access_op: /* No outputs */ break; case VKI_XENMEM_increase_reservation: @@ -1175,6 +1256,7 @@ POST(domctl){ case VKI_XEN_DOMCTL_max_mem: case VKI_XEN_DOMCTL_set_address_size: case VKI_XEN_DOMCTL_settscinfo: + case VKI_XEN_DOMCTL_ioport_permission: case VKI_XEN_DOMCTL_hypercall_init: case VKI_XEN_DOMCTL_setvcpuaffinity: case VKI_XEN_DOMCTL_setvcpucontext: @@ -1182,9 +1264,11 @@ POST(domctl){ case VKI_XEN_DOMCTL_set_cpuid: case VKI_XEN_DOMCTL_unpausedomain: case VKI_XEN_DOMCTL_sethvmcontext: + case VKI_XEN_DOMCTL_debug_op: case VKI_XEN_DOMCTL_set_max_evtchn: case VKI_XEN_DOMCTL_cacheflush: case VKI_XEN_DOMCTL_resumedomain: + case VKI_XEN_DOMCTL_set_access_required: /* No output fields */ break; @@ -1221,6 +1305,16 @@ POST(domctl){ * domctl->u.hvmcontext.size); break; + case VKI_XEN_DOMCTL_gethvmcontext_partial: + switch (domctl->u.hvmcontext_partial.type) { + case VKI_HVM_SAVE_CODE(CPU): + if ( domctl->u.hvmcontext_partial.buffer.p ) + POST_MEM_WRITE((Addr)domctl->u.hvmcontext_partial.buffer.p, + VKI_HVM_SAVE_LENGTH(CPU)); + break; + } + break; + case VKI_XEN_DOMCTL_scheduler_op: if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_getinfo ) { switch(domctl->u.scheduler_op.sched_id) { @@ -1340,6 +1434,10 @@ POST(domctl){ default: break; } + break; + case VKI_XEN_DOMCTL_mem_event_op: + POST_XEN_DOMCTL_WRITE(mem_event_op, port); + break; } #undef POST_XEN_DOMCTL_WRITE @@ -1355,19 +1453,25 @@ POST(hvm_op) POST_MEM_WRITE((Addr)&((_type*)arg)->_field, \ sizeof(((_type*)arg)->_field)) #define POST_XEN_HVMOP_WRITE(_hvm_op, _field) \ - __PRE_XEN_HVMOP_READ(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field) + __POST_XEN_HVMOP_WRITE(_hvm_op, vki_xen_hvm_ ## _hvm_op ## _t, _field) switch (op) { case VKI_XEN_HVMOP_set_param: case VKI_XEN_HVMOP_set_isa_irq_level: case VKI_XEN_HVMOP_set_pci_link_route: case VKI_XEN_HVMOP_set_mem_type: + case VKI_XEN_HVMOP_set_mem_access: + case VKI_XEN_HVMOP_inject_trap: /* No output paramters */ break; case VKI_XEN_HVMOP_get_param: __POST_XEN_HVMOP_WRITE(get_param, struct vki_xen_hvm_param, value); break; + + case VKI_XEN_HVMOP_get_mem_access: + POST_XEN_HVMOP_WRITE(get_mem_access, hvmmem_access); + break; } #undef __POST_XEN_HVMOP_WRITE #undef POST_XEN_HVMOP_WRITE diff --git a/include/vki/vki-xen-domctl.h b/include/vki/vki-xen-domctl.h index 2f55ce0b94..b5037f202b 100644 --- a/include/vki/vki-xen-domctl.h +++ b/include/vki/vki-xen-domctl.h @@ -261,6 +261,12 @@ struct vki_xen_domctl_max_vcpus { vki_uint32_t max; /* maximum number of vcpus */ }; +struct vki_xen_domctl_ioport_permission { + vki_uint32_t first_port; /* IN */ + vki_uint32_t nr_ports; /* IN */ + vki_uint8_t allow_access; /* IN */ +}; + struct vki_xen_domctl_hypercall_init { vki_xen_uint64_aligned_t gmfn; /* GMFN to be initialised */ }; @@ -294,6 +300,14 @@ struct vki_xen_domctl_hvmcontext { typedef struct vki_xen_domctl_hvmcontext vki_xen_domctl_hvmcontext_t; DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_domctl_hvmcontext_t); +struct vki_xen_domctl_hvmcontext_partial { + vki_uint32_t type; /* IN */ + vki_uint32_t instance; /* IN */ + VKI_XEN_GUEST_HANDLE_64(vki_uint8) buffer; /* IN/OUT buffer */ +}; +typedef struct vki_xen_domctl_hvmcontext_partial vki_xen_domctl_hvmcontext_partial_t; +DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_domctl_hvmcontext_partial_t); + struct vki_xen_domctl_tsc_info { VKI_XEN_GUEST_HANDLE_64(vki_xen_guest_tsc_info_t) out_info; /* OUT */ vki_xen_guest_tsc_info_t info; /* IN */ @@ -310,6 +324,22 @@ struct vki_xen_domctl_address_size { vki_uint32_t size; }; +struct vki_xen_domctl_debug_op { + vki_uint32_t op; /* IN */ + vki_uint32_t vcpu; /* IN */ +}; +typedef struct vki_xen_domctl_debug_op vki_xen_domctl_debug_op_t; + +struct vki_xen_domctl_mem_event_op { + vki_uint32_t op; /* IN */ + vki_uint32_t mode; /* IN */ + vki_uint32_t port; /* OUT */ +}; + +struct vki_xen_domctl_set_access_required { + vki_uint8_t access_required; /* IN */ +}; + struct vki_xen_domctl_set_max_evtchn { vki_uint32_t max_port; }; @@ -344,7 +374,7 @@ struct vki_xen_domctl { //struct vki_xen_domctl_setdebugging setdebugging; //struct vki_xen_domctl_irq_permission irq_permission; //struct vki_xen_domctl_iomem_permission iomem_permission; - //struct vki_xen_domctl_ioport_permission ioport_permission; + struct vki_xen_domctl_ioport_permission ioport_permission; struct vki_xen_domctl_hypercall_init hypercall_init; //struct vki_xen_domctl_arch_setup arch_setup; struct vki_xen_domctl_settimeoffset settimeoffset; @@ -352,7 +382,7 @@ struct vki_xen_domctl { struct vki_xen_domctl_tsc_info tsc_info; //struct vki_xen_domctl_real_mode_area real_mode_area; struct vki_xen_domctl_hvmcontext hvmcontext; - //struct vki_xen_domctl_hvmcontext_partial hvmcontext_partial; + struct vki_xen_domctl_hvmcontext_partial hvmcontext_partial; struct vki_xen_domctl_address_size address_size; //struct vki_xen_domctl_sendtrigger sendtrigger; //struct vki_xen_domctl_get_device_group get_device_group; @@ -364,14 +394,14 @@ struct vki_xen_domctl { //struct vki_xen_domctl_ext_vcpucontext ext_vcpucontext; //struct vki_xen_domctl_set_target set_target; //struct vki_xen_domctl_subscribe subscribe; - //struct vki_xen_domctl_debug_op debug_op; - //struct vki_xen_domctl_mem_event_op mem_event_op; + struct vki_xen_domctl_debug_op debug_op; + struct vki_xen_domctl_mem_event_op mem_event_op; //struct vki_xen_domctl_mem_sharing_op mem_sharing_op; #if defined(__i386__) || defined(__x86_64__) struct vki_xen_domctl_cpuid cpuid; struct vki_xen_domctl_vcpuextstate vcpuextstate; #endif - //struct vki_xen_domctl_set_access_required access_required; + struct vki_xen_domctl_set_access_required access_required; //struct vki_xen_domctl_audit_p2m audit_p2m; //struct vki_xen_domctl_set_virq_handler set_virq_handler; struct vki_xen_domctl_set_max_evtchn set_max_evtchn; diff --git a/include/vki/vki-xen-hvm.h b/include/vki/vki-xen-hvm.h index 19ccbeb816..f26e039114 100644 --- a/include/vki/vki-xen-hvm.h +++ b/include/vki/vki-xen-hvm.h @@ -31,10 +31,39 @@ struct vki_xen_hvm_set_mem_type { vki_xen_domid_t domid; vki_uint16_t hvmmem_type; vki_uint32_t nr; - vki_xen_uint64_aligned_t first_pfn; + vki_uint64_t first_pfn; }; typedef struct vki_xen_hvm_set_mem_type vki_xen_hvm_set_mem_type_t; +#define VKI_XEN_HVMOP_set_mem_access 12 +struct vki_xen_hvm_set_mem_access { + vki_xen_domid_t domid; + vki_uint16_t hvmmem_access; + vki_uint32_t nr; + vki_uint64_t first_pfn; +}; +typedef struct vki_xen_hvm_set_mem_access vki_xen_hvm_set_mem_access_t; + +#define VKI_XEN_HVMOP_get_mem_access 13 +struct vki_xen_hvm_get_mem_access { + vki_xen_domid_t domid; + vki_uint16_t hvmmem_access; /* OUT */ + vki_uint64_t pfn; +}; +typedef struct vki_xen_hvm_get_mem_access vki_xen_hvm_get_mem_access_t; + +#define VKI_XEN_HVMOP_inject_trap 14 +struct vki_xen_hvm_inject_trap { + vki_xen_domid_t domid; + vki_uint32_t vcpuid; + vki_uint32_t vector; + vki_uint32_t type; + vki_uint32_t error_code; + vki_uint32_t insn_len; + vki_uint64_t cr2; +}; +typedef struct vki_xen_hvm_inject_trap vki_xen_hvm_inject_trap_t; + #endif // __VKI_XEN_HVM_H /*--------------------------------------------------------------------*/ diff --git a/include/vki/vki-xen-memory.h b/include/vki/vki-xen-memory.h index 609e648d9e..2690c60c26 100644 --- a/include/vki/vki-xen-memory.h +++ b/include/vki/vki-xen-memory.h @@ -20,6 +20,7 @@ #define VKI_XENMEM_get_pod_target 17 #define VKI_XENMEM_get_sharing_freed_pages 18 #define VKI_XENMEM_get_sharing_shared_pages 19 +#define VKI_XENMEM_access_op 21 #define VKI_XENMEM_claim_pages 24 struct vki_xen_memory_map { @@ -66,6 +67,13 @@ struct vki_xen_remove_from_physmap { vki_xen_pfn_t gpfn; }; +struct vki_xen_mem_event_op { + vki_uint8_t op; + vki_xen_domid_t domain; + vki_uint64_t buffer; + vki_uint64_t gfn; +}; + #endif // __VKI_XEN_MEMORY_H /*--------------------------------------------------------------------*/ diff --git a/include/vki/vki-xen-x86.h b/include/vki/vki-xen-x86.h index 240865b30e..a2d0fb22ae 100644 --- a/include/vki/vki-xen-x86.h +++ b/include/vki/vki-xen-x86.h @@ -123,6 +123,126 @@ struct vki_xen_vcpu_guest_context { typedef struct vki_xen_vcpu_guest_context vki_xen_vcpu_guest_context_t; DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_vcpu_guest_context_t); + +/* HVM_SAVE types and declarations for getcontext_partial */ +# define VKI_DECLARE_HVM_SAVE_TYPE(_x, _code, _type) \ + struct __VKI_HVM_SAVE_TYPE_##_x { _type t; char c[_code]; char cpt[1];} + +#define VKI_HVM_SAVE_TYPE(_x) typeof (((struct __VKI_HVM_SAVE_TYPE_##_x *)(0))->t) +#define VKI_HVM_SAVE_LENGTH(_x) (sizeof (VKI_HVM_SAVE_TYPE(_x))) +#define VKI_HVM_SAVE_CODE(_x) (sizeof (((struct __VKI_HVM_SAVE_TYPE_##_x *)(0))->c)) + +struct vki_hvm_hw_cpu { + vki_uint8_t fpu_regs[512]; + + vki_uint64_t rax; + vki_uint64_t rbx; + vki_uint64_t rcx; + vki_uint64_t rdx; + vki_uint64_t rbp; + vki_uint64_t rsi; + vki_uint64_t rdi; + vki_uint64_t rsp; + vki_uint64_t r8; + vki_uint64_t r9; + vki_uint64_t r10; + vki_uint64_t r11; + vki_uint64_t r12; + vki_uint64_t r13; + vki_uint64_t r14; + vki_uint64_t r15; + + vki_uint64_t rip; + vki_uint64_t rflags; + + vki_uint64_t cr0; + vki_uint64_t cr2; + vki_uint64_t cr3; + vki_uint64_t cr4; + + vki_uint64_t dr0; + vki_uint64_t dr1; + vki_uint64_t dr2; + vki_uint64_t dr3; + vki_uint64_t dr6; + vki_uint64_t dr7; + + vki_uint32_t cs_sel; + vki_uint32_t ds_sel; + vki_uint32_t es_sel; + vki_uint32_t fs_sel; + vki_uint32_t gs_sel; + vki_uint32_t ss_sel; + vki_uint32_t tr_sel; + vki_uint32_t ldtr_sel; + + vki_uint32_t cs_limit; + vki_uint32_t ds_limit; + vki_uint32_t es_limit; + vki_uint32_t fs_limit; + vki_uint32_t gs_limit; + vki_uint32_t ss_limit; + vki_uint32_t tr_limit; + vki_uint32_t ldtr_limit; + vki_uint32_t idtr_limit; + vki_uint32_t gdtr_limit; + + vki_uint64_t cs_base; + vki_uint64_t ds_base; + vki_uint64_t es_base; + vki_uint64_t fs_base; + vki_uint64_t gs_base; + vki_uint64_t ss_base; + vki_uint64_t tr_base; + vki_uint64_t ldtr_base; + vki_uint64_t idtr_base; + vki_uint64_t gdtr_base; + + vki_uint32_t cs_arbytes; + vki_uint32_t ds_arbytes; + vki_uint32_t es_arbytes; + vki_uint32_t fs_arbytes; + vki_uint32_t gs_arbytes; + vki_uint32_t ss_arbytes; + vki_uint32_t tr_arbytes; + vki_uint32_t ldtr_arbytes; + + vki_uint64_t sysenter_cs; + vki_uint64_t sysenter_esp; + vki_uint64_t sysenter_eip; + + /* msr for em64t */ + vki_uint64_t shadow_gs; + + /* msr content saved/restored. */ + vki_uint64_t msr_flags; + vki_uint64_t msr_lstar; + vki_uint64_t msr_star; + vki_uint64_t msr_cstar; + vki_uint64_t msr_syscall_mask; + vki_uint64_t msr_efer; + vki_uint64_t msr_tsc_aux; + + /* guest's idea of what rdtsc() would return */ + vki_uint64_t tsc; + + /* pending event, if any */ + union { + vki_uint32_t pending_event; + struct { + vki_uint8_t pending_vector:8; + vki_uint8_t pending_type:3; + vki_uint8_t pending_error_valid:1; + vki_uint32_t pending_reserved:19; + vki_uint8_t pending_valid:1; + }; + }; + /* error code for pending event */ + vki_uint32_t error_code; +}; + +VKI_DECLARE_HVM_SAVE_TYPE(CPU, 2, struct vki_hvm_hw_cpu); + #endif // __VKI_XEN_H /*--------------------------------------------------------------------*/