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.
8 * (c) 2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
9 * economic rights: Technische Universität Dresden (Germany)
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.
16 #include "observers.h"
17 #include "../configuration"
21 #include <l4/plr/uu.h>
24 extern InstanceManager *_the_instance_manager;
27 Romain::ReplicaLogObserver::ReplicaLogObserver()
29 for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
30 buffers[i].local_addr = 0;
36 Romain::ReplicaLogObserver::map_eventlog(Romain::App_instance *i, int logsizeMB)
38 int size = logsizeMB << 20;
40 l4_addr_t local_map_addr = buffers[i->id()].local_addr;
41 l4_addr_t remote_map_addr = Romain::REPLICA_LOG_ADDRESS;
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);
48 /* Now initialize the shared event buffer */
49 Measurements::EventBuf* buf = reinterpret_cast<Measurements::EventBuf*>(buffers[i->id()].local_addr);
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;
59 if (size >= (4 << 20)) { // map 4 MB page
60 sz = L4_SUPERPAGESIZE;
61 shift = L4_SUPERPAGESHIFT;
62 } else { // map 4 kB page
67 i->map_aligned(local_map_addr, remote_map_addr, shift, L4_FPAGE_RW);
70 remote_map_addr += sz;
74 INFO() << "Mapped to replica. Used " << mapops << " map() operations";
78 void Romain::ReplicaLogObserver::startup_notify(Romain::App_instance *i,
79 Romain::App_thread *t,
80 Romain::Thread_group *tg,
83 static bool logregion_reserved = false;
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");
90 INFO() << "Replica log size: " << logMB << " MB";
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;
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);
104 map_eventlog(i, logMB);
106 //enter_kdebug("LogObserver::startup");
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)
116 /* We don't handle any events. */
117 return Romain::Observer::Ignored;
122 Romain::ReplicaLogObserver::dump_eventlog(unsigned id) const
124 INFO() << "Dumping ... " << id;
126 Measurements::EventBuf *buf = reinterpret_cast<Measurements::EventBuf*>(buffers[id].local_addr);
127 INFO() << " event buffer @ " << std::hex << buf;
130 snprintf(filename, 32, "replica%d.log", id);
132 INFO() << "file: " << filename;
134 unsigned oldest = buf->oldest();
136 INFO() << "oldest: " << oldest;
138 l4_umword_t dump_start, dump_size;
141 dump_size = buf->index * sizeof(Measurements::GenericEvent);
143 dump_start = oldest * sizeof(Measurements::GenericEvent);
144 dump_size = buf->size * sizeof(Measurements::GenericEvent);
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;
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);
158 Romain::ReplicaLogObserver::status() const
160 for (unsigned i = 0; i < Romain::MAX_REPLICAS; ++i) {
161 if (buffers[i].local_addr != 0) {
165 //enter_kdebug("LogObserver::status");