]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/plr/server/src/fault_handlers/swifi.cc
update
[l4.git] / l4 / pkg / plr / server / src / fault_handlers / swifi.cc
1 #include <l4/sys/compiler.h>
2
3 #include "../configuration"
4 #include "../log"
5 #define MSG() DEBUGf(Romain::Log::Swifi)
6 #include "swifi.h"
7
8 Romain::SWIFIObserver *
9 Romain::SWIFIObserver::Create()
10 { return new SWIFIPriv(); }
11
12
13 void Romain::SWIFIPriv::status() const { }
14
15 void
16 Romain::SWIFIPriv::startup_notify(Romain::App_instance *i,
17                                   Romain::App_thread *,
18                                   Romain::Thread_group *tg,
19                                   Romain::App_model *a)
20 {
21         /*
22          * We only inject faults in replica 0
23          */
24         if (i->id() != 0)
25                 return;
26
27         if (_breakpoint) {
28                 _breakpoint->activate(i, a);
29                 MSG() << "set SWIFI bp";
30         }
31 }
32
33
34 Romain::Observer::ObserverReturnVal
35 Romain::SWIFIPriv::notify(Romain::App_instance *i,
36                           Romain::App_thread *t,
37                           Romain::Thread_group *tg,
38                           Romain::App_model *a)
39 {
40         Romain::Observer::ObserverReturnVal ret = Romain::Observer::Invalid;
41         /*
42          * Faults are injected into replica 0 only. All other replicas
43          * simply get told to wait until the fault injector is done.
44          */
45         if (i->id() != 0) {
46                 t->vcpu()->r()->ip--;
47                 return Romain::Observer::Finished_wait;
48         }
49
50         if (_breakpoint && _breakpoint->was_hit(t)) {
51                 INFO() << "\033[36m======== SWIFI: start (part 1) ========\033[0m";
52                 _breakpoint->deactivate(i,a);
53                 remove_breakpoint(t);
54                 /*
55                  * Faults are injected into replica 0 only. All other replicas
56                  * simply get told to wait until the fault injector is done.
57                  */
58                 if (i->id() != 0) {
59                         return Romain::Observer::Finished_wait;
60                 }
61
62                 t->print_vcpu_state();
63
64                 switch(_flags) {
65                         case GPR:   _flipper = new GPRFlipEmulator(t->vcpu(), a, i);
66                                                 MSG() << "GPRFlipped";
67                                                 // GPR flipping does not use second phase
68                                                 ret = Romain::Observer::Finished_wakeup;
69                                                 break;
70                         case INSTR: _flipper = new InstrFlipEmulator(t->vcpu(), a, i);
71                                                 ret = Romain::Observer::Finished_step;
72                                     break;
73                         case ALU:   _flipper = new ALUFlipEmulator(t->vcpu(), a, i);
74                                                 ret = Romain::Observer::Finished_step;
75                                     break;
76                         case RAT:   _flipper = new RATFlipEmulator(t->vcpu(), a, i);
77                                                 ret = Romain::Observer::Finished_step;
78                                                 break;
79                         case MEM:   _flipper = new MemFlipEmulator(t->vcpu(), a, i);
80                                                 ret = Romain::Observer::Finished_step;
81                                                 break;
82                         default:
83                                                 ERROR() << "Unhandled injection type: " << _flags;
84                                                 return Romain::Observer::Ignored;
85                 }
86                 flipper_trap3(t);
87                 INFO() << "\033[36m======== SWIFI: end (part 1) ========\033[0m";
88
89                 return ret;
90
91         } else if ((t->vcpu()->r()->trapno == 1) || 
92                           ((t->vcpu()->r()->trapno == 3) && (a->in_trampoline(t->vcpu()->r()->ip))))
93         {
94                 MSG() << "\033[36m======== SWIFI: start (part 2) ========\033[0m";
95                 switch(_flags) {
96                         case INSTR:
97                         case ALU:
98                         case RAT:
99                         case MEM:
100                                 flipper_trap1(t);
101                                 MSG() << "\033[36m======== SWIFI: end (part 2) ========\033[0m";
102                                 return Romain::Observer::Finished_wakeup;
103                         case GPR: // not for us in this case
104                         case None:
105                                 if (_flipper) delete _flipper;
106                                 break;
107                 }
108         }
109
110         MSG() << "\033[36m======== SWIFI: end (part 2) ========\033[0m";
111         return Romain::Observer::Ignored;
112 }
113
114
115 void Romain::SWIFIPriv::flipper_trap1(Romain::App_thread *t)
116 {
117         MSG() << std::hex << t->vcpu()->r()->ip << " " << _flipper->prev_eip()
118               << " + " << _flipper->ilen();
119
120         _flipper->revert();
121
122         t->vcpu()->r()->ip = _flipper->next_eip();
123         t->vcpu()->r()->flags &= ~TrapFlag;
124         t->print_vcpu_state();
125
126         delete _flipper;
127 }
128
129
130 void Romain::SWIFIPriv::flipper_trap3(Romain::App_thread *t, bool step)
131 {
132         if (_flipper->flip()) {
133                 t->vcpu()->r()->flags |= TrapFlag;
134         }
135         t->print_vcpu_state();
136 }
137
138
139 Romain::SWIFIPriv::SWIFIPriv()
140         : _breakpoint(0), _flags(None), _flipper(0)
141 {
142         struct timeval tv;
143         gettimeofday(&tv, 0);
144         srandom(tv.tv_usec);
145
146         l4_addr_t   target = ConfigIntValue("swifi:target");
147         char const* inject = ConfigStringValue("swifi:inject");
148         if (target && inject) {
149                 MSG() << "target: " << std::hex << target;
150                 MSG() << "   inj: " << inject;
151
152                 _breakpoint = new Breakpoint(target);
153                 if (strcmp(inject, "instr") == 0) {
154                         _flags = INSTR;
155                 } else if (strcmp(inject, "gpr") == 0) {
156                         _flags = GPR;
157                 } else if (strcmp(inject, "alu") == 0) {
158                         _flags = ALU;
159                 } else if (strcmp(inject, "rat") == 0) {
160                         _flags = RAT;
161                 } else if (strcmp(inject, "mem") == 0) {
162                         _flags = MEM;
163                 }
164         }
165 }