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