s390/ctl_reg: use decoding unions in update_cr_regs
Add a decoding union for the bits in control registers 2 and use 'union ctlreg0' and 'union ctlreg2' in update_cr_regs to improve readability. Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
@@ -54,7 +54,11 @@ void smp_ctl_clear_bit(int cr, int bit);
|
|||||||
union ctlreg0 {
|
union ctlreg0 {
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
struct {
|
struct {
|
||||||
unsigned long : 32;
|
unsigned long : 8;
|
||||||
|
unsigned long tcx : 1; /* Transactional-Execution control */
|
||||||
|
unsigned long pifo : 1; /* Transactional-Execution Program-
|
||||||
|
Interruption-Filtering Override */
|
||||||
|
unsigned long : 22;
|
||||||
unsigned long : 3;
|
unsigned long : 3;
|
||||||
unsigned long lap : 1; /* Low-address-protection control */
|
unsigned long lap : 1; /* Low-address-protection control */
|
||||||
unsigned long : 4;
|
unsigned long : 4;
|
||||||
@@ -70,6 +74,19 @@ union ctlreg0 {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union ctlreg2 {
|
||||||
|
unsigned long val;
|
||||||
|
struct {
|
||||||
|
unsigned long : 33;
|
||||||
|
unsigned long ducto : 25;
|
||||||
|
unsigned long : 1;
|
||||||
|
unsigned long gse : 1;
|
||||||
|
unsigned long : 1;
|
||||||
|
unsigned long tds : 1;
|
||||||
|
unsigned long tdc : 2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
# define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
|
# define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
|
||||||
# define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
|
# define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ static void __do_machine_kdump(void *image)
|
|||||||
static noinline void __machine_kdump(void *image)
|
static noinline void __machine_kdump(void *image)
|
||||||
{
|
{
|
||||||
struct mcesa *mcesa;
|
struct mcesa *mcesa;
|
||||||
unsigned long cr2_old, cr2_new;
|
union ctlreg2 cr2_old, cr2_new;
|
||||||
int this_cpu, cpu;
|
int this_cpu, cpu;
|
||||||
|
|
||||||
lgr_info_log();
|
lgr_info_log();
|
||||||
@@ -122,11 +122,12 @@ static noinline void __machine_kdump(void *image)
|
|||||||
if (MACHINE_HAS_VX)
|
if (MACHINE_HAS_VX)
|
||||||
save_vx_regs((__vector128 *) mcesa->vector_save_area);
|
save_vx_regs((__vector128 *) mcesa->vector_save_area);
|
||||||
if (MACHINE_HAS_GS) {
|
if (MACHINE_HAS_GS) {
|
||||||
__ctl_store(cr2_old, 2, 2);
|
__ctl_store(cr2_old.val, 2, 2);
|
||||||
cr2_new = cr2_old | (1UL << 4);
|
cr2_new = cr2_old;
|
||||||
__ctl_load(cr2_new, 2, 2);
|
cr2_new.gse = 1;
|
||||||
|
__ctl_load(cr2_new.val, 2, 2);
|
||||||
save_gs_cb((struct gs_cb *) mcesa->guarded_storage_save_area);
|
save_gs_cb((struct gs_cb *) mcesa->guarded_storage_save_area);
|
||||||
__ctl_load(cr2_old, 2, 2);
|
__ctl_load(cr2_old.val, 2, 2);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* To create a good backchain for this CPU in the dump store_status
|
* To create a good backchain for this CPU in the dump store_status
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck);
|
|||||||
*/
|
*/
|
||||||
static int notrace s390_validate_registers(union mci mci, int umode)
|
static int notrace s390_validate_registers(union mci mci, int umode)
|
||||||
{
|
{
|
||||||
|
union ctlreg2 cr2;
|
||||||
int kill_task;
|
int kill_task;
|
||||||
u64 zero;
|
u64 zero;
|
||||||
void *fpt_save_area;
|
void *fpt_save_area;
|
||||||
@@ -231,7 +232,8 @@ static int notrace s390_validate_registers(union mci mci, int umode)
|
|||||||
kill_task = 1;
|
kill_task = 1;
|
||||||
}
|
}
|
||||||
/* Validate guarded storage registers */
|
/* Validate guarded storage registers */
|
||||||
if (MACHINE_HAS_GS && (S390_lowcore.cregs_save_area[2] & (1UL << 4))) {
|
cr2.val = S390_lowcore.cregs_save_area[2];
|
||||||
|
if (cr2.gse) {
|
||||||
if (!mci.gs)
|
if (!mci.gs)
|
||||||
/*
|
/*
|
||||||
* Guarded storage register can't be restored and
|
* Guarded storage register can't be restored and
|
||||||
|
|||||||
@@ -47,42 +47,42 @@ void update_cr_regs(struct task_struct *task)
|
|||||||
struct pt_regs *regs = task_pt_regs(task);
|
struct pt_regs *regs = task_pt_regs(task);
|
||||||
struct thread_struct *thread = &task->thread;
|
struct thread_struct *thread = &task->thread;
|
||||||
struct per_regs old, new;
|
struct per_regs old, new;
|
||||||
unsigned long cr0_old, cr0_new;
|
union ctlreg0 cr0_old, cr0_new;
|
||||||
unsigned long cr2_old, cr2_new;
|
union ctlreg2 cr2_old, cr2_new;
|
||||||
int cr0_changed, cr2_changed;
|
int cr0_changed, cr2_changed;
|
||||||
|
|
||||||
__ctl_store(cr0_old, 0, 0);
|
__ctl_store(cr0_old.val, 0, 0);
|
||||||
__ctl_store(cr2_old, 2, 2);
|
__ctl_store(cr2_old.val, 2, 2);
|
||||||
cr0_new = cr0_old;
|
cr0_new = cr0_old;
|
||||||
cr2_new = cr2_old;
|
cr2_new = cr2_old;
|
||||||
/* Take care of the enable/disable of transactional execution. */
|
/* Take care of the enable/disable of transactional execution. */
|
||||||
if (MACHINE_HAS_TE) {
|
if (MACHINE_HAS_TE) {
|
||||||
/* Set or clear transaction execution TXC bit 8. */
|
/* Set or clear transaction execution TXC bit 8. */
|
||||||
cr0_new |= (1UL << 55);
|
cr0_new.tcx = 1;
|
||||||
if (task->thread.per_flags & PER_FLAG_NO_TE)
|
if (task->thread.per_flags & PER_FLAG_NO_TE)
|
||||||
cr0_new &= ~(1UL << 55);
|
cr0_new.tcx = 0;
|
||||||
/* Set or clear transaction execution TDC bits 62 and 63. */
|
/* Set or clear transaction execution TDC bits 62 and 63. */
|
||||||
cr2_new &= ~3UL;
|
cr2_new.tdc = 0;
|
||||||
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
|
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
|
||||||
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
|
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
|
||||||
cr2_new |= 1UL;
|
cr2_new.tdc = 1;
|
||||||
else
|
else
|
||||||
cr2_new |= 2UL;
|
cr2_new.tdc = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Take care of enable/disable of guarded storage. */
|
/* Take care of enable/disable of guarded storage. */
|
||||||
if (MACHINE_HAS_GS) {
|
if (MACHINE_HAS_GS) {
|
||||||
cr2_new &= ~(1UL << 4);
|
cr2_new.gse = 0;
|
||||||
if (task->thread.gs_cb)
|
if (task->thread.gs_cb)
|
||||||
cr2_new |= (1UL << 4);
|
cr2_new.gse = 1;
|
||||||
}
|
}
|
||||||
/* Load control register 0/2 iff changed */
|
/* Load control register 0/2 iff changed */
|
||||||
cr0_changed = cr0_new != cr0_old;
|
cr0_changed = cr0_new.val != cr0_old.val;
|
||||||
cr2_changed = cr2_new != cr2_old;
|
cr2_changed = cr2_new.val != cr2_old.val;
|
||||||
if (cr0_changed)
|
if (cr0_changed)
|
||||||
__ctl_load(cr0_new, 0, 0);
|
__ctl_load(cr0_new.val, 0, 0);
|
||||||
if (cr2_changed)
|
if (cr2_changed)
|
||||||
__ctl_load(cr2_new, 2, 2);
|
__ctl_load(cr2_new.val, 2, 2);
|
||||||
/* Copy user specified PER registers */
|
/* Copy user specified PER registers */
|
||||||
new.control = thread->per_user.control;
|
new.control = thread->per_user.control;
|
||||||
new.start = thread->per_user.start;
|
new.start = thread->per_user.start;
|
||||||
|
|||||||
Reference in New Issue
Block a user