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>
83 #if (_NTO_VERSION >= 800)
84 #include <slog2.h>
85 #endif
87 #include <ti-ipc.h>
89 #define DENY_ALL \
90 PROCMGR_ADN_ROOT \
91 | PROCMGR_ADN_NONROOT \
92 | PROCMGR_AOP_DENY \
93 | PROCMGR_AOP_LOCK
95 // Ducati trace to slog2 static variables and defines
96 #define TRACE_BUFFER_SIZE 4096
97 // polling interval in microseconds
98 #define TRACE_POLLING_INTERVAL_US 1000000
100 #if (_NTO_VERSION >= 800)
101 static int verbosity = SLOG2_ERROR;
102 static slog2_buffer_t buffer_handle;
103 #else
104 static int verbosity = 2;
105 #endif
107 #if defined(SYSLINK_PLATFORM_VAYU)
108 static bool gatempEnabled = false;
109 #endif
110 static char trace_buffer[TRACE_BUFFER_SIZE];
111 static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
112 static Bool trace_active;
113 static pthread_t thread_traces;
115 // Syslink hibernation global variables
116 Bool syslink_hib_enable = TRUE;
117 #if !defined(SYSLINK_PLATFORM_OMAP4430) && !defined(SYSLINK_PLATFORM_OMAP5430)
118 #define PM_HIB_DEFAULT_TIME 5000
119 #endif
120 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
121 Bool syslink_hib_hibernating = FALSE;
122 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
123 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
125 extern Int rpmsg_rpc_setup (Void);
126 extern Void rpmsg_rpc_destroy (Void);
127 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
129 typedef struct syslink_firmware_info_t {
130 uint16_t proc_id;
131 char * proc;
132 char * firmware;
133 } syslink_firmware_info;
134 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
135 static unsigned int syslink_num_cores = 0;
137 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
138 int deinit_ipc(syslink_dev_t * dev, bool recover);
140 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
142 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
143 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
144 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
145 ProcMgr_State_Error,
146 ProcMgr_State_Watchdog,
147 ProcMgr_State_EndValue};
149 typedef struct syslink_trace_info_t {
150 uintptr_t va;
151 uint32_t len;
152 uint32_t * widx;
153 uint32_t * ridx;
154 Bool firstRead;
155 } syslink_trace_info;
157 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
159 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
160 {
161 int nbytes;
162 int nparts;
163 int status;
164 int nleft;
165 uint32_t len;
166 uint16_t procid = ocb->ocb.attr->procid;
168 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
169 return (status);
171 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
172 return (ENOSYS);
174 /* check to see where the trace buffer is */
175 if (proc_traces[procid].va == NULL) {
176 return (ENOSYS);
177 }
179 /* need to abort ducati trace thread if it is running as only want one reader */
180 pthread_mutex_lock(&trace_mutex);
181 if (trace_active == TRUE) {
182 trace_active = FALSE;
183 pthread_mutex_unlock(&trace_mutex);
184 // Wake up if waiting on hibernation
185 pthread_mutex_lock(&syslink_hib_mutex);
186 syslink_hib_hibernating = FALSE;
187 pthread_cond_broadcast(&syslink_hib_cond);
188 pthread_mutex_unlock(&syslink_hib_mutex);
189 pthread_join(thread_traces, NULL);
190 } else {
191 pthread_mutex_unlock(&trace_mutex);
192 }
194 if (ocb->ocb.offset == 0) {
195 ocb->widx = *(proc_traces[procid].widx);
196 ocb->ridx = *(proc_traces[procid].ridx);
197 *(proc_traces[procid].ridx) = ocb->widx;
198 }
200 /* Check for wrap-around */
201 if (ocb->widx < ocb->ridx)
202 len = proc_traces[procid].len - ocb->ridx + ocb->widx;
203 else
204 len = ocb->widx - ocb->ridx;
206 /* Determine the amount left to print */
207 if (ocb->widx >= ocb->ridx)
208 nleft = len - ocb->ocb.offset;
209 else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
210 nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
211 else
212 nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
214 nbytes = min (msg->i.nbytes, nleft);
216 /* Make sure the user has supplied a big enough buffer */
217 if (nbytes > 0) {
218 /* set up the return data IOV */
219 if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
220 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
221 else
222 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
224 /* set up the number of bytes (returned by client's read()) */
225 _IO_SET_READ_NBYTES (ctp, nbytes);
227 ocb->ocb.offset += nbytes;
229 nparts = 1;
230 }
231 else {
232 _IO_SET_READ_NBYTES (ctp, 0);
234 /* reset offset */
235 ocb->ocb.offset = 0;
237 nparts = 0;
238 }
240 /* mark the access time as invalid (we just accessed it) */
242 if (msg->i.nbytes > 0)
243 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
245 return (_RESMGR_NPARTS (nparts));
246 }
248 extern OsalSemaphore_Handle mqcopy_test_sem;
250 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
251 {
252 int status = _RESMGR_NOREPLY;
253 struct _msg_info info;
255 /*
256 * Try to run the default unblock for this message.
257 */
258 if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
259 return status;
260 }
262 /*
263 * Check if rcvid is still valid and still has an unblock
264 * request pending.
265 */
266 if (MsgInfo(ctp->rcvid, &info) == -1 ||
267 !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
268 return _RESMGR_NOREPLY;
269 }
271 if (mqcopy_test_sem)
272 OsalSemaphore_post(mqcopy_test_sem);
274 return _RESMGR_NOREPLY;
275 }
277 IOFUNC_OCB_T *
278 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
279 {
280 syslink_ocb_t *ocb = NULL;
282 /* Allocate the OCB */
283 ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
284 if (ocb == NULL){
285 errno = ENOMEM;
286 return (NULL);
287 }
289 ocb->pid = ctp->info.pid;
291 return (IOFUNC_OCB_T *)(ocb);
292 }
294 void
295 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
296 {
297 syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
299 if (ocb) {
300 #ifndef SYSLINK_PLATFORM_VAYU
301 GateHWSpinlock_LeaveLockForPID(ocb->pid);
302 #endif
303 free (ocb);
304 }
305 }
307 int init_syslink_trace_device(syslink_dev_t *dev)
308 {
309 resmgr_attr_t resmgr_attr;
310 int i;
311 syslink_attr_t * trace_attr;
312 char trace_name[_POSIX_PATH_MAX];
313 int status = 0;
314 unsigned int da = 0, pa = 0;
315 unsigned int len;
317 memset(&resmgr_attr, 0, sizeof resmgr_attr);
318 resmgr_attr.nparts_max = 10;
319 resmgr_attr.msg_max_size = 2048;
321 for (i = 0; i < syslink_num_cores; i++) {
322 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
323 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
324 trace_attr = &dev->syslink.cattr_trace[i];
325 iofunc_attr_init(&trace_attr->attr,
326 S_IFCHR | 0777, NULL, NULL);
327 trace_attr->attr.mount = &dev->syslink.mattr;
328 trace_attr->procid = i;
329 iofunc_time_update(&trace_attr->attr);
330 snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
331 "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
332 dev->syslink.iofuncs_trace[i].read = syslink_read;
333 snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
334 pa = 0;
335 status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
336 if (status == 0) {
337 /* last 8 bytes are for writeIdx/readIdx */
338 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
339 if (da && !pa) {
340 /* need to translate da->pa */
341 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
342 (Ptr *) &pa,
343 ProcMgr_AddrType_MasterPhys,
344 (Ptr) da,
345 ProcMgr_AddrType_SlaveVirt);
346 }
347 else {
348 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
349 status, "not performing ProcMgr_translate");
350 }
351 /* map length aligned to page size */
352 proc_traces[i].va =
353 mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
354 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
355 proc_traces[i].len);
356 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
357 sizeof(uint32_t));
358 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
359 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
360 status, "mmap_device_io failed");
361 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
362 proc_traces[i].va = NULL;
363 }
364 proc_traces[i].firstRead = TRUE;
365 }
366 else {
367 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
368 status, "RscTable_getInfo failed");
369 proc_traces[i].va = NULL;
370 }
371 if (-1 == (dev->syslink.resmgr_id_trace[i] =
372 resmgr_attach(dev->dpp, &resmgr_attr,
373 dev->syslink.device_name, _FTYPE_ANY, 0,
374 &dev->syslink.cfuncs_trace[i],
375 &dev->syslink.iofuncs_trace[i],
376 &trace_attr->attr))) {
377 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
378 status, "resmgr_attach failed");
379 return(-1);
380 }
381 }
383 return (status);
384 }
386 int deinit_syslink_trace_device(syslink_dev_t *dev)
387 {
388 int status = EOK;
389 int i = 0;
391 for (i = 0; i < syslink_num_cores; i++) {
392 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
393 if (status < 0) {
394 Osal_printf("syslink: resmgr_detach failed %d", errno);
395 status = errno;
396 }
397 if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
398 munmap((void *)proc_traces[i].va,
399 ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
400 }
401 proc_traces[i].va = NULL;
402 }
404 return (status);
405 }
407 /* Initialize the syslink device */
408 int init_syslink_device(syslink_dev_t *dev)
409 {
410 iofunc_attr_t * attr;
411 resmgr_attr_t resmgr_attr;
412 int status = 0;
414 pthread_mutex_init(&dev->lock, NULL);
416 memset(&resmgr_attr, 0, sizeof resmgr_attr);
417 resmgr_attr.nparts_max = 10;
418 resmgr_attr.msg_max_size = 2048;
420 memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
421 dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
422 dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
423 IOFUNC_PC_NO_TRUNC |
424 IOFUNC_PC_SYNC_IO;
425 dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
427 memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
428 dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
430 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
431 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
433 iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
435 dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
436 dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
437 dev->syslink.iofuncs.devctl = syslink_devctl;
438 dev->syslink.iofuncs.unblock = syslink_unblock;
440 attr->mount = &dev->syslink.mattr;
441 iofunc_time_update(attr);
443 if (-1 == (dev->syslink.resmgr_id =
444 resmgr_attach(dev->dpp, &resmgr_attr,
445 IPC_DEVICE_PATH, _FTYPE_ANY, 0,
446 &dev->syslink.cfuncs,
447 &dev->syslink.iofuncs, attr))) {
448 return(-1);
449 }
451 status = init_syslink_trace_device(dev);
452 if (status < 0) {
453 return status;
454 }
456 return(0);
457 }
459 /* De-initialize the syslink device */
460 int deinit_syslink_device(syslink_dev_t *dev)
461 {
462 int status = EOK;
464 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
465 if (status < 0) {
466 Osal_printf("syslink: resmgr_detach failed %d", errno);
467 status = errno;
468 }
470 status = deinit_syslink_trace_device(dev);
472 return(status);
473 }
476 /* Initialize the devices */
477 int init_devices(syslink_dev_t *dev)
478 {
479 if (init_syslink_device(dev) < 0) {
480 Osal_printf("syslink: syslink device init failed");
481 return(-1);
482 }
484 return(0);
485 }
488 /* De-initialize the devices */
489 int deinit_devices(syslink_dev_t *dev)
490 {
491 int status = EOK;
493 if ((status = deinit_syslink_device(dev)) < 0) {
494 fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
495 status = errno;
496 }
498 return(status);
499 }
501 static void ipc_recover(Ptr args)
502 {
503 syslink_dev_t * dev = (syslink_dev_t *)args;
505 deinit_ipc(dev, TRUE);
506 init_ipc(dev, syslink_firmware, TRUE);
507 deinit_syslink_trace_device(dev);
508 init_syslink_trace_device(dev);
509 }
511 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
512 ProcMgr_State fromState, ProcMgr_State toState,
513 ProcMgr_EventStatus status, Ptr args)
514 {
515 Int ret = 0;
516 String errString = NULL;
517 syslink_dev_t * dev = (syslink_dev_t *)args;
519 if (status == ProcMgr_EventStatus_Event) {
520 switch (toState) {
521 case ProcMgr_State_Mmu_Fault:
522 errString = "MMU Fault";
523 break;
524 case ProcMgr_State_Error:
525 errString = "Exception";
526 break;
527 case ProcMgr_State_Watchdog:
528 errString = "Watchdog";
529 break;
530 default:
531 errString = "Unexpected State";
532 ret = -1;
533 break;
534 }
535 GT_2trace (curTrace, GT_4CLASS,
536 "syslink_error_cb: Received Error Callback for %s : %s\n",
537 MultiProc_getName(procId), errString);
538 /* Don't allow re-schedule of recovery until complete */
539 pthread_mutex_lock(&dev->lock);
540 if (ret != -1 && dev->recover == FALSE) {
541 /* Schedule recovery. */
542 dev->recover = TRUE;
543 /* Activate a thread to handle the recovery. */
544 GT_0trace (curTrace, GT_4CLASS,
545 "syslink_error_cb: Scheduling recovery...");
546 OsalThread_activate(dev->ipc_recovery_work);
547 }
548 else {
549 GT_0trace (curTrace, GT_4CLASS,
550 "syslink_error_cb: Recovery already scheduled.");
551 }
552 pthread_mutex_unlock(&dev->lock);
553 }
554 else if (status == ProcMgr_EventStatus_Canceled) {
555 GT_1trace (curTrace, GT_3CLASS,
556 "SysLink Error Callback Cancelled for %s",
557 MultiProc_getName(procId));
558 }
559 else {
560 GT_1trace (curTrace, GT_4CLASS,
561 "SysLink Error Callback Unexpected Event for %s",
562 MultiProc_getName(procId));
563 }
565 return ret;
566 }
568 #if defined(SYSLINK_PLATFORM_OMAP4430)
569 #define SYSLINK_CARVEOUT
570 #ifdef SYSLINK_CARVEOUT
571 #define IPU_MEM_SIZE 49 * 1024 * 1024
572 #define IPU_MEM_PHYS 0x97F00000
573 #else
574 #define IPU_MEM_SIZE 104 * 1024 * 1024
575 #define IPU_MEM_ALIGN 0x1000000
576 #endif
577 #endif
580 /*
581 * Initialize the syslink ipc
582 *
583 * This function sets up the "kernel"-side IPC modules, and does any special
584 * initialization required for QNX and the platform being used. This function
585 * also registers for error notifications and initializes the recovery thread.
586 */
587 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
588 {
589 int status = 0;
590 #if defined(SYSLINK_PLATFORM_OMAP4430)
591 int32_t ret = 0;
592 uint32_t len = 0;
593 #ifndef SYSLINK_CARVEOUT
594 int64_t pa = 0;
595 void * da;
596 #endif
597 int64_t paddr = 0;
598 #endif
599 Ipc_Config iCfg;
600 OsalThread_Params threadParams;
601 ProcMgr_AttachParams attachParams;
602 UInt16 procId;
603 int i;
605 #if defined(SYSLINK_PLATFORM_OMAP4430)
606 /* Map a contiguous memory section for ipu - currently hard-coded */
607 if (!recover) {
608 #ifdef SYSLINK_CARVEOUT
609 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
610 PROT_NOCACHE | PROT_READ | PROT_WRITE,
611 MAP_PHYS,
612 NOFD,
613 IPU_MEM_PHYS);
614 #else
615 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
616 PROT_NOCACHE | PROT_READ | PROT_WRITE,
617 MAP_ANON | MAP_PHYS | MAP_SHARED,
618 NOFD,
619 0);
621 #endif
623 if (dev->da_virt == MAP_FAILED) {
624 status = ENOMEM;
625 goto exit;
626 }
627 }
629 if (status >= 0) {
630 #ifdef SYSLINK_CARVEOUT
631 /* Make sure the memory is contiguous */
632 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
633 if (ret)
634 status = ret;
635 else if (len != IPU_MEM_SIZE)
636 status = ENOMEM;
637 #else
638 /* Make sure the memory is contiguous */
639 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
640 &paddr, &len);
641 if (ret)
642 status = ret;
643 else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
644 status = ENOMEM;
645 else {
646 pa = (paddr + IPU_MEM_ALIGN - 1) / IPU_MEM_ALIGN * IPU_MEM_ALIGN;
647 if ((pa - paddr) < 0x900000)
648 pa += 0x900000;
649 else
650 pa -= 0x700000;
651 da = dev->da_virt + (pa - paddr);
652 }
653 #endif
654 if (status != 0)
655 goto memoryos_fail;
656 }
657 #endif
659 if (status >= 0) {
660 if (!recover) {
661 /* Set up the MemoryOS module */
662 status = MemoryOS_setup();
663 if (status < 0)
664 goto memoryos_fail;
665 }
667 /* Setup IPC and platform-specific items */
668 #if defined(SYSLINK_PLATFORM_OMAP4430)
669 #ifdef SYSLINK_CARVEOUT
670 iCfg.vAddr = (uint32_t)dev->da_virt;
671 iCfg.pAddr = (uint32_t)paddr;
672 #else
673 iCfg.vAddr = (uint32_t)da;
674 iCfg.pAddr = (uint32_t)pa;
675 #endif
676 #endif
677 status = Ipc_setup (&iCfg);
678 if (status < 0)
679 goto ipcsetup_fail;
681 /* NOTE: this is for handling the procmgr event notifications to userspace list */
682 if (!recover) {
683 /* Setup Fault recovery items. */
684 /* Create the thread object used for the interrupt handler. */
685 threadParams.priority = OsalThread_Priority_Medium;
686 threadParams.priorityType = OsalThread_PriorityType_Generic;
687 threadParams.once = FALSE;
688 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
689 ipc_recover,
690 dev,
691 &threadParams);
692 if (dev->ipc_recovery_work == NULL)
693 goto osalthreadcreate_fail;
694 }
695 else {
696 pthread_mutex_lock(&dev->lock);
697 dev->recover = FALSE;
698 pthread_mutex_unlock(&dev->lock);
699 }
701 for (i = 0; i < syslink_num_cores; i++) {
702 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
703 if (procId >= MultiProc_MAXPROCESSORS) {
704 status = -1;
705 fprintf(stderr, "Invalid processor name specified\n");
706 break;
707 }
709 if (procH[procId]) {
710 GT_setFailureReason (curTrace,
711 GT_4CLASS,
712 "init_ipc",
713 status,
714 "invalid proc!");
715 break;
716 }
718 if (syslink_firmware[i].firmware) {
719 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
720 if (rscHandle[procId] == NULL) {
721 status = -1;
722 break;
723 }
724 }
726 status = ProcMgr_open(&procH[procId], procId);
727 if (status < 0 || procH[procId] == NULL)
728 goto procmgropen_fail;
730 /* Load and start the remote processor. */
731 ProcMgr_getAttachParams (procH[procId], &attachParams);
732 status = ProcMgr_attach (procH[procId], &attachParams);
733 if (status < 0) {
734 GT_setFailureReason (curTrace,
735 GT_4CLASS,
736 "init_ipc",
737 status,
738 "ProcMgr_attach failed!");
739 goto procmgrattach_fail;
740 }
742 if (syslink_firmware[i].firmware) {
743 status = ProcMgr_load (procH[procId],
744 (String)firmware[i].firmware, 0, NULL,
745 NULL, &procH_fileId[procId]);
746 if (status < 0) {
747 GT_setFailureReason (curTrace,
748 GT_4CLASS,
749 "init_ipc",
750 status,
751 "ProcMgr_load failed!");
752 goto procmgrload_fail;
753 }
754 }
756 status = Ipc_attach (procId);
757 if (status < 0) {
758 GT_setFailureReason (curTrace,
759 GT_4CLASS,
760 "init_ipc",
761 status,
762 "Ipc_attach failed!");
763 goto ipcattach_fail;
764 }
766 status = ProcMgr_start(procH[procId], NULL);
767 if (status < 0) {
768 GT_setFailureReason (curTrace,
769 GT_4CLASS,
770 "init_ipc",
771 status,
772 "ProcMgr_start failed!");
773 goto procmgrstart_fail;
774 }
776 status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
777 -1, errStates);
778 if (status < 0)
779 goto procmgrreg_fail;
781 continue;
783 procmgrreg_fail:
784 ProcMgr_stop(procH[procId]);
785 procmgrstart_fail:
786 Ipc_detach(procId);
787 ipcattach_fail:
788 if (syslink_firmware[i].firmware)
789 ProcMgr_unload(procH[procId], procH_fileId[procId]);
790 procmgrload_fail:
791 ProcMgr_detach(procH[procId]);
792 procmgrattach_fail:
793 ProcMgr_close(&procH[procId]);
794 procH[procId] = NULL;
795 procmgropen_fail:
796 RscTable_free(&rscHandle[procId]);
797 break;
798 }
800 if (status < 0)
801 goto tiipcsetup_fail;
803 /* Set up rpmsg_mq */
804 status = ti_ipc_setup();
805 if (status < 0)
806 goto tiipcsetup_fail;
808 /* Set up rpmsg_rpc */
809 status = rpmsg_rpc_setup();
810 if (status < 0)
811 goto rpcsetup_fail;
813 #if defined(SYSLINK_PLATFORM_VAYU)
814 if (gatempEnabled) {
815 /* Set up NameServer for resource manager process */
816 status = NameServer_setup();
817 if (status < 0) {
818 goto nameserversetup_fail;
819 }
821 /* Set up GateMP */
822 status = GateMP_setup();
823 if (status < 0) {
824 goto gatempsetup_fail;
825 }
826 }
827 #endif
829 goto exit;
830 }
832 #if defined(SYSLINK_PLATFORM_VAYU)
833 gatempsetup_fail:
834 NameServer_destroy();
835 nameserversetup_fail:
836 rpmsg_rpc_destroy();
837 #endif
838 rpcsetup_fail:
839 ti_ipc_destroy(recover);
840 tiipcsetup_fail:
841 for (i-=1; i >= 0; i--) {
842 procId = firmware[i].proc_id;
843 if (procId >= MultiProc_MAXPROCESSORS) {
844 continue;
845 }
846 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
847 (Ptr)dev, errStates);
848 ProcMgr_stop(procH[procId]);
849 if (procH_fileId[procId]) {
850 ProcMgr_unload(procH[procId], procH_fileId[procId]);
851 procH_fileId[procId] = 0;
852 }
853 ProcMgr_detach(procH[procId]);
854 ProcMgr_close(&procH[procId]);
855 procH[procId] = NULL;
856 RscTable_free(&rscHandle[procId]);
857 rscHandle[procId] = NULL;
858 }
859 OsalThread_delete(&dev->ipc_recovery_work);
860 osalthreadcreate_fail:
861 Ipc_destroy();
862 ipcsetup_fail:
863 MemoryOS_destroy();
864 memoryos_fail:
865 #if defined(SYSLINK_PLATFORM_OMAP4430)
866 if (dev->da_virt != MAP_FAILED)
867 #ifdef SYSLINK_CARVEOUT
868 munmap(dev->da_virt, IPU_MEM_SIZE);
869 #else
870 munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
871 #endif
872 #endif
873 exit:
874 return status;
875 }
877 int deinit_ipc(syslink_dev_t * dev, bool recover)
878 {
879 int status = EOK;
880 uint32_t i = 0, id = 0;
882 // Stop the remote cores right away
883 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
884 if (procH[i]) {
885 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
886 ProcMgr_stop(procH[i]);
887 }
888 }
890 #if defined(SYSLINK_PLATFORM_VAYU)
891 if (gatempEnabled) {
892 GateMP_destroy();
894 NameServer_destroy();
895 }
896 #endif
898 rpmsg_rpc_destroy();
900 ti_ipc_destroy(recover);
902 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
903 if (procH[i]) {
904 ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
905 errStates);
906 Ipc_detach(i);
907 if (procH_fileId[i]) {
908 ProcMgr_unload(procH[i], procH_fileId[i]);
909 procH_fileId[i] = 0;
910 }
911 ProcMgr_detach(procH[i]);
912 ProcMgr_close(&procH[i]);
913 procH[i] = NULL;
914 RscTable_free(&rscHandle[i]);
915 rscHandle[i] = NULL;
916 }
917 }
919 if (!recover && dev->ipc_recovery_work != NULL) {
920 OsalThread_delete (&dev->ipc_recovery_work);
921 dev->ipc_recovery_work = NULL;
922 }
924 if (recover) {
925 static FILE *log;
926 /* Dump the trace information */
927 Osal_printf("syslink: printing remote core trace dump to"
928 " /var/log/ducati-m3-traces.log");
929 log = fopen ("/var/log/ducati-m3-traces.log", "a+");
930 if (log) {
931 for (id = 0; id < syslink_num_cores; id++) {
932 if (proc_traces[id].va) {
933 /* print traces */
934 /* wait a little bit for traces to finish dumping */
935 sleep(1);
936 fprintf(log, "****************************************\n");
937 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
938 id);
939 fprintf(log, "****************************************\n");
940 for (i = (*proc_traces[id].widx + 1);
941 i < (proc_traces[id].len - 8);
942 i++) {
943 fprintf(log, "%c",
944 *(char *)((uint32_t)proc_traces[id].va + i));
945 }
946 for (i = 0; i < *proc_traces[id].widx; i++) {
947 fprintf(log, "%c",
948 *(char *)((uint32_t)proc_traces[id].va + i));
949 }
950 }
951 }
952 fclose(log);
953 }
954 else {
955 GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
956 "error opening /var/log/ducati-m3-traces.log");
957 }
958 }
960 status = Ipc_destroy();
961 if (status < 0) {
962 printf("Ipc_destroy() failed 0x%x", status);
963 }
964 if (!recover) {
965 status = MemoryOS_destroy();
966 if (status < 0) {
967 printf("MemoryOS_destroy() failed 0x%x", status);
968 }
969 #if defined(SYSLINK_PLATFORM_OMAP4430)
970 if (dev->da_virt != MAP_FAILED) {
971 #ifdef SYSLINK_CARVEOUT
972 status = munmap(dev->da_virt, IPU_MEM_SIZE);
973 #else
974 status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
975 #endif
976 if (status < 0) {
977 printf("munmap failed %d", errno);
978 }
979 }
980 #endif
981 }
983 return status;
984 }
987 /* Read next line of available data for given 'core' and store it in buffer.
988 * Returns the number of bytes that were written or -1 on error
989 */
990 static int readNextTrace(int core, char* buffer, int bufSize)
991 {
992 char* readPtr;
993 uint32_t readBytes, ridx, widx;
994 syslink_trace_info* tinfo = &proc_traces[core];
996 /* Make sure it is valid */
997 if ( (tinfo == NULL) || (tinfo->va == NULL) ) {
998 return -1;
999 }
1001 /* Check to see if something to read */
1002 if (tinfo->ridx == tinfo->widx) {
1003 return 0;
1004 }
1006 readPtr = (char*) tinfo->va;
1007 ridx = *tinfo->ridx;
1008 widx = *tinfo->widx;
1010 /* If first read, make sure that core is ready by validating ridx, widx */
1011 if ( (tinfo->firstRead == TRUE) && ((ridx != 0) || (widx >= tinfo->len)) ) {
1012 // not ready - will try again later
1013 return 0;
1014 }
1016 /* Sanity check ridx/widx to make sure they point inside the buffer */
1017 if ( (ridx >= tinfo->len) || (widx >= tinfo->len) ) {
1018 Osal_printf("C%d: widx=%d, ridx=%d, len=%d - out of range",
1019 core, widx, ridx, tinfo->len);
1020 return -1;
1021 }
1023 readBytes = 0;
1024 tinfo->firstRead = FALSE;
1025 /* Read until we hit newline indicating end of trace */
1026 while ( (readPtr[ridx] != '\n') && (ridx != widx) && (readBytes < bufSize)) {
1027 buffer[readBytes] = readPtr[ridx];
1028 readBytes++;
1029 ridx++;
1030 // Check for wrap-around
1031 if (ridx == tinfo->len) {
1032 ridx = 0;
1033 }
1034 }
1036 /* If did not find newline, abort since either not enough info or no room in buffer */
1037 if (readPtr[ridx] != '\n') {
1038 if (readBytes >= bufSize) {
1039 Osal_printf("C%d: Insufficient size of buffer; read %d, buf %d",
1040 core, readBytes, bufSize);
1041 return -1;
1042 }
1043 return 0;
1044 }
1046 /* Newline may not be valid data if this was not ready to be read */
1047 if (ridx == widx) {
1048 return 0;
1049 }
1051 /* We read a full line - null terminate and update ridx to mark data read */
1052 if (readBytes < bufSize) {
1053 buffer[readBytes] = '\0';
1054 } else {
1055 Osal_printf("C%d: No room to write NULL character", core);
1056 return -1;
1057 }
1058 readBytes++;
1059 ridx++;
1060 if (ridx == tinfo->len) {
1061 ridx = 0;
1062 }
1063 *tinfo->ridx = ridx;
1065 return readBytes;
1066 }
1068 /* Thread reading ducati traces and writing them out to slog2 */
1069 static void *ducatiTraceThread(void *parm)
1070 {
1071 int32_t bytesRead;
1072 int core;
1073 int err;
1074 Bool exit = FALSE;
1076 pthread_setname_np(0, "ducati-trace");
1078 pthread_mutex_lock(&trace_mutex);
1079 while ( (trace_active == TRUE) && (exit == FALSE) ) {
1080 for (core = 0; core < MultiProc_MAXPROCESSORS; core++) {
1081 while ((bytesRead = readNextTrace(core, trace_buffer, TRACE_BUFFER_SIZE)) > 0) {
1082 #if (_NTO_VERSION >= 800)
1083 slog2f(buffer_handle, 0, 0, "C%d:%s", core, trace_buffer);
1084 #else
1085 slogf(42, _SLOG_NOTICE, "C%d:%s", core, trace_buffer);
1086 #endif
1087 if (trace_active == FALSE) {
1088 break;
1089 }
1090 }
1091 // Abort trace logger on errors as these should not occur
1092 if (bytesRead < 0) {
1093 trace_active = FALSE;
1094 }
1095 if (trace_active == FALSE) {
1096 break;
1097 }
1098 }
1099 if (trace_active == FALSE) {
1100 continue;
1101 }
1102 pthread_mutex_unlock(&trace_mutex);
1104 // No interrupts/events to trigger reading traces, so need to periodically poll
1105 usleep(TRACE_POLLING_INTERVAL_US);
1107 // If we are in hibernation, wait on condvar for end of hibernation
1108 pthread_mutex_lock(&syslink_hib_mutex);
1109 while ((syslink_hib_enable == TRUE) && (syslink_hib_hibernating == TRUE) ) {
1110 err = pthread_cond_wait(&syslink_hib_cond, &syslink_hib_mutex);
1111 if (err != EOK) {
1112 Osal_printf("pthread_cond_wait failed with err=%d", err);
1113 exit = TRUE;
1114 break;
1115 }
1116 }
1117 pthread_mutex_unlock(&syslink_hib_mutex);
1119 pthread_mutex_lock(&trace_mutex);
1120 }
1121 pthread_mutex_unlock(&trace_mutex);
1122 Osal_printf("ducati trace thread exited");
1123 return NULL;
1124 }
1126 /* Initialize slog2 for Ducati traces */
1127 static int init_ducati_slog2(void)
1128 {
1129 #if (_NTO_VERSION >= 800)
1130 slog2_buffer_set_config_t buffer_config;
1131 const char * buffer_set_name = "ducati";
1132 const char * buffer_name = "ducati_buffer";
1134 // Use command line verbosity for default verbosity level
1135 uint8_t verbosity_level = (uint8_t) verbosity;
1136 if ( verbosity_level > SLOG2_DEBUG2) {
1137 verbosity_level = SLOG2_DEBUG2;
1138 }
1140 // Initialize the buffer configuration
1141 buffer_config.buffer_set_name = (char *) buffer_set_name;
1142 buffer_config.num_buffers = 1;
1143 buffer_config.verbosity_level = verbosity_level;
1144 buffer_config.buffer_config[0].buffer_name = (char *) buffer_name;
1145 buffer_config.buffer_config[0].num_pages = 8;
1147 // Register the Buffer Set
1148 if( slog2_register( &buffer_config, &buffer_handle, 0 ) == -1 ) {
1149 Osal_printf("syslink error registering slogger2 buffer for Ducati!");
1150 return -1;
1151 }
1152 #endif
1154 return 0;
1155 }
1157 /** print usage */
1158 static Void printUsage (Char * app)
1159 {
1160 printf("\n\nUsage:\n");
1161 #if defined(SYSLINK_PLATFORM_OMAP5430)
1162 printf("\n%s: [-HT] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1163 app);
1164 printf(" <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1165 printf(" followed by the path to the executable to load on that core.\n");
1166 printf("Options:\n");
1167 printf(" -H enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
1168 printf(" -T specify the hibernation timeout in ms, Default: 5000 ms)\n");
1169 #else
1170 printf("\n%s: [-g] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1171 app);
1172 printf(" <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1173 printf(" followed by the path to the executable to load on that core.\n");
1174 printf("Options:\n");
1175 printf(" -g enable GateMP support on host\n");
1176 #endif
1177 exit (EXIT_SUCCESS);
1178 }
1180 dispatch_t * syslink_dpp = NULL;
1182 int main(int argc, char *argv[])
1183 {
1184 syslink_dev_t * dev = NULL;
1185 thread_pool_attr_t tattr;
1186 int status;
1187 int error = 0;
1188 sigset_t set;
1189 int channelid = 0;
1190 int c;
1191 int hib_enable = 1;
1192 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1193 char *user_parm = NULL;
1194 struct stat sbuf;
1195 int i = 0;
1196 char * abs_path = NULL;
1198 if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1199 printf ("Syslink Already Running...\n");
1200 return EXIT_FAILURE;
1201 }
1202 printf ("Starting syslink resource manager...\n");
1204 /* Parse the input args */
1205 while (1)
1206 {
1207 c = getopt (argc, argv, "H:T:U:gv:");
1208 if (c == -1)
1209 break;
1211 switch (c)
1212 {
1213 #if defined(SYSLINK_PLATFORM_OMAP5430)
1214 case 'H':
1215 hib_enable = atoi(optarg);
1216 if (hib_enable != 0 && hib_enable != 1) {
1217 hib_enable = -1;
1218 }
1219 break;
1220 case 'T':
1221 hib_timeout = atoi(optarg);
1222 break;
1223 #endif
1224 case 'U':
1225 user_parm = optarg;
1226 break;
1227 case 'v':
1228 verbosity++;
1229 break;
1230 #if defined(SYSLINK_PLATFORM_VAYU)
1231 case 'g':
1232 printf("GateMP support enabled on host\n");
1233 gatempEnabled = true;
1234 break;
1235 #endif
1236 default:
1237 fprintf (stderr, "Unrecognized argument\n");
1238 }
1239 }
1241 /* Now parse the operands, which should be in the format:
1242 * "<multiproc_name> <firmware_file> ..*/
1243 for (; optind + 1 < argc; optind+=2) {
1244 if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1245 printUsage(argv[0]);
1246 return (error);
1247 }
1248 syslink_firmware[syslink_num_cores].proc = argv [optind];
1249 syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1250 }
1253 /* Get the name of the binary from the input args */
1254 if (!syslink_num_cores) {
1255 fprintf(stderr, "At least one core_id and executable must be "\
1256 "specified");
1257 printUsage(argv[0]);
1258 return (error);
1259 }
1261 /* Validate hib_enable args */
1262 if (hib_enable == -1) {
1263 fprintf (stderr, "invalid hibernation enable value\n");
1264 printUsage(argv[0]);
1265 return (error);
1266 }
1268 syslink_hib_enable = (Bool)hib_enable;
1269 syslink_hib_timeout = hib_timeout;
1271 /* Init logging for syslink */
1272 if (Osal_initlogging(verbosity) != 0) {
1273 return -1;
1274 }
1276 /* Obtain I/O privity */
1277 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1278 if (error == -1) {
1279 Osal_printf("Unable to obtain I/O privity");
1280 return (error);
1281 }
1283 /* Get the abs path for all firmware files */
1284 for (i = 0; i < syslink_num_cores; i++) {
1285 abs_path = calloc(1, PATH_MAX + 1);
1286 if (abs_path == NULL) {
1287 return -1;
1288 }
1289 if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1290 fprintf (stderr, "invalid path to executable\n");
1291 return -1;
1292 }
1293 syslink_firmware[i].firmware = abs_path;
1294 }
1296 /* allocate the device structure */
1297 if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1298 Osal_printf("syslink: calloc() failed");
1299 return (-1);
1300 }
1302 /* create the channel */
1303 if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1304 _NTO_CHF_DISCONNECT |
1305 _NTO_CHF_COID_DISCONNECT |
1306 _NTO_CHF_REPLY_LEN |
1307 _NTO_CHF_SENDER_LEN)) < 0) {
1308 Osal_printf("Unable to create channel %d", channelid);
1309 return (channelid);
1310 }
1312 /* create the dispatch structure */
1313 if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1314 Osal_printf("syslink: dispatch_create() failed");
1315 return(-1);
1316 }
1318 /* Initialize the thread pool */
1319 memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1320 tattr.handle = dev->dpp;
1321 tattr.context_alloc = dispatch_context_alloc;
1322 tattr.context_free = dispatch_context_free;
1323 tattr.block_func = dispatch_block;
1324 tattr.unblock_func = dispatch_unblock;
1325 tattr.handler_func = dispatch_handler;
1326 tattr.lo_water = 2;
1327 tattr.hi_water = 4;
1328 tattr.increment = 1;
1329 tattr.maximum = 10;
1331 /* Create the thread pool */
1332 if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1333 Osal_printf("syslink: thread pool create failed");
1334 return(-1);
1335 }
1337 /* init syslink */
1338 status = init_ipc(dev, syslink_firmware, FALSE);
1339 if (status < 0) {
1340 Osal_printf("syslink: IPC init failed");
1341 return(-1);
1342 }
1344 /* init the syslink device */
1345 status = init_devices(dev);
1346 if (status < 0) {
1347 Osal_printf("syslink: device init failed");
1348 return(-1);
1349 }
1351 #if (_NTO_VERSION >= 800)
1352 /* Relinquish privileges */
1353 status = procmgr_ability( 0,
1354 DENY_ALL | PROCMGR_AID_SPAWN,
1355 DENY_ALL | PROCMGR_AID_FORK,
1356 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1357 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1358 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1359 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1360 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1361 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1362 (uint64_t)1, (uint64_t)~0,
1363 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1364 (uint64_t)1, (uint64_t)~0,
1365 PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1367 if (status != EOK) {
1368 Osal_printf("procmgr_ability failed! errno=%d", status);
1369 return EXIT_FAILURE;
1370 }
1372 /* Reduce priority to either what defined from command line or at least nobody */
1373 if (user_parm != NULL) {
1374 if (set_ids_from_arg(user_parm) < 0) {
1375 Osal_printf("unable to set uid/gid - %s", strerror(errno));
1376 return EXIT_FAILURE;
1377 }
1378 } else {
1379 if (setuid(99) != 0) {
1380 Osal_printf("unable to set uid - %s", strerror(errno));
1381 return EXIT_FAILURE;
1382 }
1383 }
1384 #endif
1386 /* make this a daemon process */
1387 if (-1 == procmgr_daemon(EXIT_SUCCESS,
1388 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1389 Osal_printf("syslink: procmgr_daemon() failed");
1390 return(-1);
1391 }
1393 /* start the thread pool */
1394 thread_pool_start(dev->tpool);
1396 /* Init slog2 and thread for Ducati traces */
1397 if (init_ducati_slog2() != 0) {
1398 return -1;
1399 }
1400 trace_active = TRUE;
1401 status = pthread_create (&thread_traces, NULL, ducatiTraceThread, NULL);
1402 if (status != EOK) {
1403 Osal_printf("pthread_create for trace thread failed err=%d", status);
1404 trace_active = FALSE;
1405 }
1407 /* Mask out unnecessary signals */
1408 sigfillset (&set);
1409 sigdelset (&set, SIGINT);
1410 sigdelset (&set, SIGTERM);
1411 pthread_sigmask (SIG_BLOCK, &set, NULL);
1413 /* Wait for one of these signals */
1414 sigemptyset (&set);
1415 sigaddset (&set, SIGINT);
1416 sigaddset (&set, SIGQUIT);
1417 sigaddset (&set, SIGTERM);
1419 Osal_printf("Syslink resource manager started");
1421 /* Wait for a signal */
1422 while (1)
1423 {
1424 switch (SignalWaitinfo (&set, NULL))
1425 {
1426 case SIGTERM:
1427 case SIGQUIT:
1428 case SIGINT:
1429 error = EOK;
1430 goto done;
1432 default:
1433 break;
1434 }
1435 }
1437 error = EOK;
1439 done:
1440 GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1441 /* Stop ducatiTraceThread if running */
1442 pthread_mutex_lock(&trace_mutex);
1443 if (trace_active) {
1444 trace_active = FALSE;
1445 pthread_mutex_unlock(&trace_mutex);
1446 // Wake up if waiting on hibernation
1447 pthread_mutex_lock(&syslink_hib_mutex);
1448 syslink_hib_hibernating = FALSE;
1449 pthread_cond_broadcast(&syslink_hib_cond);
1450 pthread_mutex_unlock(&syslink_hib_mutex);
1451 error = pthread_join(thread_traces, NULL);
1452 if (error < 0) {
1453 Osal_printf("syslink: pthread_join failed with err=%d", error);
1454 }
1455 } else {
1456 pthread_mutex_unlock(&trace_mutex);
1457 }
1459 error = thread_pool_destroy(dev->tpool);
1460 if (error < 0)
1461 Osal_printf("syslink: thread_pool_destroy returned an error");
1462 deinit_ipc(dev, FALSE);
1463 deinit_devices(dev);
1464 free(dev);
1465 return (EOK);
1466 }