[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / rpmsg-omx / hlos / knl / Qnx / mmap_peer.c
1 /*
2 * $QNXLicenseC$
3 */
4 /*
5 * Copyright (c) 2010, Texas Instruments Incorporated
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * * Neither the name of Texas Instruments Incorporated nor the names of
20 * its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
33 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * */
35 /*
36 * mmap_peer/munmap_peer implementation PR47400
37 */
39 #include <unistd.h>
40 #include <errno.h>
41 #include <inttypes.h>
42 #include <sys/mman.h>
43 #include <sys/memmsg.h>
45 #include "proto.h"
48 int memmgr_peer_sendnc( pid_t pid, int coid, void *smsg, size_t sbytes, void *rmsg, size_t rbytes )
49 {
50 mem_peer_t peer;
51 iov_t siov[2];
53 peer.i.type = _MEM_PEER;
54 peer.i.peer_msg_len = sizeof(peer);
55 peer.i.pid = pid;
57 SETIOV(siov + 0, &peer, sizeof peer);
58 SETIOV(siov + 1, smsg, sbytes);
59 return MsgSendvsnc( coid, siov, 2, rmsg, rbytes );
60 }
62 void *
63 _mmap2_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off,
64 unsigned align, unsigned pre_load, void **base, size_t *size) {
65 mem_map_t msg;
67 msg.i.type = _MEM_MAP;
68 msg.i.zero = 0;
69 msg.i.addr = (uintptr_t)addr;
70 msg.i.len = len;
71 msg.i.prot = prot;
72 msg.i.flags = flags;
73 msg.i.fd = fd;
74 msg.i.offset = off;
75 msg.i.align = align;
76 msg.i.preload = pre_load;
77 msg.i.reserved1 = 0;
78 if(memmgr_peer_sendnc(pid, MEMMGR_COID, &msg.i, sizeof msg.i, &msg.o, sizeof msg.o) == -1) {
79 return MAP_FAILED;
80 }
81 if(base) {
82 *base = (void *)(uintptr_t)msg.o.real_addr;
83 }
84 if(size) {
85 *size = msg.o.real_size;
86 }
87 return (void *)(uintptr_t)msg.o.addr;
88 }
91 void *
92 mmap64_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off) {
93 return _mmap2_peer(pid, addr, len, prot, flags, fd, off, 0, 0, 0, 0);
94 }
97 // Make an unsigned version of the 'off_t' type so that we get a zero
98 // extension down below.
99 #if __OFF_BITS__ == 32
100 typedef _Uint32t uoff_t;
101 #elif __OFF_BITS__ == 64
102 typedef _Uint64t uoff_t;
103 #else
104 #error Do not know what size to make uoff_t
105 #endif
107 void *
108 mmap_peer(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off_t off) {
109 return _mmap2_peer(pid, addr, len, prot, flags, fd, (uoff_t)off, 0, 0, 0, 0);
110 }
112 int
113 munmap_flags_peer(pid_t pid, void *addr, size_t len, unsigned flags) {
114 mem_ctrl_t msg;
116 msg.i.type = _MEM_CTRL;
117 msg.i.subtype = _MEM_CTRL_UNMAP;
118 msg.i.addr = (uintptr_t)addr;
119 msg.i.len = len;
120 msg.i.flags = flags;
121 return memmgr_peer_sendnc(pid, MEMMGR_COID, &msg.i, sizeof msg.i, 0, 0);
122 }
124 int
125 munmap_peer(pid_t pid, void *addr, size_t len) {
126 return munmap_flags_peer(pid, addr, len, 0);
127 }
129 int
130 mem_offset64_peer(pid_t pid, const uintptr_t addr, size_t len,
131 off64_t *offset, size_t *contig_len) {
132 struct _peer_mem_off {
133 struct _mem_peer peer;
134 struct _mem_offset msg;
135 };
136 typedef union {
137 struct _peer_mem_off i;
138 struct _mem_offset_reply o;
139 } memoffset_peer_t;
140 memoffset_peer_t msg;
142 msg.i.peer.type = _MEM_PEER;
143 msg.i.peer.peer_msg_len = sizeof(msg.i.peer);
144 msg.i.peer.pid = pid;
145 msg.i.peer.reserved1 = 0;
147 msg.i.msg.type = _MEM_OFFSET;
148 msg.i.msg.subtype = _MEM_OFFSET_PHYS;
149 msg.i.msg.addr = addr;
150 msg.i.msg.reserved = -1;
151 msg.i.msg.len = len;
152 if(MsgSendnc(MEMMGR_COID, &msg.i, sizeof msg.i, &msg.o, sizeof msg.o) == -1) {
153 return -1;
154 }
155 *offset = msg.o.offset;
156 *contig_len = msg.o.size;
157 return(0);
158 }
161 #if defined(__X86__)
162 #define CPU_VADDR_SERVER_HINT 0x30000000u
163 #elif defined(__ARM__)
164 #define CPU_VADDR_SERVER_HINT 0x20000000u
165 #else
166 #error NO CPU SOUP FOR YOU!
167 #endif
169 /*
170 * map the object into both client and server at the same virtual address
171 */
172 void *
173 mmap64_join(pid_t pid, void *addr, size_t len, int prot, int flags, int fd, off64_t off) {
174 void *svaddr, *cvaddr = MAP_FAILED;
175 uintptr_t hint = (uintptr_t)addr;
176 uintptr_t start_hint = hint;
178 if ( hint == 0 ) hint = (uintptr_t)CPU_VADDR_SERVER_HINT;
180 do {
181 svaddr = mmap64( (void *)hint, len, prot, flags, fd, off );
182 if ( svaddr == MAP_FAILED ) {
183 break;
184 }
185 if ( svaddr == cvaddr ) {
186 return svaddr;
187 }
189 cvaddr = mmap64_peer( pid, svaddr, len, prot, flags, fd, off );
190 if ( cvaddr == MAP_FAILED ) {
191 break;
192 }
193 if ( svaddr == cvaddr ) {
194 return svaddr;
195 }
197 if ( munmap( svaddr, len ) == -1 ) {
198 svaddr = MAP_FAILED;
199 break;
200 }
202 svaddr = mmap64( cvaddr, len, prot, flags, fd, off );
203 if ( svaddr == MAP_FAILED ) {
204 break;
205 }
206 if ( svaddr == cvaddr ) {
207 return svaddr;
208 }
210 if ( munmap( svaddr, len ) == -1 ) {
211 svaddr = MAP_FAILED;
212 break;
213 }
214 if ( munmap_peer( pid, cvaddr, len ) == -1 ) {
215 cvaddr = MAP_FAILED;
216 break;
217 }
219 hint += __PAGESIZE;
221 } while(hint != start_hint); /* do we really want to wrap all the way */
223 if ( svaddr != MAP_FAILED ) {
224 munmap( svaddr, len );
225 }
226 if ( cvaddr != MAP_FAILED ) {
227 munmap_peer( pid, cvaddr, len );
228 }
229 return MAP_FAILED;
230 }