mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-06 13:23:18 +00:00
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>
This commit is contained in:
parent
aa36d433b7
commit
0c4d01f395
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
62
arch/s390/kernel/ctlreg.c
Normal file
62
arch/s390/kernel/ctlreg.c
Normal file
@ -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);
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user