6 * Definition of the instance manager that knows about all
7 * redundant VCPUs as well as the fault observers.
9 * (c) 2011-2013 Björn Döbel <doebel@os.inf.tu-dresden.de>,
10 * 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.
17 * Romain instance manager
22 #include "constants.h"
24 #include "thread_group.h"
25 //#include "app_loading"
26 #include "fault_observers"
31 #include "redundancy.h"
32 #include <l4/plr/measurements.h>
35 EXTERN_C void *split_handler_fn(void*);
36 #endif // SPLIT_HANDLING
41 * Set up and keep track of the running instances
46 Romain::App_model *_am;
47 std::vector<Romain::App_instance *> _instances; // instance list
49 Romain::Observer *_observer_list[Romain::MAX_OBSERVERS]; // exception observer list
50 //Romain::RedundancyCallback *_callback; // the callback for redundancy checking
51 unsigned _num_observers;
53 char const *_name; // app name
54 unsigned _num_inst; // number of instances to run
55 l4_umword_t _num_cpu; // number of available CPUs
57 l4_addr_t _init_eip; // initial EIP (from ELF)
58 l4_addr_t _init_esp; // initial ESP (from ELF)
59 unsigned _gdt_min; // start of GDT entries
61 unsigned _argc; // client argc
62 char const **_argv; // argv of the client
64 Measurements::EventBuf *_logBuf;
67 pthread_t _split_handler; // resilient core handler thread
68 #endif // SPLIT_HANDLING
72 * Prepare handler stack by pushing 3 values:
74 * 1st parameter is an app_thread
75 * 2nd parameter is an app_instance
76 * 3rd parameter is a dummy for the location where usually the
77 * return address would be located
78 * 4th parameter is the thread group we are dealing with
80 l4_addr_t prepare_stack(l4_addr_t sp, Romain::App_instance *inst,
81 Romain::App_thread *thread, Romain::Thread_group* tgroup);
84 void configure_logflags(char *flags);
85 void configure_fault_observers();
86 void configure_redundancy();
87 void configure_logbuf(int size);
90 InstanceManager(unsigned argc, char const **argv, unsigned num_instances = 1);
94 * Prepare the replica instances (VCPUs)
96 void create_instances();
99 * Create a single replica thread along with
100 * its VCPU handler stack
102 Romain::App_thread* create_thread(l4_umword_t eip, l4_umword_t esp, unsigned inst, Romain::Thread_group *group);
105 * Create a group of replica threads, e.g., all replicas
106 * of a single original thread
108 Romain::Thread_group* create_thread_group(l4_umword_t eip, l4_umword_t esp,
109 std::string, unsigned cap, unsigned uid);
112 * Setup the VCPU handler stack.
114 * Puts fake parameters on the handler stack so that
115 * upon an event it looks like we got them passed as
118 void prepare_handler_stack(Romain::App_thread *t, Romain::App_instance* i);
121 * Start the instances
123 void run_instances();
126 void register_fault_observer(Romain::Observer* ob)
128 _check(_num_observers >= MAX_OBSERVERS, "no more observers");
129 _observer_list[_num_observers++] = ob;
134 Romain::RedundancyCallback *redundancy() const { return _callback; }
137 void set_redundancy_callback(Romain::RedundancyCallback* cb)
139 _check(_callback != 0, "there is already a callback registered?");
145 void startup_notify(Romain::App_instance *i, Romain::App_thread *t,
146 Romain::Thread_group* tg, Romain::App_model *a) const
148 // XXX would need to be aware of observer list modifications
149 // -> for now, we assume that observers are not added/removed
150 // at runtime. otherwise we'd use sth. like an r/w lock with
151 // reader prioritization??
152 for (unsigned idx = 0; idx < _num_observers; ++idx) {
153 DEBUG() << "[" << i->id() << "] startup notifying: " << _observer_list[idx]->name();
154 _observer_list[idx]->startup_notify(i,t,tg,a);
160 * Entry point for CPU exception handling.
162 * Iterates over the list of registered observers and calls
163 * every observer's notify() function. Observers may stop
164 * this iteration process. See Romain::Observer::ObserverReturnVal
166 Romain::Observer::ObserverReturnVal
167 fault_notify(Romain::App_instance *i, Romain::App_thread *t,
168 Romain::Thread_group* tg, Romain::App_model *a)
170 Romain::Observer::ObserverReturnVal v = Romain::Observer::Ignored;
171 // XXX would need to be aware of observer list modifications
172 // -> for now, we assume that observers are not added/removed
173 // at runtime. otherwise we'd use sth. like an r/w lock with
174 // reader prioritization??
175 for (unsigned idx = 0; idx < _num_observers; ++idx) {
176 //DEBUG() << "[" << i->id() << "] notifying: " << _observer_list[idx]->name();
177 v = _observer_list[idx]->notify(i,t,tg,a);
179 case Romain::Observer::Finished:
180 case Romain::Observer::Replicatable:
181 //DEBUG() << "Fault handling done: " << std::hex << v;
191 void query_observer_status()
193 for (unsigned idx = 0; idx < _num_observers; ++idx) {
194 //INFO() << "querying: " << _observer_list[idx]->name();
195 _observer_list[idx]->status();
200 unsigned instance_count() const { return _num_inst; }
202 Measurements::EventBuf* logbuf() { return _logBuf; }
205 static void VCPU_handler(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
206 static void VCPU_startup(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
211 * Read config from cfg file