From 764f1408a3fa9b1991e3e18d17ea857776c1503e Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Tue, 20 Mar 2001 17:13:39 +0000 Subject: [PATCH] * mmap support for common simulators 2001-03-16 Frank Ch. Eigler Add support for mmap-based memory regions. * sim-memopt.c (mmap_next_fd): New global. (sim_memory_init): Reinitialize it. (OPTION_MEMORY_MAPFILE, memory_option_handler): Support new "--memory-mapfile FILE" option. Check for some errors. (do_memopt_add): Conditionally do mmap instead of malloc for backing store of simulated memory. Check for more errors. (do_simopt_delete, sim_memory_uninstall): Corresponding cleanup. * sim-memopt.h (munmap_length): New member of _sim_memopt. * configure.in: Look for mmap/fstat related functions and headers. * config.in, configure: Regenerated. --- sim/common/ChangeLog | 14 +++++ sim/common/config.in | 15 +++++ sim/common/configure | 57 +++++++++++++++++- sim/common/configure.in | 3 +- sim/common/sim-memopt.c | 127 ++++++++++++++++++++++++++++++++++++---- sim/common/sim-memopt.h | 1 + 6 files changed, 205 insertions(+), 12 deletions(-) diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 98c5e81598..7ca57e7409 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,17 @@ +2001-03-16 Frank Ch. Eigler + + Add support for mmap-based memory regions. + * sim-memopt.c (mmap_next_fd): New global. + (sim_memory_init): Reinitialize it. + (OPTION_MEMORY_MAPFILE, memory_option_handler): Support new + "--memory-mapfile FILE" option. Check for some errors. + (do_memopt_add): Conditionally do mmap instead of malloc for + backing store of simulated memory. Check for more errors. + (do_simopt_delete, sim_memory_uninstall): Corresponding cleanup. + * sim-memopt.h (munmap_length): New member of _sim_memopt. + * configure.in: Look for mmap/fstat related functions and headers. + * config.in, configure: Regenerated. + 2001-03-15 Frank Ch. Eigler * sim-core.c (sim_core_map_attach): Correct overlap-related diff --git a/sim/common/config.in b/sim/common/config.in index 4df95600dd..0b222e8b6e 100644 --- a/sim/common/config.in +++ b/sim/common/config.in @@ -82,6 +82,9 @@ /* Define if you have the getrusage function. */ #undef HAVE_GETRUSAGE +/* Define if you have the mmap function. */ +#undef HAVE_MMAP + /* Define if you have the munmap function. */ #undef HAVE_MUNMAP @@ -145,12 +148,18 @@ /* Define if you have the header file. */ #undef HAVE_STRINGS_H +/* Define if you have the header file. */ +#undef HAVE_SYS_MMAN_H + /* Define if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define if you have the header file. */ #undef HAVE_SYS_RESOURCE_H +/* Define if you have the header file. */ +#undef HAVE_SYS_STAT_H + /* Define if you have the header file. */ #undef HAVE_SYS_TIME_H @@ -165,3 +174,9 @@ /* Define if you have the header file. */ #undef HAVE_VALUES_H + +/* Define if you have the nsl library (-lnsl). */ +#undef HAVE_LIBNSL + +/* Define if you have the socket library (-lsocket). */ +#undef HAVE_LIBSOCKET diff --git a/sim/common/configure b/sim/common/configure index 8fc9d0440e..11c0e64e6c 100755 --- a/sim/common/configure +++ b/sim/common/configure @@ -3522,7 +3522,7 @@ fi # These aren't all needed yet, but will be eventually. -for ac_hdr in stdlib.h string.h strings.h time.h sys/times.h +for ac_hdr in stdlib.h string.h strings.h time.h sys/times.h sys/stat.h sys/mman.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 @@ -3562,6 +3562,61 @@ else fi done +for ac_func in mmap munmap +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:3569: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:3597: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <&6 +fi +done + trap '' 1 2 15 cat > confcache <<\EOF diff --git a/sim/common/configure.in b/sim/common/configure.in index b8ea5382f5..44218783be 100644 --- a/sim/common/configure.in +++ b/sim/common/configure.in @@ -34,7 +34,8 @@ fi AC_SUBST(TARGET_SUBDIR) # These aren't all needed yet, but will be eventually. -AC_CHECK_HEADERS(stdlib.h string.h strings.h time.h sys/times.h) +AC_CHECK_HEADERS(stdlib.h string.h strings.h time.h sys/times.h sys/stat.h sys/mman.h) +AC_CHECK_FUNCS(mmap munmap) AC_OUTPUT(Makefile, [case x$CONFIG_HEADERS in xcconfig.h:config.in) echo > stamp-h ;; esac]) diff --git a/sim/common/sim-memopt.c b/sim/common/sim-memopt.c index 6e12a45552..a8e9df6533 100644 --- a/sim/common/sim-memopt.c +++ b/sim/common/sim-memopt.c @@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "cconfig.h" + #include "sim-main.h" #include "sim-assert.h" #include "sim-options.h" @@ -32,11 +34,26 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifdef HAVE_STDLIB_H #include #endif +#ifdef HAVE_ERRNO_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif -/* Memory fill byte */ +/* Memory fill byte. */ static unsigned8 fill_byte_value; static int fill_byte_flag = 0; +/* Memory mapping; see OPTION_MEMORY_MAPFILE. */ +static int mmap_next_fd = -1; + /* Memory command line options. */ enum { @@ -46,7 +63,8 @@ enum { OPTION_MEMORY_INFO, OPTION_MEMORY_ALIAS, OPTION_MEMORY_CLEAR, - OPTION_MEMORY_FILL + OPTION_MEMORY_FILL, + OPTION_MEMORY_MAPFILE }; static DECLARE_OPTION_HANDLER (memory_option_handler); @@ -80,6 +98,12 @@ static const OPTION memory_options[] = '\0', NULL, "Clear subsequently added memory regions", memory_option_handler }, +#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP) + { {"memory-mapfile", required_argument, NULL, OPTION_MEMORY_MAPFILE }, + '\0', "FILE", "Memory-map next memory region from file", + memory_option_handler }, +#endif + { {"memory-info", no_argument, NULL, OPTION_MEMORY_INFO }, '\0', NULL, "List configurable memory regions", memory_option_handler }, @@ -104,6 +128,7 @@ do_memopt_add (SIM_DESC sd, void *fill_buffer; unsigned fill_length; void *free_buffer; + unsigned long free_length; if (buffer != NULL) { @@ -113,6 +138,7 @@ do_memopt_add (SIM_DESC sd, addr, nr_bytes, modulo, NULL, buffer); free_buffer = buffer; + free_length = 0; fill_buffer = buffer; fill_length = (modulo == 0) ? nr_bytes : modulo; } @@ -123,12 +149,45 @@ do_memopt_add (SIM_DESC sd, int padding = (addr % sizeof (unsigned64)); unsigned long bytes = (modulo == 0 ? nr_bytes : modulo) + padding; - /* If filling with non-zero value, do not use clearing allocator. */ + free_buffer = NULL; + free_length = bytes; - if (fill_byte_flag && fill_byte_value != 0) - free_buffer = xmalloc (bytes); /* don't clear */ - else - free_buffer = zalloc (bytes); /* clear */ +#ifdef HAVE_MMAP + /* Memory map or malloc(). */ + if (mmap_next_fd >= 0) + { + /* Check that given file is big enough. */ + struct stat s; + int rc; + + /* Some kernels will SIGBUS the application if mmap'd file + is not large enough. */ + rc = fstat (mmap_next_fd, &s); + if (rc < 0 || s.st_size < bytes) + { + sim_io_error (sd, + "Error, cannot confirm that mmap file is large enough " + "(>= %d bytes)\n", bytes); + } + + free_buffer = mmap (0, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, mmap_next_fd, 0); + if (free_buffer == 0 || free_buffer == (char*)-1) /* MAP_FAILED */ + { + sim_io_error (sd, "Error, cannot mmap file (%s).\n", + strerror(errno)); + } + } +#endif + + /* Need heap allocation? */ + if (free_buffer == NULL) + { + /* If filling with non-zero value, do not use clearing allocator. */ + if (fill_byte_flag && fill_byte_value != 0) + free_buffer = xmalloc (bytes); /* don't clear */ + else + free_buffer = zalloc (bytes); /* clear */ + } aligned_buffer = (char*) free_buffer + padding; @@ -162,6 +221,16 @@ do_memopt_add (SIM_DESC sd, (*entry)->modulo = modulo; (*entry)->buffer = free_buffer; + /* Record memory unmapping info. */ + if (mmap_next_fd >= 0) + { + (*entry)->munmap_length = free_length; + close (mmap_next_fd); + mmap_next_fd = -1; + } + else + (*entry)->munmap_length = 0; + return (*entry); } @@ -186,7 +255,15 @@ do_memopt_delete (SIM_DESC sd, } /* delete any buffer */ if ((*entry)->buffer != NULL) - zfree ((*entry)->buffer); + { +#ifdef HAVE_MUNMAP + if ((*entry)->munmap_length > 0) + munmap ((*entry)->buffer, (*entry)->munmap_length); + else +#endif + zfree ((*entry)->buffer); + } + /* delete it and its aliases */ alias = *entry; *entry = (*entry)->next; @@ -367,6 +444,25 @@ memory_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt, break; } + case OPTION_MEMORY_MAPFILE: + { + if (mmap_next_fd >= 0) + { + sim_io_eprintf (sd, "Duplicate memory-mapfile option\n"); + return SIM_RC_FAIL; + } + + mmap_next_fd = open (arg, O_RDWR); + if (mmap_next_fd < 0) + { + sim_io_eprintf (sd, "Cannot open file `%s': %s\n", + arg, strerror(errno)); + return SIM_RC_FAIL; + } + + return SIM_RC_OK; + } + case OPTION_MEMORY_INFO: { sim_memopt *entry; @@ -445,7 +541,14 @@ sim_memory_uninstall (SIM_DESC sd) { /* delete any buffer */ if ((*entry)->buffer != NULL) - zfree ((*entry)->buffer); + { +#ifdef HAVE_MUNMAP + if ((*entry)->munmap_length > 0) + munmap ((*entry)->buffer, (*entry)->munmap_length); + else +#endif + zfree ((*entry)->buffer); + } /* delete it and its aliases */ alias = *entry; @@ -467,6 +570,10 @@ sim_memory_uninstall (SIM_DESC sd) static SIM_RC sim_memory_init (SIM_DESC sd) { - /* FIXME: anything needed? */ + /* Reinitialize option modifier flags, in case they were left + over from a previous sim startup event. */ + fill_byte_flag = 0; + mmap_next_fd = -1; + return SIM_RC_OK; } diff --git a/sim/common/sim-memopt.h b/sim/common/sim-memopt.h index 287c576f1b..cbaad0c99c 100644 --- a/sim/common/sim-memopt.h +++ b/sim/common/sim-memopt.h @@ -31,6 +31,7 @@ struct _sim_memopt { unsigned_word nr_bytes; unsigned modulo; void *buffer; + unsigned long munmap_length; sim_memopt *alias; /* linked list */ sim_memopt *next; }; -- 2.34.1