Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F166710509
D25900.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
23 KB
Referenced Files
None
Subscribers
None
D25900.diff
View Options
Index: head/tests/sys/posixshm/posixshm_test.c
===================================================================
--- head/tests/sys/posixshm/posixshm_test.c
+++ head/tests/sys/posixshm/posixshm_test.c
@@ -28,10 +28,12 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
+#include <sys/sysctl.h>
#include <sys/wait.h>
#include <ctype.h>
@@ -956,6 +958,720 @@
close(fd);
}
+static int
+shm_open_large(int psind, int policy, size_t sz)
+{
+ int error, fd;
+
+ fd = shm_create_largepage(SHM_ANON, O_CREAT | O_RDWR, psind, policy, 0);
+ if (fd < 0 && errno == ENOTTY)
+ atf_tc_skip("no large page support");
+ ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; errno=%d", errno);
+
+ error = ftruncate(fd, sz);
+ if (error != 0 && errno == ENOMEM)
+ /*
+ * The test system might not have enough memory to accommodate
+ * the request.
+ */
+ atf_tc_skip("failed to allocate %zu-byte superpage", sz);
+ ATF_REQUIRE_MSG(error == 0, "ftruncate failed; errno=%d", errno);
+
+ return (fd);
+}
+
+static int
+pagesizes(size_t ps[MAXPAGESIZES])
+{
+ int pscnt;
+
+ pscnt = getpagesizes(ps, MAXPAGESIZES);
+ ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno);
+ ATF_REQUIRE_MSG(ps[0] == PAGE_SIZE, "psind 0 is %zu", ps[0]);
+ ATF_REQUIRE_MSG(pscnt <= MAXPAGESIZES, "invalid pscnt %d", pscnt);
+ if (pscnt == 1)
+ atf_tc_skip("no large page support");
+ return (pscnt);
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_basic);
+ATF_TC_BODY(largepage_basic, tc)
+{
+ char zeroes[PAGE_SIZE];
+ char *addr, *vec;
+ size_t ps[MAXPAGESIZES];
+ int error, fd, pscnt;
+
+ memset(zeroes, 0, PAGE_SIZE);
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
+ ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0,
+ "mmap(%zu bytes) returned unaligned mapping; addr=%p",
+ ps[i], addr);
+
+ /* Force a page fault. */
+ *(volatile char *)addr = 0;
+
+ vec = malloc(ps[i] / PAGE_SIZE);
+ ATF_REQUIRE(vec != NULL);
+ error = mincore(addr, ps[i], vec);
+ ATF_REQUIRE_MSG(error == 0, "mincore failed; errno=%d", errno);
+
+ /* Verify that all pages in the run are mapped. */
+ for (size_t p = 0; p < ps[i] / PAGE_SIZE; p++) {
+ ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0,
+ "page %zu is not mapped", p);
+ ATF_REQUIRE_MSG((vec[p] & MINCORE_PSIND(i)) != 0,
+ "page %zu is not in a %zu-byte superpage",
+ p, ps[i]);
+ }
+
+ /* Validate zeroing. */
+ for (size_t p = 0; p < ps[i] / PAGE_SIZE; p++) {
+ ATF_REQUIRE_MSG(memcmp(addr + p * PAGE_SIZE, zeroes,
+ PAGE_SIZE) == 0, "page %zu miscompare", p);
+ }
+
+ free(vec);
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+extern int __sys_shm_open2(const char *, int, mode_t, int, const char *);
+
+ATF_TC_WITHOUT_HEAD(largepage_config);
+ATF_TC_BODY(largepage_config, tc)
+{
+ struct shm_largepage_conf lpc;
+ char *addr, *buf;
+ size_t ps[MAXPAGESIZES + 1]; /* silence warnings if MAXPAGESIZES == 1 */
+ int error, fd, pscnt;
+
+ pscnt = pagesizes(ps);
+
+ fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0);
+ ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno);
+
+ /*
+ * Configure a large page policy for an object created without
+ * SHM_LARGEPAGE.
+ */
+ lpc.psind = 1;
+ lpc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT;
+ error = ioctl(fd, FIOSSHMLPGCNF, &lpc);
+ ATF_REQUIRE(error != 0);
+ ATF_REQUIRE_MSG(errno == ENOTTY, "ioctl(FIOSSHMLPGCNF) returned %d",
+ errno);
+ ATF_REQUIRE(close(fd) == 0);
+
+ /*
+ * Create a largepage object and try to use it without actually
+ * configuring anything.
+ */
+ fd = __sys_shm_open2(SHM_ANON, O_CREAT | O_RDWR, 0, SHM_LARGEPAGE,
+ NULL);
+ if (fd < 0 && errno == ENOTTY)
+ atf_tc_skip("no large page support");
+ ATF_REQUIRE_MSG(fd >= 0, "shm_open2 failed; error=%d", errno);
+
+ error = ftruncate(fd, ps[1]);
+ ATF_REQUIRE(error != 0);
+ ATF_REQUIRE_MSG(errno == EINVAL, "ftruncate returned %d", errno);
+
+ addr = mmap(NULL, ps[1], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ ATF_REQUIRE(addr == MAP_FAILED);
+ ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);
+ addr = mmap(NULL, 0, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ ATF_REQUIRE(addr == MAP_FAILED);
+ ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);
+
+ buf = calloc(1, PAGE_SIZE);
+ ATF_REQUIRE(buf != NULL);
+ ATF_REQUIRE(write(fd, buf, PAGE_SIZE) == -1);
+ ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno);
+ free(buf);
+ buf = calloc(1, ps[1]);
+ ATF_REQUIRE(buf != NULL);
+ ATF_REQUIRE(write(fd, buf, ps[1]) == -1);
+ ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno);
+ free(buf);
+
+ error = posix_fallocate(fd, 0, PAGE_SIZE);
+ ATF_REQUIRE_MSG(error == EINVAL, "posix_fallocate returned %d", error);
+
+ ATF_REQUIRE(close(fd) == 0);
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_mmap);
+ATF_TC_BODY(largepage_mmap, tc)
+{
+ char *addr, *addr1, *vec;
+ size_t ps[MAXPAGESIZES];
+ int fd, pscnt;
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+
+ /* For mincore(). */
+ vec = malloc(ps[i]);
+ ATF_REQUIRE(vec != NULL);
+
+ /*
+ * Wrong mapping size.
+ */
+ addr = mmap(NULL, ps[i - 1], PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, 0);
+ ATF_REQUIRE_MSG(addr == MAP_FAILED,
+ "mmap(%zu bytes) succeeded", ps[i - 1]);
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "mmap(%zu bytes) failed; error=%d", ps[i - 1], errno);
+
+ /*
+ * Fixed mappings.
+ */
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
+ ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0,
+ "mmap(%zu bytes) returned unaligned mapping; addr=%p",
+ ps[i], addr);
+
+ /* Try mapping a small page with anonymous memory. */
+ addr1 = mmap(addr, ps[i - 1], PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+ ATF_REQUIRE_MSG(addr1 == MAP_FAILED,
+ "anon mmap(%zu bytes) succeeded", ps[i - 1]);
+ ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);
+
+ /* Check MAP_EXCL when creating a second largepage mapping. */
+ addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0);
+ ATF_REQUIRE_MSG(addr1 == MAP_FAILED,
+ "mmap(%zu bytes) succeeded", ps[i]);
+ /* XXX wrong errno */
+ ATF_REQUIRE_MSG(errno == ENOSPC, "mmap returned %d", errno);
+
+ /* Overwrite a largepage mapping with a lagepage mapping. */
+ addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED, fd, 0);
+ ATF_REQUIRE_MSG(addr1 != MAP_FAILED,
+ "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
+ ATF_REQUIRE_MSG(addr == addr1,
+ "mmap(%zu bytes) moved from %p to %p", ps[i], addr, addr1);
+
+ ATF_REQUIRE(munmap(addr, ps[i] == 0));
+
+ /* Clobber an anonymous mapping with a superpage. */
+ addr1 = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_ALIGNED(ffsl(ps[i]) - 1), -1,
+ 0);
+ ATF_REQUIRE_MSG(addr1 != MAP_FAILED,
+ "mmap failed; error=%d", errno);
+ *(volatile char *)addr1 = '\0';
+ addr = mmap(addr1, ps[i], PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED, fd, 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap failed; error=%d", errno);
+ ATF_REQUIRE_MSG(addr == addr1,
+ "mmap disobeyed MAP_FIXED, %p %p", addr, addr1);
+ *(volatile char *)addr = 0; /* fault */
+ ATF_REQUIRE(mincore(addr, ps[i], vec) == 0);
+ for (size_t p = 0; p < ps[i] / PAGE_SIZE; p++) {
+ ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0,
+ "page %zu is not resident", p);
+ ATF_REQUIRE_MSG((vec[p] & MINCORE_PSIND(i)) != 0,
+ "page %zu is not resident", p);
+ }
+
+ /*
+ * Copy-on-write mappings are not permitted.
+ */
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ fd, 0);
+ ATF_REQUIRE_MSG(addr == MAP_FAILED,
+ "mmap(%zu bytes) succeeded", ps[i]);
+
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_munmap);
+ATF_TC_BODY(largepage_munmap, tc)
+{
+ char *addr;
+ size_t ps[MAXPAGESIZES], ps1;
+ int fd, pscnt;
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+ ps1 = ps[i - 1];
+
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; errno=%d", ps[i], errno);
+
+ /* Try several unaligned munmap() requests. */
+ ATF_REQUIRE(munmap(addr, ps1) != 0);
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "unexpected error %d from munmap", errno);
+ ATF_REQUIRE(munmap(addr, ps[i] - ps1));
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "unexpected error %d from munmap", errno);
+ ATF_REQUIRE(munmap(addr + ps1, ps1) != 0);
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "unexpected error %d from munmap", errno);
+ ATF_REQUIRE(munmap(addr, 0));
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "unexpected error %d from munmap", errno);
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+static void
+largepage_madvise(char *addr, size_t sz, int advice, int error)
+{
+ if (error == 0) {
+ ATF_REQUIRE_MSG(madvise(addr, sz, advice) == 0,
+ "madvise(%zu, %d) failed; error=%d", sz, advice, errno);
+ } else {
+ ATF_REQUIRE_MSG(madvise(addr, sz, advice) != 0,
+ "madvise(%zu, %d) succeeded", sz, advice);
+ ATF_REQUIRE_MSG(errno == error,
+ "unexpected error %d from madvise(%zu, %d)",
+ errno, sz, advice);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_madvise);
+ATF_TC_BODY(largepage_madvise, tc)
+{
+ char *addr;
+ size_t ps[MAXPAGESIZES];
+ int fd, pscnt;
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ /* Advice that requires clipping. */
+ largepage_madvise(addr, PAGE_SIZE, MADV_NORMAL, EINVAL);
+ largepage_madvise(addr, ps[i], MADV_NORMAL, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_RANDOM, EINVAL);
+ largepage_madvise(addr, ps[i], MADV_RANDOM, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_SEQUENTIAL, EINVAL);
+ largepage_madvise(addr, ps[i], MADV_SEQUENTIAL, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_NOSYNC, EINVAL);
+ largepage_madvise(addr, ps[i], MADV_NOSYNC, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_AUTOSYNC, EINVAL);
+ largepage_madvise(addr, ps[i], MADV_AUTOSYNC, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_CORE, EINVAL);
+ largepage_madvise(addr, ps[i], MADV_CORE, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_NOCORE, EINVAL);
+ largepage_madvise(addr, ps[i], MADV_NOCORE, 0);
+
+ /* Advice that does not result in clipping. */
+ largepage_madvise(addr, PAGE_SIZE, MADV_DONTNEED, 0);
+ largepage_madvise(addr, ps[i], MADV_DONTNEED, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_WILLNEED, 0);
+ largepage_madvise(addr, ps[i], MADV_WILLNEED, 0);
+ largepage_madvise(addr, PAGE_SIZE, MADV_FREE, 0);
+ largepage_madvise(addr, ps[i], MADV_FREE, 0);
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+ATF_TC(largepage_mlock);
+ATF_TC_HEAD(largepage_mlock, tc)
+{
+ /* Needed to set rlimit. */
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(largepage_mlock, tc)
+{
+ struct rlimit rl;
+ char *addr;
+ size_t ps[MAXPAGESIZES], sz;
+ u_long max_wired, wired;
+ int fd, error, pscnt;
+
+ rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
+ ATF_REQUIRE_MSG(setrlimit(RLIMIT_MEMLOCK, &rl) == 0,
+ "setrlimit failed; error=%d", errno);
+
+ sz = sizeof(max_wired);
+ error = sysctlbyname("vm.max_user_wired", &max_wired, &sz, NULL, 0);
+ ATF_REQUIRE_MSG(error == 0,
+ "sysctlbyname(vm.max_user_wired) failed; error=%d", errno);
+ ATF_REQUIRE(max_wired >= 0);
+
+ sz = sizeof(wired);
+ error = sysctlbyname("vm.stats.vm.v_user_wire_count", &wired, &sz, NULL,
+ 0);
+ ATF_REQUIRE_MSG(error == 0,
+ "sysctlbyname(vm.stats.vm.v_user_wire_count) failed; error=%d",
+ errno);
+ ATF_REQUIRE(wired >= 0);
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ if (ps[i] / PAGE_SIZE > max_wired - wired) {
+ /* Cannot wire past the limit. */
+ atf_tc_skip("test would exceed wiring limit");
+ }
+
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ ATF_REQUIRE(mlock(addr, PAGE_SIZE) != 0);
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "unexpected error %d from mlock(%zu bytes)", errno, ps[i]);
+ ATF_REQUIRE(mlock(addr, ps[i] - PAGE_SIZE) != 0);
+ ATF_REQUIRE_MSG(errno == EINVAL,
+ "unexpected error %d from mlock(%zu bytes)", errno, ps[i]);
+
+ ATF_REQUIRE_MSG(mlock(addr, ps[i]) == 0,
+ "mlock failed; error=%d", errno);
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+
+ ATF_REQUIRE(mlockall(MCL_FUTURE) == 0);
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_msync);
+ATF_TC_BODY(largepage_msync, tc)
+{
+ char *addr;
+ size_t ps[MAXPAGESIZES];
+ int fd, pscnt;
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ memset(addr, 0, ps[i]);
+
+ /*
+ * "Sync" requests are no-ops for SHM objects, so small
+ * PAGE_SIZE-sized requests succeed.
+ */
+ ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_ASYNC) == 0,
+ "msync(MS_ASYNC) failed; error=%d", errno);
+ ATF_REQUIRE_MSG(msync(addr, ps[i], MS_ASYNC) == 0,
+ "msync(MS_ASYNC) failed; error=%d", errno);
+ ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_SYNC) == 0,
+ "msync(MS_SYNC) failed; error=%d", errno);
+ ATF_REQUIRE_MSG(msync(addr, ps[i], MS_SYNC) == 0,
+ "msync(MS_SYNC) failed; error=%d", errno);
+
+ ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_INVALIDATE) != 0,
+ "msync(MS_INVALIDATE) succeeded");
+ /* XXX wrong errno */
+ ATF_REQUIRE_MSG(errno == EBUSY,
+ "unexpected error %d from msync(MS_INVALIDATE)", errno);
+ ATF_REQUIRE_MSG(msync(addr, ps[i], MS_INVALIDATE) == 0,
+ "msync(MS_INVALIDATE) failed; error=%d", errno);
+ memset(addr, 0, ps[i]);
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+static void
+largepage_protect(char *addr, size_t sz, int prot, int error)
+{
+ if (error == 0) {
+ ATF_REQUIRE_MSG(mprotect(addr, sz, prot) == 0,
+ "mprotect(%zu, %x) failed; error=%d", sz, prot, errno);
+ } else {
+ ATF_REQUIRE_MSG(mprotect(addr, sz, prot) != 0,
+ "mprotect(%zu, %x) succeeded", sz, prot);
+ ATF_REQUIRE_MSG(errno == error,
+ "unexpected error %d from mprotect(%zu, %x)",
+ errno, sz, prot);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_mprotect);
+ATF_TC_BODY(largepage_mprotect, tc)
+{
+ char *addr, *addr1;
+ size_t ps[MAXPAGESIZES];
+ int fd, pscnt;
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ /*
+ * These should be no-ops from the pmap perspective since the
+ * page is not yet entered into the pmap.
+ */
+ largepage_protect(addr, PAGE_SIZE, PROT_READ, EINVAL);
+ largepage_protect(addr, ps[i], PROT_READ, 0);
+ largepage_protect(addr, PAGE_SIZE, PROT_NONE, EINVAL);
+ largepage_protect(addr, ps[i], PROT_NONE, 0);
+ largepage_protect(addr, PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL);
+ largepage_protect(addr, ps[i],
+ PROT_READ | PROT_WRITE | PROT_EXEC, 0);
+
+ /* Trigger creation of a mapping and try again. */
+ *(volatile char *)addr = 0;
+ largepage_protect(addr, PAGE_SIZE, PROT_READ, EINVAL);
+ largepage_protect(addr, ps[i], PROT_READ, 0);
+ largepage_protect(addr, PAGE_SIZE, PROT_NONE, EINVAL);
+ largepage_protect(addr, ps[i], PROT_NONE, 0);
+ largepage_protect(addr, PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL);
+ largepage_protect(addr, ps[i],
+ PROT_READ | PROT_WRITE | PROT_EXEC, 0);
+
+ memset(addr, 0, ps[i]);
+
+ /* Map two contiguous large pages and merge map entries. */
+ addr1 = mmap(addr + ps[i], ps[i], PROT_READ | PROT_WRITE,
+ MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0);
+ ATF_REQUIRE_MSG(addr1 != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ largepage_protect(addr1 - PAGE_SIZE, PAGE_SIZE * 2,
+ PROT_READ | PROT_WRITE, EINVAL);
+ largepage_protect(addr, ps[i] * 2, PROT_READ | PROT_WRITE, 0);
+
+ memset(addr, 0, ps[i] * 2);
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(munmap(addr1, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_minherit);
+ATF_TC_BODY(largepage_minherit, tc)
+{
+ char *addr;
+ size_t ps[MAXPAGESIZES];
+ pid_t child;
+ int fd, pscnt, status;
+
+ pscnt = pagesizes(ps);
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ ATF_REQUIRE(minherit(addr, PAGE_SIZE, INHERIT_SHARE) != 0);
+
+ ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_SHARE) == 0,
+ "minherit(%zu bytes) failed; error=%d", ps[i], errno);
+ child = fork();
+ ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);
+ if (child == 0) {
+ char v;
+
+ *(volatile char *)addr = 0;
+ if (mincore(addr, PAGE_SIZE, &v) != 0)
+ _exit(1);
+ if ((v & MINCORE_PSIND(i)) == 0)
+ _exit(2);
+ _exit(0);
+ }
+ ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
+ "waitpid failed; error=%d", errno);
+ ATF_REQUIRE_MSG(WIFEXITED(status),
+ "child was killed by signal %d", WTERMSIG(status));
+ ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
+ "child exited with status %d", WEXITSTATUS(status));
+
+ ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_NONE) == 0,
+ "minherit(%zu bytes) failed; error=%d", ps[i], errno);
+ child = fork();
+ ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);
+ if (child == 0) {
+ char v;
+
+ if (mincore(addr, PAGE_SIZE, &v) == 0)
+ _exit(1);
+ _exit(0);
+ }
+ ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
+ "waitpid failed; error=%d", errno);
+ ATF_REQUIRE_MSG(WIFEXITED(status),
+ "child was killed by signal %d", WTERMSIG(status));
+ ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
+ "child exited with status %d", WEXITSTATUS(status));
+
+ /* Copy-on-write is not supported for static large pages. */
+ ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_COPY) != 0,
+ "minherit(%zu bytes) succeeded", ps[i]);
+
+ ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_ZERO) == 0,
+ "minherit(%zu bytes) failed; error=%d", ps[i], errno);
+ child = fork();
+ ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);
+ if (child == 0) {
+ char v;
+
+ *(volatile char *)addr = 0;
+ if (mincore(addr, PAGE_SIZE, &v) != 0)
+ _exit(1);
+ if ((v & MINCORE_SUPER) != 0)
+ _exit(2);
+ _exit(0);
+ }
+ ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
+ "waitpid failed; error=%d", errno);
+ ATF_REQUIRE_MSG(WIFEXITED(status),
+ "child was killed by signal %d", WTERMSIG(status));
+ ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
+ "child exited with status %d", WEXITSTATUS(status));
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_pipe);
+ATF_TC_BODY(largepage_pipe, tc)
+{
+ size_t ps[MAXPAGESIZES];
+ char *addr;
+ ssize_t len;
+ int fd, pfd[2], pscnt, status;
+ pid_t child;
+
+ pscnt = pagesizes(ps);
+
+ for (int i = 1; i < pscnt; i++) {
+ fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);
+ addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,
+ 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED,
+ "mmap(%zu bytes) failed; error=%d", ps[i], errno);
+
+ /* Trigger creation of a mapping. */
+ *(volatile char *)addr = '\0';
+
+ ATF_REQUIRE(pipe(pfd) == 0);
+ child = fork();
+ ATF_REQUIRE_MSG(child != -1, "fork() failed; error=%d", errno);
+ if (child == 0) {
+ char buf[BUFSIZ];
+ ssize_t resid;
+
+ (void)close(pfd[0]);
+ for (resid = (size_t)ps[i]; resid > 0; resid -= len) {
+ len = read(pfd[1], buf, sizeof(buf));
+ if (len < 0)
+ _exit(1);
+ }
+ _exit(0);
+ }
+ ATF_REQUIRE(close(pfd[1]) == 0);
+ len = write(pfd[0], addr, ps[i]);
+ ATF_REQUIRE_MSG(len >= 0, "write() failed; error=%d", errno);
+ ATF_REQUIRE_MSG(len == (ssize_t)ps[i],
+ "short write; len=%zd", len);
+ ATF_REQUIRE(close(pfd[0]) == 0);
+
+ ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,
+ "waitpid() failed; error=%d", errno);
+ ATF_REQUIRE_MSG(WIFEXITED(status),
+ "child was killed by signal %d", WTERMSIG(status));
+ ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,
+ "child exited with status %d", WEXITSTATUS(status));
+
+ ATF_REQUIRE(munmap(addr, ps[i]) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(largepage_reopen);
+ATF_TC_BODY(largepage_reopen, tc)
+{
+ char *addr, *vec;
+ size_t ps[MAXPAGESIZES];
+ int fd, psind;
+
+ (void)pagesizes(ps);
+ psind = 1;
+
+ gen_test_path();
+ fd = shm_create_largepage(test_path, O_CREAT | O_RDWR, psind,
+ SHM_LARGEPAGE_ALLOC_DEFAULT, 0600);
+ if (fd < 0 && errno == ENOTTY)
+ atf_tc_skip("no large page support");
+ ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; error=%d", errno);
+
+ ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0,
+ "ftruncate failed; error=%d", errno);
+
+ ATF_REQUIRE_MSG(close(fd) == 0, "close failed; error=%d", errno);
+
+ fd = shm_open(test_path, O_RDWR, 0);
+ ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno);
+
+ addr = mmap(NULL, ps[psind], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ ATF_REQUIRE_MSG(addr != MAP_FAILED, "mmap failed; error=%d", errno);
+
+ /* Trigger a fault and mapping creation. */
+ *(volatile char *)addr = 0;
+
+ vec = malloc(ps[psind] / PAGE_SIZE);
+ ATF_REQUIRE(vec != NULL);
+ ATF_REQUIRE_MSG(mincore(addr, ps[psind], vec) == 0,
+ "mincore failed; error=%d", errno);
+ ATF_REQUIRE_MSG((vec[0] & MINCORE_PSIND(psind)) != 0,
+ "page not mapped into a %zu-byte superpage", ps[psind]);
+
+ ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,
+ "shm_unlink failed; errno=%d", errno);
+ ATF_REQUIRE_MSG(close(fd) == 0,
+ "close failed; errno=%d", errno);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -990,6 +1706,17 @@
ATF_TP_ADD_TC(tp, cloexec);
ATF_TP_ADD_TC(tp, mode);
ATF_TP_ADD_TC(tp, fallocate);
+ ATF_TP_ADD_TC(tp, largepage_basic);
+ ATF_TP_ADD_TC(tp, largepage_config);
+ ATF_TP_ADD_TC(tp, largepage_mmap);
+ ATF_TP_ADD_TC(tp, largepage_munmap);
+ ATF_TP_ADD_TC(tp, largepage_madvise);
+ ATF_TP_ADD_TC(tp, largepage_mlock);
+ ATF_TP_ADD_TC(tp, largepage_msync);
+ ATF_TP_ADD_TC(tp, largepage_mprotect);
+ ATF_TP_ADD_TC(tp, largepage_minherit);
+ ATF_TP_ADD_TC(tp, largepage_pipe);
+ ATF_TP_ADD_TC(tp, largepage_reopen);
return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Aug 16, 7:59 PM (2 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36810462
Default Alt Text
D25900.diff (23 KB)
Attached To
Mode
D25900: Add some basic test coverage for SHM_LARGEPAGE.
Attached
Detach File
Event Timeline
Log In to Comment