blob: 1df2c2ec183cd651e56c426d5eceff0aefe17ee2 [file] [log] [blame]
robbiewf226d4b2004-04-20 17:27:30 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2004
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
robbiewf226d4b2004-04-20 17:27:30 +000018 */
19
20/*
21 * Test Name: hugemmap02
22 *
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080023 * Test Description: There is both a low hugepage region (at 2-3G for use by
24 * 32-bit processes) and a high hugepage region (at 1-1.5T). The high region
25 * is always exclusively for hugepages, but the low region has to be activated
26 * before it can be used for hugepages. When the kernel attempts to do a
27 * hugepage mapping in a 32-bit process it will automatically attempt to open
28 * the low region. However, that will fail if there are any normal
29 * (non-hugepage) mappings in the region already.
subrata_modak4bb656a2009-02-26 12:02:09 +000030 *
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080031 * When run as a 64-bit process the kernel will still do a non-hugepage mapping
32 * in the low region, but the following hugepage mapping will succeed. This is
33 * because it comes from the high region, which is available to the 64-bit
34 * process.
35 *
36 * This test case is checking this behavior.
robbiewf226d4b2004-04-20 17:27:30 +000037 *
38 * HISTORY
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080039 * 04/2004 Written by Robbie Williamson
robbiewf226d4b2004-04-20 17:27:30 +000040 */
41
Caspar Zhang79667fa2012-03-12 14:41:46 +080042#include <sys/types.h>
43#include <sys/mman.h>
44#include <sys/mount.h>
45#include <sys/stat.h>
robbiewf226d4b2004-04-20 17:27:30 +000046#include <errno.h>
robbiewf226d4b2004-04-20 17:27:30 +000047#include <fcntl.h>
robbiewf226d4b2004-04-20 17:27:30 +000048#include <signal.h>
49#include <stdint.h>
Caspar Zhang79667fa2012-03-12 14:41:46 +080050#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
robbiewf226d4b2004-04-20 17:27:30 +000054
55#include "test.h"
Wanlong Gao56d368c2012-02-10 11:16:22 +080056#include "safe_macros.h"
Caspar Zhang79667fa2012-03-12 14:41:46 +080057#include "mem.h"
robbiewf226d4b2004-04-20 17:27:30 +000058
subrata_modak9c929012008-10-21 08:49:00 +000059#define LOW_ADDR (void *)(0x80000000)
60#define LOW_ADDR2 (void *)(0x90000000)
robbiewf226d4b2004-04-20 17:27:30 +000061
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080062static char TEMPFILE[MAXPATHLEN];
robbiewf226d4b2004-04-20 17:27:30 +000063
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080064char *TCID = "hugemmap02";
65int TST_TOTAL = 1;
66static unsigned long *addr;
67static unsigned long *addr2;
68static unsigned long *addrlist[5];
69static int i;
70static int fildes;
71static int nfildes;
72static char *Hopt;
Wanlong Gao9b4865f2012-02-08 17:13:51 +080073static char *nr_opt;
74static long hugepages = 128;
75static long orig_hugepages;
robbiewf226d4b2004-04-20 17:27:30 +000076
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080077static void help(void);
robbiewf226d4b2004-04-20 17:27:30 +000078
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080079int main(int ac, char **av)
robbiewf226d4b2004-04-20 17:27:30 +000080{
Garrett Cooper22cd8d12010-12-16 21:53:13 -080081 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +020082 const char *msg;
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080083 int Hflag = 0;
Caspar Zhang51725fc2012-03-13 11:02:55 +080084 long page_sz, map_sz;
Wanlong Gao9b4865f2012-02-08 17:13:51 +080085 int sflag = 0;
robbiewf226d4b2004-04-20 17:27:30 +000086
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080087 option_t options[] = {
Wanlong Gao354ebb42012-12-07 10:10:04 +080088 {"H:", &Hflag, &Hopt},
89 {"s:", &sflag, &nr_opt},
90 {NULL, NULL, NULL}
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080091 };
robbiewf226d4b2004-04-20 17:27:30 +000092
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080093 msg = parse_opts(ac, av, options, &help);
Wanlong Gao9b4865f2012-02-08 17:13:51 +080094 if (msg)
Wanlong Gao0be3a4e2012-02-06 11:16:24 +080095 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s,"
96 " use -help", msg);
robbiewf226d4b2004-04-20 17:27:30 +000097
Wanlong Gao9b4865f2012-02-08 17:13:51 +080098 if (!Hflag) {
99 tst_tmpdir();
Cyril Hrubis9c31ad22014-05-14 17:15:39 +0200100 Hopt = tst_get_tmpdir();
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800101 }
Wanlong Gao56d368c2012-02-10 11:16:22 +0800102 if (sflag)
103 hugepages = SAFE_STRTOL(NULL, nr_opt, 0, LONG_MAX);
subrata_modakbdbaec52009-02-26 12:14:51 +0000104
Garrett Cooper71543af2011-04-21 20:24:03 -0700105 page_sz = getpagesize();
Caspar Zhang51725fc2012-03-13 11:02:55 +0800106 map_sz = read_meminfo("Hugepagesize:") * 1024 * 2;
Garrett Cooper71543af2011-04-21 20:24:03 -0700107
robbiewf226d4b2004-04-20 17:27:30 +0000108 setup();
109
robbiewf226d4b2004-04-20 17:27:30 +0000110 for (lc = 0; TEST_LOOPING(lc); lc++) {
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800111 /* Creat a temporary file used for huge mapping */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800112 fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666);
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800113 if (fildes < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 tst_brkm(TBROK | TERRNO, cleanup,
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800115 "opening %s failed", TEMPFILE);
subrata_modakbdbaec52009-02-26 12:14:51 +0000116
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800117 /* Creat a file used for normal mapping */
118 nfildes = open("/dev/zero", O_RDONLY, 0666);
119 if (nfildes < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800120 tst_brkm(TBROK | TERRNO, cleanup,
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800121 "opening /dev/zero failed");
Garrett Cooper2c282152010-12-16 00:55:50 -0800122
Caspar Zhangd59a6592013-03-07 14:59:12 +0800123 tst_count = 0;
robbiewf226d4b2004-04-20 17:27:30 +0000124
subrata_modak4bb656a2009-02-26 12:02:09 +0000125 /*
robbiewf226d4b2004-04-20 17:27:30 +0000126 * Call mmap on /dev/zero 5 times
127 */
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800128 for (i = 0; i < 5; i++) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800129 addr = mmap(0, 256 * 1024 * 1024, PROT_READ,
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800130 MAP_SHARED, nfildes, 0);
131 addrlist[i] = addr;
132 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800133
robbiewf226d4b2004-04-20 17:27:30 +0000134 /* mmap using normal pages and a low memory address */
Garrett Cooper71543af2011-04-21 20:24:03 -0700135 addr = mmap(LOW_ADDR, page_sz, PROT_READ,
robbiewf226d4b2004-04-20 17:27:30 +0000136 MAP_SHARED | MAP_FIXED, nfildes, 0);
137 if (addr == MAP_FAILED)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800138 tst_brkm(TBROK | TERRNO, cleanup,
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800139 "mmap failed on nfildes");
robbiewf226d4b2004-04-20 17:27:30 +0000140
141 /* Attempt to mmap a huge page into a low memory address */
Garrett Cooper71543af2011-04-21 20:24:03 -0700142 addr2 = mmap(LOW_ADDR2, map_sz, PROT_READ | PROT_WRITE,
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800143 MAP_SHARED, fildes, 0);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800144#if __WORDSIZE == 64 /* 64-bit process */
robbiewf226d4b2004-04-20 17:27:30 +0000145 if (addr2 == MAP_FAILED) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800146 tst_resm(TFAIL | TERRNO, "huge mmap failed unexpectedly"
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800147 " with %s (64-bit)", TEMPFILE);
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800148 close(fildes);
robbiewf226d4b2004-04-20 17:27:30 +0000149 continue;
150 } else {
Garrett Cooper22cd8d12010-12-16 21:53:13 -0800151 tst_resm(TPASS, "huge mmap succeeded (64-bit)");
robbiewf226d4b2004-04-20 17:27:30 +0000152 }
subrata_modak4bb656a2009-02-26 12:02:09 +0000153#else /* 32-bit process */
Garrett Cooper22cd8d12010-12-16 21:53:13 -0800154 if (addr2 == MAP_FAILED)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800155 tst_resm(TFAIL | TERRNO, "huge mmap failed unexpectedly"
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800156 " with %s (32-bit)", TEMPFILE);
Garrett Cooper22cd8d12010-12-16 21:53:13 -0800157 else if (addr2 > 0) {
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800158 tst_resm(TCONF,
159 "huge mmap failed to test the scenario");
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800160 close(fildes);
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800161 continue;
162 } else if (addr == 0)
163 tst_resm(TPASS, "huge mmap succeeded (32-bit)");
robbiewf226d4b2004-04-20 17:27:30 +0000164#endif
165
166 /* Clean up things in case we are looping */
167 for (i = 0; i < 5; i++) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800168 if (munmap(addrlist[i], 256 * 1024 * 1024) == -1)
169 tst_resm(TBROK | TERRNO,
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800170 "munmap of addrlist[%d] failed", i);
171 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800172
Garrett Cooper22cd8d12010-12-16 21:53:13 -0800173#if __WORDSIZE == 64
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800174 if (munmap(addr2, map_sz) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800175 tst_brkm(TFAIL | TERRNO, NULL, "huge munmap failed");
robbiewf226d4b2004-04-20 17:27:30 +0000176#endif
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800177 if (munmap(addr, page_sz) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800178 tst_brkm(TFAIL | TERRNO, NULL, "munmap failed");
robbiewf226d4b2004-04-20 17:27:30 +0000179
180 close(fildes);
Garrett Cooper2c282152010-12-16 00:55:50 -0800181 }
robbiewf226d4b2004-04-20 17:27:30 +0000182
robbiewf226d4b2004-04-20 17:27:30 +0000183 cleanup();
Garrett Cooper22cd8d12010-12-16 21:53:13 -0800184 tst_exit();
Garrett Cooper2c282152010-12-16 00:55:50 -0800185}
robbiewf226d4b2004-04-20 17:27:30 +0000186
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800187void setup(void)
robbiewf226d4b2004-04-20 17:27:30 +0000188{
robbiewf226d4b2004-04-20 17:27:30 +0000189 TEST_PAUSE;
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800190 tst_require_root(NULL);
191 if (mount("none", Hopt, "hugetlbfs", 0, NULL) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800192 tst_brkm(TBROK | TERRNO, NULL, "mount failed on %s", Hopt);
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800193 orig_hugepages = get_sys_tune("nr_hugepages");
194 set_sys_tune("nr_hugepages", hugepages, 1);
Wanlong Gao354ebb42012-12-07 10:10:04 +0800195 snprintf(TEMPFILE, sizeof(TEMPFILE), "%s/mmapfile%d", Hopt, getpid());
robbiewf226d4b2004-04-20 17:27:30 +0000196}
197
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800198void cleanup(void)
robbiewf226d4b2004-04-20 17:27:30 +0000199{
robbiewf226d4b2004-04-20 17:27:30 +0000200 unlink(TEMPFILE);
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800201 set_sys_tune("nr_hugepages", orig_hugepages, 0);
robbiewf226d4b2004-04-20 17:27:30 +0000202
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800203 umount(Hopt);
Garrett Cooper22cd8d12010-12-16 21:53:13 -0800204 tst_rmdir();
Garrett Cooper71543af2011-04-21 20:24:03 -0700205}
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800206
207static void help(void)
208{
209 printf(" -H /.. Location of hugetlbfs, i.e. -H /var/hugetlbfs\n");
Wanlong Gao9b4865f2012-02-08 17:13:51 +0800210 printf(" -s num Set the number of the been allocated hugepages\n");
Wanlong Gao0be3a4e2012-02-06 11:16:24 +0800211}