From 0c4d01f3952911b766e6394e0053146c24c98357 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 11 Sep 2023 21:39:55 +0200 Subject: 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 Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/boot/vmem.c | 1 + arch/s390/include/asm/ctl_reg.h | 8 +++-- arch/s390/include/asm/fpu/internal.h | 1 - arch/s390/include/asm/uaccess.h | 1 - arch/s390/kernel/Makefile | 2 +- arch/s390/kernel/ctlreg.c | 62 ++++++++++++++++++++++++++++++++++++ arch/s390/kernel/smp.c | 53 ++---------------------------- arch/s390/lib/uaccess.c | 1 + arch/s390/mm/vmem.c | 1 + drivers/s390/char/sclp_early_core.c | 1 + 10 files changed, 75 insertions(+), 56 deletions(-) create mode 100644 arch/s390/kernel/ctlreg.c 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 #include #include +#include #include #include #include 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 -#include #include 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 #include -#include #include #include #include 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 +#include +#include +#include + +/* + * 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 #include #include +#include #include #include #include @@ -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 #include #include +#include #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 #include #include +#include #include #include #include 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 #include +#include #include #include #include -- cgit v1.2.3