root/tools/testing/selftests/vm/va_128TBswitch.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. run_test
  2. supported_arch
  3. main

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *
   4  * Authors: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
   5  * Authors: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
   6  */
   7 
   8 #include <stdio.h>
   9 #include <sys/mman.h>
  10 #include <string.h>
  11 
  12 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  13 
  14 #ifdef __powerpc64__
  15 #define PAGE_SIZE       (64 << 10)
  16 /*
  17  * This will work with 16M and 2M hugepage size
  18  */
  19 #define HUGETLB_SIZE    (16 << 20)
  20 #else
  21 #define PAGE_SIZE       (4 << 10)
  22 #define HUGETLB_SIZE    (2 << 20)
  23 #endif
  24 
  25 /*
  26  * >= 128TB is the hint addr value we used to select
  27  * large address space.
  28  */
  29 #define ADDR_SWITCH_HINT (1UL << 47)
  30 #define LOW_ADDR        ((void *) (1UL << 30))
  31 #define HIGH_ADDR       ((void *) (1UL << 48))
  32 
  33 struct testcase {
  34         void *addr;
  35         unsigned long size;
  36         unsigned long flags;
  37         const char *msg;
  38         unsigned int low_addr_required:1;
  39         unsigned int keep_mapped:1;
  40 };
  41 
  42 static struct testcase testcases[] = {
  43         {
  44                 /*
  45                  * If stack is moved, we could possibly allocate
  46                  * this at the requested address.
  47                  */
  48                 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
  49                 .size = PAGE_SIZE,
  50                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
  51                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, PAGE_SIZE)",
  52                 .low_addr_required = 1,
  53         },
  54         {
  55                 /*
  56                  * We should never allocate at the requested address or above it
  57                  * The len cross the 128TB boundary. Without MAP_FIXED
  58                  * we will always search in the lower address space.
  59                  */
  60                 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
  61                 .size = 2 * PAGE_SIZE,
  62                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
  63                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, (2 * PAGE_SIZE))",
  64                 .low_addr_required = 1,
  65         },
  66         {
  67                 /*
  68                  * Exact mapping at 128TB, the area is free we should get that
  69                  * even without MAP_FIXED.
  70                  */
  71                 .addr = ((void *)(ADDR_SWITCH_HINT)),
  72                 .size = PAGE_SIZE,
  73                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
  74                 .msg = "mmap(ADDR_SWITCH_HINT, PAGE_SIZE)",
  75                 .keep_mapped = 1,
  76         },
  77         {
  78                 .addr = (void *)(ADDR_SWITCH_HINT),
  79                 .size = 2 * PAGE_SIZE,
  80                 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
  81                 .msg = "mmap(ADDR_SWITCH_HINT, 2 * PAGE_SIZE, MAP_FIXED)",
  82         },
  83         {
  84                 .addr = NULL,
  85                 .size = 2 * PAGE_SIZE,
  86                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
  87                 .msg = "mmap(NULL)",
  88                 .low_addr_required = 1,
  89         },
  90         {
  91                 .addr = LOW_ADDR,
  92                 .size = 2 * PAGE_SIZE,
  93                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
  94                 .msg = "mmap(LOW_ADDR)",
  95                 .low_addr_required = 1,
  96         },
  97         {
  98                 .addr = HIGH_ADDR,
  99                 .size = 2 * PAGE_SIZE,
 100                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 101                 .msg = "mmap(HIGH_ADDR)",
 102                 .keep_mapped = 1,
 103         },
 104         {
 105                 .addr = HIGH_ADDR,
 106                 .size = 2 * PAGE_SIZE,
 107                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 108                 .msg = "mmap(HIGH_ADDR) again",
 109                 .keep_mapped = 1,
 110         },
 111         {
 112                 .addr = HIGH_ADDR,
 113                 .size = 2 * PAGE_SIZE,
 114                 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
 115                 .msg = "mmap(HIGH_ADDR, MAP_FIXED)",
 116         },
 117         {
 118                 .addr = (void *) -1,
 119                 .size = 2 * PAGE_SIZE,
 120                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 121                 .msg = "mmap(-1)",
 122                 .keep_mapped = 1,
 123         },
 124         {
 125                 .addr = (void *) -1,
 126                 .size = 2 * PAGE_SIZE,
 127                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 128                 .msg = "mmap(-1) again",
 129         },
 130         {
 131                 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
 132                 .size = PAGE_SIZE,
 133                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 134                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, PAGE_SIZE)",
 135                 .low_addr_required = 1,
 136         },
 137         {
 138                 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE),
 139                 .size = 2 * PAGE_SIZE,
 140                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 141                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, 2 * PAGE_SIZE)",
 142                 .low_addr_required = 1,
 143                 .keep_mapped = 1,
 144         },
 145         {
 146                 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE / 2),
 147                 .size = 2 * PAGE_SIZE,
 148                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 149                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE/2 , 2 * PAGE_SIZE)",
 150                 .low_addr_required = 1,
 151                 .keep_mapped = 1,
 152         },
 153         {
 154                 .addr = ((void *)(ADDR_SWITCH_HINT)),
 155                 .size = PAGE_SIZE,
 156                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
 157                 .msg = "mmap(ADDR_SWITCH_HINT, PAGE_SIZE)",
 158         },
 159         {
 160                 .addr = (void *)(ADDR_SWITCH_HINT),
 161                 .size = 2 * PAGE_SIZE,
 162                 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
 163                 .msg = "mmap(ADDR_SWITCH_HINT, 2 * PAGE_SIZE, MAP_FIXED)",
 164         },
 165 };
 166 
 167 static struct testcase hugetlb_testcases[] = {
 168         {
 169                 .addr = NULL,
 170                 .size = HUGETLB_SIZE,
 171                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
 172                 .msg = "mmap(NULL, MAP_HUGETLB)",
 173                 .low_addr_required = 1,
 174         },
 175         {
 176                 .addr = LOW_ADDR,
 177                 .size = HUGETLB_SIZE,
 178                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
 179                 .msg = "mmap(LOW_ADDR, MAP_HUGETLB)",
 180                 .low_addr_required = 1,
 181         },
 182         {
 183                 .addr = HIGH_ADDR,
 184                 .size = HUGETLB_SIZE,
 185                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
 186                 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB)",
 187                 .keep_mapped = 1,
 188         },
 189         {
 190                 .addr = HIGH_ADDR,
 191                 .size = HUGETLB_SIZE,
 192                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
 193                 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB) again",
 194                 .keep_mapped = 1,
 195         },
 196         {
 197                 .addr = HIGH_ADDR,
 198                 .size = HUGETLB_SIZE,
 199                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
 200                 .msg = "mmap(HIGH_ADDR, MAP_FIXED | MAP_HUGETLB)",
 201         },
 202         {
 203                 .addr = (void *) -1,
 204                 .size = HUGETLB_SIZE,
 205                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
 206                 .msg = "mmap(-1, MAP_HUGETLB)",
 207                 .keep_mapped = 1,
 208         },
 209         {
 210                 .addr = (void *) -1,
 211                 .size = HUGETLB_SIZE,
 212                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
 213                 .msg = "mmap(-1, MAP_HUGETLB) again",
 214         },
 215         {
 216                 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE),
 217                 .size = 2 * HUGETLB_SIZE,
 218                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
 219                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, 2*HUGETLB_SIZE, MAP_HUGETLB)",
 220                 .low_addr_required = 1,
 221                 .keep_mapped = 1,
 222         },
 223         {
 224                 .addr = (void *)(ADDR_SWITCH_HINT),
 225                 .size = 2 * HUGETLB_SIZE,
 226                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
 227                 .msg = "mmap(ADDR_SWITCH_HINT , 2*HUGETLB_SIZE, MAP_FIXED | MAP_HUGETLB)",
 228         },
 229 };
 230 
 231 static int run_test(struct testcase *test, int count)
 232 {
 233         void *p;
 234         int i, ret = 0;
 235 
 236         for (i = 0; i < count; i++) {
 237                 struct testcase *t = test + i;
 238 
 239                 p = mmap(t->addr, t->size, PROT_READ | PROT_WRITE, t->flags, -1, 0);
 240 
 241                 printf("%s: %p - ", t->msg, p);
 242 
 243                 if (p == MAP_FAILED) {
 244                         printf("FAILED\n");
 245                         ret = 1;
 246                         continue;
 247                 }
 248 
 249                 if (t->low_addr_required && p >= (void *)(ADDR_SWITCH_HINT)) {
 250                         printf("FAILED\n");
 251                         ret = 1;
 252                 } else {
 253                         /*
 254                          * Do a dereference of the address returned so that we catch
 255                          * bugs in page fault handling
 256                          */
 257                         memset(p, 0, t->size);
 258                         printf("OK\n");
 259                 }
 260                 if (!t->keep_mapped)
 261                         munmap(p, t->size);
 262         }
 263 
 264         return ret;
 265 }
 266 
 267 static int supported_arch(void)
 268 {
 269 #if defined(__powerpc64__)
 270         return 1;
 271 #elif defined(__x86_64__)
 272         return 1;
 273 #else
 274         return 0;
 275 #endif
 276 }
 277 
 278 int main(int argc, char **argv)
 279 {
 280         int ret;
 281 
 282         if (!supported_arch())
 283                 return 0;
 284 
 285         ret = run_test(testcases, ARRAY_SIZE(testcases));
 286         if (argc == 2 && !strcmp(argv[1], "--run-hugetlb"))
 287                 ret = run_test(hugetlb_testcases, ARRAY_SIZE(hugetlb_testcases));
 288         return ret;
 289 }

/* [<][>][^][v][top][bottom][index][help] */