ZXFoundation™ 26h2
Loading...
Searching...
No Matches
lowcore.cxxm
1/// SPDX-License-Identifier: Apache-2.0
2/// @file arch/s390x/cpu/lowcore_types.cxxm
3/// @brief z/Architecture 8 KB prefix (lowcore) layout.
4
5export module arch.s390x.cpu.lowcore;
6import arch.s390x.cpu.psw;
7import arch.s390x.io.types;
8import arch.s390x.trap.ext.core;
9import arch.s390x.trap.pgm.core;
10import arch.s390x.trap.mcck.core;
11import arch.s390x.cpu.teid;
12import arch.s390x.init.zxfl.protocol;
13import arch.s390x.cpu.clock;
14import arch.s390x.cpu.tx;
15import zxfoundation.sys.syschk.types;
16import zxfoundation.base.types;
17import lib.structure;
18import lib.bitfield;
19
20export {
21
22namespace arch::s390x::cpu::lowcore {
23
24 constexpr u64 LC_EXT_OLD_PSW = 0x0130UL;
25 constexpr u64 LC_SVC_OLD_PSW = 0x0140UL;
26 constexpr u64 LC_PGM_OLD_PSW = 0x0150UL;
27 constexpr u64 LC_MCCK_OLD_PSW = 0x0160UL;
28 constexpr u64 LC_IO_OLD_PSW = 0x0170UL;
29
30 constexpr u64 LC_PSW_TEMP = 0x0248UL;
31 constexpr u64 LC_RETURN_PSW = 0x0290UL;
32 constexpr u64 LC_KERNEL_STACK = 0x0348UL;
33 constexpr u64 LC_ASYNC_STACK = 0x0350UL;
34 constexpr u64 LC_NODAT_STACK = 0x0358UL;
35 constexpr u64 LC_RESTART_STACK = 0x0360UL;
36 constexpr u64 LC_MCCK_STACK = 0x0368UL;
37 constexpr u64 LC_AP_CR0 = 0x0330UL;
38 constexpr u64 LC_AP_CR13 = 0x0338UL;
39 constexpr u64 LC_CURRENT_DOMAIN = 0x0340UL;
40 constexpr u64 LC_KERNEL_ASCE = 0x0388UL;
41
42 constexpr u64 LC_CPU_ID_OFFSET = 0x03a0UL;
43 constexpr u64 LC_PERCPU_PTR = 0x0400UL;
44
45 /// @note this is the *usual* size, Lowcore spans only 6400 bytes
46 constexpr u64 LC_SIZE = 8192UL;
47 constexpr u64 LC_ALIGN = 8192UL;
48
49 enum class architectural_mode : u8 {
50 esa390 = 0,
51 zarch = 1,
52 };
53
54 using restart_fn = auto(*)(void*) noexcept -> void;
55
56 /// @brief z/Architecture "Assigned Storage Locations"
57 using zlowcore = lib::structure<LC_SIZE, LC_ALIGN, lib::endian::big,
58 lib::overlay_rw<"esa390_psw", lib::bytes<0, 7>, psw::esa390_psw>,
59 lib::overlay_rw<"short_psw", lib::bytes<0, 7>, psw::short_psw>,
60
61 lib::rw<"ipl_ccw1", lib::bytes<8, 15>, io::ccw0>,
62
63 lib::overlay_rw<"ipl_ccw2", lib::bytes<16, 23>, io::ccw0>,
64 lib::rw<"ipl_machine_loader_space_sz", lib::bytes<16, 19>, u32>,
65 lib::rw<"ipl_sysparm_block_addr", lib::bytes<20, 23>, u32>,
66
67 lib::rw<"external_int_parameter", lib::bytes<128, 131>, trap::ext::ext_parameter>,
68 lib::rw<"cpu_addr", lib::bytes<132, 133>, u16>,
69 lib::rw<"external_interruption_code", lib::bytes<134, 135>, u16>,
70
71 lib::rw<"svc_interruption_id", lib::bytes<136, 139>, lib::record<u32, lib::msb0_t,
72 lib::rw<"instruction_length_code", lib::bits<13, 14>>,
73 lib::rw<"instruction_code", lib::bits<16, 31>>
74 >>,
75
76 lib::rw<"pgm_interruption_id", lib::bytes<140, 143>, lib::record<u32, lib::msb0_t,
77 lib::rw<"instruction_length_code", lib::bits<13, 14>>,
78 lib::rw<"instruction_code", lib::bits<16, 31>>
79 >>,
80
81 lib::rw<"exception_code", lib::bytes<144, 147>, lib::record<u32, lib::msb0_t,
82 lib::overlay_rw<"vector_exception_code", lib::bits<24, 31>, trap::pgm::vector_exception_code>,
83 lib::overlay_rw<"data_exception_code", lib::bits<24, 31>, trap::pgm::data_exception_code>
84 >>,
85
86 lib::rw<"monitor_class_number", lib::bytes<148, 149>, lib::record<u16, lib::msb0_t,
87 lib::rw<"number", lib::bits<8, 15>>
88 >>,
89
90 lib::rw<"per_code", lib::bytes<150, 151>, trap::pgm::per_code>,
91 lib::rw<"per_address", lib::bytes<152, 159>, u64>,
92 lib::rw<"exception_address_id", lib::bytes<160, 160>, trap::pgm::eaid>,
93 lib::rw<"per_access_id", lib::bytes<161, 161>, trap::pgm::per_access_id>,
94 lib::rw<"operation_access_id", lib::bytes<162, 162>, lib::record<u8, lib::msb0_t,
95 lib::rw<"move_page_r1", lib::bits<0, 3>>,
96 lib::rw<"move_page_r2", lib::bits<4, 7>>
97 >>,
98
99 lib::overlay_rw<"status_arch_mode_id", lib::bytes<163, 163>, lib::record<u8, lib::msb0_t,
100 lib::rw<"architectural_mode", lib::bits<7, 7>, architectural_mode>
101 >>,
102 lib::overlay_rw<"mcck_arch_mode_id", lib::bytes<163, 163>, lib::record<u8, lib::msb0_t,
103 lib::rw<"architectural_mode", lib::bits<7, 7>, architectural_mode>
104 >>,
105
106 lib::rw<"translation_except_id", lib::bytes<168, 175>, teid::teid>,
107 lib::rw<"monitor_code", lib::bytes<176, 183>, u64>,
108
109 lib::rw<"io_interruption_code", lib::bytes<184, 195>, io::io_interruption_code>,
110
111 lib::rw<"facility_list", lib::bytes<200, 203>, lib::bf32>,
112
113 lib::rw<"mcck_interruption_code", lib::bytes<232, 239>, u64>,
114 lib::rw<"external_damage_code", lib::bytes<244, 247>, trap::mcck::external_damage_code>,
115 lib::rw<"failing_storage_address", lib::bytes<248, 255>, u64>,
116 lib::rw<"monitor_counter_array_origin", lib::bytes<256, 263>, u64>,
117 lib::rw<"monitor_ctr_array_size", lib::bytes<264, 267>, u32>,
118 lib::rw<"monitor_exception_count", lib::bytes<268, 271>, u32>,
119 lib::rw<"breaking_event_address", lib::bytes<272, 279>, u64>,
120
121 lib::rw<"restart_old_psw", lib::bytes<288, 303>, psw::zpsw>,
122 lib::rw<"external_old_psw", lib::bytes<304, 319>, psw::zpsw>,
123 lib::rw<"supervisor_call_old_psw", lib::bytes<320, 335>, psw::zpsw>,
124 lib::rw<"program_old_psw", lib::bytes<336, 351>, psw::zpsw>,
125 lib::rw<"mcck_old_psw", lib::bytes<352, 367>, psw::zpsw>,
126 lib::rw<"io_old_psw", lib::bytes<368, 383>, psw::zpsw>,
127
128 lib::rw<"restart_new_psw", lib::bytes<416, 431>, psw::zpsw>,
129 lib::rw<"external_new_psw", lib::bytes<432, 447>, psw::zpsw>,
130 lib::rw<"supervisor_call_new_psw", lib::bytes<448, 463>, psw::zpsw>,
131 lib::rw<"program_new_psw", lib::bytes<464, 479>, psw::zpsw>,
132 lib::rw<"mcck_new_psw", lib::bytes<480, 495>, psw::zpsw>,
133 lib::rw<"io_new_psw", lib::bytes<496, 511>, psw::zpsw>,
134
135 lib::rw<"save_area_sync", lib::bytes<512, 575>, u64[8]>,
136 lib::rw<"stack_canary", lib::bytes<576, 583>, u64>,
137 lib::rw<"return_psw_temp", lib::bytes<584, 599>, psw::zpsw>,
138
139 lib::rw<"save_area_restart", lib::bytes<640, 647>, u64[1]>,
140 lib::rw<"pcpu", lib::bytes<648, 655>, u64>,
141 lib::rw<"return_psw", lib::bytes<656, 671>, psw::zpsw>,
142 lib::rw<"return_mcck_psw", lib::bytes<672, 687>, psw::zpsw>,
143 lib::rw<"last_break", lib::bytes<688, 695>, u64>,
144 lib::rw<"sys_enter_timer", lib::bytes<696, 703>, u64>,
145 lib::rw<"mcck_enter_timer", lib::bytes<704, 711>, u64>,
146 lib::rw<"exit_timer", lib::bytes<712, 719>, u64>,
147 lib::rw<"user_timer", lib::bytes<720, 727>, u64>,
148 lib::rw<"guest_timer", lib::bytes<728, 735>, u64>,
149 lib::rw<"system_timer", lib::bytes<736, 743>, u64>,
150 lib::rw<"hardirq_timer", lib::bytes<744, 751>, u64>,
151 lib::rw<"softirq_timer", lib::bytes<752, 759>, u64>,
152 lib::rw<"steal_timer", lib::bytes<760, 767>, u64>,
153 lib::rw<"avg_steal_timer", lib::bytes<768, 775>, u64>,
154 lib::rw<"last_update_timer", lib::bytes<776, 783>, u64>,
155 lib::rw<"last_update_clock", lib::bytes<784, 791>, u64>,
156 lib::rw<"int_clock", lib::bytes<792, 807>, clock::tod_clock>,
157
158 lib::rw<"clock_comparator", lib::bytes<808, 815>, u64>,
159 lib::rw<"ap_cr0", lib::bytes<816, 823>, u64>,
160 lib::rw<"ap_cr13", lib::bytes<824, 831>, u64>,
161 lib::rw<"current_domain", lib::bytes<832, 839>, u64>,
162 lib::rw<"kernel_stack", lib::bytes<840, 847>, u64>,
163 lib::rw<"async_stack", lib::bytes<848, 855>, u64>,
164 lib::rw<"nodat_stack", lib::bytes<856, 863>, u64>,
165 lib::rw<"restart_stack", lib::bytes<864, 871>, u64>,
166 lib::rw<"mcck_stack", lib::bytes<872, 879>, u64>,
167 lib::rw<"restart_fn", lib::bytes<880, 887>, restart_fn>,
168 lib::rw<"restart_data", lib::bytes<888, 895>, u64>,
169 lib::rw<"restart_source", lib::bytes<896, 899>, u32>,
170 lib::rw<"restart_flags", lib::bytes<900, 903>, u32>,
171 lib::rw<"kernel_asce", lib::bytes<904, 911>, u64>,
172 lib::rw<"user_asce", lib::bytes<912, 919>, u64>,
173 lib::rw<"lpp", lib::bytes<920, 923>, u32>,
174 lib::rw<"current_pid", lib::bytes<924, 927>, u32>,
175 lib::rw<"cpu_id", lib::bytes<928, 929>, u16>,
176
177 lib::rw<"spinlock_lockval", lib::bytes<940, 943>, u32>,
178 lib::rw<"spinlock_index", lib::bytes<944, 947>, u32>,
179 lib::rw<"percpu_ptr", lib::bytes<1024, 1031>, u64>,
180
181 lib::rw<"mcck_save_area_designation", lib::bytes<4528, 4535>, trap::mcck::mcesad>,
182 lib::rw<"floating_pt_save_area", lib::bytes<4608, 4735>, u64[16]>,
183 lib::rw<"gpregs_save_area", lib::bytes<4736, 4863>, u64[16]>,
184
185 lib::overlay_rw<"psw_save_area", lib::bytes<4864, 4879>, psw::zpsw>,
186 lib::overlay_rw<"fixed_logout_area", lib::bytes<4864, 4879>, u8[16]>,
187
188 lib::rw<"prefixreg_save_area", lib::bytes<4888, 4891>, u32>,
189 lib::rw<"fpt_creg_save_area", lib::bytes<4892, 4895>, u32>,
190 lib::rw<"tod_progreg_save_area", lib::bytes<4900, 4903>, u32>,
191 lib::rw<"cpu_timer_save_area", lib::bytes<4904, 4911>, u32[2]>,
192 lib::rw<"clock_comp_save_area", lib::bytes<4912, 4919>, u32[2]>,
193 lib::rw<"last_break_save_area", lib::bytes<4920, 4927>, u64>,
194 lib::rw<"access_regs_save_area", lib::bytes<4928, 4991>, u32[16]>,
195 lib::rw<"cregs_save_area", lib::bytes<4992, 5119>, u64[16]>,
196
197 lib::rw<"crash_record", lib::bytes<5120, 5375>, zxfoundation::sys::syschk::zx_crash_record>,
198
199 lib::rw<"crypto_counter_designation", lib::bytes<5376, 5383>, lib::record<u64, lib::msb0_t,
200 lib::rw<"real_location", lib::bits<0, 52>>
201 >>,
202
203 lib::rw<"aic_designation", lib::bytes<5384, 5391>, lib::record<u64, lib::msb0_t,
204 lib::rw<"real_location", lib::bits<0, 54>>
205 >>,
206
207 lib::rw<"transactional_diagnostic_block", lib::bytes<6144, 6399>, tx::tdb>
208 >;
209
210 [[nodiscard]] auto get_current() noexcept -> zlowcore*;
211 [[nodiscard]] auto get_current_phys() noexcept -> zlowcore*;
212
213 /// @brief Retrieve the lowcore structure pointer for a specific CPU, taking prefixing into account.
214 /// @param[in] cpu_id The logical target CPU ID.
215 /// @return Pointer to the lowcore of the target CPU, or nullptr if unregistered.
216 [[nodiscard]] auto get_for_cpu(u16 cpu_id) noexcept -> zlowcore*;
217
218 auto register_cpu_lowcore(u16 cpu_id, u64 phys_lc) noexcept -> void;
219
220 /// @brief Initialize the BSP lowcore. Must be called once after HHDM is active.
221 auto init_bsp(const init::zxfl::protocol& proto) noexcept -> void;
222
223 /// @brief Get the current domain pointer from lowcore.
224 [[nodiscard]] auto current_domain_ptr() noexcept -> void*;
225
226 /// @brief Get the current strand pointer from percpu.
227 [[nodiscard]] auto current_strand_ptr() noexcept -> void*;
228
229 /// @brief Install a runtime restart-interrupt handler on the current CPU.
230 /// @param[in] fn Callback invoked by trap_restart_entry on SIGP RESTART.
231 /// @param[in] data Opaque cookie forwarded as %r2 to the callback.
232 auto register_restart_handler(
233 void(*fn)(void*) noexcept,
234 void* data
235 ) noexcept -> void;
236
237 /// @brief Parameters for AP lowcore setup.
238 struct ap_init_params {
239 u64 phys_lc{}; ///< Physical address of the AP's 8 KB lowcore page.
240 u64 ap_entry_phys{}; ///< Physical address of ap_entry (DAT-off restart target).
241 u64 kernel_asce{}; ///< Kernel ASCE (CR1) to load before enabling DAT.
242 u64 ap_cr0{}; ///< CR0 snapshot to restore on AP.
243 u64 ap_stack_phys{}; ///< Physical top of AP's initial stack (for LC_RESTART_STACK).
244 u16 cpu_id{}; ///< Logical CPU ID assigned to this AP.
245 u16 cpu_addr{}; ///< Hardware CPU address (from SIGP/STAP).
246 };
247
248 /// @brief Prepare an AP lowcore for SIGP RESTART.
249 /// @param lc HHDM-mapped pointer to the AP's lowcore page.
250 /// @param p AP initialization parameters.
251 auto init_ap(zlowcore& lc, const ap_init_params& p) noexcept -> void;
252
253} // namespace arch::s390x::cpu::lowcore
254
255} // end export