ZXFoundation™ 26h2
Loading...
Searching...
No Matches
error.cxxm
Go to the documentation of this file.
1/// SPDX-License-Identifier: Apache 2.0
2/// @file error.cxxm
3/// @brief Kernel error code system for all subsystems
4
5export module lib.error;
6import zxfoundation.base.types;
7import lib.format;
8import std;
9
10export {
11
12namespace lib {
13
14 /// @brief Error category discriminator for kernel subsystems.
15 enum class error_category : u8 {
16 none = 0, ///< No error.
17 arch, ///< s390x architecture errors (SIGP, PSW, facilities).
18 memory, ///< Memory management errors.
19 locking, ///< Lock and synchronization errors.
20 crypto, ///< Cryptographic operation errors.
21 driver, ///< Device driver errors.
22 init, ///< Initialization and boot errors.
23 time, ///< Time and clock errors.
24 generic, ///< Generic kernel errors.
25 machine ///< Machine errors.
26 };
27
28 /// @brief s390x architecture-specific error codes.
29 /// @note Maps to SIGP condition codes, PSW validation failures, and facility checks.
30 namespace arch_error {
31 enum code : u32 {
32 none = 0,
33 sigp_busy = 1, ///< SIGP instruction returned CC=2 (busy).
34 sigp_not_operational = 2, ///< SIGP instruction returned CC=3 (not operational).
35 sigp_invalid_order = 3, ///< Invalid SIGP order code.
36 psw_invalid_mask = 4, ///< PSW mask word contains invalid bits.
37 psw_invalid_address = 5, ///< PSW instruction address is invalid.
38 stfle_failed = 6, ///< STFLE instruction failed.
39 stsi_failed = 7, ///< STSI instruction failed or returned invalid data.
40 cpu_not_available = 8, ///< Target CPU is not available.
41 invalid_cpu_id = 9, ///< CPU ID exceeds CONFIG_ZX_MAX_CPUS.
42 sthyi_failed = 10, ///< STHYI instruction failed.
43 sclp_failed = 11, ///< SCLP service call failed.
44 ecag_failed = 12, ///< ECAG instruction failed.
45 cpu_mf_failed = 13, ///< CPU measurement facility failed.
46 uv_failed = 14, ///< Ultravisor call failed.
47 stp_failed = 15, ///< STP operation failed.
48 ptff_failed = 16, ///< PTFF instruction failed.
49 diag_failed = 17, ///< DIAGNOSE instruction failed.
50 sigp_failed = 18, ///< SIGP instruction failed (generic).
51 };
52 }
53
54 /// @brief Time and clock error codes.
55 namespace time_error {
56 enum code : u32 {
57 none = 0,
58 clock_not_available = 1, ///< Requested clock source is not available.
59 invalid_timestamp = 2, ///< Provided timestamp is invalid or out of range.
60 adjustment_failed = 3, ///< Clock adjustment (e.g. steering) failed.
61 };
62 }
63
64 /// @brief Memory management error codes.
65 namespace memory_error {
66 enum code : u32 {
67 none = 0,
68 out_of_memory = 1, ///< Memory allocation failed (OOM).
69 invalid_address = 2, ///< Address is outside valid range.
70 alignment_error = 3, ///< Address violates alignment requirements.
71 region_overlap = 4, ///< Memory regions overlap illegally.
72 hhdm_init_failed = 5, ///< High-Half Direct Map initialization failed.
73 page_fault = 6, ///< Page fault occurred.
74 invalid_irq_contex = 7, ///< Allocation attempted at elevated invalid ctx where it is forbidden.
75 transaction_aborted = 8, ///< Transaction rolled back; no resources were committed.
76 capability_invalid = 9, ///< Capability token is null, revoked, or wrong purpose.
77 purpose_mismatch = 10, ///< Capability purpose does not match the requested use.
78 zone_exhausted = 11, ///< All pages in the target zone are allocated.
79 ssp_check_fail = 13, ///< SSP check fail (stack smashing detected).
80 };
81 }
82
83 /// @brief Locking and synchronization error codes.
84 namespace locking_error {
85 enum code : u32 {
86 none = 0,
87 timeout = 1, ///< Lock acquisition timed out.
88 deadlock_detected = 2, ///< Potential deadlock detected.
89 already_locked = 3, ///< Lock is already held.
90 not_locked = 4, ///< Attempt to unlock a non-held lock.
91 max_depth_exceeded = 5, ///< Exceeded MAX_LOCK_DEPTH.
92 };
93 }
94
95 /// @brief Cryptographic operation error codes.
96 namespace crypto_error {
97 enum code : u32 {
98 none = 0,
99 invalid_input = 1, ///< Input data is malformed.
100 hash_mismatch = 2, ///< Computed hash does not match expected.
101 verification_failed = 3, ///< Signature or checksum verification failed.
102 };
103 }
104
105 /// @brief Device driver error codes.
106 namespace driver_error {
107 enum code : u32 {
108 none = 0,
109 not_found = 1, ///< Device not found.
110 not_ready = 2, ///< Device not ready for I/O.
111 io_error = 3, ///< I/O operation failed.
112 timeout = 4, ///< Device operation timed out.
113 busy = 5, ///< Device is busy.
114 };
115 }
116
117 /// @brief Initialization and boot error codes.
118 namespace init_error {
119 enum code : u32 {
120 none = 0,
121 boot_failed = 1, ///< Boot sequence failed.
122 invalid_protocol = 2, ///< ZXFL/ZXVL protocol violation.
123 checksum_mismatch = 3, ///< Boot image checksum mismatch.
124 };
125 }
126
127 /// @brief Generic kernel error codes.
128 namespace generic_error {
129 enum code : u32 {
130 none = 0,
131 invalid_arg = 1, ///< Invalid argument passed to function.
132 not_supported = 2, ///< Operation not supported.
133 not_implemented = 3, ///< Feature not yet implemented.
134 internal_error = 4, ///< Internal error (C++ ABI for example)
135 not_found = 5, ///< Requested item does not exist in the table.
136 unknown = 6, ///< Unknown error.
137 out_of_range = 7, ///< Index or address is outside valid bounds.
138 uninitialized = 8, ///< Uninitialized.
139 stall = 9, ///< CPU or subsystem stall detected (watchdog).
140 };
141 }
142
143 /// @brief machine error (for mcck)
144 namespace machine_error {
145 enum code : u32 {
146 none = 0,
147 system_damage = 1,
148 inst_process_damage = 2,
149 system_recovery = 3,
150 timing_facility = 4,
151 external_damage = 5,
152 failing_storage_addr = 6,
153 storage_error_uncorrected = 7,
154 storage_key_error = 8,
155 storage_degradation = 9,
156 degradation = 10,
157 warning = 11,
158 channel_report_pending = 12,
159 service_processor_damage = 13,
160 channel_subsystem_damage = 14,
161 backlog = 15,
162 };
163 }
164
165 /// @brief Unified kernel error type.
166 /// @note Combines an error category with a subsystem-specific code.
167 /// Use the from_* factory methods for type-safe construction.
168 struct kernel_error {
169 error_category category; ///< Error category discriminator.
170 u32 code; ///< Subsystem-specific error code.
171
172 /// @brief Default constructor: no error.
173 constexpr kernel_error() noexcept
174 : category(error_category::none), code(0) {}
175
176 /// @brief Construct from category and raw code.
177 /// @param[in] cat Error category.
178 /// @param[in] c Raw error code.
179 /// @warning Prefer type-safe from_* methods.
180 constexpr kernel_error(error_category cat, u32 c) noexcept
181 : category(cat), code(c) {}
182
183 /// @brief Construct architecture error.
184 /// @param[in] c arch_error::code value.
185 /// @return kernel_error with category=arch.
186 static constexpr auto from_arch(arch_error::code c) noexcept -> kernel_error {
187 return kernel_error{error_category::arch, static_cast<u32>(c)};
188 }
189
190 /// @brief Construct memory error.
191 /// @param[in] c memory_error::code value.
192 /// @return kernel_error with category=memory.
193 static constexpr auto from_memory(memory_error::code c) noexcept -> kernel_error {
194 return kernel_error{error_category::memory, static_cast<u32>(c)};
195 }
196
197 /// @brief Construct locking error.
198 /// @param[in] c locking_error::code value.
199 /// @return kernel_error with category=locking.
200 static constexpr auto from_locking(locking_error::code c) noexcept -> kernel_error {
201 return kernel_error{error_category::locking, static_cast<u32>(c)};
202 }
203
204 /// @brief Construct cryptographic error.
205 /// @param[in] c crypto_error::code value.
206 /// @return kernel_error with category=crypto.
207 static constexpr auto from_crypto(crypto_error::code c) noexcept -> kernel_error {
208 return kernel_error{error_category::crypto, static_cast<u32>(c)};
209 }
210
211 /// @brief Construct driver error.
212 /// @param[in] c driver_error::code value.
213 /// @return kernel_error with category=driver.
214 static constexpr auto from_driver(driver_error::code c) noexcept -> kernel_error {
215 return kernel_error{error_category::driver, static_cast<u32>(c)};
216 }
217
218 /// @brief Construct initialization error.
219 /// @param[in] c init_error::code value.
220 /// @return kernel_error with category=init.
221 static constexpr auto from_init(init_error::code c) noexcept -> kernel_error {
222 return kernel_error{error_category::init, static_cast<u32>(c)};
223 }
224
225 /// @brief Construct time error.
226 /// @param[in] c time_error::code value.
227 /// @return kernel_error with category=time.
228 static constexpr auto from_time(time_error::code c) noexcept -> kernel_error {
229 return kernel_error{error_category::time, static_cast<u32>(c)};
230 }
231
232 /// @brief Construct generic error.
233 /// @param[in] c generic_error::code value.
234 /// @return kernel_error with category=generic.
235 static constexpr auto from_generic(generic_error::code c) noexcept -> kernel_error {
236 return kernel_error{error_category::generic, static_cast<u32>(c)};
237 }
238
239 // @brief Construct generic error.
240 /// @param[in] c generic_error::code value.
241 /// @return kernel_error with category=generic.
242 static constexpr auto from_machine(machine_error::code c) noexcept -> kernel_error {
243 return kernel_error{error_category::machine, static_cast<u32>(c)};
244 }
245
246 /// @brief Check if two errors are identical.
247 constexpr auto operator==(const kernel_error& other) const noexcept -> bool {
248 return category == other.category && code == other.code;
249 }
250
251 /// @brief Check if two errors differ.
252 constexpr auto operator!=(const kernel_error& other) const noexcept -> bool {
253 return !(*this == other);
254 }
255
256 /// @brief Check if error is non-zero.
257 /// @return true if category is not none.
258 constexpr explicit operator bool() const noexcept {
259 return category != error_category::none;
260 }
261 };
262
263 /// @brief Return the ASCII name of an error_category.
264 /// @param[in] cat Category to name.
265 /// @return Statically allocated string; never null.
266 [[nodiscard]] constexpr auto category_name(error_category cat) noexcept -> std::string_view {
267 switch (cat) {
268 #define expand(error) case error_category::error: return stringify(error);
269 expand(none)
270 expand(arch)
271 expand(memory)
272 expand(locking)
273 expand(crypto)
274 expand(driver)
275 expand(init)
276 expand(time)
277 expand(generic)
278 expand(machine)
279 #undef expand
280 default: return "unknown";
281 }
282 }
283
284 /// @brief Return the ASCII name of a per-category error code.
285 /// @param[in] cat Category that owns the code.
286 /// @param[in] code Raw code value.
287 /// @return Statically allocated string; "?" if code is unknown.
288 [[nodiscard]] constexpr auto error_code_name(error_category cat, u32 code) noexcept -> std::string_view {
289 switch (cat) {
290 case error_category::arch:
291 switch (code) {
292 #define expand(error) case arch_error::error: return stringify(error);
293 expand(none)
294 expand(sigp_busy)
295 expand(sigp_not_operational)
296 expand(sigp_invalid_order)
297 expand(psw_invalid_mask)
298 expand(psw_invalid_address)
299 expand(stfle_failed)
300 expand(stsi_failed)
301 expand(cpu_not_available)
302 expand(invalid_cpu_id)
303 expand(sthyi_failed)
304 expand(sclp_failed)
305 expand(ecag_failed)
306 expand(cpu_mf_failed)
307 expand(uv_failed)
308 expand(stp_failed)
309 expand(ptff_failed)
310 expand(diag_failed)
311 expand(sigp_failed)
312 #undef expand
313 default: return "?";
314 }
315 case error_category::memory:
316 switch (code) {
317 #define expand(error) case memory_error::error: return stringify(error);
318 expand(none)
319 expand(out_of_memory)
320 expand(invalid_address)
321 expand(alignment_error)
322 expand(region_overlap)
323 expand(hhdm_init_failed)
324 expand(page_fault)
325 expand(invalid_irq_contex)
326 expand(transaction_aborted)
327 expand(capability_invalid)
328 expand(purpose_mismatch)
329 expand(zone_exhausted)
330 expand(ssp_check_fail)
331 #undef expand
332 default: return "?";
333 }
334 case error_category::locking:
335 switch (code) {
336 #define expand(error) case locking_error::error: return stringify(error);
337 expand(none)
338 expand(timeout)
339 expand(deadlock_detected)
340 expand(already_locked)
341 expand(not_locked)
342 expand(max_depth_exceeded)
343 #undef expand
344 default: return "?";
345 }
346 case error_category::crypto:
347 switch (code) {
348 #define expand(error) case crypto_error::error: return stringify(error);
349 expand(none)
350 expand(invalid_input)
351 expand(hash_mismatch)
352 expand(verification_failed)
353 #undef expand
354 default: return "?";
355 }
356 case error_category::driver:
357 switch (code) {
358 #define expand(error) case driver_error::error: return stringify(error);
359 expand(none)
360 expand(not_found)
361 expand(not_ready)
362 expand(io_error)
363 expand(timeout)
364 expand(busy)
365 #undef expand
366 default: return "?";
367 }
368 case error_category::init:
369 switch (code) {
370 #define expand(error) case init_error::error: return stringify(error);
371 expand(none)
372 expand(boot_failed)
373 expand(invalid_protocol)
374 expand(checksum_mismatch)
375 #undef expand
376 default: return "?";
377 }
378 case error_category::time:
379 switch (code) {
380 #define expand(error) case time_error::error: return stringify(error);
381 expand(none)
382 expand(clock_not_available)
383 expand(invalid_timestamp)
384 expand(adjustment_failed)
385 #undef expand
386 default: return "?";
387 }
388 case error_category::generic:
389 switch (code) {
390 #define expand(error) case generic_error::error: return stringify(error);
391 expand(none)
392 expand(invalid_arg)
393 expand(not_supported)
394 expand(not_implemented)
395 expand(internal_error)
396 expand(not_found)
397 expand(unknown)
398 expand(out_of_range)
399 expand(uninitialized)
400 expand(stall)
401 #undef expand
402 default: return "?";
403 }
404 case error_category::machine:
405 switch (code) {
406 #define expand(error) case machine_error::error: return stringify(error);
407 expand(none)
408 expand(system_damage)
409 expand(inst_process_damage)
410 expand(system_recovery)
411 expand(timing_facility)
412 expand(external_damage)
413 expand(failing_storage_addr)
414 expand(storage_error_uncorrected)
415 expand(storage_key_error)
416 expand(storage_degradation)
417 expand(degradation)
418 expand(warning)
419 expand(channel_report_pending)
420 expand(service_processor_damage)
421 expand(channel_subsystem_damage)
422 expand(backlog)
423 #undef expand
424 default: return "?";
425 }
426 default:
427 return "?";
428 }
429 }
430
431} // namespace lib
432
433} // end export
434
435export {
436
437 /// @brief Formatter specialization for @c lib::kernel_error.
438 template <>
439 struct lib::format::formatter<lib::kernel_error> {
440
441 /// @brief Format a kernel_error into the context.
442 /// @param[in,out] ctx Output context.
443 /// @param[in] val Error to format.
444 static auto format(format_context& ctx, const kernel_error& val) noexcept -> void {
445 ctx.write(category_name(val.category));
446 ctx.write("::");
447 std::string_view name = lib::error_code_name(val.category, val.code);
448 if (name.compare("?") == 0) {
449 formatter<u32>{}.format(ctx, val.code);
450 } else {
451 ctx.write(name);
452 }
453 }
454
455 }; // namespace lib::format
456
457} // end export
#define expand(error)