summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDam Sunwoo <dam.sunwoo@arm.com>2012-01-31 07:46:04 -0800
committerDam Sunwoo <dam.sunwoo@arm.com>2012-01-31 07:46:04 -0800
commit0ed3c84c7b05d7d3c9d5f0e3f1c05c20afef93b9 (patch)
tree9663b1af4da7ee4c063fa0047da7cbf7e8a2b9de
parentaf6aaf258171027af8d3cf0ef86dddff501a3ccb (diff)
downloadgem5-0ed3c84c7b05d7d3c9d5f0e3f1c05c20afef93b9.tar.xz
util: implements "writefile" gem5 op to export file from guest to host filesystem
Usage: m5 writefile <filename> File will be created in the gem5 output folder with the identical filename. Implementation is largely based on the existing "readfile" functionality. Currently does not support exporting of folders.
-rw-r--r--src/arch/arm/isa/formats/m5ops.isa1
-rw-r--r--src/arch/arm/isa/insts/m5ops.isa18
-rw-r--r--src/base/output.hh14
-rw-r--r--src/sim/pseudo_inst.cc45
-rw-r--r--src/sim/pseudo_inst.hh2
-rw-r--r--util/m5/m5.c43
-rw-r--r--util/m5/m5op.h1
-rw-r--r--util/m5/m5op_arm.S2
-rw-r--r--util/m5/m5ops.h1
9 files changed, 117 insertions, 10 deletions
diff --git a/src/arch/arm/isa/formats/m5ops.isa b/src/arch/arm/isa/formats/m5ops.isa
index f532d828b..534d12cd9 100644
--- a/src/arch/arm/isa/formats/m5ops.isa
+++ b/src/arch/arm/isa/formats/m5ops.isa
@@ -64,6 +64,7 @@ def format M5ops() {{
case 0x42: return new Dumpresetstats(machInst);
case 0x43: return new M5checkpoint(machInst);
#if FULL_SYSTEM
+ case 0x4F: return new M5writefile(machInst);
case 0x50: return new M5readfile(machInst);
#endif
case 0x51: return new M5break(machInst);
diff --git a/src/arch/arm/isa/insts/m5ops.isa b/src/arch/arm/isa/insts/m5ops.isa
index 222ecc647..1a154459e 100644
--- a/src/arch/arm/isa/insts/m5ops.isa
+++ b/src/arch/arm/isa/insts/m5ops.isa
@@ -265,6 +265,24 @@ let {{
decoder_output += BasicConstructor.subst(m5readfileIop)
exec_output += PredOpExecute.subst(m5readfileIop)
+ m5writefileCode = '''
+#if FULL_SYSTEM
+ int n = 4;
+ uint64_t offset = getArgument(xc->tcBase(), n, sizeof(uint64_t), false);
+ n = 6;
+ Addr filenameAddr = getArgument(xc->tcBase(), n, sizeof(Addr), false);
+ R0 = PseudoInst::writefile(xc->tcBase(), R0, join32to64(R3,R2), offset,
+ filenameAddr);
+#endif
+ '''
+ m5writefileIop = InstObjParams("m5writefile", "M5writefile", "PredOp",
+ { "code": m5writefileCode,
+ "predicate_test": predicateTest },
+ ["IsNonSpeculative"])
+ header_output += BasicDeclare.subst(m5writefileIop)
+ decoder_output += BasicConstructor.subst(m5writefileIop)
+ exec_output += PredOpExecute.subst(m5writefileIop)
+
m5breakIop = InstObjParams("m5break", "M5break", "PredOp",
{ "code": "PseudoInst::debugbreak(xc->tcBase());",
"predicate_test": predicateTest },
diff --git a/src/base/output.hh b/src/base/output.hh
index b86e68856..68d9daf85 100644
--- a/src/base/output.hh
+++ b/src/base/output.hh
@@ -73,6 +73,13 @@ class OutputDirectory
*/
std::ostream *checkForStdio(const std::string &name) const;
+ public:
+ /** Constructor. */
+ OutputDirectory();
+
+ /** Destructor. */
+ ~OutputDirectory();
+
/** Opens a file (optionally compressed).
*
* Will open a file as a compressed stream if filename ends in .gz.
@@ -84,13 +91,6 @@ class OutputDirectory
std::ostream *openFile(const std::string &filename,
std::ios_base::openmode mode = std::ios::trunc);
- public:
- /** Constructor. */
- OutputDirectory();
-
- /** Destructor. */
- ~OutputDirectory();
-
/**
* Sets name of this directory.
* @param dir name of this directory
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index 647420ca1..4e6c46f8e 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 ARM Limited
+ * Copyright (c) 2010-2011 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -50,6 +50,7 @@
#include "arch/vtophys.hh"
#include "base/debug.hh"
+#include "base/output.hh"
#include "config/full_system.hh"
#include "config/the_isa.hh"
#include "cpu/base.hh"
@@ -358,6 +359,48 @@ readfile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset)
return result;
}
+uint64_t
+writefile(ThreadContext *tc, Addr vaddr, uint64_t len, uint64_t offset,
+ Addr filename_addr)
+{
+ ostream *os;
+
+ // copy out target filename
+ char fn[100];
+ std::string filename;
+ CopyStringOut(tc, fn, filename_addr, 100);
+ filename = std::string(fn);
+
+ if (offset == 0) {
+ // create a new file (truncate)
+ os = simout.create(filename, true);
+ } else {
+ // do not truncate file if offset is non-zero
+ // (ios::in flag is required as well to keep the existing data
+ // intact, otherwise existing data will be zeroed out.)
+ os = simout.openFile(simout.directory() + filename,
+ ios::in | ios::out | ios::binary);
+ }
+ if (!os)
+ panic("could not open file %s\n", filename);
+
+ // seek to offset
+ os->seekp(offset);
+
+ // copy out data and write to file
+ char *buf = new char[len];
+ CopyOut(tc, buf, vaddr, len);
+ os->write(buf, len);
+ if (os->fail() || os->bad())
+ panic("Error while doing writefile!\n");
+
+ simout.close(os);
+
+ delete [] buf;
+
+ return len;
+}
+
#endif
void
diff --git a/src/sim/pseudo_inst.hh b/src/sim/pseudo_inst.hh
index 673ec6170..ae93c6877 100644
--- a/src/sim/pseudo_inst.hh
+++ b/src/sim/pseudo_inst.hh
@@ -55,6 +55,8 @@ void quiesceCycles(ThreadContext *tc, uint64_t cycles);
uint64_t quiesceTime(ThreadContext *tc);
uint64_t readfile(ThreadContext *tc, Addr vaddr, uint64_t len,
uint64_t offset);
+uint64_t writefile(ThreadContext *tc, Addr vaddr, uint64_t len,
+ uint64_t offset, Addr filenameAddr);
void loadsymbol(ThreadContext *xc);
void addsymbol(ThreadContext *tc, Addr addr, Addr symbolAddr);
uint64_t initParam(ThreadContext *xc);
diff --git a/util/m5/m5.c b/util/m5/m5.c
index 40328bc38..a0ce9b3ec 100644
--- a/util/m5/m5.c
+++ b/util/m5/m5.c
@@ -88,6 +88,33 @@ read_file(int dest_fid)
}
}
+int
+write_file(const char *filename)
+{
+ fprintf(stderr, "opening %s\n", filename);
+ int src_fid = open(filename, O_RDONLY);
+
+ if (src_fid < 0) {
+ fprintf(stderr, "error opening %s\n", filename);
+ return;
+ }
+
+ char buf[256*1024];
+ int offset = 0;
+ int len;
+ int bytes = 0;
+
+ memset(buf, 0, sizeof(buf));
+
+ while ((len = read(src_fid, buf, sizeof(buf))) > 0) {
+ bytes += m5_writefile(buf, len, offset, filename);
+ offset += len;
+ }
+ fprintf(stderr, "written %d bytes\n", bytes);
+
+ close(src_fid);
+}
+
void
do_exit(int argc, char *argv[])
{
@@ -131,6 +158,17 @@ do_read_file(int argc, char *argv[])
}
void
+do_write_file(int argc, char *argv[])
+{
+ if (argc != 1)
+ usage();
+
+ const char *filename = argv[0];
+
+ write_file(filename);
+}
+
+void
do_exec_file(int argc, char *argv[])
{
if (argc > 0)
@@ -227,8 +265,9 @@ struct MainFunc mainfuncs[] = {
{ "resetstats", do_reset_stats, "[delay [period]]" },
{ "dumpstats", do_dump_stats, "[delay [period]]" },
{ "dumpresetstats", do_dump_reset_stats, "[delay [period]]" },
- { "readfile", do_read_file, "[filename]" },
- { "execfile", do_exec_file, "<filename>" },
+ { "readfile", do_read_file, "" },
+ { "writefile", do_write_file, "<filename>" },
+ { "execfile", do_exec_file, "" },
{ "checkpoint", do_checkpoint, "[delay [period]]" },
{ "loadsymbol", do_load_symbol, "<address> <symbol>" },
{ "initparam", do_initparam, "" },
diff --git a/util/m5/m5op.h b/util/m5/m5op.h
index 38815e3c3..4e1d0b638 100644
--- a/util/m5/m5op.h
+++ b/util/m5/m5op.h
@@ -49,6 +49,7 @@ void m5_reset_stats(uint64_t ns_delay, uint64_t ns_period);
void m5_dump_stats(uint64_t ns_delay, uint64_t ns_period);
void m5_dumpreset_stats(uint64_t ns_delay, uint64_t ns_period);
uint64_t m5_readfile(void *buffer, uint64_t len, uint64_t offset);
+uint64_t m5_writefile(void *buffer, uint64_t len, uint64_t offset, const char *filename);
void m5_debugbreak(void);
void m5_switchcpu(void);
void m5_addsymbol(uint64_t addr, char *symbol);
diff --git a/util/m5/m5op_arm.S b/util/m5/m5op_arm.S
index b9557ee9d..8cdf5c62d 100644
--- a/util/m5/m5op_arm.S
+++ b/util/m5/m5op_arm.S
@@ -80,6 +80,7 @@ func:
#define DUMPRST_STATS INST(m5_op, 0, 0, dumprststats_func)
#define CHECKPOINT INST(m5_op, 0, 0, ckpt_func)
#define READFILE INST(m5_op, 0, 0, readfile_func)
+#define WRITEFILE INST(m5_op, 0, 0, writefile_func)
#define DEBUGBREAK INST(m5_op, 0, 0, debugbreak_func)
#define SWITCHCPU INST(m5_op, 0, 0, switchcpu_func)
#define ADDSYMBOL INST(m5_op, 0, 0, addsymbol_func)
@@ -121,6 +122,7 @@ SIMPLE_OP(m5_dump_stats, DUMP_STATS)
SIMPLE_OP(m5_dumpreset_stats, DUMPRST_STATS)
SIMPLE_OP(m5_checkpoint, CHECKPOINT)
SIMPLE_OP(m5_readfile, READFILE)
+SIMPLE_OP(m5_writefile, WRITEFILE)
SIMPLE_OP(m5_debugbreak, DEBUGBREAK)
SIMPLE_OP(m5_switchcpu, SWITCHCPU)
SIMPLE_OP(m5_addsymbol, ADDSYMBOL)
diff --git a/util/m5/m5ops.h b/util/m5/m5ops.h
index bc2ae06be..f08524014 100644
--- a/util/m5/m5ops.h
+++ b/util/m5/m5ops.h
@@ -46,6 +46,7 @@
#define dumpstats_func 0x41
#define dumprststats_func 0x42
#define ckpt_func 0x43
+#define writefile_func 0x4F
#define readfile_func 0x50
#define debugbreak_func 0x51
#define switchcpu_func 0x52