From e715149033e5f316b69d0b7c530a0229f474332f Mon Sep 17 00:00:00 2001 From: hsc <hsc@8c4709b5-6ec9-48aa-a5cd-a96041d1645a> Date: Wed, 12 Sep 2012 14:07:03 +0000 Subject: [PATCH] first steps towards a QEMU target backend - This commit only enables linking against QEMU. The abstraction layer is completely dysfunctional at this time. - QEMU's build system needs to be patched in order to create a static library. This patch is currently not included in the Fail* repository. - QEMU's JIT compilation may complicate or even preclude the implementation of some of Fail*'s backend abstractions. Only a minimal subset (serial I/O, memory, memory writes, save/restore) is planned for the first phase. git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1615 8c4709b5-6ec9-48aa-a5cd-a96041d1645a --- CMakeLists.txt | 9 +++- cmake/FindLibUUID.cmake | 64 ++++++++++++++++++++++++++++ cmake/qemu.cmake | 62 +++++++++++++++++++++++++++ src/core/config/VariantConfig.hpp.in | 3 +- src/core/sal/CMakeLists.txt | 11 +++++ src/core/sal/Listener.hpp | 6 ++- src/core/sal/SALConfig.hpp | 6 ++- src/core/sal/SALInst.hpp | 25 ++++++----- src/core/sal/qemu/QEMUConfig.hpp | 20 +++++++++ src/core/sal/qemu/QEMUController.cc | 23 ++++++++++ src/core/sal/qemu/QEMUController.hpp | 59 +++++++++++++++++++++++++ src/core/sal/qemu/QEMUListener.cc | 8 ++++ src/core/sal/qemu/QEMUListener.hpp | 24 +++++++++++ src/core/sal/qemu/QEMUMemory.hpp | 41 ++++++++++++++++++ src/core/sal/qemu/QEMURegister.hpp | 45 +++++++++++++++++++ src/core/sal/qemu/lol.h | 1 + 16 files changed, 390 insertions(+), 17 deletions(-) create mode 100644 cmake/FindLibUUID.cmake create mode 100644 cmake/qemu.cmake create mode 100644 src/core/sal/qemu/QEMUConfig.hpp create mode 100644 src/core/sal/qemu/QEMUController.cc create mode 100644 src/core/sal/qemu/QEMUController.hpp create mode 100644 src/core/sal/qemu/QEMUListener.cc create mode 100644 src/core/sal/qemu/QEMUListener.hpp create mode 100644 src/core/sal/qemu/QEMUMemory.hpp create mode 100644 src/core/sal/qemu/QEMURegister.hpp create mode 100644 src/core/sal/qemu/lol.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ae6ff481..0bd7e3ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,11 @@ include(compilerconfig) OPTION( BUILD_BOCHS "Build Bochs Variant?" ON) OPTION( BUILD_GEM5 "Build gem5 Variant?" OFF) OPTION( BUILD_OVP "Build OVP Variant?" OFF) +OPTION( BUILD_QEMU "Build QEMU Variant?" OFF) +# FIXME: only add simulators/ to include_directories, and include, e.g., +# bochs/bochs.h in Fail*. -> avoids naming conflicts (e.g., /usr/include/elf.h +# vs. qemu/elf.h) if(BUILD_BOCHS) ## add necessary additional header search paths. #add_definitions(-I${CMAKE_SOURCE_DIR}/simulators/bochs/instrument/stubs/ -I${CMAKE_SOURCE_DIR}/simulators/bochs) @@ -39,6 +43,8 @@ elseif(BUILD_GEM5) include_directories(simulators/gem5/src simulators/gem5/build/ARM) elseif(BUILD_OVP) add_subdirectory(simulators/ovp) +elseif(BUILD_QEMU) + include_directories(simulators) endif(BUILD_BOCHS) ## Additional Compiler flags ## @@ -57,8 +63,9 @@ add_subdirectory(src) #### Backend-related build system stuff include(bochs) -include(ovp) include(gem5) +include(ovp) +include(qemu) ## Just for testing: ## Invoking bochs build via external project diff --git a/cmake/FindLibUUID.cmake b/cmake/FindLibUUID.cmake new file mode 100644 index 00000000..f07ddaba --- /dev/null +++ b/cmake/FindLibUUID.cmake @@ -0,0 +1,64 @@ +# - Try to find UUID (Universally Unique Identifier) +# Once done this will define +# +# UUID_FOUND - system has UUID +# UUID_INCLUDE_DIRS - the UUID include directory +# UUID_LIBRARIES - Link these to use UUID +# UUID_DEFINITIONS - Compiler switches required for using UUID +# +# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org> +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + +if (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) + # in cache already + set(UUID_FOUND TRUE) +else (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) + find_path(UUID_INCLUDE_DIR + NAMES + uuid/uuid.h + PATHS + /usr/include + /usr/local/include + /opt/local/include + /sw/include + ) + + find_library(UUID_LIBRARY + NAMES + uuid + PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ) + + set(UUID_INCLUDE_DIRS + ${UUID_INCLUDE_DIR} + ) + set(UUID_LIBRARIES + ${UUID_LIBRARY} + ) + + if (UUID_INCLUDE_DIRS AND UUID_LIBRARIES) + set(UUID_FOUND TRUE) + endif (UUID_INCLUDE_DIRS AND UUID_LIBRARIES) + + if (UUID_FOUND) + if (NOT UUID_FIND_QUIETLY) + message(STATUS "Found UUID (Universally Unique Identifier): ${UUID_LIBRARIES}") + endif (NOT UUID_FIND_QUIETLY) + else (UUID_FOUND) + if (UUID_FIND_REQUIRED) + message(FATAL_ERROR "Could not find UUID (Universally Unique Identifier)") + endif (UUID_FIND_REQUIRED) + endif (UUID_FOUND) + + # show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced view + mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES) + +endif (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) diff --git a/cmake/qemu.cmake b/cmake/qemu.cmake new file mode 100644 index 00000000..0083211d --- /dev/null +++ b/cmake/qemu.cmake @@ -0,0 +1,62 @@ +#### Add some custom targets for qemu-system-x86_64 +if(BUILD_QEMU) + + message(STATUS "[${PROJECT_NAME}] Building QEMU variant ...") + SET(VARIANT qemu) + + # ./configure --prefix=$(echo ~/localroot/usr) --enable-sdl --disable-vnc --disable-curses --disable-curl --enable-system --target-list=x86_64-softmmu + # LIBS = -lrt -pthread -lgthread-2.0 -lglib-2.0 -lutil -luuid -lSDL -lX11 -lm -lz + + # -L/usr/lib -lSDL -lasound -latk-1.0 -lcairo -lfontconfig -lfreetype -lgdk_pixbuf-2.0 -lgdk-x11-2.0 -lgio-2.0 -lglib-2.0 -lgmodule-2.0 -lgobject-2.0 -lgthread-2.0 -lgtk-x11-2.0 -lICE -lm -lncurses -lpango-1.0 -lpangocairo-1.0 -lpangoft2-1.0 -lrt -lSM -lvga -lvgagl -lwx_baseu-2.8 -lwx_gtk2u_core-2.8 -lX11 -lXpm -lXrandr -pthread) + find_package(SDL) # -lSDL + if(SDL_FOUND) + set(qemu_library_dependencies ${qemu_library_dependencies} ${SDL_LIBRARY}) + endif(SDL_FOUND) + unset(FindSDL_DIR CACHE) + unset(SDLMAIN_LIBRARY CACHE) + unset(SDL_INCLUDE_DIR CACHE) + unset(SDL_LIBRARY CACHE) + find_package(GTK2 COMPONENTS gtk) + if(GTK2_FOUND) + set(qemu_library_dependencies ${qemu_library_dependencies} ${GTK2_GLIB_LIBRARY} -lgthread-2.0) + endif(GTK2_FOUND) + unset(FindGTK2_DIR CACHE) + unset(GTK2_GIOCONFIG_INCLUDE_DIR CACHE) + unset(GTK2_GIO_INCLUDE_DIR CACHE) + find_package(X11) # -lX11 + if(X11_FOUND) + set(qemu_library_dependencies ${qemu_library_dependencies} ${X11_X11_LIB}) + endif(X11_FOUND) + find_package(ZLIB) # -lz + if(ZLIB_FOUND) + set(qemu_library_dependencies ${qemu_library_dependencies} ${ZLIB_LIBRARIES}) + endif(ZLIB_FOUND) + find_package(LibUUID) # -luuid + if(UUID_FOUND) + set(qemu_library_dependencies ${qemu_library_dependencies} ${UUID_LIBRARIES}) + endif(UUID_FOUND) + + # FIXME: some libraries still need to be located the "cmake way" + set(qemu_library_dependencies ${qemu_library_dependencies} -lrt -pthread -lutil -lm) + + set(qemu_src_dir ${PROJECT_SOURCE_DIR}/simulators/qemu) + set(qemu_lib "${qemu_src_dir}/x86_64-softmmu/qemu-system-x86_64.a") + + add_custom_command(OUTPUT "${qemu_lib}" + COMMAND +make -C ${qemu_src_dir} CFLAGS=\"-I${PROJECT_SOURCE_DIR}/src/core -I${CMAKE_BINARY_DIR}/src/core\" + COMMENT "[${PROJECT_NAME}] Building qemu-system-x86_64.a" + ) + + # make sure aspects don't fail to match in entry.cc + include_directories(${PROJECT_SOURCE_DIR}/src/core ${CMAKE_BINARY_DIR}/src/core) + add_executable(fail-client "${qemu_lib}") + target_link_libraries(fail-client "${qemu_lib}" fail ${qemu_library_dependencies}) + install(TARGETS fail-client RUNTIME DESTINATION bin) + + # a few QEMU-specific passthrough targets: + add_custom_target(qemuclean + COMMAND +make -C ${qemu_src_dir} clean + COMMENT "[${PROJECT_NAME}] Cleaning all up (clean in qemu)" + ) + +endif(BUILD_QEMU) diff --git a/src/core/config/VariantConfig.hpp.in b/src/core/config/VariantConfig.hpp.in index b2b2fd7e..02fa8727 100644 --- a/src/core/config/VariantConfig.hpp.in +++ b/src/core/config/VariantConfig.hpp.in @@ -1,8 +1,9 @@ #ifndef __VARIANT_CONFIG_HPP__ #define __VARIANT_CONFIG_HPP__ -#cmakedefine BUILD_OVP #cmakedefine BUILD_BOCHS #cmakedefine BUILD_GEM5 +#cmakedefine BUILD_OVP +#cmakedefine BUILD_QEMU #endif // __VARIANT_CONFIG_HPP__ diff --git a/src/core/sal/CMakeLists.txt b/src/core/sal/CMakeLists.txt index fc6f95ad..4cae2c26 100644 --- a/src/core/sal/CMakeLists.txt +++ b/src/core/sal/CMakeLists.txt @@ -31,6 +31,17 @@ elseif(BUILD_OVP) SimulatorController.cc ${VARIANT}/OVPController.cc ) +elseif(BUILD_QEMU) + set(SRCS + BufferCache.cc + Listener.cc + ListenerManager.cc + SALConfig.cc + Register.cc + SimulatorController.cc + qemu/QEMUController.cc + qemu/QEMUListener.cc + ) endif(BUILD_BOCHS) add_library(fail-sal ${SRCS}) diff --git a/src/core/sal/Listener.hpp b/src/core/sal/Listener.hpp index 1e6b56e4..c183bf0d 100644 --- a/src/core/sal/Listener.hpp +++ b/src/core/sal/Listener.hpp @@ -597,10 +597,12 @@ public: #if defined BUILD_BOCHS #include "bochs/BochsListener.hpp" -#elif defined BUILD_OVP -// #include "ovp/OVPListener.hpp" #elif defined BUILD_GEM5 #include "gem5/Gem5Listener.hpp" +#elif defined BUILD_OVP +// #include "ovp/OVPListener.hpp" +#elif defined BUILD_QEMU + #include "qemu/QEMUListener.hpp" #else #error SAL Config Target not defined #endif diff --git a/src/core/sal/SALConfig.hpp b/src/core/sal/SALConfig.hpp index 14cae5b8..3353a760 100644 --- a/src/core/sal/SALConfig.hpp +++ b/src/core/sal/SALConfig.hpp @@ -8,10 +8,12 @@ // Type-config depends on the current selected simulator: #if defined BUILD_BOCHS #include "bochs/BochsConfig.hpp" -#elif defined BUILD_OVP - #include "ovp/OVPConfig.hpp" #elif defined BUILD_GEM5 #include "gem5/Gem5Config.hpp" +#elif defined BUILD_OVP + #include "ovp/OVPConfig.hpp" +#elif defined BUILD_QEMU + #include "qemu/QEMUConfig.hpp" #else #error SAL Config Target not defined #endif diff --git a/src/core/sal/SALInst.hpp b/src/core/sal/SALInst.hpp index 228fc2ca..3dfb573c 100644 --- a/src/core/sal/SALInst.hpp +++ b/src/core/sal/SALInst.hpp @@ -9,10 +9,15 @@ #include "bochs/BochsController.hpp" namespace fail { - typedef BochsController ConcreteSimulatorController; //!< concrete simulator (type) -extern ConcreteSimulatorController simulator; //!< the global simulator-controller instance +} +#elif defined BUILD_GEM5 + +#include "gem5/Gem5Controller.hpp" + +namespace fail { +typedef Gem5Controller ConcreteSimulatorController; //!< concrete simulator (type) } #elif defined BUILD_OVP @@ -20,25 +25,23 @@ extern ConcreteSimulatorController simulator; //!< the global simulator-controll #include "ovp/OVPController.hpp" namespace fail { - typedef OVPController ConcreteSimulatorController; //!< concrete simulator (type) -extern ConcreteSimulatorController simulator; //!< the global simulator-controller instance - } -#elif defined BUILD_GEM5 +#elif defined BUILD_QEMU -#include "gem5/Gem5Controller.hpp" +#include "qemu/QEMUController.hpp" namespace fail { - -typedef Gem5Controller ConcreteSimulatorController; //!< concrete simulator (type) -extern ConcreteSimulatorController simulator; //!< the global simulator-controller instance - +typedef QEMUController ConcreteSimulatorController; //!< concrete simulator (type) } #else #error SAL Instance not defined #endif +namespace fail { +extern ConcreteSimulatorController simulator; //!< the global simulator-controller instance +}; + #endif // __SAL_INSTANCE_HPP__ diff --git a/src/core/sal/qemu/QEMUConfig.hpp b/src/core/sal/qemu/QEMUConfig.hpp new file mode 100644 index 00000000..26b05690 --- /dev/null +++ b/src/core/sal/qemu/QEMUConfig.hpp @@ -0,0 +1,20 @@ +/** + * \brief Type definitions and configuration settings for the + * qemu-system-x86_64 target backend. + */ + +#ifndef __QEMU_CONFIG_HPP__ + #define __QEMU_CONFIG_HPP__ + +// FIXME: qemu/targphys.h defines address types (but relies on a global preprocessor macro) + +namespace fail { + +typedef uint64_t guest_address_t; //!< the guest memory address type +typedef unsigned char* host_address_t; //!< the host memory address type +typedef uint64_t register_data_t; //!< register data type (64 bit) +typedef int timer_t; //!< type of timer IDs + +} // end-of-namespace: fail + +#endif // __QEMU_CONFIG_HPP__ diff --git a/src/core/sal/qemu/QEMUController.cc b/src/core/sal/qemu/QEMUController.cc new file mode 100644 index 00000000..63fd2003 --- /dev/null +++ b/src/core/sal/qemu/QEMUController.cc @@ -0,0 +1,23 @@ +#include <sstream> + +#include "QEMUController.hpp" +#include "QEMUMemory.hpp" +#include "QEMURegister.hpp" +#include "../Register.hpp" +#include "../SALInst.hpp" + +namespace fail { + +QEMUController::QEMUController() + : SimulatorController(new QEMURegisterManager(), new QEMUMemoryManager()) +{ + // TODO: probably do additional RegisterManager initializations +} + +QEMUController::~QEMUController() +{ + delete m_Regs; + delete m_Mem; +} + +} // end-of-namespace: fail diff --git a/src/core/sal/qemu/QEMUController.hpp b/src/core/sal/qemu/QEMUController.hpp new file mode 100644 index 00000000..722632af --- /dev/null +++ b/src/core/sal/qemu/QEMUController.hpp @@ -0,0 +1,59 @@ +#ifndef __QEMU_CONTROLLER_HPP__ + #define __QEMU_CONTROLLER_HPP__ + +#include <string> +#include <cassert> +#include <iostream> +#include <iomanip> +#include <string.h> + +#include "../SimulatorController.hpp" +#include "../Listener.hpp" + +namespace fail { + +class ExperimentFlow; + +/** + * \class QEMUController + * Very rudimentary, QEMU-specific implementation of a SimulatorController. + */ +class QEMUController : public SimulatorController { +private: +public: + // Initialize the controller. + QEMUController(); + ~QEMUController(); + /** + * I/O port communication handler. This method is called from QEMU. TODO. + * @param data the data transmitted + * @param port the port it was transmitted on + * @param out true if the I/O traffic has been outbound, false otherwise + */ + void onIOPort(unsigned char data, unsigned port, bool out) {} + /** + * Static internal handler for TimerListeners. TODO. + */ + static void onTimerTrigger(void *thisPtr) {} + /* ******************************************************************** + * Simulator Controller & Access API: + * ********************************************************************/ + /** + * Save simulator state. TODO. + * @param path Location to store state information + */ + void save(const std::string& path) {} + /** + * Restore simulator state. Clears all Listeners. TODO. + * @param path Location to previously saved state information + */ + void restore(const std::string& path) {} + /** + * Reboot simulator. Clears all Listeners. TODO. + */ + void reboot() {} +}; + +} // end-of-namespace: fail + +#endif // __QEMU_CONTROLLER_HPP__ diff --git a/src/core/sal/qemu/QEMUListener.cc b/src/core/sal/qemu/QEMUListener.cc new file mode 100644 index 00000000..64e99084 --- /dev/null +++ b/src/core/sal/qemu/QEMUListener.cc @@ -0,0 +1,8 @@ +#include "QEMUListener.hpp" +#include "../SALInst.hpp" + +namespace fail { + +// TODO + +} // end-of-namespace: fail diff --git a/src/core/sal/qemu/QEMUListener.hpp b/src/core/sal/qemu/QEMUListener.hpp new file mode 100644 index 00000000..fb4b1006 --- /dev/null +++ b/src/core/sal/qemu/QEMUListener.hpp @@ -0,0 +1,24 @@ +#ifndef __QEMU_LISTENER_HPP__ + #define __QEMU_LISTENER_HPP__ + +#include "../Listener.hpp" + +namespace fail { + +typedef GenericBPSingleListener BPSingleListener; + +/** + * \class TimerListener + * Concrete TimerListener implementation of GenericTimerListener for QEMU. + */ +class TimerListener : public GenericTimerListener { +private: +public: + // TODO +}; + +// TODO: MemWriteListener + +} // end-of-namespace: fail + +#endif // __QEMU_LISTENER_HPP__ diff --git a/src/core/sal/qemu/QEMUMemory.hpp b/src/core/sal/qemu/QEMUMemory.hpp new file mode 100644 index 00000000..08e1ae9d --- /dev/null +++ b/src/core/sal/qemu/QEMUMemory.hpp @@ -0,0 +1,41 @@ +#ifndef __QEMU_MEMORY_HPP__ + #define __QEMU_MEMORY_HPP__ + +#include "../Memory.hpp" + +namespace fail { + +/** + * \class QEMUMemoryManager + * Represents a concrete implemenation of the abstract + * MemoryManager to provide access to QEMU's memory pool. + */ +class QEMUMemoryManager : public MemoryManager { +public: + size_t getPoolSize() const { return 0; /* TODO */ } + host_address_t getStartAddr() const { return 0; } + byte_t getByte(guest_address_t addr) + { + return static_cast<byte_t>(0); /* TODO */ + } + void getBytes(guest_address_t addr, size_t cnt, void *dest) + { + char *d = static_cast<char *>(dest); + for (size_t i = 0; i < cnt; ++i) + d[i] = getByte(addr + i); + } + void setByte(guest_address_t addr, byte_t data) + { + /* TODO */ + } + void setBytes(guest_address_t addr, size_t cnt, void const *src) + { + char const *s = static_cast<char const *>(src); + for (size_t i = 0; i < cnt; ++i) + setByte(addr + i, s[i]); + } +}; + +} // end-of-namespace: fail + +#endif // __QEMU_MEMORY_HPP__ diff --git a/src/core/sal/qemu/QEMURegister.hpp b/src/core/sal/qemu/QEMURegister.hpp new file mode 100644 index 00000000..2f966802 --- /dev/null +++ b/src/core/sal/qemu/QEMURegister.hpp @@ -0,0 +1,45 @@ +#ifndef __QEMU_REGISTER_HPP__ + #define __QEMU_REGISTER_HPP__ + +#include "../Register.hpp" + +#include <iostream> +#include <cassert> + +namespace fail { + +/** + * \class QEMURegister + * QEMU-specific implementation of x86 registers. TODO. + */ +class QEMURegister : public Register { +public: + QEMURegister(unsigned int id, regwidth_t width, regdata_t* link, RegisterType t) + : Register(id, t, width) { } + regdata_t getData() { return 0; /* TODO */ } + void setData(regdata_t data) { /* TODO */ } +}; + +/** + * \class QEMURegisterManager + * QEMU-specific implementation of the RegisterManager. TODO. + */ +class QEMURegisterManager : public RegisterManager { +public: + address_t getInstructionPointer() + { + return static_cast<address_t>(0); /* TODO */ + } + address_t getStackPointer() + { + return static_cast<address_t>(0); /* TODO */ + } + address_t getBasePointer() + { + return static_cast<address_t>(0); /* TODO */ + } +}; + +} // end-of-namespace: fail + +#endif // __QEMU_REGISTER_HPP__ diff --git a/src/core/sal/qemu/lol.h b/src/core/sal/qemu/lol.h new file mode 100644 index 00000000..43e5548d --- /dev/null +++ b/src/core/sal/qemu/lol.h @@ -0,0 +1 @@ +#error YO DAWG -- GitLab