From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH v2 06/11] hvmctl: convert HVMOP_modified_memory Date: Fri, 24 Jun 2016 04:31:43 -0600 Message-ID: <576D282F02000078000F8700@prv-mh.provo.novell.com> References: <576D25DA02000078000F86C2@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part4177761F.3__=" Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bGOOq-0003w1-IR for xen-devel@lists.xenproject.org; Fri, 24 Jun 2016 10:31:48 +0000 In-Reply-To: <576D25DA02000078000F86C2@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Stefano Stabellini , Wei Liu , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , dgdegra@tycho.nsa.gov List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part4177761F.3__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Also limiting "nr" at the libxc level to 32 bits (the high 32 bits of the previous 64-bit parameter got ignore so far). Signed-off-by: Jan Beulich Reviewed-by: Wei Liu Reviewed-by: Andrew Cooper --- a/tools/libxc/include/xenctrl.h +++ b/tools/libxc/include/xenctrl.h @@ -1620,7 +1620,7 @@ int xc_hvm_track_dirty_vram( * Notify that some pages got modified by the Device Model */ int xc_hvm_modified_memory( - xc_interface *xch, domid_t dom, uint64_t first_pfn, uint64_t nr); + xc_interface *xch, domid_t dom, uint64_t first_gfn, uint32_t nr); =20 /* * Set a range of memory to a specific type. --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -558,29 +558,13 @@ int xc_hvm_track_dirty_vram( } =20 int xc_hvm_modified_memory( - xc_interface *xch, domid_t dom, uint64_t first_pfn, uint64_t nr) + xc_interface *xch, domid_t dom, uint64_t first_gfn, uint32_t nr) { - DECLARE_HYPERCALL_BUFFER(struct xen_hvm_modified_memory, arg); - int rc; + DECLARE_HVMCTL(modified_memory, dom, + .first_gfn =3D first_gfn, + .nr =3D nr); =20 - arg =3D xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg)); - if ( arg =3D=3D NULL ) - { - PERROR("Could not allocate memory for xc_hvm_modified_memory = hypercall"); - return -1; - } - - arg->domid =3D dom; - arg->first_pfn =3D first_pfn; - arg->nr =3D nr; - - rc =3D xencall2(xch->xcall, __HYPERVISOR_hvm_op, - HVMOP_modified_memory, - HYPERCALL_BUFFER_AS_ARG(arg)); - - xc_hypercall_buffer_free(xch, arg); - - return rc; + return do_hvmctl(xch, &hvmctl); } =20 int xc_hvm_set_mem_type( --- a/xen/arch/x86/hvm/control.c +++ b/xen/arch/x86/hvm/control.c @@ -14,6 +14,7 @@ * this program; If not, see . */ =20 +#include #include #include #include @@ -90,6 +91,51 @@ static int track_dirty_vram(struct domai : hap_track_dirty_vram(d, op->first_gfn, op->nr, op->dirty_bitm= ap); } =20 +static int modified_memory(struct domain *d, + const struct xen_hvm_modified_memory *op, + uint64_t *iter) +{ + if ( !is_hvm_domain(d) ) + return -EINVAL; + + if ( op->rsvd || op->nr < *iter || + ((op->first_gfn + op->nr - 1) < op->first_gfn) || + ((op->first_gfn + op->nr - 1) > domain_get_maximum_gpfn(d)) ) + return -EINVAL; + + if ( !paging_mode_log_dirty(d) ) + return 0; + + while ( op->nr > *iter ) + { + unsigned long gfn =3D op->first_gfn + *iter; + struct page_info *page =3D get_page_from_gfn(d, gfn, NULL, = P2M_UNSHARE); + + if ( page ) + { + unsigned long mfn =3D page_to_mfn(page); + + paging_mark_dirty(d, mfn); + /* + * These are most probably not page tables any more: + * Don't take a long time, and don't die either. + */ + sh_remove_shadows(d, _mfn(mfn), 1, 0); + put_page(page); + } + + /* + * Check for continuation every once in a while, and if it's not = the + * last interation. + */ + if ( op->nr > ++*iter && !(*iter & 0xff) && + hypercall_preempt_check() ) + return -ERESTART; + } + + return 0; +} + long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xen_hvmctl_t) u_hvmctl) { xen_hvmctl_t op; @@ -140,6 +186,10 @@ long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xe rc =3D track_dirty_vram(d, &op.u.track_dirty_vram); break; =20 + case XEN_HVMCTL_modified_memory: + rc =3D modified_memory(d, &op.u.modified_memory, &op.opaque); + break; + default: rc =3D -EOPNOTSUPP; break; --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -5233,7 +5233,6 @@ long do_hvm_op(unsigned long op, XEN_GUE default: mask =3D ~0UL; break; - case HVMOP_modified_memory: case HVMOP_set_mem_type: mask =3D HVMOP_op_mask; break; @@ -5296,65 +5295,6 @@ long do_hvm_op(unsigned long op, XEN_GUE rc =3D guest_handle_is_null(arg) ? hvmop_flush_tlb_all() : = -ENOSYS; break; =20 - case HVMOP_modified_memory: - { - struct xen_hvm_modified_memory a; - struct domain *d; - - if ( copy_from_guest(&a, arg, 1) ) - return -EFAULT; - - rc =3D rcu_lock_remote_domain_by_id(a.domid, &d); - if ( rc !=3D 0 ) - return rc; - - rc =3D -EINVAL; - if ( !is_hvm_domain(d) ) - goto modmem_fail; - - rc =3D xsm_hvm_control(XSM_DM_PRIV, d, op); - if ( rc ) - goto modmem_fail; - - rc =3D -EINVAL; - if ( a.nr < start_iter || - ((a.first_pfn + a.nr - 1) < a.first_pfn) || - ((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) ) - goto modmem_fail; - - rc =3D 0; - if ( !paging_mode_log_dirty(d) ) - goto modmem_fail; - - while ( a.nr > start_iter ) - { - unsigned long pfn =3D a.first_pfn + start_iter; - struct page_info *page; - - page =3D get_page_from_gfn(d, pfn, NULL, P2M_UNSHARE); - if ( page ) - { - paging_mark_dirty(d, page_to_mfn(page)); - /* These are most probably not page tables any more */ - /* don't take a long time and don't die either */ - sh_remove_shadows(d, _mfn(page_to_mfn(page)), 1, 0); - put_page(page); - } - - /* Check for continuation if it's not the last interation */ - if ( a.nr > ++start_iter && !(start_iter & HVMOP_op_mask) && - hypercall_preempt_check() ) - { - rc =3D -ERESTART; - break; - } - } - - modmem_fail: - rcu_unlock_domain(d); - break; - } - case HVMOP_get_mem_type: { struct xen_hvm_get_mem_type a; --- a/xen/include/public/hvm/control.h +++ b/xen/include/public/hvm/control.h @@ -67,6 +67,16 @@ struct xen_hvm_track_dirty_vram { XEN_GUEST_HANDLE_64(uint8) dirty_bitmap; }; =20 +/* XEN_HVMCTL_modified_memory */ +/* Notify that some pages got modified by the Device Model. */ +struct xen_hvm_modified_memory { + /* Number of pages. */ + uint32_t nr; + uint32_t rsvd; + /* First GFN. */ + uint64_aligned_t first_gfn; +}; + struct xen_hvmctl { uint16_t interface_version; /* XEN_HVMCTL_INTERFACE_VERSION */ domid_t domain; @@ -75,12 +85,14 @@ struct xen_hvmctl { #define XEN_HVMCTL_set_isa_irq_level 2 #define XEN_HVMCTL_set_pci_link_route 3 #define XEN_HVMCTL_track_dirty_vram 4 +#define XEN_HVMCTL_modified_memory 5 uint64_t opaque; /* Must be zero on initial invocation. = */ union { struct xen_hvm_set_pci_intx_level set_pci_intx_level; struct xen_hvm_set_isa_irq_level set_isa_irq_level; struct xen_hvm_set_pci_link_route set_pci_link_route; struct xen_hvm_track_dirty_vram track_dirty_vram; + struct xen_hvm_modified_memory modified_memory; uint8_t pad[120]; } u; }; --- a/xen/include/public/hvm/hvm_op.h +++ b/xen/include/public/hvm/hvm_op.h @@ -98,19 +98,6 @@ typedef enum { /* Following tools-only interfaces may change in future. */ #if defined(__XEN__) || defined(__XEN_TOOLS__) =20 -/* Notify that some pages got modified by the Device Model. */ -#define HVMOP_modified_memory 7 -struct xen_hvm_modified_memory { - /* Domain to be updated. */ - domid_t domid; - /* Number of pages. */ - uint32_t nr; - /* First pfn. */ - uint64_aligned_t first_pfn; -}; -typedef struct xen_hvm_modified_memory xen_hvm_modified_memory_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_memory_t); - #define HVMOP_set_mem_type 8 /* Notify that a region of memory is to be treated in a specific way. */ struct xen_hvm_set_mem_type { --- a/xen/xsm/flask/policy/access_vectors +++ b/xen/xsm/flask/policy/access_vectors @@ -272,7 +272,7 @@ class hvm cacheattr # XEN_HVMCTL_track_dirty_vram trackdirtyvram -# HVMOP_modified_memory, HVMOP_get_mem_type, HVMOP_set_mem_type, +# XEN_HVMCTL_modified_memory, HVMOP_get_mem_type, HVMOP_set_mem_type, # HVMOP_set_mem_access, HVMOP_get_mem_access, HVMOP_pagetable_dying, # HVMOP_inject_trap hvmctl --=__Part4177761F.3__= Content-Type: text/plain; name="hvmctl-05.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="hvmctl-05.patch" hvmctl: convert HVMOP_modified_memory=0A=0AAlso limiting "nr" at the libxc = level to 32 bits (the high 32 bits of=0Athe previous 64-bit parameter got = ignore so far).=0A=0ASigned-off-by: Jan Beulich =0ARevie= wed-by: Wei Liu =0AReviewed-by: Andrew Cooper = =0A=0A--- a/tools/libxc/include/xenctrl.h=0A+++ = b/tools/libxc/include/xenctrl.h=0A@@ -1620,7 +1620,7 @@ int xc_hvm_track_di= rty_vram(=0A * Notify that some pages got modified by the Device Model=0A = */=0A int xc_hvm_modified_memory(=0A- xc_interface *xch, domid_t dom, = uint64_t first_pfn, uint64_t nr);=0A+ xc_interface *xch, domid_t dom, = uint64_t first_gfn, uint32_t nr);=0A =0A /*=0A * Set a range of memory to = a specific type.=0A--- a/tools/libxc/xc_misc.c=0A+++ b/tools/libxc/xc_misc.= c=0A@@ -558,29 +558,13 @@ int xc_hvm_track_dirty_vram(=0A }=0A =0A int = xc_hvm_modified_memory(=0A- xc_interface *xch, domid_t dom, uint64_t = first_pfn, uint64_t nr)=0A+ xc_interface *xch, domid_t dom, uint64_t = first_gfn, uint32_t nr)=0A {=0A- DECLARE_HYPERCALL_BUFFER(struct = xen_hvm_modified_memory, arg);=0A- int rc;=0A+ DECLARE_HVMCTL(modifie= d_memory, dom,=0A+ .first_gfn =3D first_gfn,=0A+ = .nr =3D nr);=0A =0A- arg =3D xc_hypercall_buffer_alloc(= xch, arg, sizeof(*arg));=0A- if ( arg =3D=3D NULL )=0A- {=0A- = PERROR("Could not allocate memory for xc_hvm_modified_memory hypercall");= =0A- return -1;=0A- }=0A-=0A- arg->domid =3D dom;=0A- = arg->first_pfn =3D first_pfn;=0A- arg->nr =3D nr;=0A-=0A- rc = =3D xencall2(xch->xcall, __HYPERVISOR_hvm_op,=0A- = HVMOP_modified_memory,=0A- HYPERCALL_BUFFER_AS_ARG(arg));= =0A-=0A- xc_hypercall_buffer_free(xch, arg);=0A-=0A- return rc;=0A+ = return do_hvmctl(xch, &hvmctl);=0A }=0A =0A int xc_hvm_set_mem_type(=0A--= - a/xen/arch/x86/hvm/control.c=0A+++ b/xen/arch/x86/hvm/control.c=0A@@ = -14,6 +14,7 @@=0A * this program; If not, see .=0A */=0A =0A+#include =0A #include =0A = #include =0A #include =0A@@ -90,6 +91,51 = @@ static int track_dirty_vram(struct domai=0A : hap_track_dirty= _vram(d, op->first_gfn, op->nr, op->dirty_bitmap);=0A }=0A =0A+static int = modified_memory(struct domain *d,=0A+ const = struct xen_hvm_modified_memory *op,=0A+ uint64_t = *iter)=0A+{=0A+ if ( !is_hvm_domain(d) )=0A+ return -EINVAL;=0A+= =0A+ if ( op->rsvd || op->nr < *iter ||=0A+ ((op->first_gfn + = op->nr - 1) < op->first_gfn) ||=0A+ ((op->first_gfn + op->nr - 1) = > domain_get_maximum_gpfn(d)) )=0A+ return -EINVAL;=0A+=0A+ if ( = !paging_mode_log_dirty(d) )=0A+ return 0;=0A+=0A+ while ( op->nr = > *iter )=0A+ {=0A+ unsigned long gfn =3D op->first_gfn + = *iter;=0A+ struct page_info *page =3D get_page_from_gfn(d, gfn, = NULL, P2M_UNSHARE);=0A+=0A+ if ( page )=0A+ {=0A+ = unsigned long mfn =3D page_to_mfn(page);=0A+=0A+ paging_mark_dir= ty(d, mfn);=0A+ /*=0A+ * These are most probably = not page tables any more:=0A+ * Don't take a long time, and = don't die either.=0A+ */=0A+ sh_remove_shadows(d, = _mfn(mfn), 1, 0);=0A+ put_page(page);=0A+ }=0A+=0A+ = /*=0A+ * Check for continuation every once in a while, and if = it's not the=0A+ * last interation.=0A+ */=0A+ if ( = op->nr > ++*iter && !(*iter & 0xff) &&=0A+ hypercall_preempt_ch= eck() )=0A+ return -ERESTART;=0A+ }=0A+=0A+ return = 0;=0A+}=0A+=0A long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xen_hvmctl_t) = u_hvmctl)=0A {=0A xen_hvmctl_t op;=0A@@ -140,6 +186,10 @@ long = do_hvmctl(XEN_GUEST_HANDLE_PARAM(xe=0A rc =3D track_dirty_vram(d, = &op.u.track_dirty_vram);=0A break;=0A =0A+ case XEN_HVMCTL_modif= ied_memory:=0A+ rc =3D modified_memory(d, &op.u.modified_memory, = &op.opaque);=0A+ break;=0A+=0A default:=0A rc =3D = -EOPNOTSUPP;=0A break;=0A--- a/xen/arch/x86/hvm/hvm.c=0A+++ = b/xen/arch/x86/hvm/hvm.c=0A@@ -5233,7 +5233,6 @@ long do_hvm_op(unsigned = long op, XEN_GUE=0A default:=0A mask =3D ~0UL;=0A = break;=0A- case HVMOP_modified_memory:=0A case HVMOP_set_mem_type:= =0A mask =3D HVMOP_op_mask;=0A break;=0A@@ -5296,65 = +5295,6 @@ long do_hvm_op(unsigned long op, XEN_GUE=0A rc =3D = guest_handle_is_null(arg) ? hvmop_flush_tlb_all() : -ENOSYS;=0A = break;=0A =0A- case HVMOP_modified_memory:=0A- {=0A- struct = xen_hvm_modified_memory a;=0A- struct domain *d;=0A-=0A- if = ( copy_from_guest(&a, arg, 1) )=0A- return -EFAULT;=0A-=0A- = rc =3D rcu_lock_remote_domain_by_id(a.domid, &d);=0A- if ( rc = !=3D 0 )=0A- return rc;=0A-=0A- rc =3D -EINVAL;=0A- = if ( !is_hvm_domain(d) )=0A- goto modmem_fail;=0A-=0A- = rc =3D xsm_hvm_control(XSM_DM_PRIV, d, op);=0A- if ( rc )=0A- = goto modmem_fail;=0A-=0A- rc =3D -EINVAL;=0A- if ( a.nr = < start_iter ||=0A- ((a.first_pfn + a.nr - 1) < a.first_pfn) = ||=0A- ((a.first_pfn + a.nr - 1) > domain_get_maximum_gpfn(d)) = )=0A- goto modmem_fail;=0A-=0A- rc =3D 0;=0A- if = ( !paging_mode_log_dirty(d) )=0A- goto modmem_fail;=0A-=0A- = while ( a.nr > start_iter )=0A- {=0A- unsigned long = pfn =3D a.first_pfn + start_iter;=0A- struct page_info = *page;=0A-=0A- page =3D get_page_from_gfn(d, pfn, NULL, = P2M_UNSHARE);=0A- if ( page )=0A- {=0A- = paging_mark_dirty(d, page_to_mfn(page));=0A- /* These are = most probably not page tables any more */=0A- /* don't take = a long time and don't die either */=0A- sh_remove_shadows(d,= _mfn(page_to_mfn(page)), 1, 0);=0A- put_page(page);=0A- = }=0A-=0A- /* Check for continuation if it's not the = last interation */=0A- if ( a.nr > ++start_iter && !(start_iter = & HVMOP_op_mask) &&=0A- hypercall_preempt_check() )=0A- = {=0A- rc =3D -ERESTART;=0A- = break;=0A- }=0A- }=0A-=0A- modmem_fail:=0A- = rcu_unlock_domain(d);=0A- break;=0A- }=0A-=0A case HVMOP_get_= mem_type:=0A {=0A struct xen_hvm_get_mem_type a;=0A--- = a/xen/include/public/hvm/control.h=0A+++ b/xen/include/public/hvm/control.h= =0A@@ -67,6 +67,16 @@ struct xen_hvm_track_dirty_vram {=0A XEN_GUEST_HA= NDLE_64(uint8) dirty_bitmap;=0A };=0A =0A+/* XEN_HVMCTL_modified_memory = */=0A+/* Notify that some pages got modified by the Device Model. = */=0A+struct xen_hvm_modified_memory {=0A+ /* Number of pages. */=0A+ = uint32_t nr;=0A+ uint32_t rsvd;=0A+ /* First GFN. */=0A+ = uint64_aligned_t first_gfn;=0A+};=0A+=0A struct xen_hvmctl {=0A = uint16_t interface_version; /* XEN_HVMCTL_INTERFACE_VERSION */=0A = domid_t domain;=0A@@ -75,12 +85,14 @@ struct xen_hvmctl {=0A #define = XEN_HVMCTL_set_isa_irq_level 2=0A #define XEN_HVMCTL_set_pci_li= nk_route 3=0A #define XEN_HVMCTL_track_dirty_vram = 4=0A+#define XEN_HVMCTL_modified_memory 5=0A uint64_t = opaque; /* Must be zero on initial invocation. */=0A = union {=0A struct xen_hvm_set_pci_intx_level set_pci_intx_level;=0A= struct xen_hvm_set_isa_irq_level set_isa_irq_level;=0A = struct xen_hvm_set_pci_link_route set_pci_link_route;=0A struct = xen_hvm_track_dirty_vram track_dirty_vram;=0A+ struct xen_hvm_modifi= ed_memory modified_memory;=0A uint8_t pad[120];=0A } u;=0A = };=0A--- a/xen/include/public/hvm/hvm_op.h=0A+++ b/xen/include/public/hvm/h= vm_op.h=0A@@ -98,19 +98,6 @@ typedef enum {=0A /* Following tools-only = interfaces may change in future. */=0A #if defined(__XEN__) || defined(__XE= N_TOOLS__)=0A =0A-/* Notify that some pages got modified by the Device = Model. */=0A-#define HVMOP_modified_memory 7=0A-struct xen_hvm_modified_= memory {=0A- /* Domain to be updated. */=0A- domid_t domid;=0A- = /* Number of pages. */=0A- uint32_t nr;=0A- /* First pfn. */=0A- = uint64_aligned_t first_pfn;=0A-};=0A-typedef struct xen_hvm_modified_memory= xen_hvm_modified_memory_t;=0A-DEFINE_XEN_GUEST_HANDLE(xen_hvm_modified_mem= ory_t);=0A-=0A #define HVMOP_set_mem_type 8=0A /* Notify that a region = of memory is to be treated in a specific way. */=0A struct xen_hvm_set_mem_= type {=0A--- a/xen/xsm/flask/policy/access_vectors=0A+++ b/xen/xsm/flask/po= licy/access_vectors=0A@@ -272,7 +272,7 @@ class hvm=0A cacheattr=0A # = XEN_HVMCTL_track_dirty_vram=0A trackdirtyvram=0A-# HVMOP_modified_memor= y, HVMOP_get_mem_type, HVMOP_set_mem_type,=0A+# XEN_HVMCTL_modified_memory,= HVMOP_get_mem_type, HVMOP_set_mem_type,=0A # HVMOP_set_mem_access, = HVMOP_get_mem_access, HVMOP_pagetable_dying,=0A # HVMOP_inject_trap=0A = hvmctl=0A --=__Part4177761F.3__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwOi8vbGlzdHMueGVuLm9y Zy94ZW4tZGV2ZWwK --=__Part4177761F.3__=--