ZXFoundation™ 26h2
Loading...
Searching...
No Matches
psw.cxxm
1/// SPDX-License-Identifier: Apache-2.0
2/// @file arch/s390x/cpu/psw_types.cxxm
3/// @brief z/Architecture PSW (Program Status Word) bit definitions.
4
5export module arch.s390x.cpu.psw;
6import zxfoundation.base.types;
7import lib.bitfield;
8import lib.structure;
9
10export {
11
12namespace arch::s390x::cpu::psw {
13
14 /// @brief DAT (Dynamic Address Translation) enable bit
15 constexpr u64 PSW_BIT_DAT = 0x0400000000000000ULL;
16
17 /// @brief I/O interrupt enable bit
18 constexpr u64 PSW_BIT_IO = 0x0200000000000000ULL;
19
20 /// @brief External interrupt enable bit
21 constexpr u64 PSW_BIT_EXT = 0x0100000000000000ULL;
22
23 /// @brief Machine-check interrupt enable bit
24 constexpr u64 PSW_BIT_MCCK = 0x0004000000000000ULL;
25
26 /// @brief Wait state bit
27 constexpr u64 PSW_BIT_WAIT = 0x0002000000000000ULL;
28
29 /// @brief Problem state (user mode) bit
30 constexpr u64 PSW_BIT_PSTATE = 0x0001000000000000ULL;
31
32 /// @brief Extended addressing (EA) bit
33 constexpr u64 PSW_BIT_EA = 0x0000000100000000ULL;
34
35 /// @brief Basic addressing (BA) bit
36 constexpr u64 PSW_BIT_BA = 0x0000000080000000ULL;
37
38 /// @brief Primary Space Mode (ASC = 00) — no bits set.
39 constexpr u64 PSW_ASC_PRIMARY = 0x0000000000000000ULL;
40
41 /// @brief Secondary Space Mode (ASC = 01).
42 constexpr u64 PSW_ASC_SECONDARY = 0x0000800000000000ULL;
43
44 /// @brief Access register mode (ASC = 10).
45 constexpr u64 PSW_ASC_ACCREG = 0x0000400000000000ULL;
46
47 /// @brief Home Space Mode (ASC = 11) — CR13 is the effective ASCE.
48 constexpr u64 PSW_ASC_HOME = 0x0000C00000000000ULL;
49
50 /// @brief Default PSW storage key (key 0 — master key, unrestricted).
51 constexpr u64 PSW_DEFAULT_KEY = 0ULL;
52
53 /// @brief 64-bit mode bits that MUST be present in every valid z/Arch PSW.
54 constexpr u64 PSW_ARCH_BITS = PSW_BIT_EA | PSW_BIT_BA;
55
56 /// @brief Kernel execution mask: supervisor, DAT off, all interrupts disabled, 64-bit.
57 constexpr u64 PSW_MASK_KERNEL = PSW_DEFAULT_KEY | PSW_ARCH_BITS | PSW_ASC_PRIMARY;
58
59 /// @brief Kernel DAT-on mask: supervisor, DAT on, all interrupts disabled, 64-bit.
60 constexpr u64 PSW_MASK_KERNEL_DAT = PSW_DEFAULT_KEY | PSW_BIT_DAT | PSW_ARCH_BITS | PSW_ASC_HOME;
61
62 /// @brief Kernel DAT-on mask with interrupts enabled (normal execution).
63 constexpr u64 PSW_MASK_KERNEL_ENABLED =
64 PSW_DEFAULT_KEY | PSW_BIT_DAT | PSW_BIT_IO | PSW_BIT_EXT | PSW_BIT_MCCK |
65 PSW_ARCH_BITS | PSW_ASC_HOME;
66
67 /// @brief User-mode PSW mask for entering a domain in problem state.
68 constexpr u64 PSW_MASK_USER =
69 PSW_DEFAULT_KEY |
70 PSW_BIT_PSTATE |
71 PSW_BIT_DAT |
72 PSW_BIT_IO |
73 PSW_BIT_EXT |
74 PSW_BIT_MCCK |
75 PSW_ARCH_BITS |
76 PSW_ASC_PRIMARY;
77
78 /// @brief PSW key field shift — bits 8–11 of the PSW mask word.
79 constexpr u32 PSW_KEY_SHIFT = 52;
80
81 /// @brief Disabled-wait PSW mask: wait state, no interrupts, 64-bit.
82 constexpr u64 PSW_MASK_DISABLED_WAIT = PSW_DEFAULT_KEY | PSW_BIT_WAIT | PSW_ARCH_BITS;
83
84 /// @brief Enabled-wait PSW mask.
85 constexpr u64 PSW_MASK_ENABLED_WAIT =
86 PSW_DEFAULT_KEY | PSW_BIT_DAT | PSW_BIT_IO | PSW_BIT_EXT | PSW_BIT_MCCK |
87 PSW_BIT_WAIT | PSW_ARCH_BITS | PSW_ASC_HOME;
88
89 /// @brief Standard halt address (appears in disabled-wait PSW during normal shutdown).
90 constexpr u64 PSW_STD_HALT_ADDR = 0x0000000000DEAD00ULL;
91
92 constexpr u64 PSW_LC_RESTART = 0x01A0ULL; ///< Restart new PSW
93 constexpr u64 PSW_LC_EXTERNAL = 0x01B0ULL; ///< External new PSW.
94 constexpr u64 PSW_LC_SVC = 0x01C0ULL; ///< Supervisor-call new PSW.
95 constexpr u64 PSW_LC_PROGRAM = 0x01D0ULL; ///< Program-check new PSW.
96 constexpr u64 PSW_LC_MCCK = 0x01E0ULL; ///< Machine-check new PSW.
97 constexpr u64 PSW_LC_IO = 0x01F0ULL; ///< I/O new PSW.
98
99 enum class psw_basic_addressing_modes : u64 {
100 amode24 = 0b00,
101 amode31 = 0b01,
102 amode64 = 0b11,
103 };
104
105 using psw_mask = lib::record<u64, lib::msb0_t,
106 lib::rw<"per_mask", lib::bits<1, 1>>,
107 lib::rw<"dat_mode", lib::bits<5, 5>>,
108 lib::rw<"io_mask", lib::bits<6, 6>>,
109 lib::rw<"external_mask", lib::bits<7, 7>>,
110 lib::rw<"psw_key", lib::bits<8, 11>>,
111 lib::rw<"machine_check_mask", lib::bits<13, 13>>,
112 lib::rw<"wait_state", lib::bits<14, 14>>,
113 lib::rw<"problem_state", lib::bits<15, 15>>,
114 lib::rw<"address_space_control", lib::bits<16, 17>>,
115 lib::rw<"condition_code", lib::bits<18, 19>>,
116 lib::overlay_rw<"pgm_mask", lib::bits<20, 23>>,
117 lib::rw<R"(pgm_mask\fixed_point_overflow)", lib::bits<20, 20>>,
118 lib::rw<R"(pgm_mask\decimal_overflow)", lib::bits<21, 21>>,
119 lib::rw<R"(pgm_mask\hfp_exponent_underflow)", lib::bits<22, 22>>,
120 lib::rw<R"(pgm_mask\hfp_significance)", lib::bits<23, 23>>,
121 lib::overlay_rw<"addressing_mode", lib::bits<31, 32>, psw_basic_addressing_modes>,
122 lib::rw<"extended_addressing_mode", lib::bits<31, 31>>,
123 lib::rw<"basic_addressing_mode", lib::bits<32, 32>>
124 >;
125
126 using psw_mask_view = lib::record_ref<u64, lib::msb0_t,
127 lib::rw<"per_mask", lib::bits<1, 1>>,
128 lib::rw<"dat_mode", lib::bits<5, 5>>,
129 lib::rw<"io_mask", lib::bits<6, 6>>,
130 lib::rw<"external_mask", lib::bits<7, 7>>,
131 lib::rw<"psw_key", lib::bits<8, 11>>,
132 lib::rw<"machine_check_mask", lib::bits<13, 13>>,
133 lib::rw<"wait_state", lib::bits<14, 14>>,
134 lib::rw<"problem_state", lib::bits<15, 15>>,
135 lib::rw<"address_space_control", lib::bits<16, 17>>,
136 lib::rw<"condition_code", lib::bits<18, 19>>,
137 lib::overlay_rw<"pgm_mask", lib::bits<20, 23>>,
138 lib::rw<R"(pgm_mask\fixed_point_overflow)", lib::bits<20, 20>>,
139 lib::rw<R"(pgm_mask\decimal_overflow)", lib::bits<21, 21>>,
140 lib::rw<R"(pgm_mask\hfp_exponent_underflow)", lib::bits<22, 22>>,
141 lib::rw<R"(pgm_mask\hfp_significance)", lib::bits<23, 23>>,
142 lib::overlay_rw<"addressing_mode", lib::bits<31, 32>, psw_basic_addressing_modes>,
143 lib::rw<"extended_addressing_mode", lib::bits<31, 31>>,
144 lib::rw<"basic_addressing_mode", lib::bits<32, 32>>
145 >;
146
147 using zpsw = lib::structure<16, 8, lib::endian::big,
148 lib::rw<"mask", lib::auto_layout, psw_mask>,
149 lib::rw<"address", lib::auto_layout, u64>
150 >;
151
152 using zpsw_view = lib::structure_ref<16, 8, lib::endian::big,
153 lib::rw<"mask", lib::auto_layout, psw_mask>,
154 lib::rw<"address", lib::auto_layout, u64>
155 >;
156
157 using short_psw = lib::record<u64, lib::msb0_t,
158 lib::rw<"per_mask", lib::bits<1, 1>>,
159 lib::rw<"dat_mode", lib::bits<5, 5>>,
160 lib::rw<"io_mask", lib::bits<6, 6>>,
161 lib::rw<"external_mask", lib::bits<7, 7>>,
162 lib::rw<"psw_key", lib::bits<8, 11>>,
163 lib::rw<"machine_check_mask", lib::bits<13, 13>>,
164 lib::rw<"wait_state", lib::bits<14, 14>>,
165 lib::rw<"problem_state", lib::bits<15, 15>>,
166 lib::rw<"address_space_control", lib::bits<16, 17>>,
167 lib::rw<"condition_code", lib::bits<18, 19>>,
168 lib::overlay_rw<"pgm_mask", lib::bits<20, 23>>,
169 lib::rw<R"(pgm_mask\fixed_point_overflow)", lib::bits<20, 20>>,
170 lib::rw<R"(pgm_mask\decimal_overflow)", lib::bits<21, 21>>,
171 lib::rw<R"(pgm_mask\hfp_exponent_underflow)", lib::bits<22, 22>>,
172 lib::rw<R"(pgm_mask\hfp_significance)", lib::bits<23, 23>>,
173 lib::overlay_rw<"addressing_mode", lib::bits<31, 32>, psw_basic_addressing_modes>,
174 lib::rw<"extended_addressing_mode", lib::bits<31, 31>>,
175 lib::rw<"basic_addressing_mode", lib::bits<32, 32>>,
176 lib::rw<"instruction_address", lib::bits<33, 63>>
177 >;
178
179 using short_psw_view = lib::record_ref<u64, lib::msb0_t,
180 lib::rw<"per_mask", lib::bits<1, 1>>,
181 lib::rw<"dat_mode", lib::bits<5, 5>>,
182 lib::rw<"io_mask", lib::bits<6, 6>>,
183 lib::rw<"external_mask", lib::bits<7, 7>>,
184 lib::rw<"psw_key", lib::bits<8, 11>>,
185 lib::rw<"machine_check_mask", lib::bits<13, 13>>,
186 lib::rw<"wait_state", lib::bits<14, 14>>,
187 lib::rw<"problem_state", lib::bits<15, 15>>,
188 lib::rw<"address_space_control", lib::bits<16, 17>>,
189 lib::rw<"condition_code", lib::bits<18, 19>>,
190 lib::overlay_rw<"pgm_mask", lib::bits<20, 23>>,
191 lib::rw<R"(pgm_mask\fixed_point_overflow)", lib::bits<20, 20>>,
192 lib::rw<R"(pgm_mask\decimal_overflow)", lib::bits<21, 21>>,
193 lib::rw<R"(pgm_mask\hfp_exponent_underflow)", lib::bits<22, 22>>,
194 lib::rw<R"(pgm_mask\hfp_significance)", lib::bits<23, 23>>,
195 lib::overlay_rw<"addressing_mode", lib::bits<31, 32>, psw_basic_addressing_modes>,
196 lib::rw<"extended_addressing_mode", lib::bits<31, 31>>,
197 lib::rw<"basic_addressing_mode", lib::bits<32, 32>>,
198 lib::rw<"instruction_address", lib::bits<33, 63>>
199 >;
200
201 using esa390_psw = lib::record<u64, lib::msb0_t,
202 lib::rw<"per_mask", lib::bits<1, 1>>,
203 lib::rw<"dat_mode", lib::bits<5, 5>>,
204 lib::rw<"io_mask", lib::bits<6, 6>>,
205 lib::rw<"external_mask", lib::bits<7, 7>>,
206 lib::rw<"psw_key", lib::bits<8, 11>>,
207 lib::rw<"machine_check_mask", lib::bits<13, 13>>,
208 lib::rw<"wait_state", lib::bits<14, 14>>,
209 lib::rw<"problem_state", lib::bits<15, 15>>,
210 lib::rw<"address_space_control", lib::bits<16, 17>>,
211 lib::rw<"condition_code", lib::bits<18, 19>>,
212 lib::overlay_rw<"pgm_mask", lib::bits<20, 23>>,
213 lib::rw<R"(pgm_mask\fixed_point_overflow)", lib::bits<20, 20>>,
214 lib::rw<R"(pgm_mask\decimal_overflow)", lib::bits<21, 21>>,
215 lib::rw<R"(pgm_mask\hfp_exponent_underflow)", lib::bits<22, 22>>,
216 lib::rw<R"(pgm_mask\hfp_significance)", lib::bits<23, 23>>,
217 lib::rw<"addressing_mode", lib::bits<32, 32>>,
218 lib::rw<"instruction_address", lib::bits<33, 63>>
219 >;
220
221 using esa390_psw_view = lib::record_ref<u64, lib::msb0_t,
222 lib::rw<"per_mask", lib::bits<1, 1>>,
223 lib::rw<"dat_mode", lib::bits<5, 5>>,
224 lib::rw<"io_mask", lib::bits<6, 6>>,
225 lib::rw<"external_mask", lib::bits<7, 7>>,
226 lib::rw<"psw_key", lib::bits<8, 11>>,
227 lib::rw<"machine_check_mask", lib::bits<13, 13>>,
228 lib::rw<"wait_state", lib::bits<14, 14>>,
229 lib::rw<"problem_state", lib::bits<15, 15>>,
230 lib::rw<"address_space_control", lib::bits<16, 17>>,
231 lib::rw<"condition_code", lib::bits<18, 19>>,
232 lib::overlay_rw<"pgm_mask", lib::bits<20, 23>>,
233 lib::rw<R"(pgm_mask\fixed_point_overflow)", lib::bits<20, 20>>,
234 lib::rw<R"(pgm_mask\decimal_overflow)", lib::bits<21, 21>>,
235 lib::rw<R"(pgm_mask\hfp_exponent_underflow)", lib::bits<22, 22>>,
236 lib::rw<R"(pgm_mask\hfp_significance)", lib::bits<23, 23>>,
237 lib::rw<"addressing_mode", lib::bits<32, 32>>,
238 lib::rw<"instruction_address", lib::bits<33, 63>>
239 >;
240
241 struct [[gnu::packed]] alignas(u64) epsw_words {
242 u32 hi;
243 u32 lo;
244 };
245
246 static_assert(sizeof(zpsw) == 16, "zx_psw must be exactly 16 bytes");
247 static_assert(alignof(zpsw) == 8, "zx_psw must be 8-byte aligned");
248
249 /// @brief Extract the current PSW mask via EPSW. addr is unavailable; set to 0.
250 [[nodiscard]] auto extract_psw() noexcept -> zpsw;
251
252 [[noreturn]] auto load_psw(const zpsw& psw) noexcept -> void;
253
254 [[noreturn]] auto disabled_wait() noexcept -> void;
255
256 /// @brief Enter enabled-wait state — the z/Architecture idle primitive.
257 auto enabled_wait() noexcept -> void;
258
259 auto write_psw_to_lowcore(u64 lc_offset, zpsw psw) noexcept -> void;
260
261 [[nodiscard]] auto make_handler_psw(u64 entry_virt) noexcept -> zpsw;
262 [[nodiscard]] auto make_ap_restart_psw(u64 entry_phys) noexcept -> zpsw;
263
264} // namespace arch::s390x::cpu::psw
265
266} // end export