Skip to content

Commit a9fcbe1

Browse files
dozylynxandyhhp
authored andcommitted
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 <[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
1 parent b953d43 commit a9fcbe1

File tree

4 files changed

+139
-0
lines changed

4 files changed

+139
-0
lines changed

xen/common/argo.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_argo_addr_t);
4343
DEFINE_XEN_GUEST_HANDLE(xen_argo_gfn_t);
4444
DEFINE_XEN_GUEST_HANDLE(xen_argo_register_ring_t);
4545
DEFINE_XEN_GUEST_HANDLE(xen_argo_ring_t);
46+
DEFINE_XEN_GUEST_HANDLE(xen_argo_unregister_ring_t);
4647

4748
static bool __read_mostly opt_argo;
4849
static bool __read_mostly opt_argo_mac_permissive;
@@ -346,6 +347,33 @@ find_ring_info(const struct domain *d, const struct argo_ring_id *id)
346347
return NULL;
347348
}
348349

350+
static struct argo_send_info *
351+
find_send_info(const struct domain *d, const struct argo_ring_id *id)
352+
{
353+
struct hlist_node *node;
354+
struct argo_send_info *send_info;
355+
356+
ASSERT(LOCKING_send_L2(d));
357+
358+
hlist_for_each_entry(send_info, node, &d->argo->send_hash[hash_index(id)],
359+
node)
360+
{
361+
const struct argo_ring_id *cmpid = &send_info->id;
362+
363+
if ( cmpid->aport == id->aport &&
364+
cmpid->domain_id == id->domain_id &&
365+
cmpid->partner_id == id->partner_id )
366+
{
367+
argo_dprintk("send_info=%p\n", send_info);
368+
return send_info;
369+
}
370+
}
371+
argo_dprintk("no send_info found for ring(%u:%x %u)\n",
372+
id->domain_id, id->aport, id->partner_id);
373+
374+
return NULL;
375+
}
376+
349377
static void
350378
ring_unmap(const struct domain *d, struct argo_ring_info *ring_info)
351379
{
@@ -713,6 +741,81 @@ find_ring_mfns(struct domain *d, struct argo_ring_info *ring_info,
713741
* * shrink critical sections: move acquire/release of the global lock.
714742
* * simplify the out label path when lock release has been moved.
715743
*/
744+
static long
745+
unregister_ring(struct domain *currd,
746+
XEN_GUEST_HANDLE_PARAM(xen_argo_unregister_ring_t) unreg_hnd)
747+
{
748+
xen_argo_unregister_ring_t unreg;
749+
struct argo_ring_id ring_id;
750+
struct argo_ring_info *ring_info;
751+
struct argo_send_info *send_info = NULL;
752+
struct domain *dst_d = NULL;
753+
int ret = 0;
754+
755+
ASSERT(currd == current->domain);
756+
757+
if ( copy_from_guest(&unreg, unreg_hnd, 1) )
758+
return -EFAULT;
759+
760+
if ( unreg.pad )
761+
return -EINVAL;
762+
763+
ring_id.partner_id = unreg.partner_id;
764+
ring_id.aport = unreg.aport;
765+
ring_id.domain_id = currd->domain_id;
766+
767+
read_lock(&L1_global_argo_rwlock);
768+
769+
if ( !currd->argo )
770+
{
771+
ret = -ENODEV;
772+
goto out_unlock;
773+
}
774+
775+
write_lock(&currd->argo->rings_L2_rwlock);
776+
777+
ring_info = find_ring_info(currd, &ring_id);
778+
if ( ring_info )
779+
{
780+
ring_remove_info(currd, ring_info);
781+
currd->argo->ring_count--;
782+
}
783+
784+
dst_d = get_domain_by_id(ring_id.partner_id);
785+
if ( dst_d )
786+
{
787+
if ( dst_d->argo )
788+
{
789+
spin_lock(&dst_d->argo->send_L2_lock);
790+
791+
send_info = find_send_info(dst_d, &ring_id);
792+
if ( send_info )
793+
hlist_del(&send_info->node);
794+
795+
spin_unlock(&dst_d->argo->send_L2_lock);
796+
797+
}
798+
put_domain(dst_d);
799+
}
800+
801+
write_unlock(&currd->argo->rings_L2_rwlock);
802+
803+
if ( send_info )
804+
xfree(send_info);
805+
806+
if ( !ring_info )
807+
{
808+
argo_dprintk("ENOENT\n");
809+
ret = -ENOENT;
810+
goto out_unlock;
811+
}
812+
813+
out_unlock:
814+
read_unlock(&L1_global_argo_rwlock);
815+
816+
return ret;
817+
}
818+
716819
static long
717820
register_ring(struct domain *currd,
718821
XEN_GUEST_HANDLE_PARAM(xen_argo_register_ring_t) reg_hnd,
@@ -999,6 +1102,21 @@ do_argo_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) arg1,
9991102
break;
10001103
}
10011104

1105+
case XEN_ARGO_OP_unregister_ring:
1106+
{
1107+
XEN_GUEST_HANDLE_PARAM(xen_argo_unregister_ring_t) unreg_hnd =
1108+
guest_handle_cast(arg1, xen_argo_unregister_ring_t);
1109+
1110+
if ( unlikely((!guest_handle_is_null(arg2)) || arg3 || arg4) )
1111+
{
1112+
rc = -EINVAL;
1113+
break;
1114+
}
1115+
1116+
rc = unregister_ring(currd, unreg_hnd);
1117+
break;
1118+
}
1119+
10021120
default:
10031121
rc = -EOPNOTSUPP;
10041122
break;

xen/common/compat/argo.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@
2222
CHECK_argo_addr;
2323
CHECK_argo_register_ring;
2424
CHECK_argo_ring;
25+
CHECK_argo_unregister_ring;

xen/include/public/argo.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ typedef struct xen_argo_register_ring
7979
uint32_t len;
8080
} xen_argo_register_ring_t;
8181

82+
typedef struct xen_argo_unregister_ring
83+
{
84+
xen_argo_port_t aport;
85+
domid_t partner_id;
86+
uint16_t pad;
87+
} xen_argo_unregister_ring_t;
88+
8289
/* Messages on the ring are padded to a multiple of this size. */
8390
#define XEN_ARGO_MSG_SLOT_SIZE 0x10
8491

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

148+
/*
149+
* XEN_ARGO_OP_unregister_ring
150+
*
151+
* Unregister a previously-registered ring, ending communication.
152+
*
153+
* arg1: XEN_GUEST_HANDLE(xen_argo_unregister_ring_t)
154+
* arg2: NULL
155+
* arg3: 0 (ZERO)
156+
* arg4: 0 (ZERO)
157+
*/
158+
#define XEN_ARGO_OP_unregister_ring 2
159+
141160
#endif

xen/include/xlat.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,4 @@
151151
? argo_addr argo.h
152152
? argo_ring argo.h
153153
? argo_register_ring argo.h
154+
? argo_unregister_ring argo.h

0 commit comments

Comments
 (0)