#define MUTEX_DEBUG
+u64
+svm_get_global_region_base_va ()
+{
+#if __aarch64__
+ /* On AArch64 VA space can have different size, from 36 to 48 bits.
+ Here we are trying to detect VA bits by parsing /proc/self/maps
+ address ranges */
+ int fd;
+ unformat_input_t input;
+ u64 start, end = 0;
+ u8 bits = 0;
+
+ if ((fd = open ("/proc/self/maps", 0)) < 0)
+ clib_unix_error ("open '/proc/self/maps'");
+
+ unformat_init_clib_file (&input, fd);
+ while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (&input, "%llx-%llx", &start, &end))
+ end--;
+ unformat_skip_line (&input);
+ }
+ unformat_free (&input);
+ close (fd);
+
+ count_leading_zeros (bits, end);
+ bits = 64 - bits;
+ if (bits >= 36 && bits <= 48)
+ return ((1ul << bits) / 4) - (2 * SVM_GLOBAL_REGION_SIZE);
+ else
+ clib_unix_error ("unexpected va bits '%u'", bits);
+#endif
+
+ /* default value */
+ return 0x30000000;
+}
+
static void
region_lock (svm_region_t * rp, int tag)
{
memset (a, 0, sizeof (*a));
a->root_path = 0;
a->name = SVM_GLOBAL_REGION_NAME;
- a->baseva = SVM_GLOBAL_REGION_BASEVA;
+ a->baseva = svm_get_global_region_base_va ();
a->size = SVM_GLOBAL_REGION_SIZE;
a->flags = SVM_FLAGS_NODATA;
a->uid = 0;
memset (a, 0, sizeof (*a));
a->root_path = root_path;
a->name = SVM_GLOBAL_REGION_NAME;
- a->baseva = SVM_GLOBAL_REGION_BASEVA;
+ a->baseva = svm_get_global_region_base_va ();
a->size = SVM_GLOBAL_REGION_SIZE;
a->flags = SVM_FLAGS_NODATA;
a->uid = 0;
memset (a, 0, sizeof (*a));
a->root_path = root_path;
a->name = SVM_GLOBAL_REGION_NAME;
- a->baseva = SVM_GLOBAL_REGION_BASEVA;
+ a->baseva = svm_get_global_region_base_va ();
a->size = SVM_GLOBAL_REGION_SIZE;
a->flags = SVM_FLAGS_NODATA;
a->uid = uid;
* a new region client showing up at the wrong moment.
*/
void
-svm_region_unmap (void *rp_arg)
+svm_region_unmap_internal (void *rp_arg, u8 is_client)
{
int i, mypid = getpid ();
int nclients_left;
vec_free (name);
region_unlock (rp);
- svm_region_unlink (rp);
+
+ /* If a client asks for the cleanup, don't unlink the backing
+ * file since we can't tell if it has been recreated. */
+ if (!is_client)
+ svm_region_unlink (rp);
+
munmap ((void *) virtual_base, virtual_size);
region_unlock (root_rp);
svm_pop_heap (oldheap);
munmap ((void *) virtual_base, virtual_size);
}
+void
+svm_region_unmap (void *rp_arg)
+{
+ svm_region_unmap_internal (rp_arg, 0 /* is_client */ );
+}
+
+void
+svm_region_unmap_client (void *rp_arg)
+{
+ svm_region_unmap_internal (rp_arg, 1 /* is_client */ );
+}
+
/*
* svm_region_exit
*/
-void
-svm_region_exit ()
+static void
+svm_region_exit_internal (u8 is_client)
{
void *oldheap;
int i, mypid = getpid ();
found:
- if (vec_len (root_rp->client_pids) == 0)
+ if (!is_client && vec_len (root_rp->client_pids) == 0)
svm_region_unlink (root_rp);
region_unlock (root_rp);
munmap ((void *) virtual_base, virtual_size);
}
+void
+svm_region_exit (void)
+{
+ svm_region_exit_internal (0 /* is_client */ );
+}
+
+void
+svm_region_exit_client (void)
+{
+ svm_region_exit_internal (1 /* is_client */ );
+}
+
void
svm_client_scan_this_region_nolock (svm_region_t * rp)
{