1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2001-2017 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * DESCRIPTION 7f08c3bdfSopenharmony_ci * hugeshmat01 - test that shmat() works correctly 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * ALGORITHM 10f08c3bdfSopenharmony_ci * create a large shared memory resouce with read/write permissions 11f08c3bdfSopenharmony_ci * loop if that option was specified 12f08c3bdfSopenharmony_ci * call shmat() with the TEST() macro using three valid conditions 13f08c3bdfSopenharmony_ci * check the return code 14f08c3bdfSopenharmony_ci * if failure, issue a FAIL message. 15f08c3bdfSopenharmony_ci * otherwise, 16f08c3bdfSopenharmony_ci * if doing functionality testing 17f08c3bdfSopenharmony_ci * check for the correct conditions after the call 18f08c3bdfSopenharmony_ci * if correct, 19f08c3bdfSopenharmony_ci * issue a PASS message 20f08c3bdfSopenharmony_ci * otherwise 21f08c3bdfSopenharmony_ci * issue a FAIL message 22f08c3bdfSopenharmony_ci * call cleanup 23f08c3bdfSopenharmony_ci * 24f08c3bdfSopenharmony_ci * HISTORY 25f08c3bdfSopenharmony_ci * 03/2001 - Written by Wayne Boyer 26f08c3bdfSopenharmony_ci * 04/2004 - Updated by Robbie Williamson 27f08c3bdfSopenharmony_ci */ 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci#include <limits.h> 30f08c3bdfSopenharmony_ci#include "hugetlb.h" 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#define CASE0 10 /* values to write into the shared */ 33f08c3bdfSopenharmony_ci#define CASE1 20 /* memory location. */ 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_cistatic size_t shm_size; 36f08c3bdfSopenharmony_cistatic int shm_id_1 = -1; 37f08c3bdfSopenharmony_cistatic void *addr; 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_cistatic struct tcase { 40f08c3bdfSopenharmony_ci int *shmid; 41f08c3bdfSopenharmony_ci void *addr; 42f08c3bdfSopenharmony_ci int flags; 43f08c3bdfSopenharmony_ci} tcases[] = { 44f08c3bdfSopenharmony_ci /* a straight forward read/write attach */ 45f08c3bdfSopenharmony_ci {&shm_id_1, 0, 0}, 46f08c3bdfSopenharmony_ci /* 47f08c3bdfSopenharmony_ci * an attach using non aligned memory 48f08c3bdfSopenharmony_ci * -1 will be replaced with an unaligned addr 49f08c3bdfSopenharmony_ci */ 50f08c3bdfSopenharmony_ci {&shm_id_1, (void *)-1, SHM_RND}, 51f08c3bdfSopenharmony_ci /* a read only attach */ 52f08c3bdfSopenharmony_ci {&shm_id_1, 0, SHM_RDONLY} 53f08c3bdfSopenharmony_ci}; 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_cistatic void check_functionality(unsigned int i); 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_cistatic void verify_hugeshmat(unsigned int i) 58f08c3bdfSopenharmony_ci{ 59f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[i]; 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci addr = shmat(*(tc->shmid), tc->addr, tc->flags); 62f08c3bdfSopenharmony_ci if (addr == (void *)-1) { 63f08c3bdfSopenharmony_ci tst_brk(TFAIL | TERRNO, "shmat"); 64f08c3bdfSopenharmony_ci } else { 65f08c3bdfSopenharmony_ci check_functionality(i); 66f08c3bdfSopenharmony_ci } 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_ci /* 69f08c3bdfSopenharmony_ci * addr in tcases[0] will be used to generate an unaligned 70f08c3bdfSopenharmony_ci * address for tcases[1] 71f08c3bdfSopenharmony_ci */ 72f08c3bdfSopenharmony_ci if (i == 0 && addr != (void *)-1) 73f08c3bdfSopenharmony_ci tc[1].addr = (void *)(((unsigned long)addr & 74f08c3bdfSopenharmony_ci ~(SHMLBA - 1)) + SHMLBA - 1); 75f08c3bdfSopenharmony_ci if (shmdt(addr) == -1) 76f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "shmdt"); 77f08c3bdfSopenharmony_ci} 78f08c3bdfSopenharmony_ci 79f08c3bdfSopenharmony_ci/* 80f08c3bdfSopenharmony_ci * check_functionality - check various conditions to make sure they 81f08c3bdfSopenharmony_ci * are correct. 82f08c3bdfSopenharmony_ci */ 83f08c3bdfSopenharmony_cistatic void check_functionality(unsigned int i) 84f08c3bdfSopenharmony_ci{ 85f08c3bdfSopenharmony_ci void *orig_add; 86f08c3bdfSopenharmony_ci int *shared; 87f08c3bdfSopenharmony_ci struct shmid_ds buf; 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci shared = (int *)addr; 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci /* stat the shared memory ID */ 92f08c3bdfSopenharmony_ci if (shmctl(shm_id_1, IPC_STAT, &buf) == -1) 93f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "shmctl"); 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_ci /* check the number of attaches */ 96f08c3bdfSopenharmony_ci if (buf.shm_nattch != 1) { 97f08c3bdfSopenharmony_ci tst_res(TFAIL, "# of attaches is incorrect"); 98f08c3bdfSopenharmony_ci return; 99f08c3bdfSopenharmony_ci } 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci /* check the size of the segment */ 102f08c3bdfSopenharmony_ci if (buf.shm_segsz != shm_size) { 103f08c3bdfSopenharmony_ci tst_res(TFAIL, "segment size is incorrect"); 104f08c3bdfSopenharmony_ci return; 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci 107f08c3bdfSopenharmony_ci /* check for specific conditions depending on the type of attach */ 108f08c3bdfSopenharmony_ci switch (i) { 109f08c3bdfSopenharmony_ci case 0: 110f08c3bdfSopenharmony_ci /* 111f08c3bdfSopenharmony_ci * Check the functionality of the first call by simply 112f08c3bdfSopenharmony_ci * "writing" a value to the shared memory space. 113f08c3bdfSopenharmony_ci * If this fails the program will get a SIGSEGV, dump 114f08c3bdfSopenharmony_ci * core and exit. 115f08c3bdfSopenharmony_ci */ 116f08c3bdfSopenharmony_ci *shared = CASE0; 117f08c3bdfSopenharmony_ci break; 118f08c3bdfSopenharmony_ci case 1: 119f08c3bdfSopenharmony_ci /* 120f08c3bdfSopenharmony_ci * Check the functionality of the second call by writing 121f08c3bdfSopenharmony_ci * a value to the shared memory space and then checking 122f08c3bdfSopenharmony_ci * that the original address given was rounded down as 123f08c3bdfSopenharmony_ci * specified in the man page. 124f08c3bdfSopenharmony_ci */ 125f08c3bdfSopenharmony_ci *shared = CASE1; 126f08c3bdfSopenharmony_ci orig_add = addr + ((unsigned long)tcases[i].addr % SHMLBA); 127f08c3bdfSopenharmony_ci if (orig_add != tcases[i].addr) { 128f08c3bdfSopenharmony_ci tst_res(TFAIL, "shared memory address is not " 129f08c3bdfSopenharmony_ci "correct"); 130f08c3bdfSopenharmony_ci return; 131f08c3bdfSopenharmony_ci } 132f08c3bdfSopenharmony_ci break; 133f08c3bdfSopenharmony_ci case 2: 134f08c3bdfSopenharmony_ci /* 135f08c3bdfSopenharmony_ci * This time the shared memory is read only. Read the value 136f08c3bdfSopenharmony_ci * and check that it is equal to the value set in case #2, 137f08c3bdfSopenharmony_ci * because shared memory is persistent. 138f08c3bdfSopenharmony_ci */ 139f08c3bdfSopenharmony_ci if (*shared != CASE1) { 140f08c3bdfSopenharmony_ci tst_res(TFAIL, "shared memory value isn't correct"); 141f08c3bdfSopenharmony_ci return; 142f08c3bdfSopenharmony_ci } 143f08c3bdfSopenharmony_ci break; 144f08c3bdfSopenharmony_ci } 145f08c3bdfSopenharmony_ci tst_res(TPASS, "conditions and functionality are correct"); 146f08c3bdfSopenharmony_ci} 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_cistatic void setup(void) 149f08c3bdfSopenharmony_ci{ 150f08c3bdfSopenharmony_ci long hpage_size; 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci if (tst_hugepages == 0) 153f08c3bdfSopenharmony_ci tst_brk(TCONF, "No enough hugepages for testing."); 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci hpage_size = SAFE_READ_MEMINFO("Hugepagesize:") * 1024; 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci shm_size = hpage_size * tst_hugepages / 2; 158f08c3bdfSopenharmony_ci update_shm_size(&shm_size); 159f08c3bdfSopenharmony_ci shmkey = getipckey(); 160f08c3bdfSopenharmony_ci shm_id_1 = shmget(shmkey++, shm_size, 161f08c3bdfSopenharmony_ci SHM_HUGETLB | SHM_RW | IPC_CREAT | IPC_EXCL); 162f08c3bdfSopenharmony_ci if (shm_id_1 == -1) 163f08c3bdfSopenharmony_ci tst_brk(TBROK | TERRNO, "shmget"); 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci} 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_cistatic void cleanup(void) 168f08c3bdfSopenharmony_ci{ 169f08c3bdfSopenharmony_ci rm_shm(shm_id_1); 170f08c3bdfSopenharmony_ci} 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_cistatic struct tst_test test = { 173f08c3bdfSopenharmony_ci .needs_root = 1, 174f08c3bdfSopenharmony_ci .needs_tmpdir = 1, 175f08c3bdfSopenharmony_ci .options = (struct tst_option[]) { 176f08c3bdfSopenharmony_ci {"s:", &nr_opt, "Set the number of the been allocated hugepages"}, 177f08c3bdfSopenharmony_ci {} 178f08c3bdfSopenharmony_ci }, 179f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 180f08c3bdfSopenharmony_ci .test = verify_hugeshmat, 181f08c3bdfSopenharmony_ci .setup = setup, 182f08c3bdfSopenharmony_ci .cleanup = cleanup, 183f08c3bdfSopenharmony_ci .hugepages = {128, TST_REQUEST}, 184f08c3bdfSopenharmony_ci}; 185