blob: f93f40d05262f852f8d96f37ae695c88a979d51e [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
Benoît Ganne77d42fc2020-04-20 09:52:39 +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 ();
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400186 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700187}
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400188
Dave Barach68b0fb02017-02-28 15:15:56 -0500189void
Florin Corasb384b542018-01-15 01:08:33 -0800190ssvm_delete_shm (ssvm_private_t * ssvm)
Dave Barach68b0fb02017-02-28 15:15:56 -0500191{
192 u8 *fn;
193
194 fn = format (0, "/dev/shm/%s%c", ssvm->name, 0);
195
Dave Wallaced756b352017-07-03 13:11:38 -0400196 if (CLIB_DEBUG > 1)
197 clib_warning ("[%d] unlinking ssvm (%s) backing file '%s'", getpid (),
198 ssvm->name, fn);
199
Dave Barach68b0fb02017-02-28 15:15:56 -0500200 /* Throw away the backing file */
201 if (unlink ((char *) fn) < 0)
202 clib_unix_warning ("unlink segment '%s'", ssvm->name);
203
Dave Barach68b0fb02017-02-28 15:15:56 -0500204 vec_free (fn);
Dave Wallaced756b352017-07-03 13:11:38 -0400205 vec_free (ssvm->name);
206
Florin Coras5220a262020-09-29 18:11:24 -0700207 if (ssvm->is_server)
Florin Coras2a7c0b62020-09-28 23:40:28 -0700208 clib_mem_vm_unmap (ssvm->sh);
209 else
210 munmap ((void *) ssvm->sh, ssvm->ssvm_size);
Dave Barach68b0fb02017-02-28 15:15:56 -0500211}
212
Florin Corasb384b542018-01-15 01:08:33 -0800213/**
Florin Coras5220a262020-09-29 18:11:24 -0700214 * Initialize memfd segment server
Florin Corasb384b542018-01-15 01:08:33 -0800215 */
Florin Coras4d9b9d82018-01-14 12:25:50 -0800216int
Florin Coras5220a262020-09-29 18:11:24 -0700217ssvm_server_init_memfd (ssvm_private_t * memfd)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800218{
Florin Corasbf693ff2020-10-22 11:59:55 -0700219 uword page_size, n_pages;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800220 ssvm_shared_header_t *sh;
Florin Corasbf693ff2020-10-22 11:59:55 -0700221 int log2_page_size;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800222 void *oldheap;
223
224 if (memfd->ssvm_size == 0)
225 return SSVM_API_ERROR_NO_SIZE;
226
227 ASSERT (vec_c_string_is_terminated (memfd->name));
Florin Coras4d9b9d82018-01-14 12:25:50 -0800228
Florin Coras2a7c0b62020-09-28 23:40:28 -0700229 memfd->fd = clib_mem_vm_create_fd (CLIB_MEM_PAGE_SZ_DEFAULT,
230 (char *) memfd->name);
231
232 if (memfd->fd == CLIB_MEM_ERROR)
Florin Coras6fe89982020-02-07 23:28:41 +0000233 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800234 clib_unix_warning ("failed to create memfd");
Florin Coras4d9b9d82018-01-14 12:25:50 -0800235 return SSVM_API_ERROR_CREATE_FAILURE;
236 }
237
Florin Coras2a7c0b62020-09-28 23:40:28 -0700238 log2_page_size = clib_mem_get_fd_log2_page_size (memfd->fd);
239 if (log2_page_size == 0)
240 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800241 clib_unix_warning ("cannot determine page size");
Florin Coras2a7c0b62020-09-28 23:40:28 -0700242 return SSVM_API_ERROR_CREATE_FAILURE;
243 }
244
245 n_pages = ((memfd->ssvm_size - 1) >> log2_page_size) + 1;
246
247 if ((ftruncate (memfd->fd, n_pages << log2_page_size)) == -1)
248 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800249 clib_unix_warning ("memfd ftruncate failure");
Florin Coras2a7c0b62020-09-28 23:40:28 -0700250 return SSVM_API_ERROR_CREATE_FAILURE;
251 }
252
253 sh = clib_mem_vm_map_shared (uword_to_pointer (memfd->requested_va, void *),
254 memfd->ssvm_size, memfd->fd, 0,
255 (char *) memfd->name);
256 if (sh == CLIB_MEM_VM_MAP_FAILED)
257 {
258 clib_unix_warning ("memfd map (fd %d)", memfd->fd);
259 close (memfd->fd);
260 return SSVM_API_ERROR_CREATE_FAILURE;
261 }
262
263 memfd->sh = sh;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800264 memfd->my_pid = getpid ();
Florin Coras5220a262020-09-29 18:11:24 -0700265 memfd->is_server = 1;
Florin Corasd3e83a92018-01-16 02:40:18 -0800266
Florin Coras5220a262020-09-29 18:11:24 -0700267 sh->server_pid = memfd->my_pid;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800268 sh->ssvm_size = memfd->ssvm_size;
Florin Corasb384b542018-01-15 01:08:33 -0800269 sh->ssvm_va = pointer_to_uword (sh);
270 sh->type = SSVM_SEGMENT_MEMFD;
Dave Barach6a5adc32018-07-04 10:56:23 -0400271
Florin Coras927eee42020-10-12 19:08:22 -0700272 page_size = 1ULL << log2_page_size;
Damjan Marion4537c302020-09-28 19:03:37 +0200273 sh->heap = clib_mem_create_heap (((u8 *) sh) + page_size,
274 memfd->ssvm_size - page_size,
Florin Coras5220a262020-09-29 18:11:24 -0700275 1 /* locked */ , "ssvm server memfd");
Florin Coras4d9b9d82018-01-14 12:25:50 -0800276 oldheap = ssvm_push_heap (sh);
Florin Corasb384b542018-01-15 01:08:33 -0800277 sh->name = format (0, "%s", memfd->name, 0);
Florin Coras4d9b9d82018-01-14 12:25:50 -0800278 ssvm_pop_heap (oldheap);
279
Florin Coras4d9b9d82018-01-14 12:25:50 -0800280 /* The application has to set set sh->ready... */
281 return 0;
282}
283
Florin Corasb384b542018-01-15 01:08:33 -0800284/**
Florin Coras5220a262020-09-29 18:11:24 -0700285 * Initialize memfd segment client
Florin Corasb384b542018-01-15 01:08:33 -0800286 *
Florin Coras5220a262020-09-29 18:11:24 -0700287 * Subtly different than svm_client_init. The caller needs to acquire
Florin Corasb384b542018-01-15 01:08:33 -0800288 * a usable file descriptor for the memfd segment e.g. via
289 * vppinfra/socket.c:default_socket_recvmsg
Florin Coras4d9b9d82018-01-14 12:25:50 -0800290 */
Florin Coras4d9b9d82018-01-14 12:25:50 -0800291int
Florin Coras5220a262020-09-29 18:11:24 -0700292ssvm_client_init_memfd (ssvm_private_t * memfd)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800293{
Florin Coras459a0c42020-09-30 08:13:44 -0700294 int mmap_flags = MAP_SHARED;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800295 ssvm_shared_header_t *sh;
Florin Corasd3e83a92018-01-16 02:40:18 -0800296 uword page_size;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800297
Florin Coras5220a262020-09-29 18:11:24 -0700298 memfd->is_server = 0;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800299
Damjan Marion567e61d2018-10-24 17:08:26 +0200300 page_size = clib_mem_get_fd_page_size (memfd->fd);
Florin Corasd3e83a92018-01-16 02:40:18 -0800301 if (!page_size)
302 {
303 clib_unix_warning ("page size unknown");
304 return SSVM_API_ERROR_MMAP;
305 }
306
307 /*
308 * Map the segment once, to look at the shared header
309 */
Florin Coras459a0c42020-09-30 08:13:44 -0700310 sh = (void *) mmap (0, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
311 memfd->fd, 0);
Florin Corasd3e83a92018-01-16 02:40:18 -0800312
Florin Coras459a0c42020-09-30 08:13:44 -0700313 if (sh == MAP_FAILED)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800314 {
Florin Coras459a0c42020-09-30 08:13:44 -0700315 clib_unix_warning ("client research mmap (fd %d)", memfd->fd);
Florin Coras4d9b9d82018-01-14 12:25:50 -0800316 close (memfd->fd);
317 return SSVM_API_ERROR_MMAP;
318 }
319
Florin Corasd3e83a92018-01-16 02:40:18 -0800320 memfd->requested_va = sh->ssvm_va;
Florin Coras4d9b9d82018-01-14 12:25:50 -0800321 memfd->ssvm_size = sh->ssvm_size;
Florin Coras459a0c42020-09-30 08:13:44 -0700322 munmap (sh, page_size);
Florin Coras4d9b9d82018-01-14 12:25:50 -0800323
Florin Coras4da0ea92021-01-05 23:15:49 -0800324 if (memfd->requested_va)
325 mmap_flags |= MAP_FIXED;
326
Florin Corasd3e83a92018-01-16 02:40:18 -0800327 /*
328 * Remap the segment at the 'right' address
329 */
Florin Coras459a0c42020-09-30 08:13:44 -0700330 sh = (void *) mmap (uword_to_pointer (memfd->requested_va, void *),
331 memfd->ssvm_size,
332 PROT_READ | PROT_WRITE, mmap_flags, memfd->fd, 0);
333
334 if (sh == MAP_FAILED)
Florin Coras4d9b9d82018-01-14 12:25:50 -0800335 {
Florin Coras5220a262020-09-29 18:11:24 -0700336 clib_unix_warning ("client final mmap");
Florin Coras4d9b9d82018-01-14 12:25:50 -0800337 close (memfd->fd);
338 return SSVM_API_ERROR_MMAP;
339 }
Florin Corasd3e83a92018-01-16 02:40:18 -0800340
Florin Coras5220a262020-09-29 18:11:24 -0700341 sh->client_pid = getpid ();
Florin Coras4d9b9d82018-01-14 12:25:50 -0800342 memfd->sh = sh;
343 return 0;
344}
Dave Barach68b0fb02017-02-28 15:15:56 -0500345
Florin Corasd3e83a92018-01-16 02:40:18 -0800346void
347ssvm_delete_memfd (ssvm_private_t * memfd)
348{
349 vec_free (memfd->name);
Florin Coras5220a262020-09-29 18:11:24 -0700350 if (memfd->is_server)
Florin Coras2a7c0b62020-09-28 23:40:28 -0700351 clib_mem_vm_unmap (memfd->sh);
352 else
Florin Coras459a0c42020-09-30 08:13:44 -0700353 munmap (memfd->sh, memfd->ssvm_size);
Florin Corasd3e83a92018-01-16 02:40:18 -0800354 close (memfd->fd);
355}
356
Florin Corasa332c462018-01-31 06:52:17 -0800357/**
358 * Initialize segment in a private heap
359 */
360int
Florin Coras5220a262020-09-29 18:11:24 -0700361ssvm_server_init_private (ssvm_private_t * ssvm)
Florin Corasa332c462018-01-31 06:52:17 -0800362{
Florin Coras2a7c0b62020-09-28 23:40:28 -0700363 uword page_size, log2_page_size, rnd_size = 0;
Florin Corasa332c462018-01-31 06:52:17 -0800364 ssvm_shared_header_t *sh;
Damjan Marionbfa75d62020-10-06 17:46:06 +0200365 clib_mem_heap_t *heap, *oldheap;
Florin Corasa332c462018-01-31 06:52:17 -0800366
Florin Coras2a7c0b62020-09-28 23:40:28 -0700367 log2_page_size = clib_mem_get_log2_page_size ();
368 if (log2_page_size == 0)
Florin Coras6fe89982020-02-07 23:28:41 +0000369 {
jiangxiaomingc9e9b972020-10-10 17:32:11 +0800370 clib_unix_warning ("cannot determine page size");
Florin Coras6fe89982020-02-07 23:28:41 +0000371 return SSVM_API_ERROR_CREATE_FAILURE;
372 }
373
Florin Coras927eee42020-10-12 19:08:22 -0700374 page_size = 1ULL << log2_page_size;
Florin Coras2a7c0b62020-09-28 23:40:28 -0700375 rnd_size = clib_max (ssvm->ssvm_size + (page_size - 1), ssvm->ssvm_size);
376 rnd_size &= ~(page_size - 1);
377
378 sh = clib_mem_vm_map (0, rnd_size + page_size, log2_page_size,
379 (char *) ssvm->name);
380 if (sh == CLIB_MEM_VM_MAP_FAILED)
381 {
382 clib_unix_warning ("private map failed");
383 return SSVM_API_ERROR_CREATE_FAILURE;
384 }
385
386 heap = clib_mem_create_heap ((u8 *) sh + page_size, rnd_size,
Florin Coras5220a262020-09-29 18:11:24 -0700387 1 /* locked */ , "ssvm server private");
Benoît Ganne0af49a82019-07-12 11:34:16 +0200388 if (heap == 0)
389 {
Florin Coras2a7c0b62020-09-28 23:40:28 -0700390 clib_unix_warning ("heap alloc");
Benoît Ganne0af49a82019-07-12 11:34:16 +0200391 return -1;
392 }
393
Damjan Marion4537c302020-09-28 19:03:37 +0200394 rnd_size = clib_mem_get_heap_free_space (heap);
Florin Corasa332c462018-01-31 06:52:17 -0800395
396 ssvm->ssvm_size = rnd_size;
Florin Coras5220a262020-09-29 18:11:24 -0700397 ssvm->is_server = 1;
Florin Corasa332c462018-01-31 06:52:17 -0800398 ssvm->my_pid = getpid ();
399 ssvm->requested_va = ~0;
400
Florin Coras6fe89982020-02-07 23:28:41 +0000401 /* First page in allocated memory is set aside for the shared header */
Florin Corasa332c462018-01-31 06:52:17 -0800402 ssvm->sh = sh;
403
Dave Barachb7b92992018-10-17 10:38:51 -0400404 clib_memset (sh, 0, sizeof (*sh));
Florin Corasa332c462018-01-31 06:52:17 -0800405 sh->heap = heap;
Florin Coras4453c092019-12-19 10:13:15 -0800406 sh->ssvm_size = rnd_size;
Florin Corasd2fb6012020-12-07 18:35:12 -0800407 sh->ssvm_va = pointer_to_uword (sh);
Florin Corasa332c462018-01-31 06:52:17 -0800408 sh->type = SSVM_SEGMENT_PRIVATE;
Florin Coras2a7c0b62020-09-28 23:40:28 -0700409
410 oldheap = ssvm_push_heap (sh);
411 sh->name = format (0, "%s", ssvm->name, 0);
412 ssvm_pop_heap (oldheap);
Florin Corasa332c462018-01-31 06:52:17 -0800413
414 return 0;
415}
416
417int
Florin Coras5220a262020-09-29 18:11:24 -0700418ssvm_client_init_private (ssvm_private_t * ssvm)
Florin Corasa332c462018-01-31 06:52:17 -0800419{
420 clib_warning ("BUG: this should not be called!");
421 return -1;
422}
423
424void
425ssvm_delete_private (ssvm_private_t * ssvm)
426{
427 vec_free (ssvm->name);
Damjan Marion4537c302020-09-28 19:03:37 +0200428 clib_mem_destroy_heap (ssvm->sh->heap);
Florin Coras2a7c0b62020-09-28 23:40:28 -0700429 clib_mem_vm_unmap (ssvm->sh);
Florin Corasa332c462018-01-31 06:52:17 -0800430}
431
Florin Corasb384b542018-01-15 01:08:33 -0800432int
Florin Coras5220a262020-09-29 18:11:24 -0700433ssvm_server_init (ssvm_private_t * ssvm, ssvm_segment_type_t type)
Florin Corasb384b542018-01-15 01:08:33 -0800434{
Florin Coras5220a262020-09-29 18:11:24 -0700435 return (server_init_fns[type]) (ssvm);
Florin Corasb384b542018-01-15 01:08:33 -0800436}
437
438int
Florin Coras5220a262020-09-29 18:11:24 -0700439ssvm_client_init (ssvm_private_t * ssvm, ssvm_segment_type_t type)
Florin Corasb384b542018-01-15 01:08:33 -0800440{
Florin Coras5220a262020-09-29 18:11:24 -0700441 return (client_init_fns[type]) (ssvm);
Florin Corasb384b542018-01-15 01:08:33 -0800442}
443
444void
445ssvm_delete (ssvm_private_t * ssvm)
446{
447 delete_fns[ssvm->sh->type] (ssvm);
448}
449
450ssvm_segment_type_t
451ssvm_type (const ssvm_private_t * ssvm)
452{
453 return ssvm->sh->type;
454}
455
456u8 *
457ssvm_name (const ssvm_private_t * ssvm)
458{
459 return ssvm->sh->name;
460}
461
Dave Barach8a7fb0c2016-07-08 14:44:23 -0400462/*
463 * fd.io coding-style-patch-verification: ON
464 *
465 * Local Variables:
466 * eval: (c-set-style "gnu")
467 * End:
468 */