Commit bb1cdf1c authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: detect SYSEMU_SINGLESTEP

From: Bodo Stroesser <bstroesser@fujitsu-siemens.com>

This implements checking for the new ptrace option SYSEMU_SINGLESTEP
(advanced sysemu) and allows the values 0,1,2 for /proc/sysemu,
if advanced sysemu is available:
   0 = don't use sysemu
   1 = use sysemu, but don't use advanced sysemu
   2 = use sysemu and advanced sysemu
Signed-off-by: default avatarBodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 099f5819
...@@ -21,6 +21,9 @@ extern void ptrace_pokeuser(unsigned long addr, unsigned long data); ...@@ -21,6 +21,9 @@ extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
#ifndef PTRACE_SYSEMU #ifndef PTRACE_SYSEMU
#define PTRACE_SYSEMU 31 #define PTRACE_SYSEMU 31
#endif #endif
#ifndef PTRACE_SYSEMU_SINGLESTEP
#define PTRACE_SYSEMU_SINGLESTEP 32
#endif
void set_using_sysemu(int value); void set_using_sysemu(int value);
int get_using_sysemu(void); int get_using_sysemu(void);
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#ifdef UML_CONFIG_MODE_SKAS #ifdef UML_CONFIG_MODE_SKAS
#include "ptrace-skas.h" #include "ptrace-skas.h"
#endif #endif
#ifndef PTRACE_SYSEMU_SINGLESTEP
#define PTRACE_SYSEMU_SINGLESTEP 32
#endif
#include "choose-mode.h" #include "choose-mode.h"
......
...@@ -241,7 +241,7 @@ __uml_setup("nosysemu", nosysemu_cmd_param, ...@@ -241,7 +241,7 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
static void __init check_sysemu(void) static void __init check_sysemu(void)
{ {
void *stack; void *stack;
int pid, n, status; int pid, syscall, n, status, count=0;
printk("Checking syscall emulation patch for ptrace..."); printk("Checking syscall emulation patch for ptrace...");
sysemu_supported = 0; sysemu_supported = 0;
...@@ -269,12 +269,46 @@ static void __init check_sysemu(void) ...@@ -269,12 +269,46 @@ static void __init check_sysemu(void)
sysemu_supported = 1; sysemu_supported = 1;
printk("OK\n"); printk("OK\n");
set_using_sysemu(!force_sysemu_disabled); set_using_sysemu(!force_sysemu_disabled);
printk("Checking advanced syscall emulation patch for ptrace...");
pid = start_ptraced_child(&stack);
while(1){
count++;
if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
goto fail;
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
"got status = %d", status);
syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
0);
if(syscall == __NR_getpid){
if (!count)
panic("check_ptrace : SYSEMU_SINGLESTEP doesn't singlestep");
n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if(n < 0)
panic("check_sysemu : failed to modify system "
"call return, errno = %d", errno);
break;
}
}
if (stop_ptraced_child(pid, stack, 0, 0) < 0)
goto fail_stopped;
sysemu_supported = 2;
printk("OK\n");
if ( !force_sysemu_disabled )
set_using_sysemu(sysemu_supported);
return; return;
fail: fail:
stop_ptraced_child(pid, stack, 1, 0); stop_ptraced_child(pid, stack, 1, 0);
fail_stopped: fail_stopped:
sysemu_supported = 0;
printk("missing\n"); printk("missing\n");
} }
......
...@@ -404,7 +404,9 @@ int sysemu_supported; ...@@ -404,7 +404,9 @@ int sysemu_supported;
void set_using_sysemu(int value) void set_using_sysemu(int value)
{ {
atomic_set(&using_sysemu, sysemu_supported && value); if (value > sysemu_supported)
return;
atomic_set(&using_sysemu, value);
} }
int get_using_sysemu(void) int get_using_sysemu(void)
...@@ -427,7 +429,7 @@ static int proc_write_sysemu(struct file *file,const char *buf, unsigned long co ...@@ -427,7 +429,7 @@ static int proc_write_sysemu(struct file *file,const char *buf, unsigned long co
if (copy_from_user(tmp, buf, 1)) if (copy_from_user(tmp, buf, 1))
return -EFAULT; return -EFAULT;
if (tmp[0] == '0' || tmp[0] == '1') if (tmp[0] >= '0' && tmp[0] <= '2')
set_using_sysemu(tmp[0] - '0'); set_using_sysemu(tmp[0] - '0');
return count; /*We use the first char, but pretend to write everything*/ return count; /*We use the first char, but pretend to write everything*/
} }
......
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