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