Skip to content

Commit 90d9ebd

Browse files
stettbergerMalte Bargholz
andcommitted
Virtual Fault Space Abstraction
This is a large change that will break your traces and your database layouts. However, it repairs a lot of ad-hoc hacks that came into FAIL* over the years. What has changed? ================= The Virtual Fault Space Abstraction ----------------------------------- Files: sal/faultspace/* sal/x86/X86Faultspace.* sal/arm/ArmFaultSpace.* Instead of mapping registers ad-hoc into the virtual address space in order to smuggle the bit-packed register-id from import-trace through prune-trace and DatabaseCampaign to the DatabaseExperiment, we make this mapping now official and adaptable to more complex architectures. From now on the data_address field in the database is a fsp_address_t. These addresses are translated by the FS abstraction within the importer, which uses the architecture specific description of the virtual fault space. Within our whole tool chain, we now only work with fault-space addresses, which are the Y-axis of our fault space. When the fault-space address is about to be injected, we decode the numerical address to a FaultSpaceElement*, which knows how to inject a fault into itself. Thereby, we can unify the injection over different types of machine state and support multiple memory types. Furthermore, this simplifies import-trace and the DatabaseExperiment significantly. A detailed description of can be found in Malte Bargholz' Master thesis[1] Bit-Wise Pruning ---------------- Files: tools/import-trace/Importer.cc Until now, every state (register/memory) access had to be at least 8 bits wide. While this is good for memory reads, which always access at least a whole byte, this is not properly working for register accesses. Especially, for our integration of more complex CPU architectures (i.e., CHERI), we have to have bit-wise pruning to inject only single tag bits instead of injecting always 8 tag bits. Therefore, this change introduces bit-wise pruning for our importer. Instead of tracking only a single left margin for every fault-space address, we now track up to 8 different margins that are associated with an access mask. Thereby, the importer (which is effectively a def-use pruner) has to handle up to 8 left margins when accessing a byte with an access mask of 0xff. A detailed description of can be found in Malte Bargholz' Master thesis[1] Unification of Disassembler Interface ------------------------------------- The integration of the capstone disassembler into the RegisterImporter was more or less a clone-and-own integration. However, as both disassemblers basically perform the same task, a common interface is possible. Furthermore, the *FailTo*Translator* classes are no longer used for injecting registers as the dissassembler has nothing to do with the injector. This task is no performed by the virtual fault space. This change was tested with: - The integrated test-suite - The fail-target repo and injection of register,memory,EIP,randomjump - Both disassemblers Currently untested: - Gem5 [1] Quantifying Soft-Error Resilience of Embedded RISC-V Systems with Capability-based Memory Protection https://www.sra.uni-hannover.de/Theses/2020/bargholz_20_ma.pdf Co-authored-by: Christian Dietrich <dietrich@sra.uni-hannover.de> Co-authored-by: Malte Bargholz <malte@screenri.de>
1 parent c5f85b2 commit 90d9ebd

65 files changed

Lines changed: 1788 additions & 1607 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ root = true
88
end_of_line = lf
99
insert_final_newline = true
1010

11-
[{**/*.cc,**/*.hpp,**/*.ah,**/*.ah.in,**/*.proto}]
11+
[{**/*.cc,**/*.cpp,**/*.hpp,**/*.ah,**/*.ah.in,**/*.proto}]
1212
indent_style = tab
1313
indent_size = 4
1414

