182d1873ec37000fe49ac07875a47329852b52bd
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-2013, 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>
60 #if defined(SYSLINK_PLATFORM_OMAP4430)
61 #include <login.h>
62 #endif
64 #include <IpcKnl.h>
66 /* OSAL & Utils headers */
67 #include <ti/syslink/utils/List.h>
68 #include <ti/syslink/utils/MemoryOS.h>
69 #include <ti/ipc/MultiProc.h>
70 #include <ti/ipc/NameServer.h>
71 #include <_MultiProc.h>
72 #include <_NameServer.h>
73 #include <_GateMP_daemon.h>
74 #include <OsalSemaphore.h>
75 #include <ti/syslink/utils/OsalPrint.h>
76 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
77 #include <_ipu_pm.h>
78 #endif
79 #include <ti/syslink/utils/Trace.h>
80 #include <ti/syslink/ProcMgr.h>
81 #include <Bitops.h>
82 #include <RscTable.h>
84 #include <ti-ipc.h>
86 #define DENY_ALL \
87 PROCMGR_ADN_ROOT \
88 | PROCMGR_ADN_NONROOT \
89 | PROCMGR_AOP_DENY \
90 | PROCMGR_AOP_LOCK
93 static int verbosity = 2;
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_OMAP4430) && !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)
145 {
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));
215 }
217 extern OsalSemaphore_Handle mqcopy_test_sem;
219 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
220 {
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;
244 }
246 IOFUNC_OCB_T *
247 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
248 {
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);
261 }
263 void
264 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
265 {
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 }
274 }
276 int init_syslink_trace_device(syslink_dev_t *dev)
277 {
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);
353 }
355 int deinit_syslink_trace_device(syslink_dev_t *dev)
356 {
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("syslink: 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);
374 }
376 /* Initialize the syslink device */
377 int init_syslink_device(syslink_dev_t *dev)
378 {
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);
426 }
428 /* De-initialize the syslink device */
429 int deinit_syslink_device(syslink_dev_t *dev)
430 {
431 int status = EOK;
433 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
434 if (status < 0) {
435 Osal_printf("syslink: resmgr_detach failed %d", errno);
436 status = errno;
437 }
439 status = deinit_syslink_trace_device(dev);
441 return(status);
442 }
445 /* Initialize the devices */
446 int init_devices(syslink_dev_t *dev)
447 {
448 if (init_syslink_device(dev) < 0) {
449 Osal_printf("syslink: syslink device init failed");
450 return(-1);
451 }
453 return(0);
454 }
457 /* De-initialize the devices */
458 int deinit_devices(syslink_dev_t *dev)
459 {
460 int status = EOK;
462 if ((status = deinit_syslink_device(dev)) < 0) {
463 fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
464 status = errno;
465 }
467 return(status);
468 }
470 static void ipc_recover(Ptr args)
471 {
472 syslink_dev_t * dev = (syslink_dev_t *)args;
474 deinit_ipc(dev, TRUE);
475 init_ipc(dev, syslink_firmware, TRUE);
476 deinit_syslink_trace_device(dev);
477 init_syslink_trace_device(dev);
478 }
480 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
481 ProcMgr_State fromState, ProcMgr_State toState,
482 ProcMgr_EventStatus status, Ptr args)
483 {
484 Int ret = 0;
485 String errString = NULL;
486 syslink_dev_t * dev = (syslink_dev_t *)args;
488 if (status == ProcMgr_EventStatus_Event) {
489 switch (toState) {
490 case ProcMgr_State_Mmu_Fault:
491 errString = "MMU Fault";
492 break;
493 case ProcMgr_State_Error:
494 errString = "Exception";
495 break;
496 case ProcMgr_State_Watchdog:
497 errString = "Watchdog";
498 break;
499 default:
500 errString = "Unexpected State";
501 ret = -1;
502 break;
503 }
504 GT_2trace (curTrace, GT_4CLASS,
505 "syslink_error_cb: Received Error Callback for %s : %s\n",
506 MultiProc_getName(procId), errString);
507 /* Don't allow re-schedule of recovery until complete */
508 pthread_mutex_lock(&dev->lock);
509 if (ret != -1 && dev->recover == FALSE) {
510 /* Schedule recovery. */
511 dev->recover = TRUE;
512 /* Activate a thread to handle the recovery. */
513 GT_0trace (curTrace, GT_4CLASS,
514 "syslink_error_cb: Scheduling recovery...");
515 OsalThread_activate(dev->ipc_recovery_work);
516 }
517 else {
518 GT_0trace (curTrace, GT_4CLASS,
519 "syslink_error_cb: Recovery already scheduled.");
520 }
521 pthread_mutex_unlock(&dev->lock);
522 }
523 else if (status == ProcMgr_EventStatus_Canceled) {
524 GT_1trace (curTrace, GT_3CLASS,
525 "SysLink Error Callback Cancelled for %s",
526 MultiProc_getName(procId));
527 }
528 else {
529 GT_1trace (curTrace, GT_4CLASS,
530 "SysLink Error Callback Unexpected Event for %s",
531 MultiProc_getName(procId));
532 }
534 return ret;
535 }
537 #if defined(SYSLINK_PLATFORM_OMAP4430)
538 #define SYSLINK_CARVEOUT
539 #ifdef SYSLINK_CARVEOUT
540 #define IPU_MEM_SIZE 49 * 1024 * 1024
541 #define IPU_MEM_PHYS 0x97F00000
542 #else
543 #define IPU_MEM_SIZE 104 * 1024 * 1024
544 #define IPU_MEM_ALIGN 0x1000000
545 #endif
546 #endif
549 /*
550 * Initialize the syslink ipc
551 *
552 * This function sets up the "kernel"-side IPC modules, and does any special
553 * initialization required for QNX and the platform being used. This function
554 * also registers for error notifications and initializes the recovery thread.
555 */
556 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
557 {
558 int status = 0;
559 #if defined(SYSLINK_PLATFORM_OMAP4430)
560 int32_t ret = 0;
561 uint32_t len = 0;
562 #ifndef SYSLINK_CARVEOUT
563 int64_t pa = 0;
564 void * da;
565 #endif
566 int64_t paddr = 0;
567 #endif
568 Ipc_Config iCfg;
569 OsalThread_Params threadParams;
570 ProcMgr_AttachParams attachParams;
571 UInt16 procId;
572 int i;
574 #if defined(SYSLINK_PLATFORM_OMAP4430)
575 /* Map a contiguous memory section for ipu - currently hard-coded */
576 if (!recover) {
577 #ifdef SYSLINK_CARVEOUT
578 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
579 PROT_NOCACHE | PROT_READ | PROT_WRITE,
580 MAP_PHYS,
581 NOFD,
582 IPU_MEM_PHYS);
583 #else
584 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
585 PROT_NOCACHE | PROT_READ | PROT_WRITE,
586 MAP_ANON | MAP_PHYS | MAP_SHARED,
587 NOFD,
588 0);
590 #endif
592 if (dev->da_virt == MAP_FAILED) {
593 status = ENOMEM;
594 goto exit;
595 }
596 }
598 if (status >= 0) {
599 #ifdef SYSLINK_CARVEOUT
600 /* Make sure the memory is contiguous */
601 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
602 if (ret)
603 status = ret;
604 else if (len != IPU_MEM_SIZE)
605 status = ENOMEM;
606 #else
607 /* Make sure the memory is contiguous */
608 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
609 &paddr, &len);
610 if (ret)
611 status = ret;
612 else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
613 status = ENOMEM;
614 else {
615 pa = (paddr + IPU_MEM_ALIGN - 1) / IPU_MEM_ALIGN * IPU_MEM_ALIGN;
616 if ((pa - paddr) < 0x900000)
617 pa += 0x900000;
618 else
619 pa -= 0x700000;
620 da = dev->da_virt + (pa - paddr);
621 }
622 #endif
623 if (status != 0)
624 goto memoryos_fail;
625 }
626 #endif
628 if (status >= 0) {
629 if (!recover) {
630 /* Set up the MemoryOS module */
631 status = MemoryOS_setup();
632 if (status < 0)
633 goto memoryos_fail;
634 }
636 /* Setup IPC and platform-specific items */
637 #if defined(SYSLINK_PLATFORM_OMAP4430)
638 #ifdef SYSLINK_CARVEOUT
639 iCfg.vAddr = (uint32_t)dev->da_virt;
640 iCfg.pAddr = (uint32_t)paddr;
641 #else
642 iCfg.vAddr = (uint32_t)da;
643 iCfg.pAddr = (uint32_t)pa;
644 #endif
645 #endif
646 status = Ipc_setup (&iCfg);
647 if (status < 0)
648 goto ipcsetup_fail;
650 /* NOTE: this is for handling the procmgr event notifications to userspace list */
651 if (!recover) {
652 /* Setup Fault recovery items. */
653 /* Create the thread object used for the interrupt handler. */
654 threadParams.priority = OsalThread_Priority_Medium;
655 threadParams.priorityType = OsalThread_PriorityType_Generic;
656 threadParams.once = FALSE;
657 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
658 ipc_recover,
659 dev,
660 &threadParams);
661 if (dev->ipc_recovery_work == NULL)
662 goto osalthreadcreate_fail;
663 }
664 else {
665 pthread_mutex_lock(&dev->lock);
666 dev->recover = FALSE;
667 pthread_mutex_unlock(&dev->lock);
668 }
670 for (i = 0; i < syslink_num_cores; i++) {
671 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
672 if (procId >= MultiProc_MAXPROCESSORS) {
673 status = -1;
674 fprintf(stderr, "Invalid processor name specified\n");
675 break;
676 }
678 if (procH[procId]) {
679 GT_setFailureReason (curTrace,
680 GT_4CLASS,
681 "init_ipc",
682 status,
683 "invalid proc!");
684 break;
685 }
687 if (syslink_firmware[i].firmware) {
688 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
689 if (rscHandle[procId] == NULL) {
690 status = -1;
691 break;
692 }
693 }
695 status = ProcMgr_open(&procH[procId], procId);
696 if (status < 0 || procH[procId] == NULL)
697 goto procmgropen_fail;
699 /* Load and start the remote processor. */
700 ProcMgr_getAttachParams (procH[procId], &attachParams);
701 status = ProcMgr_attach (procH[procId], &attachParams);
702 if (status < 0) {
703 GT_setFailureReason (curTrace,
704 GT_4CLASS,
705 "init_ipc",
706 status,
707 "ProcMgr_attach failed!");
708 goto procmgrattach_fail;
709 }
711 if (syslink_firmware[i].firmware) {
712 status = ProcMgr_load (procH[procId],
713 (String)firmware[i].firmware, 0, NULL,
714 NULL, &procH_fileId[procId]);
715 if (status < 0) {
716 GT_setFailureReason (curTrace,
717 GT_4CLASS,
718 "init_ipc",
719 status,
720 "ProcMgr_load failed!");
721 goto procmgrload_fail;
722 }
723 }
725 status = Ipc_attach (procId);
726 if (status < 0) {
727 GT_setFailureReason (curTrace,
728 GT_4CLASS,
729 "init_ipc",
730 status,
731 "Ipc_attach failed!");
732 goto ipcattach_fail;
733 }
735 status = ProcMgr_start(procH[procId], NULL);
736 if (status < 0) {
737 GT_setFailureReason (curTrace,
738 GT_4CLASS,
739 "init_ipc",
740 status,
741 "ProcMgr_start failed!");
742 goto procmgrstart_fail;
743 }
745 status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
746 -1, errStates);
747 if (status < 0)
748 goto procmgrreg_fail;
750 continue;
752 procmgrreg_fail:
753 ProcMgr_stop(procH[procId]);
754 procmgrstart_fail:
755 Ipc_detach(procId);
756 ipcattach_fail:
757 if (syslink_firmware[i].firmware)
758 ProcMgr_unload(procH[procId], procH_fileId[procId]);
759 procmgrload_fail:
760 ProcMgr_detach(procH[procId]);
761 procmgrattach_fail:
762 ProcMgr_close(&procH[procId]);
763 procH[procId] = NULL;
764 procmgropen_fail:
765 RscTable_free(&rscHandle[procId]);
766 break;
767 }
769 if (status < 0)
770 goto tiipcsetup_fail;
772 /* Set up rpmsg_mq */
773 status = ti_ipc_setup();
774 if (status < 0)
775 goto tiipcsetup_fail;
777 /* Set up rpmsg_rpc */
778 status = rpmsg_rpc_setup();
779 if (status < 0)
780 goto rpcsetup_fail;
782 #if defined(SYSLINK_PLATFORM_VAYU)
783 if (gatempEnabled) {
784 /* Set up NameServer for resource manager process */
785 status = NameServer_setup();
786 if (status < 0) {
787 goto nameserversetup_fail;
788 }
790 /* Set up GateMP */
791 status = GateMP_setup();
792 if (status < 0) {
793 goto gatempsetup_fail;
794 }
795 }
796 #endif
798 goto exit;
799 }
801 #if defined(SYSLINK_PLATFORM_VAYU)
802 gatempsetup_fail:
803 NameServer_destroy();
804 nameserversetup_fail:
805 rpmsg_rpc_destroy();
806 #endif
807 rpcsetup_fail:
808 ti_ipc_destroy(recover);
809 tiipcsetup_fail:
810 for (i-=1; i >= 0; i--) {
811 procId = firmware[i].proc_id;
812 if (procId >= MultiProc_MAXPROCESSORS) {
813 continue;
814 }
815 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
816 (Ptr)dev, errStates);
817 ProcMgr_stop(procH[procId]);
818 if (procH_fileId[procId]) {
819 ProcMgr_unload(procH[procId], procH_fileId[procId]);
820 procH_fileId[procId] = 0;
821 }
822 ProcMgr_detach(procH[procId]);
823 ProcMgr_close(&procH[procId]);
824 procH[procId] = NULL;
825 RscTable_free(&rscHandle[procId]);
826 rscHandle[procId] = NULL;
827 }
828 OsalThread_delete(&dev->ipc_recovery_work);
829 osalthreadcreate_fail:
830 Ipc_destroy();
831 ipcsetup_fail:
832 MemoryOS_destroy();
833 memoryos_fail:
834 #if defined(SYSLINK_PLATFORM_OMAP4430)
835 if (dev->da_virt != MAP_FAILED)
836 #ifdef SYSLINK_CARVEOUT
837 munmap(dev->da_virt, IPU_MEM_SIZE);
838 #else
839 munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
840 #endif
841 #endif
842 exit:
843 return status;
844 }
846 int deinit_ipc(syslink_dev_t * dev, bool recover)
847 {
848 int status = EOK;
849 uint32_t i = 0, id = 0;
851 // Stop the remote cores right away
852 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
853 if (procH[i]) {
854 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
855 ProcMgr_stop(procH[i]);
856 }
857 }
859 #if defined(SYSLINK_PLATFORM_VAYU)
860 if (gatempEnabled) {
861 GateMP_destroy();
863 NameServer_destroy();
864 }
865 #endif
867 rpmsg_rpc_destroy();
869 ti_ipc_destroy(recover);
871 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
872 if (procH[i]) {
873 ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
874 errStates);
875 Ipc_detach(i);
876 if (procH_fileId[i]) {
877 ProcMgr_unload(procH[i], procH_fileId[i]);
878 procH_fileId[i] = 0;
879 }
880 ProcMgr_detach(procH[i]);
881 ProcMgr_close(&procH[i]);
882 procH[i] = NULL;
883 RscTable_free(&rscHandle[i]);
884 rscHandle[i] = NULL;
885 }
886 }
888 if (!recover && dev->ipc_recovery_work != NULL) {
889 OsalThread_delete (&dev->ipc_recovery_work);
890 dev->ipc_recovery_work = NULL;
891 }
893 if (recover) {
894 static FILE *log;
895 /* Dump the trace information */
896 Osal_printf("syslink: printing remote core trace dump to"
897 " /var/log/ducati-m3-traces.log");
898 log = fopen ("/var/log/ducati-m3-traces.log", "a+");
899 if (log) {
900 for (id = 0; id < syslink_num_cores; id++) {
901 if (proc_traces[id].va) {
902 /* print traces */
903 /* wait a little bit for traces to finish dumping */
904 sleep(1);
905 fprintf(log, "****************************************\n");
906 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
907 id);
908 fprintf(log, "****************************************\n");
909 for (i = (*proc_traces[id].widx + 1);
910 i < (proc_traces[id].len - 8);
911 i++) {
912 fprintf(log, "%c",
913 *(char *)((uint32_t)proc_traces[id].va + i));
914 }
915 for (i = 0; i < *proc_traces[id].widx; i++) {
916 fprintf(log, "%c",
917 *(char *)((uint32_t)proc_traces[id].va + i));
918 }
919 }
920 }
921 fclose(log);
922 }
923 else {
924 GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
925 "error opening /var/log/ducati-m3-traces.log");
926 }
927 }
929 status = Ipc_destroy();
930 if (status < 0) {
931 printf("Ipc_destroy() failed 0x%x", status);
932 }
933 if (!recover) {
934 status = MemoryOS_destroy();
935 if (status < 0) {
936 printf("MemoryOS_destroy() failed 0x%x", status);
937 }
938 #if defined(SYSLINK_PLATFORM_OMAP4430)
939 if (dev->da_virt != MAP_FAILED) {
940 #ifdef SYSLINK_CARVEOUT
941 status = munmap(dev->da_virt, IPU_MEM_SIZE);
942 #else
943 status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
944 #endif
945 if (status < 0) {
946 printf("munmap failed %d", errno);
947 }
948 }
949 #endif
950 }
952 return status;
953 }
956 /** print usage */
957 static Void printUsage (Char * app)
958 {
959 printf("\n\nUsage:\n");
960 #if defined(SYSLINK_PLATFORM_OMAP5430)
961 printf("\n%s: [-HT] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
962 app);
963 printf(" <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
964 printf(" followed by the path to the executable to load on that core.\n");
965 printf("Options:\n");
966 printf(" -H enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
967 printf(" -T specify the hibernation timeout in ms, Default: 5000 ms)\n");
968 #else
969 printf("\n%s: [-g] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
970 app);
971 printf(" <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
972 printf(" followed by the path to the executable to load on that core.\n");
973 printf("Options:\n");
974 printf(" -g enable GateMP support on host\n");
975 #endif
976 exit (EXIT_SUCCESS);
977 }
979 dispatch_t * syslink_dpp = NULL;
981 int main(int argc, char *argv[])
982 {
983 syslink_dev_t * dev = NULL;
984 thread_pool_attr_t tattr;
985 int status;
986 int error = 0;
987 sigset_t set;
988 int channelid = 0;
989 int c;
990 int hib_enable = 1;
991 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
992 char *user_parm = NULL;
993 struct stat sbuf;
994 int i = 0;
995 char * abs_path = NULL;
997 if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
998 printf ("Syslink Already Running...\n");
999 return EXIT_FAILURE;
1000 }
1001 printf ("Starting syslink resource manager...\n");
1003 /* Parse the input args */
1004 while (1)
1005 {
1006 c = getopt (argc, argv, "H:T:U:gv:");
1007 if (c == -1)
1008 break;
1010 switch (c)
1011 {
1012 #if defined(SYSLINK_PLATFORM_OMAP5430)
1013 case 'H':
1014 hib_enable = atoi(optarg);
1015 if (hib_enable != 0 && hib_enable != 1) {
1016 hib_enable = -1;
1017 }
1018 break;
1019 case 'T':
1020 hib_timeout = atoi(optarg);
1021 break;
1022 #endif
1023 case 'U':
1024 user_parm = optarg;
1025 break;
1026 case 'v':
1027 verbosity++;
1028 break;
1029 #if defined(SYSLINK_PLATFORM_VAYU)
1030 case 'g':
1031 printf("GateMP support enabled on host\n");
1032 gatempEnabled = true;
1033 break;
1034 #endif
1035 default:
1036 fprintf (stderr, "Unrecognized argument\n");
1037 }
1038 }
1040 /* Now parse the operands, which should be in the format:
1041 * "<multiproc_name> <firmware_file> ..*/
1042 for (; optind + 1 < argc; optind+=2) {
1043 if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1044 printUsage(argv[0]);
1045 return (error);
1046 }
1047 syslink_firmware[syslink_num_cores].proc = argv [optind];
1048 syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1049 }
1052 /* Get the name of the binary from the input args */
1053 if (!syslink_num_cores) {
1054 fprintf(stderr, "At least one core_id and executable must be "\
1055 "specified");
1056 printUsage(argv[0]);
1057 return (error);
1058 }
1060 /* Validate hib_enable args */
1061 if (hib_enable == -1) {
1062 fprintf (stderr, "invalid hibernation enable value\n");
1063 printUsage(argv[0]);
1064 return (error);
1065 }
1067 syslink_hib_enable = (Bool)hib_enable;
1068 syslink_hib_timeout = hib_timeout;
1070 /* Init logging for syslink */
1071 if (Osal_initlogging(verbosity) != 0) {
1072 return -1;
1073 }
1075 /* Obtain I/O privity */
1076 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1077 if (error == -1) {
1078 Osal_printf("Unable to obtain I/O privity");
1079 return (error);
1080 }
1082 /* Get the abs path for all firmware files */
1083 for (i = 0; i < syslink_num_cores; i++) {
1084 abs_path = calloc(1, PATH_MAX + 1);
1085 if (abs_path == NULL) {
1086 return -1;
1087 }
1088 if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1089 fprintf (stderr, "invalid path to executable\n");
1090 return -1;
1091 }
1092 syslink_firmware[i].firmware = abs_path;
1093 }
1095 /* allocate the device structure */
1096 if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1097 Osal_printf("syslink: calloc() failed");
1098 return (-1);
1099 }
1101 /* create the channel */
1102 if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1103 _NTO_CHF_DISCONNECT |
1104 _NTO_CHF_COID_DISCONNECT |
1105 _NTO_CHF_REPLY_LEN |
1106 _NTO_CHF_SENDER_LEN)) < 0) {
1107 Osal_printf("Unable to create channel %d", channelid);
1108 return (channelid);
1109 }
1111 /* create the dispatch structure */
1112 if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1113 Osal_printf("syslink: dispatch_create() failed");
1114 return(-1);
1115 }
1117 /*
1118 * Mask out all signals before creating a thread pool.
1119 * This prevents other threads in the thread pool
1120 * from intercepting signals such as SIGTERM.
1121 */
1122 sigfillset(&set);
1123 pthread_sigmask(SIG_BLOCK, &set, NULL);
1125 /* Initialize the thread pool */
1126 memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1127 tattr.handle = dev->dpp;
1128 tattr.context_alloc = dispatch_context_alloc;
1129 tattr.context_free = dispatch_context_free;
1130 tattr.block_func = dispatch_block;
1131 tattr.unblock_func = dispatch_unblock;
1132 tattr.handler_func = dispatch_handler;
1133 tattr.lo_water = 2;
1134 tattr.hi_water = 4;
1135 tattr.increment = 1;
1136 tattr.maximum = 10;
1138 /* Create the thread pool */
1139 if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1140 Osal_printf("syslink: thread pool create failed");
1141 return(-1);
1142 }
1144 /* init syslink */
1145 status = init_ipc(dev, syslink_firmware, FALSE);
1146 if (status < 0) {
1147 Osal_printf("syslink: IPC init failed");
1148 return(-1);
1149 }
1151 /* init the syslink device */
1152 status = init_devices(dev);
1153 if (status < 0) {
1154 Osal_printf("syslink: device init failed");
1155 return(-1);
1156 }
1158 #if (_NTO_VERSION >= 800)
1159 /* Relinquish privileges */
1160 status = procmgr_ability( 0,
1161 DENY_ALL | PROCMGR_AID_SPAWN,
1162 DENY_ALL | PROCMGR_AID_FORK,
1163 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1164 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1165 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1166 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1167 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1168 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1169 (uint64_t)1, (uint64_t)~0,
1170 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1171 (uint64_t)1, (uint64_t)~0,
1172 PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1174 if (status != EOK) {
1175 Osal_printf("procmgr_ability failed! errno=%d", status);
1176 return EXIT_FAILURE;
1177 }
1179 /* Reduce priority to either what defined from command line or at least nobody */
1180 if (user_parm != NULL) {
1181 if (set_ids_from_arg(user_parm) < 0) {
1182 Osal_printf("unable to set uid/gid - %s", strerror(errno));
1183 return EXIT_FAILURE;
1184 }
1185 } else {
1186 if (setuid(99) != 0) {
1187 Osal_printf("unable to set uid - %s", strerror(errno));
1188 return EXIT_FAILURE;
1189 }
1190 }
1191 #endif
1193 /* make this a daemon process */
1194 if (-1 == procmgr_daemon(EXIT_SUCCESS,
1195 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1196 Osal_printf("syslink: procmgr_daemon() failed");
1197 return(-1);
1198 }
1200 /* start the thread pool */
1201 thread_pool_start(dev->tpool);
1203 /* Unmask signals to be caught */
1204 sigdelset (&set, SIGINT);
1205 sigdelset (&set, SIGTERM);
1206 pthread_sigmask (SIG_BLOCK, &set, NULL);
1208 /* Wait for one of these signals */
1209 sigemptyset (&set);
1210 sigaddset (&set, SIGINT);
1211 sigaddset (&set, SIGQUIT);
1212 sigaddset (&set, SIGTERM);
1214 Osal_printf("Syslink resource manager started");
1216 /* Wait for a signal */
1217 while (1)
1218 {
1219 switch (SignalWaitinfo (&set, NULL))
1220 {
1221 case SIGTERM:
1222 case SIGQUIT:
1223 case SIGINT:
1224 error = EOK;
1225 goto done;
1227 default:
1228 break;
1229 }
1230 }
1232 error = EOK;
1234 done:
1235 GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1237 error = thread_pool_destroy(dev->tpool);
1238 if (error < 0)
1239 Osal_printf("syslink: thread_pool_destroy returned an error");
1240 deinit_ipc(dev, FALSE);
1241 deinit_devices(dev);
1242 free(dev);
1243 return (EOK);
1244 }