]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/fault_handlers/replicalog.cc
update
[l4.git] / l4 / pkg / plr / server / src / fault_handlers / replicalog.cc
1 /*
2  * replicalog.cc --
3  *
4  *     Fault observer that attaches a magic event buffer
5  *     (see measurements.h) to each replica and dumps the replicas'
6  *     event buffers after the program terminates.
7  *
8  * (c) 2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
9  *     economic rights: Technische Universität Dresden (Germany)
10  *
11  * This file is part of TUD:OS and distributed under the terms of the
12  * GNU General Public License 2.
13  * Please see the COPYING-GPL-2 file for details.
14  */
15
16 #include "observers.h"
17 #include "../configuration"
18 #include "../memory"
19 #include "../manager"
20
21 #include <l4/plr/uu.h>
22
23 namespace Romain {
24         extern InstanceManager *_the_instance_manager;
25 }
26
27 Romain::ReplicaLogObserver::ReplicaLogObserver()
28 {
29         for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
30                 buffers[i].local_addr = 0;
31         }
32 }
33
34
35 void
36 Romain::ReplicaLogObserver::map_eventlog(Romain::App_instance *i, int logsizeMB)
37 {
38         int size = logsizeMB << 20;
39         unsigned mapops = 0;
40         l4_addr_t local_map_addr = buffers[i->id()].local_addr;
41         l4_addr_t remote_map_addr = Romain::REPLICA_LOG_ADDRESS;
42
43         /* 1. map the TSC shared page read-only */
44         INFO() << "shared tsc @ " << Romain::_the_instance_manager->logbuf()->timestamp;
45         i->map_aligned(reinterpret_cast<l4_addr_t>(Romain::_the_instance_manager->logbuf()->timestamp),
46                        Romain::REPLICA_TSC_ADDRESS, L4_PAGESHIFT, L4_FPAGE_RO);
47
48         /* Now initialize the shared event buffer */
49         Measurements::EventBuf* buf = reinterpret_cast<Measurements::EventBuf*>(buffers[i->id()].local_addr);
50         buf->index = 0;
51         buf->sharedTSC = true;
52         buf->set_buffer((unsigned char*)remote_map_addr + sizeof(Measurements::GenericEvent), (logsizeMB << 20) - sizeof(Measurements::GenericEvent));
53         INFO() << buf->index << " " << buf->size << std::endl;
54
55         while (size > 0) {
56
57                 unsigned sz, shift;
58
59                 if (size >= (4 << 20)) { // map 4 MB page
60                         sz = L4_SUPERPAGESIZE;
61                         shift = L4_SUPERPAGESHIFT;
62                 } else { // map 4 kB page
63                         sz = L4_PAGESIZE;
64                         shift = L4_PAGESHIFT;
65                 }
66
67                 i->map_aligned(local_map_addr, remote_map_addr, shift, L4_FPAGE_RW);
68                 size            -= sz;
69                 local_map_addr  += sz;
70                 remote_map_addr += sz;
71                 mapops          += 1;
72         }
73
74         INFO() << "Mapped to replica. Used " << mapops << " map() operations";
75 }
76
77
78 void Romain::ReplicaLogObserver::startup_notify(Romain::App_instance *i,
79                                                                     Romain::App_thread *t,
80                                                                     Romain::Thread_group *tg,
81                                                                     Romain::App_model *a)
82 {
83         static bool logregion_reserved = false;
84
85         int logMB = ConfigIntValue("general:replicalogsize");
86         if (logMB == -1) { // use general logbuf size if no specific size was set
87                 logMB = ConfigIntValue("general:logbuf");
88         }
89
90         INFO() << "Replica log size: " << logMB << " MB";
91
92         /* Reserve the area at the replicas' RM. We map this buffer without going through
93            the official channels. */
94         if (!logregion_reserved) {
95                 a->rm()->attach_area(Romain::REPLICA_LOG_ADDRESS, logMB << 20, 0, L4_SUPERPAGESHIFT);
96                 logregion_reserved = true;
97         }
98
99         L4::Cap<L4Re::Dataspace> mem;
100         buffers[i->id()].local_addr = Romain::Region_map::allocate_and_attach(&mem, logMB << 20, 0, L4_SUPERPAGESHIFT);
101         INFO() << "Buffer for instance " << i->id() << " @ " << std::hex << buffers[i->id()].local_addr;
102         l4_touch_rw(reinterpret_cast<void*>(buffers[i->id()].local_addr), logMB << 20);
103
104         map_eventlog(i, logMB);
105
106         //enter_kdebug("LogObserver::startup");
107 }
108
109
110 Romain::Observer::ObserverReturnVal
111 Romain::ReplicaLogObserver::notify(Romain::App_instance *i,
112                                    Romain::App_thread *t,
113                                    Romain::Thread_group *tg,
114                                    Romain::App_model *a)
115 {
116         /* We don't handle any events. */
117         return Romain::Observer::Ignored;
118 }
119
120
121 void
122 Romain::ReplicaLogObserver::dump_eventlog(unsigned id) const
123 {
124         INFO() << "Dumping ... " << id;
125
126         Measurements::EventBuf *buf = reinterpret_cast<Measurements::EventBuf*>(buffers[id].local_addr);
127         INFO() << "  event buffer @ " << std::hex << buf;
128
129         char filename[32];
130         snprintf(filename, 32, "replica%d.log", id);
131
132         INFO() << "file: " << filename;
133
134         unsigned oldest = buf->oldest();
135
136         INFO() << "oldest: " << oldest;
137
138         l4_umword_t dump_start, dump_size;
139         if (!oldest) {
140                 dump_start = 0;
141                 dump_size  = buf->index * sizeof(Measurements::GenericEvent);
142         } else {
143                 dump_start = oldest * sizeof(Measurements::GenericEvent);
144                 dump_size  = buf->size * sizeof(Measurements::GenericEvent);
145         }
146
147         /* buf addr is relocated in replica AS -> need to retransform */
148         char *bufaddr = ((l4_addr_t)buf->buffer - Romain::REPLICA_LOG_ADDRESS) + (char*)buf;
149
150         INFO() << "file: " << filename << " start " << dump_start << " size " << dump_size;
151         uu_dumpz_ringbuffer(filename, bufaddr,
152                             buf->size * sizeof(Measurements::GenericEvent),
153                             dump_start, dump_size);
154 }
155
156
157 void
158 Romain::ReplicaLogObserver::status() const
159 {
160         for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
161                 if (buffers[i].local_addr != 0) {
162                         dump_eventlog(i);
163                 }
164         }
165         //enter_kdebug("LogObserver::status");
166 }