1c8b5c478SDmitry Chagin /*- 2c8b5c478SDmitry Chagin * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org> 3c8b5c478SDmitry Chagin * 4c8b5c478SDmitry Chagin * SPDX-License-Identifier: BSD-2-Clause 5c8b5c478SDmitry Chagin */ 66dced2c6SWarner Losh 7c8b5c478SDmitry Chagin #include <sys/types.h> 8c8b5c478SDmitry Chagin #include <sys/stdint.h> 9c8b5c478SDmitry Chagin #include <sys/sysctl.h> 10c8b5c478SDmitry Chagin 11c8b5c478SDmitry Chagin #include <errno.h> 12c8b5c478SDmitry Chagin #include <sched.h> 13c8b5c478SDmitry Chagin 14c8b5c478SDmitry Chagin #include <atf-c.h> 15c8b5c478SDmitry Chagin 16c8b5c478SDmitry Chagin static uint32_t maxcpuid; 17c8b5c478SDmitry Chagin static uint32_t maxcpus; 18c8b5c478SDmitry Chagin static uint32_t cpus; 19c8b5c478SDmitry Chagin 20c8b5c478SDmitry Chagin static uint32_t 21c8b5c478SDmitry Chagin support_getcpus(void) 22c8b5c478SDmitry Chagin { 23c8b5c478SDmitry Chagin uint32_t val; 24c8b5c478SDmitry Chagin size_t sz = sizeof(val); 25c8b5c478SDmitry Chagin 26c8b5c478SDmitry Chagin ATF_REQUIRE(sysctlbyname("kern.smp.cpus", &val, &sz, NULL, 0) == 0); 27c8b5c478SDmitry Chagin return (val); 28c8b5c478SDmitry Chagin } 29c8b5c478SDmitry Chagin 30c8b5c478SDmitry Chagin static uint32_t 31c8b5c478SDmitry Chagin support_getmaxcpus(void) 32c8b5c478SDmitry Chagin { 33c8b5c478SDmitry Chagin uint32_t val; 34c8b5c478SDmitry Chagin size_t sz = sizeof(val); 35c8b5c478SDmitry Chagin 36c8b5c478SDmitry Chagin ATF_REQUIRE(sysctlbyname("kern.smp.maxcpus", &val, &sz, NULL, 0) == 0); 37c8b5c478SDmitry Chagin return (val); 38c8b5c478SDmitry Chagin } 39c8b5c478SDmitry Chagin 40c8b5c478SDmitry Chagin static uint32_t 41c8b5c478SDmitry Chagin support_getmaxcpuid(void) 42c8b5c478SDmitry Chagin { 43c8b5c478SDmitry Chagin cpuset_t *set; 44c8b5c478SDmitry Chagin int setsize, rv; 45c8b5c478SDmitry Chagin uint32_t i, id; 46c8b5c478SDmitry Chagin 47c8b5c478SDmitry Chagin for (i = 1; i < maxcpus; i++) { 48c8b5c478SDmitry Chagin setsize = CPU_ALLOC_SIZE(i); 49c8b5c478SDmitry Chagin set = CPU_ALLOC(i); 50c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 5102f7670eSDmitry Chagin CPU_ZERO_S(setsize, set); 52c8b5c478SDmitry Chagin rv = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 53c8b5c478SDmitry Chagin -1, setsize, set); 54c8b5c478SDmitry Chagin if (rv == 0) { 55c8b5c478SDmitry Chagin id = __BIT_FLS(i, set) - 1; 56c8b5c478SDmitry Chagin CPU_FREE(set); 57c8b5c478SDmitry Chagin break; 58c8b5c478SDmitry Chagin } 59c8b5c478SDmitry Chagin CPU_FREE(set); 60c8b5c478SDmitry Chagin } 61c8b5c478SDmitry Chagin ATF_REQUIRE(rv == 0); 62c8b5c478SDmitry Chagin return (id); 63c8b5c478SDmitry Chagin } 64c8b5c478SDmitry Chagin 65c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_setinvalidcpu); 66c8b5c478SDmitry Chagin ATF_TC_BODY(test_setinvalidcpu, tc) 67c8b5c478SDmitry Chagin { 68c8b5c478SDmitry Chagin size_t cpusetsize; 69c8b5c478SDmitry Chagin cpuset_t *set; 70*5b98bd30SMark Johnston int cpu; 71*5b98bd30SMark Johnston 72*5b98bd30SMark Johnston cpu = maxcpuid > 1 ? maxcpuid - 1 : 0; 73c8b5c478SDmitry Chagin 74c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 75c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpuid + 1); 76c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 7702f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 7802f7670eSDmitry Chagin CPU_SET_S(maxcpuid + 1, cpusetsize, set); 79*5b98bd30SMark Johnston CPU_SET_S(cpu, cpusetsize, set); 80c8b5c478SDmitry Chagin ATF_REQUIRE(sched_setaffinity(0, cpusetsize, set) == 0); 81c8b5c478SDmitry Chagin CPU_FREE(set); 82c8b5c478SDmitry Chagin 83c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpus + 1); 84c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpus + 1); 85c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 8602f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 8702f7670eSDmitry Chagin CPU_SET_S(maxcpuid + 1, cpusetsize, set); 88*5b98bd30SMark Johnston CPU_SET_S(cpu, cpusetsize, set); 89c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 90c8b5c478SDmitry Chagin -1, cpusetsize, set) == -1); 91c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(errno, EINVAL); 92c8b5c478SDmitry Chagin CPU_FREE(set); 93c8b5c478SDmitry Chagin } 94c8b5c478SDmitry Chagin 95c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_setvalidcpu); 96c8b5c478SDmitry Chagin ATF_TC_BODY(test_setvalidcpu, tc) 97c8b5c478SDmitry Chagin { 98c8b5c478SDmitry Chagin size_t cpusetsize; 99c8b5c478SDmitry Chagin cpuset_t *set; 100c8b5c478SDmitry Chagin int cpu; 101c8b5c478SDmitry Chagin 102c8b5c478SDmitry Chagin ATF_REQUIRE(maxcpuid < maxcpus); 103c8b5c478SDmitry Chagin cpu = maxcpuid > 1 ? maxcpuid - 1 : 0; 104c8b5c478SDmitry Chagin 105c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpus + 1); 106c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpus + 1); 107c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 10802f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 10902f7670eSDmitry Chagin CPU_SET_S(cpu, cpusetsize, set); 110c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 111c8b5c478SDmitry Chagin -1, cpusetsize, set) == 0); 112c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(cpu, sched_getcpu()); 113c8b5c478SDmitry Chagin CPU_FREE(set); 114c8b5c478SDmitry Chagin } 115c8b5c478SDmitry Chagin 116c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_setzeroset1); 117c8b5c478SDmitry Chagin ATF_TC_BODY(test_setzeroset1, tc) 118c8b5c478SDmitry Chagin { 119c8b5c478SDmitry Chagin size_t cpusetsize; 120c8b5c478SDmitry Chagin cpuset_t *set; 121c8b5c478SDmitry Chagin 122c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 123c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpuid + 1); 124c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 12502f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 126c8b5c478SDmitry Chagin ATF_REQUIRE(sched_setaffinity(0, cpusetsize, set) == -1); 127c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(errno, EINVAL); 128c8b5c478SDmitry Chagin CPU_FREE(set); 129c8b5c478SDmitry Chagin } 130c8b5c478SDmitry Chagin 131c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_setzeroset2); 132c8b5c478SDmitry Chagin ATF_TC_BODY(test_setzeroset2, tc) 133c8b5c478SDmitry Chagin { 134c8b5c478SDmitry Chagin size_t cpusetsize; 135c8b5c478SDmitry Chagin cpuset_t *set; 136c8b5c478SDmitry Chagin 137c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 138c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpuid + 1); 139c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 14002f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 141c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 142c8b5c478SDmitry Chagin -1, cpusetsize, set) == -1); 143c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(errno, EDEADLK); 144c8b5c478SDmitry Chagin CPU_FREE(set); 145c8b5c478SDmitry Chagin } 146c8b5c478SDmitry Chagin 147c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_setmaxsetsize); 148c8b5c478SDmitry Chagin ATF_TC_BODY(test_setmaxsetsize, tc) 149c8b5c478SDmitry Chagin { 150c8b5c478SDmitry Chagin size_t cpusetsize; 151c8b5c478SDmitry Chagin cpuset_t *set; 152c8b5c478SDmitry Chagin 153c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpus * 2); 154c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpus * 2); 155c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 15602f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 15702f7670eSDmitry Chagin ATF_REQUIRE(CPU_COUNT_S(cpusetsize, set) == 0); 15802f7670eSDmitry Chagin CPU_SET_S(0, cpusetsize, set); 15902f7670eSDmitry Chagin ATF_REQUIRE(CPU_COUNT_S(cpusetsize, set) == 1); 160c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 161c8b5c478SDmitry Chagin -1, cpusetsize, set) == 0); 162c8b5c478SDmitry Chagin 16302f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 16402f7670eSDmitry Chagin CPU_SET_S(maxcpuid, cpusetsize, set); 165c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 166c8b5c478SDmitry Chagin -1, cpusetsize, set) == 0); 167c8b5c478SDmitry Chagin 16802f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 16902f7670eSDmitry Chagin CPU_SET_S(maxcpuid + 1, cpusetsize, set); 170c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 171c8b5c478SDmitry Chagin -1, cpusetsize, set) == -1); 172c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(errno, EINVAL); 173c8b5c478SDmitry Chagin CPU_FREE(set); 174c8b5c478SDmitry Chagin } 175c8b5c478SDmitry Chagin 176c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_setminsetsize); 177c8b5c478SDmitry Chagin ATF_TC_BODY(test_setminsetsize, tc) 178c8b5c478SDmitry Chagin { 179c8b5c478SDmitry Chagin size_t cpusetsize = 1; 180c8b5c478SDmitry Chagin int8_t set; 181c8b5c478SDmitry Chagin 182c8b5c478SDmitry Chagin if (cpus <= 8) 183c8b5c478SDmitry Chagin return; 184c8b5c478SDmitry Chagin 185c8b5c478SDmitry Chagin set = 1; 186c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 187c8b5c478SDmitry Chagin -1, cpusetsize, (const cpuset_t *)&set) == 0); 188c8b5c478SDmitry Chagin set = 0; 189c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 190c8b5c478SDmitry Chagin -1, cpusetsize, (const cpuset_t *)&set) == -1); 191c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(errno, EDEADLK); 192c8b5c478SDmitry Chagin } 193c8b5c478SDmitry Chagin 194c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_getminsetsize); 195c8b5c478SDmitry Chagin ATF_TC_BODY(test_getminsetsize, tc) 196c8b5c478SDmitry Chagin { 197c8b5c478SDmitry Chagin size_t cpusetsize = 1; 198c8b5c478SDmitry Chagin int8_t set = 0; 199c8b5c478SDmitry Chagin 200c8b5c478SDmitry Chagin if (cpus < 9) 201c8b5c478SDmitry Chagin return; 202c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 203c8b5c478SDmitry Chagin -1, cpusetsize, (cpuset_t *)&set) == -1); 204c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(errno, ERANGE); 205c8b5c478SDmitry Chagin } 206c8b5c478SDmitry Chagin 207c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_getsetsize); 208c8b5c478SDmitry Chagin ATF_TC_BODY(test_getsetsize, tc) 209c8b5c478SDmitry Chagin { 210c8b5c478SDmitry Chagin size_t cpusetsize; 211c8b5c478SDmitry Chagin cpuset_t *set; 212c8b5c478SDmitry Chagin 213c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpuid + 1); 214c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpuid + 1); 215c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 21602f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 217c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 218c8b5c478SDmitry Chagin -1, cpusetsize, set) == 0); 219c8b5c478SDmitry Chagin CPU_FREE(set); 220c8b5c478SDmitry Chagin } 221c8b5c478SDmitry Chagin 222c8b5c478SDmitry Chagin ATF_TC_WITHOUT_HEAD(test_holes); 223c8b5c478SDmitry Chagin ATF_TC_BODY(test_holes, tc) 224c8b5c478SDmitry Chagin { 225c8b5c478SDmitry Chagin cpuset_t *set; 226c8b5c478SDmitry Chagin int cpusetsize; 227c8b5c478SDmitry Chagin 228c8b5c478SDmitry Chagin cpusetsize = CPU_ALLOC_SIZE(maxcpus * 2); 229c8b5c478SDmitry Chagin set = CPU_ALLOC(maxcpus * 2); 230c8b5c478SDmitry Chagin ATF_REQUIRE(set != NULL); 23102f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 23202f7670eSDmitry Chagin ATF_REQUIRE(CPU_COUNT_S(cpusetsize, set) == 0); 23302f7670eSDmitry Chagin CPU_SET_S(maxcpuid, cpusetsize, set); 23402f7670eSDmitry Chagin ATF_REQUIRE(CPU_COUNT_S(cpusetsize, set) == 1); 235c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 236c8b5c478SDmitry Chagin -1, cpusetsize, set) == 0); 237c8b5c478SDmitry Chagin 23802f7670eSDmitry Chagin CPU_ZERO_S(cpusetsize, set); 23902f7670eSDmitry Chagin ATF_REQUIRE(CPU_COUNT_S(cpusetsize, set) == 0); 24002f7670eSDmitry Chagin CPU_SET_S(maxcpuid + 1, cpusetsize, set); 24102f7670eSDmitry Chagin ATF_REQUIRE(CPU_COUNT_S(cpusetsize, set) == 1); 242c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 243c8b5c478SDmitry Chagin -1, cpusetsize, set) == -1); 244c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(errno, EINVAL); 245c8b5c478SDmitry Chagin 24602f7670eSDmitry Chagin ATF_REQUIRE(CPU_COUNT_S(cpusetsize, set) == 1); 247c8b5c478SDmitry Chagin ATF_REQUIRE(cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, 248c8b5c478SDmitry Chagin -1, cpusetsize, set) == 0); 24902f7670eSDmitry Chagin ATF_REQUIRE(CPU_ISSET_S(maxcpuid + 1, cpusetsize, set) == false); 25002f7670eSDmitry Chagin ATF_REQUIRE(CPU_ISSET_S(maxcpuid, cpusetsize, set) == true); 251c8b5c478SDmitry Chagin ATF_REQUIRE_EQ(maxcpuid, (uint32_t)sched_getcpu()); 252c8b5c478SDmitry Chagin } 253c8b5c478SDmitry Chagin 254c8b5c478SDmitry Chagin ATF_TP_ADD_TCS(tp) 255c8b5c478SDmitry Chagin { 256c8b5c478SDmitry Chagin 257c8b5c478SDmitry Chagin cpus = support_getcpus(); 258c8b5c478SDmitry Chagin maxcpus = support_getmaxcpus(); 259c8b5c478SDmitry Chagin maxcpuid = support_getmaxcpuid(); 260c8b5c478SDmitry Chagin 261c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_setinvalidcpu); 262c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_setvalidcpu); 263c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_setzeroset1); 264c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_setzeroset2); 265c8b5c478SDmitry Chagin 266c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_setminsetsize); 267c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_setmaxsetsize); 268c8b5c478SDmitry Chagin 269c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_getminsetsize); 270c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_getsetsize); 271c8b5c478SDmitry Chagin 272c8b5c478SDmitry Chagin ATF_TP_ADD_TC(tp, test_holes); 273c8b5c478SDmitry Chagin 274c8b5c478SDmitry Chagin return (atf_no_error()); 275c8b5c478SDmitry Chagin } 276