1// SPDX-License-Identifier: LGPL-2.1-or-later 2/* 3 * Copyright (C) 2009 IBM Corporation. 4 * Author: David Gibson 5 */ 6 7/*\ 8 * [Description] 9 * 10 * The kernel has bug for mremap() on some architecture. mremap() can 11 * cause crashes on architectures with holes in the address space 12 * (like ia64) and on powerpc with it's distinct page size "slices". 13 * 14 * This test get the normal mapping address and mremap() hugepage mapping 15 * near to this normal mapping. 16 */ 17 18#define _GNU_SOURCE 19#include "hugetlb.h" 20 21#define MNTPOINT "hugetlbfs/" 22 23static int fd = -1; 24static long hpage_size; 25 26static int do_remap(int fd, void *target) 27{ 28 void *a, *b; 29 int ret; 30 31 a = SAFE_MMAP(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 32 33 ret = do_readback(a, hpage_size, "base huge"); 34 if (ret) 35 goto cleanup; 36 37 b = mremap(a, hpage_size, hpage_size, MREMAP_MAYMOVE | MREMAP_FIXED, 38 target); 39 40 if (b != MAP_FAILED) { 41 ret = do_readback(b, hpage_size, "remapped"); 42 a = b; 43 } else { 44 tst_res(TINFO|TERRNO, "mremap(MAYMOVE|FIXED) disallowed"); 45 } 46 47cleanup: 48 SAFE_MUNMAP(a, hpage_size); 49 return ret; 50} 51 52static void *map_align(size_t size, size_t align) 53{ 54 unsigned long xsize = size + align - getpagesize(); 55 size_t t; 56 void *p, *q; 57 58 p = SAFE_MMAP(NULL, xsize, PROT_READ|PROT_WRITE, 59 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 60 61 q = PALIGN(p, align); 62 63 t = q - p; 64 if (t) 65 SAFE_MUNMAP(p, t); 66 67 t = p + xsize - (q + size); 68 if (t) 69 SAFE_MUNMAP(q + size, t); 70 71 return q; 72} 73 74static void run_test(void) 75{ 76 void *p; 77 int ret; 78 79 fd = tst_creat_unlinked(MNTPOINT, 0); 80 p = map_align(3*hpage_size, hpage_size); 81 82 SAFE_MUNMAP(p, hpage_size); 83 SAFE_MUNMAP(p + 2*hpage_size, hpage_size); 84 85 p = p + hpage_size; 86 87 tst_res(TINFO, "Normal mapping at %p", p); 88 ret = do_readback(p, hpage_size, "base normal page"); 89 if (ret) 90 goto cleanup; 91 92 ret = do_remap(fd, p - hpage_size); 93 if (ret) 94 goto cleanup; 95 96 ret = do_remap(fd, p + hpage_size); 97 if (ret == 0) 98 tst_res(TPASS, "Successfully tested mremap hpage near normal mapping"); 99 100cleanup: 101 SAFE_CLOSE(fd); 102} 103 104static void setup(void) 105{ 106 hpage_size = tst_get_hugepage_size(); 107} 108 109static void cleanup(void) 110{ 111 if (fd >= 0) 112 SAFE_CLOSE(fd); 113} 114 115static struct tst_test test = { 116 .needs_root = 1, 117 .mntpoint = MNTPOINT, 118 .needs_hugetlbfs = 1, 119 .needs_tmpdir = 1, 120 .setup = setup, 121 .cleanup = cleanup, 122 .test_all = run_test, 123 .hugepages = {3, TST_NEEDS}, 124}; 125