189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew/*
215756239e687146c5052c724352a1d16201d0927Li Wang * Copyright (c) International Business Machines  Corp., 2001
315756239e687146c5052c724352a1d16201d0927Li Wang * Copyright (c) Linux Test Project, 2001-2017
489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *
515756239e687146c5052c724352a1d16201d0927Li Wang * This program is free software;  you can redistribute it and/or modify
615756239e687146c5052c724352a1d16201d0927Li Wang * it under the terms of the GNU General Public License as published by
715756239e687146c5052c724352a1d16201d0927Li Wang * the Free Software Foundation; either version 2 of the License, or
815756239e687146c5052c724352a1d16201d0927Li Wang * (at your option) any later version.
989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *
1015756239e687146c5052c724352a1d16201d0927Li Wang * This program is distributed in the hope that it will be useful,
1115756239e687146c5052c724352a1d16201d0927Li Wang * but WITHOUT ANY WARRANTY;  without even the implied warranty of
1215756239e687146c5052c724352a1d16201d0927Li Wang * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1315756239e687146c5052c724352a1d16201d0927Li Wang * the GNU General Public License for more details.
1489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew */
1589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
1689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew/*
1789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew * DESCRIPTION
1889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	hugeshmat01 - test that shmat() works correctly
1989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *
2089e9a4fe59b3e697750b2996d45b6a19156270f4robbiew * ALGORITHM
2189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	create a large shared memory resouce with read/write permissions
2289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	loop if that option was specified
2389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	call shmat() with the TEST() macro using three valid conditions
2489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	check the return code
2589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	  if failure, issue a FAIL message.
2689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	otherwise,
2789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	  if doing functionality testing
2889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *		check for the correct conditions after the call
291cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang *		if correct,
3089e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *			issue a PASS message
3189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *		otherwise
3289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *			issue a FAIL message
3389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	call cleanup
3489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *
3589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew * HISTORY
3689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	03/2001 - Written by Wayne Boyer
3789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *	04/2004 - Updated by Robbie Williamson
3889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew */
3989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
40a14f756d5890cee192f1cffe403b7607074a9b72Cyril Hrubis#include <limits.h>
41676746ed5fc3c897c2018c310d0fb72dabd18d8cLi Wang#include "hugetlb.h"
4289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
4315756239e687146c5052c724352a1d16201d0927Li Wang#define CASE0 10 /* values to write into the shared */
4415756239e687146c5052c724352a1d16201d0927Li Wang#define CASE1 20 /* memory location.                */
4589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
461cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhangstatic size_t shm_size;
47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic int shm_id_1 = -1;
48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostatic void *addr;
4989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
50491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhangstatic long hugepages = 128;
5115756239e687146c5052c724352a1d16201d0927Li Wang
5215756239e687146c5052c724352a1d16201d0927Li Wangstatic struct tst_option options[] = {
5315756239e687146c5052c724352a1d16201d0927Li Wang	{"s:", &nr_opt, "-s   num  Set the number of the been allocated hugepages"},
54354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	{NULL, NULL, NULL}
55491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhang};
56491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhang
5715756239e687146c5052c724352a1d16201d0927Li Wangstatic struct tcase {
58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int *shmid;
5989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	void *addr;
60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int flags;
6115756239e687146c5052c724352a1d16201d0927Li Wang} tcases[] = {
6289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	/* a straight forward read/write attach */
6315756239e687146c5052c724352a1d16201d0927Li Wang	{&shm_id_1, 0, 0},
6415756239e687146c5052c724352a1d16201d0927Li Wang	/*
6515756239e687146c5052c724352a1d16201d0927Li Wang	 * an attach using non aligned memory
6615756239e687146c5052c724352a1d16201d0927Li Wang	 * -1 will be replaced with an unaligned addr
6715756239e687146c5052c724352a1d16201d0927Li Wang	 */
6815756239e687146c5052c724352a1d16201d0927Li Wang	{&shm_id_1, (void *)-1, SHM_RND},
6915756239e687146c5052c724352a1d16201d0927Li Wang	/* a read only attach */
7015756239e687146c5052c724352a1d16201d0927Li Wang	{&shm_id_1, 0, SHM_RDONLY}
7189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew};
7289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
7315756239e687146c5052c724352a1d16201d0927Li Wangstatic void check_functionality(unsigned int i);
741cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang
7515756239e687146c5052c724352a1d16201d0927Li Wangstatic void verify_hugeshmat(unsigned int i)
7689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew{
7715756239e687146c5052c724352a1d16201d0927Li Wang	struct tcase *tc = &tcases[i];
7815756239e687146c5052c724352a1d16201d0927Li Wang
7915756239e687146c5052c724352a1d16201d0927Li Wang	addr = shmat(*(tc->shmid), tc->addr, tc->flags);
8015756239e687146c5052c724352a1d16201d0927Li Wang	if (addr == (void *)-1) {
8115756239e687146c5052c724352a1d16201d0927Li Wang		tst_brk(TFAIL | TERRNO, "shmat");
8215756239e687146c5052c724352a1d16201d0927Li Wang	} else {
8315756239e687146c5052c724352a1d16201d0927Li Wang		check_functionality(i);
8489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	}
8515756239e687146c5052c724352a1d16201d0927Li Wang
8615756239e687146c5052c724352a1d16201d0927Li Wang	/*
8715756239e687146c5052c724352a1d16201d0927Li Wang	 * addr in tcases[0] will be used to generate an unaligned
8815756239e687146c5052c724352a1d16201d0927Li Wang	 * address for tcases[1]
8915756239e687146c5052c724352a1d16201d0927Li Wang	 */
9015756239e687146c5052c724352a1d16201d0927Li Wang	if (i == 0 && addr != (void *)-1)
9115756239e687146c5052c724352a1d16201d0927Li Wang		tc[1].addr = (void *)(((unsigned long)addr &
9215756239e687146c5052c724352a1d16201d0927Li Wang					~(SHMLBA - 1)) + SHMLBA - 1);
9315756239e687146c5052c724352a1d16201d0927Li Wang	if (shmdt(addr) == -1)
9415756239e687146c5052c724352a1d16201d0927Li Wang		tst_brk(TBROK | TERRNO, "shmdt");
9589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew}
9689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
9789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew/*
984bb656a129f7507823e9e6d6b98b1a02fd80ef89subrata_modak * check_functionality - check various conditions to make sure they
9989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew *			 are correct.
10089e9a4fe59b3e697750b2996d45b6a19156270f4robbiew */
10115756239e687146c5052c724352a1d16201d0927Li Wangstatic void check_functionality(unsigned int i)
10289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew{
10389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	void *orig_add;
10489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	int *shared;
10589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	struct shmid_ds buf;
10689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
10789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	shared = (int *)addr;
10889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
10989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	/* stat the shared memory ID */
1101cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang	if (shmctl(shm_id_1, IPC_STAT, &buf) == -1)
11115756239e687146c5052c724352a1d16201d0927Li Wang		tst_brk(TBROK | TERRNO, "shmctl");
11289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
11389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	/* check the number of attaches */
11489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	if (buf.shm_nattch != 1) {
11515756239e687146c5052c724352a1d16201d0927Li Wang		tst_res(TFAIL, "# of attaches is incorrect");
11689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		return;
11789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	}
11889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
11989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	/* check the size of the segment */
1201cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang	if (buf.shm_segsz != shm_size) {
12115756239e687146c5052c724352a1d16201d0927Li Wang		tst_res(TFAIL, "segment size is incorrect");
12289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		return;
12389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	}
12489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
12589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	/* check for specific conditions depending on the type of attach */
1261cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang	switch (i) {
12789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	case 0:
12889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		/*
12989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * Check the functionality of the first call by simply
13089e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * "writing" a value to the shared memory space.
13189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * If this fails the program will get a SIGSEGV, dump
13289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * core and exit.
13389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 */
13489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		*shared = CASE0;
13589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		break;
13689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	case 1:
13789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		/*
13889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * Check the functionality of the second call by writing
13989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * a value to the shared memory space and then checking
14089e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * that the original address given was rounded down as
14189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * specified in the man page.
14289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 */
14389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		*shared = CASE1;
14415756239e687146c5052c724352a1d16201d0927Li Wang		orig_add = addr + ((unsigned long)tcases[i].addr % SHMLBA);
14515756239e687146c5052c724352a1d16201d0927Li Wang		if (orig_add != tcases[i].addr) {
14615756239e687146c5052c724352a1d16201d0927Li Wang			tst_res(TFAIL, "shared memory address is not "
147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				 "correct");
1481cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang			return;
14989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		}
15089e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		break;
15189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	case 2:
15289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		/*
15389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * This time the shared memory is read only.  Read the value
15489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * and check that it is equal to the value set in case #2,
15589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 * because shared memory is persistent.
15689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		 */
15789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		if (*shared != CASE1) {
15815756239e687146c5052c724352a1d16201d0927Li Wang			tst_res(TFAIL, "shared memory value isn't correct");
1591cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang			return;
16089e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		}
16189e9a4fe59b3e697750b2996d45b6a19156270f4robbiew		break;
16289e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	}
16315756239e687146c5052c724352a1d16201d0927Li Wang	tst_res(TPASS, "conditions and functionality are correct");
16489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew}
16589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
16615756239e687146c5052c724352a1d16201d0927Li Wangstatic void setup(void)
16789e9a4fe59b3e697750b2996d45b6a19156270f4robbiew{
168491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhang	long hpage_size;
169491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhang
170a5489f1bc843b7bda74fca10fad2f8714b5fb090Li Wang	save_nr_hugepages();
17115756239e687146c5052c724352a1d16201d0927Li Wang	if (nr_opt)
17215756239e687146c5052c724352a1d16201d0927Li Wang		hugepages = SAFE_STRTOL(nr_opt, 0, LONG_MAX);
17389e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
174491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhang	set_sys_tune("nr_hugepages", hugepages, 1);
17515756239e687146c5052c724352a1d16201d0927Li Wang	hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024;
176491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhang
177491f7280f3fa1b2d90ac0b46388fc447d6ffca9dCaspar Zhang	shm_size = hpage_size * hugepages / 2;
178880e33d3c777066f9f56ac8db5ea49b6060f9d66Wanlong Gao	update_shm_size(&shm_size);
17915756239e687146c5052c724352a1d16201d0927Li Wang	shmkey = getipckey();
1801cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang	shm_id_1 = shmget(shmkey++, shm_size,
181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			  SHM_HUGETLB | SHM_RW | IPC_CREAT | IPC_EXCL);
1821cdba9b1ffe8592f544afcbd2abbd9be910f2988Caspar Zhang	if (shm_id_1 == -1)
18315756239e687146c5052c724352a1d16201d0927Li Wang		tst_brk(TBROK | TERRNO, "shmget");
18489e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
18589e9a4fe59b3e697750b2996d45b6a19156270f4robbiew}
18689e9a4fe59b3e697750b2996d45b6a19156270f4robbiew
18715756239e687146c5052c724352a1d16201d0927Li Wangstatic void cleanup(void)
18889e9a4fe59b3e697750b2996d45b6a19156270f4robbiew{
18989e9a4fe59b3e697750b2996d45b6a19156270f4robbiew	rm_shm(shm_id_1);
190a5489f1bc843b7bda74fca10fad2f8714b5fb090Li Wang	restore_nr_hugepages();
19154a90b4ff7b63731c4cb3a876265e13a2363974dShang Yanfeng}
19215756239e687146c5052c724352a1d16201d0927Li Wang
19315756239e687146c5052c724352a1d16201d0927Li Wangstatic struct tst_test test = {
19415756239e687146c5052c724352a1d16201d0927Li Wang	.needs_root = 1,
19515756239e687146c5052c724352a1d16201d0927Li Wang	.needs_tmpdir = 1,
19615756239e687146c5052c724352a1d16201d0927Li Wang	.options = options,
19715756239e687146c5052c724352a1d16201d0927Li Wang	.tcnt = ARRAY_SIZE(tcases),
19815756239e687146c5052c724352a1d16201d0927Li Wang	.test = verify_hugeshmat,
19915756239e687146c5052c724352a1d16201d0927Li Wang	.setup = setup,
20015756239e687146c5052c724352a1d16201d0927Li Wang	.cleanup = cleanup,
20115756239e687146c5052c724352a1d16201d0927Li Wang};
202