ZXFoundation™ 26h2
Loading...
Searching...
No Matches
ext.cxxm
Go to the documentation of this file.
1/// SPDX-License-Identifier: Apache-2.0
2/// @file arch/s390x/trap/ext.cxxm
3/// @brief Centralized external-interruption dispatcher.
4
5export module arch.s390x.trap.ext;
6import arch.s390x.cpu.lowcore;
7import arch.s390x.cpu.irq;
8import arch.s390x.cpu.cputimer;
9import arch.s390x.cpu.clock;
10import arch.s390x.cpu.cpumask;
11import arch.s390x.cpu.psw;
12import zxfoundation.sys.irq.consts;
13import zxfoundation.sys.irq.core;
14import zxfoundation.sched.core;
15import zxfoundation.sched.topology.core;
16import zxfoundation.dgp.domain.types;
17import zxfoundation.base.types;
18import zxfoundation.sys.syschk.core;
19import zxfoundation.sys.timer.core;
20import zxfoundation.sys.printk.core;
21import zxfoundation.sys.timer.types;
22import zxfoundation.smp.csd.core;
23import lib.error;
24import lib.softirq.core;
25
26export {
27
28namespace arch::s390x::trap::ext {
29
30 /// @brief Raw z/Architecture external-interruption codes per PoP §7-3.
31 /// @{
32 constexpr u16 EXT_INTERRUPT_KEY = 0x0040; ///< External-interrupt-key.
33 constexpr u16 EXT_CLOCK_COMPARATOR = 0x1004; ///< Clock comparator.
34 constexpr u16 EXT_CPU_TIMER = 0x1005; ///< CPU timer.
35 constexpr u16 EXT_WARNING_TRACK = 0x1007; ///< Warning track (STP).
36 constexpr u16 EXT_MALFUNCTION_ALERT = 0x1200; ///< Malfunction alert.
37 constexpr u16 EXT_EMERGENCY_SIGNAL = 0x1201; ///< Emergency-signal IPI.
38 constexpr u16 EXT_EXTERNAL_CALL = 0x1202; ///< External-call IPI.
39 constexpr u16 EXT_TIMING_ALERT = 0x1406; ///< STP timing alert.
40 constexpr u16 EXT_MEASUREMENT_ALERT = 0x1407; ///< CPU-MF measurement alert.
41 constexpr u16 EXT_SERVICE_SIGNAL = 0x2401; ///< SCLP service signal.
42 constexpr u16 EXT_CP_SERVICE = 0x2603; ///< CP service (pfault).
43 /// @}
44
45 namespace detail {
46
47 /// @brief Acknowledge the current external interrupt in lowcore.
48 auto ack_lowcore() noexcept -> void {
49 auto* lc = arch::s390x::cpu::lowcore::get_current();
50 lc->ext_int_code = 0U;
51 }
52
53 } // namespace detail
54
55 /// @brief Centralized external-interruption dispatcher.
56 /// @param[in,out] frame Saved interrupt frame from entry.S.
57 auto handle(cpu::irq::irq_frame* frame) noexcept -> void {
58 auto* lc = cpu::lowcore::get_current();
59 const u16 ext_code = lc->ext_int_code;
60
61 detail::ack_lowcore();
62
63 const u16 irq_nr = zxfoundation::sys::irq::ext_code_to_irq(ext_code);
64 if (irq_nr == zxfoundation::sys::irq::IRQ_NR_MAX) {
65 zxfoundation::sys::printk::pverbose(
66 "ext: unrecognised ext_code {:#06x} — no IRQ slot\n",
67 ext_code);
68 return;
69 }
70
71 zxfoundation::sys::irq::irq_dispatch(
72 irq_nr, frame, cpu::irq::ZX_IRQ_CLASS_EXT);
73
74 namespace irq = zxfoundation::sys::irq;
75 if (irq::deferred_test_clear(irq::DEFERRED_RESCHED_BIT)) {
76 zxfoundation::sched::sched_resched_current();
77 }
78
79 if (irq::deferred_test_clear(irq::DEFERRED_MCCK_PENDING_BIT)) {
80 // TODO:
81 // The actual deferred-MCCK handler is currently inline in the
82 // MCCK dispatcher (Phase 3.2 / 11.7 pending); until that chapter
83 // is wired we simply acknowledge the bit was set so the trap
84 // path stays self-consistent.
85 zxfoundation::sys::printk::pverbose(
86 "ext: deferred MCCK work armed on cpu={}\n",
87 arch::s390x::cpu::lowcore::this_cpu_percpu().cpu_id);
88 }
89
90 if (irq::deferred_test_clear(irq::DEFERRED_CALL_FUNCTION_BIT)) {
91 zxfoundation::smp::csd::drain_cpu();
92 }
93
94 if (irq::deferred_test_clear(irq::DEFERRED_IRQ_WORK_BIT)) {
95 lib::do_softirq();
96 }
97
98 if (irq::deferred_test_clear(irq::DEFERRED_STOP_CPU_BIT)) {
99 const auto cpu_id =
100 arch::s390x::cpu::lowcore::this_cpu_percpu().cpu_id;
101 zxfoundation::sys::printk::pnotice(
102 "ext: stop-cpu deferred work on cpu={} — halting\n", cpu_id);
103 arch::s390x::cpu::cpumask::cpu_clear_online(cpu_id);
104 zxfoundation::sched::topology::topology_offline_cpu(cpu_id);
105 arch::s390x::cpu::psw::disabled_wait();
106 }
107 }
108
109} // namespace arch::s390x::trap::ext
110
111} // end export