]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/fault_handlers/kiptime.cc
update
[l4.git] / l4 / pkg / plr / server / src / fault_handlers / kiptime.cc
1 /*
2  * kiptime.cc --
3  *
4  *   Intercept and emulate accesses to Fiasco's KIP->clock field.
5  *
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.
11  */
12
13 #include "../log"
14 #include "../app_loading"
15 #include "../configuration"
16 //#include "../emulation"
17
18 #include "observers.h"
19
20 #include <vector>
21 #include <cstdlib>
22 #include <cstring>
23 #include <l4/libc_backends/clk.h>
24
25 namespace Romain {
26 class KipTimeObserver_priv : public KIPTimeObserver
27 {
28         private:
29                 std::vector<Breakpoint*> _breakpoints;
30
31                 void configureBreakpoint(char *str)
32                 {
33                         l4_addr_t a = strtol(str, NULL, 16); // XXX check return
34                         if (errno) {
35                                 ERROR() << "Conversion error.";
36                         } else {
37                                 _breakpoints.push_back(new Breakpoint(a));
38                         }                       
39                 }
40
41         DECLARE_OBSERVER("kip time");
42         KipTimeObserver_priv();
43 };
44 }
45
46 Romain::KIPTimeObserver* Romain::KIPTimeObserver::Create()
47 {
48         return new Romain::KipTimeObserver_priv();
49 }
50
51 Romain::KipTimeObserver_priv::KipTimeObserver_priv()
52 {
53         char *rtget = strdup(ConfigStringValue("kip-time:libc_backend_rt_clock_gettime", NULL));
54         if (rtget) {
55                 INFO() << "BP @ " << rtget;
56                 configureBreakpoint(rtget);
57         } else {
58                 ERROR() << "No set address for libc_backend_rt_clock_gettime()";
59                 enter_kdebug("??");
60         }
61
62         char *monoget = strdup(ConfigStringValue("kip-time:mono_clock_gettime", NULL));
63         if (monoget) {
64                 INFO() << "BP @ " << monoget;
65                 configureBreakpoint(monoget);
66         } else {
67                 ERROR() << "No set address for mono_clock_gettime()";
68                 enter_kdebug("??");
69         }
70
71         free(monoget);
72         free(rtget);
73         enter_kdebug("kiptime");
74 }
75
76
77 void Romain::KipTimeObserver_priv::status() const { }
78
79 /*****************************************************************
80  *                      Debugging stuff                          *
81  *****************************************************************/
82 void Romain::KipTimeObserver_priv::startup_notify(Romain::App_instance *inst,
83                                                   Romain::App_thread *,
84                                                   Romain::Thread_group *,
85                                                   Romain::App_model *am)
86 {
87         for (auto i = _breakpoints.begin(); i != _breakpoints.end(); ++i) {
88                 DEBUG() << std::hex << (*i)->address();
89                 (*i)->activate(inst, am);
90         }
91 }
92
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)
98 {
99         if (!entry_reason_is_int3(t->vcpu(), i, am) &&
100                 !entry_reason_is_int1(t->vcpu()))
101                 return Romain::Observer::Ignored;
102
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;
107
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;
113
114                         int rv = libc_backend_rt_clock_gettime((struct timespec*)(spec_local));
115                         t->vcpu()->r()->ax   = rv;
116
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.
119                          */
120                         for (unsigned rep = 0; rep < Romain::_the_instance_manager->instance_count();
121                                  ++rep) {
122
123                                 if (rep == i->id())
124                                         continue;
125
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));
129                         }
130
131                         t->return_to(ret);
132
133                         return Romain::Observer::Replicatable;
134                 }
135         }
136
137         return Romain::Observer::Ignored;
138 }