|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v7 08/15] argo: implement the unregister op
Takes a single argument: a handle to the ring unregistration struct,
which specifies the port and partner domain id or wildcard.
The ring's entry is removed from the hashtable of registered rings;
any entries for pending notifications are removed; and the ring is
unmapped from Xen's address space.
If the ring had been registered to communicate with a single specified
domain (ie. a non-wildcard ring) then the partner domain state is removed
from the partner domain's argo send_info hash table.
Signed-off-by: Christopher Clark <christopher.clark6@xxxxxxxxxxxxxx>
Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
Tested-by: Chris Patterson <pattersonc@xxxxxxxxxxxx>
---
v6 #09 Jan: add compat ABI
v6 Chris: add Tested-by
v6 Roger: add Reviewed-by
v6 #04 Jan: xlat.lst: move argo struct entries to alphabetical position
v6 #04 Roger: use list_for_each_entry for looping
v5: add compat validation macros to primary source file: common/argo.c
v5: dropped external file for compat macros: common/compat/argo.c
v4 # Jan: shrink the critical sections in unregister
v4 : use standard data structures as per common code
v4 #08 Roger: skip send_info lookup for wildcard rings
v4: add ASSERT_UNREACHABLE for missing sender domain or send_info
v4: reduce indentation by using goto
v4: add unlikely to currd->argo check
v4 #08 Jan: move put_domain outside L2 critical section
v4: include ring data in debug output when ring not found
v3 #08 Jan: pull xfree out of exclusive critical sections in unregister_ring
v3 #08 Jan: rename send_find_info to find_send_info
v3 #07 Jan: rename ring_find_info to find_ring_info
v3 #08 Roger: use return and remove the out label in unregister_ring
v3 #08 Roger: better debug output in send_find_info
v3 #10 Roger: move find functions to top of file and drop prototypes
v3 #04 Jan: meld compat check for unregister_ring struct
v3 #04 Roger/Jan: make lock names clearer and assert their state
v3 #04 Jan: port -> aport with type; distinguish argo port from evtchn
v3 feedback Roger/Jan: ASSERT currd is current->domain or use 'd' variable name
v3 feedback #07 Roger: const the argo_ring_id structs in send_find_info
v2 feedback Jan: drop cookie, implement teardown
v2 feedback Jan: drop message from argo_message_op
v2 self: OVERHAUL
v2 self: reorder logic to shorten critical section
v1 #13 feedback Jan: revise use of guest_handle_okay vs __copy ops
v1 feedback Roger, Jan: drop argo prefix on static functions
v1,2 feedback Jan/Roger/Paul: drop errno returning guest access functions
v1 #5 (#14) feedback Paul: use currd in do_argo_message_op
v1 #5 (#14) feedback Paul: full use currd in argo_unregister_ring
v1 #13 (#14) feedback Paul: replace do/while with goto; reindent
v1 self: add blank lines in unregister case in do_argo_message_op
v1: #13 feedback Jan: public namespace: prefix with xen
v1: #13 feedback Jan: blank line after op case in do_argo_message_op
v1: #14 feedback Jan: replace domain id override with validation
v1: #18 feedback Jan: meld the ring count limit into the series
v1: feedback #15 Jan: verify zero in unused hypercall args
xen/common/argo.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++
xen/include/public/argo.h | 19 +++++++
xen/include/xlat.lst | 1 +
3 files changed, 160 insertions(+)
diff --git a/xen/common/argo.c b/xen/common/argo.c
index 54256ae..e724fc7 100644
--- a/xen/common/argo.c
+++ b/xen/common/argo.c
@@ -37,6 +37,7 @@ CHECK_argo_addr;
CHECK_argo_register_ring;
CHECK_argo_ring;
CHECK_argo_ring_message_header;
+CHECK_argo_unregister_ring;
#endif
#define MAX_RINGS_PER_DOMAIN 128U
@@ -52,6 +53,7 @@ CHECK_argo_ring_message_header;
DEFINE_XEN_GUEST_HANDLE(xen_argo_addr_t);
DEFINE_XEN_GUEST_HANDLE(xen_argo_register_ring_t);
DEFINE_XEN_GUEST_HANDLE(xen_argo_ring_t);
+DEFINE_XEN_GUEST_HANDLE(xen_argo_unregister_ring_t);
#ifdef CONFIG_COMPAT
DEFINE_XEN_GUEST_HANDLE(compat_pfn_t);
#endif
@@ -362,6 +364,36 @@ find_ring_info(const struct domain *d, const struct
argo_ring_id *id)
return NULL;
}
+static struct argo_send_info *
+find_send_info(const struct domain *d, const struct argo_ring_id *id)
+{
+ struct argo_send_info *send_info;
+ const struct list_head *bucket;
+
+ ASSERT(LOCKING_send_L2(d));
+
+ /* List is not modified here. Search and return the match if found. */
+ bucket = &d->argo->send_hash[hash_index(id)];
+
+ list_for_each_entry(send_info, bucket, node)
+ {
+ const struct argo_ring_id *cmpid = &send_info->id;
+
+ if ( cmpid->aport == id->aport &&
+ cmpid->domain_id == id->domain_id &&
+ cmpid->partner_id == id->partner_id )
+ {
+ argo_dprintk("found send_info for ring(%u:%x %u)\n",
+ id->domain_id, id->aport, id->partner_id);
+ return send_info;
+ }
+ }
+ argo_dprintk("no send_info for ring(%u:%x %u)\n",
+ id->domain_id, id->aport, id->partner_id);
+
+ return NULL;
+}
+
static void
ring_unmap(const struct domain *d, struct argo_ring_info *ring_info)
{
@@ -765,6 +797,85 @@ find_ring_mfns(struct domain *d, struct argo_ring_info
*ring_info,
}
static long
+unregister_ring(struct domain *currd,
+ XEN_GUEST_HANDLE_PARAM(xen_argo_unregister_ring_t) unreg_hnd)
+{
+ xen_argo_unregister_ring_t unreg;
+ struct argo_ring_id ring_id;
+ struct argo_ring_info *ring_info = NULL;
+ struct argo_send_info *send_info = NULL;
+ struct domain *dst_d = NULL;
+
+ ASSERT(currd == current->domain);
+
+ if ( copy_from_guest(&unreg, unreg_hnd, 1) )
+ return -EFAULT;
+
+ if ( unreg.pad )
+ return -EINVAL;
+
+ ring_id.partner_id = unreg.partner_id;
+ ring_id.aport = unreg.aport;
+ ring_id.domain_id = currd->domain_id;
+
+ read_lock(&L1_global_argo_rwlock);
+
+ if ( unlikely(!currd->argo) )
+ {
+ read_unlock(&L1_global_argo_rwlock);
+ return -ENODEV;
+ }
+
+ write_lock(&currd->argo->rings_L2_rwlock);
+
+ ring_info = find_ring_info(currd, &ring_id);
+ if ( !ring_info )
+ goto out;
+
+ ring_remove_info(currd, ring_info);
+ currd->argo->ring_count--;
+
+ if ( ring_id.partner_id == XEN_ARGO_DOMID_ANY )
+ goto out;
+
+ dst_d = get_domain_by_id(ring_id.partner_id);
+ if ( !dst_d || !dst_d->argo )
+ {
+ ASSERT_UNREACHABLE();
+ goto out;
+ }
+
+ spin_lock(&dst_d->argo->send_L2_lock);
+
+ send_info = find_send_info(dst_d, &ring_id);
+ if ( send_info )
+ list_del(&send_info->node);
+ else
+ ASSERT_UNREACHABLE();
+
+ spin_unlock(&dst_d->argo->send_L2_lock);
+
+ out:
+ write_unlock(&currd->argo->rings_L2_rwlock);
+
+ read_unlock(&L1_global_argo_rwlock);
+
+ if ( dst_d )
+ put_domain(dst_d);
+
+ xfree(send_info);
+
+ if ( !ring_info )
+ {
+ argo_dprintk("unregister_ring: no ring_info found for ring(%u:%x
%u)\n",
+ ring_id.domain_id, ring_id.aport, ring_id.partner_id);
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+static long
register_ring(struct domain *currd,
XEN_GUEST_HANDLE_PARAM(xen_argo_register_ring_t) reg_hnd,
XEN_GUEST_HANDLE_PARAM(void) gfn_hnd,
@@ -1049,6 +1160,21 @@ do_argo_op(unsigned int cmd,
XEN_GUEST_HANDLE_PARAM(void) arg1,
break;
}
+ case XEN_ARGO_OP_unregister_ring:
+ {
+ XEN_GUEST_HANDLE_PARAM(xen_argo_unregister_ring_t) unreg_hnd =
+ guest_handle_cast(arg1, xen_argo_unregister_ring_t);
+
+ if ( unlikely((!guest_handle_is_null(arg2)) || arg3 || arg4) )
+ {
+ rc = -EINVAL;
+ break;
+ }
+
+ rc = unregister_ring(currd, unreg_hnd);
+ break;
+ }
+
default:
rc = -EOPNOTSUPP;
break;
@@ -1096,6 +1222,20 @@ compat_argo_op(unsigned int cmd,
XEN_GUEST_HANDLE_PARAM(void) arg1,
break;
}
+ case XEN_ARGO_OP_unregister_ring:
+ {
+ XEN_GUEST_HANDLE_PARAM(xen_argo_unregister_ring_t) unreg_hnd =
+ guest_handle_cast(arg1, xen_argo_unregister_ring_t);
+
+ if ( unlikely((!guest_handle_is_null(arg2)) || arg3 || arg4) )
+ {
+ rc = -EINVAL;
+ break;
+ }
+
+ rc = unregister_ring(currd, unreg_hnd);
+ break;
+ }
default:
rc = -EOPNOTSUPP;
diff --git a/xen/include/public/argo.h b/xen/include/public/argo.h
index 667a8ba..83585de 100644
--- a/xen/include/public/argo.h
+++ b/xen/include/public/argo.h
@@ -76,6 +76,13 @@ typedef struct xen_argo_register_ring
uint32_t len;
} xen_argo_register_ring_t;
+typedef struct xen_argo_unregister_ring
+{
+ xen_argo_port_t aport;
+ domid_t partner_id;
+ uint16_t pad;
+} xen_argo_unregister_ring_t;
+
/* Messages on the ring are padded to a multiple of this size. */
#define XEN_ARGO_MSG_SLOT_SIZE 0x10
@@ -131,4 +138,16 @@ struct xen_argo_ring_message_header
#define XEN_ARGO_REGISTER_FLAG_MASK XEN_ARGO_REGISTER_FLAG_FAIL_EXIST
#endif
+/*
+ * XEN_ARGO_OP_unregister_ring
+ *
+ * Unregister a previously-registered ring, ending communication.
+ *
+ * arg1: XEN_GUEST_HANDLE(xen_argo_unregister_ring_t)
+ * arg2: NULL
+ * arg3: 0 (ZERO)
+ * arg4: 0 (ZERO)
+ */
+#define XEN_ARGO_OP_unregister_ring 2
+
#endif
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index 349fbad..ee7dffc 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -34,6 +34,7 @@
? argo_register_ring argo.h
? argo_ring argo.h
? argo_ring_message_header argo.h
+? argo_unregister_ring argo.h
? evtchn_alloc_unbound event_channel.h
? evtchn_bind_interdomain event_channel.h
? evtchn_bind_ipi event_channel.h
--
2.7.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |