Commit b50511e4 authored by Martin Schwidefsky's avatar Martin Schwidefsky

[S390] cleanup psw related bits and pieces

Split out addressing mode bits from PSW_BASE_BITS, rename PSW_BASE_BITS
to PSW_MASK_BASE, get rid of psw_user32_bits, remove unused function
enabled_wait(), introduce PSW_MASK_USER, and drop PSW_MASK_MERGE macros.
Change psw_kernel_bits / psw_user_bits to contain only the bits that
are always set in the respective mode.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent b6ef5bb3
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define PSW32_MASK_IO 0x02000000UL #define PSW32_MASK_IO 0x02000000UL
#define PSW32_MASK_EXT 0x01000000UL #define PSW32_MASK_EXT 0x01000000UL
#define PSW32_MASK_KEY 0x00F00000UL #define PSW32_MASK_KEY 0x00F00000UL
#define PSW32_MASK_BASE 0x00080000UL /* Always one */
#define PSW32_MASK_MCHECK 0x00040000UL #define PSW32_MASK_MCHECK 0x00040000UL
#define PSW32_MASK_WAIT 0x00020000UL #define PSW32_MASK_WAIT 0x00020000UL
#define PSW32_MASK_PSTATE 0x00010000UL #define PSW32_MASK_PSTATE 0x00010000UL
...@@ -19,21 +20,19 @@ ...@@ -19,21 +20,19 @@
#define PSW32_MASK_CC 0x00003000UL #define PSW32_MASK_CC 0x00003000UL
#define PSW32_MASK_PM 0x00000f00UL #define PSW32_MASK_PM 0x00000f00UL
#define PSW32_ADDR_AMODE31 0x80000000UL #define PSW32_MASK_USER 0x00003F00UL
#define PSW32_ADDR_AMODE 0x80000000UL
#define PSW32_ADDR_INSN 0x7FFFFFFFUL #define PSW32_ADDR_INSN 0x7FFFFFFFUL
#define PSW32_BASE_BITS 0x00080000UL #define PSW32_DEFAULT_KEY (((u32) PAGE_DEFAULT_ACC) << 20)
#define PSW32_ASC_PRIMARY 0x00000000UL #define PSW32_ASC_PRIMARY 0x00000000UL
#define PSW32_ASC_ACCREG 0x00004000UL #define PSW32_ASC_ACCREG 0x00004000UL
#define PSW32_ASC_SECONDARY 0x00008000UL #define PSW32_ASC_SECONDARY 0x00008000UL
#define PSW32_ASC_HOME 0x0000C000UL #define PSW32_ASC_HOME 0x0000C000UL
#define PSW32_MASK_MERGE(CURRENT,NEW) \ extern u32 psw32_user_bits;
(((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))
extern long psw32_user_bits;
#define COMPAT_USER_HZ 100 #define COMPAT_USER_HZ 100
#define COMPAT_UTS_MACHINE "s390\0\0\0\0" #define COMPAT_UTS_MACHINE "s390\0\0\0\0"
......
...@@ -118,17 +118,17 @@ struct stack_frame { ...@@ -118,17 +118,17 @@ struct stack_frame {
/* /*
* Do necessary setup to start up a new thread. * Do necessary setup to start up a new thread.
*/ */
#define start_thread(regs, new_psw, new_stackp) do { \ #define start_thread(regs, new_psw, new_stackp) do { \
regs->psw.mask = psw_user_bits; \ regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \ regs->gprs[15] = new_stackp; \
} while (0) } while (0)
#define start_thread31(regs, new_psw, new_stackp) do { \ #define start_thread31(regs, new_psw, new_stackp) do { \
regs->psw.mask = psw_user32_bits; \ regs->psw.mask = psw_user_bits | PSW_MASK_BA; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \ regs->gprs[15] = new_stackp; \
crst_table_downgrade(current->mm, 1UL << 31); \ crst_table_downgrade(current->mm, 1UL << 31); \
} while (0) } while (0)
/* Forward declaration, a strange C thing */ /* Forward declaration, a strange C thing */
...@@ -233,25 +233,15 @@ static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc) ...@@ -233,25 +233,15 @@ static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
#endif #endif
} }
/*
* Function to stop a processor until an interruption occurred
*/
static inline void enabled_wait(void)
{
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
}
/* /*
* Function to drop a processor into disabled wait state * Function to drop a processor into disabled wait state
*/ */
static inline void ATTRIB_NORET disabled_wait(unsigned long code) static inline void ATTRIB_NORET disabled_wait(unsigned long code)
{ {
unsigned long ctl_buf; unsigned long ctl_buf;
psw_t dw_psw; psw_t dw_psw;
dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; dw_psw.mask = PSW_MASK_BASE | PSW_MASK_WAIT | PSW_MASK_BA | PSW_MASK_EA;
dw_psw.addr = code; dw_psw.addr = code;
/* /*
* Store status and then load disabled wait psw, * Store status and then load disabled wait psw,
......
...@@ -230,6 +230,7 @@ typedef struct ...@@ -230,6 +230,7 @@ typedef struct
#define PSW_MASK_IO 0x02000000UL #define PSW_MASK_IO 0x02000000UL
#define PSW_MASK_EXT 0x01000000UL #define PSW_MASK_EXT 0x01000000UL
#define PSW_MASK_KEY 0x00F00000UL #define PSW_MASK_KEY 0x00F00000UL
#define PSW_MASK_BASE 0x00080000UL /* always one */
#define PSW_MASK_MCHECK 0x00040000UL #define PSW_MASK_MCHECK 0x00040000UL
#define PSW_MASK_WAIT 0x00020000UL #define PSW_MASK_WAIT 0x00020000UL
#define PSW_MASK_PSTATE 0x00010000UL #define PSW_MASK_PSTATE 0x00010000UL
...@@ -239,10 +240,11 @@ typedef struct ...@@ -239,10 +240,11 @@ typedef struct
#define PSW_MASK_EA 0x00000000UL #define PSW_MASK_EA 0x00000000UL
#define PSW_MASK_BA 0x00000000UL #define PSW_MASK_BA 0x00000000UL
#define PSW_MASK_USER 0x00003F00UL
#define PSW_ADDR_AMODE 0x80000000UL #define PSW_ADDR_AMODE 0x80000000UL
#define PSW_ADDR_INSN 0x7FFFFFFFUL #define PSW_ADDR_INSN 0x7FFFFFFFUL
#define PSW_BASE_BITS 0x00080000UL
#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 20) #define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 20)
#define PSW_ASC_PRIMARY 0x00000000UL #define PSW_ASC_PRIMARY 0x00000000UL
...@@ -256,6 +258,7 @@ typedef struct ...@@ -256,6 +258,7 @@ typedef struct
#define PSW_MASK_DAT 0x0400000000000000UL #define PSW_MASK_DAT 0x0400000000000000UL
#define PSW_MASK_IO 0x0200000000000000UL #define PSW_MASK_IO 0x0200000000000000UL
#define PSW_MASK_EXT 0x0100000000000000UL #define PSW_MASK_EXT 0x0100000000000000UL
#define PSW_MASK_BASE 0x0000000000000000UL
#define PSW_MASK_KEY 0x00F0000000000000UL #define PSW_MASK_KEY 0x00F0000000000000UL
#define PSW_MASK_MCHECK 0x0004000000000000UL #define PSW_MASK_MCHECK 0x0004000000000000UL
#define PSW_MASK_WAIT 0x0002000000000000UL #define PSW_MASK_WAIT 0x0002000000000000UL
...@@ -266,11 +269,11 @@ typedef struct ...@@ -266,11 +269,11 @@ typedef struct
#define PSW_MASK_EA 0x0000000100000000UL #define PSW_MASK_EA 0x0000000100000000UL
#define PSW_MASK_BA 0x0000000080000000UL #define PSW_MASK_BA 0x0000000080000000UL
#define PSW_MASK_USER 0x00003F0000000000UL
#define PSW_ADDR_AMODE 0x0000000000000000UL #define PSW_ADDR_AMODE 0x0000000000000000UL
#define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL
#define PSW_BASE_BITS 0x0000000180000000UL
#define PSW_BASE32_BITS 0x0000000080000000UL
#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 52) #define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 52)
#define PSW_ASC_PRIMARY 0x0000000000000000UL #define PSW_ASC_PRIMARY 0x0000000000000000UL
...@@ -283,18 +286,7 @@ typedef struct ...@@ -283,18 +286,7 @@ typedef struct
#ifdef __KERNEL__ #ifdef __KERNEL__
extern long psw_kernel_bits; extern long psw_kernel_bits;
extern long psw_user_bits; extern long psw_user_bits;
#ifdef CONFIG_64BIT
extern long psw_user32_bits;
#endif #endif
#endif
/* This macro merges a NEW PSW mask specified by the user into
the currently active PSW mask CURRENT, modifying only those
bits in CURRENT that the user may be allowed to change: this
is the condition code and the program mask bits. */
#define PSW_MASK_MERGE(CURRENT,NEW) \
(((CURRENT) & ~(PSW_MASK_CC|PSW_MASK_PM)) | \
((NEW) & (PSW_MASK_CC|PSW_MASK_PM)))
/* /*
* The s390_regs structure is used to define the elf_gregset_t. * The s390_regs structure is used to define the elf_gregset_t.
......
...@@ -212,8 +212,10 @@ __set_psw_mask(unsigned long mask) ...@@ -212,8 +212,10 @@ __set_psw_mask(unsigned long mask)
__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8))); __load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
} }
#define local_mcck_enable() __set_psw_mask(psw_kernel_bits) #define local_mcck_enable() \
#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK) __set_psw_mask(psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK)
#define local_mcck_disable() \
__set_psw_mask(psw_kernel_bits | PSW_MASK_DAT)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -60,12 +60,9 @@ ...@@ -60,12 +60,9 @@
#include "compat_linux.h" #include "compat_linux.h"
long psw_user32_bits = (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT |
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | PSW32_DEFAULT_KEY | PSW32_MASK_BASE | PSW32_MASK_MCHECK |
PSW_MASK_PSTATE | PSW_DEFAULT_KEY); PSW32_MASK_PSTATE | PSW32_ASC_HOME;
long psw32_user_bits = (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME |
PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
PSW32_MASK_PSTATE);
/* For this source file, we want overflow handling. */ /* For this source file, we want overflow handling. */
......
...@@ -300,9 +300,9 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) ...@@ -300,9 +300,9 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
_s390_regs_common32 regs32; _s390_regs_common32 regs32;
int err, i; int err, i;
regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits, regs32.psw.mask = psw32_user_bits |
(__u32)(regs->psw.mask >> 32)); ((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr; regs32.psw.addr = PSW32_ADDR_AMODE | (__u32) regs->psw.addr;
for (i = 0; i < NUM_GPRS; i++) for (i = 0; i < NUM_GPRS; i++)
regs32.gprs[i] = (__u32) regs->gprs[i]; regs32.gprs[i] = (__u32) regs->gprs[i];
save_access_regs(current->thread.acrs); save_access_regs(current->thread.acrs);
...@@ -327,8 +327,8 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) ...@@ -327,8 +327,8 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32)); err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
if (err) if (err)
return err; return err;
regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask, regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(__u64)regs32.psw.mask << 32); (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32;
regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
for (i = 0; i < NUM_GPRS; i++) for (i = 0; i < NUM_GPRS; i++)
regs->gprs[i] = (__u64) regs32.gprs[i]; regs->gprs[i] = (__u64) regs32.gprs[i];
......
...@@ -252,7 +252,7 @@ static noinline __init void setup_lowcore_early(void) ...@@ -252,7 +252,7 @@ static noinline __init void setup_lowcore_early(void)
{ {
psw_t psw; psw_t psw;
psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; psw.mask = PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA;
psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler; psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_ext_handler;
S390_lowcore.external_new_psw = psw; S390_lowcore.external_new_psw = psw;
psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
......
...@@ -2033,12 +2033,12 @@ void s390_reset_system(void (*func)(void *), void *data) ...@@ -2033,12 +2033,12 @@ void s390_reset_system(void (*func)(void *), void *data)
__ctl_clear_bit(0,28); __ctl_clear_bit(0,28);
/* Set new machine check handler */ /* Set new machine check handler */
S390_lowcore.mcck_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; S390_lowcore.mcck_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
S390_lowcore.mcck_new_psw.addr = S390_lowcore.mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler; PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_handler;
/* Set new program check handler */ /* Set new program check handler */
S390_lowcore.program_new_psw.mask = psw_kernel_bits & ~PSW_MASK_MCHECK; S390_lowcore.program_new_psw.mask = psw_kernel_bits | PSW_MASK_DAT;
S390_lowcore.program_new_psw.addr = S390_lowcore.program_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler; PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
......
...@@ -108,7 +108,7 @@ static void __do_machine_kdump(void *image) ...@@ -108,7 +108,7 @@ static void __do_machine_kdump(void *image)
#ifdef CONFIG_CRASH_DUMP #ifdef CONFIG_CRASH_DUMP
int (*start_kdump)(int) = (void *)((struct kimage *) image)->start; int (*start_kdump)(int) = (void *)((struct kimage *) image)->start;
__load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY); __load_psw_mask(PSW_MASK_BASE | PSW_DEFAULT_KEY | PSW_MASK_EA | PSW_MASK_BA);
setup_regs(); setup_regs();
start_kdump(1); start_kdump(1);
#endif #endif
......
...@@ -117,7 +117,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) ...@@ -117,7 +117,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
struct pt_regs regs; struct pt_regs regs;
memset(&regs, 0, sizeof(regs)); memset(&regs, 0, sizeof(regs));
regs.psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT; regs.psw.mask = psw_kernel_bits |
PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE; regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE;
regs.gprs[9] = (unsigned long) fn; regs.gprs[9] = (unsigned long) fn;
regs.gprs[10] = (unsigned long) arg; regs.gprs[10] = (unsigned long) arg;
......
...@@ -169,8 +169,9 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr) ...@@ -169,8 +169,9 @@ static unsigned long __peek_user(struct task_struct *child, addr_t addr)
*/ */
tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr); tmp = *(addr_t *)((addr_t) &task_pt_regs(child)->psw + addr);
if (addr == (addr_t) &dummy->regs.psw.mask) if (addr == (addr_t) &dummy->regs.psw.mask)
/* Remove per bit from user psw. */ /* Return a clean psw mask. */
tmp &= ~PSW_MASK_PER; tmp = psw_user_bits | (tmp & PSW_MASK_USER) |
PSW_MASK_EA | PSW_MASK_BA;
} else if (addr < (addr_t) &dummy->regs.orig_gpr2) { } else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
/* /*
...@@ -285,17 +286,18 @@ static inline void __poke_user_per(struct task_struct *child, ...@@ -285,17 +286,18 @@ static inline void __poke_user_per(struct task_struct *child,
static int __poke_user(struct task_struct *child, addr_t addr, addr_t data) static int __poke_user(struct task_struct *child, addr_t addr, addr_t data)
{ {
struct user *dummy = NULL; struct user *dummy = NULL;
addr_t offset; addr_t offset, tmp;
if (addr < (addr_t) &dummy->regs.acrs) { if (addr < (addr_t) &dummy->regs.acrs) {
/* /*
* psw and gprs are stored on the stack * psw and gprs are stored on the stack
*/ */
tmp = (data & ~PSW_MASK_USER) ^ psw_user_bits;
if (addr == (addr_t) &dummy->regs.psw.mask && if (addr == (addr_t) &dummy->regs.psw.mask &&
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
data != PSW_MASK_MERGE(psw_user32_bits, data) && tmp != PSW_MASK_BA &&
#endif #endif
data != PSW_MASK_MERGE(psw_user_bits, data)) tmp != (PSW_MASK_EA | PSW_MASK_BA))
/* Invalid psw mask. */ /* Invalid psw mask. */
return -EINVAL; return -EINVAL;
#ifndef CONFIG_64BIT #ifndef CONFIG_64BIT
...@@ -505,21 +507,20 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr) ...@@ -505,21 +507,20 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
__u32 tmp; __u32 tmp;
if (addr < (addr_t) &dummy32->regs.acrs) { if (addr < (addr_t) &dummy32->regs.acrs) {
struct pt_regs *regs = task_pt_regs(child);
/* /*
* psw and gprs are stored on the stack * psw and gprs are stored on the stack
*/ */
if (addr == (addr_t) &dummy32->regs.psw.mask) { if (addr == (addr_t) &dummy32->regs.psw.mask) {
/* Fake a 31 bit psw mask. */ /* Fake a 31 bit psw mask. */
tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32); tmp = (__u32)(regs->psw.mask >> 32);
tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp); tmp = psw32_user_bits | (tmp & PSW32_MASK_USER);
} else if (addr == (addr_t) &dummy32->regs.psw.addr) { } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Fake a 31 bit psw address. */ /* Fake a 31 bit psw address. */
tmp = (__u32) task_pt_regs(child)->psw.addr | tmp = (__u32) regs->psw.addr | PSW32_ADDR_AMODE;
PSW32_ADDR_AMODE31;
} else { } else {
/* gpr 0-15 */ /* gpr 0-15 */
tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw + tmp = *(__u32 *)((addr_t) &regs->psw + addr*2 + 4);
addr*2 + 4);
} }
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) { } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
/* /*
...@@ -604,20 +605,20 @@ static int __poke_user_compat(struct task_struct *child, ...@@ -604,20 +605,20 @@ static int __poke_user_compat(struct task_struct *child,
addr_t offset; addr_t offset;
if (addr < (addr_t) &dummy32->regs.acrs) { if (addr < (addr_t) &dummy32->regs.acrs) {
struct pt_regs *regs = task_pt_regs(child);
/* /*
* psw, gprs, acrs and orig_gpr2 are stored on the stack * psw, gprs, acrs and orig_gpr2 are stored on the stack
*/ */
if (addr == (addr_t) &dummy32->regs.psw.mask) { if (addr == (addr_t) &dummy32->regs.psw.mask) {
/* Build a 64 bit psw mask from 31 bit mask. */ /* Build a 64 bit psw mask from 31 bit mask. */
if (tmp != PSW32_MASK_MERGE(psw32_user_bits, tmp)) if ((tmp & ~PSW32_MASK_USER) != psw32_user_bits)
/* Invalid psw mask. */ /* Invalid psw mask. */
return -EINVAL; return -EINVAL;
task_pt_regs(child)->psw.mask = regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32); (__u64)(tmp & PSW32_MASK_USER) << 32;
} else if (addr == (addr_t) &dummy32->regs.psw.addr) { } else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Build a 64 bit psw address from 31 bit address. */ /* Build a 64 bit psw address from 31 bit address. */
task_pt_regs(child)->psw.addr = regs->psw.addr = (__u64) tmp & PSW32_ADDR_INSN;
(__u64) tmp & PSW32_ADDR_INSN;
/* /*
* The debugger changed the instruction address, * The debugger changed the instruction address,
* reset system call restart, see signal.c:do_signal * reset system call restart, see signal.c:do_signal
...@@ -625,8 +626,7 @@ static int __poke_user_compat(struct task_struct *child, ...@@ -625,8 +626,7 @@ static int __poke_user_compat(struct task_struct *child,
task_thread_info(child)->system_call = 0; task_thread_info(child)->system_call = 0;
} else { } else {
/* gpr 0-15 */ /* gpr 0-15 */
*(__u32*)((addr_t) &task_pt_regs(child)->psw *(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
+ addr*2 + 4) = tmp;
} }
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) { } else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
/* /*
......
...@@ -62,11 +62,11 @@ ...@@ -62,11 +62,11 @@
#include <asm/kvm_virtio.h> #include <asm/kvm_virtio.h>
#include <asm/diag.h> #include <asm/diag.h>
long psw_kernel_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | long psw_kernel_bits = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_ASC_PRIMARY |
PSW_MASK_MCHECK | PSW_DEFAULT_KEY); PSW_MASK_EA | PSW_MASK_BA;
long psw_user_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | long psw_user_bits = PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT |
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_MCHECK |
PSW_MASK_PSTATE | PSW_DEFAULT_KEY); PSW_MASK_PSTATE | PSW_ASC_HOME;
/* /*
* User copy operations. * User copy operations.
...@@ -278,22 +278,14 @@ early_param("mem", early_parse_mem); ...@@ -278,22 +278,14 @@ early_param("mem", early_parse_mem);
unsigned int user_mode = HOME_SPACE_MODE; unsigned int user_mode = HOME_SPACE_MODE;
EXPORT_SYMBOL_GPL(user_mode); EXPORT_SYMBOL_GPL(user_mode);
static int set_amode_and_uaccess(unsigned long user_amode, static int set_amode_primary(void)
unsigned long user32_amode)
{ {
psw_user_bits = PSW_BASE_BITS | PSW_MASK_DAT | user_amode | psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME;
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY;
PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
psw_user32_bits = PSW_BASE32_BITS | PSW_MASK_DAT | user_amode | psw32_user_bits =
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY;
PSW_MASK_PSTATE | PSW_DEFAULT_KEY;
psw32_user_bits = PSW32_BASE_BITS | PSW32_MASK_DAT | user32_amode |
PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK |
PSW32_MASK_PSTATE;
#endif #endif
psw_kernel_bits = PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
PSW_MASK_MCHECK | PSW_DEFAULT_KEY;
if (MACHINE_HAS_MVCOS) { if (MACHINE_HAS_MVCOS) {
memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess)); memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess));
...@@ -329,7 +321,7 @@ early_param("user_mode", early_parse_user_mode); ...@@ -329,7 +321,7 @@ early_param("user_mode", early_parse_user_mode);
static void setup_addressing_mode(void) static void setup_addressing_mode(void)
{ {
if (user_mode == PRIMARY_SPACE_MODE) { if (user_mode == PRIMARY_SPACE_MODE) {
if (set_amode_and_uaccess(PSW_ASC_PRIMARY, PSW32_ASC_PRIMARY)) if (set_amode_primary())
pr_info("Address spaces switched, " pr_info("Address spaces switched, "
"mvcos available\n"); "mvcos available\n");
else else
...@@ -348,24 +340,25 @@ setup_lowcore(void) ...@@ -348,24 +340,25 @@ setup_lowcore(void)
*/ */
BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096); BUILD_BUG_ON(sizeof(struct _lowcore) != LC_PAGES * 4096);
lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0); lc = __alloc_bootmem_low(LC_PAGES * PAGE_SIZE, LC_PAGES * PAGE_SIZE, 0);
lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.mask = psw_kernel_bits;
lc->restart_psw.addr = lc->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler; PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
if (user_mode != HOME_SPACE_MODE) lc->external_new_psw.mask = psw_kernel_bits |
lc->restart_psw.mask |= PSW_ASC_HOME; PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->external_new_psw.mask = psw_kernel_bits;
lc->external_new_psw.addr = lc->external_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) ext_int_handler; PSW_ADDR_AMODE | (unsigned long) ext_int_handler;
lc->svc_new_psw.mask = psw_kernel_bits | PSW_MASK_IO | PSW_MASK_EXT; lc->svc_new_psw.mask = psw_kernel_bits |
PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call; lc->svc_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) system_call;
lc->program_new_psw.mask = psw_kernel_bits; lc->program_new_psw.mask = psw_kernel_bits |
PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->program_new_psw.addr = lc->program_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long)pgm_check_handler; PSW_ADDR_AMODE | (unsigned long) pgm_check_handler;
lc->mcck_new_psw.mask = lc->mcck_new_psw.mask = psw_kernel_bits;
psw_kernel_bits & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
lc->mcck_new_psw.addr = lc->mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) mcck_int_handler; PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
lc->io_new_psw.mask = psw_kernel_bits; lc->io_new_psw.mask = psw_kernel_bits |
PSW_MASK_DAT | PSW_MASK_MCHECK;
lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler; lc->io_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) io_int_handler;
lc->clock_comparator = -1ULL; lc->clock_comparator = -1ULL;
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE; lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
...@@ -554,7 +547,7 @@ static void __init setup_restart_psw(void) ...@@ -554,7 +547,7 @@ static void __init setup_restart_psw(void)
* Setup restart PSW for absolute zero lowcore. This is necesary * Setup restart PSW for absolute zero lowcore. This is necesary
* if PSW restart is done on an offline CPU that has lowcore zero * if PSW restart is done on an offline CPU that has lowcore zero
*/ */
psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; psw.mask = PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler; psw.addr = PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw)); copy_to_absolute_zero(&S390_lowcore.restart_psw, &psw, sizeof(psw));
} }
......
...@@ -117,7 +117,8 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs) ...@@ -117,7 +117,8 @@ static int save_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
/* Copy a 'clean' PSW mask to the user to avoid leaking /* Copy a 'clean' PSW mask to the user to avoid leaking
information about whether PER is currently on. */ information about whether PER is currently on. */
user_sregs.regs.psw.mask = PSW_MASK_MERGE(psw_user_bits, regs->psw.mask); user_sregs.regs.psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA |
(regs->psw.mask & PSW_MASK_USER);
user_sregs.regs.psw.addr = regs->psw.addr; user_sregs.regs.psw.addr = regs->psw.addr;
memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs)); memcpy(&user_sregs.regs.gprs, &regs->gprs, sizeof(sregs->regs.gprs));
memcpy(&user_sregs.regs.acrs, current->thread.acrs, memcpy(&user_sregs.regs.acrs, current->thread.acrs,
...@@ -144,8 +145,8 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) ...@@ -144,8 +145,8 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs)); err = __copy_from_user(&user_sregs, sregs, sizeof(_sigregs));
if (err) if (err)
return err; return err;
regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask, regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
user_sregs.regs.psw.mask); (user_sregs.regs.psw.mask & PSW_MASK_USER);
regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr; regs->psw.addr = PSW_ADDR_AMODE | user_sregs.regs.psw.addr;
memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs)); memcpy(&regs->gprs, &user_sregs.regs.gprs, sizeof(sregs->regs.gprs));
memcpy(&current->thread.acrs, &user_sregs.regs.acrs, memcpy(&current->thread.acrs, &user_sregs.regs.acrs,
......
...@@ -108,7 +108,7 @@ void smp_restart_with_online_cpu(void) ...@@ -108,7 +108,7 @@ void smp_restart_with_online_cpu(void)
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
if (stap() == __cpu_logical_map[cpu]) { if (stap() == __cpu_logical_map[cpu]) {
/* We are online: Enable DAT again and return */ /* We are online: Enable DAT again and return */
__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); __load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
return; return;
} }
} }
...@@ -130,14 +130,16 @@ void smp_switch_to_ipl_cpu(void (*func)(void *), void *data) ...@@ -130,14 +130,16 @@ void smp_switch_to_ipl_cpu(void (*func)(void *), void *data)
if (smp_processor_id() == 0) if (smp_processor_id() == 0)
func(data); func(data);
__load_psw_mask(PSW_BASE_BITS | PSW_DEFAULT_KEY); __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE |
PSW_MASK_EA | PSW_MASK_BA);
/* Disable lowcore protection */ /* Disable lowcore protection */
__ctl_clear_bit(0, 28); __ctl_clear_bit(0, 28);
current_lc = lowcore_ptr[smp_processor_id()]; current_lc = lowcore_ptr[smp_processor_id()];
lc = lowcore_ptr[0]; lc = lowcore_ptr[0];
if (!lc) if (!lc)
lc = current_lc; lc = current_lc;
lc->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lc->restart_psw.mask =
PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu; lc->restart_psw.addr = PSW_ADDR_AMODE | (unsigned long) smp_restart_cpu;
if (!cpu_online(0)) if (!cpu_online(0))
smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]); smp_switch_to_cpu(func, data, 0, stap(), __cpu_logical_map[0]);
...@@ -159,7 +161,7 @@ void smp_send_stop(void) ...@@ -159,7 +161,7 @@ void smp_send_stop(void)
int cpu, rc; int cpu, rc;
/* Disable all interrupts/machine checks */ /* Disable all interrupts/machine checks */
__load_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK); __load_psw_mask(psw_kernel_bits | PSW_MASK_DAT);
trace_hardirqs_off(); trace_hardirqs_off();
/* stop all processors */ /* stop all processors */
...@@ -501,7 +503,8 @@ int __cpuinit start_secondary(void *cpuvoid) ...@@ -501,7 +503,8 @@ int __cpuinit start_secondary(void *cpuvoid)
set_cpu_online(smp_processor_id(), true); set_cpu_online(smp_processor_id(), true);
ipi_call_unlock(); ipi_call_unlock();
__ctl_clear_bit(0, 28); /* Disable lowcore protection */ __ctl_clear_bit(0, 28); /* Disable lowcore protection */
S390_lowcore.restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; S390_lowcore.restart_psw.mask =
PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
S390_lowcore.restart_psw.addr = S390_lowcore.restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler; PSW_ADDR_AMODE | (unsigned long) psw_restart_int_handler;
__ctl_set_bit(0, 28); /* Enable lowcore protection */ __ctl_set_bit(0, 28); /* Enable lowcore protection */
...@@ -549,7 +552,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu) ...@@ -549,7 +552,8 @@ static int __cpuinit smp_alloc_lowcore(int cpu)
memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512); memset((char *)lowcore + 512, 0, sizeof(*lowcore) - 512);
lowcore->async_stack = async_stack + ASYNC_SIZE; lowcore->async_stack = async_stack + ASYNC_SIZE;
lowcore->panic_stack = panic_stack + PAGE_SIZE; lowcore->panic_stack = panic_stack + PAGE_SIZE;
lowcore->restart_psw.mask = PSW_BASE_BITS | PSW_DEFAULT_KEY; lowcore->restart_psw.mask =
PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA;
lowcore->restart_psw.addr = lowcore->restart_psw.addr =
PSW_ADDR_AMODE | (unsigned long) restart_int_handler; PSW_ADDR_AMODE | (unsigned long) restart_int_handler;
if (user_mode != HOME_SPACE_MODE) if (user_mode != HOME_SPACE_MODE)
......
...@@ -200,7 +200,7 @@ void show_registers(struct pt_regs *regs) ...@@ -200,7 +200,7 @@ void show_registers(struct pt_regs *regs)
mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC), mask_bits(regs, PSW_MASK_PSTATE), mask_bits(regs, PSW_MASK_ASC),
mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM)); mask_bits(regs, PSW_MASK_CC), mask_bits(regs, PSW_MASK_PM));
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
printk(" EA:%x", mask_bits(regs, PSW_BASE_BITS)); printk(" EA:%x", mask_bits(regs, PSW_MASK_EA | PSW_MASK_BA));
#endif #endif
printk("\n%s GPRS: " FOURLONG, mode, printk("\n%s GPRS: " FOURLONG, mode,
regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]); regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
......
...@@ -170,7 +170,8 @@ void __kprobes vtime_stop_cpu(void) ...@@ -170,7 +170,8 @@ void __kprobes vtime_stop_cpu(void)
psw_t psw; psw_t psw;
/* Wait for external, I/O or machine check interrupt. */ /* Wait for external, I/O or machine check interrupt. */
psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT; psw.mask = psw_kernel_bits | PSW_MASK_WAIT |
PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK;
idle->nohz_delay = 0; idle->nohz_delay = 0;
...@@ -183,7 +184,8 @@ void __kprobes vtime_stop_cpu(void) ...@@ -183,7 +184,8 @@ void __kprobes vtime_stop_cpu(void)
* set_cpu_timer(VTIMER_MAX_SLICE); * set_cpu_timer(VTIMER_MAX_SLICE);
* idle->idle_enter = get_clock(); * idle->idle_enter = get_clock();
* __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT | * __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
* PSW_MASK_IO | PSW_MASK_EXT); * PSW_MASK_DAT | PSW_MASK_IO |
* PSW_MASK_EXT | PSW_MASK_MCHECK);
* The difference is that the inline assembly makes sure that * The difference is that the inline assembly makes sure that
* the last three instruction are stpt, stck and lpsw in that * the last three instruction are stpt, stck and lpsw in that
* order. This is done to increase the precision. * order. This is done to increase the precision.
...@@ -216,7 +218,8 @@ void __kprobes vtime_stop_cpu(void) ...@@ -216,7 +218,8 @@ void __kprobes vtime_stop_cpu(void)
* vq->idle = get_cpu_timer(); * vq->idle = get_cpu_timer();
* idle->idle_enter = get_clock(); * idle->idle_enter = get_clock();
* __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT | * __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
* PSW_MASK_IO | PSW_MASK_EXT); * PSW_MASK_DAT | PSW_MASK_IO |
* PSW_MASK_EXT | PSW_MASK_MCHECK);
* The difference is that the inline assembly makes sure that * The difference is that the inline assembly makes sure that
* the last three instruction are stpt, stck and lpsw in that * the last three instruction are stpt, stck and lpsw in that
* order. This is done to increase the precision. * order. This is done to increase the precision.
......
...@@ -32,7 +32,8 @@ static void __udelay_disabled(unsigned long long usecs) ...@@ -32,7 +32,8 @@ static void __udelay_disabled(unsigned long long usecs)
u64 clock_saved; u64 clock_saved;
u64 end; u64 end;
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT; mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_WAIT |
PSW_MASK_EXT | PSW_MASK_MCHECK;
end = get_clock() + (usecs << 12); end = get_clock() + (usecs << 12);
clock_saved = local_tick_disable(); clock_saved = local_tick_disable();
__ctl_store(cr0_saved, 0, 0); __ctl_store(cr0_saved, 0, 0);
......
...@@ -454,7 +454,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) ...@@ -454,7 +454,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
struct pt_regs regs; struct pt_regs regs;
int access, fault; int access, fault;
regs.psw.mask = psw_kernel_bits; regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
if (!irqs_disabled()) if (!irqs_disabled())
regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
regs.psw.addr = (unsigned long) __builtin_return_address(0); regs.psw.addr = (unsigned long) __builtin_return_address(0);
......
...@@ -61,8 +61,8 @@ static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) ...@@ -61,8 +61,8 @@ static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb)
rc = sclp_service_call(cmd, sccb); rc = sclp_service_call(cmd, sccb);
if (rc) if (rc)
goto out; goto out;
__load_psw_mask(PSW_BASE_BITS | PSW_MASK_EXT | __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA |
PSW_MASK_WAIT | PSW_DEFAULT_KEY); PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT);
local_irq_disable(); local_irq_disable();
out: out:
/* Contents of the sccb might have changed. */ /* Contents of the sccb might have changed. */
......
...@@ -30,7 +30,8 @@ static void do_machine_quiesce(void) ...@@ -30,7 +30,8 @@ static void do_machine_quiesce(void)
psw_t quiesce_psw; psw_t quiesce_psw;
smp_send_stop(); smp_send_stop();
quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; quiesce_psw.mask =
PSW_MASK_BASE | PSW_MASK_EA | PSW_MASK_BA | PSW_MASK_WAIT;
quiesce_psw.addr = 0xfff; quiesce_psw.addr = 0xfff;
__load_psw(quiesce_psw); __load_psw(quiesce_psw);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment