another directory rename: failstar -> fail

"failstar" sounds like a name for a cruise liner from the 80s.  As "*" isn't a
desirable part of directory names, just name the whole thing "fail/", the core
parts being stored in "fail/core/".

Additionally fixing two build system dependency issues:
 - missing jobserver -> protomessages dependency
 - broken bochs -> fail dependency (add_custom_target DEPENDS only allows plain
   file dependencies ... cmake for the win)


git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@956 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
hsc
2012-03-08 19:43:02 +00:00
commit b70b6fb43a
921 changed files with 473161 additions and 0 deletions

15603
doc/class-diagram.dia Normal file

File diff suppressed because it is too large Load Diff

15603
doc/class-diagram.png Normal file

File diff suppressed because it is too large Load Diff

BIN
doc/collaboration.dia Normal file

Binary file not shown.

BIN
doc/collaboration.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,29 @@
// restore previously saved simulator state
RestoreEvent ev_restore("sav/p_entry.sav");
addEventAndWait(&ev_restore);
// breakpoint $instr instructions in the future
BPEvent ev_instr_reached(ANY_ADDR, instr);
addEvent(&ev_instr_reached);
// breakpoint at function exit
BPEvent ev_func_end(INST_ADDR_FUNC_END);
addEvent(&ev_func_end);
// if we reach the exit first, we're done
if (waitAny() == ev_func_end.id()) { break; }
// commission a register bit-flip FI
RegisterBitflip fi_bitflip(*reg, bitnr);
inject(&fi_bitflip);
// catch traps and timeout
TrapEvent ev_trap(ANY_TRAP);
addEvent(&ev_trap);
BPEvent ev_timeout(ANY_ADDR, 1000);
addEvent(&ev_timeout); // [...]
// wait for function exit, trap or timeout
if ((id = waitAny()) == ev_func_end.id()) {
int result = registers(REG_EAX).cur_value();
log(*reg,bitnr,instr,LOG_RESULT,result);
} else if (id == ev_trap.id()) {
log(*reg,bitnr,instr,LOG_TRAP,ev_trap.type());
} else if (id == ev_timeout.id()) {
log(*reg,bitnr,instr,LOG_TIMEOUT); }

View File

@ -0,0 +1,49 @@
for (auto reg = registers.begin(); reg != registers.end(); ++reg) {
for (int bitnr = 0; bitnr < (*reg).width(); ++bitnr) {
for (int instr = 0; ; ++instr) {
clearEvents();
// restore previously saved simulator state
RestoreEvent ev_restore("./bochs_save_point");
addEventAndWait(&ev_restore);
// breakpoint $instr instructions in the future
BPEvent ev_instr_reached(ANY_ADDR, instr);
addEvent(&ev_instr_reached);
// breakpoint at function exit
BPEvent ev_func_end(INST_ADDR_FUNC_END);
addEvent(&ev_func_end);
// if we reach the exit first, this round is done
if (waitAny() == ev_func_end.id()) {
break;
}
// inject bit-flip at bit $bitnr in register $reg
RegisterBitflip fi_bitflip(*reg, bitnr);
inject(&fi_bitflip);
// catch traps and timeout
TrapEvent ev_trap(ANY_TRAP);
addEvent(&ev_trap);
BPEvent ev_timeout(ANY_ADDR, 1000);
addEvent(&ev_timeout);
// we assert the succeeded bit-flip is the first thing we hear
id = waitAny();
assert(id == fi_bitflip.id());
// wait for function exit, trap or timeout
id = waitAny();
if (id == ev_func_end.id()) {
// log result
int result = registers(REG_EAX).cur_value();
log_test_result(*reg, bitnr, instr, LOG_RESULT, result);
} else if (id == ev_trap.id()) {
log_test_result(*reg, bitnr, instr, LOG_TRAP, ev_trap.TrapNr());
} else if (id == ev_timeout.id()) {
log_test_result(*reg, bitnr, instr, LOG_TIMEOUT);
}
}
}
}

