mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-11-25 22:23:14 +00:00
s390/ctlreg: allow to call system_ctl_set/clear_bit() early
Allow to call system_ctl_set_bit() and system_clt_clear_bit() early, so that users do not have to take care when the control register save area has been initialized. Users are supposed to use system_ctl_set_bit() and system:clt_clear_bit() for all control register changes which are supposed to be seen globally. Depending on the system state such calls will change: - local control register contents - save area and local control register contents - save area and global control register contents Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
d11d5c8c84
commit
cce2c8606f
@ -3,9 +3,12 @@
|
|||||||
* Copyright IBM Corp. 1999, 2023
|
* Copyright IBM Corp. 1999, 2023
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/irqflags.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
|
#include <linux/cache.h>
|
||||||
#include <asm/abs_lowcore.h>
|
#include <asm/abs_lowcore.h>
|
||||||
#include <asm/ctlreg.h>
|
#include <asm/ctlreg.h>
|
||||||
|
|
||||||
@ -28,6 +31,8 @@ void system_ctlreg_unlock(void)
|
|||||||
spin_unlock(&system_ctl_lock);
|
spin_unlock(&system_ctl_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool system_ctlreg_area_init __ro_after_init;
|
||||||
|
|
||||||
void __init system_ctlreg_init_save_area(struct lowcore *lc)
|
void __init system_ctlreg_init_save_area(struct lowcore *lc)
|
||||||
{
|
{
|
||||||
struct lowcore *abs_lc;
|
struct lowcore *abs_lc;
|
||||||
@ -36,6 +41,7 @@ void __init system_ctlreg_init_save_area(struct lowcore *lc)
|
|||||||
__local_ctl_store(0, 15, lc->cregs_save_area);
|
__local_ctl_store(0, 15, lc->cregs_save_area);
|
||||||
__local_ctl_store(0, 15, abs_lc->cregs_save_area);
|
__local_ctl_store(0, 15, abs_lc->cregs_save_area);
|
||||||
put_abs_lowcore(abs_lc);
|
put_abs_lowcore(abs_lc);
|
||||||
|
system_ctlreg_area_init = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ctl_bit_parms {
|
struct ctl_bit_parms {
|
||||||
@ -55,6 +61,23 @@ static void ctl_bit_callback(void *info)
|
|||||||
__local_ctl_load(0, 15, regs);
|
__local_ctl_load(0, 15, regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void system_ctl_bit_update(void *info)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (system_state == SYSTEM_BOOTING) {
|
||||||
|
/*
|
||||||
|
* For very early calls do not call on_each_cpu()
|
||||||
|
* since not everything might be setup.
|
||||||
|
*/
|
||||||
|
local_irq_save(flags);
|
||||||
|
ctl_bit_callback(info);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
} else {
|
||||||
|
on_each_cpu(ctl_bit_callback, info, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void system_ctl_set_clear_bit(unsigned int cr, unsigned int bit, bool set)
|
void system_ctl_set_clear_bit(unsigned int cr, unsigned int bit, bool set)
|
||||||
{
|
{
|
||||||
struct ctl_bit_parms pp = { .cr = cr, };
|
struct ctl_bit_parms pp = { .cr = cr, };
|
||||||
@ -62,12 +85,16 @@ void system_ctl_set_clear_bit(unsigned int cr, unsigned int bit, bool set)
|
|||||||
|
|
||||||
pp.orval = set ? 1UL << bit : 0;
|
pp.orval = set ? 1UL << bit : 0;
|
||||||
pp.andval = set ? -1UL : ~(1UL << bit);
|
pp.andval = set ? -1UL : ~(1UL << bit);
|
||||||
system_ctlreg_lock();
|
if (system_ctlreg_area_init) {
|
||||||
abs_lc = get_abs_lowcore();
|
system_ctlreg_lock();
|
||||||
abs_lc->cregs_save_area[cr].val &= pp.andval;
|
abs_lc = get_abs_lowcore();
|
||||||
abs_lc->cregs_save_area[cr].val |= pp.orval;
|
abs_lc->cregs_save_area[cr].val &= pp.andval;
|
||||||
put_abs_lowcore(abs_lc);
|
abs_lc->cregs_save_area[cr].val |= pp.orval;
|
||||||
on_each_cpu(ctl_bit_callback, &pp, 1);
|
put_abs_lowcore(abs_lc);
|
||||||
system_ctlreg_unlock();
|
system_ctl_bit_update(&pp);
|
||||||
|
system_ctlreg_unlock();
|
||||||
|
} else {
|
||||||
|
system_ctl_bit_update(&pp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(system_ctl_set_clear_bit);
|
EXPORT_SYMBOL(system_ctl_set_clear_bit);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user