4 * Intercept and emulate accesses to Fiasco's KIP->clock field.
6 * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
7 * economic rights: Technische Universität Dresden (Germany)
8 * This file is part of TUD:OS and distributed under the terms of the
9 * GNU General Public License 2.
10 * Please see the COPYING-GPL-2 file for details.
14 #include "../app_loading"
15 #include "../configuration"
16 //#include "../emulation"
18 #include "observers.h"
23 #include <l4/libc_backends/clk.h>
26 class KipTimeObserver_priv : public KIPTimeObserver
29 std::vector<Breakpoint*> _breakpoints;
31 void configureBreakpoint(char *str)
33 l4_addr_t a = strtol(str, NULL, 16); // XXX check return
35 ERROR() << "Conversion error.";
37 _breakpoints.push_back(new Breakpoint(a));
41 DECLARE_OBSERVER("kip time");
42 KipTimeObserver_priv();
46 Romain::KIPTimeObserver* Romain::KIPTimeObserver::Create()
48 return new Romain::KipTimeObserver_priv();
51 Romain::KipTimeObserver_priv::KipTimeObserver_priv()
53 char *rtget = strdup(ConfigStringValue("kip-time:libc_backend_rt_clock_gettime", NULL));
55 INFO() << "BP @ " << rtget;
56 configureBreakpoint(rtget);
58 ERROR() << "No set address for libc_backend_rt_clock_gettime()";
62 char *monoget = strdup(ConfigStringValue("kip-time:mono_clock_gettime", NULL));
64 INFO() << "BP @ " << monoget;
65 configureBreakpoint(monoget);
67 ERROR() << "No set address for mono_clock_gettime()";
73 enter_kdebug("kiptime");
77 void Romain::KipTimeObserver_priv::status() const { }
79 /*****************************************************************
81 *****************************************************************/
82 void Romain::KipTimeObserver_priv::startup_notify(Romain::App_instance *inst,
84 Romain::Thread_group *,
85 Romain::App_model *am)
87 for (auto i = _breakpoints.begin(); i != _breakpoints.end(); ++i) {
88 DEBUG() << std::hex << (*i)->address();
89 (*i)->activate(inst, am);
93 Romain::Observer::ObserverReturnVal
94 Romain::KipTimeObserver_priv::notify(Romain::App_instance *i,
95 Romain::App_thread *t,
96 Romain::Thread_group *,
97 Romain::App_model *am)
99 if (!entry_reason_is_int3(t->vcpu(), i, am) &&
100 !entry_reason_is_int1(t->vcpu()))
101 return Romain::Observer::Ignored;
103 for (auto it = _breakpoints.begin(); it != _breakpoints.end(); ++it) {
104 if ((*it)->was_hit(t)) {
105 INFO() << "BP @ " << std::hex << (*it)->address() << " was hit.";
106 INFO() << "stack ptr 0x" << std::hex << t->vcpu()->r()->sp;
108 l4_addr_t stack = am->rm()->remote_to_local(t->vcpu()->r()->sp, i->id());
109 l4_addr_t ret = *(l4_addr_t*)stack;
110 l4_addr_t specptr = *(l4_addr_t*)(stack + 1 * sizeof(l4_addr_t));
111 l4_addr_t spec_local = am->rm()->remote_to_local(specptr, i->id());
112 INFO() << "Retaddr " << std::hex << ret << ", ptr " << specptr;
114 int rv = libc_backend_rt_clock_gettime((struct timespec*)(spec_local));
115 t->vcpu()->r()->ax = rv;
117 /* We wrote data directly into the replica's address space. Now
118 we need to make sure the other replicas see the same value.
120 for (unsigned rep = 0; rep < Romain::_the_instance_manager->instance_count();
126 l4_addr_t specptr_rep = am->rm()->remote_to_local(specptr, rep);
127 INFO() << "memcpy " << std::hex << specptr_rep << " <- " << spec_local;
128 memcpy((void*)specptr_rep, (void*)spec_local, sizeof(struct timespec));
133 return Romain::Observer::Replicatable;
137 return Romain::Observer::Ignored;