• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011  Red Hat, Inc.
3  * This program is free software; you can redistribute it and/or
4  * modify it under the terms of version 2 of the GNU General Public
5  * License as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it would be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10  *
11  * Further, this software is distributed without any warranty that it
12  * is free of the rightful claim of any third person regarding
13  * infringement or the like.  Any license provided herein, whether
14  * implied or otherwise, applies only to this software file.  Patent
15  * licenses, if any, provided herein do not apply to combinations of
16  * this program with other software, or any other product whatsoever.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301, USA.
22  *
23  * thp02 - detect mremap bug when THP is enabled.
24  *
25  * There was a bug in mremap THP support, sometimes crash happened
26  * due to the following reason according to developers:
27  *
28  * "alloc_new_pmd was forcing the allocation of a pte before calling
29  * move_huge_page and that resulted in a VM_BUG_ON in move_huge_page
30  * because the pmd wasn't zero."
31  *
32  * There are 4 cases to test this bug:
33  *
34  * 1) old_addr hpage aligned, old_end not hpage aligned, new_addr
35  *    hpage aligned;
36  * 2) old_addr hpage aligned, old_end not hpage aligned, new_addr not
37  *    hpage aligned;
38  * 3) old_addr not hpage aligned, old_end hpage aligned, new_addr
39  *    hpage aligned;
40  * 4) old_addr not hpage aligned, old_end hpage aligned, new_addr not
41  *    hpage aligned.
42  *
43  */
44 
45 #define _GNU_SOURCE
46 #include "config.h"
47 #include <sys/types.h>
48 #include <sys/mman.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53 #include "mem.h"
54 
55 char *TCID = "thp02";
56 int TST_TOTAL = 1;
57 
58 #ifdef HAVE_MREMAP_FIXED
59 static int ps;
60 static long hps, size;
61 static void *p, *p2, *p3, *p4;
62 
63 static void do_mremap(void);
64 
main(int argc,char ** argv)65 int main(int argc, char **argv)
66 {
67 	int lc;
68 
69 	tst_parse_opts(argc, argv, NULL, NULL);
70 
71 	setup();
72 
73 	for (lc = 0; TEST_LOOPING(lc); lc++) {
74 		tst_count = 0;
75 
76 		do_mremap();
77 	}
78 	tst_resm(TPASS, "Still alive.");
79 
80 	cleanup();
81 	tst_exit();
82 
83 }
84 
do_mremap(void)85 static void do_mremap(void)
86 {
87 	int i;
88 	void *old_addr, *new_addr;
89 
90 	for (i = 0; i < 4; i++) {
91 		if (posix_memalign(&p, hps, size))
92 			tst_brkm(TBROK | TERRNO, cleanup, "memalign p");
93 		if (posix_memalign(&p2, hps, size))
94 			tst_brkm(TBROK | TERRNO, cleanup, "memalign p2");
95 		if (posix_memalign(&p3, hps, size))
96 			tst_brkm(TBROK | TERRNO, cleanup, "memalign p3");
97 
98 		memset(p, 0xff, size);
99 		memset(p2, 0xff, size);
100 		memset(p3, 0x77, size);
101 
102 		/*
103 		 * Will try to do the following 4 mremaps cases:
104 		 *   mremap(p, size-ps, size-ps, flag, p3);
105 		 *   mremap(p, size-ps, size-ps, flag, p3+ps);
106 		 *   mremap(p+ps, size-ps, size-ps, flag, p3);
107 		 *   mremap(p+ps, size-ps, size-ps, flag, p3+ps);
108 		 */
109 		old_addr = p + ps * (i >> 1);
110 		new_addr = p3 + ps * (i & 1);
111 		tst_resm(TINFO, "mremap %p to %p", old_addr, new_addr);
112 
113 		p4 = mremap(old_addr, size - ps, size - ps,
114 			    MREMAP_FIXED | MREMAP_MAYMOVE, new_addr);
115 		if (p4 == MAP_FAILED)
116 			tst_brkm(TBROK | TERRNO, cleanup, "mremap");
117 		if (memcmp(p4, p2, size - ps))
118 			tst_brkm(TBROK, cleanup, "mremap bug");
119 	}
120 }
121 
setup(void)122 void setup(void)
123 {
124 	if (access(PATH_THP, F_OK) == -1)
125 		tst_brkm(TCONF, NULL, "THP not enabled in kernel?");
126 
127 	tst_sig(FORK, DEF_HANDLER, cleanup);
128 	TEST_PAUSE;
129 
130 	ps = sysconf(_SC_PAGESIZE);
131 	hps = read_meminfo("Hugepagesize:") * 1024;
132 	size = hps * 4;
133 }
134 
cleanup(void)135 void cleanup(void)
136 {
137 }
138 
139 #else
main(void)140 int main(void)
141 {
142 	tst_brkm(TCONF, NULL, "MREMAP_FIXED not present in <sys/mman.h>");
143 }
144 #endif /* HAVE_MREMAP_FIXED */
145