diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c index 1a58228086..bfb5b423a0 100644 --- a/xen/arch/x86/mm/paging.c +++ b/xen/arch/x86/mm/paging.c @@ -746,11 +746,15 @@ long do_paging_domctl_cont( ret = xsm_domctl(XSM_OTHER, d, &op); if ( !ret ) { - if ( domctl_lock_acquire() ) + bool lock = !(op.u.shadow_op.op == XEN_DOMCTL_SHADOW_OP_CLEAN || + op.u.shadow_op.op == XEN_DOMCTL_SHADOW_OP_PEEK); + + if ( !lock || domctl_lock_acquire() ) { ret = paging_domctl(d, &op.u.shadow_op, u_domctl, 1); - domctl_lock_release(); + if ( lock ) + domctl_lock_release(); } else ret = -ERESTART; diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 35144d95b8..6f71a68d51 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -546,6 +546,19 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) /* Other sub-ops handled further down. */ break; + case XEN_DOMCTL_shadow_op: + if ( op->u.shadow_op.op == XEN_DOMCTL_SHADOW_OP_CLEAN || + op->u.shadow_op.op == XEN_DOMCTL_SHADOW_OP_PEEK ) + { + ret = xsm_domctl(XSM_OTHER, d, op); + if ( ret ) + goto domctl_out_unlock_domonly; + + ret = arch_do_domctl(op, d, u_domctl); + goto domctl_out_unlock_domonly; + } + break; + case XEN_DOMCTL_get_device_group: ret = iommu_do_domctl(op, d, u_domctl); goto domctl_out_unlock_domonly;