blob: bf0a1361e4abf13afc93033ccb3347988b02c758 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
Florin Corasc5df8c72019-04-08 07:42:30 -07002 * Copyright (c) 2015-2019 Cisco and/or its affiliates.
Ed Warnickecb9cada2015-12-08 15:45:58 -07003 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
Florin Coras4d9b9d82018-01-14 12:25:50 -080015#include <svm/ssvm.h>
16#include <svm/svm_common.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070017
Florin Corasb384b542018-01-15 01:08:33 -080018typedef int (*init_fn) (ssvm_private_t *);
19typedef void (*delete_fn) (ssvm_private_t *);
20
Florin Coras5220a262020-09-29 18:11:24 -070021static init_fn server_init_fns[SSVM_N_SEGMENT_TYPES] =
22 { ssvm_server_init_shm, ssvm_server_init_memfd, ssvm_server_init_private };
23static init_fn client_init_fns[SSVM_N_SEGMENT_TYPES] =
24 { ssvm_client_init_shm, ssvm_client_init_memfd, ssvm_client_init_private };
Florin Corasb384b542018-01-15 01:08:33 -080025static delete_fn delete_fns[SSVM_N_SEGMENT_TYPES] =
Florin Corasa332c462018-01-31 06:52:17 -080026 { ssvm_delete_shm, ssvm_delete_memfd, ssvm_delete_private };
Florin Corasb384b542018-01-15 01:08:33 -080027
Dave Barach8a7fb0c2016-07-08 14:44:23 -040028int
Florin Coras5220a262020-09-29 18:11:24 -070029ssvm_server_init_shm (ssvm_private_t * ssvm)
Ed Warnickecb9cada2015-12-08 15:45:58 -070030{
Dave Barach6a5adc32018-07-04 10:56:23 -040031 int ssvm_fd;
Florin Corasb384b542018-01-15 01:08:33 -080032 u8 junk = 0, *ssvm_filename;
Dave Barach8a7fb0c2016-07-08 14:44:23 -040033 ssvm_shared_header_t *sh;
Florin Corasf8f516a2018-02-08 15:10:09 -080034 uword page_size, requested_va = 0;
Dave Barach8a7fb0c2016-07-08 14:44:23 -040035 void *oldheap;
Ed Warnickecb9cada2015-12-08 15:45:58 -070036
37 if (ssvm->ssvm_size == 0)
38 return SSVM_API_ERROR_NO_SIZE;
39
Dave Wallaced756b352017-07-03 13:11:38 -040040 if (CLIB_DEBUG > 1)
41 clib_warning ("[%d] creating segment '%s'", getpid (), ssvm->name);
42
Dave Wallaceb8856642017-07-31 13:33:11 -040043 ASSERT (vec_c_string_is_terminated (ssvm->name));
Ed Warnickecb9cada2015-12-08 15:45:58 -070044 ssvm_filename = format (0, "/dev/shm/%s%c", ssvm->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -070045 unlink ((char *) ssvm_filename);
Dave Barach8a7fb0c2016-07-08 14:44:23 -040046 vec_free (ssvm_filename);
Ed Warnickecb9cada2015-12-08 15:45:58 -070047
Dave Barach8a7fb0c2016-07-08 14:44:23 -040048 ssvm_fd = shm_open ((char *) ssvm->name, O_RDWR | O_CREAT | O_EXCL, 0777);
Ed Warnickecb9cada2015-12-08 15:45:58 -070049 if (ssvm_fd < 0)
50 {
51 clib_unix_warning ("create segment '%s'", ssvm->name);
52 return SSVM_API_ERROR_CREATE_FAILURE;
53 }
54
Dave Wallace19296112017-08-31 15:54:11 -040055 if (fchmod (ssvm_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0)
56 clib_unix_warning ("ssvm segment chmod");
Florin Coras65784c12018-07-04 04:17:41 -070057 if (svm_get_root_rp ())
58 {
59 /* TODO: is this really needed? */
60 svm_main_region_t *smr = svm_get_root_rp ()->data_base;
61 if (fchown (ssvm_fd, smr->uid, smr->gid) < 0)
62 clib_unix_warning ("ssvm segment chown");
63 }
Dave Wallace19296112017-08-31 15:54:11 -040064
Dave Barach56faee82016-08-04 18:58:05 -040065 if (lseek (ssvm_fd, ssvm->ssvm_size, SEEK_SET) < 0)
66 {
67 clib_unix_warning ("lseek");
68 close (ssvm_fd);
69 return SSVM_API_ERROR_SET_SIZE;
70 }
Ed Warnicke853e7202016-08-12 11:42:26 -070071
Dave Barach8a7fb0c2016-07-08 14:44:23 -040072 if (write (ssvm_fd, &junk, 1) != 1)
Ed Warnickecb9cada2015-12-08 15:45:58 -070073 {
74 clib_unix_warning ("set ssvm size");
Dave Barach8a7fb0c2016-07-08 14:44:23 -040075 close (ssvm_fd);
Ed Warnickecb9cada2015-12-08 15:45:58 -070076 return SSVM_API_ERROR_SET_SIZE;
77 }
Dave Barach8a7fb0c2016-07-08 14:44:23 -040078
Damjan Marion567e61d2018-10-24 17:08:26 +020079 page_size = clib_mem_get_fd_page_size (ssvm_fd);
Ed Warnickecb9cada2015-12-08 15:45:58 -070080 if (ssvm->requested_va)
Florin Corasf8f516a2018-02-08 15:10:09 -080081 {
82 requested_va = ssvm->requested_va;
83 clib_mem_vm_randomize_va (&requested_va, min_log2 (page_size));
84 }
Ed Warnickecb9cada2015-12-08 15:45:58 -070085
Florin Coras2a7c0b62020-09-28 23:40:28 -070086 sh = clib_mem_vm_map_shared (uword_to_pointer (requested_va, void *),
87 ssvm->ssvm_size, ssvm_fd, 0,
88 (char *) ssvm->name);
89 if (sh == CLIB_MEM_VM_MAP_FAILED)
Ed Warnickecb9cada2015-12-08 15:45:58 -070090 {
91 clib_unix_warning ("mmap");
Dave Barach8a7fb0c2016-07-08 14:44:23 -040092 close (ssvm_fd);
Ed Warnickecb9cada2015-12-08 15:45:58 -070093 return SSVM_API_ERROR_MMAP;
94 }
Florin Coras2a7c0b62020-09-28 23:40:28 -070095
Dave Barach8a7fb0c2016-07-08 14:44:23 -040096 close (ssvm_fd);
Ed Warnickecb9cada2015-12-08 15:45:58 -070097
Damjan Marion79934e82022-04-05 12:40:31 +020098 clib_mem_unpoison (sh, sizeof (*sh));
Florin Coras5220a262020-09-29 18:11:24 -070099 sh->server_pid = ssvm->my_pid;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700100 sh->ssvm_size = ssvm->ssvm_size;
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400101 sh->ssvm_va = pointer_to_uword (sh);
Florin Corasb384b542018-01-15 01:08:33 -0800102 sh->type = SSVM_SEGMENT_SHM;
Damjan Marion4537c302020-09-28 19:03:37 +0200103 sh->heap = clib_mem_create_heap (((u8 *) sh) + page_size,
104 ssvm->ssvm_size - page_size,
Florin Coras5220a262020-09-29 18:11:24 -0700105 1 /* locked */ , "ssvm server shm");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700106
107 oldheap = ssvm_push_heap (sh);
Florin Corasb384b542018-01-15 01:08:33 -0800108 sh->name = format (0, "%s", ssvm->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700109 ssvm_pop_heap (oldheap);
110
Florin Corasb384b542018-01-15 01:08:33 -0800111 ssvm->sh = sh;
112 ssvm->my_pid = getpid ();
Florin Coras5220a262020-09-29 18:11:24 -0700113 ssvm->is_server = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700114
115 /* The application has to set set sh->ready... */
116 return 0;
117}
118
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400119int
Florin Coras5220a262020-09-29 18:11:24 -0700120ssvm_client_init_shm (ssvm_private_t * ssvm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700121{
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400122 struct stat stat;
123 int ssvm_fd = -1;
124 ssvm_shared_header_t *sh;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700125
Dave Wallaceb8856642017-07-31 13:33:11 -0400126 ASSERT (vec_c_string_is_terminated (ssvm->name));
Florin Coras5220a262020-09-29 18:11:24 -0700127 ssvm->is_server = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700128
Florin Corasb384b542018-01-15 01:08:33 -0800129 while (ssvm->attach_timeout-- > 0)
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400130 {
131 if (ssvm_fd < 0)
132 ssvm_fd = shm_open ((char *) ssvm->name, O_RDWR, 0777);
133 if (ssvm_fd < 0)
134 {
135 sleep (1);
136 continue;
137 }
138 if (fstat (ssvm_fd, &stat) < 0)
139 {
140 sleep (1);
141 continue;
142 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700143
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400144 if (stat.st_size > 0)
145 goto map_it;
146 }
Florin Coras5220a262020-09-29 18:11:24 -0700147 clib_warning ("client timeout");
148 return SSVM_API_ERROR_CLIENT_TIMEOUT;
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400149
150map_it:
151 sh = (void *) mmap (0, MMAP_PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
152 ssvm_fd, 0);
153 if (sh == MAP_FAILED)
154 {
Florin Coras5220a262020-09-29 18:11:24 -0700155 clib_unix_warning ("client research mmap");
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400156 close (ssvm_fd);
157 return SSVM_API_ERROR_MMAP;
158 }
159
Florin Corasb384b542018-01-15 01:08:33 -0800160 while (ssvm->attach_timeout-- > 0)
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400161 {
162 if (sh->ready)
163 goto re_map_it;
164 }
165 close (ssvm_fd);
166 munmap (sh, MMAP_PAGESIZE);
Florin Coras5220a262020-09-29 18:11:24 -0700167 clib_warning ("client timeout 2");
168 return SSVM_API_ERROR_CLIENT_TIMEOUT;
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400169
170re_map_it:
David Johnsond9818dd2018-12-14 14:53:41 -0500171 ssvm->requested_va = sh->ssvm_va;
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400172 ssvm->ssvm_size = sh->ssvm_size;
173 munmap (sh, MMAP_PAGESIZE);
174
175 sh = ssvm->sh = (void *) mmap ((void *) ssvm->requested_va, ssvm->ssvm_size,
176 PROT_READ | PROT_WRITE,
177 MAP_SHARED | MAP_FIXED, ssvm_fd, 0);
178
179 if (sh == MAP_FAILED)
180 {
Florin Coras5220a262020-09-29 18:11:24 -0700181 clib_unix_warning ("client final mmap");
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400182 close (ssvm_fd);
183 return SSVM_API_ERROR_MMAP;
184 }
Florin Coras5220a262020-09-29 18:11:24 -0700185 sh->client_pid = getpid ();
root5e06e4f2022-04-01 09:09:05 +0000186 close (ssvm_fd);
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400187 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188}
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400189
Dave Barach68b0fb02017-02-28 15:15:56 -0500190void
Florin Corasb384b542018-01-15 01:08:33 -0800191ssvm_delete_shm (ssvm_private_t * ssvm)
Dave Barach68b0fb02017-02-28 15:15:56 -0500192{
193 u8 *fn;
194
195 fn = format (0, "/dev/shm/%s%c", ssvm->name, 0);
196
Dave Wallaced756b352017-07-03 13:11:38 -0400197 if (CLIB_DEBUG > 1)
198 clib_warning ("[%d] unlinking ssvm (%s) backing file '%s'", getpid (),
199 ssvm->name, fn);
200
Dave Barach68b0fb02017-02-28 15:15:56 -0500201 /* Throw away the backing file */
202 if (unlink ((char *) fn) < 0)
203 clib_unix_warning ("unlink segment '%s'", ssvm->name);
204
Dave Barach68b0fb02017-02-28 15:15:56 -0500205 vec_free (fn);
Dave Wallaced756b352017-07-03 13:11:38 -0400206 vec_free (ssvm->name);
207
Florin Coras5220a262020-09-29 18:11:24 -0700208 if (ssvm->is_server)
Florin Coras2a7c0b62020-09-28 23:40:28 -0700209 clib_mem_vm_unmap (ssvm->sh);
210 else
211 munmap ((void *) ssvm->sh, ssvm->ssvm_size);
Dave Barach68b0fb02017-02-28 15:15:56 -0500212}
213
Florin Corasb384b542018-01-15 01:08:33 -0800214/**
Florin Coras5220a262020-09-29 18:11:24 -0700215 * Initialize memfd segment server
Florin Corasb384b542018-01-15 01:08:33 -0800216 */
Florin Coras4d9b9d82018-01-14 12:25:50 -0800217int
Florin Coras5220a262020-09-29 18:11:24 -0700218ssvm_server_init_memfd (ssvm_private_t * memfd)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800219{
Florin Corasbf693ff2020-10-22 11:59:55 -0700220 uword page_size, n_pages;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800221 ssvm_shared_header_t *sh;
Florin Corasbf693ff2020-10-22 11:59:55 -0700222 int log2_page_size;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800223 void *oldheap;
224
225 if (memfd->ssvm_size == 0)
226 return SSVM_API_ERROR_NO_SIZE;
227
228 ASSERT (vec_c_string_is_terminated (memfd->name));
Florin Coras4d9b9d82018-01-14 12:25:50 -0800229
Junfeng Wangc795b882022-08-12 16:24:46 +0800230 if (memfd->huge_page)
231 memfd->fd = clib_mem_vm_create_fd (CLIB_MEM_PAGE_SZ_DEFAULT_HUGE,
232 (char *) memfd->name);
233 else
234 memfd->fd =
235 clib_mem_vm_create_fd (CLIB_MEM_PAGE_SZ_DEFAULT, (char *) memfd->name);
Florin Coras2a7c0b62020-09-28 23:40:28 -0700236
237 if (memfd->fd == CLIB_MEM_ERROR)
Florin Coras6fe89982020-02-07 23:28:41 +0000238 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800239 clib_unix_warning ("failed to create memfd");
Florin Coras4d9b9d82018-01-14 12:25:50 -0800240 return SSVM_API_ERROR_CREATE_FAILURE;
241 }
242
Florin Coras2a7c0b62020-09-28 23:40:28 -0700243 log2_page_size = clib_mem_get_fd_log2_page_size (memfd->fd);
244 if (log2_page_size == 0)
245 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800246 clib_unix_warning ("cannot determine page size");
Florin Coras2a7c0b62020-09-28 23:40:28 -0700247 return SSVM_API_ERROR_CREATE_FAILURE;
248 }
249
250 n_pages = ((memfd->ssvm_size - 1) >> log2_page_size) + 1;
251
252 if ((ftruncate (memfd->fd, n_pages << log2_page_size)) == -1)
253 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800254 clib_unix_warning ("memfd ftruncate failure");
Florin Coras2a7c0b62020-09-28 23:40:28 -0700255 return SSVM_API_ERROR_CREATE_FAILURE;
256 }
257
258 sh = clib_mem_vm_map_shared (uword_to_pointer (memfd->requested_va, void *),
259 memfd->ssvm_size, memfd->fd, 0,
260 (char *) memfd->name);
261 if (sh == CLIB_MEM_VM_MAP_FAILED)
262 {
263 clib_unix_warning ("memfd map (fd %d)", memfd->fd);
264 close (memfd->fd);
265 return SSVM_API_ERROR_CREATE_FAILURE;
266 }
267
268 memfd->sh = sh;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800269 memfd->my_pid = getpid ();
Florin Coras5220a262020-09-29 18:11:24 -0700270 memfd->is_server = 1;
Florin Corasd3e83a92018-01-16 02:40:18 -0800271
Florin Coras5220a262020-09-29 18:11:24 -0700272 sh->server_pid = memfd->my_pid;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800273 sh->ssvm_size = memfd->ssvm_size;
Florin Corasb384b542018-01-15 01:08:33 -0800274 sh->ssvm_va = pointer_to_uword (sh);
275 sh->type = SSVM_SEGMENT_MEMFD;
Dave Barach6a5adc32018-07-04 10:56:23 -0400276
Junfeng Wangc795b882022-08-12 16:24:46 +0800277 page_size = clib_mem_get_page_size ();
Damjan Marion4537c302020-09-28 19:03:37 +0200278 sh->heap = clib_mem_create_heap (((u8 *) sh) + page_size,
279 memfd->ssvm_size - page_size,
Florin Coras5220a262020-09-29 18:11:24 -0700280 1 /* locked */ , "ssvm server memfd");
Florin Coras4d9b9d82018-01-14 12:25:50 -0800281 oldheap = ssvm_push_heap (sh);
Florin Corasb384b542018-01-15 01:08:33 -0800282 sh->name = format (0, "%s", memfd->name, 0);
Florin Coras4d9b9d82018-01-14 12:25:50 -0800283 ssvm_pop_heap (oldheap);
284
Florin Coras4d9b9d82018-01-14 12:25:50 -0800285 /* The application has to set set sh->ready... */
286 return 0;
287}
288
Florin Corasb384b542018-01-15 01:08:33 -0800289/**
Florin Coras5220a262020-09-29 18:11:24 -0700290 * Initialize memfd segment client
Florin Corasb384b542018-01-15 01:08:33 -0800291 *
Florin Coras5220a262020-09-29 18:11:24 -0700292 * Subtly different than svm_client_init. The caller needs to acquire
Florin Corasb384b542018-01-15 01:08:33 -0800293 * a usable file descriptor for the memfd segment e.g. via
294 * vppinfra/socket.c:default_socket_recvmsg
Florin Coras4d9b9d82018-01-14 12:25:50 -0800295 */
Florin Coras4d9b9d82018-01-14 12:25:50 -0800296int
Florin Coras5220a262020-09-29 18:11:24 -0700297ssvm_client_init_memfd (ssvm_private_t * memfd)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800298{
Florin Coras459a0c42020-09-30 08:13:44 -0700299 int mmap_flags = MAP_SHARED;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800300 ssvm_shared_header_t *sh;
Florin Corasd3e83a92018-01-16 02:40:18 -0800301 uword page_size;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800302
Florin Coras5220a262020-09-29 18:11:24 -0700303 memfd->is_server = 0;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800304
Damjan Marion567e61d2018-10-24 17:08:26 +0200305 page_size = clib_mem_get_fd_page_size (memfd->fd);
Florin Corasd3e83a92018-01-16 02:40:18 -0800306 if (!page_size)
307 {
308 clib_unix_warning ("page size unknown");
309 return SSVM_API_ERROR_MMAP;
310 }
311
312 /*
313 * Map the segment once, to look at the shared header
314 */
Florin Coras459a0c42020-09-30 08:13:44 -0700315 sh = (void *) mmap (0, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
316 memfd->fd, 0);
Florin Corasd3e83a92018-01-16 02:40:18 -0800317
Florin Coras459a0c42020-09-30 08:13:44 -0700318 if (sh == MAP_FAILED)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800319 {
Florin Coras459a0c42020-09-30 08:13:44 -0700320 clib_unix_warning ("client research mmap (fd %d)", memfd->fd);
Florin Coras4d9b9d82018-01-14 12:25:50 -0800321 close (memfd->fd);
322 return SSVM_API_ERROR_MMAP;
323 }
324
Florin Corasd3e83a92018-01-16 02:40:18 -0800325 memfd->requested_va = sh->ssvm_va;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800326 memfd->ssvm_size = sh->ssvm_size;
Florin Coras459a0c42020-09-30 08:13:44 -0700327 munmap (sh, page_size);
Florin Coras4d9b9d82018-01-14 12:25:50 -0800328
Florin Coras4da0ea92021-01-05 23:15:49 -0800329 if (memfd->requested_va)
330 mmap_flags |= MAP_FIXED;
331
Florin Corasd3e83a92018-01-16 02:40:18 -0800332 /*
333 * Remap the segment at the 'right' address
334 */
Florin Coras459a0c42020-09-30 08:13:44 -0700335 sh = (void *) mmap (uword_to_pointer (memfd->requested_va, void *),
336 memfd->ssvm_size,
337 PROT_READ | PROT_WRITE, mmap_flags, memfd->fd, 0);
338
339 if (sh == MAP_FAILED)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800340 {
Florin Coras5220a262020-09-29 18:11:24 -0700341 clib_unix_warning ("client final mmap");
Florin Coras4d9b9d82018-01-14 12:25:50 -0800342 close (memfd->fd);
343 return SSVM_API_ERROR_MMAP;
344 }
Florin Corasd3e83a92018-01-16 02:40:18 -0800345
Florin Coras5220a262020-09-29 18:11:24 -0700346 sh->client_pid = getpid ();
Florin Coras4d9b9d82018-01-14 12:25:50 -0800347 memfd->sh = sh;
348 return 0;
349}
Dave Barach68b0fb02017-02-28 15:15:56 -0500350
Florin Corasd3e83a92018-01-16 02:40:18 -0800351void
352ssvm_delete_memfd (ssvm_private_t * memfd)
353{
354 vec_free (memfd->name);
Florin Coras5220a262020-09-29 18:11:24 -0700355 if (memfd->is_server)
Florin Coras2a7c0b62020-09-28 23:40:28 -0700356 clib_mem_vm_unmap (memfd->sh);
357 else
Florin Coras459a0c42020-09-30 08:13:44 -0700358 munmap (memfd->sh, memfd->ssvm_size);
Florin Corasd3e83a92018-01-16 02:40:18 -0800359 close (memfd->fd);
360}
361
Florin Corasa332c462018-01-31 06:52:17 -0800362/**
363 * Initialize segment in a private heap
364 */
365int
Florin Coras5220a262020-09-29 18:11:24 -0700366ssvm_server_init_private (ssvm_private_t * ssvm)
Florin Corasa332c462018-01-31 06:52:17 -0800367{
Florin Coras2a7c0b62020-09-28 23:40:28 -0700368 uword page_size, log2_page_size, rnd_size = 0;
Florin Corasa332c462018-01-31 06:52:17 -0800369 ssvm_shared_header_t *sh;
Damjan Marionbfa75d62020-10-06 17:46:06 +0200370 clib_mem_heap_t *heap, *oldheap;
Florin Corasa332c462018-01-31 06:52:17 -0800371
Florin Coras2a7c0b62020-09-28 23:40:28 -0700372 log2_page_size = clib_mem_get_log2_page_size ();
373 if (log2_page_size == 0)
Florin Coras6fe89982020-02-07 23:28:41 +0000374 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800375 clib_unix_warning ("cannot determine page size");
Florin Coras6fe89982020-02-07 23:28:41 +0000376 return SSVM_API_ERROR_CREATE_FAILURE;
377 }
378
Florin Coras927eee42020-10-12 19:08:22 -0700379 page_size = 1ULL << log2_page_size;
Florin Coras2a7c0b62020-09-28 23:40:28 -0700380 rnd_size = clib_max (ssvm->ssvm_size + (page_size - 1), ssvm->ssvm_size);
381 rnd_size &= ~(page_size - 1);
382
383 sh = clib_mem_vm_map (0, rnd_size + page_size, log2_page_size,
384 (char *) ssvm->name);
385 if (sh == CLIB_MEM_VM_MAP_FAILED)
386 {
387 clib_unix_warning ("private map failed");
388 return SSVM_API_ERROR_CREATE_FAILURE;
389 }
390
391 heap = clib_mem_create_heap ((u8 *) sh + page_size, rnd_size,
Florin Coras5220a262020-09-29 18:11:24 -0700392 1 /* locked */ , "ssvm server private");
Benoît Ganne0af49a82019-07-12 11:34:16 +0200393 if (heap == 0)
394 {
Florin Coras2a7c0b62020-09-28 23:40:28 -0700395 clib_unix_warning ("heap alloc");
Benoît Ganne0af49a82019-07-12 11:34:16 +0200396 return -1;
397 }
398
Damjan Marion4537c302020-09-28 19:03:37 +0200399 rnd_size = clib_mem_get_heap_free_space (heap);
Florin Corasa332c462018-01-31 06:52:17 -0800400
401 ssvm->ssvm_size = rnd_size;
Florin Coras5220a262020-09-29 18:11:24 -0700402 ssvm->is_server = 1;
Florin Corasa332c462018-01-31 06:52:17 -0800403 ssvm->my_pid = getpid ();
404 ssvm->requested_va = ~0;
405
Florin Coras6fe89982020-02-07 23:28:41 +0000406 /* First page in allocated memory is set aside for the shared header */
Florin Corasa332c462018-01-31 06:52:17 -0800407 ssvm->sh = sh;
408
Dave Barachb7b92992018-10-17 10:38:51 -0400409 clib_memset (sh, 0, sizeof (*sh));
Florin Corasa332c462018-01-31 06:52:17 -0800410 sh->heap = heap;
Florin Coras4453c092019-12-19 10:13:15 -0800411 sh->ssvm_size = rnd_size;
Florin Corasd2fb6012020-12-07 18:35:12 -0800412 sh->ssvm_va = pointer_to_uword (sh);
Florin Corasa332c462018-01-31 06:52:17 -0800413 sh->type = SSVM_SEGMENT_PRIVATE;
Florin Coras2a7c0b62020-09-28 23:40:28 -0700414
415 oldheap = ssvm_push_heap (sh);
416 sh->name = format (0, "%s", ssvm->name, 0);
417 ssvm_pop_heap (oldheap);
Florin Corasa332c462018-01-31 06:52:17 -0800418
419 return 0;
420}
421
422int
Florin Coras5220a262020-09-29 18:11:24 -0700423ssvm_client_init_private (ssvm_private_t * ssvm)
Florin Corasa332c462018-01-31 06:52:17 -0800424{
425 clib_warning ("BUG: this should not be called!");
426 return -1;
427}
428
429void
430ssvm_delete_private (ssvm_private_t * ssvm)
431{
432 vec_free (ssvm->name);
Damjan Marion4537c302020-09-28 19:03:37 +0200433 clib_mem_destroy_heap (ssvm->sh->heap);
Florin Coras2a7c0b62020-09-28 23:40:28 -0700434 clib_mem_vm_unmap (ssvm->sh);
Florin Corasa332c462018-01-31 06:52:17 -0800435}
436
Florin Corasb384b542018-01-15 01:08:33 -0800437int
Florin Coras5220a262020-09-29 18:11:24 -0700438ssvm_server_init (ssvm_private_t * ssvm, ssvm_segment_type_t type)
Florin Corasb384b542018-01-15 01:08:33 -0800439{
Florin Coras5220a262020-09-29 18:11:24 -0700440 return (server_init_fns[type]) (ssvm);
Florin Corasb384b542018-01-15 01:08:33 -0800441}
442
443int
Florin Coras5220a262020-09-29 18:11:24 -0700444ssvm_client_init (ssvm_private_t * ssvm, ssvm_segment_type_t type)
Florin Corasb384b542018-01-15 01:08:33 -0800445{
Florin Coras5220a262020-09-29 18:11:24 -0700446 return (client_init_fns[type]) (ssvm);
Florin Corasb384b542018-01-15 01:08:33 -0800447}
448
449void
450ssvm_delete (ssvm_private_t * ssvm)
451{
452 delete_fns[ssvm->sh->type] (ssvm);
453}
454
455ssvm_segment_type_t
456ssvm_type (const ssvm_private_t * ssvm)
457{
458 return ssvm->sh->type;
459}
460
461u8 *
462ssvm_name (const ssvm_private_t * ssvm)
463{
464 return ssvm->sh->name;
465}
466
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400467/*
468 * fd.io coding-style-patch-verification: ON
469 *
470 * Local Variables:
471 * eval: (c-set-style "gnu")
472 * End:
473 */