From 0eeec70570622338d44c341806847a255e110346 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Mon, 25 Mar 2013 19:12:24 +0100 Subject: [PATCH] sal/bochs: compress memory images on save/restore This saves a lot of disk space for campaigns with many saved VM states. Change-Id: I19c68d8545bb9b299f113d43d44202a517520b09 --- src/core/config/CMakeLists.txt | 1 + src/core/config/FailConfig.hpp.in | 1 + src/core/sal/bochs/CompressState.ah | 82 +++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 src/core/sal/bochs/CompressState.ah diff --git a/src/core/config/CMakeLists.txt b/src/core/config/CMakeLists.txt index 929ca21a..9327469c 100644 --- a/src/core/config/CMakeLists.txt +++ b/src/core/config/CMakeLists.txt @@ -16,6 +16,7 @@ OPTION(CONFIG_SR_SAVE "Target backend: State saving" OFF) OPTION(CONFIG_SR_REBOOT "Target backend: Reboot" OFF) OPTION(CONFIG_BOCHS_NON_VERBOSE "Misc: Reduced verbosity (a lot faster for large campaigns)" OFF) OPTION(CONFIG_BOCHS_NO_ABORT "Misc: Do not abort or ask the user in case the simulator stumbles on unexpected events (e.g., panics)" ON) +OPTION(CONFIG_BOCHS_COMPRESS_STATE "Misc: Reduce Bochs save/restore size by compressing memory images" OFF) OPTION(CONFIG_SUPPRESS_INTERRUPTS "Target backend: Suppress interrupts" OFF) OPTION(CONFIG_FIRE_INTERRUPTS "Target backend: Fire interrupts" OFF) OPTION(CONFIG_DISABLE_KEYB_INTERRUPTS "Target backend: Suppress keyboard interrupts" OFF) diff --git a/src/core/config/FailConfig.hpp.in b/src/core/config/FailConfig.hpp.in index 8c5a2f31..78fbe3c3 100644 --- a/src/core/config/FailConfig.hpp.in +++ b/src/core/config/FailConfig.hpp.in @@ -28,6 +28,7 @@ // Fail configuration #cmakedefine CONFIG_BOCHS_NON_VERBOSE #cmakedefine CONFIG_BOCHS_NO_ABORT +#cmakedefine CONFIG_BOCHS_COMPRESS_STATE #cmakedefine CONFIG_SUPPRESS_INTERRUPTS #cmakedefine CONFIG_FIRE_INTERRUPTS #cmakedefine CONFIG_DISABLE_KEYB_INTERRUPTS diff --git a/src/core/sal/bochs/CompressState.ah b/src/core/sal/bochs/CompressState.ah new file mode 100644 index 00000000..fea61576 --- /dev/null +++ b/src/core/sal/bochs/CompressState.ah @@ -0,0 +1,82 @@ +#ifndef __COMPRESS_STATE_AH__ + #define __COMPRESS_STATE_AH__ + +#include "config/VariantConfig.hpp" +#include "config/FailConfig.hpp" + +#if defined(BUILD_BOCHS) && defined(CONFIG_BOCHS_COMPRESS_STATE) + +#include +#include + +aspect CompressState { + advice call ("% fwrite(...)") + && within ("% bx_real_sim_c::save_sr_param(...)") + && args(ptr, size, nmemb, stream) + : around (const void *ptr, size_t size, size_t nmemb, FILE *stream) + { + *tjp->result() = fwrite_compressed(ptr, size, nmemb, stream); + } + + advice call ("% fread(...)") + && within ("% bx_real_sim_c::restore_bochs_param(...)") + && args(ptr, size, nmemb, stream) + : around (void *ptr, size_t size, size_t nmemb, FILE *stream) + { + *tjp->result() = fread_compressed(ptr, size, nmemb, stream); + } + +// FIXME move implementation to a separate compilation unit + size_t fread_compressed(void *ptr, size_t size, size_t nmemb, FILE *stream) + { + size_t remaining = size * nmemb; + ssize_t ret; + char *cbuf = (char *) ptr; + // FIXME check return values + gzFile f = gzdopen(dup(fileno(stream)), "rb"); +#if ZLIB_VERNUM >= 0x1240 + gzbuffer(f, 1024*1024); +#endif + + do { + ret = gzread(f, cbuf, remaining); + // EOF or error? + if (ret == 0 || ret == -1) { + break; + } + remaining -= ret; + cbuf += ret; + } while (remaining); + gzclose(f); + + return (cbuf - (char *)ptr) / size; + } + + size_t fwrite_compressed(const void *ptr, size_t size, size_t nmemb, FILE *stream) + { + size_t remaining = size * nmemb; + ssize_t ret; + const char *cbuf = (const char *) ptr; + // FIXME check return values + gzFile f = gzdopen(dup(fileno(stream)), "wb9"); +#if ZLIB_VERNUM >= 0x1240 + gzbuffer(f, 1024*1024); +#endif + + do { + ret = gzwrite(f, cbuf, remaining); + // error? + if (ret == 0) { + break; + } + remaining -= ret; + cbuf += ret; + } while (remaining); + gzclose(f); + + return (cbuf - (char *)ptr) / size; + } +}; + +#endif // BUILD_BOCHS && CONFIG_BOCHS_COMPRESS_STATE +#endif // __COMPRESS_STATE_AH__