s390/ctlreg: move control register code to separate file
authorHeiko Carstens <hca@linux.ibm.com>
Mon, 11 Sep 2023 19:39:55 +0000 (21:39 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 19 Sep 2023 11:26:56 +0000 (13:26 +0200)
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>
arch/s390/boot/vmem.c
arch/s390/include/asm/ctl_reg.h
arch/s390/include/asm/fpu/internal.h
arch/s390/include/asm/uaccess.h
arch/s390/kernel/Makefile
arch/s390/kernel/ctlreg.c [new file with mode: 0644]
arch/s390/kernel/smp.c
arch/s390/lib/uaccess.c
arch/s390/mm/vmem.c
drivers/s390/char/sclp_early_core.c

index 01257ce3b89c00f6fc124e2d4c3d7a331ee4250c..36b90864d69f56bae027c2c6142cb8f1ad871e7d 100644 (file)
@@ -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>
index adf7d8cdac7e64de4b9ba849f862452d0142666a..f5536fdb398d04ebe5f79ec3233e21ce4ce28601 100644 (file)
@@ -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 {
index bbdadb1c9efc6e378d9cf0a16b119ea581d69ebb..8634581b9011312b59c785527c7a4b2327252534 100644 (file)
@@ -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)
index 8a8c64a678c4a83a7310bca0f48e8139d7a6e7ea..81ae8a98e7ec2f580a7fa5d4f3c5129c9e6a03c6 100644 (file)
@@ -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>
index 0df2b88cc0dae0f49c4f8dad057efd752c999dcf..353def93973b312b0a696d4d6aa36e70b416ebf1 100644 (file)
@@ -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 (file)
index 0000000..176ada8
--- /dev/null
@@ -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);
index 9c5e107da4b48c9204b034ede098aa100e25fa7b..d12dbba9d03c0540c7969fe38a288bee0eb79304 100644 (file)
@@ -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;
 }
 
index e4a13d7cab6e4379b3e9226ac3174447aeb8d752..80b9c2d039f6266aababdce01f7ead5401e59a62 100644 (file)
@@ -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)
index 6957d2ed97bf0e18414cf5234887bcbed2f6fae4..9d3f9fa6f4986c4e857f67a69b81d6220ec73037 100644 (file)
@@ -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>
index dbd5c53d8edfe1bf406de6dd9ab56d9d02005567..a191d69573fbb4c6aaf9fb0153bf22d0eed99a4f 100644 (file)
@@ -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>