1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Copyright (C) 2012 Linux Test Project, Inc.
3f08c3bdfSopenharmony_ci *
4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or
5f08c3bdfSopenharmony_ci * modify it under the terms of version 2 of the GNU General Public
6f08c3bdfSopenharmony_ci * License as published by the Free Software Foundation.
7f08c3bdfSopenharmony_ci *
8f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful,
9f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
10f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it
13f08c3bdfSopenharmony_ci * is free of the rightful claim of any third person regarding
14f08c3bdfSopenharmony_ci * infringement or the like.  Any license provided herein, whether
15f08c3bdfSopenharmony_ci * implied or otherwise, applies only to this software file.  Patent
16f08c3bdfSopenharmony_ci * licenses, if any, provided herein do not apply to combinations of
17f08c3bdfSopenharmony_ci * this program with other software, or any other product whatsoever.
18f08c3bdfSopenharmony_ci *
19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License
20f08c3bdfSopenharmony_ci * along with this program; if not, write the Free Software
21f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22f08c3bdfSopenharmony_ci * 02110-1301, USA.
23f08c3bdfSopenharmony_ci */
24f08c3bdfSopenharmony_ci/*
25f08c3bdfSopenharmony_ci * Test Name: mremap05
26f08c3bdfSopenharmony_ci *
27f08c3bdfSopenharmony_ci * Test Description:
28f08c3bdfSopenharmony_ci *  Verify that MREMAP_FIXED fails without MREMAP_MAYMOVE.
29f08c3bdfSopenharmony_ci *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if target address
30f08c3bdfSopenharmony_ci *    is not page aligned.
31f08c3bdfSopenharmony_ci *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE fails if old range
32f08c3bdfSopenharmony_ci *    overlaps with new range.
33f08c3bdfSopenharmony_ci *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE can move mapping to new address.
34f08c3bdfSopenharmony_ci *  Verify that MREMAP_FIXED|MREMAP_MAYMOVE unmaps previous mapping
35f08c3bdfSopenharmony_ci *    at the address range specified by new_address and new_size.
36f08c3bdfSopenharmony_ci */
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#define _GNU_SOURCE
39f08c3bdfSopenharmony_ci#include "config.h"
40f08c3bdfSopenharmony_ci#include <sys/mman.h>
41f08c3bdfSopenharmony_ci#include <errno.h>
42f08c3bdfSopenharmony_ci#include <unistd.h>
43f08c3bdfSopenharmony_ci#include "test.h"
44f08c3bdfSopenharmony_ci#include "safe_macros.h"
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_cichar *TCID = "mremap05";
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_cistruct test_case_t {
49f08c3bdfSopenharmony_ci	char *old_address;
50f08c3bdfSopenharmony_ci	char *new_address;
51f08c3bdfSopenharmony_ci	size_t old_size;	/* in pages */
52f08c3bdfSopenharmony_ci	size_t new_size;	/* in pages */
53f08c3bdfSopenharmony_ci	int flags;
54f08c3bdfSopenharmony_ci	const char *msg;
55f08c3bdfSopenharmony_ci	void *exp_ret;
56f08c3bdfSopenharmony_ci	int exp_errno;
57f08c3bdfSopenharmony_ci	char *ret;
58f08c3bdfSopenharmony_ci	void (*setup) (struct test_case_t *);
59f08c3bdfSopenharmony_ci	void (*cleanup) (struct test_case_t *);
60f08c3bdfSopenharmony_ci};
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic void setup(void);
63f08c3bdfSopenharmony_cistatic void cleanup(void);
64f08c3bdfSopenharmony_cistatic void setup0(struct test_case_t *);
65f08c3bdfSopenharmony_cistatic void setup1(struct test_case_t *);
66f08c3bdfSopenharmony_cistatic void setup2(struct test_case_t *);
67f08c3bdfSopenharmony_cistatic void setup3(struct test_case_t *);
68f08c3bdfSopenharmony_cistatic void setup4(struct test_case_t *);
69f08c3bdfSopenharmony_cistatic void cleanup0(struct test_case_t *);
70f08c3bdfSopenharmony_cistatic void cleanup1(struct test_case_t *);
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_cistruct test_case_t tdat[] = {
73f08c3bdfSopenharmony_ci	{
74f08c3bdfSopenharmony_ci	 .old_size = 1,
75f08c3bdfSopenharmony_ci	 .new_size = 1,
76f08c3bdfSopenharmony_ci	 .flags = MREMAP_FIXED,
77f08c3bdfSopenharmony_ci	 .msg = "MREMAP_FIXED requires MREMAP_MAYMOVE",
78f08c3bdfSopenharmony_ci	 .exp_ret = MAP_FAILED,
79f08c3bdfSopenharmony_ci	 .exp_errno = EINVAL,
80f08c3bdfSopenharmony_ci	 .setup = setup0,
81f08c3bdfSopenharmony_ci	 .cleanup = cleanup0},
82f08c3bdfSopenharmony_ci	{
83f08c3bdfSopenharmony_ci	 .old_size = 1,
84f08c3bdfSopenharmony_ci	 .new_size = 1,
85f08c3bdfSopenharmony_ci	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
86f08c3bdfSopenharmony_ci	 .msg = "new_addr has to be page aligned",
87f08c3bdfSopenharmony_ci	 .exp_ret = MAP_FAILED,
88f08c3bdfSopenharmony_ci	 .exp_errno = EINVAL,
89f08c3bdfSopenharmony_ci	 .setup = setup1,
90f08c3bdfSopenharmony_ci	 .cleanup = cleanup0},
91f08c3bdfSopenharmony_ci	{
92f08c3bdfSopenharmony_ci	 .old_size = 2,
93f08c3bdfSopenharmony_ci	 .new_size = 1,
94f08c3bdfSopenharmony_ci	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
95f08c3bdfSopenharmony_ci	 .msg = "old/new area must not overlap",
96f08c3bdfSopenharmony_ci	 .exp_ret = MAP_FAILED,
97f08c3bdfSopenharmony_ci	 .exp_errno = EINVAL,
98f08c3bdfSopenharmony_ci	 .setup = setup2,
99f08c3bdfSopenharmony_ci	 .cleanup = cleanup0},
100f08c3bdfSopenharmony_ci	{
101f08c3bdfSopenharmony_ci	 .old_size = 1,
102f08c3bdfSopenharmony_ci	 .new_size = 1,
103f08c3bdfSopenharmony_ci	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
104f08c3bdfSopenharmony_ci	 .msg = "mremap #1",
105f08c3bdfSopenharmony_ci	 .setup = setup3,
106f08c3bdfSopenharmony_ci	 .cleanup = cleanup0},
107f08c3bdfSopenharmony_ci	{
108f08c3bdfSopenharmony_ci	 .old_size = 1,
109f08c3bdfSopenharmony_ci	 .new_size = 1,
110f08c3bdfSopenharmony_ci	 .flags = MREMAP_FIXED | MREMAP_MAYMOVE,
111f08c3bdfSopenharmony_ci	 .msg = "mremap #2",
112f08c3bdfSopenharmony_ci	 .setup = setup4,
113f08c3bdfSopenharmony_ci	 .cleanup = cleanup1},
114f08c3bdfSopenharmony_ci};
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_cistatic int pagesize;
117f08c3bdfSopenharmony_cistatic int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]);
118f08c3bdfSopenharmony_ci
119f08c3bdfSopenharmony_cistatic void free_test_area(void *p, int size)
120f08c3bdfSopenharmony_ci{
121f08c3bdfSopenharmony_ci	SAFE_MUNMAP(cleanup, p, size);
122f08c3bdfSopenharmony_ci}
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_cistatic void *get_test_area(int size, int free_area)
125f08c3bdfSopenharmony_ci{
126f08c3bdfSopenharmony_ci	void *p;
127f08c3bdfSopenharmony_ci	p = mmap(NULL, size, PROT_READ | PROT_WRITE,
128f08c3bdfSopenharmony_ci		 MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
129f08c3bdfSopenharmony_ci	if (p == MAP_FAILED)
130f08c3bdfSopenharmony_ci		tst_brkm(TBROK | TERRNO, cleanup, "get_test_area mmap");
131f08c3bdfSopenharmony_ci	if (free_area)
132f08c3bdfSopenharmony_ci		free_test_area(p, size);
133f08c3bdfSopenharmony_ci	return p;
134f08c3bdfSopenharmony_ci}
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_cistatic void test_mremap(struct test_case_t *t)
137f08c3bdfSopenharmony_ci{
138f08c3bdfSopenharmony_ci	t->ret = mremap(t->old_address, t->old_size, t->new_size, t->flags,
139f08c3bdfSopenharmony_ci			t->new_address);
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci	if (t->ret == t->exp_ret) {
142f08c3bdfSopenharmony_ci		if (t->ret != MAP_FAILED) {
143f08c3bdfSopenharmony_ci			tst_resm(TPASS, "%s", t->msg);
144f08c3bdfSopenharmony_ci			if (*(t->ret) == 0x1)
145f08c3bdfSopenharmony_ci				tst_resm(TPASS, "%s value OK", t->msg);
146f08c3bdfSopenharmony_ci			else
147f08c3bdfSopenharmony_ci				tst_resm(TPASS, "%s value failed", t->msg);
148f08c3bdfSopenharmony_ci		} else {
149f08c3bdfSopenharmony_ci			if (errno == t->exp_errno)
150f08c3bdfSopenharmony_ci				tst_resm(TPASS, "%s", t->msg);
151f08c3bdfSopenharmony_ci			else
152f08c3bdfSopenharmony_ci				tst_resm(TFAIL | TERRNO, "%s", t->msg);
153f08c3bdfSopenharmony_ci		}
154f08c3bdfSopenharmony_ci	} else {
155f08c3bdfSopenharmony_ci		tst_resm(TFAIL, "%s ret: %p, expected: %p", t->msg,
156f08c3bdfSopenharmony_ci			 t->ret, t->exp_ret);
157f08c3bdfSopenharmony_ci	}
158f08c3bdfSopenharmony_ci}
159f08c3bdfSopenharmony_ci
160f08c3bdfSopenharmony_cistatic void setup0(struct test_case_t *t)
161f08c3bdfSopenharmony_ci{
162f08c3bdfSopenharmony_ci	t->old_address = get_test_area(t->old_size * pagesize, 0);
163f08c3bdfSopenharmony_ci	t->new_address = get_test_area(t->new_size * pagesize, 1);
164f08c3bdfSopenharmony_ci}
165f08c3bdfSopenharmony_ci
166f08c3bdfSopenharmony_cistatic void setup1(struct test_case_t *t)
167f08c3bdfSopenharmony_ci{
168f08c3bdfSopenharmony_ci	t->old_address = get_test_area(t->old_size * pagesize, 0);
169f08c3bdfSopenharmony_ci	t->new_address = get_test_area((t->new_size + 1) * pagesize, 1) + 1;
170f08c3bdfSopenharmony_ci}
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_cistatic void setup2(struct test_case_t *t)
173f08c3bdfSopenharmony_ci{
174f08c3bdfSopenharmony_ci	t->old_address = get_test_area(t->old_size * pagesize, 0);
175f08c3bdfSopenharmony_ci	t->new_address = t->old_address;
176f08c3bdfSopenharmony_ci}
177f08c3bdfSopenharmony_ci
178f08c3bdfSopenharmony_cistatic void setup3(struct test_case_t *t)
179f08c3bdfSopenharmony_ci{
180f08c3bdfSopenharmony_ci	t->old_address = get_test_area(t->old_size * pagesize, 0);
181f08c3bdfSopenharmony_ci	t->new_address = get_test_area(t->new_size * pagesize, 1);
182f08c3bdfSopenharmony_ci	t->exp_ret = t->new_address;
183f08c3bdfSopenharmony_ci	*(t->old_address) = 0x1;
184f08c3bdfSopenharmony_ci}
185f08c3bdfSopenharmony_ci
186f08c3bdfSopenharmony_cistatic void setup4(struct test_case_t *t)
187f08c3bdfSopenharmony_ci{
188f08c3bdfSopenharmony_ci	t->old_address = get_test_area(t->old_size * pagesize, 0);
189f08c3bdfSopenharmony_ci	t->new_address = get_test_area(t->new_size * pagesize, 0);
190f08c3bdfSopenharmony_ci	t->exp_ret = t->new_address;
191f08c3bdfSopenharmony_ci	*(t->old_address) = 0x1;
192f08c3bdfSopenharmony_ci	*(t->new_address) = 0x2;
193f08c3bdfSopenharmony_ci}
194f08c3bdfSopenharmony_ci
195f08c3bdfSopenharmony_cistatic void cleanup0(struct test_case_t *t)
196f08c3bdfSopenharmony_ci{
197f08c3bdfSopenharmony_ci	if (t->ret == MAP_FAILED)
198f08c3bdfSopenharmony_ci		free_test_area(t->old_address, t->old_size * pagesize);
199f08c3bdfSopenharmony_ci	else
200f08c3bdfSopenharmony_ci		free_test_area(t->ret, t->new_size * pagesize);
201f08c3bdfSopenharmony_ci}
202f08c3bdfSopenharmony_ci
203f08c3bdfSopenharmony_cistatic void cleanup1(struct test_case_t *t)
204f08c3bdfSopenharmony_ci{
205f08c3bdfSopenharmony_ci	if (t->ret == MAP_FAILED) {
206f08c3bdfSopenharmony_ci		free_test_area(t->old_address, t->old_size * pagesize);
207f08c3bdfSopenharmony_ci		free_test_area(t->new_address, t->new_size * pagesize);
208f08c3bdfSopenharmony_ci	} else {
209f08c3bdfSopenharmony_ci		free_test_area(t->ret, t->new_size * pagesize);
210f08c3bdfSopenharmony_ci	}
211f08c3bdfSopenharmony_ci}
212f08c3bdfSopenharmony_ci
213f08c3bdfSopenharmony_ciint main(int ac, char **av)
214f08c3bdfSopenharmony_ci{
215f08c3bdfSopenharmony_ci	int lc, testno;
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci	tst_parse_opts(ac, av, NULL, NULL);
218f08c3bdfSopenharmony_ci
219f08c3bdfSopenharmony_ci	setup();
220f08c3bdfSopenharmony_ci	for (lc = 0; TEST_LOOPING(lc); lc++) {
221f08c3bdfSopenharmony_ci		tst_count = 0;
222f08c3bdfSopenharmony_ci		for (testno = 0; testno < TST_TOTAL; testno++) {
223f08c3bdfSopenharmony_ci			tdat[testno].setup(&tdat[testno]);
224f08c3bdfSopenharmony_ci			test_mremap(&tdat[testno]);
225f08c3bdfSopenharmony_ci			tdat[testno].cleanup(&tdat[testno]);
226f08c3bdfSopenharmony_ci		}
227f08c3bdfSopenharmony_ci	}
228f08c3bdfSopenharmony_ci	cleanup();
229f08c3bdfSopenharmony_ci	tst_exit();
230f08c3bdfSopenharmony_ci}
231f08c3bdfSopenharmony_ci
232f08c3bdfSopenharmony_cistatic void setup(void)
233f08c3bdfSopenharmony_ci{
234f08c3bdfSopenharmony_ci	pagesize = getpagesize();
235f08c3bdfSopenharmony_ci}
236f08c3bdfSopenharmony_ci
237f08c3bdfSopenharmony_cistatic void cleanup(void)
238f08c3bdfSopenharmony_ci{
239f08c3bdfSopenharmony_ci}
240