svm: calc base address on AArch64 based on autodetected VA space size 99/9999/3
authorDamjan Marion <damarion@cisco.com>
Mon, 8 Jan 2018 15:35:35 +0000 (16:35 +0100)
committerDave Barach <openvpp@barachs.net>
Wed, 10 Jan 2018 02:17:31 +0000 (02:17 +0000)
Change-Id: I7487eb74b8deebff849d662b55a6708566ccd9ef
Signed-off-by: Damjan Marion <damarion@cisco.com>
src/svm/svm.c
src/svm/svm_common.h
src/svm/svmtool.c
src/vlibmemory/memory_api.c

index c54f973..f187fbf 100644 (file)
@@ -58,6 +58,43 @@ svm_get_root_rp (void)
 
 #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)
+    {
+      unformat (&input, "%llx-%llx", &start, &end);
+      unformat_skip_line (&input);
+    }
+
+  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);
+
+  unformat_free (&input);
+  close (fd);
+#endif
+
+  /* default value */
+  return 0x30000000;
+}
+
 static void
 region_lock (svm_region_t * rp, int tag)
 {
@@ -804,7 +841,7 @@ svm_region_init (void)
   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;
@@ -821,7 +858,7 @@ svm_region_init_chroot (const char *root_path)
   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;
@@ -838,7 +875,7 @@ svm_region_init_chroot_uid_gid (const char *root_path, int uid, int gid)
   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;
index 58cd0e9..c650165 100644 (file)
@@ -85,13 +85,7 @@ typedef struct svm_map_region_args_
  */
 #define SVM_GLOBAL_REGION_SIZE    (64<<20)
 #define SVM_GLOBAL_REGION_NAME "/global_vm"
-#if defined (__aarch64__)
-#define VA_BITS 48
-#define BASEVA ((1ul << VA_BITS) / 4)
-#define SVM_GLOBAL_REGION_BASEVA (BASEVA - (2 * SVM_GLOBAL_REGION_SIZE))
-#else
-#define SVM_GLOBAL_REGION_BASEVA  0x30000000
-#endif
+u64 svm_get_global_region_base_va ();
 
 /*
  * Memory shared across individual router instances.
index 01ae422..63577d9 100644 (file)
@@ -368,7 +368,7 @@ repair (char *chroot_path, int crash_root_region)
 
   a->root_path = chroot_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;
 
index d049a62..752f507 100644 (file)
@@ -871,7 +871,7 @@ vlibmemory_init (vlib_main_t * vm)
   a->root_path = am->root_path;
   a->name = SVM_GLOBAL_REGION_NAME;
   a->baseva = (am->global_baseva != 0) ?
-    am->global_baseva : SVM_GLOBAL_REGION_BASEVA;
+    am->global_baseva : +svm_get_global_region_base_va ();
   a->size = (am->global_size != 0) ? am->global_size : SVM_GLOBAL_REGION_SIZE;
   a->flags = SVM_FLAGS_NODATA;
   a->uid = am->api_uid;