Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 272069
b: refs/heads/master
c: b50511e
h: refs/heads/master
i:
  272067: fed6ba6
v: v3
  • Loading branch information
Martin Schwidefsky committed Oct 30, 2011
1 parent 2626069 commit a8a5413
Show file tree
Hide file tree
Showing 21 changed files with 110 additions and 126 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b6ef5bb3d93efb95ba855a628740375c2280a59e
refs/heads/master: b50511e41aa51a89b4176784a670582424bc7db6
13 changes: 6 additions & 7 deletions trunk/arch/s390/include/asm/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,27 @@
#define PSW32_MASK_IO 0x02000000UL
#define PSW32_MASK_EXT 0x01000000UL
#define PSW32_MASK_KEY 0x00F00000UL
#define PSW32_MASK_BASE 0x00080000UL /* Always one */
#define PSW32_MASK_MCHECK 0x00040000UL
#define PSW32_MASK_WAIT 0x00020000UL
#define PSW32_MASK_PSTATE 0x00010000UL
#define PSW32_MASK_ASC 0x0000C000UL
#define PSW32_MASK_CC 0x00003000UL
#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_BASE_BITS 0x00080000UL
#define PSW32_DEFAULT_KEY (((u32) PAGE_DEFAULT_ACC) << 20)

#define PSW32_ASC_PRIMARY 0x00000000UL
#define PSW32_ASC_ACCREG 0x00004000UL
#define PSW32_ASC_SECONDARY 0x00008000UL
#define PSW32_ASC_HOME 0x0000C000UL

#define PSW32_MASK_MERGE(CURRENT,NEW) \
(((CURRENT) & ~(PSW32_MASK_CC|PSW32_MASK_PM)) | \
((NEW) & (PSW32_MASK_CC|PSW32_MASK_PM)))

extern long psw32_user_bits;
extern u32 psw32_user_bits;

#define COMPAT_USER_HZ 100
#define COMPAT_UTS_MACHINE "s390\0\0\0\0"
Expand Down
30 changes: 10 additions & 20 deletions trunk/arch/s390/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,17 @@ struct stack_frame {
/*
* Do necessary setup to start up a new thread.
*/
#define start_thread(regs, new_psw, new_stackp) do { \
regs->psw.mask = psw_user_bits; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \
#define start_thread(regs, new_psw, new_stackp) do { \
regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \
} while (0)

#define start_thread31(regs, new_psw, new_stackp) do { \
regs->psw.mask = psw_user32_bits; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \
crst_table_downgrade(current->mm, 1UL << 31); \
#define start_thread31(regs, new_psw, new_stackp) do { \
regs->psw.mask = psw_user_bits | PSW_MASK_BA; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
regs->gprs[15] = new_stackp; \
crst_table_downgrade(current->mm, 1UL << 31); \
} while (0)

/* Forward declaration, a strange C thing */
Expand Down Expand Up @@ -233,25 +233,15 @@ static inline unsigned long __rewind_psw(psw_t psw, unsigned long ilc)
#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
*/

