Add option to provide a valid path to crash dump file in QNX
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / build / Qnx / resmgr / syslink_main.c
1 /*
2  *  @file       syslink_main.c
3  *
4  *  @brief      syslink main
5  *
6  *
7  *  @ver        02.00.00.46_alpha1
8  *
9  *  ============================================================================
10  *
11  *  Copyright (c) 2011-2014, 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(SYSLINK_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 #if defined(SYSLINK_PLATFORM_VAYU)
97 static bool gatempEnabled = false;
98 #endif
100 // Syslink hibernation global variables
101 Bool syslink_hib_enable = TRUE;
102 #if !defined(SYSLINK_PLATFORM_OMAP5430)
103 #define PM_HIB_DEFAULT_TIME 5000
104 #endif
105 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
106 Bool syslink_hib_hibernating = FALSE;
107 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
108 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
110 extern Int rpmsg_rpc_setup (Void);
111 extern Void rpmsg_rpc_destroy (Void);
112 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
114 typedef struct syslink_firmware_info_t {
115     uint16_t proc_id;
116     char * proc;
117     char * firmware;
118 } syslink_firmware_info;
119 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
120 static unsigned int syslink_num_cores = 0;
122 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
123 int deinit_ipc(syslink_dev_t * dev, bool recover);
125 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
127 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
128 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
129 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
130                                     ProcMgr_State_Error,
131                                     ProcMgr_State_Watchdog,
132                                     ProcMgr_State_EndValue};
134 typedef struct syslink_trace_info_t {
135     uintptr_t   va;
136     uint32_t    len;
137     uint32_t *  widx;
138     uint32_t *  ridx;
139     Bool        firstRead;
140 } syslink_trace_info;
142 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
144 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
146     int         nbytes;
147     int         nparts;
148     int         status;
149     int         nleft;
150     uint32_t    len;
151     uint16_t    procid = ocb->ocb.attr->procid;
153     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
154         return (status);
156     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
157         return (ENOSYS);
159     /* check to see where the trace buffer is */
160     if (proc_traces[procid].va == NULL) {
161         return (ENOSYS);
162     }
163     if (ocb->ocb.offset == 0) {
164         ocb->widx = *(proc_traces[procid].widx);
165         ocb->ridx = *(proc_traces[procid].ridx);
166         *(proc_traces[procid].ridx) = ocb->widx;
167     }
169     /* Check for wrap-around */
170     if (ocb->widx < ocb->ridx)
171         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
172     else
173         len = ocb->widx - ocb->ridx;
175     /* Determine the amount left to print */
176     if (ocb->widx >= ocb->ridx)
177         nleft = len - ocb->ocb.offset;
178     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
179         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
180     else
181         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
183     nbytes = min (msg->i.nbytes, nleft);
185     /* Make sure the user has supplied a big enough buffer */
186     if (nbytes > 0) {
187         /* set up the return data IOV */
188         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
189             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
190         else
191             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
193         /* set up the number of bytes (returned by client's read()) */
194         _IO_SET_READ_NBYTES (ctp, nbytes);
196         ocb->ocb.offset += nbytes;
198         nparts = 1;
199     }
200     else {
201         _IO_SET_READ_NBYTES (ctp, 0);
203         /* reset offset */
204         ocb->ocb.offset = 0;
206         nparts = 0;
207     }
209     /* mark the access time as invalid (we just accessed it) */
211     if (msg->i.nbytes > 0)
212         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
214     return (_RESMGR_NPARTS (nparts));
217 extern OsalSemaphore_Handle mqcopy_test_sem;
219 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
221     int status = _RESMGR_NOREPLY;
222     struct _msg_info info;
224     /*
225      * Try to run the default unblock for this message.
226      */
227     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
228         return status;
229     }
231     /*
232      * Check if rcvid is still valid and still has an unblock
233      * request pending.
234      */
235     if (MsgInfo(ctp->rcvid, &info) == -1 ||
236         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
237         return _RESMGR_NOREPLY;
238     }
240     if (mqcopy_test_sem)
241         OsalSemaphore_post(mqcopy_test_sem);
243     return _RESMGR_NOREPLY;
246 IOFUNC_OCB_T *
247 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
249     syslink_ocb_t *ocb = NULL;
251     /* Allocate the OCB */
252     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
253     if (ocb == NULL){
254         errno = ENOMEM;
255         return (NULL);
256     }
258     ocb->pid = ctp->info.pid;
260     return (IOFUNC_OCB_T *)(ocb);
263 void
264 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
266     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
268     if (ocb) {
269 #ifndef SYSLINK_PLATFORM_VAYU
270         GateHWSpinlock_LeaveLockForPID(ocb->pid);
271 #endif
272         free (ocb);
273     }
276 int init_syslink_trace_device(syslink_dev_t *dev)
278     resmgr_attr_t    resmgr_attr;
279     int              i;
280     syslink_attr_t * trace_attr;
281     char             trace_name[_POSIX_PATH_MAX];
282     int              status = 0;
283     unsigned int     da = 0, pa = 0;
284     unsigned int     len;
286     memset(&resmgr_attr, 0, sizeof resmgr_attr);
287     resmgr_attr.nparts_max = 10;
288     resmgr_attr.msg_max_size = 2048;
290     for (i = 0; i < syslink_num_cores; i++) {
291         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
292                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
293         trace_attr = &dev->syslink.cattr_trace[i];
294         iofunc_attr_init(&trace_attr->attr,
295                          S_IFCHR | 0777, NULL, NULL);
296         trace_attr->attr.mount = &dev->syslink.mattr;
297         trace_attr->procid = i;
298         iofunc_time_update(&trace_attr->attr);
299         snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
300                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
301         dev->syslink.iofuncs_trace[i].read = syslink_read;
302         snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
303         pa = 0;
304         status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
305         if (status == 0) {
306             /* last 8 bytes are for writeIdx/readIdx */
307             proc_traces[i].len = len - (sizeof(uint32_t) * 2);
308             if (da && !pa) {
309                 /* need to translate da->pa */
310                 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
311                                                 (Ptr *) &pa,
312                                                 ProcMgr_AddrType_MasterPhys,
313                                                 (Ptr) da,
314                                                 ProcMgr_AddrType_SlaveVirt);
315             }
316             else {
317                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
318                                     status, "not performing ProcMgr_translate");
319             }
320             /* map length aligned to page size */
321             proc_traces[i].va =
322                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
323             proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
324                                                proc_traces[i].len);
325             proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
326                                                sizeof(uint32_t));
327             if (proc_traces[i].va == MAP_DEVICE_FAILED) {
328                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
329                                     status, "mmap_device_io failed");
330                 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
331                 proc_traces[i].va = NULL;
332             }
333             proc_traces[i].firstRead = TRUE;
334         }
335         else {
336             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
337                                 status, "RscTable_getInfo failed");
338             proc_traces[i].va = NULL;
339         }
340         if (-1 == (dev->syslink.resmgr_id_trace[i] =
341                        resmgr_attach(dev->dpp, &resmgr_attr,
342                                      dev->syslink.device_name, _FTYPE_ANY, 0,
343                                      &dev->syslink.cfuncs_trace[i],
344                                      &dev->syslink.iofuncs_trace[i],
345                                      &trace_attr->attr))) {
346             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
347                                 status, "resmgr_attach failed");
348             return(-1);
349         }
350     }
352     return (status);
355 int deinit_syslink_trace_device(syslink_dev_t *dev)
357     int status = EOK;
358     int i = 0;
360     for (i = 0; i < syslink_num_cores; i++) {
361         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
362         if (status < 0) {
363             Osal_printf("IPC: resmgr_detach failed %d", errno);
364             status = errno;
365         }
366         if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
367             munmap((void *)proc_traces[i].va,
368                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
369         }
370         proc_traces[i].va = NULL;
371     }
373     return (status);
376 /* Initialize the syslink device */
377 int init_syslink_device(syslink_dev_t *dev)
379     iofunc_attr_t *  attr;
380     resmgr_attr_t    resmgr_attr;
381     int              status = 0;
383     pthread_mutex_init(&dev->lock, NULL);
385     memset(&resmgr_attr, 0, sizeof resmgr_attr);
386     resmgr_attr.nparts_max = 10;
387     resmgr_attr.msg_max_size = 2048;
389     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
390     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
391     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
392                               IOFUNC_PC_NO_TRUNC |
393                               IOFUNC_PC_SYNC_IO;
394     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
396     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
397     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
399     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
400                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
402     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
404     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
405     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
406     dev->syslink.iofuncs.devctl = syslink_devctl;
407     dev->syslink.iofuncs.unblock = syslink_unblock;
409     attr->mount = &dev->syslink.mattr;
410     iofunc_time_update(attr);
412     if (-1 == (dev->syslink.resmgr_id =
413         resmgr_attach(dev->dpp, &resmgr_attr,
414                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
415                       &dev->syslink.cfuncs,
416                       &dev->syslink.iofuncs, attr))) {
417         return(-1);
418     }
420     status = init_syslink_trace_device(dev);
421     if (status < 0) {
422         return status;
423     }
425     return(0);
428 /* De-initialize the syslink device */
429 int deinit_syslink_device(syslink_dev_t *dev)
431     int status = EOK;
433     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
434     if (status < 0) {
435         Osal_printf("IPC: resmgr_detach failed %d", errno);
436         status = errno;
437     }
439     status = deinit_syslink_trace_device(dev);
441     return(status);
445 /* Initialize the devices */
446 int init_devices(syslink_dev_t *dev)
448     if (init_syslink_device(dev) < 0) {
449         Osal_printf("IPC: device init failed");
450         return(-1);
451     }
453     return(0);
457 /* De-initialize the devices */
458 int deinit_devices(syslink_dev_t *dev)
460     int status = EOK;
462     if ((status = deinit_syslink_device(dev)) < 0) {
463         fprintf( stderr, "IPC: device de-init failed %d\n", status);
464         status = errno;
465     }
467     return(status);
470 static void ipc_recover(Ptr args)
472     syslink_dev_t * dev = (syslink_dev_t *)args;
474     if (!disableRecovery) {
475         deinit_ipc(dev, TRUE);
476         init_ipc(dev, syslink_firmware, TRUE);
477         deinit_syslink_trace_device(dev);
478         init_syslink_trace_device(dev);
479     }
482 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
483                       ProcMgr_State fromState, ProcMgr_State toState,
484                       ProcMgr_EventStatus status, Ptr args)
486     Int ret = 0;
487     String errString = NULL;
488     syslink_dev_t * dev = (syslink_dev_t *)args;
490     if (status == ProcMgr_EventStatus_Event) {
491         switch (toState) {
492             case ProcMgr_State_Mmu_Fault:
493                 errString = "MMU Fault";
494                 break;
495             case ProcMgr_State_Error:
496                 errString = "Exception";
497                 break;
498             case ProcMgr_State_Watchdog:
499                 errString = "Watchdog";
500                 break;
501             default:
502                 errString = "Unexpected State";
503                 ret = -1;
504                 break;
505         }
506         GT_2trace (curTrace, GT_4CLASS,
507                    "syslink_error_cb: Received Error Callback for %s : %s\n",
508                    MultiProc_getName(procId), errString);
509         /* Don't allow re-schedule of recovery until complete */
510         pthread_mutex_lock(&dev->lock);
511         if (ret != -1 && dev->recover == FALSE) {
512             /* Schedule recovery. */
513             dev->recover = TRUE;
514             /* Activate a thread to handle the recovery. */
515             GT_0trace (curTrace, GT_4CLASS,
516                        "syslink_error_cb: Scheduling recovery...");
517             OsalThread_activate(dev->ipc_recovery_work);
518         }
519         else {
520             GT_0trace (curTrace, GT_4CLASS,
521                        "syslink_error_cb: Recovery already scheduled.");
522         }
523         pthread_mutex_unlock(&dev->lock);
524     }
525     else if (status == ProcMgr_EventStatus_Canceled) {
526         GT_1trace (curTrace, GT_3CLASS,
527                    "SysLink Error Callback Cancelled for %s",
528                    MultiProc_getName(procId));
529     }
530     else {
531         GT_1trace (curTrace, GT_4CLASS,
532                    "SysLink Error Callback Unexpected Event for %s",
533                    MultiProc_getName(procId));
534     }
536     return ret;
539 /*
540  * Initialize the syslink ipc
541  *
542  * This function sets up the "kernel"-side IPC modules, and does any special
543  * initialization required for QNX and the platform being used.  This function
544  * also registers for error notifications and initializes the recovery thread.
545  */
546 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
548     int status = 0;
549     Ipc_Config iCfg;
550     OsalThread_Params threadParams;
551     ProcMgr_AttachParams attachParams;
552     UInt16 procId;
553     int i;
555     if (status >= 0) {
556         if (!recover) {
557             /* Set up the MemoryOS module */
558             status = MemoryOS_setup();
559             if (status < 0)
560                 goto memoryos_fail;
561         }
563         /* Setup IPC and platform-specific items */
564         status = Ipc_setup (&iCfg);
565         if (status < 0)
566             goto ipcsetup_fail;
568         /* NOTE: this is for handling the procmgr event notifications to userspace list */
569         if (!recover) {
570             /* Setup Fault recovery items. */
571             /* Create the thread object used for the interrupt handler. */
572             threadParams.priority     = OsalThread_Priority_Medium;
573             threadParams.priorityType = OsalThread_PriorityType_Generic;
574             threadParams.once         = FALSE;
575             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
576                                                         ipc_recover,
577                                                         dev,
578                                                         &threadParams);
579             if (dev->ipc_recovery_work == NULL)
580                 goto osalthreadcreate_fail;
581         }
582         else {
583             pthread_mutex_lock(&dev->lock);
584             dev->recover = FALSE;
585             pthread_mutex_unlock(&dev->lock);
586         }
588         for (i = 0; i < syslink_num_cores; i++) {
589             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
590             if (procId >= MultiProc_MAXPROCESSORS) {
591                 status = -1;
592                 fprintf(stderr, "Invalid processor name specified\n");
593                 break;
594             }
596             if (procH[procId]) {
597                 GT_setFailureReason (curTrace,
598                                      GT_4CLASS,
599                                      "init_ipc",
600                                      status,
601                                      "invalid proc!");
602                 break;
603             }
605             if (syslink_firmware[i].firmware) {
606                 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
607                 if (rscHandle[procId] == NULL) {
608                     status = -1;
609                     break;
610                 }
611             }
613             status = ProcMgr_open(&procH[procId], procId);
614             if (status < 0 || procH[procId] == NULL)
615                 goto procmgropen_fail;
617             /* Load and start the remote processor. */
618             ProcMgr_getAttachParams (procH[procId], &attachParams);
619             status = ProcMgr_attach (procH[procId], &attachParams);
620             if (status < 0) {
621                 GT_setFailureReason (curTrace,
622                                      GT_4CLASS,
623                                      "init_ipc",
624                                      status,
625                                      "ProcMgr_attach failed!");
626                 goto procmgrattach_fail;
627             }
629             if (syslink_firmware[i].firmware) {
630                 status = ProcMgr_load (procH[procId],
631                                        (String)firmware[i].firmware, 0, NULL,
632                                         NULL, &procH_fileId[procId]);
633                 if (status < 0) {
634                     GT_setFailureReason (curTrace,
635                                          GT_4CLASS,
636                                          "init_ipc",
637                                          status,
638                                          "ProcMgr_load failed!");
639                     goto procmgrload_fail;
640                 }
641             }
643             status = Ipc_attach (procId);
644             if (status < 0) {
645                 GT_setFailureReason (curTrace,
646                                      GT_4CLASS,
647                                      "init_ipc",
648                                      status,
649                                      "Ipc_attach failed!");
650                 goto ipcattach_fail;
651             }
653             status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
654                                             -1, errStates);
655             if (status < 0) {
656                 goto procmgrreg_fail;
657             }
659             status = ProcMgr_start(procH[procId], NULL);
660             if (status < 0) {
661                 GT_setFailureReason (curTrace,
662                                      GT_4CLASS,
663                                      "init_ipc",
664                                      status,
665                                      "ProcMgr_start failed!");
666                 goto procmgrstart_fail;
667             }
669             continue;
671 procmgrstart_fail:
672             ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
673                                 (Ptr)dev, errStates);
674 procmgrreg_fail:
675             Ipc_detach(procId);
676 ipcattach_fail:
677             if (syslink_firmware[i].firmware)
678                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
679 procmgrload_fail:
680             ProcMgr_detach(procH[procId]);
681 procmgrattach_fail:
682             ProcMgr_close(&procH[procId]);
683             procH[procId] = NULL;
684 procmgropen_fail:
685             RscTable_free(&rscHandle[procId]);
686             break;
687         }
689         if (status < 0)
690             goto tiipcsetup_fail;
692         /* Set up rpmsg_mq */
693         status = ti_ipc_setup();
694         if (status < 0)
695             goto tiipcsetup_fail;
697         /* Set up rpmsg_rpc */
698         status = rpmsg_rpc_setup();
699         if (status < 0)
700             goto rpcsetup_fail;
702 #if defined(SYSLINK_PLATFORM_VAYU)
703         if (gatempEnabled) {
704             /* Set up NameServer for resource manager process */
705             status = NameServer_setup();
706             if (status < 0) {
707                 goto nameserversetup_fail;
708             }
710             /* Set up GateMP */
711             status = GateMP_setup();
712             if (status < 0) {
713                 goto gatempsetup_fail;
714             }
715         }
716 #endif
718         goto exit;
719     }
721 #if defined(SYSLINK_PLATFORM_VAYU)
722 gatempsetup_fail:
723     NameServer_destroy();
724 nameserversetup_fail:
725     rpmsg_rpc_destroy();
726 #endif
727 rpcsetup_fail:
728     ti_ipc_destroy(recover);
729 tiipcsetup_fail:
730     for (i-=1; i >= 0; i--) {
731         procId = firmware[i].proc_id;
732         if (procId >= MultiProc_MAXPROCESSORS) {
733             continue;
734         }
735         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
736                                 (Ptr)dev, errStates);
737         ProcMgr_stop(procH[procId]);
738         if (procH_fileId[procId]) {
739             ProcMgr_unload(procH[procId], procH_fileId[procId]);
740             procH_fileId[procId] = 0;
741         }
742         ProcMgr_detach(procH[procId]);
743         ProcMgr_close(&procH[procId]);
744         procH[procId] = NULL;
745         RscTable_free(&rscHandle[procId]);
746         rscHandle[procId] = NULL;
747     }
748     OsalThread_delete(&dev->ipc_recovery_work);
749 osalthreadcreate_fail:
750     Ipc_destroy();
751 ipcsetup_fail:
752     MemoryOS_destroy();
753 memoryos_fail:
754 exit:
755     return status;
758 int deinit_ipc(syslink_dev_t * dev, bool recover)
760     int status = EOK;
761     uint32_t i = 0, id = 0;
763     if (logFilename) {
764         /* wait a little bit for traces to finish dumping */
765         sleep(1);
766     }
768     // Stop the remote cores right away
769     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
770         if (procH[i]) {
771             GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
772             ProcMgr_stop(procH[i]);
773         }
774     }
776 #if defined(SYSLINK_PLATFORM_VAYU)
777     if (gatempEnabled) {
778         GateMP_destroy();
780         NameServer_destroy();
781     }
782 #endif
784     rpmsg_rpc_destroy();
786     ti_ipc_destroy(recover);
788     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
789         if (procH[i]) {
790             ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
791                                       errStates);
792             Ipc_detach(i);
793             if (procH_fileId[i]) {
794                 ProcMgr_unload(procH[i], procH_fileId[i]);
795                 procH_fileId[i] = 0;
796             }
797             ProcMgr_detach(procH[i]);
798             ProcMgr_close(&procH[i]);
799             procH[i] = NULL;
800             RscTable_free(&rscHandle[i]);
801             rscHandle[i] = NULL;
802         }
803     }
805     if (!recover && dev->ipc_recovery_work != NULL) {
806         OsalThread_delete (&dev->ipc_recovery_work);
807         dev->ipc_recovery_work = NULL;
808     }
810     if (recover) {
811         static FILE *log = NULL;
812         if (logFilename) {
813             /* Dump the trace information */
814             Osal_printf("IPC: printing remote core trace dump");
815             log = fopen(logFilename, "a+");
816             if (log) {
817                 for (id = 0; id < syslink_num_cores; id++) {
818                     if (proc_traces[id].va) {
819                         /* print traces */
820                         fprintf(log, "*************************************\n");
821                         fprintf(log, "***       CORE%d TRACE DUMP        ***\n",
822                             syslink_firmware[i].proc_id);
823                         fprintf(log, "*************************************\n");
824                         for (i = (*proc_traces[id].widx + 1);
825                             i < (proc_traces[id].len - 8);
826                             i++) {
827                             fprintf(log, "%c",
828                                 *(char *)((uint32_t)proc_traces[id].va + i));
829                         }
830                         for (i = 0; i < *proc_traces[id].widx; i++) {
831                             fprintf(log, "%c",
832                                 *(char *)((uint32_t)proc_traces[id].va + i));
833                         }
834                     }
835                 }
836                 fflush(log);
837                 fclose(log);
838             }
839             else {
840                 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
841                     logFilename);
842                 exit(EXIT_FAILURE);
843             }
844         }
845     }
847     status = Ipc_destroy();
848     if (status < 0) {
849         printf("Ipc_destroy() failed 0x%x", status);
850     }
851     if (!recover) {
852         status = MemoryOS_destroy();
853         if (status < 0) {
854             printf("MemoryOS_destroy() failed 0x%x", status);
855         }
856     }
858     return status;
862 /** print usage */
863 static Void printUsage (Char * app)
865     printf("\n\nUsage:\n");
866 #if defined(SYSLINK_PLATFORM_OMAP5430)
867     printf("\n%s: [-HTdc] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
868         app);
869     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
870     printf("      followed by the path to the executable to load on that core.\n");
871     printf("Options:\n");
872     printf("  -H <arg>    enable/disable hibernation, 1: ON, 0: OFF,"
873         " Default: 1)\n");
874     printf("  -T <arg>    specify the hibernation timeout in ms, Default:"
875         " 5000 ms)\n");
876 #else
877     printf("\n%s: [-gdc] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
878         app);
879     printf("  <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
880     printf("      followed by the path to the executable to load on that core.\n");
881     printf("Options:\n");
882     printf("  -g          enable GateMP support on host\n");
883 #endif
884     printf("  -d          disable recovery\n");
885     printf("  -c <file>   generate dump of slave trace during crashes (use\n");
886     printf("              absolute path for filename)\n");
888     exit (EXIT_SUCCESS);
891 dispatch_t * syslink_dpp = NULL;
893 int main(int argc, char *argv[])
895     syslink_dev_t * dev = NULL;
896     thread_pool_attr_t tattr;
897     int status;
898     int error = 0;
899     sigset_t set;
900     int channelid = 0;
901     int c;
902     int hib_enable = 1;
903     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
904     char *user_parm = NULL;
905     struct stat          sbuf;
906     int i = 0;
907     char * abs_path = NULL;
909     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
910         printf ("IPC Already Running...\n");
911         return EXIT_FAILURE;
912     }
913     printf ("Starting IPC resource manager...\n");
915     /* Parse the input args */
916     while (1)
917     {
918         c = getopt (argc, argv, "H:T:U:gc:dv:");
919         if (c == -1)
920             break;
922         switch (c)
923         {
924 #if defined(SYSLINK_PLATFORM_OMAP5430)
925         case 'H':
926             hib_enable = atoi(optarg);
927             if (hib_enable != 0 && hib_enable != 1) {
928                 hib_enable = -1;
929             }
930             break;
931         case 'T':
932             hib_timeout = atoi(optarg);
933             break;
934 #endif
935         case 'U':
936             user_parm = optarg;
937             break;
938         case 'd':
939             disableRecovery = true;
940             break;
941         case 'c':
942             logFilename = optarg;
943             break;
944         case 'v':
945             verbosity++;
946             break;
947 #if defined(SYSLINK_PLATFORM_VAYU)
948         case 'g':
949             printf("GateMP support enabled on host\n");
950             gatempEnabled = true;
951             break;
952 #endif
953         default:
954             fprintf (stderr, "Unrecognized argument\n");
955         }
956     }
958     /* Now parse the operands, which should be in the format:
959      * "<multiproc_name> <firmware_file> ..*/
960     for (; optind + 1 < argc; optind+=2) {
961         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
962             printUsage(argv[0]);
963             return (error);
964         }
965         syslink_firmware[syslink_num_cores].proc = argv [optind];
966         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
967     }
970     /* Get the name of the binary from the input args */
971     if (!syslink_num_cores) {
972         fprintf(stderr, "At least one core_id and executable must be "\
973             "specified");
974         printUsage(argv[0]);
975         return (error);
976     }
978     /* Validate hib_enable args */
979     if (hib_enable == -1) {
980         fprintf (stderr, "invalid hibernation enable value\n");
981         printUsage(argv[0]);
982         return (error);
983     }
985     syslink_hib_enable = (Bool)hib_enable;
986     syslink_hib_timeout = hib_timeout;
988     /* Init logging for syslink */
989     if (Osal_initlogging(verbosity) != 0) {
990         return -1;
991     }
993     /* Obtain I/O privity */
994     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
995     if (error == -1) {
996         Osal_printf("Unable to obtain I/O privity");
997         return (error);
998     }
1000     /* Get the abs path for all firmware files */
1001     for (i = 0; i < syslink_num_cores; i++) {
1002         abs_path = calloc(1, PATH_MAX + 1);
1003         if (abs_path == NULL) {
1004             return -1;
1005         }
1006         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1007             fprintf (stderr, "invalid path to executable\n");
1008             return -1;
1009         }
1010         syslink_firmware[i].firmware = abs_path;
1011     }
1013     /* allocate the device structure */
1014     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1015         Osal_printf("IPC: calloc() failed");
1016         return (-1);
1017     }
1019     /* create the channel */
1020     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1021                                     _NTO_CHF_DISCONNECT |
1022                                     _NTO_CHF_COID_DISCONNECT |
1023                                     _NTO_CHF_REPLY_LEN |
1024                                     _NTO_CHF_SENDER_LEN)) < 0) {
1025         Osal_printf("Unable to create channel %d", channelid);
1026         return (channelid);
1027     }
1029     /* create the dispatch structure */
1030     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1031         Osal_printf("IPC: dispatch_create() failed");
1032         return(-1);
1033     }
1035     /*
1036      * Mask out all signals before creating a thread pool.
1037      * This prevents other threads in the thread pool
1038      * from intercepting signals such as SIGTERM.
1039      */
1040     sigfillset(&set);
1041     pthread_sigmask(SIG_BLOCK, &set, NULL);
1043     /* Initialize the thread pool */
1044     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1045     tattr.handle = dev->dpp;
1046     tattr.context_alloc = dispatch_context_alloc;
1047     tattr.context_free = dispatch_context_free;
1048     tattr.block_func = dispatch_block;
1049     tattr.unblock_func = dispatch_unblock;
1050     tattr.handler_func = dispatch_handler;
1051     tattr.lo_water = 2;
1052     tattr.hi_water = 4;
1053     tattr.increment = 1;
1054     tattr.maximum = 10;
1056     /* Create the thread pool */
1057     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1058         Osal_printf("IPC: thread pool create failed");
1059         return(-1);
1060     }
1062     /* init syslink */
1063     status = init_ipc(dev, syslink_firmware, FALSE);
1064     if (status < 0) {
1065         Osal_printf("IPC: init failed");
1066         return(-1);
1067     }
1069     /* init the syslink device */
1070     status = init_devices(dev);
1071     if (status < 0) {
1072         Osal_printf("IPC: device init failed");
1073         return(-1);
1074     }
1076 #if (_NTO_VERSION >= 800)
1077     /* Relinquish privileges */
1078     status = procmgr_ability(  0,
1079                  DENY_ALL | PROCMGR_AID_SPAWN,
1080                  DENY_ALL | PROCMGR_AID_FORK,
1081                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1082                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1083                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1084                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1085                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1086                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1087                  (uint64_t)1, (uint64_t)~0,
1088                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1089                  (uint64_t)1, (uint64_t)~0,
1090                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1092     if (status != EOK) {
1093         Osal_printf("procmgr_ability failed! errno=%d", status);
1094         return EXIT_FAILURE;
1095     }
1097     /* Reduce priority to either what defined from command line or at least nobody */
1098     if (user_parm != NULL) {
1099         if (set_ids_from_arg(user_parm) < 0) {
1100             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1101             return EXIT_FAILURE;
1102         }
1103     } else {
1104         if (setuid(99) != 0) {
1105             Osal_printf("unable to set uid - %s", strerror(errno));
1106             return EXIT_FAILURE;
1107         }
1108     }
1109 #endif
1111     /* make this a daemon process */
1112     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1113         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1114         Osal_printf("IPC: procmgr_daemon() failed");
1115         return(-1);
1116     }
1118     /* start the thread pool */
1119     thread_pool_start(dev->tpool);
1121     /* Unmask signals to be caught */
1122     sigdelset (&set, SIGINT);
1123     sigdelset (&set, SIGTERM);
1124     pthread_sigmask (SIG_BLOCK, &set, NULL);
1126     /* Wait for one of these signals */
1127     sigemptyset (&set);
1128     sigaddset (&set, SIGINT);
1129     sigaddset (&set, SIGQUIT);
1130     sigaddset (&set, SIGTERM);
1132     Osal_printf("IPC resource manager started");
1134     /* Wait for a signal */
1135     while (1)
1136     {
1137         switch (SignalWaitinfo (&set, NULL))
1138         {
1139             case SIGTERM:
1140             case SIGQUIT:
1141             case SIGINT:
1142                 error = EOK;
1143                 goto done;
1145             default:
1146                 break;
1147         }
1148     }
1150     error = EOK;
1152 done:
1153     GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1155     error = thread_pool_destroy(dev->tpool);
1156     if (error < 0)
1157         Osal_printf("IPC: thread_pool_destroy returned an error");
1158     deinit_ipc(dev, FALSE);
1159     deinit_devices(dev);
1160     free(dev);
1162     return (EOK);