diff --git a/src/core/sal/SALConfig.cc b/src/core/sal/SALConfig.cc index a164ccbc..7fe641c4 100644 --- a/src/core/sal/SALConfig.cc +++ b/src/core/sal/SALConfig.cc @@ -7,6 +7,6 @@ const address_t ANY_ADDR = static_cast (-1); const unsigned ANY_INSTR = static_cast (-1); const unsigned ANY_TRAP = static_cast (-1); const unsigned ANY_INTERRUPT = static_cast (-1); -const timer_id_t INVALID_TIMER = static_cast (-1); +const timer_id_t INVALID_TIMER = static_cast (0); } // end-of-namespace: fail diff --git a/src/core/sal/qemu/QEMUConfig.hpp b/src/core/sal/qemu/QEMUConfig.hpp index 26b05690..801b48ea 100644 --- a/src/core/sal/qemu/QEMUConfig.hpp +++ b/src/core/sal/qemu/QEMUConfig.hpp @@ -8,12 +8,14 @@ // FIXME: qemu/targphys.h defines address types (but relies on a global preprocessor macro) +struct QEMUTimer; + 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 +typedef QEMUTimer* timer_t; //!< type of timer IDs } // end-of-namespace: fail diff --git a/src/core/sal/qemu/QEMUController.cc b/src/core/sal/qemu/QEMUController.cc index c868c02c..c6345dab 100644 --- a/src/core/sal/qemu/QEMUController.cc +++ b/src/core/sal/qemu/QEMUController.cc @@ -40,4 +40,20 @@ void QEMUController::onIOPort(unsigned char data, unsigned port, bool out) { m_LstList.triggerActiveListeners(); } +void QEMUController::onTimerTrigger(TimerListener *pli) +{ + // FIXME: The timer logic can be modified to use only one timer in QEMU. + // (For now, this suffices.) + + // Check for a matching TimerListener. (In fact, we are only + // interessted in the iterator pointing at pli.) + ListenerManager::iterator it = std::find(m_LstList.begin(), + simulator.m_LstList.end(), pli); + // TODO: This has O(|m_LstList|) time complexity. We can further improve this + // by creating a method such that makeActive(pli) works as well, + // reducing the time complexity to O(1). + m_LstList.makeActive(it); + m_LstList.triggerActiveListeners(); +} + } // end-of-namespace: fail diff --git a/src/core/sal/qemu/QEMUController.hpp b/src/core/sal/qemu/QEMUController.hpp index 69f81e8d..b34e0402 100644 --- a/src/core/sal/qemu/QEMUController.hpp +++ b/src/core/sal/qemu/QEMUController.hpp @@ -38,9 +38,9 @@ public: */ void onIOPort(unsigned char data, unsigned port, bool out); /** - * Static internal handler for TimerListeners. TODO. + * Internal handler for TimerListeners. */ - static void onTimerTrigger(void *thisPtr) {} + void onTimerTrigger(TimerListener *pli); /* ******************************************************************** * Simulator Controller & Access API: * ********************************************************************/ diff --git a/src/core/sal/qemu/QEMUListener.cc b/src/core/sal/qemu/QEMUListener.cc index b1eb4104..e093ad47 100644 --- a/src/core/sal/qemu/QEMUListener.cc +++ b/src/core/sal/qemu/QEMUListener.cc @@ -25,4 +25,21 @@ void QEMUMemWriteListener::onDeletion() failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1); } +bool QEMUTimerListener::onAddition() +{ + //std::cout << "QEMUTimerListener::onAddition" << std::endl; + setId(failqemu_register_timer(getTimeout(), (void *)this)); + //std::cout << "this = " << std::hex << (unsigned) this << std::endl; + //std::cout << "id = " << std::hex << (unsigned) getId() << std::endl; + return true; +} + +void QEMUTimerListener::onDeletion() +{ + //std::cout << "QEMUTimerListener::onDeletion" << std::endl; + //std::cout << "this = " << std::hex << (unsigned) this << std::endl; + //std::cout << "id = " << std::hex << (unsigned) getId() << std::endl; + failqemu_unregister_timer(getId()); +} + } // end-of-namespace: fail diff --git a/src/core/sal/qemu/QEMUListener.hpp b/src/core/sal/qemu/QEMUListener.hpp index 2707bd22..f2719f7a 100644 --- a/src/core/sal/qemu/QEMUListener.hpp +++ b/src/core/sal/qemu/QEMUListener.hpp @@ -8,14 +8,19 @@ namespace fail { typedef GenericBPSingleListener BPSingleListener; /** - * \class TimerListener + * \class QEMUTimerListener * Concrete TimerListener implementation of GenericTimerListener for QEMU. */ -class TimerListener : public GenericTimerListener { +class QEMUTimerListener : public GenericTimerListener { private: public: - // TODO + QEMUTimerListener(unsigned timeout) + : GenericTimerListener(timeout) { } + ~QEMUTimerListener() { onDeletion(); } // FIXME ~BaseListener should automatically dequeue a Listener, and then indirectly calls onDeletion. In the current implementation, no dequeueing happens at all. + bool onAddition(); + void onDeletion(); }; +typedef QEMUTimerListener TimerListener; class QEMUMemWriteListener : public GenericMemWriteListener { public: diff --git a/src/core/sal/qemu/wrappers.cc b/src/core/sal/qemu/wrappers.cc index 36d57663..24a31abe 100644 --- a/src/core/sal/qemu/wrappers.cc +++ b/src/core/sal/qemu/wrappers.cc @@ -29,4 +29,10 @@ void fail_io(int port, int width, int32_t data, int is_write) fail::simulator.onIOPort((unsigned char)data, port, is_write == 1); } +void fail_timer_callback(void *opaque) +{ + fail::TimerListener *l = static_cast(opaque); + fail::simulator.onTimerTrigger(l); +} + }