diff options
author | Jeff Dike <jdike@addtoit.com> | 2005-01-11 01:53:34 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-01-11 01:53:34 -0800 |
commit | 39b896fd47b9083b29c68dcd1227a17ba2653bae (patch) | |
tree | 051abe2e907e3cb21508e6b5aa4129c89dfdc19c /arch | |
parent | 0c8e90d533d5ea2c60525687404c901a1d563d6d (diff) | |
download | history-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.h | 27 | ||||
-rw-r--r-- | arch/um/kernel/process.c | 1 | ||||
-rw-r--r-- | arch/um/kernel/skas/include/skas.h | 3 | ||||
-rw-r--r-- | arch/um/kernel/skas/process.c | 89 | ||||
-rw-r--r-- | arch/um/kernel/skas/process_kern.c | 8 | ||||
-rw-r--r-- | arch/um/os-Linux/Makefile | 3 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/Makefile | 11 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 115 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/Makefile | 11 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/registers.c | 82 |
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: + */ |