243
doc/howto-build.txt Normal file
View File

@ -0,0 +1,243 @@
Additional libraries/packages/tools needed for Fail*:
libprotobuf-dev
libpthread
libpcl1-dev
libboost-dev
libboost-all-dev (or at least libboost-thread-dev)
protobuf-compiler
cmake
cmake-curses-gui
AspectC++ (ag++, ac++) SVN
(2012-01-25 or newer is known to work and can be obtained from
http://akut.aspectc.org/)
For distribution/parallelization:
rsync
tmux
32-bit FailBochs on x86_64 Linux machines:
libc6-i386
+ all libraries listed by "ldd bochs|awk '{print $3}'" in ~/bochslibs
(client.sh will add these to LD_LIBRARY_PATH)
===========
Build steps
===========
Build Fail*
===========
For the first time
------------------
cd failbochs/
> (optional) Cleanup previous cmake remnants
find -name CMakeCache.txt | xargs rm
> Create out of source build directory
mkdir build
> Enter out-of-source build directory
> All generated files end up there.
cd build
>> Generate cmake environment.
cmake ..
>> Setup build configuration
> Select BUILD_BOCHS or BUILD_OVP
> Select an experiment to enable by naming its experiments/ subdirectory under
> EXPERIMENTS_ACTIVATED
> Press 'c', 'g' to regenerate the build system
> (alternatively use "cmake-gui ." for a Qt GUI)
ccmake .
> Additionally make sure Bochs is at least configured (see below).
After changes to Fail* code
---------------------------
> Compile (optionally add -jN for parallel building)
make
> cmake will build all fail* libraries, merge them into
> a libfail.a and put it into failbochs/fail.
> (as the current Bochs Makefile expects it there..)
Debug build
-----------
> Choose "Debug" as the build type:
ccmake .
Add new (fail*) sources to build chain
--------------------------------------
To add new files to the build, see CMakeLists.txt in
failbochs/fail, which is hopefully self explanatory. :)
Add new user-defined experiment/campaign
----------------------------------------
Look at experiments/coolchecksum/ as a template. After creating a new
subdirectory in experiments/, activate it in the cmake configuration step (see
above).
Build Bochs
===========
For the first time
------------------
cd ../bochs
./configure --prefix=$(echo ~/localroot/usr) --enable-{a20-pin,x86-64,cpu-level=6,ne2000,acpi,pci,usb,repeat-speedups,trace-cache,fast-function-calls,host-specific-asms,disasm,all-optimizations,readline,clgd54xx,fpu,vmx=2,monitor-mwait,cdrom,sb16=linux,gdb-stub} --disable-docbook --with-all-libs
> Instead of --with-all-libs, you could use --with-nogui for "headless"
> experiments, additionally removing lots of library dependencies (thus
> reducing startup overhead). --with-x11 enables only the "x" (X11), --with-wx
> only the "wx" (wxWidgets) GUI. Note that "wx" does not play well together
> with Fail*'s "restore" feature (FailBochs will fall back to "x" if available,
> or die trying.)
>
> Once you know everything works as it should, you may want to add the
> following flags before running larger campaigns:
> --disable-logging --disable-assert-checks
>
> FIXME remove more redundant flags/libraries
After changes to Bochs code or Bochs-affecting aspects
------------------------------------------------------
> The make call from the make-ag++.sh is now invokable by calling (still in
> your build dir, optionally adding -jN for parallel building):
cd ../build
make bochs
> The former make all-clean is now invokable by
make bochsallclean
> For installing the bochs executable (former make install)
make bochsinstall
> (see >make help< for a target listing.)
> You may use scripts/rebuild-bochs.sh to speed up repetitive tasks regarding
> Fail/Bochs builds. This script contains a concise documentation on itself.
Debug build
-----------
> Configure Bochs to use debugging-related compiler flags:
cd ../bochs
CXXFLAGS="-g -O0" ./configure --prefix=... ... (see above)
Profiling-based optimization build
----------------------------------
> FIXME: ag++ needs to be run with --keep_woven
> Configure Bochs to use compiler flags to enable profiling:
cd ../bochs
CXXFLAGS="-fprofile-generate" LDFLAGS="-fprofile-generate" ./configure --prefix=... ... (see above)
> Build Bochs normally, and run it.
> Configure Bochs to use compiler flags to enable optimizations based on profiling results:
CXXFLAGS="-fprofile-use -Wcoverage-mismatch" LDFLAGS="-fprofile-use" ./configure --prefix=... ... (see above)
Benchmarking
------------
> Simple instructions/second measurement:
> - configure Bochs with --enable-show-ips (see above)
> - bochsrc: print_timestamps: enabled=1
> Comparison IPS numbers are shown in the default bochsrc.
> Headless bochsrc configuration, all aspects disabled, guest system executes
> endless loop, host CPU Xeon X5470 (3.33GHz): IPS: 66124283 average = 66964789
Steps to run a boot image in FailBochs:
---------------------------------------
Follow the Bochs documentation, and start your own "bochsrc" configuration file based on the
$PREFIX/share/doc/bochs/bochsrc-sample.txt template (or
/usr/share/doc/bochs/examples/bochsrc.gz on Debian systems with Bochs
installed).
- Add your floppy/cdrom/hdd image in the floppya/ata0-master/ata0-slave
sections; configure the boot: section appropriately.
- Comment out com1 and parport1.
- For "headless" experiments:
config_interface: textconfig
display_library: nogui
- For an X11 GUI:
config_interface: textconfig
display_library: x
- For a wxWidgets GUI (does not play well with Fail*'s "restore" feature):
config_interface: wx
display_library: wx
- Reduce the guest system's RAM to a minimum to reduce FailBochs's memory
footprint and save/restore overhead, e.g.:
memory: guest=16, host=16
- If you want to redirect FailBochs's output to a file using the shell's
redirection operator '>', make sure /dev/stdout is not used as a target
file for logging. (The Debian bochsrc template unfortunately does this in
two places. It suffices to comment out these entries.)
- To make FailBochs terminate if something unexpected happens in a larger
campaign, be sure it doesn't "ask" in these cases, e.g.:
panic: action=fatal
error: action=fatal
info: action=ignore
debug: action=ignore
pass: action=ignore
- If you need a quick-and-dirty way to pass data from the guest system to the
outside world, and you don't want to write an experiment utilizing
GuestEvents, you can use the "port e9 hack" that prints all outb's to port
0xe9 to the console:
port_e9_hack: enabled=1
- Determinism: (Fail)Bochs is deterministic regarding timer interrupts,
i.e., two experiment runs after calling simulator.restore() will count the
same number of instructions between two interrupts. Though, you need to be
careful when running (Fail)Bochs with a GUI enabled: Typing "bochs -q<return>"
on the command line may lead to the GUI window receiving a "return key
released" event, resulting in a keyboard interrupt for the guest system.
This can be avoided by starting Bochs with "sleep 1; bochs -q", or
disabling the GUI (see "headless experiments" above).
Build OVP for Cortex-M3
=======================
For the first time
------------------
> Get a license from ovpworld.org
> Download:
> - Downloads -> Main OVP Download including OVPsim Simulator
> - Downloads -> ARM -> ARM OVP Cortex-M Profile Model
> - -> Self contained ARM Cortex-M examples
> - -> ARM GNU GCC and GDB tools
> Install OVP by running the self-extracting archives.
>
> Get Sourcery CodeBench Lite Edition from
> http://www.mentor.com/embedded-software/codesourcery
> - ARM processors -> EABI release
> Install the self-extracting archive, or use the installation in
> /fs/proj/compiler/codesourcery-arm-eabi (DO, ios/kos)
>
> TODO source setup.sh, setupImperas ...
> TODO hard-coded paths
=====================================
Example experiments and code snippets
=====================================
hscsimple
---------
A simple standalone experiment (without a separate campaign).
MHTestCampaign
--------------
An example for separate campaign/experiment implementations.
1. execute Campaign (job server):
<your_build_dir>/core/experiments/MHTestCampaign/mhcampaign
2. run the FailBochs instance, in properly defined environment:
bochs
Dwarf example (tests/dwarf.cc)
------------------------------
Dependencies:
LibDwarf: (debian/ubuntu package: libdwarf-dev)
LibElf: (debian/ubuntu package: libelf-dev)
Build with cmake:
cd {your-out-of-source-dir}
cmake {path to fail dir}
-> cmake checks if libelf and libdwarf are present
make dwarf
./tests/dwarf main.elf

180
doc/todo.txt Normal file
View File

@ -0,0 +1,180 @@
FailBochs-Bausteine TODO
========================
Wer gerade an was arbeitet, steht in Klammern hinter dem TODO.
Bochs:
- Determinismus: Wie kann für Mikroexperimente sichergestellt werden, dass
externe Ereignisse (Timer, Eingang von Netzwerkpaketen, ...) reproduzierbar
zum selben Zeitpunkt eintreffen? (rh)
- Interrupts teilweise oder komplett sperren
- optional: Interrupts auslösen
- gemeinsame Namen fuer RDX/EDX (ab)
Abstraktionen:
- Backend-Schnittstelle (z.B. direkte Anbindung an Simulator vs.
GDB-Schnittstelle zu Simulator vs. Anbindung an reale HW) von
Backend-Metainformationen (welche Register gibt es, wie breit ist der
Datenbus, welche Traps können ausgelöst werden)
- Endianness?
- Merkmalmodell von Implementierungsdetails trennen (hsc)
-> automatische Konfigurierung anhand Experimentauswahl
-> Annotierung von Experimentcode, automatisches Nachladen von Aspekten
- zum Verpacken in ExperimentData-Nachrichten Register<->String-Konvertierung
vereinfachen (ab)
- Namespace Confusion: was gehört in fi::, was in sal::? Brauchen wir noch
beides, brauchen wir was Zusätzliches?
- einheitliches Namensschema für Backend-Beeinflussungen (Interrupt-Synthese,
Interrupt-Unterdrückung, Speicher schreiben, Register schreiben, ...) finden
-> "Fehlerinjektion" ist das ja nicht immer
- (Allgemeine) Testfälle?
-> Modifikationen an FAIL* sind damit leichter zu verifizieren
- Ausgaben (z.B. im Bochs-Controller, siehe BochsController::save)
vereinheitlichen, evtl. zusätzlich via (Non-)Verbose-Mode(s)
-> "Ausgabesystem", "Logger"
Events:
- sobald mehrere Aspekte an derselben Stelle hooken, muss in einer Schleife
nach jeder Kontrollübergabe an den SimulatorController geprüft werden, ob
neue Events oder Fehlerinjektionsaufträge vorliegen
-> Anwendungsfall z.B. Breakpoint an Adresse X, danach Zustandssicherung;
man will natürlich EIP==X in dem gesicherten Zustand haben, nicht X+y (hsc)
- MemEvents: Instruction-Fetch und weitere CPU-interne Speicherzugriffe
(Interrupt-Kontextsicherung, HW-Tasks, Interrupt-Vektoren, ...) ermöglichen
und konfigurierbar machen
Parallelisierung:
- Momentan landen initial *alle* Parametersätze im Speicher. Sobald das viel
mehr werden, wird das eventuell eng.
-> BoundedSynchronizedQueue basteln, Kampagne blockiert dann, wenn die voll ist
-> eingehende Resultate nicht in der Kampagne "verarbeiten" (rausschreiben)
-- sonst bekommen wir dasselbe Problem mit der Queue der Resultate;
stattdessen z.B. die Idee der ExperimentDataStorage weiterverfolgen,
Ergebnisse werden asynchron zur Kampagne weggeschrieben
(oder: Zweiteilung der Kampagne vornehmen, "Verarbeitung" in eigenem
Thread)
- coolcampaign fährt momentan ziemlich Achterbahn bei RAM-Benutzung
-> Grund analysieren, ggf. beheben (Ressourcenverwaltung? Threadpool?)
- warum skalieren die Experimente/s nicht (ganz) linear mit der Anzahl der
Cores auf einer Maschine? Jobserver-Problem, oder lokal Contention auf dem
Client (Kernel, Disk-IO)?
-> mal Experimente ohne Kommunikation laufenlassen, Durchsatz messen
-> mal mit mehreren Maschinen durchmessen
- JobServer Statistiken ausgeben lassen, dafür keine Meldung mehr bei jedem Auftrag
* Anzahl Hosts
* Anzahl Clients (momentan ununterscheidbar ...)
* Aufträge pro Sekunde
* ETA bis Kampagne komplett
- Client/Server-TCP-Verbindungen aufrechterhalten
- Client-Timeouts untersuchen, Server-Implementierung tunen? Retries im Client?
- unbeantwortete Jobs am Ende einer Kampagne erneut vergeben
- die Möglichkeit schaffen, im Server mehr Informationen über einen Job
vorhält (und dann auch loggt), als man an den Client kommuniziert
-> bei Fault-Space-Pruning hat man im Server Äquivalenzklassen, aus denen
man nur einen einzelnen Parametersatz auswählt und dem Client zum
Ausprobieren gibt; die Informationen über die Äquivalenzklasse müss(t)en
nicht über die Leitung, werden aber am Schluss zur Auswertung gebraucht
Implementierungsdetails:
- EventList, RegisterIterator, ...: nach Möglichkeit keine selbstgebauten
Container/Iteratoren etc. benutzen, sondern in der STL bedienen (z.B. von
std::list ableiten)
* falls doch ein Eigenbau notwendig ist, unbedingt STL-Schnittstellen
nachbilden
- einheitliche Fehlerbehandlung
- einheitliches Logging (Loglevels?)
Effizienz:
- zuerst: Bottleneck identifizieren!
- getrennte Queues?
- Queue-Suche optimieren (z.B. Hash-Idee)?
- boolean/Counter für Events (um Durchlaufen der Queue zu verhindern)?
- Dynamic AspectC++ ausprobieren
- Löschliste in EventList via Hashing implementieren (o.Ä.)?
Buildsystem:
- (mittelfristig) in cmake nur wirklich Build-spezifische Dinge konfigurieren
(verwendeter Compiler, Installationsverzeichnis, ...), den Rest in einem
brauchbaren Konfigurationswerkzeug mit Ausdrucksmöglichkeiten für
Merkmalmodelle, Abhängigkeiten, Mehrfachauswahl etc. (kconfig?)
* Bochs / OVP sind Alternativen, nicht beide anschaltbar (?)
- EXP*-options nur einmal in config/, nicht in drei verschiedenen Dateien
(config/CMakelists.txt, config/experiments.hpp.in,
experiments/CMakeLists.txt)
* Hinzufügen eines neuen Experiments konkreter dokumentieren (howto-build.txt?)
- AspectConfig.hpp in cmake-config einbinden (genauso behandeln wie experiments.hpp!)
-> generierte Datei landet in Buildtree, wird nicht mehr eingecheckt
- variant_config.h in cmake-config einbinden (genauso behandeln wie experiments.hpp!)
-> generierte Datei landet in Buildtree, wird nicht mehr eingecheckt
Dokumentation:
- Änderungen im Klassendiagramm nachziehen (hsc)
------------------------------------------------
Erledigt:
- alle Events mit Zähler versehen, so dass sie erst bei Erreichen der 0 feuern
* z.B. erst nach dem 5ten Mal Lesen von Adresse X auslösen
- Bereiche von Instruction-Pointern
- Wrapper für häufig auftretende Experimentmuster, z.B. einzelnes Event
anlegen und dann genau darauf warten
- Wildcards für beliebige Instruktions- bzw. Speicheradresse (ANY_ADDR, siehe Event.hpp),
inkl. Anpassung des ausgelösten Events
- Registerzugriff aus dem Experiment-Controller, RegisterBitflip vorbereitet
- Auslösen von Reboot (rh)
- Auslesen von Register- und Speicherzustand (Kontext Golden-Run-Vergleiche etc.)
- Coroutinen-Bibliothek (oder getcontext/setcontext) statt Threads+Synchronisation?
- Bitflips in Register
- nach Eintreten eines Events wird das Event- (oder FI-)Objekt mit
Detailinformationen befüllt
-> insbesondere bei "Wildcards" (ANY_TRAP) will man ja im
Experimentablauf wissen, was jetzt eigentlich passiert ist
- Event-Aspekt zur Kommunikation mit dem Gastsystem fertig stellen (siehe events/GuestSysCom.ah)
- Bochs-Spezifika von Bochs-unabhängigen Codeteilen trennen
-> Simulator-Abstraktionsschicht
-> Schnittstelle für Informationen über Plattformspezifika, z.B. Register + Bitbreiten
-> Bochs-spezifische Aspekte leiten nur noch Kontrollfluss um,
Implementierung von Ereignissen separat
- (sofern möglich) Ereignisse von FI trennen
- Scattering-Graphik (ab)
- ohne GUI bzw. gesetztem $DISPLAY lauffähig? (rh)
- Save (rh):
- Zielverzeichnis anlegen, falls nicht existent
- Fehlermeldung, falls Zielverzeichnis nicht schreibbar
- FI-Jobs gibt's nicht mehr, überall rauswerfen (ab)
- Traps und Interrupts (alle, oder Match auf beliebige Teilmenge)
(Aspekte existieren bereits. Matchen auf beliebige Teilmenge der Traps ist noch nicht moeglich)
(rh)
- die schlimmsten Speicherlecks in Bochs eliminieren (rh)
- Event-IDs als Identifikationsmittel für Events auf den zweiten Platz verweisen
-> IDs gibt's weiterhin (getId()), aber z.B. waitAny() liefert einen Pointer
- Brauchen wir eigentlich IDs als Handles für Events, oder genügt es nicht
eigentlich, die Event-Objektadresse zu verwenden?
- Event-Match-Schleife von Event-Feuer-Schleife trennen (ab):
- erst alle Events, die aktuell matchen, sammeln (Code ggf. spezifisch für die Ereignisart)
- dann sequentiell feuern (Code zentral in SimulatorController)
-> keine Probleme mit nachträglich hinzukommenden Events
- dann leider immer noch Probleme mit nachträglich entfernten Events
-> siehe fail/experiments/coolchecksum/experiment.cc FIXME am Ende
-> Lösung: Löschliste
- ggf. zusammen mit Datenstruktur-Implementierungsdetails-TODO (s.u.) angehen
==================================
Theorie TODO
==================================
Problem Fork von FI Tools -> Merging eklig.
-> Liste mit konkreten Beispielen
========================
FailOVP-Bausteine TODO
========================
- save/restore implementieren -> Speicher-, Register-, Timer-, ??- Zustaende
- Sections aus ELF Datei extrahieren, entsprechende Speicherbereiche (generisch) anlegen (rz)
- Symbole aus ELF extrahieren -> Adressen von globalen Objekten/Funktionen in Experimenten angeben (rz)
- Prozessormodell per cmake cleanen und neu bauen (mh)
- CiAO ELF in OVP ausfuehren
ERLEDIGT
========================