diff options
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r-- | arch/s390/kernel/head31.S | 11 | ||||
-rw-r--r-- | arch/s390/kernel/head64.S | 11 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 9 | ||||
-rw-r--r-- | arch/s390/kernel/sys_s390.c | 20 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 7 |
5 files changed, 51 insertions, 7 deletions
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 1fa9fa1ca74..1b952a3664e 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -254,6 +254,16 @@ startup_continue: oi 3(%r12),0x80 # set IDTE flag .Lchkidte: +# +# find out if the diag 0x9c is available +# + mvc __LC_PGM_NEW_PSW(8),.Lpcdiag9c-.LPG1(%r13) + stap __LC_CPUID+4 # store cpu address + lh %r1,__LC_CPUID+4 + diag %r1,0,0x9c # test diag 0x9c + oi 2(%r12),1 # set diag9c flag +.Lchkdiag9c: + lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 8 @@ -281,6 +291,7 @@ startup_continue: .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg .Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte +.Lpcdiag9c:.long 0x00080000,0x80000000 + .Lchkdiag9c .Lmemsize:.long memory_size .Lmchunk:.long memory_chunk .Lmflags:.long machine_flags diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 48998d50b00..b30e5897cdf 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -251,6 +251,17 @@ startup_continue: 0: # +# find out if the diag 0x9c is available +# + la %r1,0f-.LPG1(%r13) # set program check address + stg %r1,__LC_PGM_NEW_PSW+8 + stap __LC_CPUID+4 # store cpu address + lh %r1,__LC_CPUID+4 + diag %r1,0,0x9c # test diag 0x9c + oi 6(%r12),1 # set diag9c flag +0: + +# # find out if we have the MVCOS instruction # la %r1,0f-.LPG1(%r13) # set program check address diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index ca28fb0b379..4d9ff5ce4cb 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c @@ -369,11 +369,12 @@ void __kprobes kretprobe_trampoline_holder(void) int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; - struct hlist_head *head; + struct hlist_head *head, empty_rp; struct hlist_node *node, *tmp; unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline; + INIT_HLIST_HEAD(&empty_rp); spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); @@ -399,7 +400,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) ri->rp->handler(ri, regs); orig_ret_address = (unsigned long)ri->ret_addr; - recycle_rp_inst(ri); + recycle_rp_inst(ri, &empty_rp); if (orig_ret_address != trampoline_address) { /* @@ -417,6 +418,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); + hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { + hlist_del(&ri->hlist); + kfree(ri); + } /* * By returning a non-zero value, we are telling * kprobe_handler() that we don't want the post_handler diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c index e351780bb66..584ed95f338 100644 --- a/arch/s390/kernel/sys_s390.c +++ b/arch/s390/kernel/sys_s390.c @@ -27,6 +27,7 @@ #include <linux/file.h> #include <linux/utsname.h> #include <linux/personality.h> +#include <linux/unistd.h> #include <asm/uaccess.h> #include <asm/ipc.h> @@ -266,3 +267,22 @@ s390_fadvise64_64(struct fadvise64_64_args __user *args) return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); } +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, char *const argv[], char *const envp[]) +{ + register const char *__arg1 asm("2") = filename; + register char *const*__arg2 asm("3") = argv; + register char *const*__arg3 asm("4") = envp; + register long __svcres asm("2"); + asm volatile( + "svc %b1" + : "=d" (__svcres) + : "i" (__NR_execve), + "0" (__arg1), + "d" (__arg2), + "d" (__arg3) : "memory"); + return __svcres; +} diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index abab42e9f5f..4bf66cc4a26 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -53,8 +53,6 @@ static u64 init_timer_cc; static u64 jiffies_timer_cc; static u64 xtime_cc; -extern unsigned long wall_jiffies; - /* * Scheduler clock - returns current time in nanosec units. */ @@ -87,9 +85,8 @@ static inline unsigned long do_gettimeoffset(void) { __u64 now; - now = (get_clock() - jiffies_timer_cc) >> 12; - /* We require the offset from the latest update of xtime */ - now -= (__u64) wall_jiffies*USECS_PER_JIFFY; + now = (get_clock() - jiffies_timer_cc) >> 12; + now -= (__u64) jiffies * USECS_PER_JIFFY; return (unsigned long) now; } |