static inline void ATTRIB_NORET disabled_wait(unsigned long code)
{
unsigned long ctl_buf;
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;
/*
* Store status and then load disabled wait psw,
Expand Down
20 changes: 6 additions & 14 deletions trunk/arch/s390/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ typedef struct
#define PSW_MASK_IO 0x02000000UL
#define PSW_MASK_EXT 0x01000000UL
#define PSW_MASK_KEY 0x00F00000UL
#define PSW_MASK_BASE 0x00080000UL /* always one */
#define PSW_MASK_MCHECK 0x00040000UL
#define PSW_MASK_WAIT 0x00020000UL
#define PSW_MASK_PSTATE 0x00010000UL
Expand All @@ -239,10 +240,11 @@ typedef struct
#define PSW_MASK_EA 0x00000000UL
#define PSW_MASK_BA 0x00000000UL

#define PSW_MASK_USER 0x00003F00UL

#define PSW_ADDR_AMODE 0x80000000UL
#define PSW_ADDR_INSN 0x7FFFFFFFUL

#define PSW_BASE_BITS 0x00080000UL
#define PSW_DEFAULT_KEY (((unsigned long) PAGE_DEFAULT_ACC) << 20)

#define PSW_ASC_PRIMARY 0x00000000UL
Expand All @@ -256,6 +258,7 @@ typedef struct
#define PSW_MASK_DAT 0x0400000000000000UL
#define PSW_MASK_IO 0x0200000000000000UL
#define PSW_MASK_EXT 0x0100000000000000UL
#define PSW_MASK_BASE 0x0000000000000000UL
#define PSW_MASK_KEY 0x00F0000000000000UL
#define PSW_MASK_MCHECK 0x0004000000000000UL
#define PSW_MASK_WAIT 0x0002000000000000UL
Expand All @@ -266,11 +269,11 @@ typedef struct
#define PSW_MASK_EA 0x0000000100000000UL
#define PSW_MASK_BA 0x0000000080000000UL

#define PSW_MASK_USER 0x00003F0000000000UL

#define PSW_ADDR_AMODE 0x0000000000000000UL
#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_ASC_PRIMARY 0x0000000000000000UL
Expand All @@ -283,18 +286,7 @@ typedef struct
#ifdef __KERNEL__
extern long psw_kernel_bits;
extern long psw_user_bits;
#ifdef CONFIG_64BIT
extern long psw_user32_bits;
#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.
Expand Down
6 changes: 4 additions & 2 deletions trunk/arch/s390/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,10 @@ __set_psw_mask(unsigned long mask)
__load_psw_mask(mask | (arch_local_save_flags() & ~(-1UL >> 8)));
}

#define local_mcck_enable() __set_psw_mask(psw_kernel_bits)
#define local_mcck_disable() __set_psw_mask(psw_kernel_bits & ~PSW_MASK_MCHECK)
#define local_mcck_enable() \
__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

Expand Down
9 changes: 3 additions & 6 deletions trunk/arch/s390/kernel/compat_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,9 @@

#include "compat_linux.h"

long psw_user32_bits = (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK |
PSW_MASK_PSTATE | PSW_DEFAULT_KEY);
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);
u32 psw32_user_bits = PSW32_MASK_DAT | PSW32_MASK_IO | PSW32_MASK_EXT |
PSW32_DEFAULT_KEY | PSW32_MASK_BASE | PSW32_MASK_MCHECK |
PSW32_MASK_PSTATE | PSW32_ASC_HOME;

/* For this source file, we want overflow handling. */

Expand Down
10 changes: 5 additions & 5 deletions trunk/arch/s390/kernel/compat_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,9 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
_s390_regs_common32 regs32;
int err, i;

regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
(__u32)(regs->psw.mask >> 32));
regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
regs32.psw.mask = psw32_user_bits |
((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
regs32.psw.addr = PSW32_ADDR_AMODE | (__u32) regs->psw.addr;
for (i = 0; i < NUM_GPRS; i++)
regs32.gprs[i] = (__u32) regs->gprs[i];
save_access_regs(current->thread.acrs);
Expand All @@ -327,8 +327,8 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
if (err)
return err;
regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
(__u64)regs32.psw.mask << 32);
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32;
regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
for (i = 0; i < NUM_GPRS; i++)
regs->gprs[i] = (__u64) regs32.gprs[i];
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/s390/kernel/early.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ static noinline __init void setup_lowcore_early(void)
{
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;
S390_lowcore.external_new_psw = psw;
psw.addr = PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/s390/kernel/ipl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2033,12 +2033,12 @@ void s390_reset_system(void (*func)(void *), void *data)
__ctl_clear_bit(0,28);

/* 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 =
PSW_ADDR_AMODE | (unsigned long) s390_base_mcck_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 =
PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;

Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/s390/kernel/machine_kexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ static void __do_machine_kdump(void *image)
#ifdef CONFIG_CRASH_DUMP
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();
start_kdump(1);
#endif
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/s390/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
struct pt_regs 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.gprs[9] = (unsigned long) fn;
regs.gprs[10] = (unsigned long) arg;
Expand Down
36 changes: 18 additions & 18 deletions trunk/arch/s390/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
if (addr == (addr_t) &dummy->regs.psw.mask)
/* Remove per bit from user psw. */
tmp &= ~PSW_MASK_PER;
/* Return a clean psw mask. */
tmp = psw_user_bits | (tmp & PSW_MASK_USER) |
PSW_MASK_EA | PSW_MASK_BA;

} else if (addr < (addr_t) &dummy->regs.orig_gpr2) {
/*
Expand Down Expand Up @@ -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)
{
struct user *dummy = NULL;
addr_t offset;
addr_t offset, tmp;

if (addr < (addr_t) &dummy->regs.acrs) {
/*
* psw and gprs are stored on the stack
*/
tmp = (data & ~PSW_MASK_USER) ^ psw_user_bits;
if (addr == (addr_t) &dummy->regs.psw.mask &&
#ifdef CONFIG_COMPAT
data != PSW_MASK_MERGE(psw_user32_bits, data) &&
tmp != PSW_MASK_BA &&
#endif
data != PSW_MASK_MERGE(psw_user_bits, data))
tmp != (PSW_MASK_EA | PSW_MASK_BA))
/* Invalid psw mask. */
return -EINVAL;
#ifndef CONFIG_64BIT
Expand Down Expand Up @@ -505,21 +507,20 @@ static u32 __peek_user_compat(struct task_struct *child, addr_t addr)
__u32 tmp;

if (addr < (addr_t) &dummy32->regs.acrs) {
struct pt_regs *regs = task_pt_regs(child);
/*
* psw and gprs are stored on the stack
*/
if (addr == (addr_t) &dummy32->regs.psw.mask) {
/* Fake a 31 bit psw mask. */
tmp = (__u32)(task_pt_regs(child)->psw.mask >> 32);
tmp = PSW32_MASK_MERGE(psw32_user_bits, tmp);
tmp = (__u32)(regs->psw.mask >> 32);
tmp = psw32_user_bits | (tmp & PSW32_MASK_USER);
} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Fake a 31 bit psw address. */
tmp = (__u32) task_pt_regs(child)->psw.addr |
PSW32_ADDR_AMODE31;
tmp = (__u32) regs->psw.addr | PSW32_ADDR_AMODE;
} else {
/* gpr 0-15 */
tmp = *(__u32 *)((addr_t) &task_pt_regs(child)->psw +
addr*2 + 4);
tmp = *(__u32 *)((addr_t) &regs->psw + addr*2 + 4);
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
/*
Expand Down Expand Up @@ -604,29 +605,28 @@ static int __poke_user_compat(struct task_struct *child,
addr_t offset;

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
*/
if (addr == (addr_t) &dummy32->regs.psw.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. */
return -EINVAL;
task_pt_regs(child)->psw.mask =
PSW_MASK_MERGE(psw_user32_bits, (__u64) tmp << 32);
regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
(__u64)(tmp & PSW32_MASK_USER) << 32;
} else if (addr == (addr_t) &dummy32->regs.psw.addr) {
/* Build a 64 bit psw address from 31 bit address. */
task_pt_regs(child)->psw.addr =
(__u64) tmp & PSW32_ADDR_INSN;
regs->psw.addr = (__u64) tmp & PSW32_ADDR_INSN;
/*
* The debugger changed the instruction address,
* reset system call restart, see signal.c:do_signal
*/
task_thread_info(child)->system_call = 0;
} else {
/* gpr 0-15 */
*(__u32*)((addr_t) &task_pt_regs(child)->psw
+ addr*2 + 4) = tmp;
*(__u32*)((addr_t) &regs->psw + addr*2 + 4) = tmp;
}
} else if (addr < (addr_t) (&dummy32->regs.orig_gpr2)) {
/*
Expand Down
Loading

0 comments on commit a8a5413

Please sign in to comment.