Skip to content

Commit

Permalink
argo: implement the unregister op
Browse files Browse the repository at this point in the history
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 <[email protected]>

v3 xen-project#8 Jan: pull xfree out of exclusive critical sections in unregister_ring
v3 xen-project#8 Jan: rename send_find_info to find_send_info
v3 xen-project#7 Jan: rename ring_find_info to find_ring_info
v3 xen-project#8 Roger: use return and remove the out label in unregister_ring
v3 xen-project#8 Roger: better debug output in send_find_info
v3 #10 Roger: move find functions to top of file and drop prototypes
v3 xen-project#4 Jan: meld compat check for unregister_ring struct
v3 xen-project#4 Roger/Jan: make lock names clearer and assert their state
v3 xen-project#4 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 xen-project#7 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 xen-project#5 (#14) feedback Paul: use currd in do_argo_message_op
v1 xen-project#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
  • Loading branch information
dozylynx authored and andyhhp committed Jan 15, 2019
1 parent e40c07f commit c2f0128
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 0 deletions.
118 changes: 118 additions & 0 deletions xen/common/argo.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_argo_addr_t);
DEFINE_XEN_GUEST_HANDLE(xen_argo_gfn_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);

static bool __read_mostly opt_argo;
static bool __read_mostly opt_argo_mac_permissive;
Expand Down Expand Up @@ -346,6 +347,33 @@ 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 hlist_node *node;
struct argo_send_info *send_info;

ASSERT(LOCKING_send_L2(d));

hlist_for_each_entry(send_info, node, &d->argo->send_hash[hash_index(id)],
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("send_info=%p\n", send_info);
return send_info;
}
}
argo_dprintk("no send_info found 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)
{
Expand Down Expand Up @@ -713,6 +741,81 @@ find_ring_mfns(struct domain *d, struct argo_ring_info *ring_info,
* * shrink critical sections: move acquire/release of the global lock.
* * simplify the out label path when lock release has been moved.
*/
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;
struct argo_send_info *send_info = NULL;
struct domain *dst_d = NULL;
int ret = 0;

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 ( !currd->argo )
{
ret = -ENODEV;
goto out_unlock;
}

write_lock(&currd->argo->rings_L2_rwlock);

ring_info = find_ring_info(currd, &ring_id);
if ( ring_info )
{
ring_remove_info(currd, ring_info);
currd->argo->ring_count--;
}

dst_d = get_domain_by_id(ring_id.partner_id);
if ( dst_d )
{
if ( dst_d->argo )
{
spin_lock(&dst_d->argo->send_L2_lock);

send_info = find_send_info(dst_d, &ring_id);
if ( send_info )
hlist_del(&send_info->node);

spin_unlock(&dst_d->argo->send_L2_lock);

}
put_domain(dst_d);
}

write_unlock(&currd->argo->rings_L2_rwlock);

if ( send_info )
xfree(send_info);

if ( !ring_info )
{
argo_dprintk("ENOENT\n");
ret = -ENOENT;
goto out_unlock;
}

out_unlock:
read_unlock(&L1_global_argo_rwlock);

return ret;
}

static long
register_ring(struct domain *currd,
XEN_GUEST_HANDLE_PARAM(xen_argo_register_ring_t) reg_hnd,
Expand Down Expand Up @@ -999,6 +1102,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;
Expand Down
1 change: 1 addition & 0 deletions xen/common/compat/argo.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@
CHECK_argo_addr;
CHECK_argo_register_ring;
CHECK_argo_ring;
CHECK_argo_unregister_ring;
19 changes: 19 additions & 0 deletions xen/include/public/argo.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,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

Expand Down Expand Up @@ -138,4 +145,16 @@ struct xen_argo_ring_message_header
/* Mask for all defined flags. unsigned long type so ok for both 32/64-bit */
#define XEN_ARGO_REGISTER_FLAG_MASK 0x1UL

/*
* 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
1 change: 1 addition & 0 deletions xen/include/xlat.lst
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,4 @@
? argo_addr argo.h
? argo_ring argo.h
? argo_register_ring argo.h
? argo_unregister_ring argo.h

0 comments on commit c2f0128

Please sign in to comment.