1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) 2013 FNST, DAN LI <li.dan@cn.fujitsu.com> 4f08c3bdfSopenharmony_ci */ 5f08c3bdfSopenharmony_ci 6f08c3bdfSopenharmony_ci/* 7f08c3bdfSopenharmony_ci * Test Description: 8f08c3bdfSopenharmony_ci * Verify MAP_POPULATE works fine. 9f08c3bdfSopenharmony_ci * "For a file mapping, this causes read-ahead on the file. 10f08c3bdfSopenharmony_ci * Later accesses to the mapping will not be blocked by page faults" 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * Expected Result: 13f08c3bdfSopenharmony_ci * mmap() with MAP_POPULATE should succeed returning the address of the 14f08c3bdfSopenharmony_ci * mapped region and this file has been read into RAM, so pages should 15f08c3bdfSopenharmony_ci * be present. 16f08c3bdfSopenharmony_ci */ 17f08c3bdfSopenharmony_ci#include <stdio.h> 18f08c3bdfSopenharmony_ci#include <stdlib.h> 19f08c3bdfSopenharmony_ci#include <sys/types.h> 20f08c3bdfSopenharmony_ci#include <errno.h> 21f08c3bdfSopenharmony_ci#include <unistd.h> 22f08c3bdfSopenharmony_ci#include <fcntl.h> 23f08c3bdfSopenharmony_ci#include <string.h> 24f08c3bdfSopenharmony_ci#include <signal.h> 25f08c3bdfSopenharmony_ci#include <stdint.h> 26f08c3bdfSopenharmony_ci#include <sys/stat.h> 27f08c3bdfSopenharmony_ci#include <sys/mman.h> 28f08c3bdfSopenharmony_ci#include <sys/shm.h> 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include "tst_test.h" 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#define TEMPFILE "mmapfile" 33f08c3bdfSopenharmony_ci#define PATHLEN 256 34f08c3bdfSopenharmony_ci#define MMAPSIZE (1UL<<20) 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_cistatic int fildes; 37f08c3bdfSopenharmony_cistatic char *addr; 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic void page_check(void) 40f08c3bdfSopenharmony_ci{ 41f08c3bdfSopenharmony_ci int i = 1; 42f08c3bdfSopenharmony_ci int flag = 0; 43f08c3bdfSopenharmony_ci int pm; 44f08c3bdfSopenharmony_ci int num_pages; 45f08c3bdfSopenharmony_ci long index; 46f08c3bdfSopenharmony_ci off_t offset; 47f08c3bdfSopenharmony_ci size_t page_sz; 48f08c3bdfSopenharmony_ci uint64_t pagemap; 49f08c3bdfSopenharmony_ci unsigned long vmstart; 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci vmstart = (unsigned long)addr; 52f08c3bdfSopenharmony_ci page_sz = getpagesize(); 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_ci num_pages = MMAPSIZE / page_sz; 55f08c3bdfSopenharmony_ci index = (vmstart / page_sz) * sizeof(uint64_t); 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci pm = open("/proc/self/pagemap", O_RDONLY); 58f08c3bdfSopenharmony_ci if (pm == -1) { 59f08c3bdfSopenharmony_ci if ((errno == EPERM) && (geteuid() != 0)) { 60f08c3bdfSopenharmony_ci tst_res(TCONF | TERRNO, 61f08c3bdfSopenharmony_ci "don't have permission to open dev pagemap"); 62f08c3bdfSopenharmony_ci return; 63f08c3bdfSopenharmony_ci } else { 64f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, "pen dev pagemap failed"); 65f08c3bdfSopenharmony_ci } 66f08c3bdfSopenharmony_ci } 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci offset = SAFE_LSEEK(pm, index, SEEK_SET); 69f08c3bdfSopenharmony_ci if (offset != index) 70f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, "Reposition offset failed"); 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci while (i <= num_pages) { 73f08c3bdfSopenharmony_ci SAFE_READ(1, pm, &pagemap, sizeof(uint64_t)); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci /* 76f08c3bdfSopenharmony_ci * Check if the page is present. 77f08c3bdfSopenharmony_ci */ 78f08c3bdfSopenharmony_ci if (!(pagemap & (1ULL<<63))) { 79f08c3bdfSopenharmony_ci tst_res(TINFO, "The %dth page addressed at %lX is not " 80f08c3bdfSopenharmony_ci "present", i, vmstart + i * page_sz); 81f08c3bdfSopenharmony_ci flag = 1; 82f08c3bdfSopenharmony_ci } 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_ci i++; 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci 87f08c3bdfSopenharmony_ci close(pm); 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci if (!flag) 90f08c3bdfSopenharmony_ci tst_res(TINFO, "All pages are present"); 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_civoid verify_mmap(void) 94f08c3bdfSopenharmony_ci{ 95f08c3bdfSopenharmony_ci unsigned int i; 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci addr = mmap(NULL, MMAPSIZE, PROT_READ | PROT_WRITE, 98f08c3bdfSopenharmony_ci MAP_PRIVATE | MAP_POPULATE, fildes, 0); 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci if (addr == MAP_FAILED) { 101f08c3bdfSopenharmony_ci tst_res(TFAIL | TERRNO, "mmap of %s failed", TEMPFILE); 102f08c3bdfSopenharmony_ci return; 103f08c3bdfSopenharmony_ci } 104f08c3bdfSopenharmony_ci 105f08c3bdfSopenharmony_ci page_check(); 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci for (i = 0; i < MMAPSIZE; i++) { 108f08c3bdfSopenharmony_ci if (addr[i]) { 109f08c3bdfSopenharmony_ci tst_res(TFAIL, "Non-zero byte at offset %i", i); 110f08c3bdfSopenharmony_ci goto unmap; 111f08c3bdfSopenharmony_ci } 112f08c3bdfSopenharmony_ci } 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci tst_res(TPASS, "File mapped properly"); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ciunmap: 117f08c3bdfSopenharmony_ci SAFE_MUNMAP(addr, MMAPSIZE); 118f08c3bdfSopenharmony_ci} 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_cistatic void setup(void) 121f08c3bdfSopenharmony_ci{ 122f08c3bdfSopenharmony_ci fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0766); 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci SAFE_FTRUNCATE(fildes, MMAPSIZE); 125f08c3bdfSopenharmony_ci} 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_cistatic void cleanup(void) 128f08c3bdfSopenharmony_ci{ 129f08c3bdfSopenharmony_ci if (fildes > 0) 130f08c3bdfSopenharmony_ci SAFE_CLOSE(fildes); 131f08c3bdfSopenharmony_ci} 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_cistatic struct tst_test test = { 134f08c3bdfSopenharmony_ci .setup = setup, 135f08c3bdfSopenharmony_ci .cleanup = cleanup, 136f08c3bdfSopenharmony_ci .test_all = verify_mmap, 137f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 138f08c3bdfSopenharmony_ci}; 139