Commit f90dc9f3 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390 update (19/27): ptrace cleanup.

Rewrite s390 ptrace code in a more readable and less buggy way. As a part of
this, all psw related definitions are moved into ptrace.h from a number of
different locations.
parent 91b9f2e4
......@@ -75,9 +75,10 @@ void default_idle(void)
/*
* Wait for external, I/O or machine check interrupt and
* switch of machine check bit after the wait has ended.
* switch off machine check bit after the wait has ended.
*/
wait_psw.mask = _WAIT_PSW_MASK;
wait_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK | PSW_MASK_WAIT |
PSW_MASK_IO | PSW_MASK_EXT;
asm volatile (
" basr %0,0\n"
"0: la %0,1f-0b(%0)\n"
......@@ -114,7 +115,7 @@ void show_regs(struct pt_regs *regs)
show_registers(regs);
/* Show stack backtrace if pt_regs is from kernel mode */
if (!(regs->psw.mask & PSW_PROBLEM_STATE))
if (!(regs->psw.mask & PSW_MASK_PSTATE))
show_trace((unsigned long *) regs->gprs[15]);
}
......@@ -135,8 +136,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
struct pt_regs regs;
memset(&regs, 0, sizeof(regs));
regs.psw.mask = _SVC_PSW_MASK;
regs.psw.addr = (__u32) kernel_thread_starter | _ADDR_31;
regs.psw.mask = PSW_KERNEL_BITS;
regs.psw.addr = (__u32) kernel_thread_starter | PSW_ADDR_AMODE31;
regs.gprs[7] = STACK_FRAME_OVERHEAD;
regs.gprs[8] = __LC_KERNEL_STACK;
regs.gprs[9] = (unsigned long) fn;
......
This diff is collapsed.
......@@ -304,7 +304,7 @@ void __init setup_arch(char **cmdline_p)
unsigned long start_pfn, end_pfn;
static unsigned int smptrap=0;
unsigned long delay = 0;
struct _lowcore *lowcore;
struct _lowcore *lc;
int i;
if (smptrap)
......@@ -451,27 +451,26 @@ void __init setup_arch(char **cmdline_p)
/*
* Setup lowcore for boot cpu
*/
lowcore = (struct _lowcore *)
__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
memset(lowcore, 0, PAGE_SIZE);
lowcore->restart_psw.mask = _RESTART_PSW_MASK;
lowcore->restart_psw.addr = _ADDR_31 + (addr_t) &restart_int_handler;
lowcore->external_new_psw.mask = _EXT_PSW_MASK;
lowcore->external_new_psw.addr = _ADDR_31 + (addr_t) &ext_int_handler;
lowcore->svc_new_psw.mask = _SVC_PSW_MASK;
lowcore->svc_new_psw.addr = _ADDR_31 + (addr_t) &system_call;
lowcore->program_new_psw.mask = _PGM_PSW_MASK;
lowcore->program_new_psw.addr = _ADDR_31 + (addr_t) &pgm_check_handler;
lowcore->mcck_new_psw.mask = _MCCK_PSW_MASK;
lowcore->mcck_new_psw.addr = _ADDR_31 + (addr_t) &mcck_int_handler;
lowcore->io_new_psw.mask = _IO_PSW_MASK;
lowcore->io_new_psw.addr = _ADDR_31 + (addr_t) &io_int_handler;
lowcore->ipl_device = S390_lowcore.ipl_device;
lowcore->kernel_stack = ((__u32) &init_thread_union) + 8192;
lowcore->async_stack = (__u32)
lc = (struct _lowcore *) __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
memset(lc, 0, PAGE_SIZE);
lc->restart_psw.mask = PSW_BASE_BITS;
lc->restart_psw.addr = PSW_ADDR_AMODE31 + (__u32) restart_int_handler;
lc->external_new_psw.mask = PSW_KERNEL_BITS;
lc->external_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) ext_int_handler;
lc->svc_new_psw.mask = PSW_KERNEL_BITS;
lc->svc_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) system_call;
lc->program_new_psw.mask = PSW_KERNEL_BITS;
lc->program_new_psw.addr = PSW_ADDR_AMODE31 + (__u32)pgm_check_handler;
lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
lc->mcck_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) mcck_int_handler;
lc->io_new_psw.mask = PSW_KERNEL_BITS;
lc->io_new_psw.addr = PSW_ADDR_AMODE31 + (__u32) io_int_handler;
lc->ipl_device = S390_lowcore.ipl_device;
lc->kernel_stack = ((__u32) &init_thread_union) + 8192;
lc->async_stack = (__u32)
__alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0) + 8192;
lowcore->jiffy_timer = -1LL;
set_prefix((__u32) lowcore);
lc->jiffy_timer = -1LL;
set_prefix((__u32) lc);
cpu_init();
__cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
......
......@@ -167,8 +167,8 @@ static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
int err;
err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
regs->psw.mask = _USER_PSW_MASK | (regs->psw.mask & PSW_MASK_DEBUGCHANGE);
regs->psw.addr |= _ADDR_31;
regs->psw.mask = PSW_USER_BITS | (regs->psw.mask & PSW_MASK_CC);
regs->psw.addr |= PSW_ADDR_AMODE31;
if (err)
return err;
......@@ -298,9 +298,9 @@ static void setup_frame(int sig, struct k_sigaction *ka,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
regs->gprs[14] = (__u32) ka->sa.sa_restorer | PSW_ADDR_AMODE31;
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
regs->gprs[14] = (__u32) frame->retcode | PSW_ADDR_AMODE31;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 *)(frame->retcode)))
goto give_sigsegv;
......@@ -311,12 +311,12 @@ static void setup_frame(int sig, struct k_sigaction *ka,
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
regs->psw.mask = _USER_PSW_MASK;
regs->gprs[15] = (__u32) frame;
regs->psw.addr = (__u32) ka->sa.sa_handler | PSW_ADDR_AMODE31;
regs->psw.mask = PSW_USER_BITS;
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->sc;
regs->gprs[3] = (__u32) &frame->sc;
/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */
......@@ -356,9 +356,9 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
regs->gprs[14] = (__u32) ka->sa.sa_restorer | PSW_ADDR_AMODE31;
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
regs->gprs[14] = (__u32) frame->retcode | PSW_ADDR_AMODE31;
err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 *)(frame->retcode));
}
......@@ -368,13 +368,13 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
regs->psw.mask = _USER_PSW_MASK;
regs->gprs[15] = (__u32) frame;
regs->psw.addr = (__u32) ka->sa.sa_handler | PSW_ADDR_AMODE31;
regs->psw.mask = PSW_USER_BITS;
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->info;
regs->gprs[4] = (addr_t)&frame->uc;
regs->gprs[3] = (__u32) &frame->info;
regs->gprs[4] = (__u32) &frame->uc;
return;
give_sigsegv:
......
......@@ -116,22 +116,22 @@ void show_trace(unsigned long * stack)
stack = (unsigned long*)&stack;
printk("Call Trace: ");
low_addr = ((unsigned long) stack) & PSW_ADDR_MASK;
low_addr = ((unsigned long) stack) & PSW_ADDR_INSN;
high_addr = (low_addr & (-THREAD_SIZE)) + THREAD_SIZE;
/* Skip the first frame (biased stack) */
backchain = *((unsigned long *) low_addr) & PSW_ADDR_MASK;
backchain = *((unsigned long *) low_addr) & PSW_ADDR_INSN;
/* Print up to 8 lines */
for (i = 0; i < 8; i++) {
if (backchain < low_addr || backchain >= high_addr)
break;
ret_addr = *((unsigned long *) (backchain+56)) & PSW_ADDR_MASK;
ret_addr = *((unsigned long *) (backchain+56)) & PSW_ADDR_INSN;
if (!kernel_text_address(ret_addr))
break;
if (i && ((i % 6) == 0))
printk("\n ");
printk("[<%08lx>] ", ret_addr);
low_addr = backchain;
backchain = *((unsigned long *) backchain) & PSW_ADDR_MASK;
backchain = *((unsigned long *) backchain) & PSW_ADDR_INSN;
}
printk("\n");
}
......@@ -184,7 +184,7 @@ void show_registers(struct pt_regs *regs)
char *mode;
int i;
mode = (regs->psw.mask & PSW_PROBLEM_STATE) ? "User" : "Krnl";
mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
printk("%s PSW : %08lx %08lx\n",
mode, (unsigned long) regs->psw.mask,
(unsigned long) regs->psw.addr);
......@@ -210,7 +210,7 @@ void show_registers(struct pt_regs *regs)
* time of the fault.
*/
old_fs = get_fs();
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
set_fs(USER_DS);
else
set_fs(KERNEL_DS);
......@@ -287,10 +287,10 @@ static void inline do_trap(long interruption_code, int signr, char *str,
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
if (regs->psw.mask & PSW_PROBLEM_STATE) {
if (regs->psw.mask & PSW_MASK_PSTATE) {
struct task_struct *tsk = current;
tsk->thread.trap_no = interruption_code & 0xffff;
......@@ -322,12 +322,12 @@ static void inline do_trap(long interruption_code, int signr, char *str,
static inline void *get_check_address(struct pt_regs *regs)
{
return (void *) ADDR_BITS_REMOVE(regs->psw.addr-S390_lowcore.pgm_ilc);
return (void *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN);
}
int do_debugger_trap(struct pt_regs *regs,int signal)
{
if(regs->psw.mask&PSW_PROBLEM_STATE)
if(regs->psw.mask&PSW_MASK_PSTATE)
{
if(current->ptrace & PT_PTRACED)
force_sig(signal,current);
......@@ -423,10 +423,10 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
get_user(*((__u16 *) opcode), location);
else
*((__u16 *)opcode)=*((__u16 *)location);
......@@ -436,7 +436,7 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
signal = SIGILL;
}
#ifdef CONFIG_MATHEMU
else if (regs->psw.mask & PSW_PROBLEM_STATE)
else if (regs->psw.mask & PSW_MASK_PSTATE)
{
if (opcode[0] == 0xb3) {
get_user(*((__u16 *) (opcode+2)), location+1);
......@@ -484,10 +484,10 @@ specification_exception(struct pt_regs * regs, long interruption_code)
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
if (regs->psw.mask & PSW_PROBLEM_STATE) {
if (regs->psw.mask & PSW_MASK_PSTATE) {
get_user(*((__u16 *) opcode), location);
switch (opcode[0]) {
case 0x28: /* LDR Rx,Ry */
......@@ -547,7 +547,7 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
if (MACHINE_HAS_IEEE)
......@@ -555,7 +555,7 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
: "=m" (current->thread.fp_regs.fpc));
#ifdef CONFIG_MATHEMU
else if (regs->psw.mask & PSW_PROBLEM_STATE) {
else if (regs->psw.mask & PSW_MASK_PSTATE) {
__u8 opcode[6];
get_user(*((__u16 *) opcode), location);
switch (opcode[0]) {
......@@ -679,21 +679,19 @@ void __init trap_init(void)
void handle_per_exception(struct pt_regs *regs)
{
if(regs->psw.mask&PSW_PROBLEM_STATE)
{
if (regs->psw.mask & PSW_MASK_PSTATE) {
per_struct *per_info=&current->thread.per_info;
per_info->lowcore.words.perc_atmid=S390_lowcore.per_perc_atmid;
per_info->lowcore.words.address=S390_lowcore.per_address;
per_info->lowcore.words.access_id=S390_lowcore.per_access_id;
}
if(do_debugger_trap(regs,SIGTRAP))
{
if (do_debugger_trap(regs,SIGTRAP)) {
/* I've seen this possibly a task structure being reused ? */
printk("Spurious per exception detected\n");
printk("switching off per tracing for this task.\n");
show_regs(regs);
/* Hopefully switching off per tracing will help us survive */
regs->psw.mask &= ~PSW_PER_MASK;
regs->psw.mask &= ~PSW_MASK_PER;
}
}
......@@ -48,7 +48,7 @@ search_exception_table(unsigned long addr)
addr &= 0x7fffffff; /* remove amode bit from address */
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
if (ret) ret = FIX_PSW(ret);
if (ret) ret = ret | PSW_ADDR_AMODE31;
return ret;
#else
unsigned long flags;
......@@ -63,7 +63,7 @@ search_exception_table(unsigned long addr)
ret = search_one_table(mp->ex_table_start,
mp->ex_table_end - 1, addr);
if (ret) {
ret = FIX_PSW(ret);
ret = ret | PSW_ADDR_AMODE31;
break;
}
}
......
......@@ -166,7 +166,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
/* Low-address protection hit in kernel mode means
NULL pointer write access in kernel mode. */
if (!(regs->psw.mask & PSW_PROBLEM_STATE)) {
if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
address = 0;
user_address = 0;
goto no_context;
......@@ -258,7 +258,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
up_read(&mm->mmap_sem);
/* User mode accesses just cause a SIGSEGV */
if (regs->psw.mask & PSW_PROBLEM_STATE) {
if (regs->psw.mask & PSW_MASK_PSTATE) {
tsk->thread.prot_addr = address;
tsk->thread.trap_no = error_code;
force_sigsegv(regs, error_code, si_code, address);
......@@ -298,7 +298,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
do_exit(SIGKILL);
goto no_context;
......@@ -314,7 +314,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
force_sig(SIGBUS, tsk);
/* Kernel mode? Handle exceptions or die */
if (!(regs->psw.mask & PSW_PROBLEM_STATE))
if (!(regs->psw.mask & PSW_MASK_PSTATE))
goto no_context;
}
......@@ -393,7 +393,7 @@ do_pseudo_page_fault(struct pt_regs *regs, unsigned long error_code)
spin_unlock(&pseudo_wait_spinlock);
} else {
/* Pseudo page faults in kernel mode is a bad idea */
if (!(regs->psw.mask & PSW_PROBLEM_STATE)) {
if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
/*
* VM presents pseudo page faults if the interrupted
* state was not disabled for interrupts. So we can
......@@ -528,7 +528,7 @@ pfault_interrupt(struct pt_regs *regs, __u16 error_code)
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
if (subcode & 0x0080) {
......
......@@ -8,8 +8,6 @@
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/export.h>
#ifdef CONFIG_S390_SUPPORT
/* Macro that masks the high order bit of an 32 bit pointer and converts it*/
/* to a 64 bit pointer */
#define A(__x) ((unsigned long)((__x) & 0x7FFFFFFFUL))
......@@ -194,6 +192,32 @@ typedef struct
__u32 addr;
} _psw_t32 __attribute__ ((aligned(8)));
#define PSW32_MASK_PER 0x40000000UL
#define PSW32_MASK_DAT 0x04000000UL
#define PSW32_MASK_IO 0x02000000UL
#define PSW32_MASK_EXT 0x01000000UL
#define PSW32_MASK_KEY 0x00F00000UL
#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_ADDR_INSN 0x7FFFFFFFUL
#define PSW32_BASE_BITS 0x00080000UL
#define PSW32_ASC_PRIMARY 0x00000000UL
#define PSW32_ASC_ACCREG 0x00004000UL
#define PSW32_ASC_SECONDARY 0x00008000UL
#define PSW32_ASC_HOME 0x0000C000UL
#define PSW32_USER_BITS (PSW32_BASE_BITS | PSW32_MASK_DAT | PSW32_ASC_HOME | \
PSW32_MASK_IO | PSW32_MASK_EXT | PSW32_MASK_MCHECK | \
PSW32_MASK_PSTATE)
typedef struct
{
_psw_t32 psw;
......@@ -241,6 +265,4 @@ struct ucontext32 {
sigset_t32 uc_sigmask; /* mask last for extensibility */
};
#endif /* !CONFIG_S390_SUPPORT */
#endif /* _ASM_S390X_S390_H */
......@@ -75,9 +75,10 @@ void default_idle(void)
/*
* Wait for external, I/O or machine check interrupt and
* switch of machine check bit after the wait has ended.
* switch off machine check bit after the wait has ended.
*/
wait_psw.mask = _WAIT_PSW_MASK;
wait_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK | PSW_MASK_WAIT |
PSW_MASK_IO | PSW_MASK_EXT;
asm volatile (
" larl %0,0f\n"
" stg %0,8(%1)\n"
......@@ -111,7 +112,7 @@ void show_regs(struct pt_regs *regs)
show_registers(regs);
/* Show stack backtrace if pt_regs is from kernel mode */
if (!(regs->psw.mask & PSW_PROBLEM_STATE))
if (!(regs->psw.mask & PSW_MASK_PSTATE))
show_trace((unsigned long *) regs->gprs[15]);
}
......@@ -132,7 +133,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
struct pt_regs regs;
memset(&regs, 0, sizeof(regs));
regs.psw.mask = _SVC_PSW_MASK;
regs.psw.mask = PSW_KERNEL_BITS;
regs.psw.addr = (__u64) kernel_thread_starter;
regs.gprs[7] = STACK_FRAME_OVERHEAD;
regs.gprs[8] = __LC_KERNEL_STACK;
......
This diff is collapsed.
#ifndef _PTRACE32_H
#define _PTRACE32_H
#include "linux32.h" /* needed for _psw_t32 */
typedef struct
{
__u32 cr[3];
} per_cr_words32 __attribute__((packed));
typedef struct
{
__u16 perc_atmid; /* 0x096 */
__u32 address; /* 0x098 */
__u8 access_id; /* 0x0a1 */
} per_lowcore_words32 __attribute__((packed));
typedef struct
{
union {
per_cr_words32 words;
} control_regs __attribute__((packed));
/*
* Use these flags instead of setting em_instruction_fetch
* directly they are used so that single stepping can be
* switched on & off while not affecting other tracing
*/
unsigned single_step : 1;
unsigned instruction_fetch : 1;
unsigned : 30;
/*
* These addresses are copied into cr10 & cr11 if single
* stepping is switched off
*/
__u32 starting_addr;
__u32 ending_addr;
union {
per_lowcore_words32 words;
} lowcore;
} per_struct32 __attribute__((packed));
struct user_regs_struct32
{
_psw_t32 psw;
u32 gprs[NUM_GPRS];
u32 acrs[NUM_ACRS];
u32 orig_gpr2;
s390_fp_regs fp_regs;
/*
* These per registers are in here so that gdb can modify them
* itself as there is no "official" ptrace interface for hardware
* watchpoints. This is the way intel does it.
*/
per_struct32 per_info;
u32 ieee_instruction_pointer;
/* Used to give failing instruction back to user for ieee exceptions */
};
struct user32 {
/* We start with the registers, to mimic the way that "memory"
is returned from the ptrace(3,...) function. */
struct user_regs_struct32 regs; /* Where the registers are actually stored */
/* The rest of this junk is to help gdb figure out what goes where */
u32 u_tsize; /* Text segment size (pages). */
u32 u_dsize; /* Data segment size (pages). */
u32 u_ssize; /* Stack segment size (pages). */
u32 start_code; /* Starting virtual address of text. */
u32 start_stack; /* Starting virtual address of stack area.
This is actually the bottom of the stack,
the top of the stack is always found in the
esp register. */
s32 signal; /* Signal that caused the core dump. */
u32 u_ar0; /* Used by gdb to help find the values for */
/* the registers. */
u32 magic; /* To uniquely identify a core file */
char u_comm[32]; /* User command that was responsible */
};
typedef struct
{
__u32 len;
__u32 kernel_addr;
__u32 process_addr;
} ptrace_area_emu31;
#endif /* _PTRACE32_H */
......@@ -304,7 +304,7 @@ void __init setup_arch(char **cmdline_p)
unsigned long start_pfn, end_pfn;
static unsigned int smptrap=0;
unsigned long delay = 0;
struct _lowcore *lowcore;
struct _lowcore *lc;
int i;
if (smptrap)
......@@ -441,27 +441,30 @@ void __init setup_arch(char **cmdline_p)
/*
* Setup lowcore for boot cpu
*/
lowcore = (struct _lowcore *)
__alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0);
memset(lowcore, 0, 2*PAGE_SIZE);
lowcore->restart_psw.mask = _RESTART_PSW_MASK;
lowcore->restart_psw.addr = (addr_t) &restart_int_handler;
lowcore->external_new_psw.mask = _EXT_PSW_MASK;
lowcore->external_new_psw.addr = (addr_t) &ext_int_handler;
lowcore->svc_new_psw.mask = _SVC_PSW_MASK;
lowcore->svc_new_psw.addr = (addr_t) &system_call;
lowcore->program_new_psw.mask = _PGM_PSW_MASK;
lowcore->program_new_psw.addr = (addr_t) &pgm_check_handler;
lowcore->mcck_new_psw.mask = _MCCK_PSW_MASK;
lowcore->mcck_new_psw.addr = (addr_t) &mcck_int_handler;
lowcore->io_new_psw.mask = _IO_PSW_MASK;
lowcore->io_new_psw.addr = (addr_t) &io_int_handler;
lowcore->ipl_device = S390_lowcore.ipl_device;
lowcore->kernel_stack = ((__u64) &init_thread_union) + 16384;
lowcore->async_stack = (__u64)
lc = (struct _lowcore *) __alloc_bootmem(2*PAGE_SIZE, 2*PAGE_SIZE, 0);
memset(lc, 0, 2*PAGE_SIZE);
lc->restart_psw.mask = PSW_BASE_BITS;
lc->restart_psw.addr = (addr_t) &restart_int_handler;
lc->external_new_psw.mask = PSW_KERNEL_BITS;
lc->external_new_psw.addr = (addr_t) &ext_int_handler;
lc->svc_new_psw.mask = PSW_KERNEL_BITS;
lc->svc_new_psw.addr = (addr_t) &system_call;
lc->program_new_psw.mask = PSW_KERNEL_BITS;
lc->program_new_psw.addr = (addr_t) &pgm_check_handler;
lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
lc->mcck_new_psw.addr = (addr_t) &mcck_int_handler;
lc->io_new_psw.mask = PSW_KERNEL_BITS;
lc->io_new_psw.addr = (addr_t) &io_int_handler;
lc->ipl_device = S390_lowcore.ipl_device;
lc->kernel_stack = ((__u64) &init_thread_union) + 16384;
lc->async_stack = (__u64)
__alloc_bootmem(4*PAGE_SIZE, 4*PAGE_SIZE, 0) + 16384;
lowcore->jiffy_timer = -1LL;
set_prefix((__u32)(__u64) lowcore);
lc->jiffy_timer = -1LL;
if (MACHINE_HAS_DIAG44)
lc->diag44_opcode = 0x83000044;
else
lc->diag44_opcode = 0x07000700;
set_prefix((__u32)(__u64) lc);
cpu_init();
__cpu_logical_map[0] = S390_lowcore.cpu_data.cpu_addr;
......
......@@ -162,7 +162,7 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs *sregs)
int err;
err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common));
regs->psw.mask = _USER_PSW_MASK | (regs->psw.mask & PSW_MASK_DEBUGCHANGE);
regs->psw.mask = PSW_USER_BITS | (regs->psw.mask & PSW_MASK_CC);
if (err)
return err;
......@@ -292,9 +292,9 @@ static void setup_frame(int sig, struct k_sigaction *ka,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
regs->gprs[14] = (__u64) ka->sa.sa_restorer;
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
regs->gprs[14] = (__u64) frame->retcode;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 *)(frame->retcode)))
goto give_sigsegv;
......@@ -305,12 +305,12 @@ static void setup_frame(int sig, struct k_sigaction *ka,
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
regs->psw.mask = _USER_PSW_MASK;
regs->gprs[15] = (__u64) frame;
regs->psw.addr = (__u64) ka->sa.sa_handler;
regs->psw.mask = PSW_USER_BITS;
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->sc;
regs->gprs[3] = (__u64) &frame->sc;
/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */
......@@ -350,9 +350,9 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
regs->gprs[14] = (__u64) ka->sa.sa_restorer;
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
regs->gprs[14] = (__u64) frame->retcode;
err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 *)(frame->retcode));
}
......@@ -362,13 +362,13 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
regs->psw.mask = _USER_PSW_MASK;
regs->gprs[15] = (__u64) frame;
regs->psw.addr = (__u64) ka->sa.sa_handler;
regs->psw.mask = PSW_USER_BITS;
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->info;
regs->gprs[4] = (addr_t)&frame->uc;
regs->gprs[3] = (__u64) &frame->info;
regs->gprs[4] = (__u64) &frame->uc;
return;
give_sigsegv:
......
......@@ -29,15 +29,10 @@
#include <asm/ucontext.h>
#include <asm/uaccess.h>
#include "linux32.h"
#include "ptrace32.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define _ADDR_31 0x80000000
#define _USER_PSW_MASK_EMU32 0x070DC000
#define _USER_PSW_MASK32 0x0705C00080000000
#define PSW_MASK_DEBUGCHANGE32 0x00003000UL
#define PSW_ADDR_DEBUGCHANGE32 0x7FFFFFFFUL
typedef struct
{
__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
......@@ -297,9 +292,9 @@ static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
_s390_regs_common32 regs32;
int err, i;
regs32.psw.mask = _USER_PSW_MASK_EMU32 |
(__u32)((regs->psw.mask & PSW_MASK_DEBUGCHANGE) >> 32);
regs32.psw.addr = _ADDR_31 | (__u32) regs->psw.addr;
regs32.psw.mask = PSW32_USER_BITS |
((__u32)(regs->psw.mask >> 32) & PSW32_MASK_CC);
regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
for (i = 0; i < NUM_GPRS; i++)
regs32.gprs[i] = (__u32) regs->gprs[i];
memcpy(regs32.acrs, regs->acrs, sizeof(regs32.acrs));
......@@ -320,9 +315,9 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
if (err)
return err;
regs->psw.mask = _USER_PSW_MASK32 |
(__u64)(regs32.psw.mask & PSW_MASK_DEBUGCHANGE32) << 32;
regs->psw.addr = (__u64)(regs32.psw.addr & PSW_ADDR_DEBUGCHANGE32);
regs->psw.mask = PSW_USER32_BITS |
(__u64)(regs32.psw.mask & PSW32_MASK_CC) << 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];
memcpy(regs->acrs, regs32.acrs, sizeof(regs32.acrs));
......@@ -467,9 +462,9 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
regs->gprs[14] = (__u64) ka->sa.sa_restorer;
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
regs->gprs[14] = (__u64) frame->retcode;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 *)(frame->retcode)))
goto give_sigsegv;
......@@ -480,12 +475,12 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
regs->psw.mask = _USER_PSW_MASK32;
regs->gprs[15] = (__u64) frame;
regs->psw.addr = (__u64) ka->sa.sa_handler;
regs->psw.mask = PSW_USER32_BITS;
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->sc;
regs->gprs[3] = (__u64) &frame->sc;
/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility, they are passed as args. */
......@@ -525,9 +520,9 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
regs->gprs[14] = (__u64) ka->sa.sa_restorer;
} else {
regs->gprs[14] = FIX_PSW(frame->retcode);
regs->gprs[14] = (__u64) frame->retcode;
err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 *)(frame->retcode));
}
......@@ -537,13 +532,13 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Set up registers for signal handler */
regs->gprs[15] = (addr_t)frame;
regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
regs->psw.mask = _USER_PSW_MASK32;
regs->gprs[15] = (__u64) frame;
regs->psw.addr = (__u64) ka->sa.sa_handler;
regs->psw.mask = PSW_USER32_BITS;
regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (addr_t)&frame->info;
regs->gprs[4] = (addr_t)&frame->uc;
regs->gprs[3] = (__u64) &frame->info;
regs->gprs[4] = (__u64) &frame->uc;
return;
give_sigsegv:
......
......@@ -118,22 +118,22 @@ void show_trace(unsigned long * stack)
stack = (unsigned long*)&stack;
printk("Call Trace: ");
low_addr = ((unsigned long) stack) & PSW_ADDR_MASK;
low_addr = (unsigned long) stack;
high_addr = (low_addr & (-THREAD_SIZE)) + THREAD_SIZE;
/* Skip the first frame (biased stack) */
backchain = *((unsigned long *) low_addr) & PSW_ADDR_MASK;
backchain = *(unsigned long *) low_addr;
/* Print up to 8 lines */
for (i = 0; i < 8; i++) {
if (backchain < low_addr || backchain >= high_addr)
break;
ret_addr = *((unsigned long *) (backchain+112)) & PSW_ADDR_MASK;
ret_addr = *(unsigned long *) (backchain+112);
if (!kernel_text_address(ret_addr))
break;
if (i && ((i % 3) == 0))
printk("\n ");
printk("[<%016lx>] ", ret_addr);
low_addr = backchain;
backchain = *((unsigned long *) backchain) & PSW_ADDR_MASK;
backchain = *(unsigned long *) backchain;
}
printk("\n");
}
......@@ -186,7 +186,7 @@ void show_registers(struct pt_regs *regs)
char *mode;
int i;
mode = (regs->psw.mask & PSW_PROBLEM_STATE) ? "User" : "Krnl";
mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
printk("%s PSW : %016lx %016lx\n",
mode, (unsigned long) regs->psw.mask,
(unsigned long) regs->psw.addr);
......@@ -212,7 +212,7 @@ void show_registers(struct pt_regs *regs)
* time of the fault.
*/
old_fs = get_fs();
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
set_fs(USER_DS);
else
set_fs(KERNEL_DS);
......@@ -289,10 +289,10 @@ static void inline do_trap(long interruption_code, int signr, char *str,
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
if (regs->psw.mask & PSW_PROBLEM_STATE) {
if (regs->psw.mask & PSW_MASK_PSTATE) {
struct task_struct *tsk = current;
tsk->thread.trap_no = interruption_code & 0xffff;
if (info)
......@@ -323,12 +323,12 @@ static void inline do_trap(long interruption_code, int signr, char *str,
static inline void *get_check_address(struct pt_regs *regs)
{
return (void *) ADDR_BITS_REMOVE(regs->psw.addr-S390_lowcore.pgm_ilc);
return (void *)(regs->psw.addr - S390_lowcore.pgm_ilc);
}
int do_debugger_trap(struct pt_regs *regs,int signal)
{
if(regs->psw.mask&PSW_PROBLEM_STATE)
if(regs->psw.mask&PSW_MASK_PSTATE)
{
if(current->ptrace & PT_PTRACED)
force_sig(signal,current);
......@@ -426,14 +426,14 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
/* WARNING don't change this check back to */
/* int problem_state=(regs->psw.mask & PSW_PROBLEM_STATE); */
/* int problem_state=(regs->psw.mask & PSW_MASK_PSTATE); */
/* & then doing if(problem_state) an int is too small for this */
/* check on 64 bit. */
if(regs->psw.mask & PSW_PROBLEM_STATE)
if(regs->psw.mask & PSW_MASK_PSTATE)
get_user(*((__u16 *) opcode), location);
else
*((__u16 *)opcode)=*((__u16 *)location);
......@@ -459,7 +459,7 @@ asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
__asm__ volatile ("stfpc %0\n\t"
......@@ -527,21 +527,19 @@ void __init trap_init(void)
void handle_per_exception(struct pt_regs *regs)
{
if(regs->psw.mask&PSW_PROBLEM_STATE)
{
if (regs->psw.mask&PSW_MASK_PSTATE) {
per_struct *per_info=&current->thread.per_info;
per_info->lowcore.words.perc_atmid=S390_lowcore.per_perc_atmid;
per_info->lowcore.words.address=S390_lowcore.per_address;
per_info->lowcore.words.access_id=S390_lowcore.per_access_id;
}
if(do_debugger_trap(regs,SIGTRAP))
{
if (do_debugger_trap(regs,SIGTRAP)) {
/* I've seen this possibly a task structure being reused ? */
printk("Spurious per exception detected\n");
printk("switching off per tracing for this task.\n");
show_regs(regs);
/* Hopefully switching off per tracing will help us survive */
regs->psw.mask &= ~PSW_PER_MASK;
regs->psw.mask &= ~PSW_MASK_PER;
}
}
......@@ -166,7 +166,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
/* Low-address protection hit in kernel mode means
NULL pointer write access in kernel mode. */
if (!(regs->psw.mask & PSW_PROBLEM_STATE)) {
if (!(regs->psw.mask & PSW_MASK_PSTATE)) {
address = 0;
user_address = 0;
goto no_context;
......@@ -258,7 +258,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
up_read(&mm->mmap_sem);
/* User mode accesses just cause a SIGSEGV */
if (regs->psw.mask & PSW_PROBLEM_STATE) {
if (regs->psw.mask & PSW_MASK_PSTATE) {
tsk->thread.prot_addr = address;
tsk->thread.trap_no = error_code;
force_sigsegv(regs, error_code, si_code, address);
......@@ -298,7 +298,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
goto survive;
}
printk("VM: killing process %s\n", tsk->comm);
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
do_exit(SIGKILL);
goto no_context;
......@@ -314,7 +314,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
force_sig(SIGBUS, tsk);
/* Kernel mode? Handle exceptions or die */
if (!(regs->psw.mask & PSW_PROBLEM_STATE))
if (!(regs->psw.mask & PSW_MASK_PSTATE))
goto no_context;
}
......@@ -440,7 +440,7 @@ pfault_interrupt(struct pt_regs *regs, __u16 error_code)
* We got all needed information from the lowcore and can
* now safely switch on interrupts.
*/
if (regs->psw.mask & PSW_PROBLEM_STATE)
if (regs->psw.mask & PSW_MASK_PSTATE)
local_irq_enable();
if (subcode & 0x0080) {
......
......@@ -98,7 +98,6 @@ static inline int
s390_do_sync_wait(int irq, int do_tpi)
{
unsigned long psw_mask;
int ccode;
uint64_t time_start;
uint64_t time_curr;
......@@ -116,31 +115,7 @@ s390_do_sync_wait(int irq, int do_tpi)
* sync. interrupt arrived we reset the I/O old PSW to
* its original value.
*/
ccode = iac ();
switch (ccode) {
case 0: /* primary-space */
psw_mask = _IO_PSW_MASK
| _PSW_PRIM_SPACE_MODE | _PSW_IO_WAIT;
break;
case 1: /* secondary-space */
psw_mask = _IO_PSW_MASK
| _PSW_SEC_SPACE_MODE | _PSW_IO_WAIT;
break;
case 2: /* access-register */
psw_mask = _IO_PSW_MASK
| _PSW_ACC_REG_MODE | _PSW_IO_WAIT;
break;
case 3: /* home-space */
psw_mask = _IO_PSW_MASK
| _PSW_HOME_SPACE_MODE | _PSW_IO_WAIT;
break;
default:
panic ("start_IO() : unexpected "
"address-space-control %d\n", ccode);
break;
}
psw_mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_WAIT;
/*
* Martin didn't like modifying the new PSW, now we take
......@@ -201,7 +176,6 @@ s390_do_sync_wait_haltclear(int irq, int halt)
int io_sub;
__u32 io_parm;
unsigned long psw_mask;
int ccode;
int ready = 0;
......@@ -212,32 +186,7 @@ s390_do_sync_wait_haltclear(int irq, int halt)
* FIXME: Are there case where we can't rely on an interrupt
* to occurr? Need to check...
*/
ccode = iac ();
switch (ccode) {
case 0: /* primary-space */
psw_mask = _IO_PSW_MASK
| _PSW_PRIM_SPACE_MODE | _PSW_IO_WAIT;
break;
case 1: /* secondary-space */
psw_mask = _IO_PSW_MASK
| _PSW_SEC_SPACE_MODE | _PSW_IO_WAIT;
break;
case 2: /* access-register */
psw_mask = _IO_PSW_MASK
| _PSW_ACC_REG_MODE | _PSW_IO_WAIT;
break;
case 3: /* home-space */
psw_mask = _IO_PSW_MASK
| _PSW_HOME_SPACE_MODE | _PSW_IO_WAIT;
break;
default: /* FIXME: isn't ccode only 2 bits anyway? */
panic (halt?"halt":"clear"
"_IO() : unexpected address-space-control %d\n",
ccode);
break;
}
psw_mask = PSW_KERNEL_BITS | PSW_MASK_IO | PSW_MASK_WAIT;
/*
* Martin didn't like modifying the new PSW, now we take
......@@ -960,7 +909,7 @@ do_IRQ (struct pt_regs regs)
* entry condition to synchronous I/O.
*/
if (*(__u32 *) __LC_SYNC_IO_WORD) {
regs.psw.mask &= ~(_PSW_WAIT_MASK_BIT | _PSW_IO_MASK_BIT);
regs.psw.mask &= ~(PSW_MASK_WAIT | PSW_MASK_IO);
return;
}
/* endif */
......
......@@ -52,41 +52,12 @@
#define __LC_PFAULT_INTPARM 0x080
/* interrupt handler start with all io, external and mcck interrupt disabled */
#define _RESTART_PSW_MASK 0x00080000
#define _EXT_PSW_MASK 0x04080000
#define _PGM_PSW_MASK 0x04080000
#define _SVC_PSW_MASK 0x04080000
#define _MCCK_PSW_MASK 0x04080000
#define _IO_PSW_MASK 0x04080000
#define _USER_PSW_MASK 0x070DC000/* DAT, IO, EXT, Home-space */
#define _WAIT_PSW_MASK 0x070E0000/* DAT, IO, EXT, Wait, Home-space */
#define _DW_PSW_MASK 0x000A0000/* disabled wait PSW mask */
#define _PRIMARY_MASK 0x0000 /* MASK for SACF */
#define _SECONDARY_MASK 0x0100 /* MASK for SACF */
#define _ACCESS_MASK 0x0200 /* MASK for SACF */
#define _HOME_MASK 0x0300 /* MASK for SACF */
#define _PSW_PRIM_SPACE_MODE 0x00000000
#define _PSW_SEC_SPACE_MODE 0x00008000
#define _PSW_ACC_REG_MODE 0x00004000
#define _PSW_HOME_SPACE_MODE 0x0000C000
#define _PSW_WAIT_MASK_BIT 0x00020000 /* Wait bit */
#define _PSW_IO_MASK_BIT 0x02000000 /* IO bit */
#define _PSW_IO_WAIT 0x02020000 /* IO & Wait bit */
/* we run in 31 Bit mode */
#define _ADDR_31 0x80000000
#ifndef __ASSEMBLY__
#include <linux/config.h>
#include <asm/processor.h>
#include <linux/types.h>
#include <asm/atomic.h>
#include <asm/processor.h>
#include <asm/sigp.h>
void restart_int_handler(void);
......
......@@ -101,8 +101,8 @@ typedef struct thread_struct thread_struct;
/* need to define ... */
#define start_thread(regs, new_psw, new_stackp) do { \
regs->psw.mask = _USER_PSW_MASK; \
regs->psw.addr = new_psw | 0x80000000; \
regs->psw.mask = PSW_USER_BITS; \
regs->psw.addr = new_psw | PSW_ADDR_AMODE31; \
regs->gprs[15] = new_stackp ; \
} while (0)
......@@ -136,19 +136,6 @@ unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
/* Only let our hackers near the condition codes */
#define PSW_MASK_DEBUGCHANGE 0x00003000UL
/* Don't let em near the addressing mode either */
#define PSW_ADDR_DEBUGCHANGE 0x7FFFFFFFUL
#define PSW_ADDR_MASK 0x7FFFFFFFUL
/* Program event recording mask */
#define PSW_PER_MASK 0x40000000UL
#define USER_STD_MASK 0x00000080UL
#define PSW_PROBLEM_STATE 0x00010000UL
/*
* Set PSW mask to specified value, while leaving the
* PSW addr pointing to the next instruction.
......@@ -178,7 +165,8 @@ static inline void enabled_wait(void)
unsigned long reg;
psw_t wait_psw;
wait_psw.mask = 0x070e0000;
wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
PSW_MASK_MCHECK | PSW_MASK_WAIT;
asm volatile (
" basr %0,0\n"
"0: la %0,1f-0b(%0)\n"
......@@ -200,7 +188,7 @@ static inline void disabled_wait(unsigned long code)
psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
& -sizeof(psw_t));
dw_psw->mask = 0x000a0000;
dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT;
dw_psw->addr = code;
/*
* Store status and then load disabled wait psw,
......
......@@ -114,7 +114,6 @@
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <asm/setup.h>
/* this typedef defines how a Program Status Word looks like */
......@@ -124,10 +123,32 @@ typedef struct
__u32 addr;
} __attribute__ ((aligned(8))) psw_t;
#ifdef __KERNEL__
#define FIX_PSW(addr) ((unsigned long)(addr)|0x80000000UL)
#define ADDR_BITS_REMOVE(addr) ((addr)&0x7fffffff)
#endif
#define PSW_MASK_PER 0x40000000UL
#define PSW_MASK_DAT 0x04000000UL
#define PSW_MASK_IO 0x02000000UL
#define PSW_MASK_EXT 0x01000000UL
#define PSW_MASK_KEY 0x00F00000UL
#define PSW_MASK_MCHECK 0x00040000UL
#define PSW_MASK_WAIT 0x00020000UL
#define PSW_MASK_PSTATE 0x00010000UL
#define PSW_MASK_ASC 0x0000C000UL
#define PSW_MASK_CC 0x00003000UL
#define PSW_MASK_PM 0x00000F00UL
#define PSW_ADDR_AMODE31 0x80000000UL
#define PSW_ADDR_INSN 0x7FFFFFFFUL
#define PSW_BASE_BITS 0x00080000UL
#define PSW_ASC_PRIMARY 0x00000000UL
#define PSW_ASC_ACCREG 0x00004000UL
#define PSW_ASC_SECONDARY 0x00008000UL
#define PSW_ASC_HOME 0x0000C000UL
#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY)
#define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
PSW_MASK_PSTATE)
typedef union
{
......@@ -328,8 +349,8 @@ struct user_regs_struct
};
#ifdef __KERNEL__
#define user_mode(regs) (((regs)->psw.mask & PSW_PROBLEM_STATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr)
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr & PSW_MASK_INSN)
extern void show_regs(struct pt_regs * regs);
#endif
......
......@@ -56,32 +56,6 @@
#define __LC_PFAULT_INTPARM 0x11B8
/* interrupt handler start with all io, external and mcck interrupt disabled */
#define _RESTART_PSW_MASK 0x0000000180000000
#define _EXT_PSW_MASK 0x0400000180000000
#define _PGM_PSW_MASK 0x0400000180000000
#define _SVC_PSW_MASK 0x0400000180000000
#define _MCCK_PSW_MASK 0x0400000180000000
#define _IO_PSW_MASK 0x0400000180000000
#define _USER_PSW_MASK 0x0705C00180000000
#define _WAIT_PSW_MASK 0x0706000180000000
#define _DW_PSW_MASK 0x0002000180000000
#define _PRIMARY_MASK 0x0000 /* MASK for SACF */
#define _SECONDARY_MASK 0x0100 /* MASK for SACF */
#define _ACCESS_MASK 0x0200 /* MASK for SACF */
#define _HOME_MASK 0x0300 /* MASK for SACF */
#define _PSW_PRIM_SPACE_MODE 0x0000000000000000
#define _PSW_SEC_SPACE_MODE 0x0000800000000000
#define _PSW_ACC_REG_MODE 0x0000400000000000
#define _PSW_HOME_SPACE_MODE 0x0000C00000000000
#define _PSW_WAIT_MASK_BIT 0x0002000000000000
#define _PSW_IO_MASK_BIT 0x0200000000000000
#define _PSW_IO_WAIT 0x0202000000000000
#ifndef __ASSEMBLY__
#include <linux/config.h>
......
......@@ -111,13 +111,13 @@ typedef struct thread_struct thread_struct;
/* need to define ... */
#define start_thread(regs, new_psw, new_stackp) do { \
regs->psw.mask = _USER_PSW_MASK; \
regs->psw.mask = PSW_USER_BITS; \
regs->psw.addr = new_psw; \
regs->gprs[15] = new_stackp; \
} while (0)
#define start_thread31(regs, new_psw, new_stackp) do { \
regs->psw.mask = _USER_PSW_MASK & ~(1L << 32); \
regs->psw.mask = PSW_USER32_BITS; \
regs->psw.addr = new_psw; \
regs->gprs[15] = new_stackp; \
} while (0)
......@@ -153,19 +153,6 @@ unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
/* Only let our hackers near the condition codes */
#define PSW_MASK_DEBUGCHANGE 0x0000300000000000UL
/* Don't let em near the addressing mode either */
#define PSW_ADDR_DEBUGCHANGE 0xFFFFFFFFFFFFFFFFUL
#define PSW_ADDR_MASK 0xFFFFFFFFFFFFFFFFUL
/* Program event recording mask */
#define PSW_PER_MASK 0x4000000000000000UL
#define USER_STD_MASK 0x0000000000000080UL
#define PSW_PROBLEM_STATE 0x0001000000000000UL
/*
* Set PSW mask to specified value, while leaving the
* PSW addr pointing to the next instruction.
......@@ -194,7 +181,8 @@ static inline void enabled_wait(void)
unsigned long reg;
psw_t wait_psw;
wait_psw.mask = 0x0706000180000000;
wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
PSW_MASK_MCHECK | PSW_MASK_WAIT;
asm volatile (
" larl %0,0f\n"
" stg %0,8(%1)\n"
......@@ -214,7 +202,7 @@ static inline void disabled_wait(addr_t code)
psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
& -sizeof(psw_t));
dw_psw->mask = 0x0002000180000000;
dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT;
dw_psw->addr = code;
/*
* Store status and then load disabled wait psw,
......
......@@ -104,10 +104,33 @@ typedef struct
__u64 addr;
} __attribute__ ((aligned(8))) psw_t;
#ifdef __KERNEL__
#define FIX_PSW(addr) ((unsigned long)(addr))
#define ADDR_BITS_REMOVE(addr) ((addr))
#endif
#define PSW_MASK_PER 0x4000000000000000UL
#define PSW_MASK_DAT 0x0400000000000000UL
#define PSW_MASK_IO 0x0200000000000000UL
#define PSW_MASK_EXT 0x0100000000000000UL
#define PSW_MASK_KEY 0x00F0000000000000UL
#define PSW_MASK_MCHECK 0x0004000000000000UL
#define PSW_MASK_WAIT 0x0002000000000000UL
#define PSW_MASK_PSTATE 0x0001000000000000UL
#define PSW_MASK_ASC 0x0000C00000000000UL
#define PSW_MASK_CC 0x0000300000000000UL
#define PSW_MASK_PM 0x00000F0000000000UL
#define PSW_BASE_BITS 0x0000000180000000UL
#define PSW_BASE32_BITS 0x0000000080000000UL
#define PSW_ASC_PRIMARY 0x0000000000000000UL
#define PSW_ASC_ACCREG 0x0000400000000000UL
#define PSW_ASC_SECONDARY 0x0000800000000000UL
#define PSW_ASC_HOME 0x0000C00000000000UL
#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY)
#define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
PSW_MASK_PSTATE)
#define PSW_USER32_BITS (PSW_BASE32_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
PSW_MASK_PSTATE)
typedef union
{
......@@ -309,7 +332,7 @@ struct user_regs_struct
};
#ifdef __KERNEL__
#define user_mode(regs) (((regs)->psw.mask & PSW_PROBLEM_STATE) != 0)
#define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0)
#define instruction_pointer(regs) ((regs)->psw.addr)
extern void show_regs(struct pt_regs * regs);
#endif
......
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