summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko Carstens <hca@linux.ibm.com>2023-09-11 21:39:55 +0200
committerVasily Gorbik <gor@linux.ibm.com>2023-09-19 13:26:56 +0200
commit0c4d01f3952911b766e6394e0053146c24c98357 (patch)
treee6c8945708e64dca2374bda03fa6d31e93e3083e
parentaa36d433b79657c1fed31ff5ae2bbd6f7bc123aa (diff)
s390/ctlreg: move control register code to separate file
Control register handling has nothing to do with low level SMP code. Move it to a separate file. Reviewed-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>
-rw-r--r--arch/s390/boot/vmem.c1
-rw-r--r--arch/s390/include/asm/ctl_reg.h8
-rw-r--r--arch/s390/include/asm/fpu/internal.h1
-rw-r--r--arch/s390/include/asm/uaccess.h1
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/ctlreg.c62
-rw-r--r--arch/s390/kernel/smp.c53
-rw-r--r--arch/s390/lib/uaccess.c1
-rw-r--r--arch/s390/mm/vmem.c1
-rw-r--r--drivers/s390/char/sclp_early_core.c1
10 files changed, 75 insertions, 56 deletions
diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c
index 01257ce3b89c..36b90864d69f 100644
--- a/arch/s390/boot/vmem.c
+++ b/arch/s390/boot/vmem.c
@@ -2,6 +2,7 @@
#include <linux/sched/task.h>
#include <linux/pgtable.h>
#include <linux/kasan.h>
+#include <asm/ctl_reg.h>
#include <asm/pgalloc.h>
#include <asm/facility.h>
#include <asm/sections.h>
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
index adf7d8cdac7e..f5536fdb398d 100644
--- a/arch/s390/include/asm/ctl_reg.h
+++ b/arch/s390/include/asm/ctl_reg.h
@@ -74,16 +74,18 @@ static __always_inline void __ctl_clear_bit(unsigned int cr, unsigned int bit)
__ctl_load(reg, cr, cr);
}
-void smp_ctl_set_clear_bit(int cr, int bit, bool set);
+void ctlreg_lock(void);
+void ctlreg_unlock(void);
+void ctl_set_clear_bit(int cr, int bit, bool set);
static inline void ctl_set_bit(int cr, int bit)
{
- smp_ctl_set_clear_bit(cr, bit, true);
+ ctl_set_clear_bit(cr, bit, true);
}
static inline void ctl_clear_bit(int cr, int bit)
{
- smp_ctl_set_clear_bit(cr, bit, false);
+ ctl_set_clear_bit(cr, bit, false);
}
union ctlreg0 {
diff --git a/arch/s390/include/asm/fpu/internal.h b/arch/s390/include/asm/fpu/internal.h
index bbdadb1c9efc..8634581b9011 100644
--- a/arch/s390/include/asm/fpu/internal.h
+++ b/arch/s390/include/asm/fpu/internal.h
@@ -10,7 +10,6 @@
#define _ASM_S390_FPU_INTERNAL_H
#include <linux/string.h>
-#include <asm/ctl_reg.h>
#include <asm/fpu/types.h>
static inline void save_vx_regs(__vector128 *vxrs)
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h
index 8a8c64a678c4..81ae8a98e7ec 100644
--- a/arch/s390/include/asm/uaccess.h
+++ b/arch/s390/include/asm/uaccess.h
@@ -15,7 +15,6 @@
*/
#include <asm/asm-extable.h>
#include <asm/processor.h>
-#include <asm/ctl_reg.h>
#include <asm/extable.h>
#include <asm/facility.h>
#include <asm-generic/access_ok.h>
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 0df2b88cc0da..353def93973b 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -37,7 +37,7 @@ CFLAGS_unwind_bc.o += -fno-optimize-sibling-calls
obj-y := head64.o traps.o time.o process.o earlypgm.o early.o setup.o idle.o vtime.o
obj-y += processor.o syscall.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o
obj-y += debug.o irq.o ipl.o dis.o diag.o vdso.o cpufeature.o
-obj-y += sysinfo.o lgr.o os_info.o
+obj-y += sysinfo.o lgr.o os_info.o ctlreg.o
obj-y += runtime_instr.o cache.o fpu.o dumpstack.o guarded_storage.o sthyi.o
obj-y += entry.o reipl.o kdebugfs.o alternative.o
obj-y += nospec-branch.o ipl_vmparm.o machine_kexec_reloc.o unwind_bc.o
diff --git a/arch/s390/kernel/ctlreg.c b/arch/s390/kernel/ctlreg.c
new file mode 100644
index 000000000000..176ada8b45c2
--- /dev/null
+++ b/arch/s390/kernel/ctlreg.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright IBM Corp. 1999, 2023
+ */
+
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <asm/abs_lowcore.h>
+#include <asm/ctl_reg.h>
+
+/*
+ * ctl_lock guards access to global control register contents which
+ * are kept in the control register save area within absolute lowcore
+ * at physical address zero.
+ */
+static DEFINE_SPINLOCK(ctl_lock);
+
+void ctlreg_lock(void)
+ __acquires(&ctl_lock)
+{
+ spin_lock(&ctl_lock);
+}
+
+void ctlreg_unlock(void)
+ __releases(&ctl_lock)
+{
+ spin_unlock(&ctl_lock);
+}
+
+struct ctl_bit_parms {
+ unsigned long orval;
+ unsigned long andval;
+ int cr;
+};
+
+static void ctl_bit_callback(void *info)
+{
+ struct ctl_bit_parms *pp = info;
+ unsigned long regs[16];
+
+ __ctl_store(regs, 0, 15);
+ regs[pp->cr] &= pp->andval;
+ regs[pp->cr] |= pp->orval;
+ __ctl_load(regs, 0, 15);
+}
+
+void ctl_set_clear_bit(int cr, int bit, bool set)
+{
+ struct ctl_bit_parms pp = { .cr = cr, };
+ struct lowcore *abs_lc;
+
+ pp.orval = set ? 1UL << bit : 0;
+ pp.andval = set ? -1UL : ~(1UL << bit);
+ ctlreg_lock();
+ abs_lc = get_abs_lowcore();
+ abs_lc->cregs_save_area[cr] &= pp.andval;
+ abs_lc->cregs_save_area[cr] |= pp.orval;
+ put_abs_lowcore(abs_lc);
+ on_each_cpu(ctl_bit_callback, &pp, 1);
+ ctlreg_unlock();
+}
+EXPORT_SYMBOL(ctl_set_clear_bit);
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 9c5e107da4b4..d12dbba9d03c 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -37,6 +37,7 @@
#include <linux/crash_dump.h>
#include <linux/kprobes.h>
#include <asm/asm-offsets.h>
+#include <asm/ctl_reg.h>
#include <asm/pfault.h>
#include <asm/diag.h>
#include <asm/switch_to.h>
@@ -567,54 +568,6 @@ void arch_irq_work_raise(void)
}
#endif
-/*
- * parameter area for the set/clear control bit callbacks
- */
-struct ec_creg_mask_parms {
- unsigned long orval;
- unsigned long andval;
- int cr;
-};
-
-/*
- * callback for setting/clearing control bits
- */
-static void smp_ctl_bit_callback(void *info)
-{
- struct ec_creg_mask_parms *pp = info;
- unsigned long cregs[16];
-
- __ctl_store(cregs, 0, 15);
- cregs[pp->cr] = (cregs[pp->cr] & pp->andval) | pp->orval;
- __ctl_load(cregs, 0, 15);
-}
-
-static DEFINE_SPINLOCK(ctl_lock);
-
-void smp_ctl_set_clear_bit(int cr, int bit, bool set)
-{
- struct ec_creg_mask_parms parms = { .cr = cr, };
- struct lowcore *abs_lc;
- u64 ctlreg;
-
- if (set) {
- parms.orval = 1UL << bit;
- parms.andval = -1UL;
- } else {
- parms.orval = 0;
- parms.andval = ~(1UL << bit);
- }
- spin_lock(&ctl_lock);
- abs_lc = get_abs_lowcore();
- ctlreg = abs_lc->cregs_save_area[cr];
- ctlreg = (ctlreg & parms.andval) | parms.orval;
- abs_lc->cregs_save_area[cr] = ctlreg;
- put_abs_lowcore(abs_lc);
- on_each_cpu(smp_ctl_bit_callback, &parms, 1);
- spin_unlock(&ctl_lock);
-}
-EXPORT_SYMBOL(smp_ctl_set_clear_bit);
-
#ifdef CONFIG_CRASH_DUMP
int smp_store_status(int cpu)
@@ -935,14 +888,14 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
* Make sure global control register contents do not change
* until new CPU has initialized control registers.
*/
- spin_lock(&ctl_lock);
+ ctlreg_lock();
pcpu_prepare_secondary(pcpu, cpu);
pcpu_attach_task(pcpu, tidle);
pcpu_start_fn(pcpu, smp_start_secondary, NULL);
/* Wait until cpu puts itself in the online & active maps */
while (!cpu_online(cpu))
cpu_relax();
- spin_unlock(&ctl_lock);
+ ctlreg_unlock();
return 0;
}
diff --git a/arch/s390/lib/uaccess.c b/arch/s390/lib/uaccess.c
index e4a13d7cab6e..80b9c2d039f6 100644
--- a/arch/s390/lib/uaccess.c
+++ b/arch/s390/lib/uaccess.c
@@ -12,6 +12,7 @@
#include <linux/export.h>
#include <linux/mm.h>
#include <asm/asm-extable.h>
+#include <asm/ctl_reg.h>
#ifdef CONFIG_DEBUG_ENTRY
void debug_user_asce(int exit)
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index 6957d2ed97bf..9d3f9fa6f498 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -14,6 +14,7 @@
#include <linux/sort.h>
#include <asm/cacheflush.h>
#include <asm/nospec-branch.h>
+#include <asm/ctl_reg.h>
#include <asm/pgalloc.h>
#include <asm/setup.h>
#include <asm/tlbflush.h>
diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c
index dbd5c53d8edf..a191d69573fb 100644
--- a/drivers/s390/char/sclp_early_core.c
+++ b/drivers/s390/char/sclp_early_core.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <asm/processor.h>
+#include <asm/ctl_reg.h>
#include <asm/lowcore.h>
#include <asm/ebcdic.h>
#include <asm/irq.h>