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 static Int32 sr0OwnerProcId = -1;
102 #endif
104 // Syslink hibernation global variables
105 Bool syslink_hib_enable = TRUE;
106 #if !defined(SYSLINK_PLATFORM_OMAP5430)
107 #define PM_HIB_DEFAULT_TIME 5000
108 #endif
109 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
110 Bool syslink_hib_hibernating = FALSE;
111 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
112 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
114 extern Int rpmsg_rpc_setup (Void);
115 extern Void rpmsg_rpc_destroy (Void);
116 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
118 typedef struct syslink_firmware_info_t {
119 uint16_t proc_id;
120 char * proc;
121 char * firmware;
122 bool attachOnly;
123 int procState; /* state of processor - index into procStateNames array */
124 int readProcState; /* state that is currently being printed */
125 bool reload; /* reload core during recovery */
126 bool freeString; /* Need to free previously allocated firmware string */
127 } syslink_firmware_info;
128 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
130 /* Number of valid entries in syslink_firmware array */
131 static unsigned int syslink_num_cores = 0;
133 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
134 bool recover);
135 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
136 bool recover);
137 int init_syslink_trace_device(syslink_dev_t *dev);
138 int deinit_syslink_trace_device(syslink_dev_t *dev);
140 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
141 ProcMgr_State fromState, ProcMgr_State toState,
142 ProcMgr_EventStatus status, Ptr args);
144 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
146 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
147 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
148 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
149 ProcMgr_State_Error,
150 ProcMgr_State_Watchdog,
151 ProcMgr_State_EndValue};
153 /* Processor states */
154 #define RESET_STATE 0
155 #define RUNNING_STATE 1
157 static String procStateNames[] = { "In reset",
158 "Running" };
160 typedef struct syslink_trace_info_t {
161 uintptr_t va;
162 uint32_t len;
163 uint32_t * widx;
164 uint32_t * ridx;
165 Bool firstRead;
166 } syslink_trace_info;
168 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
170 static int runSlave(syslink_dev_t *dev, uint16_t procId,
171 syslink_firmware_info * firmware_info)
172 {
173 int status = 0;
174 ProcMgr_AttachParams attachParams;
176 if (firmware_info->firmware) {
177 rscHandle[procId] = RscTable_alloc(firmware_info->firmware, procId);
178 if (rscHandle[procId] == NULL) {
179 status = -1;
180 return status;
181 }
182 }
184 status = ProcMgr_open(&procH[procId], procId);
185 if (status < 0 || procH[procId] == NULL) {
186 goto procmgropen_fail;
187 }
189 /* Load and start the remote processor. */
190 ProcMgr_getAttachParams(procH[procId], &attachParams);
191 if (firmware_info->attachOnly) {
192 attachParams.bootMode = ProcMgr_BootMode_NoBoot;
193 }
194 status = ProcMgr_attach(procH[procId], &attachParams);
195 if (status < 0) {
196 GT_setFailureReason(curTrace,
197 GT_4CLASS,
198 "init_ipc",
199 status,
200 "ProcMgr_attach failed!");
201 goto procmgrattach_fail;
202 }
204 if ((firmware_info->firmware) &&
205 (!firmware_info->attachOnly)) {
206 status = ProcMgr_load(procH[procId],
207 (String)firmware_info->firmware, 0, NULL,
208 NULL, &procH_fileId[procId]);
209 if (status < 0) {
210 GT_setFailureReason(curTrace,
211 GT_4CLASS,
212 "init_ipc",
213 status,
214 "ProcMgr_load failed!");
215 goto procmgrload_fail;
216 }
217 }
219 status = Ipc_attach(procId);
220 if (status < 0) {
221 GT_setFailureReason(curTrace,
222 GT_4CLASS,
223 "init_ipc",
224 status,
225 "Ipc_attach failed!");
226 goto ipcattach_fail;
227 }
229 status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
230 -1, errStates);
231 if (status < 0) {
232 goto procmgrreg_fail;
233 }
235 if (!firmware_info->attachOnly) {
236 status = ProcMgr_start(procH[procId], NULL);
237 if (status < 0) {
238 GT_setFailureReason(curTrace,
239 GT_4CLASS,
240 "init_ipc",
241 status,
242 "ProcMgr_start failed!");
243 goto procmgrstart_fail;
244 }
245 }
247 Osal_printf("runSlave successful for core %d\n", procId);
249 return 0;
251 procmgrstart_fail:
252 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
253 (Ptr)dev, errStates);
254 procmgrreg_fail:
255 Ipc_detach(procId);
256 ipcattach_fail:
257 if ((firmware_info->firmware) &&
258 (!firmware_info->attachOnly)) {
259 ProcMgr_unload(procH[procId], procH_fileId[procId]);
260 }
261 procmgrload_fail:
262 ProcMgr_detach(procH[procId]);
263 procmgrattach_fail:
264 ProcMgr_close(&procH[procId]);
265 procH[procId] = NULL;
266 procmgropen_fail:
267 RscTable_free(&rscHandle[procId]);
269 return -1;
270 }
272 static int resetSlave(syslink_dev_t *dev, uint16_t procId)
273 {
274 if ((procH[procId]) && (procH_fileId[procId])) {
275 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(procId));
276 ProcMgr_stop(procH[procId]);
277 }
279 if (procH[procId]) {
280 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb, (Ptr)dev,
281 errStates);
282 Ipc_detach(procId);
283 if (procH_fileId[procId]) {
284 ProcMgr_unload(procH[procId], procH_fileId[procId]);
285 procH_fileId[procId] = 0;
286 }
287 ProcMgr_detach(procH[procId]);
288 ProcMgr_close(&procH[procId]);
289 procH[procId] = NULL;
290 RscTable_free(&rscHandle[procId]);
291 rscHandle[procId] = NULL;
292 }
294 Osal_printf("resetSlave successful for core %d\n", procId);
296 return 0;
297 }
299 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
300 syslink_ocb_t *ocb)
301 {
302 int nbytes;
303 int nparts;
304 int status;
305 int nleft;
306 int i;
307 uint16_t procid = ocb->ocb.attr->procid;
308 syslink_dev_t * dev = ocb->ocb.attr->dev;
310 if ((status = iofunc_read_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
311 return (status);
312 }
314 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
315 return (ENOSYS);
316 }
318 pthread_mutex_lock(&dev->firmwareLock);
320 for (i = 0; i < syslink_num_cores; i++) {
321 if (syslink_firmware[i].proc_id == procid) {
322 break;
323 }
324 }
325 if (i == syslink_num_cores) {
326 if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
327 syslink_firmware[syslink_num_cores].proc =
328 MultiProc_getName(procid);
329 syslink_firmware[syslink_num_cores].proc_id = procid;
330 syslink_firmware[syslink_num_cores].attachOnly = false;
331 syslink_firmware[syslink_num_cores].reload = false;
332 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
333 syslink_firmware[syslink_num_cores].freeString = false;
334 syslink_firmware[syslink_num_cores++].firmware = NULL;
335 }
336 else {
337 pthread_mutex_unlock(&dev->firmwareLock);
338 return (EBADSLT);
339 }
340 }
342 if (ocb->ocb.offset == 0) {
343 /* latch onto new state, so that we print out complete strings */
344 syslink_firmware[i].readProcState = syslink_firmware[i].procState;
345 }
347 nleft = strlen(procStateNames[syslink_firmware[i].readProcState])
348 - ocb->ocb.offset; /* the state is expressed in one byte */
349 nbytes = min(msg->i.nbytes, nleft);
351 /* Make sure the user has supplied a big enough buffer */
352 if (nbytes > 0) {
353 /* set up the return data IOV */
354 SETIOV(ctp->iov,
355 (char *)procStateNames[syslink_firmware[i].readProcState]
356 + ocb->ocb.offset, nbytes);
358 pthread_mutex_unlock(&dev->firmwareLock);
360 /* set up the number of bytes (returned by client's read()) */
361 _IO_SET_READ_NBYTES(ctp, nbytes);
363 ocb->ocb.offset += nbytes;
365 nparts = 1;
366 }
367 else {
368 pthread_mutex_unlock(&dev->firmwareLock);
370 _IO_SET_READ_NBYTES (ctp, 0);
372 /* reset offset */
373 ocb->ocb.offset = 0;
375 nparts = 0;
376 }
378 /* mark the access time as invalid (we just accessed it) */
380 if (msg->i.nbytes > 0) {
381 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
382 }
384 return (_RESMGR_NPARTS(nparts));
385 }
387 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
388 syslink_ocb_t *ocb)
389 {
390 int status;
391 char * buf;
392 uint16_t procid = ocb->ocb.attr->procid;
393 int i;
394 char * ptr;
395 syslink_dev_t * dev = ocb->ocb.attr->dev;
396 Int32 sr0ProcId;
398 if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
399 return (status);
400 }
402 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
403 return (ENOSYS);
404 }
406 /* set up the number of bytes (returned by client's write()) */
407 _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
409 buf = (char *) malloc(msg->i.nbytes + 1);
410 if (buf == NULL) {
411 return (ENOMEM);
412 }
414 /*
415 * Read the data from the sender's message buffer.
416 */
417 resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
418 buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
419 if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
420 *ptr = '\0';
421 }
423 pthread_mutex_lock(&dev->firmwareLock);
424 for (i = 0; i < syslink_num_cores; i++) {
425 if (syslink_firmware[i].proc_id == procid) {
426 break;
427 }
428 }
429 if (i == syslink_num_cores) {
430 if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
431 syslink_firmware[syslink_num_cores].proc =
432 MultiProc_getName(procid);
433 syslink_firmware[syslink_num_cores].proc_id = procid;
434 syslink_firmware[syslink_num_cores].attachOnly = false;
435 syslink_firmware[syslink_num_cores].reload = false;
436 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
437 syslink_firmware[syslink_num_cores].freeString = false;
438 syslink_firmware[syslink_num_cores++].firmware = NULL;
439 }
440 else {
441 pthread_mutex_unlock(&dev->firmwareLock);
442 return (EBADSLT);
443 }
444 }
446 if (strcmp("1", buf) == 0) {
447 if ((syslink_firmware[i].procState == RESET_STATE) &&
448 (syslink_firmware[i].firmware != NULL)) {
449 runSlave(ocb->ocb.attr->dev, procid, &syslink_firmware[i]);
450 #if defined(SYSLINK_PLATFORM_VAYU)
451 if (gatempEnabled) {
452 if (sr0OwnerProcId == -1) {
453 /* Set up GateMP */
454 status = GateMP_setup(&sr0ProcId);
455 if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
456 resetSlave(ocb->ocb.attr->dev, procid);
457 pthread_mutex_unlock(&dev->firmwareLock);
458 free(buf);
459 return (EIO);
460 }
461 else if (status == 0) {
462 /* We have discovered an owner for SR0 */
463 sr0OwnerProcId = sr0ProcId;
464 }
465 }
466 else {
467 /*
468 * We have already identified SR0 owner and setup GateMP.
469 * Do nothing.
470 */
471 }
472 }
473 #endif
474 printf("Core is now running with image '%s'\n",
475 syslink_firmware[i].firmware);
476 syslink_firmware[i].procState = RUNNING_STATE;
477 syslink_firmware[i].reload = true;
478 status = init_syslink_trace_device(dev);
479 if (status < 0) {
480 pthread_mutex_unlock(&dev->firmwareLock);
481 free(buf);
482 return (EIO);
483 }
484 printf("Core %s has been started.\n", MultiProc_getName(procid));
485 }
486 }
487 else if (strcmp("0", buf) == 0) {
488 if (syslink_firmware[i].procState == RUNNING_STATE) {
489 resetSlave(ocb->ocb.attr->dev, procid);
490 syslink_firmware[i].procState = RESET_STATE;
491 syslink_firmware[i].reload = false;
492 status = deinit_syslink_trace_device(dev);
493 if (status < 0) {
494 pthread_mutex_unlock(&dev->firmwareLock);
495 free(buf);
496 Osal_printf("IPC: deinit_syslink_trace_device failed %d",
497 status);
498 return (EIO);
499 }
500 #if defined(SYSLINK_PLATFORM_VAYU)
501 if ((gatempEnabled) && (procid == sr0OwnerProcId)) {
502 sr0OwnerProcId = -1;
503 GateMP_destroy();
504 }
505 #endif
506 printf("Core %s has been reset.\n", MultiProc_getName(procid));
507 }
508 }
509 else {
510 /* ignore the input as it is not recognized */
511 fprintf(stderr, "Unrecognized input\n");
512 }
514 pthread_mutex_unlock(&dev->firmwareLock);
516 free(buf);
518 if (msg->i.nbytes > 0) {
519 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
520 }
522 return (_RESMGR_NPARTS(0));
523 }
525 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
526 syslink_ocb_t *ocb)
527 {
528 int nbytes;
529 int nparts;
530 int status;
531 int nleft;
532 int i;
533 uint16_t procid = ocb->ocb.attr->procid;
534 syslink_dev_t * dev = ocb->ocb.attr->dev;
536 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK) {
537 return (status);
538 }
540 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
541 return (ENOSYS);
542 }
544 pthread_mutex_lock(&dev->firmwareLock);
545 for (i = 0; i < syslink_num_cores; i++) {
546 if (syslink_firmware[i].proc_id == procid) {
547 break;
548 }
549 }
551 if (i == syslink_num_cores) {
552 if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
553 syslink_firmware[syslink_num_cores].proc =
554 MultiProc_getName(procid);
555 syslink_firmware[syslink_num_cores].proc_id = procid;
556 syslink_firmware[syslink_num_cores].attachOnly = false;
557 syslink_firmware[syslink_num_cores].reload = false;
558 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
559 syslink_firmware[syslink_num_cores].freeString = false;
560 syslink_firmware[syslink_num_cores++].firmware = NULL;
561 }
562 else {
563 pthread_mutex_unlock(&dev->firmwareLock);
564 return (EBADSLT);
565 }
566 }
568 if (syslink_firmware[i].firmware == NULL) {
569 nbytes = 0;
570 }
571 else {
572 nleft = strlen(syslink_firmware[i].firmware)
573 - ocb->ocb.offset; /* the state is expressed in one byte */
574 nbytes = min(msg->i.nbytes, nleft);
575 }
577 /* Make sure the user has supplied a big enough buffer */
578 if (nbytes > 0) {
579 /* set up the return data IOV */
580 SETIOV(ctp->iov, (char *)syslink_firmware[i].firmware
581 + ocb->ocb.offset, nbytes);
583 /* set up the number of bytes (returned by client's read()) */
584 _IO_SET_READ_NBYTES(ctp, nbytes);
586 ocb->ocb.offset += nbytes;
588 nparts = 1;
589 }
590 else {
591 _IO_SET_READ_NBYTES (ctp, 0);
593 /* reset offset */
594 ocb->ocb.offset = 0;
596 nparts = 0;
597 }
599 pthread_mutex_unlock(&dev->firmwareLock);
601 /* mark the access time as invalid (we just accessed it) */
603 if (msg->i.nbytes > 0) {
604 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
605 }
607 return (_RESMGR_NPARTS(nparts));
608 }
610 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
611 syslink_ocb_t *ocb)
612 {
613 int status;
614 char * buf;
615 uint16_t procid = ocb->ocb.attr->procid;
616 int i;
617 char * absPath;
618 char * ptr;
619 syslink_dev_t * dev = ocb->ocb.attr->dev;
621 if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
622 return (status);
623 }
625 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
626 return (ENOSYS);
627 }
629 /* set up the number of bytes (returned by client's write()) */
630 _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
632 buf = (char *) malloc(msg->i.nbytes + 1);
633 if (buf == NULL) {
634 return (ENOMEM);
635 }
637 /*
638 * Read the data from the sender's message buffer.
639 */
640 resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
641 buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
642 if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
643 *ptr = '\0';
644 }
646 /* Get the abs path for all firmware files */
647 absPath = calloc(1, PATH_MAX + 1);
648 if (absPath == NULL) {
649 free(buf);
650 return (ENOMEM);
651 }
652 if (NULL == realpath(buf, absPath)) {
653 fprintf(stderr, "invalid path to executable: %d\n", errno);
654 fprintf(stderr, "make sure you are specifying the full path to the "
655 "file.\n");
656 free(absPath);
657 free(buf);
658 return (ENOENT);
659 }
660 free(buf);
662 pthread_mutex_lock(&dev->firmwareLock);
664 /*
665 * Check if an entry in syslink_firmware already exists for this core.
666 * If not, create one. Otherwise just update the firmware path.
667 */
668 for (i = 0; i < syslink_num_cores; i++) {
669 if (syslink_firmware[i].proc_id == procid) {
670 break;
671 }
672 }
673 if (i == syslink_num_cores) {
674 if (syslink_num_cores < MultiProc_MAXPROCESSORS) {
675 syslink_firmware[syslink_num_cores].proc =
676 MultiProc_getName(procid);
677 syslink_firmware[syslink_num_cores].proc_id = procid;
678 syslink_firmware[syslink_num_cores].attachOnly = false;
679 syslink_firmware[syslink_num_cores].reload = false;
680 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
681 syslink_firmware[syslink_num_cores].freeString = true;
682 syslink_firmware[syslink_num_cores++].firmware = absPath;
683 }
684 else {
685 pthread_mutex_unlock(&dev->firmwareLock);
686 free(absPath);
687 return (EBADSLT);
688 }
689 }
690 else {
691 /* Free previously allocated string */
692 if ((syslink_firmware[syslink_num_cores].freeString) &&
693 (syslink_firmware[syslink_num_cores].firmware)) {
694 free(syslink_firmware[i].firmware);
695 }
696 syslink_firmware[i].firmware = absPath;
697 }
699 pthread_mutex_unlock(&dev->firmwareLock);
701 if (msg->i.nbytes > 0) {
702 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
703 }
705 return (_RESMGR_NPARTS(0));
706 }
708 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
709 {
710 int nbytes;
711 int nparts;
712 int status;
713 int nleft;
714 uint32_t len;
715 uint16_t procid = ocb->ocb.attr->procid;
717 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
718 return (status);
720 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
721 return (ENOSYS);
723 /* check to see where the trace buffer is */
724 if (proc_traces[procid].va == NULL) {
725 return (ENOSYS);
726 }
727 if (ocb->ocb.offset == 0) {
728 ocb->widx = *(proc_traces[procid].widx);
729 ocb->ridx = *(proc_traces[procid].ridx);
730 *(proc_traces[procid].ridx) = ocb->widx;
731 }
733 /* Check for wrap-around */
734 if (ocb->widx < ocb->ridx)
735 len = proc_traces[procid].len - ocb->ridx + ocb->widx;
736 else
737 len = ocb->widx - ocb->ridx;
739 /* Determine the amount left to print */
740 if (ocb->widx >= ocb->ridx)
741 nleft = len - ocb->ocb.offset;
742 else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
743 nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
744 else
745 nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
747 nbytes = min (msg->i.nbytes, nleft);
749 /* Make sure the user has supplied a big enough buffer */
750 if (nbytes > 0) {
751 /* set up the return data IOV */
752 if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
753 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
754 else
755 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
757 /* set up the number of bytes (returned by client's read()) */
758 _IO_SET_READ_NBYTES (ctp, nbytes);
760 ocb->ocb.offset += nbytes;
762 nparts = 1;
763 }
764 else {
765 _IO_SET_READ_NBYTES (ctp, 0);
767 /* reset offset */
768 ocb->ocb.offset = 0;
770 nparts = 0;
771 }
773 /* mark the access time as invalid (we just accessed it) */
775 if (msg->i.nbytes > 0)
776 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
778 return (_RESMGR_NPARTS (nparts));
779 }
781 extern OsalSemaphore_Handle mqcopy_test_sem;
783 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
784 {
785 int status = _RESMGR_NOREPLY;
786 struct _msg_info info;
788 /*
789 * Try to run the default unblock for this message.
790 */
791 if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
792 return status;
793 }
795 /*
796 * Check if rcvid is still valid and still has an unblock
797 * request pending.
798 */
799 if (MsgInfo(ctp->rcvid, &info) == -1 ||
800 !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
801 return _RESMGR_NOREPLY;
802 }
804 if (mqcopy_test_sem)
805 OsalSemaphore_post(mqcopy_test_sem);
807 return _RESMGR_NOREPLY;
808 }
810 IOFUNC_OCB_T *
811 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
812 {
813 syslink_ocb_t *ocb = NULL;
815 /* Allocate the OCB */
816 ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
817 if (ocb == NULL){
818 errno = ENOMEM;
819 return (NULL);
820 }
822 ocb->pid = ctp->info.pid;
824 return (IOFUNC_OCB_T *)(ocb);
825 }
827 void
828 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
829 {
830 syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
832 if (ocb) {
833 #ifndef SYSLINK_PLATFORM_VAYU
834 GateHWSpinlock_LeaveLockForPID(ocb->pid);
835 #endif
836 free (ocb);
837 }
838 }
840 int init_slave_devices(syslink_dev_t *dev)
841 {
842 resmgr_attr_t resmgr_attr;
843 int i;
844 syslink_attr_t * slave_attr;
845 int status = 0;
847 memset(&resmgr_attr, 0, sizeof resmgr_attr);
848 resmgr_attr.nparts_max = 1;
849 resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
851 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
852 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_state[i],
853 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_state[i]);
854 slave_attr = &dev->syslink.cattr_slave[i];
855 iofunc_attr_init(&slave_attr->attr,
856 S_IFCHR | 0777, NULL, NULL);
857 slave_attr->attr.mount = &dev->syslink.mattr;
858 slave_attr->procid = i;
859 slave_attr->dev = (Ptr)dev;
860 iofunc_time_update(&slave_attr->attr);
861 snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
862 "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
863 dev->syslink.iofuncs_state[i].read = slave_state_read;
864 dev->syslink.iofuncs_state[i].write = slave_state_write;
866 if (-1 == (dev->syslink.resmgr_id_state[i] =
867 resmgr_attach(dev->dpp, &resmgr_attr,
868 dev->syslink.device_name, _FTYPE_ANY, 0,
869 &dev->syslink.cfuncs_state[i],
870 &dev->syslink.iofuncs_state[i],
871 &slave_attr->attr))) {
872 GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
873 status, "resmgr_attach failed");
874 return (-1);
875 }
876 }
878 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
879 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_file[i],
880 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_file[i]);
881 slave_attr = &dev->syslink.cattr_slave[i];
882 iofunc_attr_init(&slave_attr->attr,
883 S_IFCHR | 0777, NULL, NULL);
884 slave_attr->attr.mount = &dev->syslink.mattr;
885 slave_attr->procid = i;
886 slave_attr->dev = (Ptr)dev;
887 iofunc_time_update(&slave_attr->attr);
888 snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
889 "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
890 dev->syslink.iofuncs_file[i].read = slave_file_read;
891 dev->syslink.iofuncs_file[i].write = slave_file_write;
893 if (-1 == (dev->syslink.resmgr_id_file[i] =
894 resmgr_attach(dev->dpp, &resmgr_attr,
895 dev->syslink.device_name, _FTYPE_ANY, 0,
896 &dev->syslink.cfuncs_file[i],
897 &dev->syslink.iofuncs_file[i],
898 &slave_attr->attr))) {
899 GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
900 status, "resmgr_attach failed");
901 return (-1);
902 }
903 }
905 return (status);
906 }
908 int deinit_slave_devices(syslink_dev_t *dev)
909 {
910 int status = EOK;
911 int i = 0;
913 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
914 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_state[i], 0);
915 if (status < 0) {
916 Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
917 i, errno);
918 }
919 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_file[i], 0);
920 if (status < 0) {
921 Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
922 i, errno);
923 }
924 }
926 return (status);
927 }
929 int init_syslink_trace_device(syslink_dev_t *dev)
930 {
931 resmgr_attr_t resmgr_attr;
932 int i;
933 syslink_attr_t * trace_attr;
934 char trace_name[_POSIX_PATH_MAX];
935 int status = 0;
936 unsigned int da = 0, pa = 0;
937 unsigned int len;
939 memset(&resmgr_attr, 0, sizeof resmgr_attr);
940 resmgr_attr.nparts_max = 10;
941 resmgr_attr.msg_max_size = 2048;
943 for (i = 0; i < syslink_num_cores; i++) {
944 /*
945 * Initialize trace device only for cores that are running and their
946 * device is not yet setup.
947 */
948 if ((syslink_firmware[i].procState == RUNNING_STATE) &&
949 (proc_traces[i].va == NULL)) {
950 iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
951 &dev->syslink.cfuncs_trace[i],
952 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
953 trace_attr = &dev->syslink.cattr_trace[i];
954 iofunc_attr_init(&trace_attr->attr,
955 S_IFCHR | 0777, NULL, NULL);
956 trace_attr->attr.mount = &dev->syslink.mattr;
957 trace_attr->procid = i;
958 iofunc_time_update(&trace_attr->attr);
959 snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
960 "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
961 dev->syslink.iofuncs_trace[i].read = syslink_read;
962 snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
963 pa = 0;
964 status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE,
965 0, &da, &pa, &len);
966 if (status == 0) {
967 /* last 8 bytes are for writeIdx/readIdx */
968 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
969 if (da && !pa) {
970 /* need to translate da->pa */
971 status = ProcMgr_translateAddr(
972 procH[syslink_firmware[i].proc_id],
973 (Ptr *) &pa,
974 ProcMgr_AddrType_MasterPhys,
975 (Ptr) da,
976 ProcMgr_AddrType_SlaveVirt);
977 }
978 else {
979 GT_setFailureReason(curTrace, GT_4CLASS,
980 "init_syslink_trace_device",
981 status, "not performing ProcMgr_translate");
982 }
983 /* map length aligned to page size */
984 proc_traces[i].va =
985 mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
986 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
987 proc_traces[i].len);
988 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
989 + sizeof(uint32_t));
990 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
991 GT_setFailureReason(curTrace, GT_4CLASS,
992 "init_syslink_trace_device",
993 status, "mmap_device_io failed");
994 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
995 proc_traces[i].va = NULL;
996 }
997 proc_traces[i].firstRead = TRUE;
998 }
999 else {
1000 GT_setFailureReason(curTrace, GT_4CLASS,
1001 "init_syslink_trace_device",
1002 status, "RscTable_getInfo failed");
1003 proc_traces[i].va = NULL;
1004 }
1005 if (-1 == (dev->syslink.resmgr_id_trace[i] =
1006 resmgr_attach(dev->dpp, &resmgr_attr,
1007 dev->syslink.device_name, _FTYPE_ANY, 0,
1008 &dev->syslink.cfuncs_trace[i],
1009 &dev->syslink.iofuncs_trace[i],
1010 &trace_attr->attr))) {
1011 GT_setFailureReason(curTrace, GT_4CLASS,
1012 "init_syslink_trace_device",
1013 status, "resmgr_attach failed");
1014 return(-1);
1015 }
1016 }
1017 }
1019 return (status);
1020 }
1022 int deinit_syslink_trace_device(syslink_dev_t *dev)
1023 {
1024 int status = EOK;
1025 int i = 0;
1027 for (i = 0; i < syslink_num_cores; i++) {
1028 /* Only disable trace device on cores in RESET state */
1029 if ((syslink_firmware[i].procState == RESET_STATE) &&
1030 (proc_traces[i].va != NULL)) {
1031 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i],
1032 0);
1033 if (status < 0) {
1034 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1035 i, errno);
1036 status = errno;
1037 }
1038 if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1039 munmap((void *)proc_traces[i].va,
1040 ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1041 }
1042 proc_traces[i].va = NULL;
1043 }
1044 }
1046 return (status);
1047 }
1049 /* Initialize the syslink device */
1050 int init_syslink_device(syslink_dev_t *dev)
1051 {
1052 iofunc_attr_t * attr;
1053 resmgr_attr_t resmgr_attr;
1054 int status = 0;
1056 pthread_mutex_init(&dev->lock, NULL);
1057 pthread_mutex_init(&dev->firmwareLock, NULL);
1059 memset(&resmgr_attr, 0, sizeof resmgr_attr);
1060 resmgr_attr.nparts_max = 10;
1061 resmgr_attr.msg_max_size = 2048;
1063 memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
1064 dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
1065 dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1066 IOFUNC_PC_NO_TRUNC |
1067 IOFUNC_PC_SYNC_IO;
1068 dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
1070 memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
1071 dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1073 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
1074 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
1076 iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
1078 dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
1079 dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
1080 dev->syslink.iofuncs.devctl = syslink_devctl;
1081 dev->syslink.iofuncs.unblock = syslink_unblock;
1083 attr->mount = &dev->syslink.mattr;
1084 iofunc_time_update(attr);
1086 if (-1 == (dev->syslink.resmgr_id =
1087 resmgr_attach(dev->dpp, &resmgr_attr,
1088 IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1089 &dev->syslink.cfuncs,
1090 &dev->syslink.iofuncs, attr))) {
1091 return(-1);
1092 }
1094 status = init_slave_devices(dev);
1095 if (status < 0) {
1096 return status;
1097 }
1099 status = init_syslink_trace_device(dev);
1100 if (status < 0) {
1101 return status;
1102 }
1104 return(0);
1105 }
1107 /* De-initialize the syslink device */
1108 int deinit_syslink_device(syslink_dev_t *dev)
1109 {
1110 int status = EOK;
1112 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
1113 if (status < 0) {
1114 Osal_printf("IPC: resmgr_detach of %s failed: %d",
1115 IPC_DEVICE_PATH, errno);
1116 status = errno;
1117 }
1119 status = deinit_syslink_trace_device(dev);
1120 if (status < 0) {
1121 Osal_printf("IPC: deinit_syslink_trace_device failed %d", status);
1122 }
1124 status = deinit_slave_devices(dev);
1125 if (status < 0) {
1126 Osal_printf("IPC: deinit_slave_devices failed %d", status);
1127 }
1129 return(status);
1130 }
1133 /* Initialize the devices */
1134 int init_devices(syslink_dev_t *dev)
1135 {
1136 if (init_syslink_device(dev) < 0) {
1137 Osal_printf("IPC: device init failed");
1138 return(-1);
1139 }
1141 return(0);
1142 }
1145 /* De-initialize the devices */
1146 int deinit_devices(syslink_dev_t *dev)
1147 {
1148 int status = EOK;
1150 if ((status = deinit_syslink_device(dev)) < 0) {
1151 fprintf( stderr, "IPC: device de-init failed %d\n", status);
1152 status = errno;
1153 }
1155 return(status);
1156 }
1158 static void ipc_recover(Ptr args)
1159 {
1160 syslink_dev_t * dev = (syslink_dev_t *)args;
1162 if (!disableRecovery) {
1163 /* Protect the syslink_firmware array as we recover */
1164 pthread_mutex_lock(&dev->firmwareLock);
1165 deinit_ipc(dev, syslink_firmware, TRUE);
1166 deinit_syslink_trace_device(dev);
1167 init_ipc(dev, syslink_firmware, TRUE);
1168 init_syslink_trace_device(dev);
1169 pthread_mutex_unlock(&dev->firmwareLock);
1170 }
1171 else {
1172 GT_0trace(curTrace, GT_4CLASS,
1173 "ipc_recover: Recovery disabled.\n");
1174 }
1175 }
1177 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
1178 ProcMgr_State fromState, ProcMgr_State toState,
1179 ProcMgr_EventStatus status, Ptr args)
1180 {
1181 Int ret = 0;
1182 String errString = NULL;
1183 syslink_dev_t * dev = (syslink_dev_t *)args;
1185 if (status == ProcMgr_EventStatus_Event) {
1186 switch (toState) {
1187 case ProcMgr_State_Mmu_Fault:
1188 errString = "MMU Fault";
1189 break;
1190 case ProcMgr_State_Error:
1191 errString = "Exception";
1192 break;
1193 case ProcMgr_State_Watchdog:
1194 errString = "Watchdog";
1195 break;
1196 default:
1197 errString = "Unexpected State";
1198 ret = -1;
1199 break;
1200 }
1201 GT_2trace (curTrace, GT_4CLASS,
1202 "syslink_error_cb: Received Error Callback for %s : %s\n",
1203 MultiProc_getName(procId), errString);
1204 /* Don't allow re-schedule of recovery until complete */
1205 pthread_mutex_lock(&dev->lock);
1206 if (ret != -1 && dev->recover == FALSE) {
1207 /* Schedule recovery. */
1208 dev->recover = TRUE;
1209 /* Activate a thread to handle the recovery. */
1210 GT_0trace (curTrace, GT_4CLASS,
1211 "syslink_error_cb: Scheduling recovery...");
1212 OsalThread_activate(dev->ipc_recovery_work);
1213 }
1214 else {
1215 GT_0trace (curTrace, GT_4CLASS,
1216 "syslink_error_cb: Recovery already scheduled.");
1217 }
1218 pthread_mutex_unlock(&dev->lock);
1219 }
1220 else if (status == ProcMgr_EventStatus_Canceled) {
1221 GT_1trace (curTrace, GT_3CLASS,
1222 "SysLink Error Callback Cancelled for %s",
1223 MultiProc_getName(procId));
1224 }
1225 else {
1226 GT_1trace (curTrace, GT_4CLASS,
1227 "SysLink Error Callback Unexpected Event for %s",
1228 MultiProc_getName(procId));
1229 }
1231 return ret;
1232 }
1234 /*
1235 * Initialize the syslink ipc
1236 *
1237 * This function sets up the "kernel"-side IPC modules, and does any special
1238 * initialization required for QNX and the platform being used. This function
1239 * also registers for error notifications and initializes the recovery thread.
1240 */
1241 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
1242 {
1243 int status = 0;
1244 Ipc_Config iCfg;
1245 OsalThread_Params threadParams;
1246 ProcMgr_AttachParams attachParams;
1247 UInt16 procId;
1248 int i;
1250 if (status >= 0) {
1251 if (!recover) {
1252 /* Set up the MemoryOS module */
1253 status = MemoryOS_setup();
1254 if (status < 0)
1255 goto memoryos_fail;
1256 }
1258 /* Setup IPC and platform-specific items */
1259 status = Ipc_setup (&iCfg);
1260 if (status < 0)
1261 goto ipcsetup_fail;
1263 /* NOTE: this is for handling the procmgr event notifications to userspace list */
1264 if (!recover) {
1265 /* Setup Fault recovery items. */
1266 /* Create the thread object used for the interrupt handler. */
1267 threadParams.priority = OsalThread_Priority_Medium;
1268 threadParams.priorityType = OsalThread_PriorityType_Generic;
1269 threadParams.once = FALSE;
1270 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1271 ipc_recover,
1272 dev,
1273 &threadParams);
1274 if (dev->ipc_recovery_work == NULL)
1275 goto osalthreadcreate_fail;
1276 }
1277 else {
1278 pthread_mutex_lock(&dev->lock);
1279 dev->recover = FALSE;
1280 pthread_mutex_unlock(&dev->lock);
1281 }
1283 memset(procH_fileId, 0, sizeof(procH_fileId));
1285 for (i = 0; i < syslink_num_cores; i++) {
1286 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1287 if (procId >= MultiProc_MAXPROCESSORS) {
1288 status = -1;
1289 fprintf(stderr, "Invalid processor name specified\n");
1290 break;
1291 }
1293 if (procH[procId]) {
1294 GT_setFailureReason (curTrace,
1295 GT_4CLASS,
1296 "init_ipc",
1297 status,
1298 "invalid proc!");
1299 break;
1300 }
1302 if (recover) {
1303 /*
1304 * if we are in recovery, we load the cores we previously
1305 * attached to
1306 */
1307 firmware[i].attachOnly = false;
1308 }
1310 if ((!recover) || (firmware[i].reload)) {
1311 status = runSlave(dev, procId, &firmware[i]);
1312 if (status == 0) {
1313 firmware[i].procState = RUNNING_STATE;
1314 continue;
1315 }
1316 else {
1317 break;
1318 }
1319 }
1320 else {
1321 /*
1322 * During recovery, do not run cores unless they were previously
1323 * running
1324 */
1325 continue;
1326 }
1327 }
1329 if (status < 0)
1330 goto tiipcsetup_fail;
1332 /* Set up rpmsg_mq */
1333 status = ti_ipc_setup();
1334 if (status < 0)
1335 goto tiipcsetup_fail;
1337 /* Set up rpmsg_rpc */
1338 status = rpmsg_rpc_setup();
1339 if (status < 0)
1340 goto rpcsetup_fail;
1342 #if defined(SYSLINK_PLATFORM_VAYU)
1343 if (gatempEnabled) {
1344 Int32 sr0ProcId;
1346 /* Set up NameServer for resource manager process */
1347 status = NameServer_setup();
1348 if (status < 0) {
1349 goto nameserversetup_fail;
1350 }
1352 /* Set up GateMP */
1353 status = GateMP_setup(&sr0ProcId);
1354 if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1355 goto gatempsetup_fail;
1356 }
1357 else if (status == 0) {
1358 sr0OwnerProcId = sr0ProcId;
1359 }
1360 else {
1361 /*
1362 * If we did not find the default gate, perhaps SR0 is
1363 * not yet loaded. This is ok.
1364 */
1365 status = 0;
1366 }
1367 }
1368 #endif
1370 goto exit;
1371 }
1373 #if defined(SYSLINK_PLATFORM_VAYU)
1374 gatempsetup_fail:
1375 NameServer_destroy();
1376 nameserversetup_fail:
1377 rpmsg_rpc_destroy();
1378 #endif
1379 rpcsetup_fail:
1380 ti_ipc_destroy(recover);
1381 tiipcsetup_fail:
1382 for (i-=1; i >= 0; i--) {
1383 procId = firmware[i].proc_id;
1384 if (procId >= MultiProc_MAXPROCESSORS) {
1385 continue;
1386 }
1387 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
1388 (Ptr)dev, errStates);
1389 if (!firmware[i].attachOnly) {
1390 ProcMgr_stop(procH[procId]);
1391 if (procH_fileId[procId]) {
1392 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1393 procH_fileId[procId] = 0;
1394 }
1395 }
1396 ProcMgr_detach(procH[procId]);
1397 ProcMgr_close(&procH[procId]);
1398 procH[procId] = NULL;
1399 RscTable_free(&rscHandle[procId]);
1400 rscHandle[procId] = NULL;
1401 }
1402 OsalThread_delete(&dev->ipc_recovery_work);
1403 osalthreadcreate_fail:
1404 Ipc_destroy();
1405 ipcsetup_fail:
1406 MemoryOS_destroy();
1407 memoryos_fail:
1408 exit:
1409 return status;
1410 }
1412 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
1413 bool recover)
1414 {
1415 int status = EOK;
1416 uint32_t i = 0, id = 0;
1418 if (logFilename) {
1419 /* wait a little bit for traces to finish dumping */
1420 sleep(1);
1421 }
1423 // Stop the remote cores right away
1424 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1425 if (procH[i]) {
1426 resetSlave(dev, i);
1427 }
1428 }
1430 #if defined(SYSLINK_PLATFORM_VAYU)
1431 if (gatempEnabled) {
1432 GateMP_destroy();
1434 NameServer_destroy();
1435 }
1436 #endif
1438 rpmsg_rpc_destroy();
1440 ti_ipc_destroy(recover);
1442 if (!recover && dev->ipc_recovery_work != NULL) {
1443 OsalThread_delete (&dev->ipc_recovery_work);
1444 dev->ipc_recovery_work = NULL;
1445 }
1447 if (recover) {
1448 static FILE *log = NULL;
1449 if (logFilename) {
1450 /* Dump the trace information */
1451 Osal_printf("IPC: printing remote core trace dump");
1452 log = fopen(logFilename, "a+");
1453 if (log) {
1454 for (id = 0; id < syslink_num_cores; id++) {
1455 if (firmware[id].procState == RUNNING_STATE) {
1456 if (proc_traces[id].va) {
1457 /* print traces */
1458 fprintf(log, "*************************************\n");
1459 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
1460 firmware[i].proc_id);
1461 fprintf(log, "*************************************\n");
1462 for (i = (*proc_traces[id].widx + 1);
1463 i < (proc_traces[id].len - 8);
1464 i++) {
1465 fprintf(log, "%c",
1466 *(char *)((uint32_t)proc_traces[id].va + i));
1467 }
1468 for (i = 0; i < *proc_traces[id].widx; i++) {
1469 fprintf(log, "%c",
1470 *(char *)((uint32_t)proc_traces[id].va + i));
1471 }
1472 }
1473 }
1474 }
1475 fflush(log);
1476 fclose(log);
1477 }
1478 else {
1479 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1480 logFilename);
1481 exit(EXIT_FAILURE);
1482 }
1483 }
1484 }
1486 /* After printing trace, set all processor states to RESET */
1487 for (id = 0; id < syslink_num_cores; id++) {
1488 firmware[id].procState = RESET_STATE;
1489 }
1491 status = Ipc_destroy();
1492 if (status < 0) {
1493 printf("Ipc_destroy() failed 0x%x", status);
1494 }
1495 if (!recover) {
1496 status = MemoryOS_destroy();
1497 if (status < 0) {
1498 printf("MemoryOS_destroy() failed 0x%x", status);
1499 }
1500 }
1502 return status;
1503 }
1506 /** print usage */
1507 static Void printUsage (Char * app)
1508 {
1509 printf("\n\nUsage:\n");
1510 #if defined(SYSLINK_PLATFORM_OMAP5430)
1511 printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1512 app);
1513 printf(" <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1514 printf(" followed by the path to the executable to load on that core.\n");
1515 printf("Options:\n");
1516 printf(" -H <arg> enable/disable hibernation, 1: ON, 0: OFF,"
1517 " Default: 1)\n");
1518 printf(" -T <arg> specify the hibernation timeout in ms, Default:"
1519 " 5000 ms)\n");
1520 #else
1521 printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1522 app);
1523 printf(" <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1524 printf(" followed by the path to the executable to load on that core.\n");
1525 printf("Options:\n");
1526 printf(" -g enable GateMP support on host\n");
1527 #endif
1528 printf(" -d disable recovery\n");
1529 printf(" -c <file> generate dump of slave trace during crashes (use\n");
1530 printf(" absolute path for filename)\n");
1531 printf(" -a<n> specify that the first n cores have been pre-loaded\n");
1532 printf(" and started. Perform late-attach to these cores.\n");
1534 exit (EXIT_SUCCESS);
1535 }
1537 dispatch_t * syslink_dpp = NULL;
1539 int main(int argc, char *argv[])
1540 {
1541 syslink_dev_t * dev = NULL;
1542 thread_pool_attr_t tattr;
1543 int status;
1544 int error = EOK;
1545 sigset_t set;
1546 int channelid = 0;
1547 int c;
1548 int hib_enable = 1;
1549 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1550 char *user_parm = NULL;
1551 struct stat sbuf;
1552 int i = 0;
1553 char * abs_path = NULL;
1555 if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1556 printf ("IPC Already Running...\n");
1557 return EXIT_FAILURE;
1558 }
1559 printf ("Starting IPC resource manager...\n");
1561 /* Parse the input args */
1562 while (1)
1563 {
1564 c = getopt (argc, argv, "H:T:U:gc:dv:a:");
1565 if (c == -1)
1566 break;
1568 switch (c)
1569 {
1570 #if defined(SYSLINK_PLATFORM_OMAP5430)
1571 case 'H':
1572 hib_enable = atoi(optarg);
1573 if (hib_enable != 0 && hib_enable != 1) {
1574 hib_enable = -1;
1575 }
1576 break;
1577 case 'T':
1578 hib_timeout = atoi(optarg);
1579 break;
1580 #endif
1581 case 'U':
1582 user_parm = optarg;
1583 break;
1584 case 'd':
1585 disableRecovery = true;
1586 break;
1587 case 'c':
1588 logFilename = optarg;
1589 break;
1590 case 'a':
1591 numAttach = atoi(optarg);
1592 printf("Late-attaching to %d core(s)\n", numAttach);
1593 break;
1594 case 'v':
1595 verbosity++;
1596 break;
1597 #if defined(SYSLINK_PLATFORM_VAYU)
1598 case 'g':
1599 printf("GateMP support enabled on host\n");
1600 gatempEnabled = true;
1601 break;
1602 #endif
1603 default:
1604 fprintf (stderr, "Unrecognized argument\n");
1605 }
1606 }
1608 /* Now parse the operands, which should be in the format:
1609 * "<multiproc_name> <firmware_file> ..*/
1610 for (; optind + 1 < argc; optind+=2) {
1611 if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1612 printUsage(argv[0]);
1613 return (error);
1614 }
1615 syslink_firmware[syslink_num_cores].proc = argv [optind];
1616 syslink_firmware[syslink_num_cores].attachOnly =
1617 ((numAttach-- > 0) ? true : false);
1618 syslink_firmware[syslink_num_cores].reload = true;
1619 syslink_firmware[syslink_num_cores].freeString = false;
1620 syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1621 }
1623 /* Get the name of the binary from the input args */
1624 if (!syslink_num_cores) {
1625 fprintf(stderr, "At least one core_id and executable must be "\
1626 "specified");
1627 printUsage(argv[0]);
1628 return (error);
1629 }
1631 /* Validate hib_enable args */
1632 if (hib_enable == -1) {
1633 fprintf (stderr, "invalid hibernation enable value\n");
1634 printUsage(argv[0]);
1635 return (error);
1636 }
1638 syslink_hib_enable = (Bool)hib_enable;
1639 syslink_hib_timeout = hib_timeout;
1641 /* Init logging for syslink */
1642 if (Osal_initlogging(verbosity) != 0) {
1643 return -1;
1644 }
1646 /* Obtain I/O privity */
1647 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1648 if (error == -1) {
1649 Osal_printf("Unable to obtain I/O privity");
1650 return (error);
1651 }
1653 /* Get the abs path for all firmware files */
1654 for (i = 0; i < syslink_num_cores; i++) {
1655 abs_path = calloc(1, PATH_MAX + 1);
1656 if (abs_path == NULL) {
1657 return -1;
1658 }
1659 if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1660 fprintf (stderr, "invalid path to executable\n");
1661 return -1;
1662 }
1663 syslink_firmware[i].firmware = abs_path;
1664 }
1666 /* allocate the device structure */
1667 if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1668 Osal_printf("IPC: calloc() failed");
1669 return (-1);
1670 }
1672 /* create the channel */
1673 if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1674 _NTO_CHF_DISCONNECT |
1675 _NTO_CHF_COID_DISCONNECT |
1676 _NTO_CHF_REPLY_LEN |
1677 _NTO_CHF_SENDER_LEN)) < 0) {
1678 Osal_printf("Unable to create channel %d", channelid);
1679 return (channelid);
1680 }
1682 /* create the dispatch structure */
1683 if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1684 Osal_printf("IPC: dispatch_create() failed");
1685 return(-1);
1686 }
1688 /*
1689 * Mask out all signals before creating a thread pool.
1690 * This prevents other threads in the thread pool
1691 * from intercepting signals such as SIGTERM.
1692 */
1693 sigfillset(&set);
1694 pthread_sigmask(SIG_BLOCK, &set, NULL);
1696 /* Initialize the thread pool */
1697 memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1698 tattr.handle = dev->dpp;
1699 tattr.context_alloc = dispatch_context_alloc;
1700 tattr.context_free = dispatch_context_free;
1701 tattr.block_func = dispatch_block;
1702 tattr.unblock_func = dispatch_unblock;
1703 tattr.handler_func = dispatch_handler;
1704 tattr.lo_water = 2;
1705 tattr.hi_water = 4;
1706 tattr.increment = 1;
1707 tattr.maximum = 10;
1709 /* Create the thread pool */
1710 if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1711 Osal_printf("IPC: thread pool create failed");
1712 return(-1);
1713 }
1715 /* init syslink */
1716 status = init_ipc(dev, syslink_firmware, FALSE);
1717 if (status < 0) {
1718 Osal_printf("IPC: init failed");
1719 return(-1);
1720 }
1722 /* init the syslink device */
1723 status = init_devices(dev);
1724 if (status < 0) {
1725 Osal_printf("IPC: device init failed");
1726 return(-1);
1727 }
1729 #if (_NTO_VERSION >= 800)
1730 /* Relinquish privileges */
1731 status = procmgr_ability( 0,
1732 DENY_ALL | PROCMGR_AID_SPAWN,
1733 DENY_ALL | PROCMGR_AID_FORK,
1734 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1735 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1736 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1737 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1738 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1739 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1740 (uint64_t)1, (uint64_t)~0,
1741 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1742 (uint64_t)1, (uint64_t)~0,
1743 PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1745 if (status != EOK) {
1746 Osal_printf("procmgr_ability failed! errno=%d", status);
1747 return EXIT_FAILURE;
1748 }
1750 /* Reduce priority to either what defined from command line or at least nobody */
1751 if (user_parm != NULL) {
1752 if (set_ids_from_arg(user_parm) < 0) {
1753 Osal_printf("unable to set uid/gid - %s", strerror(errno));
1754 return EXIT_FAILURE;
1755 }
1756 } else {
1757 if (setuid(99) != 0) {
1758 Osal_printf("unable to set uid - %s", strerror(errno));
1759 return EXIT_FAILURE;
1760 }
1761 }
1762 #endif
1764 /* make this a daemon process */
1765 if (-1 == procmgr_daemon(EXIT_SUCCESS,
1766 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1767 Osal_printf("IPC: procmgr_daemon() failed");
1768 return(-1);
1769 }
1771 /* start the thread pool */
1772 thread_pool_start(dev->tpool);
1774 /* Unmask signals to be caught */
1775 sigdelset (&set, SIGINT);
1776 sigdelset (&set, SIGTERM);
1777 pthread_sigmask (SIG_BLOCK, &set, NULL);
1779 /* Wait for one of these signals */
1780 sigemptyset (&set);
1781 sigaddset (&set, SIGINT);
1782 sigaddset (&set, SIGQUIT);
1783 sigaddset (&set, SIGTERM);
1785 Osal_printf("IPC resource manager started");
1787 /* Wait for a signal */
1788 while (1)
1789 {
1790 switch (SignalWaitinfo (&set, NULL))
1791 {
1792 case SIGTERM:
1793 case SIGQUIT:
1794 case SIGINT:
1795 error = EOK;
1796 goto done;
1798 default:
1799 break;
1800 }
1801 }
1803 error = EOK;
1805 done:
1806 GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1808 error = thread_pool_destroy(dev->tpool);
1809 if (error < 0) {
1810 Osal_printf("IPC: thread_pool_destroy returned an error");
1811 }
1812 deinit_ipc(dev, syslink_firmware, FALSE);
1813 deinit_devices(dev);
1814 free(dev);
1816 /* Free the abs path of firmware files if necessary */
1817 for (i = 0; i < syslink_num_cores; i++) {
1818 if ((syslink_firmware[i].freeString) &&
1819 (syslink_firmware[i].firmware)) {
1820 free(syslink_firmware[i].firmware);
1821 }
1822 }
1824 return (error);
1825 }