Commit b202690b authored by Paolo \'Blaisorblade\' Giarrusso's avatar Paolo \'Blaisorblade\' Giarrusso Committed by Linus Torvalds

[PATCH] uml: Adds /proc/sysemu to toggle SYSEMU usage.

Adds /proc/sysemu to toggle SYSEMU usage.
Signed-off-by: default avatarPaolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 33700bae
...@@ -246,7 +246,7 @@ void __init check_ptrace(void) ...@@ -246,7 +246,7 @@ void __init check_ptrace(void)
printk("OK\n"); printk("OK\n");
printk("Checking syscall emulation patch for ptrace..."); printk("Checking syscall emulation patch for ptrace...");
use_sysemu = 0; set_using_sysemu(0);
pid = start_ptraced_child(&stack); pid = start_ptraced_child(&stack);
if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) { if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
struct user_regs_struct regs; struct user_regs_struct regs;
...@@ -269,7 +269,7 @@ void __init check_ptrace(void) ...@@ -269,7 +269,7 @@ void __init check_ptrace(void)
if (!force_sysemu_disabled) { if (!force_sysemu_disabled) {
printk("found\n"); printk("found\n");
use_sysemu = 1; set_using_sysemu(1);
} else { } else {
printk("found but disabled\n"); printk("found but disabled\n");
} }
......
...@@ -15,7 +15,9 @@ ...@@ -15,7 +15,9 @@
#ifndef PTRACE_SYSEMU #ifndef PTRACE_SYSEMU
#define PTRACE_SYSEMU 31 #define PTRACE_SYSEMU 31
#endif #endif
extern int use_sysemu;
void set_using_sysemu(int value);
int get_using_sysemu(void);
#include "skas_ptregs.h" #include "skas_ptregs.h"
......
...@@ -28,10 +28,6 @@ ...@@ -28,10 +28,6 @@
#include "chan_user.h" #include "chan_user.h"
#include "signal_user.h" #include "signal_user.h"
#ifdef PTRACE_SYSEMU
int use_sysemu = 0;
#endif
int is_skas_winch(int pid, int fd, void *data) int is_skas_winch(int pid, int fd, void *data)
{ {
if(pid != getpid()) if(pid != getpid())
...@@ -61,7 +57,8 @@ static void handle_segv(int pid) ...@@ -61,7 +57,8 @@ static void handle_segv(int pid)
segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
} }
static void handle_trap(int pid, union uml_pt_regs *regs) /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
{ {
int err, syscall_nr, status; int err, syscall_nr, status;
...@@ -72,27 +69,23 @@ static void handle_trap(int pid, union uml_pt_regs *regs) ...@@ -72,27 +69,23 @@ static void handle_trap(int pid, union uml_pt_regs *regs)
return; return;
} }
#ifdef PTRACE_SYSEMU if (!local_using_sysemu)
if (!use_sysemu)
{ {
#endif err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); if(err < 0)
if(err < 0) panic("handle_trap - nullifying syscall failed errno = %d\n",
panic("handle_trap - nullifying syscall failed errno = %d\n", errno);
errno);
err = ptrace(PTRACE_SYSCALL, pid, 0, 0); err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
if(err < 0) if(err < 0)
panic("handle_trap - continuing to end of syscall failed, " panic("handle_trap - continuing to end of syscall failed, "
"errno = %d\n", errno); "errno = %d\n", errno);
err = waitpid(pid, &status, WUNTRACED); err = waitpid(pid, &status, WUNTRACED);
if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
panic("handle_trap - failed to wait at end of syscall, " panic("handle_trap - failed to wait at end of syscall, "
"errno = %d, status = %d\n", errno, status); "errno = %d, status = %d\n", errno, status);
#ifdef PTRACE_SYSEMU
} }
#endif
handle_syscall(regs); handle_syscall(regs);
} }
...@@ -147,15 +140,16 @@ void start_userspace(int cpu) ...@@ -147,15 +140,16 @@ void start_userspace(int cpu)
void userspace(union uml_pt_regs *regs) void userspace(union uml_pt_regs *regs)
{ {
int err, status, op, pid = userspace_pid[0]; int err, status, op, pid = userspace_pid[0];
int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
restore_registers(regs); restore_registers(regs);
#ifdef PTRACE_SYSEMU local_using_sysemu = get_using_sysemu();
if (use_sysemu)
if (local_using_sysemu)
err = ptrace(PTRACE_SYSEMU, pid, 0, 0); err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
else else
#endif err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
if(err) if(err)
panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", panic("userspace - PTRACE_SYSCALL failed, errno = %d\n",
errno); errno);
...@@ -174,7 +168,7 @@ void userspace(union uml_pt_regs *regs) ...@@ -174,7 +168,7 @@ void userspace(union uml_pt_regs *regs)
handle_segv(pid); handle_segv(pid);
break; break;
case SIGTRAP: case SIGTRAP:
handle_trap(pid, regs); handle_trap(pid, regs, local_using_sysemu);
break; break;
case SIGIO: case SIGIO:
case SIGVTALRM: case SIGVTALRM:
...@@ -193,14 +187,16 @@ void userspace(union uml_pt_regs *regs) ...@@ -193,14 +187,16 @@ void userspace(union uml_pt_regs *regs)
restore_registers(regs); restore_registers(regs);
#ifdef PTRACE_SYSEMU /*Now we ended the syscall, so re-read local_using_sysemu.*/
if (use_sysemu) local_using_sysemu = get_using_sysemu();
if (local_using_sysemu)
op = singlestepping_skas() ? PTRACE_SINGLESTEP : op = singlestepping_skas() ? PTRACE_SINGLESTEP :
PTRACE_SYSEMU; PTRACE_SYSEMU;
else else
#endif op = singlestepping_skas() ? PTRACE_SINGLESTEP :
op = singlestepping_skas() ? PTRACE_SINGLESTEP : PTRACE_SYSCALL;
PTRACE_SYSCALL;
err = ptrace(op, pid, 0, 0); err = ptrace(op, pid, 0, 0);
if(err) if(err)
panic("userspace - PTRACE_SYSCALL failed, " panic("userspace - PTRACE_SYSCALL failed, "
......
...@@ -6,6 +6,12 @@ ...@@ -6,6 +6,12 @@
#include "linux/sched.h" #include "linux/sched.h"
#include "linux/slab.h" #include "linux/slab.h"
#include "linux/ptrace.h" #include "linux/ptrace.h"
#include "linux/proc_fs.h"
#include "linux/file.h"
#include "linux/errno.h"
#include "linux/init.h"
#include "asm/uaccess.h"
#include "asm/atomic.h"
#include "kern_util.h" #include "kern_util.h"
#include "time_user.h" #include "time_user.h"
#include "signal_user.h" #include "signal_user.h"
...@@ -17,6 +23,59 @@ ...@@ -17,6 +23,59 @@
#include "kern.h" #include "kern.h"
#include "mode.h" #include "mode.h"
#ifdef PTRACE_SYSEMU
static atomic_t using_sysemu;
#endif
void set_using_sysemu(int value)
{
atomic_set(&using_sysemu, value);
}
int get_using_sysemu(void)
{
return atomic_read(&using_sysemu);
}
int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
*eof = 1;
return strlen(buf);
}
int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
{
char tmp[2];
if (copy_from_user(tmp, buf, 1))
return -EFAULT;
if (tmp[0] == '0' || tmp[0] == '1')
set_using_sysemu(tmp[0] - '0');
return count; /*We use the first char, but pretend to write everything*/
}
int __init make_proc_sysemu(void)
{
struct proc_dir_entry *ent;
ent = create_proc_entry("sysemu", 00600, &proc_root);
ent->read_proc = proc_read_sysemu;
ent->write_proc = proc_write_sysemu;
if (ent == NULL)
{
printk("Failed to register /proc/sysemu\n");
return(0);
}
return 0;
}
late_initcall(make_proc_sysemu);
int singlestepping_skas(void) int singlestepping_skas(void)
{ {
int ret = current->ptrace & PT_DTRACE; int ret = current->ptrace & PT_DTRACE;
......
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