util: implements "writefile" gem5 op to export file from guest to host filesystem
authorDam Sunwoo <dam.sunwoo@arm.com>
Tue, 31 Jan 2012 15:46:04 +0000 (07:46 -0800)
committerDam Sunwoo <dam.sunwoo@arm.com>
Tue, 31 Jan 2012 15:46:04 +0000 (07:46 -0800)
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.

src/arch/arm/isa/formats/m5ops.isa
src/arch/arm/isa/insts/m5ops.isa
src/base/output.hh
src/sim/pseudo_inst.cc
src/sim/pseudo_inst.hh
util/m5/m5.c
util/m5/m5op.h
util/m5/m5op_arm.S
util/m5/m5ops.h

index f532d828baa61ef8708fc8fcf128611d022cbc7f..534d12cd933139ccd7fc92d6fafd89ea709a9801 100644 (file)
@@ -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);
index 222ecc6474d818983101e286a0e61f9623ef8df4..1a154459eaf3d67759c979216ef1b5854221a295 100644 (file)
@@ -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 },
index b86e68856a9d2c8037aadcfbad55d3bec6380897..68d9daf85ef33c524a699aa695d407adc1ddd596 100644 (file)
@@ -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
index 647420ca13d61229addb8a82a85768ac9739da17..4e6c46f8e99f9e3480c8738277fddd42609d3405 100644 (file)
@@ -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
index 673ec61705ca4047e68c83b682943cccd58fe0df..ae93c6877ccaa236ae0f12049aacd7ff9ef4638b 100644 (file)
@@ -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);
index 40328bc388338ccfd9a9313b2f8e0f4cf604a3ee..a0ce9b3ec4064b7d96c0c533178b84628529b591 100644 (file)
@@ -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[])
 {
@@ -130,6 +157,17 @@ do_read_file(int argc, char *argv[])
     read_file(STDOUT_FILENO);
 }
 
+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[])
 {
@@ -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,        "" },
index 38815e3c30e26edf87adfad506124f3a49fd36bc..4e1d0b638e424e15c38c90f04e0d210be23277e5 100644 (file)
@@ -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);
index b9557ee9d0abcfa715fe19e2d8ccc3d330a202e4..8cdf5c62df2e177ff93a15a38504694642e1b386 100644 (file)
@@ -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)
index bc2ae06be927d996f84db7dc1e7df19c6f227642..f08524014bd4862569652ed7cf2f69bae02c0a50 100644 (file)
@@ -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