summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2023-09-05 16:49:37 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-09-04 14:17:33 +0300
commit0f83d77926303534bff2b5cedaa20fff7be8e01a (patch)
tree303f72da4435fad6afae116639be69825196931b
parentaeda7043c4db1446b8def022bf1fc101e83b335e (diff)
downloadlinux-0f83d77926303534bff2b5cedaa20fff7be8e01a.tar.xz
s390/smp,mcck: fix early IPI handling
[ Upstream commit 4a1725281fc5b0009944b1c0e1d2c1dc311a09ec ] Both the external call as well as the emergency signal submask bits in control register 0 are set before any interrupt handler is registered. Change the order and first register the interrupt handler and only then enable the interrupts by setting the corresponding bits in control register 0. This prevents that the second part of the machine check handler for early machine check handling is not executed: the machine check handler sends an IPI to the CPU it runs on. If the corresponding interrupts are enabled, but no interrupt handler is present, the interrupt is ignored. Reviewed-by: Sven Schnelle <svens@linux.ibm.com> Acked-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--arch/s390/kernel/early.c12
-rw-r--r--arch/s390/kernel/smp.c4
2 files changed, 5 insertions, 11 deletions
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 985e1e755333..bac1be43d36c 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -252,15 +252,9 @@ static inline void save_vector_registers(void)
#endif
}
-static inline void setup_control_registers(void)
+static inline void setup_low_address_protection(void)
{
- unsigned long reg;
-
- __ctl_store(reg, 0, 0);
- reg |= CR0_LOW_ADDRESS_PROTECTION;
- reg |= CR0_EMERGENCY_SIGNAL_SUBMASK;
- reg |= CR0_EXTERNAL_CALL_SUBMASK;
- __ctl_load(reg, 0, 0);
+ __ctl_set_bit(0, 28);
}
static inline void setup_access_registers(void)
@@ -313,7 +307,7 @@ void __init startup_init(void)
save_vector_registers();
setup_topology();
sclp_early_detect();
- setup_control_registers();
+ setup_low_address_protection();
setup_access_registers();
lockdep_on();
}
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 5674792726cd..2e0c3b0a5a58 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -982,12 +982,12 @@ void __init smp_fill_possible_mask(void)
void __init smp_prepare_cpus(unsigned int max_cpus)
{
- /* request the 0x1201 emergency signal external interrupt */
if (register_external_irq(EXT_IRQ_EMERGENCY_SIG, do_ext_call_interrupt))
panic("Couldn't request external interrupt 0x1201");
- /* request the 0x1202 external call external interrupt */
+ ctl_set_bit(0, 14);
if (register_external_irq(EXT_IRQ_EXTERNAL_CALL, do_ext_call_interrupt))
panic("Couldn't request external interrupt 0x1202");
+ ctl_set_bit(0, 13);
}
void __init smp_prepare_boot_cpu(void)