mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	uml: throw out CONFIG_MODE_TT
This patchset throws out tt mode, which has been non-functional for a while. This is done in phases, interspersed with code cleanups on the affected files. The removal is done as follows: remove all code, config options, and files which depend on CONFIG_MODE_TT get rid of the CHOOSE_MODE macro, which decided whether to call tt-mode or skas-mode code, and replace invocations with their skas portions replace all now-trivial procedures with their skas equivalents There are now a bunch of now-redundant pieces of data structures, including mode-specific pieces of the thread structure, pt_regs, and mm_context. These are all replaced with their skas-specific contents. As part of the ongoing style compliance project, I made a style pass over all files that were changed. There are three such patches, one for each phase, covering the files affected by that phase but no later ones. I noticed that we weren't freeing the LDT state associated with a process when it exited, so that's fixed in one of the later patches. The last patch is a tidying patch which I've had for a while, but which caused inexplicable crashes under tt mode. Since that is no longer a problem, this can now go in. This patch: Start getting rid of tt mode support. This patch throws out CONFIG_MODE_TT and all config options, code, and files which depend on it. CONFIG_MODE_SKAS is gone and everything that depends on it is included unconditionally. The few changed lines are in re-written Kconfig help, lines which needed something skas-related removed from them, and a few more which weren't strictly deletions. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									a1ff5878d2
								
							
						
					
					
						commit
						42fda66387
					
				
					 87 changed files with 34 additions and 4203 deletions
				
			
		| 
						 | 
					@ -62,55 +62,16 @@ config IRQ_RELEASE_METHOD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
menu "UML-specific options"
 | 
					menu "UML-specific options"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config MODE_TT
 | 
					 | 
				
			||||||
	bool "Tracing thread support (DEPRECATED)"
 | 
					 | 
				
			||||||
	default n
 | 
					 | 
				
			||||||
	depends on BROKEN
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	This option controls whether tracing thread support is compiled
 | 
					 | 
				
			||||||
	into UML. This option is largely obsolete, given that skas0 provides
 | 
					 | 
				
			||||||
	skas security and performance without needing to patch the host.
 | 
					 | 
				
			||||||
	It is safe to say 'N' here; saying 'Y' may cause additional problems
 | 
					 | 
				
			||||||
	with the resulting binary even if you run UML in SKAS mode, and running
 | 
					 | 
				
			||||||
	in TT mode is strongly *NOT RECOMMENDED*.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config STATIC_LINK
 | 
					config STATIC_LINK
 | 
				
			||||||
	bool "Force a static link"
 | 
						bool "Force a static link"
 | 
				
			||||||
	default n
 | 
						default n
 | 
				
			||||||
	depends on !MODE_TT
 | 
					 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	If CONFIG_MODE_TT is disabled, then this option gives you the ability
 | 
						This option gives you the ability to force a static link of UML.
 | 
				
			||||||
	to force a static link of UML.  Normally, if only skas mode is built
 | 
						Normally, UML is linked as a shared binary.  This is inconvenient for
 | 
				
			||||||
	in to UML, it will be linked as a shared binary.  This is inconvenient
 | 
						use in a chroot jail.  So, if you intend to run UML inside a chroot,
 | 
				
			||||||
	for use in a chroot jail.  So, if you intend to run UML inside a
 | 
						you probably want to say Y here.
 | 
				
			||||||
	chroot, and you disable CONFIG_MODE_TT, you probably want to say Y
 | 
					 | 
				
			||||||
	here.
 | 
					 | 
				
			||||||
	Additionally, this option enables using higher memory spaces (up to
 | 
						Additionally, this option enables using higher memory spaces (up to
 | 
				
			||||||
	2.75G) for UML - disabling CONFIG_MODE_TT and enabling this option leads
 | 
						2.75G) for UML.
 | 
				
			||||||
	to best results for this.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config KERNEL_HALF_GIGS
 | 
					 | 
				
			||||||
	int "Kernel address space size (in .5G units)"
 | 
					 | 
				
			||||||
	default "1"
 | 
					 | 
				
			||||||
	depends on MODE_TT
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
        This determines the amount of address space that UML will allocate for
 | 
					 | 
				
			||||||
        its own, measured in half Gigabyte units.  The default is 1.
 | 
					 | 
				
			||||||
        Change this only if you need to boot UML with an unusually large amount
 | 
					 | 
				
			||||||
        of physical memory.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config MODE_SKAS
 | 
					 | 
				
			||||||
	bool "Separate Kernel Address Space support" if MODE_TT
 | 
					 | 
				
			||||||
	default y
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	This option controls whether skas (separate kernel address space)
 | 
					 | 
				
			||||||
	support is compiled in.
 | 
					 | 
				
			||||||
	Unless you have specific needs to use TT mode (which applies almost only
 | 
					 | 
				
			||||||
	to developers), you should say Y here.
 | 
					 | 
				
			||||||
	SKAS mode will make use of the SKAS3 patch if it is applied on the host
 | 
					 | 
				
			||||||
	(and your UML will run in SKAS3 mode), but if no SKAS patch is applied
 | 
					 | 
				
			||||||
	on the host it will run in SKAS0 mode, which is anyway faster than TT
 | 
					 | 
				
			||||||
	mode.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
source "arch/um/Kconfig.arch"
 | 
					source "arch/um/Kconfig.arch"
 | 
				
			||||||
source "mm/Kconfig"
 | 
					source "mm/Kconfig"
 | 
				
			||||||
| 
						 | 
					@ -118,7 +79,7 @@ source "mm/Kconfig"
 | 
				
			||||||
config LD_SCRIPT_STATIC
 | 
					config LD_SCRIPT_STATIC
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
	default y
 | 
						default y
 | 
				
			||||||
	depends on MODE_TT || STATIC_LINK
 | 
						depends on STATIC_LINK
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config LD_SCRIPT_DYN
 | 
					config LD_SCRIPT_DYN
 | 
				
			||||||
	bool
 | 
						bool
 | 
				
			||||||
| 
						 | 
					@ -220,7 +181,7 @@ config SMP
 | 
				
			||||||
	bool "Symmetric multi-processing support (EXPERIMENTAL)"
 | 
						bool "Symmetric multi-processing support (EXPERIMENTAL)"
 | 
				
			||||||
	default n
 | 
						default n
 | 
				
			||||||
	#SMP_BROKEN is for x86_64.
 | 
						#SMP_BROKEN is for x86_64.
 | 
				
			||||||
	depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
 | 
						depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
	This option enables UML SMP support.
 | 
						This option enables UML SMP support.
 | 
				
			||||||
	It is NOT related to having a real SMP box. Not directly, at least.
 | 
						It is NOT related to having a real SMP box. Not directly, at least.
 | 
				
			||||||
| 
						 | 
					@ -258,11 +219,6 @@ config NEST_LEVEL
 | 
				
			||||||
        inside another UML, set CONFIG_NEST_LEVEL to one more than the host
 | 
					        inside another UML, set CONFIG_NEST_LEVEL to one more than the host
 | 
				
			||||||
        UML.
 | 
					        UML.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to
 | 
					 | 
				
			||||||
        greater than one, then the guest UML should have its CONFIG_NEST_LEVEL
 | 
					 | 
				
			||||||
        set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
 | 
					 | 
				
			||||||
        Only change this if you are running nested UMLs.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config HIGHMEM
 | 
					config HIGHMEM
 | 
				
			||||||
	bool "Highmem support (EXPERIMENTAL)"
 | 
						bool "Highmem support (EXPERIMENTAL)"
 | 
				
			||||||
	depends on !64BIT && EXPERIMENTAL
 | 
						depends on !64BIT && EXPERIMENTAL
 | 
				
			||||||
| 
						 | 
					@ -271,9 +227,9 @@ config HIGHMEM
 | 
				
			||||||
	This was used to allow UML to run with big amounts of memory.
 | 
						This was used to allow UML to run with big amounts of memory.
 | 
				
			||||||
	Currently it is unstable, so if unsure say N.
 | 
						Currently it is unstable, so if unsure say N.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	To use big amounts of memory, it is recommended to disable TT mode (i.e.
 | 
						To use big amounts of memory, it is recommended enable static
 | 
				
			||||||
	CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) -
 | 
						linking (i.e. CONFIG_STATIC_LINK) - this should allow the
 | 
				
			||||||
	this should allow the guest to use up to 2.75G of memory.
 | 
						guest to use up to 2.75G of memory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config KERNEL_STACK_ORDER
 | 
					config KERNEL_STACK_ORDER
 | 
				
			||||||
	int "Kernel stack size order"
 | 
						int "Kernel stack size order"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,8 +65,6 @@ config XTERM_CHAN
 | 
				
			||||||
        This option enables support for attaching UML consoles and serial
 | 
					        This option enables support for attaching UML consoles and serial
 | 
				
			||||||
        lines to xterms.  Each UML device so assigned will be brought up in
 | 
					        lines to xterms.  Each UML device so assigned will be brought up in
 | 
				
			||||||
        its own xterm.
 | 
					        its own xterm.
 | 
				
			||||||
        If you disable this option, then CONFIG_PT_PROXY will be disabled as
 | 
					 | 
				
			||||||
        well, since UML's gdb currently requires an xterm.
 | 
					 | 
				
			||||||
        It is safe to say 'Y' here.
 | 
					        It is safe to say 'Y' here.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config NOCONFIG_CHAN
 | 
					config NOCONFIG_CHAN
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,28 +2,9 @@ menu "Kernel hacking"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
source "lib/Kconfig.debug"
 | 
					source "lib/Kconfig.debug"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config CMDLINE_ON_HOST
 | 
					 | 
				
			||||||
	bool "Show command line arguments on the host in TT mode"
 | 
					 | 
				
			||||||
	depends on MODE_TT
 | 
					 | 
				
			||||||
	default !DEBUG_INFO
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	This controls whether arguments in guest processes should be shown on
 | 
					 | 
				
			||||||
	the host's ps output.
 | 
					 | 
				
			||||||
	Enabling this option hinders debugging on some recent GDB versions
 | 
					 | 
				
			||||||
	(because GDB gets "confused" when we do an execvp()). So probably you
 | 
					 | 
				
			||||||
	should disable it.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config PT_PROXY
 | 
					 | 
				
			||||||
	bool "Enable ptrace proxy"
 | 
					 | 
				
			||||||
	depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
 | 
					 | 
				
			||||||
	help
 | 
					 | 
				
			||||||
	This option enables a debugging interface which allows gdb to debug
 | 
					 | 
				
			||||||
	the kernel without needing to actually attach to kernel threads.
 | 
					 | 
				
			||||||
	If you want to do kernel debugging, say Y here; otherwise say N.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
config GPROF
 | 
					config GPROF
 | 
				
			||||||
	bool "Enable gprof support"
 | 
						bool "Enable gprof support"
 | 
				
			||||||
	depends on DEBUG_INFO && MODE_SKAS && !MODE_TT
 | 
						depends on DEBUG_INFO
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
        This allows profiling of a User-Mode Linux kernel with the gprof
 | 
					        This allows profiling of a User-Mode Linux kernel with the gprof
 | 
				
			||||||
        utility.
 | 
					        utility.
 | 
				
			||||||
| 
						 | 
					@ -36,7 +17,7 @@ config GPROF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config GCOV
 | 
					config GCOV
 | 
				
			||||||
	bool "Enable gcov support"
 | 
						bool "Enable gcov support"
 | 
				
			||||||
	depends on DEBUG_INFO && MODE_SKAS
 | 
						depends on DEBUG_INFO
 | 
				
			||||||
	help
 | 
						help
 | 
				
			||||||
        This option allows developers to retrieve coverage data from a UML
 | 
					        This option allows developers to retrieve coverage data from a UML
 | 
				
			||||||
        session.
 | 
					        session.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,18 +31,9 @@ SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
 | 
				
			||||||
ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
 | 
					ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
 | 
				
			||||||
	$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
 | 
						$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
um-modes-$(CONFIG_MODE_TT) += tt
 | 
					MODE_INCLUDE	+= -I$(srctree)/$(ARCH_DIR)/include/skas
 | 
				
			||||||
um-modes-$(CONFIG_MODE_SKAS) += skas
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
MODE_INCLUDE	+= $(foreach mode,$(um-modes-y),\
 | 
					include $(srctree)/$(ARCH_DIR)/Makefile-skas
 | 
				
			||||||
		   -I$(srctree)/$(ARCH_DIR)/include/$(mode))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MAKEFILES-INCL	+= $(foreach mode,$(um-modes-y),\
 | 
					 | 
				
			||||||
		   $(srctree)/$(ARCH_DIR)/Makefile-$(mode))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ifneq ($(MAKEFILES-INCL),)
 | 
					 | 
				
			||||||
  include $(MAKEFILES-INCL)
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
ARCH_INCLUDE	:= -I$(ARCH_DIR)/include
 | 
					ARCH_INCLUDE	:= -I$(ARCH_DIR)/include
 | 
				
			||||||
ifneq ($(KBUILD_SRC),)
 | 
					ifneq ($(KBUILD_SRC),)
 | 
				
			||||||
| 
						 | 
					@ -89,9 +80,8 @@ CFLAGS += $(call cc-option,-fno-unit-at-a-time,)
 | 
				
			||||||
# included; the values here are meaningless
 | 
					# included; the values here are meaningless
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_NEST_LEVEL ?= 0
 | 
					CONFIG_NEST_LEVEL ?= 0
 | 
				
			||||||