src/core/comm/DatabaseCampaignMessage.proto.in

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,12 @@ message DatabaseCampaignMessage {
2222

2323
required InjectionPointMessage injection_point = 10 [(sql_ignore) = true];
2424

25-
required bool inject_bursts = 11 [default = false];
26-
enum RegisterInjectionMode {
27-
OFF = 0;
28-
AUTO = 1;
29-
FORCE = 2;
30-
RANDOMJUMP = 3;
25+
enum InjectionMode {
26+
BITFLIP = 0;
27+
BURST = 1;
28+
RANDOMJUMP = 2;
3129
}
32-
optional RegisterInjectionMode register_injection_mode = 12 [default = OFF];
30+
optional InjectionMode injection_mode = 11 [default = BITFLIP];
3331
}
3432

3533
message DatabaseExperimentMessage {

src/core/cpn/DatabaseCampaign.cc

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,7 @@ bool DatabaseCampaign::run() {
4949
CommandLine::option_handle BURST =
5050
cmd.addOption("","inject-bursts", Arg::None,
5151
"--inject-bursts \tinject burst faults (default: single bitflips)");
52-
CommandLine::option_handle REGISTERS =
53-
cmd.addOption("","inject-registers", Arg::None,
54-
"--inject-registers \tinject into ISA registers (default: memory)");
55-
CommandLine::option_handle REGISTERS_FORCE =
56-
cmd.addOption("","force-inject-registers", Arg::None,
57-
"--force-inject-registers \tinject into ISA registers only, ignore high addresses");
58-
CommandLine::option_handle REGISTERS_RANDOMJUMP =
52+
CommandLine::option_handle RANDOMJUMP =
5953
cmd.addOption("","inject-randomjumps", Arg::None,
6054
"--inject-randomjumps \tinject random jumps (interpret data_address as jump target, as prepared by RandomJumpImporter)");
6155

@@ -105,27 +99,16 @@ bool DatabaseCampaign::run() {
10599
}
106100

107101
if (cmd[BURST]) {
108-
m_inject_bursts = true;
102+
m_injection_mode = DatabaseCampaignMessage::BURST;
109103
log_send << "fault model: burst" << std::endl;
104+
} else if (cmd[RANDOMJUMP]) {
105+
m_injection_mode = DatabaseCampaignMessage::RANDOMJUMP;
106+
log_send << "fault model: randomjump" << std::endl;
110107
} else {
111-
m_inject_bursts = false;
108+
m_injection_mode = DatabaseCampaignMessage::BITFLIP;
112109
log_send << "fault model: single-bit flip" << std::endl;
113110
}
114111

115-
if (cmd[REGISTERS] && !cmd[REGISTERS_FORCE]) {
116-
m_register_injection_mode = DatabaseCampaignMessage::AUTO;
117-
log_send << "register injection: auto" << std::endl;
118-
} else if (cmd[REGISTERS_FORCE]) {
119-
m_register_injection_mode = DatabaseCampaignMessage::FORCE;
120-
log_send << "register injection: on" << std::endl;
121-
} else if (cmd[REGISTERS_RANDOMJUMP]) {
122-
m_register_injection_mode = DatabaseCampaignMessage::RANDOMJUMP;
123-
log_send << "register injection: randomjump" << std::endl;
124-
} else {
125-
m_register_injection_mode = DatabaseCampaignMessage::OFF;
126-
log_send << "register injection: off" << std::endl;
127-
}
128-
129112
if (cmd[PRUNER]) {
130113
m_fspmethod = std::string(cmd[PRUNER].first()->arg);
131114
} else {
@@ -219,8 +202,6 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
219202
MYSQL_ROW row = mysql_fetch_row(count);
220203
experiment_count = strtoul(row[0], NULL, 10);
221204

222-
223-
224205
MYSQL_RES *pilots = db->query_stream ((sql_select + sql_body).c_str());
225206
if (!pilots) {
226207
exit(1);
@@ -237,7 +218,7 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
237218
ConcreteInjectionPoint ip;
238219

239220
unsigned sent_pilots = 0, skipped_pilots = 0;
240-
unsigned long long expected_injections = 0;
221+
unsigned long long expected_injections = 0;
241222
while ((row = mysql_fetch_row(pilots)) != 0) {
242223
unsigned pilot_id = strtoul(row[0], NULL, 10);
243224
unsigned injection_instr = strtoul(row[1], NULL, 10);
@@ -246,13 +227,17 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
246227
unsigned instr1 = strtoul(row[5], NULL, 10);
247228
unsigned instr2 = strtoul(row[6], NULL, 10);
248229

249-
unsigned expected_results = m_inject_bursts ? 1 : __builtin_popcount(data_mask);
230+
unsigned expected_results = __builtin_popcount(data_mask);
231+
if (m_injection_mode == DatabaseCampaignMessage::BURST
232+
|| m_injection_mode == DatabaseCampaignMessage::RANDOMJUMP)
233+
expected_results = 1;
234+
250235
if (existing_results_for_pilot(pilot_id) == expected_results) {
251236
skipped_pilots++;
252237
campaignmanager.skipJobs(1);
253238
continue;
254239
}
255-
expected_injections += expected_results - existing_results_for_pilot(pilot_id);
240+
expected_injections += expected_results - existing_results_for_pilot(pilot_id);
256241

257242

258243
DatabaseCampaignMessage pilot;
@@ -271,16 +256,15 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
271256
}
272257
pilot.set_data_address(data_address);
273258
pilot.set_data_mask(data_mask);
274-
pilot.set_inject_bursts(m_inject_bursts);
275-
pilot.set_register_injection_mode(m_register_injection_mode);
259+
pilot.set_injection_mode(m_injection_mode);
276260

277261
this->cb_send_pilot(pilot);
278262

279263
if ((++sent_pilots) % 10000 == 0) {
280264
log_send << "pushed " << sent_pilots << " pilots into the queue" << std::endl;
281265
}
282266
}
283-
log_send << "expecting " << expected_injections << " injections to take place." << std::endl;
267+
log_send << "expecting " << expected_injections << " injections to take place." << std::endl;
284268

285269
if (*mysql_error(db->getHandle())) {
286270
log_send << "MYSQL ERROR: " << mysql_error(db->getHandle()) << std::endl;

src/core/cpn/DatabaseCampaign.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@ class DatabaseCampaign : public Campaign {
3939
id_map completed_pilots; // !< map: Pilot IDs -> result count
4040
#endif
4141

42-
bool m_inject_bursts; // !< inject burst faults?
43-
DatabaseCampaignMessage::RegisterInjectionMode m_register_injection_mode; // !< inject into registers? OFF, ON, AUTO (= use registers if address is small)
42+
DatabaseCampaignMessage::InjectionMode m_injection_mode; // !< How should we inject?
4443

4544
public:
4645
DatabaseCampaign() {};

0 commit comments

Comments
 (0)