Add FD_CLOEXEC flag for sockets, /dev/mem and LAD pipes
[ipc/ipcdev.git] / linux / src / daemon / GateMP_daemon.c
1 /*
2  * Copyright (c) 2013-2015, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /*
34  *  ======== GateMP_daemon.c ========
35  */
38 /* Standard headers */
39 #include <ti/ipc/Std.h>
41 /* Linux specific header files */
42 #include <pthread.h>
44 /* System headers */
45 #include <sys/mman.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <stdlib.h>
49 #include <assert.h>
51 /* Module level headers */
52 #include <ti/ipc/GateMP.h>
53 #include <ti/ipc/NameServer.h>
54 #include <ti/ipc/MultiProc.h>
55 #include <_MultiProc.h>
56 #include <GateMP_config.h>
57 #include <_GateMP.h>
59 #include <IGateProvider.h>
60 #include <_GateMP_daemon.h>
61 #include <_lad.h>
63 #if defined (__cplusplus)
64 extern "C" {
65 #endif
67 #define NUM_INFO_FIELDS       6    /* Number of fields in info entry */
69 /* Values used to populate the resource 'inUse' arrays */
70 #define UNUSED          ((UInt8)0)
71 #define USED            ((UInt8)1)
72 #define RESERVED        ((UInt8)-1)
74 /* Name of GateMP's nameserver */
75 #define GateMP_NAMESERVER  "GateMP"
77 #define PAGE_ALIGN(size, psz)  (((size) + psz - 1) & ~(psz -1))
79 /* =============================================================================
80  * Structures & Enums
81  * =============================================================================
82  */
84 /* structure for GateMP module state */
85 typedef struct {
86     Int               numRemoteSystem;
87     Int               numRemoteCustom1;
88     Int               numRemoteCustom2;
89     UInt8 *           remoteSystemInUse;
90     UInt8 *           remoteCustom1InUse;
91     UInt8 *           remoteCustom2InUse;
92     GateMP_Handle     defaultGate;
93     NameServer_Handle nameServer;
94     Bool              isSetup;
95     Int               refCount[MultiProc_MAXPROCESSORS];
96     UInt16            attachedProcId;
97 } GateMP_ModuleObject;
99 /* Internal functions */
100 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr, UInt16 procId[]);
101 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
103 /* =============================================================================
104  *  Globals
105  * =============================================================================
106  */
107 /*
108  * GateMP_state
109  */
110 static GateMP_ModuleObject GateMP_state = {
111     .numRemoteSystem                 = 0,
112     .numRemoteCustom1                = 0,
113     .numRemoteCustom2                = 0,
114     .remoteSystemInUse               = NULL,
115     .remoteCustom1InUse              = NULL,
116     .remoteCustom2InUse              = NULL,
117     .defaultGate                     = NULL,
118     .nameServer                      = NULL,
119     .isSetup                         = FALSE,
120     .refCount                        = {0},
121     .attachedProcId                  = MultiProc_INVALIDID,
122 };
124 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
126 /* =============================================================================
127  * APIS
128  * =============================================================================
129  */
131 /*
132  * Function to setup the gatemp module.
133  *
134  * No need to refCount this since it's not callable by user.
135  */
136 Int GateMP_setup(Void)
138     Int               status = GateMP_S_SUCCESS;
139     NameServer_Params params;
141     NameServer_Params_init(&params);
142     params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
143     params.maxNameLen = MAX_NAME_LEN;
145     /* Assume info entry has more fields than other entries */
146     params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
148     GateMP_module->nameServer =
149                 NameServer_create(GateMP_NAMESERVER, &params);
151     if (GateMP_module->nameServer == NULL) {
152         status = GateMP_E_FAIL;
153         LOG0("GateMP_setup: NameServer_create failed\n");
154     }
155     else {
156         GateMP_module->isSetup = TRUE;
157     }
159     return status;
162 Int GateMP_attach(UInt16 procId)
164     GateMP_Handle     deflateGate;  /* that's right, Pats fan here */
165     Int               status = GateMP_S_SUCCESS;
166     UInt32            nsValue[NUM_INFO_FIELDS];
167     UInt32            len;
168     UInt32            size;
169     UInt32            alignDiff;
170     UInt32            offset;
171     Int32             fdMem;
172     UInt16            procList[2];
173     UInt16            clId;
175     /* procId already validated in API layer */
176     clId = procId - MultiProc_getBaseIdOfCluster();
177     if (clId >= MultiProc_getNumProcsInCluster()) {
178         LOG1("GateMP_attach: procId %d not in range for local cluster\n",
179              procId);
180         return GateMP_E_INVALIDARG;
181     }
183     /* must reference count because we have multiple clients */
184     if (GateMP_module->refCount[clId] > 0) {
185         GateMP_module->refCount[clId]++;
186         goto done;
187     }
189     procList[0] = procId;
190     procList[1] = MultiProc_INVALIDID;
191     status = GateMP_openDefaultGate(&deflateGate, procList);
193     if (status < 0) {
194         LOG1("GateMP_attach: failed to open default gate on procId %d\n",
195              procId);
196         goto done;
197     }
199     if (status == GateMP_S_SUCCESS) {
200         if (GateMP_module->attachedProcId != MultiProc_INVALIDID) {
201             LOG1("GateMP_attach: can't attach to procId %d\n", procId);
202             LOG1("               already attached to %d\n",
203                  GateMP_module->attachedProcId);
204             status = GateMP_E_ALREADYEXISTS;
205             goto done;
206         }
208         GateMP_module->attachedProcId = procId;
209         GateMP_module->defaultGate = deflateGate;
211         GateMP_module->refCount[clId]++;
213         /* Process global info NameServer entry */
214         len = sizeof(nsValue);
216         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
217             &nsValue, &len, procList);
219         if (status < 0) {
220             LOG0("GateMP_attach: failed to find info entry\n");
221             status = GateMP_E_NOTFOUND;
222         }
223         else {
224             fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
226             if (fdMem < 0){
227                 LOG0("GateMP_attach: failed to open the /dev/mem!\n");
228                 status = GateMP_E_OSFAILURE;
229                 goto done;
230             }
232             GateMP_module->numRemoteSystem = nsValue[3];
233             GateMP_module->numRemoteCustom1 = nsValue[4];
234             GateMP_module->numRemoteCustom2 = nsValue[5];
236             /* Map InUse arrays to daemon's address space */
237             size = GateMP_module->numRemoteSystem * sizeof (UInt8) +
238                 (nsValue[0] & (sysconf(_SC_PAGE_SIZE) - 1));
239             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
240             offset = nsValue[0] & ~(sysconf(_SC_PAGE_SIZE) - 1);
241 #if defined(IPC_BUILDOS_ANDROID)
242             GateMP_module->remoteSystemInUse = mmap64(NULL, size,
243                 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
244                 (off64_t)offset);
245 #else
246             GateMP_module->remoteSystemInUse = mmap(NULL, size,
247                 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
248                 (off_t)offset);
249 #endif
250             if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
251                  LOG1("Failed to map remoteSystemInUse=0x%p to host address" \
252                       "  space!", GateMP_module->remoteSystemInUse);
253                  GateMP_module->remoteSystemInUse = NULL;
254                  status = GateMP_E_MEMORY;
255             }
256             else {
257                 alignDiff = nsValue[0] - offset;
258                 GateMP_module->remoteSystemInUse =
259                     GateMP_module->remoteSystemInUse + alignDiff;
260             }
262             size = GateMP_module->numRemoteCustom1 * sizeof (UInt8) +
263                 (nsValue[1] & (sysconf(_SC_PAGE_SIZE) - 1));
264             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
265             offset = nsValue[1] & ~(sysconf(_SC_PAGE_SIZE) - 1);
266             if (status == GateMP_S_SUCCESS) {
267 #if defined(IPC_BUILDOS_ANDROID)
268                 GateMP_module->remoteCustom1InUse = mmap64(NULL, size,
269                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
270                     (off64_t)offset);
271 #else
272                 GateMP_module->remoteCustom1InUse = mmap(NULL, size,
273                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
274                     (off_t)offset);
275 #endif
276                 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
277                     LOG1("Failed to map remoteCustom1InUse=%p to host address" \
278                         " space!", GateMP_module->remoteCustom1InUse);
279                     GateMP_module->remoteCustom1InUse = NULL;
280                     status = GateMP_E_MEMORY;
281                 }
282                 else {
283                     alignDiff = nsValue[1] - offset;
284                     GateMP_module->remoteCustom1InUse =
285                         GateMP_module->remoteCustom1InUse + alignDiff;
286                 }
287             }
289             size = GateMP_module->numRemoteCustom2 * sizeof (UInt8) +
290                 (nsValue[2] & (sysconf(_SC_PAGE_SIZE) - 1));
291             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
292             offset = nsValue[2] & ~(sysconf(_SC_PAGE_SIZE) - 1);
293             if (status == GateMP_S_SUCCESS) {
294 #if defined(IPC_BUILDOS_ANDROID)
295                 GateMP_module->remoteCustom2InUse = mmap64(NULL, size,
296                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
297                     (off64_t)offset);
298 #else
299                 GateMP_module->remoteCustom2InUse = mmap(NULL, size,
300                     (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
301                     (off_t)offset);
302 #endif
303                 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
304                     LOG1("Failed to map remoteCustom2InUse=%p to host address" \
305                         " space!", GateMP_module->remoteCustom2InUse);
306                     GateMP_module->remoteCustom2InUse = NULL;
307                     status = GateMP_E_MEMORY;
308                 }
309                 else {
310                     alignDiff = nsValue[2] - offset;
311                     GateMP_module->remoteCustom2InUse =
312                         GateMP_module->remoteCustom2InUse + alignDiff;
313                 }
314             }
315         }
316     }
318     /* TODO: setup the proxy map */
320 done:
322     return (status);
325 Int GateMP_detach(UInt16 procId)
327     UInt16 clId;
329     if (procId != GateMP_module->attachedProcId) {
330         return GateMP_E_NOTFOUND;
331     }
333     /* procId already validated in API layer */
334     clId = procId - MultiProc_getBaseIdOfCluster();
335     if (clId >= MultiProc_getNumProcsInCluster()) {
336         LOG1("GateMP_detach: procId %d not in range for local cluster\n",
337              procId);
338         return GateMP_E_INVALIDARG;
339     }
342     /* decrement reference count regardless of outcome below */
343     if (--GateMP_module->refCount[clId] > 0) {
344         goto done;
345     }
347     if (GateMP_module->remoteSystemInUse) {
348         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
349             GateMP_module->numRemoteSystem * sizeof (UInt8));
350         GateMP_module->remoteSystemInUse = NULL;
351     }
353     if (GateMP_module->remoteCustom1InUse) {
354         munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
355             GateMP_module->numRemoteCustom1 * sizeof (UInt8));
356         GateMP_module->remoteCustom1InUse = NULL;
357     }
359     if (GateMP_module->remoteCustom2InUse) {
360         munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
361             GateMP_module->numRemoteCustom2 * sizeof (UInt8));
362         GateMP_module->remoteCustom2InUse = NULL;
363     }
365     if (GateMP_module->defaultGate) {
366         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
367         GateMP_module->attachedProcId = MultiProc_INVALIDID;
368     }
370 done:
372     return GateMP_S_SUCCESS;
375 Void GateMP_destroy(Void)
377     if (GateMP_module->nameServer) {
378         NameServer_delete(&GateMP_module->nameServer);
379         GateMP_module->nameServer = NULL;
380     }
382     GateMP_module->isSetup = FALSE;
384     return;
387 /* Open default gate during GateMP_attach. Should only be called once */
388 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr, UInt16 procId[])
390     Int             status = GateMP_S_SUCCESS;
391     UInt32          len;
392     UInt32          nsValue[4];
393     GateMP_Object * obj = NULL;
394     UInt32          arg;
395     UInt32          mask;
397     GateMP_RemoteSystemProxy_Params     systemParams;
399     /* assert that a valid pointer has been supplied */
400     if (handlePtr == NULL) {
401         LOG0("GateMP_openDefaultGate: argument cannot be null\n");
402         status = GateMP_E_INVALIDARG;
403     }
405     if (status == GateMP_S_SUCCESS) {
406         len = sizeof(nsValue);
408         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
409             &nsValue, &len, procId);
411         if (status < 0) {
412             *handlePtr = NULL;
413             status = GateMP_E_NOTFOUND;
414         }
415         else {
416             arg = nsValue[2];
417             mask = nsValue[3];
418         }
419     }
421     if (status == GateMP_S_SUCCESS) {
422         /* allocate the instance object */
423         obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
424         if (obj != NULL) {
425             obj->localGate  = NULL;  /* TODO: create the local gate instance */
426             obj->localProtect  = GETLOCAL(mask);
427             obj->remoteProtect = GETREMOTE(mask);
428             obj->nsKey         = 0;
429             obj->numOpens      = 1;
430             obj->objType       = Ipc_ObjType_OPENDYNAMIC;
431             obj->resourceId    = arg;
433             assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
435             /* create the proxy object */
436             GateMP_RemoteSystemProxy_Params_init(&systemParams);
437             systemParams.resourceId = obj->resourceId;
438             systemParams.openFlag = TRUE;
440             /*
441              * TODO: Currently passing in localProtect instead of localGate,
442              * since GateHWSpinlock owns the local gate
443              */
444             obj->gateHandle = (IGateProvider_Handle)
445                 GateMP_RemoteSystemProxy_create(obj->localProtect,
446                     &systemParams);
448             if (obj->gateHandle == NULL) {
449                 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
450                 free(obj);
451                 obj = NULL;
452             }
453         }
454         else {
455             LOG0("GateMP_openDefaultGate: Memory allocation failed")
456         }
458         if (obj == NULL) {
459             status = GateMP_E_FAIL;
460         }
461     }
463     /* Return the "opened" GateMP instance  */
464     *handlePtr = (GateMP_Handle)obj;
466     return status;
469 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
471     Int status = GateMP_S_SUCCESS;
472     GateMP_Object * obj = *(GateMP_Object **)handlePtr;
474     if (obj->gateHandle != NULL) {
475         /* Default gate is always of type System when more than 1 processor */
476         GateMP_RemoteSystemProxy_delete(
477             (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
478     }
480     free(*handlePtr);
481     *handlePtr = NULL;
483     return(status);
486 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
488     IArg   key;
489     Bool   flag = FALSE;
490     Int    resourceId = -1;
491     UInt8* inUse = NULL;
492     Int    num = 0;
494     /* Remote case */
495     switch (type) {
496         /* TODO: currently only support System proxy */
497         case GateMP_RemoteProtect_SYSTEM:
498         case GateMP_RemoteProtect_CUSTOM1:
499         case GateMP_RemoteProtect_CUSTOM2:
500             inUse = GateMP_module->remoteSystemInUse;
501             num = GateMP_module->numRemoteSystem;
502             break;
504         default:
505             LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
506             break;
507     }
509     if (inUse != NULL) {
510         assert(GateMP_module->defaultGate != NULL);
511         key = GateMP_enter(GateMP_module->defaultGate);
513         /*
514          *  Find a free resource id. Note: zero is reserved on the
515          *  system proxy for the default gate.
516          */
517         for (resourceId = 0; resourceId < num; resourceId++) {
518             /*
519              *  If not in-use, set the inUse to TRUE to prevent other
520              *  creates from getting this one.
521              */
522             if (inUse[resourceId] == UNUSED) {
523                 flag = TRUE;
525                 /* Denote in shared memory that the resource is used */
526                 inUse[resourceId] = USED;
527                 break;
528             }
529         }
531         GateMP_leave(GateMP_module->defaultGate, key);
532     }
534     if (flag == FALSE) {
535         resourceId = -1;
536     }
538     return (resourceId);
541 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
543     Int    status = GateMP_S_SUCCESS;
544     IArg   key;
545     UInt8* inUse = NULL;
546     Int    num = 0;
548     /* Remote case */
549     switch (type) {
550         /* TODO: currently only support System proxy */
551         case GateMP_RemoteProtect_SYSTEM:
552         case GateMP_RemoteProtect_CUSTOM1:
553         case GateMP_RemoteProtect_CUSTOM2:
554             inUse = GateMP_module->remoteSystemInUse;
555             num = GateMP_module->numRemoteSystem;
556             break;
558         default:
559             LOG0("GateMP_releaseResource: Invalid remote protection type\n");
560             status = GateMP_E_FAIL;
561             break;
562     }
564     if ((inUse != NULL) && (id < num)) {
565         assert(GateMP_module->defaultGate != NULL);
566         key = GateMP_enter(GateMP_module->defaultGate);
567         inUse[id] = UNUSED;
568         GateMP_leave(GateMP_module->defaultGate, key);
569     }
570     else {
571         /* Should not happen if module is properly setup */
572         status = GateMP_E_FAIL;
573     }
575     return (status);
578 Int GateMP_getNumResources(GateMP_RemoteProtect type)
580     Int   num = -1;
582     /* Remote case */
583     switch (type) {
584         /* TODO: currently only support System proxy */
585         case GateMP_RemoteProtect_SYSTEM:
586         case GateMP_RemoteProtect_CUSTOM1:
587         case GateMP_RemoteProtect_CUSTOM2:
588             num = GateMP_module->numRemoteSystem;
589             break;
591         default:
592             LOG0("GateMP_getNumResources: Invalid remote protection type\n");
593             break;
594     }
596     return (num);
599 NameServer_Handle GateMP_getNameServer(Void)
601     return (GateMP_module->nameServer);
604 Bool GateMP_isSetup(Void)
606     return (GateMP_module->isSetup);
609 IArg GateMP_enter(GateMP_Handle handle)
611     GateMP_Object * obj;
612     IArg            key;
614     obj = (GateMP_Object *)handle;
615     key = IGateProvider_enter(obj->gateHandle);
617     return(key);
620 Void GateMP_leave(GateMP_Handle handle, IArg key)
622     GateMP_Object *obj;
624     obj = (GateMP_Object *)handle;
625     IGateProvider_leave(obj->gateHandle, key);