1 /*
2 * @file syslink_main.c
3 *
4 * @brief ipc main
5 *
6 *
7 * @ver 02.00.00.46_alpha1
8 *
9 * ============================================================================
10 *
11 * Copyright (c) 2011-2015, Texas Instruments Incorporated
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * * Neither the name of Texas Instruments Incorporated nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
35 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * Contact information for paper mail:
40 * Texas Instruments
41 * Post Office Box 655303
42 * Dallas, Texas 75265
43 * Contact information:
44 * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
45 * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
46 * ============================================================================
47 *
48 */
50 #include "proto.h"
52 #include <pthread.h>
53 #include <fcntl.h>
54 #include <stdint.h>
55 #include <sys/procmgr.h>
56 #include <sys/neutrino.h>
57 #include <sys/siginfo.h>
58 #include <signal.h>
59 #include <stdbool.h>
61 #include <IpcKnl.h>
63 /* OSAL & Utils headers */
64 #include <ti/syslink/utils/List.h>
65 #include <ti/syslink/utils/MemoryOS.h>
66 #include <ti/ipc/MultiProc.h>
67 #include <ti/ipc/NameServer.h>
68 #include <_MultiProc.h>
69 #include <_NameServer.h>
70 #include <_GateMP_daemon.h>
71 #include <OsalSemaphore.h>
72 #include <ti/syslink/utils/OsalPrint.h>
73 #if defined(IPC_PLATFORM_OMAP5430)
74 #include <_ipu_pm.h>
75 #endif
76 #include <ti/syslink/utils/Trace.h>
77 #include <ti/syslink/ProcMgr.h>
78 #include <Bitops.h>
79 #include <RscTable.h>
81 #include <ti-ipc.h>
83 #define DENY_ALL \
84 PROCMGR_ADN_ROOT \
85 | PROCMGR_ADN_NONROOT \
86 | PROCMGR_AOP_DENY \
87 | PROCMGR_AOP_LOCK
90 static int verbosity = 2;
92 /* Disable recovery mechanism if true */
93 static int disableRecovery = false;
94 static char * logFilename = NULL;
96 /* Number of cores to attach to */
97 static int numAttach = 0;
99 #if defined(IPC_PLATFORM_VAYU)
100 /* DSP2 is invalid on Vayu */
101 #define INVALID_PROC "DSP2"
103 static bool gatempEnabled = false;
104 static Int32 sr0OwnerProcId = -1;
105 #else
106 #define INVALID_PROC ""
107 #endif
109 // IPC hibernation global variables
110 Bool ipc_hib_enable = TRUE;
111 #if !defined(IPC_PLATFORM_OMAP5430)
112 #define PM_HIB_DEFAULT_TIME 5000
113 #endif
114 uint32_t ipc_hib_timeout = PM_HIB_DEFAULT_TIME;
115 Bool ipc_hib_hibernating = FALSE;
116 pthread_mutex_t ipc_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
117 pthread_cond_t ipc_hib_cond = PTHREAD_COND_INITIALIZER;
119 extern Int rpmsg_rpc_setup (Void);
120 extern Void rpmsg_rpc_destroy (Void);
121 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
123 typedef struct ipc_firmware_info_t {
124 uint16_t proc_id;
125 char * proc;
126 char * firmware;
127 bool attachOnly;
128 int procState; /* state of processor - index into procStateNames array */
129 int readProcState; /* state that is currently being printed */
130 bool reload; /* reload core during recovery */
131 bool freeString; /* Need to free previously allocated firmware string */
132 } ipc_firmware_info;
133 static ipc_firmware_info ipc_firmware[MultiProc_MAXPROCESSORS];
135 /* Number of valid entries in ipc_firmware array */
136 static unsigned int ipc_num_cores = 0;
138 int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
139 bool recover);
140 int deinit_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
141 bool recover);
142 int init_ipc_trace_device(ipc_dev_t *dev);
143 int deinit_ipc_trace_device(ipc_dev_t *dev);
145 Int ipc_error_cb (UInt16 procId, ProcMgr_Handle handle,
146 ProcMgr_State fromState, ProcMgr_State toState,
147 ProcMgr_EventStatus status, Ptr args);
149 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
151 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
152 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
153 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
154 ProcMgr_State_Error,
155 ProcMgr_State_Watchdog,
156 ProcMgr_State_EndValue};
158 /* Processor states */
159 #define RESET_STATE 0
160 #define RUNNING_STATE 1
162 static String procStateNames[] = { "In reset\n",
163 "Running\n" };
165 typedef struct ipc_trace_info_t {
166 uintptr_t va;
167 uint32_t len;
168 uint32_t * widx;
169 uint32_t * ridx;
170 Bool firstRead;
171 } ipc_trace_info;
173 static ipc_trace_info proc_traces[MultiProc_MAXPROCESSORS];
175 static int runSlave(ipc_dev_t *dev, uint16_t procId,
176 ipc_firmware_info * firmware_info)
177 {
178 int status = 0;
179 ProcMgr_AttachParams attachParams;
181 if (firmware_info->firmware) {
182 rscHandle[procId] = RscTable_alloc(firmware_info->firmware, procId);
183 if (rscHandle[procId] == NULL) {
184 status = -1;
185 return status;
186 }
187 }
189 status = ProcMgr_open(&procH[procId], procId);
190 if (status < 0 || procH[procId] == NULL) {
191 goto procmgropen_fail;
192 }
194 /* Load and start the remote processor. */
195 ProcMgr_getAttachParams(procH[procId], &attachParams);
196 if (firmware_info->attachOnly) {
197 attachParams.bootMode = ProcMgr_BootMode_NoBoot;
198 }
199 status = ProcMgr_attach(procH[procId], &attachParams);
200 if (status < 0) {
201 GT_setFailureReason(curTrace,
202 GT_4CLASS,
203 "runSlave",
204 status,
205 "ProcMgr_attach failed!");
206 goto procmgrattach_fail;
207 }
209 if ((firmware_info->firmware) &&
210 (!firmware_info->attachOnly)) {
211 status = ProcMgr_load(procH[procId],
212 (String)firmware_info->firmware, 0, NULL,
213 NULL, &procH_fileId[procId]);
214 if (status < 0) {
215 GT_setFailureReason(curTrace,
216 GT_4CLASS,
217 "runSlave",
218 status,
219 "ProcMgr_load failed!");
220 goto procmgrload_fail;
221 }
222 }
224 status = Ipc_attach(procId);
225 if (status < 0) {
226 GT_setFailureReason(curTrace,
227 GT_4CLASS,
228 "runSlave",
229 status,
230 "Ipc_attach failed!");
231 goto ipcattach_fail;
232 }
234 status = ProcMgr_registerNotify(procH[procId], ipc_error_cb, (Ptr)dev,
235 -1, errStates);
236 if (status < 0) {
237 goto procmgrreg_fail;
238 }
240 if (!firmware_info->attachOnly) {
241 status = ProcMgr_start(procH[procId], NULL);
242 if (status < 0) {
243 GT_setFailureReason(curTrace,
244 GT_4CLASS,
245 "runSlave",
246 status,
247 "ProcMgr_start failed!");
248 goto procmgrstart_fail;
249 }
250 }
252 Osal_printf("runSlave successful for core %d\n", procId);
254 return 0;
256 procmgrstart_fail:
257 ProcMgr_unregisterNotify(procH[procId], ipc_error_cb,
258 (Ptr)dev, errStates);
259 procmgrreg_fail:
260 Ipc_detach(procId);
261 ipcattach_fail:
262 if ((firmware_info->firmware) &&
263 (!firmware_info->attachOnly)) {
264 ProcMgr_unload(procH[procId], procH_fileId[procId]);
265 }
266 procmgrload_fail:
267 ProcMgr_detach(procH[procId]);
268 procmgrattach_fail:
269 ProcMgr_close(&procH[procId]);
270 procH[procId] = NULL;
271 procmgropen_fail:
272 RscTable_free(&rscHandle[procId]);
274 return -1;
275 }
277 static int resetSlave(ipc_dev_t *dev, uint16_t procId)
278 {
279 if ((procH[procId]) && (procH_fileId[procId])) {
280 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(procId));
281 ProcMgr_stop(procH[procId]);
282 }
284 if (procH[procId]) {
285 ProcMgr_unregisterNotify(procH[procId], ipc_error_cb, (Ptr)dev,
286 errStates);
287 Ipc_detach(procId);
288 if (procH_fileId[procId]) {
289 ProcMgr_unload(procH[procId], procH_fileId[procId]);
290 procH_fileId[procId] = 0;
291 }
292 ProcMgr_detach(procH[procId]);
293 ProcMgr_close(&procH[procId]);
294 procH[procId] = NULL;
295 RscTable_free(&rscHandle[procId]);
296 rscHandle[procId] = NULL;
297 }
299 Osal_printf("resetSlave successful for core %d\n", procId);
301 return 0;
302 }
304 /* Add firmware entry after IPC is setup */
305 static void addFirmware(uint16_t procId)
306 {
307 ipc_firmware[ipc_num_cores].proc =
308 MultiProc_getName(procId);
309 ipc_firmware[ipc_num_cores].proc_id = procId;
310 ipc_firmware[ipc_num_cores].attachOnly = false;
311 ipc_firmware[ipc_num_cores].reload = false;
312 ipc_firmware[ipc_num_cores].procState = RESET_STATE;
313 ipc_firmware[ipc_num_cores].freeString = false;
314 ipc_firmware[ipc_num_cores++].firmware = NULL;
316 return;
317 }
319 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
320 ipc_ocb_t *ocb)
321 {
322 int nbytes;
323 int nparts;
324 int status;
325 int nleft;
326 int i;
327 uint16_t procId = ocb->ocb.attr->procid;
328 ipc_dev_t * dev = ocb->ocb.attr->dev;
330 if ((status = iofunc_read_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
331 return (status);
332 }
334 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
335 return (ENOSYS);
336 }
338 if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
339 fprintf(stderr, "Unsupported core\n");
340 return (EPERM);
341 }
343 pthread_mutex_lock(&dev->firmwareLock);
345 for (i = 0; i < ipc_num_cores; i++) {
346 if (ipc_firmware[i].proc_id == procId) {
347 break;
348 }
349 }
350 if (i == ipc_num_cores) {
351 if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
352 addFirmware(procId);
353 }
354 else {
355 pthread_mutex_unlock(&dev->firmwareLock);
356 return (EBADSLT);
357 }
358 }
360 if (ocb->ocb.offset == 0) {
361 /* latch onto new state, so that we print out complete strings */
362 ipc_firmware[i].readProcState = ipc_firmware[i].procState;
363 }
365 nleft = strlen(procStateNames[ipc_firmware[i].readProcState])
366 - ocb->ocb.offset; /* the state is expressed in one byte */
367 nbytes = min(msg->i.nbytes, nleft);
369 /* Make sure the user has supplied a big enough buffer */
370 if (nbytes > 0) {
371 /* set up the return data IOV */
372 SETIOV(ctp->iov,
373 (char *)procStateNames[ipc_firmware[i].readProcState]
374 + ocb->ocb.offset, nbytes);
376 pthread_mutex_unlock(&dev->firmwareLock);
378 /* set up the number of bytes (returned by client's read()) */
379 _IO_SET_READ_NBYTES(ctp, nbytes);
381 ocb->ocb.offset += nbytes;
383 nparts = 1;
384 }
385 else {
386 pthread_mutex_unlock(&dev->firmwareLock);
388 _IO_SET_READ_NBYTES (ctp, 0);
390 /* reset offset */
391 ocb->ocb.offset = 0;
393 nparts = 0;
394 }
396 /* mark the access time as invalid (we just accessed it) */
398 if (msg->i.nbytes > 0) {
399 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
400 }
402 return (_RESMGR_NPARTS(nparts));
403 }
405 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
406 ipc_ocb_t *ocb)
407 {
408 int status;
409 char * buf;
410 uint16_t procId = ocb->ocb.attr->procid;
411 int i;
412 char * ptr;
413 ipc_dev_t * dev = ocb->ocb.attr->dev;
414 Int32 sr0ProcId;
416 if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
417 return (status);
418 }
420 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
421 return (ENOSYS);
422 }
424 if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
425 fprintf(stderr, "Unsupported core\n");
426 return (EPERM);
427 }
429 /* set up the number of bytes (returned by client's write()) */
430 _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
432 buf = (char *) malloc(msg->i.nbytes + 1);
433 if (buf == NULL) {
434 return (ENOMEM);
435 }
437 /*
438 * Read the data from the sender's message buffer.
439 */
440 resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
441 buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
442 if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
443 *ptr = '\0';
444 }
446 pthread_mutex_lock(&dev->firmwareLock);
447 for (i = 0; i < ipc_num_cores; i++) {
448 if (ipc_firmware[i].proc_id == procId) {
449 break;
450 }
451 }
452 if (i == ipc_num_cores) {
453 if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
454 addFirmware(procId);
455 }
456 else {
457 pthread_mutex_unlock(&dev->firmwareLock);
458 return (EBADSLT);
459 }
460 }
462 if (strcmp("1", buf) == 0) {
463 if ((ipc_firmware[i].procState == RESET_STATE) &&
464 (ipc_firmware[i].firmware != NULL)) {
465 runSlave(ocb->ocb.attr->dev, procId, &ipc_firmware[i]);
466 #if defined(IPC_PLATFORM_VAYU)
467 if (gatempEnabled) {
468 if (sr0OwnerProcId == -1) {
469 /* Set up GateMP */
470 status = GateMP_setup(&sr0ProcId);
471 if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
472 resetSlave(ocb->ocb.attr->dev, procId);
473 pthread_mutex_unlock(&dev->firmwareLock);
474 free(buf);
475 return (EIO);
476 }
477 else if (status == 0) {
478 /* We have discovered an owner for SR0 */
479 sr0OwnerProcId = sr0ProcId;
480 }
481 }
482 else {
483 /*
484 * We have already identified SR0 owner and setup GateMP.
485 * Do nothing.
486 */
487 }
488 }
489 #endif
490 printf("Core is now running with image '%s'\n",
491 ipc_firmware[i].firmware);
492 ipc_firmware[i].procState = RUNNING_STATE;
493 ipc_firmware[i].reload = true;
494 status = init_ipc_trace_device(dev);
495 if (status < 0) {
496 pthread_mutex_unlock(&dev->firmwareLock);
497 free(buf);
498 return (EIO);
499 }
500 printf("Core %s has been started.\n", MultiProc_getName(procId));
501 }
502 }
503 else if (strcmp("0", buf) == 0) {
504 if (ipc_firmware[i].procState == RUNNING_STATE) {
505 #if defined(IPC_PLATFORM_VAYU)
506 if ((gatempEnabled) && (procId == sr0OwnerProcId)) {
507 sr0OwnerProcId = -1;
508 status = GateMP_destroy(FALSE);
509 if (status < 0) {
510 pthread_mutex_unlock(&dev->firmwareLock);
511 free(buf);
512 fprintf(stderr, "Core %s cannot be reset. GateMP may still"
513 " be in use by host\n", MultiProc_getName(procId));
514 return (EIO);
515 }
516 }
517 #endif
518 resetSlave(ocb->ocb.attr->dev, procId);
519 ipc_firmware[i].procState = RESET_STATE;
520 ipc_firmware[i].reload = false;
521 status = deinit_ipc_trace_device(dev);
522 if (status < 0) {
523 pthread_mutex_unlock(&dev->firmwareLock);
524 free(buf);
525 Osal_printf("IPC: deinit_ipc_trace_device failed %d",
526 status);
527 return (EIO);
528 }
529 printf("Core %s has been reset.\n", MultiProc_getName(procId));
530 }
531 }
532 else {
533 /* ignore the input as it is not recognized */
534 fprintf(stderr, "Unrecognized input\n");
535 }
537 pthread_mutex_unlock(&dev->firmwareLock);
539 free(buf);
541 if (msg->i.nbytes > 0) {
542 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
543 }
545 return (_RESMGR_NPARTS(0));
546 }
548 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
549 ipc_ocb_t *ocb)
550 {
551 int nbytes;
552 int nparts;
553 int status;
554 int nleft;
555 int i;
556 uint16_t procId = ocb->ocb.attr->procid;
557 ipc_dev_t * dev = ocb->ocb.attr->dev;
559 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK) {
560 return (status);
561 }
563 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
564 return (ENOSYS);
565 }
567 if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
568 fprintf(stderr, "Unsupported core\n");
569 return (EPERM);
570 }
572 pthread_mutex_lock(&dev->firmwareLock);
573 for (i = 0; i < ipc_num_cores; i++) {
574 if (ipc_firmware[i].proc_id == procId) {
575 break;
576 }
577 }
579 if (i == ipc_num_cores) {
580 if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
581 addFirmware(procId);
582 }
583 else {
584 pthread_mutex_unlock(&dev->firmwareLock);
585 return (EBADSLT);
586 }
587 }
589 if (ipc_firmware[i].firmware == NULL) {
590 nbytes = 0;
591 }
592 else {
593 nleft = strlen(ipc_firmware[i].firmware)
594 - ocb->ocb.offset + 1; /* Add one byte for carriage return */
595 nbytes = min(msg->i.nbytes, nleft);
596 }
598 /* Make sure the user has supplied a big enough buffer */
599 if (nbytes > 0) {
600 if (nbytes == nleft) {
601 /* set up the return data IOV */
602 SETIOV(&ctp->iov[0], (char *)ipc_firmware[i].firmware
603 + ocb->ocb.offset, nbytes - 1);
605 /* add a carriage return */
606 SETIOV(&ctp->iov[1], "\n", 1);
608 nparts = 2;
609 }
610 else {
611 /* set up the return data IOV */
612 SETIOV(ctp->iov, (char *)ipc_firmware[i].firmware
613 + ocb->ocb.offset, nbytes);
615 nparts = 1;
616 }
618 /* set up the number of bytes (returned by client's read()) */
619 _IO_SET_READ_NBYTES(ctp, nbytes);
621 ocb->ocb.offset += nbytes;
622 }
623 else {
624 _IO_SET_READ_NBYTES (ctp, 0);
626 /* reset offset */
627 ocb->ocb.offset = 0;
629 nparts = 0;
630 }
632 pthread_mutex_unlock(&dev->firmwareLock);
634 /* mark the access time as invalid (we just accessed it) */
636 if (msg->i.nbytes > 0) {
637 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
638 }
640 return (_RESMGR_NPARTS(nparts));
641 }
643 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
644 ipc_ocb_t *ocb)
645 {
646 int status;
647 char * buf;
648 uint16_t procId = ocb->ocb.attr->procid;
649 int i;
650 char * absPath;
651 char * ptr;
652 ipc_dev_t * dev = ocb->ocb.attr->dev;
654 if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
655 return (status);
656 }
658 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
659 return (ENOSYS);
660 }
662 if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
663 fprintf(stderr, "Unsupported core\n");
664 return (EPERM);
665 }
667 /* set up the number of bytes (returned by client's write()) */
668 _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
670 buf = (char *) malloc(msg->i.nbytes + 1);
671 if (buf == NULL) {
672 return (ENOMEM);
673 }
675 /*
676 * Read the data from the sender's message buffer.
677 */
678 resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
679 buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
680 if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
681 *ptr = '\0';
682 }
684 /* Get the abs path for all firmware files */
685 absPath = calloc(1, PATH_MAX + 1);
686 if (absPath == NULL) {
687 free(buf);
688 return (ENOMEM);
689 }
690 if (NULL == realpath(buf, absPath)) {
691 fprintf(stderr, "invalid path to executable: %d\n", errno);
692 fprintf(stderr, "make sure you are specifying the full path to the "
693 "file.\n");
694 free(absPath);
695 free(buf);
696 return (ENOENT);
697 }
698 free(buf);
700 pthread_mutex_lock(&dev->firmwareLock);
702 /*
703 * Check if an entry in ipc_firmware already exists for this core.
704 * If not, create one. Otherwise just update the firmware path.
705 */
706 for (i = 0; i < ipc_num_cores; i++) {
707 if (ipc_firmware[i].proc_id == procId) {
708 break;
709 }
710 }
711 if (i == ipc_num_cores) {
712 if (ipc_num_cores < MultiProc_MAXPROCESSORS) {
713 addFirmware(procId);
714 ipc_firmware[ipc_num_cores - 1].freeString = true;
715 ipc_firmware[ipc_num_cores - 1].firmware = absPath;
716 }
717 else {
718 pthread_mutex_unlock(&dev->firmwareLock);
719 free(absPath);
720 return (EBADSLT);
721 }
722 }
723 else {
724 /* Free previously allocated string */
725 if ((ipc_firmware[i].freeString) &&
726 (ipc_firmware[i].firmware)) {
727 free(ipc_firmware[i].firmware);
728 }
729 ipc_firmware[i].firmware = absPath;
730 }
732 pthread_mutex_unlock(&dev->firmwareLock);
734 if (msg->i.nbytes > 0) {
735 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
736 }
738 return (_RESMGR_NPARTS(0));
739 }
741 int ipc_read(resmgr_context_t *ctp, io_read_t *msg, ipc_ocb_t *ocb)
742 {
743 int nbytes;
744 int nparts;
745 int status;
746 int nleft;
747 uint32_t len;
748 uint16_t procid = ocb->ocb.attr->procid;
750 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
751 return (status);
753 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
754 return (ENOSYS);
756 /* check to see where the trace buffer is */
757 if (proc_traces[procid].va == NULL) {
758 return (ENOSYS);
759 }
760 if (ocb->ocb.offset == 0) {
761 ocb->widx = *(proc_traces[procid].widx);
762 ocb->ridx = *(proc_traces[procid].ridx);
763 *(proc_traces[procid].ridx) = ocb->widx;
764 }
766 /* Check for wrap-around */
767 if (ocb->widx < ocb->ridx)
768 len = proc_traces[procid].len - ocb->ridx + ocb->widx;
769 else
770 len = ocb->widx - ocb->ridx;
772 /* Determine the amount left to print */
773 if (ocb->widx >= ocb->ridx)
774 nleft = len - ocb->ocb.offset;
775 else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
776 nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
777 else
778 nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
780 nbytes = min (msg->i.nbytes, nleft);
782 /* Make sure the user has supplied a big enough buffer */
783 if (nbytes > 0) {
784 /* set up the return data IOV */
785 if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
786 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
787 else
788 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
790 /* set up the number of bytes (returned by client's read()) */
791 _IO_SET_READ_NBYTES (ctp, nbytes);
793 ocb->ocb.offset += nbytes;
795 nparts = 1;
796 }
797 else {
798 _IO_SET_READ_NBYTES (ctp, 0);
800 /* reset offset */
801 ocb->ocb.offset = 0;
803 nparts = 0;
804 }
806 /* mark the access time as invalid (we just accessed it) */
808 if (msg->i.nbytes > 0)
809 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
811 return (_RESMGR_NPARTS (nparts));
812 }
814 extern OsalSemaphore_Handle mqcopy_test_sem;
816 int ipc_unblock(resmgr_context_t *ctp, io_pulse_t *msg, ipc_ocb_t *ocb)
817 {
818 int status = _RESMGR_NOREPLY;
819 struct _msg_info info;
821 /*
822 * Try to run the default unblock for this message.
823 */
824 if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
825 return status;
826 }
828 /*
829 * Check if rcvid is still valid and still has an unblock
830 * request pending.
831 */
832 if (MsgInfo(ctp->rcvid, &info) == -1 ||
833 !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
834 return _RESMGR_NOREPLY;
835 }
837 if (mqcopy_test_sem)
838 OsalSemaphore_post(mqcopy_test_sem);
840 return _RESMGR_NOREPLY;
841 }
843 IOFUNC_OCB_T *
844 ipc_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
845 {
846 ipc_ocb_t *ocb = NULL;
848 /* Allocate the OCB */
849 ocb = (ipc_ocb_t *) calloc (1, sizeof (ipc_ocb_t));
850 if (ocb == NULL){
851 errno = ENOMEM;
852 return (NULL);
853 }
855 ocb->pid = ctp->info.pid;
857 return (IOFUNC_OCB_T *)(ocb);
858 }
860 void
861 ipc_ocb_free (IOFUNC_OCB_T * i_ocb)
862 {
863 ipc_ocb_t * ocb = (ipc_ocb_t *)i_ocb;
865 if (ocb) {
866 #ifndef IPC_PLATFORM_VAYU
867 GateHWSpinlock_LeaveLockForPID(ocb->pid);
868 #endif
869 free (ocb);
870 }
871 }
873 int init_slave_devices(ipc_dev_t *dev)
874 {
875 resmgr_attr_t resmgr_attr;
876 int i;
877 ipc_attr_t * slave_attr;
878 int status = 0;
880 memset(&resmgr_attr, 0, sizeof resmgr_attr);
881 resmgr_attr.nparts_max = 2;
882 resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
884 /* Populate the /dev/ipc-state namespace */
885 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
886 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs_state[i],
887 _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_state[i]);
888 slave_attr = &dev->ipc.cattr_slave[i];
889 iofunc_attr_init(&slave_attr->attr,
890 S_IFCHR | 0777, NULL, NULL);
891 slave_attr->attr.mount = &dev->ipc.mattr;
892 slave_attr->procid = i;
893 slave_attr->dev = (Ptr)dev;
894 iofunc_time_update(&slave_attr->attr);
895 snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
896 "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
897 dev->ipc.iofuncs_state[i].read = slave_state_read;
898 dev->ipc.iofuncs_state[i].write = slave_state_write;
900 if (-1 == (dev->ipc.resmgr_id_state[i] =
901 resmgr_attach(dev->dpp, &resmgr_attr,
902 dev->ipc.device_name, _FTYPE_ANY, 0,
903 &dev->ipc.cfuncs_state[i],
904 &dev->ipc.iofuncs_state[i],
905 &slave_attr->attr))) {
906 GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
907 status, "resmgr_attach failed");
908 return (-1);
909 }
910 }
912 /* Populate the /dev/ipc-file namespace */
913 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
914 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs_file[i],
915 _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_file[i]);
916 slave_attr = &dev->ipc.cattr_slave[i];
917 iofunc_attr_init(&slave_attr->attr,
918 S_IFCHR | 0777, NULL, NULL);
919 slave_attr->attr.mount = &dev->ipc.mattr;
920 slave_attr->procid = i;
921 slave_attr->dev = (Ptr)dev;
922 iofunc_time_update(&slave_attr->attr);
923 snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
924 "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
925 dev->ipc.iofuncs_file[i].read = slave_file_read;
926 dev->ipc.iofuncs_file[i].write = slave_file_write;
928 if (-1 == (dev->ipc.resmgr_id_file[i] =
929 resmgr_attach(dev->dpp, &resmgr_attr,
930 dev->ipc.device_name, _FTYPE_ANY, 0,
931 &dev->ipc.cfuncs_file[i],
932 &dev->ipc.iofuncs_file[i],
933 &slave_attr->attr))) {
934 GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
935 status, "resmgr_attach failed");
936 return (-1);
937 }
938 }
940 return (status);
941 }
943 int deinit_slave_devices(ipc_dev_t *dev)
944 {
945 int status = EOK;
946 int i = 0;
948 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
949 status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_state[i], 0);
950 if (status < 0) {
951 Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
952 i, errno);
953 }
954 status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_file[i], 0);
955 if (status < 0) {
956 Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
957 i, errno);
958 }
959 }
961 return (status);
962 }
964 int init_ipc_trace_device(ipc_dev_t *dev)
965 {
966 resmgr_attr_t resmgr_attr;
967 int i;
968 ipc_attr_t * trace_attr;
969 char trace_name[_POSIX_PATH_MAX];
970 int status = 0;
971 unsigned int da = 0, pa = 0;
972 unsigned int len;
974 memset(&resmgr_attr, 0, sizeof resmgr_attr);
975 resmgr_attr.nparts_max = 10;
976 resmgr_attr.msg_max_size = 2048;
978 for (i = 0; i < ipc_num_cores; i++) {
979 /*
980 * Initialize trace device only for cores that are running and their
981 * device is not yet setup.
982 */
983 if ((ipc_firmware[i].procState == RUNNING_STATE) &&
984 (proc_traces[i].va == NULL)) {
985 iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
986 &dev->ipc.cfuncs_trace[i],
987 _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_trace[i]);
988 trace_attr = &dev->ipc.cattr_trace[i];
989 iofunc_attr_init(&trace_attr->attr,
990 S_IFCHR | 0777, NULL, NULL);
991 trace_attr->attr.mount = &dev->ipc.mattr;
992 trace_attr->procid = i;
993 iofunc_time_update(&trace_attr->attr);
994 snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
995 "%s-trace/%s", IPC_DEVICE_PATH,
996 MultiProc_getName(ipc_firmware[i].proc_id));
997 dev->ipc.iofuncs_trace[i].read = ipc_read;
998 snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
999 pa = 0;
1000 status = RscTable_getInfo(ipc_firmware[i].proc_id, TYPE_TRACE,
1001 0, &da, &pa, &len);
1002 if (status == 0) {
1003 /* last 8 bytes are for writeIdx/readIdx */
1004 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
1005 if (da && !pa) {
1006 /* need to translate da->pa */
1007 status = ProcMgr_translateAddr(
1008 procH[ipc_firmware[i].proc_id],
1009 (Ptr *) &pa,
1010 ProcMgr_AddrType_MasterPhys,
1011 (Ptr) da,
1012 ProcMgr_AddrType_SlaveVirt);
1013 }
1014 else {
1015 GT_setFailureReason(curTrace, GT_4CLASS,
1016 "init_ipc_trace_device",
1017 status, "not performing ProcMgr_translate");
1018 }
1019 /* map length aligned to page size */
1020 proc_traces[i].va =
1021 mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
1022 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
1023 proc_traces[i].len);
1024 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
1025 + sizeof(uint32_t));
1026 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
1027 GT_setFailureReason(curTrace, GT_4CLASS,
1028 "init_ipc_trace_device",
1029 status, "mmap_device_io failed");
1030 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
1031 proc_traces[i].va = NULL;
1032 }
1033 proc_traces[i].firstRead = TRUE;
1034 }
1035 else {
1036 GT_setFailureReason(curTrace, GT_4CLASS,
1037 "init_ipc_trace_device",
1038 status, "RscTable_getInfo failed");
1039 proc_traces[i].va = NULL;
1040 }
1041 if (-1 == (dev->ipc.resmgr_id_trace[i] =
1042 resmgr_attach(dev->dpp, &resmgr_attr,
1043 dev->ipc.device_name, _FTYPE_ANY, 0,
1044 &dev->ipc.cfuncs_trace[i],
1045 &dev->ipc.iofuncs_trace[i],
1046 &trace_attr->attr))) {
1047 GT_setFailureReason(curTrace, GT_4CLASS,
1048 "init_ipc_trace_device",
1049 status, "resmgr_attach failed");
1050 return(-1);
1051 }
1052 }
1053 }
1055 return (status);
1056 }
1058 int deinit_ipc_trace_device(ipc_dev_t *dev)
1059 {
1060 int status = EOK;
1061 int i = 0;
1063 for (i = 0; i < ipc_num_cores; i++) {
1064 /* Only disable trace device on cores in RESET state */
1065 if ((ipc_firmware[i].procState == RESET_STATE) &&
1066 (proc_traces[i].va != NULL)) {
1067 status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_trace[i],
1068 0);
1069 if (status < 0) {
1070 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1071 i, errno);
1072 status = errno;
1073 }
1074 if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1075 munmap((void *)proc_traces[i].va,
1076 ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1077 }
1078 proc_traces[i].va = NULL;
1079 }
1080 }
1082 return (status);
1083 }
1085 /* Initialize the ipc device */
1086 int init_ipc_device(ipc_dev_t *dev)
1087 {
1088 iofunc_attr_t * attr;
1089 resmgr_attr_t resmgr_attr;
1090 int status = 0;
1092 pthread_mutex_init(&dev->lock, NULL);
1093 pthread_mutex_init(&dev->firmwareLock, NULL);
1095 memset(&resmgr_attr, 0, sizeof resmgr_attr);
1096 resmgr_attr.nparts_max = 10;
1097 resmgr_attr.msg_max_size = 2048;
1099 memset(&dev->ipc.mattr, 0, sizeof(iofunc_mount_t));
1100 dev->ipc.mattr.flags = ST_NOSUID | ST_NOEXEC;
1101 dev->ipc.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1102 IOFUNC_PC_NO_TRUNC |
1103 IOFUNC_PC_SYNC_IO;
1104 dev->ipc.mattr.funcs = &dev->ipc.mfuncs;
1106 memset(&dev->ipc.mfuncs, 0, sizeof(iofunc_funcs_t));
1107 dev->ipc.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1109 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs,
1110 _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs);
1112 iofunc_attr_init(attr = &dev->ipc.cattr, S_IFCHR | 0777, NULL, NULL);
1114 dev->ipc.mfuncs.ocb_calloc = ipc_ocb_calloc;
1115 dev->ipc.mfuncs.ocb_free = ipc_ocb_free;
1116 dev->ipc.iofuncs.devctl = ipc_devctl;
1117 dev->ipc.iofuncs.unblock = ipc_unblock;
1119 attr->mount = &dev->ipc.mattr;
1120 iofunc_time_update(attr);
1122 if (-1 == (dev->ipc.resmgr_id =
1123 resmgr_attach(dev->dpp, &resmgr_attr,
1124 IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1125 &dev->ipc.cfuncs,
1126 &dev->ipc.iofuncs, attr))) {
1127 return(-1);
1128 }
1130 status = init_slave_devices(dev);
1131 if (status < 0) {
1132 return status;
1133 }
1135 status = init_ipc_trace_device(dev);
1136 if (status < 0) {
1137 return status;
1138 }
1140 return(0);
1141 }
1143 /* De-initialize the ipc device */
1144 int deinit_ipc_device(ipc_dev_t *dev)
1145 {
1146 int status = EOK;
1148 status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id, 0);
1149 if (status < 0) {
1150 Osal_printf("IPC: resmgr_detach of %s failed: %d",
1151 IPC_DEVICE_PATH, errno);
1152 status = errno;
1153 }
1155 status = deinit_ipc_trace_device(dev);
1156 if (status < 0) {
1157 Osal_printf("IPC: deinit_ipc_trace_device failed %d", status);
1158 }
1160 status = deinit_slave_devices(dev);
1161 if (status < 0) {
1162 Osal_printf("IPC: deinit_slave_devices failed %d", status);
1163 }
1165 return(status);
1166 }
1169 /* Initialize the devices */
1170 int init_devices(ipc_dev_t *dev)
1171 {
1172 if (init_ipc_device(dev) < 0) {
1173 Osal_printf("IPC: device init failed");
1174 return(-1);
1175 }
1177 return(0);
1178 }
1181 /* De-initialize the devices */
1182 int deinit_devices(ipc_dev_t *dev)
1183 {
1184 int status = EOK;
1186 if ((status = deinit_ipc_device(dev)) < 0) {
1187 fprintf( stderr, "IPC: device de-init failed %d\n", status);
1188 status = errno;
1189 }
1191 return(status);
1192 }
1194 static void ipc_recover(Ptr args)
1195 {
1196 ipc_dev_t * dev = (ipc_dev_t *)args;
1198 if (!disableRecovery) {
1199 /* Protect the ipc_firmware array as we recover */
1200 pthread_mutex_lock(&dev->firmwareLock);
1201 deinit_ipc(dev, ipc_firmware, TRUE);
1202 deinit_ipc_trace_device(dev);
1203 init_ipc(dev, ipc_firmware, TRUE);
1204 init_ipc_trace_device(dev);
1205 pthread_mutex_unlock(&dev->firmwareLock);
1206 }
1207 else {
1208 GT_0trace(curTrace, GT_4CLASS,
1209 "ipc_recover: Recovery disabled.\n");
1210 }
1211 }
1213 Int ipc_error_cb (UInt16 procId, ProcMgr_Handle handle,
1214 ProcMgr_State fromState, ProcMgr_State toState,
1215 ProcMgr_EventStatus status, Ptr args)
1216 {
1217 Int ret = 0;
1218 String errString = NULL;
1219 ipc_dev_t * dev = (ipc_dev_t *)args;
1221 if (status == ProcMgr_EventStatus_Event) {
1222 switch (toState) {
1223 case ProcMgr_State_Mmu_Fault:
1224 errString = "MMU Fault";
1225 break;
1226 case ProcMgr_State_Error:
1227 errString = "Exception";
1228 break;
1229 case ProcMgr_State_Watchdog:
1230 errString = "Watchdog";
1231 break;
1232 default:
1233 errString = "Unexpected State";
1234 ret = -1;
1235 break;
1236 }
1237 GT_2trace (curTrace, GT_4CLASS,
1238 "ipc_error_cb: Received Error Callback for %s : %s\n",
1239 MultiProc_getName(procId), errString);
1240 /* Don't allow re-schedule of recovery until complete */
1241 pthread_mutex_lock(&dev->lock);
1242 if (ret != -1 && dev->recover == FALSE) {
1243 /* Schedule recovery. */
1244 dev->recover = TRUE;
1245 /* Activate a thread to handle the recovery. */
1246 GT_0trace (curTrace, GT_4CLASS,
1247 "ipc_error_cb: Scheduling recovery...");
1248 OsalThread_activate(dev->ipc_recovery_work);
1249 }
1250 else {
1251 GT_0trace (curTrace, GT_4CLASS,
1252 "ipc_error_cb: Recovery already scheduled.");
1253 }
1254 pthread_mutex_unlock(&dev->lock);
1255 }
1256 else if (status == ProcMgr_EventStatus_Canceled) {
1257 GT_1trace (curTrace, GT_3CLASS,
1258 "Ipc Error Callback Cancelled for %s",
1259 MultiProc_getName(procId));
1260 }
1261 else {
1262 GT_1trace (curTrace, GT_4CLASS,
1263 "Ipc Error Callback Unexpected Event for %s",
1264 MultiProc_getName(procId));
1265 }
1267 return ret;
1268 }
1270 /*
1271 * Initialize ipc
1272 *
1273 * This function sets up the "kernel"-side IPC modules, and does any special
1274 * initialization required for QNX and the platform being used. This function
1275 * also registers for error notifications and initializes the recovery thread.
1276 */
1277 int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware, bool recover)
1278 {
1279 int status = 0;
1280 Ipc_Config iCfg;
1281 OsalThread_Params threadParams;
1282 UInt16 procId;
1283 int i;
1285 if (status >= 0) {
1286 if (!recover) {
1287 /* Set up the MemoryOS module */
1288 status = MemoryOS_setup();
1289 if (status < 0)
1290 goto memoryos_fail;
1291 }
1293 /* Setup IPC and platform-specific items */
1294 status = Ipc_setup (&iCfg);
1295 if (status < 0)
1296 goto ipcsetup_fail;
1298 /* NOTE: this is for handling the procmgr event notifications to userspace list */
1299 if (!recover) {
1300 /* Setup Fault recovery items. */
1301 /* Create the thread object used for the interrupt handler. */
1302 threadParams.priority = OsalThread_Priority_Medium;
1303 threadParams.priorityType = OsalThread_PriorityType_Generic;
1304 threadParams.once = FALSE;
1305 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1306 ipc_recover,
1307 dev,
1308 &threadParams);
1309 if (dev->ipc_recovery_work == NULL)
1310 goto osalthreadcreate_fail;
1311 }
1312 else {
1313 pthread_mutex_lock(&dev->lock);
1314 dev->recover = FALSE;
1315 pthread_mutex_unlock(&dev->lock);
1316 }
1318 memset(procH_fileId, 0, sizeof(procH_fileId));
1320 for (i = 0; i < ipc_num_cores; i++) {
1321 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1322 if (procId >= MultiProc_MAXPROCESSORS) {
1323 status = -1;
1324 fprintf(stderr, "Invalid processor name specified\n");
1325 break;
1326 }
1328 if (procH[procId]) {
1329 GT_setFailureReason (curTrace,
1330 GT_4CLASS,
1331 "init_ipc",
1332 status,
1333 "invalid proc!");
1334 break;
1335 }
1337 if (recover) {
1338 /*
1339 * if we are in recovery, we load the cores we previously
1340 * attached to
1341 */
1342 firmware[i].attachOnly = false;
1343 }
1345 if ((!recover) || (firmware[i].reload)) {
1346 status = runSlave(dev, procId, &firmware[i]);
1347 if (status == 0) {
1348 firmware[i].procState = RUNNING_STATE;
1349 continue;
1350 }
1351 else {
1352 break;
1353 }
1354 }
1355 else {
1356 /*
1357 * During recovery, do not run cores unless they were previously
1358 * running
1359 */
1360 continue;
1361 }
1362 }
1364 if (status < 0)
1365 goto tiipcsetup_fail;
1367 /* Set up rpmsg_mq */
1368 status = ti_ipc_setup();
1369 if (status < 0)
1370 goto tiipcsetup_fail;
1372 /* Set up rpmsg_rpc */
1373 status = rpmsg_rpc_setup();
1374 if (status < 0)
1375 goto rpcsetup_fail;
1377 #if defined(IPC_PLATFORM_VAYU)
1378 if (gatempEnabled) {
1379 Int32 sr0ProcId;
1381 /* Set up NameServer for resource manager process */
1382 status = NameServer_setup();
1383 if (status < 0) {
1384 goto nameserversetup_fail;
1385 }
1387 /* Set up GateMP */
1388 status = GateMP_setup(&sr0ProcId);
1389 if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1390 goto gatempsetup_fail;
1391 }
1392 else if (status == 0) {
1393 sr0OwnerProcId = sr0ProcId;
1394 }
1395 else {
1396 /*
1397 * If we did not find the default gate, perhaps SR0 is
1398 * not yet loaded. This is ok.
1399 */
1400 status = 0;
1401 }
1402 }
1403 #endif
1405 goto exit;
1406 }
1408 #if defined(IPC_PLATFORM_VAYU)
1409 gatempsetup_fail:
1410 NameServer_destroy();
1411 nameserversetup_fail:
1412 rpmsg_rpc_destroy();
1413 #endif
1414 rpcsetup_fail:
1415 ti_ipc_destroy(recover);
1416 tiipcsetup_fail:
1417 for (i-=1; i >= 0; i--) {
1418 procId = firmware[i].proc_id;
1419 if (procId >= MultiProc_MAXPROCESSORS) {
1420 continue;
1421 }
1422 ProcMgr_unregisterNotify(procH[procId], ipc_error_cb,
1423 (Ptr)dev, errStates);
1424 if (!firmware[i].attachOnly) {
1425 ProcMgr_stop(procH[procId]);
1426 if (procH_fileId[procId]) {
1427 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1428 procH_fileId[procId] = 0;
1429 }
1430 }
1431 ProcMgr_detach(procH[procId]);
1432 ProcMgr_close(&procH[procId]);
1433 procH[procId] = NULL;
1434 RscTable_free(&rscHandle[procId]);
1435 rscHandle[procId] = NULL;
1436 }
1437 OsalThread_delete(&dev->ipc_recovery_work);
1438 osalthreadcreate_fail:
1439 Ipc_destroy();
1440 ipcsetup_fail:
1441 MemoryOS_destroy();
1442 memoryos_fail:
1443 exit:
1444 return status;
1445 }
1447 int deinit_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
1448 bool recover)
1449 {
1450 int status = EOK;
1451 uint32_t i = 0, id = 0;
1453 if (logFilename) {
1454 /* wait a little bit for traces to finish dumping */
1455 sleep(1);
1456 }
1458 // Stop the remote cores right away
1459 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1460 if (procH[i]) {
1461 resetSlave(dev, i);
1462 }
1463 }
1465 #if defined(IPC_PLATFORM_VAYU)
1466 if (gatempEnabled) {
1467 GateMP_destroy(TRUE);
1469 NameServer_destroy();
1470 }
1471 #endif
1473 rpmsg_rpc_destroy();
1475 ti_ipc_destroy(recover);
1477 if (!recover && dev->ipc_recovery_work != NULL) {
1478 OsalThread_delete (&dev->ipc_recovery_work);
1479 dev->ipc_recovery_work = NULL;
1480 }
1482 if (recover) {
1483 static FILE *log = NULL;
1484 if (logFilename) {
1485 /* Dump the trace information */
1486 Osal_printf("IPC: printing remote core trace dump");
1487 log = fopen(logFilename, "a+");
1488 if (log) {
1489 for (id = 0; id < ipc_num_cores; id++) {
1490 if (firmware[id].procState == RUNNING_STATE) {
1491 if (proc_traces[id].va) {
1492 /* print traces */
1493 fprintf(log, "*************************************\n");
1494 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
1495 firmware[i].proc_id);
1496 fprintf(log, "*************************************\n");
1497 for (i = (*proc_traces[id].widx + 1);
1498 i < (proc_traces[id].len - 8);
1499 i++) {
1500 fprintf(log, "%c",
1501 *(char *)((uint32_t)proc_traces[id].va + i));
1502 }
1503 for (i = 0; i < *proc_traces[id].widx; i++) {
1504 fprintf(log, "%c",
1505 *(char *)((uint32_t)proc_traces[id].va + i));
1506 }
1507 }
1508 }
1509 }
1510 fflush(log);
1511 fclose(log);
1512 }
1513 else {
1514 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1515 logFilename);
1516 exit(EXIT_FAILURE);
1517 }
1518 }
1519 }
1521 /* After printing trace, set all processor states to RESET */
1522 for (id = 0; id < ipc_num_cores; id++) {
1523 firmware[id].procState = RESET_STATE;
1524 }
1526 status = Ipc_destroy();
1527 if (status < 0) {
1528 printf("Ipc_destroy() failed 0x%x", status);
1529 }
1530 if (!recover) {
1531 status = MemoryOS_destroy();
1532 if (status < 0) {
1533 printf("MemoryOS_destroy() failed 0x%x", status);
1534 }
1535 }
1537 return status;
1538 }
1541 /** print usage */
1542 static Void printUsage (Char * app)
1543 {
1544 printf("\n\nUsage:\n");
1545 #if defined(IPC_PLATFORM_OMAP5430)
1546 printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1547 app);
1548 printf(" <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1549 printf(" followed by the path to the executable to load on that core.\n");
1550 printf("Options:\n");
1551 printf(" -H <arg> enable/disable hibernation, 1: ON, 0: OFF,"
1552 " Default: 1)\n");
1553 printf(" -T <arg> specify the hibernation timeout in ms, Default:"
1554 " 5000 ms)\n");
1555 #else
1556 printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1557 app);
1558 printf(" <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1559 printf(" followed by the path to the executable to load on that core.\n");
1560 printf("Options:\n");
1561 printf(" -g enable GateMP support on host\n");
1562 #endif
1563 printf(" -d disable recovery\n");
1564 printf(" -c <file> generate dump of slave trace during crashes (use\n");
1565 printf(" absolute path for filename)\n");
1566 printf(" -a<n> specify that the first n cores have been pre-loaded\n");
1567 printf(" and started. Perform late-attach to these cores.\n");
1569 exit (EXIT_SUCCESS);
1570 }
1572 dispatch_t * ipc_dpp = NULL;
1574 int main(int argc, char *argv[])
1575 {
1576 ipc_dev_t * dev = NULL;
1577 thread_pool_attr_t tattr;
1578 int status;
1579 int error = EOK;
1580 sigset_t set;
1581 int channelid = 0;
1582 int c;
1583 int hib_enable = 1;
1584 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1585 char *user_parm = NULL;
1586 struct stat sbuf;
1587 int i = 0;
1588 char * abs_path = NULL;
1590 if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1591 printf ("IPC Already Running...\n");
1592 return EXIT_FAILURE;
1593 }
1594 printf ("Starting IPC resource manager...\n");
1596 /* Parse the input args */
1597 while (1)
1598 {
1599 c = getopt (argc, argv, "H:T:U:gc:dv:a:");
1600 if (c == -1)
1601 break;
1603 switch (c)
1604 {
1605 #if defined(IPC_PLATFORM_OMAP5430)
1606 case 'H':
1607 hib_enable = atoi(optarg);
1608 if (hib_enable != 0 && hib_enable != 1) {
1609 hib_enable = -1;
1610 }
1611 break;
1612 case 'T':
1613 hib_timeout = atoi(optarg);
1614 break;
1615 #endif
1616 case 'U':
1617 user_parm = optarg;
1618 break;
1619 case 'd':
1620 disableRecovery = true;
1621 break;
1622 case 'c':
1623 logFilename = optarg;
1624 break;
1625 case 'a':
1626 numAttach = atoi(optarg);
1627 printf("Late-attaching to %d core(s)\n", numAttach);
1628 break;
1629 case 'v':
1630 verbosity++;
1631 break;
1632 #if defined(IPC_PLATFORM_VAYU)
1633 case 'g':
1634 printf("GateMP support enabled on host\n");
1635 gatempEnabled = true;
1636 break;
1637 #endif
1638 default:
1639 fprintf (stderr, "Unrecognized argument\n");
1640 }
1641 }
1643 /* Now parse the operands, which should be in the format:
1644 * "<multiproc_name> <firmware_file> ..*/
1645 for (; optind + 1 < argc; optind+=2) {
1646 if (ipc_num_cores == MultiProc_MAXPROCESSORS) {
1647 printUsage(argv[0]);
1648 return (error);
1649 }
1650 if (strcmp(argv[optind], INVALID_PROC) == 0) {
1651 fprintf (stderr, "Unsupported core specified\n");
1652 return (error);
1653 }
1655 ipc_firmware[ipc_num_cores].proc = argv [optind];
1656 ipc_firmware[ipc_num_cores].attachOnly =
1657 ((numAttach-- > 0) ? true : false);
1658 ipc_firmware[ipc_num_cores].reload = true;
1659 ipc_firmware[ipc_num_cores].freeString = false;
1660 ipc_firmware[ipc_num_cores++].firmware = argv [optind+1];
1661 }
1663 /* Validate hib_enable args */
1664 if (hib_enable == -1) {
1665 fprintf (stderr, "invalid hibernation enable value\n");
1666 printUsage(argv[0]);
1667 return (error);
1668 }
1670 ipc_hib_enable = (Bool)hib_enable;
1671 ipc_hib_timeout = hib_timeout;
1673 /* Init logging for ipc */
1674 if (Osal_initlogging(verbosity) != 0) {
1675 return -1;
1676 }
1678 /* Obtain I/O privity */
1679 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1680 if (error == -1) {
1681 Osal_printf("Unable to obtain I/O privity");
1682 return (error);
1683 }
1685 /* Get the abs path for all firmware files */
1686 for (i = 0; i < ipc_num_cores; i++) {
1687 abs_path = calloc(1, PATH_MAX + 1);
1688 if (abs_path == NULL) {
1689 return -1;
1690 }
1691 if (NULL == realpath(ipc_firmware[i].firmware, abs_path)) {
1692 fprintf (stderr, "invalid path to executable\n");
1693 return -1;
1694 }
1695 ipc_firmware[i].firmware = abs_path;
1696 }
1698 /* allocate the device structure */
1699 if (NULL == (dev = calloc(1, sizeof(ipc_dev_t)))) {
1700 Osal_printf("IPC: calloc() failed");
1701 return (-1);
1702 }
1704 /* create the channel */
1705 if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1706 _NTO_CHF_DISCONNECT |
1707 _NTO_CHF_COID_DISCONNECT |
1708 _NTO_CHF_REPLY_LEN |
1709 _NTO_CHF_SENDER_LEN)) < 0) {
1710 Osal_printf("Unable to create channel %d", channelid);
1711 return (channelid);
1712 }
1714 /* create the dispatch structure */
1715 if (NULL == (dev->dpp = ipc_dpp = dispatch_create_channel (channelid, 0))) {
1716 Osal_printf("IPC: dispatch_create() failed");
1717 return(-1);
1718 }
1720 /*
1721 * Mask out all signals before creating a thread pool.
1722 * This prevents other threads in the thread pool
1723 * from intercepting signals such as SIGTERM.
1724 */
1725 sigfillset(&set);
1726 pthread_sigmask(SIG_BLOCK, &set, NULL);
1728 /* Initialize the thread pool */
1729 memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1730 tattr.handle = dev->dpp;
1731 tattr.context_alloc = dispatch_context_alloc;
1732 tattr.context_free = dispatch_context_free;
1733 tattr.block_func = dispatch_block;
1734 tattr.unblock_func = dispatch_unblock;
1735 tattr.handler_func = dispatch_handler;
1736 tattr.lo_water = 2;
1737 tattr.hi_water = 4;
1738 tattr.increment = 1;
1739 tattr.maximum = 10;
1741 /* Create the thread pool */
1742 if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1743 Osal_printf("IPC: thread pool create failed");
1744 return(-1);
1745 }
1747 /* init ipc */
1748 status = init_ipc(dev, ipc_firmware, FALSE);
1749 if (status < 0) {
1750 Osal_printf("IPC: init failed");
1751 return(-1);
1752 }
1754 /* init the ipc device */
1755 status = init_devices(dev);
1756 if (status < 0) {
1757 Osal_printf("IPC: device init failed");
1758 return(-1);
1759 }
1761 #if (_NTO_VERSION >= 800)
1762 /* Relinquish privileges */
1763 status = procmgr_ability( 0,
1764 DENY_ALL | PROCMGR_AID_SPAWN,
1765 DENY_ALL | PROCMGR_AID_FORK,
1766 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1767 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1768 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1769 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1770 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1771 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1772 (uint64_t)1, (uint64_t)~0,
1773 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1774 (uint64_t)1, (uint64_t)~0,
1775 PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1777 if (status != EOK) {
1778 Osal_printf("procmgr_ability failed! errno=%d", status);
1779 return EXIT_FAILURE;
1780 }
1782 /* Reduce priority to either what defined from command line or at least nobody */
1783 if (user_parm != NULL) {
1784 if (set_ids_from_arg(user_parm) < 0) {
1785 Osal_printf("unable to set uid/gid - %s", strerror(errno));
1786 return EXIT_FAILURE;
1787 }
1788 } else {
1789 if (setuid(99) != 0) {
1790 Osal_printf("unable to set uid - %s", strerror(errno));
1791 return EXIT_FAILURE;
1792 }
1793 }
1794 #endif
1796 /* make this a daemon process */
1797 if (-1 == procmgr_daemon(EXIT_SUCCESS,
1798 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1799 Osal_printf("IPC: procmgr_daemon() failed");
1800 return(-1);
1801 }
1803 /* start the thread pool */
1804 thread_pool_start(dev->tpool);
1806 /* Unmask signals to be caught */
1807 sigdelset (&set, SIGINT);
1808 sigdelset (&set, SIGTERM);
1809 pthread_sigmask (SIG_BLOCK, &set, NULL);
1811 /* Wait for one of these signals */
1812 sigemptyset (&set);
1813 sigaddset (&set, SIGINT);
1814 sigaddset (&set, SIGQUIT);
1815 sigaddset (&set, SIGTERM);
1817 Osal_printf("IPC resource manager started");
1819 /* Wait for a signal */
1820 while (1)
1821 {
1822 switch (SignalWaitinfo (&set, NULL))
1823 {
1824 case SIGTERM:
1825 case SIGQUIT:
1826 case SIGINT:
1827 error = EOK;
1828 goto done;
1830 default:
1831 break;
1832 }
1833 }
1835 error = EOK;
1837 done:
1838 GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1840 error = thread_pool_destroy(dev->tpool);
1841 if (error < 0) {
1842 Osal_printf("IPC: thread_pool_destroy returned an error");
1843 }
1844 deinit_ipc(dev, ipc_firmware, FALSE);
1845 deinit_devices(dev);
1846 free(dev);
1848 /* Free the abs path of firmware files if necessary */
1849 for (i = 0; i < ipc_num_cores; i++) {
1850 if ((ipc_firmware[i].freeString) &&
1851 (ipc_firmware[i].firmware)) {
1852 free(ipc_firmware[i].firmware);
1853 }
1854 }
1856 return (error);
1857 }