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
@@ -1613,7 +1613,7 @@ int xc_hvm_inject_msi(
*/
int xc_hvm_track_dirty_vram(
xc_interface *xch, domid_t dom,
-uint64_t first_pfn, uint64_t nr,
+uint64_t first_gfn, uint32_t nr,
unsigned long *bitmap);
/*
--- a/tools/libxc/xc_misc.c
+++ b/tools/libxc/xc_misc.c
@@ -533,33 +533,27 @@ int xc_hvm_inject_msi(
int xc_hvm_track_dirty_vram(
xc_interface *xch, domid_t dom,
-uint64_t first_pfn, uint64_t nr,
+uint64_t first_gfn, uint32_t nr,
unsigned long *dirty_bitmap)
{
+DECLARE_HVMCTL(track_dirty_vram, dom,
+ .first_gfn = first_gfn,
+ .nr= nr);
DECLARE_HYPERCALL_BOUNCE(dirty_bitmap, (nr+7) / 8,
XC_HYPERCALL_BUFFER_BOUNCE_OUT);
-DECLARE_HYPERCALL_BUFFER(struct xen_hvm_track_dirty_vram, arg);
int rc;
-arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
-if ( arg == NULL || xc_hypercall_bounce_pre(xch, dirty_bitmap) )
+if ( xc_hypercall_bounce_pre(xch, dirty_bitmap) )
{
PERROR("Could not bounce memory for xc_hvm_track_dirty_vram
hypercall");
-rc = -1;
-goto out;
+return -1;
}
-arg->domid = dom;
-arg->first_pfn = first_pfn;
-arg->nr= nr;
-set_xen_guest_handle(arg->dirty_bitmap, dirty_bitmap);
-
-rc = xencall2(xch->xcall, __HYPERVISOR_hvm_op,
- HVMOP_track_dirty_vram,
- HYPERCALL_BUFFER_AS_ARG(arg));
+set_xen_guest_handle(hvmctl.u.track_dirty_vram.dirty_bitmap, dirty_bitmap);
+
+rc = do_hvmctl(xch, );
-out:
-xc_hypercall_buffer_free(xch, arg);
xc_hypercall_bounce_post(xch, dirty_bitmap);
+
return rc;
}
--- a/xen/arch/x86/hvm/control.c
+++ b/xen/arch/x86/hvm/control.c
@@ -17,6 +17,8 @@
#include
#include
#include
+#include
+#include
#include
static int set_pci_intx_level(struct domain *d,
@@ -67,6 +69,27 @@ static int set_isa_irq_level(struct doma
return 0;
}
+static int track_dirty_vram(struct domain *d,
+const struct xen_hvm_track_dirty_vram *op)
+{
+if ( !is_hvm_domain(d) )
+return -EINVAL;
+
+if ( op->rsvd || op->nr > (GB(1) >> PAGE_SHIFT) )
+return -EINVAL;
+
+if ( d->is_dying )
+return -ESRCH;
+
+if ( !d->max_vcpus || !d->vcpu[0] )
+return -EINVAL;
+
+return shadow_mode_enabled(d)
+ ? shadow_track_dirty_vram(d, op->first_gfn, op->nr,
+ op->dirty_bitmap)
+ : hap_track_dirty_vram(d, op->first_gfn, op->nr, op->dirty_bitmap);
+}
+
long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xen_hvmctl_t) u_hvmctl)
{
xen_hvmctl_t op;
@@ -113,6 +136,10 @@ long do_hvmctl(XEN_GUEST_HANDLE_PARAM(xe
op.u.set_pci_link_route.isa_irq);
break;
+case XEN_HVMCTL_track_dirty_vram:
+rc = track_dirty_vram(d, _dirty_vram);
+break;
+
default:
rc = -EOPNOTSUPP;
break;
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -5296,47 +5296,6 @@ long do_hvm_op(unsigned long op, XEN_GUE
rc = guest_handle_is_null(arg) ? hvmop_flush_tlb_all() : -ENOSYS;
break;
-case HVMOP_track_dirty_vram:
-{
-struct xen_hvm_track_dirty_vram a;
-struct domain *d;
-
-if ( copy_from_guest(, arg, 1) )
-return -EFAULT;
-
-rc = rcu_lock_remote_domain_by_id(a.domid, );
-if ( rc != 0 )
-return rc;
-
-rc = -EINVAL;
-if ( !is_hvm_domain(d) )
-goto tdv_fail;
-
-if ( a.nr > GB(1) >> PAGE_SHIFT )
-goto tdv_fail;
-
-rc = xsm_hvm_control(XSM_DM_PRIV, d, op);
-if ( rc )
-goto tdv_fail;
-
-rc = -ESRCH;
-if ( d->is_dying )
-goto tdv_fail;
-
-rc = -EINVAL;
-if ( d->vcpu == NULL || d->vcpu[0] == NULL )
-goto tdv_fail;
-
-if ( shadow_mode_enabled(d) )
-rc = shadow_track_dirty_vram(d, a.first_pfn, a.nr, a.dirty_bitmap);
-else
-rc = hap_track_dirty_vram(d, a.first_pfn, a.nr, a.dirty_bitmap);
-
-tdv_fail:
-rcu_unlock_domain(d);
-break;
-}
-
case HVMOP_modified_memory:
{
struct xen_hvm_modified_memory a;
--- a/xen/include/public/hvm/control.h
+++ b/xen/include/public/hvm/control.h
@@ -55,6 +55,18 @@ struct xen_hvm_set_pci_link_route {
uint8_t isa_irq;
};
+/* XEN_HVMCTL_track_dirty_vram */
+struct xen_hvm_track_dirty_vram {
+/* Number of pages to track. */
+uint32_t nr;
+uint32_t rsvd;
+/* First GFN to track. */
+