├── .gitignore ├── .gitmodules ├── .travis.yml ├── BUGS ├── CHANGELOG ├── COPYING ├── INSTALL ├── Makefile ├── README.md ├── VERSION ├── arm-build.sh ├── build-qemu.sh ├── des ├── des.h └── des.test.cpp ├── distorm ├── distorm.h ├── distorm64.a └── distorm64 │ ├── .gitignore │ ├── CHANGES │ ├── COPYING │ ├── README │ ├── build │ ├── dmc │ │ ├── README │ │ └── make.bat │ ├── linux │ │ ├── Makefile │ │ └── instpython.sh │ ├── mac │ │ ├── Makefile │ │ └── instpython.sh │ ├── tcc │ │ ├── README │ │ └── make.bat │ ├── watcom │ │ ├── README │ │ └── make.bat │ └── win32 │ │ ├── cdistorm.vcproj │ │ ├── distorm.sln │ │ ├── dyndistorm.vcproj │ │ ├── main.py │ │ ├── pydistorm.vcproj │ │ ├── resource.h │ │ └── resource.rc │ ├── config.h │ ├── ddkproj │ ├── README │ ├── distorm.ini │ ├── dummy.c │ ├── main.c │ ├── makefile │ └── sources │ ├── distorm.h │ ├── doc │ ├── distorm.html │ ├── qa.txt │ ├── vol1.html │ └── vol2.html │ ├── linuxproj │ ├── Makefile │ └── main.c │ ├── python │ ├── README │ └── pydistorm.py │ ├── src │ ├── decoder.c │ ├── decoder.h │ ├── distorm.c │ ├── instructions.c │ ├── instructions.h │ ├── insts.c │ ├── insts.h │ ├── operands.c │ ├── operands.h │ ├── prefix.c │ ├── prefix.h │ ├── pydistorm.c │ ├── pydistorm.h │ ├── textdefs.c │ ├── textdefs.h │ ├── wstring.c │ ├── wstring.h │ ├── x86defs.c │ └── x86defs.h │ └── win32proj │ ├── disasm.sln │ ├── disasm.vcproj │ └── main.cpp ├── doc ├── Makefile ├── atomics.fig ├── fast_forwarder.fig ├── mod_qemu.fig ├── qemu_diagram.fig ├── qsim_architecture.png ├── qsim_diagram.fig ├── simple_example.fig ├── simulation_diagram.fig ├── translation.fig ├── user_guide.tex └── web │ ├── index.html │ ├── qsim_diagram.png │ └── qsim_splash.png ├── examples ├── arm64 │ ├── .gitignore │ ├── Makefile │ ├── cachesim.cpp │ ├── cs_disas.cpp │ ├── cs_disas.h │ └── simple.cpp └── x86 │ ├── Makefile │ ├── cachesim.cpp │ ├── io-test.cpp │ ├── qtm.cpp │ ├── simple.cpp │ ├── test.cpp │ ├── utrace.cpp │ ├── virt_rw.cpp │ └── vistrace.cpp ├── fastforwarder.cpp ├── initrd ├── .gitignore ├── Makefile ├── busybox-config ├── etc │ └── fstab ├── getbusybox.sh ├── init ├── mark_app.c ├── qsim_io.c ├── sbin │ ├── .gitignore │ ├── init │ ├── qsim_bin_out │ ├── qsim_in │ └── qsim_out ├── test_inst.c ├── test_mem.c └── test_threads.c ├── linux ├── Image ├── README.linux ├── bzImage ├── getkernel.sh ├── linux-2.6.34.qsim.config ├── linux-2.6.34.qsim.patch ├── linux-4.1.qsim-arm64.config ├── linux-4.1.qsim-x86.config └── linux-4.1.qsim.patch ├── mgzd.h ├── mkstate.sh ├── qcache ├── BUGS ├── Makefile ├── doc │ ├── README │ └── qcache.fig ├── main.cpp ├── qcache-bloom.h ├── qcache-dir.h ├── qcache-mesi.h ├── qcache-moesi.h ├── qcache-msi.h ├── qcache-repl.h ├── qcache.cpp ├── qcache.h ├── qcpu.h ├── qtickable.h └── test_qcache.sh ├── qdb ├── BUGS ├── Makefile ├── System.map ├── banner.h ├── bzImage ├── help.cpp ├── lexer.lex ├── parser.ypp ├── qdb.cpp ├── qdb.h └── util.h ├── qdram ├── Makefile ├── README ├── main.cpp ├── qdram-config.h ├── qdram-event.h ├── qdram-sched-fcfs.h ├── qdram-sched.h └── qdram.h ├── qsim-arm-regs.h ├── qsim-arm64-regs.h ├── qsim-context.h ├── qsim-func.h ├── qsim-load.cpp ├── qsim-load.h ├── qsim-prof.cpp ├── qsim-prof.h ├── qsim-regs.h ├── qsim-vm.h ├── qsim-x86-regs.h ├── qsim.cpp ├── qsim.h ├── qsim_magic.h ├── setup.sh ├── setup_sudo.sh ├── simplesim ├── Makefile ├── README ├── cache.cpp ├── cache.h ├── cpu.cpp ├── cpu.h ├── data.cpp ├── data.h ├── debug.h ├── des.cpp ├── des.h └── main.cpp ├── statesaver.cpp ├── statesaver.h └── tests ├── .gitignore ├── Makefile ├── arm64 ├── Makefile ├── contention.cpp ├── icount.cpp ├── icount_gold.out ├── memory.cpp ├── memory_gold.out └── threads.cpp ├── runme_orig.sh ├── tester.cpp └── x86 ├── Makefile ├── icount.cpp ├── icount_gold.out ├── memory.cpp ├── memory_gold.out ├── reg.cpp └── reg_gold.out /.gitignore: -------------------------------------------------------------------------------- 1 | distorm/distorm64/build/linux/libdistorm64.so 2 | distorm/distorm64/distorm64.a 3 | distorm/distorm64/src/*.o 4 | doc/*.pdf 5 | doc/*.aux 6 | doc/*.log 7 | doc/*.toc 8 | doc/*.tmp.out 9 | libqsim.so 10 | qcache/*.o 11 | qcache/qcache 12 | qcache/QSIM_PROF 13 | qemu-0.12.3.tar.gz 14 | qemu-0.12.3/ 15 | qsim-fastforwarder 16 | *.o 17 | state.* 18 | linux/*.tar.bz2 19 | linux/*.tar.xz 20 | linux/linux 21 | examples/x86/io-test 22 | examples/x86/qtm 23 | examples/x86/simple 24 | examples/x86/cachesim 25 | examples/TRACE 26 | mkstate.log 27 | lib 28 | examples/arm64/simple 29 | examples/arm64/trace* 30 | examples/arm64/cachesim 31 | examples/arm64trace* 32 | examples/x86/cachesim_headless 33 | examples/x86/headless 34 | examples/x86/virt_rw 35 | examples/x86/trace.log 36 | initrd/init_old 37 | initrd/test_inst 38 | initrd/test_mem 39 | initrd/initrd.cpio.x86 40 | initrd/initrd.cpio.arm64 41 | initrd/busybox-1.26.2 42 | include/ 43 | .dbg_build 44 | .opt_build 45 | tools 46 | images 47 | build 48 | mkstate.a64.log 49 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "qemu"] 2 | path = qemu 3 | url = https://github.com/gtcasl/qemu 4 | [submodule "capstone"] 5 | path = capstone 6 | url = https://github.com/pranith/capstone 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | cache: ccache 3 | sudo: required 4 | dist: trusty 5 | addons: 6 | apt: 7 | sources: 8 | - ubuntu-toolchain-r-test 9 | packages: 10 | - g++-4.9 11 | - clang-3.5 12 | - gcc-aarch64-linux-gnu 13 | - g++-aarch64-linux-gnu 14 | - bc 15 | - qemu-user 16 | - qemu 17 | before_install: 18 | - sudo apt-get -y build-dep qemu linux-meta 19 | - export QSIM_PREFIX=`pwd` 20 | - export LD_LIBRARY_PATH=$QSIM_PREFIX/lib:$LD_LIBRARY_PATH 21 | - cd capstone 22 | - make 23 | - cd .. 24 | - cd distorm/distorm64/build/linux 25 | - make clib 26 | - cd $QSIM_PREFIX/linux 27 | - ./getkernel.sh 28 | - ./getkernel.sh arm64 29 | - cd $QSIM_PREFIX/initrd 30 | - ./getbusybox.sh 31 | - cd $QSIM_PREFIX 32 | script: 33 | - make release install 34 | - make tests 35 | after_success: 36 | - cd $QSIM_PREFIX/examples/x86/ 37 | - make 38 | - cd $QSIM_PREFIX/examples/arm64/ 39 | - make 40 | compiler: 41 | - clang 42 | - gcc 43 | git: 44 | submodules: true 45 | notifications: 46 | email: 47 | recipients: 48 | - bobby.prani@gmail.com 49 | on_success: change 50 | on_failure: always 51 | irc: "irc.oftc.net#qsim" 52 | -------------------------------------------------------------------------------- /BUGS: -------------------------------------------------------------------------------- 1 | * Temporary files are not deleted when a QSIM-using program exits, unexpectedly 2 | or otherwise. Attempts to delete the files, even after they are dlclosed() 3 | have caused bus errors. This could perhaps be fixed by a cleanup function. 4 | 5 | * The temporary filenames created in mgzd.h are not safe. The tempnam() 6 | function is used for their creation, which leads to a race condition. 7 | Unfortunately, there is no easy way around this in file systems that do not 8 | support file locking: dlopen() requires a filename, not just a file 9 | descriptor or pointer to a FILE structure. 10 | 11 | * Loads must be performed twice within QEMU in order to maintain proper 12 | semantics. This is more a kludge than a bug (no incorrect behavior). 13 | 14 | * There is currently no way to broadcast a translation cache flush. This means 15 | that one CPU can overwrite code that another has already cached and this 16 | change will not propagate. Luckily this seems to be rare. 17 | 18 | * The server doesn't handle application exit gracefully. It should probably 19 | also exit, since no further instructions will be needed. Otherwise, it 20 | continues to run after the client exists, creating a problem. 21 | 22 | * No thread can call run() while any thread is constructing OSDomains. There is 23 | no lock to protect the running threads from the constructor (but there are 24 | locks to protect constructors from one another). The real "bug" here is that 25 | this is not currently adequately documented. -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ------------------------- 3 | 4 | If you are on Ubuntu (>= 14.04), run sudo_setup.sh script in the qsim 5 | directory. Otherwise run setup.sh This will set up the entire QSim 6 | infrastructure. On other distributions, comment the apt-get lines, 7 | install build dependencies for QEMU and run the script. 8 | 9 | $ ./setup.sh 10 | 11 | Please note that download OS images needs atleast 10G space. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | qsim [![Build Status](https://travis-ci.org/gtcasl/qsim.svg?branch=master)](https://travis-ci.org/gtcasl/qsim) 2 | ========================= 3 | 4 | 1. See building/installation instructions in INSTALL. 5 | 2. Build and run examples in examples/ 6 | 3. For more information, consult the QSim website. 7 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2.6 2 | -------------------------------------------------------------------------------- /arm-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -n "${QSIM_PREFIX+1}" ]; then 4 | echo "QSIM_PREFIX environment variable is set to: ${QSIM_PREFIX}" 5 | else 6 | echo "QSIM_PREFIX is not defined. Please set it to the root qsim folder." 7 | exit 0; 8 | fi 9 | 10 | QEMU_CFLAGS="-I/usr/include/pixman-1 -I${QSIM_PREFIX} -shared -m64 -g -Werror -fPIC -m64 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-all -I/usr/include/p11-kit-1 -I/usr/include/p11-kit-1 -I/usr/include/libpng12 -I/usr/include/spice-server -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/spice-1 -I/usr/include/libusb-1.0" ../qemu/configure --target-list=arm-softmmu --disable-pie --enable-debug 11 | make -j8 12 | -------------------------------------------------------------------------------- /build-qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -n "${QSIM_PREFIX+1}" ]; then 4 | echo "QSIM_PREFIX environment variable is set to: ${QSIM_PREFIX}" 5 | else 6 | echo "QSIM_PREFIX is not defined. Please set it to the root qsim folder." 7 | exit 0; 8 | fi 9 | 10 | if [[ $1 = "debug" ]]; then 11 | debug_flags="--enable-debug --enable-debug-tcg --enable-debug-info" 12 | build_dir=.dbg_build 13 | fi 14 | 15 | if [[ $1 = "release" ]]; then 16 | build_dir=.opt_build 17 | fi 18 | 19 | mkdir -p $QSIM_PREFIX/lib/ 20 | if [ ! -d "$build_dir" ]; then 21 | mkdir -p $build_dir 22 | cd $build_dir 23 | QEMU_CFLAGS="-I${QSIM_PREFIX} -g -fPIC -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wno-deprecated-declarations -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -Wendif-labels -Wmissing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wtype-limits -fstack-protector-all -Wno-uninitialized" ../qemu/configure --extra-ldflags=-shared --target-list=aarch64-softmmu,x86_64-softmmu --disable-pie --disable-brlapi --disable-rdma --disable-rbd --disable-tcmalloc --disable-xen --disable-gtk --disable-glusterfs --disable-xfsctl --disable-uuid $debug_flags --datadir=$QSIM_PREFIX/qemu/pc-bios --with-confsuffix=/ 24 | else 25 | cd $build_dir 26 | fi 27 | 28 | make -j4 29 | cd .. 30 | rm -f build 31 | ln -s $build_dir build 32 | -------------------------------------------------------------------------------- /des/des.h: -------------------------------------------------------------------------------- 1 | #ifndef __SLIDE_DES_H 2 | #define __SLIDE_DES_H 3 | 4 | #include 5 | 6 | // schedule(cycles, S* c, void(*f)(T*), T* arg) 7 | // 8 | // This is the single function that must be implemented in order to port the 9 | // Slide libraries to your simulation infrastructure of choice. A very simple 10 | // serial discrete event simulator is included for both testing and simple 11 | // standalone simulations. The only thing it can do is call single-argument 12 | // class member functions at arbitrary times in the future. 13 | // 14 | // The following define the control mechanism for the built-in DES. Other DES 15 | // systems will have their own main loops to control advancement. 16 | // 17 | // bool _tick(); 18 | // 19 | // Advance the builtin DES to the next event and execute it. Returns true if 20 | // more events remain to process. 21 | // 22 | // bool _advance(uint64_t n); 23 | // 24 | // Advance the builtin DES by n cycles. Returns true if more events remain to 25 | // process. 26 | 27 | namespace Slide { 28 | #ifdef MANIFOLD 29 | template static inline void schedule(unsigned cycles, 30 | void(*f)(T*), 31 | T* arg) 32 | { 33 | #error schedule() not implemented for Manifold. 34 | } 35 | #else 36 | #ifdef SST 37 | #else /* Standalone serial DES : */ 38 | 39 | uint64_t _now = 0; 40 | 41 | struct _event_t { virtual ~_event_t() {} }; 42 | template struct _event_spec_t: public _event_t { 43 | _event_spec_t(S* s, void (S::*f)(T*), T* a): s(s), f(f), a(a) {} 44 | virtual ~_event_spec_t() { ((s)->*(f))(a); } 45 | S* s; void (S::*f)(T*); T* a; 46 | }; 47 | 48 | std::multimap _event_q; 49 | static inline bool _tick() { 50 | if (_event_q.empty()) return false; 51 | _now = _event_q.begin()->first; 52 | delete _event_q.begin()->second; 53 | _event_q.erase(_event_q.begin()); 54 | return true; 55 | } 56 | 57 | static inline bool _advance(uint64_t cycles) { 58 | _now += cycles; 59 | while (!_event_q.empty() && _event_q.begin()->first <= _now && _tick()); 60 | return !_event_q.empty(); 61 | } 62 | 63 | template 64 | static inline void schedule(unsigned cycles, 65 | S* s, 66 | void (S::*f)(T*), 67 | T* arg) 68 | { 69 | _event_q.insert( std::pair(_now+cycles, 70 | new _event_spec_t 71 | (s, f, arg))); 72 | } 73 | #endif 74 | #endif 75 | }; 76 | #endif /*__SLIDE_DES_H*/ 77 | -------------------------------------------------------------------------------- /des/des.test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "des.h" 5 | 6 | using Slide::schedule; 7 | 8 | class juicematic { 9 | public: 10 | juicematic(): fruits_left(10) {} 11 | juicematic(unsigned n) : fruits_left(n) {} 12 | 13 | void rest(void *v) { 14 | if (fruits_left > 0) { 15 | // Squeeze a random fraction of my fruits a random amount of time in the 16 | // future. 17 | unsigned fruits_to_squeeze = rand()%(fruits_left) + 1; 18 | schedule(rand()%1000, 19 | this, 20 | &juicematic::squeeze_some, 21 | new unsigned(fruits_to_squeeze)); 22 | } else { 23 | std::cout << "Juicematic " << this << " has no fruits left.\n"; 24 | } 25 | } 26 | 27 | void squeeze_some(unsigned *n) { 28 | if (fruits_left >= *n) { 29 | fruits_left -= *n; 30 | std::cout << "Juicematic " << this << " squeezing " 31 | << *n << " fruits.\n"; 32 | // That squeezin' was hard work. Rest for a little while. 33 | schedule(rand()%1000, this, &juicematic::rest, (void*)0); 34 | } else { 35 | std::cerr << "Wanted to squeeze " << *n << " fruits, but I only have " 36 | << fruits_left << "!\n"; 37 | // Don't squeeze anymore. 38 | } 39 | 40 | delete n; 41 | } 42 | 43 | private: 44 | unsigned fruits_left; 45 | }; 46 | 47 | int main() { 48 | juicematic j(101), k(102), l(103); 49 | 50 | schedule(rand()%1000, &j, &juicematic::rest, (void*)0); 51 | schedule(rand()%1000, &k, &juicematic::rest, (void*)0); 52 | schedule(rand()%1000, &l, &juicematic::rest, (void*)0); 53 | 54 | while(Slide::_tick()); 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /distorm/distorm.h: -------------------------------------------------------------------------------- 1 | distorm64/distorm.h -------------------------------------------------------------------------------- /distorm/distorm64.a: -------------------------------------------------------------------------------- 1 | distorm64/distorm64.a -------------------------------------------------------------------------------- /distorm/distorm64/.gitignore: -------------------------------------------------------------------------------- 1 | src/*.o 2 | *.a 3 | build/linux/*.so 4 | -------------------------------------------------------------------------------- /distorm/distorm64/CHANGES: -------------------------------------------------------------------------------- 1 | Copyright (C) 2003-2007 Gil Dabah, http://ragestorm.net/distorm/ 2 | 3 | History: 4 | -+------ 5 | FPU(387) parsing added Feb 2004. 6 | Prefixes parsing added July 2004. 7 | SIB parsing added Dec 2004. 8 | Rep/lock/xlat explicit-operand forms added Dec 2004. 9 | Wrapped in Python Jan 2005. 10 | Using static instructions tables Jan 2005. 11 | MMX parsing added Feb 2005. 12 | SSE parsing added Feb 2005. 13 | SSE2 parsing added March 2005. 14 | SSE3 parsing added March 2005. 15 | Pseudo Opcodes parsing added March 2005. 16 | 3DNow! parsing added March 2005. 17 | Global Optimization April 2005. 18 | AMD64 added July 2005. 19 | Linux Port November 2005. 20 | Strings Optimization November 2005. 21 | New API December 2005. 22 | LGPL December 2005. 23 | Doc + Sources uploaded Januar 2006. 24 | 64bit Offsets are now supported January 2006. 25 | diStorm is now licensed under the BSD license January 2006. 26 | 1.2.8 diStorm can be compiled for Big Endian systems May 2006. 27 | 1.3.9: SSE4 (later known as SSSE3) parsing added May 2006. 28 | 1.3.9: VMX instructions set is now supported. 29 | 1.4.10: Instructions' flags were changed, engine supports instsruction set class type. May 2006. 30 | 1.4.10: All comments are now C style, source code is now 64bits compiler compatible. 31 | 1.5.10: Operand size of Memory Indirection is now determined inside operands.c and not instructions.c. May 2006. 32 | 1.5.15 SVM Instructions set is added Aug 2006. 33 | Python2.5 is compiled too. Sep 2006. 34 | 1.5.17 Formerly unofficial SSE4 is now officially called SSSE3. 35 | diStorm has a sample code for Ring0 using the DDK. Jan 2007. 36 | 1.6.18 Instructions table are now more optimized for size. Feb 2007. 37 | 1.6.21 Added a new Mac makefile to compile diStorm on a Mac. Apr 2007. 38 | 1.7.22 Real SSE4 parsing added April 2007. 39 | 1.7.26 New AMD instructions, support of different compilers. 40 | 41 | Fixed bugs: 42 | -+--------- 43 | 2/11/05 1.0.1 Call instruction wasn't promoted to 64 bits automatically. 44 | 16/11/05 1.0.2 Mov MOFF instruction used RAX in 32 bits, and wasnt dropped in 16 bits. 45 | 17/01/06 1.1.3 Some special instructions were ignoring the REX.B flag. 46 | 27/01/06 1.1.4 Support for 64bit offsets was added. 47 | 03/02/06 1.1.5 PUSH, JMP and CMP instructions were slightly fixed. 48 | 18/03/06 1.1.6 MOVZX/MOVSX and RETF operands' types were changed. 49 | 20/03/06 1.1.7 A bug treating mandatory prefixes in 64bits was fixed. 50 | 18/04/06 1.1.8 LOOPxx instructions are now categorized as Natives. 51 | 18/05/06 1.2.9 A few FPU instructions weren't set correctly in IGEN. 52 | 28/05/06 1.4.10 Push/Pop instructions with ModR/M fields are now fixed. 53 | 02/06/06 1.5.11 Fixed a new bug in operands.c, where OT_IMM_FULL was broken in 64bits. 54 | 03/06/06 1.5.12 Invalid memory access occurred in 64bit environments only is now fixed. 55 | 09/06/06 1.5.13 SGDT, SIDT, LGDT, LIDT, JMP FAR, CALL FAR, SMSW, LMSW, LDS, LES, LFS, LGS, LSS and other instructions which have special memory operands' types were fully corrected. And a bug in locate_raw_inst when using mingw environment. 56 | 01/07/06 1.5.14 REX prefix with BASE bit isn't dropped always, and string instructions are now promoted to 64bits only with REX prefix. 57 | 08/07/06 1.5.14 The sample projects of both Linux and Windows have been updated. 58 | 02/10/06 1.5.16 MOVSXD wasn't decoded properly and it now supports MOVZXD. 59 | 08/01/07 1.5.17 Removed redundant #include's to standard libraries. 60 | 11/02/07 1.5.18 Fixed a bug in OT_RM32_64 decoding. 61 | 28/02/07 1.6.19 All string/IO instructions support both REP and REPNZ. 62 | 03/03/07 1.6.20 3DNow! instructions weren't decoded (produced in 1.6.19). 63 | 17/04/07 1.6.21 MOV-Offset instructions weren't decoded correctly in 64bits. 64 | 23/04/07 1.6.22 The mnemonic of MOVD/MOVQ wasn't changed according to operand size. 65 | 12/05/07 1.7.23 Added the instructions MOVSLDUP and INVLPGA and fixed SVM instructions. 66 | 03/07/07 1.7.24 Added multi-byte NOP instruction. 67 | 19/07/07 1.7.25 Fixed a memory leak in Python extension module. 68 | 07/12/07 1.7.27 Fixed various instructions. 69 | 09/02/08 1.7.28 NOP and XCHG are treated correctly in 64bits. 70 | 07/03/08 1.7.29 LEA now ignores segment override prefixes. 71 | 17/09/08 1.7.30 DLL project added to the Win32 solution and fixed DDK compilation. 72 | -------------------------------------------------------------------------------- /distorm/distorm64/COPYING: -------------------------------------------------------------------------------- 1 | :[diStorm64}: 2 | The ultimate disassembler library. 3 | Copyright (c) 2003,2004,2005,2006,2007,2008, Gil Dabah 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 10 | * Neither the name of the diStorm nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /distorm/distorm64/README: -------------------------------------------------------------------------------- 1 | :[diStorm64}: (v1.7.30) 2 | The ultimate disassembler library (for AMD64, X86-64). 3 | 4 | diStorm is licensed under the BSD license. 5 | 6 | For documentation and MUCH MORE please refer to doc/distorm.html. 7 | 8 | 9 | Directory Listing: 10 | -+---------------- 11 | doc/ - Contains documentation files. 12 | build/win32/ - Solution file for VS03. 13 | build/linux/ - Make file and installation script for Python. 14 | build/mac/ - Make file and installation script for Python2.3 (works for Tiger). 15 | src/ - Full source code. 16 | linuxproj/ - Raw file disassembler, sample project, shows how to use the C Library. 17 | win32proj/ - Ditto, but for Win32. 18 | ddkproj/ - A Windows kernel driver source that disassembles the beginning of KeBugCheck as an example. 19 | 20 | distorm.h - Header file for diStorm's C library (Used by win32proj and linuxproj). 21 | config.h - Compiler specific macros definitions (Endianity support too). 22 | 23 | NOTE - See config.h and distorm.h for library configuration (such as exports, size of integers, etc). 24 | 25 | Win32 Compilation: 26 | -+---------------- 27 | The distorm.sln file contains two projects: cdistorm and pydistorm. 28 | There are three configurations: clib, py24 and py23. 29 | 'clib' configuration will create a distorm.lib file for win32proj used with the 30 | header file (distorm.h). 31 | 'py25/24/23' configuration will create distorm.pyd in the corresponding directory, 32 | which should be copied into the Python\Lib\site-packages. 33 | You might want to change the directories of the Python library/include directories 34 | which are set in the configurations. 35 | There is also a 'dyndistorm' project which will create a distorm.dll file which you can use along with 'distorm.h'. 36 | 37 | Linux Compilation: 38 | -+---------------- 39 | The makefile will compile diStorm for clib and py24. 40 | 'make clib' will create a static archive library named 'distorm64.a' 41 | which is used by linuxproj. 42 | 'make py' will create a shared object file, named 'libdistorm64.so' 43 | which is installed with the instpython.sh script (have to be root for that). 44 | 45 | Mac Compilation: 46 | -+-------------- 47 | The makefile will compile diStorm for clib and py23. 48 | You can easily edit it to compile diStorm for py2x. 49 | See the 'Linux Compilation' above for how to use the makefile. 50 | You can also use the same sample of linux project. 51 | 52 | DDK Compilation (Ring0): 53 | -+---------------------- 54 | diStorm can also be compiled as a kernel driver, 55 | there's a sample bundled under ddkproj. 56 | Follow accurately all the steps in the ddkproj/readme file to accomplish this task. 57 | 58 | For updates please visit http://ragestorm.net/distorm/ 59 | Note that there are currently not-known bugs. 60 | Please contact me for any bugs that are found in the source code 61 | by reporting to me, so people could enjoy a better product! 62 | 63 | If you wish to contact me, use this email: arkon@ragestorm.net 64 | Gil Dabah 65 | May 2007 66 | -------------------------------------------------------------------------------- /distorm/distorm64/build/dmc/README: -------------------------------------------------------------------------------- 1 | http://ragestorm.net/distorm/ 2 | Gil Dabah, Larry Lee Aug 2007 3 | 4 | Support for Digital Mars Compiler (DOS/Windows) 5 | 6 | Make sure the DMCPATH variable is set to the DMC\Bin directory. 7 | The make.bat will create the disasm.exe of the linux project. 8 | 9 | I prefered to compile a library since it will make the compilation of the linux project easier. So you only have to link it with the created library. Thus it's a two-steps compilation/linkage. 10 | 11 | If you want to port it to other platforms, it should be easy now that you got where to start from, just change the make file and output file name... 12 | -------------------------------------------------------------------------------- /distorm/distorm64/build/dmc/make.bat: -------------------------------------------------------------------------------- 1 | set DMCPATH=C:\dm\bin 2 | "%DMCPATH%\dmc" -c -DSUPPORT_64BIT_OFFSET ../../src/x86defs.c ../../src/wstring.c ../../src/textdefs.c ../../src/prefix.c ../../src/operands.c ../../src/insts.c ../../src/instructions.c ../../src/distorm.c ../../src/decoder.c 3 | "%DMCPATH%\lib" -n -c distorm.lib x86defs.obj wstring.obj textdefs.obj prefix.obj operands.obj insts.obj instructions.obj distorm.obj decoder.obj 4 | "%DMCPATH%\dmc" ../../linuxproj/main.c distorm.lib -o disasm.exe 5 | del *.obj;*.map;*.lib 6 | -------------------------------------------------------------------------------- /distorm/distorm64/build/linux/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm64 (Linux Port) 3 | # 4 | 5 | TARGET = libdistorm64.so 6 | COBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/distorm.o ../../src/decoder.o 7 | PYOBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/pydistorm.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/decoder.o 8 | CC = gcc 9 | CFLAGS = -O2 -Wall -fPIC -DSUPPORT_64BIT_OFFSET -D_DLL 10 | 11 | all: clib py 12 | 13 | clean: 14 | /bin/rm -rf ../../src/*.o ${TARGET} ../../distorm64.a 15 | 16 | clib: ${COBJS} 17 | ${CC} ${CFLAGS} ${VERSION} ${COBJS} -fPIC -shared -o ${TARGET} 18 | ar rs ../../distorm64.a ${COBJS} 19 | 20 | py: ${PYOBJS} 21 | ${CC} ${CFLAGS} ${VERSION} ${PYOBJS} -fPIC -shared -o ${TARGET} 22 | 23 | install: libdistorm64.so 24 | install -s ${TARGET} /usr/local/lib 25 | @echo "... running ldconfig might be smart ..." 26 | 27 | .c.o: 28 | ${CC} ${CFLAGS} ${VERSION} -c $< -o $@ 29 | 30 | -------------------------------------------------------------------------------- /distorm/distorm64/build/linux/instpython.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # instpython.sh, Install .so into Python Library 5 | # 6 | 7 | # 8 | # Check for libdistorm64.so in given Directory 9 | # 10 | 11 | if [ ! -f libdistorm64.so ]; then 12 | echo "*** Error: Can't find libdistorm64.so!" 13 | exit 0 14 | fi 15 | 16 | # 17 | # Lookup 'python' 18 | # 19 | 20 | PYTHONDIRS=`whereis python | awk -F ": " '{ print $2 }'` 21 | 22 | if [ -z "$PYTHONDIRS" ]; then 23 | echo "*** Error: Can't find Python at all!" 24 | exit 0 25 | fi 26 | 27 | 28 | # 29 | # Go through result, looking for 'lib' 30 | # 31 | 32 | FOUND=0 33 | 34 | for PDIR in $PYTHONDIRS; do 35 | 36 | echo $PDIR | grep "lib" > /dev/null 37 | 38 | # 39 | # Found lib Directory! 40 | # 41 | 42 | if [ $? == 0 ]; then 43 | 44 | # 45 | # Check if it include 'lib-dynload/' sub-directory 46 | # 47 | 48 | if [ -d $PDIR/lib-dynload/ ]; then 49 | FOUND=1 50 | break 51 | fi 52 | fi 53 | 54 | done 55 | 56 | # 57 | # Found it? 58 | # 59 | 60 | if [ $FOUND == 0 ]; then 61 | echo "*** Error: Can't find Python 'lib' or 'lib/lib-dynload/' directory!" 62 | exit 0 63 | fi 64 | 65 | # 66 | # Copy it 67 | # 68 | 69 | cp libdistorm64.so $PDIR/lib-dynload/distorm.so 2> /dev/null 70 | 71 | # 72 | # Everything went well? 73 | # 74 | 75 | if [ $? == 1 ]; then 76 | echo "*** Error: Unable to copy libdistorm64.so to $PDIR/lib-dynload, Permission denied?" 77 | exit 0 78 | fi 79 | 80 | # 81 | # Done. 82 | # 83 | 84 | echo "* Done!" 85 | exit 1 86 | -------------------------------------------------------------------------------- /distorm/distorm64/build/mac/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm64 (Mac Port) 3 | # 4 | 5 | TARGET = libdistorm64.dylib 6 | COBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/distorm.o ../../src/decoder.o 7 | PYOBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/pydistorm.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/decoder.o 8 | CC = gcc 9 | CFLAGS = -O2 -Wall -fPIC -DSUPPORT_64BIT_OFFSET -D_DLL -I/System/Library/Frameworks/Python.framework/Headers 10 | 11 | all: clib py 12 | 13 | clean: 14 | /bin/rm -rf ../../src/*.o ${TARGET} ../../distorm64.dylib 15 | 16 | clib: ${COBJS} 17 | ${CC} ${CFLAGS} ${VERSION} ${COBJS} -fPIC -dynamiclib -o ${TARGET} 18 | ar rs ../../distorm64.a ${COBJS} 19 | 20 | py: ${PYOBJS} 21 | ${CC} ${CFLAGS} ${VERSION} ${PYOBJS} -fPIC -dynamiclib -o ${TARGET} -lpython 22 | .c.o: 23 | ${CC} ${CFLAGS} ${VERSION} -c $< -o $@ 24 | 25 | -------------------------------------------------------------------------------- /distorm/distorm64/build/mac/instpython.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # instpython.sh, Install .so into Python2.3 Library 5 | # 6 | 7 | # 8 | # Check for libdistorm64.so in given Directory 9 | # 10 | 11 | if [ ! -f libdistorm64.dylib ]; then 12 | echo "*** Error: Can't find libdistorm64.dylib!" 13 | exit 0 14 | fi 15 | 16 | # 17 | # Copy it 18 | # 19 | 20 | cp libdistorm64.so /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.5/lib-dynload/distorm.so 2> /dev/null 21 | 22 | # 23 | # Everything went well? 24 | # 25 | 26 | if [ $? == 1 ]; then 27 | echo "*** Error: Unable to copy libdistorm64.so to /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.5/lib-dynload, Permission denied?" 28 | exit 0 29 | fi 30 | 31 | # 32 | # Done. 33 | # 34 | 35 | echo "* Done!" 36 | exit 1 37 | -------------------------------------------------------------------------------- /distorm/distorm64/build/tcc/README: -------------------------------------------------------------------------------- 1 | http://ragestorm.net/distorm/ 2 | Gil Dabah Aug 2007 3 | Support for Tiny C Compiler (DOS/Windows) 4 | 5 | Set the path of TCC inside make.bat and then run it. 6 | Since you cannot compile a library with TCC, you have to build diStorm itself with the linuxproj directly along. 7 | 8 | Note that since TCC is buggy and is abandoned by the original author, I changed some code so it will be compiled well with the official version of TCC. 9 | -------------------------------------------------------------------------------- /distorm/distorm64/build/tcc/make.bat: -------------------------------------------------------------------------------- 1 | set tccroot=c:\tcc\ 2 | "%tccroot%tcc\tcc.exe" "-I%tccroot%include" "-L%tccroot%lib" ../../src/x86defs.c ../../src/wstring.c ../../src/textdefs.c ../../src/prefix.c ../../src/operands.c ../../src/insts.c ../../src/instructions.c ../../src/distorm.c ../../src/decoder.c ../../linuxproj/main.c -o disasm.exe 3 | -------------------------------------------------------------------------------- /distorm/distorm64/build/watcom/README: -------------------------------------------------------------------------------- 1 | http://ragestorm.net/distorm/ 2 | JvW, Gil Dabah 2007 3 | 4 | Support for OpenWatcom 5 | 6 | Make sure the watcom variable, which must be set, points to the correct full path of the installed Watcom\ directory. 7 | The make.bat will create the disasm.exe of the linux project. 8 | 9 | I prefered to compile a library since it will make the compilation of the linux project easier. So you only have to link it with the created library. Thus it's a two-steps compilation/linkage. 10 | 11 | It can easily be changed to support other platforms but Windows. For now I chose to omit them and try to make the support as easy as possible. If you need further help just let me know. 12 | -------------------------------------------------------------------------------- /distorm/distorm64/build/watcom/make.bat: -------------------------------------------------------------------------------- 1 | set watcom=c:\watcom 2 | "%watcom%\binnt\cl386" -O2 -c -DSUPPORT_64BIT_OFFSET ../../src/x86defs.c ../../src/wstring.c ../../src/textdefs.c ../../src/prefix.c ../../src/operands.c ../../src/insts.c ../../src/instructions.c ../../src/distorm.c ../../src/decoder.c -I%watcom%\h 3 | 4 | "%watcom%\binnt\lib386" -out:distorm.lib x86defs.obj wstring.obj textdefs.obj prefix.obj operands.obj insts.obj instructions.obj distorm.obj decoder.obj 5 | "%watcom%\binnt\cl386" -O2 -c ../../linuxproj/main.c -I%watcom%\h 6 | set path=%path%;%watcom%\binnt\ 7 | "%watcom%\binnt\wlink" FILE main.obj LIBRARY distorm.lib NAME disasm.exe OPTION STACK=512K 8 | del *.obj;*.lib;*.map 9 | -------------------------------------------------------------------------------- /distorm/distorm64/build/win32/cdistorm.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 26 | 29 | 32 | 35 | 38 | 41 | 61 | 64 | 67 | 70 | 74 | 77 | 80 | 83 | 86 | 89 | 90 | 91 | 92 | 93 | 94 | 98 | 101 | 102 | 105 | 106 | 109 | 110 | 113 | 114 | 117 | 118 | 121 | 122 | 125 | 126 | 129 | 130 | 133 | 134 | 135 | 139 | 142 | 143 | 146 | 147 | 150 | 151 | 154 | 155 | 158 | 159 | 162 | 163 | 166 | 167 | 170 | 171 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /distorm/distorm64/build/win32/distorm.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 9.00 2 | # Visual Studio 2005 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libdistorm", "cdistorm.vcproj", "{15051CE1-AB10-4239-973D-01B84F2AD0A9}" 4 | EndProject 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pydistorm", "pydistorm.vcproj", "{E96298DA-D2F7-4619-BA93-26CCDBD13DDA}" 6 | EndProject 7 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dyndistorm", "dyndistorm.vcproj", "{3AC89F45-A773-435F-B001-012180AC4CBB}" 8 | EndProject 9 | Global 10 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 11 | clib|Win32 = clib|Win32 12 | dll|Win32 = dll|Win32 13 | py23|Win32 = py23|Win32 14 | py24|Win32 = py24|Win32 15 | py25|Win32 = py25|Win32 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|Win32.ActiveCfg = clib|Win32 19 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|Win32.Build.0 = clib|Win32 20 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|Win32.ActiveCfg = clib|Win32 21 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|Win32.Build.0 = clib|Win32 22 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py23|Win32.ActiveCfg = clib|Win32 23 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py24|Win32.ActiveCfg = clib|Win32 24 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py25|Win32.ActiveCfg = clib|Win32 25 | {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py25|Win32.Build.0 = clib|Win32 26 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.clib|Win32.ActiveCfg = py23|Win32 27 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.dll|Win32.ActiveCfg = py25|Win32 28 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.dll|Win32.Build.0 = py25|Win32 29 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py23|Win32.ActiveCfg = py23|Win32 30 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py23|Win32.Build.0 = py23|Win32 31 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py24|Win32.ActiveCfg = py24|Win32 32 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py24|Win32.Build.0 = py24|Win32 33 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py25|Win32.ActiveCfg = py25|Win32 34 | {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py25|Win32.Build.0 = py25|Win32 35 | {3AC89F45-A773-435F-B001-012180AC4CBB}.clib|Win32.ActiveCfg = dll|Win32 36 | {3AC89F45-A773-435F-B001-012180AC4CBB}.clib|Win32.Build.0 = dll|Win32 37 | {3AC89F45-A773-435F-B001-012180AC4CBB}.dll|Win32.ActiveCfg = dll|Win32 38 | {3AC89F45-A773-435F-B001-012180AC4CBB}.dll|Win32.Build.0 = dll|Win32 39 | {3AC89F45-A773-435F-B001-012180AC4CBB}.py23|Win32.ActiveCfg = dll|Win32 40 | {3AC89F45-A773-435F-B001-012180AC4CBB}.py23|Win32.Build.0 = dll|Win32 41 | {3AC89F45-A773-435F-B001-012180AC4CBB}.py24|Win32.ActiveCfg = dll|Win32 42 | {3AC89F45-A773-435F-B001-012180AC4CBB}.py24|Win32.Build.0 = dll|Win32 43 | {3AC89F45-A773-435F-B001-012180AC4CBB}.py25|Win32.ActiveCfg = dll|Win32 44 | {3AC89F45-A773-435F-B001-012180AC4CBB}.py25|Win32.Build.0 = dll|Win32 45 | EndGlobalSection 46 | GlobalSection(SolutionProperties) = preSolution 47 | HideSolutionNode = FALSE 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /distorm/distorm64/build/win32/main.py: -------------------------------------------------------------------------------- 1 | import distorm 2 | import binascii 3 | import random 4 | import time 5 | 6 | def decode16(hexcode): 7 | print "-----------------------Decode16Bits-----------------------" 8 | lines = distorm.Decode(0x100, binascii.unhexlify(hexcode), distorm.Decode16Bits) 9 | for i in lines: 10 | print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) 11 | print 12 | 13 | def decode32(hexcode): 14 | print "-----------------------Decode32Bits-----------------------" 15 | lines = distorm.Decode(0x100, binascii.unhexlify(hexcode), distorm.Decode32Bits) 16 | for i in lines: 17 | print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) 18 | print 19 | 20 | def decode64(hexcode): 21 | print "-----------------------Decode64Bits-----------------------" 22 | lines = distorm.Decode(0x100, binascii.unhexlify(hexcode), distorm.Decode64Bits) 23 | for i in lines: 24 | print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) 25 | print 26 | 27 | def main(): 28 | print distorm.info 29 | 30 | hexcode = "658d00" 31 | decode16(hexcode) 32 | decode32(hexcode) 33 | decode64(hexcode) 34 | 35 | def main_old(): 36 | print distorm.info 37 | hexcode = "" 38 | random.seed(9879877) 39 | print "start generating: %s" % time.asctime(time.localtime()) 40 | for i in xrange(1024): 41 | hexcode += chr(random.randint(0, 255)) 42 | print "start unpacking: %s" % time.asctime(time.localtime()) 43 | hexcode *= (1024*5) 44 | print "start decoding: %s" % time.asctime(time.localtime()) 45 | lines = distorm.Decode(0x55551, hexcode, distorm.Decode32Bits) 46 | print "end: %s" % time.asctime(time.localtime()) 47 | for i in lines: 48 | print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) 49 | 50 | #main_old() 51 | main() 52 | raw_input() 53 | -------------------------------------------------------------------------------- /distorm/distorm64/build/win32/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by resource.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /distorm/distorm64/build/win32/resource.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #include "afxres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (U.S.) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 19 | #ifdef _WIN32 20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 21 | #pragma code_page(1252) 22 | #endif //_WIN32 23 | 24 | #ifdef APSTUDIO_INVOKED 25 | ///////////////////////////////////////////////////////////////////////////// 26 | // 27 | // TEXTINCLUDE 28 | // 29 | 30 | 1 TEXTINCLUDE 31 | BEGIN 32 | "resource.h\0" 33 | END 34 | 35 | 2 TEXTINCLUDE 36 | BEGIN 37 | "#include ""afxres.h""\r\n" 38 | "\0" 39 | END 40 | 41 | 3 TEXTINCLUDE 42 | BEGIN 43 | "\r\n" 44 | "\0" 45 | END 46 | 47 | #endif // APSTUDIO_INVOKED 48 | 49 | 50 | ///////////////////////////////////////////////////////////////////////////// 51 | // 52 | // Version 53 | // 54 | 55 | VS_VERSION_INFO VERSIONINFO 56 | FILEVERSION 2,1,7,30 57 | PRODUCTVERSION 2,1,7,30 58 | FILEFLAGSMASK 0x17L 59 | #ifdef _DEBUG 60 | FILEFLAGS 0x1L 61 | #else 62 | FILEFLAGS 0x0L 63 | #endif 64 | FILEOS 0x4L 65 | FILETYPE 0x2L 66 | FILESUBTYPE 0x0L 67 | BEGIN 68 | BLOCK "StringFileInfo" 69 | BEGIN 70 | BLOCK "040904b0" 71 | BEGIN 72 | VALUE "FileDescription", "diStorm module" 73 | VALUE "FileVersion", "2, 1, 7, 30" 74 | VALUE "InternalName", "diStorm64" 75 | VALUE "LegalCopyright", "Gil Dabah Copyright (C) 2008" 76 | VALUE "OriginalFilename", "distorm.pyd" 77 | VALUE "ProductName", ":[diStorm64}:" 78 | VALUE "ProductVersion", "2, 1, 7, 30" 79 | END 80 | END 81 | BLOCK "VarFileInfo" 82 | BEGIN 83 | VALUE "Translation", 0x409, 1200 84 | END 85 | END 86 | 87 | #endif // English (U.S.) resources 88 | ///////////////////////////////////////////////////////////////////////////// 89 | 90 | 91 | 92 | #ifndef APSTUDIO_INVOKED 93 | ///////////////////////////////////////////////////////////////////////////// 94 | // 95 | // Generated from the TEXTINCLUDE 3 resource. 96 | // 97 | 98 | 99 | ///////////////////////////////////////////////////////////////////////////// 100 | #endif // not APSTUDIO_INVOKED 101 | 102 | -------------------------------------------------------------------------------- /distorm/distorm64/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | config.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef CONFIG_H 10 | #define CONFIG_H 11 | 12 | /* diStorm version number. */ 13 | #define DISTORM_VER 0x01071e 14 | 15 | #include /* strlen, memset, memcpy - can be easily self implemented for libc independency. */ 16 | 17 | /* 18 | * 64 bit offsets support: 19 | * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET 20 | * #define SUPPORT_64BIT_OFFSET 21 | * Note: make sure that the caller (library user) defines it too! 22 | */ 23 | 24 | /* 25 | * If you compile diStorm as a .DLL file, make sure you uncomment the next line. 26 | * So the interface functions will be exported, otherwise they are useable only as a library. 27 | * For example, the Python extension module defines this macro in its configuration. 28 | */ 29 | /* #define _DLL */ 30 | 31 | /* 32 | * diStorm now supports little/big endian CPU's. 33 | * It should detect the endianness according to predefined macro's of the compiler. 34 | * If you don't use GCC/MSVC you will have to define it on your own. 35 | */ 36 | 37 | /* These macros are used in order to make the code portable. */ 38 | #ifdef __GNUC__ 39 | 40 | #include 41 | 42 | #define _PACKED_ __attribute__((__packed__)) 43 | #define _DLLEXPORT_ 44 | #define _FASTCALL_ 45 | #define _INLINE_ static __inline__ 46 | /* GCC ignores this directive... */ 47 | /*#define _FASTCALL_ __attribute__((__fastcall__)) */ 48 | 49 | /* Set endianity (supposed to be LE though): */ 50 | #ifdef __BIG_ENDIAN__ 51 | #define BE_SYSTEM 52 | #endif 53 | 54 | /* End of __GCC__ */ 55 | 56 | #elif __WATCOMC__ 57 | 58 | #include 59 | 60 | #define _PACKED_ 61 | #define _DLLEXPORT_ 62 | #define _FASTCALL_ 63 | #define _INLINE_ __inline 64 | 65 | /* End of __WATCOMC__ */ 66 | 67 | #elif __DMC__ 68 | 69 | #include 70 | 71 | #define _PACKED_ 72 | #define _DLLEXPORT_ 73 | #define _FASTCALL_ 74 | #define _INLINE_ static __inline 75 | 76 | /* End of __DMC__ */ 77 | 78 | #elif __TINYC__ 79 | 80 | #include 81 | 82 | #define _PACKED_ 83 | #define _DLLEXPORT_ 84 | #define _FASTCALL_ 85 | #define _INLINE_ static 86 | 87 | /* End of __TINYC__ */ 88 | 89 | #elif _MSC_VER 90 | 91 | /* Since MSVC isn't shipped with stdint.h, we will have our own: */ 92 | typedef signed __int64 int64_t; 93 | typedef unsigned __int64 uint64_t; 94 | typedef signed __int32 int32_t; 95 | typedef unsigned __int32 uint32_t; 96 | typedef signed __int16 int16_t; 97 | typedef unsigned __int16 uint16_t; 98 | typedef signed __int8 int8_t; 99 | typedef unsigned __int8 uint8_t; 100 | 101 | #define _PACKED_ 102 | #define _DLLEXPORT_ __declspec(dllexport) 103 | #define _FASTCALL_ __fastcall 104 | #define _INLINE_ static __inline 105 | 106 | /* Set endianity (supposed to be LE though): */ 107 | #ifndef _M_IX86 108 | #define BE_SYSTEM 109 | #endif 110 | 111 | #endif /* #elif _MSC_VER */ 112 | 113 | /* 32 or 64 bits integer for instruction offset. */ 114 | #ifdef SUPPORT_64BIT_OFFSET 115 | #define OFFSET_INTEGER uint64_t 116 | #else 117 | #define OFFSET_INTEGER uint32_t 118 | #endif 119 | 120 | #ifndef FALSE 121 | #define FALSE 0 122 | #endif 123 | #ifndef TRUE 124 | #define TRUE 1 125 | #endif 126 | 127 | /* If the library isn't compiled as a .DLL don't export functions. */ 128 | #ifndef _DLL 129 | #undef _DLLEXPORT_ 130 | #define _DLLEXPORT_ 131 | #endif 132 | 133 | /* Define stream read functions for big endian systems. */ 134 | #ifdef BE_SYSTEM 135 | /* 136 | * These functions can read from the stream safely! 137 | * Swap endianity of input to little endian. 138 | */ 139 | _INLINE_ int16_t RSHORT(const uint8_t *s) 140 | { 141 | return s[0] | (s[1] << 8); 142 | } 143 | _INLINE_ uint16_t RUSHORT(const uint8_t *s) 144 | { 145 | return s[0] | (s[1] << 8); 146 | } 147 | _INLINE_ int32_t RLONG(const uint8_t *s) 148 | { 149 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 150 | } 151 | _INLINE_ uint32_t RULONG(const uint8_t *s) 152 | { 153 | return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); 154 | } 155 | #else 156 | /* Little endian macro's will just make the cast. */ 157 | #define RSHORT(x) *(int16_t *)x 158 | #define RUSHORT(x) *(uint16_t *)x 159 | #define RLONG(x) *(int32_t *)x 160 | #define RULONG(x) *(uint32_t *)x 161 | #endif 162 | 163 | #endif /* CONFIG_H */ 164 | -------------------------------------------------------------------------------- /distorm/distorm64/ddkproj/README: -------------------------------------------------------------------------------- 1 | diStorm64 for Ring 0 2 | Gil Dabah Jan 2007 3 | http://ragestorm.net/distorm/ 4 | 5 | Tested sample with DDK 3790.1830 using WinXPSP2. 6 | 7 | Steps of how to build the diStorm64 sample using the DDK. 8 | 9 | Warning - Make sure the path you extracted diStorm to does not include any spaces, otherwise you will get an error from the build. 10 | 11 | 1) Open the DDK's build environment, for example: "Win XP Free Build Environment", 12 | which readies the evnrionment variables for building a driver. 13 | 14 | 2) Launch "build". 15 | 16 | 3) If everything worked smoothly, you should see a new file named "distorm.sys" under objfre_wxp_x86\i386 17 | (that's if you use WinXP and the Free Environment). 18 | 19 | - If you experienced any errors, try moving the whole distorm directory to c:\winddk\src\ 20 | (or any other directory tree which doesn't contain spaces in its name). 21 | 22 | 4) Now you will have to register the new driver: 23 | a. Copy the distorm.sys file to \windows\system32\drivers\. 24 | b. Use the DDK's regini.exe with the supplied distorm.ini. 25 | c. Restart Windows for the effect to take place. :( 26 | (this can be bypassed, if you register the driver directly in the SCM, there are other tools which do so). 27 | 28 | 5) Now open your favorite debug-strings monitor (mine is DebugView). 29 | Make sure you monitor kernel debug-strings. 30 | 31 | 6) Launching "net start distorm" from command line, will run the DriverEntry code in "main.c", 32 | which will disassemble a few instructions from the KeBugcheck routine and dump it using DbgPrint. 33 | 34 | 7) Later launch "net stop distorm" from command line to stop the test driver. 35 | 36 | 37 | NOTES: 38 | -+---- 39 | The sample uses the stack for storing the results from the decode function. 40 | If you have too many structures on the stack, you better allocate memory before calling the decode function, 41 | and later on free that memory. Don't use the NONPAGED pool if you don't really need it. 42 | 43 | _OffsetType is the type of the DecodedInstruction.Offset field, which defaults to 64bits, 44 | so make sure that when you print this variable you use %I64X, or when you use it anywhere else, you use the _OffsetType as well. 45 | If you want to change the _OffsetType into 32 bits, edit the "disconfig.h" file. 46 | 47 | diStorm can be really compiled for all IRQL, it doesn't use any resource or the standard C library at all. 48 | Although the sample uses diStorm at PASSIVE level. 49 | -------------------------------------------------------------------------------- /distorm/distorm64/ddkproj/distorm.ini: -------------------------------------------------------------------------------- 1 | \registry\machine\system\currentcontrolset\services\distorm 2 | ImagePath = system32\drivers\distorm.sys 3 | DisplayName = "distorm" 4 | Type = REG_DWORD 0x1 5 | Start = REG_DWORD 0x3 6 | Group = Extended base 7 | ErrorControl = REG_DWORD 0x1 8 | \registry\machine\system\currentcontrolset\services\distorm\Parameters 9 | BreakOnEntry = REG_DWORD 0x0 10 | DebugMask = REG_DWORD 0x0 11 | LogEvents = REG_DWORD 0x0 -------------------------------------------------------------------------------- /distorm/distorm64/ddkproj/dummy.c: -------------------------------------------------------------------------------- 1 | // Since the DDK's nmake is limited with directories, we will bypass that with this simple hack. 2 | // Thanks to Razvan Hobeanu. 3 | // Sep 2009. 4 | 5 | #include "x86defs.c" 6 | #include "wstring.c" 7 | #include "textdefs.c" 8 | #include "prefix.c" 9 | #include "operands.c" 10 | #include "insts.c" 11 | #include "instructions.c" 12 | #include "distorm.c" 13 | #include "decoder.c" 14 | -------------------------------------------------------------------------------- /distorm/distorm64/ddkproj/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * main.c 3 | * Sample kernel driver to show how diStorm can be easily compiled and used in Ring 0. 4 | * 5 | * /// Follow the README file in order to compile diStorm using the DDK. \\\ 6 | * 7 | * Izik, Gil Dabah 8 | * Jan 2007 9 | * http://ragestorm.net/distorm/ 10 | */ 11 | 12 | #include 13 | #include "../distorm.h" 14 | 15 | // The number of the array of instructions the decoder function will use to return the disassembled instructions. 16 | // Play with this value for performance... 17 | #define MAX_INSTRUCTIONS (15) 18 | 19 | void DriverUnload(IN PDRIVER_OBJECT DriverObject) 20 | { 21 | } 22 | 23 | NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) 24 | { 25 | UNICODE_STRING pFcnName; 26 | 27 | // Holds the result of the decoding. 28 | _DecodeResult res; 29 | // Decoded instruction information. 30 | _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; 31 | // next is used for instruction's offset synchronization. 32 | // decodedInstructionsCount holds the count of filled instructions' array by the decoder. 33 | unsigned int decodedInstructionsCount = 0, i, next; 34 | // Default decoding mode is 32 bits, could be set by command line. 35 | _DecodeType dt = Decode32Bits; 36 | 37 | // Default offset for buffer is 0, could be set in command line. 38 | _OffsetType offset = 0; 39 | char* errch = NULL; 40 | 41 | // Buffer to disassemble. 42 | unsigned char *buf; 43 | int len = 100; 44 | 45 | // Register unload routine 46 | DriverObject->DriverUnload = DriverUnload; 47 | 48 | DbgPrint("diStorm Loaded!\n"); 49 | 50 | // Get address of KeBugCheck 51 | RtlInitUnicodeString(&pFcnName, L"KeBugCheck"); 52 | buf = (char *)MmGetSystemRoutineAddress(&pFcnName); 53 | offset = (unsigned) (_OffsetType)buf; 54 | 55 | DbgPrint("Resolving KeBugCheck @ 0x%08x\n", buf); 56 | // Decode the buffer at given offset (virtual address). 57 | 58 | while (1) { 59 | res = distorm_decode(offset, (const unsigned char*)buf, len, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); 60 | if (res == DECRES_INPUTERR) { 61 | DbgPrint(("NULL Buffer?!\n")); 62 | break; 63 | } 64 | 65 | for (i = 0; i < decodedInstructionsCount; i++) { 66 | // Note that we print the offset as a 64 bits variable!!! 67 | // It might be that you'll have to change it to %08X... 68 | DbgPrint("%08I64x (%02d) %s %s %s\n", decodedInstructions[i].offset, decodedInstructions[i].size, 69 | (char*)decodedInstructions[i].instructionHex.p, 70 | (char*)decodedInstructions[i].mnemonic.p, 71 | (char*)decodedInstructions[i].operands.p); 72 | } 73 | 74 | if (res == DECRES_SUCCESS || decodedInstructionsCount == 0) { 75 | break; // All instructions were decoded. 76 | } 77 | 78 | // Synchronize: 79 | next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset); 80 | next += decodedInstructions[decodedInstructionsCount-1].size; 81 | 82 | // Advance ptr and recalc offset. 83 | buf += next; 84 | len -= next; 85 | offset += next; 86 | } 87 | 88 | DbgPrint(("Done!\n")); 89 | return STATUS_SUCCESS; 90 | } 91 | -------------------------------------------------------------------------------- /distorm/distorm64/ddkproj/makefile: -------------------------------------------------------------------------------- 1 | !INCLUDE $(NTMAKEENV)\makefile.def -------------------------------------------------------------------------------- /distorm/distorm64/ddkproj/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME = distorm 2 | TARGETPATH = obj 3 | TARGETTYPE = DRIVER 4 | 5 | C_DEFINES = $(C_DEFINES) -DSUPPORT_64BIT_OFFSET 6 | 7 | INCLUDES = %BUILD%\inc;..\src; 8 | LIBS = %BUILD%\lib 9 | 10 | SOURCES = main.c dummy.c 11 | -------------------------------------------------------------------------------- /distorm/distorm64/doc/vol1.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtcasl/qsim/b1e33516426663f277a5da5b56b2b59d28fa5099/distorm/distorm64/doc/vol1.html -------------------------------------------------------------------------------- /distorm/distorm64/linuxproj/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # diStorm (Linux Port) / Demo Application Makefile 3 | # 4 | 5 | TARGET = disasm 6 | CC = gcc 7 | CFLAGS = -Wall -O2 -I. -o 8 | 9 | all: disasm 10 | 11 | disasm: 12 | ${CC} ${CFLAGS} ${TARGET} main.c ../distorm64.a 13 | 14 | clean: 15 | /bin/rm -rf *.o ${TARGET} 16 | -------------------------------------------------------------------------------- /distorm/distorm64/python/README: -------------------------------------------------------------------------------- 1 | This is a sample code of how to use diStorm as a dynamic library using Python's ctypes module. 2 | 3 | Compile diStorm as a DLL under Windows or as a Shared Object under *nix. 4 | Make sure the output file can be found by Python. 5 | 6 | --------- 7 | from pydistorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits 8 | for i in Decode(0x100, open("file.com", "rb").read(), Decode16Bits): 9 | print "0x%08x (%02x) %-20s %s" % (i.offset, i.size, i.instructionHex, str(i.mnemonic) + " " + str(i.operands)) 10 | 11 | Victor Stinner, Gil Dabah 12 | May 2008 13 | -------------------------------------------------------------------------------- /distorm/distorm64/python/pydistorm.py: -------------------------------------------------------------------------------- 1 | """ 2 | :[diStorm64 1.7.29}: 3 | Copyright RageStorm (C) 2007, Gil Dabah 4 | 5 | diStorm is licensed under the BSD license. 6 | http://ragestorm.net/distorm/ 7 | --- 8 | Python binding for diStorm64 written by Victor Stinner 9 | """ 10 | 11 | import platform 12 | from ctypes import cdll, c_long, c_ulong, c_int, c_uint, c_char, c_char_p, POINTER, c_byte, Structure, addressof, byref, c_void_p, create_string_buffer, sizeof, cast 13 | 14 | # Define (u)int32_t and (u)int64_t types 15 | int32_t = c_int 16 | uint32_t = c_uint 17 | if sizeof(c_ulong) == 8: 18 | int64_t = c_long 19 | uint64_t = c_ulong 20 | else: 21 | from ctypes import c_longlong, c_ulonglong 22 | assert sizeof(c_longlong) == 8 23 | assert sizeof(c_ulonglong) == 8 24 | int64_t = c_longlong 25 | uint64_t = c_ulonglong 26 | 27 | SUPPORT_64BIT_OFFSET = True 28 | if SUPPORT_64BIT_OFFSET: 29 | _OffsetType = uint64_t 30 | else: 31 | _OffsetType = uint32_t 32 | 33 | osVer = platform.system() 34 | if osVer == "Windows": 35 | LIB_FILENAME = "distorm64.dll" 36 | else: 37 | LIB_FILENAME = 'libdistorm64.so' 38 | 39 | distorm = cdll.LoadLibrary(LIB_FILENAME) 40 | Decode16Bits = 0 41 | Decode32Bits = 1 42 | Decode64Bits = 2 43 | DECODERS = (Decode16Bits, Decode32Bits, Decode64Bits) 44 | 45 | if osVer == "Windows": 46 | if SUPPORT_64BIT_OFFSET: 47 | decode_func = distorm.distorm_decode64 48 | else: 49 | decode_func = distorm.distorm_decode32 50 | else: 51 | decode_func = distorm.internal_decode 52 | 53 | DECRES_NONE = 0 54 | DECRES_SUCCESS = 1 55 | DECRES_MEMORYERR = 2 56 | DECRES_INPUTERR = 3 57 | 58 | MAX_INSTRUCTIONS = 100 59 | MAX_TEXT_SIZE = 60 60 | 61 | class _WString(Structure): 62 | _fields_ = ( 63 | ("pos", c_uint), # Unused. 64 | ("p", c_char * MAX_TEXT_SIZE), 65 | ) 66 | def __str__(self): 67 | return self.p 68 | 69 | class _DecodedInst(Structure): 70 | _fields_ = ( 71 | ("mnemonic", _WString), 72 | ("operands", _WString), 73 | ("instructionHex", _WString), 74 | ("size", c_uint), 75 | ("offset", _OffsetType), 76 | ) 77 | def __str__(self): 78 | return "%s %s" % (self.mnemonic, self.operands) 79 | 80 | decode_func.argtypes = (_OffsetType, c_void_p, c_int, c_int, c_void_p, c_uint, POINTER(c_uint)) 81 | 82 | def Decode(codeOffset, code, dt=Decode32Bits): 83 | """ 84 | Errors: TypeError, IndexError, MemoryError, ValueError 85 | """ 86 | # Check arguments 87 | if not isinstance(codeOffset, (int, long)): 88 | raise TypeError("codeOffset have to be an integer") 89 | if not isinstance(code, str): 90 | raise TypeError("code have to be a string") 91 | if dt not in DECODERS: 92 | raise IndexError("Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits.") 93 | 94 | # Allocate memory for decoder 95 | code_buffer = create_string_buffer(code) 96 | decodedInstructionsCount = c_uint() 97 | result = create_string_buffer(sizeof(_DecodedInst)*MAX_INSTRUCTIONS) 98 | 99 | # Prepare arguments 100 | codeLen = len(code) 101 | code = addressof(code_buffer) 102 | while codeLen: 103 | # Call internal decoder 104 | res = decode_func(codeOffset, code, codeLen, dt, result, MAX_INSTRUCTIONS, byref(decodedInstructionsCount)) 105 | 106 | # Check for errors 107 | if res == DECRES_INPUTERR: 108 | raise ValueError("Invalid argument") 109 | count = decodedInstructionsCount.value 110 | if res == DECRES_MEMORYERR and not count: 111 | raise MemoryError() 112 | 113 | # No more instruction 114 | if not count: 115 | break 116 | 117 | # Yield instruction and compute decoded size 118 | size = 0 119 | instr_array = cast(result, POINTER(_DecodedInst)) 120 | for index in xrange(count): 121 | instr = instr_array[index] 122 | size += instr.size 123 | yield instr 124 | 125 | # Update parameters to move to next instructions 126 | code += size 127 | codeOffset += size 128 | codeLen -= size 129 | 130 | -------------------------------------------------------------------------------- /distorm/distorm64/src/decoder.h: -------------------------------------------------------------------------------- 1 | /* 2 | decoder.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef DECODER_H 10 | #define DECODER_H 11 | 12 | #include "../config.h" 13 | 14 | #include "wstring.h" 15 | 16 | typedef unsigned int _iflags; 17 | 18 | /* DEFAULT instructions decoding mode. */ 19 | typedef enum {Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2} _DecodeType; 20 | 21 | typedef OFFSET_INTEGER _OffsetType; 22 | 23 | typedef struct { 24 | _WString mnemonic; 25 | _WString operands; 26 | _WString instructionHex; 27 | unsigned int size; 28 | _OffsetType offset; 29 | } _DecodedInst; 30 | 31 | typedef struct { 32 | const uint8_t* code; 33 | int codeLen; 34 | _OffsetType codeOffset; 35 | } _CodeInfo; 36 | 37 | typedef enum {DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR} _DecodeResult; 38 | _DecodeResult internal_decode(_OffsetType codeOffset, const uint8_t* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxResultCount, unsigned int* usedEntriesCount); 39 | 40 | _DecodeType ADDR_SIZE_AFFECT(_DecodeType dt, _iflags totalPrefixes); 41 | _DecodeType OP_SIZE_AFFECT(_DecodeType dt, _iflags totalPrefixes, unsigned int rex, _iflags instFlags); 42 | 43 | #endif /* DECODER_H */ 44 | -------------------------------------------------------------------------------- /distorm/distorm64/src/distorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | distorm.c 3 | 4 | :[diStorm64}: C Library Interface 5 | The ultimate disassembler library (80x86, AMD64) 6 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 7 | This library is licensed under the BSD license. See the file COPYING. 8 | */ 9 | 10 | #include "../config.h" 11 | #include "decoder.h" 12 | #include "x86defs.h" 13 | 14 | /* C LIBRARY EXPORTS */ 15 | #ifdef SUPPORT_64BIT_OFFSET 16 | _DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 17 | #else 18 | _DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) 19 | #endif 20 | { 21 | *usedInstructionsCount = 0; 22 | 23 | /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ 24 | if (codeLen < 0) { 25 | return DECRES_INPUTERR; 26 | } 27 | 28 | if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) { 29 | return DECRES_INPUTERR; 30 | } 31 | 32 | if (code == NULL || result == NULL) { 33 | return DECRES_INPUTERR; 34 | } 35 | 36 | /* Assume length=0 is success. */ 37 | if (codeLen == 0) { 38 | return DECRES_SUCCESS; 39 | } 40 | 41 | /* We need to supply at least 15 entries so the internal_decoder could return anything possible. */ 42 | if (maxInstructions < INST_MAXIMUM_SIZE) { 43 | return DECRES_MEMORYERR; 44 | } 45 | 46 | return internal_decode(codeOffset, code, codeLen, dt, result, maxInstructions, usedInstructionsCount); 47 | } 48 | 49 | _DLLEXPORT_ unsigned int distorm_version() 50 | { 51 | return DISTORM_VER; 52 | } 53 | -------------------------------------------------------------------------------- /distorm/distorm64/src/insts.h: -------------------------------------------------------------------------------- 1 | /* 2 | insts.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef INSTS_H 10 | #define INSTS_H 11 | 12 | #include "instructions.h" 13 | 14 | /* Root Trie DB */ 15 | extern _InstNode Instructions; 16 | /* 3DNow! Trie DB */ 17 | extern _InstNode Table_0F_0F; 18 | /* NOP/XCHG instruction. */ 19 | extern _InstInfo II_90; 20 | /* LEA instruction. */ 21 | extern _InstInfo II_8D; 22 | 23 | /* See instructions.cpp for more info. */ 24 | 25 | #endif /* INSTS_H */ 26 | -------------------------------------------------------------------------------- /distorm/distorm64/src/operands.h: -------------------------------------------------------------------------------- 1 | /* 2 | operands.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef OPERANDS_H 10 | #define OPERANDS_H 11 | 12 | #include "../config.h" 13 | 14 | #include "decoder.h" 15 | #include "prefix.h" 16 | #include "wstring.h" 17 | #include "instructions.h" 18 | 19 | /* Return codes from extract_operand. */ 20 | typedef enum {EO_HALT, EO_CONTINUE, EO_SUFFIX} _ExOpRCType; 21 | 22 | _ExOpRCType extract_operand(_CodeInfo* ci, 23 | _WString* instructionHex, _WString* operandText, _OpType type, _OpType op2, 24 | _OperandNumberType opNum, _iflags instFlags, unsigned int modrm, 25 | _PrefixState* ps, _DecodeType dt, int* lockableInstruction); 26 | 27 | #endif /* OPERANDS_H */ 28 | -------------------------------------------------------------------------------- /distorm/distorm64/src/prefix.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtcasl/qsim/b1e33516426663f277a5da5b56b2b59d28fa5099/distorm/distorm64/src/prefix.c -------------------------------------------------------------------------------- /distorm/distorm64/src/prefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | prefix.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef PREFIX_H 10 | #define PREFIX_H 11 | 12 | #include "../config.h" 13 | 14 | #include "decoder.h" 15 | #include "wstring.h" 16 | 17 | /* 18 | * This holds the prefixes state for the current instruction we decode. 19 | * totalPrefixes includes all specific prefixes that the instruction got. 20 | * start is a pointer to the first prefix to take into account. 21 | * last is a pointer to the last byte we scanned. 22 | * Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. 23 | */ 24 | typedef struct { 25 | unsigned int unusedCount, specialPrefixesSize, isREXPrefixValid; 26 | _iflags totalPrefixes, usedPrefixes; 27 | const uint8_t *lokrepPos, *segovrdPos, *opsizePos, *addrsizePos, *rexpos, *start, *last; 28 | } _PrefixState; 29 | 30 | /* Describe the type of the prefix and which one it was in a flag manner. */ 31 | typedef enum {PRE_NONE = -1, PRE_LOKREP, PRE_SEGOVRD, PRE_OPSIZE, PRE_ADDRSIZE, PRE_REX} _PrefixType; 32 | 33 | typedef struct { 34 | _iflags flag; 35 | _PrefixType type; 36 | } _PrefixInfo; 37 | 38 | /* 39 | * Intel supports 4 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). 40 | * REX is the fifth prefix type, this time I'm based on AMD64. 41 | */ 42 | #define MAX_PREFIXES (5) 43 | 44 | int is_prefix(unsigned int ch, _DecodeType dt); 45 | void decode_prefixes(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt); 46 | void get_unused_prefixes_list(uint8_t unusedList[MAX_PREFIXES], _PrefixState* ps); 47 | 48 | void str_seg_text(_WString* s, _PrefixState* ps, _DecodeType dt); 49 | 50 | #endif /* PREFIX_H */ 51 | -------------------------------------------------------------------------------- /distorm/distorm64/src/pydistorm.h: -------------------------------------------------------------------------------- 1 | /* 2 | pydistorm.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef PYDISTORM_H 10 | #define PYDISTORM_H 11 | 12 | #ifdef SUPPORT_64BIT_OFFSET 13 | /* 14 | * PyArg_ParseTuple/Py_BuildValue uses a format string in order to parse/build the offset. 15 | * type: int 64 16 | */ 17 | #define _PY_OFF_INT_SIZE_ "K" 18 | #else 19 | #define _PY_OFF_INT_SIZE_ "k" 20 | #endif 21 | 22 | #include "decoder.h" 23 | 24 | #ifdef __GNUC__ 25 | #include 26 | #elif _MSC_VER 27 | #include 28 | #endif 29 | 30 | PyObject* distorm_Decode(PyObject* pSelf, PyObject* pArgs); 31 | 32 | char distorm_Decode_DOCSTR[] = 33 | "Disassemble a given buffer.\r\n" 34 | #ifdef SUPPORT_64BIT_OFFSET 35 | "Decode(INT64 offset, string code, int type)\r\n" 36 | #else 37 | "Decode(unsigned long offset, string code, int type)\r\n" 38 | #endif 39 | "type:\r\n" 40 | " Decode16Bits - 16 bits decoding.\r\n" 41 | " Decode32Bits - 32 bits decoding.\r\n" 42 | " Decode64Bits - AMD64 decoding.\r\n" 43 | "Returns a list of tuples of offset, size, mnemonic and hex string.\r\n"; 44 | 45 | static PyMethodDef distormModulebMethods[] = { 46 | {"Decode", distorm_Decode, METH_VARARGS, distorm_Decode_DOCSTR}, 47 | {NULL, NULL, 0, NULL} 48 | }; 49 | 50 | #endif /* PYDISTORM_H */ 51 | 52 | -------------------------------------------------------------------------------- /distorm/distorm64/src/textdefs.h: -------------------------------------------------------------------------------- 1 | /* 2 | textdefs.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef TEXTDEFS_H 10 | #define TEXTDEFS_H 11 | 12 | #include "../config.h" 13 | 14 | #include "wstring.h" 15 | 16 | #define PLUS_DISP_CHR '+' 17 | #define MINUS_DISP_CHR '-' 18 | /* CHR0 is used for FPU, ST(i) register */ 19 | #define OPEN_CHR0 '(' 20 | #define CLOSE_CHR0 ')' 21 | #define OPEN_CHR '[' 22 | #define CLOSE_CHR ']' 23 | extern int8_t SEP_STR[3]; 24 | #define SEP_CHR ',' 25 | #define SP_CHR ' ' 26 | #define SEG_OFF_CHR ':' 27 | 28 | /* 29 | Naming Convention: 30 | 31 | * get - returns a pointer to a string. 32 | * str - concatenates to string. 33 | 34 | * hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. 35 | * code - means the function is used for disassembled instruction - Big Endian output. 36 | * off - means the function is used for 64bit offset - Big Endian output. 37 | 38 | * sp - space character in front of the string. 39 | * h - '0x' in front of the string. 40 | 41 | * b - byte 42 | * w - word 43 | * dw - double word 44 | * qw - quad word 45 | 46 | * all numbers are in HEX. 47 | */ 48 | 49 | extern int8_t TextBTable[256][4]; 50 | 51 | _INLINE_ int8_t* get_hex_b(unsigned int x) 52 | { 53 | return &TextBTable[x & 255][1]; /* Skip space character. */ 54 | } 55 | 56 | void _FASTCALL_ str_hex_b(_WString* s, unsigned int x); 57 | void _FASTCALL_ str_code_hb(_WString* s, unsigned int x); 58 | 59 | void _FASTCALL_ str_hex_sp_b(_WString* s, unsigned int x); 60 | void _FASTCALL_ str_code_sp_hb(_WString* s, unsigned int x); 61 | 62 | void _FASTCALL_ str_hex_sp_w(_WString* s, unsigned int x); 63 | void _FASTCALL_ str_code_hw(_WString* s, unsigned int x); 64 | 65 | void _FASTCALL_ str_hex_sp_dw(_WString* s, uint32_t x); 66 | void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x); 67 | 68 | void _FASTCALL_ str_hex_sp_qw(_WString* s, uint8_t src[8]); 69 | void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]); 70 | 71 | #ifdef SUPPORT_64BIT_OFFSET 72 | void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x); 73 | #endif 74 | 75 | #endif /* TEXTDEFS_H */ 76 | -------------------------------------------------------------------------------- /distorm/distorm64/src/wstring.c: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.c 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #include "wstring.h" 10 | 11 | void _FASTCALL_ strcpy_WS(_WString* s, const int8_t* buf) 12 | { 13 | s->pos = (unsigned int)strlen((const char*)buf); 14 | memcpy((int8_t*)s->p, buf, s->pos + 1); 15 | } 16 | 17 | void _FASTCALL_ strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len) 18 | { 19 | s->pos = len; 20 | memcpy((int8_t*)s->p, buf, len + 1); 21 | } 22 | 23 | void _FASTCALL_ strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len) 24 | { 25 | memcpy((int8_t*)&s->p[s->pos], buf, len + 1); 26 | s->pos += len; 27 | } 28 | -------------------------------------------------------------------------------- /distorm/distorm64/src/wstring.h: -------------------------------------------------------------------------------- 1 | /* 2 | wstring.h 3 | 4 | Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ 5 | This library is licensed under the BSD license. See the file COPYING. 6 | */ 7 | 8 | 9 | #ifndef WSTRING_H 10 | #define WSTRING_H 11 | 12 | #include "../config.h" 13 | 14 | /* Make sure the buffer isn't overflowed. */ 15 | #define MAX_TEXT_SIZE (60) 16 | 17 | typedef struct { 18 | unsigned int pos; 19 | int8_t p[MAX_TEXT_SIZE]; 20 | } _WString; 21 | 22 | /* 23 | * Warning, this macro should be used only when the compiler knows the size of string in advance! 24 | * This macro is used in order to spare the call to strlen when the strings are known already. 25 | * Note: sizeof includes NULL terminated character. 26 | */ 27 | #define strcat_WSN(s, t) strcatlen_WS((s), (t), sizeof((t))-1) 28 | #define strcpy_WSN(s, t) strcpylen_WS((s), (t), sizeof((t))-1) 29 | 30 | void _FASTCALL_ strcpy_WS(_WString* s, const int8_t* buf); 31 | void _FASTCALL_ strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len); 32 | void _FASTCALL_ strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len); 33 | 34 | _INLINE_ void strclear_WS(_WString* s) 35 | { 36 | s->p[0] = '\0'; 37 | s->pos = 0; 38 | } 39 | 40 | _INLINE_ void chrcat_WS(_WString* s, uint8_t ch) 41 | { 42 | s->p[s->pos] = ch; 43 | s->p[s->pos + 1] = '\0'; 44 | s->pos += 1; 45 | } 46 | 47 | 48 | #endif /* WSTRING_H */ 49 | -------------------------------------------------------------------------------- /distorm/distorm64/win32proj/disasm.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 9.00 2 | # Visual Studio 2005 3 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "disasm", "disasm.vcproj", "{91227BA8-F7EB-43CC-8C4A-A4944C00567B}" 4 | EndProject 5 | Global 6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 7 | Debug|Win32 = Debug|Win32 8 | Release|Win32 = Release|Win32 9 | EndGlobalSection 10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 11 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|Win32.ActiveCfg = Debug|Win32 12 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|Win32.Build.0 = Debug|Win32 13 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|Win32.ActiveCfg = Release|Win32 14 | {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|Win32.Build.0 = Release|Win32 15 | EndGlobalSection 16 | GlobalSection(SolutionProperties) = preSolution 17 | HideSolutionNode = FALSE 18 | EndGlobalSection 19 | EndGlobal 20 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | user_guide.pdf: user_guide.tex qemu_diagram.pdf mod_qemu.pdf qsim_diagram.pdf \ 2 | translation.pdf simple_example.pdf fast_forwarder.pdf \ 3 | ../VERSION ../examples/x86/simple.cpp 4 | sed s/%%%VERSION%%%/`cat ../VERSION`/ user_guide.tex > \ 5 | user_guide.tmp.tex 6 | nl ../examples/x86/simple.cpp > simple.cpp.num 7 | pdflatex user_guide.tmp.tex 8 | pdflatex user_guide.tmp.tex 9 | mv user_guide.tmp.pdf user_guide.pdf 10 | rm user_guide.tmp.tex 11 | rm simple.cpp.num 12 | 13 | %.pdf : %.fig 14 | fig2mpdf $< 15 | 16 | clean: 17 | rm -f *.pdf *.aux *.log *.toc *~ *\# 18 | -------------------------------------------------------------------------------- /doc/atomics.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5b 2 | Landscape 3 | Center 4 | Inches 5 | A4 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 6 5175 1875 7125 2325 11 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 12 | 5175 1875 7125 1875 7125 2325 5175 2325 5175 1875 13 | 4 1 0 50 -1 16 12 0.0000 4 165 1770 6150 2175 Shared RAM State\001 14 | -6 15 | 6 900 1875 2850 2325 16 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 17 | 900 1875 2850 1875 2850 2325 900 2325 900 1875 18 | 4 1 0 50 -1 16 12 0.0000 4 165 1770 1875 2175 Shared RAM State\001 19 | -6 20 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 21 | 0 0 1.00 60.00 120.00 22 | 0 0 1.00 60.00 120.00 23 | 6675 750 6450 1875 24 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 25 | 0 0 1.00 60.00 120.00 26 | 0 0 1.00 60.00 120.00 27 | 225 1425 900 2025 28 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 29 | 0 0 1.00 60.00 120.00 30 | 0 0 1.00 60.00 120.00 31 | 975 750 1275 1875 32 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 33 | 0 0 1.00 60.00 120.00 34 | 0 0 1.00 60.00 120.00 35 | 1725 750 1725 1875 36 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 37 | 0 0 1.00 60.00 120.00 38 | 0 0 1.00 60.00 120.00 39 | 2400 750 2175 1875 40 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 41 | 0 0 1.00 60.00 120.00 42 | 0 0 1.00 60.00 120.00 43 | 3225 900 2550 1875 44 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 45 | 5925 75 5850 150 5925 225 5850 300 5925 375 5850 450 46 | 5925 525 5850 600 5925 675 47 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 48 | 0.000 49 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 50 | 6675 0 6600 75 6675 150 6600 225 6675 300 6600 375 51 | 6675 450 6600 525 6675 600 52 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 53 | 0.000 54 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 55 | 7575 225 7500 300 7575 375 7500 450 7575 525 7500 600 56 | 7575 675 7500 750 7575 825 57 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 58 | 0.000 59 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 60 | 5100 450 5025 525 5100 600 5025 675 5100 750 5025 825 61 | 5100 900 5025 975 5100 1050 62 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 63 | 0.000 64 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 65 | 4350 1050 4275 1125 4350 1200 4275 1275 4350 1350 4275 1425 66 | 4350 1500 4275 1575 4350 1650 67 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 68 | 0.000 69 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 70 | 1650 75 1575 150 1650 225 1575 300 1650 375 1575 450 71 | 1650 525 1575 600 1650 675 72 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 73 | 0.000 74 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 75 | 2400 0 2325 75 2400 150 2325 225 2400 300 2325 375 76 | 2400 450 2325 525 2400 600 77 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 78 | 0.000 79 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 80 | 3300 225 3225 300 3300 375 3225 450 3300 525 3225 600 81 | 3300 675 3225 750 3300 825 82 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 83 | 0.000 84 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 85 | 825 450 750 525 825 600 750 675 825 750 750 825 86 | 825 900 750 975 825 1050 87 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 88 | 0.000 89 | 3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 9 90 | 75 1050 0 1125 75 1200 0 1275 75 1350 0 1425 91 | 75 1500 0 1575 75 1650 92 | 0.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 93 | 0.000 94 | 4 1 0 50 -1 18 12 0.0000 4 165 840 6225 2625 Atomics\001 95 | 4 1 0 50 -1 18 12 0.0000 4 210 2385 1950 2625 Ordinary Reads/Writes\001 96 | -------------------------------------------------------------------------------- /doc/fast_forwarder.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5b 2 | Landscape 3 | Center 4 | Metric 5 | A4 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 6 4005 1395 4905 2475 11 | 5 1 0 1 0 7 50 -1 -1 0.000 0 1 0 0 4455.000 1912.500 4185 2115 4455 2250 4725 2115 12 | 1 1 0 1 0 7 50 -1 -1 0.000 1 0.0000 4455 1530 270 135 4455 1530 4725 1665 13 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 14 | 4185 2115 4185 1530 15 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 16 | 4725 1530 4725 2115 17 | 4 1 0 50 -1 16 12 0.0000 4 165 885 4455 2475 State File\001 18 | -6 19 | 6 5850 855 6930 1485 20 | 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 21 | 6930 1485 6930 855 5850 855 5850 1485 6930 1485 22 | 4 1 0 50 -1 16 12 0.0000 4 165 960 6390 1170 Simulation\001 23 | 4 1 0 50 -1 16 12 0.0000 4 165 120 6390 1425 1\001 24 | -6 25 | 6 2025 1530 3105 2160 26 | 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 27 | 3105 2160 3105 1530 2025 1530 2025 2160 3105 2160 28 | 4 1 0 50 -1 16 12 0.0000 4 165 405 2565 1800 Fast\001 29 | 4 1 0 50 -1 16 12 0.0000 4 165 780 2565 2070 Forward\001 30 | -6 31 | 6 5850 1575 6930 2205 32 | 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 33 | 6930 2205 6930 1575 5850 1575 5850 2205 6930 2205 34 | 4 1 0 50 -1 16 12 0.0000 4 165 960 6390 1890 Simulation\001 35 | 4 1 0 50 -1 16 12 0.0000 4 165 120 6390 2145 2\001 36 | -6 37 | 6 5850 2295 6930 2925 38 | 2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5 39 | 6930 2925 6930 2295 5850 2295 5850 2925 6930 2925 40 | 4 1 0 50 -1 16 12 0.0000 4 165 960 6390 2610 Simulation\001 41 | 4 1 0 50 -1 16 12 0.0000 4 165 120 6390 2865 3\001 42 | -6 43 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 44 | 0 0 1.00 60.00 120.00 45 | 3105 1800 4185 1800 46 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 47 | 0 0 1.00 60.00 120.00 48 | 4725 1710 5850 1170 49 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 50 | 0 0 1.00 60.00 120.00 51 | 4725 1845 5850 1845 52 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 53 | 0 0 1.00 60.00 120.00 54 | 4725 1980 5850 2565 55 | 4 1 0 50 -1 18 12 0.0000 4 30 300 6390 3195 . . .\001 56 | -------------------------------------------------------------------------------- /doc/mod_qemu.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5b 2 | Landscape 3 | Center 4 | Inches 5 | Letter 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 6 3075 975 4275 1650 11 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 12 | 3075 1650 4275 1650 4275 975 3075 975 3075 1650 13 | 4 1 0 50 -1 16 12 0.0000 4 210 570 3750 1500 Mgmt.\001 14 | 4 1 0 50 -1 16 12 0.0000 4 165 735 3750 1275 Context\001 15 | -6 16 | 6 75 0 1275 525 17 | 4 1 0 50 -1 16 12 0.0000 4 165 1020 675 480 RAM State\001 18 | 4 1 0 50 -1 16 12 0.0000 4 165 1095 675 225 To External\001 19 | -6 20 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 21 | 0 0 1.00 60.00 120.00 22 | 0 0 1.00 60.00 120.00 23 | 675 2250 675 2025 1950 2025 1950 2250 24 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 25 | 0 0 1.00 60.00 120.00 26 | 0 0 1.00 60.00 120.00 27 | 2400 1650 2400 1875 3675 1875 3675 1650 28 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 29 | 150 2250 1350 2250 1350 3675 150 3675 150 2250 30 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 31 | 3075 2250 4275 2250 4275 3675 3075 3675 3075 2250 32 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 33 | 1950 2325 2250 2325 2250 2475 1950 2475 1950 2325 34 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 35 | 0 0 1.00 60.00 120.00 36 | 0 0 1.00 60.00 120.00 37 | 2400 2250 2400 2025 3675 2025 3675 2250 38 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 39 | 1500 2250 2925 2250 2925 3675 1500 3675 1500 2250 40 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 4 41 | 0 0 1.00 60.00 120.00 42 | 2250 3150 2700 3150 2700 2400 2250 2400 43 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 44 | 0 0 1.00 60.00 120.00 45 | 2025 2475 1800 2700 46 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 47 | 0 0 1.00 60.00 120.00 48 | 2175 2475 2400 2700 49 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 50 | 1650 2700 1950 2700 1950 2850 1650 2850 1650 2700 51 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 52 | 2250 2700 2550 2700 2550 2850 2250 2850 2250 2700 53 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 54 | 0 0 1.00 60.00 120.00 55 | 2400 2850 2175 3075 56 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 57 | 0 0 1.00 60.00 120.00 58 | 1875 2850 2025 3075 59 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 60 | 1950 3075 2250 3075 2250 3225 1950 3225 1950 3075 61 | 2 2 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 62 | 0 825 4425 825 4425 3825 0 3825 0 825 63 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 64 | 1500 1650 2925 1650 2925 975 1500 975 1500 1650 65 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 66 | 0 0 1.00 60.00 120.00 67 | 0 0 1.00 60.00 120.00 68 | 2175 1650 2175 2250 69 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 70 | 0 0 1.00 60.00 120.00 71 | 675 2100 675 600 72 | 4 1 0 50 -1 16 12 0.0000 4 210 795 750 2850 Register\001 73 | 4 1 0 50 -1 16 12 0.0000 4 165 900 3675 3225 Functions\001 74 | 4 1 0 50 -1 16 12 0.0000 4 165 495 750 3225 State\001 75 | 4 1 0 50 -1 16 12 0.0000 4 165 615 2175 3600 Cache\001 76 | 4 1 0 50 -1 16 12 0.0000 4 165 1065 2175 3375 Translation\001 77 | 4 1 0 50 -1 16 12 0.0000 4 165 465 2175 1275 Main\001 78 | 4 1 0 50 -1 16 12 0.0000 4 210 480 2175 1500 Loop\001 79 | 4 1 0 50 -1 16 12 0.0000 4 210 630 3675 2850 Helper\001 80 | -------------------------------------------------------------------------------- /doc/qemu_diagram.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5b 2 | Landscape 3 | Center 4 | Inches 5 | Letter 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 6 0 0 1215 675 11 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 12 | 0 675 1200 675 1200 0 0 0 0 675 13 | 4 1 0 50 -1 16 12 0.0000 4 165 495 600 525 State\001 14 | 4 1 0 50 -1 16 12 0.0000 4 165 465 600 300 RAM\001 15 | -6 16 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 17 | 0 0 1.00 60.00 120.00 18 | 0 0 1.00 60.00 120.00 19 | 525 1275 525 1050 1800 1050 1800 1275 20 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 21 | 0 0 1.00 60.00 120.00 22 | 525 1125 525 675 23 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 24 | 1350 0 2775 0 2775 675 1350 675 1350 0 25 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 26 | 2925 675 4125 675 4125 0 2925 0 2925 675 27 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 28 | 0 0 1.00 60.00 120.00 29 | 0 0 1.00 60.00 120.00 30 | 2025 675 2025 1275 31 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 32 | 0 0 1.00 60.00 120.00 33 | 0 0 1.00 60.00 120.00 34 | 2250 675 2250 900 3525 900 3525 675 35 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 36 | 0 1275 1200 1275 1200 2700 0 2700 0 1275 37 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 38 | 2925 1275 4125 1275 4125 2700 2925 2700 2925 1275 39 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 40 | 1800 1350 2100 1350 2100 1500 1800 1500 1800 1350 41 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 42 | 0 0 1.00 60.00 120.00 43 | 0 0 1.00 60.00 120.00 44 | 2250 1275 2250 1050 3525 1050 3525 1275 45 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 46 | 1350 1275 2775 1275 2775 2700 1350 2700 1350 1275 47 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 4 48 | 0 0 1.00 60.00 120.00 49 | 2100 2175 2550 2175 2550 1425 2100 1425 50 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 51 | 0 0 1.00 60.00 120.00 52 | 1875 1500 1650 1725 53 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 54 | 0 0 1.00 60.00 120.00 55 | 2025 1500 2250 1725 56 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 57 | 1500 1725 1800 1725 1800 1875 1500 1875 1500 1725 58 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 59 | 2100 1725 2400 1725 2400 1875 2100 1875 2100 1725 60 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 61 | 0 0 1.00 60.00 120.00 62 | 2250 1875 2025 2100 63 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 64 | 0 0 1.00 60.00 120.00 65 | 1725 1875 1875 2100 66 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 67 | 1800 2100 2100 2100 2100 2250 1800 2250 1800 2100 68 | 4 1 0 50 -1 16 12 0.0000 4 165 465 2025 300 Main\001 69 | 4 1 0 50 -1 16 12 0.0000 4 210 480 2025 525 Loop\001 70 | 4 1 0 50 -1 16 12 0.0000 4 210 795 600 1875 Register\001 71 | 4 1 0 50 -1 16 12 0.0000 4 165 900 3525 2250 Functions\001 72 | 4 1 0 50 -1 16 12 0.0000 4 165 495 600 2250 State\001 73 | 4 1 0 50 -1 16 12 0.0000 4 165 615 2025 2625 Cache\001 74 | 4 1 0 50 -1 16 12 0.0000 4 165 1065 2025 2400 Translation\001 75 | 4 1 0 50 -1 16 12 0.0000 4 210 510 3600 300 Utility\001 76 | 4 1 0 50 -1 16 12 0.0000 4 165 900 3600 525 Functions\001 77 | 4 1 0 50 -1 16 12 0.0000 4 210 630 3525 1875 Helper\001 78 | -------------------------------------------------------------------------------- /doc/qsim_architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtcasl/qsim/b1e33516426663f277a5da5b56b2b59d28fa5099/doc/qsim_architecture.png -------------------------------------------------------------------------------- /doc/qsim_diagram.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5b 2 | Landscape 3 | Center 4 | Inches 5 | Letter 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 6 2625 675 5850 1125 11 | 2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 12 | 2625 675 5850 675 5850 1125 2625 1125 2625 675 13 | 2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 14 | 4650 675 4650 1125 15 | 4 1 0 50 -1 16 12 0.0000 4 165 900 5250 975 Callbacks\001 16 | 4 1 0 50 -1 16 12 0.0000 4 210 1410 3675 975 Client Program\001 17 | -6 18 | 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 1 2 19 | 0 0 1.00 60.00 120.00 20 | 0 0 1.00 60.00 120.00 21 | 4200 2100 3750 3000 22 | 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 1 2 23 | 0 0 1.00 60.00 120.00 24 | 0 0 1.00 60.00 120.00 25 | 4500 2100 5175 3000 26 | 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 1 2 27 | 0 0 1.00 60.00 120.00 28 | 0 0 1.00 60.00 120.00 29 | 5622 2121 6297 3021 30 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 31 | 0 0 1.00 60.00 120.00 32 | 0 0 1.00 60.00 120.00 33 | 675 4275 675 4050 1950 4050 1950 4275 34 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 35 | 3075 3675 4275 3675 4275 3000 3075 3000 3075 3675 36 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 2 37 | 0 0 1.00 60.00 120.00 38 | 0 0 1.00 60.00 120.00 39 | 2175 3675 2175 4275 40 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 41 | 0 0 1.00 60.00 120.00 42 | 0 0 1.00 60.00 120.00 43 | 2400 3675 2400 3900 3675 3900 3675 3675 44 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 45 | 150 4275 1350 4275 1350 5700 150 5700 150 4275 46 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 47 | 3075 4275 4275 4275 4275 5700 3075 5700 3075 4275 48 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 49 | 1950 4350 2250 4350 2250 4500 1950 4500 1950 4350 50 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 1 4 51 | 0 0 1.00 60.00 120.00 52 | 0 0 1.00 60.00 120.00 53 | 2400 4275 2400 4050 3675 4050 3675 4275 54 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 55 | 1500 4275 2925 4275 2925 5700 1500 5700 1500 4275 56 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 4 57 | 0 0 1.00 60.00 120.00 58 | 2250 5175 2700 5175 2700 4425 2250 4425 59 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 60 | 0 0 1.00 60.00 120.00 61 | 2025 4500 1800 4725 62 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 63 | 0 0 1.00 60.00 120.00 64 | 2175 4500 2400 4725 65 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 66 | 1650 4725 1950 4725 1950 4875 1650 4875 1650 4725 67 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 68 | 2250 4725 2550 4725 2550 4875 2250 4875 2250 4725 69 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 70 | 0 0 1.00 60.00 120.00 71 | 2400 4875 2175 5100 72 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 73 | 0 0 1.00 60.00 120.00 74 | 1875 4875 2025 5100 75 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 76 | 1950 5100 2250 5100 2250 5250 1950 5250 1950 5100 77 | 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 1 2 78 | 0 0 1.00 60.00 120.00 79 | 0 0 1.00 60.00 120.00 80 | 2850 5700 3525 7050 81 | 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 1 2 82 | 0 0 1.00 60.00 120.00 83 | 0 0 1.00 60.00 120.00 84 | 4800 5775 4200 7050 85 | 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 1 2 86 | 0 0 1.00 60.00 120.00 87 | 0 0 1.00 60.00 120.00 88 | 5850 5850 5400 7050 89 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 90 | 150 3000 2925 3000 2925 3675 150 3675 150 3000 91 | 2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 92 | 2625 7050 5850 7050 5850 7500 2625 7500 2625 7050 93 | 2 2 0 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 94 | 2625 1650 5850 1650 5850 2100 2625 2100 2625 1650 95 | 2 1 0 1 0 7 50 -1 -1 3.000 0 0 -1 1 1 2 96 | 0 0 1.00 60.00 120.00 97 | 0 0 1.00 60.00 120.00 98 | 4200 1125 4200 1650 99 | 2 2 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 5 100 | 0 2925 4425 2925 4425 5925 0 5925 0 2925 101 | 3 2 0 1 0 7 50 -1 -1 3.000 0 1 1 3 102 | 0 0 1.00 60.00 120.00 103 | 0 0 1.00 60.00 120.00 104 | 4275 5550 7800 3600 5850 750 105 | 0.000 -1.000 0.000 106 | 3 2 0 1 0 7 50 -1 -1 3.000 0 1 1 3 107 | 0 0 1.00 60.00 120.00 108 | 0 0 1.00 60.00 120.00 109 | 5400 4725 7125 3300 5850 900 110 | 0.000 -1.000 0.000 111 | 3 2 0 1 0 7 50 -1 -1 3.000 0 1 1 3 112 | 0 0 1.00 60.00 120.00 113 | 0 0 1.00 60.00 120.00 114 | 6375 3525 6525 2550 5775 1125 115 | 0.000 -1.000 0.000 116 | 4 1 0 50 -1 16 12 0.0000 4 30 375 4875 4425 . . .\001 117 | 4 1 0 50 -1 16 12 0.0000 4 165 1125 2250 6150 QEMU CPU\001 118 | 4 1 0 50 -1 16 12 0.0000 4 210 570 3750 3525 Mgmt.\001 119 | 4 1 0 50 -1 16 12 0.0000 4 165 735 3750 3300 Context\001 120 | 4 1 0 50 -1 16 12 0.0000 4 210 795 750 4875 Register\001 121 | 4 1 0 50 -1 16 12 0.0000 4 165 900 3675 5250 Functions\001 122 | 4 1 0 50 -1 16 12 0.0000 4 165 495 750 5250 State\001 123 | 4 1 0 50 -1 16 12 0.0000 4 165 615 2175 5625 Cache\001 124 | 4 1 0 50 -1 16 12 0.0000 4 165 1065 2175 5400 Translation\001 125 | 4 1 0 50 -1 16 12 0.0000 4 210 1005 1575 3450 Main Loop\001 126 | 4 1 0 50 -1 16 12 0.0000 4 210 1215 4200 1950 QSim Library\001 127 | 4 1 0 50 -1 16 12 0.0000 4 165 1770 4200 7350 Shared RAM State\001 128 | 4 1 0 50 -1 16 12 0.0000 4 210 630 3675 4875 Helper\001 129 | -------------------------------------------------------------------------------- /doc/translation.fig: -------------------------------------------------------------------------------- 1 | #FIG 3.2 Produced by xfig version 3.2.5b 2 | Landscape 3 | Center 4 | Inches 5 | A4 6 | 100.00 7 | Single 8 | -2 9 | 1200 2 10 | 0 32 #888888 11 | 6 0 1875 1800 2175 12 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 13 | 0 1875 1800 1875 1800 2175 0 2175 0 1875 14 | 4 1 0 50 -1 16 12 0.0000 4 165 1125 900 2100 Guest Block\001 15 | -6 16 | 6 5400 1875 7200 2175 17 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 18 | 5400 1875 7200 1875 7200 2175 5400 2175 5400 1875 19 | 4 1 0 50 -1 16 12 0.0000 4 165 1590 6300 2100 Translated Block\001 20 | -6 21 | 6 2625 1875 4425 2175 22 | 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 23 | 2625 1875 4425 1875 4425 2175 2625 2175 2625 1875 24 | 4 1 0 50 -1 16 12 0.0000 4 210 900 3525 2100 TCG Ops\001 25 | -6 26 | 6 5400 -1050 7650 1725 27 | 4 0 0 50 -1 16 12 0.0000 4 210 2220 5400 -870 mov 0x10(%ebp), %eax\001 28 | 4 0 0 50 -1 16 12 0.0000 4 195 1590 5400 -615 mov %eax, %ecx\001 29 | 4 0 0 50 -1 16 12 0.0000 4 210 1740 5400 -360 mov (%ecx), %eax\001 30 | 4 0 0 50 -1 16 12 0.0000 4 210 2220 5400 -105 mov 0x10(%ebp), %edx\001 31 | 4 0 0 50 -1 16 12 0.0000 4 210 1515 5400 150 add $0x4, %edx\001 32 | 4 0 0 50 -1 16 12 0.0000 4 210 2220 5400 405 mov %edx, 0x10(%ebp)\001 33 | 4 0 0 50 -1 16 12 0.0000 4 210 2220 5400 660 mov %eax, 0x20(%ebp)\001 34 | 4 0 0 50 -1 16 12 0.0000 4 210 1665 5400 915 mov $0x18, %eax\001 35 | 4 0 0 50 -1 16 12 0.0000 4 210 2220 5400 1170 mov %eax, 0x30(%ebp)\001 36 | 4 0 0 50 -1 16 12 0.0000 4 195 1515 5400 1425 xor %eax, %eax\001 37 | 4 0 0 50 -1 16 12 0.0000 4 210 1185 5400 1680 jmp epilogue\001 38 | -6 39 | 6 2625 -600 5325 1725 40 | 4 0 0 50 -1 16 12 0.0000 4 225 2265 2625 -375 ld_i32 tmp2, env+$0x10\001 41 | 4 0 0 50 -1 16 12 0.0000 4 225 2670 2625 -120 qemu_ld32 utmp0, tmp2+$-1\001 42 | 4 0 0 50 -1 16 12 0.0000 4 225 2265 2625 135 ld_i32 tmp4, env+$0x10\001 43 | 4 0 0 50 -1 16 12 0.0000 4 225 1830 2625 390 movi_i32 tmp14, $4\001 44 | 4 0 0 50 -1 16 12 0.0000 4 210 2550 2625 645 add_i32 tmp4, tmp4, tmp14\001 45 | 4 0 0 50 -1 16 12 0.0000 4 225 2265 2625 900 st_i32 tmp4, env+$0x10\001 46 | 4 0 0 50 -1 16 12 0.0000 4 225 2265 2625 1155 st_i32 tmp0, env+$0x20\001 47 | 4 0 0 50 -1 16 12 0.0000 4 225 2160 2625 1410 movi_i32 cc_op, $0x18\001 48 | 4 0 0 50 -1 16 12 0.0000 4 210 795 2625 1665 exit_tb 0\001 49 | -6 50 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 51 | 0 0 1.00 60.00 120.00 52 | 1800 2025 2625 2025 53 | 2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 54 | 0 0 1.00 60.00 120.00 55 | 4425 2025 5400 2025 56 | 4 0 32 50 -1 16 12 0.0000 4 210 1035 0 -75 push %ebp\001 57 | 4 0 32 50 -1 16 12 0.0000 4 210 1605 0 180 mov %esp, %ebp\001 58 | 4 0 32 50 -1 16 12 0.0000 4 165 885 0 435 not %eax\001 59 | 4 0 32 50 -1 16 12 0.0000 4 195 1605 0 945 mov %edx, %eax\001 60 | 4 0 32 50 -1 16 12 0.0000 4 210 2295 0 1200 xor $0x55555555, %eax\001 61 | 4 0 32 50 -1 16 12 0.0000 4 210 945 0 1455 pop %ebp\001 62 | 4 0 0 50 -1 16 12 0.0000 4 150 255 0 1710 ret\001 63 | 4 0 32 50 -1 16 12 0.0000 4 195 1575 0 690 add %eax, %edx\001 64 | -------------------------------------------------------------------------------- /doc/web/qsim_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtcasl/qsim/b1e33516426663f277a5da5b56b2b59d28fa5099/doc/web/qsim_diagram.png -------------------------------------------------------------------------------- /doc/web/qsim_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtcasl/qsim/b1e33516426663f277a5da5b56b2b59d28fa5099/doc/web/qsim_splash.png -------------------------------------------------------------------------------- /examples/arm64/.gitignore: -------------------------------------------------------------------------------- 1 | cachesim 2 | simple 3 | tracelog 4 | macsim_tracegen 5 | -------------------------------------------------------------------------------- /examples/arm64/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Qemu Simulation Framework (qsim) # 3 | # Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled # 4 | # a C++ API, for the use of computer architecture researchers. # 5 | # # 6 | # This work is licensed under the terms of the GNU GPL, version 2. See the # 7 | # COPYING file in the top-level directory. # 8 | ############################################################################### 9 | QSIM_PREFIX ?= /usr/local 10 | CXXFLAGS ?= -O3 -g -Wall -I$(QSIM_PREFIX)/include -std=c++0x -Wall 11 | LDLIBS ?= -L$(QSIM_PREFIX)/lib -lqsim -pthread -ldl -lz 12 | 13 | EXAMPLES = simple cachesim 14 | 15 | all: $(EXAMPLES) 16 | 17 | vistrace: vistrace.cpp $(QSIM_PREFIX)/lib/libqsim.so 18 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) -lImlib2 19 | 20 | simple: simple.cpp cs_disas.o $(QSIM_PREFIX)/lib/libqsim.so 21 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ cs_disas.o $< $(LDLIBS) -lcapstone 22 | 23 | cachesim: cachesim.cpp $(QSIM_PREFIX)/lib/libqsim.so 24 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) 25 | 26 | macsim_tracegen: macsim_tracegen.cpp cs_disas.o $(QSIM_PREFIX)/lib/libqsim.so 27 | $(CXX) $(CXXFLAGS) -o $@ cs_disas.o $< $(LDLIBS) -lcapstone 28 | 29 | io-test: io-test.cpp $(QSIM_PREFIX)/lib/libqsim.so 30 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) 31 | 32 | qtm: qtm.cpp $(QSIM_PREFIX)/lib/libqsim.so 33 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -lpthread -o $@ $< $(LDLIBS) 34 | 35 | clean: 36 | rm -f *.o $(EXAMPLES) *~ *\# 37 | 38 | -------------------------------------------------------------------------------- /examples/arm64/cs_disas.cpp: -------------------------------------------------------------------------------- 1 | #include "cs_disas.h" 2 | #include 3 | 4 | cs_disas::cs_disas(cs_arch arch, cs_mode mode) 5 | { 6 | pf = { arch, mode}; 7 | cs_err err = cs_open(pf.arch, pf.mode, &handle); 8 | if (err) { 9 | std::cerr << "Failed on cs_open with error: " << err << std::endl; 10 | return; 11 | } 12 | 13 | cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 14 | } 15 | 16 | cs_disas::~cs_disas() 17 | { 18 | cs_close(&handle); 19 | } 20 | 21 | int cs_disas::decode(unsigned char *code, int size, cs_insn *&insn) 22 | { 23 | int count; 24 | 25 | count = cs_disasm(handle, code, size, 0, 0, &insn); 26 | 27 | return count; 28 | } 29 | 30 | void cs_disas::free_insn(cs_insn *insn, int count) 31 | { 32 | cs_free(insn, count); 33 | } 34 | 35 | bool cs_disas::get_regs_access(cs_insn *insn, cs_regs regs_read, cs_regs regs_write, uint8_t *regs_read_count, uint8_t *regs_write_count) 36 | { 37 | bool ret; 38 | 39 | ret = cs_regs_access(handle, insn, regs_read, regs_read_count, 40 | regs_write, regs_write_count); 41 | 42 | 43 | return ret; 44 | } 45 | -------------------------------------------------------------------------------- /examples/arm64/cs_disas.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct platform { 4 | cs_arch arch; 5 | cs_mode mode; 6 | }; 7 | 8 | class cs_disas { 9 | 10 | public: 11 | cs_disas(cs_arch arch, cs_mode mode); 12 | ~cs_disas(); 13 | 14 | int decode(unsigned char *code, int size, cs_insn *&insn); 15 | void free_insn(cs_insn *insn, int count); 16 | bool get_regs_access(cs_insn *insn, cs_regs regs_read, cs_regs regs_write, uint8_t *regs_read_count, 17 | uint8_t *regs_write_count); 18 | private: 19 | csh handle; 20 | struct platform pf; 21 | }; 22 | -------------------------------------------------------------------------------- /examples/x86/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Qemu Simulation Framework (qsim) # 3 | # Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled # 4 | # a C++ API, for the use of computer architecture researchers. # 5 | # # 6 | # This work is licensed under the terms of the GNU GPL, version 2. See the # 7 | # COPYING file in the top-level directory. # 8 | ############################################################################### 9 | QSIM_PREFIX ?= /usr/local 10 | CXXFLAGS ?= -g -O2 -std=c++0x -Wall -I$(QSIM_PREFIX)/distorm/ -I$(QSIM_PREFIX)/include -L$(QSIM_PREFIX)/lib 11 | LDLIBS ?= -lqsim -pthread -ldl 12 | 13 | EXAMPLES = qtm simple io-test cachesim virt_rw 14 | 15 | all: $(EXAMPLES) 16 | 17 | vistrace: vistrace.cpp $(QSIM_PREFIX)/lib/libqsim.so 18 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) -lImlib2 19 | 20 | simple: simple.cpp $(QSIM_PREFIX)/lib/libqsim.so 21 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(QSIM_PREFIX)/distorm/distorm64.a $(LDLIBS) 22 | 23 | headless: simple_headless.cpp $(QSIM_PREFIX)/lib/libqsim.so 24 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(QSIM_PREFIX)/distorm/distorm64.a $(LDLIBS) 25 | 26 | io-test: io-test.cpp $(QSIM_PREFIX)/lib/libqsim.so 27 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(QSIM_PREFIX)/distorm/distorm64.a $(LDLIBS) 28 | 29 | qtm: qtm.cpp $(QSIM_PREFIX)/lib/libqsim.so 30 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -lpthread -o $@ $< $(QSIM_PREFIX)/distorm/distorm64.a $(LDLIBS) 31 | 32 | clean: 33 | rm -f $(EXAMPLES) *~ *\# 34 | 35 | -------------------------------------------------------------------------------- /examples/x86/virt_rw.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), couled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #include 10 | #include 11 | #include 12 | 13 | #include "distorm.h" 14 | 15 | #include 16 | #include 17 | 18 | using Qsim::OSDomain; 19 | 20 | using std::ostream; 21 | 22 | class TraceWriter { 23 | public: 24 | TraceWriter(OSDomain &osd) : 25 | osd(osd), finished(false) 26 | { 27 | osd.set_app_start_cb(this, &TraceWriter::app_start_cb); 28 | } 29 | 30 | bool hasFinished() { return finished; } 31 | 32 | int app_start_cb(int c) { 33 | static bool ran = false; 34 | if (!ran) { 35 | ran = true; 36 | osd.set_magic_cb(this, &TraceWriter::magic_cb); 37 | osd.set_app_end_cb(this, &TraceWriter::app_end_cb); 38 | } 39 | 40 | return 0; 41 | } 42 | 43 | int magic_cb(int c, uint64_t rax) 44 | { 45 | if (rax == 0xc5b1fffd) { 46 | uint64_t vaddr = osd.get_reg(c, QSIM_X86_RBX); 47 | uint32_t val = 0xfafa; 48 | osd.mem_wr_virt(c, val, vaddr); 49 | osd.set_reg(c, QSIM_X86_RCX, sizeof(val)); 50 | } 51 | 52 | return 0; 53 | } 54 | 55 | int app_end_cb(int c) { finished = true; return 0; } 56 | 57 | private: 58 | OSDomain &osd; 59 | bool finished; 60 | 61 | static const char * itype_str[]; 62 | }; 63 | 64 | const char *TraceWriter::itype_str[] = { 65 | "QSIM_INST_NULL", 66 | "QSIM_INST_INTBASIC", 67 | "QSIM_INST_INTMUL", 68 | "QSIM_INST_INTDIV", 69 | "QSIM_INST_STACK", 70 | "QSIM_INST_BR", 71 | "QSIM_INST_CALL", 72 | "QSIM_INST_RET", 73 | "QSIM_INST_TRAP", 74 | "QSIM_INST_FPBASIC", 75 | "QSIM_INST_FPMUL", 76 | "QSIM_INST_FPDIV" 77 | }; 78 | 79 | int main(int argc, char** argv) { 80 | using std::istringstream; 81 | using std::ofstream; 82 | 83 | ofstream *outfile(NULL); 84 | 85 | unsigned n_cpus = 1; 86 | 87 | std::string qsim_prefix(getenv("QSIM_PREFIX")); 88 | 89 | // Read number of CPUs as a parameter. 90 | if (argc >= 2) { 91 | istringstream s(argv[1]); 92 | s >> n_cpus; 93 | } 94 | 95 | OSDomain *osd_p(NULL); 96 | 97 | if (argc >= 3) { 98 | // Create new OSDomain from saved state. 99 | osd_p = new OSDomain(n_cpus, argv[2]); 100 | } else { 101 | osd_p = new OSDomain(n_cpus, qsim_prefix + "/images/x86_64_images/vmlinuz", "x86", QSIM_INTERACTIVE); 102 | } 103 | OSDomain &osd(*osd_p); 104 | 105 | std::string benchmark; 106 | if (argc >= 4) { 107 | istringstream bench_file(argv[3]); 108 | bench_file >> benchmark; 109 | } 110 | 111 | // Attach a TraceWriter if a trace file is given. 112 | TraceWriter tw(osd); 113 | 114 | // If this OSDomain was created from a saved state, the app start callback was 115 | // received prior to the state being saved. 116 | if (argc >= 4) tw.app_start_cb(0); 117 | Qsim::load_file(osd, benchmark.c_str()); 118 | 119 | osd.connect_console(std::cout); 120 | 121 | unsigned long inst_per_iter = 1000000000, inst_run; 122 | // The main loop: run until 'finished' is true. 123 | inst_run = inst_per_iter; 124 | while (!tw.hasFinished() && !(inst_per_iter - inst_run)) { 125 | inst_run = osd.run(inst_per_iter); 126 | } 127 | 128 | if (outfile) { outfile->close(); } 129 | delete outfile; 130 | 131 | delete osd_p; 132 | 133 | return 0; 134 | } 135 | -------------------------------------------------------------------------------- /fastforwarder.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | // The fast-forwarder: runs until it sees an application start marker and then 10 | // saves the state of the CPUs so it can be reloaded later. 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "statesaver.h" 16 | 17 | // The following two defines can be used to create instruction traces. DEBUG 18 | // enables tracing and LOAD reconfigures the fastforwarder to load a state 19 | // file and trace this. Doing this allows comparison of the trace of the 20 | // loaded state to the trace of the fastforwarder after loading a state. 21 | //#define LOAD 22 | //#define DEBUG 23 | 24 | struct Magic_cb_s { 25 | Magic_cb_s(Qsim::OSDomain &osd): osd(osd), app_started(false) {} 26 | 27 | Qsim::OSDomain &osd; 28 | 29 | int magic_cb_f(int cpu_id, uint64_t rax) { 30 | if (rax == 0xaaaaaaaa) { 31 | app_started = true; 32 | return 1; 33 | } 34 | return 0; 35 | } 36 | bool app_started; 37 | 38 | void inst_cb_f(int i, uint64_t p, uint64_t v, uint8_t l, const uint8_t *b, 39 | enum inst_type t) 40 | { 41 | std::cerr << '\n' << std::dec << i << ' ' << std::hex << p << '/' << v; 42 | } 43 | 44 | void reg_cb_f(int i, int r, uint8_t s, int w) { 45 | if (!w && s) { 46 | std::cerr << ' ' << x86_regs_str[r] << '(' << osd.get_reg(i, r) << ')'; 47 | } else if (!w) { 48 | std::cerr << " f" << std::setw(2) << std::setfill('0') << r 49 | << '(' << std::setw(2) << osd.get_reg(i, QSIM_ARM_CPSR) << ')'; 50 | } 51 | } 52 | }; 53 | 54 | int main(int argc, char** argv) { 55 | if (argc < 5) { 56 | std::cout << "Usage:\n " << argv[0] 57 | << " <# CPUs> <{x86/a64}>\n"; 58 | return 1; 59 | } 60 | 61 | std::string arch("x86"); 62 | 63 | if (argc == 6) 64 | arch = argv[5]; 65 | 66 | int cpus(atoi(argv[2])), ram_mb(atoi(argv[3])); 67 | if (cpus <= 0) { 68 | std::cerr << "# CPUs " << cpus << " out of range.\n"; return 1; 69 | } 70 | 71 | if (ram_mb < 64) { 72 | std::cerr << "Ram size " << ram_mb << " out of range.\n"; return 1; 73 | } 74 | 75 | #ifdef LOAD 76 | Qsim::OSDomain osd("state.debug"); 77 | #else 78 | Qsim::OSDomain osd(cpus, argv[1], arch, QSIM_HEADLESS, ram_mb); 79 | #endif 80 | Magic_cb_s magic_cb_s(osd); 81 | 82 | osd.connect_console(std::cout); 83 | #ifndef LOAD 84 | osd.set_magic_cb(&magic_cb_s, &Magic_cb_s::magic_cb_f); 85 | 86 | std::cout << "Fast forwarding...\n"; 87 | 88 | // The thread will be "idle" during initialization. The "slow cycles" 89 | // mechanism is a dirty hack that keeps timer interrupts from happening 90 | // before the core is fully booted. 91 | std::vector slow_cycles(osd.get_n(), 10); 92 | slow_cycles[0] = 70000; 93 | do { 94 | for (unsigned i = 0; i < 100 && !magic_cb_s.app_started; i++) { 95 | for (int j = 0; j < cpus && !magic_cb_s.app_started; j++) { 96 | if (osd.runnable(j)) { 97 | if (osd.idle(j) && !slow_cycles[j]) { 98 | osd.run(100); 99 | } else { 100 | if (osd.idle(j)) --slow_cycles[j]; 101 | osd.run(10000); 102 | } 103 | } 104 | 105 | // So we don't immediately run the app start callback on load 106 | if (magic_cb_s.app_started) osd.run(j, 1); 107 | } 108 | } 109 | if (!magic_cb_s.app_started) osd.timer_interrupt(); 110 | } while (!magic_cb_s.app_started); 111 | #endif 112 | 113 | #ifdef DEBUG 114 | osd.set_inst_cb(&magic_cb_s, &Magic_cb_s::inst_cb_f); 115 | osd.set_reg_cb(&magic_cb_s, &Magic_cb_s::reg_cb_f); 116 | #endif 117 | 118 | #ifndef LOAD 119 | std::cout << "Saving state...\n"; 120 | Qsim::save_state(osd, argv[4]); 121 | #endif 122 | 123 | #ifdef DEBUG 124 | std::cout << "Tracing 1M instructions.\n"; 125 | #endif 126 | 127 | retry: 128 | int runfor = 1, ran = runfor; 129 | while (ran == runfor) { 130 | ran = osd.run(runfor); 131 | } 132 | 133 | if (access(argv[4], F_OK) == -1) { 134 | goto retry; 135 | } 136 | 137 | std::cout << "Finished.\n"; 138 | 139 | return 0; 140 | } 141 | -------------------------------------------------------------------------------- /initrd/.gitignore: -------------------------------------------------------------------------------- 1 | dev 2 | proc 3 | sys 4 | data 5 | *.cpio 6 | *.tar.bz2 7 | busybox-1.24.1 8 | -------------------------------------------------------------------------------- /initrd/Makefile: -------------------------------------------------------------------------------- 1 | initrd.cpio: sbin/test_threads sbin/test_inst sbin/test_mem sbin/qsim_io sbin/mark_app etc/fstab init sbin/hexdump dev proc sys data 2 | find dev sbin proc init etc sys data -path "*/.*" -o -print |\ 3 | cpio -H newc -o > initrd.cpio 4 | 5 | sbin/mark_app : mark_app.c 6 | sbin/test_threads : test_threads.c 7 | sbin/qsim_io : qsim_io.c 8 | sbin/test_inst: test_inst.c 9 | sbin/test_mem: test_mem.c 10 | 11 | sbin/hexdump : sbin/busybox 12 | bash -c 'cd sbin; for a in `$(QEMU) ./busybox --list-full`; do ln -sf ./busybox $$a; done; cd ..' 13 | 14 | sbin/% : %.c 15 | $(CC) -o $@ -pthread -static $< 16 | 17 | dev proc sys data: 18 | mkdir -p dev proc sys data 19 | 20 | .PHONY: arm64 21 | arm64: 22 | $(MAKE) CC=aarch64-linux-gnu-gcc QEMU=qemu-aarch64 23 | 24 | x86: 25 | $(MAKE) 26 | 27 | clean: 28 | rm -f sbin/test_inst sbin/test_mem sbin/qsim_io sbin/test_threads sbin/mark_app initrd.cpio *~ \#* 29 | -------------------------------------------------------------------------------- /initrd/etc/fstab: -------------------------------------------------------------------------------- 1 | proc /proc proc defaults 0 0 2 | devpts /dev/pts devpts defaults 0 0 3 | sysfs /sys sysfs defaults 0 0 4 | -------------------------------------------------------------------------------- /initrd/getbusybox.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Download and configure busybox. 3 | 4 | # NOTE: This is optional. The binary of busybox distributed with QSim should 5 | # work perfectly adequately. 6 | 7 | ARCH=x86 8 | CROSS=aarch64-linux-gnu- 9 | HOST=`uname -m` 10 | if [ "$HOST" == "aarch64" ]; then 11 | ARCH=arm64 12 | CROSS= 13 | fi 14 | 15 | BBOX=busybox-1.26.2 16 | BBOX_ARCHIVE=$BBOX.tar.bz2 17 | BBOX_URL=https://www.busybox.net/downloads/$BBOX_ARCHIVE 18 | 19 | UNPACK="tar -xjf" 20 | 21 | pushd ../linux 22 | LINUX_DIR=`pwd`/linux/ 23 | popd 24 | 25 | # Download the archive if we don't already have it. 26 | if [ ! -e $BBOX_ARCHIVE ]; then 27 | echo === DOWNLOADING ARCHIVE === 28 | wget $BBOX_URL --no-check-certificate 29 | fi 30 | 31 | # Delete the busybox directory if it already exists. 32 | if [ -e $BBOX ]; then 33 | rm -r $BBOX 34 | fi 35 | 36 | echo === UNPACKING ARCHIVE === 37 | $UNPACK $BBOX_ARCHIVE 38 | 39 | echo === COPYING CONFIG === 40 | sed "s#\\%LINUX_DIR\\%#$LINUX_DIR#g" < busybox-config \ 41 | > $BBOX/.config 42 | 43 | echo == BUILDING == 44 | cd $BBOX 45 | if [ -z "$1" ]; then 46 | make -j4 47 | cp busybox ../sbin/ 48 | cd ../ 49 | make clean && make $ARCH 50 | cp -f initrd.cpio initrd.cpio.$ARCH 51 | else 52 | make -j4 CROSS_COMPILE=$CROSS 53 | cp busybox ../sbin/ 54 | cd ../ 55 | make clean && make arm64 56 | cp -f initrd.cpio initrd.cpio.arm64 57 | fi 58 | -------------------------------------------------------------------------------- /initrd/init: -------------------------------------------------------------------------------- 1 | #!/sbin/ash 2 | 3 | mknod /dev/null c 1 3 4 | mknod /dev/ptmx c 4 2 5 | mknod /dev/ram0 b 1 0 6 | mknod /dev/tty0 c 5 0 7 | mknod /dev/ttyS0 c 4 64 8 | 9 | mount /proc 10 | mount /sys 11 | 12 | PATH=/sbin 13 | 14 | export NCPUS=`grep processor /proc/cpuinfo | wc -l` 15 | 16 | echo Number of CPUs: $NCPUS | /sbin/qsim_out 17 | 18 | cd data 19 | 20 | /sbin/mark_app 21 | 22 | echo Restoring state 23 | echo Copying benchmark binary... 24 | 25 | /sbin/qsim_in | tar -x 26 | if [ $? != 0 ]; then 27 | echo Untar input failed. Are you providing a .tar archive? | /sbin/qsim_out 28 | fi 29 | 30 | if [ ! -e runme.sh ]; then 31 | echo \"runme.sh\" not found. Input .tar must contain this. | /sbin/qsim_out 32 | fi 33 | 34 | echo Executing benchmark 35 | /sbin/chmod +x ./runme.sh 36 | /sbin/ash ./runme.sh 37 | 38 | echo --- program exit, will shutdown shortly... --- 39 | # Spin forever. 40 | while true; do 41 | sleep 10 42 | done 43 | -------------------------------------------------------------------------------- /initrd/mark_app.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | __attribute__((always_inline)) 6 | static inline void do_cpuid(uint32_t val) { 7 | #if defined(__aarch64__) 8 | asm volatile("msr pmcr_el0, %0" :: "r" (val)); 9 | #else 10 | asm("cpuid;\n":: "a"(val) : "%ebx", "%ecx", "%edx"); 11 | #endif 12 | } 13 | 14 | static inline void set_n_cpus(void) { 15 | #if defined(__aarch64__) 16 | #else 17 | asm volatile("cpuid;\n":: "a"(0xc5b1fffc), "b"(get_nprocs()):"ecx","edx"); 18 | #endif 19 | } 20 | 21 | int main(int argc, char** argv) { 22 | if (argc == 1) do_cpuid(0xaaaaaaaa); 23 | else if (argc == 2) do_cpuid(0xfa11dead); 24 | 25 | // set number of processors in qsim 26 | set_n_cpus(); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /initrd/qsim_io.c: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | static inline void do_cpuid(uint32_t val) { 16 | #if defined(__aarch64__) 17 | asm volatile("msr pmcr_el0, %0" :: "r" (val)); 18 | #else 19 | asm("cpuid;\n":: "a"(val) : "%ebx", "%ecx", "%edx"); 20 | #endif 21 | } 22 | 23 | static inline int do_cpuid_return(uint32_t val) { 24 | int ret; 25 | 26 | #if defined(__aarch64__) 27 | asm volatile("msr pmcr_el0, %0\n" 28 | "mov %0, x0\n" 29 | : "=r"(ret) : "r" (val)); 30 | #else 31 | asm("cpuid;\n": "=a"(ret) : "a"(val) : "%edx", "%ecx"); 32 | #endif 33 | 34 | return ret; 35 | } 36 | 37 | static inline int do_cpuid2_return(uint32_t val, char* buf) { 38 | int ret; 39 | 40 | #if defined(__aarch64__) 41 | asm volatile("mov x0, %1\n" 42 | "mov x1, %2\n" 43 | "msr pmcr_el0, %0\n" 44 | "mov %0, x2\n" 45 | : "=&r"(ret) : "r" (val), "r" (buf)); 46 | #else 47 | asm("cpuid;\n": "=c"(ret) : "a"(val), "b"(buf) : "%edx"); 48 | #endif 49 | 50 | return ret; 51 | } 52 | 53 | static inline void qsim_out(char i) { 54 | do_cpuid((0xff & i) | 0xc501e000); 55 | } 56 | 57 | static inline void qsim_bin_out(char i) { 58 | do_cpuid((0xff & i) | 0xc5b10000); 59 | } 60 | 61 | static inline char qsim_in() { 62 | char out; 63 | int ready; 64 | ready = do_cpuid_return(0xc5b1fffe); 65 | if (!ready) exit(0); 66 | out = do_cpuid_return(0xc5b1ffff); 67 | 68 | return out; 69 | } 70 | 71 | static inline size_t qsim_in_block(char* buf) { 72 | size_t s; 73 | s = do_cpuid2_return(0xc5b1fffd, buf); 74 | 75 | return s; 76 | } 77 | 78 | int main(int argc, char **argv) { 79 | int c; 80 | if (!strcmp(argv[0], "/sbin/qsim_out")) { 81 | while ((c = fgetc(stdin)) != EOF ) qsim_out(c); 82 | } else if (!strcmp(argv[0], "/sbin/qsim_bin_out")) { 83 | while ((c = fgetc(stdin)) != EOF) qsim_bin_out(c); 84 | } else if (!strcmp(argv[0], "/sbin/qsim_in")) { 85 | //do { char c = qsim_in(); write(1, &c, 1); } while(1); 86 | size_t s; 87 | char buf[1024]; 88 | while ((s = qsim_in_block(buf)) != 0) write(1, buf, s); 89 | } 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /initrd/sbin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !init 3 | !qsim_bin_out 4 | !qsim_in 5 | !qsim_out 6 | -------------------------------------------------------------------------------- /initrd/sbin/init: -------------------------------------------------------------------------------- 1 | ../init -------------------------------------------------------------------------------- /initrd/sbin/qsim_bin_out: -------------------------------------------------------------------------------- 1 | qsim_io -------------------------------------------------------------------------------- /initrd/sbin/qsim_in: -------------------------------------------------------------------------------- 1 | qsim_io -------------------------------------------------------------------------------- /initrd/sbin/qsim_out: -------------------------------------------------------------------------------- 1 | qsim_io -------------------------------------------------------------------------------- /initrd/test_inst.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static inline void do_cpuid(uint32_t val) { 5 | #if defined(__arm__) || defined(__aarch64__) 6 | asm volatile("msr pmcr_el0, %0" :: "r" (val)); 7 | #else 8 | asm("cpuid;\n":: "a"(val) : "%edx", "%ecx"); 9 | #endif 10 | } 11 | 12 | volatile int val = 0; 13 | 14 | int main(int argc, char** argv) 15 | { 16 | int i; 17 | do_cpuid(0xaaaaaaaa); 18 | 19 | for (i = 0; i < 10; i++) 20 | val += 1; 21 | 22 | do_cpuid(0xfa11dead); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /initrd/test_mem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static inline void do_cpuid(uint32_t val) { 5 | #if defined(__arm__) || defined(__aarch64__) 6 | asm volatile("msr pmcr_el0, %0" :: "r" (val)); 7 | #else 8 | asm("cpuid;\n":: "a"(val) : "%edx", "%ecx"); 9 | #endif 10 | } 11 | 12 | volatile int val = 0; 13 | 14 | int main(int argc, char** argv) 15 | { 16 | int i, array[10]; 17 | do_cpuid(0xaaaaaaaa); 18 | 19 | for (i = 0; i < 10; i++) 20 | array[i] = val; 21 | 22 | do_cpuid(0xfa11dead); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /initrd/test_threads.c: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define N_THREADS 150 16 | const unsigned int N_LOOPS_PER_THREAD = 100000; 17 | 18 | pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; 19 | unsigned counter = 0; 20 | pthread_barrier_t all_spawned_barrier; 21 | pthread_t threads[N_THREADS]; 22 | 23 | void *thread_main(void *arg_vp) { 24 | volatile unsigned j = (unsigned)arg_vp; 25 | unsigned int i; 26 | 27 | pthread_mutex_lock(&counter_mutex); { 28 | counter++; 29 | } pthread_mutex_unlock(&counter_mutex); 30 | 31 | printf("test_threads: Now there are %u threads waiting\n", counter); 32 | 33 | pthread_barrier_wait(&all_spawned_barrier); 34 | 35 | for (i = 0; i < N_LOOPS_PER_THREAD; i++) { 36 | j ^= (i&(-i)); 37 | } 38 | 39 | pthread_mutex_lock(&counter_mutex); { 40 | counter--; 41 | } pthread_mutex_unlock(&counter_mutex); 42 | 43 | return NULL; 44 | } 45 | 46 | void init_threads(void) { 47 | unsigned int i; 48 | 49 | pthread_barrier_init(&all_spawned_barrier, NULL, N_THREADS); 50 | 51 | for (i = 0; i < N_THREADS; i++) { 52 | int rval = pthread_create(&threads[i], NULL, thread_main, NULL); 53 | if (rval != 0) exit(1); 54 | } 55 | 56 | puts("test_threads: All threads spawned.\n"); 57 | } 58 | 59 | int main(void) { 60 | unsigned int i; 61 | 62 | init_threads(); 63 | 64 | for (i = 0; i < N_THREADS; i++) pthread_join(threads[i], NULL); 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /linux/Image: -------------------------------------------------------------------------------- 1 | linux/arch/arm64/boot/Image -------------------------------------------------------------------------------- /linux/bzImage: -------------------------------------------------------------------------------- 1 | linux/arch/x86/boot/bzImage -------------------------------------------------------------------------------- /linux/getkernel.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Download and patch Linux kernel 3 | KERNEL_MAJOR=linux-4.1 4 | KERNEL_MINOR=39 5 | KERNEL_ARC=$KERNEL_MAJOR.$KERNEL_MINOR.tar.xz 6 | KERNEL_URL=https://www.kernel.org/pub/linux/kernel/v4.x/$KERNEL_ARC 7 | UNPACKAGE="tar -xf" 8 | 9 | INITRD=`pwd`/../initrd/initrd.cpio 10 | 11 | ARCH=x86 12 | CROSS=aarch64-linux-gnu- 13 | HOST=`uname -m` 14 | if [ "$HOST" == "aarch64" ]; then 15 | ARCH=arm64 16 | CROSS= 17 | fi 18 | 19 | # Only download the archive if we don't alreay have it. 20 | if [ ! -e $KERNEL_ARC ]; then 21 | echo === DOWNLOADING ARCHIVE === 22 | wget $KERNEL_URL 23 | fi 24 | 25 | # unpack if kernel does not exists 26 | if [ ! -e linux ]; then 27 | echo === UNPACKING ARCHIVE === 28 | $UNPACKAGE $KERNEL_ARC 29 | mv $KERNEL_MAJOR.$KERNEL_MINOR linux 30 | cd linux 31 | echo === PATCHING === 32 | patch -p1 < ../$KERNEL_MAJOR.qsim.patch 33 | cd .. 34 | fi 35 | 36 | echo === BUILDING LINUX === 37 | if [ -z "$1" ]; then 38 | cp $KERNEL_MAJOR.qsim-$ARCH.config linux/.config 39 | cd linux 40 | make -j4 KCPPFLAGS="-fno-pic -Wno-pointer-sign" 41 | else 42 | cp $KERNEL_MAJOR.qsim-arm64.config linux/.config 43 | cd linux 44 | make -j4 ARCH=arm64 CROSS_COMPILE=$CROSS KCPPFLAGS="-fno-pic -Wno-pointer-sign" 45 | fi 46 | -------------------------------------------------------------------------------- /linux/linux-4.1.qsim.patch: -------------------------------------------------------------------------------- 1 | From b56dc62f1908b6a65c46765c47ef66afb6b04008 Mon Sep 17 00:00:00 2001 2 | From: Pranith Kumar 3 | Date: Tue, 8 Dec 2015 13:57:13 -0500 4 | Subject: [PATCH 1/1] Qsim specific changes to the linux kernel 5 | 6 | * Enable qsim to track process pids 7 | * Enable qsim to track CPU boot 8 | 9 | Signed-off-by: Pranith Kumar 10 | --- 11 | arch/arm64/include/asm/mmu_context.h | 6 +++++- 12 | arch/arm64/kernel/smp.c | 8 ++++++-- 13 | arch/x86/kernel/smpboot.c | 10 ++++++++++ 14 | kernel/sched/core.c | 19 +++++++++++++++++++ 15 | 4 files changed, 40 insertions(+), 3 deletions(-) 16 | 17 | diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h 18 | index 8ec41e5..a8ac574 100644 19 | --- a/arch/arm64/include/asm/mmu_context.h 20 | +++ b/arch/arm64/include/asm/mmu_context.h 21 | @@ -35,6 +35,8 @@ extern unsigned int cpu_last_asid; 22 | void __init_new_context(struct task_struct *tsk, struct mm_struct *mm); 23 | void __new_context(struct mm_struct *mm); 24 | 25 | +extern void do_cpuid(uint32_t val); 26 | + 27 | #ifdef CONFIG_PID_IN_CONTEXTIDR 28 | static inline void contextidr_thread_switch(struct task_struct *next) 29 | { 30 | @@ -42,7 +44,9 @@ static inline void contextidr_thread_switch(struct task_struct *next) 31 | " msr contextidr_el1, %0\n" 32 | " isb" 33 | : 34 | - : "r" (task_pid_nr(next))); 35 | + : "r" (task_tgid_nr(next))); 36 | + 37 | + do_cpuid(0xc75c0000 | (u16)task_tgid_nr(next)); 38 | } 39 | #else 40 | static inline void contextidr_thread_switch(struct task_struct *next) 41 | diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c 42 | index d3a202b..cfd98cf 100644 43 | --- a/arch/arm64/kernel/smp.c 44 | +++ b/arch/arm64/kernel/smp.c 45 | @@ -76,10 +76,14 @@ enum ipi_msg_type { 46 | */ 47 | static int boot_secondary(unsigned int cpu, struct task_struct *idle) 48 | { 49 | + int ret = -EOPNOTSUPP; 50 | if (cpu_ops[cpu]->cpu_boot) 51 | - return cpu_ops[cpu]->cpu_boot(cpu); 52 | + ret = cpu_ops[cpu]->cpu_boot(cpu); 53 | 54 | - return -EOPNOTSUPP; 55 | + if (ret != -EOPNOTSUPP) 56 | + asm("msr pmcr_el0, %0\n"::"r"(cpu | 0xb0070000)); 57 | + 58 | + return ret; 59 | } 60 | 61 | static DECLARE_COMPLETION(cpu_running); 62 | diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c 63 | index 50e547e..11af828 100644 64 | --- a/arch/x86/kernel/smpboot.c 65 | +++ b/arch/x86/kernel/smpboot.c 66 | @@ -552,11 +552,19 @@ wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip) 67 | return (send_status | accept_status); 68 | } 69 | 70 | +/* Use magic instruction to boot other CPUs. */ 71 | +static inline void QSIM_BOOTSTRAP(u16 cpu) 72 | +{ 73 | + asm volatile("mov %0, %%eax;\n cpuid;\n" :: "r"(0xb0070000 | cpu) : 74 | + "%eax", "%ebx", "%edx", "%ecx"); 75 | +} 76 | + 77 | static int 78 | wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) 79 | { 80 | unsigned long send_status, accept_status = 0; 81 | int maxlvt, num_starts, j; 82 | + static u16 cur_cpu = 1; 83 | 84 | maxlvt = lapic_get_maxlvt(); 85 | 86 | @@ -594,6 +602,8 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) 87 | pr_debug("Waiting for send to finish...\n"); 88 | send_status = safe_apic_wait_icr_idle(); 89 | 90 | + QSIM_BOOTSTRAP(cur_cpu++); 91 | + 92 | mb(); 93 | atomic_set(&init_deasserted, 1); 94 | 95 | diff --git a/kernel/sched/core.c b/kernel/sched/core.c 96 | index 4d870eb..0b304de 100644 97 | --- a/kernel/sched/core.c 98 | +++ b/kernel/sched/core.c 99 | @@ -2293,6 +2293,16 @@ 100 | put_user(task_pid_vnr(current), current->set_child_tid); 101 | } 102 | 103 | +void do_cpuid(uint32_t val) 104 | +{ 105 | +#if defined(__aarch64__) 106 | + asm volatile("msr pmcr_el0, %0" :: "r" (val)); 107 | +#else 108 | + asm("cpuid;\n":: "a"(val) : "%ebx", "%ecx", "%edx"); 109 | +#endif 110 | +} 111 | +EXPORT_SYMBOL(do_cpuid); 112 | + 113 | /* 114 | * context_switch - switch to the new MM and the new thread's register state. 115 | */ 116 | @@ -2302,6 +2312,15 @@ 117 | { 118 | struct mm_struct *mm, *oldmm; 119 | 120 | + /* tell qsim the pid of the next task or that it is idle 121 | + */ 122 | + if (IS_ENABLED(CONFIG_X86) || IS_ENABLED(CONFIG_ARM64)) { 123 | + if (next == rq->idle) 124 | + do_cpuid(0x1d1e1d1e); 125 | + else 126 | + do_cpuid(0xc75c0000 | (u16)task_tgid_nr(next)); 127 | + } 128 | + 129 | prepare_task_switch(rq, prev, next); 130 | 131 | mm = next->mm; 132 | -- 133 | 2.7.1 134 | 135 | -------------------------------------------------------------------------------- /mgzd.h: -------------------------------------------------------------------------------- 1 | #ifndef __MGZD_H 2 | #define __MGZD_H 3 | /*****************************************************************************\ 4 | * Qemu Simulation Framework (qsim) * 5 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 6 | * a C++ API, for the use of computer architecture researchers. * 7 | * * 8 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 9 | * COPYING file in the top-level directory. * 10 | \*****************************************************************************/ 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | static const char* TMP_DIR = "/tmp/"; 23 | static const char* TMP_PFX = "qsim_XXXXXX"; 24 | 25 | namespace Mgzd { 26 | struct lib_t { 27 | void* handle; 28 | std::string file; 29 | }; 30 | 31 | static lib_t __attribute__((unused)) open(const char *libfile) { 32 | lib_t lib; 33 | 34 | // Use $QSIM_TMP, if it's set. 35 | const char* tmpdir = getenv("QSIM_TMP"); 36 | if (tmpdir) TMP_DIR = tmpdir; 37 | 38 | const int buf_size = 1024; // 1KB 39 | char tmpfile[buf_size], buf[buf_size]; 40 | 41 | size_t size = strlen(TMP_DIR); 42 | strncpy(tmpfile, TMP_DIR, size); 43 | tmpfile[size] = '\0'; 44 | strcat(tmpfile, TMP_PFX); 45 | 46 | int fd = mkstemp(tmpfile); 47 | FILE* fp = fdopen(fd, "wb"); 48 | 49 | if (!fp) { 50 | std::cerr << "Cannot open tmp file " << tmpfile << std::endl; 51 | exit(1); 52 | } 53 | 54 | FILE* libfp = fopen(libfile, "r"); 55 | 56 | if (!libfp) { 57 | std::cerr << "Cannot open library " << libfile << std::endl; 58 | exit(1); 59 | } 60 | 61 | while ((size = fread(buf, 1, buf_size, libfp)) > 0) { 62 | if (fwrite(buf, 1, size, fp) != size) { 63 | std::cerr << "couldn't write whole buffer" << std::endl; 64 | exit(1); 65 | } 66 | } 67 | fclose(fp); 68 | 69 | // Make temporary copy of libfile, so opening multiple copies of the same 70 | // file results in independent copies of global variables. 71 | lib.file = strdup(tmpfile); 72 | std::cout << "Opening " << lib.file.c_str() << std::endl; 73 | 74 | lib.handle = dlopen(lib.file.c_str(), RTLD_NOW|RTLD_LOCAL); 75 | if (lib.handle == NULL) { 76 | std::cerr << "dlopen(\"" << lib.file.c_str() << "\") failed: " 77 | << dlerror() << '\n'; 78 | } 79 | 80 | return lib; 81 | } 82 | 83 | static void __attribute__((unused)) close(const lib_t &lib) { 84 | //dlclose(lib.handle); 85 | unlink(lib.file.c_str()); 86 | } 87 | 88 | template static void sym(T *&ret, 89 | const lib_t lib, 90 | const char *sym) { 91 | (void*&)ret = dlsym(lib.handle, sym); 92 | if (char *err = dlerror()) { 93 | std::cerr << "dlsym(\"" << lib.file.c_str() << "\", \"" << sym 94 | << "\") failed: " << err << '\n'; 95 | exit(1); 96 | } 97 | } 98 | 99 | }; 100 | #endif 101 | -------------------------------------------------------------------------------- /mkstate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Create state files for 1 through 64 guest cores. 3 | 4 | if [ -z $LOG2MINCPUS ]; then 5 | LOG2MINCPUS=0 6 | fi 7 | 8 | if [ -z $LOG2MAXCPUS ]; then 9 | LOG2MAXCPUS=6 10 | fi 11 | 12 | # Ensure QSIM_PREFIX is set and set LD_LIBRARY_PATH and FF appropriately. 13 | if [ -z $QSIM_PREFIX ]; then 14 | QSIM_PREFIX=/usr/local 15 | fi 16 | export LD_LIBRARY_PATH=$QSIM_PREFIX/lib 17 | FF=$QSIM_PREFIX/bin/qsim-fastforwarder 18 | 19 | if [ -z $RAMSIZE ]; then 20 | # 3580 is the minimum needed to run Parsec with the simsmall data set. 21 | RAMSIZE=1024 22 | fi 23 | 24 | # Truncate our log file 25 | echo > mkstate.log 26 | echo > mkstate.a64.log 27 | 28 | for i in `seq $LOG2MINCPUS $LOG2MAXCPUS`; do 29 | n=`echo 2 $i ^ p | dc` 30 | echo "-- running qsim-fastforwarder for $n core(s) --" 31 | $FF linux/bzImage $n $RAMSIZE state.$n 2>&1 >> mkstate.log 32 | if [ "$n" -le 8 ]; then 33 | $FF linux/Image $n $RAMSIZE state.$n.a64 a64 2>&1 >> mkstate.a64.log 34 | fi 35 | # examples/io-test \ 36 | # $n TRACE state.$n ../benchmarks/splash2-tar/fft.tar > state.$n.testout & 37 | done 38 | -------------------------------------------------------------------------------- /qcache/BUGS: -------------------------------------------------------------------------------- 1 | Qcache Known Issues 2 | ------------------- 3 | 4 | - qDRAM expects boolean flags, but now we've switched to counters. It will 5 | either not compile or hang. 6 | 7 | - The in-order CPU has not been tested with counters instead of flags. 8 | 9 | - The counters are not being accessed with atomic increments and decrements. 10 | 11 | - The instruction cache does not participate in the coherence protocol, but 12 | does bring lines into lower-level private caches. These lines are not in the 13 | directory. Correctness issues then arise in self-modifying code (e.g. dynamic 14 | recompilers). 15 | 16 | - The L1 icache MUST be initialized before the L1 d-cache, if there are mult- 17 | iple levels of private cache. Failure to do so will probably cause failed 18 | assertions or, with assertions disabled, incorrect results. This is because 19 | caches maintain a pointer both to the level below and the level above, and 20 | lower-level private caches use this pointer to talk to higher-level private 21 | caches. Folding the instruction cache into the coherence protocol in some way 22 | would prevent this. 23 | 24 | - Private caches are exclusive by design, and writebacks (which "miss" by 25 | definition in an exclusive cache) are counted as accesses, even though they 26 | do not cause additional delay (but may cause evictions). 27 | 28 | - The following race condition could occur: 29 | 30 | Thread 1 | Thread 2 31 | ----------------+---------------- 32 | miss on X | miss on Y 33 | lock X | lock Y 34 | access L2 | access L2 35 | miss on X | miss on Y 36 | victim: Y | victim: X 37 | lock Y | lock X 38 | 39 | Several solutions have been proposed and one should eventually be 40 | implemented: 41 | 42 | - Directory locking units corresponding to sets in L1 43 | - Would require no locking at levels lower than L1, as long as L2SETS of 44 | lower-level private caches <= L2SETS of L1. 45 | 46 | - Deadlock detection 47 | - Keep information on lock nest in the directory. 48 | -------------------------------------------------------------------------------- /qcache/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Qemu Simulation Framework (qsim) # 3 | # Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled # 4 | # a C++ API, for the use of computer architecture researchers. # 5 | # # 6 | # This work is licensed under the terms of the GNU GPL, version 2. See the # 7 | # COPYING file in the top-level directory. # 8 | ############################################################################### 9 | QSIM_PREFIX ?= /usr/local 10 | CXXFLAGS ?= -g -O3 -DENABLE_ASSERTIONS -I$(QSIM_PREFIX)/include \ 11 | -L$(QSIM_PREFIX)/lib -I./ -I../qdram 12 | #CXXFLAGS ?= -g -O0 -DDEBUG -DENABLE_ASSERTIONS -I$(QSIM_PREFIX)/include \ 13 | # -L$(QSIM_PREFIX)/lib -I./ -I../qdram 14 | LDLIBS ?= -lqsim -pthread -ldl 15 | 16 | qcache: qcache.o main.o 17 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ qcache.o main.o $(LDLIBS) 18 | 19 | main.o: qcache.h qcache-msi.h qcache-mesi.h qcache-dir.h qcache-repl.h \ 20 | qcache-bloom.h qcpu.h ../qdram/qdram.h ../qdram/qdram-config.h \ 21 | ../qdram/qdram-sched.h ../qdram/qdram-event.h 22 | 23 | qcache.o: qcache.cpp qcache.h 24 | 25 | clean: 26 | rm -f qcache.o main.o qcache 27 | -------------------------------------------------------------------------------- /qcache/qcache-bloom.h: -------------------------------------------------------------------------------- 1 | // A fairly ordinary bloom filter implementation. Hashes are random binary 2 | // matrices. Can count false positives and produce a report in destructor if 3 | // desired (FPCOUNT parameter). 4 | #ifndef __BLOOM_H 5 | #define __BLOOM_H 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Qcache { 12 | template 13 | class BloomFilter 14 | { 15 | public: 16 | BloomFilter(unsigned int rseed = 0): aCount(0), hitCount(0), fpCount(0) { 17 | // Clear all bits in the filter. 18 | clear(); 19 | 20 | // Generate some hash matrices. 21 | for (unsigned i = 0; i < HASHES; ++i) { 22 | for (unsigned j = 0; j < L2_BITS; ++j) { 23 | uint64_t hash = 0; 24 | for (unsigned k = 0; k < 64; ++k) { 25 | hash <<= 1; 26 | hash |= (rand_r(&rseed) < RAND_MAX/2); 27 | } 28 | hashes[i][j] = hash; 29 | } 30 | } 31 | } 32 | 33 | ~BloomFilter() { 34 | if (FPCOUNT) { 35 | std::cout << "2^" << L2_BITS << " bits, " << HASHES << " hash func., " 36 | << aCount << " accesses, " << fpset.size() << " unique, " 37 | << hitCount << " hits, " << fpCount << " false pos.\n"; 38 | } 39 | } 40 | 41 | void add(uint64_t val) { 42 | for (unsigned i = 0; i < HASHES; ++i) { 43 | unsigned b = bitIdx(val, i); 44 | bits[b/64] |= 1ll<<(b%64); 45 | } 46 | 47 | if (FPCOUNT) { fpset.insert(val); } 48 | } 49 | 50 | bool check(uint64_t val) { 51 | bool p(true); 52 | for (unsigned i = 0; i < HASHES; ++i) { 53 | unsigned b = bitIdx(val, i); 54 | if (!(bits[b/64] & (1ll<<(b%64)))) p = false; 55 | } 56 | 57 | if (FPCOUNT) { 58 | ++aCount; 59 | if (p) ++hitCount; 60 | if (p && fpset.find(val) == fpset.end()) ++fpCount; 61 | } 62 | 63 | return p; 64 | } 65 | 66 | void clear() { 67 | const unsigned N = L2_BITS<6 ? 1 : (1ll<<(L2_BITS-6)); 68 | for (unsigned i = 0; i < N; ++i) bits[i] = 0; 69 | 70 | if (FPCOUNT) fpset.clear(); 71 | } 72 | 73 | void print() { 74 | for (unsigned i = 0; i < (1ll< fpset; 84 | 85 | unsigned bitIdx(uint64_t val, unsigned hash) { 86 | unsigned bitIdx = 0; 87 | for (unsigned i = 0; i < L2_BITS; ++i) { 88 | bitIdx <<= 1; 89 | bitIdx |= __builtin_parityll(hashes[hash][i] & val); 90 | } 91 | return bitIdx; 92 | } 93 | }; 94 | }; 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /qcache/qcache-moesi.h: -------------------------------------------------------------------------------- 1 | #ifndef __QCACHE_MOESI_H 2 | #define __QCACHE_MOESI_H 3 | 4 | // There is a MUCH MUCH nicer way to do this in C++ 11 with alias templates, but 5 | // this was decided to be the most elegant way to do this without violating 6 | // earlier, more widely supported C++ standards 7 | #define __QCACHE_DEF_MOESI 1 8 | #include "qcache-mesi.h" 9 | #undef __QCACHE_DEF_MOESI 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /qcache/qcache-msi.h: -------------------------------------------------------------------------------- 1 | #ifndef __QCACHE_MSI_H 2 | #define __QCACHE_MSI_H 3 | 4 | // There is a MUCH MUCH nicer way to do this in C++ 11 with alias templates, but 5 | // this was decided to be the most elegant way to do this without violating 6 | // earlier, more widely supported C++ standards 7 | #define __QCACHE_DEF_MSI 1 8 | #include "qcache-mesi.h" 9 | #undef __QCACHE_DEF_MSI 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /qcache/qcache.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qcache.h" 4 | 5 | pthread_mutex_t Qcache::errLock = PTHREAD_MUTEX_INITIALIZER; 6 | bool Qcache::printResults = false; 7 | -------------------------------------------------------------------------------- /qcache/qtickable.h: -------------------------------------------------------------------------------- 1 | #ifndef __QTICKABLE_H 2 | #define __QTICKABLE_H 3 | 4 | #include 5 | 6 | namespace Qcache { 7 | class Tickable { 8 | public: 9 | virtual void tick() { ASSERT(false); } 10 | }; 11 | }; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /qcache/test_qcache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | QSIM_PREFIX=${QSIM_PREFIX:-"/usr/local"} 4 | LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-"$QSIM_PREFIX/lib"} 5 | LOGFILE=${LOGFILE:-"test_qcache.log"} 6 | BENCHMARK_DIR=${BENCHMARK_DIR:-"$QSIM_PREFIX/benchmarks"} 7 | QCPROG=${QCPROG:-"./qcache"} 8 | 9 | export QSIM_PREFIX 10 | export LD_LIBRARY_PATH 11 | 12 | TARFILES=$BENCHMARK_DIR/*-tar/*.tar 13 | #THREADCOUNTS="1 2 4 8 16 32" 14 | THREADCOUNTS=1 15 | GUESTCORECOUNT=1 16 | 17 | for TAR in `cat BENCHMARKS`; do 18 | APP=`echo $TAR | sed 's/\.tar//' | sed 's/^.*\///'` 19 | echo > $LOGFILE.$APP 20 | echo === $APP === 21 | for i in $THREADCOUNTS; do 22 | echo -n "$i " 23 | $QCPROG ../state.$GUESTCORECOUNT $TAR $i TRACE.$APP.$i >> $LOGFILE.$APP 24 | done 25 | echo 26 | done 27 | -------------------------------------------------------------------------------- /qdb/BUGS: -------------------------------------------------------------------------------- 1 | * Profiler uses statistical sampling with a fixed mean instructions between 2 | samples of 1000000. This should be configurable. 3 | * Watchpoints and breakpoints not implemented. 4 | * Trace and Memtr not implemented. 5 | * Step not implemented. 6 | * Dumps, disassemblies, and setting of invalid virtual addressess cause SIGSEGV 7 | within QEMU. A gentler warning would be much preferred. 8 | * Dumps and disassemblies are not paginated, so they scroll off the top of the 9 | screen if they are longer than the terminal is high. 10 | -------------------------------------------------------------------------------- /qdb/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Qemu Simulation Framework (qsim) # 3 | # Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled # 4 | # a C++ API, for the use of computer architecture researchers. # 5 | # # 6 | # This work is licensed under the terms of the GNU GPL, version 2. See the # 7 | # COPYING file in the top-level directory. # 8 | ############################################################################### 9 | QSIM_PREFIX ?= /usr/local/ 10 | CXXFLAGS = -g -pthread -I../distorm/ -I$(QSIM_PREFIX)/include 11 | LDFLAGS= -L$(QSIM_PREFIX)/lib 12 | LDLIBS = -pthread -lreadline -ltermcap -ldl -lqsim 13 | OBJS = qdb.o lex.yy.o parser.tab.o help.o ../distorm/distorm64.a 14 | 15 | #Killed making docs by default because the output is annoying/Doxygen isn't 16 | #really configured yet/Doxygen shouldn't need to run every time anyway. 17 | all: qdb 18 | 19 | qdb: $(OBJS) 20 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) 21 | 22 | parser.tab.cpp tok.h: parser.ypp 23 | bison -v --defines=tok.h parser.ypp 24 | 25 | lex.yy.c: tok.h lexer.lex 26 | flex -olex.yy.c lexer.lex 27 | 28 | help.o: help.cpp tok.h 29 | qdb.o: qdb.cpp util.h qdb.h banner.h 30 | lex.yy.o: lex.yy.c util.h tok.h 31 | parser.tab.o: parser.tab.cpp qdb.h 32 | 33 | clean: 34 | rm -rf doc/* qdb *.tab.cpp lex.yy.c *.o \#*\# *~ tok.h -------------------------------------------------------------------------------- /qdb/System.map: -------------------------------------------------------------------------------- 1 | ../linux/linux/System.map -------------------------------------------------------------------------------- /qdb/banner.h: -------------------------------------------------------------------------------- 1 | #ifndef __BANNER_H 2 | #define __BANNER_H 3 | 4 | const char* banner = 5 | "QDB: The QSIM Multiprocessor Debugger\n" 6 | "=====================================\n" 7 | ; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /qdb/bzImage: -------------------------------------------------------------------------------- 1 | ../linux/bzImage -------------------------------------------------------------------------------- /qdb/lexer.lex: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | %{ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "util.h" 16 | #include "tok.h" 17 | 18 | #define YY_NO_YYWRAP 19 | inline int yywrap(void) { return 0; } 20 | 21 | size_t linebuf_pos = 0; 22 | size_t linebuf_len = 0; 23 | char *linebuf = NULL; 24 | 25 | /*We redefine YY_INPUT to use readline. Only goes one character at a time.*/ 26 | #define YY_INPUT(buf, result, max_size) { \ 27 | if (linebuf == NULL) { \ 28 | linebuf = readline("qdb> "); \ 29 | if (linebuf == NULL) linebuf = strdup("quit"); \ 30 | add_history(linebuf); \ 31 | linebuf_len = strlen(linebuf); \ 32 | if (linebuf_len == 0) { free(linebuf); linebuf = NULL; } \ 33 | linebuf_pos = 0; \ 34 | } \ 35 | if (max_size == 0) { \ 36 | result = 0; \ 37 | } else if (linebuf_pos == linebuf_len) { \ 38 | free(linebuf); linebuf = NULL; \ 39 | buf[0] = '\n'; buf[1] = '\0'; \ 40 | result = 1; \ 41 | } else if (max_size > linebuf_len-linebuf_pos + 1) { \ 42 | strncpy(buf, linebuf+linebuf_pos, linebuf_len-linebuf_pos+1);\ 43 | result = linebuf_len-linebuf_pos+1; \ 44 | linebuf_pos = linebuf_len; \ 45 | strncat(buf, "\n", 1); \ 46 | free(linebuf); linebuf = NULL; \ 47 | } else { \ 48 | buf[0] = linebuf[linebuf_pos++]; buf[1] = '\0'; \ 49 | result = 1; \ 50 | } \ 51 | } 52 | 53 | int yyerror(char* s); 54 | %} 55 | 56 | %start NONCOMMAND FILETIME FAIL 57 | 58 | space [ \t]* 59 | endl \r?\n 60 | dblquot \" 61 | 62 | %% 63 | [Ii][A-Za-z]* {BEGIN NONCOMMAND; return T_INTERVAL;} 64 | [Ss][Yy][A-Za-z]* {BEGIN NONCOMMAND; return T_SYNC; } 65 | [Tt][Rr][A-Za-z]* {BEGIN NONCOMMAND; return T_TRACE; } 66 | [Mm][A-Za-z]* {BEGIN NONCOMMAND; return T_MEMTR; } 67 | [Rr][Uu][A-Za-z]* {BEGIN NONCOMMAND; return T_RUN; } 68 | [Tt][Ii][A-Za-z]* {BEGIN NONCOMMAND; return T_TICK; } 69 | [Dd][Uu][A-Za-z]* {BEGIN NONCOMMAND; return T_DUMP; } 70 | [Dd][Ii][A-Za-z]* {BEGIN NONCOMMAND; return T_DISAS; } 71 | [Ll][A-Za-z]* {BEGIN FILETIME; return T_LSYMS; } 72 | [Uu][A-Za-z]* {BEGIN NONCOMMAND; return T_USYMS; } 73 | [Cc][A-Za-z]* {BEGIN NONCOMMAND; return T_CPUSTAT; } 74 | [Ss][Ee][A-Za-z]* {BEGIN NONCOMMAND; return T_SET; } 75 | [Ss][Tt][A-Za-z]* {BEGIN NONCOMMAND; return T_STEP; } 76 | [Pp][A-Za-z]* {BEGIN NONCOMMAND; return T_PROF; } 77 | [Rr][Ee][A-Za-z]* {BEGIN NONCOMMAND; return T_REPORT; } 78 | [Ww][A-Za-z]* {BEGIN NONCOMMAND; return T_WATCH; } 79 | [Bb][A-Za-z]* {BEGIN NONCOMMAND; return T_BREAK; } 80 | [Qq][A-Za-z]* {BEGIN NONCOMMAND; return T_QUIT; } 81 | 82 | [Hh][A-Za-z]* {return T_HELP; } 83 | 84 | [Oo][Nn] {return T_ON; } 85 | [Oo][Ff][Ff] {return T_OFF; } 86 | 87 | %[A-Za-z0-9]+ { 88 | yylval.i = register_lookup(yytext); 89 | return T_REG; 90 | } 91 | 92 | (0|[1-9][0-9]*) { 93 | unsigned long long num; 94 | sscanf(yytext, "%llu", &num); 95 | yylval.l = num; 96 | return T_LITERAL; 97 | } 98 | 99 | 0[0-7]+ { 100 | uint64_t num; 101 | sscanf(yytext, "%llo", &num); 102 | yylval.l = num; 103 | return T_LITERAL; 104 | } 105 | 106 | 0x[0-9a-fA-F]+ { 107 | uint64_t num; 108 | sscanf(yytext, "%llx", &num); 109 | yylval.l = num; 110 | return T_LITERAL; 111 | } 112 | 113 | [A-Za-z_][A-Za-z0-9_]* { 114 | yylval.l = symbol_lookup(yytext); 115 | return T_LITERAL; 116 | } 117 | 118 | [^ \t\n]+ { 119 | yylval.s = strdup(yytext); 120 | BEGIN NONCOMMAND; 121 | return T_FILE; 122 | } 123 | 124 | {endl} {BEGIN INITIAL; return T_ERROR; } 125 | . {/*Ignore everything up to the next endline while in fail state.*/} 126 | 127 | {space} {} 128 | {endl} {BEGIN INITIAL; return T_END;} 129 | . { printf("Unrecognized \"%s\".\n", yytext); BEGIN FAIL;} 130 | -------------------------------------------------------------------------------- /qdb/qdb.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #ifndef __QDB_H 10 | #define __QDB_H 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | // Forward declarations 19 | class CPUThread; 20 | 21 | // Shared global variables 22 | extern Qsim::OSDomain *cd; 23 | extern std::vector thread_objs; 24 | extern unsigned n_cpus; 25 | extern unsigned barriers_per_interrupt; 26 | // Symbol table manipulation 27 | void load_symbols (std::string filename, bool global, uint64_t cr3); 28 | void clear_symbols( bool global, uint64_t cr3); 29 | 30 | // Helper functions 31 | void cpu_stat(unsigned i); 32 | void do_report(); 33 | void prof_all(); 34 | void prof_on(int tid); 35 | void prof_off(int tid); 36 | void prof_off(); 37 | void mem_dump(uint64_t paddr, uint64_t size); 38 | void disas(uint64_t vaddr, uint64_t size); 39 | 40 | // Class representing the CPU thread. 41 | class CPUThread { 42 | public: 43 | CPUThread(Qsim::OSDomain *cd, unsigned cpu_id); 44 | ~CPUThread(); 45 | 46 | // Control the CPU 47 | void run(uint64_t insts); // Nonblocking call: run the CPU. 48 | void ctrl_c (); // Cancel current instruction run. 49 | void set_interval(uint64_t); // Set interval to a new value. 50 | 51 | // QSIM Callbacks 52 | static int atomic_callback(int cpu_id); 53 | 54 | // CPU Progress Synchronization (initialized in main()) 55 | static pthread_barrier_t before_int; 56 | static pthread_barrier_t after_int; 57 | 58 | private: 59 | pthread_t thread; 60 | static std::map directory; 61 | 62 | static void *thread_main(void* arg); 63 | 64 | pthread_mutex_t countdown_mutex; // Keep the countdown from getting weird. 65 | pthread_cond_t wake_up_thread; // Wake up the sleeping barber. 66 | uint64_t countdown; // Number of instructions left to run. 67 | uint64_t tickcount; // Countdown to next timer interrupt. 68 | uint64_t interval; // Initialize tickcount to this. 69 | 70 | unsigned cpu_id; 71 | 72 | CPUThread(const CPUThread &cputhread); // Don't allow copies 73 | void operator=(CPUThread &rval); // or assignment. 74 | }; 75 | 76 | // Paginator for long output 77 | class Paginate { 78 | public: 79 | Paginate(); 80 | void operator()(std::list &lines); 81 | 82 | private: 83 | int rows, cols; //Screen dimensions 84 | void pause(); 85 | }; 86 | 87 | extern Paginate paginate; 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /qdb/util.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #ifndef __UTIL_H 10 | #define __UTIL_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | uint64_t symbol_lookup (const char* symbol ); 17 | int register_lookup(const char* regname); 18 | 19 | #ifdef __cplusplus 20 | }; 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /qdram/Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Qemu Simulation Framework (qsim) # 3 | # Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled # 4 | # a C++ API, for the use of computer architecture researchers. # 5 | # # 6 | # This work is licensed under the terms of the GNU GPL, version 2. See the # 7 | # COPYING file in the top-level directory. # 8 | ############################################################################### 9 | QSIM_PREFIX ?= /usr/local 10 | CXXFLAGS ?= -g -O3 -DENABLE_ASSERTIONS -I$(QSIM_PREFIX)/include -L$(QSIM_PREFIX)/lib -I../qcache 11 | #CXXFLAGS ?= -g -O0 -DDEBUG -DENABLE_ASSERTIONS -I$(QSIM_PREFIX)/include \ 12 | # -L$(QSIM_PREFIX)/lib -I../qcache 13 | LDLIBS ?= -lqsim -pthread -ldl 14 | 15 | qdram: main.o ../qcache/qcache.o 16 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ ../qcache/qcache.o main.o $(LDLIBS) 17 | 18 | main.o: main.cpp qdram.h qdram-sched.h qdram-sched-fcfs.h qdram-event.h qdram-config.h 19 | 20 | clean: 21 | rm -f main.o qdram 22 | -------------------------------------------------------------------------------- /qdram/README: -------------------------------------------------------------------------------- 1 | Timing Parameters 2 | ----------------- 3 | Below are some timing parameters, along wiht their default values and some 4 | minimal explanation. 5 | 6 | tCPD(1) Command period (the "1t" or "2t" you set in BIOS) 7 | tFAW(27) Four activate window 8 | tCL(14) Column latency (7, 9, 11, 13, 14) 9 | tCWL(10) CAS Write Latency 10 | tCCD(4) CAS to CAS delay (between or within banks: 4) 11 | tRCD(14) Row-to-column delay 12 | tRP(14) Precharge to Activate (within a bank) 13 | tRAS(36) Activate to precharge delay (usually tCL + tRCD + 2) 14 | tRRD(6) Activate to activate delay 15 | tRTP(8) Read to precharge delay (> of 4 or 7.5ns) 16 | tWR(16) Write recovery time (Write to prec: 8, 10, 12, 14, 16) 17 | tRFC(118) Refresh to activate delay (110,160,260,350ns) 18 | tWTR(8) Write to read delay (4, 5, 6, 7, 8; bank) 19 | tRTW(16) Read to write delay (tCL + tCCD - tCWL + 2, channel?) 20 | tREF(8319) Refresh period (4164,5198,6240,7277,8319) 21 | tPD(6) Minimum time spent in power down (> of 3 or 5ns) 22 | tXP(7) Time to exit active powerdown/ppd fast exit (>3, 6ns) 23 | tXPDLL(26) Time to exit precharge powerdown slow exit (>10, 24ns) 24 | tACTPDEN(2) Activate to powerdown. 25 | tPRPDEN(2) Precharge to powerdown. 26 | tREFPDEN(2) Refresh to powerdown. 27 | tRDPDEN(19) Read to powerdown. 28 | tWRPDEN(34) Write to powerdown. 29 | tWRAPDEN(35) Write (auto precharge) to powerdown. 30 | -------------------------------------------------------------------------------- /qdram/main.cpp: -------------------------------------------------------------------------------- 1 | #include "qdram-config.h" 2 | #include "qdram.h" 3 | #include "qdram-sched.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | typedef Qcache::MemController mc_t; 12 | 13 | int main(int argc, char** argv) { 14 | mc_t *mc(new mc_t()); 15 | 16 | if (argc < 2) return 1; 17 | std::ifstream infile(argv[1]); 18 | 19 | bool readAddr(true), write; 20 | Qcache::addr_t addr; 21 | while (!!infile || !mc->empty()) { 22 | mc->tickBegin(); 23 | 24 | if (!!infile) { 25 | char c; 26 | infile >> addr >> c; 27 | write = (c == 'W'); 28 | 29 | if (!!infile) mc->access(addr, 0, 0, write); 30 | } 31 | 32 | mc->tickEnd(); 33 | //mc->printStats(); 34 | } 35 | 36 | mc->printStats(); 37 | 38 | delete(mc); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /qdram/qdram-event.h: -------------------------------------------------------------------------------- 1 | // A special-purpose event queue and scoreboard for DRAM constraints. 2 | #ifndef __QDRAM_EVENT_H 3 | #define __QDRAM_EVENT_H 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace Qcache { 10 | 11 | typedef uint64_t cycle_t; 12 | 13 | enum DramConstraint { 14 | CAN_USE_BUS, CAN_ACTIVATE, CAN_READ, 15 | CAN_WRITE, CAN_PRECHARGE, CAN_PDN, 16 | FAW_INC, N_CONSTRAINTS 17 | }; 18 | 19 | template class EventQueue { 20 | public: 21 | EventQueue(): eq(t.tMAX(), std::vector(N_CONSTRAINTS)), 22 | constraintCtr(N_CONSTRAINTS) {} 23 | 24 | void sched(cycle_t t, DramConstraint c) { 25 | if (!eq[t%eq.size()][c]) { 26 | eq[t%eq.size()][c] = true; 27 | ++constraintCtr[c]; 28 | } 29 | } 30 | 31 | void apply(cycle_t t) { 32 | for (unsigned i = 0; i < N_CONSTRAINTS; ++i) { 33 | if (eq[t%eq.size()][i]) { 34 | --constraintCtr[i]; 35 | eq[t%eq.size()][i] = false; 36 | } 37 | } 38 | } 39 | 40 | void enterPdn() { ++constraintCtr[CAN_PDN]; } 41 | void exitPdn() { --constraintCtr[CAN_PDN]; } 42 | 43 | bool check(DramConstraint c) { return !constraintCtr[c]; } 44 | bool fawCheck() { return constraintCtr[FAW_INC] < 4; } 45 | 46 | private: 47 | TIMING_T t; 48 | std::vector > eq; 49 | std::vector constraintCtr; 50 | }; 51 | 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /qdram/qdram-sched-fcfs.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtcasl/qsim/b1e33516426663f277a5da5b56b2b59d28fa5099/qdram/qdram-sched-fcfs.h -------------------------------------------------------------------------------- /qsim-arm-regs.h: -------------------------------------------------------------------------------- 1 | #ifndef __ARM_REGS_H 2 | #define __ARM_REGS_H 3 | 4 | //> ARM registers from Capstone 5 | typedef enum qsim_arm_reg { 6 | QSIM_ARM_INVALID = 0, 7 | QSIM_ARM_APSR, 8 | QSIM_ARM_APSR_NZCV, 9 | QSIM_ARM_CPSR, 10 | QSIM_ARM_FPEXC, 11 | QSIM_ARM_FPINST, 12 | QSIM_ARM_FPSCR, 13 | QSIM_ARM_FPSCR_NZCV, 14 | QSIM_ARM_FPSID, 15 | QSIM_ARM_ITSTATE, 16 | QSIM_ARM_LR, 17 | QSIM_ARM_PC, 18 | QSIM_ARM_SP, 19 | QSIM_ARM_SPSR, 20 | QSIM_ARM_D0, 21 | QSIM_ARM_D1, 22 | QSIM_ARM_D2, 23 | QSIM_ARM_D3, 24 | QSIM_ARM_D4, 25 | QSIM_ARM_D5, 26 | QSIM_ARM_D6, 27 | QSIM_ARM_D7, 28 | QSIM_ARM_D8, 29 | QSIM_ARM_D9, 30 | QSIM_ARM_D10, 31 | QSIM_ARM_D11, 32 | QSIM_ARM_D12, 33 | QSIM_ARM_D13, 34 | QSIM_ARM_D14, 35 | QSIM_ARM_D15, 36 | QSIM_ARM_D16, 37 | QSIM_ARM_D17, 38 | QSIM_ARM_D18, 39 | QSIM_ARM_D19, 40 | QSIM_ARM_D20, 41 | QSIM_ARM_D21, 42 | QSIM_ARM_D22, 43 | QSIM_ARM_D23, 44 | QSIM_ARM_D24, 45 | QSIM_ARM_D25, 46 | QSIM_ARM_D26, 47 | QSIM_ARM_D27, 48 | QSIM_ARM_D28, 49 | QSIM_ARM_D29, 50 | QSIM_ARM_D30, 51 | QSIM_ARM_D31, 52 | QSIM_ARM_FPINST2, 53 | QSIM_ARM_MVFR0, 54 | QSIM_ARM_MVFR1, 55 | QSIM_ARM_MVFR2, 56 | QSIM_ARM_Q0, 57 | QSIM_ARM_Q1, 58 | QSIM_ARM_Q2, 59 | QSIM_ARM_Q3, 60 | QSIM_ARM_Q4, 61 | QSIM_ARM_Q5, 62 | QSIM_ARM_Q6, 63 | QSIM_ARM_Q7, 64 | QSIM_ARM_Q8, 65 | QSIM_ARM_Q9, 66 | QSIM_ARM_Q10, 67 | QSIM_ARM_Q11, 68 | QSIM_ARM_Q12, 69 | QSIM_ARM_Q13, 70 | QSIM_ARM_Q14, 71 | QSIM_ARM_Q15, 72 | QSIM_ARM_R0, 73 | QSIM_ARM_R1, 74 | QSIM_ARM_R2, 75 | QSIM_ARM_R3, 76 | QSIM_ARM_R4, 77 | QSIM_ARM_R5, 78 | QSIM_ARM_R6, 79 | QSIM_ARM_R7, 80 | QSIM_ARM_R8, 81 | QSIM_ARM_R9, 82 | QSIM_ARM_R10, 83 | QSIM_ARM_R11, 84 | QSIM_ARM_R12, 85 | QSIM_ARM_S0, 86 | QSIM_ARM_S1, 87 | QSIM_ARM_S2, 88 | QSIM_ARM_S3, 89 | QSIM_ARM_S4, 90 | QSIM_ARM_S5, 91 | QSIM_ARM_S6, 92 | QSIM_ARM_S7, 93 | QSIM_ARM_S8, 94 | QSIM_ARM_S9, 95 | QSIM_ARM_S10, 96 | QSIM_ARM_S11, 97 | QSIM_ARM_S12, 98 | QSIM_ARM_S13, 99 | QSIM_ARM_S14, 100 | QSIM_ARM_S15, 101 | QSIM_ARM_S16, 102 | QSIM_ARM_S17, 103 | QSIM_ARM_S18, 104 | QSIM_ARM_S19, 105 | QSIM_ARM_S20, 106 | QSIM_ARM_S21, 107 | QSIM_ARM_S22, 108 | QSIM_ARM_S23, 109 | QSIM_ARM_S24, 110 | QSIM_ARM_S25, 111 | QSIM_ARM_S26, 112 | QSIM_ARM_S27, 113 | QSIM_ARM_S28, 114 | QSIM_ARM_S29, 115 | QSIM_ARM_S30, 116 | QSIM_ARM_S31, 117 | 118 | QSIM_ARM_ENDING, // <-- mark the end of the list or registers 119 | } qsim_arm_reg; 120 | 121 | static const char *arm_regs_str[] __attribute__((unused)) = { 122 | "r0", "r1", "r2", "r3", 123 | "r4", "r5", "r6", "r7", 124 | "r8", "r9", "r10", "r11", 125 | "r12", "r13", "r14", "r15", 126 | "cpsr", 127 | NULL 128 | }; 129 | 130 | uint64_t get_reg(int c, int r); 131 | void set_reg(int c, int r, uint64_t val ); 132 | 133 | #endif 134 | -------------------------------------------------------------------------------- /qsim-context.h: -------------------------------------------------------------------------------- 1 | #ifndef QSIM_CONTEXT_H 2 | #define QSIM_CONTEXT_H 3 | 4 | #if 0 5 | #if defined(__linux__) && (defined(__i386__) || defined(__x86_64__)) 6 | typedef struct { 7 | struct { 8 | size_t ss_size; 9 | void *ss_base; 10 | void *ss_sp; 11 | } uc_stack; 12 | void *uc_link; 13 | } qsim_ucontext_t; 14 | 15 | static void swapcontext(qsim_ucontext_t *from, qsim_ucontext_t *to) 16 | __attribute__((noinline)); 17 | static void makecontext(qsim_ucontext_t *p, void(*f)(void), unsigned args) 18 | __attribute__((noinline)); 19 | static void getcontext(qsim_ucontext_t *p); 20 | 21 | static __attribute__((unused)) void swapcontext(qsim_ucontext_t *from, qsim_ucontext_t *to) { 22 | #ifdef __i386__ 23 | asm("push %%ebp;" 24 | "push %%ebx;" 25 | "push %%esi;" 26 | "push %%edi;" 27 | "sub $6, %%esp;" 28 | "fstcw 4(%%esp);" 29 | "stmxcsr (%%esp);" 30 | "mov %%esp, (%%eax);" 31 | "mov (%%ecx), %%esp;" 32 | "ldmxcsr (%%esp);" 33 | "fldcw 4(%%esp);" 34 | "add $6, %%esp;" 35 | "pop %%edi;" 36 | "pop %%esi;" 37 | "pop %%ebx;" 38 | "pop %%ebp;" 39 | "leave;" 40 | "ret;" :: "a"(&(from->uc_stack.ss_sp)), "c"(&(to->uc_stack.ss_sp))); 41 | #elif __x86_64__ 42 | asm("push %%rdi;" // Save 'from' registers 43 | "push %%rbp;" 44 | "push %%rbx;" 45 | "push %%r12;" 46 | "push %%r13;" 47 | "push %%r14;" 48 | "push %%r15;" 49 | "sub $6, %%rsp;" 50 | "fstcw 4(%%rsp);" 51 | "stmxcsr (%%rsp);" 52 | "mov %%rsp, (%%rdi);"// Save old stack pointer 53 | "mov (%%rsi), %%rsp;"// Load new stack pointer 54 | "ldmxcsr (%%rsp);" 55 | "fldcw 4(%%rsp);" 56 | "add $6, %%rsp;" 57 | "pop %%r15;" // Restore 'to' registers 58 | "pop %%r14;" 59 | "pop %%r13;" 60 | "pop %%r12;" 61 | "pop %%rbx;" 62 | "pop %%rbp;" 63 | "pop %%rdi;" 64 | #ifndef __OPTIMIZE__ 65 | "leave;" 66 | #endif 67 | "ret;" :: "D"(&(from->uc_stack.ss_sp)), "S"(&(to->uc_stack.ss_sp))); 68 | #endif 69 | } 70 | 71 | static __attribute__((unused)) void makecontext(qsim_ucontext_t *p, void (*f)(void), unsigned args) { 72 | // Set initial stack pointer. The stack grows down, so the size is needed. 73 | p->uc_stack.ss_base = p->uc_stack.ss_sp; 74 | p->uc_stack.ss_sp += (size_t)p->uc_stack.ss_size - sizeof(void*)*9; 75 | 76 | void **stack = (void**)p->uc_stack.ss_sp; 77 | 78 | unsigned i; 79 | for (i = 2; i < 9; i++) stack[i] = (void*)(0x57ac0l + i); 80 | #ifdef __i386__ 81 | stack[4] = (void*)f; 82 | stack[5] = (void*)f; 83 | stack[3] = (void*)((char*)p->uc_stack.ss_sp + sizeof(void*)*4); 84 | p->uc_stack.ss_sp = (uint8_t*)stack - 6; 85 | asm("stmxcsr (%%eax); fstcw 4(%%eax);" :: "a"(p->uc_stack.ss_sp)); 86 | #elif __x86_64__ 87 | stack[7] = (void*)f; // One of these, depending on whether the 88 | stack[8] = (void*)f; // base pointer is saved. 89 | stack[5] = (void*)((char*)p->uc_stack.ss_sp + sizeof(void*)*7); // Init. bp 90 | p->uc_stack.ss_sp = (uint8_t*)stack - 6; 91 | asm("stmxcsr (%%rax); fstcw 4(%%rax);" :: "a"(p->uc_stack.ss_sp)); 92 | #endif 93 | } 94 | 95 | static __attribute__((unused)) void getcontext(qsim_ucontext_t *p) {} 96 | 97 | #endif 98 | #endif 99 | #include 100 | typedef ucontext_t qsim_ucontext_t; 101 | 102 | void qsim_swap_ctx(void); 103 | void qsim_swap(void *opaque); 104 | 105 | #endif 106 | 107 | -------------------------------------------------------------------------------- /qsim-func.h: -------------------------------------------------------------------------------- 1 | #ifndef __VM_FUNC_H 2 | #define __VM_FUNC_H 3 | /*****************************************************************************\ 4 | * Qemu Simulation Framework (qsim) * 5 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 6 | * a C++ API, for the use of computer architecture researchers. * 7 | * * 8 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 9 | * COPYING file in the top-level directory. * 10 | \*****************************************************************************/ 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #include 16 | #include 17 | #include "qsim-vm.h" 18 | 19 | // Functions that QEMU must export 20 | void qemu_init(const char* argv[]); 21 | 22 | uint64_t run(uint64_t n); 23 | uint64_t run_cpu(int i, uint64_t n); 24 | 25 | void set_atomic_cb(atomic_cb_t); 26 | void set_inst_cb (inst_cb_t ); 27 | void set_int_cb (int_cb_t ); 28 | void set_mem_cb (mem_cb_t ); 29 | void set_magic_cb (magic_cb_t ); 30 | void set_io_cb (io_cb_t ); 31 | void set_reg_cb (reg_cb_t ); 32 | void set_trans_cb (trans_cb_t ); 33 | void set_gen_cbs (bool state ); 34 | void set_sys_cbs (bool state ); 35 | 36 | #ifdef __cplusplus 37 | }; 38 | #endif 39 | #endif 40 | -------------------------------------------------------------------------------- /qsim-load.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #include 10 | 11 | #include 12 | 13 | #include "qsim-load.h" 14 | 15 | 16 | using namespace Qsim; 17 | using namespace std; 18 | 19 | class QsimLoadHelper { 20 | public: 21 | QsimLoadHelper(OSDomain &osd, ifstream &infile): 22 | osd(osd), infile(infile), finished(false) 23 | { 24 | 25 | // Set the callbacks. 26 | OSDomain::magic_cb_handle_t magic_handle( 27 | osd.set_magic_cb(this, &QsimLoadHelper::magic_cb) 28 | ); 29 | 30 | OSDomain::start_cb_handle_t app_start_handle( 31 | osd.set_app_start_cb(this, &QsimLoadHelper::app_start_cb) 32 | ); 33 | 34 | // The main loop: run until 'finished' is true. 35 | while (!finished) { 36 | osd.run(10000); 37 | osd.timer_interrupt(); 38 | } 39 | 40 | osd.run(finished_core, 1); 41 | 42 | // Unset the callbacks. 43 | osd.unset_magic_cb(magic_handle); 44 | osd.unset_app_start_cb(app_start_handle); 45 | } 46 | 47 | private: 48 | OSDomain &osd; 49 | ifstream &infile; 50 | bool finished; 51 | int finished_core; 52 | 53 | int app_start_cb(int c) { 54 | finished = true; 55 | finished_core = c; 56 | osd.set_bench_pid(osd.get_tid(c)); 57 | return 1; 58 | } 59 | 60 | int magic_cb(int c, uint64_t rax) { 61 | 62 | static int addr_reg, size_reg, ready_reg; 63 | 64 | if (osd.getCpuType(0) == "x86") { 65 | addr_reg = QSIM_X86_RBX; 66 | size_reg = QSIM_X86_RCX; 67 | ready_reg = QSIM_X86_RAX; 68 | } else { 69 | addr_reg = QSIM_ARM64_X1; 70 | size_reg = QSIM_ARM64_X2; 71 | ready_reg = QSIM_ARM64_X0; 72 | } 73 | 74 | if (rax == 0xc5b1fffd) { 75 | // Giving an address to deposit 1024 bytes in %rbx. Wants number of bytes 76 | // actually deposited in %rcx. 77 | 78 | uint64_t vaddr = osd.get_reg(c, addr_reg); 79 | int count = 1024; 80 | while (infile.good() && count) { 81 | char ch; 82 | infile.get(ch); 83 | osd.mem_wr_virt(c, ch, vaddr++); 84 | count--; 85 | } 86 | osd.set_reg(c, size_reg, 1024-count); 87 | } else if (rax == 0xc5b1fffe) { 88 | // Asking if input is ready 89 | osd.set_reg(c, ready_reg, !(!infile)); 90 | } else if (rax == 0xc5b1ffff) { 91 | // Asking for a byte of input. 92 | char ch; 93 | infile.get(ch); 94 | osd.set_reg(c, ready_reg, ch); 95 | } else if ((rax & 0xffffff00) == 0xc5b100) { 96 | std::cout << "binary write: " << (rax&0xff) << '\n'; 97 | } else if (rax == 0xc5b1fffc) { 98 | osd.set_n(osd.get_reg(c, addr_reg)); 99 | } 100 | 101 | return 0; 102 | } 103 | }; 104 | 105 | void Qsim::load_file(OSDomain &osd, const char *filename) { 106 | ifstream infile(filename); 107 | if (infile.fail()) { 108 | std::cerr << "Error: Could not open benchmark tar " << filename << std::endl; 109 | exit(1); 110 | } 111 | 112 | QsimLoadHelper qlh(osd, infile); 113 | infile.close(); 114 | } 115 | -------------------------------------------------------------------------------- /qsim-load.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #ifndef __QSIM_LOAD_H 10 | #define __QSIM_LOAD_H 11 | 12 | #include 13 | 14 | namespace Qsim { 15 | void load_file(Qsim::OSDomain &osd, const char *filename); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /qsim-prof.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | #include 19 | 20 | using namespace Qsim; 21 | using namespace std; 22 | 23 | class QsimProf { 24 | public: 25 | QsimProf(OSDomain &osd, const char *filename, unsigned w, unsigned s): 26 | tr(filename), osd(osd), w(w), s(s), t(osd.get_n()) 27 | { 28 | pthread_mutex_init(&trLock, NULL); 29 | icbH = osd.set_inst_cb(this, &QsimProf::inst_cb); 30 | } 31 | 32 | ~QsimProf() { 33 | //osd.unset_inst_cb(icbH); 34 | tr.close(); 35 | } 36 | 37 | void inst_cb(int c, uint64_t va, uint64_t pa, uint8_t len, const uint8_t *b, 38 | enum inst_type type) 39 | { 40 | if (++t[c].windowCount == w) t[c].windowCount = 0; 41 | if (t[c].windowCount == 0) { 42 | t[c].samp.clear(); 43 | for (unsigned i = 0; i < s; ++i) t[c].samp.insert(rand()%w); 44 | } 45 | 46 | if (t[c].samp.find(t[c].windowCount) != t[c].samp.end()) { 47 | pthread_mutex_lock(&trLock); 48 | tr << std::dec << c << ", " << va << ", " 49 | << (osd.get_prot(c) == OSDomain::PROT_KERN) << ", "; 50 | for (unsigned i = 0; i < len; ++i) 51 | tr << std::hex << setw(2) << setfill('0') << (unsigned)b[i] << ' '; 52 | tr << '\n'; 53 | pthread_mutex_unlock(&trLock); 54 | } 55 | } 56 | 57 | private: 58 | struct Thread { 59 | Thread(): samp(), windowCount(0) {} 60 | set samp; 61 | unsigned windowCount; 62 | unsigned char padding[64]; 63 | }; 64 | 65 | OSDomain::inst_cb_handle_t icbH; 66 | 67 | pthread_mutex_t trLock; 68 | ofstream tr; 69 | 70 | OSDomain &osd; 71 | unsigned w, s; 72 | 73 | vector t; 74 | }; 75 | 76 | static QsimProf *prof(NULL); 77 | 78 | void Qsim::start_prof(OSDomain &osd, const char *tracefile, 79 | unsigned window, unsigned samplesPerWindow) 80 | { 81 | prof = new QsimProf(osd, tracefile, window, samplesPerWindow); 82 | } 83 | 84 | void Qsim::end_prof(OSDomain &osd) { 85 | if (prof) delete(prof); 86 | } 87 | -------------------------------------------------------------------------------- /qsim-prof.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #ifndef __QSIM_PROF_H 10 | #define __QSIM_PROF_H 11 | 12 | #include 13 | 14 | namespace Qsim { 15 | void start_prof(Qsim::OSDomain &osd, const char *tracefile, 16 | unsigned window=1000000, unsigned samples_per_window=10); 17 | void end_prof(Qsim::OSDomain &osd); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /qsim-regs.h: -------------------------------------------------------------------------------- 1 | #ifndef __QSIM_REGS_H 2 | #define __QSIM_REGS_H 3 | /*****************************************************************************\ 4 | * Qemu Simulation Framework (qsim) * 5 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 6 | * a C++ API, for the use of computer architecture researchers. * 7 | * * 8 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 9 | * COPYING file in the top-level directory. * 10 | \*****************************************************************************/ 11 | 12 | #include "qsim-x86-regs.h" 13 | #include "qsim-arm64-regs.h" 14 | #include "qsim-arm-regs.h" 15 | 16 | /* 17 | union regs { 18 | enum _x86_regs x86_regs; 19 | enum _a64_regs a64_regs; 20 | enum _arm_regs arm_regs; 21 | 22 | regs& operator=(const _x86_regs& rhs); 23 | regs& operator=(const _a64_regs& rhs); 24 | regs& operator=(const _arm_regs& rhs); 25 | regs(int i) { memset(this, i, sizeof(*this));} 26 | }; 27 | */ 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /qsim-vm.h: -------------------------------------------------------------------------------- 1 | #ifndef __VM_H 2 | #define __VM_H 3 | /*****************************************************************************\ 4 | * Qemu Simulation Framework (qsim) * 5 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 6 | * a C++ API, for the use of computer architecture researchers. * 7 | * * 8 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 9 | * COPYING file in the top-level directory. * 10 | \*****************************************************************************/ 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | #include 15 | #include 16 | 17 | /* Possible values for "type" field of instruction callbacks. */ 18 | enum inst_type { 19 | QSIM_INST_NULL, /* NOP or load/store only. */ 20 | QSIM_INST_INTBASIC, /* Simple ALU operation. */ 21 | QSIM_INST_INTMUL, 22 | QSIM_INST_INTDIV, 23 | QSIM_INST_STACK, 24 | QSIM_INST_BR, /* Branch. */ 25 | QSIM_INST_CALL, 26 | QSIM_INST_RET, 27 | QSIM_INST_TRAP, /* Interrupt/syscall. */ 28 | QSIM_INST_FPBASIC, /* Floating point add, subtract */ 29 | QSIM_INST_FPMUL, 30 | QSIM_INST_FPDIV 31 | }; 32 | 33 | enum qsim_mode { 34 | QSIM_HEADLESS, 35 | QSIM_INTERACTIVE, 36 | QSIM_KVM, 37 | QSIM_NUM_MODES 38 | }; 39 | 40 | typedef void (*inst_cb_t)(int cpu_id, uint64_t vaddr, uint64_t paddr, 41 | uint8_t length, const uint8_t *bytes, 42 | enum inst_type type); 43 | typedef void (*mem_cb_t)(int cpu_id, uint64_t vaddr, uint64_t paddr, 44 | uint8_t size, int type); 45 | typedef uint32_t* (*io_cb_t) (int cpu_id, uint64_t addr, uint8_t size, 46 | int type, uint32_t val); 47 | 48 | typedef int (*int_cb_t)(int cpu_id, uint8_t vector); 49 | typedef int (*magic_cb_t) (int cpu_id, uint64_t rax); 50 | typedef int (*atomic_cb_t)(int cpu_id); 51 | typedef void (*reg_cb_t)(int cpu_id, int reg, uint8_t val, int type); 52 | typedef void (*trans_cb_t)(int cpu_id); 53 | 54 | #ifdef __cplusplus 55 | }; 56 | #endif 57 | #endif 58 | -------------------------------------------------------------------------------- /qsim-x86-regs.h: -------------------------------------------------------------------------------- 1 | #ifndef __x86_REGS_H 2 | #define __x86_REGS_H 3 | /*****************************************************************************\ 4 | * Qemu Simulation Framework (qsim) * 5 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 6 | * a C++ API, for the use of computer architecture researchers. * 7 | * * 8 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 9 | * COPYING file in the top-level directory. * 10 | \*****************************************************************************/ 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /* The ordering here is important: it is the order in which registers are saved 17 | and restored when we save or restore a machine state. */ 18 | enum qsim_x86_reg { 19 | QSIM_X86_RAX = 0, QSIM_X86_RCX, QSIM_X86_RDX, QSIM_X86_RBX, 20 | QSIM_X86_RSP, QSIM_X86_RBP, 21 | QSIM_X86_RSI, QSIM_X86_RDI, 22 | QSIM_X86_R7, QSIM_X86_R8, QSIM_X86_R9, QSIM_X86_R10, 23 | QSIM_X86_R11, QSIM_X86_R12, QSIM_X86_R13, QSIM_X86_R14, QSIM_X86_R15, 24 | QSIM_X86_FP0, QSIM_X86_FP1, QSIM_X86_FP2, QSIM_X86_FP3, QSIM_X86_FP4, QSIM_X86_FP5, QSIM_X86_FP6, QSIM_X86_FP7, QSIM_X86_FPSP, 25 | QSIM_X86_CR0, QSIM_X86_CR2, QSIM_X86_CR3, QSIM_X86_CR4, 26 | QSIM_X86_GDTB, QSIM_X86_IDTB, QSIM_X86_GDTL, QSIM_X86_IDTL, 27 | QSIM_X86_TR, QSIM_X86_TRB, QSIM_X86_TRL, QSIM_X86_TRF, 28 | QSIM_X86_LDT, QSIM_X86_LDTB, QSIM_X86_LDTL, QSIM_X86_LDTF, 29 | QSIM_X86_DR6, QSIM_X86_DR7, 30 | QSIM_X86_ES, QSIM_X86_CS, QSIM_X86_SS, QSIM_X86_DS, QSIM_X86_FS, QSIM_X86_GS, 31 | QSIM_X86_ESB, QSIM_X86_CSB, QSIM_X86_SSB, QSIM_X86_DSB, QSIM_X86_FSB, QSIM_X86_GSB, 32 | QSIM_X86_ESL, QSIM_X86_CSL, QSIM_X86_SSL, QSIM_X86_DSL, QSIM_X86_FSL, QSIM_X86_GSL, 33 | QSIM_X86_ESF, QSIM_X86_CSF, QSIM_X86_SSF, QSIM_X86_DSF, QSIM_X86_FSF, QSIM_X86_GSF, 34 | QSIM_X86_RIP, QSIM_X86_RFLAGS, 35 | QSIM_X86_HFLAGS, QSIM_X86_HFLAGS2, 36 | QSIM_X86_SE_CS, QSIM_X86_SE_SP, QSIM_X86_SE_IP, 37 | QSIM_X86_N_REGS 38 | }; 39 | 40 | /* This has to be manually kept consistent with the above. Ugly, I know. */ 41 | static const char *x86_regs_str[] __attribute__((unused)) = { 42 | "rax", "rcx", "rdx", "rbx", 43 | "rsp", "rbp", 44 | "rsi", "rdi", 45 | "cr0", "cr2", "cr3", "cr4", 46 | "gdtb", "idtb", "gdtl", "idtl", 47 | "tr", "trb", "trl", "trf", 48 | "ldt", "ldtb", "ldtl", "ldtf", 49 | "dr6", "dr7", 50 | "es", "cs", "ss", "ds", "fs", "gs", 51 | "esb", "csb", "ssb", "dsb", "fsb", "gsb", 52 | "esl", "csl", "ssl", "dsl", "fsl", "gsl", 53 | "esf", "csf", "ssf", "dsf", "fsf", "gsf", 54 | "rip", "rflags", 55 | "hflags", "hflags2", 56 | "se_cs", "se_sp", "se_ip", 57 | NULL 58 | }; 59 | 60 | /* The flags enum is used with the register access callback (size=0) to signal 61 | condition code access. */ 62 | enum flags { 63 | QSIM_FLAG_OF = 0x01, 64 | QSIM_FLAG_SF = 0x02, 65 | QSIM_FLAG_ZF = 0x04, 66 | QSIM_FLAG_AF = 0x08, 67 | QSIM_FLAG_PF = 0x10, 68 | QSIM_FLAG_CF = 0x20 69 | }; 70 | 71 | /* Flags touched when the flags register is modified, and written by 72 | add/subtract instructions. */ 73 | #define QSIM_FLAG_ALL (QSIM_FLAG_OF|QSIM_FLAG_SF|QSIM_FLAG_ZF|QSIM_FLAG_AF|\ 74 | QSIM_FLAG_PF|QSIM_FLAG_CF) 75 | 76 | /* Flags written by increment/decrement instructions: */ 77 | #define QSIM_FLAG_INC (QSIM_FLAG_OF|QSIM_FLAG_SF|QSIM_FLAG_ZF|QSIM_FLAG_AF|\ 78 | QSIM_FLAG_PF) 79 | 80 | /* Flags written by bitwise logic instructions: */ 81 | #define QSIM_FLAG_LOG (QSIM_FLAG_OF|QSIM_FLAG_SF|QSIM_FLAG_ZF|QSIM_FLAG_PF|\ 82 | QSIM_FLAG_CF) 83 | 84 | /* Flags written by rotate instructions: */ 85 | #define QSIM_FLAG_ROT (QSIM_FLAG_OF|QSIM_FLAG_CF) 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | 91 | #endif /* __x86_REGS_H */ 92 | -------------------------------------------------------------------------------- /qsim_magic.h: -------------------------------------------------------------------------------- 1 | #ifndef _QSIM_MAGIC_H 2 | #define _QSIM_MAGIC_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined(__arm__) || defined(__aarch64__) 9 | 10 | #define qsim_magic_enable() \ 11 | asm volatile("msr pmcr_el0, %0" :: "r" (0xaaaaaaaa)); 12 | #define qsim_magic_disable() \ 13 | asm volatile("msr pmcr_el0, %0" :: "r" (0xfa11dead)); 14 | 15 | #elif defined(__i386__) || defined(__x86_64__) 16 | 17 | #define qsim_magic_enable() \ 18 | asm volatile("cpuid;"::"a"(0xaaaaaaaa):"ebx","ecx","edx"); 19 | #define qsim_magic_disable() \ 20 | asm volatile("cpuid;"::"a"(0xfa11dead):"ebx","ecx","edx"); 21 | 22 | #endif 23 | 24 | #define APP_START() qsim_magic_enable() 25 | #define APP_END() qsim_magic_disable() 26 | 27 | __attribute__((unused)) 28 | static void qsim_sig_handler(int signo) 29 | { 30 | char c; 31 | qsim_magic_disable(); 32 | printf("Callbacks disabled. Quit(y/n)?"); 33 | scanf("%c", &c); 34 | 35 | if (c == 'y') 36 | exit(0); 37 | } 38 | 39 | #define qsim_init() \ 40 | do { \ 41 | signal(SIGINT, qsim_sig_handler); \ 42 | } while(0); 43 | 44 | #endif /* _QSIM_MAGIC_H */ 45 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Run this script to set up the qsim environment for the first time. 4 | # You can read the following steps to see what each is doing. 5 | # 6 | # Author: Pranith Kumar 7 | # Date: 01/05/2016 8 | # Usage: ./setup.sh {arm64} 9 | 10 | bold=$(tput bold) 11 | normal=$(tput sgr0) 12 | 13 | ARCH=`uname -m` 14 | 15 | # setup the aarch64 toolchain 16 | aarch64_tool=$PWD/tools/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu 17 | 18 | if command -v aarch64-linux-gnu-gcc >/dev/null 2>&1 ; then 19 | echo -e "AARCH64 toolchain is already installed!" 20 | else 21 | echo -e "\nAARCH64 toolchain is not set, download from linaro website..." 22 | echo -e "Press any key to continue..." 23 | read inp 24 | mkdir -p tools 25 | cd tools 26 | wget -c "https://github.com/gtcasl/qsim_prebuilt/releases/download/v0.1/aarch64_toolchain.tar.xz" 27 | echo -e "\nUncompressing the toolchain..." 28 | tar -xf aarch64_toolchain.tar.xz 29 | export PATH="$PATH:$aarch64_tool/bin" 30 | echo -e "\n\nAdd the following lines to your bashrc:\n" 31 | echo -e "${bold}export PATH=\$PATH:\$QSIM_PREFIX/tools/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin${normal}" 32 | cd .. 33 | fi 34 | 35 | # set the QSIM environment variable 36 | echo -e "Setting QSIM environment variable..." 37 | export QSIM_PREFIX=`pwd` 38 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QSIM_PREFIX/lib 39 | echo -e "\n\nAdd the following lines to your bashrc:\n" 40 | echo -e "${bold}export QSIM_PREFIX=$QSIM_PREFIX${bold}" 41 | echo -e "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$QSIM_PREFIX/lib${normal}\n" 42 | echo -e "Press any key to continue..." 43 | read inp 44 | 45 | echo -e "\n\nDown QEMU OS images? This will take a while. (y/N):" 46 | read inp 47 | 48 | if [ "$inp" = "y" -o "$inp" = "Y" ]; then 49 | # get qemu images 50 | echo -e "\nDownloading arm QEMU images..." 51 | mkdir -p images 52 | cd images 53 | wget -c https://github.com/gtcasl/qsim_prebuilt/releases/download/v0.1/arm64_images.tar.xz 54 | wget -c https://github.com/gtcasl/qsim_prebuilt/releases/download/v0.1/x86_64_images.tar.xz 55 | 56 | echo -e "\nUncompresssing images. This might take a while..." 57 | tar -xf arm64_images.tar.xz 58 | tar -xf x86_64_images.tar.xz 59 | cd $QSIM_PREFIX 60 | fi 61 | 62 | # update submodules 63 | git submodule update --init 64 | echo -e "Building capstone disassembler..." 65 | cd capstone 66 | make -j4 67 | echo -e "Building distorm disassembler..." 68 | cd ../distorm/distorm64/build/linux 69 | make clib 2> /dev/null 70 | cd $QSIM_PREFIX 71 | echo -e "Get qemu submodules..." 72 | cd qemu 73 | git submodule update --init pixman 74 | git submodule update --init dtc 75 | cd $QSIM_PREFIX 76 | 77 | # build linux kernel and initrd 78 | echo -e "Building Linux kernel..." 79 | cd linux 80 | ./getkernel.sh 81 | if [ "$HOST" != "aarch64" ]; then 82 | ./getkernel.sh arm64 83 | fi 84 | cd $QSIM_PREFIX 85 | 86 | # build qemu 87 | echo -e "\nConfiguring and building qemu...\n" 88 | ./build-qemu.sh release 89 | 90 | # build qsim 91 | # copy header files to include directory 92 | make release install 93 | 94 | echo -e "\n\nBuilding busybox" 95 | cd initrd/ 96 | ./getbusybox.sh 97 | if [ "$HOST" != "aarch64" ]; then 98 | ./getbusybox.sh arm64 99 | fi 100 | cd $QSIM_PREFIX 101 | 102 | # run tests 103 | make tests 104 | # run simple example 105 | # echo -e "Running the cache simulator example..." 106 | # cd qsim/arm-examples/ 107 | # make && ./cachesim 108 | 109 | if [ $? -eq "0" ]; then 110 | echo -e "\n${bold}Setup finished successfully!${normal}" 111 | fi 112 | -------------------------------------------------------------------------------- /setup_sudo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Run this script to set up the qsim environment for the first time. 4 | # You can read the following steps to see what each is doing. 5 | # 6 | # Author: Pranith Kumar 7 | # Date: 01/05/2016 8 | # Usage: ./setup.sh {arm64} 9 | 10 | bold=$(tput bold) 11 | normal=$(tput sgr0) 12 | 13 | ARCH=`uname -m` 14 | 15 | # setup the aarch64 toolchain 16 | aarch64_tool=$PWD/tools/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu 17 | 18 | if command -v aarch64-linux-gnu-gcc >/dev/null 2>&1 ; then 19 | echo -e "AARCH64 toolchain is already installed!" 20 | else 21 | echo -e "\nAARCH64 toolchain is not set, download from linaro website..." 22 | echo -e "Press any key to continue..." 23 | read inp 24 | mkdir -p tools 25 | cd tools 26 | wget -c "https://github.com/gtcasl/qsim_prebuilt/releases/download/v0.1/aarch64_toolchain.tar.xz" 27 | echo -e "\nUncompressing the toolchain..." 28 | tar -xf aarch64_toolchain.tar.xz 29 | export PATH="$PATH:$aarch64_tool/bin" 30 | echo -e "\n\nAdd the following lines to your bashrc:\n" 31 | echo -e "${bold}export PATH=\$PATH:\$QSIM_PREFIX/tools/gcc-linaro-5.3-2016.02-x86_64_aarch64-linux-gnu/bin${normal}" 32 | cd .. 33 | fi 34 | 35 | # set the QSIM environment variable 36 | echo -e "Setting QSIM environment variable..." 37 | export QSIM_PREFIX=`pwd` 38 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QSIM_PREFIX/lib 39 | echo -e "\n\nAdd the following lines to your bashrc:\n" 40 | echo -e "${bold}export QSIM_PREFIX=$QSIM_PREFIX${bold}" 41 | echo -e "export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$QSIM_PREFIX/lib${normal}\n" 42 | echo -e "Press any key to continue..." 43 | read inp 44 | 45 | echo -e "\n\nDown QEMU OS images? This will take a while. (y/N):" 46 | read inp 47 | 48 | # Install dependencies 49 | if hash apt-get 2>/dev/null; then 50 | echo "Installing dependencies..." 51 | echo "sudo apt-get -y build-dep qemu" 52 | sudo apt-get -y build-dep qemu 53 | #sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu 54 | else 55 | echo "please refer to Qsim manual for installation dependencies" 56 | echo "Press any key to continue..." 57 | read dump 58 | fi 59 | 60 | if [ "$inp" = "y" -o "$inp" = "Y" ]; then 61 | # get qemu images 62 | echo -e "\nDownloading arm QEMU images..." 63 | mkdir -p images 64 | cd images 65 | wget -c https://github.com/gtcasl/qsim_prebuilt/releases/download/v0.1/arm64_images.tar.xz 66 | wget -c https://github.com/gtcasl/qsim_prebuilt/releases/download/v0.1/x86_64_images.tar.xz 67 | 68 | echo -e "\nUncompresssing images. This might take a while..." 69 | tar -xf arm64_images.tar.xz 70 | tar -xf x86_64_images.tar.xz 71 | cd $QSIM_PREFIX 72 | fi 73 | 74 | # update submodules 75 | git submodule update --init 76 | echo -e "Building capstone disassembler..." 77 | cd capstone 78 | make -j4 79 | echo -e "Building distorm disassembler..." 80 | cd ../distorm/distorm64/build/linux 81 | make clib 2> /dev/null 82 | cd $QSIM_PREFIX 83 | echo -e "Get qemu submodules..." 84 | cd qemu 85 | git submodule update --init pixman 86 | git submodule update --init dtc 87 | cd $QSIM_PREFIX 88 | 89 | # build linux kernel and initrd 90 | echo -e "Building Linux kernel..." 91 | cd linux 92 | ./getkernel.sh 93 | if [ "$HOST" != "aarch64" ]; then 94 | ./getkernel.sh arm64 95 | fi 96 | cd $QSIM_PREFIX 97 | 98 | # build qemu 99 | echo -e "\nConfiguring and building qemu...\n" 100 | ./build-qemu.sh release 101 | 102 | # build qsim 103 | # copy header files to include directory 104 | make release install 105 | 106 | echo -e "\n\nBuilding busybox" 107 | cd initrd/ 108 | ./getbusybox.sh 109 | if [ "$HOST" != "aarch64" ]; then 110 | ./getbusybox.sh arm64 111 | fi 112 | cd $QSIM_PREFIX 113 | 114 | # run tests 115 | make tests 116 | # run simple example 117 | # echo "Running the cache simulator example..." 118 | # cd qsim/arm-examples/ 119 | # make && ./cachesim 120 | 121 | if [ $? -eq "0" ]; then 122 | echo -e "\n${bold}Setup finished successfully!${normal}" 123 | fi 124 | -------------------------------------------------------------------------------- /simplesim/Makefile: -------------------------------------------------------------------------------- 1 | QSIM_PREFIX?=/usr/local 2 | 3 | # Choose a CXXFLAGS. One for production, one for profiling, and one for debug. 4 | CXXFLAGS = -O3 -I$(QSIM_PREFIX)/include 5 | #CXXFLAGS = -g -pg -O0 6 | #CXXFLAGS = -g -O0 -DDEBUG -DVERBOSE_DEBUG -I$(QSIM_PREFIX)/include -pthread 7 | LDFLAGS = -L$(QSIM_PREFIX)/lib -lqsim -ldl -pthread 8 | 9 | main : main.cpp data.o data.h cpu.o cpu.h cache.o cache.h des.o des.h 10 | 11 | des.o : des.cpp des.h 12 | data.o : data.cpp data.h 13 | cache.o : cache.cpp cache.h data.h des.h debug.h 14 | cpu.o : cpu.cpp cpu.h cache.h data.h des.h debug.h 15 | 16 | clean: 17 | rm -f *.o *~ \#* main 18 | -------------------------------------------------------------------------------- /simplesim/README: -------------------------------------------------------------------------------- 1 | SimpleSim Readme 2 | ================ 3 | 4 | SimpleSim is a simple computer system simulator using the QSim emulation infrastructure. It 5 | provides a processor pipeline model for the back-end (issue through retirement) of an out-of- 6 | order x86 core. 7 | 8 | Discrete Event Simulator 9 | ------------------------ 10 | 11 | Code for the discrete event simulator is in des.h and des.cpp. The SimpleSim DES provides a 12 | prioritized cycle-based simulation. The interface is primarily through the following: 13 | 14 | uint64_t Slide::_now 15 | 16 | The current simulation cycle. 17 | 18 | bool Slide::_advance(uint64_t) 19 | 20 | Advance the simulation to cycle t. 21 | 22 | bool Slide::_tick() 23 | 24 | Run the next event. Return true if more events remain to process. 25 | 26 | void Slide::_terminate() 27 | 28 | Stop the simulation before the next event is processed. 29 | 30 | template void Slide::schedule(uint64_t t, T* o, void (*f)(T*), uint8_t p) 31 | 32 | Call member f of object pointed to by o t cycles into the future, with priority p. This can be 33 | used with t=0 to insert events into the queue to happen within the same simulation cycle as 34 | called. Events are allowed to create new events with higher priority (smaller p). 35 | 36 | Memory System 37 | ------------- 38 | 39 | The memory system is made of a hierarchy of MemSysDevice objects, usually a CPU, a collection 40 | of coherent caches, and a memory controller. Memory system objects (other than the CPU) are 41 | defined in cache.h and cache.cpp. 42 | 43 | CPU 44 | --- 45 | 46 | There are several options in SimpleSim for simulated CPU. These options, defined in cpu.h and 47 | cpu.cpp, including: 48 | 49 | SimpleSim::RandomCpu 50 | 51 | Connects to a single lower-level memory device and sends sequential requests, randomly 52 | switching to alternate base addresses. Does not depend on QSim. 53 | 54 | SimpleSim::SimpleCpu 55 | 56 | Connects to a QSim instance, blocks on stalled memory requests (both load/store and fetch), 57 | otherwise executes one instruction per cycle. SimpleCpu connects to separate instruction and 58 | data MemSysDevice objects, which are considered peers on the coherence network. 59 | 60 | SimpleSim::SuperscalarCpu 61 | 62 | main.cpp 63 | -------- 64 | 65 | This file is responsible for wiring up and running the simulation. -------------------------------------------------------------------------------- /simplesim/cache.h: -------------------------------------------------------------------------------- 1 | #ifndef __CACHE_H 2 | #define __CACHE_H 3 | 4 | #include "des.h" 5 | #include "data.h" 6 | #include "debug.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace SimpleSim { 14 | typedef uint64_t addr_t; 15 | 16 | class MemReq; 17 | 18 | class MemSysDevice { 19 | public: 20 | virtual ~MemSysDevice() {} 21 | 22 | virtual void req(MemReq *mr) = 0; 23 | virtual void resp(MemReq *mr) = 0; 24 | }; 25 | 26 | class MemReq { 27 | public: 28 | MemReq(addr_t addr, bool wr): addr(addr), wr(wr), respStack() {} 29 | 30 | void pushDev(MemSysDevice *d) { respStack.push(d); } 31 | 32 | void resp() { 33 | ASSERT(!respStack.empty()); 34 | MemSysDevice *msd(respStack.top()); 35 | respStack.pop(); 36 | msd->resp(this); 37 | } 38 | 39 | addr_t getAddr() { return addr; } 40 | bool getWr() { return wr; } 41 | void setWr(bool w) { wr = w; } 42 | bool atOrig() { return respStack.empty(); } 43 | bool operator==(MemReq &r) { return (addr == r.addr) && (wr == r.wr); } 44 | 45 | private: 46 | addr_t addr; 47 | bool wr; 48 | std::stack respStack; 49 | }; 50 | 51 | class Cache : public MemSysDevice { 52 | public: 53 | Cache(unsigned lvl, unsigned id, unsigned l2Linesize, 54 | unsigned l2Sets, unsigned ways, const char *nameaddendum="U"); 55 | 56 | void addPeer(Cache* p) { peers.push_back(p); } 57 | void setLowerLevel(MemSysDevice *ll) { lowerLevel = ll; } 58 | 59 | virtual void req(MemReq *mr); 60 | virtual void resp(MemReq *mr); 61 | 62 | private: 63 | struct Line; 64 | 65 | Line *lookup(addr_t addr, unsigned &set, unsigned &way); 66 | void broadcastInvalidate(addr_t addr); 67 | void broadcastShare(addr_t addr); 68 | 69 | void invalidateReq(addr_t addr); 70 | void shareReq(addr_t addr); 71 | 72 | void doResp(MemReq *mr); 73 | void doLowerLevelReq(MemReq *mr); 74 | 75 | Line *evictIfNeeded(unsigned set, bool &writeBack); 76 | 77 | struct Line { 78 | Line() : state('i') {} 79 | addr_t base; 80 | char state; // 'm', 's', or 'i' 81 | }; 82 | 83 | std::string name; 84 | unsigned l2Linesize, l2Sets, ways; 85 | std::vector peers; 86 | std::vector > array; 87 | Counter outstandingReqs, completedReqs, totalWrites, misses, invalidates; 88 | MemSysDevice *lowerLevel; 89 | }; 90 | 91 | class DramController : public MemSysDevice { 92 | public: 93 | DramController(unsigned d): 94 | delayCycles(d), 95 | outstandingReqs(std::string("DramController:outstandingReqs"), false), 96 | completedReqs(std::string("DramController:completedReqs")), 97 | outstandingWrites(std::string("DramController:outstandingWrites"), false), 98 | completedWrites(std::string("DramController:completedWrites")) {} 99 | 100 | void req(MemReq *mr); 101 | void resp(MemReq *mr) { throw "Sent memory response to DramController."; } 102 | 103 | private: 104 | void doResp(MemReq *mr); 105 | 106 | Counter outstandingReqs, completedReqs, outstandingWrites, completedWrites; 107 | unsigned delayCycles; 108 | }; 109 | 110 | }; 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /simplesim/data.cpp: -------------------------------------------------------------------------------- 1 | #include "data.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | std::map SimpleSim::Counter::counterReg; 8 | std::set SimpleSim::Counter::resetSet; 9 | typedef std::map::iterator CRegIt; 10 | typedef std::set::iterator ResetIt; 11 | 12 | void SimpleSim::Counter::resetAll() { 13 | for (ResetIt i = resetSet.begin(); i != resetSet.end(); i++) **i = 0; 14 | } 15 | 16 | void SimpleSim::Counter::printAll(std::ostream &os) { 17 | for (CRegIt i = counterReg.begin(); i != counterReg.end(); i++) { 18 | os << i->first << ", " << i->second << '\n'; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /simplesim/data.h: -------------------------------------------------------------------------------- 1 | #ifndef __DATA_H 2 | #define __DATA_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace SimpleSim { 15 | class Counter { 16 | public: 17 | // Default constructor for temporaries leaves ptr NULL 18 | Counter(): ptr(NULL) {} 19 | 20 | Counter(std::string name, bool resettable = true): ptr(&counterReg[name]) { 21 | if (resettable) resetSet.insert(ptr); 22 | } 23 | 24 | operator long long() { return *ptr; } 25 | 26 | Counter &operator++() { ++(*ptr); return *this; } 27 | Counter &operator--() { --(*ptr); return *this; } 28 | 29 | unsigned operator++(int) { return (*ptr)++; } 30 | unsigned operator--(int) { return (*ptr)--; } 31 | 32 | unsigned operator+=(unsigned n) { return *ptr += n; } 33 | unsigned operator-=(unsigned n) { return *ptr -= n; } 34 | 35 | static void printAll(std::ostream &os); 36 | static void resetAll(); 37 | 38 | private: 39 | int64_t *ptr; 40 | 41 | static std::map counterReg; 42 | static std::set resetSet; 43 | }; 44 | 45 | template std::string toStr(T &x) { 46 | std::ostringstream os; 47 | os << x; 48 | return os.str(); 49 | } 50 | 51 | static inline double fRand() { 52 | int r = rand(); 53 | return r/((double)RAND_MAX+1); 54 | } 55 | 56 | static inline unsigned uniformRand (unsigned max) { 57 | return (unsigned)(fRand()*max); 58 | } 59 | 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /simplesim/debug.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEBUG_H 2 | #define __DEBUG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef DEBUG 9 | #define ASSERT(x) do { \ 10 | if (!(x)) { \ 11 | std::cout << "Failed assertion \"" #x "\" in " << __FILE__ << ':' << \ 12 | std::dec << __LINE__ << ".\n"; \ 13 | exit(1); \ 14 | } \ 15 | } while (0) 16 | #else 17 | #define ASSERT(x) do {} while (0) 18 | #endif 19 | 20 | #ifdef VERBOSE_DEBUG 21 | #define DBG(x) do { \ 22 | std::cout << x; \ 23 | } while (0) 24 | 25 | #define IFDBG(x) do { \ 26 | x; \ 27 | } while(0) 28 | #else 29 | #define DBG(x) do {} while (0) 30 | #define IFDBG(x) do {} while(0) 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /simplesim/des.cpp: -------------------------------------------------------------------------------- 1 | // Build this for the stand-alone DES. 2 | 3 | #include "des.h" 4 | #include 5 | #include 6 | 7 | uint64_t Slide::_now = 0; 8 | bool Slide::_terminated(false); 9 | std::multimap Slide::_event_q; 10 | std::vector Slide::_clocks; 11 | 12 | -------------------------------------------------------------------------------- /simplesim/main.cpp: -------------------------------------------------------------------------------- 1 | #include "data.h" 2 | #include "cache.h" 3 | #include "cpu.h" 4 | #include "des.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | template bool sstreamRead(T& dest, const char *src) { 17 | std::istringstream is(src); 18 | 19 | is >> dest; 20 | 21 | return !!is; 22 | } 23 | 24 | int Main(int argc, char **argv) { 25 | using std::cout; using std::vector; 26 | using SimpleSim::SuperscalarCpu; using SimpleSim::SimpleCpu; using SimpleSim::Cache; 27 | using SimpleSim::DramController; 28 | 29 | unsigned nCpus, rSeed(0); 30 | uint64_t nCycles; 31 | std::string statefile, benchmark; 32 | 33 | // Read arguments; print usage if we don't have the right number. 34 | if (argc != 4 || !sstreamRead(statefile, argv[1]) || 35 | !sstreamRead(benchmark, argv[2]) || 36 | !sstreamRead(nCycles, argv[3])) 37 | { 38 | cout << "Usage:\n " << argv[0] << " <# Cycles>\n"; 39 | return 1; 40 | } 41 | 42 | srand(rSeed); 43 | 44 | // Instantiate QSIM with appropriate state file or whatever it needs. 45 | Qsim::OSDomain osd(statefile.c_str()); 46 | nCpus = osd.get_n(); 47 | osd.connect_console(cout); 48 | Qsim::load_file(osd, benchmark.c_str()); 49 | 50 | // Instantiate CPUs. 51 | #ifdef SIMPLE_CPU 52 | vector cpus; 53 | #else 54 | vector cpus; 55 | #endif 56 | 57 | for (unsigned i = 0; i < nCpus; ++i) { 58 | #ifdef SIMPLE_CPU 59 | cpus.push_back(new SimpleCpu(i, osd)); 60 | #else 61 | cpus.push_back(new SuperscalarCpu(i, osd, 64, 4, 4)); 62 | // Op Type, Res. Stations, #Func. Units, Lat., Interval 63 | cpus[i]->addFu(QSIM_INST_NULL, 16, 16, 3, 1); 64 | cpus[i]->addFu(QSIM_INST_INTBASIC, 6, 4, 1, 1); 65 | cpus[i]->addFu(QSIM_INST_INTMUL, 6, 1, 4, 1); 66 | cpus[i]->addFu(QSIM_INST_INTDIV, 6, 1, 8, 4); 67 | cpus[i]->addFu(QSIM_INST_STACK, 6, 2, 1, 1); 68 | cpus[i]->addFu(QSIM_INST_FPBASIC, 6, 2, 8, 1); 69 | cpus[i]->addFu(QSIM_INST_FPMUL, 3, 1, 16, 4); 70 | cpus[i]->addFu(QSIM_INST_FPDIV, 3, 1, 32, 16); 71 | #endif 72 | } 73 | 74 | // Instantiate L1 caches. (nCpus*2 of them if we have separate I and D cache) 75 | vector l1i, l1d; 76 | for (unsigned i = 0; i < nCpus; ++i) { 77 | l1i.push_back(new Cache(1, i, 5, 8, 4, "i")); // 1-way, 32k L1i 78 | l1d.push_back(new Cache(1, i, 5, 8, 4, "d")); // 1-way, 32k L1d 79 | cpus[i]->setCache(l1i[i], l1d[i]); 80 | } 81 | 82 | // Connect L1 caches together. 83 | for (unsigned i = 0; i < nCpus; ++i) { 84 | l1i[i]->addPeer(l1d[i]); 85 | l1d[i]->addPeer(l1i[i]); 86 | for (unsigned j = 0; j < nCpus; ++j) { 87 | if (i == j) continue; 88 | l1i[i]->addPeer(l1i[j]); 89 | l1i[i]->addPeer(l1d[j]); 90 | l1d[i]->addPeer(l1i[j]); 91 | l1d[i]->addPeer(l1d[j]); 92 | } 93 | } 94 | 95 | // Instantiate L2 cache. 96 | Cache l2(2, 0, 5, 13, 4); // 4-way 1024k L2 97 | for (unsigned i = 0; i < nCpus; ++i) { 98 | l1i[i]->setLowerLevel(&l2); 99 | l1d[i]->setLowerLevel(&l2); 100 | } 101 | 102 | // Instantiate Memory controller (200 cycle round trip). 103 | DramController mc(200); 104 | l2.setLowerLevel(&mc); 105 | 106 | // Run everything for a while. 107 | if (nCycles == 0) { 108 | while(Slide::_advance(Slide::_now + 1000)) { 109 | SimpleSim::Counter::printAll(cout); 110 | SimpleSim::Counter::resetAll(); 111 | } 112 | } else { 113 | while (nCycles) { 114 | unsigned n(nCycles>=1000?1000:nCycles); 115 | bool finished = !Slide::_advance(Slide::_now + n); 116 | SimpleSim::Counter::printAll(cout); 117 | //SimpleSim::Counter::resetAll(); 118 | nCycles -= n; 119 | if (finished) break; 120 | } 121 | } 122 | 123 | SimpleSim::Counter::printAll(cout); 124 | SimpleSim::Counter::resetAll(); 125 | 126 | cout << "Finished at cycle " << Slide::_now << ".\n"; 127 | 128 | return 0; 129 | } 130 | 131 | // The real main function, calls our main function and catches any exceptions. 132 | // All of the SimpleSim exceptions are C strings, so it just prints the error 133 | // and exits. 134 | int main(int argc, char** argv) { 135 | using std::cout; 136 | try { 137 | return Main(argc, argv); 138 | } catch (const char *s) { 139 | cout << "Caught exception: \"" << s << "\".\n"; 140 | return 1; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /statesaver.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | // This bit of code is designed to enable saving state in QSim. The primary 10 | // barrier to successfully saving state is that the program counter available is 11 | // that of the most recent instruction executed, not that of the next 12 | // instruction to be executed. An effective way to get the EIP of the next 13 | // instruction to be executed it to run() it, and using barriers in the 14 | // instruction callbacks, save the state while the callbacks are being called 15 | // and before the instructions have actually been executed. 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | 24 | #include 25 | 26 | #include "statesaver.h" 27 | 28 | class Statesaver; 29 | 30 | class Statesaver { 31 | public: 32 | Statesaver(Qsim::OSDomain &_osd, const char* state_filename): 33 | osd(_osd), last_was_br(_osd.get_n()), last_was_cbr(_osd.get_n()) 34 | { 35 | Qsim::OSDomain::inst_cb_handle_t icb_handle; 36 | Qsim::OSDomain::reg_cb_handle_t rcb_handle; 37 | 38 | icb_handle = osd.set_inst_cb(this, &Statesaver::inst_cb); 39 | rcb_handle = osd.set_reg_cb(this, &Statesaver::reg_cb); 40 | 41 | osd.save_state(state_filename); 42 | 43 | // Unset the callbacks so we can continue. 44 | osd.unset_inst_cb(icb_handle); 45 | osd.unset_reg_cb(rcb_handle); 46 | } 47 | 48 | private: 49 | void inst_cb(int cpu, uint64_t va, uint64_t pa, uint8_t l, const uint8_t *b, 50 | enum inst_type t); 51 | void reg_cb(int cpu, int r, uint8_t s, int t); 52 | 53 | Qsim::OSDomain &osd; 54 | std::vector last_was_br, last_was_cbr; 55 | }; 56 | 57 | void Statesaver::inst_cb(int cpu, uint64_t va, uint64_t pa, 58 | uint8_t l, const uint8_t *b, enum inst_type t) 59 | { 60 | // Wait for the start of a basic block. 61 | if (last_was_cbr[cpu]) { 62 | //pthread_barrier_wait(&barrier1); 63 | //pthread_barrier_wait(&barrier2); 64 | } else { 65 | // Handle unconditional branches (jmps) 66 | last_was_br[cpu] = false; 67 | } 68 | 69 | if (t == QSIM_INST_BR) { 70 | last_was_br[cpu] = true; 71 | } 72 | } 73 | 74 | void Statesaver::reg_cb(int cpu, int r, uint8_t s, int t) { 75 | // If we read flags and are a BR instruction, we're probably conditional. 76 | if (last_was_br[cpu] && s == 0 && !t) last_was_cbr[cpu] = true; 77 | } 78 | 79 | void Qsim::save_state(Qsim::OSDomain &osd, const char *filename) { 80 | Statesaver ss(osd, filename); 81 | } 82 | -------------------------------------------------------------------------------- /statesaver.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), coupled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #ifndef __STATESAVER_H 10 | #define __STATESAVER_H 11 | 12 | #include 13 | 14 | namespace Qsim { 15 | void save_state(Qsim::OSDomain &osd, const char *filename); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | tester 2 | x86/icount 3 | x86/icount.tar 4 | x86/memory 5 | x86/memory.tar 6 | x86/reg 7 | x86/reg.tar 8 | x86/runme.sh 9 | x86/*.out 10 | arm64/icount 11 | arm64/icount.tar 12 | arm64/memory 13 | arm64/memory.tar 14 | arm64/runme.sh 15 | arm64/threads.tar 16 | arm64/threads 17 | arm64/*.tar 18 | arm64/contention 19 | arm64/*.out 20 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS ?= -g -O2 -std=c++0x -Wall -I$(QSIM_PREFIX)/include -Wl,--no-as-needed 2 | LDFLAGS ?= -L$(QSIM_PREFIX)/lib 3 | LDLIBS ?= -pthread -ldl -lqsim -lrt 4 | 5 | TESTS = tester 6 | 7 | all: $(TESTS) 8 | 9 | %: %.cpp 10 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) 11 | 12 | clean: 13 | rm -f $(TESTS) 14 | -------------------------------------------------------------------------------- /tests/arm64/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS ?= -g -O2 -static -fopenmp -lpthread -std=c++0x -Wall -I$(QSIM_PREFIX)/include 2 | LDFLAGS ?= -ldl -lpthread 3 | 4 | TESTS = icount memory threads contention 5 | 6 | all: $(TESTS) 7 | 8 | %: %.cpp 9 | aarch64-linux-gnu-g++ $(CXXFLAGS) $(LDFLAGS) -o $@ $< 10 | sed 's/TEST/$@/g' ../runme_orig.sh > runme.sh 11 | tar -cf $@.tar $@ runme.sh 12 | 13 | clean: 14 | rm -f $(TESTS) runme.sh *.tar 15 | -------------------------------------------------------------------------------- /tests/arm64/contention.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define ENABLE_QSIM 1 6 | 7 | #if ENABLE_QSIM 8 | #include 9 | #else 10 | #define qsim_magic_enable() do{}while(0) 11 | #define qsim_magic_disable() do{}while(0) 12 | #endif 13 | 14 | 15 | volatile int value; 16 | volatile int threads = 2; 17 | 18 | void *thread1(void *arg) 19 | { 20 | if (__sync_fetch_and_sub(&threads, 1) == 1) 21 | qsim_magic_enable(); 22 | 23 | while(threads); 24 | 25 | for (uint64_t i = 0; i < 10000; i++) 26 | __sync_fetch_and_add(&value, i); 27 | 28 | return 0; 29 | } 30 | 31 | void *thread2(void *arg) 32 | { 33 | if (__sync_fetch_and_sub(&threads, 1) == 1) 34 | qsim_magic_enable(); 35 | 36 | while(threads); 37 | 38 | for (uint64_t i = 0; i < 10000; i++) 39 | __sync_fetch_and_add(&value, i); 40 | 41 | return 0; 42 | } 43 | 44 | int main() 45 | { 46 | pthread_t t1, t2; 47 | 48 | printf("Creating threads...\n"); 49 | pthread_create(&t1, NULL, thread1, NULL); 50 | pthread_create(&t2, NULL, thread2, NULL); 51 | 52 | pthread_join(t1, NULL); 53 | pthread_join(t2, NULL); 54 | printf("Killing threads...\n"); 55 | 56 | qsim_magic_disable(); 57 | 58 | printf("%d\n", value); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /tests/arm64/icount.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qsim_magic.h" 4 | 5 | int main() 6 | { 7 | qsim_magic_enable(); 8 | asm volatile("cbz %0, 1f\n1:"::"r"(0)); 9 | asm volatile("dmb ishst;\n" 10 | "dmb ishst;\n" 11 | "dmb ishst;\n" 12 | "dmb ishst;\n" 13 | "dmb ishst;\n" 14 | "dmb ishst;\n" 15 | "dmb ishst;\n" 16 | "dmb ishst;\n" 17 | "dmb ishst;\n" 18 | "dmb ishst;\n"); 19 | qsim_magic_disable(); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/arm64/icount_gold.out: -------------------------------------------------------------------------------- 1 | 0: 15, 0, 5 2 | -------------------------------------------------------------------------------- /tests/arm64/memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "qsim_magic.h" 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | char *p; 9 | p = new char[10]; 10 | p[0] = 'a'; 11 | qsim_magic_enable(); 12 | asm volatile("cbz %0, 1f\n1:"::"r"(0)); 13 | asm volatile("ldr x1, [%0, #0]\n" 14 | "ldr x1, [%0, #1]\n" 15 | "ldr x1, [%0, #2]\n" 16 | "ldr x1, [%0, #3]\n" 17 | "ldr x1, [%0, #4]\n" 18 | "ldr x1, [%0, #5]\n" 19 | "ldr x1, [%0, #6]\n" 20 | "ldr x1, [%0, #7]\n" 21 | "ldr x1, [%0, #8]\n" 22 | "ldr x1, [%0, #9]\n" 23 | :: "r"(p)); 24 | qsim_magic_disable(); 25 | 26 | std::cout << "val is " << p[0] << std::endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/arm64/memory_gold.out: -------------------------------------------------------------------------------- 1 | 0: 15, 10, 25 2 | -------------------------------------------------------------------------------- /tests/arm64/threads.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #define NUM_THREADS 5 7 | #define NUM_ELEM 1000 8 | 9 | int main() 10 | { 11 | int p[NUM_ELEM], i; 12 | 13 | for (i = 0; i < NUM_ELEM; i++) 14 | p[i] = 0; 15 | 16 | omp_set_num_threads(NUM_THREADS); 17 | qsim_magic_enable(); 18 | #pragma omp parallel for private(i) shared(p) 19 | for (i = 0; i < NUM_ELEM - 3; i++) 20 | { 21 | p[i] += i; 22 | p[i+1] += (i+1); 23 | p[i+2] += (i+2); 24 | p[i+3] += (i+3); 25 | } 26 | qsim_magic_disable(); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /tests/runme_orig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./TEST 4 | -------------------------------------------------------------------------------- /tests/tester.cpp: -------------------------------------------------------------------------------- 1 | /*****************************************************************************\ 2 | * Qemu Simulation Framework (qsim) * 3 | * Qsim is a modified version of the Qemu emulator (www.qemu.org), couled * 4 | * a C++ API, for the use of computer architecture researchers. * 5 | * * 6 | * This work is licensed under the terms of the GNU GPL, version 2. See the * 7 | * COPYING file in the top-level directory. * 8 | \*****************************************************************************/ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | using Qsim::OSDomain; 19 | 20 | using std::ostream; 21 | 22 | class Tester { 23 | public: 24 | Tester(OSDomain &osd): 25 | osd(osd), finished(false), inst(0), mem(0), reg(0) 26 | { 27 | osd.set_app_start_cb(this, &Tester::app_start_cb); 28 | inst = (uint64_t *)malloc(osd.get_n() * sizeof(uint64_t)); 29 | mem = (uint64_t *)malloc(osd.get_n() * sizeof(uint64_t)); 30 | reg = (uint64_t *)malloc(osd.get_n() * sizeof(uint64_t)); 31 | 32 | for (int i = 0; i < osd.get_n(); i++) { 33 | inst[i] = 0; 34 | mem[i] = 0; 35 | reg[i] = 0; 36 | } 37 | } 38 | 39 | bool hasFinished() { return finished; } 40 | 41 | int app_start_cb(int c) { 42 | static bool ran = false; 43 | if (!ran) { 44 | ran = true; 45 | osd.set_inst_cb(this, &Tester::inst_cb); 46 | osd.set_mem_cb(this, &Tester::mem_cb); 47 | osd.set_reg_cb(this, &Tester::reg_cb); 48 | osd.set_app_end_cb(this, &Tester::app_end_cb); 49 | 50 | return 0; 51 | } 52 | 53 | return 0; 54 | } 55 | 56 | int app_end_cb(int c) 57 | { 58 | finished = true; 59 | 60 | return 1; 61 | } 62 | 63 | void reg_cb(int c, int r, uint8_t s, int type) 64 | { 65 | if (!finished) 66 | reg[c]++; 67 | 68 | //std::cout << "reg: " << r << " type: " << type << "\n"; 69 | } 70 | 71 | void inst_cb(int c, uint64_t v, uint64_t p, uint8_t l, const uint8_t *b, 72 | enum inst_type t) 73 | { 74 | if (!finished) 75 | inst[c]++; 76 | 77 | //std::cout << "inst: " << inst << "\r"; 78 | } 79 | 80 | void mem_cb(int c, uint64_t v, uint64_t p, uint8_t s, int w) 81 | { 82 | if (!finished) 83 | mem[c]++; 84 | } 85 | 86 | void print_stats(std::ofstream& out) 87 | { 88 | uint64_t total_inst = 0, total_mem = 0, total_reg = 0; 89 | for (int i = 0; i < osd.get_n(); i++) { 90 | total_inst += inst[i]; 91 | total_mem += mem[i]; 92 | total_reg += reg[i]; 93 | std::cout << i << ": " << inst[i] << ", " << mem[i] << ", " << reg[i] << std::endl; 94 | out << i << ": " << inst[i] << ", " << mem[i] << ", " << reg[i] << std::endl; 95 | } 96 | std::cout << "Total" << ": " << total_inst << ", " << total_mem << ", " << total_reg << std::endl; 97 | } 98 | 99 | private: 100 | OSDomain &osd; 101 | bool finished; 102 | uint64_t *inst, *mem, *reg; 103 | }; 104 | 105 | int main(int argc, char** argv) { 106 | using std::istringstream; 107 | using std::ofstream; 108 | 109 | unsigned n_cpus = 1; 110 | 111 | std::string qsim_prefix(getenv("QSIM_PREFIX")); 112 | 113 | if (argc < 4) { 114 | std::cerr << "Usage: " << argv[0] << " \n"; 115 | exit(1); 116 | } 117 | 118 | istringstream s(argv[1]); 119 | s >> n_cpus; 120 | 121 | OSDomain *osd_p(NULL); 122 | 123 | // Create new OSDomain from saved state. 124 | osd_p = new OSDomain(n_cpus, argv[2]); 125 | 126 | OSDomain &osd(*osd_p); 127 | Tester tw(osd); 128 | 129 | Qsim::load_file(osd, argv[3]); 130 | std::string bench(argv[3]); 131 | std::string ofname = bench.substr(0, bench.find(".tar")) + ".out"; 132 | std::ofstream out(ofname); 133 | // If this OSDomain was created from a saved state, the app start callback was 134 | // received prior to the state being saved. 135 | tw.app_start_cb(0); 136 | 137 | osd.connect_console(std::cout); 138 | 139 | // The main loop: run until 'finished' is true. 140 | while (!tw.hasFinished()) { 141 | for (unsigned i = 0; i < n_cpus; i++) { 142 | osd.run(i, 1000); 143 | osd.timer_interrupt(); 144 | } 145 | } 146 | 147 | tw.print_stats(out); 148 | 149 | out.close(); 150 | 151 | delete osd_p; 152 | 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /tests/x86/Makefile: -------------------------------------------------------------------------------- 1 | CXXFLAGS ?= -g -O2 -static -std=c++0x -Wall -I$(QSIM_PREFIX)/include 2 | LDLIBS ?= -lpthread -ldl 3 | 4 | TESTS = icount memory reg 5 | 6 | all: $(TESTS) 7 | 8 | %: %.cpp 9 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LDLIBS) 10 | sed 's/TEST/$@/g' ../runme_orig.sh > runme.sh 11 | tar -cf $@.tar $@ runme.sh 12 | 13 | clean: 14 | rm -f $(TESTS) runme.sh *.tar 15 | -------------------------------------------------------------------------------- /tests/x86/icount.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qsim_magic.h" 4 | 5 | int main() 6 | { 7 | qsim_magic_enable(); 8 | asm volatile("cmp %eax, %eax;\nje label\nlabel:"); 9 | asm volatile("mfence;\n" 10 | "mfence;\n" 11 | "mfence;\n" 12 | "mfence;\n" 13 | "mfence;\n" 14 | "mfence;\n" 15 | "mfence;\n" 16 | "mfence;\n" 17 | "mfence;\n" 18 | "mfence;\n"); 19 | qsim_magic_disable(); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /tests/x86/icount_gold.out: -------------------------------------------------------------------------------- 1 | 0: 12, 0, 5 2 | -------------------------------------------------------------------------------- /tests/x86/memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qsim_magic.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | int *p; 8 | p = new int[argc]; 9 | qsim_magic_enable(); 10 | asm volatile("cmp %eax, %eax;\nje label\nlabel:"); 11 | asm volatile("movl $1, (%1)\n" 12 | "movl $1, (%1)\n" 13 | "movl $1, (%1)\n" 14 | "movl $1, (%1)\n" 15 | "movl $1, (%1)\n" 16 | "movl $1, (%1)\n" 17 | "movl $1, (%1)\n" 18 | "movl $1, (%1)\n" 19 | "movl $1, (%1)\n" 20 | "movl $1, (%1)\n" 21 | :"+r"(p)); 22 | qsim_magic_disable(); 23 | 24 | std::cout << "val is " << p[0] << std::endl; 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /tests/x86/memory_gold.out: -------------------------------------------------------------------------------- 1 | 0: 12, 10, 5 2 | -------------------------------------------------------------------------------- /tests/x86/reg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "qsim_magic.h" 4 | 5 | int main() 6 | { 7 | qsim_magic_enable(); 8 | asm volatile("cmp %eax, %eax;\nje label\nlabel:"); 9 | asm volatile("movl $1, %eax;\n"); 10 | asm volatile("movl $1, %ebx;\n"); 11 | asm volatile("movl $1, %ecx;\n"); 12 | asm volatile("movl $1, %edx;\n"); 13 | asm volatile("mov $1, %r8;\n"); 14 | asm volatile("mov $1, %r9;\n"); 15 | asm volatile("mov $1, %r10;\n"); 16 | asm volatile("mov $1, %r11;\n"); 17 | asm volatile("mov $1, %r12;\n"); 18 | asm volatile("mov $1, %r13;\n"); 19 | asm volatile("mov $1, %r14;\n"); 20 | asm volatile("mov $1, %r15;\n"); 21 | asm volatile("addl $1, %eax;\n"); 22 | asm volatile("addl $1, %ebx;\n"); 23 | asm volatile("addl $1, %ecx;\n"); 24 | asm volatile("addl $1, %edx;\n"); 25 | asm volatile("add $1, %r8;\n"); 26 | asm volatile("add $1, %r9;\n"); 27 | asm volatile("add $1, %r10;\n"); 28 | asm volatile("add $1, %r11;\n"); 29 | asm volatile("add $1, %r12;\n"); 30 | asm volatile("add $1, %r13;\n"); 31 | asm volatile("add $1, %r14;\n"); 32 | asm volatile("add $1, %r15;\n"); 33 | qsim_magic_disable(); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /tests/x86/reg_gold.out: -------------------------------------------------------------------------------- 1 | 0: 26, 0, 53 2 | --------------------------------------------------------------------------------