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