From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8734AC3ABBE for ; Thu, 8 May 2025 22:20:54 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 9481D6B00A0; Thu, 8 May 2025 18:20:53 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 8F9566B00A3; Thu, 8 May 2025 18:20:53 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7978F6B00A4; Thu, 8 May 2025 18:20:53 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 594776B00A0 for ; Thu, 8 May 2025 18:20:53 -0400 (EDT) Received: from smtpin19.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 4CB89C1360 for ; Thu, 8 May 2025 22:20:53 +0000 (UTC) X-FDA: 83421161586.19.6575201 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf01.hostedemail.com (Postfix) with ESMTP id 1FCF04000A for ; Thu, 8 May 2025 22:20:50 +0000 (UTC) Authentication-Results: imf01.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=CWDvvZQf; spf=pass (imf01.hostedemail.com: domain of dhildenb@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhildenb@redhat.com; dmarc=pass (policy=quarantine) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1746742851; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:in-reply-to: references:dkim-signature; bh=8oSlQOGx5PSAeVG5B2JhkthMK6xKfNEYwRdVE1GMRZ4=; b=UETK5jFnh2SYkZ+LtI9Xn9f8evYcCFIpBYRl4WRFWH9otu7HIH2CKVkNzlH4x/oLcBg5HF EnSbBTbvH26etcY5R+GklCgk1dJAknS8LprxolzVUH+MYqBYm33C1BlRykdQSqKvROKZFN PCkFec2u5kmUJJEjdI2nnR6EnSyUjuw= ARC-Authentication-Results: i=1; imf01.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=CWDvvZQf; spf=pass (imf01.hostedemail.com: domain of dhildenb@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=dhildenb@redhat.com; dmarc=pass (policy=quarantine) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1746742851; a=rsa-sha256; cv=none; b=hCKkVFXFcUTXn5CX6ww2Sc0QUEcrLPKFuOfnqm6Tq8VUhs526xokCJ/a5VQuvOF+YS00zm AeTp29mhiJe99x35Z8pVbSEK1pq7Tq1cqqrZzJ9rTgdHowoEkxZVBYdH4YMqTmet+SogeH HHAwDf0C7e9L+npvfU68z0pk4kBLARI= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1746742850; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=8oSlQOGx5PSAeVG5B2JhkthMK6xKfNEYwRdVE1GMRZ4=; b=CWDvvZQfWy0Z/zIBOKTXkVbaXG5JjI7WFGk7gC47K8ET2/78Ky6qLzJiM4E5UoFD8ZQUjb gxL4lZoJBbgORQ/7vBgS0mg1RO6ymyWZ/VMsWRMRJ2YTSD46SEA864PnIcZslYKi75Dlvp //3KRrVFJ//Qt/YUe29RArGvSH1VFlY= Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-307-VpkY5DdcO3uG60UtFXKmWQ-1; Thu, 08 May 2025 18:20:44 -0400 X-MC-Unique: VpkY5DdcO3uG60UtFXKmWQ-1 X-Mimecast-MFC-AGG-ID: VpkY5DdcO3uG60UtFXKmWQ_1746742843 Received: by mail-wm1-f71.google.com with SMTP id 5b1f17b1804b1-43efa869b19so9562045e9.2 for ; Thu, 08 May 2025 15:20:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746742843; x=1747347643; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=8oSlQOGx5PSAeVG5B2JhkthMK6xKfNEYwRdVE1GMRZ4=; b=HZaTEXmsEA/W3KD5s3sSLmyxkv/uRjtrsHRWuyyMpYPPn8okp26pBgZQ8IV+6AcxZj PEMJWVRHcCzgE3ENkNMmwPcXQ0lyEah8dViMJy4NFL/vXzPvCDYjwuaAQ4TaP4/J+vs+ RuK1a7VQMMXNGHfdWSNYKyOiNohGZHO6sSKP0bfF9YvS6cZr9meyddb9l34TaJh7F+00 nk5+RFhH9E1SfCYHtnDT5dmoolzHvNy5jK4zP38oRmyac27xdxycBiwBqfvqyLM7dTi4 EfNbEdoebBA8fkeHryW14cP71EV9CetI1WlXEO7UkQCQusOKqSYLjoLUM0wYh53VhxWR VOaQ== X-Gm-Message-State: AOJu0YzuYyVAdB8iYZpYb4W7Jkg7UXVb384z87x0cHfVIPrWaRLyHvqA i46yx7wdtclZsMlw1OfJH9ttIk0QzhpMr8m5Ab25upwHjMWDoPzyfT+6J2mp7x3DryZutDHmk45 +9sRZ/wjAOhw7Q2iIpeJFOShdxOk3fwNYCDZ++fd3/HYmtsg3 X-Gm-Gg: ASbGnct0EKAF1+PuC0ELPixxv5fMw0lNsJASsHQD0DfGB16Et5baaT0Yn1C9tfQhUYx zHUFR8jOODkdCAItMG7buoGC49C4sIt8HkS/UuapczvTNUALI6W6MHggrwxoPQTCjJ86m8nsSsV IKYHUZL9QSeM+Sbg9wJz9PlWDfdumCwpS1OSIlsfnbKBcRKlhZuZwXzYc3eRfBBIyoJ2gT10W7F BrwNWL8z7gVfTik8JnBHtX7jzBQqeGTyVfPTq6TRJysW2eaxjtDwdqD91wGauhMR5ajSg3jWNyB F7pV1XcS3pMxek/gnDvOPeSm3YEkVhqdZnXqjaRSwV/Rjp7wVwOTqxyDA5GFEBkyNXlIqFP6 X-Received: by 2002:a5d:59ae:0:b0:391:2c67:798f with SMTP id ffacd0b85a97d-3a1f64b5771mr893888f8f.41.1746742843062; Thu, 08 May 2025 15:20:43 -0700 (PDT) X-Google-Smtp-Source: AGHT+IExtd4XQA/4NBIzZFkMCTxyRAAu0Q9sQeHtqaKbIjLYrVZYxEpbgKVOcMDojh/vgVIQ4jquVw== X-Received: by 2002:a5d:59ae:0:b0:391:2c67:798f with SMTP id ffacd0b85a97d-3a1f64b5771mr893877f8f.41.1746742842698; Thu, 08 May 2025 15:20:42 -0700 (PDT) Received: from localhost (p200300d82f3e590027aa5f4ab65c3d3c.dip0.t-ipconnect.de. [2003:d8:2f3e:5900:27aa:5f4a:b65c:3d3c]) by smtp.gmail.com with UTF8SMTPSA id ffacd0b85a97d-3a1f58ebd6asm1231706f8f.35.2025.05.08.15.20.41 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 08 May 2025 15:20:42 -0700 (PDT) From: David Hildenbrand To: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org, linux-kselftest@vger.kernel.org, David Hildenbrand , Andrew Morton , Shuah Khan , Lorenzo Stoakes , Ingo Molnar , Peter Xu Subject: [PATCH v1] selftests/mm: add simple VM_PFNMAP tests based on mmap'ing /dev/mem Date: Fri, 9 May 2025 00:20:41 +0200 Message-ID: <20250508222041.1647645-1-david@redhat.com> X-Mailer: git-send-email 2.49.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: wZ_VbDAr-v_8CwjW6KuS6goLW_Sm4gwLJa2lVObwb4w_1746742843 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true X-Stat-Signature: dxz1eipunm8rurr5zo6kmirj1e1ttbm3 X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: 1FCF04000A X-Rspam-User: X-HE-Tag: 1746742850-717626 X-HE-Meta: U2FsdGVkX1/nyz0w+eLXQgKsVBKBYkjyG6sjpK7L5aVaW7jDXegHvLCZ9PDcA6t1JMThgw2giuFa9mAXwDSH674T5awMzpIstwwtS2jG+k1AnCZLF4Ev7AydJc1KKbhFG3PGiO/4m8ngILyl6BNqF1Eu+XayrksS6R7818hhkuRgEqhIB1iidvBcvcGceBRB3tuvAjoxJRKmR55IQ94rep8NuDFtmQudCSA/z66Lp0PoMjS+7HVN36wYGoPChty+oTwYUPh7VKzP9Tu4XUSoyWeq36usJ30iIbz1EEb3whgiLCGxqq78aoF1nN0fJ/enio4Xg4k7dKpDg19FtaI6z4HSFt2YVtQ8L/ewW8NqkxKVOFViQxUBrGaTWQHEQ0zXfOuu8j8aZpuBC8ceD43RpxF2mffxjj6EemnIT6MTLIBU0rImabuBe8zAvlaaqkuuakIgEBTS3I1TOybETxN4I/B6ZdDF5I5zB98qwdKFCI7mKf3iNqQ8q1rvYY4DjQVKiPxbiq20+gvcOoWH36l0gpT2fn8MKZwX3R0sczvccYrlRZ32NF3P7aAIcruyJtV7RG5ihiUNG3cu3r7R9Mbtp9rbl0GjlOmi6hj0d+TI4rFnPGgPIZKW7PinAoR5wg1elX1Aqk1eOxTq6wPL6fRP4WfmqpbhTRiEbaHb+4geOh9HS8hr4vMyoCtFsSZoY4+ZUIC1Ly7S6b+6wUwGZoXyiJUnBs9AbwCjRHzuqwWsF8wfDpP4FydIzuc9AQ5bD3+2Q6W6wS+xbHz7uaWM3vbQqmNvnCxvrq8PrmR+NGt8EVMJsYxrz0NAe8BylOlYxUUy6URaQ0KzrvDzPhf0PAK+on/7qvIWbk43hIvFQvmE9lPxSGHN4S/MUVYBJJLQTbROSIB9egxHQ1swCplzY2nNfJ2+wAHyU5La51SPruvhNQKkgTpADuwk5wA/dGC2SjuEbnExc41bq19uSP6YkgH 0lPxGeOe 6CqdZMCSU/Z6SEJdXMMBY2qP4AiyRnx2zeiHVzXO5f2NTyZWn9f6l6/M+9VF+ecFqwRLDYJktsfKyx9+sE4KngsD9B5+xlhsgpVhlrq2IanD2nAx09X2v96gEOnk77pOULcEUjixbce1OUuxSZm5l3hk+dEH4KCJ9fzql1TIK9gQQrJTsPy/ZBOn3q7TXxgfA3zfRNDWia+b4QyAfciXR1BWH0IeFD0114TNncjiSYkAT1PzzJi6ToCCcuSvYQp+7AD/wS41dSS/eYCqESln57b+xNMpq3Wu9WqZCDbLJNqE2WYlMq1cO8bM9A7p0ggdQYZEdvlLtBPmL0qd3BPolKdeNPlECEojQmZMEuKNBxqDViFIu85CS4CtFYAKVv9KBbcKy4NU7FxhKAIShF8fPULXxZxwaqXphuSDXaXlb12FCF1UvEKlsPodQYI8M93brxGyEweHzi6La/VPz3ufwkP2XRWfkTzNVXlv9fIuZDcexnKRYmMVy1fLUBCl3uPpUKjGCNAadlAdiL8mOZNb7kL3UzjHQDwy+b728CqdVu8WPa1sdBi5of+5XwxsM05X1yD2sqAxjO+Tkc/SLvEyWSUUp/T016aNIlMYxp9FpBqKscTjwqng6wdEjmYRU/bwsS0eNbVJM9EzwIkdz+wkpiJsFOXRykZ6+DWDJ X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: Let's test some basic functionality using /dev/mem. These tests will implicitly cover some PAT (Page Attribute Handling) handling on x86. These tests will only run when /dev/mem access to the first two pages in physical address space is possible and allowed; otherwise, the tests are skipped. On current x86-64 with PAT inside a VM, all tests pass: TAP version 13 1..19 ok 1 madvise(MADV_DONTNEED) should be disallowed ok 2 madvise(MADV_DONTNEED_LOCKED) should be disallowed ok 3 madvise(MADV_FREE) should be disallowed ok 4 madvise(MADV_WIPEONFORK) should be disallowed ok 5 madvise(MADV_COLD) should be disallowed ok 6 madvise(MADV_PAGEOUT) should be disallowed ok 7 madvise(MADV_POPULATE_READ) should be disallowed ok 8 madvise(MADV_POPULATE_WRITE) should be disallowed ok 9 munmap() splitting ok 10 mmap() after splitting ok 11 mremap(MREMAP_FIXED) ok 12 mremap() shrinking ok 13 mremap() growing should be disallowed ok 14 mprotect(PROT_NONE) ok 15 SIGSEGV expected ok 16 mprotect(PROT_READ) ok 17 SIGSEGV not expected ok 18 fork() ok 19 SIGSEGV in child not expected # Totals: pass:19 fail:0 xfail:0 xpass:0 skip:0 error:0 However, we are able to trigger: [ 27.888251] x86/PAT: pfnmap:1790 freeing invalid memtype [mem 0x00000000-0x00000fff] There are probably more things worth testing in the future, such as MAP_PRIVATE handling. But this set of tests is sufficient to cover most of the things we will rework regarding PAT handling. Cc: Andrew Morton Cc: Shuah Khan Cc: Lorenzo Stoakes Cc: Ingo Molnar Cc: Peter Xu Signed-off-by: David Hildenbrand --- On current mm-unstable, the MADV_POPULATE_READ test fails because mm-unstable contains a patch [1] that must be dropped. [1] https://lore.kernel.org/all/20250507154105.763088-2-p.antoniou@partner.samsung.com/ --- tools/testing/selftests/mm/Makefile | 1 + tools/testing/selftests/mm/pfnmap.c | 278 ++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 tools/testing/selftests/mm/pfnmap.c diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile index ad4d6043a60f0..ae6f994d3add7 100644 --- a/tools/testing/selftests/mm/Makefile +++ b/tools/testing/selftests/mm/Makefile @@ -84,6 +84,7 @@ TEST_GEN_FILES += mremap_test TEST_GEN_FILES += mseal_test TEST_GEN_FILES += on-fault-limit TEST_GEN_FILES += pagemap_ioctl +TEST_GEN_FILES += pfnmap TEST_GEN_FILES += thuge-gen TEST_GEN_FILES += transhuge-stress TEST_GEN_FILES += uffd-stress diff --git a/tools/testing/selftests/mm/pfnmap.c b/tools/testing/selftests/mm/pfnmap.c new file mode 100644 index 0000000000000..59be2f3221124 --- /dev/null +++ b/tools/testing/selftests/mm/pfnmap.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Basic VM_PFNMAP tests relying on mmap() of '/dev/mem' + * + * Copyright 2025, Red Hat, Inc. + * + * Author(s): David Hildenbrand + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../kselftest.h" +#include "vm_util.h" + +static size_t pagesize; +static int pagemap_fd; +static int dev_mem_fd; +static sigjmp_buf env; + +static void signal_handler(int sig) +{ + if (sig == SIGSEGV) + siglongjmp(env, 1); + siglongjmp(env, 2); +} + +static void sense_support(void) +{ + char *addr, tmp; + int ret; + + dev_mem_fd = open("/dev/mem", O_RDONLY); + if (dev_mem_fd < 0) + ksft_exit_skip("Cannot open '/dev/mem': %s\n", strerror(errno)); + + /* We'll require the first two pages throughout our tests ... */ + addr = mmap(0, pagesize * 2, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr == MAP_FAILED) + ksft_exit_skip("Cannot mmap '/dev/mem'"); + + /* ... and want to be able to read from them. */ + ret = sigsetjmp(env, 1); + if (!ret) { + tmp = *addr + *(addr + pagesize); + asm volatile("" : "+r" (tmp)); + } + if (ret) + ksft_exit_skip("Cannot read-access mmap'ed '/dev/mem'"); + + munmap(addr, pagesize * 2); +} + +static void test_madvise(void) +{ +#define INIT_ADVICE(nr) { nr, #nr} + const struct { + int nr; + const char *name; + } advices[] = { + INIT_ADVICE(MADV_DONTNEED), + INIT_ADVICE(MADV_DONTNEED_LOCKED), + INIT_ADVICE(MADV_FREE), + INIT_ADVICE(MADV_WIPEONFORK), + INIT_ADVICE(MADV_COLD), + INIT_ADVICE(MADV_PAGEOUT), + INIT_ADVICE(MADV_POPULATE_READ), + INIT_ADVICE(MADV_POPULATE_WRITE), + }; + char *addr; + int ret, i; + + addr = mmap(0, pagesize, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* All these advices must be rejected. */ + for (i = 0; i < ARRAY_SIZE(advices); i++) { + ret = madvise(addr, pagesize, advices[i].nr); + ksft_test_result(ret && errno == EINVAL, + "madvise(%s) should be disallowed\n", + advices[i].name); + } + + munmap(addr, pagesize); +} + +static void test_munmap_splitting(void) +{ + char *addr1, *addr2; + int ret; + + addr1 = mmap(0, pagesize * 2, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr1 == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* Unmap the first pages. */ + ret = munmap(addr1, pagesize); + ksft_test_result(!ret, "munmap() splitting\n"); + + /* Remap the first page while the second page is still mapped. */ + addr2 = mmap(0, pagesize, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + ksft_test_result(addr2 != MAP_FAILED, "mmap() after splitting\n"); + + if (addr2 != MAP_FAILED) + munmap(addr2, pagesize); + if (!ret) + munmap(addr1 + pagesize, pagesize); + else + munmap(addr1, pagesize * 2); +} + +static void test_mremap_fixed(void) +{ + char *addr, *new_addr, *ret; + + addr = mmap(0, pagesize * 2, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* Reserve a destination area. */ + new_addr = mmap(0, pagesize * 2, PROT_READ, MAP_ANON | MAP_PRIVATE, -1, 0); + if (new_addr == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* mremap() over our destination. */ + ret = mremap(addr, pagesize * 2, pagesize * 2, + MREMAP_FIXED | MREMAP_MAYMOVE, new_addr); + ksft_test_result(ret == new_addr, "mremap(MREMAP_FIXED)\n"); + if (ret != new_addr) + munmap(new_addr, pagesize * 2); + munmap(addr, pagesize * 2); +} + +static void test_mremap_shrinking(void) +{ + char *addr, *ret; + + addr = mmap(0, pagesize * 2, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* Shrinking is expected to work. */ + ret = mremap(addr, pagesize * 2, pagesize, 0); + ksft_test_result(ret == addr, "mremap() shrinking\n"); + if (ret != addr) + munmap(addr, pagesize * 2); + else + munmap(addr, pagesize); +} + +static void test_mremap_growing(void) +{ + char *addr, *ret; + + addr = mmap(0, pagesize, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* Growing is not expected to work. */ + ret = mremap(addr, pagesize, pagesize * 2, MREMAP_MAYMOVE); + ksft_test_result(ret == MAP_FAILED, + "mremap() growing should be disallowed\n"); + if (ret == MAP_FAILED) + munmap(addr, pagesize); + else + munmap(ret, pagesize * 2); +} + +static void test_mprotect(void) +{ + char *addr, tmp; + int ret; + + addr = mmap(0, pagesize, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* With PROT_NONE, read access must result in SIGSEGV. */ + ret = mprotect(addr, pagesize, PROT_NONE); + ksft_test_result(!ret, "mprotect(PROT_NONE)\n"); + + ret = sigsetjmp(env, 1); + if (!ret) { + tmp = *addr; + asm volatile("" : "+r" (tmp)); + } + ksft_test_result(ret == 1, "SIGSEGV expected\n"); + + /* With PROT_READ, read access must again succeed. */ + ret = mprotect(addr, pagesize, PROT_READ); + ksft_test_result(!ret, "mprotect(PROT_READ)\n"); + + ret = sigsetjmp(env, 1); + if (!ret) { + tmp = *addr; + asm volatile("" : "+r" (tmp)); + } + ksft_test_result(!ret, "SIGSEGV not expected\n"); + + munmap(addr, pagesize); +} + +static void test_fork(void) +{ + char *addr, tmp; + int ret; + + addr = mmap(0, pagesize, PROT_READ, MAP_SHARED, dev_mem_fd, 0); + if (addr == MAP_FAILED) + ksft_exit_fail_msg("mmap() failed: %s\n", strerror(errno)); + + /* fork() a child and test if the child can access the page. */ + ret = fork(); + if (ret < 0) { + ksft_test_result_fail("fork()\n"); + goto out; + } else if (!ret) { + ret = sigsetjmp(env, 1); + if (!ret) { + tmp = *addr; + asm volatile("" : "+r" (tmp)); + } + /* Return the result to the parent. */ + exit(ret); + } + ksft_test_result_pass("fork()\n"); + + /* Wait for our child and obtain the result. */ + wait(&ret); + if (WIFEXITED(ret)) + ret = WEXITSTATUS(ret); + else + ret = -EINVAL; + + ksft_test_result(!ret, "SIGSEGV in child not expected\n"); +out: + munmap(addr, pagesize); +} + +int main(int argc, char **argv) +{ + int err; + + ksft_print_header(); + ksft_set_plan(19); + + pagesize = getpagesize(); + pagemap_fd = open("/proc/self/pagemap", O_RDONLY); + if (pagemap_fd < 0) + ksft_exit_fail_msg("opening pagemap failed\n"); + if (signal(SIGSEGV, signal_handler) == SIG_ERR) + ksft_exit_fail_msg("signal() failed: %s\n", strerror(errno)); + + sense_support(); + test_madvise(); + test_munmap_splitting(); + test_mremap_fixed(); + test_mremap_shrinking(); + test_mremap_growing(); + test_mprotect(); + test_fork(); + + err = ksft_get_fail_cnt(); + if (err) + ksft_exit_fail_msg("%d out of %d tests failed\n", + err, ksft_test_num()); + ksft_exit_pass(); +} -- 2.49.0