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