1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <ctype.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <sys/uio.h>
40 #include <sys/sysmacros.h>
41 #include <sys/resource.h>
42 #include <errno.h>
43 #include <assert.h>
44 #include <fcntl.h>
45 #include <dlfcn.h>
46 #include <sched.h>
47 #include <stropts.h>
48 #include <poll.h>
49
50 #include <rsmapi.h>
51 #include <sys/rsm/rsmndi.h>
52 #include <rsmlib_in.h>
53 #include <sys/rsm/rsm.h>
54
55 /* lint -w2 */
56 extern void __rsmloopback_init_ops(rsm_segops_t *);
57 extern void __rsmdefault_setops(rsm_segops_t *);
58
59 typedef void (*rsm_access_func_t)(void *, void *, rsm_access_size_t);
60
61 #ifdef DEBUG
62
63 #define RSMLOG_BUF_SIZE 256
64 FILE *rsmlog_fd = NULL;
65 static mutex_t rsmlog_lock;
66 int rsmlibdbg_category = RSM_LIBRARY;
67 int rsmlibdbg_level = RSM_ERR;
68 void dbg_printf(int category, int level, char *fmt, ...);
69
70 #endif /* DEBUG */
71
72 rsm_node_id_t rsm_local_nodeid = 0;
73
74 static rsm_controller_t *controller_list = NULL;
75
76 static rsm_segops_t loopback_ops;
77
78 #define MAX_STRLEN 80
79
80 #define RSM_IOTYPE_PUTGET 1
81 #define RSM_IOTYPE_SCATGATH 2
82
83 #define RSMFILE_BUFSIZE 256
84
85 #pragma init(_rsm_librsm_init)
86
87 static mutex_t _rsm_lock;
88
89 static int _rsm_fd = -1;
90 static rsm_gnum_t *bar_va, bar_fixed = 0;
91 static rsm_pollfd_table_t pollfd_table;
92
93 static int _rsm_get_hwaddr(rsmapi_controller_handle_t handle,
94 rsm_node_id_t, rsm_addr_t *hwaddrp);
95 static int _rsm_get_nodeid(rsmapi_controller_handle_t,
96 rsm_addr_t, rsm_node_id_t *);
97 static int __rsm_import_implicit_map(rsmseg_handle_t *, int);
98 static int __rsm_intr_signal_wait_common(struct pollfd [], minor_t [],
99 nfds_t, int, int *);
100
101 static rsm_lib_funcs_t lib_functions = {
102 RSM_LIB_FUNCS_VERSION,
103 _rsm_get_hwaddr,
104 _rsm_get_nodeid
105 };
106
107 rsm_topology_t *tp;
108
109
110 /*
111 * service module function templates:
112 */
113
114 /*
115 * The _rsm_librsm_init function is called the first time an application
116 * references the RSMAPI library
117 */
118 int
_rsm_librsm_init()119 _rsm_librsm_init()
120 {
121 rsm_ioctlmsg_t msg;
122 int e, tmpfd;
123 int i;
124 char logname[MAXNAMELEN];
125
126 mutex_init(&_rsm_lock, USYNC_THREAD, NULL);
127
128 #ifdef DEBUG
129 mutex_init(&rsmlog_lock, USYNC_THREAD, NULL);
130 sprintf(logname, "%s.%d", TRACELOG, getpid());
131 rsmlog_fd = fopen(logname, "w+F");
132 if (rsmlog_fd == NULL) {
133 fprintf(stderr, "Log file open failed\n");
134 return (errno);
135 }
136
137 #endif /* DEBUG */
138
139 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
140 "_rsm_librsm_init: enter\n"));
141
142 /* initialize the pollfd_table */
143 mutex_init(&pollfd_table.lock, USYNC_THREAD, NULL);
144
145 for (i = 0; i < RSM_MAX_BUCKETS; i++) {
146 pollfd_table.buckets[i] = NULL;
147 }
148
149 /* open /dev/rsm and mmap barrier generation pages */
150 mutex_lock(&_rsm_lock);
151 _rsm_fd = open(DEVRSM, O_RDONLY);
152 if (_rsm_fd < 0) {
153 DBPRINTF((RSM_LIBRARY, RSM_ERR,
154 "unable to open /dev/rsm\n"));
155 mutex_unlock(&_rsm_lock);
156 return (errno);
157 }
158
159 /*
160 * DUP the opened file descriptor to something greater than
161 * STDERR_FILENO so that we never use the STDIN_FILENO,
162 * STDOUT_FILENO or STDERR_FILENO.
163 */
164 tmpfd = fcntl(_rsm_fd, F_DUPFD, 3);
165 if (tmpfd < 0) {
166 DBPRINTF((RSM_LIBRARY, RSM_ERR,
167 "F_DUPFD failed\n"));
168 } else {
169 (void) close(_rsm_fd);
170 _rsm_fd = tmpfd;
171 }
172
173 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
174 "_rsm_fd is %d\n", _rsm_fd));
175
176 if (fcntl(_rsm_fd, F_SETFD, FD_CLOEXEC) < 0) {
177 DBPRINTF((RSM_LIBRARY, RSM_ERR,
178 "F_SETFD failed\n"));
179 }
180
181 /* get mapping generation number page info */
182 if (ioctl(_rsm_fd, RSM_IOCTL_BAR_INFO, &msg) < 0) {
183 DBPRINTF((RSM_LIBRARY, RSM_ERR,
184 "RSM_IOCTL_BAR_INFO failed\n"));
185 mutex_unlock(&_rsm_lock);
186 return (errno);
187 }
188
189 /*
190 * bar_va is mapped to the mapping generation number page
191 * in order to support close barrier
192 */
193 /* LINTED */
194 bar_va = (rsm_gnum_t *)mmap(NULL, msg.len,
195 PROT_READ, MAP_SHARED, _rsm_fd, msg.off);
196 if (bar_va == (rsm_gnum_t *)MAP_FAILED) {
197 bar_va = NULL;
198 mutex_unlock(&_rsm_lock);
199 DBPRINTF((RSM_LIBRARY, RSM_ERR,
200 "unable to map barrier page\n"));
201 return (RSMERR_MAP_FAILED);
202 }
203
204 mutex_unlock(&_rsm_lock);
205
206 /* get local nodeid */
207 e = rsm_get_interconnect_topology(&tp);
208 if (e != RSM_SUCCESS) {
209 DBPRINTF((RSM_LIBRARY, RSM_ERR,
210 "unable to obtain topology data\n"));
211 return (e);
212 } else
213 rsm_local_nodeid = tp->topology_hdr.local_nodeid;
214
215 rsm_free_interconnect_topology(tp);
216
217 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
218 "_rsm_librsm_init: exit\n"));
219
220 return (RSM_SUCCESS);
221 }
222
223 static int
_rsm_loopbackload(caddr_t name,int unit,rsm_controller_t ** chdl)224 _rsm_loopbackload(caddr_t name, int unit, rsm_controller_t **chdl)
225 {
226 rsm_controller_t *p;
227 rsm_ioctlmsg_t msg;
228
229 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
230 "_rsm_loopbackload: enter\n"));
231 /*
232 * For now do this, but we should open some file and read the
233 * list of supported controllers and there numbers.
234 */
235
236 p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
237 if (!p) {
238 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
239 "not enough memory\n"));
240 return (RSMERR_INSUFFICIENT_MEM);
241 }
242
243 msg.cname = name;
244 msg.cname_len = strlen(name) +1;
245 msg.cnum = unit;
246 msg.arg = (caddr_t)&p->cntr_attr;
247 if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
248 int error = errno;
249 free((void *)p);
250 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
251 "RSM_IOCTL_ATTR failed\n"));
252 return (error);
253 }
254
255 __rsmloopback_init_ops(&loopback_ops);
256 __rsmdefault_setops(&loopback_ops);
257 p->cntr_segops = &loopback_ops;
258
259 /*
260 * Should add this entry into list
261 */
262 p->cntr_fd = _rsm_fd;
263 p->cntr_name = strcpy((char *)(p+1), name);
264 p->cntr_unit = unit;
265 p->cntr_refcnt = 1;
266
267
268 mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
269 cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
270 p->cntr_rqlist = NULL;
271 p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
272 p->cntr_next = controller_list;
273 controller_list = p;
274
275 *chdl = p;
276
277 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_DEBUG_VERBOSE,
278 "_rsm_loopbackload: exit\n"));
279 return (RSM_SUCCESS);
280
281 }
282
283 static int
_rsm_modload(caddr_t name,int unit,rsmapi_controller_handle_t * controller)284 _rsm_modload(caddr_t name, int unit, rsmapi_controller_handle_t *controller)
285 {
286 int error = RSM_SUCCESS;
287 char clib[MAX_STRLEN];
288 rsm_controller_t *p = NULL;
289 void *dlh;
290 rsm_attach_entry_t fptr;
291 rsm_ioctlmsg_t msg;
292
293 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
294 "_rsm_modload: enter\n"));
295
296 (void) sprintf(clib, "%s.so", name);
297
298 /* found entry, try to load library */
299 dlh = dlopen(clib, RTLD_LAZY);
300 if (dlh == NULL) {
301 DBPRINTF((RSM_LIBRARY, RSM_ERR,
302 "unable to find plugin library\n"));
303 error = RSMERR_CTLR_NOT_PRESENT;
304 goto skiplib;
305 }
306
307 (void) sprintf(clib, "%s_opendevice", name);
308
309 fptr = (rsm_attach_entry_t)dlsym(dlh, clib); /* lint !e611 */
310 if (fptr != NULL) {
311 /* allocate new lib structure */
312 /* get ops handler, attr and ops */
313 p = (rsm_controller_t *)malloc(sizeof (*p) + strlen(name) + 1);
314 if (p != NULL) {
315 error = fptr(unit, &p->cntr_segops);
316 } else {
317 error = RSMERR_INSUFFICIENT_MEM;
318 DBPRINTF((RSM_LIBRARY, RSM_ERR,
319 "not enough memory\n"));
320 }
321 } else {
322 DBPRINTF((RSM_LIBRARY, RSM_ERR,
323 "can't find symbol %s\n", clib));
324 error = RSMERR_CTLR_NOT_PRESENT;
325 (void) dlclose(dlh);
326 }
327
328 skiplib:
329 if ((error != RSM_SUCCESS) || (p == NULL)) {
330 if (p != NULL)
331 free((void *)p);
332 DBPRINTF((RSM_LIBRARY, RSM_ERR,
333 "_rsm_modload error %d\n", error));
334 return (error);
335 }
336
337 /* check the version number */
338 if (p->cntr_segops->rsm_version != RSM_LIB_VERSION) {
339 /* bad version number */
340 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
341 "wrong version; "
342 "found %d, expected %d\n",
343 p->cntr_segops->rsm_version, RSM_LIB_VERSION));
344 free(p);
345 return (RSMERR_BAD_LIBRARY_VERSION);
346 } else {
347 /* pass the fuctions to NDI library */
348 if ((p->cntr_segops->rsm_register_lib_funcs == NULL) ||
349 (p->cntr_segops->rsm_register_lib_funcs(
350 &lib_functions) != RSM_SUCCESS)) {
351 DBPRINTF((RSM_LIBRARY, RSM_ERR,
352 "RSMNDI library not registering lib functions\n"));
353 }
354
355 /* get controller attributes */
356 msg.cnum = unit;
357 msg.cname = name;
358 msg.cname_len = strlen(name) +1;
359 msg.arg = (caddr_t)&p->cntr_attr;
360 if (ioctl(_rsm_fd, RSM_IOCTL_ATTR, &msg) < 0) {
361 error = errno;
362 free((void *)p);
363 DBPRINTF((RSM_LIBRARY, RSM_ERR,
364 "RSM_IOCTL_ATTR failed\n"));
365 return (error);
366 }
367
368 /* set controller access functions */
369 __rsmdefault_setops(p->cntr_segops);
370
371 mutex_init(&p->cntr_lock, USYNC_THREAD, NULL);
372 cond_init(&p->cntr_cv, USYNC_THREAD, NULL);
373 p->cntr_rqlist = NULL;
374 p->cntr_segops->rsm_get_lib_attr(&p->cntr_lib_attr);
375 /* insert into list of controllers */
376 p->cntr_name = strcpy((char *)(p+1), name);
377 p->cntr_fd = _rsm_fd;
378 p->cntr_unit = unit;
379 p->cntr_refcnt = 1; /* first reference */
380 p->cntr_next = controller_list;
381 controller_list = p;
382 *controller = (rsmapi_controller_handle_t)p;
383 errno = RSM_SUCCESS;
384 }
385
386 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
387 "_rsm_modload: exit\n"));
388 return (error);
389 }
390
391 /*
392 * inserts a given segment handle into the pollfd table, this is called
393 * when rsm_memseg_get_pollfd() is called the first time on a segment handle.
394 * Returns RSM_SUCCESS if successful otherwise the error code is returned
395 */
396 static int
_rsm_insert_pollfd_table(int segfd,minor_t segrnum)397 _rsm_insert_pollfd_table(int segfd, minor_t segrnum)
398 {
399 int i;
400 int hash;
401 rsm_pollfd_chunk_t *chunk;
402
403 hash = RSM_POLLFD_HASH(segfd);
404
405 mutex_lock(&pollfd_table.lock);
406
407 chunk = pollfd_table.buckets[hash];
408 while (chunk) {
409 if (chunk->nfree > 0)
410 break;
411 chunk = chunk->next;
412 }
413
414 if (!chunk) { /* couldn't find a free chunk - allocate a new one */
415 chunk = malloc(sizeof (rsm_pollfd_chunk_t));
416 if (!chunk) {
417 mutex_unlock(&pollfd_table.lock);
418 return (RSMERR_INSUFFICIENT_MEM);
419 }
420 chunk->nfree = RSM_POLLFD_PER_CHUNK - 1;
421 chunk->fdarray[0].fd = segfd;
422 chunk->fdarray[0].segrnum = segrnum;
423 for (i = 1; i < RSM_POLLFD_PER_CHUNK; i++) {
424 chunk->fdarray[i].fd = -1;
425 chunk->fdarray[i].segrnum = 0;
426 }
427 /* insert this into the hash table */
428 chunk->next = pollfd_table.buckets[hash];
429 pollfd_table.buckets[hash] = chunk;
430 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
431 "rsm_insert_pollfd: new chunk(%p) @ %d for %d:%d\n",
432 chunk, hash, segfd, segrnum));
433 } else { /* a chunk with free slot was found */
434 for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
435 if (chunk->fdarray[i].fd == -1) {
436 chunk->fdarray[i].fd = segfd;
437 chunk->fdarray[i].segrnum = segrnum;
438 chunk->nfree--;
439 break;
440 }
441 }
442 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
443 "rsm_insert_pollfd: inserted @ %d for %d:%d chunk(%p)\n",
444 hash, segfd, segrnum, chunk));
445 assert(i < RSM_POLLFD_PER_CHUNK);
446 }
447
448 mutex_unlock(&pollfd_table.lock);
449 return (RSM_SUCCESS);
450 }
451
452 /*
453 * Given a file descriptor returns the corresponding segment handles
454 * resource number, if the fd is not found returns 0. 0 is not a valid
455 * minor number for a rsmapi segment since it is used for the barrier
456 * resource.
457 */
458 static minor_t
_rsm_lookup_pollfd_table(int segfd)459 _rsm_lookup_pollfd_table(int segfd)
460 {
461 int i;
462 rsm_pollfd_chunk_t *chunk;
463
464 if (segfd < 0)
465 return (0);
466
467 mutex_lock(&pollfd_table.lock);
468
469 chunk = pollfd_table.buckets[RSM_POLLFD_HASH(segfd)];
470 while (chunk) {
471 assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
472
473 for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
474 if (chunk->fdarray[i].fd == segfd) {
475 mutex_unlock(&pollfd_table.lock);
476 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
477 "rsm_lookup_pollfd: found(%d) rnum(%d)\n",
478 segfd, chunk->fdarray[i].segrnum));
479 return (chunk->fdarray[i].segrnum);
480 }
481 }
482 chunk = chunk->next;
483 }
484
485 mutex_unlock(&pollfd_table.lock);
486
487 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
488 "rsm_lookup_pollfd: not found(%d)\n", segfd));
489
490 return (0);
491 }
492
493 /*
494 * Remove the entry corresponding to the given file descriptor from the
495 * pollfd table.
496 */
497 static void
_rsm_remove_pollfd_table(int segfd)498 _rsm_remove_pollfd_table(int segfd)
499 {
500 int i;
501 int hash;
502 rsm_pollfd_chunk_t *chunk;
503 rsm_pollfd_chunk_t *prev_chunk;
504
505 if (segfd < 0)
506 return;
507
508 hash = RSM_POLLFD_HASH(segfd);
509
510 mutex_lock(&pollfd_table.lock);
511
512 prev_chunk = chunk = pollfd_table.buckets[hash];
513 while (chunk) {
514 assert(chunk->nfree < RSM_POLLFD_PER_CHUNK);
515
516 for (i = 0; i < RSM_POLLFD_PER_CHUNK; i++) {
517 if (chunk->fdarray[i].fd == segfd) {
518 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
519 "rsm_remove_pollfd: %d:%d\n",
520 chunk->fdarray[i].fd,
521 chunk->fdarray[i].segrnum));
522 chunk->fdarray[i].fd = -1;
523 chunk->fdarray[i].segrnum = 0;
524 chunk->nfree++;
525 if (chunk->nfree == RSM_POLLFD_PER_CHUNK) {
526 /* chunk is empty free it */
527 if (prev_chunk == chunk) {
528 pollfd_table.buckets[hash] =
529 chunk->next;
530 } else {
531 prev_chunk->next = chunk->next;
532 }
533 DBPRINTF((RSM_LIBRARY,
534 RSM_DEBUG_VERBOSE,
535 "rsm_remove_pollfd:free(%p)\n",
536 chunk));
537 free(chunk);
538 mutex_unlock(&pollfd_table.lock);
539 return;
540 }
541 }
542 }
543 prev_chunk = chunk;
544 chunk = chunk->next;
545 }
546
547 mutex_unlock(&pollfd_table.lock);
548 }
549
550 int
rsm_get_controller(char * name,rsmapi_controller_handle_t * chdl)551 rsm_get_controller(char *name, rsmapi_controller_handle_t *chdl)
552 {
553 rsm_controller_t *p;
554 char cntr_name[MAXNAMELEN]; /* cntr_name=<cntr_type><unit> */
555 char *cntr_type;
556 int unit = 0;
557 int i, e;
558
559 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
560 "rsm_get_controller: enter\n"));
561 /*
562 * Lookup controller name and return ops vector and controller
563 * structure
564 */
565
566 if (!chdl) {
567 DBPRINTF((RSM_LIBRARY, RSM_ERR,
568 "Invalid controller handle\n"));
569 return (RSMERR_BAD_CTLR_HNDL);
570 }
571 if (!name) {
572 /* use loopback if null */
573 cntr_type = LOOPBACK;
574 } else {
575 (void) strcpy(cntr_name, name);
576 /* scan from the end till a non-digit is found */
577 for (i = strlen(cntr_name) - 1; i >= 0; i--) {
578 if (! isdigit((int)cntr_name[i]))
579 break;
580 }
581 i++;
582 unit = atoi((char *)cntr_name+i);
583 cntr_name[i] = '\0'; /* null terminate the cntr_type part */
584 cntr_type = (char *)cntr_name;
585 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
586 "cntr_type=%s, instance=%d\n",
587 cntr_type, unit));
588 }
589
590 /* protect the controller_list by locking the device/library */
591 mutex_lock(&_rsm_lock);
592
593 for (p = controller_list; p; p = p->cntr_next) {
594 if (!strcasecmp(p->cntr_name, cntr_type) &&
595 !strcasecmp(cntr_type, LOOPBACK)) {
596 p->cntr_refcnt++;
597 *chdl = (rsmapi_controller_handle_t)p;
598 mutex_unlock(&_rsm_lock);
599 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
600 "rsm_get_controller: exit\n"));
601 return (RSM_SUCCESS);
602 } else if (!strcasecmp(p->cntr_name, cntr_type) &&
603 (p->cntr_unit == unit)) {
604 p->cntr_refcnt++;
605 *chdl = (rsmapi_controller_handle_t)p;
606 mutex_unlock(&_rsm_lock);
607 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
608 "rsm_get_controller: exit\n"));
609 return (RSM_SUCCESS);
610 }
611 }
612
613
614 if (!strcasecmp(cntr_type, LOOPBACK)) {
615 e = _rsm_loopbackload(cntr_type, unit,
616 (rsm_controller_t **)chdl);
617 } else {
618 e = _rsm_modload(cntr_type, unit, chdl);
619 }
620
621 mutex_unlock(&_rsm_lock);
622
623 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
624 " rsm_get_controller: exit\n"));
625 return (e);
626 }
627
628 int
rsm_release_controller(rsmapi_controller_handle_t cntr_handle)629 rsm_release_controller(rsmapi_controller_handle_t cntr_handle)
630 {
631 int e = RSM_SUCCESS;
632 rsm_controller_t *chdl = (rsm_controller_t *)cntr_handle;
633 rsm_controller_t *curr, *prev;
634
635 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
636 "rsm_release_controller: enter\n"));
637
638 mutex_lock(&_rsm_lock);
639
640 if (chdl->cntr_refcnt == 0) {
641 mutex_unlock(&_rsm_lock);
642 DBPRINTF((RSM_LIBRARY, RSM_ERR,
643 "controller reference count is zero\n"));
644 return (RSMERR_BAD_CTLR_HNDL);
645 }
646
647 chdl->cntr_refcnt--;
648
649 if (chdl->cntr_refcnt > 0) {
650 mutex_unlock(&_rsm_lock);
651 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
652 "rsm_release_controller: exit\n"));
653 return (RSM_SUCCESS);
654 }
655
656 e = chdl->cntr_segops->rsm_closedevice(cntr_handle);
657
658 /*
659 * remove the controller in any case from the controller list
660 */
661
662 prev = curr = controller_list;
663 while (curr != NULL) {
664 if (curr == chdl) {
665 if (curr == prev) {
666 controller_list = curr->cntr_next;
667 } else {
668 prev->cntr_next = curr->cntr_next;
669 }
670 free(curr);
671 break;
672 }
673 prev = curr;
674 curr = curr->cntr_next;
675 }
676 mutex_unlock(&_rsm_lock);
677
678 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
679 "rsm_release_controller: exit\n"));
680
681 return (e);
682 }
683
684 int
rsm_get_controller_attr(rsmapi_controller_handle_t chandle,rsmapi_controller_attr_t * attr)685 rsm_get_controller_attr(rsmapi_controller_handle_t chandle,
686 rsmapi_controller_attr_t *attr)
687 {
688 rsm_controller_t *p;
689
690 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
691 "rsm_get_controller_attr: enter\n"));
692
693 if (!chandle) {
694 DBPRINTF((RSM_LIBRARY, RSM_ERR,
695 "invalid controller handle\n"));
696 return (RSMERR_BAD_CTLR_HNDL);
697 }
698
699 if (!attr) {
700 DBPRINTF((RSM_LIBRARY, RSM_ERR,
701 "invalid attribute pointer\n"));
702 return (RSMERR_BAD_ADDR);
703 }
704
705 p = (rsm_controller_t *)chandle;
706
707 mutex_lock(&_rsm_lock);
708 if (p->cntr_refcnt == 0) {
709 mutex_unlock(&_rsm_lock);
710 DBPRINTF((RSM_LIBRARY, RSM_ERR,
711 "cntr refcnt is 0\n"));
712 return (RSMERR_CTLR_NOT_PRESENT);
713 }
714
715 /* copy only the user part of the attr structure */
716 attr->attr_direct_access_sizes =
717 p->cntr_attr.attr_direct_access_sizes;
718 attr->attr_atomic_sizes =
719 p->cntr_attr.attr_atomic_sizes;
720 attr->attr_page_size =
721 p->cntr_attr.attr_page_size;
722 attr->attr_max_export_segment_size =
723 p->cntr_attr.attr_max_export_segment_size;
724 attr->attr_tot_export_segment_size =
725 p->cntr_attr.attr_tot_export_segment_size;
726 attr->attr_max_export_segments =
727 p->cntr_attr.attr_max_export_segments;
728 attr->attr_max_import_map_size =
729 p->cntr_attr.attr_max_import_map_size;
730 attr->attr_tot_import_map_size =
731 p->cntr_attr.attr_tot_import_map_size;
732 attr->attr_max_import_segments =
733 p->cntr_attr.attr_max_import_segments;
734
735 mutex_unlock(&_rsm_lock);
736
737 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
738 "rsm_get_controller_attr: exit\n"));
739
740 return (RSM_SUCCESS);
741 }
742
743
744
745 /*
746 * Create a segment handle for the virtual address range specified
747 * by vaddr and size
748 */
749 int
rsm_memseg_export_create(rsmapi_controller_handle_t controller,rsm_memseg_export_handle_t * memseg,void * vaddr,size_t length,uint_t flags)750 rsm_memseg_export_create(rsmapi_controller_handle_t controller,
751 rsm_memseg_export_handle_t *memseg,
752 void *vaddr,
753 size_t length,
754 uint_t flags)
755 {
756
757 rsm_controller_t *chdl = (rsm_controller_t *)controller;
758 rsmseg_handle_t *p;
759 rsm_ioctlmsg_t msg;
760 int e;
761 #ifndef _LP64
762 int tmpfd;
763 #endif
764
765 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
766 "rsm_memseg_export_create: enter\n"));
767
768 if (!controller) {
769 DBPRINTF((RSM_LIBRARY, RSM_ERR,
770 "invalid controller handle\n"));
771 return (RSMERR_BAD_CTLR_HNDL);
772 }
773 if (!memseg) {
774 DBPRINTF((RSM_LIBRARY, RSM_ERR,
775 "invalid segment handle\n"));
776 return (RSMERR_BAD_SEG_HNDL);
777 }
778
779 *memseg = 0;
780
781 /*
782 * Check vaddr and size alignment, both must be mmu page size
783 * aligned
784 */
785 if (!vaddr) {
786 DBPRINTF((RSM_LIBRARY, RSM_ERR,
787 "invalid arguments\n"));
788 return (RSMERR_BAD_ADDR);
789 }
790
791 if (!length) {
792 DBPRINTF((RSM_LIBRARY, RSM_ERR,
793 "invalid arguments\n"));
794 return (RSMERR_BAD_LENGTH);
795 }
796
797 if (((size_t)vaddr & (PAGESIZE - 1)) ||
798 (length & (PAGESIZE - 1))) {
799 DBPRINTF((RSM_LIBRARY, RSM_ERR,
800 "invalid mem alignment for vaddr or length\n"));
801 return (RSMERR_BAD_MEM_ALIGNMENT);
802 }
803
804 /*
805 * The following check does not apply for loopback controller
806 * since for the loopback adapter, the attr_max_export_segment_size
807 * is always 0.
808 */
809 if (strcasecmp(chdl->cntr_name, LOOPBACK)) {
810 if (length > chdl->cntr_attr.attr_max_export_segment_size) {
811 DBPRINTF((RSM_LIBRARY, RSM_ERR,
812 "length exceeds controller limits\n"));
813 DBPRINTF((RSM_LIBRARY, RSM_ERR,
814 "controller limits %d\n",
815 chdl->cntr_attr.attr_max_export_segment_size));
816 return (RSMERR_BAD_LENGTH);
817 }
818 }
819
820 p = (rsmseg_handle_t *)malloc(sizeof (*p));
821 if (p == NULL) {
822 DBPRINTF((RSM_LIBRARY, RSM_ERR,
823 "not enough memory\n"));
824 return (RSMERR_INSUFFICIENT_MEM);
825 }
826
827 p->rsmseg_fd = open(DEVRSM, O_RDWR);
828 if (p->rsmseg_fd < 0) {
829 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
830 "unable to open device /dev/rsm\n"));
831 free((void *)p);
832 return (RSMERR_INSUFFICIENT_RESOURCES);
833 }
834
835 #ifndef _LP64
836 /*
837 * libc can't handle fd's greater than 255, in order to
838 * insure that these values remain available make /dev/rsm
839 * fd > 255. Note: not needed for LP64
840 */
841 tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256);
842 e = errno;
843 if (tmpfd < 0) {
844 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
845 "F_DUPFD failed\n"));
846 } else {
847 (void) close(p->rsmseg_fd);
848 p->rsmseg_fd = tmpfd;
849 }
850 #endif /* _LP64 */
851
852 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, ""
853 "rsmseg_fd is %d\n", p->rsmseg_fd));
854
855 if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
856 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
857 "F_SETFD failed\n"));
858 }
859
860 p->rsmseg_state = EXPORT_CREATE;
861 p->rsmseg_size = length;
862 /* increment controller handle */
863 p->rsmseg_controller = chdl;
864
865 /* try to bind user address range */
866 msg.cnum = chdl->cntr_unit;
867 msg.cname = chdl->cntr_name;
868 msg.cname_len = strlen(chdl->cntr_name) +1;
869 msg.vaddr = vaddr;
870 msg.len = length;
871 msg.perm = flags;
872 msg.off = 0;
873 e = RSM_IOCTL_BIND;
874
875 /* Try to bind */
876 if (ioctl(p->rsmseg_fd, e, &msg) < 0) {
877 e = errno;
878 (void) close(p->rsmseg_fd);
879 free((void *)p);
880 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
881 "RSM_IOCTL_BIND failed\n"));
882 return (e);
883 }
884 /* OK */
885 p->rsmseg_type = RSM_EXPORT_SEG;
886 p->rsmseg_vaddr = vaddr;
887 p->rsmseg_size = length;
888 p->rsmseg_state = EXPORT_BIND;
889 p->rsmseg_pollfd_refcnt = 0;
890 p->rsmseg_rnum = msg.rnum;
891
892 mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
893
894 *memseg = (rsm_memseg_export_handle_t)p;
895
896 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
897 "rsm_memseg_export_create: exit\n"));
898
899 return (RSM_SUCCESS);
900 }
901
902 int
rsm_memseg_export_destroy(rsm_memseg_export_handle_t memseg)903 rsm_memseg_export_destroy(rsm_memseg_export_handle_t memseg)
904 {
905 rsmseg_handle_t *seg;
906
907 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
908 "rsm_memseg_export_destroy: enter\n"));
909
910 if (!memseg) {
911 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
912 "invalid segment handle\n"));
913 return (RSMERR_BAD_SEG_HNDL);
914 }
915
916 seg = (rsmseg_handle_t *)memseg;
917
918 mutex_lock(&seg->rsmseg_lock);
919 if (seg->rsmseg_pollfd_refcnt) {
920 mutex_unlock(&seg->rsmseg_lock);
921 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
922 "segment reference count not zero\n"));
923 return (RSMERR_POLLFD_IN_USE);
924 }
925 else
926 seg->rsmseg_state = EXPORT_BIND;
927
928 mutex_unlock(&seg->rsmseg_lock);
929
930 (void) close(seg->rsmseg_fd);
931 mutex_destroy(&seg->rsmseg_lock);
932 free((void *)seg);
933
934 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
935 "rsm_memseg_export_destroy: exit\n"));
936
937 return (RSM_SUCCESS);
938 }
939
940 int
rsm_memseg_export_rebind(rsm_memseg_export_handle_t memseg,void * vaddr,offset_t off,size_t length)941 rsm_memseg_export_rebind(rsm_memseg_export_handle_t memseg, void *vaddr,
942 offset_t off, size_t length)
943 {
944 rsm_ioctlmsg_t msg;
945 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
946
947 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
948 "rsm_memseg_export_rebind: enter\n"));
949
950 off = off;
951
952 if (!seg) {
953 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
954 "invalid segment handle\n"));
955 return (RSMERR_BAD_SEG_HNDL);
956 }
957 if (!vaddr) {
958 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
959 "invalid vaddr\n"));
960 return (RSMERR_BAD_ADDR);
961 }
962
963 /*
964 * Same as bind except it's ok to have elimint in list.
965 * Call into driver to remove any existing mappings.
966 */
967 msg.vaddr = vaddr;
968 msg.len = length;
969 msg.off = 0;
970
971 mutex_lock(&seg->rsmseg_lock);
972 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REBIND, &msg) < 0) {
973 mutex_unlock(&seg->rsmseg_lock);
974 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
975 "RSM_IOCTL_REBIND failed\n"));
976 return (errno);
977 }
978
979 mutex_unlock(&seg->rsmseg_lock);
980
981 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
982 "rsm_memseg_export_rebind: exit\n"));
983
984 return (RSM_SUCCESS);
985 }
986
987 int
rsm_memseg_export_publish(rsm_memseg_export_handle_t memseg,rsm_memseg_id_t * seg_id,rsmapi_access_entry_t access_list[],uint_t access_list_length)988 rsm_memseg_export_publish(rsm_memseg_export_handle_t memseg,
989 rsm_memseg_id_t *seg_id,
990 rsmapi_access_entry_t access_list[],
991 uint_t access_list_length)
992
993 {
994 rsm_ioctlmsg_t msg;
995 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
996
997 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
998 "rsm_memseg_export_publish: enter\n"));
999
1000 if (seg_id == NULL) {
1001 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1002 "invalid segment id\n"));
1003 return (RSMERR_BAD_SEGID);
1004 }
1005
1006 if (!seg) {
1007 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1008 "invalid segment handle\n"));
1009 return (RSMERR_BAD_SEG_HNDL);
1010 }
1011
1012 if (access_list_length > 0 && !access_list) {
1013 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1014 "invalid access control list\n"));
1015 return (RSMERR_BAD_ACL);
1016 }
1017
1018 mutex_lock(&seg->rsmseg_lock);
1019 if (seg->rsmseg_state != EXPORT_BIND) {
1020 mutex_unlock(&seg->rsmseg_lock);
1021 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1022 "invalid segment state\n"));
1023 return (RSMERR_SEG_ALREADY_PUBLISHED);
1024 }
1025
1026 /*
1027 * seg id < RSM_DLPI_END and in the RSM_USER_APP_ID range
1028 * are reserved for internal use.
1029 */
1030 if ((*seg_id > 0) &&
1031 ((*seg_id <= RSM_DLPI_ID_END) ||
1032 BETWEEN (*seg_id, RSM_USER_APP_ID_BASE, RSM_USER_APP_ID_END))) {
1033 mutex_unlock(&seg->rsmseg_lock);
1034 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1035 "invalid segment id\n"));
1036 return (RSMERR_RESERVED_SEGID);
1037 }
1038
1039 msg.key = *seg_id;
1040 msg.acl = access_list;
1041 msg.acl_len = access_list_length;
1042
1043 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_PUBLISH, &msg) < 0) {
1044 mutex_unlock(&seg->rsmseg_lock);
1045 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1046 "RSM_IOCTL_PUBLISH failed\n"));
1047 return (errno);
1048 }
1049
1050 seg->rsmseg_keyid = msg.key;
1051 seg->rsmseg_state = EXPORT_PUBLISH;
1052 mutex_unlock(&seg->rsmseg_lock);
1053
1054 if (*seg_id == 0)
1055 *seg_id = msg.key;
1056
1057 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1058 "rsm_memseg_export_publish: exit\n"));
1059
1060 return (RSM_SUCCESS);
1061
1062 }
1063
1064 int
rsm_memseg_export_unpublish(rsm_memseg_export_handle_t memseg)1065 rsm_memseg_export_unpublish(rsm_memseg_export_handle_t memseg)
1066 {
1067 rsm_ioctlmsg_t msg;
1068 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1069
1070 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1071 "rsm_memseg_export_unpublish: enter\n"));
1072
1073 if (!seg) {
1074 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1075 "invalid arguments\n"));
1076 return (RSMERR_BAD_SEG_HNDL);
1077 }
1078
1079 mutex_lock(&seg->rsmseg_lock);
1080 if (seg->rsmseg_state != EXPORT_PUBLISH) {
1081 mutex_unlock(&seg->rsmseg_lock);
1082 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1083 "segment not published %d\n",
1084 seg->rsmseg_keyid));
1085 return (RSMERR_SEG_NOT_PUBLISHED);
1086 }
1087
1088 msg.key = seg->rsmseg_keyid;
1089 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_UNPUBLISH, &msg) < 0) {
1090 mutex_unlock(&seg->rsmseg_lock);
1091 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1092 "RSM_IOCTL_UNPUBLISH failed\n"));
1093 return (errno);
1094 }
1095
1096 seg->rsmseg_state = EXPORT_BIND;
1097 mutex_unlock(&seg->rsmseg_lock);
1098
1099 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1100 "rsm_memseg_export_unpublish: exit\n"));
1101
1102 return (RSM_SUCCESS);
1103 }
1104
1105
1106 int
rsm_memseg_export_republish(rsm_memseg_export_handle_t memseg,rsmapi_access_entry_t access_list[],uint_t access_list_length)1107 rsm_memseg_export_republish(rsm_memseg_export_handle_t memseg,
1108 rsmapi_access_entry_t access_list[],
1109 uint_t access_list_length)
1110 {
1111 rsm_ioctlmsg_t msg;
1112 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
1113
1114 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1115 "rsm_memseg_export_republish: enter\n"));
1116
1117 if (!seg) {
1118 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1119 "invalid segment or segment state\n"));
1120 return (RSMERR_BAD_SEG_HNDL);
1121 }
1122
1123 mutex_lock(&seg->rsmseg_lock);
1124 if (seg->rsmseg_state != EXPORT_PUBLISH) {
1125 mutex_unlock(&seg->rsmseg_lock);
1126 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1127 "segment not published\n"));
1128 return (RSMERR_SEG_NOT_PUBLISHED);
1129 }
1130
1131 if (access_list_length > 0 && !access_list) {
1132 mutex_unlock(&seg->rsmseg_lock);
1133 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1134 "invalid access control list\n"));
1135 return (RSMERR_BAD_ACL);
1136 }
1137
1138 msg.key = seg->rsmseg_keyid;
1139 msg.acl = access_list;
1140 msg.acl_len = access_list_length;
1141
1142 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_REPUBLISH, &msg) < 0) {
1143 mutex_unlock(&seg->rsmseg_lock);
1144 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1145 "RSM_IOCTL_REPUBLISH failed\n"));
1146 return (errno);
1147 }
1148 mutex_unlock(&seg->rsmseg_lock);
1149
1150 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_DEBUG_VERBOSE,
1151 "rsm_memseg_export_republish: exit\n"));
1152
1153 return (RSM_SUCCESS);
1154 }
1155
1156
1157 /*
1158 * import side memory segment operations:
1159 */
1160 int
rsm_memseg_import_connect(rsmapi_controller_handle_t controller,rsm_node_id_t node_id,rsm_memseg_id_t segment_id,rsm_permission_t perm,rsm_memseg_import_handle_t * im_memseg)1161 rsm_memseg_import_connect(rsmapi_controller_handle_t controller,
1162 rsm_node_id_t node_id,
1163 rsm_memseg_id_t segment_id,
1164 rsm_permission_t perm,
1165 rsm_memseg_import_handle_t *im_memseg)
1166 {
1167 rsm_ioctlmsg_t msg;
1168 rsmseg_handle_t *p;
1169 rsm_controller_t *cntr = (rsm_controller_t *)controller;
1170 #ifndef _LP64 /* added for fd > 255 fix */
1171 int tmpfd;
1172 #endif
1173 int e;
1174
1175 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1176 "rsm_memseg_import_connect: enter\n"));
1177
1178 if (!cntr) {
1179 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1180 "invalid controller handle\n"));
1181 return (RSMERR_BAD_CTLR_HNDL);
1182 }
1183
1184 *im_memseg = 0;
1185
1186 p = (rsmseg_handle_t *)malloc(sizeof (*p));
1187 if (!p) {
1188 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1189 "not enough memory\n"));
1190 return (RSMERR_INSUFFICIENT_MEM);
1191 }
1192
1193 if (perm & ~RSM_PERM_RDWR) {
1194 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1195 "invalid permissions\n"));
1196 return (RSMERR_PERM_DENIED);
1197 }
1198
1199 /*
1200 * Get size, va from driver
1201 */
1202 msg.cnum = cntr->cntr_unit;
1203 msg.cname = cntr->cntr_name;
1204 msg.cname_len = strlen(cntr->cntr_name) +1;
1205 msg.nodeid = node_id;
1206 msg.key = segment_id;
1207 msg.perm = perm;
1208
1209 p->rsmseg_fd = open(DEVRSM, O_RDWR);
1210 if (p->rsmseg_fd < 0) {
1211 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1212 "unable to open /dev/rsm"));
1213 free((void *)p);
1214 return (RSMERR_INSUFFICIENT_RESOURCES);
1215 }
1216
1217 #ifndef _LP64
1218 /*
1219 * libc can't handle fd's greater than 255, in order to
1220 * insure that these values remain available make /dev/rsm
1221 * fd > 255. Note: not needed for LP64
1222 */
1223 tmpfd = fcntl(p->rsmseg_fd, F_DUPFD, 256); /* make fd > 255 */
1224 e = errno;
1225 if (tmpfd < 0) {
1226 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1227 "F_DUPFD failed\n"));
1228 } else {
1229 (void) close(p->rsmseg_fd);
1230 p->rsmseg_fd = tmpfd;
1231 }
1232 #endif /* _LP64 */
1233
1234 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
1235 "rsmseg_fd is %d\n", p->rsmseg_fd));
1236
1237 if (fcntl(p->rsmseg_fd, F_SETFD, FD_CLOEXEC) < 0) {
1238 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1239 "F_SETFD failed\n"));
1240 }
1241 if (ioctl(p->rsmseg_fd, RSM_IOCTL_CONNECT, &msg) < 0) {
1242 e = errno;
1243 (void) close(p->rsmseg_fd);
1244 free((void *)p);
1245 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1246 "RSM_IOCTL_CONNECT failed\n"));
1247 return (e);
1248 }
1249
1250 /*
1251 * We connected ok.
1252 */
1253 p->rsmseg_type = RSM_IMPORT_SEG;
1254 p->rsmseg_state = IMPORT_CONNECT;
1255 p->rsmseg_keyid = segment_id;
1256 p->rsmseg_nodeid = node_id;
1257 p->rsmseg_size = msg.len;
1258 p->rsmseg_perm = perm;
1259 p->rsmseg_controller = cntr;
1260 p->rsmseg_barrier = NULL;
1261 p->rsmseg_barmode = RSM_BARRIER_MODE_IMPLICIT;
1262 p->rsmseg_bar = (bar_va ? bar_va + msg.off : &bar_fixed);
1263 p->rsmseg_gnum = msg.gnum;
1264 p->rsmseg_pollfd_refcnt = 0;
1265 p->rsmseg_maplen = 0; /* initialized, set in import_map */
1266 p->rsmseg_mapoffset = 0;
1267 p->rsmseg_flags = 0;
1268 p->rsmseg_rnum = msg.rnum;
1269 mutex_init(&p->rsmseg_lock, USYNC_THREAD, NULL);
1270
1271 p->rsmseg_ops = cntr->cntr_segops;
1272
1273 /*
1274 * XXX: Based on permission and controller direct_access attribute
1275 * we fix the segment ops vector
1276 */
1277
1278 p->rsmseg_vaddr = 0; /* defer mapping till using maps or trys to rw */
1279
1280 *im_memseg = (rsm_memseg_import_handle_t)p;
1281
1282 e = p->rsmseg_ops->rsm_memseg_import_connect(controller,
1283 node_id, segment_id, perm, im_memseg);
1284
1285 if (e != RSM_SUCCESS) {
1286 (void) close(p->rsmseg_fd);
1287 mutex_destroy(&p->rsmseg_lock);
1288 free((void *)p);
1289 }
1290
1291 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1292 "rsm_memseg_import_connect: exit\n"));
1293
1294 return (e);
1295 }
1296
1297
1298 int
rsm_memseg_import_disconnect(rsm_memseg_import_handle_t im_memseg)1299 rsm_memseg_import_disconnect(rsm_memseg_import_handle_t im_memseg)
1300 {
1301 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1302 int e;
1303
1304 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1305 "rsm_memseg_import_disconnect: enter\n"));
1306
1307 if (!seg) {
1308 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1309 "invalid segment handle\n"));
1310 return (RSMERR_BAD_SEG_HNDL);
1311 }
1312
1313 if (seg->rsmseg_state != IMPORT_CONNECT) {
1314 if (seg->rsmseg_flags & RSM_IMPLICIT_MAP) {
1315 e = rsm_memseg_import_unmap(im_memseg);
1316 if (e != RSM_SUCCESS) {
1317 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1318 "unmap failure\n"));
1319 return (e);
1320 }
1321 } else {
1322 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1323 "segment busy\n"));
1324 return (RSMERR_SEG_STILL_MAPPED);
1325 }
1326 }
1327
1328 mutex_lock(&seg->rsmseg_lock);
1329 if (seg->rsmseg_pollfd_refcnt) {
1330 mutex_unlock(&seg->rsmseg_lock);
1331 DBPRINTF((RSM_LIBRARY|RSM_EXPORT, RSM_ERR,
1332 "segment reference count not zero\n"));
1333 return (RSMERR_POLLFD_IN_USE);
1334 }
1335 mutex_unlock(&seg->rsmseg_lock);
1336
1337 e = seg->rsmseg_ops->rsm_memseg_import_disconnect(im_memseg);
1338
1339 if (e == RSM_SUCCESS) {
1340 (void) close(seg->rsmseg_fd);
1341 mutex_destroy(&seg->rsmseg_lock);
1342 free((void *)seg);
1343 }
1344
1345 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1346 "rsm_memseg_import_disconnect: exit\n"));
1347
1348 return (e);
1349 }
1350
1351 /*
1352 * import side memory segment operations (read access functions):
1353 */
1354
1355 static int
__rsm_import_verify_access(rsmseg_handle_t * seg,off_t offset,caddr_t datap,size_t len,rsm_permission_t perm,rsm_access_size_t das)1356 __rsm_import_verify_access(rsmseg_handle_t *seg,
1357 off_t offset,
1358 caddr_t datap,
1359 size_t len,
1360 rsm_permission_t perm,
1361 rsm_access_size_t das)
1362 {
1363 int error;
1364
1365 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1366 " __rsm_import_verify_access: enter\n"));
1367
1368 if (!seg) {
1369 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1370 "invalid segment handle\n"));
1371 return (RSMERR_BAD_SEG_HNDL);
1372 }
1373 if (!datap) {
1374 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1375 "invalid data pointer\n"));
1376 return (RSMERR_BAD_ADDR);
1377 }
1378
1379 /*
1380 * Check alignment of pointer
1381 */
1382 if ((uintptr_t)datap & (das - 1)) {
1383 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1384 "invalid alignment of data pointer\n"));
1385 return (RSMERR_BAD_MEM_ALIGNMENT);
1386 }
1387
1388 if (offset & (das - 1)) {
1389 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1390 "invalid offset\n"));
1391 return (RSMERR_BAD_MEM_ALIGNMENT);
1392 }
1393
1394 /* make sure that the import seg is connected */
1395 if (seg->rsmseg_state != IMPORT_CONNECT &&
1396 seg->rsmseg_state != IMPORT_MAP) {
1397 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1398 "incorrect segment state\n"));
1399 return (RSMERR_BAD_SEG_HNDL);
1400 }
1401
1402 /* do an implicit map if required */
1403 if (seg->rsmseg_state == IMPORT_CONNECT) {
1404 error = __rsm_import_implicit_map(seg, RSM_IOTYPE_PUTGET);
1405 if (error != RSM_SUCCESS) {
1406 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1407 "implicit map failure\n"));
1408 return (error);
1409 }
1410 }
1411
1412 if ((seg->rsmseg_perm & perm) != perm) {
1413 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1414 "invalid permissions\n"));
1415 return (RSMERR_PERM_DENIED);
1416 }
1417
1418 if (seg->rsmseg_state == IMPORT_MAP) {
1419 if ((offset < seg->rsmseg_mapoffset) ||
1420 (offset + len > seg->rsmseg_mapoffset +
1421 seg->rsmseg_maplen)) {
1422 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1423 "incorrect offset+length\n"));
1424 return (RSMERR_BAD_OFFSET);
1425 }
1426 } else { /* IMPORT_CONNECT */
1427 if ((len + offset) > seg->rsmseg_size) {
1428 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1429 "incorrect offset+length\n"));
1430 return (RSMERR_BAD_LENGTH);
1431 }
1432 }
1433
1434 if ((seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) &&
1435 (seg->rsmseg_barrier == NULL)) {
1436 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1437 "invalid barrier\n"));
1438 return (RSMERR_BARRIER_UNINITIALIZED);
1439 }
1440
1441 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1442 " __rsm_import_verify_access: exit\n"));
1443
1444 return (RSM_SUCCESS);
1445 }
1446
1447 static int
__rsm_import_implicit_map(rsmseg_handle_t * seg,int iotype)1448 __rsm_import_implicit_map(rsmseg_handle_t *seg, int iotype)
1449 {
1450 caddr_t va;
1451 int flag = MAP_SHARED;
1452 int prot = PROT_READ|PROT_WRITE;
1453 int mapping_reqd = 0;
1454
1455 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1456 " __rsm_import_implicit_map: enter\n"));
1457
1458 if (iotype == RSM_IOTYPE_PUTGET)
1459 mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1460 rsm_putget_map_reqd;
1461 else if (iotype == RSM_IOTYPE_SCATGATH)
1462 mapping_reqd = seg->rsmseg_controller->cntr_lib_attr->
1463 rsm_scatgath_map_reqd;
1464
1465
1466 if (mapping_reqd) {
1467 va = mmap(NULL, seg->rsmseg_size, prot,
1468 flag, seg->rsmseg_fd, 0);
1469
1470 if (va == MAP_FAILED) {
1471 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1472 "implicit map failed\n"));
1473 if (errno == ENOMEM || errno == ENXIO ||
1474 errno == EOVERFLOW)
1475 return (RSMERR_BAD_LENGTH);
1476 else if (errno == ENODEV)
1477 return (RSMERR_CONN_ABORTED);
1478 else if (errno == EAGAIN)
1479 return (RSMERR_INSUFFICIENT_RESOURCES);
1480 else if (errno == ENOTSUP)
1481 return (RSMERR_MAP_FAILED);
1482 else if (errno == EACCES)
1483 return (RSMERR_BAD_PERMS);
1484 else
1485 return (RSMERR_MAP_FAILED);
1486 }
1487 seg->rsmseg_vaddr = va;
1488 seg->rsmseg_maplen = seg->rsmseg_size;
1489 seg->rsmseg_mapoffset = 0;
1490 seg->rsmseg_state = IMPORT_MAP;
1491 seg->rsmseg_flags |= RSM_IMPLICIT_MAP;
1492 }
1493
1494 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1495 " __rsm_import_implicit_map: exit\n"));
1496
1497 return (RSM_SUCCESS);
1498 }
1499
1500 int
rsm_memseg_import_get8(rsm_memseg_import_handle_t im_memseg,off_t offset,uint8_t * datap,ulong_t rep_cnt)1501 rsm_memseg_import_get8(rsm_memseg_import_handle_t im_memseg,
1502 off_t offset,
1503 uint8_t *datap,
1504 ulong_t rep_cnt)
1505 {
1506 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1507 int e;
1508
1509 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1510 "rsm_memseg_import_get8: enter\n"));
1511
1512 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1513 RSM_PERM_READ,
1514 RSM_DAS8);
1515 if (e == RSM_SUCCESS) {
1516 rsm_segops_t *ops = seg->rsmseg_ops;
1517 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1518
1519 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1520 /* generation number snapshot */
1521 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1522 }
1523
1524 e = ops->rsm_memseg_import_get8(im_memseg, offset, datap,
1525 rep_cnt, 0);
1526
1527 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1528 /* check the generation number for force disconnects */
1529 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1530 return (RSMERR_CONN_ABORTED);
1531 }
1532 }
1533 }
1534
1535 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1536 "rsm_memseg_import_get8: exit\n"));
1537
1538 return (e);
1539 }
1540
1541 int
rsm_memseg_import_get16(rsm_memseg_import_handle_t im_memseg,off_t offset,uint16_t * datap,ulong_t rep_cnt)1542 rsm_memseg_import_get16(rsm_memseg_import_handle_t im_memseg,
1543 off_t offset,
1544 uint16_t *datap,
1545 ulong_t rep_cnt)
1546 {
1547 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1548 int e;
1549
1550 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1551 "rsm_memseg_import_get16: enter\n"));
1552
1553 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1554 RSM_PERM_READ,
1555 RSM_DAS16);
1556 if (e == RSM_SUCCESS) {
1557 rsm_segops_t *ops = seg->rsmseg_ops;
1558 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1559
1560 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1561 /* generation number snapshot */
1562 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1563 }
1564
1565 e = ops->rsm_memseg_import_get16(im_memseg, offset, datap,
1566 rep_cnt, 0);
1567
1568 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1569 /* check the generation number for force disconnects */
1570 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1571 return (RSMERR_CONN_ABORTED);
1572 }
1573 }
1574
1575 }
1576
1577 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1578 "rsm_memseg_import_get16: exit\n"));
1579
1580 return (e);
1581 }
1582
1583 int
rsm_memseg_import_get32(rsm_memseg_import_handle_t im_memseg,off_t offset,uint32_t * datap,ulong_t rep_cnt)1584 rsm_memseg_import_get32(rsm_memseg_import_handle_t im_memseg,
1585 off_t offset,
1586 uint32_t *datap,
1587 ulong_t rep_cnt)
1588 {
1589 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1590 int e;
1591
1592 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1593 "rsm_memseg_import_get32: enter\n"));
1594
1595 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1596 RSM_PERM_READ,
1597 RSM_DAS32);
1598 if (e == RSM_SUCCESS) {
1599 rsm_segops_t *ops = seg->rsmseg_ops;
1600 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1601
1602 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1603 /* generation number snapshot */
1604 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1605 }
1606
1607 e = ops->rsm_memseg_import_get32(im_memseg, offset, datap,
1608 rep_cnt, 0);
1609
1610 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1611 /* check the generation number for force disconnects */
1612 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1613 return (RSMERR_CONN_ABORTED);
1614 }
1615 }
1616 }
1617
1618 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1619 "rsm_memseg_import_get32: exit\n"));
1620
1621 return (e);
1622 }
1623
1624 int
rsm_memseg_import_get64(rsm_memseg_import_handle_t im_memseg,off_t offset,uint64_t * datap,ulong_t rep_cnt)1625 rsm_memseg_import_get64(rsm_memseg_import_handle_t im_memseg,
1626 off_t offset,
1627 uint64_t *datap,
1628 ulong_t rep_cnt)
1629 {
1630 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1631 int e;
1632
1633 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1634 "rsm_memseg_import_get64: enter\n"));
1635
1636 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
1637 RSM_PERM_READ,
1638 RSM_DAS64);
1639 if (e == RSM_SUCCESS) {
1640 rsm_segops_t *ops = seg->rsmseg_ops;
1641 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1642
1643 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1644 /* generation number snapshot */
1645 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1646 }
1647
1648 e = ops->rsm_memseg_import_get64(im_memseg, offset, datap,
1649 rep_cnt, 0);
1650
1651 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1652 /* check the generation number for force disconnects */
1653 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1654 return (RSMERR_CONN_ABORTED);
1655 }
1656 }
1657 }
1658
1659 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1660 "rsm_memseg_import_get64: exit\n"));
1661
1662 return (e);
1663 }
1664
1665 int
rsm_memseg_import_get(rsm_memseg_import_handle_t im_memseg,off_t offset,void * dst_addr,size_t length)1666 rsm_memseg_import_get(rsm_memseg_import_handle_t im_memseg,
1667 off_t offset,
1668 void *dst_addr,
1669 size_t length)
1670 {
1671 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1672 int e;
1673
1674 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1675 "rsm_memseg_import_get: enter\n"));
1676
1677 e = __rsm_import_verify_access(seg, offset, (caddr_t)dst_addr, length,
1678 RSM_PERM_READ,
1679 RSM_DAS8);
1680 if (e == RSM_SUCCESS) {
1681 rsm_segops_t *ops = seg->rsmseg_ops;
1682 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1683
1684 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1685 /* generation number snapshot */
1686 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1687 }
1688
1689 e = ops->rsm_memseg_import_get(im_memseg, offset, dst_addr,
1690 length);
1691
1692 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1693 /* check the generation number for force disconnects */
1694 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1695 return (RSMERR_CONN_ABORTED);
1696 }
1697 }
1698 }
1699
1700 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1701 "rsm_memseg_import_get: exit\n"));
1702
1703 return (e);
1704 }
1705
1706
1707 int
rsm_memseg_import_getv(rsm_scat_gath_t * sg_io)1708 rsm_memseg_import_getv(rsm_scat_gath_t *sg_io)
1709 {
1710 rsm_controller_t *cntrl;
1711 rsmseg_handle_t *seg;
1712 uint_t save_sg_io_flags;
1713
1714 int e;
1715
1716 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1717 "rsm_memseg_import_getv: enter\n"));
1718
1719 if (sg_io == NULL) {
1720 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1721 "invalid sg_io structure\n"));
1722 return (RSMERR_BAD_SGIO);
1723 }
1724
1725 seg = (rsmseg_handle_t *)sg_io->remote_handle;
1726 if (seg == NULL) {
1727 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1728 "invalid remote segment handle in sg_io\n"));
1729 return (RSMERR_BAD_SEG_HNDL);
1730 }
1731
1732 cntrl = (rsm_controller_t *)seg->rsmseg_controller;
1733 if (cntrl == NULL) {
1734 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1735 "invalid controller handle\n"));
1736 return (RSMERR_BAD_SEG_HNDL);
1737 }
1738
1739 if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
1740 (sg_io->io_request_count == 0)) {
1741 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1742 "io_request_count value incorrect\n"));
1743 return (RSMERR_BAD_SGIO);
1744 }
1745
1746 if (seg->rsmseg_state == IMPORT_CONNECT) {
1747 e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
1748 if (e != RSM_SUCCESS) {
1749 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
1750 "implicit map failure\n"));
1751 return (e);
1752 }
1753 }
1754
1755 /*
1756 * Copy the flags field of the sg_io structure in a local
1757 * variable.
1758 * This is required since the flags field can be
1759 * changed by the plugin library routine to indicate that
1760 * the signal post was done.
1761 * This change in the flags field of the sg_io structure
1762 * should not be reflected to the user. Hence once the flags
1763 * field has been used for the purpose of determining whether
1764 * the plugin executed a signal post, it must be restored to
1765 * its original value which is stored in the local variable.
1766 */
1767 save_sg_io_flags = sg_io->flags;
1768
1769 e = cntrl->cntr_segops->rsm_memseg_import_getv(sg_io);
1770
1771 /*
1772 * At this point, if an implicit signal post was requested by
1773 * the user, there could be two possibilities that arise:
1774 * 1. the plugin routine has already executed the implicit
1775 * signal post either successfully or unsuccessfully
1776 * 2. the plugin does not have the capability of doing an
1777 * implicit signal post and hence the signal post needs
1778 * to be done here.
1779 * The above two cases can be idenfied by the flags
1780 * field within the sg_io structure as follows:
1781 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
1782 * plugin, indicating that the signal post was done.
1783 * In case 2, the bit remains set to a 1 as originally given
1784 * by the user, and hence a signal post needs to be done here.
1785 */
1786 if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
1787 e == RSM_SUCCESS) {
1788 /* Do the implicit signal post */
1789
1790 /*
1791 * The value of the second argument to this call
1792 * depends on the value of the sg_io->flags field.
1793 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
1794 * ored into the sg_io->flags field, this indicates
1795 * that the rsm_intr_signal_post is to be done with
1796 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
1797 * Else, the flags argument is set to 0. These
1798 * semantics can be achieved simply by masking off
1799 * all other bits in the sg_io->flags field except the
1800 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
1801 * as the flags argument for the rsm_intr_signal_post.
1802 */
1803
1804 int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
1805 e = rsm_intr_signal_post(seg, sigpost_flags);
1806 }
1807
1808 /* Restore the flags field within the users scatter gather structure */
1809 sg_io->flags = save_sg_io_flags;
1810
1811 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1812 "rsm_memseg_import_getv: exit\n"));
1813
1814 return (e);
1815
1816 }
1817
1818 /*
1819 * import side memory segment operations (write access functions):
1820 */
1821
1822 int
rsm_memseg_import_put8(rsm_memseg_import_handle_t im_memseg,off_t offset,uint8_t * datap,ulong_t rep_cnt)1823 rsm_memseg_import_put8(rsm_memseg_import_handle_t im_memseg,
1824 off_t offset,
1825 uint8_t *datap,
1826 ulong_t rep_cnt)
1827 {
1828 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1829 int e;
1830
1831 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1832 "rsm_memseg_import_put8: enter\n"));
1833
1834 /* addr of data will always pass the alignment check, avoids */
1835 /* need for a special case in verify_access for PUTs */
1836 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt,
1837 RSM_PERM_WRITE,
1838 RSM_DAS8);
1839 if (e == RSM_SUCCESS) {
1840 rsm_segops_t *ops = seg->rsmseg_ops;
1841 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1842
1843 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1844 /* generation number snapshot */
1845 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1846 }
1847
1848 e = ops->rsm_memseg_import_put8(im_memseg, offset, datap,
1849 rep_cnt, 0);
1850
1851 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1852 /* check the generation number for force disconnects */
1853 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1854 return (RSMERR_CONN_ABORTED);
1855 }
1856 }
1857 }
1858
1859 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1860 "rsm_memseg_import_put8: exit\n"));
1861
1862 return (e);
1863 }
1864
1865 int
rsm_memseg_import_put16(rsm_memseg_import_handle_t im_memseg,off_t offset,uint16_t * datap,ulong_t rep_cnt)1866 rsm_memseg_import_put16(rsm_memseg_import_handle_t im_memseg,
1867 off_t offset,
1868 uint16_t *datap,
1869 ulong_t rep_cnt)
1870 {
1871 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1872 int e;
1873
1874 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1875 "rsm_memseg_import_put16: enter\n"));
1876
1877 /* addr of data will always pass the alignment check, avoids */
1878 /* need for a special case in verify_access for PUTs */
1879 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*2,
1880 RSM_PERM_WRITE,
1881 RSM_DAS16);
1882 if (e == RSM_SUCCESS) {
1883 rsm_segops_t *ops = seg->rsmseg_ops;
1884 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1885
1886 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1887 /* generation number snapshot */
1888 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1889 }
1890
1891 e = ops->rsm_memseg_import_put16(im_memseg, offset, datap,
1892 rep_cnt, 0);
1893
1894 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1895 /* check the generation number for force disconnects */
1896 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1897 return (RSMERR_CONN_ABORTED);
1898 }
1899 }
1900
1901 }
1902
1903 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1904 "rsm_memseg_import_put16: exit\n"));
1905
1906 return (e);
1907 }
1908
1909 int
rsm_memseg_import_put32(rsm_memseg_import_handle_t im_memseg,off_t offset,uint32_t * datap,ulong_t rep_cnt)1910 rsm_memseg_import_put32(rsm_memseg_import_handle_t im_memseg,
1911 off_t offset,
1912 uint32_t *datap,
1913 ulong_t rep_cnt)
1914 {
1915 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1916 int e;
1917
1918 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1919 "rsm_memseg_import_put32: enter\n"));
1920
1921 /* addr of data will always pass the alignment check, avoids */
1922 /* need for a special case in verify_access for PUTs */
1923 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*4,
1924 RSM_PERM_WRITE,
1925 RSM_DAS32);
1926 if (e == RSM_SUCCESS) {
1927 rsm_segops_t *ops = seg->rsmseg_ops;
1928 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1929
1930 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1931 /* generation number snapshot */
1932 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1933 }
1934
1935 e = ops->rsm_memseg_import_put32(im_memseg, offset, datap,
1936 rep_cnt, 0);
1937
1938 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1939 /* check the generation number for force disconnects */
1940 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1941 return (RSMERR_CONN_ABORTED);
1942 }
1943 }
1944 }
1945
1946 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1947 "rsm_memseg_import_put32: exit\n"));
1948
1949 return (e);
1950 }
1951
1952 int
rsm_memseg_import_put64(rsm_memseg_import_handle_t im_memseg,off_t offset,uint64_t * datap,ulong_t rep_cnt)1953 rsm_memseg_import_put64(rsm_memseg_import_handle_t im_memseg,
1954 off_t offset,
1955 uint64_t *datap,
1956 ulong_t rep_cnt)
1957 {
1958 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
1959 int e;
1960
1961 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1962 "rsm_memseg_import_put64: enter\n"));
1963
1964 /* addr of data will always pass the alignment check, avoids */
1965 /* need for a special case in verify_access for PUTs */
1966 e = __rsm_import_verify_access(seg, offset, (caddr_t)datap, rep_cnt*8,
1967 RSM_PERM_WRITE,
1968 RSM_DAS64);
1969 if (e == RSM_SUCCESS) {
1970 rsm_segops_t *ops = seg->rsmseg_ops;
1971 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
1972
1973 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1974 /* generation number snapshot */
1975 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
1976 }
1977
1978 e = ops->rsm_memseg_import_put64(im_memseg, offset, datap,
1979 rep_cnt, 0);
1980
1981 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
1982 /* check the generation number for force disconnects */
1983 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
1984 return (RSMERR_CONN_ABORTED);
1985 }
1986 }
1987 }
1988
1989 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
1990 "rsm_memseg_import_put64: exit\n"));
1991
1992 return (e);
1993 }
1994
1995 int
rsm_memseg_import_put(rsm_memseg_import_handle_t im_memseg,off_t offset,void * src_addr,size_t length)1996 rsm_memseg_import_put(rsm_memseg_import_handle_t im_memseg,
1997 off_t offset,
1998 void *src_addr,
1999 size_t length)
2000 {
2001 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2002 int e;
2003
2004 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2005 "rsm_memseg_import_put: enter\n"));
2006
2007 e = __rsm_import_verify_access(seg, offset, (caddr_t)src_addr, length,
2008 RSM_PERM_WRITE,
2009 RSM_DAS8);
2010 if (e == RSM_SUCCESS) {
2011 rsm_segops_t *ops = seg->rsmseg_ops;
2012 rsmbar_handle_t *bar = (rsmbar_handle_t *)seg->rsmseg_barrier;
2013
2014 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2015 /* generation number snapshot */
2016 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum;
2017 }
2018
2019 e = ops->rsm_memseg_import_put(im_memseg, offset, src_addr,
2020 length);
2021
2022 if (seg->rsmseg_barmode == RSM_BARRIER_MODE_IMPLICIT) {
2023 /* check the generation number for force disconnects */
2024 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2025 return (RSMERR_CONN_ABORTED);
2026 }
2027 }
2028
2029 }
2030
2031 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2032 "rsm_memseg_import_put: exit\n"));
2033 return (e);
2034 }
2035
2036
2037 int
rsm_memseg_import_putv(rsm_scat_gath_t * sg_io)2038 rsm_memseg_import_putv(rsm_scat_gath_t *sg_io)
2039 {
2040 rsm_controller_t *cntrl;
2041 rsmseg_handle_t *seg;
2042 uint_t save_sg_io_flags;
2043
2044 int e;
2045
2046 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2047 "rsm_memseg_import_putv: enter\n"));
2048
2049
2050 if (sg_io == NULL) {
2051 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2052 "invalid sg_io structure\n"));
2053 return (RSMERR_BAD_SGIO);
2054 }
2055
2056 seg = (rsmseg_handle_t *)sg_io->remote_handle;
2057 if (seg == NULL) {
2058 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2059 "invalid remote segment handle in sg_io\n"));
2060 return (RSMERR_BAD_SEG_HNDL);
2061 }
2062
2063 cntrl = (rsm_controller_t *)seg->rsmseg_controller;
2064 if (cntrl == NULL) {
2065 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2066 "invalid controller handle\n"));
2067 return (RSMERR_BAD_SEG_HNDL);
2068 }
2069
2070 if ((sg_io->io_request_count > RSM_MAX_SGIOREQS) ||
2071 (sg_io->io_request_count == 0)) {
2072 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2073 "io_request_count value incorrect\n"));
2074 return (RSMERR_BAD_SGIO);
2075 }
2076
2077 /* do an implicit map if required */
2078 if (seg->rsmseg_state == IMPORT_CONNECT) {
2079 e = __rsm_import_implicit_map(seg, RSM_IOTYPE_SCATGATH);
2080 if (e != RSM_SUCCESS) {
2081 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2082 "implicit map failed\n"));
2083 return (e);
2084 }
2085 }
2086
2087 /*
2088 * Copy the flags field of the sg_io structure in a local
2089 * variable.
2090 * This is required since the flags field can be
2091 * changed by the plugin library routine to indicate that
2092 * the signal post was done.
2093 * This change in the flags field of the sg_io structure
2094 * should not be reflected to the user. Hence once the flags
2095 * field has been used for the purpose of determining whether
2096 * the plugin executed a signal post, it must be restored to
2097 * its original value which is stored in the local variable.
2098 */
2099 save_sg_io_flags = sg_io->flags;
2100
2101 e = cntrl->cntr_segops->rsm_memseg_import_putv(sg_io);
2102
2103 /*
2104 * At this point, if an implicit signal post was requested by
2105 * the user, there could be two possibilities that arise:
2106 * 1. the plugin routine has already executed the implicit
2107 * signal post either successfully or unsuccessfully
2108 * 2. the plugin does not have the capability of doing an
2109 * implicit signal post and hence the signal post needs
2110 * to be done here.
2111 * The above two cases can be idenfied by the flags
2112 * field within the sg_io structure as follows:
2113 * In case 1, the RSM_IMPLICIT_SIGPOST bit is reset to 0 by the
2114 * plugin, indicating that the signal post was done.
2115 * In case 2, the bit remains set to a 1 as originally given
2116 * by the user, and hence a signal post needs to be done here.
2117 */
2118 if (sg_io->flags & RSM_IMPLICIT_SIGPOST &&
2119 e == RSM_SUCCESS) {
2120 /* Do the implicit signal post */
2121
2122 /*
2123 * The value of the second argument to this call
2124 * depends on the value of the sg_io->flags field.
2125 * If the RSM_SIGPOST_NO_ACCUMULATE flag has been
2126 * ored into the sg_io->flags field, this indicates
2127 * that the rsm_intr_signal_post is to be done with
2128 * the flags argument set to RSM_SIGPOST_NO_ACCUMULATE
2129 * Else, the flags argument is set to 0. These
2130 * semantics can be achieved simply by masking off
2131 * all other bits in the sg_io->flags field except the
2132 * RSM_SIGPOST_NO_ACCUMULATE bit and using the result
2133 * as the flags argument for the rsm_intr_signal_post.
2134 */
2135
2136 int sigpost_flags = sg_io->flags & RSM_SIGPOST_NO_ACCUMULATE;
2137 e = rsm_intr_signal_post(seg, sigpost_flags);
2138
2139 }
2140
2141 /* Restore the flags field within the users scatter gather structure */
2142 sg_io->flags = save_sg_io_flags;
2143
2144 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2145 "rsm_memseg_import_putv: exit\n"));
2146
2147 return (e);
2148 }
2149
2150
2151 /*
2152 * import side memory segment operations (mapping):
2153 */
2154 int
rsm_memseg_import_map(rsm_memseg_import_handle_t im_memseg,void ** address,rsm_attribute_t attr,rsm_permission_t perm,off_t offset,size_t length)2155 rsm_memseg_import_map(rsm_memseg_import_handle_t im_memseg,
2156 void **address,
2157 rsm_attribute_t attr,
2158 rsm_permission_t perm,
2159 off_t offset,
2160 size_t length)
2161 {
2162 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2163 int flag = MAP_SHARED;
2164 int prot;
2165 caddr_t va;
2166
2167 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2168 "rsm_memseg_import_map: enter\n"));
2169
2170 if (!seg) {
2171 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2172 "invalid segment\n"));
2173 return (RSMERR_BAD_SEG_HNDL);
2174 }
2175 if (!address) {
2176 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2177 "invalid address\n"));
2178 return (RSMERR_BAD_ADDR);
2179 }
2180
2181 /*
2182 * Only one map per segment handle!
2183 * XXX need to take a lock here
2184 */
2185 mutex_lock(&seg->rsmseg_lock);
2186
2187 if (seg->rsmseg_state == IMPORT_MAP) {
2188 mutex_unlock(&seg->rsmseg_lock);
2189 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2190 "segment already mapped\n"));
2191 return (RSMERR_SEG_ALREADY_MAPPED);
2192 }
2193
2194 /* Only import segments allowed to map */
2195 if (seg->rsmseg_state != IMPORT_CONNECT) {
2196 mutex_unlock(&seg->rsmseg_lock);
2197 return (RSMERR_BAD_SEG_HNDL);
2198 }
2199
2200 /* check for permissions */
2201 if (perm > RSM_PERM_RDWR) {
2202 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2203 "bad permissions when mapping\n"));
2204 mutex_unlock(&seg->rsmseg_lock);
2205 return (RSMERR_BAD_PERMS);
2206 }
2207
2208 if (length == 0) {
2209 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2210 "mapping with length 0\n"));
2211 mutex_unlock(&seg->rsmseg_lock);
2212 return (RSMERR_BAD_LENGTH);
2213 }
2214
2215 if (offset + length > seg->rsmseg_size) {
2216 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2217 "map length + offset exceed segment size\n"));
2218 mutex_unlock(&seg->rsmseg_lock);
2219 return (RSMERR_BAD_LENGTH);
2220 }
2221
2222 if ((size_t)offset & (PAGESIZE - 1)) {
2223 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2224 "bad mem alignment\n"));
2225 return (RSMERR_BAD_MEM_ALIGNMENT);
2226 }
2227
2228 if (attr & RSM_MAP_FIXED) {
2229 if ((uintptr_t)(*address) & (PAGESIZE - 1)) {
2230 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2231 "bad mem alignment\n"));
2232 return (RSMERR_BAD_MEM_ALIGNMENT);
2233 }
2234 flag |= MAP_FIXED;
2235 }
2236
2237 prot = PROT_NONE;
2238 if (perm & RSM_PERM_READ)
2239 prot |= PROT_READ;
2240 if (perm & RSM_PERM_WRITE)
2241 prot |= PROT_WRITE;
2242
2243 va = mmap(*address, length, prot, flag, seg->rsmseg_fd, offset);
2244 if (va == MAP_FAILED) {
2245 int e = errno;
2246 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2247 "error %d during map\n", e));
2248
2249 mutex_unlock(&seg->rsmseg_lock);
2250 if (e == ENXIO || e == EOVERFLOW ||
2251 e == ENOMEM)
2252 return (RSMERR_BAD_LENGTH);
2253 else if (e == ENODEV)
2254 return (RSMERR_CONN_ABORTED);
2255 else if (e == EAGAIN)
2256 return (RSMERR_INSUFFICIENT_RESOURCES);
2257 else if (e == ENOTSUP)
2258 return (RSMERR_MAP_FAILED);
2259 else if (e == EACCES)
2260 return (RSMERR_BAD_PERMS);
2261 else
2262 return (RSMERR_MAP_FAILED);
2263 }
2264 *address = va;
2265
2266 /*
2267 * Fix segment ops vector to handle direct access.
2268 */
2269 /*
2270 * XXX: Set this only for full segment mapping. Keep a list
2271 * of mappings to use for access functions
2272 */
2273 seg->rsmseg_vaddr = va;
2274 seg->rsmseg_maplen = length;
2275 seg->rsmseg_mapoffset = offset;
2276 seg->rsmseg_state = IMPORT_MAP;
2277
2278 mutex_unlock(&seg->rsmseg_lock);
2279
2280 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2281 "rsm_memseg_import_map: exit\n"));
2282
2283 return (RSM_SUCCESS);
2284 }
2285
2286 int
rsm_memseg_import_unmap(rsm_memseg_import_handle_t im_memseg)2287 rsm_memseg_import_unmap(rsm_memseg_import_handle_t im_memseg)
2288 {
2289 /*
2290 * Until we fix the rsm driver to catch unload, we unload
2291 * the whole segment.
2292 */
2293
2294 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2295
2296 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2297 "rsm_memseg_import_unmap: enter\n"));
2298
2299 if (!seg) {
2300 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2301 "invalid segment or segment state\n"));
2302 return (RSMERR_BAD_SEG_HNDL);
2303 }
2304
2305 mutex_lock(&seg->rsmseg_lock);
2306 if (seg->rsmseg_state != IMPORT_MAP) {
2307 mutex_unlock(&seg->rsmseg_lock);
2308 return (RSMERR_SEG_NOT_MAPPED);
2309 }
2310
2311 seg->rsmseg_mapoffset = 0; /* reset the offset */
2312 seg->rsmseg_state = IMPORT_CONNECT;
2313 seg->rsmseg_flags &= ~RSM_IMPLICIT_MAP;
2314 (void) munmap(seg->rsmseg_vaddr, seg->rsmseg_maplen);
2315
2316 mutex_unlock(&seg->rsmseg_lock);
2317
2318 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2319 "rsm_memseg_import_unmap: exit\n"));
2320
2321 return (RSM_SUCCESS);
2322 }
2323
2324
2325 /*
2326 * import side memory segment operations (barriers):
2327 */
2328 int
rsm_memseg_import_init_barrier(rsm_memseg_import_handle_t im_memseg,rsm_barrier_type_t type,rsmapi_barrier_t * barrier)2329 rsm_memseg_import_init_barrier(rsm_memseg_import_handle_t im_memseg,
2330 rsm_barrier_type_t type,
2331 rsmapi_barrier_t *barrier)
2332 {
2333 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2334 rsmbar_handle_t *bar;
2335
2336 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2337 "rsm_memseg_import_init_barrier: enter\n"));
2338
2339 if (!seg) {
2340 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2341 "invalid segment or barrier\n"));
2342 return (RSMERR_BAD_SEG_HNDL);
2343 }
2344 if (!barrier) {
2345 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2346 "invalid barrier pointer\n"));
2347 return (RSMERR_BAD_BARRIER_PTR);
2348 }
2349
2350 bar = (rsmbar_handle_t *)barrier;
2351 bar->rsmbar_seg = seg;
2352
2353 seg->rsmseg_barrier = barrier; /* used in put/get fns */
2354
2355 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2356 "rsm_memseg_import_init_barrier: exit\n"));
2357
2358 return (seg->rsmseg_ops->rsm_memseg_import_init_barrier(im_memseg,
2359 type, (rsm_barrier_handle_t)barrier));
2360 }
2361
2362 int
rsm_memseg_import_open_barrier(rsmapi_barrier_t * barrier)2363 rsm_memseg_import_open_barrier(rsmapi_barrier_t *barrier)
2364 {
2365 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2366 rsm_segops_t *ops;
2367
2368 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2369 "rsm_memseg_import_open_barrier: enter\n"));
2370
2371 if (!bar) {
2372 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2373 "invalid barrier\n"));
2374 return (RSMERR_BAD_BARRIER_PTR);
2375 }
2376 if (!bar->rsmbar_seg) {
2377 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2378 "uninitialized barrier\n"));
2379 return (RSMERR_BARRIER_UNINITIALIZED);
2380 }
2381
2382 /* generation number snapshot */
2383 bar->rsmbar_gen = bar->rsmbar_seg->rsmseg_gnum; /* bar[0] */
2384
2385 ops = bar->rsmbar_seg->rsmseg_ops;
2386
2387 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2388 "rsm_memseg_import_open_barrier: exit\n"));
2389
2390 return (ops->rsm_memseg_import_open_barrier(
2391 (rsm_barrier_handle_t)barrier));
2392 }
2393
2394 int
rsm_memseg_import_order_barrier(rsmapi_barrier_t * barrier)2395 rsm_memseg_import_order_barrier(rsmapi_barrier_t *barrier)
2396 {
2397 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2398 rsm_segops_t *ops;
2399
2400 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2401 "rsm_memseg_import_order_barrier: enter\n"));
2402
2403 if (!bar) {
2404 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2405 "invalid barrier\n"));
2406 return (RSMERR_BAD_BARRIER_PTR);
2407 }
2408 if (!bar->rsmbar_seg) {
2409 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2410 "uninitialized barrier\n"));
2411 return (RSMERR_BARRIER_UNINITIALIZED);
2412 }
2413
2414 ops = bar->rsmbar_seg->rsmseg_ops;
2415
2416 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2417 "rsm_memseg_import_order_barrier: exit\n"));
2418
2419 return (ops->rsm_memseg_import_order_barrier(
2420 (rsm_barrier_handle_t)barrier));
2421 }
2422
2423 int
rsm_memseg_import_close_barrier(rsmapi_barrier_t * barrier)2424 rsm_memseg_import_close_barrier(rsmapi_barrier_t *barrier)
2425 {
2426 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2427 rsm_segops_t *ops;
2428
2429 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2430 "rsm_memseg_import_close_barrier: enter\n"));
2431
2432 if (!bar) {
2433 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2434 "invalid barrier\n"));
2435 return (RSMERR_BAD_BARRIER_PTR);
2436 }
2437 if (!bar->rsmbar_seg) {
2438 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2439 "uninitialized barrier\n"));
2440 return (RSMERR_BARRIER_UNINITIALIZED);
2441 }
2442
2443 /* generation number snapshot */
2444 if (bar->rsmbar_gen != bar->rsmbar_seg->rsmseg_bar[0]) {
2445 return (RSMERR_CONN_ABORTED);
2446 }
2447
2448 ops = bar->rsmbar_seg->rsmseg_ops;
2449
2450 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2451 "rsm_memseg_import_close_barrier: exit\n"));
2452
2453 return (ops->rsm_memseg_import_close_barrier(
2454 (rsm_barrier_handle_t)barrier));
2455 }
2456
2457 int
rsm_memseg_import_destroy_barrier(rsmapi_barrier_t * barrier)2458 rsm_memseg_import_destroy_barrier(rsmapi_barrier_t *barrier)
2459 {
2460 rsmbar_handle_t *bar = (rsmbar_handle_t *)barrier;
2461 rsm_segops_t *ops;
2462
2463 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2464 "rsm_memseg_import_destroy_barrier: enter\n"));
2465
2466 if (!bar) {
2467 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2468 "invalid barrier\n"));
2469 return (RSMERR_BAD_BARRIER_PTR);
2470 }
2471 if (!bar->rsmbar_seg) {
2472 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2473 "uninitialized barrier\n"));
2474 return (RSMERR_BARRIER_UNINITIALIZED);
2475 }
2476
2477 bar->rsmbar_seg->rsmseg_barrier = NULL;
2478
2479 ops = bar->rsmbar_seg->rsmseg_ops;
2480
2481 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2482 "rsm_memseg_import_destroy_barrier: exit\n"));
2483
2484 return (ops->rsm_memseg_import_destroy_barrier
2485 ((rsm_barrier_handle_t)barrier));
2486 }
2487
2488 int
rsm_memseg_import_get_mode(rsm_memseg_import_handle_t im_memseg,rsm_barrier_mode_t * mode)2489 rsm_memseg_import_get_mode(rsm_memseg_import_handle_t im_memseg,
2490 rsm_barrier_mode_t *mode)
2491 {
2492 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2493
2494 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2495 "rsm_memseg_import_get_mode: enter\n"));
2496
2497 if (seg) {
2498 *mode = seg->rsmseg_barmode;
2499 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2500 "rsm_memseg_import_get_mode: exit\n"));
2501
2502 return (seg->rsmseg_ops->rsm_memseg_import_get_mode(im_memseg,
2503 mode));
2504 }
2505
2506 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2507 "invalid arguments \n"));
2508
2509 return (RSMERR_BAD_SEG_HNDL);
2510
2511 }
2512
2513 int
rsm_memseg_import_set_mode(rsm_memseg_import_handle_t im_memseg,rsm_barrier_mode_t mode)2514 rsm_memseg_import_set_mode(rsm_memseg_import_handle_t im_memseg,
2515 rsm_barrier_mode_t mode)
2516 {
2517 rsmseg_handle_t *seg = (rsmseg_handle_t *)im_memseg;
2518
2519 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2520 "rsm_memseg_import_set_mode: enter\n"));
2521 if (seg) {
2522 if ((mode == RSM_BARRIER_MODE_IMPLICIT ||
2523 mode == RSM_BARRIER_MODE_EXPLICIT)) {
2524 seg->rsmseg_barmode = mode;
2525 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2526 "rsm_memseg_import_set_mode: exit\n"));
2527
2528 return (seg->rsmseg_ops->rsm_memseg_import_set_mode(
2529 im_memseg,
2530 mode));
2531 } else {
2532 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_DEBUG_VERBOSE,
2533 "bad barrier mode\n"));
2534 return (RSMERR_BAD_MODE);
2535 }
2536 }
2537
2538 DBPRINTF((RSM_LIBRARY|RSM_IMPORT, RSM_ERR,
2539 "invalid arguments\n"));
2540
2541 return (RSMERR_BAD_SEG_HNDL);
2542 }
2543
2544 int
rsm_intr_signal_post(void * memseg,uint_t flags)2545 rsm_intr_signal_post(void *memseg, uint_t flags)
2546 {
2547 rsm_ioctlmsg_t msg;
2548 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2549
2550 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2551 "rsm_intr_signal_post: enter\n"));
2552
2553 flags = flags;
2554
2555 if (!seg) {
2556 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2557 "invalid segment handle\n"));
2558 return (RSMERR_BAD_SEG_HNDL);
2559 }
2560
2561 if (ioctl(seg->rsmseg_fd, RSM_IOCTL_RING_BELL, &msg) < 0) {
2562 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2563 "RSM_IOCTL_RING_BELL failed\n"));
2564 return (errno);
2565 }
2566
2567 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2568 "rsm_intr_signal_post: exit\n"));
2569
2570 return (RSM_SUCCESS);
2571 }
2572
2573 int
rsm_intr_signal_wait(void * memseg,int timeout)2574 rsm_intr_signal_wait(void *memseg, int timeout)
2575 {
2576 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2577 struct pollfd fds;
2578 minor_t rnum;
2579
2580 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2581 "rsm_intr_signal_wait: enter\n"));
2582
2583 if (!seg) {
2584 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2585 "invalid segment\n"));
2586 return (RSMERR_BAD_SEG_HNDL);
2587 }
2588
2589 fds.fd = seg->rsmseg_fd;
2590 fds.events = POLLRDNORM;
2591
2592 rnum = seg->rsmseg_rnum;
2593
2594 return (__rsm_intr_signal_wait_common(&fds, &rnum, 1, timeout, NULL));
2595 }
2596
2597 int
rsm_intr_signal_wait_pollfd(struct pollfd fds[],nfds_t nfds,int timeout,int * numfdsp)2598 rsm_intr_signal_wait_pollfd(struct pollfd fds[], nfds_t nfds, int timeout,
2599 int *numfdsp)
2600 {
2601 return (__rsm_intr_signal_wait_common(fds, NULL, nfds, timeout,
2602 numfdsp));
2603 }
2604
2605 /*
2606 * This is the generic wait routine, it takes the following arguments
2607 * - pollfd array
2608 * - rnums array corresponding to the pollfd if known, if this is
2609 * NULL then the fds are looked up from the pollfd_table.
2610 * - number of fds in pollfd array,
2611 * - timeout
2612 * - pointer to a location where the number of fds with successful
2613 * events is returned.
2614 */
2615 static int
__rsm_intr_signal_wait_common(struct pollfd fds[],minor_t rnums[],nfds_t nfds,int timeout,int * numfdsp)2616 __rsm_intr_signal_wait_common(struct pollfd fds[], minor_t rnums[],
2617 nfds_t nfds, int timeout, int *numfdsp)
2618 {
2619 int i;
2620 int numsegs = 0;
2621 int numfd;
2622 int fds_processed = 0;
2623 minor_t segrnum;
2624 rsm_poll_event_t event_arr[RSM_MAX_POLLFDS];
2625 rsm_poll_event_t *event_list = NULL;
2626 rsm_poll_event_t *events;
2627 rsm_consume_event_msg_t msg;
2628
2629 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE, "wait_common enter\n"));
2630
2631 if (numfdsp) {
2632 *numfdsp = 0;
2633 }
2634
2635 numfd = poll(fds, nfds, timeout);
2636
2637 switch (numfd) {
2638 case -1: /* poll returned error - map to RSMERR_... */
2639 DBPRINTF((RSM_LIBRARY, RSM_ERR, "signal wait pollfd err\n"));
2640 switch (errno) {
2641 case EAGAIN:
2642 return (RSMERR_INSUFFICIENT_RESOURCES);
2643 case EFAULT:
2644 return (RSMERR_BAD_ADDR);
2645 case EINTR:
2646 return (RSMERR_INTERRUPTED);
2647 case EINVAL:
2648 default:
2649 return (RSMERR_BAD_ARGS_ERRORS);
2650 }
2651 case 0: /* timedout - return from here */
2652 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2653 "signal wait timed out\n"));
2654 return (RSMERR_TIMEOUT);
2655 default:
2656 break;
2657 }
2658
2659 if (numfd <= RSM_MAX_POLLFDS) {
2660 /* use the event array on the stack */
2661 events = (rsm_poll_event_t *)event_arr;
2662 } else {
2663 /*
2664 * actual number of fds corresponding to rsmapi segments might
2665 * be < numfd, don't want to scan the list to figure that out
2666 * lets just allocate on the heap
2667 */
2668 event_list = (rsm_poll_event_t *)malloc(
2669 sizeof (rsm_poll_event_t)*numfd);
2670 if (!event_list) {
2671 /*
2672 * return with error even if poll might have succeeded
2673 * since the application can retry and the events will
2674 * still be available.
2675 */
2676 return (RSMERR_INSUFFICIENT_MEM);
2677 }
2678 events = event_list;
2679 }
2680
2681 /*
2682 * process the fds for events and if it corresponds to an rsmapi
2683 * segment consume the event
2684 */
2685 for (i = 0; i < nfds; i++) {
2686 if (fds[i].revents == POLLRDNORM) {
2687 /*
2688 * poll returned an event and if its POLLRDNORM, it
2689 * might correspond to an rsmapi segment
2690 */
2691 if (rnums) { /* resource num is passed in */
2692 segrnum = rnums[i];
2693 } else { /* lookup pollfd table to get resource num */
2694 segrnum = _rsm_lookup_pollfd_table(fds[i].fd);
2695 }
2696 if (segrnum) {
2697 events[numsegs].rnum = segrnum;
2698 events[numsegs].revent = 0;
2699 events[numsegs].fdsidx = i; /* fdlist index */
2700 numsegs++;
2701 }
2702 }
2703
2704 if ((fds[i].revents) && (++fds_processed == numfd)) {
2705 /*
2706 * only "numfd" events have revents field set, once we
2707 * process that many break out of the loop
2708 */
2709 break;
2710 }
2711 }
2712
2713 if (numsegs == 0) { /* No events for rsmapi segs in the fdlist */
2714 if (event_list) {
2715 free(event_list);
2716 }
2717 if (numfdsp) {
2718 *numfdsp = numfd;
2719 }
2720 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2721 "wait_common exit: no rsmapi segs\n"));
2722 return (RSM_SUCCESS);
2723 }
2724
2725 msg.seglist = (caddr_t)events;
2726 msg.numents = numsegs;
2727
2728 if (ioctl(_rsm_fd, RSM_IOCTL_CONSUMEEVENT, &msg) < 0) {
2729 int error = errno;
2730 if (event_list) {
2731 free(event_list);
2732 }
2733 DBPRINTF((RSM_LIBRARY|RSM_LOOPBACK, RSM_ERR,
2734 "RSM_IOCTL_CONSUMEEVENT failed(%d)\n", error));
2735 return (error);
2736 }
2737
2738 /* count the number of segs for which consumeevent was successful */
2739 numfd -= numsegs;
2740
2741 for (i = 0; i < numsegs; i++) {
2742 if (events[i].revent != 0) {
2743 fds[events[i].fdsidx].revents = POLLRDNORM;
2744 numfd++;
2745 } else { /* failed to consume event so set revents to 0 */
2746 fds[events[i].fdsidx].revents = 0;
2747 }
2748 }
2749
2750 if (event_list) {
2751 free(event_list);
2752 }
2753
2754 if (numfd > 0) {
2755 if (numfdsp) {
2756 *numfdsp = numfd;
2757 }
2758 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2759 "wait_common exit\n"));
2760 return (RSM_SUCCESS);
2761 } else {
2762 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2763 "wait_common exit\n"));
2764 return (RSMERR_TIMEOUT);
2765 }
2766 }
2767
2768 /*
2769 * This function provides the data (file descriptor and event) for
2770 * the specified pollfd struct. The pollfd struct may then be
2771 * subsequently used with the poll system call to wait for an event
2772 * signalled by rsm_intr_signal_post. The memory segment must be
2773 * currently published for a successful return with a valid pollfd.
2774 * A reference count for the descriptor is incremented.
2775 */
2776 int
rsm_memseg_get_pollfd(void * memseg,struct pollfd * poll_fd)2777 rsm_memseg_get_pollfd(void *memseg,
2778 struct pollfd *poll_fd)
2779 {
2780 int i;
2781 int err = RSM_SUCCESS;
2782 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2783
2784 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2785 "rsm_memseg_get_pollfd: enter\n"));
2786
2787 if (!seg) {
2788 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2789 "invalid segment\n"));
2790 return (RSMERR_BAD_SEG_HNDL);
2791 }
2792
2793 mutex_lock(&seg->rsmseg_lock);
2794
2795 poll_fd->fd = seg->rsmseg_fd;
2796 poll_fd->events = POLLRDNORM;
2797 seg->rsmseg_pollfd_refcnt++;
2798 if (seg->rsmseg_pollfd_refcnt == 1) {
2799 /* insert the segment into the pollfd table */
2800 err = _rsm_insert_pollfd_table(seg->rsmseg_fd,
2801 seg->rsmseg_rnum);
2802 }
2803
2804 mutex_unlock(&seg->rsmseg_lock);
2805
2806 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2807 "rsm_memseg_get_pollfd: exit(%d)\n", err));
2808
2809 return (err);
2810 }
2811
2812 /*
2813 * This function decrements the segment pollfd reference count.
2814 * A segment unpublish or destroy operation will fail if the reference count is
2815 * non zero.
2816 */
2817 int
rsm_memseg_release_pollfd(void * memseg)2818 rsm_memseg_release_pollfd(void * memseg)
2819 {
2820 int i;
2821 rsmseg_handle_t *seg = (rsmseg_handle_t *)memseg;
2822
2823 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2824 "rsm_memseg_release_pollfd: enter\n"));
2825
2826 if (!seg) {
2827 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2828 "invalid segment handle\n"));
2829 return (RSMERR_BAD_SEG_HNDL);
2830 }
2831
2832 mutex_lock(&seg->rsmseg_lock);
2833
2834 if (seg->rsmseg_pollfd_refcnt) {
2835 seg->rsmseg_pollfd_refcnt--;
2836 if (seg->rsmseg_pollfd_refcnt == 0) {
2837 /* last reference removed - update the pollfd_table */
2838 _rsm_remove_pollfd_table(seg->rsmseg_fd);
2839 }
2840 }
2841
2842 mutex_unlock(&seg->rsmseg_lock);
2843
2844 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2845 "rsm_memseg_release_pollfd: exit\n"));
2846
2847 return (RSM_SUCCESS);
2848 }
2849
2850 /*
2851 * The interconnect topology data is obtained from the Kernel Agent
2852 * and stored in a memory buffer allocated by this function. A pointer
2853 * to the buffer is stored in the location specified by the caller in
2854 * the function argument. It is the callers responsibility to
2855 * call rsm_free_interconnect_topolgy() to free the allocated memory.
2856 */
2857 int
rsm_get_interconnect_topology(rsm_topology_t ** topology_data)2858 rsm_get_interconnect_topology(rsm_topology_t **topology_data)
2859 {
2860 uint32_t topology_data_size;
2861 rsm_topology_t *topology_ptr;
2862 int error;
2863
2864 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2865 "rsm_get_interconnect_topology: enter\n"));
2866
2867 if (topology_data == NULL)
2868 return (RSMERR_BAD_TOPOLOGY_PTR);
2869
2870 *topology_data = NULL;
2871
2872 again:
2873 /* obtain the size of the topology data */
2874 if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_SIZE, &topology_data_size) < 0) {
2875 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2876 "RSM_IOCTL_TOPOLOGY_SIZE failed\n"));
2877 return (errno);
2878 }
2879
2880 /* allocate double-word aligned memory to hold the topology data */
2881 topology_ptr = (rsm_topology_t *)memalign(8, topology_data_size);
2882 if (topology_ptr == NULL) {
2883 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2884 "not enough memory\n"));
2885 return (RSMERR_INSUFFICIENT_MEM);
2886 }
2887
2888 /*
2889 * Request the topology data.
2890 * Pass in the size to be used as a check in case
2891 * the data has grown since the size was obtained - if
2892 * it has, the errno value will be E2BIG.
2893 */
2894 topology_ptr->topology_hdr.local_nodeid =
2895 (rsm_node_id_t)topology_data_size;
2896 if (ioctl(_rsm_fd, RSM_IOCTL_TOPOLOGY_DATA, topology_ptr) < 0) {
2897 error = errno;
2898 free((void *)topology_ptr);
2899 if (error == E2BIG)
2900 goto again;
2901 else {
2902 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2903 "RSM_IOCTL_TOPOLOGY_DATA failed\n"));
2904 return (error);
2905 }
2906 } else
2907 *topology_data = topology_ptr;
2908
2909 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2910 " rsm_get_interconnect_topology: exit\n"));
2911
2912 return (RSM_SUCCESS);
2913 }
2914
2915
2916 void
rsm_free_interconnect_topology(rsm_topology_t * topology_ptr)2917 rsm_free_interconnect_topology(rsm_topology_t *topology_ptr)
2918 {
2919
2920 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2921 "rsm_free_interconnect_topology: enter\n"));
2922
2923 if (topology_ptr) {
2924 free((void *)topology_ptr);
2925 }
2926
2927 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2928 "rsm_free_interconnect_topology: exit\n"));
2929 }
2930
2931 int
rsm_create_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,rsm_localmemory_handle_t * local_hndl_p,caddr_t local_vaddr,size_t len)2932 rsm_create_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
2933 rsm_localmemory_handle_t *local_hndl_p,
2934 caddr_t local_vaddr, size_t len)
2935 {
2936 int e;
2937 rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
2938
2939 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2940 "rsm_create_localmemory_handle: enter\n"));
2941
2942 if ((size_t)local_vaddr & (PAGESIZE - 1)) {
2943 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2944 "invalid arguments\n"));
2945 return (RSMERR_BAD_ADDR);
2946 }
2947
2948 if (!cntrl_handle) {
2949 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2950 "invalid controller handle\n"));
2951 return (RSMERR_BAD_CTLR_HNDL);
2952 }
2953 if (!local_hndl_p) {
2954 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2955 "invalid local memory handle pointer\n"));
2956 return (RSMERR_BAD_LOCALMEM_HNDL);
2957 }
2958 if (len == 0) {
2959 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2960 "invalid length\n"));
2961 return (RSMERR_BAD_LENGTH);
2962 }
2963
2964 e = cntrl->cntr_segops->rsm_create_localmemory_handle(
2965 cntrl_handle,
2966 local_hndl_p,
2967 local_vaddr,
2968 len);
2969
2970 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2971 "rsm_create_localmemory_handle: exit\n"));
2972
2973 return (e);
2974 }
2975
2976 int
rsm_free_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,rsm_localmemory_handle_t local_handle)2977 rsm_free_localmemory_handle(rsmapi_controller_handle_t cntrl_handle,
2978 rsm_localmemory_handle_t local_handle)
2979 {
2980 int e;
2981
2982 rsm_controller_t *cntrl = (rsm_controller_t *)cntrl_handle;
2983
2984 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
2985 "rsm_free_localmemory_handle: enter\n"));
2986
2987
2988 if (!cntrl_handle) {
2989 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2990 "invalid controller handle\n"));
2991 return (RSMERR_BAD_CTLR_HNDL);
2992 }
2993
2994 if (!local_handle) {
2995 DBPRINTF((RSM_LIBRARY, RSM_ERR,
2996 "invalid localmemory handle\n"));
2997 return (RSMERR_BAD_LOCALMEM_HNDL);
2998 }
2999
3000 e = cntrl->cntr_segops->rsm_free_localmemory_handle(local_handle);
3001
3002 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3003 "rsm_free_localmemory_handle: exit\n"));
3004
3005 return (e);
3006 }
3007
3008 int
rsm_get_segmentid_range(const char * appid,rsm_memseg_id_t * baseid,uint32_t * length)3009 rsm_get_segmentid_range(const char *appid, rsm_memseg_id_t *baseid,
3010 uint32_t *length)
3011 {
3012 char buf[RSMFILE_BUFSIZE];
3013 char *s;
3014 char *fieldv[4];
3015 int fieldc = 0;
3016 int found = 0;
3017 int err = RSMERR_BAD_APPID;
3018 FILE *fp;
3019
3020 if (appid == NULL || baseid == NULL || length == NULL)
3021 return (RSMERR_BAD_ADDR);
3022
3023 if ((fp = fopen(RSMSEGIDFILE, "rF")) == NULL) {
3024 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3025 "cannot open <%s>\n", RSMSEGIDFILE));
3026 return (RSMERR_BAD_CONF);
3027 }
3028
3029 while (s = fgets(buf, RSMFILE_BUFSIZE, fp)) {
3030 fieldc = 0;
3031 while (isspace(*s)) /* skip the leading spaces */
3032 s++;
3033
3034 if (*s == '#') { /* comment line - skip it */
3035 continue;
3036 }
3037
3038 /*
3039 * parse the reserved segid file and
3040 * set the pointers appropriately.
3041 * fieldv[0] : keyword
3042 * fieldv[1] : application identifier
3043 * fieldv[2] : baseid
3044 * fieldv[3] : length
3045 */
3046 while ((*s != '\n') && (*s != '\0') && (fieldc < 4)) {
3047
3048 while (isspace(*s)) /* skip the leading spaces */
3049 s++;
3050
3051 fieldv[fieldc++] = s;
3052
3053 if (fieldc == 4) {
3054 if (fieldv[3][strlen(fieldv[3])-1] == '\n')
3055 fieldv[3][strlen(fieldv[3])-1] = '\0';
3056 break;
3057 }
3058
3059 while (*s && !isspace(*s))
3060 ++s; /* move to the next white space */
3061
3062 if (*s)
3063 *s++ = '\0';
3064 }
3065
3066 if (fieldc < 4) { /* some fields are missing */
3067 err = RSMERR_BAD_CONF;
3068 break;
3069 }
3070
3071 if (strcasecmp(fieldv[1], appid) == 0) { /* found a match */
3072 if (strcasecmp(fieldv[0], RSMSEG_RESERVED) == 0) {
3073 errno = 0;
3074 *baseid = strtol(fieldv[2], (char **)NULL, 16);
3075 if (errno != 0) {
3076 err = RSMERR_BAD_CONF;
3077 break;
3078 }
3079
3080 errno = 0;
3081 *length = (int)strtol(fieldv[3],
3082 (char **)NULL, 10);
3083 if (errno != 0) {
3084 err = RSMERR_BAD_CONF;
3085 break;
3086 }
3087
3088 found = 1;
3089 } else { /* error in format */
3090 err = RSMERR_BAD_CONF;
3091 }
3092 break;
3093 }
3094 }
3095
3096 (void) fclose(fp);
3097
3098 if (found)
3099 return (RSM_SUCCESS);
3100
3101 return (err);
3102 }
3103
3104 static int
_rsm_get_hwaddr(rsmapi_controller_handle_t handle,rsm_node_id_t nodeid,rsm_addr_t * hwaddrp)3105 _rsm_get_hwaddr(rsmapi_controller_handle_t handle, rsm_node_id_t nodeid,
3106 rsm_addr_t *hwaddrp)
3107 {
3108 rsm_ioctlmsg_t msg = {0};
3109 rsm_controller_t *ctrlp;
3110
3111 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3112 "_rsm_get_hwaddr: enter\n"));
3113
3114 ctrlp = (rsm_controller_t *)handle;
3115
3116 if (ctrlp == NULL) {
3117 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3118 "invalid controller handle\n"));
3119 return (RSMERR_BAD_CTLR_HNDL);
3120 }
3121
3122 msg.cname = ctrlp->cntr_name;
3123 msg.cname_len = strlen(ctrlp->cntr_name) +1;
3124 msg.cnum = ctrlp->cntr_unit;
3125 msg.nodeid = nodeid;
3126
3127 if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_ADDR, &msg) < 0) {
3128 int error = errno;
3129 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3130 "RSM_IOCTL_MAP_TO_ADDR failed\n"));
3131 return (error);
3132 }
3133
3134 *hwaddrp = msg.hwaddr;
3135
3136 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3137 "_rsm_get_hwaddr: exit\n"));
3138
3139 return (RSM_SUCCESS);
3140
3141 }
3142
3143 static int
_rsm_get_nodeid(rsmapi_controller_handle_t handle,rsm_addr_t hwaddr,rsm_node_id_t * nodeidp)3144 _rsm_get_nodeid(rsmapi_controller_handle_t handle, rsm_addr_t hwaddr,
3145 rsm_node_id_t *nodeidp)
3146 {
3147
3148 rsm_ioctlmsg_t msg = {0};
3149 rsm_controller_t *ctrlp;
3150
3151 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3152 "_rsm_get_nodeid: enter\n"));
3153
3154 ctrlp = (rsm_controller_t *)handle;
3155
3156 if (ctrlp == NULL) {
3157 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3158 "invalid arguments\n"));
3159 return (RSMERR_BAD_CTLR_HNDL);
3160 }
3161
3162 msg.cname = ctrlp->cntr_name;
3163 msg.cname_len = strlen(ctrlp->cntr_name) +1;
3164 msg.cnum = ctrlp->cntr_unit;
3165 msg.hwaddr = hwaddr;
3166
3167 if (ioctl(_rsm_fd, RSM_IOCTL_MAP_TO_NODEID, &msg) < 0) {
3168 int error = errno;
3169 DBPRINTF((RSM_LIBRARY, RSM_ERR,
3170 "RSM_IOCTL_MAP_TO_NODEID failed\n"));
3171 return (error);
3172 }
3173
3174 *nodeidp = msg.nodeid;
3175
3176 DBPRINTF((RSM_LIBRARY, RSM_DEBUG_VERBOSE,
3177 "_rsm_get_nodeid: exit\n"));
3178
3179 return (RSM_SUCCESS);
3180
3181 }
3182
3183 #ifdef DEBUG
3184 void
dbg_printf(int msg_category,int msg_level,char * fmt,...)3185 dbg_printf(int msg_category, int msg_level, char *fmt, ...)
3186 {
3187 if ((msg_category & rsmlibdbg_category) &&
3188 (msg_level <= rsmlibdbg_level)) {
3189 va_list arg_list;
3190 va_start(arg_list, fmt);
3191 mutex_lock(&rsmlog_lock);
3192 fprintf(rsmlog_fd, "Thread %d ", thr_self());
3193 vfprintf(rsmlog_fd, fmt, arg_list);
3194 fflush(rsmlog_fd);
3195 mutex_unlock(&rsmlog_lock);
3196 va_end(arg_list);
3197 }
3198 }
3199 #endif /* DEBUG */
3200