···8181 mm_segment_t mm_segment;8282 unsigned long prot_addr; /* address of protection-excep. */8383 unsigned int trap_no;8484- per_struct per_info;8484+ struct per_regs per_user; /* User specified PER registers */8585+ struct per_event per_event; /* Cause of the last PER trap */8586 /* pfault_wait is used to block the process on a pfault event */8687 unsigned long pfault_wait;8788};
+51-1
arch/s390/include/asm/ptrace.h
···331331 unsigned short ilc;332332 unsigned short svcnr;333333};334334+335335+/*336336+ * Program event recording (PER) register set.337337+ */338338+struct per_regs {339339+ unsigned long control; /* PER control bits */340340+ unsigned long start; /* PER starting address */341341+ unsigned long end; /* PER ending address */342342+};343343+344344+/*345345+ * PER event contains information about the cause of the last PER exception.346346+ */347347+struct per_event {348348+ unsigned short cause; /* PER code, ATMID and AI */349349+ unsigned long address; /* PER address */350350+ unsigned char paid; /* PER access identification */351351+};352352+353353+/*354354+ * Simplified per_info structure used to decode the ptrace user space ABI.355355+ */356356+struct per_struct_kernel {357357+ unsigned long cr9; /* PER control bits */358358+ unsigned long cr10; /* PER starting address */359359+ unsigned long cr11; /* PER ending address */360360+ unsigned long bits; /* Obsolete software bits */361361+ unsigned long starting_addr; /* User specified start address */362362+ unsigned long ending_addr; /* User specified end address */363363+ unsigned short perc_atmid; /* PER trap ATMID */364364+ unsigned long address; /* PER trap instruction address */365365+ unsigned char access_id; /* PER trap access identification */366366+};367367+368368+#define PER_EVENT_MASK 0xE9000000UL369369+370370+#define PER_EVENT_BRANCH 0x80000000UL371371+#define PER_EVENT_IFETCH 0x40000000UL372372+#define PER_EVENT_STORE 0x20000000UL373373+#define PER_EVENT_STORE_REAL 0x08000000UL374374+#define PER_EVENT_NULLIFICATION 0x01000000UL375375+376376+#define PER_CONTROL_MASK 0x00a00000UL377377+378378+#define PER_CONTROL_BRANCH_ADDRESS 0x00800000UL379379+#define PER_CONTROL_ALTERATION 0x00200000UL380380+334381#endif335382336383/*337337- * Now for the program event recording (trace) definitions.384384+ * Now for the user space program event recording (trace) definitions.385385+ * The following structures are used only for the ptrace interface, don't386386+ * touch or even look at it if you don't want to modify the user-space387387+ * ptrace interface. In particular stay away from it for in-kernel PER.338388 */339389typedef struct340390{
···44#include <asm/ptrace.h> /* needed for NUM_CR_WORDS */55#include "compat_linux.h" /* needed for psw_compat_t */6677-typedef struct {88- __u32 cr[NUM_CR_WORDS];99-} per_cr_words32;77+struct compat_per_struct_kernel {88+ __u32 cr9; /* PER control bits */99+ __u32 cr10; /* PER starting address */1010+ __u32 cr11; /* PER ending address */1111+ __u32 bits; /* Obsolete software bits */1212+ __u32 starting_addr; /* User specified start address */1313+ __u32 ending_addr; /* User specified end address */1414+ __u16 perc_atmid; /* PER trap ATMID */1515+ __u32 address; /* PER trap instruction address */1616+ __u8 access_id; /* PER trap access identification */1717+};10181111-typedef struct {1212- __u16 perc_atmid; /* 0x096 */1313- __u32 address; /* 0x098 */1414- __u8 access_id; /* 0x0a1 */1515-} per_lowcore_words32;1616-1717-typedef struct {1818- union {1919- per_cr_words32 words;2020- } control_regs;2121- /*2222- * Use these flags instead of setting em_instruction_fetch2323- * directly they are used so that single stepping can be2424- * switched on & off while not affecting other tracing2525- */2626- unsigned single_step : 1;2727- unsigned instruction_fetch : 1;2828- unsigned : 30;2929- /*3030- * These addresses are copied into cr10 & cr11 if single3131- * stepping is switched off3232- */3333- __u32 starting_addr;3434- __u32 ending_addr;3535- union {3636- per_lowcore_words32 words;3737- } lowcore; 3838-} per_struct32;3939-4040-struct user_regs_struct321919+struct compat_user_regs_struct4120{4221 psw_compat_t psw;4322 u32 gprs[NUM_GPRS];···2950 * itself as there is no "official" ptrace interface for hardware3051 * watchpoints. This is the way intel does it.3152 */3232- per_struct32 per_info;5353+ struct compat_per_struct_kernel per_info;3354 u32 ieee_instruction_pointer; /* obsolete, always 0 */3455};35563636-struct user32 {5757+struct compat_user {3758 /* We start with the registers, to mimic the way that "memory"3859 is returned from the ptrace(3,...) function. */3939- struct user_regs_struct32 regs; /* Where the registers are actually stored */6060+ struct compat_user_regs_struct regs;4061 /* The rest of this junk is to help gdb figure out what goes where */4162 u32 u_tsize; /* Text segment size (pages). */4263 u32 u_dsize; /* Data segment size (pages). */···5879 __u32 len;5980 __u32 kernel_addr;6081 __u32 process_addr;6161-} ptrace_area_emu31;8282+} compat_ptrace_area;62836384#endif /* _PTRACE32_H */
+30-40
arch/s390/kernel/entry.S
···4848SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE49495050_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \5151- _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )5151+ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )5252_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \5353 _TIF_MCCK_PENDING)5454_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \···200200 .globl __switch_to201201__switch_to:202202 basr %r1,0203203-__switch_to_base:204204- tm __THREAD_per(%r3),0xe8 # new process is using per ?205205- bz __switch_to_noper-__switch_to_base(%r1) # if not we're fine206206- stctl %c9,%c11,__SF_EMPTY(%r15) # We are using per stuff207207- clc __THREAD_per(12,%r3),__SF_EMPTY(%r15)208208- be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's209209- lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't210210-__switch_to_noper:211211- l %r4,__THREAD_info(%r2) # get thread_info of prev203203+0: l %r4,__THREAD_info(%r2) # get thread_info of prev204204+ l %r5,__THREAD_info(%r3) # get thread_info of next212205 tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?213213- bz __switch_to_no_mcck-__switch_to_base(%r1)214214- ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev215215- l %r4,__THREAD_info(%r3) # get thread_info of next216216- oi __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next217217-__switch_to_no_mcck:218218- stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task219219- st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp220220- l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp221221- lm %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task222222- st %r3,__LC_CURRENT # __LC_CURRENT = current task struct223223- lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4224224- l %r3,__THREAD_info(%r3) # load thread_info from task struct225225- st %r3,__LC_THREAD_INFO226226- ahi %r3,STACK_SIZE227227- st %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack206206+ bz 1f-0b(%r1)207207+ ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev208208+ oi __TI_flags+3(%r5),_TIF_MCCK_PENDING # set it in next209209+1: stm %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task210210+ st %r15,__THREAD_ksp(%r2) # store kernel stack of prev211211+ l %r15,__THREAD_ksp(%r3) # load kernel stack of next212212+ lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4213213+ lm %r6,%r15,__SF_GPRS(%r15) # load gprs of next task214214+ st %r3,__LC_CURRENT # store task struct of next215215+ st %r5,__LC_THREAD_INFO # store thread info of next216216+ ahi %r5,STACK_SIZE # end of kernel stack of next217217+ st %r5,__LC_KERNEL_STACK # store end of kernel stack228218 br %r14229219230220__critical_start:···287297 bo BASED(sysc_notify_resume)288298 tm __TI_flags+3(%r12),_TIF_RESTART_SVC289299 bo BASED(sysc_restart)290290- tm __TI_flags+3(%r12),_TIF_SINGLE_STEP300300+ tm __TI_flags+3(%r12),_TIF_PER_TRAP291301 bo BASED(sysc_singlestep)292302 b BASED(sysc_return) # beware of critical section cleanup293303···311321# _TIF_SIGPENDING is set, call do_signal312322#313323sysc_sigpending:314314- ni __TI_flags+3(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP324324+ ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP315325 la %r2,SP_PTREGS(%r15) # load pt_regs316326 l %r1,BASED(.Ldo_signal)317327 basr %r14,%r1 # call do_signal318328 tm __TI_flags+3(%r12),_TIF_RESTART_SVC319329 bo BASED(sysc_restart)320320- tm __TI_flags+3(%r12),_TIF_SINGLE_STEP330330+ tm __TI_flags+3(%r12),_TIF_PER_TRAP321331 bo BASED(sysc_singlestep)322332 b BASED(sysc_return)323333···343353 b BASED(sysc_nr_ok) # restart svc344354345355#346346-# _TIF_SINGLE_STEP is set, call do_single_step356356+# _TIF_PER_TRAP is set, call do_per_trap347357#348358sysc_singlestep:349349- ni __TI_flags+3(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP359359+ ni __TI_flags+3(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP350360 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number351361 la %r2,SP_PTREGS(%r15) # address of register-save area352362 l %r1,BASED(.Lhandle_per) # load adr. of per handler353363 la %r14,BASED(sysc_return) # load adr. of system return354354- br %r1 # branch to do_single_step364364+ br %r1 # branch to do_per_trap355365356366#357367# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before···510520 l %r1,__TI_task(%r12)511521 tm SP_PSW+1(%r15),0x01 # kernel per event ?512522 bz BASED(kernel_per)513513- mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID514514- mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS515515- mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID516516- oi __TI_flags+3(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP523523+ mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE524524+ mvc __THREAD_per_address(4,%r1),__LC_PER_ADDRESS525525+ mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID526526+ oi __TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP517527 l %r3,__LC_PGM_ILC # load program interruption code518528 l %r4,__LC_TRANS_EXC_CODE519529 REENABLE_IRQS···541551 UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER542552 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER543553 l %r8,__TI_task(%r12)544544- mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID545545- mvc __THREAD_per+__PER_address(4,%r8),__LC_PER_ADDRESS546546- mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID547547- oi __TI_flags+3(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP554554+ mvc __THREAD_per_cause(2,%r8),__LC_PER_CAUSE555555+ mvc __THREAD_per_address(4,%r8),__LC_PER_ADDRESS556556+ mvc __THREAD_per_paid(1,%r8),__LC_PER_PAID557557+ oi __TI_flags+3(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP548558 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts549559 lm %r2,%r6,SP_R2(%r15) # load svc arguments550560 b BASED(sysc_do_svc)···10461056.Ldo_signal: .long do_signal10471057.Ldo_notify_resume:10481058 .long do_notify_resume10491049-.Lhandle_per: .long do_single_step10591059+.Lhandle_per: .long do_per_trap10501060.Ldo_execve: .long do_execve10511061.Lexecve_tail: .long execve_tail10521062.Ljump_table: .long pgm_check_table
···5151STACK_SIZE = 1 << STACK_SHIFT52525353_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \5454- _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )5454+ _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_PER_TRAP )5555_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \5656 _TIF_MCCK_PENDING)5757_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \···208208 */209209 .globl __switch_to210210__switch_to:211211- tm __THREAD_per+4(%r3),0xe8 # is the new process using per ?212212- jz __switch_to_noper # if not we're fine213213- stctg %c9,%c11,__SF_EMPTY(%r15)# We are using per stuff214214- clc __THREAD_per(24,%r3),__SF_EMPTY(%r15)215215- je __switch_to_noper # we got away without bashing TLB's216216- lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't217217-__switch_to_noper:218218- lg %r4,__THREAD_info(%r2) # get thread_info of prev211211+ lg %r4,__THREAD_info(%r2) # get thread_info of prev212212+ lg %r5,__THREAD_info(%r3) # get thread_info of next219213 tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?220220- jz __switch_to_no_mcck221221- ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev222222- lg %r4,__THREAD_info(%r3) # get thread_info of next223223- oi __TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next224224-__switch_to_no_mcck:225225- stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task226226- stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp227227- lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp228228- lmg %r6,%r15,__SF_GPRS(%r15)# load __switch_to registers of next task229229- stg %r3,__LC_CURRENT # __LC_CURRENT = current task struct230230- lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4231231- lg %r3,__THREAD_info(%r3) # load thread_info from task struct232232- stg %r3,__LC_THREAD_INFO233233- aghi %r3,STACK_SIZE234234- stg %r3,__LC_KERNEL_STACK # __LC_KERNEL_STACK = new kernel stack214214+ jz 0f215215+ ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev216216+ oi __TI_flags+7(%r5),_TIF_MCCK_PENDING # set it in next217217+0: stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task218218+ stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev219219+ lg %r15,__THREAD_ksp(%r3) # load kernel stack of next220220+ lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4221221+ lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task222222+ stg %r3,__LC_CURRENT # store task struct of next223223+ stg %r5,__LC_THREAD_INFO # store thread info of next224224+ aghi %r5,STACK_SIZE # end of kernel stack of next225225+ stg %r5,__LC_KERNEL_STACK # store end of kernel stack235226 br %r14236227237228__critical_start:···302311 jo sysc_notify_resume303312 tm __TI_flags+7(%r12),_TIF_RESTART_SVC304313 jo sysc_restart305305- tm __TI_flags+7(%r12),_TIF_SINGLE_STEP314314+ tm __TI_flags+7(%r12),_TIF_PER_TRAP306315 jo sysc_singlestep307316 j sysc_return # beware of critical section cleanup308317···324333# _TIF_SIGPENDING is set, call do_signal325334#326335sysc_sigpending:327327- ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP336336+ ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP328337 la %r2,SP_PTREGS(%r15) # load pt_regs329338 brasl %r14,do_signal # call do_signal330339 tm __TI_flags+7(%r12),_TIF_RESTART_SVC331340 jo sysc_restart332332- tm __TI_flags+7(%r12),_TIF_SINGLE_STEP341341+ tm __TI_flags+7(%r12),_TIF_PER_TRAP333342 jo sysc_singlestep334343 j sysc_return335344···354363 j sysc_nr_ok # restart svc355364356365#357357-# _TIF_SINGLE_STEP is set, call do_single_step366366+# _TIF_PER_TRAP is set, call do_per_trap358367#359368sysc_singlestep:360360- ni __TI_flags+7(%r12),255-_TIF_SINGLE_STEP # clear TIF_SINGLE_STEP369369+ ni __TI_flags+7(%r12),255-_TIF_PER_TRAP # clear TIF_PER_TRAP361370 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number362371 la %r2,SP_PTREGS(%r15) # address of register-save area363372 larl %r14,sysc_return # load adr. of system return364364- jg do_single_step # branch to do_sigtrap373373+ jg do_per_trap365374366375#367376# call tracehook_report_syscall_entry/tracehook_report_syscall_exit before···517526 lg %r1,__TI_task(%r12)518527 tm SP_PSW+1(%r15),0x01 # kernel per event ?519528 jz kernel_per520520- mvc __THREAD_per+__PER_atmid(2,%r1),__LC_PER_ATMID521521- mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS522522- mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID523523- oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP529529+ mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE530530+ mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS531531+ mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID532532+ oi __TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP524533 lgf %r3,__LC_PGM_ILC # load program interruption code525534 lg %r4,__LC_TRANS_EXC_CODE526535 REENABLE_IRQS···549558 mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER550559 LAST_BREAK551560 lg %r8,__TI_task(%r12)552552- mvc __THREAD_per+__PER_atmid(2,%r8),__LC_PER_ATMID553553- mvc __THREAD_per+__PER_address(8,%r8),__LC_PER_ADDRESS554554- mvc __THREAD_per+__PER_access_id(1,%r8),__LC_PER_ACCESS_ID555555- oi __TI_flags+7(%r12),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP561561+ mvc __THREAD_per_cause(2,%r8),__LC_PER_CAUSE562562+ mvc __THREAD_per_address(8,%r8),__LC_PER_ADDRESS563563+ mvc __THREAD_per_paid(1,%r8),__LC_PER_PAID564564+ oi __TI_flags+7(%r12),_TIF_PER_TRAP # set TIF_PER_TRAP556565 stosm __SF_EMPTY(%r15),0x03 # reenable interrupts557566 lmg %r2,%r6,SP_R2(%r15) # load svc arguments558567 j sysc_do_svc···564573 REENABLE_IRQS565574 xc SP_SVCNR(2,%r15),SP_SVCNR(%r15) # clear svc number566575 la %r2,SP_PTREGS(%r15) # address of register-save area567567- brasl %r14,do_single_step576576+ brasl %r14,do_per_trap568577 j pgm_exit569578570579/*
+6-7
arch/s390/kernel/kprobes.c
···175175 struct pt_regs *regs,176176 unsigned long ip)177177{178178- per_cr_bits kprobe_per_regs[1];178178+ struct per_regs per_kprobe;179179180180- /* Set up the per control reg info, will pass to lctl */181181- memset(kprobe_per_regs, 0, sizeof(per_cr_bits));182182- kprobe_per_regs[0].em_instruction_fetch = 1;183183- kprobe_per_regs[0].starting_addr = ip;184184- kprobe_per_regs[0].ending_addr = ip;180180+ /* Set up the PER control registers %cr9-%cr11 */181181+ per_kprobe.control = PER_EVENT_IFETCH;182182+ per_kprobe.start = ip;183183+ per_kprobe.end = ip;185184186185 /* Save control regs and psw mask */187186 __ctl_store(kcb->kprobe_saved_ctl, 9, 11);···188189 (PSW_MASK_PER | PSW_MASK_IO | PSW_MASK_EXT);189190190191 /* Set PER control regs, turns on single step for the given address */191191- __ctl_load(kprobe_per_regs, 9, 11);192192+ __ctl_load(per_kprobe, 9, 11);192193 regs->psw.mask |= PSW_MASK_PER;193194 regs->psw.mask &= ~(PSW_MASK_IO | PSW_MASK_EXT);194195 regs->psw.addr = ip | PSW_ADDR_AMODE;
+3-1
arch/s390/kernel/process.c
···213213 /* start new process with ar4 pointing to the correct address space */214214 p->thread.mm_segment = get_fs();215215 /* Don't copy debug registers */216216- memset(&p->thread.per_info, 0, sizeof(p->thread.per_info));216216+ memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));217217+ memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));217218 clear_tsk_thread_flag(p, TIF_SINGLE_STEP);219219+ clear_tsk_thread_flag(p, TIF_PER_TRAP);218220 /* Initialize per thread user and system timer values */219221 ti = task_thread_info(p);220222 ti->user_timer = 0;
+186-118
arch/s390/kernel/ptrace.c
···11/*22- * arch/s390/kernel/ptrace.c22+ * Ptrace user space interface.33 *44- * S390 version55- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation66- * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),44+ * Copyright IBM Corp. 1999,201055+ * Author(s): Denis Joseph Barrow76 * Martin Schwidefsky (schwidefsky@de.ibm.com)88- *99- * Based on PowerPC version 1010- * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)1111- *1212- * Derived from "arch/m68k/kernel/ptrace.c"1313- * Copyright (C) 1994 by Hamish Macdonald1414- * Taken from linux/kernel/ptrace.c and modified for M680x0.1515- * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds1616- *1717- * Modified by Cort Dougan (cort@cs.nmt.edu) 1818- *1919- *2020- * This file is subject to the terms and conditions of the GNU General2121- * Public License. See the file README.legal in the main directory of2222- * this archive for more details.237 */248259#include <linux/kernel.h>···4561 REGSET_GENERAL_EXTENDED,4662};47634848-static void4949-FixPerRegisters(struct task_struct *task)6464+void update_per_regs(struct task_struct *task)5065{5151- struct pt_regs *regs;5252- per_struct *per_info;5353- per_cr_words cr_words;6666+ static const struct per_regs per_single_step = {6767+ .control = PER_EVENT_IFETCH,6868+ .start = 0,6969+ .end = PSW_ADDR_INSN,7070+ };7171+ struct pt_regs *regs = task_pt_regs(task);7272+ struct thread_struct *thread = &task->thread;7373+ const struct per_regs *new;7474+ struct per_regs old;54755555- regs = task_pt_regs(task);5656- per_info = (per_struct *) &task->thread.per_info;5757- per_info->control_regs.bits.em_instruction_fetch =5858- per_info->single_step | per_info->instruction_fetch;5959-6060- if (per_info->single_step) {6161- per_info->control_regs.bits.starting_addr = 0;6262-#ifdef CONFIG_COMPAT6363- if (is_compat_task())6464- per_info->control_regs.bits.ending_addr = 0x7fffffffUL;6565- else6666-#endif6767- per_info->control_regs.bits.ending_addr = PSW_ADDR_INSN;6868- } else {6969- per_info->control_regs.bits.starting_addr =7070- per_info->starting_addr;7171- per_info->control_regs.bits.ending_addr =7272- per_info->ending_addr;7373- }7474- /*7575- * if any of the control reg tracing bits are on 7676- * we switch on per in the psw7777- */7878- if (per_info->control_regs.words.cr[0] & PER_EM_MASK)7979- regs->psw.mask |= PSW_MASK_PER;8080- else7676+ /* TIF_SINGLE_STEP overrides the user specified PER registers. */7777+ new = test_tsk_thread_flag(task, TIF_SINGLE_STEP) ?7878+ &per_single_step : &thread->per_user;7979+8080+ /* Take care of the PER enablement bit in the PSW. */8181+ if (!(new->control & PER_EVENT_MASK)) {8182 regs->psw.mask &= ~PSW_MASK_PER;8282-8383- if (per_info->control_regs.bits.em_storage_alteration)8484- per_info->control_regs.bits.storage_alt_space_ctl = 1;8585- else8686- per_info->control_regs.bits.storage_alt_space_ctl = 0;8787-8888- if (task == current) {8989- __ctl_store(cr_words, 9, 11);9090- if (memcmp(&cr_words, &per_info->control_regs.words,9191- sizeof(cr_words)) != 0)9292- __ctl_load(per_info->control_regs.words, 9, 11);8383+ return;9384 }8585+ regs->psw.mask |= PSW_MASK_PER;8686+ __ctl_store(old, 9, 11);8787+ if (memcmp(new, &old, sizeof(struct per_regs)) != 0)8888+ __ctl_load(*new, 9, 11);9489}95909691void user_enable_single_step(struct task_struct *task)9792{9898- task->thread.per_info.single_step = 1;9999- FixPerRegisters(task);9393+ set_tsk_thread_flag(task, TIF_SINGLE_STEP);9494+ if (task == current)9595+ update_per_regs(task);10096}1019710298void user_disable_single_step(struct task_struct *task)10399{104104- task->thread.per_info.single_step = 0;105105- FixPerRegisters(task);100100+ clear_tsk_thread_flag(task, TIF_SINGLE_STEP);101101+ if (task == current)102102+ update_per_regs(task);106103}107104108105/*109106 * Called by kernel/ptrace.c when detaching..110107 *111111- * Make sure single step bits etc are not set.108108+ * Clear all debugging related fields.112109 */113113-void114114-ptrace_disable(struct task_struct *child)110110+void ptrace_disable(struct task_struct *task)115111{116116- /* make sure the single step bit is not set. */117117- user_disable_single_step(child);112112+ memset(&task->thread.per_user, 0, sizeof(task->thread.per_user));113113+ memset(&task->thread.per_event, 0, sizeof(task->thread.per_event));114114+ clear_tsk_thread_flag(task, TIF_SINGLE_STEP);115115+ clear_tsk_thread_flag(task, TIF_PER_TRAP);118116}119117120118#ifndef CONFIG_64BIT···104138#else105139# define __ADDR_MASK 7106140#endif141141+142142+static inline unsigned long __peek_user_per(struct task_struct *child,143143+ addr_t addr)144144+{145145+ struct per_struct_kernel *dummy = NULL;146146+147147+ if (addr == (addr_t) &dummy->cr9)148148+ /* Control bits of the active per set. */149149+ return test_thread_flag(TIF_SINGLE_STEP) ?150150+ PER_EVENT_IFETCH : child->thread.per_user.control;151151+ else if (addr == (addr_t) &dummy->cr10)152152+ /* Start address of the active per set. */153153+ return test_thread_flag(TIF_SINGLE_STEP) ?154154+ 0 : child->thread.per_user.start;155155+ else if (addr == (addr_t) &dummy->cr11)156156+ /* End address of the active per set. */157157+ return test_thread_flag(TIF_SINGLE_STEP) ?158158+ PSW_ADDR_INSN : child->thread.per_user.end;159159+ else if (addr == (addr_t) &dummy->bits)160160+ /* Single-step bit. */161161+ return test_thread_flag(TIF_SINGLE_STEP) ?162162+ (1UL << (BITS_PER_LONG - 1)) : 0;163163+ else if (addr == (addr_t) &dummy->starting_addr)164164+ /* Start address of the user specified per set. */165165+ return child->thread.per_user.start;166166+ else if (addr == (addr_t) &dummy->ending_addr)167167+ /* End address of the user specified per set. */168168+ return child->thread.per_user.end;169169+ else if (addr == (addr_t) &dummy->perc_atmid)170170+ /* PER code, ATMID and AI of the last PER trap */171171+ return (unsigned long)172172+ child->thread.per_event.cause << (BITS_PER_LONG - 16);173173+ else if (addr == (addr_t) &dummy->address)174174+ /* Address of the last PER trap */175175+ return child->thread.per_event.address;176176+ else if (addr == (addr_t) &dummy->access_id)177177+ /* Access id of the last PER trap */178178+ return (unsigned long)179179+ child->thread.per_event.paid << (BITS_PER_LONG - 8);180180+ return 0;181181+}107182108183/*109184 * Read the word at offset addr from the user area of a process. The···211204212205 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {213206 /*214214- * per_info is found in the thread structure207207+ * Handle access to the per_info structure.215208 */216216- offset = addr - (addr_t) &dummy->regs.per_info;217217- tmp = *(addr_t *)((addr_t) &child->thread.per_info + offset);209209+ addr -= (addr_t) &dummy->regs.per_info;210210+ tmp = __peek_user_per(child, addr);218211219212 } else220213 tmp = 0;···242235243236 tmp = __peek_user(child, addr);244237 return put_user(tmp, (addr_t __user *) data);238238+}239239+240240+static inline void __poke_user_per(struct task_struct *child,241241+ addr_t addr, addr_t data)242242+{243243+ struct per_struct_kernel *dummy = NULL;244244+245245+ /*246246+ * There are only three fields in the per_info struct that the247247+ * debugger user can write to.248248+ * 1) cr9: the debugger wants to set a new PER event mask249249+ * 2) starting_addr: the debugger wants to set a new starting250250+ * address to use with the PER event mask.251251+ * 3) ending_addr: the debugger wants to set a new ending252252+ * address to use with the PER event mask.253253+ * The user specified PER event mask and the start and end254254+ * addresses are used only if single stepping is not in effect.255255+ * Writes to any other field in per_info are ignored.256256+ */257257+ if (addr == (addr_t) &dummy->cr9)258258+ /* PER event mask of the user specified per set. */259259+ child->thread.per_user.control =260260+ data & (PER_EVENT_MASK | PER_CONTROL_MASK);261261+ else if (addr == (addr_t) &dummy->starting_addr)262262+ /* Starting address of the user specified per set. */263263+ child->thread.per_user.start = data;264264+ else if (addr == (addr_t) &dummy->ending_addr)265265+ /* Ending address of the user specified per set. */266266+ child->thread.per_user.end = data;245267}246268247269/*···347311348312 } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {349313 /*350350- * per_info is found in the thread structure 314314+ * Handle access to the per_info structure.351315 */352352- offset = addr - (addr_t) &dummy->regs.per_info;353353- *(addr_t *)((addr_t) &child->thread.per_info + offset) = data;316316+ addr -= (addr_t) &dummy->regs.per_info;317317+ __poke_user_per(child, addr, data);354318355319 }356320357357- FixPerRegisters(child);358321 return 0;359322}360323361361-static int362362-poke_user(struct task_struct *child, addr_t addr, addr_t data)324324+static int poke_user(struct task_struct *child, addr_t addr, addr_t data)363325{364326 addr_t mask;365327···444410 */445411446412/*413413+ * Same as peek_user_per but for a 31 bit program.414414+ */415415+static inline __u32 __peek_user_per_compat(struct task_struct *child,416416+ addr_t addr)417417+{418418+ struct compat_per_struct_kernel *dummy32 = NULL;419419+420420+ if (addr == (addr_t) &dummy32->cr9)421421+ /* Control bits of the active per set. */422422+ return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?423423+ PER_EVENT_IFETCH : child->thread.per_user.control;424424+ else if (addr == (addr_t) &dummy32->cr10)425425+ /* Start address of the active per set. */426426+ return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?427427+ 0 : child->thread.per_user.start;428428+ else if (addr == (addr_t) &dummy32->cr11)429429+ /* End address of the active per set. */430430+ return test_thread_flag(TIF_SINGLE_STEP) ?431431+ PSW32_ADDR_INSN : child->thread.per_user.end;432432+ else if (addr == (addr_t) &dummy32->bits)433433+ /* Single-step bit. */434434+ return (__u32) test_thread_flag(TIF_SINGLE_STEP) ?435435+ 0x80000000 : 0;436436+ else if (addr == (addr_t) &dummy32->starting_addr)437437+ /* Start address of the user specified per set. */438438+ return (__u32) child->thread.per_user.start;439439+ else if (addr == (addr_t) &dummy32->ending_addr)440440+ /* End address of the user specified per set. */441441+ return (__u32) child->thread.per_user.end;442442+ else if (addr == (addr_t) &dummy32->perc_atmid)443443+ /* PER code, ATMID and AI of the last PER trap */444444+ return (__u32) child->thread.per_event.cause << 16;445445+ else if (addr == (addr_t) &dummy32->address)446446+ /* Address of the last PER trap */447447+ return (__u32) child->thread.per_event.address;448448+ else if (addr == (addr_t) &dummy32->access_id)449449+ /* Access id of the last PER trap */450450+ return (__u32) child->thread.per_event.paid << 24;451451+ return 0;452452+}453453+454454+/*447455 * Same as peek_user but for a 31 bit program.448456 */449457static u32 __peek_user_compat(struct task_struct *child, addr_t addr)450458{451451- struct user32 *dummy32 = NULL;452452- per_struct32 *dummy_per32 = NULL;459459+ struct compat_user *dummy32 = NULL;453460 addr_t offset;454461 __u32 tmp;455462···540465541466 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {542467 /*543543- * per_info is found in the thread structure468468+ * Handle access to the per_info structure.544469 */545545- offset = addr - (addr_t) &dummy32->regs.per_info;546546- /* This is magic. See per_struct and per_struct32. */547547- if ((offset >= (addr_t) &dummy_per32->control_regs &&548548- offset < (addr_t) (&dummy_per32->control_regs + 1)) ||549549- (offset >= (addr_t) &dummy_per32->starting_addr &&550550- offset <= (addr_t) &dummy_per32->ending_addr) ||551551- offset == (addr_t) &dummy_per32->lowcore.words.address)552552- offset = offset*2 + 4;553553- else554554- offset = offset*2;555555- tmp = *(__u32 *)((addr_t) &child->thread.per_info + offset);470470+ addr -= (addr_t) &dummy32->regs.per_info;471471+ tmp = __peek_user_per_compat(child, addr);556472557473 } else558474 tmp = 0;···564498}565499566500/*501501+ * Same as poke_user_per but for a 31 bit program.502502+ */503503+static inline void __poke_user_per_compat(struct task_struct *child,504504+ addr_t addr, __u32 data)505505+{506506+ struct compat_per_struct_kernel *dummy32 = NULL;507507+508508+ if (addr == (addr_t) &dummy32->cr9)509509+ /* PER event mask of the user specified per set. */510510+ child->thread.per_user.control =511511+ data & (PER_EVENT_MASK | PER_CONTROL_MASK);512512+ else if (addr == (addr_t) &dummy32->starting_addr)513513+ /* Starting address of the user specified per set. */514514+ child->thread.per_user.start = data;515515+ else if (addr == (addr_t) &dummy32->ending_addr)516516+ /* Ending address of the user specified per set. */517517+ child->thread.per_user.end = data;518518+}519519+520520+/*567521 * Same as poke_user but for a 31 bit program.568522 */569523static int __poke_user_compat(struct task_struct *child,570524 addr_t addr, addr_t data)571525{572572- struct user32 *dummy32 = NULL;573573- per_struct32 *dummy_per32 = NULL;526526+ struct compat_user *dummy32 = NULL;574527 __u32 tmp = (__u32) data;575528 addr_t offset;576529···646561647562 } else if (addr < (addr_t) (&dummy32->regs.per_info + 1)) {648563 /*649649- * per_info is found in the thread structure.564564+ * Handle access to the per_info structure.650565 */651651- offset = addr - (addr_t) &dummy32->regs.per_info;652652- /*653653- * This is magic. See per_struct and per_struct32.654654- * By incident the offsets in per_struct are exactly655655- * twice the offsets in per_struct32 for all fields.656656- * The 8 byte fields need special handling though,657657- * because the second half (bytes 4-7) is needed and658658- * not the first half.659659- */660660- if ((offset >= (addr_t) &dummy_per32->control_regs &&661661- offset < (addr_t) (&dummy_per32->control_regs + 1)) ||662662- (offset >= (addr_t) &dummy_per32->starting_addr &&663663- offset <= (addr_t) &dummy_per32->ending_addr) ||664664- offset == (addr_t) &dummy_per32->lowcore.words.address)665665- offset = offset*2 + 4;666666- else667667- offset = offset*2;668668- *(__u32 *)((addr_t) &child->thread.per_info + offset) = tmp;669669-566566+ addr -= (addr_t) &dummy32->regs.per_info;567567+ __poke_user_per_compat(child, addr, data);670568 }671569672672- FixPerRegisters(child);673570 return 0;674571}675572676573static int poke_user_compat(struct task_struct *child,677574 addr_t addr, addr_t data)678575{679679- if (!is_compat_task() || (addr & 3) || addr > sizeof(struct user32) - 3)576576+ if (!is_compat_task() || (addr & 3) ||577577+ addr > sizeof(struct compat_user) - 3)680578 return -EIO;681579682580 return __poke_user_compat(child, addr, data);···670602{671603 unsigned long addr = caddr;672604 unsigned long data = cdata;673673- ptrace_area_emu31 parea; 605605+ compat_ptrace_area parea;674606 int copied, ret;675607676608 switch (request) {
+1-1
arch/s390/kernel/signal.c
···505505 * Let tracing know that we've done the handler setup.506506 */507507 tracehook_signal_handler(signr, &info, &ka, regs,508508- current->thread.per_info.single_step);508508+ test_thread_flag(TIF_SINGLE_STEP));509509 }510510 return;511511 }