[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 |