Skip to content

Commit 2ff183a

Browse files
dozylynxEric Chanudet
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]> 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 xen-project#8 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 xen-project#8 Jan: move put_domain outside L2 critical section v4: include ring data in debug output when ring not found 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 5d0443c commit 2ff183a

File tree

3 files changed

+147
-0
lines changed

3 files changed

+147
-0
lines changed

xen/common/argo.c

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
CHECK_argo_addr;
3535
CHECK_argo_register_ring;
3636
CHECK_argo_ring;
37+
CHECK_argo_unregister_ring;
3738
#endif
3839

3940
#define MAX_RINGS_PER_DOMAIN 128U
@@ -50,6 +51,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_argo_addr_t);
5051
DEFINE_XEN_GUEST_HANDLE(xen_argo_gfn_t);
5152
DEFINE_XEN_GUEST_HANDLE(xen_argo_register_ring_t);
5253
DEFINE_XEN_GUEST_HANDLE(xen_argo_ring_t);
54+
DEFINE_XEN_GUEST_HANDLE(xen_argo_unregister_ring_t);
5355

5456
static bool __read_mostly opt_argo;
5557
static bool __read_mostly opt_argo_mac_permissive;
@@ -358,6 +360,37 @@ find_ring_info(const struct domain *d, const struct argo_ring_id *id)
358360
return NULL;
359361
}
360362

363+
static struct argo_send_info *
364+
find_send_info(const struct domain *d, const struct argo_ring_id *id)
365+
{
366+
struct list_head *cursor, *bucket;
367+
368+
ASSERT(LOCKING_send_L2(d));
369+
370+
/* List is not modified here. Search and return the match if found. */
371+
bucket = &d->argo->send_hash[hash_index(id)];
372+
373+
for ( cursor = bucket->next; cursor != bucket; cursor = cursor->next )
374+
{
375+
struct argo_send_info *send_info =
376+
list_entry(cursor, struct argo_send_info, node);
377+
const struct argo_ring_id *cmpid = &send_info->id;
378+
379+
if ( cmpid->aport == id->aport &&
380+
cmpid->domain_id == id->domain_id &&
381+
cmpid->partner_id == id->partner_id )
382+
{
383+
argo_dprintk("found send_info for ring(%u:%x %u)\n",
384+
id->domain_id, id->aport, id->partner_id);
385+
return send_info;
386+
}
387+
}
388+
argo_dprintk("no send_info for ring(%u:%x %u)\n",
389+
id->domain_id, id->aport, id->partner_id);
390+
391+
return NULL;
392+
}
393+
361394
static void
362395
ring_unmap(const struct domain *d, struct argo_ring_info *ring_info)
363396
{
@@ -741,6 +774,85 @@ find_ring_mfns(struct domain *d, struct argo_ring_info *ring_info,
741774
return ret;
742775
}
743776

777+
static long
778+
unregister_ring(struct domain *currd,
779+
XEN_GUEST_HANDLE_PARAM(xen_argo_unregister_ring_t) unreg_hnd)
780+
{
781+
xen_argo_unregister_ring_t unreg;
782+
struct argo_ring_id ring_id;
783+
struct argo_ring_info *ring_info = NULL;
784+
struct argo_send_info *send_info = NULL;
785+
struct domain *dst_d = NULL;
786+
787+
ASSERT(currd == current->domain);
788+
789+
if ( copy_from_guest(&unreg, unreg_hnd, 1) )
790+
return -EFAULT;
791+
792+
if ( unreg.pad )
793+
return -EINVAL;
794+
795+
ring_id.partner_id = unreg.partner_id;
796+
ring_id.aport = unreg.aport;
797+
ring_id.domain_id = currd->domain_id;
798+
799+
read_lock(&L1_global_argo_rwlock);
800+
801+
if ( unlikely(!currd->argo) )
802+
{
803+
read_unlock(&L1_global_argo_rwlock);
804+
return -ENODEV;
805+
}
806+
807+
write_lock(&currd->argo->rings_L2_rwlock);
808+
809+
ring_info = find_ring_info(currd, &ring_id);
810+
if ( !ring_info )
811+
goto out;
812+
813+
ring_remove_info(currd, ring_info);
814+
currd->argo->ring_count--;
815+
816+
if ( ring_id.partner_id == XEN_ARGO_DOMID_ANY )
817+
goto out;
818+
819+
dst_d = get_domain_by_id(ring_id.partner_id);
820+
if ( !dst_d || !dst_d->argo )
821+
{
822+
ASSERT_UNREACHABLE();
823+
goto out;
824+
}
825+
826+
spin_lock(&dst_d->argo->send_L2_lock);
827+
828+
send_info = find_send_info(dst_d, &ring_id);
829+
if ( send_info )
830+
list_del(&send_info->node);
831+
else
832+
ASSERT_UNREACHABLE();
833+
834+
spin_unlock(&dst_d->argo->send_L2_lock);
835+
836+
out:
837+
write_unlock(&currd->argo->rings_L2_rwlock);
838+
839+
read_unlock(&L1_global_argo_rwlock);
840+
841+
if ( dst_d )
842+
put_domain(dst_d);
843+
844+
xfree(send_info);
845+
846+
if ( !ring_info )
847+
{
848+
argo_dprintk("unregister_ring: no ring_info found for ring(%u:%x %u)\n",
849+
ring_id.domain_id, ring_id.aport, ring_id.partner_id);
850+
return -ENOENT;
851+
}
852+
853+
return 0;
854+
}
855+
744856
static long
745857
register_ring(struct domain *currd,
746858
XEN_GUEST_HANDLE_PARAM(xen_argo_register_ring_t) reg_hnd,
@@ -1031,6 +1143,21 @@ do_argo_op(unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) arg1,
10311143
break;
10321144
}
10331145

1146+
case XEN_ARGO_OP_unregister_ring:
1147+
{
1148+
XEN_GUEST_HANDLE_PARAM(xen_argo_unregister_ring_t) unreg_hnd =
1149+
guest_handle_cast(arg1, xen_argo_unregister_ring_t);
1150+
1151+
if ( unlikely((!guest_handle_is_null(arg2)) || arg3 || arg4) )
1152+
{
1153+
rc = -EINVAL;
1154+
break;
1155+
}
1156+
1157+
rc = unregister_ring(currd, unreg_hnd);
1158+
break;
1159+
}
1160+
10341161
default:
10351162
rc = -EOPNOTSUPP;
10361163
break;

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

@@ -134,4 +141,16 @@ struct xen_argo_ring_message_header
134141
#define XEN_ARGO_REGISTER_FLAG_MASK XEN_ARGO_REGISTER_FLAG_FAIL_EXIST
135142
#endif
136143

144+
/*
145+
* XEN_ARGO_OP_unregister_ring
146+
*
147+
* Unregister a previously-registered ring, ending communication.
148+
*
149+
* arg1: XEN_GUEST_HANDLE(xen_argo_unregister_ring_t)
150+
* arg2: NULL
151+
* arg3: 0 (ZERO)
152+
* arg4: 0 (ZERO)
153+
*/
154+
#define XEN_ARGO_OP_unregister_ring 2
155+
137156
#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)