1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: LGPL-2.1-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (C) 2005-2006 David Gibson & Adam Litke, IBM Corporation. 4f08c3bdfSopenharmony_ci * Author: David Gibson & Adam Litke 5f08c3bdfSopenharmony_ci */ 6f08c3bdfSopenharmony_ci 7f08c3bdfSopenharmony_ci/*\ 8f08c3bdfSopenharmony_ci * [Description] 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * On some old ppc64 kernel, when hpage is mmaped on 32 bit boundary and 11f08c3bdfSopenharmony_ci * normal page below it, it triggers the bug caused by off-by-one error. 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * WARNING: The offsets and addresses used within are specifically 14f08c3bdfSopenharmony_ci * calculated to trigger the bug as it existed. Don't mess with them 15f08c3bdfSopenharmony_ci * unless you *really* know what you're doing. 16f08c3bdfSopenharmony_ci */ 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_ci#define _GNU_SOURCE 19f08c3bdfSopenharmony_ci#include <stdio.h> 20f08c3bdfSopenharmony_ci#include <sys/mount.h> 21f08c3bdfSopenharmony_ci#include <limits.h> 22f08c3bdfSopenharmony_ci#include <sys/param.h> 23f08c3bdfSopenharmony_ci#include <sys/types.h> 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include "hugetlb.h" 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci#define FOURGB (1ULL << 32) 28f08c3bdfSopenharmony_ci#define MNTPOINT "hugetlbfs/" 29f08c3bdfSopenharmony_cistatic int fd = -1; 30f08c3bdfSopenharmony_cistatic unsigned long hpage_size; 31f08c3bdfSopenharmony_cistatic int page_size; 32f08c3bdfSopenharmony_ci 33f08c3bdfSopenharmony_cistatic void run_test(void) 34f08c3bdfSopenharmony_ci{ 35f08c3bdfSopenharmony_ci void *p, *q = NULL; 36f08c3bdfSopenharmony_ci unsigned long long lowaddr; 37f08c3bdfSopenharmony_ci unsigned long long below_start; 38f08c3bdfSopenharmony_ci unsigned long long above_end; 39f08c3bdfSopenharmony_ci 40f08c3bdfSopenharmony_ci p = mmap((void *)FOURGB, hpage_size, PROT_READ|PROT_WRITE, 41f08c3bdfSopenharmony_ci MAP_SHARED | MAP_FIXED, fd, 0); 42f08c3bdfSopenharmony_ci if (p == MAP_FAILED) { 43f08c3bdfSopenharmony_ci /* slice 0 (high) spans from 4G-1T */ 44f08c3bdfSopenharmony_ci below_start = FOURGB; 45f08c3bdfSopenharmony_ci above_end = 1024ULL*1024*1024*1024; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_ci if (range_is_mapped(below_start, above_end) == 1) { 48f08c3bdfSopenharmony_ci tst_res(TINFO|TERRNO, "region 4G-IT is not free & " 49f08c3bdfSopenharmony_ci "mmap() failed expected"); 50f08c3bdfSopenharmony_ci tst_res(TPASS, "Successful but inconclusive"); 51f08c3bdfSopenharmony_ci } else 52f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, "mmap() huge failed unexpected"); 53f08c3bdfSopenharmony_ci goto cleanup; 54f08c3bdfSopenharmony_ci } 55f08c3bdfSopenharmony_ci if (p != (void *)FOURGB) { 56f08c3bdfSopenharmony_ci tst_res(TFAIL, "Wrong address with MAP_FIXED huge"); 57f08c3bdfSopenharmony_ci goto cleanup; 58f08c3bdfSopenharmony_ci } 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_ci tst_res(TINFO, "Mapped hugetlb at %p", p); 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci memset(p, 0, hpage_size); 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci /* Test just below 4GB to check for off-by-one errors */ 65f08c3bdfSopenharmony_ci lowaddr = FOURGB - page_size; 66f08c3bdfSopenharmony_ci q = mmap((void *)lowaddr, page_size, PROT_READ|PROT_WRITE, 67f08c3bdfSopenharmony_ci MAP_SHARED|MAP_FIXED|MAP_ANONYMOUS, 0, 0); 68f08c3bdfSopenharmony_ci if (q == MAP_FAILED) { 69f08c3bdfSopenharmony_ci below_start = FOURGB - page_size; 70f08c3bdfSopenharmony_ci above_end = FOURGB; 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci if (range_is_mapped(below_start, above_end) == 1) { 73f08c3bdfSopenharmony_ci tst_res(TINFO|TERRNO, "region (4G-page)-4G is not free & " 74f08c3bdfSopenharmony_ci "mmap() failed expected"); 75f08c3bdfSopenharmony_ci tst_res(TPASS, "Successful but inconclusive"); 76f08c3bdfSopenharmony_ci } else 77f08c3bdfSopenharmony_ci tst_res(TFAIL|TERRNO, "mmap() normal failed unexpected"); 78f08c3bdfSopenharmony_ci goto cleanup; 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci if (q != (void *)lowaddr) { 81f08c3bdfSopenharmony_ci tst_res(TFAIL, "Wrong address with MAP_FIXED normal"); 82f08c3bdfSopenharmony_ci goto cleanup; 83f08c3bdfSopenharmony_ci } 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci memset(q, 0, page_size); 86f08c3bdfSopenharmony_ci tst_res(TPASS, "Successful"); 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_cicleanup: 89f08c3bdfSopenharmony_ci if (p && p != MAP_FAILED) 90f08c3bdfSopenharmony_ci SAFE_MUNMAP(p, hpage_size); 91f08c3bdfSopenharmony_ci if (q && q != MAP_FAILED) 92f08c3bdfSopenharmony_ci SAFE_MUNMAP(q, page_size); 93f08c3bdfSopenharmony_ci} 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_cistatic void setup(void) 96f08c3bdfSopenharmony_ci{ 97f08c3bdfSopenharmony_ci page_size = getpagesize(); 98f08c3bdfSopenharmony_ci hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024; 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci if (sizeof(void *) <= 4) 101f08c3bdfSopenharmony_ci tst_brk(TCONF, "Machine must be >32 bit"); 102f08c3bdfSopenharmony_ci if (hpage_size > FOURGB) 103f08c3bdfSopenharmony_ci tst_brk(TCONF, "Huge page size is too large"); 104f08c3bdfSopenharmony_ci fd = tst_creat_unlinked(MNTPOINT, 0); 105f08c3bdfSopenharmony_ci} 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_cistatic void cleanup(void) 108f08c3bdfSopenharmony_ci{ 109f08c3bdfSopenharmony_ci if (fd > 0) 110f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 111f08c3bdfSopenharmony_ci} 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_cistatic struct tst_test test = { 114f08c3bdfSopenharmony_ci .tags = (struct tst_tag[]) { 115f08c3bdfSopenharmony_ci {"linux-git", "9a94c5793a7b"}, 116f08c3bdfSopenharmony_ci {} 117f08c3bdfSopenharmony_ci }, 118f08c3bdfSopenharmony_ci .needs_root = 1, 119f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 120f08c3bdfSopenharmony_ci .needs_hugetlbfs = 1, 121f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 122f08c3bdfSopenharmony_ci .setup = setup, 123f08c3bdfSopenharmony_ci .cleanup = cleanup, 124f08c3bdfSopenharmony_ci .test_all = run_test, 125f08c3bdfSopenharmony_ci .hugepages = {2, TST_NEEDS}, 126f08c3bdfSopenharmony_ci}; 127