Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:39

0001 /*-
0002  * Copyright (c) 2009 Simon L. Nielsen <simon@FreeBSD.org>,
0003  *      Bjoern A. Zeeb <bz@FreeBSD.org>
0004  *
0005  * Redistribution and use in source and binary forms, with or without
0006  * modification, are permitted provided that the following conditions
0007  * are met:
0008  * 1. Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  *
0014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0015  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0016  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0017  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0018  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0019  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0020  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0021  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0022  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0023  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0024  * SUCH DAMAGE.
0025  *
0026  * $FreeBSD$
0027  */
0028 
0029 #ifdef HAVE_CONFIG_H
0030 #include "config.h"
0031 #endif
0032 
0033 #define CONFIGURE_INIT
0034 #include "system.h"
0035 #include "pritime.h"
0036 #include "test_helper.h"
0037 #include "test_driver.h"
0038 
0039 #include <sys/mman.h>
0040 
0041 #include <errno.h>
0042 #include <fcntl.h>
0043 #include <string.h>
0044 
0045 const char rtems_test_name[] = "PSX MMAP01";
0046 const char test_driver_name[] = "/dev/test_driver";
0047 
0048 static const struct {
0049   void  *addr;
0050   int ok;
0051 } map_at_zero_tests[] = {
0052   { (void *)0,                    0 },
0053   { (void *)1,                    0 },
0054   { (void *)(PAGE_SIZE - 1),      0 },
0055   { (void *)PAGE_SIZE,            1 },
0056   { (void *)-1,                   0 },
0057   { (void *)(-PAGE_SIZE),         0 },
0058   { (void *)(-1 - PAGE_SIZE),     0 },
0059   { (void *)(-1 - PAGE_SIZE - 1), 0 },
0060   { (void *)(0x1000 * PAGE_SIZE), 1 },
0061 };
0062 
0063 #define MAP_AT_ZERO_NITEMS (sizeof(map_at_zero_tests) / sizeof(map_at_zero_tests[0]))
0064 
0065 static void* checked_mmap(
0066   int prot,
0067   int flags,
0068   int fd,
0069   int error,
0070   const char *msg
0071 )
0072 {
0073   void *p;
0074   int pagesize, err;
0075 
0076   rtems_test_assert((pagesize = getpagesize()) > 0);
0077   p = mmap(NULL, pagesize, prot, flags, fd, 0);
0078   if (p == MAP_FAILED) {
0079     if (error == 0)
0080       mmap_test_assert(0, "%s failed with errno %d\n", msg, errno);
0081     else {
0082       err = errno;
0083       mmap_test_assert_equal(error, err,
0084           "%s failed with wrong errno %d (expected %d)\n", msg,
0085           errno, error);
0086     }
0087   } else {
0088     mmap_test_check(error == 0, "%s succeeded\n", msg);
0089     munmap(p, pagesize);
0090   }
0091   return p;
0092 }
0093 
0094 static void mmap_map_at_zero( void )
0095 {
0096   void *p;
0097   unsigned int i;
0098 
0099   for (i = 0; i < MAP_AT_ZERO_NITEMS; i++) {
0100     p = mmap((void *)map_at_zero_tests[i].addr, PAGE_SIZE,
0101         PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED | MAP_PRIVATE,
0102         -1, 0);
0103     if (p == MAP_FAILED) {
0104       mmap_test_assert( map_at_zero_tests[i].ok == 0,
0105           "mmap(%p, ...) failed\n", map_at_zero_tests[i].addr );
0106     } else {
0107       mmap_test_check( map_at_zero_tests[i].ok == 1,
0108           "mmap(%p, ...) succeeded: p=%p\n",
0109           map_at_zero_tests[i].addr, p );
0110     }
0111   }
0112 }
0113 
0114 static void mmap_bad_arguments( void )
0115 {
0116   int devfd, pagesize, shmfd, zerofd;
0117   void* p;
0118 
0119   rtems_test_assert((pagesize = getpagesize()) > 0);
0120   rtems_test_assert((devfd = open(&test_driver_name[0], O_RDONLY)) >= 0);
0121   rtems_test_assert((shmfd = shm_open("/shm", O_CREAT | O_RDWR, 0644)) >= 0);
0122   rtems_test_assert(ftruncate(shmfd, pagesize) == 0);
0123   rtems_test_assert((zerofd = open("/dev/zero", O_RDONLY)) >= 0);
0124 
0125   /*
0126    * These should normally work on FREEBSD. Test cases below that fail are
0127    * due to unsupported features in RTEMS.
0128    */
0129   checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON, -1, 0,
0130       "simple MAP_ANON");
0131   checked_mmap(PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0,
0132       "simple shm fd shared");
0133   checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE, shmfd, 0,
0134       "simple shm fd private");
0135   /* RTEMS cannot protect against writes so this will fail */
0136   checked_mmap(PROT_READ, MAP_SHARED, zerofd, ENOTSUP,
0137       "simple /dev/zero shared");
0138    /*
0139     * Repeat with no write protection. Will fail because of unimplemented
0140     * mmap handler in /dev/zero.
0141     */
0142   checked_mmap(PROT_READ | PROT_WRITE, MAP_SHARED, zerofd, ENOTSUP,
0143       "simple /dev/zero shared");
0144   /* RTEMS /dev/zero is a character device so this will fail */
0145   checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE, zerofd, EINVAL,
0146       "simple /dev/zero private");
0147   /* RTEMS cannot protect against writes so this will fail */
0148   checked_mmap(PROT_READ, MAP_SHARED, devfd, ENOTSUP,
0149       "simple test driver shared");
0150    /*
0151     * Repeat with no write protection. Should fail because of unimplemented
0152     * mmap handler in /dev/null.
0153     */
0154   p = checked_mmap(PROT_READ | PROT_WRITE, MAP_SHARED, devfd, 0,
0155       "simple test driver shared");
0156   rtems_test_assert(p == &test_data[0]);
0157 
0158   /* Extra PROT flags. */
0159   checked_mmap(PROT_READ | PROT_WRITE | 0x100000, MAP_ANON, -1, EINVAL,
0160       "MAP_ANON with extra PROT flags");
0161   checked_mmap(0xffff, MAP_SHARED, shmfd, EINVAL,
0162       "shm fd with garbage PROT");
0163 
0164   /* Undefined flag. */
0165   checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_RESERVED0080, -1,
0166       EINVAL, "Undefined flag");
0167 
0168   /* Both MAP_SHARED and MAP_PRIVATE */
0169   checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE |
0170       MAP_SHARED, -1, EINVAL, "MAP_ANON with both SHARED and PRIVATE");
0171   checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_SHARED, shmfd,
0172       EINVAL, "shm fd with both SHARED and PRIVATE");
0173 
0174   /* At least one of MAP_SHARED or MAP_PRIVATE without ANON */
0175   checked_mmap(PROT_READ | PROT_WRITE, 0, shmfd, EINVAL,
0176       "shm fd without sharing flag");
0177 
0178   /* MAP_ANON with sharing flag. Will fail on RTEMS*/
0179   checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, EINVAL,
0180       "shared MAP_ANON");
0181   /* MAP_ANON with private flag*/
0182   checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0,
0183       "private MAP_ANON");
0184 
0185   /* MAP_ANON should require an fd of -1. */
0186   checked_mmap(PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, 0, EINVAL,
0187       "MAP_ANON with fd != -1");
0188 
0189   /*
0190    * Writable MAP_SHARED should fail on read-only descriptors. Will fail
0191    * on RTEMS because of unimplemented mmap handler in /dev/null and the fact
0192    * that there is no read only protection.
0193    */
0194   checked_mmap(PROT_READ | PROT_WRITE, MAP_SHARED, zerofd, ENOTSUP,
0195       "MAP_SHARED of read-only /dev/zero");
0196 
0197   /*
0198    * Character devices other than /dev/zero do not support private
0199    * mappings. RTEMS cannot protect against writes so this will fail with
0200    * ENOTSUP
0201    */
0202   checked_mmap(PROT_READ, MAP_PRIVATE, devfd, ENOTSUP,
0203       "MAP_PRIVATE of test driver");
0204 
0205    /*
0206     * Repeat with no write protection.
0207     */
0208   checked_mmap(PROT_READ | PROT_WRITE, MAP_PRIVATE, devfd, EINVAL,
0209       "MAP_PRIVATE of test driver");
0210 
0211   close(devfd);
0212   close(shmfd);
0213   close(zerofd);
0214 }
0215 
0216 static void mmap_dev_zero_private( void )
0217 {
0218   char *p1, *p2, *p3;
0219   int fd, pagesize;
0220   /*int i*/
0221 
0222   rtems_test_assert((pagesize = getpagesize()) > 0);
0223   rtems_test_assert((fd = open("/dev/zero", O_RDONLY)) >= 0);
0224 
0225   /* This should not return MAP_FAILED but does on RTEMS */
0226   p1 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
0227   /*rtems_test_assert(p1 != MAP_FAILED);*/
0228   rtems_test_assert(p1 == MAP_FAILED);
0229 
0230   /* This should not return MAP_FAILED but does on RTEMS */
0231   p2 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
0232   /*rtems_test_assert(p2 != MAP_FAILED);*/
0233   rtems_test_assert(p2 == MAP_FAILED);
0234 
0235   /* These tests can not run due to failures above */
0236   /*for (i = 0; i < pagesize; i++)
0237     mmap_test_assert_equal(0, p1[i], "byte at p1[%d] is %x", i, p1[i]);
0238 
0239   rtems_test_assert(memcmp(p1, p2, pagesize) == 0);
0240 
0241   p1[0] = 1;
0242 
0243   rtems_test_assert(p2[0] == 0);
0244 
0245   p2[0] = 2;
0246 
0247   rtems_test_assert(p1[0] == 1);*/
0248 
0249   /* This should not return MAP_FAILED but does on RTEMS */
0250   p3 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
0251   /*rtems_test_assert(p3 != MAP_FAILED);*/
0252   rtems_test_assert(p3 == MAP_FAILED);
0253 
0254   /*rtems_test_assert(p3[0] == 0);
0255 
0256   munmap(p1, pagesize);
0257   munmap(p2, pagesize);
0258   munmap(p3, pagesize);*/
0259   close(fd);
0260 }
0261 
0262 static void mmap_dev_zero_shared( void )
0263 {
0264   char *p1, *p2, *p3;
0265   int fd, pagesize;
0266   /*int i*/
0267 
0268   rtems_test_assert((pagesize = getpagesize()) > 0);
0269   rtems_test_assert((fd = open("/dev/zero", O_RDWR)) >= 0);
0270 
0271   /* This should not return MAP_FAILED but does on RTEMS */
0272   p1 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
0273   /*rtems_test_assert(p1 != MAP_FAILED);*/
0274   rtems_test_assert(p1 == MAP_FAILED);
0275 
0276   /* This should not return MAP_FAILED but does on RTEMS */
0277   p2 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
0278   /*rtems_test_assert(p2 != MAP_FAILED);*/
0279   rtems_test_assert(p2 == MAP_FAILED);
0280 
0281   /* These tests can not run due to failures above */
0282   /*for (i = 0; i < pagesize; i++)
0283     mmap_test_assert_equal(0, p1[i], "byte at p1[%d] is %x", i, p1[i]);
0284 
0285   rtems_test_assert(memcmp(p1, p2, pagesize) == 0);
0286 
0287   p1[0] = 1;
0288 
0289   rtems_test_assert(p2[0] == 0);
0290 
0291   p2[0] = 2;
0292 
0293   rtems_test_assert(p1[0] == 1);*/
0294 
0295   p3 = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
0296   /*rtems_test_assert(p3 != MAP_FAILED);*/
0297   rtems_test_assert(p3 == MAP_FAILED);
0298 
0299   /*rtems_test_assert(p3[0] == 0);
0300 
0301   munmap(p1, pagesize);
0302   munmap(p2, pagesize);
0303   munmap(p3, pagesize);*/
0304   close(fd);
0305 }
0306 
0307 void *POSIX_Init(
0308   void *argument
0309 )
0310 {
0311   int rv;
0312 
0313   TEST_BEGIN();
0314 
0315   rv = IMFS_make_generic_node(
0316     &test_driver_name[0],
0317     S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO,
0318     &node_control,
0319     NULL
0320   );
0321   rtems_test_assert(rv == 0);
0322 
0323   puts( "Init: mmap - map at zero" );
0324   mmap_map_at_zero();
0325   puts( "Init: mmap - bad arguments" );
0326   mmap_bad_arguments();
0327   /*
0328    * The following test does not work on RTEMS because /dev/zero is
0329    * implemented as a character device which does not support MAP_PRIVATE.
0330    */
0331   puts( "Init: mmap - /dev/zero private" );
0332   mmap_dev_zero_private();
0333   /*
0334    * The following test does not work on RTEMS because /dev/zero does not
0335    * implemented the mmap handler.
0336    */
0337   puts( "Init: mmap - /dev/zero shared" );
0338   mmap_dev_zero_shared();
0339 
0340   TEST_END();
0341 
0342   rtems_test_exit(0);
0343   return 0;
0344 }