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 * [Descriptiom] 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * At one stage, a misconversion of hugetlb_vmtruncate_list to a prio_tree 11f08c3bdfSopenharmony_ci * meant that on 32-bit machines, certain combinations of mapping and 12f08c3bdfSopenharmony_ci * truncations could truncate incorrect pages, or overwrite pmds from 13f08c3bdfSopenharmony_ci * other VMAs, triggering BUG_ON()s or other wierdness. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * Test adapted from an example by Kenneth Chen <kenneth.w.chen@intel.com> 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * WARNING: The offsets and addresses used within are specifically 18f08c3bdfSopenharmony_ci * calculated to trigger the bug as it existed. Don't mess with them 19f08c3bdfSopenharmony_ci * unless you *really* know what you're doing. 20f08c3bdfSopenharmony_ci * 21f08c3bdfSopenharmony_ci * The kernel bug in question was fixed with commit 22f08c3bdfSopenharmony_ci * 856fc2950555. 23f08c3bdfSopenharmony_ci */ 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#define _GNU_SOURCE 26f08c3bdfSopenharmony_ci#include <stdio.h> 27f08c3bdfSopenharmony_ci#include <sys/mount.h> 28f08c3bdfSopenharmony_ci#include <limits.h> 29f08c3bdfSopenharmony_ci#include <sys/param.h> 30f08c3bdfSopenharmony_ci#include <sys/types.h> 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#include "hugetlb.h" 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci#define MNTPOINT "hugetlbfs/" 35f08c3bdfSopenharmony_ci#define MAP_LENGTH (4UL * hpage_size) 36f08c3bdfSopenharmony_ci#if defined(__s390__) && __WORDSIZE == 32 37f08c3bdfSopenharmony_ci#define TRUNCATE_POINT 0x20000000UL 38f08c3bdfSopenharmony_ci#else 39f08c3bdfSopenharmony_ci#define TRUNCATE_POINT 0x60000000UL 40f08c3bdfSopenharmony_ci#endif 41f08c3bdfSopenharmony_ci#define HIGH_ADDR 0xa0000000UL 42f08c3bdfSopenharmony_ci#define FOURGIG ((off64_t)0x100000000ULL) 43f08c3bdfSopenharmony_ci 44f08c3bdfSopenharmony_cistatic unsigned long hpage_size; 45f08c3bdfSopenharmony_cistatic int fd = -1; 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_cistatic void run_test(void) 48f08c3bdfSopenharmony_ci{ 49f08c3bdfSopenharmony_ci char *p, *q; 50f08c3bdfSopenharmony_ci unsigned long i; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci p = SAFE_MMAP(0, MAP_LENGTH + TRUNCATE_POINT, PROT_READ | PROT_WRITE, 53f08c3bdfSopenharmony_ci MAP_PRIVATE | MAP_NORESERVE, fd, 0); 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci SAFE_MUNMAP(p, MAP_LENGTH + TRUNCATE_POINT); 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci q = SAFE_MMAP((void *)HIGH_ADDR, MAP_LENGTH, PROT_READ | PROT_WRITE, 58f08c3bdfSopenharmony_ci MAP_PRIVATE, fd, 0); 59f08c3bdfSopenharmony_ci tst_res(TINFO, "High map at %p", q); 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci for (i = 0; i < MAP_LENGTH; i += hpage_size) 62f08c3bdfSopenharmony_ci q[i] = 1; 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci SAFE_FTRUNCATE(fd, TRUNCATE_POINT); 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_ci if (q[0] != 1) 67f08c3bdfSopenharmony_ci tst_res(TFAIL, "data mismatch"); 68f08c3bdfSopenharmony_ci else 69f08c3bdfSopenharmony_ci tst_res(TPASS, "Successful"); 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci SAFE_MUNMAP(q, MAP_LENGTH); 72f08c3bdfSopenharmony_ci} 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_cistatic void setup(void) 75f08c3bdfSopenharmony_ci{ 76f08c3bdfSopenharmony_ci hpage_size = SAFE_READ_MEMINFO("Hugepagesize:")*1024; 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci if (hpage_size > TRUNCATE_POINT) 79f08c3bdfSopenharmony_ci tst_brk(TCONF, "Huge page size is too large"); 80f08c3bdfSopenharmony_ci if (TRUNCATE_POINT % hpage_size) 81f08c3bdfSopenharmony_ci tst_brk(TCONF, "Truncation point is not aligned to huge page size"); 82f08c3bdfSopenharmony_ci fd = tst_creat_unlinked(MNTPOINT, 0); 83f08c3bdfSopenharmony_ci} 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_cistatic void cleanup(void) 86f08c3bdfSopenharmony_ci{ 87f08c3bdfSopenharmony_ci if (fd >= 0) 88f08c3bdfSopenharmony_ci SAFE_CLOSE(fd); 89f08c3bdfSopenharmony_ci} 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_cistatic struct tst_test test = { 92f08c3bdfSopenharmony_ci .tags = (struct tst_tag[]) { 93f08c3bdfSopenharmony_ci {"linux-git", "856fc2950555"}, 94f08c3bdfSopenharmony_ci {} 95f08c3bdfSopenharmony_ci }, 96f08c3bdfSopenharmony_ci .needs_root = 1, 97f08c3bdfSopenharmony_ci .mntpoint = MNTPOINT, 98f08c3bdfSopenharmony_ci .needs_hugetlbfs = 1, 99f08c3bdfSopenharmony_ci .setup = setup, 100f08c3bdfSopenharmony_ci .cleanup = cleanup, 101f08c3bdfSopenharmony_ci .test_all = run_test, 102f08c3bdfSopenharmony_ci .hugepages = {4, TST_NEEDS}, 103f08c3bdfSopenharmony_ci}; 104