| 1 | #pragma once |
| 2 | #include <atomic.h> |
| 3 | #include <console/crash.h> |
| 4 | #include <nightmare/nightmare.h> |
| 5 | #include <nightmare/perturb.h> |
| 6 | #include <stringify.h> |
| 7 | #include <sync/event.h> |
| 8 | #include <test/conc.h> |
| 9 | #include <thread/queue.h> |
| 10 | #include <time/timer.h> |
| 11 | #include <watchdog.h> |
| 12 | |
| 13 | #define nightmare_panic(fmt, ...) \ |
| 14 | do { \ |
| 15 | char _nm_msg[CRASH_MSG_MAX]; \ |
| 16 | snprintf(_nm_msg, sizeof(_nm_msg), fmt, ##__VA_ARGS__); \ |
| 17 | crash_full(&(struct crash_context) { \ |
| 18 | .source = CRASH_SOURCE_NIGHTMARE, \ |
| 19 | .formats = CRASH_FMT_DEFAULT, \ |
| 20 | .file = __FILE__, \ |
| 21 | .line = __LINE__, \ |
| 22 | .func = __func__, \ |
| 23 | .msg = _nm_msg, \ |
| 24 | }); \ |
| 25 | } while (0) |
| 26 | |
| 27 | struct nightmare_cmdline_config { |
| 28 | const char *selector; |
| 29 | fx32_32_t intensity; |
| 30 | uint64_t seed; |
| 31 | bool seed_present; |
| 32 | enum nightmare_seed_mode seed_mode; |
| 33 | time_ms_t duration_ms; |
| 34 | time_ms_t drain_grace_ms; |
| 35 | time_ms_t stat_interval_ms; |
| 36 | time_ms_t stall_threshold_ms; |
| 37 | enum test_on_stall on_stall; |
| 38 | uint64_t boot_index; |
| 39 | const char *campaign_id; |
| 40 | struct cmdline_list perturb; |
| 41 | bool perturb_present; |
| 42 | }; |
| 43 | |
| 44 | #define NIGHTMARE_MAX_PERTURBERS 8 |
| 45 | |
| 46 | struct nightmare_runtime { |
| 47 | struct nightmare_ctx ctx; |
| 48 | |
| 49 | struct test_conc conc; |
| 50 | |
| 51 | atomic_size_t finding_count; |
| 52 | atomic_bool terminal; |
| 53 | atomic_bool perturb_verdict_ready; |
| 54 | struct nightmare_verdict perturb_verdict; |
| 55 | char perturb_reason[64]; |
| 56 | char perturb_msg[256]; |
| 57 | size_t perturber_count; |
| 58 | const struct test_perturb_desc *perturbers[NIGHTMARE_MAX_PERTURBERS]; |
| 59 | struct timer soft_timer; |
| 60 | struct timer hard_timer; |
| 61 | time_ms_t started_ms; |
| 62 | time_ms_t stat_interval_ms; |
| 63 | const char *campaign_id; |
| 64 | uint64_t boot_index; |
| 65 | char caps[256]; |
| 66 | }; |
| 67 | |
| 68 | extern struct nightmare_runtime nightmare_runtime; |
| 69 | extern struct test_liveness_state nightmare_liveness; |
| 70 | |
| 71 | void nightmare_publish_stop(enum test_stop reason); |
| 72 | void nightmare_cmdline_get(struct nightmare_cmdline_config *config); |
| 73 | void nightmare_thread_main(void *arg); |
| 74 | void nightmare_heartbeat_main(void *arg); |
| 75 | void nightmare_publish_perturb_verdict(struct nightmare_verdict verdict); |
| 76 | bool nightmare_load_perturb_verdict(struct nightmare_verdict *out); |
| 77 | enum nightmare_result |
| 78 | nightmare_result_with_findings(enum nightmare_result result, size_t findings); |
| 79 | struct nightmare_verdict |
| 80 | nightmare_verdict_for_stop(struct nightmare_verdict verdict, |
| 81 | enum test_stop stop); |
| 82 | |
| 83 | STRINGIFY_DECLARE_ENUM(nightmare_result) { |
| 84 | switch (stringify_in) { |
| 85 | case NIGHTMARE_RESULT_OK: return "ok" ; |
| 86 | case NIGHTMARE_RESULT_FINDING: return "finding" ; |
| 87 | case NIGHTMARE_RESULT_FAIL: return "fail" ; |
| 88 | case NIGHTMARE_RESULT_STALL: return "stall" ; |
| 89 | case NIGHTMARE_RESULT_SKIP: return "skip" ; |
| 90 | default: cc_unreachable(); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | STRINGIFY_DECLARE(nightmare_skip_to_str, enum nightmare_skip_reason) { |
| 95 | switch (stringify_in) { |
| 96 | case NIGHTMARE_SKIP_NONE: return "none" ; |
| 97 | case NIGHTMARE_SKIP_NOT_COMPILED: return "not_compiled" ; |
| 98 | case NIGHTMARE_SKIP_NO_SUCH_NIGHTMARE: return "no_such_nightmare" ; |
| 99 | case NIGHTMARE_SKIP_NEEDS_SMP: return "needs_smp" ; |
| 100 | case NIGHTMARE_SKIP_NEEDS_PREEMPT: return "needs_preempt" ; |
| 101 | case NIGHTMARE_SKIP_NEEDS_ASAN: return "needs_asan" ; |
| 102 | case NIGHTMARE_SKIP_NEEDS_INJECT: return "needs_inject" ; |
| 103 | case NIGHTMARE_SKIP_RAM_LOW: return "ram_low" ; |
| 104 | case NIGHTMARE_SKIP_SEED_UNUSED: return "seed_unused" ; |
| 105 | case NIGHTMARE_SKIP_SEED_MISSING: return "seed_missing" ; |
| 106 | case NIGHTMARE_SKIP_SERVICE_MISSING: return "service_missing" ; |
| 107 | case NIGHTMARE_SKIP_PREPARE_REFUSED: return "prepare_refused" ; |
| 108 | default: return "unknown" ; |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | STRINGIFY_DECLARE_ENUM(nightmare_seed_policy) { |
| 113 | switch (stringify_in) { |
| 114 | case NIGHTMARE_SEED_IGNORED: return "ignored" ; |
| 115 | case NIGHTMARE_SEED_OPTIONAL: return "optional" ; |
| 116 | case NIGHTMARE_SEED_REQUIRED: return "required" ; |
| 117 | default: cc_unreachable(); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | STRINGIFY_DECLARE_ENUM(nightmare_seed_mode) { |
| 122 | switch (stringify_in) { |
| 123 | case NIGHTMARE_SEED_SPLIT: return "split" ; |
| 124 | case NIGHTMARE_SEED_SEEDFUL: return "seedful" ; |
| 125 | case NIGHTMARE_SEED_SEEDLESS: return "seedless" ; |
| 126 | default: cc_unreachable(); |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | bool nightmare_liveness_start(time_ms_t threshold_ms, |
| 131 | enum test_on_stall policy); |
| 132 | void nightmare_liveness_stop(void); |
| 133 | void nightmare_liveness_poll(void); |
| 134 | |