This set of patches teaches valgrind about new hypercalls. Valgrind can now completely inspect xc_domain_save()/restore() Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> CC: Ian Campbell <Ian.Campbell@citrix.com> -- 1.7.10.4
Andrew Cooper
2013-Nov-28 18:56 UTC
[PATCH 01/13] xen: Fix XEN_SYSCTL_getdomaininfolist for version 0xa
Also add a default case so future bumps of the sysctl interface version dont result in spurious passes of the IOCTL handler. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 17 +++++++++++++++++ include/vki/vki-xen-sysctl.h | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index ce300e8..0314451 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -401,6 +401,17 @@ PRE(sysctl) { PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, max_domains); PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, buffer); break; + case 0x0000000a: + PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, first_domain); + PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, max_domains); + PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, buffer); + break; + default: + VG_(dmsg)("WARNING: XEN_SYSCTL_getdomaininfolist for sysctl version " + "%"PRIx32" not implemented yet\n", + sysctl->interface_version); + SET_STATUS_Failure(VKI_EINVAL); + return; } break; @@ -801,6 +812,12 @@ POST(sysctl) sizeof(*sysctl->u.getdomaininfolist_00000009.buffer.p) * sysctl->u.getdomaininfolist_00000009.num_domains); break; + case 0x0000000a: + POST_XEN_SYSCTL_WRITE(getdomaininfolist_0000000a, num_domains); + POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_0000000a.buffer.p, + sizeof(*sysctl->u.getdomaininfolist_0000000a.buffer.p) + * sysctl->u.getdomaininfolist_0000000a.num_domains); + break; } break; diff --git a/include/vki/vki-xen-sysctl.h b/include/vki/vki-xen-sysctl.h index 453752c..06cbaf6 100644 --- a/include/vki/vki-xen-sysctl.h +++ b/include/vki/vki-xen-sysctl.h @@ -56,6 +56,15 @@ struct vki_xen_sysctl_getdomaininfolist_00000009 { vki_uint32_t num_domains; }; +struct vki_xen_sysctl_getdomaininfolist_0000000a { + /* IN variables. */ + vki_xen_domid_t first_domain; + vki_uint32_t max_domains; + VKI_XEN_GUEST_HANDLE_64(vki_xen_domctl_getdomaininfo_00000009_t) buffer; + /* OUT variables. */ + vki_uint32_t num_domains; +}; + #define VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE 1 /* C */ #define VKI_XEN_SYSCTL_CPUPOOL_OP_DESTROY 2 /* D */ #define VKI_XEN_SYSCTL_CPUPOOL_OP_INFO 3 /* I */ @@ -139,6 +148,7 @@ struct vki_xen_sysctl { //struct vki_xen_sysctl_perfc_op perfc_op; struct vki_xen_sysctl_getdomaininfolist_00000008 getdomaininfolist_00000008; struct vki_xen_sysctl_getdomaininfolist_00000009 getdomaininfolist_00000009; + struct vki_xen_sysctl_getdomaininfolist_0000000a getdomaininfolist_0000000a; //struct vki_xen_sysctl_debug_keys debug_keys; //struct vki_xen_sysctl_getcpuinfo getcpuinfo; //struct vki_xen_sysctl_availheap availheap; -- 1.7.10.4
Andrew Cooper
2013-Nov-28 18:56 UTC
[PATCH 02/13] xen: Infratructure for XEN_TMEM_* hypercalls
and an implementation of XEN_TMEM_control save_begin. Xen will read various fields at various time, but write nothing back for a save_begin subop. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 75 ++++++++++++++++++++++++++++++++++++- include/vki/vki-xen-tmem.h | 75 +++++++++++++++++++++++++++++++++++++ include/vki/vki-xen.h | 2 + 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 include/vki/vki-xen-tmem.h diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 0314451..e80c05d 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -670,6 +670,61 @@ PRE(hvm_op) #undef PRE_XEN_HVMOP_READ } +PRE(tmem_op) +{ + struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1; + + PRINT("__HYPERVISOR_tmem_op ( %d )", tmem->cmd); + + /* Common part for xen_tmem_op: + * vki_uint32_t cmd; + */ + PRE_MEM_READ("__HYPERVISOR_tmem_op cmd", ARG1, sizeof(vki_uint32_t)); + + +#define __PRE_XEN_TMEMOP_READ(_tmem, _union, _field) \ + PRE_MEM_READ("XEN_tmem_op_" #_tmem " u." #_union "." #_field, \ + (Addr)&tmem->u._union._field, \ + sizeof(tmem->u._union._field)) +#define PRE_XEN_TMEMOP_READ(_tmem, _field) \ + __PRE_XEN_TMEMOP_READ(_tmem, _tmem, _field) + + switch(tmem->cmd) { + + case VKI_XEN_TMEM_control: + + /* Common part for control hypercall: + * vki_int32_t pool_id; + * vki_uint32_t subop; + */ + PRE_MEM_READ("__HYPERVISOR_tmem_op pool_id", + (Addr)&tmem->pool_id, sizeof(&tmem->pool_id)); + PRE_XEN_TMEMOP_READ(ctrl, subop); + + switch (tmem->u.ctrl.subop) { + + case VKI_XEN_TMEMC_save_begin: + PRE_XEN_TMEMOP_READ(ctrl, cli_id); + PRE_XEN_TMEMOP_READ(ctrl, arg1); + PRE_XEN_TMEMOP_READ(ctrl, buf); + break; + + default: + bad_subop(tid, layout, arrghs, status, flags, + "__HYPERVISOR_tmem_op_control", tmem->u.ctrl.subop); + } + + break; + + default: + bad_subop(tid, layout, arrghs, status, flags, + "__HYPERVISOR_tmem_op", ARG1); + } + +#undef PRE_XEN_TMEMOP_READ +#undef __PRE_XEN_TMEMOP_READ +} + POST(memory_op) { switch (ARG1) { @@ -1080,6 +1135,24 @@ POST(hvm_op) #undef POST_XEN_HVMOP_WRITE } +POST(tmem_op) +{ + struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1; + + switch(tmem->cmd) { + + case VKI_XEN_TMEM_control: + + switch(tmem->u.ctrl.subop) { + /* No outputs */ + case VKI_XEN_TMEMC_save_begin: + break; + } + + break; + } +} + typedef struct { SyscallTableEntry entry; @@ -1140,7 +1213,7 @@ static XenHypercallTableEntry hypercall_table[] = { HYPXY(__VKI_XEN_sysctl, sysctl, 1), // 35 HYPXY(__VKI_XEN_domctl, domctl, 1), // 36 // __VKI_XEN_kexec_op // 37 - // __VKI_XEN_tmem_op // 38 + HYPXY(__VKI_XEN_tmem_op, tmem_op, 1), // 38 }; static void bad_before ( ThreadId tid, diff --git a/include/vki/vki-xen-tmem.h b/include/vki/vki-xen-tmem.h new file mode 100644 index 0000000..ab402f0 --- /dev/null +++ b/include/vki/vki-xen-tmem.h @@ -0,0 +1,75 @@ +#ifndef __VKI_XEN_TMEM_H +#define __VKI_XEN_TMEM_H + +typedef VKI_XEN_GUEST_HANDLE(char) vki_xen_tmem_cli_va_t; + + +/* version of ABI */ +#define VKI_XEN_TMEM_spec_version 1 + +/* Commands to HYPERVISOR_tmem_op() */ +#define VKI_XEN_TMEM_control 0 +#define VKI_XEN_TMEM_new_pool 1 +#define VKI_XEN_TMEM_destroy_pool 2 +#define VKI_XEN_TMEM_new_page 3 +#define VKI_XEN_TMEM_put_page 4 +#define VKI_XEN_TMEM_get_page 5 +#define VKI_XEN_TMEM_flush_page 6 +#define VKI_XEN_TMEM_flush_object 7 +#define VKI_XEN_TMEM_read 8 +#define VKI_XEN_TMEM_write 9 +#define VKI_XEN_TMEM_xchg 10 +/* Privileged commands to HYPERVISOR_tmem_op() */ +#define VKI_XEN_tmem_auth 101 +#define VKI_XEN_tmem_restore_new 102 + +/* for cmd = TMEM_CONTROL */ +struct vki_xen_tmem_ctrl { + vki_uint32_t subop; + +/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */ +#define VKI_XEN_TMEMC_thaw 0 +#define VKI_XEN_TMEMC_freeze 1 +#define VKI_XEN_TMEMC_flush 2 +#define VKI_XEN_TMEMC_destroy 3 +#define VKI_XEN_TMEMC_list 4 +#define VKI_XEN_TMEMC_set_weight 5 +#define VKI_XEN_TMEMC_set_cap 6 +#define VKI_XEN_TMEMC_set_compress 7 +#define VKI_XEN_TMEMC_query_freeable_mb 8 +#define VKI_XEN_TMEMC_save_begin 10 +#define VKI_XEN_TMEMC_save_get_version 11 +#define VKI_XEN_TMEMC_save_get_maxpools 12 +#define VKI_XEN_TMEMC_save_get_client_weight 13 +#define VKI_XEN_TMEMC_save_get_client_cap 14 +#define VKI_XEN_TMEMC_save_get_client_flags 15 +#define VKI_XEN_TMEMC_save_get_pool_flags 16 +#define VKI_XEN_TMEMC_save_get_pool_npages 17 +#define VKI_XEN_TMEMC_save_get_pool_uuid 18 +#define VKI_XEN_TMEMC_save_get_next_page 19 +#define VKI_XEN_TMEMC_save_get_next_inv 20 +#define VKI_XEN_TMEMC_save_end 21 +#define VKI_XEN_TMEMC_restore_begin 30 +#define VKI_XEN_TMEMC_restore_put_page 32 +#define VKI_XEN_TMEMC_restore_flush_page 33 + + vki_uint32_t cli_id; + vki_uint32_t arg1; + vki_uint32_t arg2; + vki_uint64_t oid[3]; + vki_xen_tmem_cli_va_t buf; +}; + +struct vki_xen_tmem_op { + vki_uint32_t cmd; + vki_int32_t pool_id; + union { + struct vki_xen_tmem_ctrl ctrl; + } u; +}; + +#endif // __VKI_XEN_TMEM_H + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/include/vki/vki-xen.h b/include/vki/vki-xen.h index 87fbb4f..e2f3d81 100644 --- a/include/vki/vki-xen.h +++ b/include/vki/vki-xen.h @@ -58,6 +58,7 @@ typedef vki_uint16_t vki_xen_domid_t; #endif DEFINE_VKI_XEN_GUEST_HANDLE(void); +DEFINE_VKI_XEN_GUEST_HANDLE(char); DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_pfn_t); __DEFINE_VKI_XEN_GUEST_HANDLE(vki_ulong, unsigned long); @@ -84,6 +85,7 @@ struct vki_xenctl_bitmap { #include <vki/vki-xen-gnttab.h> #include <vki/vki-xen-version.h> #include <vki/vki-xen-hvm.h> +#include <vki/vki-xen-tmem.h> #endif // __VKI_XEN_H -- 1.7.10.4
Xen does not read or write any memory for this hypercall Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index e80c05d..08c92b0 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -93,6 +93,11 @@ PRE(memory_op) PRINT("__HYPERVISOR_memory_op ( %ld, %lx )", ARG1, ARG2); switch (ARG1) { + + case VKI_XENMEM_maximum_ram_page: + /* No inputs */ + break; + case VKI_XENMEM_set_memory_map: { struct vki_xen_foreign_memory_map *arg (struct vki_xen_foreign_memory_map *)ARG2; @@ -728,6 +733,7 @@ PRE(tmem_op) POST(memory_op) { switch (ARG1) { + case VKI_XENMEM_maximum_ram_page: case VKI_XENMEM_set_memory_map: case VKI_XENMEM_decrease_reservation: case VKI_XENMEM_claim_pages: -- 1.7.10.4
Xen reads a 16 bit domid from the pointer provided in ARG2, but does not write anything back. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 08c92b0..99d5e91 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -98,6 +98,11 @@ PRE(memory_op) /* No inputs */ break; + case VKI_XENMEM_maximum_gpfn: + PRE_MEM_READ("XENMEM_maximum_gpfn domid", + (Addr)ARG2, sizeof(vki_xen_domid_t)); + break; + case VKI_XENMEM_set_memory_map: { struct vki_xen_foreign_memory_map *arg (struct vki_xen_foreign_memory_map *)ARG2; @@ -737,6 +742,7 @@ POST(memory_op) case VKI_XENMEM_set_memory_map: case VKI_XENMEM_decrease_reservation: case VKI_XENMEM_claim_pages: + case VKI_XENMEM_maximum_gpfn: /* No outputs */ break; case VKI_XENMEM_increase_reservation: -- 1.7.10.4
The XENMEM_machphys_mfn_list implementation reads ''max_extents'' and ''extents_start''. It writes to the array at ''extents_start'', and writes the number of extents written into the ''nr_extents'' field. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 19 +++++++++++++++++++ include/vki/vki-xen-memory.h | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 99d5e91..76e8b4a 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -103,6 +103,16 @@ PRE(memory_op) (Addr)ARG2, sizeof(vki_xen_domid_t)); break; + case VKI_XENMEM_machphys_mfn_list: { + struct vki_xen_machphys_mfn_list *arg + (struct vki_xen_machphys_mfn_list *)ARG2; + PRE_MEM_READ("XENMEM_machphys_mfn_list max_extents", + (Addr)&arg->max_extents, sizeof(arg->max_extents)); + PRE_MEM_READ("XENMEM_machphys_mfn_list extent_start", + (Addr)&arg->extent_start, sizeof(arg->extent_start)); + break; + } + case VKI_XENMEM_set_memory_map: { struct vki_xen_foreign_memory_map *arg (struct vki_xen_foreign_memory_map *)ARG2; @@ -755,6 +765,15 @@ POST(memory_op) break; } + case VKI_XENMEM_machphys_mfn_list: { + struct vki_xen_machphys_mfn_list *arg + (struct vki_xen_machphys_mfn_list *)ARG2; + POST_MEM_WRITE((Addr)&arg->nr_extents, sizeof(arg->nr_extents)); + POST_MEM_WRITE((Addr)arg->extent_start.p, + sizeof(vki_xen_pfn_t) * arg->nr_extents); + break; + } + case VKI_XENMEM_get_sharing_freed_pages: case VKI_XENMEM_get_sharing_shared_pages: /* No outputs */ diff --git a/include/vki/vki-xen-memory.h b/include/vki/vki-xen-memory.h index eac7871..208d642 100644 --- a/include/vki/vki-xen-memory.h +++ b/include/vki/vki-xen-memory.h @@ -40,6 +40,12 @@ struct xen_memory_reservation { vki_xen_domid_t domid; }; +struct vki_xen_machphys_mfn_list { + unsigned int max_extents; /* IN */ + VKI_XEN_GUEST_HANDLE(vki_xen_pfn_t) extent_start; /* OUT */ + unsigned int nr_extents; /* OUT */ +}; + #endif // __VKI_XEN_MEMORY_H /*--------------------------------------------------------------------*/ -- 1.7.10.4
Xen reads the entire structure, and if the space is _gmfn, will write the structure back Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> -- TODO: verifiy whether the POST_MEM_WRITE is requred if it is entirely contained within the space identified by the PRE_MEM_READs --- coregrind/m_syswrap/syswrap-xen.c | 23 +++++++++++++++++++++++ include/vki/vki-xen-memory.h | 15 +++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 76e8b4a..60a5f3d 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -172,6 +172,22 @@ PRE(memory_op) break; } + case VKI_XENMEM_add_to_physmap: { + struct vki_xen_add_to_physmap *arg + (struct vki_xen_add_to_physmap *)ARG2; + PRE_MEM_READ("XENMEM_add_to_physmap domid", + (Addr)&arg->domid, sizeof(arg->domid)); + PRE_MEM_READ("XENMEM_add_to_physmap size", + (Addr)&arg->size, sizeof(arg->size)); + PRE_MEM_READ("XENMEM_add_to_physmap space", + (Addr)&arg->space, sizeof(arg->space)); + PRE_MEM_READ("XENMEM_add_to_physmap idx", + (Addr)&arg->idx, sizeof(arg->idx)); + PRE_MEM_READ("XENMEM_add_to_physmap gpfn", + (Addr)&arg->gpfn, sizeof(arg->gpfn)); + break; + }; + case VKI_XENMEM_get_sharing_freed_pages: case VKI_XENMEM_get_sharing_shared_pages: break; @@ -774,6 +790,13 @@ POST(memory_op) break; } + case VKI_XENMEM_add_to_physmap: { + struct vki_xen_add_to_physmap *arg + (struct vki_xen_add_to_physmap *)ARG2; + if (arg->space == VKI_XENMAPSPACE_gmfn_range) + POST_MEM_WRITE(ARG2, sizeof(*arg)); + } + case VKI_XENMEM_get_sharing_freed_pages: case VKI_XENMEM_get_sharing_shared_pages: /* No outputs */ diff --git a/include/vki/vki-xen-memory.h b/include/vki/vki-xen-memory.h index 208d642..d7e8df5 100644 --- a/include/vki/vki-xen-memory.h +++ b/include/vki/vki-xen-memory.h @@ -46,6 +46,21 @@ struct vki_xen_machphys_mfn_list { unsigned int nr_extents; /* OUT */ }; +struct vki_xen_add_to_physmap { + vki_xen_domid_t domid; + vki_uint16_t size; + +#define VKI_XENMAPSPACE_shared_info 0 +#define VKI_XENMAPSPACE_grant_table 1 +#define VKI_XENMAPSPACE_gmfn 2 +#define VKI_XENMAPSPACE_gmfn_range 3 +#define VKI_XENMAPSPACE_gmfn_foreign 4 + + unsigned int space; + vki_xen_ulong_t idx; + vki_xen_pfn_t gpfn; +}; + #endif // __VKI_XEN_MEMORY_H /*--------------------------------------------------------------------*/ -- 1.7.10.4
Andrew Cooper
2013-Nov-28 18:56 UTC
[PATCH 07/13] xen: XENMEM_remove_from_physmap hypercall
Xen reads the entire structure and writes nothing. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 10 ++++++++++ include/vki/vki-xen-memory.h | 5 +++++ 2 files changed, 15 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 60a5f3d..f99b1ab 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -188,6 +188,15 @@ PRE(memory_op) break; }; + case VKI_XENMEM_remove_from_physmap: { + struct vki_xen_remove_from_physmap *arg + (struct vki_xen_remove_from_physmap *)ARG2; + PRE_MEM_READ("XENMEM_remove_from_physmap domid", + (Addr)&arg->domid, sizeof(arg->domid)); + PRE_MEM_READ("XENMEM_remove_from_physmap gpfn", + (Addr)&arg->gpfn, sizeof(arg->gpfn)); + } + case VKI_XENMEM_get_sharing_freed_pages: case VKI_XENMEM_get_sharing_shared_pages: break; @@ -769,6 +778,7 @@ POST(memory_op) case VKI_XENMEM_decrease_reservation: case VKI_XENMEM_claim_pages: case VKI_XENMEM_maximum_gpfn: + case VKI_XENMEM_remove_from_physmap: /* No outputs */ break; case VKI_XENMEM_increase_reservation: diff --git a/include/vki/vki-xen-memory.h b/include/vki/vki-xen-memory.h index d7e8df5..609e648 100644 --- a/include/vki/vki-xen-memory.h +++ b/include/vki/vki-xen-memory.h @@ -61,6 +61,11 @@ struct vki_xen_add_to_physmap { vki_xen_pfn_t gpfn; }; +struct vki_xen_remove_from_physmap { + vki_xen_domid_t domid; + vki_xen_pfn_t gpfn; +}; + #endif // __VKI_XEN_MEMORY_H /*--------------------------------------------------------------------*/ -- 1.7.10.4
The semantics of XEN_DOMCTL_gethvmcontext are little interesting. If the ''buffer'' field of the structure is NULL, the hypercall is a request for the required buffer size, which written into the ''size'' paramater. If ''buffer'' is non NULL, Xen will write to the buffer, and update ''size'' with the amount of data written. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 19 +++++++++++++++++++ include/vki/vki-xen-domctl.h | 9 ++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index f99b1ab..f5053bb 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -581,6 +581,15 @@ PRE(domctl) PRE_XEN_DOMCTL_READ(createdomain, flags); break; + case VKI_XEN_DOMCTL_gethvmcontext: + /* Xen unconditionally reads the ''buffer'' pointer */ + __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, buffer); + /* Xen only consumes ''size'' if ''buffer'' is non NULL. A NULL + * buffer is a request for the required size. */ + if ( domctl->u.hvmcontext.buffer.p ) + __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, size); + break; + case VKI_XEN_DOMCTL_max_mem: PRE_XEN_DOMCTL_READ(max_mem, max_memkb); break; @@ -1077,6 +1086,16 @@ POST(domctl){ POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu); break; + case VKI_XEN_DOMCTL_gethvmcontext: + /* Xen unconditionally writes size... */ + __POST_XEN_DOMCTL_WRITE(gethvmcontext, hvmcontext, size); + /* ...but only writes to the buffer if it was non NULL */ + if ( domctl->u.hvmcontext.buffer.p ) + POST_MEM_WRITE((Addr)domctl->u.hvmcontext.buffer.p, + sizeof(*domctl->u.hvmcontext.buffer.p) + * domctl->u.hvmcontext.size); + 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) { diff --git a/include/vki/vki-xen-domctl.h b/include/vki/vki-xen-domctl.h index 815e0a7..24191bd 100644 --- a/include/vki/vki-xen-domctl.h +++ b/include/vki/vki-xen-domctl.h @@ -243,6 +243,13 @@ struct vki_xen_guest_tsc_info { typedef struct vki_xen_guest_tsc_info vki_xen_guest_tsc_info_t; DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_guest_tsc_info_t); +struct vki_xen_domctl_hvmcontext { + vki_uint32_t size; /* IN/OUT size of buffer */ + VKI_XEN_GUEST_HANDLE_64(vki_uint8) buffer; /* IN/OUT */ +}; +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_tsc_info { VKI_XEN_GUEST_HANDLE_64(vki_xen_guest_tsc_info_t) out_info; /* OUT */ vki_xen_guest_tsc_info_t info; /* IN */ @@ -291,7 +298,7 @@ struct vki_xen_domctl { //struct vki_xen_domctl_disable_migrate disable_migrate; 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 hvmcontext; //struct vki_xen_domctl_hvmcontext_partial hvmcontext_partial; struct vki_xen_domctl_address_size address_size; //struct vki_xen_domctl_sendtrigger sendtrigger; -- 1.7.10.4
Andrew Cooper
2013-Nov-28 18:56 UTC
[PATCH 09/13] xen: XEN_DOMCTL_getpageframeinfo3 hypercall
Xen reads ''num'' and the ''array'' pointer from ARG1, and proceeds to read and modify-in-place the entire userspace array. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 14 ++++++++++++++ include/vki/vki-xen-domctl.h | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index f5053bb..116276f 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -673,6 +673,14 @@ PRE(domctl) (Addr)&domctl->u.cpuid, sizeof(domctl->u.cpuid)); break; + case VKI_XEN_DOMCTL_getpageframeinfo3: + PRE_XEN_DOMCTL_READ(getpageframeinfo3, num); + PRE_XEN_DOMCTL_READ(getpageframeinfo3, array.p); + PRE_MEM_READ("XEN_DOMCTL_getpageframeinfo3 *u.getpageframeinfo3.array.p", + (Addr)domctl->u.getpageframeinfo3.array.p, + domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t)); + break; + case VKI_XEN_DOMCTL_getvcpuextstate: __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, vcpu); __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, xfeature_mask); @@ -1182,6 +1190,12 @@ POST(domctl){ __POST_XEN_DOMCTL_WRITE(getvcpucontext, vcpucontext, ctxt.p); break; + case VKI_XEN_DOMCTL_getpageframeinfo3: + POST_MEM_WRITE((Addr)domctl->u.getpageframeinfo3.array.p, + domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t)); + break; + + case VKI_XEN_DOMCTL_getvcpuextstate: __POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, xfeature_mask); __POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, size); diff --git a/include/vki/vki-xen-domctl.h b/include/vki/vki-xen-domctl.h index 24191bd..67dc2ef 100644 --- a/include/vki/vki-xen-domctl.h +++ b/include/vki/vki-xen-domctl.h @@ -163,6 +163,10 @@ struct vki_xen_domctl_nodeaffinity { typedef struct vki_xen_domctl_nodeaffinity vki_xen_domctl_nodeaffinity_t; DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_domctl_nodeaffinity_t); +struct vki_xen_domctl_getpageframeinfo3 { + vki_xen_uint64_aligned_t num; /* IN */ + VKI_XEN_GUEST_HANDLE_64(vki_xen_pfn_t) array; /* IN/OUT */ +}; struct vki_xen_domctl_vcpuaffinity { vki_uint32_t vcpu; /* IN */ @@ -278,7 +282,7 @@ struct vki_xen_domctl { //struct vki_xen_domctl_getmemlist getmemlist; //struct vki_xen_domctl_getpageframeinfo getpageframeinfo; //struct vki_xen_domctl_getpageframeinfo2 getpageframeinfo2; - //struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3; + struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3; struct vki_xen_domctl_nodeaffinity nodeaffinity; struct vki_xen_domctl_vcpuaffinity vcpuaffinity; //struct vki_xen_domctl_shadow_op shadow_op; -- 1.7.10.4
Xen reads ''num'' and ''array'' from the structure, and reads the entire buffer. Nothing gets written back. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 116276f..ea4a7c0 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -590,6 +590,14 @@ PRE(domctl) __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, size); break; + case VKI_XEN_DOMCTL_sethvmcontext: + __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, size); + __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, buffer); + PRE_MEM_READ("XEN_DOMCTL_sethvmcontext *buffer", + (Addr)domctl->u.hvmcontext.buffer.p, + domctl->u.hvmcontext.size); + break; + case VKI_XEN_DOMCTL_max_mem: PRE_XEN_DOMCTL_READ(max_mem, max_memkb); break; @@ -1068,6 +1076,7 @@ POST(domctl){ case VKI_XEN_DOMCTL_setnodeaffinity: case VKI_XEN_DOMCTL_set_cpuid: case VKI_XEN_DOMCTL_unpausedomain: + case VKI_XEN_DOMCTL_sethvmcontext: /* No output fields */ break; -- 1.7.10.4
And some of the sub-subops. It is a little hacky given the legacy way of having several methods of enabling/disbling LOG_DIRTY mode. Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 64 +++++++++++++++++++++++++++++++++++++ include/vki/vki-xen-domctl.h | 36 ++++++++++++++++++++- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index ea4a7c0..056f2b8 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -696,6 +696,49 @@ PRE(domctl) __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer); break; + case VKI_XEN_DOMCTL_shadow_op: + PRE_XEN_DOMCTL_READ(shadow_op, op); + + switch(domctl->u.shadow_op.op) + { + case VKI_XEN_DOMCTL_SHADOW_OP_OFF: + /* No further inputs */ + break; + + case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE: + PRE_XEN_DOMCTL_READ(shadow_op, mode); + switch(domctl->u.shadow_op.mode) + { + case XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY: + goto domctl_shadow_op_enable_logdirty; + + + default: + bad_subop(tid, layout, arrghs, status, flags, + "__HYPERVISOR_domctl shadowop mode", + domctl->u.shadow_op.mode); + break; + } + + case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY: + domctl_shadow_op_enable_logdirty: + /* No further inputs */ + break; + + case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: + case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: + PRE_XEN_DOMCTL_READ(shadow_op, dirty_bitmap); + PRE_XEN_DOMCTL_READ(shadow_op, pages); + break; + + default: + bad_subop(tid, layout, arrghs, status, flags, + "__HYPERVISOR_domctl shadow(10)", + domctl->u.shadow_op.op); + break; + } + break; + default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl", domctl->cmd); @@ -1212,6 +1255,27 @@ POST(domctl){ domctl->u.vcpuextstate.size); break; + case VKI_XEN_DOMCTL_shadow_op: + switch(domctl->u.shadow_op.op) + { + case VKI_XEN_DOMCTL_SHADOW_OP_OFF: + /* No outputs */ + break; + + case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: + case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: + POST_XEN_DOMCTL_WRITE(shadow_op, pages); + POST_XEN_DOMCTL_WRITE(shadow_op, stats.fault_count); + POST_XEN_DOMCTL_WRITE(shadow_op, stats.dirty_count); + if(domctl->u.shadow_op.dirty_bitmap.p) + POST_MEM_WRITE((Addr)domctl->u.shadow_op.dirty_bitmap.p, + domctl->u.shadow_op.pages * sizeof(vki_uint8_t)); + break; + + default: + break; + } + break; } #undef POST_XEN_DOMCTL_WRITE #undef __POST_XEN_DOMCTL_WRITE diff --git a/include/vki/vki-xen-domctl.h b/include/vki/vki-xen-domctl.h index 67dc2ef..7cce4af 100644 --- a/include/vki/vki-xen-domctl.h +++ b/include/vki/vki-xen-domctl.h @@ -173,6 +173,40 @@ struct vki_xen_domctl_vcpuaffinity { struct vki_xenctl_bitmap cpumap; /* IN/OUT */ }; +struct vki_xen_domctl_shadow_op_stats { + vki_uint32_t fault_count; + vki_uint32_t dirty_count; +}; + +/* vki_xen_domctl_shadow_op.op is an utter mess for compatibily reasons. */ + +struct vki_xen_domctl_shadow_op { + vki_uint32_t op; /* IN */ + +#define VKI_XEN_DOMCTL_SHADOW_OP_OFF 0 +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE 32 +#define VKI_XEN_DOMCTL_SHADOW_OP_CLEAN 11 +#define VKI_XEN_DOMCTL_SHADOW_OP_PEEK 12 +#define VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 +#define VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 + +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1 +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2 +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3 + + vki_uint32_t mode; + +#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1) +#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2) +#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3) +#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4) + + vki_uint32_t mb; + VKI_XEN_GUEST_HANDLE_64(vki_uint8) dirty_bitmap; + vki_xen_uint64_aligned_t pages; + struct vki_xen_domctl_shadow_op_stats stats; +}; + struct vki_xen_domctl_max_mem { /* IN variables. */ vki_xen_uint64_aligned_t max_memkb; @@ -285,7 +319,7 @@ struct vki_xen_domctl { struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3; struct vki_xen_domctl_nodeaffinity nodeaffinity; struct vki_xen_domctl_vcpuaffinity vcpuaffinity; - //struct vki_xen_domctl_shadow_op shadow_op; + struct vki_xen_domctl_shadow_op shadow_op; struct vki_xen_domctl_max_mem max_mem; struct vki_xen_domctl_vcpucontext vcpucontext; struct vki_xen_domctl_getvcpuinfo getvcpuinfo; -- 1.7.10.4
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 17 +++++++++++++++++ include/vki/vki-xen-sysctl.h | 23 ++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index 056f2b8..ffe4e22 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -433,6 +433,18 @@ PRE(sysctl) { __PRE_XEN_SYSCTL_READ(_sysctl, _sysctl, _field) switch (sysctl->cmd) { + case VKI_XEN_SYSCTL_readconsole: + /* These are all unconditionally read */ + PRE_XEN_SYSCTL_READ(readconsole, clear); + PRE_XEN_SYSCTL_READ(readconsole, incremental); + PRE_XEN_SYSCTL_READ(readconsole, buffer); + PRE_XEN_SYSCTL_READ(readconsole, count); + + /* ''index'' only read if ''incremental'' is nonzero */ + if (sysctl->u.readconsole.incremental) + PRE_XEN_SYSCTL_READ(readconsole, index); + break; + case VKI_XEN_SYSCTL_getdomaininfolist: switch (sysctl->interface_version) { @@ -984,6 +996,11 @@ POST(sysctl) __POST_XEN_SYSCTL_WRITE(_sysctl, _sysctl, _field) switch (sysctl->cmd) { + case VKI_XEN_SYSCTL_readconsole: + POST_MEM_WRITE((Addr)sysctl->u.readconsole.buffer.p, + sysctl->u.readconsole.count * sizeof(char)); + break; + case VKI_XEN_SYSCTL_getdomaininfolist: switch (sysctl->interface_version) { diff --git a/include/vki/vki-xen-sysctl.h b/include/vki/vki-xen-sysctl.h index 06cbaf6..f406bd0 100644 --- a/include/vki/vki-xen-sysctl.h +++ b/include/vki/vki-xen-sysctl.h @@ -38,6 +38,27 @@ #define VKI_XEN_SYSCTL_scheduler_op 19 #define VKI_XEN_SYSCTL_coverage_op 20 +struct vki_xen_sysctl_readconsole { + /* IN */ + vki_uint8_t clear; + vki_uint8_t incremental; + + vki_uint8_t pad0, pad1; + + /* + * IN: Start index for consumption if @incremental. + * OUT: End index after consuming from the console. + */ + vki_uint32_t index; + VKI_XEN_GUEST_HANDLE_64(char) buffer; /* IN */ + + /* + * IN: size of buffer. + * OUT: bytes written into buffer. + */ + vki_uint32_t count; +}; + struct vki_xen_sysctl_getdomaininfolist_00000008 { /* IN variables. */ vki_xen_domid_t first_domain; @@ -138,7 +159,7 @@ struct vki_xen_sysctl { vki_uint32_t cmd; vki_uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */ union { - //struct vki_xen_sysctl_readconsole readconsole; + struct vki_xen_sysctl_readconsole readconsole; //struct vki_xen_sysctl_tbuf_op tbuf_op; struct vki_xen_sysctl_physinfo_00000008 physinfo_00000008; struct vki_xen_sysctl_physinfo_0000000a physinfo_0000000a; -- 1.7.10.4
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> --- coregrind/m_syswrap/syswrap-xen.c | 12 ++++++++++++ include/vki/vki-xen-sysctl.h | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c index ffe4e22..7561dda 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -472,6 +472,14 @@ PRE(sysctl) { } break; + case VKI_XEN_SYSCTL_debug_keys: + PRE_XEN_SYSCTL_READ(debug_keys, keys); + PRE_XEN_SYSCTL_READ(debug_keys, nr_keys); + PRE_MEM_READ("XEN_SYSCTL_debug_keys *keys", + (Addr)sysctl->u.debug_keys.keys.p, + sysctl->u.debug_keys.nr_keys * sizeof(char)); + break; + case VKI_XEN_SYSCTL_sched_id: /* No inputs */ break; @@ -1100,6 +1108,10 @@ POST(sysctl) POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_node_distance.p, sizeof(uint32_t) * sysctl->u.numainfo.max_node_index); break; + + /* No outputs */ + case VKI_XEN_SYSCTL_debug_keys: + break; } #undef POST_XEN_SYSCTL_WRITE #undef __POST_XEN_SYSCTL_WRITE diff --git a/include/vki/vki-xen-sysctl.h b/include/vki/vki-xen-sysctl.h index f406bd0..1621b7a 100644 --- a/include/vki/vki-xen-sysctl.h +++ b/include/vki/vki-xen-sysctl.h @@ -104,6 +104,12 @@ struct vki_xen_sysctl_cpupool_op { struct vki_xenctl_bitmap cpumap; /* OUT: IF */ }; +struct vki_xen_sysctl_debug_keys { + /* IN variables. */ + VKI_XEN_GUEST_HANDLE_64(char) keys; + vki_uint32_t nr_keys; +}; + struct vki_xen_sysctl_topologyinfo { vki_uint32_t max_cpu_index; VKI_XEN_GUEST_HANDLE_64(vki_uint32) cpu_to_core; @@ -170,7 +176,7 @@ struct vki_xen_sysctl { struct vki_xen_sysctl_getdomaininfolist_00000008 getdomaininfolist_00000008; struct vki_xen_sysctl_getdomaininfolist_00000009 getdomaininfolist_00000009; struct vki_xen_sysctl_getdomaininfolist_0000000a getdomaininfolist_0000000a; - //struct vki_xen_sysctl_debug_keys debug_keys; + struct vki_xen_sysctl_debug_keys debug_keys; //struct vki_xen_sysctl_getcpuinfo getcpuinfo; //struct vki_xen_sysctl_availheap availheap; //struct vki_xen_sysctl_get_pmstat get_pmstat; -- 1.7.10.4
On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote:> Xen reads the entire structure, and if the space is _gmfn, will write the > structure back > > Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> > > -- > TODO: verifiy whether the POST_MEM_WRITE is requred if it is entirely > contained within the space identified by the PRE_MEM_READsI expect it is fine and don''t intend to let it put me off sending these upstream. Ian.
Ian Campbell
2013-Nov-29 11:22 UTC
Re: [PATCH 10/13] xen: XEN_DOMCTL_sethvmcontext hypercall
On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote:> + case VKI_XEN_DOMCTL_sethvmcontext: > + __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, size); > + __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, buffer); > + PRE_MEM_READ("XEN_DOMCTL_sethvmcontext *buffer", > + (Addr)domctl->u.hvmcontext.buffer.p,This is the common idiom so I don''t intend to block this series for it, but: Do you think these uses of .p are correct? I''m wondering if we ought not to actually be marking as read the entire struct, including the padded "q" member, perhaps by making the guest handles be of some non-struct type. I''m thinking of a 32-on-64 situation where the 32-bit userland fills in the bottom 4 bytes but the hypervisor actually reads all 8 and assumes the top is 0 (which is done in the set_xen_guest_handle_raw definition for x86_32). Thoughts?> + domctl->u.hvmcontext.size); > + break; > + > case VKI_XEN_DOMCTL_max_mem: > PRE_XEN_DOMCTL_READ(max_mem, max_memkb); > break; > @@ -1068,6 +1076,7 @@ POST(domctl){ > case VKI_XEN_DOMCTL_setnodeaffinity: > case VKI_XEN_DOMCTL_set_cpuid: > case VKI_XEN_DOMCTL_unpausedomain: > + case VKI_XEN_DOMCTL_sethvmcontext: > /* No output fields */ > break; >
On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote:> And some of the sub-subops. It is a little hacky given the legacy way of > having several methods of enabling/disbling LOG_DIRTY mode.Does the hypervisor still support all those methods. For valgrind purposes we only care as far back as 4.1 I think? Regardless, I intend to send this patch upstream.> > Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> > --- > coregrind/m_syswrap/syswrap-xen.c | 64 +++++++++++++++++++++++++++++++++++++ > include/vki/vki-xen-domctl.h | 36 ++++++++++++++++++++- > 2 files changed, 99 insertions(+), 1 deletion(-) > > diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c > index ea4a7c0..056f2b8 100644 > --- a/coregrind/m_syswrap/syswrap-xen.c > +++ b/coregrind/m_syswrap/syswrap-xen.c > @@ -696,6 +696,49 @@ PRE(domctl) > __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer); > break; > > + case VKI_XEN_DOMCTL_shadow_op: > + PRE_XEN_DOMCTL_READ(shadow_op, op); > + > + switch(domctl->u.shadow_op.op) > + { > + case VKI_XEN_DOMCTL_SHADOW_OP_OFF: > + /* No further inputs */ > + break; > + > + case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE: > + PRE_XEN_DOMCTL_READ(shadow_op, mode); > + switch(domctl->u.shadow_op.mode) > + { > + case XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY: > + goto domctl_shadow_op_enable_logdirty; > + > + > + default: > + bad_subop(tid, layout, arrghs, status, flags, > + "__HYPERVISOR_domctl shadowop mode", > + domctl->u.shadow_op.mode); > + break; > + } > + > + case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY: > + domctl_shadow_op_enable_logdirty: > + /* No further inputs */ > + break; > + > + case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: > + case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: > + PRE_XEN_DOMCTL_READ(shadow_op, dirty_bitmap); > + PRE_XEN_DOMCTL_READ(shadow_op, pages); > + break; > + > + default: > + bad_subop(tid, layout, arrghs, status, flags, > + "__HYPERVISOR_domctl shadow(10)", > + domctl->u.shadow_op.op); > + break; > + } > + break; > + > default: > bad_subop(tid, layout, arrghs, status, flags, > "__HYPERVISOR_domctl", domctl->cmd); > @@ -1212,6 +1255,27 @@ POST(domctl){ > domctl->u.vcpuextstate.size); > break; > > + case VKI_XEN_DOMCTL_shadow_op: > + switch(domctl->u.shadow_op.op) > + { > + case VKI_XEN_DOMCTL_SHADOW_OP_OFF: > + /* No outputs */ > + break; > + > + case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: > + case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: > + POST_XEN_DOMCTL_WRITE(shadow_op, pages); > + POST_XEN_DOMCTL_WRITE(shadow_op, stats.fault_count); > + POST_XEN_DOMCTL_WRITE(shadow_op, stats.dirty_count); > + if(domctl->u.shadow_op.dirty_bitmap.p) > + POST_MEM_WRITE((Addr)domctl->u.shadow_op.dirty_bitmap.p, > + domctl->u.shadow_op.pages * sizeof(vki_uint8_t)); > + break; > + > + default: > + break; > + } > + break; > } > #undef POST_XEN_DOMCTL_WRITE > #undef __POST_XEN_DOMCTL_WRITE > diff --git a/include/vki/vki-xen-domctl.h b/include/vki/vki-xen-domctl.h > index 67dc2ef..7cce4af 100644 > --- a/include/vki/vki-xen-domctl.h > +++ b/include/vki/vki-xen-domctl.h > @@ -173,6 +173,40 @@ struct vki_xen_domctl_vcpuaffinity { > struct vki_xenctl_bitmap cpumap; /* IN/OUT */ > }; > > +struct vki_xen_domctl_shadow_op_stats { > + vki_uint32_t fault_count; > + vki_uint32_t dirty_count; > +}; > + > +/* vki_xen_domctl_shadow_op.op is an utter mess for compatibily reasons. */ > + > +struct vki_xen_domctl_shadow_op { > + vki_uint32_t op; /* IN */ > + > +#define VKI_XEN_DOMCTL_SHADOW_OP_OFF 0 > +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE 32 > +#define VKI_XEN_DOMCTL_SHADOW_OP_CLEAN 11 > +#define VKI_XEN_DOMCTL_SHADOW_OP_PEEK 12 > +#define VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 > +#define VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 > + > +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1 > +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2 > +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3 > + > + vki_uint32_t mode; > + > +#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1) > +#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2) > +#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3) > +#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4) > + > + vki_uint32_t mb; > + VKI_XEN_GUEST_HANDLE_64(vki_uint8) dirty_bitmap; > + vki_xen_uint64_aligned_t pages; > + struct vki_xen_domctl_shadow_op_stats stats; > +}; > + > struct vki_xen_domctl_max_mem { > /* IN variables. */ > vki_xen_uint64_aligned_t max_memkb; > @@ -285,7 +319,7 @@ struct vki_xen_domctl { > struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3; > struct vki_xen_domctl_nodeaffinity nodeaffinity; > struct vki_xen_domctl_vcpuaffinity vcpuaffinity; > - //struct vki_xen_domctl_shadow_op shadow_op; > + struct vki_xen_domctl_shadow_op shadow_op; > struct vki_xen_domctl_max_mem max_mem; > struct vki_xen_domctl_vcpucontext vcpucontext; > struct vki_xen_domctl_getvcpuinfo getvcpuinfo;
On 29/11/13 11:25, Ian Campbell wrote:> On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote: >> And some of the sub-subops. It is a little hacky given the legacy way of >> having several methods of enabling/disbling LOG_DIRTY mode. > Does the hypervisor still support all those methods. For valgrind > purposes we only care as far back as 4.1 I think?Sadly yes, and xc_domain_save() I believe makes use of both of them. (Most of these patches are from 6 months ago, so I don''t remember for certain) While it is not explicitly deprecated in the ABI, it is still fair game to use either method. ~Andrew> > Regardless, I intend to send this patch upstream. > >> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> >> --- >> coregrind/m_syswrap/syswrap-xen.c | 64 +++++++++++++++++++++++++++++++++++++ >> include/vki/vki-xen-domctl.h | 36 ++++++++++++++++++++- >> 2 files changed, 99 insertions(+), 1 deletion(-) >> >> diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xen.c >> index ea4a7c0..056f2b8 100644 >> --- a/coregrind/m_syswrap/syswrap-xen.c >> +++ b/coregrind/m_syswrap/syswrap-xen.c >> @@ -696,6 +696,49 @@ PRE(domctl) >> __PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer); >> break; >> >> + case VKI_XEN_DOMCTL_shadow_op: >> + PRE_XEN_DOMCTL_READ(shadow_op, op); >> + >> + switch(domctl->u.shadow_op.op) >> + { >> + case VKI_XEN_DOMCTL_SHADOW_OP_OFF: >> + /* No further inputs */ >> + break; >> + >> + case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE: >> + PRE_XEN_DOMCTL_READ(shadow_op, mode); >> + switch(domctl->u.shadow_op.mode) >> + { >> + case XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY: >> + goto domctl_shadow_op_enable_logdirty; >> + >> + >> + default: >> + bad_subop(tid, layout, arrghs, status, flags, >> + "__HYPERVISOR_domctl shadowop mode", >> + domctl->u.shadow_op.mode); >> + break; >> + } >> + >> + case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY: >> + domctl_shadow_op_enable_logdirty: >> + /* No further inputs */ >> + break; >> + >> + case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: >> + case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: >> + PRE_XEN_DOMCTL_READ(shadow_op, dirty_bitmap); >> + PRE_XEN_DOMCTL_READ(shadow_op, pages); >> + break; >> + >> + default: >> + bad_subop(tid, layout, arrghs, status, flags, >> + "__HYPERVISOR_domctl shadow(10)", >> + domctl->u.shadow_op.op); >> + break; >> + } >> + break; >> + >> default: >> bad_subop(tid, layout, arrghs, status, flags, >> "__HYPERVISOR_domctl", domctl->cmd); >> @@ -1212,6 +1255,27 @@ POST(domctl){ >> domctl->u.vcpuextstate.size); >> break; >> >> + case VKI_XEN_DOMCTL_shadow_op: >> + switch(domctl->u.shadow_op.op) >> + { >> + case VKI_XEN_DOMCTL_SHADOW_OP_OFF: >> + /* No outputs */ >> + break; >> + >> + case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN: >> + case VKI_XEN_DOMCTL_SHADOW_OP_PEEK: >> + POST_XEN_DOMCTL_WRITE(shadow_op, pages); >> + POST_XEN_DOMCTL_WRITE(shadow_op, stats.fault_count); >> + POST_XEN_DOMCTL_WRITE(shadow_op, stats.dirty_count); >> + if(domctl->u.shadow_op.dirty_bitmap.p) >> + POST_MEM_WRITE((Addr)domctl->u.shadow_op.dirty_bitmap.p, >> + domctl->u.shadow_op.pages * sizeof(vki_uint8_t)); >> + break; >> + >> + default: >> + break; >> + } >> + break; >> } >> #undef POST_XEN_DOMCTL_WRITE >> #undef __POST_XEN_DOMCTL_WRITE >> diff --git a/include/vki/vki-xen-domctl.h b/include/vki/vki-xen-domctl.h >> index 67dc2ef..7cce4af 100644 >> --- a/include/vki/vki-xen-domctl.h >> +++ b/include/vki/vki-xen-domctl.h >> @@ -173,6 +173,40 @@ struct vki_xen_domctl_vcpuaffinity { >> struct vki_xenctl_bitmap cpumap; /* IN/OUT */ >> }; >> >> +struct vki_xen_domctl_shadow_op_stats { >> + vki_uint32_t fault_count; >> + vki_uint32_t dirty_count; >> +}; >> + >> +/* vki_xen_domctl_shadow_op.op is an utter mess for compatibily reasons. */ >> + >> +struct vki_xen_domctl_shadow_op { >> + vki_uint32_t op; /* IN */ >> + >> +#define VKI_XEN_DOMCTL_SHADOW_OP_OFF 0 >> +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE 32 >> +#define VKI_XEN_DOMCTL_SHADOW_OP_CLEAN 11 >> +#define VKI_XEN_DOMCTL_SHADOW_OP_PEEK 12 >> +#define VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30 >> +#define VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31 >> + >> +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1 >> +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2 >> +#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3 >> + >> + vki_uint32_t mode; >> + >> +#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1) >> +#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2) >> +#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3) >> +#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4) >> + >> + vki_uint32_t mb; >> + VKI_XEN_GUEST_HANDLE_64(vki_uint8) dirty_bitmap; >> + vki_xen_uint64_aligned_t pages; >> + struct vki_xen_domctl_shadow_op_stats stats; >> +}; >> + >> struct vki_xen_domctl_max_mem { >> /* IN variables. */ >> vki_xen_uint64_aligned_t max_memkb; >> @@ -285,7 +319,7 @@ struct vki_xen_domctl { >> struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3; >> struct vki_xen_domctl_nodeaffinity nodeaffinity; >> struct vki_xen_domctl_vcpuaffinity vcpuaffinity; >> - //struct vki_xen_domctl_shadow_op shadow_op; >> + struct vki_xen_domctl_shadow_op shadow_op; >> struct vki_xen_domctl_max_mem max_mem; >> struct vki_xen_domctl_vcpucontext vcpucontext; >> struct vki_xen_domctl_getvcpuinfo getvcpuinfo; >
On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote:> This set of patches teaches valgrind about new hypercalls. > > Valgrind can now completely inspect xc_domain_save()/restore() > > Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> > CC: Ian Campbell <Ian.Campbell@citrix.com>Thanks, these look OK to me on a quick skim and build so I''ve sent them upstream to: https://bugs.kde.org/show_bug.cgi?id=328205 I also tacked on the following patch which git diff RELEASE-4.3.0 -- xen/include/public/*ctl* called out as the only interesting look new sys/domctl coming in 4.4 Ian. commit 63230747f04a094a242e19b8c5c06eed773e56e3 Author: Ian Campbell <ian.campbell@citrix.com> Date: Fri Nov 29 11:43:18 2013 +0000 xen: Implement XEN_DOMCTL_set_max_evtchn This is new in Xen 4.4. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> diff --git a/coregrind/m_syswrap/syswrap-xen.c b/coregrind/m_syswrap/syswrap-xe index 7561dda..02205da 100644 --- a/coregrind/m_syswrap/syswrap-xen.c +++ b/coregrind/m_syswrap/syswrap-xen.c @@ -759,6 +759,10 @@ PRE(domctl) } break; + case VKI_XEN_DOMCTL_set_max_evtchn: + PRE_XEN_DOMCTL_READ(set_max_evtchn, max_port); + break; + default: bad_subop(tid, layout, arrghs, status, flags, "__HYPERVISOR_domctl", domctl->cmd); @@ -1149,6 +1153,7 @@ POST(domctl){ case VKI_XEN_DOMCTL_set_cpuid: case VKI_XEN_DOMCTL_unpausedomain: case VKI_XEN_DOMCTL_sethvmcontext: + case VKI_XEN_DOMCTL_set_max_evtchn: /* No output fields */ break; diff --git a/include/vki/vki-xen-domctl.h b/include/vki/vki-xen-domctl.h index 7cce4af..2d07f41 100644 --- a/include/vki/vki-xen-domctl.h +++ b/include/vki/vki-xen-domctl.h @@ -84,6 +84,7 @@ #define VKI_XEN_DOMCTL_set_broken_page_p2m 67 #define VKI_XEN_DOMCTL_setnodeaffinity 68 #define VKI_XEN_DOMCTL_getnodeaffinity 69 +#define VKI_XEN_DOMCTL_set_max_evtchn 70 #define VKI_XEN_DOMCTL_gdbsx_guestmemio 1000 #define VKI_XEN_DOMCTL_gdbsx_pausevcpu 1001 #define VKI_XEN_DOMCTL_gdbsx_unpausevcpu 1002 @@ -304,6 +305,10 @@ struct vki_xen_domctl_address_size { vki_uint32_t size; }; +struct vki_xen_domctl_set_max_evtchn { + vki_uint32_t max_port; +}; + struct vki_xen_domctl { vki_uint32_t cmd; vki_uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */ @@ -359,6 +364,7 @@ struct vki_xen_domctl { //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; //struct vki_xen_domctl_gdbsx_memio gdbsx_guest_memio; //struct vki_xen_domctl_set_broken_page_p2m set_broken_page_p2m;
On Fri, 2013-11-29 at 11:45 +0000, Ian Campbell wrote:> On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote: > > This set of patches teaches valgrind about new hypercalls. > > > > Valgrind can now completely inspect xc_domain_save()/restore() > > > > Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> > > CC: Ian Campbell <Ian.Campbell@citrix.com> > > Thanks, these look OK to me on a quick skim and build so I''ve sent them > upstream to: https://bugs.kde.org/show_bug.cgi?id=328205Which has just resulted in them being applied, thanks to Bart Van Assche. Thanks, Ian.
On 02/12/13 10:37, Ian Campbell wrote:> On Fri, 2013-11-29 at 11:45 +0000, Ian Campbell wrote: >> On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote: >>> This set of patches teaches valgrind about new hypercalls. >>> >>> Valgrind can now completely inspect xc_domain_save()/restore() >>> >>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> >>> CC: Ian Campbell <Ian.Campbell@citrix.com> >> Thanks, these look OK to me on a quick skim and build so I''ve sent them >> upstream to: https://bugs.kde.org/show_bug.cgi?id=328205 > Which has just resulted in them being applied, thanks to Bart Van > Assche. > > Thanks, > Ian. > >Wow - that was quick going. I wonder how well valgrind now does with xl create... ~Andrew
On Mon, 2013-12-02 at 10:46 +0000, Andrew Cooper wrote:> On 02/12/13 10:37, Ian Campbell wrote: > > On Fri, 2013-11-29 at 11:45 +0000, Ian Campbell wrote: > >> On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote: > >>> This set of patches teaches valgrind about new hypercalls. > >>> > >>> Valgrind can now completely inspect xc_domain_save()/restore() > >>> > >>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> > >>> CC: Ian Campbell <Ian.Campbell@citrix.com> > >> Thanks, these look OK to me on a quick skim and build so I''ve sent them > >> upstream to: https://bugs.kde.org/show_bug.cgi?id=328205 > > Which has just resulted in them being applied, thanks to Bart Van > > Assche. > > > > Thanks, > > Ian. > > > > > > Wow - that was quick going.Yes!> I wonder how well valgrind now does with xl create...It used to work for me, that''s what I was doing when I first implemented this stuff. IIRC it doesn''t play especially well with the deaemonisation aspect for some reason, but you can keep it in the foreground and/or disable the monitoring bit (both on the cmdline) and it works ok, for at least bog standard PV and HVM guests. That was then of course. Ian.
On 02/12/13 10:49, Ian Campbell wrote:> On Mon, 2013-12-02 at 10:46 +0000, Andrew Cooper wrote: >> On 02/12/13 10:37, Ian Campbell wrote: >>> On Fri, 2013-11-29 at 11:45 +0000, Ian Campbell wrote: >>>> On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote: >>>>> This set of patches teaches valgrind about new hypercalls. >>>>> >>>>> Valgrind can now completely inspect xc_domain_save()/restore() >>>>> >>>>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> >>>>> CC: Ian Campbell <Ian.Campbell@citrix.com> >>>> Thanks, these look OK to me on a quick skim and build so I''ve sent them >>>> upstream to: https://bugs.kde.org/show_bug.cgi?id=328205 >>> Which has just resulted in them being applied, thanks to Bart Van >>> Assche. >>> >>> Thanks, >>> Ian. >>> >>> >> Wow - that was quick going. > Yes! > >> I wonder how well valgrind now does with xl create... > It used to work for me, that''s what I was doing when I first implemented > this stuff. > > IIRC it doesn''t play especially well with the deaemonisation aspect for > some reason, but you can keep it in the foreground and/or disable the > monitoring bit (both on the cmdline) and it works ok, for at least bog > standard PV and HVM guests. > > That was then of course. > > Ian. >Sadly, its the daemonisation aspect which is the interesting one to look at. Memory leaks in the daemon are far more critical than in the short-lived runs. ~Andrew
On Mon, 2013-12-02 at 10:55 +0000, Andrew Cooper wrote:> Sadly, its the daemonisation aspect which is the interesting one to look > at. Memory leaks in the daemon are far more critical than in the > short-lived runs.I think the issue was just that you get confusing output from multiple processes after the fork etc, nothing inherently "buggy" as such, at least not WRT the handling of the hypercalls. Note that you can still debug the monitoring aspect without daemonising it, by running the monitor in the foreground. Ian.
On Thu, 2013-11-28 at 18:56 +0000, Andrew Cooper wrote:> This set of patches teaches valgrindBTW, I''ve just noticed that Valgrind 3.9.0 was released in October with the baseline Xen stuff in it. Of course that won''t get the very latest stuff, but cool! Ian.