CONFIG_KERNEL_HALF_GIGS ?= 0
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
 | 
					SIZE = ($(CONFIG_NEST_LEVEL) * 0x20000000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PHONY += linux
 | 
					PHONY += linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,7 +114,6 @@ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,)
 | 
				
			||||||
	$(call cc-option, -fno-stack-protector,) \
 | 
						$(call cc-option, -fno-stack-protector,) \
 | 
				
			||||||
	$(call cc-option, -fno-stack-protector-all,)
 | 
						$(call cc-option, -fno-stack-protector-all,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CPP_MODE-$(CONFIG_MODE_TT) := -DMODE_TT
 | 
					 | 
				
			||||||
CONFIG_KERNEL_STACK_ORDER ?= 2
 | 
					CONFIG_KERNEL_STACK_ORDER ?= 2
 | 
				
			||||||
STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
 | 
					STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,11 +121,8 @@ ifndef START
 | 
				
			||||||
  START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] )
 | 
					  START = $(shell echo $$[ $(TOP_ADDR) - $(SIZE) ] )
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \
 | 
					CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
 | 
				
			||||||
	-DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
 | 
						-DELF_FORMAT="$(ELF_FORMAT)" -DKERNEL_STACK_SIZE=$(STACK_SIZE)
 | 
				
			||||||
	-DELF_FORMAT="$(ELF_FORMAT)" $(CPP_MODE-y) \
 | 
					 | 
				
			||||||
	-DKERNEL_STACK_SIZE=$(STACK_SIZE) \
 | 
					 | 
				
			||||||
	-DUNMAP_PATH=arch/um/sys-$(SUBARCH)/unmap.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#The wrappers will select whether using "malloc" or the kernel allocator.
 | 
					#The wrappers will select whether using "malloc" or the kernel allocator.
 | 
				
			||||||
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 | 
					LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,11 +2,7 @@ core-y += arch/um/sys-i386/ arch/x86/crypto/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TOP_ADDR := $(CONFIG_TOP_ADDR)
 | 
					TOP_ADDR := $(CONFIG_TOP_ADDR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ifeq ($(CONFIG_MODE_SKAS),y)
 | 
					START := 0x8048000
 | 
				
			||||||
  ifneq ($(CONFIG_MODE_TT),y)
 | 
					 | 
				
			||||||
     START := 0x8048000
 | 
					 | 
				
			||||||
  endif
 | 
					 | 
				
			||||||
endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
LDFLAGS			+= -m elf_i386
 | 
					LDFLAGS			+= -m elf_i386
 | 
				
			||||||
ELF_ARCH		:= $(SUBARCH)
 | 
					ELF_ARCH		:= $(SUBARCH)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,9 +12,7 @@ CONFIG_IRQ_RELEASE_METHOD=y
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# UML-specific options
 | 
					# UML-specific options
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# CONFIG_MODE_TT is not set
 | 
					 | 
				
			||||||
# CONFIG_STATIC_LINK is not set
 | 
					# CONFIG_STATIC_LINK is not set
 | 
				
			||||||
CONFIG_MODE_SKAS=y
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Host processor type and features
 | 
					# Host processor type and features
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -735,8 +735,6 @@ void mconsole_sysrq(struct mc_request *req)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void stack_proc(void *arg)
 | 
					static void stack_proc(void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct task_struct *from = current, *to = arg;
 | 
						struct task_struct *from = current, *to = arg;
 | 
				
			||||||
| 
						 | 
					@ -750,7 +748,7 @@ static void stack_proc(void *arg)
 | 
				
			||||||
 *  Dumps a stacks registers to the linux console.
 | 
					 *  Dumps a stacks registers to the linux console.
 | 
				
			||||||
 *  Usage stack <pid>.
 | 
					 *  Usage stack <pid>.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void do_stack_trace(struct mc_request *req)
 | 
					void mconsole_stack(struct mc_request *req)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char *ptr = req->request.data;
 | 
						char *ptr = req->request.data;
 | 
				
			||||||
	int pid_requested= -1;
 | 
						int pid_requested= -1;
 | 
				
			||||||
| 
						 | 
					@ -781,17 +779,6 @@ static void do_stack_trace(struct mc_request *req)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	with_console(req, stack_proc, to);
 | 
						with_console(req, stack_proc, to);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* CONFIG_MODE_SKAS */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void mconsole_stack(struct mc_request *req)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	/* This command doesn't work in TT mode, so let's check and then
 | 
					 | 
				
			||||||
	 * get out of here
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	CHOOSE_MODE(mconsole_reply(req, "Sorry, this doesn't work in TT mode",
 | 
					 | 
				
			||||||
				   1, 0),
 | 
					 | 
				
			||||||
		    do_stack_trace(req));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Changed by mconsole_setup, which is __setup, and called before SMP is
 | 
					/* Changed by mconsole_setup, which is __setup, and called before SMP is
 | 
				
			||||||
 * active.
 | 
					 * active.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,6 @@ extern unsigned long _unprotected_end;
 | 
				
			||||||
extern unsigned long brk_start;
 | 
					extern unsigned long brk_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int linux_main(int argc, char **argv);
 | 
					extern int linux_main(int argc, char **argv);
 | 
				
			||||||
extern void set_cmdline(char *cmd);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void (*sig_info[])(int, union uml_pt_regs *);
 | 
					extern void (*sig_info[])(int, union uml_pt_regs *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,26 +8,8 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "uml-config.h"
 | 
					#include "uml-config.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(UML_CONFIG_MODE_TT) && defined(UML_CONFIG_MODE_SKAS)
 | 
					 | 
				
			||||||
#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int mode_tt;
 | 
					 | 
				
			||||||
static inline void *__choose_mode(void *tt, void *skas) {
 | 
					 | 
				
			||||||
	return mode_tt ? tt : skas;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define __CHOOSE_MODE(tt, skas) (*( (typeof(tt) *) __choose_mode(&(tt), &(skas))))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#elif defined(UML_CONFIG_MODE_SKAS)
 | 
					 | 
				
			||||||
#define CHOOSE_MODE(tt, skas) (skas)
 | 
					#define CHOOSE_MODE(tt, skas) (skas)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#elif defined(UML_CONFIG_MODE_TT)
 | 
					 | 
				
			||||||
#define CHOOSE_MODE(tt, skas) (tt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#error CONFIG_MODE_SKAS and CONFIG_MODE_TT are both disabled
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CHOOSE_MODE_PROC(tt, skas, args...) \
 | 
					#define CHOOSE_MODE_PROC(tt, skas, args...) \
 | 
				
			||||||
	CHOOSE_MODE(tt(args), skas(args))
 | 
						CHOOSE_MODE(tt(args), skas(args))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,6 @@
 | 
				
			||||||
/* for use by sys-$SUBARCH/kernel-offsets.c */
 | 
					/* for use by sys-$SUBARCH/kernel-offsets.c */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 | 
					DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
 | 
					OFFSET(HOST_TASK_REGS, task_struct, thread.regs);
 | 
				
			||||||
OFFSET(HOST_TASK_PID, task_struct, pid);
 | 
					OFFSET(HOST_TASK_PID, task_struct, pid);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,8 +30,4 @@ extern void deactivate_fd(int fd, int irqnum);
 | 
				
			||||||
extern int deactivate_all_fds(void);
 | 
					extern int deactivate_all_fds(void);
 | 
				
			||||||
extern int activate_ipi(int fd, int pid);
 | 
					extern int activate_ipi(int fd, int pid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
extern void forward_interrupts(int pid);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,9 +34,6 @@ extern int nsyscalls;
 | 
				
			||||||
	UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
 | 
						UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
 | 
					extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
extern unsigned long stack_sp(unsigned long page);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
extern int kernel_thread_proc(void *data);
 | 
					extern int kernel_thread_proc(void *data);
 | 
				
			||||||
extern void syscall_segv(int sig);
 | 
					extern void syscall_segv(int sig);
 | 
				
			||||||
extern int current_pid(void);
 | 
					extern int current_pid(void);
 | 
				
			||||||
| 
						 | 
					@ -82,9 +79,6 @@ extern void check_stack_overflow(void *ptr);
 | 
				
			||||||
extern void relay_signal(int sig, union uml_pt_regs *regs);
 | 
					extern void relay_signal(int sig, union uml_pt_regs *regs);
 | 
				
			||||||
extern int user_context(unsigned long sp);
 | 
					extern int user_context(unsigned long sp);
 | 
				
			||||||
extern void timer_irq(union uml_pt_regs *regs);
 | 
					extern void timer_irq(union uml_pt_regs *regs);
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
extern void unprotect_stack(unsigned long stack);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
extern void do_uml_exitcalls(void);
 | 
					extern void do_uml_exitcalls(void);
 | 
				
			||||||
extern int attach_debugger(int idle_pid, int pid, int stop);
 | 
					extern int attach_debugger(int idle_pid, int pid, int stop);
 | 
				
			||||||
extern int config_gdb(char *str);
 | 
					extern int config_gdb(char *str);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,25 +6,6 @@
 | 
				
			||||||
#ifndef __MODE_H__
 | 
					#ifndef __MODE_H__
 | 
				
			||||||
#define __MODE_H__
 | 
					#define __MODE_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "uml-config.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#include "mode-tt.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "mode-skas.h"
 | 
					#include "mode-skas.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,12 +6,6 @@
 | 
				
			||||||
#ifndef __MODE_KERN_H__
 | 
					#ifndef __MODE_KERN_H__
 | 
				
			||||||
#define __MODE_KERN_H__
 | 
					#define __MODE_KERN_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#include "mode_kern_tt.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "mode_kern_skas.h"
 | 
					#include "mode_kern_skas.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,11 +178,7 @@ extern void check_host_supports_tls(int *supports_tls, int *tls_min);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Make sure they are clear when running in TT mode. Required by
 | 
					/* Make sure they are clear when running in TT mode. Required by
 | 
				
			||||||
 * SEGV_MAYBE_FIXABLE */
 | 
					 * SEGV_MAYBE_FIXABLE */
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
 | 
					#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define clear_can_do_skas() do {} while (0)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* mem.c */
 | 
					/* mem.c */
 | 
				
			||||||
extern int create_mem_file(unsigned long long len);
 | 
					extern int create_mem_file(unsigned long long len);
 | 
				
			||||||
| 
						 | 
					@ -193,18 +189,11 @@ extern int os_process_parent(int pid);
 | 
				
			||||||
extern void os_stop_process(int pid);
 | 
					extern void os_stop_process(int pid);
 | 
				
			||||||
extern void os_kill_process(int pid, int reap_child);
 | 
					extern void os_kill_process(int pid, int reap_child);
 | 
				
			||||||
extern void os_kill_ptraced_process(int pid, int reap_child);
 | 
					extern void os_kill_ptraced_process(int pid, int reap_child);
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
extern void os_usr1_process(int pid);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
extern long os_ptrace_ldt(long pid, long addr, long data);
 | 
					extern long os_ptrace_ldt(long pid, long addr, long data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int os_getpid(void);
 | 
					extern int os_getpid(void);
 | 
				
			||||||
extern int os_getpgrp(void);
 | 
					extern int os_getpgrp(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
 | 
					 | 
				
			||||||
extern void stop(void);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
extern void init_new_thread_signals(void);
 | 
					extern void init_new_thread_signals(void);
 | 
				
			||||||
extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
 | 
					extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,18 +206,6 @@ extern int os_drop_memory(void *addr, int length);
 | 
				
			||||||
extern int can_drop_memory(void);
 | 
					extern int can_drop_memory(void);
 | 
				
			||||||
extern void os_flush_stdout(void);
 | 
					extern void os_flush_stdout(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* tt.c
 | 
					 | 
				
			||||||
 * for tt mode only (will be deleted in future...)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
extern void forward_ipi(int fd, int pid);
 | 
					 | 
				
			||||||
extern void kill_child_dead(int pid);
 | 
					 | 
				
			||||||
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
 | 
					 | 
				
			||||||
extern int protect_memory(unsigned long addr, unsigned long len,
 | 
					 | 
				
			||||||
			  int r, int w, int x, int must_succeed);
 | 
					 | 
				
			||||||
extern void forward_pending_sigio(int target);
 | 
					 | 
				
			||||||
extern int start_fork_tramp(void *arg, unsigned long temp_stack,
 | 
					 | 
				
			||||||
			    int clone_flags, int (*tramp)(void *));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* uaccess.c */
 | 
					/* uaccess.c */
 | 
				
			||||||
extern unsigned long __do_user_copy(void *to, const void *from, int n,
 | 
					extern unsigned long __do_user_copy(void *to, const void *from, int n,
 | 
				
			||||||
				    void **fault_addr, void **fault_catcher,
 | 
									    void **fault_addr, void **fault_catcher,
 | 
				
			||||||
| 
						 | 
					@ -281,9 +258,6 @@ extern void os_dump_core(void);
 | 
				
			||||||
extern void switch_timers(int to_real);
 | 
					extern void switch_timers(int to_real);
 | 
				
			||||||
extern void idle_sleep(int secs);
 | 
					extern void idle_sleep(int secs);
 | 
				
			||||||
extern int set_interval(int is_virtual);
 | 
					extern int set_interval(int is_virtual);
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
extern void enable_timer(void);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
extern void disable_timer(void);
 | 
					extern void disable_timer(void);
 | 
				
			||||||
extern void uml_idle_timer(void);
 | 
					extern void uml_idle_timer(void);
 | 
				
			||||||
extern unsigned long long os_nsecs(void);
 | 
					extern unsigned long long os_nsecs(void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,12 +14,7 @@
 | 
				
			||||||
#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
 | 
					#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
 | 
				
			||||||
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
 | 
					#define MAX_REG_OFFSET (UM_FRAME_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_PT_PROXY
 | 
					 | 
				
			||||||
extern void update_debugregs(int seq);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
static inline void update_debugregs(int seq) {}
 | 
					static inline void update_debugregs(int seq) {}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* syscall emulation path in ptrace */
 | 
					/* syscall emulation path in ptrace */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,12 +26,6 @@ void set_using_sysemu(int value);
 | 
				
			||||||
int get_using_sysemu(void);
 | 
					int get_using_sysemu(void);
 | 
				
			||||||
extern int sysemu_supported;
 | 
					extern int sysemu_supported;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#include "sysdep/sc.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "skas_ptregs.h"
 | 
					#include "skas_ptregs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define REGS_IP(r) ((r)[HOST_IP])
 | 
					#define REGS_IP(r) ((r)[HOST_IP])
 | 
				
			||||||
| 
						 | 
					@ -60,20 +49,11 @@ extern int sysemu_supported;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
 | 
					#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifndef PTRACE_SYSEMU_SINGLESTEP
 | 
					#ifndef PTRACE_SYSEMU_SINGLESTEP
 | 
				
			||||||
#define PTRACE_SYSEMU_SINGLESTEP 32
 | 
					#define PTRACE_SYSEMU_SINGLESTEP 32
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
union uml_pt_regs {
 | 
					union uml_pt_regs {
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
	struct tt_regs {
 | 
					 | 
				
			||||||
		long syscall;
 | 
					 | 
				
			||||||
		void *sc;
 | 
					 | 
				
			||||||
                struct faultinfo faultinfo;
 | 
					 | 
				
			||||||
	} tt;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
	struct skas_regs {
 | 
						struct skas_regs {
 | 
				
			||||||
		unsigned long regs[MAX_REG_NR];
 | 
							unsigned long regs[MAX_REG_NR];
 | 
				
			||||||
		unsigned long fp[HOST_FP_SIZE];
 | 
							unsigned long fp[HOST_FP_SIZE];
 | 
				
			||||||
| 
						 | 
					@ -82,13 +62,10 @@ union uml_pt_regs {
 | 
				
			||||||
		long syscall;
 | 
							long syscall;
 | 
				
			||||||
		int is_user;
 | 
							int is_user;
 | 
				
			||||||
	} skas;
 | 
						} skas;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EMPTY_UML_PT_REGS { }
 | 
					#define EMPTY_UML_PT_REGS { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int mode_tt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define UPT_SC(r) ((r)->tt.sc)
 | 
					#define UPT_SC(r) ((r)->tt.sc)
 | 
				
			||||||
#define UPT_IP(r) \
 | 
					#define UPT_IP(r) \
 | 
				
			||||||
	__CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
 | 
						__CHOOSE_MODE(SC_IP(UPT_SC(r)), REGS_IP((r)->skas.regs))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,11 +30,7 @@
 | 
				
			||||||
#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
 | 
					#define SEGV_IS_FIXABLE(fi)	((fi)->trap_no == 14)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
 | 
					/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
 | 
					#define SEGV_MAYBE_FIXABLE(fi)	((fi)->trap_no == 0 && ptrace_faultinfo)
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define SEGV_MAYBE_FIXABLE(fi)	0
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern unsigned long *sc_sigmask(void *sc_ptr);
 | 
					extern unsigned long *sc_sigmask(void *sc_ptr);
 | 
				
			||||||
extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
 | 
					extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,8 +4,5 @@
 | 
				
			||||||
#include <kern_constants.h>
 | 
					#include <kern_constants.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS]))
 | 
					#define TASK_DEBUGREGS(task) ((unsigned long *) &(((char *) (task))[HOST_TASK_DEBUGREGS]))
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID]))
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2003 PathScale, Inc.
 | 
					 * Copyright 2003 PathScale, Inc.
 | 
				
			||||||
 | 
					 * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the GPL
 | 
					 * Licensed under the GPL
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -14,11 +15,6 @@
 | 
				
			||||||
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
 | 
					#define MAX_REG_OFFSET (UM_FRAME_SIZE)
 | 
				
			||||||
#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
 | 
					#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#include "sysdep/sc.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "skas_ptregs.h"
 | 
					#include "skas_ptregs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define REGS_IP(r) ((r)[HOST_IP])
 | 
					#define REGS_IP(r) ((r)[HOST_IP])
 | 
				
			||||||
| 
						 | 
					@ -88,21 +84,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define REGS_ERR(r) ((r)->fault_type)
 | 
					#define REGS_ERR(r) ((r)->fault_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "choose-mode.h"
 | 
					#include "choose-mode.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XXX */
 | 
					/* XXX */
 | 
				
			||||||
union uml_pt_regs {
 | 
					union uml_pt_regs {
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
	struct tt_regs {
 | 
					 | 
				
			||||||
		long syscall;
 | 
					 | 
				
			||||||
		unsigned long orig_rax;
 | 
					 | 
				
			||||||
		void *sc;
 | 
					 | 
				
			||||||
                struct faultinfo faultinfo;
 | 
					 | 
				
			||||||
	} tt;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
	struct skas_regs {
 | 
						struct skas_regs {
 | 
				
			||||||
		unsigned long regs[MAX_REG_NR];
 | 
							unsigned long regs[MAX_REG_NR];
 | 
				
			||||||
		unsigned long fp[HOST_FP_SIZE];
 | 
							unsigned long fp[HOST_FP_SIZE];
 | 
				
			||||||
| 
						 | 
					@ -110,14 +95,10 @@ union uml_pt_regs {
 | 
				
			||||||
		long syscall;
 | 
							long syscall;
 | 
				
			||||||
		int is_user;
 | 
							int is_user;
 | 
				
			||||||
	} skas;
 | 
						} skas;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define EMPTY_UML_PT_REGS { }
 | 
					#define EMPTY_UML_PT_REGS { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* XXX */
 | 
					 | 
				
			||||||
extern int mode_tt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define UPT_RBX(r) __CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs))
 | 
					#define UPT_RBX(r) __CHOOSE_MODE(SC_RBX(UPT_SC(r)), REGS_RBX((r)->skas.regs))
 | 
				
			||||||
#define UPT_RCX(r) __CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs))
 | 
					#define UPT_RCX(r) __CHOOSE_MODE(SC_RCX(UPT_SC(r)), REGS_RCX((r)->skas.regs))
 | 
				
			||||||
#define UPT_RDX(r) __CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs))
 | 
					#define UPT_RDX(r) __CHOOSE_MODE(SC_RDX(UPT_SC(r)), REGS_RDX((r)->skas.regs))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,4 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <kern_constants.h>
 | 
					#include <kern_constants.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#define TASK_EXTERN_PID(task) *((int *) &(((char *) (task))[HOST_TASK_EXTERN_PID]))
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,18 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2000, 2001, 2002  Jeff Dike (jdike@karaya.com) and
 | 
					 | 
				
			||||||
 * Lars Brinkhoff.
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __UML_TT_DEBUG_H
 | 
					 | 
				
			||||||
#define __UML_TT_DEBUG_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int debugger_proxy(int status, pid_t pid);
 | 
					 | 
				
			||||||
extern void child_proxy(pid_t pid, int status);
 | 
					 | 
				
			||||||
extern void init_proxy (pid_t pid, int waiting, int status);
 | 
					 | 
				
			||||||
extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
 | 
					 | 
				
			||||||
extern void fake_child_exit(void);
 | 
					 | 
				
			||||||
extern int gdb_config(char *str);
 | 
					 | 
				
			||||||
extern int gdb_remove(int unused);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,12 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __TT_MMU_H
 | 
					 | 
				
			||||||
#define __TT_MMU_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct mmu_context_tt {
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,23 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __MODE_TT_H__
 | 
					 | 
				
			||||||
#define __MODE_TT_H__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int tracing_pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int tracer(int (*init_proc)(void *), void *sp);
 | 
					 | 
				
			||||||
extern void sig_handler_common_tt(int sig, void *sc);
 | 
					 | 
				
			||||||
extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
 | 
					 | 
				
			||||||
extern void reboot_tt(void);
 | 
					 | 
				
			||||||
extern void halt_tt(void);
 | 
					 | 
				
			||||||
extern int is_tracer_winch(int pid, int fd, void *data);
 | 
					 | 
				
			||||||
extern void kill_off_processes_tt(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,40 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __TT_MODE_KERN_H__
 | 
					 | 
				
			||||||
#define __TT_MODE_KERN_H__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/sched.h"
 | 
					 | 
				
			||||||
#include "asm/page.h"
 | 
					 | 
				
			||||||
#include "asm/ptrace.h"
 | 
					 | 
				
			||||||
#include "asm/uaccess.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern void switch_to_tt(void *prev, void *next);
 | 
					 | 
				
			||||||
extern void flush_thread_tt(void);
 | 
					 | 
				
			||||||
extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
 | 
					 | 
				
			||||||
			   unsigned long esp);
 | 
					 | 
				
			||||||
extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
 | 
					 | 
				
			||||||
			  unsigned long stack_top, struct task_struct *p,
 | 
					 | 
				
			||||||
			  struct pt_regs *regs);
 | 
					 | 
				
			||||||
extern void release_thread_tt(struct task_struct *task);
 | 
					 | 
				
			||||||
extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
 | 
					 | 
				
			||||||
extern void init_idle_tt(void);
 | 
					 | 
				
			||||||
extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end);
 | 
					 | 
				
			||||||
extern void flush_tlb_kernel_vm_tt(void);
 | 
					 | 
				
			||||||
extern void __flush_tlb_one_tt(unsigned long addr);
 | 
					 | 
				
			||||||
extern void flush_tlb_range_tt(struct vm_area_struct *vma,
 | 
					 | 
				
			||||||
			       unsigned long start, unsigned long end);
 | 
					 | 
				
			||||||
extern void flush_tlb_mm_tt(struct mm_struct *mm);
 | 
					 | 
				
			||||||
extern void force_flush_all_tt(void);
 | 
					 | 
				
			||||||
extern long execute_syscall_tt(void *r);
 | 
					 | 
				
			||||||
extern void before_mem_tt(unsigned long brk_start);
 | 
					 | 
				
			||||||
extern unsigned long set_task_sizes_tt(unsigned long *task_size_out);
 | 
					 | 
				
			||||||
extern int start_uml_tt(void);
 | 
					 | 
				
			||||||
extern int external_pid_tt(struct task_struct *task);
 | 
					 | 
				
			||||||
extern int thread_pid_tt(struct task_struct *task);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define kmem_end_tt (host_task_size - ABOVE_KMEM)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,37 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __TT_H__
 | 
					 | 
				
			||||||
#define __TT_H__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int gdb_pid;
 | 
					 | 
				
			||||||
extern int debug;
 | 
					 | 
				
			||||||
extern int debug_stop;
 | 
					 | 
				
			||||||
extern int debug_trace;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int honeypot;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int fork_tramp(void *sig_stack);
 | 
					 | 
				
			||||||
extern int do_proc_op(void *t, int proc_id);
 | 
					 | 
				
			||||||
extern int tracer(int (*init_proc)(void *), void *sp);
 | 
					 | 
				
			||||||
extern void attach_process(int pid);
 | 
					 | 
				
			||||||
extern void tracer_panic(char *format, ...)
 | 
					 | 
				
			||||||
	__attribute__ ((format (printf, 1, 2)));
 | 
					 | 
				
			||||||
extern void set_init_pid(int pid);
 | 
					 | 
				
			||||||
extern int set_user_mode(void *task);
 | 
					 | 
				
			||||||
extern void set_tracing(void *t, int tracing);
 | 
					 | 
				
			||||||
extern int is_tracing(void *task);
 | 
					 | 
				
			||||||
extern void syscall_handler(int sig, union uml_pt_regs *regs);
 | 
					 | 
				
			||||||
extern void exit_kernel(int pid, void *task);
 | 
					 | 
				
			||||||
extern void do_syscall(void *task, int pid, int local_using_sysemu);
 | 
					 | 
				
			||||||
extern void do_sigtrap(void *task);
 | 
					 | 
				
			||||||
extern int is_valid_pid(int pid);
 | 
					 | 
				
			||||||
extern void remap_data(void *segment_start, void *segment_end, int w);
 | 
					 | 
				
			||||||
extern long execute_syscall_tt(void *r);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,46 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __TT_UACCESS_H
 | 
					 | 
				
			||||||
#define __TT_UACCESS_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/string.h"
 | 
					 | 
				
			||||||
#include "linux/sched.h"
 | 
					 | 
				
			||||||
#include "asm/processor.h"
 | 
					 | 
				
			||||||
#include "asm/errno.h"
 | 
					 | 
				
			||||||
#include "asm/current.h"
 | 
					 | 
				
			||||||
#include "asm/a.out.h"
 | 
					 | 
				
			||||||
#include "uml_uaccess.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define ABOVE_KMEM (16 * 1024 * 1024)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern unsigned long end_vm;
 | 
					 | 
				
			||||||
extern unsigned long uml_physmem;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define is_stack(addr, size) \
 | 
					 | 
				
			||||||
	(((unsigned long) (addr) < STACK_TOP) && \
 | 
					 | 
				
			||||||
	 ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
 | 
					 | 
				
			||||||
	 (((unsigned long) (addr) + (size)) <= STACK_TOP))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define access_ok_tt(type, addr, size) \
 | 
					 | 
				
			||||||
	(is_stack(addr, size))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int __do_copy_from_user(void *to, const void *from, int n,
 | 
					 | 
				
			||||||
			       void **fault_addr, void **fault_catcher);
 | 
					 | 
				
			||||||
extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
 | 
					 | 
				
			||||||
				  void **fault_addr, void **fault_catcher);
 | 
					 | 
				
			||||||
extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
 | 
					 | 
				
			||||||
			   void **fault_catcher);
 | 
					 | 
				
			||||||
extern int __do_strnlen_user(const char *str, unsigned long n,
 | 
					 | 
				
			||||||
			     void **fault_addr, void **fault_catcher);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int copy_from_user_tt(void *to, const void __user *from, int n);
 | 
					 | 
				
			||||||
extern int copy_to_user_tt(void __user *to, const void *from, int n);
 | 
					 | 
				
			||||||
extern int strncpy_from_user_tt(char *dst, const char __user *src, int count);
 | 
					 | 
				
			||||||
extern int __clear_user_tt(void __user *mem, int len);
 | 
					 | 
				
			||||||
extern int clear_user_tt(void __user *mem, int len);
 | 
					 | 
				
			||||||
extern int strnlen_user_tt(const void __user *str, int len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -8,33 +8,10 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "uml-config.h"
 | 
					#include "uml-config.h"
 | 
				
			||||||
#include "choose-mode.h"
 | 
					#include "choose-mode.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#include "mmu-tt.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "mmu-skas.h"
 | 
					#include "mmu-skas.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef union mm_context {
 | 
					typedef union mm_context {
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
	struct mmu_context_tt tt;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
	struct mmu_context_skas skas;
 | 
						struct mmu_context_skas skas;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
} mm_context_t;
 | 
					} mm_context_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,15 +7,7 @@
 | 
				
			||||||
#define __ARCH_UM_UACCESS_H
 | 
					#define __ARCH_UM_UACCESS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "choose-mode.h"
 | 
					#include "choose-mode.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#include "uaccess-tt.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "uaccess-skas.h"
 | 
					#include "uaccess-skas.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "asm/fixmap.h"
 | 
					#include "asm/fixmap.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define __under_task_size(addr, size) \
 | 
					#define __under_task_size(addr, size) \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,15 +9,12 @@ clean-files :=
 | 
				
			||||||
obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
 | 
					obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \
 | 
				
			||||||
	physmem.o process.o ptrace.o reboot.o sigio.o \
 | 
						physmem.o process.o ptrace.o reboot.o sigio.o \
 | 
				
			||||||
	signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
 | 
						signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \
 | 
				
			||||||
	um_arch.o umid.o
 | 
						um_arch.o umid.o skas/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 | 
					obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 | 
				
			||||||
obj-$(CONFIG_GPROF)	+= gprof_syms.o
 | 
					obj-$(CONFIG_GPROF)	+= gprof_syms.o
 | 
				
			||||||
obj-$(CONFIG_GCOV)	+= gmon_syms.o
 | 
					obj-$(CONFIG_GCOV)	+= gmon_syms.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_MODE_TT) += tt/
 | 
					 | 
				
			||||||
obj-$(CONFIG_MODE_SKAS) += skas/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USER_OBJS := config.o
 | 
					USER_OBJS := config.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include arch/um/scripts/Makefile.rules
 | 
					include arch/um/scripts/Makefile.rules
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,8 +10,6 @@ SECTIONS
 | 
				
			||||||
  PROVIDE (__executable_start = START);
 | 
					  PROVIDE (__executable_start = START);
 | 
				
			||||||
  . = START + SIZEOF_HEADERS;
 | 
					  . = START + SIZEOF_HEADERS;
 | 
				
			||||||
  .interp         : { *(.interp) }
 | 
					  .interp         : { *(.interp) }
 | 
				
			||||||
  /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
 | 
					 | 
				
			||||||
   * is remapped.*/
 | 
					 | 
				
			||||||
  __binary_start = .;
 | 
					  __binary_start = .;
 | 
				
			||||||
  . = ALIGN(4096);		/* Init code and data */
 | 
					  . = ALIGN(4096);		/* Init code and data */
 | 
				
			||||||
  _text = .;
 | 
					  _text = .;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,7 +57,6 @@ static long execve1(char *file, char __user * __user *argv,
 | 
				
			||||||
		SUBARCH_EXECVE1(¤t->thread.regs.regs);
 | 
							SUBARCH_EXECVE1(¤t->thread.regs.regs);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		task_unlock(current);
 | 
							task_unlock(current);
 | 
				
			||||||
                set_cmdline(current_cmd());
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return(error);
 | 
					        return(error);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,10 +46,3 @@ union thread_union init_thread_union
 | 
				
			||||||
union thread_union cpu0_irqstack
 | 
					union thread_union cpu0_irqstack
 | 
				
			||||||
	__attribute__((__section__(".data.init_irqstack"))) =
 | 
						__attribute__((__section__(".data.init_irqstack"))) =
 | 
				
			||||||
		{ INIT_THREAD_INFO(init_task) };
 | 
							{ INIT_THREAD_INFO(init_task) };
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
void unprotect_stack(unsigned long stack)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -339,30 +339,6 @@ int deactivate_all_fds(void)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
void forward_interrupts(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct irq_fd *irq;
 | 
					 | 
				
			||||||
	unsigned long flags;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	spin_lock_irqsave(&irq_lock, flags);
 | 
					 | 
				
			||||||
	for (irq = active_fds; irq != NULL; irq = irq->next) {
 | 
					 | 
				
			||||||
		err = os_set_owner(irq->fd, pid);
 | 
					 | 
				
			||||||
		if (err < 0) {
 | 
					 | 
				
			||||||
			/* XXX Just remove the irq rather than
 | 
					 | 
				
			||||||
			 * print out an infinite stream of these
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			printk("Failed to forward %d to pid %d, err = %d\n",
 | 
					 | 
				
			||||||
			       irq->fd, pid, -err);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		irq->pid = pid;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	spin_unlock_irqrestore(&irq_lock, flags);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * do_IRQ handles all normal device IRQ's (the special
 | 
					 * do_IRQ handles all normal device IRQ's (the special
 | 
				
			||||||
 * SMP cross-CPU interrupts have their own specific
 | 
					 * SMP cross-CPU interrupts have their own specific
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,24 +34,14 @@ EXPORT_SYMBOL(get_kmem_end);
 | 
				
			||||||
EXPORT_SYMBOL(high_physmem);
 | 
					EXPORT_SYMBOL(high_physmem);
 | 
				
			||||||
EXPORT_SYMBOL(empty_zero_page);
 | 
					EXPORT_SYMBOL(empty_zero_page);
 | 
				
			||||||
EXPORT_SYMBOL(um_virt_to_phys);
 | 
					EXPORT_SYMBOL(um_virt_to_phys);
 | 
				
			||||||
EXPORT_SYMBOL(mode_tt);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(handle_page_fault);
 | 
					EXPORT_SYMBOL(handle_page_fault);
 | 
				
			||||||
EXPORT_SYMBOL(find_iomem);
 | 
					EXPORT_SYMBOL(find_iomem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(stop);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(strncpy_from_user_tt);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(copy_from_user_tt);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(copy_to_user_tt);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(strnlen_user_skas);
 | 
					EXPORT_SYMBOL(strnlen_user_skas);
 | 
				
			||||||
EXPORT_SYMBOL(strncpy_from_user_skas);
 | 
					EXPORT_SYMBOL(strncpy_from_user_skas);
 | 
				
			||||||
EXPORT_SYMBOL(copy_to_user_skas);
 | 
					EXPORT_SYMBOL(copy_to_user_skas);
 | 
				
			||||||
EXPORT_SYMBOL(copy_from_user_skas);
 | 
					EXPORT_SYMBOL(copy_from_user_skas);
 | 
				
			||||||
EXPORT_SYMBOL(clear_user_skas);
 | 
					EXPORT_SYMBOL(clear_user_skas);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(uml_strdup);
 | 
					EXPORT_SYMBOL(uml_strdup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPORT_SYMBOL(os_stat_fd);
 | 
					EXPORT_SYMBOL(os_stat_fd);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -183,13 +183,6 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
 | 
				
			||||||
	kmalloc_ok = save_kmalloc_ok;
 | 
						kmalloc_ok = save_kmalloc_ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
unsigned long stack_sp(unsigned long page)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return page + PAGE_SIZE - sizeof(void *);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void default_idle(void)
 | 
					void default_idle(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	CHOOSE_MODE(uml_idle_timer(), (void) 0);
 | 
						CHOOSE_MODE(uml_idle_timer(), (void) 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,28 +14,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void (*pm_power_off)(void);
 | 
					void (*pm_power_off)(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					 | 
				
			||||||
static void kill_idlers(int me)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
	struct task_struct *p;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for(i = 0; i < ARRAY_SIZE(idle_threads); i++){
 | 
					 | 
				
			||||||
		p = idle_threads[i];
 | 
					 | 
				
			||||||
		if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
 | 
					 | 
				
			||||||
			os_kill_process(p->thread.mode.tt.extern_pid, 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void kill_off_processes(void)
 | 
					static void kill_off_processes(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas());
 | 
						CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas());
 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					 | 
				
			||||||
	kill_idlers(os_getpid());
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void uml_cleanup(void)
 | 
					void uml_cleanup(void)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,6 @@ static int idle_proc(void *cpup)
 | 
				
			||||||
static struct task_struct *idle_thread(int cpu)
 | 
					static struct task_struct *idle_thread(int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct task_struct *new_task;
 | 
						struct task_struct *new_task;
 | 
				
			||||||
	unsigned char c;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	current->thread.request.u.thread.proc = idle_proc;
 | 
						current->thread.request.u.thread.proc = idle_proc;
 | 
				
			||||||
	current->thread.request.u.thread.arg = (void *) cpu;
 | 
						current->thread.request.u.thread.arg = (void *) cpu;
 | 
				
			||||||
| 
						 | 
					@ -108,9 +107,7 @@ static struct task_struct *idle_thread(int cpu)
 | 
				
			||||||
		          { .pid = 	new_task->thread.mode.tt.extern_pid,
 | 
							          { .pid = 	new_task->thread.mode.tt.extern_pid,
 | 
				
			||||||
			    .task = 	new_task } );
 | 
								    .task = 	new_task } );
 | 
				
			||||||
	idle_threads[cpu] = new_task;
 | 
						idle_threads[cpu] = new_task;
 | 
				
			||||||
	CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
 | 
						panic("skas mode doesn't support SMP");
 | 
				
			||||||
				  sizeof(c)),
 | 
					 | 
				
			||||||
		    ({ panic("skas mode doesn't support SMP"); }));
 | 
					 | 
				
			||||||
	return new_task;
 | 
						return new_task;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,9 +29,7 @@
 | 
				
			||||||
#include "sysdep/sigcontext.h"
 | 
					#include "sysdep/sigcontext.h"
 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					#include "sysdep/ptrace.h"
 | 
				
			||||||
#include "os.h"
 | 
					#include "os.h"
 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "skas.h"
 | 
					#include "skas.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					#include "os.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
 | 
					/* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +0,0 @@
 | 
				
			||||||
# 
 | 
					 | 
				
			||||||
# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
 | 
					 | 
				
			||||||
# Licensed under the GPL
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
 | 
					 | 
				
			||||||
	syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \
 | 
					 | 
				
			||||||
	uaccess.o uaccess_user.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USER_OBJS := gdb.o tracer.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include arch/um/scripts/Makefile.rules
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,84 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/kernel.h"
 | 
					 | 
				
			||||||
#include "linux/mm.h"
 | 
					 | 
				
			||||||
#include "asm/signal.h"
 | 
					 | 
				
			||||||
#include "asm/ptrace.h"
 | 
					 | 
				
			||||||
#include "asm/uaccess.h"
 | 
					 | 
				
			||||||
#include "asm/pgalloc.h"
 | 
					 | 
				
			||||||
#include "asm/tlbflush.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "irq_user.h"
 | 
					 | 
				
			||||||
#include "mem_user.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
#include "tlb.h"
 | 
					 | 
				
			||||||
#include "mode.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int exec_tramp(void *sig_stack)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	init_new_thread_stack(sig_stack, NULL);
 | 
					 | 
				
			||||||
	init_new_thread_signals();
 | 
					 | 
				
			||||||
	os_stop_process(os_getpid());
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void flush_thread_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long stack;
 | 
					 | 
				
			||||||
	int new_pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stack = alloc_stack(0, 0);
 | 
					 | 
				
			||||||
	if(stack == 0){
 | 
					 | 
				
			||||||
		printk(KERN_ERR 
 | 
					 | 
				
			||||||
		       "flush_thread : failed to allocate temporary stack\n");
 | 
					 | 
				
			||||||
		do_exit(SIGKILL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
	new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp);
 | 
					 | 
				
			||||||
	if(new_pid < 0){
 | 
					 | 
				
			||||||
		printk(KERN_ERR 
 | 
					 | 
				
			||||||
		       "flush_thread : new thread failed, errno = %d\n",
 | 
					 | 
				
			||||||
		       -new_pid);
 | 
					 | 
				
			||||||
		do_exit(SIGKILL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(current_thread->cpu == 0)
 | 
					 | 
				
			||||||
		forward_interrupts(new_pid);
 | 
					 | 
				
			||||||
	current->thread.request.op = OP_EXEC;
 | 
					 | 
				
			||||||
	current->thread.request.u.exec.pid = new_pid;
 | 
					 | 
				
			||||||
	unprotect_stack((unsigned long) current_thread);
 | 
					 | 
				
			||||||
	os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 0);
 | 
					 | 
				
			||||||
	enable_timer();
 | 
					 | 
				
			||||||
	free_page(stack);
 | 
					 | 
				
			||||||
	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
 | 
					 | 
				
			||||||
	stack_protections((unsigned long) current_thread);
 | 
					 | 
				
			||||||
	force_flush_all();
 | 
					 | 
				
			||||||
	unblock_signals();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void start_thread_tt(struct pt_regs *regs, unsigned long eip, 
 | 
					 | 
				
			||||||
		     unsigned long esp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	set_fs(USER_DS);
 | 
					 | 
				
			||||||
	flush_tlb_mm(current->mm);
 | 
					 | 
				
			||||||
	PT_REGS_IP(regs) = eip;
 | 
					 | 
				
			||||||
	PT_REGS_SP(regs) = esp;
 | 
					 | 
				
			||||||
	PT_FIX_EXEC_STACK(esp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,56 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <sched.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "user.h"
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void do_exec(int old_pid, int new_pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long regs[FRAME_SIZE];
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) ||
 | 
					 | 
				
			||||||
	   (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0))
 | 
					 | 
				
			||||||
		tracer_panic("do_exec failed to attach proc - errno = %d",
 | 
					 | 
				
			||||||
			     errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED));
 | 
					 | 
				
			||||||
	if (err < 0)
 | 
					 | 
				
			||||||
		tracer_panic("do_exec failed to attach proc in waitpid - errno = %d",
 | 
					 | 
				
			||||||
			     errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(ptrace_getregs(old_pid, regs) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("do_exec failed to get registers - errno = %d",
 | 
					 | 
				
			||||||
			     errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	os_kill_ptraced_process(old_pid, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (ptrace(PTRACE_OLDSETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(ptrace_setregs(new_pid, regs) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("do_exec failed to start new proc - 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
 | 
					 | 
				
			||||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
					 | 
				
			||||||
 * of the file.
 | 
					 | 
				
			||||||
 * ---------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * Local variables:
 | 
					 | 
				
			||||||
 * c-file-style: "linux"
 | 
					 | 
				
			||||||
 * End:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,280 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
#include "uml-config.h"
 | 
					 | 
				
			||||||
#include "kern_constants.h"
 | 
					 | 
				
			||||||
#include "chan_user.h"
 | 
					 | 
				
			||||||
#include "init.h"
 | 
					 | 
				
			||||||
#include "user.h"
 | 
					 | 
				
			||||||
#include "debug.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
#include "sysdep/thread.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int debugger_pid;
 | 
					 | 
				
			||||||
extern int debugger_fd;
 | 
					 | 
				
			||||||
extern int debugger_parent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int detach(int pid, int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(ptrace(PTRACE_DETACH, pid, 0, sig));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int attach(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = ptrace(PTRACE_ATTACH, pid, 0, 0);
 | 
					 | 
				
			||||||
	if(err < 0) return(-errno);
 | 
					 | 
				
			||||||
	else return(err);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int cont(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(ptrace(PTRACE_CONT, pid, 0, 0));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_PT_PROXY
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int debugger_signal(int status, pid_t pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(debugger_proxy(status, pid));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void child_signal(pid_t pid, int status)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	child_proxy(pid, status);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void gdb_announce(char *dev_name, int dev)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("gdb assigned device '%s'\n", dev_name);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct chan_opts opts = {
 | 
					 | 
				
			||||||
	.announce  	= gdb_announce,
 | 
					 | 
				
			||||||
	.xterm_title 	= "UML kernel debugger",
 | 
					 | 
				
			||||||
	.raw 		= 0,
 | 
					 | 
				
			||||||
	.tramp_stack 	= 0,
 | 
					 | 
				
			||||||
	.in_kernel  	= 0,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Accessed by the tracing thread, which automatically serializes access */
 | 
					 | 
				
			||||||
static void *xterm_data;
 | 
					 | 
				
			||||||
static int xterm_fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern void *xterm_init(char *, int, struct chan_opts *);
 | 
					 | 
				
			||||||
extern int xterm_open(int, int, int, void *, char **);
 | 
					 | 
				
			||||||
extern void xterm_close(int, void *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int open_gdb_chan(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char stack[UM_KERN_PAGE_SIZE], *dummy;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	opts.tramp_stack = (unsigned long) stack;
 | 
					 | 
				
			||||||
	xterm_data = xterm_init("", 0, &opts);
 | 
					 | 
				
			||||||
	xterm_fd = xterm_open(1, 1, 1, xterm_data, &dummy);
 | 
					 | 
				
			||||||
	return(xterm_fd);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void exit_debugger_cb(void *unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(debugger_pid != -1){
 | 
					 | 
				
			||||||
		if(gdb_pid != -1){
 | 
					 | 
				
			||||||
			fake_child_exit();
 | 
					 | 
				
			||||||
			gdb_pid = -1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else kill_child_dead(debugger_pid);
 | 
					 | 
				
			||||||
		debugger_pid = -1;
 | 
					 | 
				
			||||||
		if(debugger_parent != -1)
 | 
					 | 
				
			||||||
			detach(debugger_parent, SIGINT);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void exit_debugger(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	initial_thread_cb(exit_debugger_cb, NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__uml_exitcall(exit_debugger);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct gdb_data {
 | 
					 | 
				
			||||||
	char *str;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern char *linux_prog;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void config_gdb_cb(void *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct gdb_data *data = arg;
 | 
					 | 
				
			||||||
	void *task;
 | 
					 | 
				
			||||||
	int pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	data->err = -1;
 | 
					 | 
				
			||||||
	if(debugger_pid != -1) exit_debugger_cb(NULL);
 | 
					 | 
				
			||||||
	if(!strncmp(data->str, "pid,", strlen("pid,"))){
 | 
					 | 
				
			||||||
		data->str += strlen("pid,");
 | 
					 | 
				
			||||||
		pid = strtoul(data->str, NULL, 0);
 | 
					 | 
				
			||||||
		task = cpu_tasks[0].task;
 | 
					 | 
				
			||||||
		debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0);
 | 
					 | 
				
			||||||
		if(debugger_pid != -1){
 | 
					 | 
				
			||||||
			data->err = 0;
 | 
					 | 
				
			||||||
			gdb_pid = pid;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	data->err = 0;
 | 
					 | 
				
			||||||
	debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
 | 
					 | 
				
			||||||
	init_proxy(debugger_pid, 0, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int gdb_config(char *str, char **error_out)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct gdb_data data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(*str++ != '=') return(-1);
 | 
					 | 
				
			||||||
	data.str = str;
 | 
					 | 
				
			||||||
	initial_thread_cb(config_gdb_cb, &data);
 | 
					 | 
				
			||||||
	return(data.err);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void remove_gdb_cb(void *unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	exit_debugger_cb(NULL);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int gdb_remove(int unused, char **error_out)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	initial_thread_cb(remove_gdb_cb, NULL);
 | 
					 | 
				
			||||||
        return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void signal_usr1(int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(debugger_pid != -1){
 | 
					 | 
				
			||||||
		printf("The debugger is already running\n");
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
 | 
					 | 
				
			||||||
	init_proxy(debugger_pid, 0, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int init_ptrace_proxy(int idle_pid, int startup, int stop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int pid, status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pid = start_debugger(linux_prog, startup, stop, &debugger_fd);
 | 
					 | 
				
			||||||
	status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
 | 
					 | 
				
			||||||
 	if(pid < 0){
 | 
					 | 
				
			||||||
		cont(idle_pid);
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	init_proxy(pid, 1, status);
 | 
					 | 
				
			||||||
	return(pid);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int attach_debugger(int idle_pid, int pid, int stop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int status = 0, err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = attach(pid);
 | 
					 | 
				
			||||||
	if(err < 0){
 | 
					 | 
				
			||||||
		printf("Failed to attach pid %d, errno = %d\n", pid, -err);
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
 | 
					 | 
				
			||||||
	init_proxy(pid, 1, status);
 | 
					 | 
				
			||||||
	return(pid);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef notdef /* Put this back in when it does something useful */
 | 
					 | 
				
			||||||
static int __init uml_gdb_init_setup(char *line, int *add)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	gdb_init = uml_strdup(line);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__uml_setup("gdb=", uml_gdb_init_setup, 
 | 
					 | 
				
			||||||
"gdb=<channel description>\n\n"
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init uml_gdb_pid_setup(char *line, int *add)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	gdb_pid = strtoul(line, NULL, 0);
 | 
					 | 
				
			||||||
	*add = 0;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__uml_setup("gdb-pid=", uml_gdb_pid_setup, 
 | 
					 | 
				
			||||||
"gdb-pid=<pid>\n"
 | 
					 | 
				
			||||||
"    gdb-pid is used to attach an external debugger to UML.  This may be\n"
 | 
					 | 
				
			||||||
"    an already-running gdb or a debugger-like process like strace.\n\n"
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int debugger_signal(int status, pid_t pid){ return(0); }
 | 
					 | 
				
			||||||
void child_signal(pid_t pid, int status){ }
 | 
					 | 
				
			||||||
int init_ptrace_proxy(int idle_pid, int startup, int stop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("debug requested when CONFIG_PT_PROXY is off\n");
 | 
					 | 
				
			||||||
	kill_child_dead(idle_pid);
 | 
					 | 
				
			||||||
	exit(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void signal_usr1(int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("debug requested when CONFIG_PT_PROXY is off\n");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int attach_debugger(int idle_pid, int pid, int stop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("attach_debugger called when CONFIG_PT_PROXY "
 | 
					 | 
				
			||||||
	       "is off\n");
 | 
					 | 
				
			||||||
	return(-1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int config_gdb(char *str)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(-1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int remove_gdb(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(-1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int init_parent_proxy(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(-1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void debugger_parent_signal(int status, 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,40 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/init.h"
 | 
					 | 
				
			||||||
#include "mconsole_kern.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MCONSOLE
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int gdb_config(char *str, char **error_out);
 | 
					 | 
				
			||||||
extern int gdb_remove(int n, char **error_out);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static struct mc_device gdb_mc = {
 | 
					 | 
				
			||||||
	.list		= INIT_LIST_HEAD(gdb_mc.list),
 | 
					 | 
				
			||||||
	.name		= "gdb",
 | 
					 | 
				
			||||||
	.config		= gdb_config,
 | 
					 | 
				
			||||||
	.remove		= gdb_remove,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int gdb_mc_init(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	mconsole_register_dev(&gdb_mc);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__initcall(gdb_mc_init);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,34 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __MODE_TT_H__
 | 
					 | 
				
			||||||
#define __MODE_TT_H__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int tracing_pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int tracer(int (*init_proc)(void *), void *sp);
 | 
					 | 
				
			||||||
extern void sig_handler_common_tt(int sig, void *sc);
 | 
					 | 
				
			||||||
extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
 | 
					 | 
				
			||||||
extern void reboot_tt(void);
 | 
					 | 
				
			||||||
extern void halt_tt(void);
 | 
					 | 
				
			||||||
extern int is_tracer_winch(int pid, int fd, void *data);
 | 
					 | 
				
			||||||
extern void kill_off_processes_tt(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,29 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/module.h"
 | 
					 | 
				
			||||||
#include "asm/uaccess.h"
 | 
					 | 
				
			||||||
#include "mode.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(__do_copy_from_user);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(__do_copy_to_user);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(__do_strncpy_from_user);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(__do_strnlen_user); 
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(__do_clear_user);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(clear_user_tt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(tracing_pid);
 | 
					 | 
				
			||||||
EXPORT_SYMBOL(honeypot);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,34 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/stddef.h"
 | 
					 | 
				
			||||||
#include "linux/mm.h"
 | 
					 | 
				
			||||||
#include "asm/uaccess.h"
 | 
					 | 
				
			||||||
#include "mem_user.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "kern.h"
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void before_mem_tt(unsigned long brk_start)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(debug)
 | 
					 | 
				
			||||||
		remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
 | 
					 | 
				
			||||||
	remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
 | 
					 | 
				
			||||||
	remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
 | 
					 | 
				
			||||||
#define START (CONFIG_TOP_ADDR - SIZE)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
unsigned long set_task_sizes_tt(unsigned long *task_size_out)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long host_task_size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Round up to the nearest 4M */
 | 
					 | 
				
			||||||
	host_task_size = ROUND_4M((unsigned long) &host_task_size);
 | 
					 | 
				
			||||||
	*task_size_out = START;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return host_task_size;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,49 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <sys/mman.h>
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
#include "mem_user.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void remap_data(void *segment_start, void *segment_end, int w)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	void *addr;
 | 
					 | 
				
			||||||
	unsigned long size;
 | 
					 | 
				
			||||||
	int data, prot;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(w) prot = PROT_WRITE;
 | 
					 | 
				
			||||||
	else prot = 0;
 | 
					 | 
				
			||||||
	prot |= PROT_READ | PROT_EXEC;
 | 
					 | 
				
			||||||
	size = (unsigned long) segment_end - 
 | 
					 | 
				
			||||||
		(unsigned long) segment_start;
 | 
					 | 
				
			||||||
	data = create_mem_file(size);
 | 
					 | 
				
			||||||
	addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
 | 
					 | 
				
			||||||
	if(addr == MAP_FAILED){
 | 
					 | 
				
			||||||
		perror("mapping new data segment");
 | 
					 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	memcpy(addr, segment_start, size);
 | 
					 | 
				
			||||||
	if(switcheroo(data, prot, addr, segment_start, size) < 0){
 | 
					 | 
				
			||||||
		printf("switcheroo failed\n");
 | 
					 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,461 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/sched.h"
 | 
					 | 
				
			||||||
#include "linux/signal.h"
 | 
					 | 
				
			||||||
#include "linux/kernel.h"
 | 
					 | 
				
			||||||
#include "linux/interrupt.h"
 | 
					 | 
				
			||||||
#include "linux/ptrace.h"
 | 
					 | 
				
			||||||
#include "asm/system.h"
 | 
					 | 
				
			||||||
#include "asm/pgalloc.h"
 | 
					 | 
				
			||||||
#include "asm/ptrace.h"
 | 
					 | 
				
			||||||
#include "asm/tlbflush.h"
 | 
					 | 
				
			||||||
#include "irq_user.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
#include "kern.h"
 | 
					 | 
				
			||||||
#include "sigcontext.h"
 | 
					 | 
				
			||||||
#include "mem_user.h"
 | 
					 | 
				
			||||||
#include "tlb.h"
 | 
					 | 
				
			||||||
#include "mode.h"
 | 
					 | 
				
			||||||
#include "mode_kern.h"
 | 
					 | 
				
			||||||
#include "init.h"
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void switch_to_tt(void *prev, void *next)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct task_struct *from, *to, *prev_sched;
 | 
					 | 
				
			||||||
	unsigned long flags;
 | 
					 | 
				
			||||||
	int err, vtalrm, alrm, prof, cpu;
 | 
					 | 
				
			||||||
	char c;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	from = prev;
 | 
					 | 
				
			||||||
	to = next;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cpu = task_thread_info(from)->cpu;
 | 
					 | 
				
			||||||
	if(cpu == 0)
 | 
					 | 
				
			||||||
		forward_interrupts(to->thread.mode.tt.extern_pid);
 | 
					 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					 | 
				
			||||||
	forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	local_irq_save(flags);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	vtalrm = change_sig(SIGVTALRM, 0);
 | 
					 | 
				
			||||||
	alrm = change_sig(SIGALRM, 0);
 | 
					 | 
				
			||||||
	prof = change_sig(SIGPROF, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	forward_pending_sigio(to->thread.mode.tt.extern_pid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Notice that here we "up" the semaphore on which "to" is waiting, and
 | 
					 | 
				
			||||||
	 * below (the read) we wait on this semaphore (which is implemented by
 | 
					 | 
				
			||||||
	 * switch_pipe) and go sleeping. Thus, after that, we have resumed in
 | 
					 | 
				
			||||||
	 * "to", and can't use any more the value of "from" (which is outdated),
 | 
					 | 
				
			||||||
	 * nor the value in "to" (since it was the task which stole us the CPU,
 | 
					 | 
				
			||||||
	 * which we don't care about). */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
 | 
					 | 
				
			||||||
	if(err != sizeof(c))
 | 
					 | 
				
			||||||
		panic("write of switch_pipe failed, err = %d", -err);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(from->thread.mode.tt.switch_pipe[0] == -1)
 | 
					 | 
				
			||||||
		os_kill_process(os_getpid(), 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c,
 | 
					 | 
				
			||||||
			     sizeof(c));
 | 
					 | 
				
			||||||
	if(err != sizeof(c))
 | 
					 | 
				
			||||||
		panic("read of switch_pipe failed, errno = %d", -err);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* If the process that we have just scheduled away from has exited,
 | 
					 | 
				
			||||||
	 * then it needs to be killed here.  The reason is that, even though
 | 
					 | 
				
			||||||
	 * it will kill itself when it next runs, that may be too late.  Its
 | 
					 | 
				
			||||||
	 * stack will be freed, possibly before then, and if that happens,
 | 
					 | 
				
			||||||
	 * we have a use-after-free situation.  So, it gets killed here
 | 
					 | 
				
			||||||
	 * in case it has not already killed itself.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	prev_sched = current->thread.prev_sched;
 | 
					 | 
				
			||||||
        if(prev_sched->thread.mode.tt.switch_pipe[0] == -1)
 | 
					 | 
				
			||||||
		os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	change_sig(SIGVTALRM, vtalrm);
 | 
					 | 
				
			||||||
	change_sig(SIGALRM, alrm);
 | 
					 | 
				
			||||||
	change_sig(SIGPROF, prof);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	arch_switch_to_tt(prev_sched, current);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	flush_tlb_all();
 | 
					 | 
				
			||||||
	local_irq_restore(flags);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void release_thread_tt(struct task_struct *task)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int pid = task->thread.mode.tt.extern_pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
         * We first have to kill the other process, before
 | 
					 | 
				
			||||||
         * closing its switch_pipe. Else it might wake up
 | 
					 | 
				
			||||||
         * and receive "EOF" before we could kill it.
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
	if(os_getpid() != pid)
 | 
					 | 
				
			||||||
		os_kill_process(pid, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        os_close_file(task->thread.mode.tt.switch_pipe[0]);
 | 
					 | 
				
			||||||
        os_close_file(task->thread.mode.tt.switch_pipe[1]);
 | 
					 | 
				
			||||||
	/* use switch_pipe as flag: thread is released */
 | 
					 | 
				
			||||||
        task->thread.mode.tt.switch_pipe[0] = -1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void suspend_new_thread(int fd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
	char c;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	os_stop_process(os_getpid());
 | 
					 | 
				
			||||||
	err = os_read_file(fd, &c, sizeof(c));
 | 
					 | 
				
			||||||
	if(err != sizeof(c))
 | 
					 | 
				
			||||||
		panic("read failed in suspend_new_thread, err = %d", -err);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void schedule_tail(struct task_struct *prev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void new_thread_handler(int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long disable;
 | 
					 | 
				
			||||||
	int (*fn)(void *);
 | 
					 | 
				
			||||||
	void *arg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fn = current->thread.request.u.thread.proc;
 | 
					 | 
				
			||||||
	arg = current->thread.request.u.thread.arg;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
 | 
					 | 
				
			||||||
	disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
 | 
					 | 
				
			||||||
		(1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
 | 
					 | 
				
			||||||
	SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	force_flush_all();
 | 
					 | 
				
			||||||
	if(current->thread.prev_sched != NULL)
 | 
					 | 
				
			||||||
		schedule_tail(current->thread.prev_sched);
 | 
					 | 
				
			||||||
	current->thread.prev_sched = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	init_new_thread_signals();
 | 
					 | 
				
			||||||
	enable_timer();
 | 
					 | 
				
			||||||
	free_page(current->thread.temp_stack);
 | 
					 | 
				
			||||||
	set_cmdline("(kernel thread)");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
	change_sig(SIGPROF, 1);
 | 
					 | 
				
			||||||
	local_irq_enable();
 | 
					 | 
				
			||||||
	if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf))
 | 
					 | 
				
			||||||
		do_exit(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* XXX No set_user_mode here because a newly execed process will
 | 
					 | 
				
			||||||
	 * immediately segfault on its non-existent IP, coming straight back
 | 
					 | 
				
			||||||
	 * to the signal handler, which will call set_user_mode on its way
 | 
					 | 
				
			||||||
	 * out.  This should probably change since it's confusing.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int new_thread_proc(void *stack)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	/* local_irq_disable is needed to block out signals until this thread is
 | 
					 | 
				
			||||||
	 * properly scheduled.  Otherwise, the tracing thread will get mighty
 | 
					 | 
				
			||||||
	 * upset about any signals that arrive before that.
 | 
					 | 
				
			||||||
	 * This has the complication that it sets the saved signal mask in
 | 
					 | 
				
			||||||
	 * the sigcontext to block signals.  This gets restored when this
 | 
					 | 
				
			||||||
	 * thread (or a descendant, since they get a copy of this sigcontext)
 | 
					 | 
				
			||||||
	 * returns to userspace.
 | 
					 | 
				
			||||||
	 * So, this is compensated for elsewhere.
 | 
					 | 
				
			||||||
	 * XXX There is still a small window until local_irq_disable() actually
 | 
					 | 
				
			||||||
	 * finishes where signals are possible - shouldn't be a problem in
 | 
					 | 
				
			||||||
	 * practice since SIGIO hasn't been forwarded here yet, and the
 | 
					 | 
				
			||||||
	 * local_irq_disable should finish before a SIGVTALRM has time to be
 | 
					 | 
				
			||||||
	 * delivered.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	local_irq_disable();
 | 
					 | 
				
			||||||
	init_new_thread_stack(stack, new_thread_handler);
 | 
					 | 
				
			||||||
	os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Signal masking - signals are blocked at the start of fork_tramp.  They
 | 
					 | 
				
			||||||
 * are re-enabled when finish_fork_handler is entered by fork_tramp hitting
 | 
					 | 
				
			||||||
 * itself with a SIGUSR1.  set_user_mode has to be run with SIGUSR1 off,
 | 
					 | 
				
			||||||
 * so it is blocked before it's called.  They are re-enabled on sigreturn
 | 
					 | 
				
			||||||
 * despite the fact that they were blocked when the SIGUSR1 was issued because
 | 
					 | 
				
			||||||
 * copy_thread copies the parent's sigcontext, including the signal mask
 | 
					 | 
				
			||||||
 * onto the signal frame.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void finish_fork_handler(int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 	UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
 | 
					 | 
				
			||||||
	suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	force_flush_all();
 | 
					 | 
				
			||||||
	if(current->thread.prev_sched != NULL)
 | 
					 | 
				
			||||||
		schedule_tail(current->thread.prev_sched);
 | 
					 | 
				
			||||||
	current->thread.prev_sched = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	enable_timer();
 | 
					 | 
				
			||||||
	change_sig(SIGVTALRM, 1);
 | 
					 | 
				
			||||||
	local_irq_enable();
 | 
					 | 
				
			||||||
	if(current->mm != current->parent->mm)
 | 
					 | 
				
			||||||
		protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 
 | 
					 | 
				
			||||||
			       1, 0, 1);
 | 
					 | 
				
			||||||
	stack_protections((unsigned long) current_thread);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	free_page(current->thread.temp_stack);
 | 
					 | 
				
			||||||
	local_irq_disable();
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 0);
 | 
					 | 
				
			||||||
	set_user_mode(current);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int fork_tramp(void *stack)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	local_irq_disable();
 | 
					 | 
				
			||||||
	arch_init_thread();
 | 
					 | 
				
			||||||
	init_new_thread_stack(stack, finish_fork_handler);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
 | 
					 | 
				
			||||||
		   unsigned long stack_top, struct task_struct * p, 
 | 
					 | 
				
			||||||
		   struct pt_regs *regs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int (*tramp)(void *);
 | 
					 | 
				
			||||||
	int new_pid, err;
 | 
					 | 
				
			||||||
	unsigned long stack;
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if(current->thread.forking)
 | 
					 | 
				
			||||||
		tramp = fork_tramp;
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		tramp = new_thread_proc;
 | 
					 | 
				
			||||||
		p->thread.request.u.thread = current->thread.request.u.thread;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
 | 
					 | 
				
			||||||
	if(err < 0){
 | 
					 | 
				
			||||||
		printk("copy_thread : pipe failed, err = %d\n", -err);
 | 
					 | 
				
			||||||
		return(err);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	stack = alloc_stack(0, 0);
 | 
					 | 
				
			||||||
	if(stack == 0){
 | 
					 | 
				
			||||||
		printk(KERN_ERR "copy_thread : failed to allocate "
 | 
					 | 
				
			||||||
		       "temporary stack\n");
 | 
					 | 
				
			||||||
		return(-ENOMEM);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	clone_flags &= CLONE_VM;
 | 
					 | 
				
			||||||
	p->thread.temp_stack = stack;
 | 
					 | 
				
			||||||
	new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp);
 | 
					 | 
				
			||||||
	if(new_pid < 0){
 | 
					 | 
				
			||||||
		printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", 
 | 
					 | 
				
			||||||
		       -new_pid);
 | 
					 | 
				
			||||||
		return(new_pid);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(current->thread.forking){
 | 
					 | 
				
			||||||
		sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(®s->regs));
 | 
					 | 
				
			||||||
		SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
 | 
					 | 
				
			||||||
		if(sp != 0)
 | 
					 | 
				
			||||||
			SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	p->thread.mode.tt.extern_pid = new_pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	current->thread.request.op = OP_FORK;
 | 
					 | 
				
			||||||
	current->thread.request.u.fork.pid = new_pid;
 | 
					 | 
				
			||||||
	os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Enable the signal and then disable it to ensure that it is handled
 | 
					 | 
				
			||||||
	 * here, and nowhere else.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 0);
 | 
					 | 
				
			||||||
	err = 0;
 | 
					 | 
				
			||||||
	return(err);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void reboot_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	current->thread.request.op = OP_REBOOT;
 | 
					 | 
				
			||||||
	os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void halt_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	current->thread.request.op = OP_HALT;
 | 
					 | 
				
			||||||
	os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
	change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void kill_off_processes_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct task_struct *p;
 | 
					 | 
				
			||||||
	int me;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	me = os_getpid();
 | 
					 | 
				
			||||||
        for_each_process(p){
 | 
					 | 
				
			||||||
		if(p->thread.mode.tt.extern_pid != me) 
 | 
					 | 
				
			||||||
			os_kill_process(p->thread.mode.tt.extern_pid, 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(init_task.thread.mode.tt.extern_pid != me) 
 | 
					 | 
				
			||||||
		os_kill_process(init_task.thread.mode.tt.extern_pid, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void initial_thread_cb_tt(void (*proc)(void *), void *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(os_getpid() == tracing_pid){
 | 
					 | 
				
			||||||
		(*proc)(arg);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		current->thread.request.op = OP_CB;
 | 
					 | 
				
			||||||
		current->thread.request.u.cb.proc = proc;
 | 
					 | 
				
			||||||
		current->thread.request.u.cb.arg = arg;
 | 
					 | 
				
			||||||
		os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
		change_sig(SIGUSR1, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		change_sig(SIGUSR1, 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int do_proc_op(void *t, int proc_id)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct task_struct *task;
 | 
					 | 
				
			||||||
	struct thread_struct *thread;
 | 
					 | 
				
			||||||
	int op, pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	task = t;
 | 
					 | 
				
			||||||
	thread = &task->thread;
 | 
					 | 
				
			||||||
	op = thread->request.op;
 | 
					 | 
				
			||||||
	switch(op){
 | 
					 | 
				
			||||||
	case OP_NONE:
 | 
					 | 
				
			||||||
	case OP_TRACE_ON:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case OP_EXEC:
 | 
					 | 
				
			||||||
		pid = thread->request.u.exec.pid;
 | 
					 | 
				
			||||||
		do_exec(thread->mode.tt.extern_pid, pid);
 | 
					 | 
				
			||||||
		thread->mode.tt.extern_pid = pid;
 | 
					 | 
				
			||||||
		cpu_tasks[task_thread_info(task)->cpu].pid = pid;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case OP_FORK:
 | 
					 | 
				
			||||||
		attach_process(thread->request.u.fork.pid);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case OP_CB:
 | 
					 | 
				
			||||||
		(*thread->request.u.cb.proc)(thread->request.u.cb.arg);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case OP_REBOOT:
 | 
					 | 
				
			||||||
	case OP_HALT:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		tracer_panic("Bad op in do_proc_op");
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	thread->request.op = OP_NONE;
 | 
					 | 
				
			||||||
	return(op);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void init_idle_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	default_idle();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern void start_kernel(void);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int start_kernel_proc(void *unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	block_signals();
 | 
					 | 
				
			||||||
	pid = os_getpid();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cpu_tasks[0].pid = pid;
 | 
					 | 
				
			||||||
	cpu_tasks[0].task = current;
 | 
					 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					 | 
				
			||||||
 	cpu_online_map = cpumask_of_cpu(0);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	if(debug) os_stop_process(pid);
 | 
					 | 
				
			||||||
	start_kernel();
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_tracing(void *task, int tracing)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	((struct task_struct *) task)->thread.mode.tt.tracing = tracing;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int is_tracing(void *t)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return (((struct task_struct *) t)->thread.mode.tt.tracing);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int set_user_mode(void *t)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct task_struct *task;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	task = t ? t : current;
 | 
					 | 
				
			||||||
	if(task->thread.mode.tt.tracing) 
 | 
					 | 
				
			||||||
		return(1);
 | 
					 | 
				
			||||||
	task->thread.request.op = OP_TRACE_ON;
 | 
					 | 
				
			||||||
	os_usr1_process(os_getpid());
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void set_init_pid(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	init_task.thread.mode.tt.extern_pid = pid;
 | 
					 | 
				
			||||||
	err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
 | 
					 | 
				
			||||||
	if(err)
 | 
					 | 
				
			||||||
		panic("Can't create switch pipe for init_task, errno = %d",
 | 
					 | 
				
			||||||
		      -err);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int start_uml_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	void *sp;
 | 
					 | 
				
			||||||
	int pages;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
 | 
					 | 
				
			||||||
	sp = task_stack_page(&init_task) +
 | 
					 | 
				
			||||||
		pages * PAGE_SIZE - sizeof(unsigned long);
 | 
					 | 
				
			||||||
	return(tracer(start_kernel_proc, sp));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int external_pid_tt(struct task_struct *task)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(task->thread.mode.tt.extern_pid);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int thread_pid_tt(struct task_struct *task)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(task->thread.mode.tt.extern_pid);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int is_valid_pid(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct task_struct *task;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        read_lock(&tasklist_lock);
 | 
					 | 
				
			||||||
        for_each_process(task){
 | 
					 | 
				
			||||||
                if(task->thread.mode.tt.extern_pid == pid){
 | 
					 | 
				
			||||||
			read_unlock(&tasklist_lock);
 | 
					 | 
				
			||||||
			return(1);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
	read_unlock(&tasklist_lock);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,10 +0,0 @@
 | 
				
			||||||
# 
 | 
					 | 
				
			||||||
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
# Licensed under the GPL
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-y = proxy.o ptrace.o sysdep.o wait.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USER_OBJS := $(obj-y)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
include arch/um/scripts/Makefile.rules
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,377 +0,0 @@
 | 
				
			||||||
/**********************************************************************
 | 
					 | 
				
			||||||
proxy.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright (C) 1999 Lars Brinkhoff.  See the file COPYING for licensing
 | 
					 | 
				
			||||||
terms and conditions.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Jeff Dike (jdike@karaya.com) : Modified for integration into uml
 | 
					 | 
				
			||||||
**********************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* XXX This file shouldn't refer to CONFIG_* */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <termios.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
#include <sys/ioctl.h>
 | 
					 | 
				
			||||||
#include <asm/unistd.h>
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "ptproxy.h"
 | 
					 | 
				
			||||||
#include "sysdep.h"
 | 
					 | 
				
			||||||
#include "wait.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "user.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
#include "tempfile.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int debugger_wait(debugger_state *debugger, int *status, int options,
 | 
					 | 
				
			||||||
			 int (*syscall)(debugger_state *debugger, pid_t child),
 | 
					 | 
				
			||||||
			 int (*normal_return)(debugger_state *debugger, 
 | 
					 | 
				
			||||||
					      pid_t unused),
 | 
					 | 
				
			||||||
			 int (*wait_return)(debugger_state *debugger, 
 | 
					 | 
				
			||||||
					    pid_t unused))
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(debugger->real_wait){
 | 
					 | 
				
			||||||
		debugger->handle_trace = normal_return;
 | 
					 | 
				
			||||||
		syscall_continue(debugger->pid);
 | 
					 | 
				
			||||||
		debugger->real_wait = 0;
 | 
					 | 
				
			||||||
		return(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	debugger->wait_status_ptr = status;
 | 
					 | 
				
			||||||
	debugger->wait_options = options;
 | 
					 | 
				
			||||||
	if((debugger->debugee != NULL) && debugger->debugee->event){
 | 
					 | 
				
			||||||
		syscall_continue(debugger->pid);
 | 
					 | 
				
			||||||
		wait_for_stop(debugger->pid, SIGTRAP, PTRACE_SYSCALL,
 | 
					 | 
				
			||||||
			      NULL);
 | 
					 | 
				
			||||||
		(*wait_return)(debugger, -1);
 | 
					 | 
				
			||||||
		return(0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if(debugger->wait_options & WNOHANG){
 | 
					 | 
				
			||||||
		syscall_cancel(debugger->pid, 0);
 | 
					 | 
				
			||||||
		debugger->handle_trace = syscall;
 | 
					 | 
				
			||||||
		return(0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		syscall_pause(debugger->pid);
 | 
					 | 
				
			||||||
		debugger->handle_trace = wait_return;
 | 
					 | 
				
			||||||
		debugger->waiting = 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Handle debugger trap, i.e. syscall.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int debugger_syscall(debugger_state *debugger, pid_t child)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	long arg1, arg2, arg3, arg4, arg5, result;
 | 
					 | 
				
			||||||
	int syscall, ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	syscall = get_syscall(debugger->pid, &arg1, &arg2, &arg3, &arg4, 
 | 
					 | 
				
			||||||
			      &arg5);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(syscall){
 | 
					 | 
				
			||||||
	case __NR_execve:
 | 
					 | 
				
			||||||
		/* execve never returns */
 | 
					 | 
				
			||||||
		debugger->handle_trace = debugger_syscall; 
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case __NR_ptrace:
 | 
					 | 
				
			||||||
		if(debugger->debugee->pid != 0) arg2 = debugger->debugee->pid;
 | 
					 | 
				
			||||||
		if(!debugger->debugee->in_context) 
 | 
					 | 
				
			||||||
			child = debugger->debugee->pid;
 | 
					 | 
				
			||||||
		result = proxy_ptrace(debugger, arg1, arg2, arg3, arg4, child,
 | 
					 | 
				
			||||||
				      &ret);
 | 
					 | 
				
			||||||
		syscall_cancel(debugger->pid, result);
 | 
					 | 
				
			||||||
		debugger->handle_trace = debugger_syscall;
 | 
					 | 
				
			||||||
		return(ret);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __NR_waitpid
 | 
					 | 
				
			||||||
	case __NR_waitpid:
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	case __NR_wait4:
 | 
					 | 
				
			||||||
		if(!debugger_wait(debugger, (int *) arg2, arg3, 
 | 
					 | 
				
			||||||
				  debugger_syscall, debugger_normal_return, 
 | 
					 | 
				
			||||||
				  proxy_wait_return))
 | 
					 | 
				
			||||||
			return(0);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case __NR_kill:
 | 
					 | 
				
			||||||
		if(!debugger->debugee->in_context) 
 | 
					 | 
				
			||||||
			child = debugger->debugee->pid;
 | 
					 | 
				
			||||||
		if(arg1 == debugger->debugee->pid){
 | 
					 | 
				
			||||||
			result = kill(child, arg2);
 | 
					 | 
				
			||||||
			syscall_cancel(debugger->pid, result);
 | 
					 | 
				
			||||||
			debugger->handle_trace = debugger_syscall;
 | 
					 | 
				
			||||||
			return(0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else debugger->handle_trace = debugger_normal_return;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		debugger->handle_trace = debugger_normal_return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	syscall_continue(debugger->pid);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Used by the tracing thread */
 | 
					 | 
				
			||||||
static debugger_state parent;
 | 
					 | 
				
			||||||
static int parent_syscall(debugger_state *debugger, int pid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int init_parent_proxy(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	parent = ((debugger_state) { .pid 		= pid,
 | 
					 | 
				
			||||||
				     .wait_options 	= 0,
 | 
					 | 
				
			||||||
				     .wait_status_ptr 	= NULL,
 | 
					 | 
				
			||||||
				     .waiting 		= 0,
 | 
					 | 
				
			||||||
				     .real_wait 	= 0,
 | 
					 | 
				
			||||||
				     .expecting_child 	= 0,
 | 
					 | 
				
			||||||
				     .handle_trace  	= parent_syscall,
 | 
					 | 
				
			||||||
				     .debugee 		= NULL } );
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int parent_normal_return(debugger_state *debugger, pid_t unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debugger->handle_trace = parent_syscall;
 | 
					 | 
				
			||||||
	syscall_continue(debugger->pid);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int parent_syscall(debugger_state *debugger, int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	long arg1, arg2, arg3, arg4, arg5;
 | 
					 | 
				
			||||||
	int syscall;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	syscall = get_syscall(pid, &arg1, &arg2, &arg3, &arg4, &arg5);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
	if((syscall == __NR_wait4)
 | 
					 | 
				
			||||||
#ifdef __NR_waitpid
 | 
					 | 
				
			||||||
	   || (syscall == __NR_waitpid)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	){
 | 
					 | 
				
			||||||
		debugger_wait(&parent, (int *) arg2, arg3, parent_syscall,
 | 
					 | 
				
			||||||
			      parent_normal_return, parent_wait_return);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else ptrace(PTRACE_SYSCALL, pid, 0, 0);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int debugger_normal_return(debugger_state *debugger, pid_t unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debugger->handle_trace = debugger_syscall;
 | 
					 | 
				
			||||||
	syscall_continue(debugger->pid);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void debugger_cancelled_return(debugger_state *debugger, int result)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debugger->handle_trace = debugger_syscall;
 | 
					 | 
				
			||||||
	syscall_set_result(debugger->pid, result);
 | 
					 | 
				
			||||||
	syscall_continue(debugger->pid);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Used by the tracing thread */
 | 
					 | 
				
			||||||
static debugger_state debugger;
 | 
					 | 
				
			||||||
static debugee_state debugee;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void init_proxy (pid_t debugger_pid, int stopped, int status)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debugger.pid = debugger_pid;
 | 
					 | 
				
			||||||
	debugger.handle_trace = debugger_syscall;
 | 
					 | 
				
			||||||
	debugger.debugee = &debugee;
 | 
					 | 
				
			||||||
	debugger.waiting = 0;
 | 
					 | 
				
			||||||
	debugger.real_wait = 0;
 | 
					 | 
				
			||||||
	debugger.expecting_child = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	debugee.pid = 0;
 | 
					 | 
				
			||||||
	debugee.traced = 0;
 | 
					 | 
				
			||||||
	debugee.stopped = stopped;
 | 
					 | 
				
			||||||
	debugee.event = 0;
 | 
					 | 
				
			||||||
	debugee.zombie = 0;
 | 
					 | 
				
			||||||
	debugee.died = 0;
 | 
					 | 
				
			||||||
	debugee.wait_status = status;
 | 
					 | 
				
			||||||
	debugee.in_context = 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int debugger_proxy(int status, int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret = 0, sig;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(WIFSTOPPED(status)){
 | 
					 | 
				
			||||||
		sig = WSTOPSIG(status);
 | 
					 | 
				
			||||||
		if (sig == SIGTRAP)
 | 
					 | 
				
			||||||
			ret = (*debugger.handle_trace)(&debugger, pid);
 | 
					 | 
				
			||||||
						       
 | 
					 | 
				
			||||||
		else if(sig == SIGCHLD){
 | 
					 | 
				
			||||||
			if(debugger.expecting_child){
 | 
					 | 
				
			||||||
				ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
 | 
					 | 
				
			||||||
				debugger.expecting_child = 0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else if(debugger.waiting)
 | 
					 | 
				
			||||||
				real_wait_return(&debugger);
 | 
					 | 
				
			||||||
			else {
 | 
					 | 
				
			||||||
				ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
 | 
					 | 
				
			||||||
				debugger.real_wait = 1;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else ptrace(PTRACE_SYSCALL, debugger.pid, 0, sig);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if(WIFEXITED(status)){
 | 
					 | 
				
			||||||
		tracer_panic("debugger (pid %d) exited with status %d", 
 | 
					 | 
				
			||||||
			     debugger.pid, WEXITSTATUS(status));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if(WIFSIGNALED(status)){
 | 
					 | 
				
			||||||
		tracer_panic("debugger (pid %d) exited with signal %d", 
 | 
					 | 
				
			||||||
			     debugger.pid, WTERMSIG(status));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else {
 | 
					 | 
				
			||||||
		tracer_panic("proxy got unknown status (0x%x) on debugger "
 | 
					 | 
				
			||||||
			     "(pid %d)", status, debugger.pid);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return(ret);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void child_proxy(pid_t pid, int status)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debugee.event = 1;
 | 
					 | 
				
			||||||
	debugee.wait_status = status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(WIFSTOPPED(status)){
 | 
					 | 
				
			||||||
		debugee.stopped = 1;
 | 
					 | 
				
			||||||
		debugger.expecting_child = 1;
 | 
					 | 
				
			||||||
		kill(debugger.pid, SIGCHLD);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else if(WIFEXITED(status) || WIFSIGNALED(status)){
 | 
					 | 
				
			||||||
		debugee.zombie = 1;
 | 
					 | 
				
			||||||
		debugger.expecting_child = 1;
 | 
					 | 
				
			||||||
		kill(debugger.pid, SIGCHLD);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else panic("proxy got unknown status (0x%x) on child (pid %d)", 
 | 
					 | 
				
			||||||
		   status, pid);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void debugger_parent_signal(int status, int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int sig;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(WIFSTOPPED(status)){
 | 
					 | 
				
			||||||
		sig = WSTOPSIG(status);
 | 
					 | 
				
			||||||
		if(sig == SIGTRAP) (*parent.handle_trace)(&parent, pid);
 | 
					 | 
				
			||||||
		else ptrace(PTRACE_SYSCALL, pid, 0, sig);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void fake_child_exit(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int status, pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	child_proxy(1, W_EXITCODE(0, 0));
 | 
					 | 
				
			||||||
	while(debugger.waiting == 1){
 | 
					 | 
				
			||||||
		CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
 | 
					 | 
				
			||||||
		if(pid != debugger.pid){
 | 
					 | 
				
			||||||
			printk("fake_child_exit - waitpid failed, "
 | 
					 | 
				
			||||||
			       "errno = %d\n", errno);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		debugger_proxy(status, debugger.pid);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED));
 | 
					 | 
				
			||||||
	if(pid != debugger.pid){
 | 
					 | 
				
			||||||
		printk("fake_child_exit - waitpid failed, "
 | 
					 | 
				
			||||||
		       "errno = %d\n", errno);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(ptrace(PTRACE_DETACH, debugger.pid, 0, SIGCONT) < 0)
 | 
					 | 
				
			||||||
		printk("fake_child_exit - PTRACE_DETACH failed, errno = %d\n",
 | 
					 | 
				
			||||||
		       errno);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
char gdb_init_string[] = 
 | 
					 | 
				
			||||||
"att 1 \n\
 | 
					 | 
				
			||||||
b panic \n\
 | 
					 | 
				
			||||||
b stop \n\
 | 
					 | 
				
			||||||
handle SIGWINCH nostop noprint pass \n\
 | 
					 | 
				
			||||||
";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int start_debugger(char *prog, int startup, int stop, int *fd_out)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int slave, child;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	slave = open_gdb_chan();
 | 
					 | 
				
			||||||
	child = fork();
 | 
					 | 
				
			||||||
	if(child == 0){
 | 
					 | 
				
			||||||
		char *tempname = NULL;
 | 
					 | 
				
			||||||
		int fd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	        if(setsid() < 0) perror("setsid");
 | 
					 | 
				
			||||||
		if((dup2(slave, 0) < 0) || (dup2(slave, 1) < 0) || 
 | 
					 | 
				
			||||||
		   (dup2(slave, 2) < 0)){
 | 
					 | 
				
			||||||
			printk("start_debugger : dup2 failed, errno = %d\n",
 | 
					 | 
				
			||||||
			       errno);
 | 
					 | 
				
			||||||
			exit(1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(ioctl(0, TIOCSCTTY, 0) < 0){
 | 
					 | 
				
			||||||
			printk("start_debugger : TIOCSCTTY failed, "
 | 
					 | 
				
			||||||
			       "errno = %d\n", errno);
 | 
					 | 
				
			||||||
			exit(1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(tcsetpgrp (1, os_getpid()) < 0){
 | 
					 | 
				
			||||||
			printk("start_debugger : tcsetpgrp failed, "
 | 
					 | 
				
			||||||
			       "errno = %d\n", errno);
 | 
					 | 
				
			||||||
#ifdef notdef
 | 
					 | 
				
			||||||
			exit(1);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
 | 
					 | 
				
			||||||
		if(fd < 0){
 | 
					 | 
				
			||||||
			printk("start_debugger : make_tempfile failed,"
 | 
					 | 
				
			||||||
			       "err = %d\n", -fd);
 | 
					 | 
				
			||||||
			exit(1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		os_write_file(fd, gdb_init_string,
 | 
					 | 
				
			||||||
			      sizeof(gdb_init_string) - 1);
 | 
					 | 
				
			||||||
		if(startup){
 | 
					 | 
				
			||||||
			if(stop){
 | 
					 | 
				
			||||||
				os_write_file(fd, "b start_kernel\n",
 | 
					 | 
				
			||||||
						strlen("b start_kernel\n"));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			os_write_file(fd, "c\n", strlen("c\n"));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
 | 
					 | 
				
			||||||
			printk("start_debugger :  PTRACE_TRACEME failed, "
 | 
					 | 
				
			||||||
			       "errno = %d\n", errno);
 | 
					 | 
				
			||||||
			exit(1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		execlp("gdb", "gdb", "--command", tempname, prog, NULL);
 | 
					 | 
				
			||||||
		printk("start_debugger : exec of gdb failed, errno = %d\n",
 | 
					 | 
				
			||||||
		       errno);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(child < 0){
 | 
					 | 
				
			||||||
		printk("start_debugger : fork for gdb failed, errno = %d\n",
 | 
					 | 
				
			||||||
		       errno);
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	*fd_out = slave;
 | 
					 | 
				
			||||||
	return(child);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,61 +0,0 @@
 | 
				
			||||||
/**********************************************************************
 | 
					 | 
				
			||||||
ptproxy.h
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright (C) 1999 Lars Brinkhoff.  See the file COPYING for licensing
 | 
					 | 
				
			||||||
terms and conditions.
 | 
					 | 
				
			||||||
**********************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __PTPROXY_H
 | 
					 | 
				
			||||||
#define __PTPROXY_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct debugger debugger_state;
 | 
					 | 
				
			||||||
typedef struct debugee debugee_state;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct debugger
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	pid_t pid;
 | 
					 | 
				
			||||||
	int wait_options;
 | 
					 | 
				
			||||||
	int *wait_status_ptr;
 | 
					 | 
				
			||||||
	unsigned int waiting : 1;
 | 
					 | 
				
			||||||
	unsigned int real_wait : 1;
 | 
					 | 
				
			||||||
	unsigned int expecting_child : 1;
 | 
					 | 
				
			||||||
	int (*handle_trace) (debugger_state *, pid_t);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	debugee_state *debugee;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct debugee
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	pid_t pid;
 | 
					 | 
				
			||||||
	int wait_status;
 | 
					 | 
				
			||||||
	unsigned int died : 1;
 | 
					 | 
				
			||||||
	unsigned int event : 1;
 | 
					 | 
				
			||||||
	unsigned int stopped : 1;
 | 
					 | 
				
			||||||
	unsigned int trace_singlestep : 1;
 | 
					 | 
				
			||||||
	unsigned int trace_syscall : 1;
 | 
					 | 
				
			||||||
	unsigned int traced : 1;
 | 
					 | 
				
			||||||
	unsigned int zombie : 1;
 | 
					 | 
				
			||||||
	unsigned int in_context : 1;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int debugger_syscall(debugger_state *debugger, pid_t pid);
 | 
					 | 
				
			||||||
extern int debugger_normal_return (debugger_state *debugger, pid_t unused);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern long proxy_ptrace (struct debugger *, int, pid_t, long, long, pid_t,
 | 
					 | 
				
			||||||
			  int *strace_out);
 | 
					 | 
				
			||||||
extern void debugger_cancelled_return(debugger_state *debugger, int result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,237 +0,0 @@
 | 
				
			||||||
/**********************************************************************
 | 
					 | 
				
			||||||
ptrace.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright (C) 1999 Lars Brinkhoff.  See the file COPYING for licensing
 | 
					 | 
				
			||||||
terms and conditions.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Jeff Dike (jdike@karaya.com) : Modified for integration into uml
 | 
					 | 
				
			||||||
**********************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
#include <sys/time.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "ptproxy.h"
 | 
					 | 
				
			||||||
#include "debug.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
 | 
					 | 
				
			||||||
		  long arg3, long arg4, pid_t child, int *ret)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	sigset_t relay;
 | 
					 | 
				
			||||||
	long result;
 | 
					 | 
				
			||||||
	int status;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*ret = 0;
 | 
					 | 
				
			||||||
	if(debugger->debugee->died) return(-ESRCH);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(arg1){
 | 
					 | 
				
			||||||
	case PTRACE_ATTACH:
 | 
					 | 
				
			||||||
		if(debugger->debugee->traced) return(-EPERM);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		debugger->debugee->pid = arg2;
 | 
					 | 
				
			||||||
		debugger->debugee->traced = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if(is_valid_pid(arg2) && (arg2 != child)){
 | 
					 | 
				
			||||||
			debugger->debugee->in_context = 0;
 | 
					 | 
				
			||||||
			kill(arg2, SIGSTOP);
 | 
					 | 
				
			||||||
			debugger->debugee->event = 1;
 | 
					 | 
				
			||||||
			debugger->debugee->wait_status = W_STOPCODE(SIGSTOP);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else {
 | 
					 | 
				
			||||||
			debugger->debugee->in_context = 1;
 | 
					 | 
				
			||||||
			if(debugger->debugee->stopped) 
 | 
					 | 
				
			||||||
				child_proxy(child, W_STOPCODE(SIGSTOP));
 | 
					 | 
				
			||||||
			else kill(child, SIGSTOP);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_DETACH:
 | 
					 | 
				
			||||||
		if(!debugger->debugee->traced) return(-EPERM);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		debugger->debugee->traced = 0;
 | 
					 | 
				
			||||||
		debugger->debugee->pid = 0;
 | 
					 | 
				
			||||||
		if(!debugger->debugee->in_context)
 | 
					 | 
				
			||||||
			kill(child, SIGCONT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_CONT:
 | 
					 | 
				
			||||||
		if(!debugger->debugee->in_context) return(-EPERM);
 | 
					 | 
				
			||||||
		*ret = PTRACE_CONT;
 | 
					 | 
				
			||||||
		return(ptrace(PTRACE_CONT, child, arg3, arg4));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UM_HAVE_GETFPREGS
 | 
					 | 
				
			||||||
	case PTRACE_GETFPREGS:
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		long regs[FP_FRAME_SIZE];
 | 
					 | 
				
			||||||
		int i, result;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_GETFPREGS, child, 0, regs);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
 | 
					 | 
				
			||||||
			ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
 | 
					 | 
				
			||||||
			       regs[i]);
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UM_HAVE_GETFPXREGS
 | 
					 | 
				
			||||||
	case PTRACE_GETFPXREGS:
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		long regs[FPX_FRAME_SIZE];
 | 
					 | 
				
			||||||
		int i, result;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_GETFPXREGS, child, 0, regs);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
 | 
					 | 
				
			||||||
			ptrace(PTRACE_POKEDATA, debugger->pid, arg4 + 4 * i,
 | 
					 | 
				
			||||||
			       regs[i]);
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UM_HAVE_GETREGS
 | 
					 | 
				
			||||||
	case PTRACE_GETREGS:
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		long regs[FRAME_SIZE];
 | 
					 | 
				
			||||||
		int i, result;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_GETREGS, child, 0, regs);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
 | 
					 | 
				
			||||||
			ptrace (PTRACE_POKEDATA, debugger->pid,
 | 
					 | 
				
			||||||
				arg4 + 4 * i, regs[i]);
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	break;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_KILL:
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_KILL, child, arg3, arg4);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_PEEKDATA:
 | 
					 | 
				
			||||||
	case PTRACE_PEEKTEXT:
 | 
					 | 
				
			||||||
	case PTRACE_PEEKUSR:
 | 
					 | 
				
			||||||
		/* The value being read out could be -1, so we have to 
 | 
					 | 
				
			||||||
		 * check errno to see if there's an error, and zero it
 | 
					 | 
				
			||||||
		 * beforehand so we're not faked out by an old error
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		errno = 0;
 | 
					 | 
				
			||||||
		result = ptrace(arg1, child, arg3, 0);
 | 
					 | 
				
			||||||
		if((result == -1) && (errno != 0)) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_POKEDATA, debugger->pid, arg4, result);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_POKEDATA:
 | 
					 | 
				
			||||||
	case PTRACE_POKETEXT:
 | 
					 | 
				
			||||||
	case PTRACE_POKEUSR:
 | 
					 | 
				
			||||||
		result = ptrace(arg1, child, arg3, arg4);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UM_HAVE_SETFPREGS
 | 
					 | 
				
			||||||
	case PTRACE_SETFPREGS:
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		long regs[FP_FRAME_SIZE];
 | 
					 | 
				
			||||||
		int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
 | 
					 | 
				
			||||||
			regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
 | 
					 | 
				
			||||||
					  arg4 + 4 * i, 0);
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_SETFPREGS, child, 0, regs);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UM_HAVE_SETFPXREGS
 | 
					 | 
				
			||||||
	case PTRACE_SETFPXREGS:
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		long regs[FPX_FRAME_SIZE];
 | 
					 | 
				
			||||||
		int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
 | 
					 | 
				
			||||||
			regs[i] = ptrace (PTRACE_PEEKDATA, debugger->pid,
 | 
					 | 
				
			||||||
					  arg4 + 4 * i, 0);
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_SETFPXREGS, child, 0, regs);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UM_HAVE_SETREGS
 | 
					 | 
				
			||||||
	case PTRACE_SETREGS:
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		long regs[FRAME_SIZE];
 | 
					 | 
				
			||||||
		int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++)
 | 
					 | 
				
			||||||
			regs[i] = ptrace(PTRACE_PEEKDATA, debugger->pid,
 | 
					 | 
				
			||||||
					 arg4 + 4 * i, 0);
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_SETREGS, child, 0, regs);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_SINGLESTEP:
 | 
					 | 
				
			||||||
		if(!debugger->debugee->in_context) return(-EPERM);
 | 
					 | 
				
			||||||
		sigemptyset(&relay);
 | 
					 | 
				
			||||||
		sigaddset(&relay, SIGSEGV);
 | 
					 | 
				
			||||||
		sigaddset(&relay, SIGILL);
 | 
					 | 
				
			||||||
		sigaddset(&relay, SIGBUS);
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_SINGLESTEP, child, arg3, arg4);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		status = wait_for_stop(child, SIGTRAP, PTRACE_SINGLESTEP,
 | 
					 | 
				
			||||||
				       &relay);
 | 
					 | 
				
			||||||
		child_proxy(child, status);
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_SYSCALL:
 | 
					 | 
				
			||||||
		if(!debugger->debugee->in_context) return(-EPERM);
 | 
					 | 
				
			||||||
		result = ptrace(PTRACE_SYSCALL, child, arg3, arg4);
 | 
					 | 
				
			||||||
		if(result == -1) return(-errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		*ret = PTRACE_SYSCALL;
 | 
					 | 
				
			||||||
		return(result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	case PTRACE_TRACEME:
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		return(-EINVAL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,70 +0,0 @@
 | 
				
			||||||
/**********************************************************************
 | 
					 | 
				
			||||||
sysdep.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright (C) 1999 Lars Brinkhoff.  See the file COPYING for licensing
 | 
					 | 
				
			||||||
terms and conditions.
 | 
					 | 
				
			||||||
**********************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <sys/types.h>
 | 
					 | 
				
			||||||
#include <linux/unistd.h>
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
#include "user.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, 
 | 
					 | 
				
			||||||
		long *arg5)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	*arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0);
 | 
					 | 
				
			||||||
	*arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0);
 | 
					 | 
				
			||||||
	*arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0);
 | 
					 | 
				
			||||||
	*arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0);
 | 
					 | 
				
			||||||
	*arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0);
 | 
					 | 
				
			||||||
	return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void syscall_cancel(pid_t pid, int result)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
 | 
					 | 
				
			||||||
		   __NR_getpid) < 0) ||
 | 
					 | 
				
			||||||
	   (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) ||
 | 
					 | 
				
			||||||
	   (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) ||
 | 
					 | 
				
			||||||
	   (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
 | 
					 | 
				
			||||||
	   (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0))
 | 
					 | 
				
			||||||
		printk("ptproxy: couldn't cancel syscall: errno = %d\n", 
 | 
					 | 
				
			||||||
		       errno);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void syscall_set_result(pid_t pid, long result)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void syscall_continue(pid_t pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ptrace(PTRACE_SYSCALL, pid, 0, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int syscall_pause(pid_t pid) 
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
 | 
					 | 
				
			||||||
		printk("syscall_change - ptrace failed, errno = %d\n", errno);
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,25 +0,0 @@
 | 
				
			||||||
/**********************************************************************
 | 
					 | 
				
			||||||
sysdep.h
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright (C) 1999 Lars Brinkhoff.
 | 
					 | 
				
			||||||
Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
See the file COPYING for licensing terms and conditions.
 | 
					 | 
				
			||||||
**********************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, 
 | 
					 | 
				
			||||||
		       long *arg4, long *arg5);
 | 
					 | 
				
			||||||
extern void syscall_cancel (pid_t pid, long result);
 | 
					 | 
				
			||||||
extern void syscall_set_result (pid_t pid, long result);
 | 
					 | 
				
			||||||
extern void syscall_continue (pid_t pid);
 | 
					 | 
				
			||||||
extern int syscall_pause(pid_t pid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,85 +0,0 @@
 | 
				
			||||||
/**********************************************************************
 | 
					 | 
				
			||||||
wait.c
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright (C) 1999 Lars Brinkhoff.  See the file COPYING for licensing
 | 
					 | 
				
			||||||
terms and conditions.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**********************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "ptproxy.h"
 | 
					 | 
				
			||||||
#include "sysdep.h"
 | 
					 | 
				
			||||||
#include "wait.h"
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					 | 
				
			||||||
#include "sysdep/sigcontext.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int proxy_wait_return(struct debugger *debugger, pid_t unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debugger->waiting = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(debugger->debugee->died || (debugger->wait_options & __WCLONE)){
 | 
					 | 
				
			||||||
		debugger_cancelled_return(debugger, -ECHILD);
 | 
					 | 
				
			||||||
		return(0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(debugger->debugee->zombie && debugger->debugee->event)
 | 
					 | 
				
			||||||
		debugger->debugee->died = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(debugger->debugee->event){
 | 
					 | 
				
			||||||
		debugger->debugee->event = 0;
 | 
					 | 
				
			||||||
		ptrace(PTRACE_POKEDATA, debugger->pid,
 | 
					 | 
				
			||||||
		       debugger->wait_status_ptr, 
 | 
					 | 
				
			||||||
		       debugger->debugee->wait_status);
 | 
					 | 
				
			||||||
		/* if (wait4)
 | 
					 | 
				
			||||||
		   ptrace (PTRACE_POKEDATA, pid, rusage_ptr, ...); */
 | 
					 | 
				
			||||||
		debugger_cancelled_return(debugger, debugger->debugee->pid);
 | 
					 | 
				
			||||||
		return(0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* pause will return -EINTR, which happens to be right for wait */
 | 
					 | 
				
			||||||
	debugger_normal_return(debugger, -1);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int parent_wait_return(struct debugger *debugger, pid_t unused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(debugger_normal_return(debugger, -1));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int real_wait_return(struct debugger *debugger)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long ip;
 | 
					 | 
				
			||||||
	int pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pid = debugger->pid;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
 | 
					 | 
				
			||||||
	IP_RESTART_SYSCALL(ip);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("real_wait_return : Failed to restart system "
 | 
					 | 
				
			||||||
			     "call, errno = %d\n", errno);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
 | 
					 | 
				
			||||||
	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 | 
					 | 
				
			||||||
	   (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
 | 
					 | 
				
			||||||
	   debugger_normal_return(debugger, -1))
 | 
					 | 
				
			||||||
		tracer_panic("real_wait_return : gdb failed to wait, "
 | 
					 | 
				
			||||||
			     "errno = %d\n", errno);
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,15 +0,0 @@
 | 
				
			||||||
/**********************************************************************
 | 
					 | 
				
			||||||
wait.h
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Copyright (C) 1999 Lars Brinkhoff.  See the file COPYING for licensing
 | 
					 | 
				
			||||||
terms and conditions.
 | 
					 | 
				
			||||||
**********************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef __PTPROXY_WAIT_H
 | 
					 | 
				
			||||||
#define __PTPROXY_WAIT_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int proxy_wait_return(struct debugger *debugger, pid_t unused);
 | 
					 | 
				
			||||||
extern int real_wait_return(struct debugger *debugger);
 | 
					 | 
				
			||||||
extern int parent_wait_return(struct debugger *debugger, pid_t unused);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,46 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/types.h"
 | 
					 | 
				
			||||||
#include "linux/utime.h"
 | 
					 | 
				
			||||||
#include "linux/sys.h"
 | 
					 | 
				
			||||||
#include "linux/ptrace.h"
 | 
					 | 
				
			||||||
#include "asm/unistd.h"
 | 
					 | 
				
			||||||
#include "asm/ptrace.h"
 | 
					 | 
				
			||||||
#include "asm/uaccess.h"
 | 
					 | 
				
			||||||
#include "asm/stat.h"
 | 
					 | 
				
			||||||
#include "sysdep/syscalls.h"
 | 
					 | 
				
			||||||
#include "sysdep/sigcontext.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "syscall.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void syscall_handler_tt(int sig, struct pt_regs *regs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	void *sc;
 | 
					 | 
				
			||||||
	long result;
 | 
					 | 
				
			||||||
	int syscall;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	sc = UPT_SC(®s->regs);
 | 
					 | 
				
			||||||
	SC_START_SYSCALL(sc);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	syscall = UPT_SYSCALL_NR(®s->regs);
 | 
					 | 
				
			||||||
	syscall_trace(®s->regs, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	current->thread.nsyscalls++;
 | 
					 | 
				
			||||||
	nsyscalls++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if((syscall >= NR_syscalls) || (syscall < 0))
 | 
					 | 
				
			||||||
		result = -ENOSYS;
 | 
					 | 
				
			||||||
	else result = EXECUTE_SYSCALL(syscall, regs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* regs->sc may have changed while the system call ran (there may
 | 
					 | 
				
			||||||
	 * have been an interrupt or segfault), so it needs to be refreshed.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	UPT_SC(®s->regs) = sc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	SC_SET_SYSCALL_RETURN(sc, result);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	syscall_trace(®s->regs, 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,60 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <asm/unistd.h>
 | 
					 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					 | 
				
			||||||
#include "sigcontext.h"
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
#include "task.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "syscall.h"
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void do_sigtrap(void *task)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void do_syscall(void *task, int pid, int local_using_sysemu)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long proc_regs[FRAME_SIZE];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(ptrace_getregs(pid, proc_regs) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("Couldn't read registers");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UPT_ORIGGPR2
 | 
					 | 
				
			||||||
        UPT_ORIGGPR2(TASK_REGS(task)) = REGS_ORIGGPR2(proc_regs);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
 | 
					 | 
				
			||||||
	   ((unsigned long *) PT_IP(proc_regs) <= &_etext))
 | 
					 | 
				
			||||||
		tracer_panic("I'm tracing myself and I can't get out");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* advanced sysemu mode set syscall number to -1 automatically */
 | 
					 | 
				
			||||||
	if (local_using_sysemu==2)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* syscall number -1 in sysemu skips syscall restarting in host */
 | 
					 | 
				
			||||||
	if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
 | 
					 | 
				
			||||||
		  local_using_sysemu ? -1 : __NR_getpid) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("do_syscall : Nullifying syscall 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
 | 
					 | 
				
			||||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
					 | 
				
			||||||
 * of the file.
 | 
					 | 
				
			||||||
 * ---------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * Local variables:
 | 
					 | 
				
			||||||
 * c-file-style: "linux"
 | 
					 | 
				
			||||||
 * End:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,120 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Copyright 2003 PathScale, Inc.
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/stddef.h"
 | 
					 | 
				
			||||||
#include "linux/kernel.h"
 | 
					 | 
				
			||||||
#include "linux/sched.h"
 | 
					 | 
				
			||||||
#include "linux/mm.h"
 | 
					 | 
				
			||||||
#include "asm/page.h"
 | 
					 | 
				
			||||||
#include "asm/pgtable.h"
 | 
					 | 
				
			||||||
#include "asm/uaccess.h"
 | 
					 | 
				
			||||||
#include "asm/tlbflush.h"
 | 
					 | 
				
			||||||
#include "mem_user.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
#include "tlb.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int do_ops(union mm_context *mmu, struct host_vm_op *ops, int last,
 | 
					 | 
				
			||||||
		    int finished, void **flush)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct host_vm_op *op;
 | 
					 | 
				
			||||||
        int i, ret=0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(i = 0; i <= last && !ret; i++){
 | 
					 | 
				
			||||||
		op = &ops[i];
 | 
					 | 
				
			||||||
		switch(op->type){
 | 
					 | 
				
			||||||
		case MMAP:
 | 
					 | 
				
			||||||
                        ret = os_map_memory((void *) op->u.mmap.addr,
 | 
					 | 
				
			||||||
                                            op->u.mmap.fd, op->u.mmap.offset,
 | 
					 | 
				
			||||||
                                            op->u.mmap.len, op->u.mmap.r,
 | 
					 | 
				
			||||||
                                            op->u.mmap.w, op->u.mmap.x);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case MUNMAP:
 | 
					 | 
				
			||||||
                        ret = os_unmap_memory((void *) op->u.munmap.addr,
 | 
					 | 
				
			||||||
                                              op->u.munmap.len);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case MPROTECT:
 | 
					 | 
				
			||||||
                        ret = protect_memory(op->u.mprotect.addr,
 | 
					 | 
				
			||||||
                                             op->u.munmap.len,
 | 
					 | 
				
			||||||
                                             op->u.mprotect.r,
 | 
					 | 
				
			||||||
                                             op->u.mprotect.w,
 | 
					 | 
				
			||||||
                                             op->u.mprotect.x, 1);
 | 
					 | 
				
			||||||
			protect_memory(op->u.mprotect.addr, op->u.munmap.len,
 | 
					 | 
				
			||||||
				       op->u.mprotect.r, op->u.mprotect.w,
 | 
					 | 
				
			||||||
				       op->u.mprotect.x, 1);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			printk("Unknown op type %d in do_ops\n", op->type);
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void fix_range(struct mm_struct *mm, unsigned long start_addr, 
 | 
					 | 
				
			||||||
		      unsigned long end_addr, int force)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
        if((current->thread.mode.tt.extern_pid != -1) &&
 | 
					 | 
				
			||||||
           (current->thread.mode.tt.extern_pid != os_getpid()))
 | 
					 | 
				
			||||||
                panic("fix_range fixing wrong address space, current = 0x%p",
 | 
					 | 
				
			||||||
                      current);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fix_range_common(mm, start_addr, end_addr, force, do_ops);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
atomic_t vmchange_seq = ATOMIC_INIT(1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
        if(flush_tlb_kernel_range_common(start, end))
 | 
					 | 
				
			||||||
                atomic_inc(&vmchange_seq);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void flush_tlb_kernel_vm_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
        flush_tlb_kernel_range(start_vm, end_vm);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void __flush_tlb_one_tt(unsigned long addr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
        flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start, 
 | 
					 | 
				
			||||||
		     unsigned long end)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(vma->vm_mm != current->mm) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Assumes that the range start ... end is entirely within
 | 
					 | 
				
			||||||
	 * either process memory or kernel vm
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if((start >= start_vm) && (start < end_vm)){
 | 
					 | 
				
			||||||
		if(flush_tlb_kernel_range_common(start, end))
 | 
					 | 
				
			||||||
			atomic_inc(&vmchange_seq);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else fix_range(vma->vm_mm, start, end, 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void flush_tlb_mm_tt(struct mm_struct *mm)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long seq;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(mm != current->mm) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fix_range(mm, 0, STACK_TOP, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	seq = atomic_read(&vmchange_seq);
 | 
					 | 
				
			||||||
	if(current->thread.mode.tt.vm_seq == seq)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	current->thread.mode.tt.vm_seq = seq;
 | 
					 | 
				
			||||||
	flush_tlb_kernel_range_common(start_vm, end_vm);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void force_flush_all_tt(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	fix_range(current->mm, 0, STACK_TOP, 1);
 | 
					 | 
				
			||||||
	flush_tlb_kernel_range_common(start_vm, end_vm);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,461 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <stdarg.h>
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <sched.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <sys/mman.h>
 | 
					 | 
				
			||||||
#include <sys/time.h>
 | 
					 | 
				
			||||||
#include <sys/wait.h>
 | 
					 | 
				
			||||||
#include "user.h"
 | 
					 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					 | 
				
			||||||
#include "sigcontext.h"
 | 
					 | 
				
			||||||
#include "sysdep/sigcontext.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
#include "mem_user.h"
 | 
					 | 
				
			||||||
#include "process.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "chan_user.h"
 | 
					 | 
				
			||||||
#include "ptrace_user.h"
 | 
					 | 
				
			||||||
#include "irq_user.h"
 | 
					 | 
				
			||||||
#include "mode.h"
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int tracer_winch[2];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int is_tracer_winch(int pid, int fd, void *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(pid != os_getpgrp())
 | 
					 | 
				
			||||||
		return(0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	register_winch_irq(tracer_winch[0], fd, -1, data);
 | 
					 | 
				
			||||||
	return(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void tracer_winch_handler(int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int n;
 | 
					 | 
				
			||||||
	char c = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	n = os_write_file(tracer_winch[1], &c, sizeof(c));
 | 
					 | 
				
			||||||
	if(n != sizeof(c))
 | 
					 | 
				
			||||||
		printk("tracer_winch_handler - write failed, err = %d\n", -n);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Called only by the tracing thread during initialization */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void setup_tracer_winch(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = os_pipe(tracer_winch, 1, 1);
 | 
					 | 
				
			||||||
	if(err < 0){
 | 
					 | 
				
			||||||
		printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	signal(SIGWINCH, tracer_winch_handler);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void attach_process(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
 | 
					 | 
				
			||||||
	   (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
 | 
					 | 
				
			||||||
		tracer_panic("OP_FORK failed to attach pid");
 | 
					 | 
				
			||||||
	wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
 | 
					 | 
				
			||||||
	if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno);
 | 
					 | 
				
			||||||
	if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
 | 
					 | 
				
			||||||
		tracer_panic("OP_FORK failed to continue process");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void tracer_panic(char *format, ...)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	va_list ap;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	va_start(ap, format);
 | 
					 | 
				
			||||||
	vprintf(format, ap);
 | 
					 | 
				
			||||||
	va_end(ap);
 | 
					 | 
				
			||||||
	printf("\n");
 | 
					 | 
				
			||||||
	while(1) pause();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void tracer_segv(int sig, struct sigcontext sc)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
        struct faultinfo fi;
 | 
					 | 
				
			||||||
        GET_FAULTINFO_FROM_SC(fi, &sc);
 | 
					 | 
				
			||||||
	printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
 | 
					 | 
				
			||||||
               FAULT_ADDRESS(fi), SC_IP(&sc));
 | 
					 | 
				
			||||||
	while(1)
 | 
					 | 
				
			||||||
		pause();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Changed early in boot, and then only read */
 | 
					 | 
				
			||||||
int debug = 0;
 | 
					 | 
				
			||||||
int debug_stop = 1;
 | 
					 | 
				
			||||||
int debug_parent = 0;
 | 
					 | 
				
			||||||
int honeypot = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int signal_tramp(void *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int (*proc)(void *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(honeypot && munmap((void *) (host_task_size - 0x10000000),
 | 
					 | 
				
			||||||
			      0x10000000)) 
 | 
					 | 
				
			||||||
		panic("Unmapping stack failed");
 | 
					 | 
				
			||||||
	if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
 | 
					 | 
				
			||||||
		panic("ptrace PTRACE_TRACEME failed");
 | 
					 | 
				
			||||||
	os_stop_process(os_getpid());
 | 
					 | 
				
			||||||
	change_sig(SIGWINCH, 0);
 | 
					 | 
				
			||||||
	signal(SIGUSR1, SIG_IGN);
 | 
					 | 
				
			||||||
	change_sig(SIGCHLD, 0);
 | 
					 | 
				
			||||||
	signal(SIGSEGV, (__sighandler_t) sig_handler);
 | 
					 | 
				
			||||||
	set_cmdline("(idle thread)");
 | 
					 | 
				
			||||||
	set_init_pid(os_getpid());
 | 
					 | 
				
			||||||
	init_irq_signals(0);
 | 
					 | 
				
			||||||
	proc = arg;
 | 
					 | 
				
			||||||
	return((*proc)(NULL));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void sleeping_process_signal(int pid, int sig)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	switch(sig){
 | 
					 | 
				
			||||||
	/* These two result from UML being ^Z-ed and bg-ed.  PTRACE_CONT is
 | 
					 | 
				
			||||||
	 * right because the process must be in the kernel already.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	case SIGCONT:
 | 
					 | 
				
			||||||
	case SIGTSTP:
 | 
					 | 
				
			||||||
		if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
 | 
					 | 
				
			||||||
			tracer_panic("sleeping_process_signal : Failed to "
 | 
					 | 
				
			||||||
				     "continue pid %d, signal = %d, "
 | 
					 | 
				
			||||||
				     "errno = %d\n", pid, sig, errno);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* This happens when the debugger (e.g. strace) is doing system call 
 | 
					 | 
				
			||||||
	 * tracing on the kernel.  During a context switch, the current task
 | 
					 | 
				
			||||||
	 * will be set to the incoming process and the outgoing process will
 | 
					 | 
				
			||||||
	 * hop into write and then read.  Since it's not the current process
 | 
					 | 
				
			||||||
	 * any more, the trace of those will land here.  So, we need to just 
 | 
					 | 
				
			||||||
	 * PTRACE_SYSCALL it.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	case (SIGTRAP + 0x80):
 | 
					 | 
				
			||||||
		if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
 | 
					 | 
				
			||||||
			tracer_panic("sleeping_process_signal : Failed to "
 | 
					 | 
				
			||||||
				     "PTRACE_SYSCALL pid %d, errno = %d\n",
 | 
					 | 
				
			||||||
				     pid, errno);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case SIGSTOP:
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		tracer_panic("sleeping process %d got unexpected "
 | 
					 | 
				
			||||||
			     "signal : %d\n", pid, sig);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Accessed only by the tracing thread */
 | 
					 | 
				
			||||||
int debugger_pid = -1;
 | 
					 | 
				
			||||||
int debugger_parent = -1;
 | 
					 | 
				
			||||||
int debugger_fd = -1;
 | 
					 | 
				
			||||||
int gdb_pid = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct {
 | 
					 | 
				
			||||||
	int pid;
 | 
					 | 
				
			||||||
	int signal;
 | 
					 | 
				
			||||||
	unsigned long addr;
 | 
					 | 
				
			||||||
	struct timeval time;
 | 
					 | 
				
			||||||
} signal_record[1024][32];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int signal_index[32];
 | 
					 | 
				
			||||||
int nsignals = 0;
 | 
					 | 
				
			||||||
int debug_trace = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern void signal_usr1(int sig);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int tracing_pid = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int tracer(int (*init_proc)(void *), void *sp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	void *task = NULL;
 | 
					 | 
				
			||||||
	int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
 | 
					 | 
				
			||||||
	int proc_id = 0, n, err, old_tracing = 0, strace = 0;
 | 
					 | 
				
			||||||
	int local_using_sysemu = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	signal(SIGPIPE, SIG_IGN);
 | 
					 | 
				
			||||||
	setup_tracer_winch();
 | 
					 | 
				
			||||||
	tracing_pid = os_getpid();
 | 
					 | 
				
			||||||
	printf("tracing thread pid = %d\n", tracing_pid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
 | 
					 | 
				
			||||||
	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 | 
					 | 
				
			||||||
	if(n < 0){
 | 
					 | 
				
			||||||
		printf("waitpid on idle thread failed, errno = %d\n", errno);
 | 
					 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) {
 | 
					 | 
				
			||||||
		printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno);
 | 
					 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
 | 
					 | 
				
			||||||
		printf("Failed to continue idle thread, errno = %d\n", errno);
 | 
					 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	signal(SIGSEGV, (sighandler_t) tracer_segv);
 | 
					 | 
				
			||||||
	signal(SIGUSR1, signal_usr1);
 | 
					 | 
				
			||||||
	if(debug_trace){
 | 
					 | 
				
			||||||
		printf("Tracing thread pausing to be attached\n");
 | 
					 | 
				
			||||||
		stop();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(debug){
 | 
					 | 
				
			||||||
		if(gdb_pid != -1) 
 | 
					 | 
				
			||||||
			debugger_pid = attach_debugger(pid, gdb_pid, 1);
 | 
					 | 
				
			||||||
		else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop);
 | 
					 | 
				
			||||||
		if(debug_parent){
 | 
					 | 
				
			||||||
			debugger_parent = os_process_parent(debugger_pid);
 | 
					 | 
				
			||||||
			init_parent_proxy(debugger_parent);
 | 
					 | 
				
			||||||
			err = attach(debugger_parent);
 | 
					 | 
				
			||||||
			if(err){
 | 
					 | 
				
			||||||
				printf("Failed to attach debugger parent %d, "
 | 
					 | 
				
			||||||
				       "errno = %d\n", debugger_parent, -err);
 | 
					 | 
				
			||||||
				debugger_parent = -1;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else {
 | 
					 | 
				
			||||||
				if(ptrace(PTRACE_SYSCALL, debugger_parent, 
 | 
					 | 
				
			||||||
					  0, 0) < 0){
 | 
					 | 
				
			||||||
					printf("Failed to continue debugger "
 | 
					 | 
				
			||||||
					       "parent, errno = %d\n", errno);
 | 
					 | 
				
			||||||
					debugger_parent = -1;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	set_cmdline("(tracing thread)");
 | 
					 | 
				
			||||||
	while(1){
 | 
					 | 
				
			||||||
		CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED));
 | 
					 | 
				
			||||||
		if(pid <= 0){
 | 
					 | 
				
			||||||
			if(errno != ECHILD){
 | 
					 | 
				
			||||||
				printf("wait failed - errno = %d\n", errno);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(pid == debugger_pid){
 | 
					 | 
				
			||||||
			int cont = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(WIFEXITED(status) || WIFSIGNALED(status))
 | 
					 | 
				
			||||||
				debugger_pid = -1;
 | 
					 | 
				
			||||||
			/* XXX Figure out how to deal with gdb and SMP */
 | 
					 | 
				
			||||||
			else cont = debugger_signal(status, cpu_tasks[0].pid);
 | 
					 | 
				
			||||||
			if(cont == PTRACE_SYSCALL) strace = 1;
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if(pid == debugger_parent){
 | 
					 | 
				
			||||||
			debugger_parent_signal(status, pid);
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		nsignals++;
 | 
					 | 
				
			||||||
		if(WIFEXITED(status)) ;
 | 
					 | 
				
			||||||
#ifdef notdef
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			printf("Child %d exited with status %d\n", pid, 
 | 
					 | 
				
			||||||
			       WEXITSTATUS(status));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
		else if(WIFSIGNALED(status)){
 | 
					 | 
				
			||||||
			sig = WTERMSIG(status);
 | 
					 | 
				
			||||||
			if(sig != 9){
 | 
					 | 
				
			||||||
				printf("Child %d exited with signal %d\n", pid,
 | 
					 | 
				
			||||||
				       sig);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if(WIFSTOPPED(status)){
 | 
					 | 
				
			||||||
			proc_id = pid_to_processor_id(pid);
 | 
					 | 
				
			||||||
			sig = WSTOPSIG(status);
 | 
					 | 
				
			||||||
			if(proc_id == -1){
 | 
					 | 
				
			||||||
				sleeping_process_signal(pid, sig);
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			task = cpu_tasks[proc_id].task;
 | 
					 | 
				
			||||||
			tracing = is_tracing(task);
 | 
					 | 
				
			||||||
			old_tracing = tracing;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/* Assume: no syscall, when coming from user */
 | 
					 | 
				
			||||||
			if ( tracing )
 | 
					 | 
				
			||||||
				do_sigtrap(task);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			switch(sig){
 | 
					 | 
				
			||||||
			case SIGUSR1:
 | 
					 | 
				
			||||||
				sig = 0;
 | 
					 | 
				
			||||||
				op = do_proc_op(task, proc_id);
 | 
					 | 
				
			||||||
				switch(op){
 | 
					 | 
				
			||||||
				/*
 | 
					 | 
				
			||||||
				 * This is called when entering user mode; after
 | 
					 | 
				
			||||||
				 * this, we start intercepting syscalls.
 | 
					 | 
				
			||||||
				 *
 | 
					 | 
				
			||||||
				 * In fact, a process is started in kernel mode,
 | 
					 | 
				
			||||||
				 * so with is_tracing() == 0 (and that is reset
 | 
					 | 
				
			||||||
				 * when executing syscalls, since UML kernel has
 | 
					 | 
				
			||||||
				 * the right to do syscalls);
 | 
					 | 
				
			||||||
				 */
 | 
					 | 
				
			||||||
				case OP_TRACE_ON:
 | 
					 | 
				
			||||||
					arch_leave_kernel(task, pid);
 | 
					 | 
				
			||||||
					tracing = 1;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				case OP_REBOOT:
 | 
					 | 
				
			||||||
				case OP_HALT:
 | 
					 | 
				
			||||||
					unmap_physmem();
 | 
					 | 
				
			||||||
					kmalloc_ok = 0;
 | 
					 | 
				
			||||||
					os_kill_ptraced_process(pid, 0);
 | 
					 | 
				
			||||||
					/* Now let's reap remaining zombies */
 | 
					 | 
				
			||||||
					errno = 0;
 | 
					 | 
				
			||||||
					do {
 | 
					 | 
				
			||||||
						waitpid(-1, &status,
 | 
					 | 
				
			||||||
							WUNTRACED);
 | 
					 | 
				
			||||||
					} while (errno != ECHILD);
 | 
					 | 
				
			||||||
					return(op == OP_REBOOT);
 | 
					 | 
				
			||||||
				case OP_NONE:
 | 
					 | 
				
			||||||
					printf("Detaching pid %d\n", pid);
 | 
					 | 
				
			||||||
					detach(pid, SIGSTOP);
 | 
					 | 
				
			||||||
					continue;
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				/* OP_EXEC switches host processes on us,
 | 
					 | 
				
			||||||
				 * we want to continue the new one.
 | 
					 | 
				
			||||||
				 */
 | 
					 | 
				
			||||||
				pid = cpu_tasks[proc_id].pid;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case (SIGTRAP + 0x80):
 | 
					 | 
				
			||||||
				if(!tracing && (debugger_pid != -1)){
 | 
					 | 
				
			||||||
					child_signal(pid, status & 0x7fff);
 | 
					 | 
				
			||||||
					continue;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				tracing = 0;
 | 
					 | 
				
			||||||
				/* local_using_sysemu has been already set
 | 
					 | 
				
			||||||
				 * below, since if we are here, is_tracing() on
 | 
					 | 
				
			||||||
				 * the traced task was 1, i.e. the process had
 | 
					 | 
				
			||||||
				 * already run through one iteration of the
 | 
					 | 
				
			||||||
				 * loop which executed a OP_TRACE_ON request.*/
 | 
					 | 
				
			||||||
				do_syscall(task, pid, local_using_sysemu);
 | 
					 | 
				
			||||||
				sig = SIGUSR2;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case SIGTRAP:
 | 
					 | 
				
			||||||
				if(!tracing && (debugger_pid != -1)){
 | 
					 | 
				
			||||||
					child_signal(pid, status);
 | 
					 | 
				
			||||||
					continue;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				tracing = 0;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case SIGPROF:
 | 
					 | 
				
			||||||
				if(tracing) sig = 0;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case SIGCHLD:
 | 
					 | 
				
			||||||
			case SIGHUP:
 | 
					 | 
				
			||||||
				sig = 0;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			case SIGSEGV:
 | 
					 | 
				
			||||||
			case SIGIO:
 | 
					 | 
				
			||||||
			case SIGALRM:
 | 
					 | 
				
			||||||
			case SIGVTALRM:
 | 
					 | 
				
			||||||
			case SIGFPE:
 | 
					 | 
				
			||||||
			case SIGBUS:
 | 
					 | 
				
			||||||
			case SIGILL:
 | 
					 | 
				
			||||||
			case SIGWINCH:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			default:
 | 
					 | 
				
			||||||
				tracing = 0;
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			set_tracing(task, tracing);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(!tracing && old_tracing)
 | 
					 | 
				
			||||||
				arch_enter_kernel(task, pid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(!tracing && (debugger_pid != -1) && (sig != 0) &&
 | 
					 | 
				
			||||||
				(sig != SIGALRM) && (sig != SIGVTALRM) &&
 | 
					 | 
				
			||||||
				(sig != SIGSEGV) && (sig != SIGTRAP) &&
 | 
					 | 
				
			||||||
				(sig != SIGUSR2) && (sig != SIGIO) &&
 | 
					 | 
				
			||||||
				(sig != SIGFPE)){
 | 
					 | 
				
			||||||
				child_signal(pid, status);
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			local_using_sysemu = get_using_sysemu();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(tracing)
 | 
					 | 
				
			||||||
				cont_type = SELECT_PTRACE_OPERATION(local_using_sysemu,
 | 
					 | 
				
			||||||
				                                    singlestepping(task));
 | 
					 | 
				
			||||||
			else if((debugger_pid != -1) && strace)
 | 
					 | 
				
			||||||
				cont_type = PTRACE_SYSCALL;
 | 
					 | 
				
			||||||
			else
 | 
					 | 
				
			||||||
				cont_type = PTRACE_CONT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if(ptrace(cont_type, pid, 0, sig) != 0){
 | 
					 | 
				
			||||||
				tracer_panic("ptrace failed to continue "
 | 
					 | 
				
			||||||
					     "process - errno = %d\n", 
 | 
					 | 
				
			||||||
					     errno);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init uml_debug_setup(char *line, int *add)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	char *next;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	debug = 1;
 | 
					 | 
				
			||||||
	*add = 0;
 | 
					 | 
				
			||||||
	if(*line != '=') return(0);
 | 
					 | 
				
			||||||
	line++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while(line != NULL){
 | 
					 | 
				
			||||||
		next = strchr(line, ',');
 | 
					 | 
				
			||||||
		if(next) *next++ = '\0';
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		if(!strcmp(line, "go"))	debug_stop = 0;
 | 
					 | 
				
			||||||
		else if(!strcmp(line, "parent")) debug_parent = 1;
 | 
					 | 
				
			||||||
		else printf("Unknown debug option : '%s'\n", line);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		line = next;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__uml_setup("debug", uml_debug_setup,
 | 
					 | 
				
			||||||
"debug\n"
 | 
					 | 
				
			||||||
"    Starts up the kernel under the control of gdb. See the \n"
 | 
					 | 
				
			||||||
"    kernel debugging tutorial and the debugging session pages\n"
 | 
					 | 
				
			||||||
"    at http://user-mode-linux.sourceforge.net/ for more information.\n\n"
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init uml_debugtrace_setup(char *line, int *add)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	debug_trace = 1;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
__uml_setup("debugtrace", uml_debugtrace_setup,
 | 
					 | 
				
			||||||
"debugtrace\n"
 | 
					 | 
				
			||||||
"    Causes the tracing thread to pause until it is attached by a\n"
 | 
					 | 
				
			||||||
"    debugger and continued.  This is mostly for debugging crashes\n"
 | 
					 | 
				
			||||||
"    early during boot, and should be pretty much obsoleted by\n"
 | 
					 | 
				
			||||||
"    the debug switch.\n\n"
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,70 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <signal.h>
 | 
					 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					 | 
				
			||||||
#include "sysdep/sigcontext.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "task.h"
 | 
					 | 
				
			||||||
#include "tt.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void sig_handler_common_tt(int sig, void *sc_ptr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct sigcontext *sc = sc_ptr;
 | 
					 | 
				
			||||||
	struct tt_regs save_regs, *r;
 | 
					 | 
				
			||||||
	int save_errno = errno, is_user = 0;
 | 
					 | 
				
			||||||
	void (*handler)(int, union uml_pt_regs *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* This is done because to allow SIGSEGV to be delivered inside a SEGV
 | 
					 | 
				
			||||||
	 * handler.  This can happen in copy_user, and if SEGV is disabled,
 | 
					 | 
				
			||||||
	 * the process will die.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if(sig == SIGSEGV)
 | 
					 | 
				
			||||||
		change_sig(SIGSEGV, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	r = &TASK_REGS(get_current())->tt;
 | 
					 | 
				
			||||||
        if ( sig == SIGFPE || sig == SIGSEGV ||
 | 
					 | 
				
			||||||
             sig == SIGBUS || sig == SIGILL ||
 | 
					 | 
				
			||||||
             sig == SIGTRAP ) {
 | 
					 | 
				
			||||||
                GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
	save_regs = *r;
 | 
					 | 
				
			||||||
	if (sc)
 | 
					 | 
				
			||||||
		is_user = user_context(SC_SP(sc));
 | 
					 | 
				
			||||||
	r->sc = sc;
 | 
					 | 
				
			||||||
	if(sig != SIGUSR2) 
 | 
					 | 
				
			||||||
		r->syscall = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	handler = sig_info[sig];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */
 | 
					 | 
				
			||||||
	if (sig != SIGIO && sig != SIGWINCH &&
 | 
					 | 
				
			||||||
	    sig != SIGVTALRM && sig != SIGALRM)
 | 
					 | 
				
			||||||
		unblock_signals();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	handler(sig, (union uml_pt_regs *) r);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(is_user){
 | 
					 | 
				
			||||||
		interrupt_end();
 | 
					 | 
				
			||||||
		block_signals();
 | 
					 | 
				
			||||||
		set_user_mode(NULL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	*r = save_regs;
 | 
					 | 
				
			||||||
	errno = save_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
 | 
					 | 
				
			||||||
 * adjust the settings for this buffer only.  This must remain at the end
 | 
					 | 
				
			||||||
 * of the file.
 | 
					 | 
				
			||||||
 * ---------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 * Local variables:
 | 
					 | 
				
			||||||
 * c-file-style: "linux"
 | 
					 | 
				
			||||||
 * End:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,73 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "linux/sched.h"
 | 
					 | 
				
			||||||
#include "asm/uaccess.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int copy_from_user_tt(void *to, const void __user *from, int n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(!access_ok(VERIFY_READ, from, n))
 | 
					 | 
				
			||||||
		return(n);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr,
 | 
					 | 
				
			||||||
				   ¤t->thread.fault_catcher));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int copy_to_user_tt(void __user *to, const void *from, int n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(!access_ok(VERIFY_WRITE, to, n))
 | 
					 | 
				
			||||||
		return(n);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr,
 | 
					 | 
				
			||||||
				 ¤t->thread.fault_catcher));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int strncpy_from_user_tt(char *dst, const char __user *src, int count)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int n;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(!access_ok(VERIFY_READ, src, 1))
 | 
					 | 
				
			||||||
		return(-EFAULT);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	n = __do_strncpy_from_user(dst, src, count,
 | 
					 | 
				
			||||||
				   ¤t->thread.fault_addr,
 | 
					 | 
				
			||||||
				   ¤t->thread.fault_catcher);
 | 
					 | 
				
			||||||
	if(n < 0) return(-EFAULT);
 | 
					 | 
				
			||||||
	return(n);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int __clear_user_tt(void __user *mem, int len)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(__do_clear_user(mem, len,
 | 
					 | 
				
			||||||
			       ¤t->thread.fault_addr,
 | 
					 | 
				
			||||||
			       ¤t->thread.fault_catcher));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int clear_user_tt(void __user *mem, int len)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(!access_ok(VERIFY_WRITE, mem, len))
 | 
					 | 
				
			||||||
		return(len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return(__do_clear_user(mem, len, ¤t->thread.fault_addr,
 | 
					 | 
				
			||||||
			       ¤t->thread.fault_catcher));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int strnlen_user_tt(const void __user *str, int len)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(__do_strnlen_user(str, len,
 | 
					 | 
				
			||||||
				 ¤t->thread.fault_addr,
 | 
					 | 
				
			||||||
				 ¤t->thread.fault_catcher));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,105 +0,0 @@
 | 
				
			||||||
/* 
 | 
					 | 
				
			||||||
 * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk)
 | 
					 | 
				
			||||||
 * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include "uml_uaccess.h"
 | 
					 | 
				
			||||||
#include "task.h"
 | 
					 | 
				
			||||||
#include "kern_util.h"
 | 
					 | 
				
			||||||
#include "os.h"
 | 
					 | 
				
			||||||
#include "longjmp.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int __do_copy_from_user(void *to, const void *from, int n,
 | 
					 | 
				
			||||||
			void **fault_addr, void **fault_catcher)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct tt_regs save = TASK_REGS(get_current())->tt;
 | 
					 | 
				
			||||||
	unsigned long fault;
 | 
					 | 
				
			||||||
	int faulted;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
 | 
					 | 
				
			||||||
			       __do_copy, &faulted);
 | 
					 | 
				
			||||||
	TASK_REGS(get_current())->tt = save;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(!faulted)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	else if (fault)
 | 
					 | 
				
			||||||
		return n - (fault - (unsigned long) from);
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		/* In case of a general protection fault, we don't have the
 | 
					 | 
				
			||||||
		 * fault address, so NULL is used instead. Pretend we didn't
 | 
					 | 
				
			||||||
		 * copy anything. */
 | 
					 | 
				
			||||||
		return n;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void __do_strncpy(void *dst, const void *src, int count)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	strncpy(dst, src, count);
 | 
					 | 
				
			||||||
}	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
 | 
					 | 
				
			||||||
			   void **fault_addr, void **fault_catcher)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct tt_regs save = TASK_REGS(get_current())->tt;
 | 
					 | 
				
			||||||
	unsigned long fault;
 | 
					 | 
				
			||||||
	int faulted;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
 | 
					 | 
				
			||||||
			       __do_strncpy, &faulted);
 | 
					 | 
				
			||||||
	TASK_REGS(get_current())->tt = save;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(!faulted) return(strlen(dst));
 | 
					 | 
				
			||||||
	else return(-1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void __do_clear(void *to, const void *from, int n)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	memset(to, 0, n);
 | 
					 | 
				
			||||||
}	
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int __do_clear_user(void *mem, unsigned long len,
 | 
					 | 
				
			||||||
		    void **fault_addr, void **fault_catcher)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct tt_regs save = TASK_REGS(get_current())->tt;
 | 
					 | 
				
			||||||
	unsigned long fault;
 | 
					 | 
				
			||||||
	int faulted;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
 | 
					 | 
				
			||||||
			       __do_clear, &faulted);
 | 
					 | 
				
			||||||
	TASK_REGS(get_current())->tt = save;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(!faulted) return(0);
 | 
					 | 
				
			||||||
	else return(len - (fault - (unsigned long) mem));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int __do_strnlen_user(const char *str, unsigned long n,
 | 
					 | 
				
			||||||
		      void **fault_addr, void **fault_catcher)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct tt_regs save = TASK_REGS(get_current())->tt;
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
	unsigned long *faddrp = (unsigned long *)fault_addr;
 | 
					 | 
				
			||||||
	jmp_buf jbuf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*fault_catcher = &jbuf;
 | 
					 | 
				
			||||||
	if(UML_SETJMP(&jbuf) == 0)
 | 
					 | 
				
			||||||
		ret = strlen(str) + 1;
 | 
					 | 
				
			||||||
	else ret = *faddrp - (unsigned long) str;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*fault_addr = NULL;
 | 
					 | 
				
			||||||
	*fault_catcher = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	TASK_REGS(get_current())->tt = save;
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * 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:
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
| 
						 | 
					@ -38,9 +38,7 @@
 | 
				
			||||||
#include "choose-mode.h"
 | 
					#include "choose-mode.h"
 | 
				
			||||||
#include "mode_kern.h"
 | 
					#include "mode_kern.h"
 | 
				
			||||||
#include "mode.h"
 | 
					#include "mode.h"
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "skas.h"
 | 
					#include "skas.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_COMMAND_LINE "root=98:0"
 | 
					#define DEFAULT_COMMAND_LINE "root=98:0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,43 +130,12 @@ unsigned long end_vm;
 | 
				
			||||||
/* Set in uml_ncpus_setup */
 | 
					/* Set in uml_ncpus_setup */
 | 
				
			||||||
int ncpus = 1;
 | 
					int ncpus = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_CMDLINE_ON_HOST
 | 
					 | 
				
			||||||
/* Pointer set in linux_main, the array itself is private to each thread,
 | 
					 | 
				
			||||||
 * and changed at address space creation time so this poses no concurrency
 | 
					 | 
				
			||||||
 * problems.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static char *argv1_begin = NULL;
 | 
					 | 
				
			||||||
static char *argv1_end = NULL;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Set in early boot */
 | 
					/* Set in early boot */
 | 
				
			||||||
static int have_root __initdata = 0;
 | 
					static int have_root __initdata = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Set in uml_mem_setup and modified in linux_main */
 | 
					/* Set in uml_mem_setup and modified in linux_main */
 | 
				
			||||||
long long physmem_size = 32 * 1024 * 1024;
 | 
					long long physmem_size = 32 * 1024 * 1024;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void set_cmdline(char *cmd)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#ifdef CONFIG_CMDLINE_ON_HOST
 | 
					 | 
				
			||||||
	char *umid, *ptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(CHOOSE_MODE(honeypot, 0)) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	umid = get_umid();
 | 
					 | 
				
			||||||
	if(*umid != '\0'){
 | 
					 | 
				
			||||||
		snprintf(argv1_begin, 
 | 
					 | 
				
			||||||
			 (argv1_end - argv1_begin) * sizeof(*ptr), 
 | 
					 | 
				
			||||||
			 "(%s) ", umid);
 | 
					 | 
				
			||||||
		ptr = &argv1_begin[strlen(argv1_begin)];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else ptr = argv1_begin;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
 | 
					 | 
				
			||||||
	memset(argv1_begin + strlen(argv1_begin), '\0', 
 | 
					 | 
				
			||||||
	       argv1_end - argv1_begin - strlen(argv1_begin));
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static char *usage_string = 
 | 
					static char *usage_string = 
 | 
				
			||||||
"User Mode Linux v%s\n"
 | 
					"User Mode Linux v%s\n"
 | 
				
			||||||
"	available at http://user-mode-linux.sourceforge.net/\n\n";
 | 
					"	available at http://user-mode-linux.sourceforge.net/\n\n";
 | 
				
			||||||
| 
						 | 
					@ -201,13 +168,10 @@ __uml_setup("root=", uml_root_setup,
 | 
				
			||||||
"        root=/dev/ubd5\n\n"
 | 
					"        root=/dev/ubd5\n\n"
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init no_skas_debug_setup(char *line, int *add)
 | 
					static int __init no_skas_debug_setup(char *line, int *add)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	printf("'debug' is not necessary to gdb UML in skas mode - run \n");
 | 
						printf("'debug' is not necessary to gdb UML in skas mode - run \n");
 | 
				
			||||||
	printf("'gdb linux' and disable CONFIG_CMDLINE_ON_HOST if gdb \n");
 | 
						printf("'gdb linux'");
 | 
				
			||||||
	printf("doesn't work as expected\n");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -217,8 +181,6 @@ __uml_setup("debug", no_skas_debug_setup,
 | 
				
			||||||
"    this flag is not needed to run gdb on UML in skas mode\n\n"
 | 
					"    this flag is not needed to run gdb on UML in skas mode\n\n"
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_SMP
 | 
					#ifdef CONFIG_SMP
 | 
				
			||||||
static int __init uml_ncpus_setup(char *line, int *add)
 | 
					static int __init uml_ncpus_setup(char *line, int *add)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -236,52 +198,6 @@ __uml_setup("ncpus=", uml_ncpus_setup,
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int force_tt = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
 | 
					 | 
				
			||||||
#define DEFAULT_TT 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init mode_tt_setup(char *line, int *add)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	force_tt = 1;
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define DEFAULT_TT 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init mode_tt_setup(char *line, int *add)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define DEFAULT_TT 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init mode_tt_setup(char *line, int *add)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__uml_setup("mode=tt", mode_tt_setup,
 | 
					 | 
				
			||||||
"mode=tt\n"
 | 
					 | 
				
			||||||
"    When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n"
 | 
					 | 
				
			||||||
"    forces UML to run in tt (tracing thread) mode.  It is not the default\n"
 | 
					 | 
				
			||||||
"    because it's slower and less secure than skas mode.\n\n"
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int mode_tt = DEFAULT_TT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int __init Usage(char *line, int *add)
 | 
					static int __init Usage(char *line, int *add)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const char **p;
 | 
						const char **p;
 | 
				
			||||||
| 
						 | 
					@ -357,29 +273,13 @@ int __init linux_main(int argc, char **argv)
 | 
				
			||||||
		add_arg(DEFAULT_COMMAND_LINE);
 | 
							add_arg(DEFAULT_COMMAND_LINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os_early_checks();
 | 
						os_early_checks();
 | 
				
			||||||
	if (force_tt)
 | 
					 | 
				
			||||||
		clear_can_do_skas();
 | 
					 | 
				
			||||||
	mode_tt = force_tt ? 1 : !can_do_skas();
 | 
					 | 
				
			||||||
#ifndef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
	if (mode_tt) {
 | 
					 | 
				
			||||||
		/*Since CONFIG_MODE_TT is #undef'ed, force_tt cannot be 1. So,
 | 
					 | 
				
			||||||
		 * can_do_skas() returned 0, and the message is correct. */
 | 
					 | 
				
			||||||
		printf("Support for TT mode is disabled, and no SKAS support is present on the host.\n");
 | 
					 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef CONFIG_MODE_SKAS
 | 
						can_do_skas();
 | 
				
			||||||
	mode = "TT";
 | 
					
 | 
				
			||||||
#else
 | 
						if (proc_mm && ptrace_faultinfo)
 | 
				
			||||||
	/* Show to the user the result of selection */
 | 
					 | 
				
			||||||
	if (mode_tt)
 | 
					 | 
				
			||||||
		mode = "TT";
 | 
					 | 
				
			||||||
	else if (proc_mm && ptrace_faultinfo)
 | 
					 | 
				
			||||||
		mode = "SKAS3";
 | 
							mode = "SKAS3";
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		mode = "SKAS0";
 | 
							mode = "SKAS0";
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	printf("UML running in %s mode\n", mode);
 | 
						printf("UML running in %s mode\n", mode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -411,11 +311,6 @@ int __init linux_main(int argc, char **argv)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_machinename(init_utsname()->machine);
 | 
						setup_machinename(init_utsname()->machine);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_CMDLINE_ON_HOST
 | 
					 | 
				
			||||||
	argv1_begin = argv[1];
 | 
					 | 
				
			||||||
	argv1_end = &argv[1][strlen(argv[1])];
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	highmem = 0;
 | 
						highmem = 0;
 | 
				
			||||||
	iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
 | 
						iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
 | 
				
			||||||
	max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
 | 
						max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,13 +18,6 @@ SECTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  . = START + SIZEOF_HEADERS;
 | 
					  . = START + SIZEOF_HEADERS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef MODE_TT
 | 
					 | 
				
			||||||
  .remap_data : { UNMAP_PATH (.data .bss) }
 | 
					 | 
				
			||||||
  .remap : { UNMAP_PATH (.text) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  . = ALIGN(4096);		/* Init code and data */
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  _text = .;
 | 
					  _text = .;
 | 
				
			||||||
  _stext = .;
 | 
					  _stext = .;
 | 
				
			||||||
  __init_begin = .;
 | 
					  __init_begin = .;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,12 +5,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
 | 
					obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
 | 
				
			||||||
	registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \
 | 
						registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \
 | 
				
			||||||
	umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/
 | 
						umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-$(CONFIG_MODE_SKAS) += skas/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-$(CONFIG_MODE_TT) += tt.o
 | 
					 | 
				
			||||||
user-objs-$(CONFIG_MODE_TT) += tt.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_TTY_LOG) += tty_log.o
 | 
					obj-$(CONFIG_TTY_LOG) += tty_log.o
 | 
				
			||||||
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 | 
					user-objs-$(CONFIG_TTY_LOG) += tty_log.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,9 +25,6 @@
 | 
				
			||||||
#include "um_malloc.h"
 | 
					#include "um_malloc.h"
 | 
				
			||||||
#include "kern_constants.h"
 | 
					#include "kern_constants.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Set in main, unchanged thereafter */
 | 
					 | 
				
			||||||
char *linux_prog;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define PGD_BOUND (4 * 1024 * 1024)
 | 
					#define PGD_BOUND (4 * 1024 * 1024)
 | 
				
			||||||
#define STACKSIZE (8 * 1024 * 1024)
 | 
					#define STACKSIZE (8 * 1024 * 1024)
 | 
				
			||||||
#define THREAD_NAME_LEN (256)
 | 
					#define THREAD_NAME_LEN (256)
 | 
				
			||||||
| 
						 | 
					@ -125,35 +122,6 @@ int __init main(int argc, char **argv, char **envp)
 | 
				
			||||||
	char **new_argv;
 | 
						char **new_argv;
 | 
				
			||||||
	int ret, i, err;
 | 
						int ret, i, err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_CMDLINE_ON_HOST
 | 
					 | 
				
			||||||
	/* Allocate memory for thread command lines */
 | 
					 | 
				
			||||||
	if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		char padding[THREAD_NAME_LEN] = {
 | 
					 | 
				
			||||||
			[ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0'
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		new_argv = malloc((argc + 2) * sizeof(char*));
 | 
					 | 
				
			||||||
		if(!new_argv) {
 | 
					 | 
				
			||||||
			perror("Allocating extended argv");
 | 
					 | 
				
			||||||
			exit(1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		new_argv[0] = argv[0];
 | 
					 | 
				
			||||||
		new_argv[1] = padding;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for(i = 2; i <= argc; i++)
 | 
					 | 
				
			||||||
			new_argv[i] = argv[i - 1];
 | 
					 | 
				
			||||||
		new_argv[argc + 1] = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		execvp(new_argv[0], new_argv);
 | 
					 | 
				
			||||||
		perror("execing with extended args");
 | 
					 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	linux_prog = argv[0];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	set_stklim();
 | 
						set_stklim();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setup_env_path();
 | 
						setup_env_path();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,13 +133,6 @@ void os_kill_ptraced_process(int pid, int reap_child)
 | 
				
			||||||
		CATCH_EINTR(waitpid(pid, NULL, 0));
 | 
							CATCH_EINTR(waitpid(pid, NULL, 0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
void os_usr1_process(int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	kill(pid, SIGUSR1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Don't use the glibc version, which caches the result in TLS. It misses some
 | 
					/* Don't use the glibc version, which caches the result in TLS. It misses some
 | 
				
			||||||
 * syscalls, and also breaks with clone(), which does not unshare the TLS.
 | 
					 * syscalls, and also breaks with clone(), which does not unshare the TLS.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -239,30 +232,6 @@ int __init can_drop_memory(void)
 | 
				
			||||||
	return ok;
 | 
						return ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int flags = 0, pages;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(sig_stack != NULL){
 | 
					 | 
				
			||||||
		pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER);
 | 
					 | 
				
			||||||
		set_sigstack(sig_stack, pages * UM_KERN_PAGE_SIZE);
 | 
					 | 
				
			||||||
		flags = SA_ONSTACK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(usr1_handler){
 | 
					 | 
				
			||||||
		struct sigaction sa;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		sa.sa_handler = usr1_handler;
 | 
					 | 
				
			||||||
		sigemptyset(&sa.sa_mask);
 | 
					 | 
				
			||||||
		sa.sa_flags = flags;
 | 
					 | 
				
			||||||
		sa.sa_restorer = NULL;
 | 
					 | 
				
			||||||
		if(sigaction(SIGUSR1, &sa, NULL) < 0)
 | 
					 | 
				
			||||||
			panic("init_new_thread_stack - sigaction failed - "
 | 
					 | 
				
			||||||
			      "errno = %d\n", errno);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void init_new_thread_signals(void)
 | 
					void init_new_thread_signals(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
 | 
						set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,12 +35,9 @@
 | 
				
			||||||
#include "mode.h"
 | 
					#include "mode.h"
 | 
				
			||||||
#include "tempfile.h"
 | 
					#include "tempfile.h"
 | 
				
			||||||
#include "kern_constants.h"
 | 
					#include "kern_constants.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "skas.h"
 | 
					#include "skas.h"
 | 
				
			||||||
#include "skas_ptrace.h"
 | 
					#include "skas_ptrace.h"
 | 
				
			||||||
#include "registers.h"
 | 
					#include "registers.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ptrace_child(void *arg)
 | 
					static int ptrace_child(void *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -407,7 +404,6 @@ __uml_setup("noptraceldt", noptraceldt_cmd_param,
 | 
				
			||||||
"    To support PTRACE_LDT, the host needs to be patched using\n"
 | 
					"    To support PTRACE_LDT, the host needs to be patched using\n"
 | 
				
			||||||
"    the current skas3 patch.\n\n");
 | 
					"    the current skas3 patch.\n\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
static inline void check_skas3_ptrace_faultinfo(void)
 | 
					static inline void check_skas3_ptrace_faultinfo(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ptrace_faultinfo fi;
 | 
						struct ptrace_faultinfo fi;
 | 
				
			||||||
| 
						 | 
					@ -504,12 +500,6 @@ int can_do_skas(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
int can_do_skas(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int __init parse_iomem(char *str, int *add)
 | 
					int __init parse_iomem(char *str, int *add)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
# Licensed under the GPL
 | 
					# Licensed under the GPL
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o
 | 
					obj-y = registers.o signal.o tls.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USER_OBJS := $(obj-y)
 | 
					USER_OBJS := $(obj-y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
# Licensed under the GPL
 | 
					# Licensed under the GPL
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_MODE_SKAS) = registers.o prctl.o signal.o
 | 
					obj-y = registers.o prctl.o signal.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USER_OBJS := $(obj-y)
 | 
					USER_OBJS := $(obj-y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,13 +30,6 @@ int set_interval(int is_virtual)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
void enable_timer(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	set_interval(1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void disable_timer(void)
 | 
					void disable_timer(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
 | 
						struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
 | 
				
			||||||
| 
						 | 
					@ -71,18 +64,6 @@ void switch_timers(int to_real)
 | 
				
			||||||
		       errno);
 | 
							       errno);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
void uml_idle_timer(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
 | 
					 | 
				
			||||||
		panic("Couldn't unset SIGVTALRM handler");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	set_handler(SIGALRM, (__sighandler_t) alarm_handler,
 | 
					 | 
				
			||||||
		    SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
 | 
					 | 
				
			||||||
	set_interval(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
unsigned long long os_nsecs(void)
 | 
					unsigned long long os_nsecs(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct timeval tv;
 | 
						struct timeval tv;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,11 +8,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* TLS support - we basically rely on the host's one.*/
 | 
					/* TLS support - we basically rely on the host's one.*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* In TT mode, this should be called only by the tracing thread, and makes sense
 | 
					 | 
				
			||||||
 * only for PTRACE_SET_THREAD_AREA. In SKAS mode, it's used normally.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef PTRACE_GET_THREAD_AREA
 | 
					#ifndef PTRACE_GET_THREAD_AREA
 | 
				
			||||||
#define PTRACE_GET_THREAD_AREA 25
 | 
					#define PTRACE_GET_THREAD_AREA 25
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -32,8 +27,6 @@ int os_set_thread_area(user_desc_t *info, int pid)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef UML_CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int os_get_thread_area(user_desc_t *info, int pid)
 | 
					int os_get_thread_area(user_desc_t *info, int pid)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -44,32 +37,3 @@ int os_get_thread_area(user_desc_t *info, int pid)
 | 
				
			||||||
		ret = -errno;
 | 
							ret = -errno;
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
#include "linux/unistd.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int do_set_thread_area_tt(user_desc_t *info)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = syscall(__NR_set_thread_area,info);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		ret = -errno;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int do_get_thread_area_tt(user_desc_t *info)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = syscall(__NR_get_thread_area,info);
 | 
					 | 
				
			||||||
	if (ret < 0) {
 | 
					 | 
				
			||||||
		ret = -errno;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* UML_CONFIG_MODE_TT */
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ $(UNPROFILE_OBJS:.o=.%): \
 | 
				
			||||||
$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
 | 
					$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \
 | 
				
			||||||
	-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
 | 
						-Dunix -D__unix__ -D__$(SUBARCH)__ $(CF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The stubs and unmap.o can't try to call mcount or update basic block data
 | 
					# The stubs can't try to call mcount or update basic block data
 | 
				
			||||||
define unprofile
 | 
					define unprofile
 | 
				
			||||||
	$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
 | 
						$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
 | 
				
			||||||
endef
 | 
					endef
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,6 @@
 | 
				
			||||||
obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
 | 
					obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
 | 
				
			||||||
	ptrace_user.o setjmp.o signal.o sigcontext.o syscalls.o sysrq.o \
 | 
						ptrace_user.o setjmp.o signal.o sigcontext.o stub.o stub_segv.o \
 | 
				
			||||||
	sys_call_table.o tls.o
 | 
						syscalls.o sysrq.o sys_call_table.o tls.o
 | 
				
			||||||
 | 
					 | 
				
			||||||
obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o
 | 
					subarch-obj-y = lib/bitops_32.o lib/semaphore_32.o lib/string_32.o
 | 
				
			||||||
subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
 | 
					subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
 | 
				
			||||||
| 
						 | 
					@ -13,11 +11,7 @@ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
 | 
				
			||||||
USER_OBJS += user-offsets.s
 | 
					USER_OBJS += user-offsets.s
 | 
				
			||||||
extra-y += user-offsets.s
 | 
					extra-y += user-offsets.s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extra-$(CONFIG_MODE_TT) += unmap.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
UNPROFILE_OBJS := stub_segv.o
 | 
					UNPROFILE_OBJS := stub_segv.o
 | 
				
			||||||
CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
 | 
					CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include arch/um/scripts/Makefile.rules
 | 
					include arch/um/scripts/Makefile.rules
 | 
				
			||||||
 | 
					 | 
				
			||||||
$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,72 +19,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 | 
					extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static long do_modify_ldt_tt(int func, void __user *ptr,
 | 
					 | 
				
			||||||
			      unsigned long bytecount)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct user_desc info;
 | 
					 | 
				
			||||||
	int res = 0;
 | 
					 | 
				
			||||||
	void *buf = NULL;
 | 
					 | 
				
			||||||
	void *p = NULL; /* What we pass to host. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(func){
 | 
					 | 
				
			||||||
	case 1:
 | 
					 | 
				
			||||||
	case 0x11: /* write_ldt */
 | 
					 | 
				
			||||||
		/* Do this check now to avoid overflows. */
 | 
					 | 
				
			||||||
		if (bytecount != sizeof(struct user_desc)) {
 | 
					 | 
				
			||||||
			res = -EINVAL;
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if(copy_from_user(&info, ptr, sizeof(info))) {
 | 
					 | 
				
			||||||
			res = -EFAULT;
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		p = &info;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case 0:
 | 
					 | 
				
			||||||
	case 2: /* read_ldt */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/* The use of info avoids kmalloc on the write case, not on the
 | 
					 | 
				
			||||||
		 * read one. */
 | 
					 | 
				
			||||||
		buf = kmalloc(bytecount, GFP_KERNEL);
 | 
					 | 
				
			||||||
		if (!buf) {
 | 
					 | 
				
			||||||
			res = -ENOMEM;
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		p = buf;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		res = -ENOSYS;
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	res = modify_ldt(func, p, bytecount);
 | 
					 | 
				
			||||||
	if(res < 0)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(func){
 | 
					 | 
				
			||||||
	case 0:
 | 
					 | 
				
			||||||
	case 2:
 | 
					 | 
				
			||||||
		/* Modify_ldt was for reading and returned the number of read
 | 
					 | 
				
			||||||
		 * bytes.*/
 | 
					 | 
				
			||||||
		if(copy_to_user(ptr, p, res))
 | 
					 | 
				
			||||||
			res = -EFAULT;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	kfree(buf);
 | 
					 | 
				
			||||||
	return res;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "skas.h"
 | 
					#include "skas.h"
 | 
				
			||||||
#include "skas_ptrace.h"
 | 
					#include "skas_ptrace.h"
 | 
				
			||||||
#include "asm/mmu_context.h"
 | 
					#include "asm/mmu_context.h"
 | 
				
			||||||
| 
						 | 
					@ -569,7 +503,6 @@ void free_ldt(struct mmu_context_skas * mm)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	mm->ldt.entry_count = 0;
 | 
						mm->ldt.entry_count = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
 | 
					int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,12 +14,6 @@
 | 
				
			||||||
#include "sysdep/sigcontext.h"
 | 
					#include "sysdep/sigcontext.h"
 | 
				
			||||||
#include "sysdep/sc.h"
 | 
					#include "sysdep/sc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void arch_switch_to_tt(struct task_struct *from, struct task_struct *to)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	update_debugregs(to->thread.arch.debugregs_seq);
 | 
					 | 
				
			||||||
	arch_switch_tls_tt(from, to);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
 | 
					void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int err = arch_switch_tls_skas(from, to);
 | 
						int err = arch_switch_tls_skas(from, to);
 | 
				
			||||||
| 
						 | 
					@ -233,79 +227,12 @@ static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * FXSR floating point environment conversions.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
static inline int convert_fxsr_to_user_tt(struct _fpstate __user *buf,
 | 
					 | 
				
			||||||
					  struct pt_regs *regs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
 | 
					 | 
				
			||||||
	unsigned long env[7];
 | 
					 | 
				
			||||||
	struct _fpreg __user *to;
 | 
					 | 
				
			||||||
	struct _fpxreg *from;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	env[0] = (unsigned long)fxsave->cwd | 0xffff0000;
 | 
					 | 
				
			||||||
	env[1] = (unsigned long)fxsave->swd | 0xffff0000;
 | 
					 | 
				
			||||||
	env[2] = twd_fxsr_to_i387(fxsave);
 | 
					 | 
				
			||||||
	env[3] = fxsave->fip;
 | 
					 | 
				
			||||||
	env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
 | 
					 | 
				
			||||||
	env[5] = fxsave->foo;
 | 
					 | 
				
			||||||
	env[6] = fxsave->fos;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ( __copy_to_user( buf, env, 7 * sizeof(unsigned long) ) )
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to = &buf->_st[0];
 | 
					 | 
				
			||||||
	from = (struct _fpxreg *) &fxsave->st_space[0];
 | 
					 | 
				
			||||||
	for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
 | 
					 | 
				
			||||||
		if ( __copy_to_user( to, from, sizeof(*to) ) )
 | 
					 | 
				
			||||||
			return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int convert_fxsr_to_user(struct _fpstate __user *buf,
 | 
					static inline int convert_fxsr_to_user(struct _fpstate __user *buf,
 | 
				
			||||||
				       struct pt_regs *regs)
 | 
									       struct pt_regs *regs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0));
 | 
						return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
static inline int convert_fxsr_from_user_tt(struct pt_regs *regs,
 | 
					 | 
				
			||||||
					    struct _fpstate __user *buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
 | 
					 | 
				
			||||||
	unsigned long env[7];
 | 
					 | 
				
			||||||
	struct _fpxreg *to;
 | 
					 | 
				
			||||||
	struct _fpreg __user *from;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ( __copy_from_user( env, buf, 7 * sizeof(long) ) )
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fxsave->cwd = (unsigned short)(env[0] & 0xffff);
 | 
					 | 
				
			||||||
	fxsave->swd = (unsigned short)(env[1] & 0xffff);
 | 
					 | 
				
			||||||
	fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
 | 
					 | 
				
			||||||
	fxsave->fip = env[3];
 | 
					 | 
				
			||||||
	fxsave->fop = (unsigned short)((env[4] & 0xffff0000) >> 16);
 | 
					 | 
				
			||||||
	fxsave->fcs = (env[4] & 0xffff);
 | 
					 | 
				
			||||||
	fxsave->foo = env[5];
 | 
					 | 
				
			||||||
	fxsave->fos = env[6];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to = (struct _fpxreg *) &fxsave->st_space[0];
 | 
					 | 
				
			||||||
	from = &buf->_st[0];
 | 
					 | 
				
			||||||
	for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
 | 
					 | 
				
			||||||
		if ( __copy_from_user( to, from, sizeof(*from) ) )
 | 
					 | 
				
			||||||
			return 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int convert_fxsr_from_user(struct pt_regs *regs, 
 | 
					static inline int convert_fxsr_from_user(struct pt_regs *regs, 
 | 
				
			||||||
					 struct _fpstate __user *buf)
 | 
										 struct _fpstate __user *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -332,39 +259,11 @@ int set_fpregs(unsigned long buf, struct task_struct *child)
 | 
				
			||||||
	else return(0);
 | 
						else return(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct pt_regs *regs = &tsk->thread.regs;
 | 
					 | 
				
			||||||
	struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = __copy_to_user((void __user *) buf, fxsave,
 | 
					 | 
				
			||||||
			     sizeof(struct user_fxsr_struct));
 | 
					 | 
				
			||||||
	if(err) return -EFAULT;
 | 
					 | 
				
			||||||
	else return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int get_fpxregs(unsigned long buf, struct task_struct *tsk)
 | 
					int get_fpxregs(unsigned long buf, struct task_struct *tsk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0));
 | 
						return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct pt_regs *regs = &tsk->thread.regs;
 | 
					 | 
				
			||||||
	struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = __copy_from_user(fxsave, (void __user *) buf,
 | 
					 | 
				
			||||||
			       sizeof(struct user_fxsr_struct) );
 | 
					 | 
				
			||||||
	if(err) return -EFAULT;
 | 
					 | 
				
			||||||
	else return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int set_fpxregs(unsigned long buf, struct task_struct *tsk)
 | 
					int set_fpxregs(unsigned long buf, struct task_struct *tsk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0));
 | 
						return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0));
 | 
				
			||||||
| 
						 | 
					@ -387,25 +286,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
static inline void copy_fpu_fxsave_tt(struct pt_regs *regs,
 | 
					 | 
				
			||||||
				      struct user_i387_struct *buf)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs));
 | 
					 | 
				
			||||||
	unsigned short *to;
 | 
					 | 
				
			||||||
	unsigned short *from;
 | 
					 | 
				
			||||||
	int i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	memcpy( buf, fpu, 7 * sizeof(long) );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to = (unsigned short *) &buf->st_space[0];
 | 
					 | 
				
			||||||
	from = (unsigned short *) &fpu->st_space[0];
 | 
					 | 
				
			||||||
	for ( i = 0 ; i < 8 ; i++, to += 5, from += 8 ) {
 | 
					 | 
				
			||||||
		memcpy( to, from, 5 * sizeof(unsigned short) );
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline void copy_fpu_fxsave(struct pt_regs *regs,
 | 
					static inline void copy_fpu_fxsave(struct pt_regs *regs,
 | 
				
			||||||
				   struct user_i387_struct *buf)
 | 
									   struct user_i387_struct *buf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,89 +43,3 @@ int ptrace_setfpregs(long pid, unsigned long *regs)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_MODE_TT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void write_debugregs(int pid, unsigned long *regs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct user *dummy;
 | 
					 | 
				
			||||||
	int nregs, i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dummy = NULL;
 | 
					 | 
				
			||||||
	nregs = ARRAY_SIZE(dummy->u_debugreg);
 | 
					 | 
				
			||||||
	for(i = 0; i < nregs; i++){
 | 
					 | 
				
			||||||
		if((i == 4) || (i == 5)) continue;
 | 
					 | 
				
			||||||
		if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
 | 
					 | 
				
			||||||
			  regs[i]) < 0)
 | 
					 | 
				
			||||||
			printk("write_debugregs - ptrace failed on "
 | 
					 | 
				
			||||||
			       "register %d, value = 0x%lx, errno = %d\n", i,
 | 
					 | 
				
			||||||
			       regs[i], errno);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void read_debugregs(int pid, unsigned long *regs)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct user *dummy;
 | 
					 | 
				
			||||||
	int nregs, i;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	dummy = NULL;
 | 
					 | 
				
			||||||
	nregs = ARRAY_SIZE(dummy->u_debugreg);
 | 
					 | 
				
			||||||
	for(i = 0; i < nregs; i++){
 | 
					 | 
				
			||||||
		regs[i] = ptrace(PTRACE_PEEKUSR, pid,
 | 
					 | 
				
			||||||
				 &dummy->u_debugreg[i], 0);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Accessed only by the tracing thread */
 | 
					 | 
				
			||||||
static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void arch_enter_kernel(void *task, int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	read_debugregs(pid, TASK_DEBUGREGS(task));
 | 
					 | 
				
			||||||
	write_debugregs(pid, kernel_debugregs);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void arch_leave_kernel(void *task, int pid)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	read_debugregs(pid, kernel_debugregs);
 | 
					 | 
				
			||||||
	write_debugregs(pid, TASK_DEBUGREGS(task));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef UML_CONFIG_PT_PROXY
 | 
					 | 
				
			||||||
/* Accessed only by the tracing thread */
 | 
					 | 
				
			||||||
static int debugregs_seq;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Only called by the ptrace proxy */
 | 
					 | 
				
			||||||
void ptrace_pokeuser(unsigned long addr, unsigned long data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if((addr < offsetof(struct user, u_debugreg[0])) ||
 | 
					 | 
				
			||||||
	   (addr > offsetof(struct user, u_debugreg[7])))
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	addr -= offsetof(struct user, u_debugreg[0]);
 | 
					 | 
				
			||||||
	addr = addr >> 2;
 | 
					 | 
				
			||||||
	if(kernel_debugregs[addr] == data) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	kernel_debugregs[addr] = data;
 | 
					 | 
				
			||||||
	debugregs_seq++;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void update_debugregs_cb(void *arg)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int pid = *((int *) arg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	write_debugregs(pid, kernel_debugregs);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Optimized out in its header when not defined */
 | 
					 | 
				
			||||||
void update_debugregs(int seq)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	int me;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(seq == debugregs_seq) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	me = os_getpid();
 | 
					 | 
				
			||||||
	initial_thread_cb(update_debugregs_cb, &me);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,9 +13,6 @@
 | 
				
			||||||
#include "sigcontext.h"
 | 
					#include "sigcontext.h"
 | 
				
			||||||
#include "registers.h"
 | 
					#include "registers.h"
 | 
				
			||||||
#include "mode.h"
 | 
					#include "mode.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "skas.h"
 | 
					#include "skas.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void copy_sc(union uml_pt_regs *regs, void *from)
 | 
					void copy_sc(union uml_pt_regs *regs, void *from)
 | 
				
			||||||
| 
						 | 
					@ -108,61 +105,6 @@ int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *t
 | 
				
			||||||
	return copy_to_user(to, &sc, sizeof(sc)) ||
 | 
						return copy_to_user(to, &sc, sizeof(sc)) ||
 | 
				
			||||||
	       copy_to_user(to_fp, fpregs, sizeof(fpregs));
 | 
						       copy_to_user(to_fp, fpregs, sizeof(fpregs));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* These copy a sigcontext to/from userspace.  They copy the fpstate pointer,
 | 
					 | 
				
			||||||
 * blowing away the old, good one.  So, that value is saved, and then restored
 | 
					 | 
				
			||||||
 * after the sigcontext copy.  In copy_from, the variable holding the saved
 | 
					 | 
				
			||||||
 * fpstate pointer, and the sigcontext that it should be restored to are both
 | 
					 | 
				
			||||||
 * in the kernel, so we can just restore using an assignment.  In copy_to, the
 | 
					 | 
				
			||||||
 * saved pointer is in the kernel, but the sigcontext is in userspace, so we
 | 
					 | 
				
			||||||
 * copy_to_user it.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
 | 
					 | 
				
			||||||
			 int fpsize)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct _fpstate *to_fp;
 | 
					 | 
				
			||||||
	struct _fpstate __user *from_fp;
 | 
					 | 
				
			||||||
	unsigned long sigs;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to_fp = to->fpstate;
 | 
					 | 
				
			||||||
	sigs = to->oldmask;
 | 
					 | 
				
			||||||
	err = copy_from_user(to, from, sizeof(*to));
 | 
					 | 
				
			||||||
	from_fp = to->fpstate;
 | 
					 | 
				
			||||||
	to->oldmask = sigs;
 | 
					 | 
				
			||||||
	to->fpstate = to_fp;
 | 
					 | 
				
			||||||
	if(to_fp != NULL)
 | 
					 | 
				
			||||||
		err |= copy_from_user(to_fp, from_fp, fpsize);
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
 | 
					 | 
				
			||||||
		       struct sigcontext *from, int fpsize, unsigned long sp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct _fpstate __user *to_fp;
 | 
					 | 
				
			||||||
	struct _fpstate *from_fp;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to_fp =	(fp ? fp : (struct _fpstate __user *) (to + 1));
 | 
					 | 
				
			||||||
	from_fp = from->fpstate;
 | 
					 | 
				
			||||||
	err = copy_to_user(to, from, sizeof(*to));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* The SP in the sigcontext is the updated one for the signal
 | 
					 | 
				
			||||||
	 * delivery.  The sp passed in is the original, and this needs
 | 
					 | 
				
			||||||
	 * to be restored, so we stick it in separately.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(from_fp != NULL){
 | 
					 | 
				
			||||||
		err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
 | 
					 | 
				
			||||||
		err |= copy_to_user(to_fp, from_fp, fpsize);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int copy_sc_from_user(struct pt_regs *to, void __user *from)
 | 
					static int copy_sc_from_user(struct pt_regs *to, void __user *from)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,10 +18,7 @@
 | 
				
			||||||
#include "mode_kern.h"
 | 
					#include "mode_kern.h"
 | 
				
			||||||
#include "os.h"
 | 
					#include "os.h"
 | 
				
			||||||
#include "mode.h"
 | 
					#include "mode.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#include "skas.h"
 | 
					#include "skas.h"
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * If needed we can detect when it's uninitialized.
 | 
					 * If needed we can detect when it's uninitialized.
 | 
				
			||||||
| 
						 | 
					@ -31,7 +28,6 @@
 | 
				
			||||||
static int host_supports_tls = -1;
 | 
					static int host_supports_tls = -1;
 | 
				
			||||||
int host_gdt_entry_tls_min;
 | 
					int host_gdt_entry_tls_min;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
int do_set_thread_area_skas(struct user_desc *info)
 | 
					int do_set_thread_area_skas(struct user_desc *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -53,7 +49,6 @@ int do_get_thread_area_skas(struct user_desc *info)
 | 
				
			||||||
	put_cpu();
 | 
						put_cpu();
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * sys_get_thread_area: get a yet unused TLS descriptor index.
 | 
					 * sys_get_thread_area: get a yet unused TLS descriptor index.
 | 
				
			||||||
| 
						 | 
					@ -187,17 +182,6 @@ int arch_switch_tls_skas(struct task_struct *from, struct task_struct *to)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int arch_switch_tls_tt(struct task_struct *from, struct task_struct *to)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!host_supports_tls)
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (needs_TLS_update(to))
 | 
					 | 
				
			||||||
		return load_TLS(0, to);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int set_tls_entry(struct task_struct* task, struct user_desc *info,
 | 
					static int set_tls_entry(struct task_struct* task, struct user_desc *info,
 | 
				
			||||||
			 int idx, int flushed)
 | 
								 int idx, int flushed)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <linux/mman.h>
 | 
					 | 
				
			||||||
#include <asm/unistd.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int errno;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline _syscall2(int,munmap,void *,start,size_t,len)
 | 
					 | 
				
			||||||
static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
 | 
					 | 
				
			||||||
int switcheroo(int fd, int prot, void *from, void *to, int size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(munmap(to, size) < 0){
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1 ){
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(munmap(from, size) < 0){
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -5,10 +5,9 @@
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
 | 
					obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
 | 
				
			||||||
	setjmp.o sigcontext.o signal.o syscalls.o syscall_table.o sysrq.o \
 | 
						setjmp.o sigcontext.o signal.o stub.o stub_segv.o syscalls.o \
 | 
				
			||||||
	ksyms.o tls.o
 | 
						syscall_table.o sysrq.o ksyms.o tls.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o
 | 
					 | 
				
			||||||
obj-$(CONFIG_MODULES) += um_module.o
 | 
					obj-$(CONFIG_MODULES) += um_module.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
 | 
					subarch-obj-y = lib/bitops_64.o lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o
 | 
				
			||||||
| 
						 | 
					@ -21,11 +20,7 @@ USER_OBJS := ptrace_user.o sigcontext.o
 | 
				
			||||||
USER_OBJS += user-offsets.s
 | 
					USER_OBJS += user-offsets.s
 | 
				
			||||||
extra-y += user-offsets.s
 | 
					extra-y += user-offsets.s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extra-$(CONFIG_MODE_TT) += unmap.o
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
UNPROFILE_OBJS := stub_segv.o
 | 
					UNPROFILE_OBJS := stub_segv.o
 | 
				
			||||||
CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
 | 
					CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include arch/um/scripts/Makefile.rules
 | 
					include arch/um/scripts/Makefile.rules
 | 
				
			||||||
 | 
					 | 
				
			||||||
$(obj)/unmap.%: _c_flags = $(call unprofile,$(CFLAGS))
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,9 +15,6 @@
 | 
				
			||||||
#include "choose-mode.h"
 | 
					#include "choose-mode.h"
 | 
				
			||||||
#include "sysdep/ptrace.h"
 | 
					#include "sysdep/ptrace.h"
 | 
				
			||||||
#include "frame_kern.h"
 | 
					#include "frame_kern.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "skas.h"
 | 
					#include "skas.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void copy_sc(union uml_pt_regs *regs, void *from)
 | 
					void copy_sc(union uml_pt_regs *regs, void *from)
 | 
				
			||||||
| 
						 | 
					@ -134,53 +131,6 @@ int copy_sc_to_user_skas(struct sigcontext __user *to,
 | 
				
			||||||
	return(err);
 | 
						return(err);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
 | 
					 | 
				
			||||||
			 int fpsize)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct _fpstate *to_fp;
 | 
					 | 
				
			||||||
	struct _fpstate __user *from_fp;
 | 
					 | 
				
			||||||
	unsigned long sigs;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to_fp = to->fpstate;
 | 
					 | 
				
			||||||
	sigs = to->oldmask;
 | 
					 | 
				
			||||||
	err = copy_from_user(to, from, sizeof(*to));
 | 
					 | 
				
			||||||
	from_fp = to->fpstate;
 | 
					 | 
				
			||||||
	to->fpstate = to_fp;
 | 
					 | 
				
			||||||
	to->oldmask = sigs;
 | 
					 | 
				
			||||||
	if(to_fp != NULL)
 | 
					 | 
				
			||||||
		err |= copy_from_user(to_fp, from_fp, fpsize);
 | 
					 | 
				
			||||||
	return(err);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
 | 
					 | 
				
			||||||
		       struct sigcontext *from, int fpsize, unsigned long sp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct _fpstate __user *to_fp;
 | 
					 | 
				
			||||||
	struct _fpstate *from_fp;
 | 
					 | 
				
			||||||
	int err;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	to_fp = (fp ? fp : (struct _fpstate __user *) (to + 1));
 | 
					 | 
				
			||||||
	from_fp = from->fpstate;
 | 
					 | 
				
			||||||
	err = copy_to_user(to, from, sizeof(*to));
 | 
					 | 
				
			||||||
	/* The SP in the sigcontext is the updated one for the signal
 | 
					 | 
				
			||||||
	 * delivery.  The sp passed in is the original, and this needs
 | 
					 | 
				
			||||||
	 * to be restored, so we stick it in separately.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	err |= copy_to_user(&SC_SP(to), &sp, sizeof(sp));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if(from_fp != NULL){
 | 
					 | 
				
			||||||
		err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
 | 
					 | 
				
			||||||
		err |= copy_to_user(to_fp, from_fp, fpsize);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int copy_sc_from_user(struct pt_regs *to, void __user *from)
 | 
					static int copy_sc_from_user(struct pt_regs *to, void __user *from)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
       int ret;
 | 
					       int ret;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,36 +29,6 @@ asmlinkage long sys_uname64(struct new_utsname __user * name)
 | 
				
			||||||
	return err ? -EFAULT : 0;
 | 
						return err ? -EFAULT : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
extern long arch_prctl(int code, unsigned long addr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static long arch_prctl_tt(int code, unsigned long addr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long tmp;
 | 
					 | 
				
			||||||
	long ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	switch(code){
 | 
					 | 
				
			||||||
	case ARCH_SET_GS:
 | 
					 | 
				
			||||||
	case ARCH_SET_FS:
 | 
					 | 
				
			||||||
		ret = arch_prctl(code, addr);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	case ARCH_GET_FS:
 | 
					 | 
				
			||||||
	case ARCH_GET_GS:
 | 
					 | 
				
			||||||
		ret = arch_prctl(code, (unsigned long) &tmp);
 | 
					 | 
				
			||||||
		if(!ret)
 | 
					 | 
				
			||||||
			ret = put_user(tmp, (long __user *)addr);
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		ret = -EINVAL;
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return(ret);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
long arch_prctl_skas(struct task_struct *task, int code,
 | 
					long arch_prctl_skas(struct task_struct *task, int code,
 | 
				
			||||||
                     unsigned long __user *addr)
 | 
					                     unsigned long __user *addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -119,7 +89,6 @@ long arch_prctl_skas(struct task_struct *task, int code,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
long sys_arch_prctl(int code, unsigned long addr)
 | 
					long sys_arch_prctl(int code, unsigned long addr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,25 +0,0 @@
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
 | 
					 | 
				
			||||||
 * Licensed under the GPL
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <linux/mman.h>
 | 
					 | 
				
			||||||
#include <asm/unistd.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int errno;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline _syscall2(int,munmap,void *,start,size_t,len)
 | 
					 | 
				
			||||||
static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
 | 
					 | 
				
			||||||
int switcheroo(int fd, int prot, void *from, void *to, int size)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if(munmap(to, size) < 0){
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) == (void*) -1){
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(munmap(from, size) < 0){
 | 
					 | 
				
			||||||
		return(-1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -56,12 +56,6 @@ static inline void enter_lazy_tlb(struct mm_struct *mm,
 | 
				
			||||||
extern int init_new_context_skas(struct task_struct *task, 
 | 
					extern int init_new_context_skas(struct task_struct *task, 
 | 
				
			||||||
				 struct mm_struct *mm);
 | 
									 struct mm_struct *mm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int init_new_context_tt(struct task_struct *task, 
 | 
					 | 
				
			||||||
				      struct mm_struct *mm)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return(0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static inline int init_new_context(struct task_struct *task, 
 | 
					static inline int init_new_context(struct task_struct *task, 
 | 
				
			||||||
				   struct mm_struct *mm)
 | 
									   struct mm_struct *mm)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,20 +34,10 @@ struct thread_struct {
 | 
				
			||||||
	void *exec_buf;
 | 
						void *exec_buf;
 | 
				
			||||||
	struct arch_thread arch;
 | 
						struct arch_thread arch;
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
#ifdef CONFIG_MODE_TT
 | 
					 | 
				
			||||||
		struct {
 | 
					 | 
				
			||||||
			int extern_pid;
 | 
					 | 
				
			||||||
			int tracing;
 | 
					 | 
				
			||||||
			int switch_pipe[2];
 | 
					 | 
				
			||||||
			int vm_seq;
 | 
					 | 
				
			||||||
		} tt;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			jmp_buf switch_buf;
 | 
								jmp_buf switch_buf;
 | 
				
			||||||
			int mm_count;
 | 
								int mm_count;
 | 
				
			||||||
		} skas;
 | 
							} skas;
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
	} mode;
 | 
						} mode;
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		int op;
 | 
							int op;
 | 
				
			||||||
| 
						 | 
					@ -136,12 +126,8 @@ extern struct cpuinfo_um cpu_data[];
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_MODE_SKAS
 | 
					 | 
				
			||||||
#define KSTK_REG(tsk, reg) \
 | 
					#define KSTK_REG(tsk, reg) \
 | 
				
			||||||
	get_thread_reg(reg, &tsk->thread.mode.skas.switch_buf)
 | 
						get_thread_reg(reg, &tsk->thread.mode.skas.switch_buf)
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define KSTK_REG(tsk, reg) (0xbadbabe)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#define get_wchan(p) (0)
 | 
					#define get_wchan(p) (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue