aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2005-01-11 01:53:34 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-11 01:53:34 -0800
commit39b896fd47b9083b29c68dcd1227a17ba2653bae (patch)
tree051abe2e907e3cb21508e6b5aa4129c89dfdc19c /arch
parent0c8e90d533d5ea2c60525687404c901a1d563d6d (diff)
downloadhistory-39b896fd47b9083b29c68dcd1227a17ba2653bae.tar.gz
[PATCH] UML: Factor out register saving and restoring
This moves the register shuffling code into arch/um/os-Linux/sys-$(SUBARCH), making it purely userspace code. It also adds an x86_64 implementation of registers.c. Signed-off-by: Jeff Dike <jdike@addtoit.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/um/include/registers.h27
-rw-r--r--arch/um/kernel/process.c1
-rw-r--r--arch/um/kernel/skas/include/skas.h3
-rw-r--r--arch/um/kernel/skas/process.c89
-rw-r--r--arch/um/kernel/skas/process_kern.c8
-rw-r--r--arch/um/os-Linux/Makefile3
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile11
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c115
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile11
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c82
10 files changed, 255 insertions, 95 deletions
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
new file mode 100644
index 00000000000000..87899df0072f81
--- /dev/null
+++ b/arch/um/include/registers.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#ifndef __REGISTERS_H
+#define __REGISTERS_H
+
+#include "sysdep/ptrace.h"
+
+extern void init_thread_registers(union uml_pt_regs *to);
+extern void save_registers(int pid, union uml_pt_regs *regs);
+extern void restore_registers(int pid, union uml_pt_regs *regs);
+extern void init_registers(int pid);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 7460bd36e534e1..0fca3f073c86b3 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -40,6 +40,7 @@
#ifdef UML_CONFIG_MODE_SKAS
#include "skas.h"
#include "skas_ptrace.h"
+#include "registers.h"
#endif
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
index 2f6eaa37455d79..1c7fcd3effc204 100644
--- a/arch/um/kernel/skas/include/skas.h
+++ b/arch/um/kernel/skas/include/skas.h
@@ -29,10 +29,7 @@ extern int protect(int fd, unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern void user_signal(int sig, union uml_pt_regs *regs);
extern int new_mm(int from);
-extern void save_registers(union uml_pt_regs *regs);
-extern void restore_registers(union uml_pt_regs *regs);
extern void start_userspace(int cpu);
-extern void init_registers(int pid);
#endif
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 247b06d09c59f9..4b368908e5a450 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -28,6 +28,7 @@
#include "skas_ptrace.h"
#include "chan_user.h"
#include "signal_user.h"
+#include "registers.h"
int is_skas_winch(int pid, int fd, void *data)
{
@@ -38,13 +39,6 @@ int is_skas_winch(int pid, int fd, void *data)
return(1);
}
-/* These are set once at boot time and not changed thereafter */
-
-unsigned long exec_regs[FRAME_SIZE];
-unsigned long exec_fp_regs[HOST_FP_SIZE];
-unsigned long exec_fpx_regs[HOST_XFP_SIZE];
-int have_fpx_regs = 1;
-
static void handle_segv(int pid)
{
struct ptrace_faultinfo fault;
@@ -143,7 +137,7 @@ void userspace(union uml_pt_regs *regs)
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(pid, regs);
local_using_sysemu = get_using_sysemu();
@@ -160,7 +154,7 @@ void userspace(union uml_pt_regs *regs)
errno);
regs->skas.is_user = 1;
- save_registers(regs);
+ save_registers(pid, regs);
UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
if(WIFSTOPPED(status)){
@@ -192,7 +186,7 @@ void userspace(union uml_pt_regs *regs)
PT_SYSCALL_NR(regs->skas.regs) = -1;
}
- restore_registers(regs);
+ restore_registers(pid, regs);
/*Now we ended the syscall, so re-read local_using_sysemu.*/
local_using_sysemu = get_using_sysemu();
@@ -243,58 +237,6 @@ void thread_wait(void *sw, void *fb)
siglongjmp(*fork_buf, 1);
}
-static int move_registers(int pid, int int_op, int fp_op,
- union uml_pt_regs *regs, unsigned long *fp_regs)
-{
- if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
- return(-errno);
- if(ptrace(fp_op, pid, 0, fp_regs) < 0)
- return(-errno);
- return(0);
-}
-
-void save_registers(union uml_pt_regs *regs)
-{
- unsigned long *fp_regs;
- int err, fp_op;
-
- if(have_fpx_regs){
- fp_op = PTRACE_GETFPXREGS;
- fp_regs = regs->skas.xfp;
- }
- else {
- fp_op = PTRACE_GETFPREGS;
- fp_regs = regs->skas.fp;
- }
-
- err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
- fp_regs);
- if(err)
- panic("save_registers - saving registers failed, errno = %d\n",
- -err);
-}
-
-void restore_registers(union uml_pt_regs *regs)
-{
- unsigned long *fp_regs;
- int err, fp_op;
-
- if(have_fpx_regs){
- fp_op = PTRACE_SETFPXREGS;
- fp_regs = regs->skas.xfp;
- }
- else {
- fp_op = PTRACE_SETFPREGS;
- fp_regs = regs->skas.fp;
- }
-
- err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
- fp_regs);
- if(err)
- panic("restore_registers - saving registers failed, "
- "errno = %d\n", -err);
-}
-
void switch_threads(void *me, void *next)
{
sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
@@ -394,29 +336,6 @@ void kill_off_processes_skas(void)
os_kill_ptraced_process(userspace_pid[0], 1);
}
-void init_registers(int pid)
-{
- int err;
-
- if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0)
- panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
- errno);
-
- err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
- if(!err)
- return;
-
- have_fpx_regs = 0;
- if(errno != EIO)
- panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
- errno);
-
- err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
- if(err)
- panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
- errno);
-}
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index 648955b0476ff9..5d096ea63b97a6 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -22,6 +22,7 @@
#include "kern.h"
#include "mode.h"
#include "proc_mm.h"
+#include "registers.h"
void *switch_to_skas(void *prev, void *next)
{
@@ -118,12 +119,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
handler = fork_handler;
}
else {
- memcpy(p->thread.regs.regs.skas.regs, exec_regs,
- sizeof(p->thread.regs.regs.skas.regs));
- memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs,
- sizeof(p->thread.regs.regs.skas.fp));
- memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs,
- sizeof(p->thread.regs.regs.skas.xfp));
+ init_thread_registers(&p->thread.regs.regs);
p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler;
}
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 3521466db282a7..af998df18c96c9 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,7 +3,8 @@
# Licensed under the GPL
#
-obj-y = elf_aux.o file.o process.o time.o tty.o user_syms.o drivers/
+obj-y = elf_aux.o file.o process.o time.o tty.o user_syms.o drivers/ \
+ sys-$(SUBARCH)/
USER_OBJS := elf_aux.o file.o process.o time.o tty.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
new file mode 100644
index 00000000000000..bdfa841fca165d
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-$(CONFIG_MODE_SKAS) = registers.o
+
+USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
new file mode 100644
index 00000000000000..cbfbaf2ab78d81
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include "sysdep/ptrace.h"
+#include "uml-config.h"
+#include "skas_ptregs.h"
+#include "registers.h"
+#include "user.h"
+
+/* These are set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[HOST_FRAME_SIZE];
+static unsigned long exec_fp_regs[HOST_FP_SIZE];
+static unsigned long exec_fpx_regs[HOST_XFP_SIZE];
+static int have_fpx_regs = 1;
+
+void init_thread_registers(union uml_pt_regs *to)
+{
+ memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs));
+ memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp));
+ if(have_fpx_regs)
+ memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp));
+}
+
+static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
+ int fp_op, unsigned long *fp_regs)
+{
+ if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
+ return(-errno);
+
+ if(ptrace(fp_op, pid, 0, fp_regs) < 0)
+ return(-errno);
+
+ return(0);
+}
+
+void save_registers(int pid, union uml_pt_regs *regs)
+{
+ unsigned long *fp_regs;
+ int err, fp_op;
+
+ if(have_fpx_regs){
+ fp_op = PTRACE_GETFPXREGS;
+ fp_regs = regs->skas.xfp;
+ }
+ else {
+ fp_op = PTRACE_GETFPREGS;
+ fp_regs = regs->skas.fp;
+ }
+
+ err = move_registers(pid, PTRACE_GETREGS, regs, fp_op, fp_regs);
+ if(err)
+ panic("save_registers - saving registers failed, errno = %d\n",
+ -err);
+}
+
+void restore_registers(int pid, union uml_pt_regs *regs)
+{
+ unsigned long *fp_regs;
+ int err, fp_op;
+
+ if(have_fpx_regs){
+ fp_op = PTRACE_SETFPXREGS;
+ fp_regs = regs->skas.xfp;
+ }
+ else {
+ fp_op = PTRACE_SETFPREGS;
+ fp_regs = regs->skas.fp;
+ }
+
+ err = move_registers(pid, PTRACE_SETREGS, regs, fp_op, fp_regs);
+ if(err)
+ panic("restore_registers - saving registers failed, "
+ "errno = %d\n", -err);
+}
+
+void init_registers(int pid)
+{
+ int err;
+
+ err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
+ err);
+
+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
+ if(!err)
+ return;
+
+ have_fpx_regs = 0;
+ if(err != EIO)
+ panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
+ err);
+
+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
+ err);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
new file mode 100644
index 00000000000000..bdfa841fca165d
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -0,0 +1,11 @@
+#
+# Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-$(CONFIG_MODE_SKAS) = registers.o
+
+USER_OBJS := $(foreach file,$(obj-y),$(obj)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
new file mode 100644
index 00000000000000..31b1f4fa67e0e0
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2004 PathScale, Inc
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include "sysdep/ptrace.h"
+#include "uml-config.h"
+#include "skas_ptregs.h"
+#include "registers.h"
+#include "user.h"
+
+/* These are set once at boot time and not changed thereafter */
+
+static unsigned long exec_regs[HOST_FRAME_SIZE];
+static unsigned long exec_fp_regs[HOST_FP_SIZE];
+
+void init_thread_registers(union uml_pt_regs *to)
+{
+ memcpy(to->skas.regs, exec_regs, sizeof(to->skas.regs));
+ memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp));
+}
+
+static int move_registers(int pid, int int_op, int fp_op,
+ union uml_pt_regs *regs)
+{
+ if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
+ return(-errno);
+
+ if(ptrace(fp_op, pid, 0, regs->skas.fp) < 0)
+ return(-errno);
+
+ return(0);
+}
+
+void save_registers(int pid, union uml_pt_regs *regs)
+{
+ int err;
+
+ err = move_registers(pid, PTRACE_GETREGS, PTRACE_GETFPREGS, regs);
+ if(err)
+ panic("save_registers - saving registers failed, errno = %d\n",
+ -err);
+}
+
+void restore_registers(int pid, union uml_pt_regs *regs)
+{
+ int err;
+
+ err = move_registers(pid, PTRACE_SETREGS, PTRACE_SETFPREGS, regs);
+ if(err)
+ panic("restore_registers - saving registers failed, "
+ "errno = %d\n", -err);
+}
+
+void init_registers(int pid)
+{
+ int err;
+
+ err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
+ err);
+
+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
+ err);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */