ZXFoundation™ 26h2
Loading...
Searching...
No Matches
irq.cxxm
1/// SPDX-License-Identifier: Apache-2.0
2/// @file arch/s390x/cpu/irq_frame.cxxm
3/// @brief z/Architecture interrupt/trap frame layout.
4
5export module arch.s390x.cpu.irq;
6import zxfoundation.base.types;
7
8export {
9
10using irqflags = u64;
11
12namespace arch::s390x::cpu::irq {
13
14 /// @brief Offset of the GPR save area within the frame.
15 constexpr u32 IRQ_FRAME_GPRS = 0x00U;
16
17 /// @brief Offset of the saved old PSW mask word within the frame.
18 constexpr u32 IRQ_FRAME_PSW_MASK = 0x80U; ///< = 16 GPRs × 8 bytes = 128 = 0x80.
19
20 /// @brief Offset of the saved old PSW instruction address within the frame.
21 constexpr u32 IRQ_FRAME_PSW_ADDR = 0x88U; ///< = IRQ_FRAME_PSW_MASK + 8.
22
23 /// @brief Offset of the access register save area within the frame.
24 constexpr u32 IRQ_FRAME_ARS = 0x90U; ///< = IRQ_FRAME_PSW_ADDR + 8.
25
26 /// @brief Offset of the FPC save area within the frame.
27 constexpr u32 IRQ_FRAME_FPC = 0xD0U; ///< = ARS + 64.
28
29 /// @brief Offset of the vector register save area (v0-v15) within the frame.
30 constexpr u32 IRQ_FRAME_VRS = 0xD8U; ///< = FPC + 8 (incl pad).
31
32 /// @brief Total size of the interrupt frame in bytes.
33 /// 128 (GPRs) + 16 (PSW) + 64 (ARs) + 8 (FPC+pad) + 512 (VRs v0-v31) = 728 = 0x2D8.
34 constexpr u32 IRQ_FRAME_SIZE = 0x02D8U;
35
36 constexpr u64 IRQ_RESTORE_MASK_LC = 0x0200UL;
37
38 /// @brief Interrupt frame saved by entry.S on every trap or interrupt.
39 struct [[gnu::packed]] alignas(8) irq_frame {
40 u64 gprs[16]{}; ///< General-purpose registers r0–r15 at interrupt time.
41 u64 psw_mask{}; ///< Old PSW mask word (hardware-saved in lowcore, copied here).
42 u64 psw_addr{}; ///< Old PSW instruction address (hardware-saved, copied here).
43 u32 access_regs[16]{}; ///< Access registers ar0-ar15 (PoP §2-6).
44 u32 fpc{}; ///< Floating point control register (PoP §4-67).
45 u32 pad{}; ///< Pad to 8-byte boundary
46 u64 vector_regs_lo[16][2]{}; ///< Vector registers v0-v15 (lower half).
47 u64 vector_regs_hi[16][2]{}; ///< Vector registers v16-v31 (upper half).
48 };
49
50 static_assert(sizeof(irq_frame) == IRQ_FRAME_SIZE,
51 "arch_s390x_irq_frame size must be IRQ_FRAME_SIZE (0x2D8 = 728 bytes)");
52 static_assert(__builtin_offsetof(irq_frame, psw_mask) == IRQ_FRAME_PSW_MASK,
53 "IRQ_FRAME_PSW_MASK offset mismatch");
54 static_assert(__builtin_offsetof(irq_frame, psw_addr) == IRQ_FRAME_PSW_ADDR,
55 "IRQ_FRAME_PSW_ADDR offset mismatch");
56 static_assert(__builtin_offsetof(irq_frame, access_regs) == IRQ_FRAME_ARS,
57 "IRQ_FRAME_ARS offset mismatch");
58 static_assert(__builtin_offsetof(irq_frame, fpc) == IRQ_FRAME_FPC,
59 "IRQ_FRAME_FPC offset mismatch");
60 static_assert(__builtin_offsetof(irq_frame, vector_regs_lo) == IRQ_FRAME_VRS,
61 "IRQ_FRAME_VRS offset mismatch for vector_regs_lo");
62 static_assert(__builtin_offsetof(irq_frame, vector_regs_hi) == IRQ_FRAME_VRS + 256,
63 "IRQ_FRAME_VRS + 256 offset mismatch for vector_regs_hi");
64
65 /// @brief Interrupt class tag — identifies which lowcore new-PSW slot fired.
66 enum irq_class : u8 {
67 ZX_IRQ_CLASS_PGM = 0, ///< Program check (0x01D0).
68 ZX_IRQ_CLASS_EXT = 1, ///< External interrupt (0x01B0).
69 ZX_IRQ_CLASS_IO = 2, ///< I/O interrupt (0x01F0).
70 ZX_IRQ_CLASS_MCCK = 3, ///< Machine check (0x01E0).
71 ZX_IRQ_CLASS_SVC = 4, ///< Supervisor call (0x01C0).
72 };
73
74 [[gnu::no_stack_protector]] auto irq_restore_mask_byte(u8 byte0) noexcept -> void;
75
76 [[gnu::no_stack_protector]] [[nodiscard]] auto irq_save_disable() noexcept -> irqflags;
77
78 /// @brief Restore PSW byte 0 from a saved irqflags.
79 [[gnu::no_stack_protector]] auto irq_restore(irqflags flags) noexcept -> void;
80
81 auto irq_disable() noexcept -> void;
82
83 auto irq_enable() noexcept -> void;
84
85 [[nodiscard]] auto irqs_enabled() noexcept -> bool;
86
87
88} // namespace arch::s390x::cpu::irq
89
90} // end export