diff options
Diffstat (limited to 'arch/um')
306 files changed, 2657 insertions, 11000 deletions
diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index 70dabd1e065..f10738d68b2 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -1,5 +1,4 @@ - -menu "Character Devices" +menu "UML Character Devices" config STDERR_CONSOLE bool "stderr console" @@ -7,10 +6,6 @@ config STDERR_CONSOLE help console driver which dumps all printk messages to stderr. -config STDIO_CONSOLE - bool - default y - config SSL bool "Virtual serial line" help @@ -105,92 +100,6 @@ config SSL_CHAN this if you expect the UML that you build to be run in environments which don't have a set of /dev/pty* devices. -config UNIX98_PTYS - bool "Unix98 PTY support" - help - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx for - masters and /dev/ttyxx for slaves of pseudo terminals. This scheme - has a number of problems. The GNU C library glibc 2.1 and later, - however, supports the Unix98 naming standard: in order to acquire a - pseudo terminal, a process opens /dev/ptmx; the number of the pseudo - terminal is then made available to the process and the pseudo - terminal slave can be accessed as /dev/pts/<number>. What was - traditionally /dev/ttyp2 will then be /dev/pts/2, for example. - - All modern Linux systems use the Unix98 ptys. Say Y unless - you're on an embedded system and want to conserve memory. - -config LEGACY_PTYS - bool "Legacy (BSD) PTY support" - default y - help - A pseudo terminal (PTY) is a software device consisting of two - halves: a master and a slave. The slave device behaves identical to - a physical terminal; the master device is used by a process to - read data from and write data to the slave, thereby emulating a - terminal. Typical programs for the master side are telnet servers - and xterms. - - Linux has traditionally used the BSD-like names /dev/ptyxx - for masters and /dev/ttyxx for slaves of pseudo - terminals. This scheme has a number of problems, including - security. This option enables these legacy devices; on most - systems, it is safe to say N. - -config RAW_DRIVER - tristate "RAW driver (/dev/raw/rawN)" - depends on BLOCK - help - The raw driver permits block devices to be bound to /dev/raw/rawN. - Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. - See the raw(8) manpage for more details. - - Applications should preferably open the device (eg /dev/hda1) - with the O_DIRECT flag. - -config MAX_RAW_DEVS - int "Maximum number of RAW devices to support (1-8192)" - depends on RAW_DRIVER - default "256" - help - The maximum number of RAW devices that are supported. - Default is 256. Increase this number in case you need lots of - raw devices. - -config LEGACY_PTY_COUNT - int "Maximum number of legacy PTY in use" - depends on LEGACY_PTYS - default "256" - help - The maximum number of legacy PTYs that can be used at any one time. - The default is 256, and should be more than enough. Embedded - systems may want to reduce this to save memory. - - When not in use, each legacy PTY occupies 12 bytes on 32-bit - architectures and 24 bytes on 64-bit architectures. - -config WATCHDOG - bool "Watchdog Timer Support" - -config WATCHDOG_NOWAYOUT - bool "Disable watchdog shutdown on close" - depends on WATCHDOG - -config SOFT_WATCHDOG - tristate "Software Watchdog" - depends on WATCHDOG - -config UML_WATCHDOG - tristate "UML watchdog" - depends on WATCHDOG - config UML_SOUND tristate "Sound support" help @@ -211,29 +120,4 @@ config HOSTAUDIO tristate default UML_SOUND -#It is selected elsewhere, so kconfig would warn without this. -config HW_RANDOM - tristate - default n - -config UML_RANDOM - tristate "Hardware random number generator" - help - This option enables UML's "hardware" random number generator. It - attaches itself to the host's /dev/random, supplying as much entropy - as the host has, rather than the small amount the UML gets from its - own drivers. It registers itself as a standard hardware random number - generator, major 10, minor 183, and the canonical device name is - /dev/hwrng. - The way to make use of this is to install the rng-tools package - (check your distro, or download from - http://sourceforge.net/projects/gkernel/). rngd periodically reads - /dev/hwrng and injects the entropy into /dev/random. - -config MMAPPER - tristate "iomem emulation driver" - help - This driver allows a host file to be used as emulated IO memory inside - UML. - endmenu diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common index a9234838e8a..6915d28cf11 100644 --- a/arch/um/Kconfig.common +++ b/arch/um/Kconfig.common @@ -1,13 +1,13 @@ -config DEFCONFIG_LIST - string - option defconfig_list - default "arch/$ARCH/defconfig" - config UML bool default y - select HAVE_GENERIC_HARDIRQS + select HAVE_ARCH_AUDITSYSCALL + select HAVE_UID16 select GENERIC_IRQ_SHOW + select GENERIC_CPU_DEVICES + select GENERIC_IO + select GENERIC_CLOCKEVENTS + select TTY # Needed for line.c config MMU bool @@ -50,15 +50,6 @@ config GENERIC_BUG default y depends on BUG -config GENERIC_CLOCKEVENTS - bool - default y - -# Used in kernel/irq/manage.c and include/linux/irq.h -config IRQ_RELEASE_METHOD - bool - default y - config HZ int default 100 diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug index 8fce5e536b0..68205fd3b08 100644 --- a/arch/um/Kconfig.debug +++ b/arch/um/Kconfig.debug @@ -28,13 +28,13 @@ config GCOV If you're involved in UML kernel development and want to use gcov, say Y. If you're unsure, say N. -config DEBUG_STACK_USAGE - bool "Stack utilization instrumentation" - default N - help - Track the maximum kernel stack usage - this will look at each - kernel stack at process exit and log it if it's the deepest - stack seen so far. +config EARLY_PRINTK + bool "Early printk" + default y + ---help--- + Write kernel log output directly to stdout. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. - This option will slow down process creation and destruction somewhat. endmenu diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net index 3160b1a5adb..820a56f0033 100644 --- a/arch/um/Kconfig.net +++ b/arch/um/Kconfig.net @@ -157,7 +157,7 @@ config UML_NET_MCAST config UML_NET_PCAP bool "pcap transport" - depends on UML_NET && EXPERIMENTAL + depends on UML_NET help The pcap transport makes a pcap packet stream on the host look like an ethernet device inside UML. This is useful for making diff --git a/arch/um/Kconfig.rest b/arch/um/Kconfig.rest index 0ccad0ff6d6..567eb5fc21d 100644 --- a/arch/um/Kconfig.rest +++ b/arch/um/Kconfig.rest @@ -2,20 +2,14 @@ source "init/Kconfig" source "kernel/Kconfig.freezer" -source "drivers/block/Kconfig" - source "arch/um/Kconfig.char" -source "drivers/base/Kconfig" +source "drivers/Kconfig" source "net/Kconfig" source "arch/um/Kconfig.net" -source "drivers/net/Kconfig" - -source "drivers/connector/Kconfig" - source "fs/Kconfig" source "security/Kconfig" @@ -24,19 +18,4 @@ source "crypto/Kconfig" source "lib/Kconfig" -source "drivers/scsi/Kconfig" - -source "drivers/md/Kconfig" - -if BROKEN - source "drivers/mtd/Kconfig" -endif - -source "drivers/leds/Kconfig" - -#This is just to shut up some Kconfig warnings, so no prompt. -config INPUT - tristate - default n - source "arch/um/Kconfig.debug" diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um index 90a438acbfa..a7520c90f62 100644 --- a/arch/um/Kconfig.um +++ b/arch/um/Kconfig.um @@ -10,7 +10,6 @@ config STATIC_LINK 2.75G) for UML. source "mm/Kconfig" -source "kernel/time/Kconfig" config LD_SCRIPT_STATIC bool @@ -46,8 +45,8 @@ config HOSTFS say Y or M here; otherwise say N. config HPPFS - tristate "HoneyPot ProcFS (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "HoneyPot ProcFS" + depends on PROC_FS help hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc entries to be overridden, removed, or fabricated from the host. @@ -97,7 +96,7 @@ config MAGIC_SYSRQ unless you really know what this hack does. config SMP - bool "Symmetric multi-processing support (EXPERIMENTAL)" + bool "Symmetric multi-processing support" default n depends on BROKEN help @@ -127,7 +126,7 @@ config NR_CPUS default "32" config HIGHMEM - bool "Highmem support (EXPERIMENTAL)" + bool "Highmem support" depends on !64BIT && BROKEN default n help @@ -148,5 +147,11 @@ config KERNEL_STACK_ORDER be 1 << order pages. The default is OK unless you're running Valgrind on UML, in which case, set this to 3. +config MMAPPER + tristate "iomem emulation driver" + help + This driver allows a host file to be used as emulated IO memory inside + UML. + config NO_DMA def_bool y diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86 deleted file mode 100644 index a9da516a527..00000000000 --- a/arch/um/Kconfig.x86 +++ /dev/null @@ -1,65 +0,0 @@ -source "arch/um/Kconfig.common" - -menu "UML-specific options" - -menu "Host processor type and features" - -config CMPXCHG_LOCAL - bool - default n - -source "arch/x86/Kconfig.cpu" - -endmenu - -config UML_X86 - def_bool y - select GENERIC_FIND_FIRST_BIT - select GENERIC_FIND_NEXT_BIT - -config 64BIT - bool - default SUBARCH = "x86_64" - -config X86_32 - def_bool !64BIT - select HAVE_AOUT - -config X86_64 - def_bool 64BIT - -config RWSEM_XCHGADD_ALGORITHM - def_bool X86_XADD - -config RWSEM_GENERIC_SPINLOCK - def_bool !X86_XADD - -config 3_LEVEL_PGTABLES - bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT - default 64BIT - depends on EXPERIMENTAL - help - Three-level pagetables will let UML have more than 4G of physical - memory. All the memory that can't be mapped directly will be treated - as high memory. - - However, this it experimental on 32-bit architectures, so if unsure say - N (on x86-64 it's automatically enabled, instead, as it's safe there). - -config ARCH_HAS_SC_SIGNALS - def_bool !64BIT - -config ARCH_REUSE_HOST_VSYSCALL_AREA - def_bool !64BIT - -config SMP_BROKEN - def_bool 64BIT - -config GENERIC_HWEIGHT - def_bool y - -source "arch/um/Kconfig.um" - -endmenu - -source "arch/um/Kconfig.rest" diff --git a/arch/um/Makefile b/arch/um/Makefile index fab8121d2b3..e4b1a9639c4 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -6,6 +6,17 @@ # Licensed under the GPL # +# select defconfig based on actual architecture +ifeq ($(SUBARCH),x86) + ifeq ($(shell uname -m),x86_64) + KBUILD_DEFCONFIG := x86_64_defconfig + else + KBUILD_DEFCONFIG := i386_defconfig + endif +else + KBUILD_DEFCONFIG := $(SUBARCH)_defconfig +endif + ARCH_DIR := arch/um OS := $(shell uname -s) # We require bash because the vmlinux link and loader script cpp use bash @@ -20,15 +31,27 @@ core-y += $(ARCH_DIR)/kernel/ \ MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/shared/skas +HEADER_ARCH := $(SUBARCH) + +ifneq ($(filter $(SUBARCH),x86 x86_64 i386),) + HEADER_ARCH := x86 +endif + +ifdef CONFIG_64BIT + KBUILD_CFLAGS += -mcmodel=large +endif + +HOST_DIR := arch/$(HEADER_ARCH) + include $(srctree)/$(ARCH_DIR)/Makefile-skas +include $(srctree)/$(HOST_DIR)/Makefile.um + +core-y += $(HOST_DIR)/um/ SHARED_HEADERS := $(ARCH_DIR)/include/shared ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS) -ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared -ifneq ($(KBUILD_SRC),) -ARCH_INCLUDE += -I$(SHARED_HEADERS) -endif -KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH) +ARCH_INCLUDE += -I$(srctree)/$(HOST_DIR)/um/shared +KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/um # -Dvmap=kernel_vmap prevents anything from referencing the libpcap.o symbol so # named - it's a common symbol in libpcap, so we get a binary which crashes. @@ -38,23 +61,24 @@ KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH) # # These apply to USER_CFLAGS to. -KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ +KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \ $(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \ -Din6addr_loopback=kernel_in6addr_loopback \ - -Din6addr_any=kernel_in6addr_any + -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr KBUILD_AFLAGS += $(ARCH_INCLUDE) USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ - $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 - -include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH) + $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include #This will adjust *FLAGS accordingly to the platform. include $(srctree)/$(ARCH_DIR)/Makefile-os-$(OS) -KBUILD_CPPFLAGS += -I$(srctree)/arch/$(HEADER_ARCH)/include +KBUILD_CPPFLAGS += -I$(srctree)/$(HOST_DIR)/include \ + -I$(srctree)/$(HOST_DIR)/include/uapi \ + -I$(HOST_DIR)/include/generated \ + -I$(HOST_DIR)/include/generated/uapi # -Derrno=kernel_errno - This turns all kernel references to errno into # kernel_errno to separate them from the libc errno. This allows -fno-common @@ -84,10 +108,12 @@ define archhelp echo ' find in the kernel root.' endef -KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH) +KBUILD_KCONFIG := $(HOST_DIR)/um/Kconfig -archprepare: $(SHARED_HEADERS)/user_constants.h -archprepare: $(SHARED_HEADERS)/kern_constants.h +archheaders: + $(Q)$(MAKE) KBUILD_SRC= ARCH=$(HEADER_ARCH) archheaders + +archprepare: include/generated/user_constants.h LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib @@ -106,21 +132,12 @@ LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt)) -CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE) -define cmd_vmlinux__ - $(CC) $(CFLAGS_vmlinux) -o $@ \ - -Wl,-T,$(vmlinux-lds) $(vmlinux-init) \ - -Wl,--start-group $(vmlinux-main) -Wl,--end-group \ - -lutil \ - $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o \ - FORCE ,$^) ; rm -f linux -endef +# Used by link-vmlinux.sh which has special support for um link +export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE) # When cleaning we don't include .config, so we don't include # TT or skas makefiles and don't clean skas_ptregs.h. -CLEAN_FILES += linux x.i gmon.out \ - $(SHARED_HEADERS)/user_constants.h \ - $(SHARED_HEADERS)/kern_constants.h +CLEAN_FILES += linux x.i gmon.out archclean: @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ @@ -128,8 +145,8 @@ archclean: # Generated files -$(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE - $(Q)$(MAKE) $(build)=$(ARCH_DIR)/sys-$(SUBARCH) $@ +$(HOST_DIR)/um/user-offsets.s: __headers FORCE + $(Q)$(MAKE) $(build)=$(HOST_DIR)/um $@ define filechk_gen-asm-offsets (set -e; \ @@ -144,11 +161,7 @@ define filechk_gen-asm-offsets echo ""; ) endef -$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s +include/generated/user_constants.h: $(HOST_DIR)/um/user-offsets.s $(call filechk,gen-asm-offsets) -$(SHARED_HEADERS)/kern_constants.h: - $(Q)mkdir -p $(dir $@) - $(Q)echo '#include "../../../../include/generated/asm-offsets.h"' >$@ - -export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH +export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS DEV_NULL_PATH diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 deleted file mode 100644 index 302cbe50454..00000000000 --- a/arch/um/Makefile-i386 +++ /dev/null @@ -1,42 +0,0 @@ -core-y += arch/um/sys-i386/ arch/x86/crypto/ - -TOP_ADDR := $(CONFIG_TOP_ADDR) - -START := 0x8048000 - -LDFLAGS += -m elf_i386 -ELF_ARCH := $(SUBARCH) -ELF_FORMAT := elf32-$(SUBARCH) -OBJCOPYFLAGS := -O binary -R .note -R .comment -S -HEADER_ARCH := x86 -CHECKFLAGS += -D__i386__ - -ifeq ("$(origin SUBARCH)", "command line") -ifneq ("$(shell uname -m | sed -e s/i.86/i386/)", "$(SUBARCH)") -KBUILD_CFLAGS += $(call cc-option,-m32) -KBUILD_AFLAGS += $(call cc-option,-m32) -LINK-y += $(call cc-option,-m32) -UML_OBJCOPYFLAGS += -F $(ELF_FORMAT) - -export LDFLAGS HOSTCFLAGS HOSTLDFLAGS UML_OBJCOPYFLAGS -endif -endif - -# First of all, tune CFLAGS for the specific CPU. This actually sets cflags-y. -include $(srctree)/arch/x86/Makefile_32.cpu - -# prevent gcc from keeping the stack 16 byte aligned. Taken from i386. -cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) - -# Prevent sprintf in nfsd from being converted to strcpy and resulting in -# an unresolved reference. -cflags-y += -ffreestanding - -# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use -# a lot more stack due to the lack of sharing of stacklots. Also, gcc -# 4.3.0 needs -funit-at-a-time for extern inline functions. -KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \ - echo $(call cc-option,-fno-unit-at-a-time); \ - else echo $(call cc-option,-funit-at-a-time); fi ;) - -KBUILD_CFLAGS += $(cflags-y) diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 deleted file mode 100644 index a9cd7e77a7a..00000000000 --- a/arch/um/Makefile-x86_64 +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2003 - 2004 Pathscale, Inc -# Released under the GPL - -core-y += arch/um/sys-x86_64/ arch/x86/crypto/ -START := 0x60000000 - -_extra_flags_ = -fno-builtin -m64 - -KBUILD_CFLAGS += $(_extra_flags_) - -CHECKFLAGS += -m64 -D__x86_64__ -KBUILD_AFLAGS += -m64 -LDFLAGS += -m elf_x86_64 -KBUILD_CPPFLAGS += -m64 - -ELF_ARCH := i386:x86-64 -ELF_FORMAT := elf64-x86-64 -HEADER_ARCH := x86 - -# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example. - -LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64 -LINK-y += -m64 - -# Do unit-at-a-time unconditionally on x86_64, following the host -KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time) diff --git a/arch/um/configs/i386_defconfig b/arch/um/configs/i386_defconfig new file mode 100644 index 00000000000..a12bf68c9f3 --- /dev/null +++ b/arch/um/configs/i386_defconfig @@ -0,0 +1,76 @@ +CONFIG_3_LEVEL_PGTABLES=y +# CONFIG_COMPACTION is not set +CONFIG_BINFMT_MISC=m +CONFIG_HOSTFS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_KERNEL_STACK_ORDER=1 +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_PID_NS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_IOSCHED_CFQ=m +CONFIG_SSL=y +CONFIG_NULL_CHAN=y +CONFIG_PORT_CHAN=y +CONFIG_PTY_CHAN=y +CONFIG_TTY_CHAN=y +CONFIG_XTERM_CHAN=y +CONFIG_CON_CHAN="pts" +CONFIG_SSL_CHAN="pts" +CONFIG_UML_SOUND=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_BLK_DEV_UBD=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_DUMMY=m +CONFIG_TUN=m +CONFIG_PPP=m +CONFIG_SLIP=m +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_HW_RANDOM is not set +CONFIG_UML_RANDOM=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_INET_LRO is not set +# CONFIG_IPV6 is not set +CONFIG_UML_NET=y +CONFIG_UML_NET_ETHERTAP=y +CONFIG_UML_NET_TUNTAP=y +CONFIG_UML_NET_SLIP=y +CONFIG_UML_NET_DAEMON=y +CONFIG_UML_NET_MCAST=y +CONFIG_UML_NET_SLIRP=y +CONFIG_EXT4_FS=y +CONFIG_REISERFS_FS=y +CONFIG_QUOTA=y +CONFIG_AUTOFS4_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_NLS=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_KERNEL=y diff --git a/arch/um/configs/x86_64_defconfig b/arch/um/configs/x86_64_defconfig new file mode 100644 index 00000000000..3aab117bd55 --- /dev/null +++ b/arch/um/configs/x86_64_defconfig @@ -0,0 +1,75 @@ +# CONFIG_COMPACTION is not set +CONFIG_BINFMT_MISC=m +CONFIG_HOSTFS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_CGROUP_SCHED=y +CONFIG_BLK_CGROUP=y +# CONFIG_PID_NS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SLAB=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_IOSCHED_CFQ=m +CONFIG_SSL=y +CONFIG_NULL_CHAN=y +CONFIG_PORT_CHAN=y +CONFIG_PTY_CHAN=y +CONFIG_TTY_CHAN=y +CONFIG_XTERM_CHAN=y +CONFIG_CON_CHAN="pts" +CONFIG_SSL_CHAN="pts" +CONFIG_UML_SOUND=m +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_BLK_DEV_UBD=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_DUMMY=m +CONFIG_TUN=m +CONFIG_PPP=m +CONFIG_SLIP=m +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_HW_RANDOM is not set +CONFIG_UML_RANDOM=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_INET_LRO is not set +# CONFIG_IPV6 is not set +CONFIG_UML_NET=y +CONFIG_UML_NET_ETHERTAP=y +CONFIG_UML_NET_TUNTAP=y +CONFIG_UML_NET_SLIP=y +CONFIG_UML_NET_DAEMON=y +CONFIG_UML_NET_MCAST=y +CONFIG_UML_NET_SLIRP=y +CONFIG_EXT4_FS=y +CONFIG_REISERFS_FS=y +CONFIG_QUOTA=y +CONFIG_AUTOFS4_FS=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_NLS=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1024 +CONFIG_DEBUG_KERNEL=y diff --git a/arch/um/defconfig b/arch/um/defconfig deleted file mode 100644 index 9f7634f08cf..00000000000 --- a/arch/um/defconfig +++ /dev/null @@ -1,616 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.24 -# Thu Feb 7 11:48:55 2008 -# -CONFIG_DEFCONFIG_LIST="arch/$ARCH/defconfig" -CONFIG_GENERIC_HARDIRQS=y -CONFIG_UML=y -CONFIG_MMU=y -CONFIG_NO_IOMEM=y -# CONFIG_TRACE_IRQFLAGS_SUPPORT is not set -CONFIG_LOCKDEP_SUPPORT=y -# CONFIG_STACKTRACE_SUPPORT is not set -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_TIME=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_IRQ_RELEASE_METHOD=y -CONFIG_HZ=100 - -# -# UML-specific options -# -# CONFIG_STATIC_LINK is not set - -# -# Host processor type and features -# -# CONFIG_M386 is not set -# CONFIG_M486 is not set -# CONFIG_M586 is not set -# CONFIG_M586TSC is not set -# CONFIG_M586MMX is not set -CONFIG_M686=y -# CONFIG_MPENTIUMII is not set -# CONFIG_MPENTIUMIII is not set -# CONFIG_MPENTIUMM is not set -# CONFIG_MPENTIUM4 is not set -# CONFIG_MK6 is not set -# CONFIG_MK7 is not set -# CONFIG_MK8 is not set -# CONFIG_MCRUSOE is not set -# CONFIG_MEFFICEON is not set -# CONFIG_MWINCHIPC6 is not set -# CONFIG_MWINCHIP2 is not set -# CONFIG_MWINCHIP3D is not set -# CONFIG_MGEODEGX1 is not set -# CONFIG_MGEODE_LX is not set -# CONFIG_MCYRIXIII is not set -# CONFIG_MVIAC3_2 is not set -# CONFIG_MVIAC7 is not set -# CONFIG_MPSC is not set -# CONFIG_MCORE2 is not set -# CONFIG_GENERIC_CPU is not set -# CONFIG_X86_GENERIC is not set -CONFIG_X86_CMPXCHG=y -CONFIG_X86_L1_CACHE_SHIFT=5 -CONFIG_X86_XADD=y -CONFIG_X86_PPRO_FENCE=y -CONFIG_X86_WP_WORKS_OK=y -CONFIG_X86_INVLPG=y -CONFIG_X86_BSWAP=y -CONFIG_X86_POPAD_OK=y -CONFIG_X86_GOOD_APIC=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_TSC=y -CONFIG_X86_CMOV=y -CONFIG_X86_MINIMUM_CPU_FAMILY=4 -CONFIG_X86_DEBUGCTLMSR=y -CONFIG_UML_X86=y -CONFIG_X86_32=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_64BIT is not set -CONFIG_SEMAPHORE_SLEEPERS=y -# CONFIG_3_LEVEL_PGTABLES is not set -CONFIG_ARCH_HAS_SC_SIGNALS=y -CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_VIRT_TO_BUS=y -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ=y -CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y -CONFIG_LD_SCRIPT_DYN=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_MISC=m -CONFIG_HOSTFS=y -# CONFIG_HPPFS is not set -CONFIG_MCONSOLE=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_HIGHMEM is not set -CONFIG_KERNEL_STACK_ORDER=0 - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=128 -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_POSIX_MQUEUE=y -CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set -# CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_PID_NS is not set -# CONFIG_AUDIT is not set -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -# CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_SYSCTL=y -# CONFIG_EXPERT is not set -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -CONFIG_KALLSYMS_EXTRA_PASS=y -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_ANON_INODES=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -# CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set -# CONFIG_HAVE_OPROFILE is not set -# CONFIG_HAVE_KPROBES is not set -CONFIG_PROC_PAGE_MONITOR=y -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -CONFIG_DEFAULT_AS=y -# CONFIG_DEFAULT_DEADLINE is not set -# CONFIG_DEFAULT_CFQ is not set -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="anticipatory" -CONFIG_CLASSIC_RCU=y -# CONFIG_PREEMPT_RCU is not set -CONFIG_BLK_DEV=y -CONFIG_BLK_DEV_UBD=y -# CONFIG_BLK_DEV_UBD_SYNC is not set -CONFIG_BLK_DEV_COW_COMMON=y -CONFIG_BLK_DEV_LOOP=m -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_ATA_OVER_ETH is not set - -# -# Character Devices -# -CONFIG_STDERR_CONSOLE=y -CONFIG_STDIO_CONSOLE=y -CONFIG_SSL=y -CONFIG_NULL_CHAN=y -CONFIG_PORT_CHAN=y -CONFIG_PTY_CHAN=y -CONFIG_TTY_CHAN=y -CONFIG_XTERM_CHAN=y -# CONFIG_NOCONFIG_CHAN is not set -CONFIG_CON_ZERO_CHAN="fd:0,fd:1" -CONFIG_CON_CHAN="xterm" -CONFIG_SSL_CHAN="pts" -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -# CONFIG_RAW_DRIVER is not set -CONFIG_LEGACY_PTY_COUNT=32 -# CONFIG_WATCHDOG is not set -CONFIG_UML_SOUND=m -CONFIG_SOUND=m -CONFIG_HOSTAUDIO=m -# CONFIG_HW_RANDOM is not set -CONFIG_UML_RANDOM=y -# CONFIG_MMAPPER is not set - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_UNIX=y -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -# CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -# CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set - -# -# UML Network Devices -# -CONFIG_UML_NET=y -CONFIG_UML_NET_ETHERTAP=y -CONFIG_UML_NET_TUNTAP=y -CONFIG_UML_NET_SLIP=y -CONFIG_UML_NET_DAEMON=y -# CONFIG_UML_NET_VDE is not set -CONFIG_UML_NET_MCAST=y -# CONFIG_UML_NET_PCAP is not set -CONFIG_UML_NET_SLIRP=y -CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set -CONFIG_DUMMY=m -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=m -# CONFIG_VETH is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set -# CONFIG_WAN is not set -CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_FILTER is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPP_MPPE is not set -# CONFIG_PPPOE is not set -# CONFIG_PPPOL2TP is not set -CONFIG_SLIP=m -# CONFIG_SLIP_COMPRESSED is not set -CONFIG_SLHC=m -# CONFIG_SLIP_SMART is not set -# CONFIG_SLIP_MODE_SLIP6 is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_CONNECTOR is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set -# CONFIG_EXT4DEV_FS is not set -CONFIG_JBD=y -CONFIG_REISERFS_FS=y -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_REISERFS_FS_XATTR is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -CONFIG_QUOTA=y -# CONFIG_QUOTA_NETLINK_INTERFACE is not set -CONFIG_PRINT_QUOTA_WARNING=y -# CONFIG_QFMT_V1 is not set -# CONFIG_QFMT_V2 is not set -CONFIG_QUOTACTL=y -CONFIG_DNOTIFY=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -CONFIG_ISO9660_FS=m -CONFIG_JOLIET=y -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -# CONFIG_HUGETLB_PAGE is not set -# CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set -# CONFIG_DLM is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -CONFIG_CRYPTO=y -# CONFIG_CRYPTO_SEQIV is not set -# CONFIG_CRYPTO_MANAGER is not set -# CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_NULL is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA256 is not set -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_GF128MUL is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_CBC is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_CTR is not set -# CONFIG_CRYPTO_GCM is not set -# CONFIG_CRYPTO_CCM is not set -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_TWOFISH_586 is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES is not set -# CONFIG_CRYPTO_AES_586 is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_ARC4 is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SALSA20_586 is not set -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_TEST is not set -# CONFIG_CRYPTO_AUTHENC is not set -# CONFIG_CRYPTO_LZO is not set -CONFIG_CRYPTO_HW=y - -# -# Library routines -# -CONFIG_BITREVERSE=m -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=m -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_PLIST=y - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_MD is not set -# CONFIG_INPUT is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_SCHED_DEBUG=y -# CONFIG_SCHEDSTATS is not set -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -CONFIG_FRAME_POINTER=y -CONFIG_FORCED_INLINING=y -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SAMPLES is not set -# CONFIG_GPROF is not set -# CONFIG_GCOV is not set -# CONFIG_DEBUG_STACK_USAGE is not set diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index 1d9b6ae967b..e7582e1d248 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -9,7 +9,7 @@ slip-objs := slip_kern.o slip_user.o slirp-objs := slirp_kern.o slirp_user.o daemon-objs := daemon_kern.o daemon_user.o -mcast-objs := mcast_kern.o mcast_user.o +umcast-objs := umcast_kern.o umcast_user.o net-objs := net_kern.o net_user.o mconsole-objs := mconsole_kern.o mconsole_user.o hostaudio-objs := hostaudio_kern.o @@ -44,7 +44,7 @@ obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o obj-$(CONFIG_UML_NET_DAEMON) += daemon.o obj-$(CONFIG_UML_NET_VDE) += vde.o -obj-$(CONFIG_UML_NET_MCAST) += mcast.o +obj-$(CONFIG_UML_NET_MCAST) += umcast.o obj-$(CONFIG_UML_NET_PCAP) += pcap.o obj-$(CONFIG_UML_NET) += net.o obj-$(CONFIG_MCONSOLE) += mconsole.o diff --git a/arch/um/include/shared/chan_kern.h b/arch/um/drivers/chan.h index 1e651457e04..c512b0306dd 100644 --- a/arch/um/include/shared/chan_kern.h +++ b/arch/um/drivers/chan.h @@ -6,9 +6,9 @@ #ifndef __CHAN_KERN_H__ #define __CHAN_KERN_H__ -#include "linux/tty.h" -#include "linux/list.h" -#include "linux/console.h" +#include <linux/tty.h> +#include <linux/list.h> +#include <linux/console.h> #include "chan_user.h" #include "line.h" @@ -27,24 +27,23 @@ struct chan { void *data; }; -extern void chan_interrupt(struct list_head *chans, struct delayed_work *task, - struct tty_struct *tty, int irq); +extern void chan_interrupt(struct line *line, int irq); extern int parse_chan_pair(char *str, struct line *line, int device, const struct chan_opts *opts, char **error_out); -extern int write_chan(struct list_head *chans, const char *buf, int len, +extern int write_chan(struct chan *chan, const char *buf, int len, int write_irq); -extern int console_write_chan(struct list_head *chans, const char *buf, +extern int console_write_chan(struct chan *chan, const char *buf, int len); extern int console_open_chan(struct line *line, struct console *co); -extern void deactivate_chan(struct list_head *chans, int irq); -extern void reactivate_chan(struct list_head *chans, int irq); -extern void chan_enable_winch(struct list_head *chans, struct tty_struct *tty); +extern void deactivate_chan(struct chan *chan, int irq); +extern void reactivate_chan(struct chan *chan, int irq); +extern void chan_enable_winch(struct chan *chan, struct tty_port *port); extern int enable_chan(struct line *line); -extern void close_chan(struct list_head *chans, int delay_free_irq); -extern int chan_window_size(struct list_head *chans, +extern void close_chan(struct line *line); +extern int chan_window_size(struct line *line, unsigned short *rows_out, unsigned short *cols_out); -extern int chan_config_string(struct list_head *chans, char *str, int size, +extern int chan_config_string(struct line *line, char *str, int size, char **error_out); #endif diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 25e1965df7c..acbe6c67afb 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -6,8 +6,9 @@ #include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_flip.h> -#include "chan_kern.h" -#include "os.h" +#include "chan.h" +#include <os.h> +#include <irq_kern.h> #ifdef CONFIG_NOCONFIG_CHAN static void *not_configged_init(char *str, int device, @@ -80,25 +81,6 @@ static const struct chan_ops not_configged_ops = { }; #endif /* CONFIG_NOCONFIG_CHAN */ -static void tty_receive_char(struct tty_struct *tty, char ch) -{ - if (tty == NULL) - return; - - if (I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { - if (ch == STOP_CHAR(tty)) { - stop_tty(tty); - return; - } - else if (ch == START_CHAR(tty)) { - start_tty(tty); - return; - } - } - - tty_insert_flip_char(tty, ch, TTY_NORMAL); -} - static int open_one_chan(struct chan *chan) { int fd, err; @@ -140,18 +122,18 @@ static int open_chan(struct list_head *chans) return err; } -void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) +void chan_enable_winch(struct chan *chan, struct tty_port *port) { - struct list_head *ele; - struct chan *chan; + if (chan && chan->primary && chan->ops->winch) + register_winch(chan->fd, port); +} - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - if (chan->primary && chan->output && chan->ops->winch) { - register_winch(chan->fd, tty); - return; - } - } +static void line_timer_cb(struct work_struct *work) +{ + struct line *line = container_of(work, struct line, task.work); + + if (!line->throttled) + chan_interrupt(line, line->driver->read_irq); } int enable_chan(struct line *line) @@ -160,6 +142,8 @@ int enable_chan(struct line *line) struct chan *chan; int err; + INIT_DELAYED_WORK(&line->task, line_timer_cb); + list_for_each(ele, &line->chan_list) { chan = list_entry(ele, struct chan, list); err = open_one_chan(chan); @@ -183,7 +167,7 @@ int enable_chan(struct line *line) return 0; out_close: - close_chan(&line->chan_list, 0); + close_chan(line); return err; } @@ -211,9 +195,9 @@ void free_irqs(void) chan = list_entry(ele, struct chan, free_list); if (chan->input && chan->enabled) - free_irq(chan->line->driver->read_irq, chan); + um_free_irq(chan->line->driver->read_irq, chan); if (chan->output && chan->enabled) - free_irq(chan->line->driver->write_irq, chan); + um_free_irq(chan->line->driver->write_irq, chan); chan->enabled = 0; } } @@ -232,9 +216,9 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) } else { if (chan->input && chan->enabled) - free_irq(chan->line->driver->read_irq, chan); + um_free_irq(chan->line->driver->read_irq, chan); if (chan->output && chan->enabled) - free_irq(chan->line->driver->write_irq, chan); + um_free_irq(chan->line->driver->write_irq, chan); chan->enabled = 0; } if (chan->ops->close != NULL) @@ -244,7 +228,7 @@ static void close_one_chan(struct chan *chan, int delay_free_irq) chan->fd = -1; } -void close_chan(struct list_head *chans, int delay_free_irq) +void close_chan(struct line *line) { struct chan *chan; @@ -253,77 +237,50 @@ void close_chan(struct list_head *chans, int delay_free_irq) * state. Then, the first one opened will have the original state, * so it must be the last closed. */ - list_for_each_entry_reverse(chan, chans, list) { - close_one_chan(chan, delay_free_irq); + list_for_each_entry_reverse(chan, &line->chan_list, list) { + close_one_chan(chan, 0); } } -void deactivate_chan(struct list_head *chans, int irq) +void deactivate_chan(struct chan *chan, int irq) { - struct list_head *ele; - - struct chan *chan; - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - - if (chan->enabled && chan->input) - deactivate_fd(chan->fd, irq); - } + if (chan && chan->enabled) + deactivate_fd(chan->fd, irq); } -void reactivate_chan(struct list_head *chans, int irq) +void reactivate_chan(struct chan *chan, int irq) { - struct list_head *ele; - struct chan *chan; - - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - - if (chan->enabled && chan->input) - reactivate_fd(chan->fd, irq); - } + if (chan && chan->enabled) + reactivate_fd(chan->fd, irq); } -int write_chan(struct list_head *chans, const char *buf, int len, +int write_chan(struct chan *chan, const char *buf, int len, int write_irq) { - struct list_head *ele; - struct chan *chan = NULL; int n, ret = 0; - if (len == 0) + if (len == 0 || !chan || !chan->ops->write) return 0; - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - if (!chan->output || (chan->ops->write == NULL)) - continue; - - n = chan->ops->write(chan->fd, buf, len, chan->data); - if (chan->primary) { - ret = n; - if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) - reactivate_fd(chan->fd, write_irq); - } + n = chan->ops->write(chan->fd, buf, len, chan->data); + if (chan->primary) { + ret = n; + if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) + reactivate_fd(chan->fd, write_irq); } return ret; } -int console_write_chan(struct list_head *chans, const char *buf, int len) +int console_write_chan(struct chan *chan, const char *buf, int len) { - struct list_head *ele; - struct chan *chan; int n, ret = 0; - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - if (!chan->output || (chan->ops->console_write == NULL)) - continue; + if (!chan || !chan->ops->console_write) + return 0; - n = chan->ops->console_write(chan->fd, buf, len); - if (chan->primary) - ret = n; - } + n = chan->ops->console_write(chan->fd, buf, len); + if (chan->primary) + ret = n; return ret; } @@ -340,29 +297,33 @@ int console_open_chan(struct line *line, struct console *co) return 0; } -int chan_window_size(struct list_head *chans, unsigned short *rows_out, +int chan_window_size(struct line *line, unsigned short *rows_out, unsigned short *cols_out) { - struct list_head *ele; struct chan *chan; - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - if (chan->primary) { - if (chan->ops->window_size == NULL) - return 0; - return chan->ops->window_size(chan->fd, chan->data, - rows_out, cols_out); - } + chan = line->chan_in; + if (chan && chan->primary) { + if (chan->ops->window_size == NULL) + return 0; + return chan->ops->window_size(chan->fd, chan->data, + rows_out, cols_out); + } + chan = line->chan_out; + if (chan && chan->primary) { + if (chan->ops->window_size == NULL) + return 0; + return chan->ops->window_size(chan->fd, chan->data, + rows_out, cols_out); } return 0; } -static void free_one_chan(struct chan *chan, int delay_free_irq) +static void free_one_chan(struct chan *chan) { list_del(&chan->list); - close_one_chan(chan, delay_free_irq); + close_one_chan(chan, 0); if (chan->ops->free != NULL) (*chan->ops->free)(chan->data); @@ -372,14 +333,14 @@ static void free_one_chan(struct chan *chan, int delay_free_irq) kfree(chan); } -static void free_chan(struct list_head *chans, int delay_free_irq) +static void free_chan(struct list_head *chans) { struct list_head *ele, *next; struct chan *chan; list_for_each_safe(ele, next, chans) { chan = list_entry(ele, struct chan, list); - free_one_chan(chan, delay_free_irq); + free_one_chan(chan); } } @@ -429,21 +390,15 @@ static int chan_pair_config_string(struct chan *in, struct chan *out, return n; } -int chan_config_string(struct list_head *chans, char *str, int size, +int chan_config_string(struct line *line, char *str, int size, char **error_out) { - struct list_head *ele; - struct chan *chan, *in = NULL, *out = NULL; + struct chan *in = line->chan_in, *out = line->chan_out; - list_for_each(ele, chans) { - chan = list_entry(ele, struct chan, list); - if (!chan->primary) - continue; - if (chan->input) - in = chan; - if (chan->output) - out = chan; - } + if (in && !in->primary) + in = NULL; + if (out && !out->primary) + out = NULL; return chan_pair_config_string(in, out, str, size, error_out); } @@ -543,15 +498,18 @@ int parse_chan_pair(char *str, struct line *line, int device, const struct chan_opts *opts, char **error_out) { struct list_head *chans = &line->chan_list; - struct chan *new, *chan; + struct chan *new; char *in, *out; if (!list_empty(chans)) { - chan = list_entry(chans->next, struct chan, list); - free_chan(chans, 0); + line->chan_in = line->chan_out = NULL; + free_chan(chans); INIT_LIST_HEAD(chans); } + if (!str) + return 0; + out = strchr(str, ','); if (out != NULL) { in = str; @@ -563,6 +521,7 @@ int parse_chan_pair(char *str, struct line *line, int device, new->input = 1; list_add(&new->list, chans); + line->chan_in = new; new = parse_chan(line, out, device, opts, error_out); if (new == NULL) @@ -570,6 +529,7 @@ int parse_chan_pair(char *str, struct line *line, int device, list_add(&new->list, chans); new->output = 1; + line->chan_out = new; } else { new = parse_chan(line, str, device, opts, error_out); @@ -579,45 +539,43 @@ int parse_chan_pair(char *str, struct line *line, int device, list_add(&new->list, chans); new->input = 1; new->output = 1; + line->chan_in = line->chan_out = new; } return 0; } -void chan_interrupt(struct list_head *chans, struct delayed_work *task, - struct tty_struct *tty, int irq) +void chan_interrupt(struct line *line, int irq) { - struct list_head *ele, *next; - struct chan *chan; + struct tty_port *port = &line->port; + struct chan *chan = line->chan_in; int err; char c; - list_for_each_safe(ele, next, chans) { - chan = list_entry(ele, struct chan, list); - if (!chan->input || (chan->ops->read == NULL)) - continue; - do { - if (tty && !tty_buffer_request_room(tty, 1)) { - schedule_delayed_work(task, 1); - goto out; - } - err = chan->ops->read(chan->fd, &c, chan->data); - if (err > 0) - tty_receive_char(tty, c); - } while (err > 0); - - if (err == 0) - reactivate_fd(chan->fd, irq); - if (err == -EIO) { - if (chan->primary) { - if (tty != NULL) - tty_hangup(tty); - close_chan(chans, 1); - return; - } - else close_one_chan(chan, 1); + if (!chan || !chan->ops->read) + goto out; + + do { + if (!tty_buffer_request_room(port, 1)) { + schedule_delayed_work(&line->task, 1); + goto out; } + err = chan->ops->read(chan->fd, &c, chan->data); + if (err > 0) + tty_insert_flip_char(port, c, TTY_NORMAL); + } while (err > 0); + + if (err == 0) + reactivate_fd(chan->fd, irq); + if (err == -EIO) { + if (chan->primary) { + tty_port_tty_hangup(&line->port, false); + if (line->chan_out != chan) + close_one_chan(line->chan_out, 1); + } + close_one_chan(chan, 1); + if (chan->primary) + return; } out: - if (tty) - tty_flip_buffer_push(tty); + tty_flip_buffer_push(port); } diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index cfeb3f4a44a..3fd7c3efdb1 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -11,10 +11,8 @@ #include <termios.h> #include <sys/ioctl.h> #include "chan_user.h" -#include "kern_constants.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <os.h> +#include <um_malloc.h> void generic_close(int fd, void *unused) { @@ -218,7 +216,7 @@ static int winch_thread(void *arg) } } -static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, +static int winch_tramp(int fd, struct tty_port *port, int *fd_out, unsigned long *stack_out) { struct winch_data data; @@ -273,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out, return err; } -void register_winch(int fd, struct tty_struct *tty) +void register_winch(int fd, struct tty_port *port) { unsigned long stack; int pid, thread, count, thread_fd = -1; @@ -283,12 +281,17 @@ void register_winch(int fd, struct tty_struct *tty) return; pid = tcgetpgrp(fd); - if (!is_skas_winch(pid, fd, tty) && (pid == -1)) { - thread = winch_tramp(fd, tty, &thread_fd, &stack); + if (is_skas_winch(pid, fd, port)) { + register_winch_irq(-1, fd, -1, port, 0); + return; + } + + if (pid == -1) { + thread = winch_tramp(fd, port, &thread_fd, &stack); if (thread < 0) return; - register_winch_irq(thread_fd, fd, thread, tty, stack); + register_winch_irq(thread_fd, fd, thread, port, stack); count = write(thread_fd, &c, sizeof(c)); if (count != sizeof(c)) diff --git a/arch/um/include/shared/chan_user.h b/arch/um/drivers/chan_user.h index 9b9ced85b70..03f1b565c5f 100644 --- a/arch/um/include/shared/chan_user.h +++ b/arch/um/drivers/chan_user.h @@ -6,7 +6,7 @@ #ifndef __CHAN_USER_H__ #define __CHAN_USER_H__ -#include "init.h" +#include <init.h> struct chan_opts { void (*const announce)(char *dev_name, int dev); @@ -14,8 +14,6 @@ struct chan_opts { const int raw; }; -enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE }; - struct chan_ops { char *type; void *(*init)(char *, int, const struct chan_opts *); @@ -40,10 +38,10 @@ extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, unsigned short *cols_out); extern void generic_free(void *data); -struct tty_struct; -extern void register_winch(int fd, struct tty_struct *tty); +struct tty_port; +extern void register_winch(int fd, struct tty_port *port); extern void register_winch_irq(int fd, int tty_fd, int pid, - struct tty_struct *tty, unsigned long stack); + struct tty_port *port, unsigned long stack); #define __channel_help(fn, prefix) \ __uml_help(fn, prefix "[0-9]*=<channel description>\n" \ diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index dc36b222100..6673508f342 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h @@ -3,41 +3,6 @@ #include <asm/types.h> -#if defined(__KERNEL__) - -# include <asm/byteorder.h> - -# if defined(__BIG_ENDIAN) -# define ntohll(x) (x) -# define htonll(x) (x) -# elif defined(__LITTLE_ENDIAN) -# define ntohll(x) be64_to_cpu(x) -# define htonll(x) cpu_to_be64(x) -# else -# error "Could not determine byte order" -# endif - -#else -/* For the definition of ntohl, htonl and __BYTE_ORDER */ -#include <endian.h> -#include <netinet/in.h> -#if defined(__BYTE_ORDER) - -# if __BYTE_ORDER == __BIG_ENDIAN -# define ntohll(x) (x) -# define htonll(x) (x) -# elif __BYTE_ORDER == __LITTLE_ENDIAN -# define ntohll(x) bswap_64(x) -# define htonll(x) bswap_64(x) -# else -# error "Could not determine byte order: __BYTE_ORDER uncorrectly defined" -# endif - -#else /* ! defined(__BYTE_ORDER) */ -# error "Could not determine byte order: __BYTE_ORDER not defined" -#endif -#endif /* ! defined(__KERNEL__) */ - extern int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out); diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index f5701fd2ef9..67cbee63e70 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h @@ -1,10 +1,9 @@ #ifndef __COW_SYS_H__ #define __COW_SYS_H__ -#include "kern_util.h" -#include "os.h" -#include "user.h" -#include "um_malloc.h" +#include <kern_util.h> +#include <os.h> +#include <um_malloc.h> static inline void *cow_malloc(int size) { diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 93f227a25ba..0ee9cc6cc4c 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c @@ -8,11 +8,10 @@ * that. */ #include <unistd.h> -#include <byteswap.h> #include <errno.h> #include <string.h> #include <arpa/inet.h> -#include <asm/types.h> +#include <endian.h> #include "cow.h" #include "cow_sys.h" @@ -186,7 +185,11 @@ static int absolutize(char *to, int size, char *from) strcat(to, "/"); strcat(to, from); } - chdir(save_cwd); + if (chdir(save_cwd)) { + cow_printf("absolutize : Can't cd to '%s' - " + "errno = %d\n", save_cwd, errno); + return -1; + } return 0; } @@ -210,8 +213,8 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, "header\n"); goto out; } - header->magic = htonl(COW_MAGIC); - header->version = htonl(COW_VERSION); + header->magic = htobe32(COW_MAGIC); + header->version = htobe32(COW_VERSION); err = -EINVAL; if (strlen(backing_file) > sizeof(header->backing_file) - 1) { @@ -242,10 +245,10 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, goto out_free; } - header->mtime = htonl(modtime); - header->size = htonll(*size); - header->sectorsize = htonl(sectorsize); - header->alignment = htonl(alignment); + header->mtime = htobe32(modtime); + header->size = htobe64(*size); + header->sectorsize = htobe32(sectorsize); + header->alignment = htobe32(alignment); header->cow_format = COW_BITMAP; err = cow_write_file(fd, header, sizeof(*header)); @@ -297,8 +300,8 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, magic = header->v1.magic; if (magic == COW_MAGIC) version = header->v1.version; - else if (magic == ntohl(COW_MAGIC)) - version = ntohl(header->v1.version); + else if (magic == be32toh(COW_MAGIC)) + version = be32toh(header->v1.version); /* No error printed because the non-COW case comes through here */ else goto out; @@ -323,9 +326,9 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, "header\n"); goto out; } - *mtime_out = ntohl(header->v2.mtime); - *size_out = ntohll(header->v2.size); - *sectorsize_out = ntohl(header->v2.sectorsize); + *mtime_out = be32toh(header->v2.mtime); + *size_out = be64toh(header->v2.size); + *sectorsize_out = be32toh(header->v2.sectorsize); *bitmap_offset_out = sizeof(header->v2); *align_out = *sectorsize_out; file = header->v2.backing_file; @@ -337,10 +340,10 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, "header\n"); goto out; } - *mtime_out = ntohl(header->v3.mtime); - *size_out = ntohll(header->v3.size); - *sectorsize_out = ntohl(header->v3.sectorsize); - *align_out = ntohl(header->v3.alignment); + *mtime_out = be32toh(header->v3.mtime); + *size_out = be64toh(header->v3.size); + *sectorsize_out = be32toh(header->v3.sectorsize); + *align_out = be32toh(header->v3.alignment); if (*align_out == 0) { cow_printf("read_cow_header - invalid COW header, " "align == 0\n"); @@ -362,16 +365,16 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, * this was used until Dec2005 - 64bits are needed to represent * 2038+. I.e. we can safely do this truncating cast. * - * Additionally, we must use ntohl() instead of ntohll(), since + * Additionally, we must use be32toh() instead of be64toh(), since * the program used to use the former (tested - I got mtime * mismatch "0 vs whatever"). * * Ever heard about bug-to-bug-compatibility ? ;-) */ - *mtime_out = (time32_t) ntohl(header->v3_b.mtime); + *mtime_out = (time32_t) be32toh(header->v3_b.mtime); - *size_out = ntohll(header->v3_b.size); - *sectorsize_out = ntohl(header->v3_b.sectorsize); - *align_out = ntohl(header->v3_b.alignment); + *size_out = be64toh(header->v3_b.size); + *sectorsize_out = be32toh(header->v3_b.sectorsize); + *align_out = be32toh(header->v3_b.alignment); if (*align_out == 0) { cow_printf("read_cow_header - invalid COW header, " "align == 0\n"); diff --git a/arch/um/drivers/daemon.h b/arch/um/drivers/daemon.h index 6e0e891f8a0..c2dd1951559 100644 --- a/arch/um/drivers/daemon.h +++ b/arch/um/drivers/daemon.h @@ -6,7 +6,7 @@ #ifndef __DAEMON_H__ #define __DAEMON_H__ -#include "net_user.h" +#include <net_user.h> #define SWITCH_VERSION 3 diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index b4a1522f215..7568cc2f3cd 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c @@ -6,9 +6,9 @@ * Licensed under the GPL. */ -#include "linux/init.h" +#include <linux/init.h> #include <linux/netdevice.h> -#include "net_kern.h" +#include <net_kern.h> #include "daemon.h" struct daemon_init { diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index f8e85e0bdac..8813c10d017 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -14,10 +14,9 @@ #include <sys/time.h> #include <sys/un.h> #include "daemon.h" -#include "net_user.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <net_user.h> +#include <os.h> +#include <um_malloc.h> enum request_type { REQ_NEW_CONTROL }; diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index f5a981a1624..a13a427b996 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -9,10 +9,8 @@ #include <errno.h> #include <termios.h> #include "chan_user.h" -#include "kern_constants.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <os.h> +#include <um_malloc.h> struct fd_chan { int fd; diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index b56f8e0196a..f99b32a4dbf 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -6,8 +6,7 @@ #include <stdio.h> #include <unistd.h> #include <errno.h> -#include "os.h" -#include "user.h" +#include <os.h> struct dog_data { int stdin; @@ -32,7 +31,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) { struct dog_data data; int in_fds[2], out_fds[2], pid, n, err; - char pid_buf[sizeof("nnnnn\0")], c; + char pid_buf[sizeof("nnnnnnn\0")], c; char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, NULL }; diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index f9f6a4e2059..9b90fdc4b15 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -3,15 +3,15 @@ * Licensed under the GPL */ -#include "linux/fs.h" -#include "linux/module.h" -#include "linux/slab.h" -#include "linux/sound.h" -#include "linux/soundcard.h" -#include "linux/mutex.h" -#include "asm/uaccess.h" -#include "init.h" -#include "os.h" +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/sound.h> +#include <linux/soundcard.h> +#include <linux/mutex.h> +#include <asm/uaccess.h> +#include <init.h> +#include <os.h> struct hostaudio_state { int fd; diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 35dd0b86401..8035145f043 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c @@ -3,15 +3,15 @@ * Licensed under the GPL */ -#include "linux/irqreturn.h" -#include "linux/kd.h" -#include "linux/sched.h" -#include "linux/slab.h" -#include "chan_kern.h" -#include "irq_kern.h" -#include "irq_user.h" -#include "kern_util.h" -#include "os.h" +#include <linux/irqreturn.h> +#include <linux/kd.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include "chan.h" +#include <irq_kern.h> +#include <irq_user.h> +#include <kern_util.h> +#include <os.h> #define LINE_BUFSIZE 4096 @@ -21,17 +21,9 @@ static irqreturn_t line_interrupt(int irq, void *data) struct line *line = chan->line; if (line) - chan_interrupt(&line->chan_list, &line->task, line->tty, irq); - return IRQ_HANDLED; -} + chan_interrupt(line, irq); -static void line_timer_cb(struct work_struct *work) -{ - struct line *line = container_of(work, struct line, task.work); - - if (!line->throttled) - chan_interrupt(&line->chan_list, &line->task, line->tty, - line->driver->read_irq); + return IRQ_HANDLED; } /* @@ -145,7 +137,7 @@ static int flush_buffer(struct line *line) /* line->buffer + LINE_BUFSIZE is the end of the buffer! */ count = line->buffer + LINE_BUFSIZE - line->head; - n = write_chan(&line->chan_list, line->head, count, + n = write_chan(line->chan_out, line->head, count, line->driver->write_irq); if (n < 0) return n; @@ -162,7 +154,7 @@ static int flush_buffer(struct line *line) } count = line->tail - line->head; - n = write_chan(&line->chan_list, line->head, count, + n = write_chan(line->chan_out, line->head, count, line->driver->write_irq); if (n < 0) @@ -176,10 +168,9 @@ void line_flush_buffer(struct tty_struct *tty) { struct line *line = tty->driver_data; unsigned long flags; - int err; spin_lock_irqsave(&line->lock, flags); - err = flush_buffer(line); + flush_buffer(line); spin_unlock_irqrestore(&line->lock, flags); } @@ -207,7 +198,7 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len) if (line->head != line->tail) ret = buffer_data(line, buf, len); else { - n = write_chan(&line->chan_list, buf, len, + n = write_chan(line->chan_out, buf, len, line->driver->write_irq); if (n < 0) { ret = n; @@ -229,97 +220,11 @@ void line_set_termios(struct tty_struct *tty, struct ktermios * old) /* nothing */ } -static const struct { - int cmd; - char *level; - char *name; -} tty_ioctls[] = { - /* don't print these, they flood the log ... */ - { TCGETS, NULL, "TCGETS" }, - { TCSETS, NULL, "TCSETS" }, - { TCSETSW, NULL, "TCSETSW" }, - { TCFLSH, NULL, "TCFLSH" }, - { TCSBRK, NULL, "TCSBRK" }, - - /* general tty stuff */ - { TCSETSF, KERN_DEBUG, "TCSETSF" }, - { TCGETA, KERN_DEBUG, "TCGETA" }, - { TIOCMGET, KERN_DEBUG, "TIOCMGET" }, - { TCSBRKP, KERN_DEBUG, "TCSBRKP" }, - { TIOCMSET, KERN_DEBUG, "TIOCMSET" }, - - /* linux-specific ones */ - { TIOCLINUX, KERN_INFO, "TIOCLINUX" }, - { KDGKBMODE, KERN_INFO, "KDGKBMODE" }, - { KDGKBTYPE, KERN_INFO, "KDGKBTYPE" }, - { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" }, -}; - -int line_ioctl(struct tty_struct *tty, unsigned int cmd, - unsigned long arg) -{ - int ret; - int i; - - ret = 0; - switch(cmd) { -#ifdef TIOCGETP - case TIOCGETP: - case TIOCSETP: - case TIOCSETN: -#endif -#ifdef TIOCGETC - case TIOCGETC: - case TIOCSETC: -#endif -#ifdef TIOCGLTC - case TIOCGLTC: - case TIOCSLTC: -#endif - /* Note: these are out of date as we now have TCGETS2 etc but this - whole lot should probably go away */ - case TCGETS: - case TCSETSF: - case TCSETSW: - case TCSETS: - case TCGETA: - case TCSETAF: - case TCSETAW: - case TCSETA: - case TCXONC: - case TCFLSH: - case TIOCOUTQ: - case TIOCINQ: - case TIOCGLCKTRMIOS: - case TIOCSLCKTRMIOS: - case TIOCPKT: - case TIOCGSOFTCAR: - case TIOCSSOFTCAR: - return -ENOIOCTLCMD; -#if 0 - case TCwhatever: - /* do something */ - break; -#endif - default: - for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++) - if (cmd == tty_ioctls[i].cmd) - break; - if (i == ARRAY_SIZE(tty_ioctls)) { - printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n", - __func__, tty->name, cmd); - } - ret = -ENOIOCTLCMD; - break; - } - return ret; -} - void line_throttle(struct tty_struct *tty) { struct line *line = tty->driver_data; - deactivate_chan(&line->chan_list, line->driver->read_irq); + deactivate_chan(line->chan_in, line->driver->read_irq); line->throttled = 1; } @@ -328,8 +233,7 @@ void line_unthrottle(struct tty_struct *tty) struct line *line = tty->driver_data; line->throttled = 0; - chan_interrupt(&line->chan_list, &line->task, tty, - line->driver->read_irq); + chan_interrupt(line, line->driver->read_irq); /* * Maybe there is enough stuff pending that calling the interrupt @@ -337,24 +241,24 @@ void line_unthrottle(struct tty_struct *tty) * again and we shouldn't turn the interrupt back on. */ if (!line->throttled) - reactivate_chan(&line->chan_list, line->driver->read_irq); + reactivate_chan(line->chan_in, line->driver->read_irq); } static irqreturn_t line_write_interrupt(int irq, void *data) { struct chan *chan = data; struct line *line = chan->line; - struct tty_struct *tty = line->tty; int err; /* - * Interrupts are disabled here because we registered the interrupt with - * IRQF_DISABLED (see line_setup_irq). + * Interrupts are disabled here because genirq keep irqs disabled when + * calling the action handler. */ spin_lock(&line->lock); err = flush_buffer(line); if (err == 0) { + spin_unlock(&line->lock); return IRQ_NONE; } else if (err < 0) { line->head = line->buffer; @@ -362,125 +266,100 @@ static irqreturn_t line_write_interrupt(int irq, void *data) } spin_unlock(&line->lock); - if (tty == NULL) - return IRQ_NONE; + tty_port_tty_wakeup(&line->port); - tty_wakeup(tty); return IRQ_HANDLED; } int line_setup_irq(int fd, int input, int output, struct line *line, void *data) { const struct line_driver *driver = line->driver; - int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM; + int err = 0; if (input) err = um_request_irq(driver->read_irq, fd, IRQ_READ, - line_interrupt, flags, - driver->read_irq_name, data); + line_interrupt, IRQF_SHARED, + driver->read_irq_name, data); if (err) return err; if (output) err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, - line_write_interrupt, flags, - driver->write_irq_name, data); - line->have_irq = 1; + line_write_interrupt, IRQF_SHARED, + driver->write_irq_name, data); return err; } -/* - * Normally, a driver like this can rely mostly on the tty layer - * locking, particularly when it comes to the driver structure. - * However, in this case, mconsole requests can come in "from the - * side", and race with opens and closes. - * - * mconsole config requests will want to be sure the device isn't in - * use, and get_config, open, and close will want a stable - * configuration. The checking and modification of the configuration - * is done under a spinlock. Checking whether the device is in use is - * line->tty->count > 1, also under the spinlock. - * - * tty->count serves to decide whether the device should be enabled or - * disabled on the host. If it's equal to 1, then we are doing the - * first open or last close. Otherwise, open and close just return. - */ - -int line_open(struct line *lines, struct tty_struct *tty) +static int line_activate(struct tty_port *port, struct tty_struct *tty) { - struct line *line = &lines[tty->index]; - int err = -ENODEV; - - spin_lock(&line->count_lock); - if (!line->valid) - goto out_unlock; - - err = 0; - if (tty->count > 1) - goto out_unlock; - - spin_unlock(&line->count_lock); - - tty->driver_data = line; - line->tty = tty; - - err = enable_chan(line); - if (err) - return err; + int ret; + struct line *line = tty->driver_data; - INIT_DELAYED_WORK(&line->task, line_timer_cb); + ret = enable_chan(line); + if (ret) + return ret; if (!line->sigio) { - chan_enable_winch(&line->chan_list, tty); + chan_enable_winch(line->chan_out, port); line->sigio = 1; } - chan_window_size(&line->chan_list, &tty->winsize.ws_row, - &tty->winsize.ws_col); - - return err; + chan_window_size(line, &tty->winsize.ws_row, + &tty->winsize.ws_col); -out_unlock: - spin_unlock(&line->count_lock); - return err; + return 0; } static void unregister_winch(struct tty_struct *tty); -void line_close(struct tty_struct *tty, struct file * filp) +static void line_destruct(struct tty_port *port) { + struct tty_struct *tty = tty_port_tty_get(port); struct line *line = tty->driver_data; - /* - * If line_open fails (and tty->driver_data is never set), - * tty_open will call line_close. So just return in this case. - */ - if (line == NULL) - return; + if (line->sigio) { + unregister_winch(tty); + line->sigio = 0; + } +} - /* We ignore the error anyway! */ - flush_buffer(line); +static const struct tty_port_operations line_port_ops = { + .activate = line_activate, + .destruct = line_destruct, +}; - spin_lock(&line->count_lock); - if (!line->valid) - goto out_unlock; +int line_open(struct tty_struct *tty, struct file *filp) +{ + struct line *line = tty->driver_data; + + return tty_port_open(&line->port, tty, filp); +} - if (tty->count > 1) - goto out_unlock; +int line_install(struct tty_driver *driver, struct tty_struct *tty, + struct line *line) +{ + int ret; - spin_unlock(&line->count_lock); + ret = tty_standard_install(driver, tty); + if (ret) + return ret; - line->tty = NULL; - tty->driver_data = NULL; + tty->driver_data = line; - if (line->sigio) { - unregister_winch(tty); - line->sigio = 0; - } + return 0; +} - return; +void line_close(struct tty_struct *tty, struct file * filp) +{ + struct line *line = tty->driver_data; + + tty_port_close(&line->port, tty, filp); +} + +void line_hangup(struct tty_struct *tty) +{ + struct line *line = tty->driver_data; -out_unlock: - spin_unlock(&line->count_lock); + tty_port_hangup(&line->port); } void close_lines(struct line *lines, int nlines) @@ -488,34 +367,58 @@ void close_lines(struct line *lines, int nlines) int i; for(i = 0; i < nlines; i++) - close_chan(&lines[i].chan_list, 0); + close_chan(&lines[i]); } -static int setup_one_line(struct line *lines, int n, char *init, int init_prio, - char **error_out) +int setup_one_line(struct line *lines, int n, char *init, + const struct chan_opts *opts, char **error_out) { struct line *line = &lines[n]; + struct tty_driver *driver = line->driver->driver; int err = -EINVAL; - spin_lock(&line->count_lock); - - if (line->tty != NULL) { + if (line->port.count) { *error_out = "Device is already open"; goto out; } - if (line->init_pri <= init_prio) { - line->init_pri = init_prio; - if (!strcmp(init, "none")) + if (!strcmp(init, "none")) { + if (line->valid) { line->valid = 0; - else { - line->init_str = init; - line->valid = 1; + kfree(line->init_str); + tty_unregister_device(driver, n); + parse_chan_pair(NULL, line, n, opts, error_out); + err = 0; + } + } else { + char *new = kstrdup(init, GFP_KERNEL); + if (!new) { + *error_out = "Failed to allocate memory"; + return -ENOMEM; + } + if (line->valid) { + tty_unregister_device(driver, n); + kfree(line->init_str); + } + line->init_str = new; + line->valid = 1; + err = parse_chan_pair(new, line, n, opts, error_out); + if (!err) { + struct device *d = tty_port_register_device(&line->port, + driver, n, NULL); + if (IS_ERR(d)) { + *error_out = "Failed to register device"; + err = PTR_ERR(d); + parse_chan_pair(NULL, line, n, opts, error_out); + } + } + if (err) { + line->init_str = NULL; + line->valid = 0; + kfree(new); } } - err = 0; out: - spin_unlock(&line->count_lock); return err; } @@ -526,54 +429,43 @@ out: * @error_out is an error string in the case of failure; */ -int line_setup(struct line *lines, unsigned int num, char *init, - char **error_out) +int line_setup(char **conf, unsigned int num, char **def, + char *init, char *name) { - int i, n, err; - char *end; + char *error; if (*init == '=') { /* * We said con=/ssl= instead of con#=, so we are configuring all * consoles at once. */ - n = -1; - } - else { - n = simple_strtoul(init, &end, 0); + *def = init + 1; + } else { + char *end; + unsigned n = simple_strtoul(init, &end, 0); + if (*end != '=') { - *error_out = "Couldn't parse device number"; - return -EINVAL; + error = "Couldn't parse device number"; + goto out; } - init = end; - } - init++; - - if (n >= (signed int) num) { - *error_out = "Device number out of range"; - return -EINVAL; - } - else if (n >= 0) { - err = setup_one_line(lines, n, init, INIT_ONE, error_out); - if (err) - return err; - } - else { - for(i = 0; i < num; i++) { - err = setup_one_line(lines, i, init, INIT_ALL, - error_out); - if (err) - return err; + if (n >= num) { + error = "Device number out of range"; + goto out; } + conf[n] = end + 1; } - return n == -1 ? num : n; + return 0; + +out: + printk(KERN_ERR "Failed to set up %s with " + "configuration string \"%s\" : %s\n", name, init, error); + return -EINVAL; } int line_config(struct line *lines, unsigned int num, char *str, const struct chan_opts *opts, char **error_out) { - struct line *line; - char *new; + char *end; int n; if (*str == '=') { @@ -581,17 +473,17 @@ int line_config(struct line *lines, unsigned int num, char *str, return -EINVAL; } - new = kstrdup(str, GFP_KERNEL); - if (new == NULL) { - *error_out = "Failed to allocate memory"; - return -ENOMEM; + n = simple_strtoul(str, &end, 0); + if (*end++ != '=') { + *error_out = "Couldn't parse device number"; + return -EINVAL; + } + if (n >= num) { + *error_out = "Device number out of range"; + return -EINVAL; } - n = line_setup(lines, num, new, error_out); - if (n < 0) - return n; - line = &lines[n]; - return parse_chan_pair(line->init_str, line, n, opts, error_out); + return setup_one_line(lines, n, end, opts, error_out); } int line_get_config(char *name, struct line *lines, unsigned int num, char *str, @@ -614,13 +506,17 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str, line = &lines[dev]; - spin_lock(&line->count_lock); if (!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); - else if (line->tty == NULL) - CONFIG_CHUNK(str, size, n, line->init_str, 1); - else n = chan_config_string(&line->chan_list, str, size, error_out); - spin_unlock(&line->count_lock); + else { + struct tty_struct *tty = tty_port_tty_get(&line->port); + if (tty == NULL) { + CONFIG_CHUNK(str, size, n, line->init_str, 1); + } else { + n = chan_config_string(line, str, size, error_out); + tty_kref_put(tty); + } + } return n; } @@ -642,25 +538,23 @@ int line_id(char **str, int *start_out, int *end_out) int line_remove(struct line *lines, unsigned int num, int n, char **error_out) { - int err; - char config[sizeof("conxxxx=none\0")]; - - sprintf(config, "%d=none", n); - err = line_setup(lines, num, config, error_out); - if (err >= 0) - err = 0; - return err; + if (n >= num) { + *error_out = "Device number out of range"; + return -EINVAL; + } + return setup_one_line(lines, n, "none", NULL, error_out); } -struct tty_driver *register_lines(struct line_driver *line_driver, - const struct tty_operations *ops, - struct line *lines, int nlines) +int register_lines(struct line_driver *line_driver, + const struct tty_operations *ops, + struct line *lines, int nlines) { - int i; struct tty_driver *driver = alloc_tty_driver(nlines); + int err; + int i; if (!driver) - return NULL; + return -ENOMEM; driver->driver_name = line_driver->name; driver->name = line_driver->device_name; @@ -668,109 +562,104 @@ struct tty_driver *register_lines(struct line_driver *line_driver, driver->minor_start = line_driver->minor_start; driver->type = line_driver->type; driver->subtype = line_driver->subtype; - driver->flags = TTY_DRIVER_REAL_RAW; + driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; driver->init_termios = tty_std_termios; + + for (i = 0; i < nlines; i++) { + tty_port_init(&lines[i].port); + lines[i].port.ops = &line_port_ops; + spin_lock_init(&lines[i].lock); + lines[i].driver = line_driver; + INIT_LIST_HEAD(&lines[i].chan_list); + } tty_set_operations(driver, ops); - if (tty_register_driver(driver)) { + err = tty_register_driver(driver); + if (err) { printk(KERN_ERR "register_lines : can't register %s driver\n", line_driver->name); put_tty_driver(driver); - return NULL; - } - - for(i = 0; i < nlines; i++) { - if (!lines[i].valid) - tty_unregister_device(driver, i); + for (i = 0; i < nlines; i++) + tty_port_destroy(&lines[i].port); + return err; } + line_driver->driver = driver; mconsole_register_dev(&line_driver->mc); - return driver; + return 0; } static DEFINE_SPINLOCK(winch_handler_lock); static LIST_HEAD(winch_handlers); -void lines_init(struct line *lines, int nlines, struct chan_opts *opts) -{ - struct line *line; - char *error; - int i; - - for(i = 0; i < nlines; i++) { - line = &lines[i]; - INIT_LIST_HEAD(&line->chan_list); - - if (line->init_str == NULL) - continue; - - line->init_str = kstrdup(line->init_str, GFP_KERNEL); - if (line->init_str == NULL) - printk(KERN_ERR "lines_init - kstrdup returned NULL\n"); - - if (parse_chan_pair(line->init_str, line, i, opts, &error)) { - printk(KERN_ERR "parse_chan_pair failed for " - "device %d : %s\n", i, error); - line->valid = 0; - } - } -} - struct winch { struct list_head list; int fd; int tty_fd; int pid; - struct tty_struct *tty; + struct tty_port *port; unsigned long stack; + struct work_struct work; }; -static void free_winch(struct winch *winch, int free_irq_ok) +static void __free_winch(struct work_struct *work) { - if (free_irq_ok) - free_irq(WINCH_IRQ, winch); - - list_del(&winch->list); + struct winch *winch = container_of(work, struct winch, work); + um_free_irq(WINCH_IRQ, winch); if (winch->pid != -1) os_kill_process(winch->pid, 1); - if (winch->fd != -1) - os_close_file(winch->fd); if (winch->stack != 0) free_stack(winch->stack, 0); kfree(winch); } +static void free_winch(struct winch *winch) +{ + int fd = winch->fd; + winch->fd = -1; + if (fd != -1) + os_close_file(fd); + list_del(&winch->list); + __free_winch(&winch->work); +} + static irqreturn_t winch_interrupt(int irq, void *data) { struct winch *winch = data; struct tty_struct *tty; struct line *line; + int fd = winch->fd; int err; char c; - if (winch->fd != -1) { - err = generic_read(winch->fd, &c, NULL); + if (fd != -1) { + err = generic_read(fd, &c, NULL); if (err < 0) { if (err != -EAGAIN) { + winch->fd = -1; + list_del(&winch->list); + os_close_file(fd); printk(KERN_ERR "winch_interrupt : " "read failed, errno = %d\n", -err); printk(KERN_ERR "fd %d is losing SIGWINCH " "support\n", winch->tty_fd); - free_winch(winch, 0); + INIT_WORK(&winch->work, __free_winch); + schedule_work(&winch->work); return IRQ_HANDLED; } goto out; } } - tty = winch->tty; + tty = tty_port_tty_get(winch->port); if (tty != NULL) { line = tty->driver_data; if (line != NULL) { - chan_window_size(&line->chan_list, &tty->winsize.ws_row, + chan_window_size(line, &tty->winsize.ws_row, &tty->winsize.ws_col); kill_pgrp(tty->pgrp, SIGWINCH, 1); } + tty_kref_put(tty); } out: if (winch->fd != -1) @@ -778,7 +667,7 @@ static irqreturn_t winch_interrupt(int irq, void *data) return IRQ_HANDLED; } -void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, +void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port, unsigned long stack) { struct winch *winch; @@ -793,12 +682,11 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty, .fd = fd, .tty_fd = tty_fd, .pid = pid, - .tty = tty, + .port = port, .stack = stack }); if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt, - IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "winch", winch) < 0) { + IRQF_SHARED, "winch", winch) < 0) { printk(KERN_ERR "register_winch_irq - failed to register " "IRQ\n"); goto out_free; @@ -823,15 +711,18 @@ static void unregister_winch(struct tty_struct *tty) { struct list_head *ele, *next; struct winch *winch; + struct tty_struct *wtty; spin_lock(&winch_handler_lock); list_for_each_safe(ele, next, &winch_handlers) { winch = list_entry(ele, struct winch, list); - if (winch->tty == tty) { - free_winch(winch, 1); + wtty = tty_port_tty_get(winch->port); + if (wtty == tty) { + free_winch(winch); break; } + tty_kref_put(wtty); } spin_unlock(&winch_handler_lock); } @@ -845,7 +736,7 @@ static void winch_cleanup(void) list_for_each_safe(ele, next, &winch_handlers) { winch = list_entry(ele, struct winch, list); - free_winch(winch, 1); + free_winch(winch); } spin_unlock(&winch_handler_lock); diff --git a/arch/um/include/shared/line.h b/arch/um/drivers/line.h index 72f4f25af24..138a14526d9 100644 --- a/arch/um/include/shared/line.h +++ b/arch/um/drivers/line.h @@ -6,16 +6,16 @@ #ifndef __LINE_H__ #define __LINE_H__ -#include "linux/list.h" -#include "linux/workqueue.h" -#include "linux/tty.h" -#include "linux/interrupt.h" -#include "linux/spinlock.h" -#include "linux/mutex.h" +#include <linux/list.h> +#include <linux/workqueue.h> +#include <linux/tty.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/mutex.h> #include "chan_user.h" #include "mconsole_kern.h" -/* There's only one modifiable field in this - .mc.list */ +/* There's only two modifiable fields in this - .mc.list and .driver */ struct line_driver { const char *name; const char *device_name; @@ -28,16 +28,16 @@ struct line_driver { const int write_irq; const char *write_irq_name; struct mc_device mc; + struct tty_driver *driver; }; struct line { - struct tty_struct *tty; - spinlock_t count_lock; + struct tty_port port; int valid; char *init_str; - int init_pri; struct list_head chan_list; + struct chan *chan_in, *chan_out; /*This lock is actually, mostly, local to*/ spinlock_t lock; @@ -54,21 +54,16 @@ struct line { int sigio; struct delayed_work task; const struct line_driver *driver; - int have_irq; }; -#define LINE_INIT(str, d) \ - { .count_lock = __SPIN_LOCK_UNLOCKED((str).count_lock), \ - .init_str = str, \ - .init_pri = INIT_STATIC, \ - .valid = 1, \ - .lock = __SPIN_LOCK_UNLOCKED((str).lock), \ - .driver = d } - extern void line_close(struct tty_struct *tty, struct file * filp); -extern int line_open(struct line *lines, struct tty_struct *tty); -extern int line_setup(struct line *lines, unsigned int sizeof_lines, - char *init, char **error_out); +extern int line_open(struct tty_struct *tty, struct file *filp); +extern int line_install(struct tty_driver *driver, struct tty_struct *tty, + struct line *line); +extern void line_cleanup(struct tty_struct *tty); +extern void line_hangup(struct tty_struct *tty); +extern int line_setup(char **conf, unsigned nlines, char **def, + char *init, char *name); extern int line_write(struct tty_struct *tty, const unsigned char *buf, int len); extern int line_put_char(struct tty_struct *tty, unsigned char ch); @@ -77,8 +72,6 @@ extern int line_chars_in_buffer(struct tty_struct *tty); extern void line_flush_buffer(struct tty_struct *tty); extern void line_flush_chars(struct tty_struct *tty); extern int line_write_room(struct tty_struct *tty); -extern int line_ioctl(struct tty_struct *tty, unsigned int cmd, - unsigned long arg); extern void line_throttle(struct tty_struct *tty); extern void line_unthrottle(struct tty_struct *tty); @@ -86,10 +79,11 @@ extern char *add_xterm_umid(char *base); extern int line_setup_irq(int fd, int input, int output, struct line *line, void *data); extern void line_close_chan(struct line *line); -extern struct tty_driver *register_lines(struct line_driver *line_driver, - const struct tty_operations *driver, - struct line *lines, int nlines); -extern void lines_init(struct line *lines, int nlines, struct chan_opts *opts); +extern int register_lines(struct line_driver *line_driver, + const struct tty_operations *driver, + struct line *lines, int nlines); +extern int setup_one_line(struct line *lines, int n, char *init, + const struct chan_opts *opts, char **error_out); extern void close_lines(struct line *lines, int nlines); extern int line_config(struct line *lines, unsigned int sizeof_lines, diff --git a/arch/um/drivers/mcast.h b/arch/um/drivers/mcast.h deleted file mode 100644 index 6fa282e896b..00000000000 --- a/arch/um/drivers/mcast.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __DRIVERS_MCAST_H -#define __DRIVERS_MCAST_H - -#include "net_user.h" - -struct mcast_data { - char *addr; - unsigned short port; - void *mcast_addr; - int ttl; - void *dev; -}; - -extern const struct net_user_info mcast_user_info; - -extern int mcast_user_write(int fd, void *buf, int len, - struct mcast_data *pri); - -#endif diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c deleted file mode 100644 index ffc6416d5ed..00000000000 --- a/arch/um/drivers/mcast_kern.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * user-mode-linux networking multicast transport - * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * - * based on the existing uml-networking code, which is - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and - * James Leu (jleu@mindspring.net). - * Copyright (C) 2001 by various other people who didn't put their name here. - * - * Licensed under the GPL. - */ - -#include "linux/init.h" -#include <linux/netdevice.h> -#include "mcast.h" -#include "net_kern.h" - -struct mcast_init { - char *addr; - int port; - int ttl; -}; - -static void mcast_init(struct net_device *dev, void *data) -{ - struct uml_net_private *pri; - struct mcast_data *dpri; - struct mcast_init *init = data; - - pri = netdev_priv(dev); - dpri = (struct mcast_data *) pri->user; - dpri->addr = init->addr; - dpri->port = init->port; - dpri->ttl = init->ttl; - dpri->dev = dev; - - printk("mcast backend multicast address: %s:%u, TTL:%u\n", - dpri->addr, dpri->port, dpri->ttl); -} - -static int mcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) -{ - return net_recvfrom(fd, skb_mac_header(skb), - skb->dev->mtu + ETH_HEADER_OTHER); -} - -static int mcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) -{ - return mcast_user_write(fd, skb->data, skb->len, - (struct mcast_data *) &lp->user); -} - -static const struct net_kern_info mcast_kern_info = { - .init = mcast_init, - .protocol = eth_protocol, - .read = mcast_read, - .write = mcast_write, -}; - -static int mcast_setup(char *str, char **mac_out, void *data) -{ - struct mcast_init *init = data; - char *port_str = NULL, *ttl_str = NULL, *remain; - char *last; - - *init = ((struct mcast_init) - { .addr = "239.192.168.1", - .port = 1102, - .ttl = 1 }); - - remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, - NULL); - if (remain != NULL) { - printk(KERN_ERR "mcast_setup - Extra garbage on " - "specification : '%s'\n", remain); - return 0; - } - - if (port_str != NULL) { - init->port = simple_strtoul(port_str, &last, 10); - if ((*last != '\0') || (last == port_str)) { - printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", - port_str); - return 0; - } - } - - if (ttl_str != NULL) { - init->ttl = simple_strtoul(ttl_str, &last, 10); - if ((*last != '\0') || (last == ttl_str)) { - printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", - ttl_str); - return 0; - } - } - - printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, - init->port, init->ttl); - - return 1; -} - -static struct transport mcast_transport = { - .list = LIST_HEAD_INIT(mcast_transport.list), - .name = "mcast", - .setup = mcast_setup, - .user = &mcast_user_info, - .kern = &mcast_kern_info, - .private_size = sizeof(struct mcast_data), - .setup_size = sizeof(struct mcast_init), -}; - -static int register_mcast(void) -{ - register_transport(&mcast_transport); - return 0; -} - -late_initcall(register_mcast); diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c deleted file mode 100644 index ee19e91568a..00000000000 --- a/arch/um/drivers/mcast_user.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * user-mode-linux networking multicast transport - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> - * - * based on the existing uml-networking code, which is - * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and - * James Leu (jleu@mindspring.net). - * Copyright (C) 2001 by various other people who didn't put their name here. - * - * Licensed under the GPL. - * - */ - -#include <unistd.h> -#include <errno.h> -#include <netinet/in.h> -#include "kern_constants.h" -#include "mcast.h" -#include "net_user.h" -#include "um_malloc.h" -#include "user.h" - -static struct sockaddr_in *new_addr(char *addr, unsigned short port) -{ - struct sockaddr_in *sin; - - sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); - if (sin == NULL) { - printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " - "failed\n"); - return NULL; - } - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = in_aton(addr); - sin->sin_port = htons(port); - return sin; -} - -static int mcast_user_init(void *data, void *dev) -{ - struct mcast_data *pri = data; - - pri->mcast_addr = new_addr(pri->addr, pri->port); - pri->dev = dev; - return 0; -} - -static void mcast_remove(void *data) -{ - struct mcast_data *pri = data; - - kfree(pri->mcast_addr); - pri->mcast_addr = NULL; -} - -static int mcast_open(void *data) -{ - struct mcast_data *pri = data; - struct sockaddr_in *sin = pri->mcast_addr; - struct ip_mreq mreq; - int fd, yes = 1, err = -EINVAL; - - - if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) - goto out; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - - if (fd < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open : data socket failed, " - "errno = %d\n", errno); - goto out; - } - - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: SO_REUSEADDR failed, " - "errno = %d\n", errno); - goto out_close; - } - - /* set ttl according to config */ - if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, - sizeof(pri->ttl)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_TTL failed, " - "error = %d\n", errno); - goto out_close; - } - - /* set LOOP, so data does get fed back to local sockets */ - if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_MULTICAST_LOOP failed, " - "error = %d\n", errno); - goto out_close; - } - - /* bind socket to mcast address */ - if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open : data bind failed, " - "errno = %d\n", errno); - goto out_close; - } - - /* subscribe to the multicast group */ - mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; - mreq.imr_interface.s_addr = 0; - if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - err = -errno; - printk(UM_KERN_ERR "mcast_open: IP_ADD_MEMBERSHIP failed, " - "error = %d\n", errno); - printk(UM_KERN_ERR "There appears not to be a multicast-" - "capable network interface on the host.\n"); - printk(UM_KERN_ERR "eth0 should be configured in order to use " - "the multicast transport.\n"); - goto out_close; - } - - return fd; - - out_close: - close(fd); - out: - return err; -} - -static void mcast_close(int fd, void *data) -{ - struct ip_mreq mreq; - struct mcast_data *pri = data; - struct sockaddr_in *sin = pri->mcast_addr; - - mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr; - mreq.imr_interface.s_addr = 0; - if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, - &mreq, sizeof(mreq)) < 0) { - printk(UM_KERN_ERR "mcast_open: IP_DROP_MEMBERSHIP failed, " - "error = %d\n", errno); - } - - close(fd); -} - -int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) -{ - struct sockaddr_in *data_addr = pri->mcast_addr; - - return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); -} - -const struct net_user_info mcast_user_info = { - .init = mcast_user_init, - .open = mcast_open, - .close = mcast_close, - .remove = mcast_remove, - .add_address = NULL, - .delete_address = NULL, - .mtu = ETH_MAX_PACKET, - .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, -}; diff --git a/arch/um/include/shared/mconsole.h b/arch/um/drivers/mconsole.h index c139ae1d682..8b22535c62c 100644 --- a/arch/um/include/shared/mconsole.h +++ b/arch/um/drivers/mconsole.h @@ -12,7 +12,7 @@ #define u32 uint32_t #endif -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> #define MCONSOLE_MAGIC (0xcafebabe) #define MCONSOLE_MAX_DATA (512) diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c index c70e047eed7..29880c9b324 100644 --- a/arch/um/drivers/mconsole_kern.c +++ b/arch/um/drivers/mconsole_kern.c @@ -21,15 +21,19 @@ #include <linux/un.h> #include <linux/workqueue.h> #include <linux/mutex.h> +#include <linux/fs.h> +#include <linux/mount.h> +#include <linux/file.h> #include <asm/uaccess.h> +#include <asm/switch_to.h> -#include "init.h" -#include "irq_kern.h" -#include "irq_user.h" -#include "kern_util.h" +#include <init.h> +#include <irq_kern.h> +#include <irq_user.h> +#include <kern_util.h> #include "mconsole.h" #include "mconsole_kern.h" -#include "os.h" +#include <os.h> static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) @@ -117,90 +121,38 @@ void mconsole_log(struct mc_request *req) mconsole_reply(req, "", 0, 0); } -/* This is a more convoluted version of mconsole_proc, which has some stability - * problems; however, we need it fixed, because it is expected that UML users - * mount HPPFS instead of procfs on /proc. And we want mconsole_proc to still - * show the real procfs content, not the ones from hppfs.*/ -#if 0 void mconsole_proc(struct mc_request *req) { - struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; - struct file *file; - int n; - char *ptr = req->request.data, *buf; - mm_segment_t old_fs = get_fs(); - - ptr += strlen("proc"); - ptr = skip_spaces(ptr); - - file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); - if (IS_ERR(file)) { - mconsole_reply(req, "Failed to open file", 1, 0); - goto out; - } - - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (buf == NULL) { - mconsole_reply(req, "Failed to allocate buffer", 1, 0); - goto out_fput; - } - - if (file->f_op->read) { - do { - loff_t pos; - set_fs(KERNEL_DS); - n = vfs_read(file, buf, PAGE_SIZE - 1, &pos); - file_pos_write(file, pos); - set_fs(old_fs); - if (n >= 0) { - buf[n] = '\0'; - mconsole_reply(req, buf, 0, (n > 0)); - } - else { - mconsole_reply(req, "Read of file failed", - 1, 0); - goto out_free; - } - } while (n > 0); - } - else mconsole_reply(req, "", 0, 0); - - out_free: - kfree(buf); - out_fput: - fput(file); - out: ; -} -#endif - -void mconsole_proc(struct mc_request *req) -{ - char path[64]; + struct vfsmount *mnt = task_active_pid_ns(current)->proc_mnt; char *buf; int len; - int fd; + struct file *file; int first_chunk = 1; char *ptr = req->request.data; ptr += strlen("proc"); ptr = skip_spaces(ptr); - snprintf(path, sizeof(path), "/proc/%s", ptr); - fd = sys_open(path, 0, 0); - if (fd < 0) { + file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY); + if (IS_ERR(file)) { mconsole_reply(req, "Failed to open file", 1, 0); - printk(KERN_ERR "open %s: %d\n",path,fd); + printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file)); goto out; } buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (buf == NULL) { mconsole_reply(req, "Failed to allocate buffer", 1, 0); - goto out_close; + goto out_fput; } - for (;;) { - len = sys_read(fd, buf, PAGE_SIZE-1); + do { + loff_t pos = file->f_pos; + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + len = vfs_read(file, buf, PAGE_SIZE - 1, &pos); + set_fs(old_fs); + file->f_pos = pos; if (len < 0) { mconsole_reply(req, "Read of file failed", 1, 0); goto out_free; @@ -210,22 +162,14 @@ void mconsole_proc(struct mc_request *req) mconsole_reply(req, "\n", 0, 1); first_chunk = 0; } - if (len == PAGE_SIZE-1) { - buf[len] = '\0'; - mconsole_reply(req, buf, 0, 1); - } else { - buf[len] = '\0'; - mconsole_reply(req, buf, 0, 0); - break; - } - } - + buf[len] = '\0'; + mconsole_reply(req, buf, 0, (len > 0)); + } while (len > 0); out_free: kfree(buf); - out_close: - sys_close(fd); - out: - /* nothing */; + out_fput: + fput(file); + out: ; } #define UML_MCONSOLE_HELPTEXT \ @@ -701,10 +645,9 @@ void mconsole_sysrq(struct mc_request *req) static void stack_proc(void *arg) { - struct task_struct *from = current, *to = arg; + struct task_struct *task = arg; - to->thread.saved_task = from; - switch_to(from, to, from); + show_stack(task, NULL); } /* @@ -773,8 +716,7 @@ static int __init mconsole_init(void) register_reboot_notifier(&reboot_notifier); err = um_request_irq(MCONSOLE_IRQ, sock, IRQ_READ, mconsole_interrupt, - IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "mconsole", (void *)sock); + IRQF_SHARED, "mconsole", (void *)sock); if (err) { printk(KERN_ERR "Failed to get IRQ for management console\n"); goto out; @@ -838,8 +780,7 @@ static int create_proc_mconsole(void) ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_fops); if (ent == NULL) { - printk(KERN_INFO "create_proc_mconsole : create_proc_entry " - "failed\n"); + printk(KERN_INFO "create_proc_mconsole : proc_create failed\n"); return 0; } return 0; diff --git a/arch/um/include/shared/mconsole_kern.h b/arch/um/drivers/mconsole_kern.h index d2fe07e7895..7a0c6a1ad1d 100644 --- a/arch/um/include/shared/mconsole_kern.h +++ b/arch/um/drivers/mconsole_kern.h @@ -6,7 +6,7 @@ #ifndef __MCONSOLE_KERN_H__ #define __MCONSOLE_KERN_H__ -#include "linux/list.h" +#include <linux/list.h> #include "mconsole.h" struct mconsole_entry { diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c index f8cf4c8bede..99209826adb 100644 --- a/arch/um/drivers/mconsole_user.c +++ b/arch/um/drivers/mconsole_user.c @@ -10,9 +10,7 @@ #include <sys/socket.h> #include <sys/uio.h> #include <sys/un.h> -#include "kern_constants.h" #include "mconsole.h" -#include "user.h" static struct mconsole_command commands[] = { /* diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c index 7e0619c2c2c..62145c27616 100644 --- a/arch/um/drivers/mmapper_kern.c +++ b/arch/um/drivers/mmapper_kern.c @@ -18,7 +18,7 @@ #include <linux/mm.h> #include <asm/uaccess.h> -#include "mem_user.h" +#include <mem_user.h> /* These are set in mmapper_init, which is called at boot time */ static unsigned long mmapper_size; @@ -116,7 +116,7 @@ static int __init mmapper_init(void) if (err) { printk(KERN_ERR "mmapper - misc_register failed, err = %d\n", err); - return err;; + return err; } return 0; } diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 47d0c37897d..7d26d9c0b2f 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -18,12 +18,12 @@ #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/spinlock.h> -#include "init.h" -#include "irq_kern.h" -#include "irq_user.h" +#include <init.h> +#include <irq_kern.h> +#include <irq_user.h> #include "mconsole_kern.h" -#include "net_kern.h" -#include "net_user.h" +#include <net_kern.h> +#include <net_user.h> #define DRIVER_NAME "uml-netdev" @@ -161,7 +161,7 @@ static int uml_net_open(struct net_device *dev) } err = um_request_irq(dev->irq, lp->fd, IRQ_READ, uml_net_interrupt, - IRQF_DISABLED | IRQF_SHARED, dev->name, dev); + IRQF_SHARED, dev->name, dev); if (err != 0) { printk(KERN_ERR "uml_net_open: failed to get irq(%d)\n", err); err = -ENETUNREACH; @@ -195,7 +195,7 @@ static int uml_net_close(struct net_device *dev) netif_stop_queue(dev); - free_irq(dev->irq, dev); + um_free_irq(dev->irq, dev); if (lp->close != NULL) (*lp->close)(lp->fd, &lp->user); lp->fd = -1; @@ -218,6 +218,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_lock_irqsave(&lp->lock, flags); len = (*lp->write)(lp->fd, skb, lp); + skb_tx_timestamp(skb); if (len == skb->len) { dev->stats.tx_packets++; @@ -239,7 +240,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&lp->lock, flags); - dev_kfree_skb(skb); + dev_consume_skb_any(skb); return NETDEV_TX_OK; } @@ -262,16 +263,26 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu) return 0; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void uml_net_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + uml_net_interrupt(dev->irq, dev); + enable_irq(dev->irq); +} +#endif + static void uml_net_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strcpy(info->driver, DRIVER_NAME); - strcpy(info->version, "42"); + strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver)); + strlcpy(info->version, "42", sizeof(info->version)); } static const struct ethtool_ops uml_net_ethtool_ops = { .get_drvinfo = uml_net_get_drvinfo, .get_link = ethtool_op_get_link, + .get_ts_info = ethtool_op_get_ts_info, }; static void uml_net_user_timer_expire(unsigned long _conn) @@ -284,8 +295,9 @@ static void uml_net_user_timer_expire(unsigned long _conn) #endif } -static void setup_etheraddr(char *str, unsigned char *addr, char *name) +static void setup_etheraddr(struct net_device *dev, char *str) { + unsigned char *addr = dev->dev_addr; char *end; int i; @@ -329,8 +341,8 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name) random: printk(KERN_INFO - "Choosing a random ethernet address for device %s\n", name); - random_ether_addr(addr); + "Choosing a random ethernet address for device %s\n", dev->name); + eth_hw_addr_random(dev); } static DEFINE_SPINLOCK(devices_lock); @@ -359,11 +371,14 @@ static const struct net_device_ops uml_netdev_ops = { .ndo_open = uml_net_open, .ndo_stop = uml_net_close, .ndo_start_xmit = uml_net_start_xmit, - .ndo_set_multicast_list = uml_net_set_multicast_list, + .ndo_set_rx_mode = uml_net_set_multicast_list, .ndo_tx_timeout = uml_net_tx_timeout, .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = uml_net_change_mtu, .ndo_validate_addr = eth_validate_addr, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = uml_net_poll_controller, +#endif }; /* @@ -405,9 +420,9 @@ static void eth_configure(int n, void *init, char *mac, */ snprintf(dev->name, sizeof(dev->name), "eth%d", n); - setup_etheraddr(mac, device->mac, dev->name); + setup_etheraddr(dev, mac); - printk(KERN_INFO "Netdevice %d (%pM) : ", n, device->mac); + printk(KERN_INFO "Netdevice %d (%pM) : ", n, dev->dev_addr); lp = netdev_priv(dev); /* This points to the transport private data. It's still clear, but we @@ -454,14 +469,12 @@ static void eth_configure(int n, void *init, char *mac, init_timer(&lp->tl); spin_lock_init(&lp->lock); lp->tl.function = uml_net_user_timer_expire; - memcpy(lp->mac, device->mac, sizeof(lp->mac)); + memcpy(lp->mac, dev->dev_addr, sizeof(lp->mac)); if ((transport->user->init != NULL) && ((*transport->user->init)(&lp->user, dev) != 0)) goto out_unregister; - /* don't use eth_mac_addr, it will not work here */ - memcpy(dev->dev_addr, device->mac, ETH_ALEN); dev->mtu = transport->user->mtu; dev->netdev_ops = ¨_netdev_ops; dev->ethtool_ops = ¨_net_ethtool_ops; @@ -818,7 +831,7 @@ static void close_devices(void) spin_lock(&opened_lock); list_for_each(ele, &opened) { lp = list_entry(ele, struct uml_net_private, list); - free_irq(lp->dev->irq, lp->dev); + um_free_irq(lp->dev->irq, lp->dev); if ((lp->close != NULL) && (lp->fd >= 0)) (*lp->close)(lp->fd, &lp->user); if (lp->remove != NULL) diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index 9415dd9e63e..cd14157b556 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -11,11 +11,9 @@ #include <string.h> #include <sys/socket.h> #include <sys/wait.h> -#include "net_user.h" -#include "kern_constants.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <net_user.h> +#include <os.h> +#include <um_malloc.h> int tap_open_common(void *dev, char *gate_addr) { @@ -228,7 +226,10 @@ static void change(char *dev, char *what, unsigned char *addr, "buffer\n"); pid = change_tramp(argv, output, output_len); - if (pid < 0) return; + if (pid < 0) { + kfree(output); + return; + } if (output != NULL) { printk("%s", output); diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c index 2b45a1446c8..10495747ce8 100644 --- a/arch/um/drivers/null.c +++ b/arch/um/drivers/null.c @@ -7,7 +7,7 @@ #include <errno.h> #include <fcntl.h> #include "chan_user.h" -#include "os.h" +#include <os.h> /* This address is used only as a unique identifier */ static int null_chan; diff --git a/arch/um/drivers/pcap_kern.c b/arch/um/drivers/pcap_kern.c index 2860525f8ff..be0fb57bd1d 100644 --- a/arch/um/drivers/pcap_kern.c +++ b/arch/um/drivers/pcap_kern.c @@ -3,9 +3,9 @@ * Licensed under the GPL. */ -#include "linux/init.h" +#include <linux/init.h> #include <linux/netdevice.h> -#include "net_kern.h" +#include <net_kern.h> #include "pcap_user.h" struct pcap_init { diff --git a/arch/um/drivers/pcap_user.c b/arch/um/drivers/pcap_user.c index 5f903587d69..c07b9c752c8 100644 --- a/arch/um/drivers/pcap_user.c +++ b/arch/um/drivers/pcap_user.c @@ -7,11 +7,9 @@ #include <pcap.h> #include <string.h> #include <asm/types.h> -#include "net_user.h" +#include <net_user.h> #include "pcap_user.h" -#include "kern_constants.h" -#include "um_malloc.h" -#include "user.h" +#include <um_malloc.h> #define PCAP_FD(p) (*(int *)(p)) diff --git a/arch/um/drivers/pcap_user.h b/arch/um/drivers/pcap_user.h index d8ba6153f91..1ca7c764cc6 100644 --- a/arch/um/drivers/pcap_user.h +++ b/arch/um/drivers/pcap_user.h @@ -3,7 +3,7 @@ * Licensed under the GPL */ -#include "net_user.h" +#include <net_user.h> struct pcap_data { char *host_if; diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c index a11573be096..40ca5cc275e 100644 --- a/arch/um/drivers/port_kern.c +++ b/arch/um/drivers/port_kern.c @@ -3,16 +3,16 @@ * Licensed under the GPL */ -#include "linux/completion.h" -#include "linux/interrupt.h" -#include "linux/list.h" -#include "linux/mutex.h" -#include "linux/slab.h" -#include "linux/workqueue.h" -#include "asm/atomic.h" -#include "init.h" -#include "irq_kern.h" -#include "os.h" +#include <linux/completion.h> +#include <linux/interrupt.h> +#include <linux/list.h> +#include <linux/mutex.h> +#include <linux/slab.h> +#include <linux/workqueue.h> +#include <asm/atomic.h> +#include <init.h> +#include <irq_kern.h> +#include <os.h> #include "port.h" struct port_list { @@ -100,8 +100,7 @@ static int port_accept(struct port_list *port) .port = port }); if (um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt, - IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "telnetd", conn)) { + IRQF_SHARED, "telnetd", conn)) { printk(KERN_ERR "port_accept : failed to get IRQ for " "telnetd\n"); goto out_free; @@ -184,8 +183,7 @@ void *port_data(int port_num) } if (um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt, - IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "port", port)) { + IRQF_SHARED, "port", port)) { printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num); goto out_close; } @@ -254,7 +252,7 @@ int port_wait(void *data) * connection. Then we loop here throwing out failed * connections until a good one is found. */ - free_irq(TELNETD_IRQ, conn); + um_free_irq(TELNETD_IRQ, conn); if (conn->fd >= 0) break; diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index b49bf56a56a..9a8e1b64c22 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -10,11 +10,9 @@ #include <unistd.h> #include <netinet/in.h> #include "chan_user.h" -#include "kern_constants.h" -#include "os.h" +#include <os.h> #include "port.h" -#include "um_malloc.h" -#include "user.h" +#include <um_malloc.h> struct port_chan { int raw; diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 1113911dcb2..f1fcc2cedb5 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -12,10 +12,8 @@ #include <termios.h> #include <sys/stat.h> #include "chan_user.h" -#include "kern_constants.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <os.h> +#include <um_malloc.h> struct pty_chan { void (*announce)(char *dev_name, int dev); diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 981085a93f3..9e3a7220582 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -13,8 +13,8 @@ #include <linux/miscdevice.h> #include <linux/delay.h> #include <asm/uaccess.h> -#include "irq_kern.h" -#include "os.h" +#include <irq_kern.h> +#include <os.h> /* * core module and version information @@ -131,8 +131,7 @@ static int __init rng_init (void) random_fd = err; err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, - IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random", - NULL); + 0, "random", NULL); if (err) goto err_out_cleanup_hw; diff --git a/arch/um/drivers/slip_common.c b/arch/um/drivers/slip_common.c index e89cfc68fc3..f597fa7c91d 100644 --- a/arch/um/drivers/slip_common.c +++ b/arch/um/drivers/slip_common.c @@ -1,6 +1,6 @@ #include <string.h> #include "slip_common.h" -#include "net_user.h" +#include <net_user.h> int slip_proto_read(int fd, void *buf, int len, struct slip_proto *slip) { diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index dd2aadc14af..ed5249fc057 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c @@ -6,7 +6,7 @@ #include <linux/if_arp.h> #include <linux/init.h> #include <linux/netdevice.h> -#include "net_kern.h" +#include <net_kern.h> #include "slip.h" struct slip_init { diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index a1c2d2c98a9..55c290d925f 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -11,12 +11,10 @@ #include <string.h> #include <sys/termios.h> #include <sys/wait.h> -#include "kern_constants.h" -#include "net_user.h" -#include "os.h" +#include <net_user.h> +#include <os.h> #include "slip.h" -#include "um_malloc.h" -#include "user.h" +#include <um_malloc.h> static int slip_user_init(void *data, void *dev) { @@ -102,7 +100,7 @@ static int slip_tramp(char **argv, int fd) "buffer\n"); os_kill_process(pid, 1); err = -ENOMEM; - goto out_free; + goto out_close; } close(fds[1]); @@ -112,7 +110,6 @@ static int slip_tramp(char **argv, int fd) err = helper_wait(pid); close(fds[0]); -out_free: kfree(output); return err; diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index e376284f0fb..4ef11ca7cac 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c @@ -4,11 +4,11 @@ */ #include <linux/if_arp.h> -#include "linux/init.h" +#include <linux/init.h> #include <linux/netdevice.h> #include <linux/string.h> -#include "net_kern.h" -#include "net_user.h" +#include <net_kern.h> +#include <net_user.h> #include "slirp.h" struct slirp_init { diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index a0ada8fec72..c999d187abb 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c @@ -7,11 +7,9 @@ #include <errno.h> #include <string.h> #include <sys/wait.h> -#include "kern_constants.h" -#include "net_user.h" -#include "os.h" +#include <net_user.h> +#include <os.h> #include "slirp.h" -#include "user.h" static int slirp_user_init(void *data, void *dev) { diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c index f1786e64607..b8d14fa5205 100644 --- a/arch/um/drivers/ssl.c +++ b/arch/um/drivers/ssl.c @@ -3,31 +3,23 @@ * Licensed under the GPL */ -#include "linux/fs.h" -#include "linux/tty.h" -#include "linux/tty_driver.h" -#include "linux/major.h" -#include "linux/mm.h" -#include "linux/init.h" -#include "linux/console.h" -#include "asm/termbits.h" -#include "asm/irq.h" -#include "line.h" +#include <linux/fs.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/major.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/console.h> +#include <asm/termbits.h> +#include <asm/irq.h> #include "ssl.h" -#include "chan_kern.h" -#include "kern.h" -#include "init.h" -#include "irq_user.h" +#include "chan.h" +#include <init.h> +#include <irq_user.h> #include "mconsole_kern.h" static const int ssl_version = 1; -/* Referenced only by tty_driver below - presumably it's locked correctly - * by the tty driver. - */ - -static struct tty_driver *ssl_driver; - #define NR_PORTS 64 static void ssl_announce(char *dev_name, int dev) @@ -73,8 +65,9 @@ static struct line_driver driver = { /* The array is initialized by line_init, at initcall time. The * elements are locked individually as needed. */ -static struct line serial_lines[NR_PORTS] = - { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) }; +static char *conf[NR_PORTS]; +static char *def_conf = CONFIG_SSL_CHAN; +static struct line serial_lines[NR_PORTS]; static int ssl_config(char *str, char **error_out) { @@ -94,40 +87,13 @@ static int ssl_remove(int n, char **error_out) error_out); } -static int ssl_open(struct tty_struct *tty, struct file *filp) -{ - int err = line_open(serial_lines, tty); - - if (err) - printk(KERN_ERR "Failed to open serial line %d, err = %d\n", - tty->index, err); - - return err; -} - -#if 0 -static void ssl_flush_buffer(struct tty_struct *tty) -{ - return; -} - -static void ssl_stop(struct tty_struct *tty) -{ - printk(KERN_ERR "Someone should implement ssl_stop\n"); -} - -static void ssl_start(struct tty_struct *tty) +static int ssl_install(struct tty_driver *driver, struct tty_struct *tty) { - printk(KERN_ERR "Someone should implement ssl_start\n"); + return line_install(driver, tty, &serial_lines[tty->index]); } -void ssl_hangup(struct tty_struct *tty) -{ -} -#endif - static const struct tty_operations ssl_ops = { - .open = ssl_open, + .open = line_open, .close = line_close, .write = line_write, .put_char = line_put_char, @@ -136,14 +102,10 @@ static const struct tty_operations ssl_ops = { .flush_buffer = line_flush_buffer, .flush_chars = line_flush_chars, .set_termios = line_set_termios, - .ioctl = line_ioctl, .throttle = line_throttle, .unthrottle = line_unthrottle, -#if 0 - .stop = ssl_stop, - .start = ssl_start, - .hangup = ssl_hangup, -#endif + .install = ssl_install, + .hangup = line_hangup, }; /* Changed by ssl_init and referenced by ssl_exit, which are both serialized @@ -158,14 +120,14 @@ static void ssl_console_write(struct console *c, const char *string, unsigned long flags; spin_lock_irqsave(&line->lock, flags); - console_write_chan(&line->chan_list, string, len); + console_write_chan(line->chan_out, string, len); spin_unlock_irqrestore(&line->lock, flags); } static struct tty_driver *ssl_console_device(struct console *c, int *index) { *index = c->index; - return ssl_driver; + return driver.driver; } static int ssl_console_setup(struct console *co, char *options) @@ -188,17 +150,30 @@ static struct console ssl_cons = { static int ssl_init(void) { char *new_title; + int err; + int i; printk(KERN_INFO "Initializing software serial port version %d\n", ssl_version); - ssl_driver = register_lines(&driver, &ssl_ops, serial_lines, + + err = register_lines(&driver, &ssl_ops, serial_lines, ARRAY_SIZE(serial_lines)); + if (err) + return err; new_title = add_xterm_umid(opts.xterm_title); if (new_title != NULL) opts.xterm_title = new_title; - lines_init(serial_lines, ARRAY_SIZE(serial_lines), &opts); + for (i = 0; i < NR_PORTS; i++) { + char *error; + char *s = conf[i]; + if (!s) + s = def_conf; + if (setup_one_line(serial_lines, i, s, &opts, &error)) + printk(KERN_ERR "setup_one_line failed for " + "device %d : %s\n", i, error); + } ssl_init_done = 1; register_console(&ssl_cons); @@ -216,14 +191,7 @@ __uml_exitcall(ssl_exit); static int ssl_chan_setup(char *str) { - char *error; - int ret; - - ret = line_setup(serial_lines, ARRAY_SIZE(serial_lines), str, &error); - if(ret < 0) - printk(KERN_ERR "Failed to set up serial line with " - "configuration string \"%s\" : %s\n", str, error); - + line_setup(conf, NR_PORTS, &def_conf, str, "serial line"); return 1; } diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c index 49266f6108c..7b361f36ca9 100644 --- a/arch/um/drivers/stdio_console.c +++ b/arch/um/drivers/stdio_console.c @@ -3,37 +3,30 @@ * Licensed under the GPL */ -#include "linux/posix_types.h" -#include "linux/tty.h" -#include "linux/tty_flip.h" -#include "linux/types.h" -#include "linux/major.h" -#include "linux/kdev_t.h" -#include "linux/console.h" -#include "linux/string.h" -#include "linux/sched.h" -#include "linux/list.h" -#include "linux/init.h" -#include "linux/interrupt.h" -#include "linux/slab.h" -#include "linux/hardirq.h" -#include "asm/current.h" -#include "asm/irq.h" +#include <linux/posix_types.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/types.h> +#include <linux/major.h> +#include <linux/kdev_t.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/sched.h> +#include <linux/list.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/slab.h> +#include <linux/hardirq.h> +#include <asm/current.h> +#include <asm/irq.h> #include "stdio_console.h" -#include "line.h" -#include "chan_kern.h" -#include "irq_user.h" +#include "chan.h" +#include <irq_user.h> #include "mconsole_kern.h" -#include "init.h" +#include <init.h> #define MAX_TTYS (16) -/* Referenced only by tty_driver below - presumably it's locked correctly - * by the tty driver. - */ - -static struct tty_driver *console_driver; - static void stdio_announce(char *dev_name, int dev) { printk(KERN_INFO "Virtual console %d assigned device '%s'\n", dev, @@ -77,9 +70,9 @@ static struct line_driver driver = { /* The array is initialized by line_init, at initcall time. The * elements are locked individually as needed. */ -static struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver), - [ 1 ... MAX_TTYS - 1 ] = - LINE_INIT(CONFIG_CON_CHAN, &driver) }; +static char *vt_conf[MAX_TTYS]; +static char *def_conf; +static struct line vts[MAX_TTYS]; static int con_config(char *str, char **error_out) { @@ -96,21 +89,17 @@ static int con_remove(int n, char **error_out) return line_remove(vts, ARRAY_SIZE(vts), n, error_out); } -static int con_open(struct tty_struct *tty, struct file *filp) -{ - int err = line_open(vts, tty); - if (err) - printk(KERN_ERR "Failed to open console %d, err = %d\n", - tty->index, err); - - return err; -} - /* Set in an initcall, checked in an exitcall */ static int con_init_done = 0; +static int con_install(struct tty_driver *driver, struct tty_struct *tty) +{ + return line_install(driver, tty, &vts[tty->index]); +} + static const struct tty_operations console_ops = { - .open = con_open, + .open = line_open, + .install = con_install, .close = line_close, .write = line_write, .put_char = line_put_char, @@ -119,9 +108,9 @@ static const struct tty_operations console_ops = { .flush_buffer = line_flush_buffer, .flush_chars = line_flush_chars, .set_termios = line_set_termios, - .ioctl = line_ioctl, .throttle = line_throttle, .unthrottle = line_unthrottle, + .hangup = line_hangup, }; static void uml_console_write(struct console *console, const char *string, @@ -131,14 +120,14 @@ static void uml_console_write(struct console *console, const char *string, unsigned long flags; spin_lock_irqsave(&line->lock, flags); - console_write_chan(&line->chan_list, string, len); + console_write_chan(line->chan_out, string, len); spin_unlock_irqrestore(&line->lock, flags); } static struct tty_driver *uml_console_device(struct console *c, int *index) { *index = c->index; - return console_driver; + return driver.driver; } static int uml_console_setup(struct console *co, char *options) @@ -161,18 +150,31 @@ static struct console stdiocons = { static int stdio_init(void) { char *new_title; + int err; + int i; - console_driver = register_lines(&driver, &console_ops, vts, + err = register_lines(&driver, &console_ops, vts, ARRAY_SIZE(vts)); - if (console_driver == NULL) - return -1; + if (err) + return err; + printk(KERN_INFO "Initialized stdio console driver\n"); new_title = add_xterm_umid(opts.xterm_title); if(new_title != NULL) opts.xterm_title = new_title; - lines_init(vts, ARRAY_SIZE(vts), &opts); + for (i = 0; i < MAX_TTYS; i++) { + char *error; + char *s = vt_conf[i]; + if (!s) + s = def_conf; + if (!s) + s = i ? CONFIG_CON_CHAN : CONFIG_CON_ZERO_CHAN; + if (setup_one_line(vts, i, s, &opts, &error)) + printk(KERN_ERR "setup_one_line failed for " + "device %d : %s\n", i, error); + } con_init_done = 1; register_console(&stdiocons); @@ -190,14 +192,7 @@ __uml_exitcall(console_exit); static int console_chan_setup(char *str) { - char *error; - int ret; - - ret = line_setup(vts, ARRAY_SIZE(vts), str, &error); - if(ret < 0) - printk(KERN_ERR "Failed to set up console with " - "configuration string \"%s\" : %s\n", str, error); - + line_setup(vt_conf, MAX_TTYS, &def_conf, str, "console"); return 1; } __setup("con", console_chan_setup); diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index 495858a090e..eaa201bca5e 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -7,10 +7,8 @@ #include <fcntl.h> #include <termios.h> #include "chan_user.h" -#include "kern_constants.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <os.h> +#include <um_malloc.h> struct tty_chan { char *dev; diff --git a/arch/um/include/shared/ubd_user.h b/arch/um/drivers/ubd.h index 3845051f1b1..3b48cd2081e 100644 --- a/arch/um/include/shared/ubd_user.h +++ b/arch/um/drivers/ubd.h @@ -7,7 +7,6 @@ #ifndef __UM_UBD_USER_H #define __UM_UBD_USER_H -extern void ignore_sigwinch_sig(void); extern int start_io_thread(unsigned long sp, int *fds_out); extern int io_thread(void *arg); extern int kernel_fd; diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 620f5b70957..3716e695255 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -19,45 +19,29 @@ #define UBD_SHIFT 4 -#include "linux/kernel.h" -#include "linux/module.h" -#include "linux/blkdev.h" -#include "linux/ata.h" -#include "linux/hdreg.h" -#include "linux/init.h" -#include "linux/cdrom.h" -#include "linux/proc_fs.h" -#include "linux/seq_file.h" -#include "linux/ctype.h" -#include "linux/capability.h" -#include "linux/mm.h" -#include "linux/slab.h" -#include "linux/vmalloc.h" -#include "linux/mutex.h" -#include "linux/blkpg.h" -#include "linux/genhd.h" -#include "linux/spinlock.h" -#include "linux/platform_device.h" -#include "linux/scatterlist.h" -#include "asm/segment.h" -#include "asm/uaccess.h" -#include "asm/irq.h" -#include "asm/types.h" -#include "asm/tlbflush.h" -#include "mem_user.h" -#include "kern_util.h" -#include "kern.h" +#include <linux/module.h> +#include <linux/init.h> +#include <linux/blkdev.h> +#include <linux/ata.h> +#include <linux/hdreg.h> +#include <linux/cdrom.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <linux/ctype.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/platform_device.h> +#include <linux/scatterlist.h> +#include <asm/tlbflush.h> +#include <kern_util.h> #include "mconsole_kern.h" -#include "init.h" -#include "irq_user.h" -#include "irq_kern.h" -#include "ubd_user.h" -#include "os.h" -#include "mem.h" -#include "mem_kern.h" +#include <init.h> +#include <irq_kern.h> +#include "ubd.h" +#include <os.h> #include "cow.h" -enum ubd_req { UBD_READ, UBD_WRITE }; +enum ubd_req { UBD_READ, UBD_WRITE, UBD_FLUSH }; struct io_thread_req { struct request *req; @@ -103,7 +87,7 @@ static DEFINE_MUTEX(ubd_lock); static DEFINE_MUTEX(ubd_mutex); /* replaces BKL, might not be needed */ static int ubd_open(struct block_device *bdev, fmode_t mode); -static int ubd_release(struct gendisk *disk, fmode_t mode); +static void ubd_release(struct gendisk *disk, fmode_t mode); static int ubd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -513,8 +497,37 @@ __uml_exitcall(kill_io_thread); static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) { char *file; + int fd; + int err; + + __u32 version; + __u32 align; + char *backing_file; + time_t mtime; + unsigned long long size; + int sector_size; + int bitmap_offset; + + if (ubd_dev->file && ubd_dev->cow.file) { + file = ubd_dev->cow.file; + + goto out; + } + + fd = os_open_file(ubd_dev->file, of_read(OPENFLAGS()), 0); + if (fd < 0) + return fd; - file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; + err = read_cow_header(file_reader, &fd, &version, &backing_file, \ + &mtime, &size, §or_size, &align, &bitmap_offset); + os_close_file(fd); + + if(err == -EINVAL) + file = ubd_dev->file; + else + file = backing_file; + +out: return os_file_size(file, size_out); } @@ -853,6 +866,7 @@ static int ubd_add(int n, char **error_out) goto out; } ubd_dev->queue->queuedata = ubd_dev; + blk_queue_flush(ubd_dev->queue, REQ_FLUSH); blk_queue_max_segments(ubd_dev->queue, MAX_SG); err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, &ubd_gendisk[n]); @@ -1088,7 +1102,7 @@ static int __init ubd_driver_init(void){ return 0; } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, - IRQF_DISABLED, "ubd", ubd_devs); + 0, "ubd", ubd_devs); if(err != 0) printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return 0; @@ -1125,7 +1139,7 @@ out: return err; } -static int ubd_release(struct gendisk *disk, fmode_t mode) +static void ubd_release(struct gendisk *disk, fmode_t mode) { struct ubd *ubd_dev = disk->private_data; @@ -1133,7 +1147,6 @@ static int ubd_release(struct gendisk *disk, fmode_t mode) if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); mutex_unlock(&ubd_mutex); - return 0; } static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, @@ -1227,11 +1240,40 @@ static void prepare_request(struct request *req, struct io_thread_req *io_req, } /* Called with dev->lock held */ +static void prepare_flush_request(struct request *req, + struct io_thread_req *io_req) +{ + struct gendisk *disk = req->rq_disk; + struct ubd *ubd_dev = disk->private_data; + + io_req->req = req; + io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : + ubd_dev->fd; + io_req->op = UBD_FLUSH; +} + +static bool submit_request(struct io_thread_req *io_req, struct ubd *dev) +{ + int n = os_write_file(thread_fd, &io_req, + sizeof(io_req)); + if (n != sizeof(io_req)) { + if (n != -EAGAIN) + printk("write to io thread failed, " + "errno = %d\n", -n); + else if (list_empty(&dev->restart)) + list_add(&dev->restart, &restart); + + kfree(io_req); + return false; + } + return true; +} + +/* Called with dev->lock held */ static void do_ubd_request(struct request_queue *q) { struct io_thread_req *io_req; struct request *req; - int n; while(1){ struct ubd *dev = q->queuedata; @@ -1247,6 +1289,19 @@ static void do_ubd_request(struct request_queue *q) } req = dev->request; + + if (req->cmd_flags & REQ_FLUSH) { + io_req = kmalloc(sizeof(struct io_thread_req), + GFP_ATOMIC); + if (io_req == NULL) { + if (list_empty(&dev->restart)) + list_add(&dev->restart, &restart); + return; + } + prepare_flush_request(req, io_req); + submit_request(io_req, dev); + } + while(dev->start_sg < dev->end_sg){ struct scatterlist *sg = &dev->sg[dev->start_sg]; @@ -1261,17 +1316,8 @@ static void do_ubd_request(struct request_queue *q) (unsigned long long)dev->rq_pos << 9, sg->offset, sg->length, sg_page(sg)); - n = os_write_file(thread_fd, &io_req, - sizeof(struct io_thread_req *)); - if(n != sizeof(struct io_thread_req *)){ - if(n != -EAGAIN) - printk("write to io thread failed, " - "errno = %d\n", -n); - else if(list_empty(&dev->restart)) - list_add(&dev->restart, &restart); - kfree(io_req); + if (submit_request(io_req, dev) == false) return; - } dev->rq_pos += sg->length >> 9; dev->start_sg++; @@ -1355,6 +1401,17 @@ static void do_io(struct io_thread_req *req) int err; __u64 off; + if (req->op == UBD_FLUSH) { + /* fds[0] is always either the rw image or our cow file */ + n = os_sync_file(req->fds[0]); + if (n != 0) { + printk("do_io - sync failed err = %d " + "fd = %d\n", -n, req->fds[0]); + req->error = 1; + } + return; + } + nsectors = req->length / req->sectorsize; start = 0; do { @@ -1419,7 +1476,8 @@ int io_thread(void *arg) struct io_thread_req *req; int n; - ignore_sigwinch_sig(); + os_fix_helper_signals(); + while(1){ n = os_read_file(kernel_fd, &req, sizeof(struct io_thread_req *)); diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c index b591bb9c41d..e376f9b9c68 100644 --- a/arch/um/drivers/ubd_user.c +++ b/arch/um/drivers/ubd_user.c @@ -15,19 +15,11 @@ #include <sys/socket.h> #include <sys/mman.h> #include <sys/param.h> -#include "asm/types.h" -#include "user.h" -#include "ubd_user.h" -#include "os.h" -#include "cow.h" - #include <endian.h> #include <byteswap.h> -void ignore_sigwinch_sig(void) -{ - signal(SIGWINCH, SIG_IGN); -} +#include "ubd.h" +#include <os.h> int start_io_thread(unsigned long sp, int *fd_out) { diff --git a/arch/um/drivers/umcast.h b/arch/um/drivers/umcast.h new file mode 100644 index 00000000000..c190c644091 --- /dev/null +++ b/arch/um/drivers/umcast.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + +#ifndef __DRIVERS_UMCAST_H +#define __DRIVERS_UMCAST_H + +#include <net_user.h> + +struct umcast_data { + char *addr; + unsigned short lport; + unsigned short rport; + void *listen_addr; + void *remote_addr; + int ttl; + int unicast; + void *dev; +}; + +extern const struct net_user_info umcast_user_info; + +extern int umcast_user_write(int fd, void *buf, int len, + struct umcast_data *pri); + +#endif diff --git a/arch/um/drivers/umcast_kern.c b/arch/um/drivers/umcast_kern.c new file mode 100644 index 00000000000..f5ba6e37791 --- /dev/null +++ b/arch/um/drivers/umcast_kern.c @@ -0,0 +1,188 @@ +/* + * user-mode-linux networking multicast transport + * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * + * based on the existing uml-networking code, which is + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 by various other people who didn't put their name here. + * + * Licensed under the GPL. + */ + +#include <linux/init.h> +#include <linux/netdevice.h> +#include "umcast.h" +#include <net_kern.h> + +struct umcast_init { + char *addr; + int lport; + int rport; + int ttl; + bool unicast; +}; + +static void umcast_init(struct net_device *dev, void *data) +{ + struct uml_net_private *pri; + struct umcast_data *dpri; + struct umcast_init *init = data; + + pri = netdev_priv(dev); + dpri = (struct umcast_data *) pri->user; + dpri->addr = init->addr; + dpri->lport = init->lport; + dpri->rport = init->rport; + dpri->unicast = init->unicast; + dpri->ttl = init->ttl; + dpri->dev = dev; + + if (dpri->unicast) { + printk(KERN_INFO "ucast backend address: %s:%u listen port: " + "%u\n", dpri->addr, dpri->rport, dpri->lport); + } else { + printk(KERN_INFO "mcast backend multicast address: %s:%u, " + "TTL:%u\n", dpri->addr, dpri->lport, dpri->ttl); + } +} + +static int umcast_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + return net_recvfrom(fd, skb_mac_header(skb), + skb->dev->mtu + ETH_HEADER_OTHER); +} + +static int umcast_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +{ + return umcast_user_write(fd, skb->data, skb->len, + (struct umcast_data *) &lp->user); +} + +static const struct net_kern_info umcast_kern_info = { + .init = umcast_init, + .protocol = eth_protocol, + .read = umcast_read, + .write = umcast_write, +}; + +static int mcast_setup(char *str, char **mac_out, void *data) +{ + struct umcast_init *init = data; + char *port_str = NULL, *ttl_str = NULL, *remain; + char *last; + + *init = ((struct umcast_init) + { .addr = "239.192.168.1", + .lport = 1102, + .ttl = 1 }); + + remain = split_if_spec(str, mac_out, &init->addr, &port_str, &ttl_str, + NULL); + if (remain != NULL) { + printk(KERN_ERR "mcast_setup - Extra garbage on " + "specification : '%s'\n", remain); + return 0; + } + + if (port_str != NULL) { + init->lport = simple_strtoul(port_str, &last, 10); + if ((*last != '\0') || (last == port_str)) { + printk(KERN_ERR "mcast_setup - Bad port : '%s'\n", + port_str); + return 0; + } + } + + if (ttl_str != NULL) { + init->ttl = simple_strtoul(ttl_str, &last, 10); + if ((*last != '\0') || (last == ttl_str)) { + printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n", + ttl_str); + return 0; + } + } + + init->unicast = false; + init->rport = init->lport; + + printk(KERN_INFO "Configured mcast device: %s:%u-%u\n", init->addr, + init->lport, init->ttl); + + return 1; +} + +static int ucast_setup(char *str, char **mac_out, void *data) +{ + struct umcast_init *init = data; + char *lport_str = NULL, *rport_str = NULL, *remain; + char *last; + + *init = ((struct umcast_init) + { .addr = "", + .lport = 1102, + .rport = 1102 }); + + remain = split_if_spec(str, mac_out, &init->addr, + &lport_str, &rport_str, NULL); + if (remain != NULL) { + printk(KERN_ERR "ucast_setup - Extra garbage on " + "specification : '%s'\n", remain); + return 0; + } + + if (lport_str != NULL) { + init->lport = simple_strtoul(lport_str, &last, 10); + if ((*last != '\0') || (last == lport_str)) { + printk(KERN_ERR "ucast_setup - Bad listen port : " + "'%s'\n", lport_str); + return 0; + } + } + + if (rport_str != NULL) { + init->rport = simple_strtoul(rport_str, &last, 10); + if ((*last != '\0') || (last == rport_str)) { + printk(KERN_ERR "ucast_setup - Bad remote port : " + "'%s'\n", rport_str); + return 0; + } + } + + init->unicast = true; + + printk(KERN_INFO "Configured ucast device: :%u -> %s:%u\n", + init->lport, init->addr, init->rport); + + return 1; +} + +static struct transport mcast_transport = { + .list = LIST_HEAD_INIT(mcast_transport.list), + .name = "mcast", + .setup = mcast_setup, + .user = &umcast_user_info, + .kern = &umcast_kern_info, + .private_size = sizeof(struct umcast_data), + .setup_size = sizeof(struct umcast_init), +}; + +static struct transport ucast_transport = { + .list = LIST_HEAD_INIT(ucast_transport.list), + .name = "ucast", + .setup = ucast_setup, + .user = &umcast_user_info, + .kern = &umcast_kern_info, + .private_size = sizeof(struct umcast_data), + .setup_size = sizeof(struct umcast_init), +}; + +static int register_umcast(void) +{ + register_transport(&mcast_transport); + register_transport(&ucast_transport); + return 0; +} + +late_initcall(register_umcast); diff --git a/arch/um/drivers/umcast_user.c b/arch/um/drivers/umcast_user.c new file mode 100644 index 00000000000..6074184bb51 --- /dev/null +++ b/arch/um/drivers/umcast_user.c @@ -0,0 +1,184 @@ +/* + * user-mode-linux networking multicast transport + * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2001 by Harald Welte <laforge@gnumonks.org> + * + * based on the existing uml-networking code, which is + * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and + * James Leu (jleu@mindspring.net). + * Copyright (C) 2001 by various other people who didn't put their name here. + * + * Licensed under the GPL. + * + */ + +#include <unistd.h> +#include <errno.h> +#include <netinet/in.h> +#include "umcast.h" +#include <net_user.h> +#include <um_malloc.h> + +static struct sockaddr_in *new_addr(char *addr, unsigned short port) +{ + struct sockaddr_in *sin; + + sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); + if (sin == NULL) { + printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " + "failed\n"); + return NULL; + } + sin->sin_family = AF_INET; + if (addr) + sin->sin_addr.s_addr = in_aton(addr); + else + sin->sin_addr.s_addr = INADDR_ANY; + sin->sin_port = htons(port); + return sin; +} + +static int umcast_user_init(void *data, void *dev) +{ + struct umcast_data *pri = data; + + pri->remote_addr = new_addr(pri->addr, pri->rport); + if (pri->unicast) + pri->listen_addr = new_addr(NULL, pri->lport); + else + pri->listen_addr = pri->remote_addr; + pri->dev = dev; + return 0; +} + +static void umcast_remove(void *data) +{ + struct umcast_data *pri = data; + + kfree(pri->listen_addr); + if (pri->unicast) + kfree(pri->remote_addr); + pri->listen_addr = pri->remote_addr = NULL; +} + +static int umcast_open(void *data) +{ + struct umcast_data *pri = data; + struct sockaddr_in *lsin = pri->listen_addr; + struct sockaddr_in *rsin = pri->remote_addr; + struct ip_mreq mreq; + int fd, yes = 1, err = -EINVAL; + + + if ((!pri->unicast && lsin->sin_addr.s_addr == 0) || + (rsin->sin_addr.s_addr == 0) || + (lsin->sin_port == 0) || (rsin->sin_port == 0)) + goto out; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + + if (fd < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open : data socket failed, " + "errno = %d\n", errno); + goto out; + } + + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: SO_REUSEADDR failed, " + "errno = %d\n", errno); + goto out_close; + } + + if (!pri->unicast) { + /* set ttl according to config */ + if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, + sizeof(pri->ttl)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_TTL " + "failed, error = %d\n", errno); + goto out_close; + } + + /* set LOOP, so data does get fed back to local sockets */ + if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, + &yes, sizeof(yes)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: IP_MULTICAST_LOOP " + "failed, error = %d\n", errno); + goto out_close; + } + } + + /* bind socket to the address */ + if (bind(fd, (struct sockaddr *) lsin, sizeof(*lsin)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open : data bind failed, " + "errno = %d\n", errno); + goto out_close; + } + + if (!pri->unicast) { + /* subscribe to the multicast group */ + mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; + mreq.imr_interface.s_addr = 0; + if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) { + err = -errno; + printk(UM_KERN_ERR "umcast_open: IP_ADD_MEMBERSHIP " + "failed, error = %d\n", errno); + printk(UM_KERN_ERR "There appears not to be a " + "multicast-capable network interface on the " + "host.\n"); + printk(UM_KERN_ERR "eth0 should be configured in order " + "to use the multicast transport.\n"); + goto out_close; + } + } + + return fd; + + out_close: + close(fd); + out: + return err; +} + +static void umcast_close(int fd, void *data) +{ + struct umcast_data *pri = data; + + if (!pri->unicast) { + struct ip_mreq mreq; + struct sockaddr_in *lsin = pri->listen_addr; + + mreq.imr_multiaddr.s_addr = lsin->sin_addr.s_addr; + mreq.imr_interface.s_addr = 0; + if (setsockopt(fd, SOL_IP, IP_DROP_MEMBERSHIP, + &mreq, sizeof(mreq)) < 0) { + printk(UM_KERN_ERR "umcast_close: IP_DROP_MEMBERSHIP " + "failed, error = %d\n", errno); + } + } + + close(fd); +} + +int umcast_user_write(int fd, void *buf, int len, struct umcast_data *pri) +{ + struct sockaddr_in *data_addr = pri->remote_addr; + + return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); +} + +const struct net_user_info umcast_user_info = { + .init = umcast_user_init, + .open = umcast_open, + .close = umcast_close, + .remove = umcast_remove, + .add_address = NULL, + .delete_address = NULL, + .mtu = ETH_MAX_PACKET, + .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, +}; diff --git a/arch/um/drivers/vde_kern.c b/arch/um/drivers/vde_kern.c index 1b852bffdeb..6a365fadc7c 100644 --- a/arch/um/drivers/vde_kern.c +++ b/arch/um/drivers/vde_kern.c @@ -7,10 +7,10 @@ * */ -#include "linux/init.h" +#include <linux/init.h> #include <linux/netdevice.h> -#include "net_kern.h" -#include "net_user.h" +#include <net_kern.h> +#include <net_user.h> #include "vde.h" static void vde_init(struct net_device *dev, void *data) diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c index c5c43253e6c..64cb630d115 100644 --- a/arch/um/drivers/vde_user.c +++ b/arch/um/drivers/vde_user.c @@ -6,10 +6,8 @@ #include <stddef.h> #include <errno.h> #include <libvdeplug.h> -#include "kern_constants.h" -#include "net_user.h" -#include "um_malloc.h" -#include "user.h" +#include <net_user.h> +#include <um_malloc.h> #include "vde.h" static int vde_user_init(void *data, void *dev) diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index da2caa5a21e..20e30be4479 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -11,10 +11,8 @@ #include <string.h> #include <termios.h> #include "chan_user.h" -#include "kern_constants.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <os.h> +#include <um_malloc.h> #include "xterm.h" struct xterm_chan { @@ -90,7 +88,7 @@ static int xterm_open(int input, int output, int primary, void *d, int pid, fd, new, err; char title[256], file[] = "/tmp/xterm-pipeXXXXXX"; char *argv[] = { terminal_emulator, title_switch, title, exec_switch, - "/usr/lib/uml/port-helper", "-uml-socket", + OS_LIB_PATH "/uml/port-helper", "-uml-socket", file, NULL }; if (access(argv[4], X_OK) < 0) @@ -123,6 +121,7 @@ static int xterm_open(int input, int output, int primary, void *d, err = -errno; printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n", errno); + close(fd); return err; } close(fd); diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c index b646bccef37..e8f9957bfbf 100644 --- a/arch/um/drivers/xterm_kern.c +++ b/arch/um/drivers/xterm_kern.c @@ -7,8 +7,8 @@ #include <linux/completion.h> #include <linux/irqreturn.h> #include <asm/irq.h> -#include "irq_kern.h" -#include "os.h" +#include <irq_kern.h> +#include <os.h> struct xterm_wait { struct completion ready; @@ -50,8 +50,7 @@ int xterm_fd(int socket, int *pid_out) init_completion(&data->ready); err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, - IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM, - "xterm", data); + IRQF_SHARED, "xterm", data); if (err) { printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " "err = %d\n", err); @@ -65,7 +64,7 @@ int xterm_fd(int socket, int *pid_out) * isn't set) this will hang... */ wait_for_completion(&data->ready); - free_irq(XTERM_IRQ, data); + um_free_irq(XTERM_IRQ, data); ret = data->new_fd; *pid_out = data->pid; diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild new file mode 100644 index 00000000000..a5e4b606821 --- /dev/null +++ b/arch/um/include/asm/Kbuild @@ -0,0 +1,28 @@ +generic-y += barrier.h +generic-y += bug.h +generic-y += clkdev.h +generic-y += cputime.h +generic-y += current.h +generic-y += delay.h +generic-y += device.h +generic-y += emergency-restart.h +generic-y += exec.h +generic-y += ftrace.h +generic-y += futex.h +generic-y += hardirq.h +generic-y += hash.h +generic-y += hw_irq.h +generic-y += io.h +generic-y += irq_regs.h +generic-y += kdebug.h +generic-y += mcs_spinlock.h +generic-y += mutex.h +generic-y += param.h +generic-y += pci.h +generic-y += percpu.h +generic-y += preempt.h +generic-y += sections.h +generic-y += switch_to.h +generic-y += topology.h +generic-y += trace_clock.h +generic-y += xor.h diff --git a/arch/um/include/asm/apic.h b/arch/um/include/asm/apic.h deleted file mode 100644 index 876dee84ab1..00000000000 --- a/arch/um/include/asm/apic.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __UM_APIC_H -#define __UM_APIC_H - -#endif diff --git a/arch/um/include/asm/arch_hweight.h b/arch/um/include/asm/arch_hweight.h deleted file mode 100644 index c656cf443f4..00000000000 --- a/arch/um/include/asm/arch_hweight.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_UM_HWEIGHT_H -#define _ASM_UM_HWEIGHT_H - -#include <asm-generic/bitops/arch_hweight.h> - -#endif diff --git a/arch/um/include/asm/asm-offsets.h b/arch/um/include/asm/asm-offsets.h deleted file mode 100644 index d370ee36a18..00000000000 --- a/arch/um/include/asm/asm-offsets.h +++ /dev/null @@ -1 +0,0 @@ -#include <generated/asm-offsets.h> diff --git a/arch/um/include/asm/auxvec.h b/arch/um/include/asm/auxvec.h deleted file mode 100644 index 1e5e1c2fc9b..00000000000 --- a/arch/um/include/asm/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __UM_AUXVEC_H -#define __UM_AUXVEC_H - -#endif diff --git a/arch/um/include/asm/bug.h b/arch/um/include/asm/bug.h deleted file mode 100644 index 9e33b864c35..00000000000 --- a/arch/um/include/asm/bug.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_BUG_H -#define __UM_BUG_H - -#include <asm-generic/bug.h> - -#endif diff --git a/arch/um/include/asm/checksum.h b/arch/um/include/asm/checksum.h deleted file mode 100644 index 5b501361e36..00000000000 --- a/arch/um/include/asm/checksum.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_CHECKSUM_H -#define __UM_CHECKSUM_H - -#include "sysdep/checksum.h" - -#endif diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S index 34bede8aad4..1dd5bd8a8c5 100644 --- a/arch/um/include/asm/common.lds.S +++ b/arch/um/include/asm/common.lds.S @@ -42,7 +42,7 @@ INIT_SETUP(0) } - PERCPU(32, 32) + PERCPU_SECTION(32) .initcall.init : { INIT_CALLS @@ -57,7 +57,6 @@ *(.uml.initcall.init) __uml_initcall_end = .; } - __init_end = .; SECURITY_INIT diff --git a/arch/um/include/asm/cputime.h b/arch/um/include/asm/cputime.h deleted file mode 100644 index c84acbadfa2..00000000000 --- a/arch/um/include/asm/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_CPUTIME_H -#define __UM_CPUTIME_H - -#include <asm-generic/cputime.h> - -#endif /* __UM_CPUTIME_H */ diff --git a/arch/um/include/asm/current.h b/arch/um/include/asm/current.h deleted file mode 100644 index c2191d9aa03..00000000000 --- a/arch/um/include/asm/current.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __UM_CURRENT_H -#define __UM_CURRENT_H - -#include "linux/thread_info.h" - -#define current (current_thread_info()->task) - -#endif diff --git a/arch/um/include/asm/delay.h b/arch/um/include/asm/delay.h deleted file mode 100644 index c71e32b6741..00000000000 --- a/arch/um/include/asm/delay.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __UM_DELAY_H -#define __UM_DELAY_H - -#define MILLION 1000000 - -/* Undefined on purpose */ -extern void __bad_udelay(void); - -extern void __udelay(unsigned long usecs); -extern void __delay(unsigned long loops); - -#define udelay(n) ((__builtin_constant_p(n) && (n) > 20000) ? \ - __bad_udelay() : __udelay(n)) - -/* It appears that ndelay is not used at all for UML, and has never been - * implemented. */ -extern void __unimplemented_ndelay(void); -#define ndelay(n) __unimplemented_ndelay() - -#endif diff --git a/arch/um/include/asm/desc.h b/arch/um/include/asm/desc.h deleted file mode 100644 index 4ec34a51b62..00000000000 --- a/arch/um/include/asm/desc.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __UM_DESC_H -#define __UM_DESC_H - -/* Taken from asm-i386/desc.h, it's the only thing we need. The rest wouldn't - * compile, and has never been used. */ -#define LDT_empty(info) (\ - (info)->base_addr == 0 && \ - (info)->limit == 0 && \ - (info)->contents == 0 && \ - (info)->read_exec_only == 1 && \ - (info)->seg_32bit == 0 && \ - (info)->limit_in_pages == 0 && \ - (info)->seg_not_present == 1 && \ - (info)->useable == 0 ) - -#endif diff --git a/arch/um/include/asm/device.h b/arch/um/include/asm/device.h deleted file mode 100644 index d8f9872b0e2..00000000000 --- a/arch/um/include/asm/device.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Arch specific extensions to struct device - * - * This file is released under the GPLv2 - */ -#include <asm-generic/device.h> - diff --git a/arch/um/include/asm/dma.h b/arch/um/include/asm/dma.h index 9f6139a8a52..f88c5860520 100644 --- a/arch/um/include/asm/dma.h +++ b/arch/um/include/asm/dma.h @@ -1,7 +1,7 @@ #ifndef __UM_DMA_H #define __UM_DMA_H -#include "asm/io.h" +#include <asm/io.h> extern unsigned long uml_physmem; diff --git a/arch/um/include/asm/emergency-restart.h b/arch/um/include/asm/emergency-restart.h deleted file mode 100644 index 108d8c48e42..00000000000 --- a/arch/um/include/asm/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include <asm-generic/emergency-restart.h> - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/um/include/asm/fixmap.h b/arch/um/include/asm/fixmap.h index 69c0252345f..3094ea3c73b 100644 --- a/arch/um/include/asm/fixmap.h +++ b/arch/um/include/asm/fixmap.h @@ -2,7 +2,6 @@ #define __UM_FIXMAP_H #include <asm/processor.h> -#include <asm/system.h> #include <asm/kmap_types.h> #include <asm/archparam.h> #include <asm/page.h> @@ -44,13 +43,6 @@ enum fixed_addresses { extern void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags); -#define set_fixmap(idx, phys) \ - __set_fixmap(idx, phys, PAGE_KERNEL) -/* - * Some hardware wants to get fixmapped without caching. - */ -#define set_fixmap_nocache(idx, phys) \ - __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) /* * used by vmalloc.c. * @@ -63,37 +55,6 @@ extern void __set_fixmap (enum fixed_addresses idx, #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) -#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) -#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) - -extern void __this_fixmap_does_not_exist(void); - -/* - * 'index to address' translation. If anyone tries to use the idx - * directly without tranlation, we catch the bug with a NULL-deference - * kernel oops. Illegal ranges of incoming indices are caught too. - */ -static inline unsigned long fix_to_virt(const unsigned int idx) -{ - /* - * this branch gets completely eliminated after inlining, - * except when someone tries to use fixaddr indices in an - * illegal way. (such as mixing up address types or using - * out-of-range indices). - * - * If it doesn't get removed, the linker will complain - * loudly with a reasonably clear error message.. - */ - if (idx >= __end_of_fixed_addresses) - __this_fixmap_does_not_exist(); - - return __fix_to_virt(idx); -} - -static inline unsigned long virt_to_fix(const unsigned long vaddr) -{ - BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); - return __virt_to_fix(vaddr); -} +#include <asm-generic/fixmap.h> #endif diff --git a/arch/um/include/asm/ftrace.h b/arch/um/include/asm/ftrace.h deleted file mode 100644 index 40a8c178f10..00000000000 --- a/arch/um/include/asm/ftrace.h +++ /dev/null @@ -1 +0,0 @@ -/* empty */ diff --git a/arch/um/include/asm/futex.h b/arch/um/include/asm/futex.h deleted file mode 100644 index 6a332a9f099..00000000000 --- a/arch/um/include/asm/futex.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#include <asm-generic/futex.h> - -#endif diff --git a/arch/um/include/asm/hardirq.h b/arch/um/include/asm/hardirq.h deleted file mode 100644 index fb3c05a0cbb..00000000000 --- a/arch/um/include/asm/hardirq.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/hardirq.h> diff --git a/arch/um/include/asm/hw_irq.h b/arch/um/include/asm/hw_irq.h deleted file mode 100644 index 1cf84cf5f21..00000000000 --- a/arch/um/include/asm/hw_irq.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _ASM_UM_HW_IRQ_H -#define _ASM_UM_HW_IRQ_H - -#include "asm/irq.h" -#include "asm/archparam.h" - -#endif diff --git a/arch/um/include/asm/io.h b/arch/um/include/asm/io.h deleted file mode 100644 index 44e8b8c772a..00000000000 --- a/arch/um/include/asm/io.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __UM_IO_H -#define __UM_IO_H - -#include "asm/page.h" - -#define IO_SPACE_LIMIT 0xdeadbeef /* Sure hope nothing uses this */ - -static inline int inb(unsigned long i) { return(0); } -static inline void outb(char c, unsigned long i) { } - -/* - * Change virtual addresses to physical addresses and vv. - * These are pretty trivial - */ -static inline unsigned long virt_to_phys(volatile void * address) -{ - return __pa((void *) address); -} - -static inline void * phys_to_virt(unsigned long address) -{ - return __va(address); -} - -/* - * Convert a physical pointer to a virtual kernel pointer for /dev/mem - * access - */ -#define xlate_dev_mem_ptr(p) __va(p) - -/* - * Convert a virtual cached pointer to an uncached pointer - */ -#define xlate_dev_kmem_ptr(p) p - -static inline void writeb(unsigned char b, volatile void __iomem *addr) -{ - *(volatile unsigned char __force *) addr = b; -} -static inline void writew(unsigned short b, volatile void __iomem *addr) -{ - *(volatile unsigned short __force *) addr = b; -} -static inline void writel(unsigned int b, volatile void __iomem *addr) -{ - *(volatile unsigned int __force *) addr = b; -} -static inline void writeq(unsigned int b, volatile void __iomem *addr) -{ - *(volatile unsigned long long __force *) addr = b; -} -#define __raw_writeb writeb -#define __raw_writew writew -#define __raw_writel writel -#define __raw_writeq writeq - -#endif diff --git a/arch/um/include/asm/irq_regs.h b/arch/um/include/asm/irq_regs.h deleted file mode 100644 index 3dd9c0b7027..00000000000 --- a/arch/um/include/asm/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/irq_regs.h> diff --git a/arch/um/include/asm/irq_vectors.h b/arch/um/include/asm/irq_vectors.h deleted file mode 100644 index 272a81e0ce1..00000000000 --- a/arch/um/include/asm/irq_vectors.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __UM_IRQ_VECTORS_H -#define __UM_IRQ_VECTORS_H - -#endif - diff --git a/arch/um/include/asm/irqflags.h b/arch/um/include/asm/irqflags.h index 659b9abdfdb..c780d8a1677 100644 --- a/arch/um/include/asm/irqflags.h +++ b/arch/um/include/asm/irqflags.h @@ -1,6 +1,42 @@ #ifndef __UM_IRQFLAGS_H #define __UM_IRQFLAGS_H -/* Empty for now */ +extern int get_signals(void); +extern int set_signals(int enable); +extern void block_signals(void); +extern void unblock_signals(void); + +static inline unsigned long arch_local_save_flags(void) +{ + return get_signals(); +} + +static inline void arch_local_irq_restore(unsigned long flags) +{ + set_signals(flags); +} + +static inline void arch_local_irq_enable(void) +{ + unblock_signals(); +} + +static inline void arch_local_irq_disable(void) +{ + block_signals(); +} + +static inline unsigned long arch_local_irq_save(void) +{ + unsigned long flags; + flags = arch_local_save_flags(); + arch_local_irq_disable(); + return flags; +} + +static inline bool arch_irqs_disabled(void) +{ + return arch_local_save_flags() == 0; +} #endif diff --git a/arch/um/include/asm/kdebug.h b/arch/um/include/asm/kdebug.h deleted file mode 100644 index 6ece1b03766..00000000000 --- a/arch/um/include/asm/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/kdebug.h> diff --git a/arch/um/include/asm/kmap_types.h b/arch/um/include/asm/kmap_types.h index 6c03acdb440..2e0a6b1d830 100644 --- a/arch/um/include/asm/kmap_types.h +++ b/arch/um/include/asm/kmap_types.h @@ -8,22 +8,6 @@ /* No more #include "asm/arch/kmap_types.h" ! */ -enum km_type { - KM_BOUNCE_READ, - KM_SKB_SUNRPC_DATA, - KM_SKB_DATA_SOFTIRQ, - KM_USER0, - KM_USER1, - KM_UML_USERCOPY, /* UML specific, for copy_*_user - used in do_op_one_page */ - KM_BIO_SRC_IRQ, - KM_BIO_DST_IRQ, - KM_PTE0, - KM_PTE1, - KM_IRQ0, - KM_IRQ1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, - KM_TYPE_NR -}; +#define KM_TYPE_NR 14 #endif diff --git a/arch/um/include/asm/kvm_para.h b/arch/um/include/asm/kvm_para.h new file mode 100644 index 00000000000..14fab8f0b95 --- /dev/null +++ b/arch/um/include/asm/kvm_para.h @@ -0,0 +1 @@ +#include <asm-generic/kvm_para.h> diff --git a/arch/um/include/asm/mmu.h b/arch/um/include/asm/mmu.h index cf259de5153..da705448590 100644 --- a/arch/um/include/asm/mmu.h +++ b/arch/um/include/asm/mmu.h @@ -1,12 +1,24 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ -#ifndef __MMU_H -#define __MMU_H +#ifndef __ARCH_UM_MMU_H +#define __ARCH_UM_MMU_H -#include "um_mmu.h" +#include <mm_id.h> +#include <asm/mm_context.h> -#endif +typedef struct mm_context { + struct mm_id id; + struct uml_arch_mm_context arch; + struct page *stub_pages[2]; +} mm_context_t; + +extern void __switch_mm(struct mm_id * mm_idp); +/* Avoid tangled inclusion with asm/ldt.h */ +extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm); +extern void free_ldt(struct mm_context *mm); + +#endif diff --git a/arch/um/include/asm/mmu_context.h b/arch/um/include/asm/mmu_context.h index 34d813011b7..aa4a743dc4a 100644 --- a/arch/um/include/asm/mmu_context.h +++ b/arch/um/include/asm/mmu_context.h @@ -6,15 +6,12 @@ #ifndef __UM_MMU_CONTEXT_H #define __UM_MMU_CONTEXT_H -#include "linux/sched.h" -#include "um_mmu.h" +#include <linux/sched.h> +#include <asm/mmu.h> -extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm); +extern void uml_setup_stubs(struct mm_struct *mm); extern void arch_exit_mmap(struct mm_struct *mm); -#define get_mmu_context(task) do ; while(0) -#define activate_context(tsk) do ; while(0) - #define deactivate_mm(tsk,mm) do { } while (0) extern void force_flush_all(void); @@ -26,7 +23,9 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) * when the new ->mm is used for the first time. */ __switch_mm(&new->context.id); - arch_dup_mmap(old, new); + down_write(&new->mmap_sem); + uml_setup_stubs(new); + up_write(&new->mmap_sem); } static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, @@ -42,6 +41,11 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, } } +static inline void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) +{ + uml_setup_stubs(mm); +} + static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { diff --git a/arch/um/include/asm/mutex.h b/arch/um/include/asm/mutex.h deleted file mode 100644 index 458c1f7fbc1..00000000000 --- a/arch/um/include/asm/mutex.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Pull in the generic implementation for the mutex fastpath. - * - * TODO: implement optimized primitives instead, or leave the generic - * implementation in place, or pick the atomic_xchg() based generic - * implementation. (see asm-generic/mutex-xchg.h for details) - */ - -#include <asm-generic/mutex-dec.h> diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h index 4cc9b6cf480..5ff53d9185f 100644 --- a/arch/um/include/asm/page.h +++ b/arch/um/include/asm/page.h @@ -19,7 +19,7 @@ struct page; #include <linux/types.h> -#include <sysdep/vm-flags.h> +#include <asm/vm-flags.h> /* * These are used to make use of C type-checking.. @@ -99,7 +99,7 @@ extern unsigned long uml_physmem; #define __va_space (8*1024*1024) -#include "mem.h" +#include <mem.h> /* Cast to unsigned long before casting to void * to avoid a warning from * mmap_kmem about cutting a long long down to a void *. Not sure that diff --git a/arch/um/include/asm/page_offset.h b/arch/um/include/asm/page_offset.h deleted file mode 100644 index 1c168dfbf35..00000000000 --- a/arch/um/include/asm/page_offset.h +++ /dev/null @@ -1 +0,0 @@ -#define PAGE_OFFSET_RAW (uml_physmem) diff --git a/arch/um/include/asm/param.h b/arch/um/include/asm/param.h deleted file mode 100644 index e44f4e60d16..00000000000 --- a/arch/um/include/asm/param.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef _UM_PARAM_H -#define _UM_PARAM_H - -#define EXEC_PAGESIZE 4096 - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#ifdef __KERNEL__ -#define HZ CONFIG_HZ -#define USER_HZ 100 /* .. some user interfaces are in "ticks" */ -#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ -#else -#define HZ 100 -#endif - -#endif diff --git a/arch/um/include/asm/pci.h b/arch/um/include/asm/pci.h deleted file mode 100644 index b44cf59ede1..00000000000 --- a/arch/um/include/asm/pci.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_PCI_H -#define __UM_PCI_H - -#define PCI_DMA_BUS_IS_PHYS (1) - -#endif diff --git a/arch/um/include/asm/pda.h b/arch/um/include/asm/pda.h deleted file mode 100644 index ddcd774fc2a..00000000000 --- a/arch/um/include/asm/pda.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __UM_PDA_X86_64_H -#define __UM_PDA_X86_64_H - -/* XXX */ -struct foo { - unsigned int __softirq_pending; - unsigned int __nmi_count; -}; - -extern struct foo me; - -#define read_pda(me) (&me) - -#endif - diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h index 32c8ce4e151..bf90b2aa200 100644 --- a/arch/um/include/asm/pgalloc.h +++ b/arch/um/include/asm/pgalloc.h @@ -8,8 +8,7 @@ #ifndef __UM_PGALLOC_H #define __UM_PGALLOC_H -#include "linux/mm.h" -#include "asm/fixmap.h" +#include <linux/mm.h> #define pmd_populate_kernel(mm, pmd, pte) \ set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) __pa(pte))) diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index 41474fb5eee..bf974f712af 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h @@ -23,9 +23,9 @@ pte_present gives true */ #ifdef CONFIG_3_LEVEL_PGTABLES -#include "asm/pgtable-3level.h" +#include <asm/pgtable-3level.h> #else -#include "asm/pgtable-2level.h" +#include <asm/pgtable-2level.h> #endif extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; @@ -271,6 +271,12 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval) } #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) +#define __HAVE_ARCH_PTE_SAME +static inline int pte_same(pte_t pte_a, pte_t pte_b) +{ + return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE); +} + /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. @@ -346,11 +352,11 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); #define update_mmu_cache(vma,address,ptep) do ; while (0) /* Encode and de-code a swap entry */ -#define __swp_type(x) (((x).val >> 4) & 0x3f) +#define __swp_type(x) (((x).val >> 5) & 0x1f) #define __swp_offset(x) ((x).val >> 11) #define __swp_entry(type, offset) \ - ((swp_entry_t) { ((type) << 4) | ((offset) << 11) }) + ((swp_entry_t) { ((type) << 5) | ((offset) << 11) }) #define __pte_to_swp_entry(pte) \ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index d1d1b0d8a0c..cbc5edd5a90 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h @@ -10,32 +10,23 @@ struct pt_regs; struct task_struct; -#include "asm/ptrace.h" -#include "registers.h" -#include "sysdep/archsetjmp.h" +#include <asm/ptrace.h> +#include <registers.h> +#include <sysdep/archsetjmp.h> + +#include <linux/prefetch.h> struct mm_struct; struct thread_struct { - struct task_struct *saved_task; - /* - * This flag is set to 1 before calling do_fork (and analyzed in - * copy_thread) to mark that we are begin called from userspace (fork / - * vfork / clone), and reset to 0 after. It is left to 0 when called - * from kernelspace (i.e. kernel_thread() or fork_idle(), - * as of 2.6.11). - */ - int forking; struct pt_regs regs; + struct pt_regs *segv_regs; int singlestep_syscall; void *fault_addr; jmp_buf *fault_catcher; struct task_struct *prev_sched; - unsigned long temp_stack; - jmp_buf *exec_buf; struct arch_thread arch; jmp_buf switch_buf; - int mm_count; struct { int op; union { @@ -56,29 +47,17 @@ struct thread_struct { #define INIT_THREAD \ { \ - .forking = 0, \ .regs = EMPTY_REGS, \ .fault_addr = NULL, \ .prev_sched = NULL, \ - .temp_stack = 0, \ - .exec_buf = NULL, \ .arch = INIT_ARCH_THREAD, \ .request = { 0 } \ } -extern struct task_struct *alloc_task_struct_node(int node); - static inline void release_thread(struct task_struct *task) { } -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - -static inline void prepare_to_copy(struct task_struct *tsk) -{ -} - - extern unsigned long thread_saved_pc(struct task_struct *t); static inline void mm_copy_segments(struct mm_struct *from_mm, diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h index b7c5bab9bd7..cb9b3c47ca8 100644 --- a/arch/um/include/asm/ptrace-generic.h +++ b/arch/um/include/asm/ptrace-generic.h @@ -9,8 +9,7 @@ #ifndef __ASSEMBLY__ #include <asm/ptrace-abi.h> -#include <asm/user.h> -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> struct pt_regs { struct uml_pt_regs regs; @@ -23,17 +22,10 @@ struct pt_regs { #define PT_REGS_IP(r) UPT_IP(&(r)->regs) #define PT_REGS_SP(r) UPT_SP(&(r)->regs) -#define PT_REG(r, reg) UPT_REG(&(r)->regs, reg) -#define PT_REGS_SET(r, reg, val) UPT_SET(&(r)->regs, reg, val) - -#define PT_REGS_SET_SYSCALL_RETURN(r, res) \ - UPT_SET_SYSCALL_RETURN(&(r)->regs, res) #define PT_REGS_RESTART_SYSCALL(r) UPT_RESTART_SYSCALL(&(r)->regs) #define PT_REGS_SYSCALL_NR(r) UPT_SYSCALL_NR(&(r)->regs) -#define PT_REGS_SC(r) UPT_SC(&(r)->regs) - #define instruction_pointer(regs) PT_REGS_IP(regs) struct task_struct; @@ -42,15 +34,11 @@ extern long subarch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data); extern unsigned long getreg(struct task_struct *child, int regno); extern int putreg(struct task_struct *child, int regno, unsigned long value); -extern int get_fpregs(struct user_i387_struct __user *buf, - struct task_struct *child); -extern int set_fpregs(struct user_i387_struct __user *buf, - struct task_struct *child); - -extern void show_regs(struct pt_regs *regs); extern int arch_copy_tls(struct task_struct *new); extern void clear_flushed_tls(struct task_struct *task); +extern void syscall_trace_enter(struct pt_regs *regs); +extern void syscall_trace_leave(struct pt_regs *regs); #endif diff --git a/arch/um/include/asm/required-features.h b/arch/um/include/asm/required-features.h deleted file mode 100644 index dfb967b2d2f..00000000000 --- a/arch/um/include/asm/required-features.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __UM_REQUIRED_FEATURES_H -#define __UM_REQUIRED_FEATURES_H - -/* - * Nothing to see, just need something for the i386 and x86_64 asm - * headers to include. - */ - -#endif diff --git a/arch/um/include/asm/sections.h b/arch/um/include/asm/sections.h deleted file mode 100644 index 6b0231eefea..00000000000 --- a/arch/um/include/asm/sections.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _UM_SECTIONS_H -#define _UM_SECTIONS_H - -/* nothing to see, move along */ -#include <asm-generic/sections.h> - -#endif diff --git a/arch/um/include/asm/segment.h b/arch/um/include/asm/segment.h deleted file mode 100644 index 45183fcd10b..00000000000 --- a/arch/um/include/asm/segment.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __UM_SEGMENT_H -#define __UM_SEGMENT_H - -extern int host_gdt_entry_tls_min; - -#define GDT_ENTRY_TLS_ENTRIES 3 -#define GDT_ENTRY_TLS_MIN host_gdt_entry_tls_min -#define GDT_ENTRY_TLS_MAX (GDT_ENTRY_TLS_MIN + GDT_ENTRY_TLS_ENTRIES - 1) - -#endif diff --git a/arch/um/include/asm/smp.h b/arch/um/include/asm/smp.h index f27a9631317..e4507938d8c 100644 --- a/arch/um/include/asm/smp.h +++ b/arch/um/include/asm/smp.h @@ -3,15 +3,14 @@ #ifdef CONFIG_SMP -#include "linux/bitops.h" -#include "asm/current.h" -#include "linux/cpumask.h" +#include <linux/bitops.h> +#include <asm/current.h> +#include <linux/cpumask.h> #define raw_smp_processor_id() (current_thread->cpu) #define cpu_logical_map(n) (n) #define cpu_number_map(n) (n) -#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ extern int hard_smp_processor_id(void); #define NO_PROC_ID -1 diff --git a/arch/um/include/shared/sysrq.h b/arch/um/include/asm/sysrq.h index c8d332b56b9..c8d332b56b9 100644 --- a/arch/um/include/shared/sysrq.h +++ b/arch/um/include/asm/sysrq.h diff --git a/arch/um/include/asm/system.h b/arch/um/include/asm/system.h deleted file mode 100644 index 68a90ecd145..00000000000 --- a/arch/um/include/asm/system.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __UM_SYSTEM_GENERIC_H -#define __UM_SYSTEM_GENERIC_H - -#include "sysdep/system.h" - -extern int get_signals(void); -extern int set_signals(int enable); -extern void block_signals(void); -extern void unblock_signals(void); - -static inline unsigned long arch_local_save_flags(void) -{ - return get_signals(); -} - -static inline void arch_local_irq_restore(unsigned long flags) -{ - set_signals(flags); -} - -static inline void arch_local_irq_enable(void) -{ - unblock_signals(); -} - -static inline void arch_local_irq_disable(void) -{ - block_signals(); -} - -static inline unsigned long arch_local_irq_save(void) -{ - unsigned long flags; - flags = arch_local_save_flags(); - arch_local_irq_disable(); - return flags; -} - -static inline bool arch_irqs_disabled(void) -{ - return arch_local_save_flags() == 0; -} - -extern void *_switch_to(void *prev, void *next, void *last); -#define switch_to(prev, next, last) prev = _switch_to(prev, next, last) - -#endif diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index e2cf786bda0..1c5b2a83046 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -49,7 +49,10 @@ static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; unsigned long mask = THREAD_SIZE - 1; - ti = (struct thread_info *) (((unsigned long) &ti) & ~mask); + void *p; + + asm volatile ("" : "=r" (p) : "0" (&ti)); + ti = (struct thread_info *) (((unsigned long)p) & ~mask); return ti; } @@ -57,26 +60,19 @@ static inline struct thread_info *current_thread_info(void) #endif -#define PREEMPT_ACTIVE 0x10000000 - #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ #define TIF_SIGPENDING 1 /* signal pending */ #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ -#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling - * TIF_NEED_RESCHED */ #define TIF_RESTART_BLOCK 4 #define TIF_MEMDIE 5 /* is terminating due to OOM killer */ #define TIF_SYSCALL_AUDIT 6 #define TIF_RESTORE_SIGMASK 7 -#define TIF_FREEZE 16 /* is freezing for suspend */ +#define TIF_NOTIFY_RESUME 8 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_MEMDIE (1 << TIF_MEMDIE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) -#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) -#define _TIF_FREEZE (1 << TIF_FREEZE) #endif diff --git a/arch/um/include/asm/tlb.h b/arch/um/include/asm/tlb.h index 660caedac9e..16eb63fac57 100644 --- a/arch/um/include/asm/tlb.h +++ b/arch/um/include/asm/tlb.h @@ -22,9 +22,6 @@ struct mmu_gather { unsigned int fullmm; /* non-zero means full mm flush */ }; -/* Users of the generic TLB shootdown code must declare this storage space. */ -DECLARE_PER_CPU(struct mmu_gather, mmu_gathers); - static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep, unsigned long address) { @@ -47,33 +44,40 @@ static inline void init_tlb_gather(struct mmu_gather *tlb) } } -/* tlb_gather_mmu - * Return a pointer to an initialized struct mmu_gather. - */ -static inline struct mmu_gather * -tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush) +static inline void +tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, unsigned long start, unsigned long end) { - struct mmu_gather *tlb = &get_cpu_var(mmu_gathers); - tlb->mm = mm; - tlb->fullmm = full_mm_flush; + tlb->start = start; + tlb->end = end; + tlb->fullmm = !(start | (end+1)); init_tlb_gather(tlb); - - return tlb; } extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long end); static inline void -tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) +tlb_flush_mmu_tlbonly(struct mmu_gather *tlb) +{ + flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end); +} + +static inline void +tlb_flush_mmu_free(struct mmu_gather *tlb) +{ + init_tlb_gather(tlb); +} + +static inline void +tlb_flush_mmu(struct mmu_gather *tlb) { if (!tlb->need_flush) return; - flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end); - init_tlb_gather(tlb); + tlb_flush_mmu_tlbonly(tlb); + tlb_flush_mmu_free(tlb); } /* tlb_finish_mmu @@ -83,12 +87,10 @@ tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) static inline void tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) { - tlb_flush_mmu(tlb, start, end); + tlb_flush_mmu(tlb); /* keep the page table cache within bounds */ check_pgt_cache(); - - put_cpu_var(mmu_gathers); } /* tlb_remove_page @@ -96,11 +98,16 @@ tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end) * while handling the additional races in SMP caused by other CPUs * caching valid mappings in their TLBs. */ -static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +static inline int __tlb_remove_page(struct mmu_gather *tlb, struct page *page) { tlb->need_flush = 1; free_page_and_swap_cache(page); - return; + return 1; /* avoid calling tlb_flush_mmu */ +} + +static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page) +{ + __tlb_remove_page(tlb, page); } /** diff --git a/arch/um/include/asm/topology.h b/arch/um/include/asm/topology.h deleted file mode 100644 index 0905e4f21d4..00000000000 --- a/arch/um/include/asm/topology.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_UM_TOPOLOGY_H -#define _ASM_UM_TOPOLOGY_H - -#include <asm-generic/topology.h> - -#endif diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h index b9a895d6fa1..3f22fbf7ca1 100644 --- a/arch/um/include/asm/uaccess.h +++ b/arch/um/include/asm/uaccess.h @@ -6,15 +6,15 @@ #ifndef __UM_UACCESS_H #define __UM_UACCESS_H -#include <asm/errno.h> -#include <asm/processor.h> - /* thread_info has a mm_segment_t in it, so put the definition up here */ typedef struct { unsigned long seg; } mm_segment_t; -#include "linux/thread_info.h" +#include <linux/thread_info.h> +#include <linux/errno.h> +#include <asm/processor.h> +#include <asm/elf.h> #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -38,7 +38,86 @@ typedef struct { #define segment_eq(a, b) ((a).seg == (b).seg) -#include "um_uaccess.h" +#define __under_task_size(addr, size) \ + (((unsigned long) (addr) < TASK_SIZE) && \ + (((unsigned long) (addr) + (size)) < TASK_SIZE)) + +#define __access_ok_vsyscall(type, addr, size) \ + ((type == VERIFY_READ) && \ + ((unsigned long) (addr) >= FIXADDR_USER_START) && \ + ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ + ((unsigned long) (addr) + (size) >= (unsigned long)(addr))) + +#define __addr_range_nowrap(addr, size) \ + ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) + +#define access_ok(type, addr, size) \ + (__addr_range_nowrap(addr, size) && \ + (__under_task_size(addr, size) || \ + __access_ok_vsyscall(type, addr, size) || \ + segment_eq(get_fs(), KERNEL_DS))) + +extern int copy_from_user(void *to, const void __user *from, int n); +extern int copy_to_user(void __user *to, const void *from, int n); + +/* + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ + +extern int strncpy_from_user(char *dst, const char __user *src, int count); + +/* + * __clear_user: - Zero a block of memory in user space, with less checking. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ +extern int __clear_user(void __user *mem, int len); + +/* + * clear_user: - Zero a block of memory in user space. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ +extern int clear_user(void __user *mem, int len); + +/* + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * @n: The maximum valid length + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * If the string is too long, returns a value greater than @n. + */ +extern int strnlen_user(const void __user *str, int len); #define __copy_from_user(to, from, n) copy_from_user(to, from, n) diff --git a/arch/um/include/asm/xor.h b/arch/um/include/asm/xor.h deleted file mode 100644 index a19db3e1724..00000000000 --- a/arch/um/include/asm/xor.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_XOR_H -#define __UM_XOR_H - -#include "asm-generic/xor.h" - -#endif diff --git a/arch/um/include/shared/arch.h b/arch/um/include/shared/arch.h index 2de92a08a76..4f46abda060 100644 --- a/arch/um/include/shared/arch.h +++ b/arch/um/include/shared/arch.h @@ -6,7 +6,7 @@ #ifndef __ARCH_H__ #define __ARCH_H__ -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> extern void arch_check_bugs(void); extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs); diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h index a92b678503c..41c8c774ec1 100644 --- a/arch/um/include/shared/as-layout.h +++ b/arch/um/include/shared/as-layout.h @@ -6,7 +6,7 @@ #ifndef __START_H__ #define __START_H__ -#include "kern_constants.h" +#include <generated/asm-offsets.h> /* * Stolen from linux/const.h, which can't be directly included since @@ -35,7 +35,7 @@ #ifndef __ASSEMBLY__ -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> struct cpu_task { int pid; @@ -44,7 +44,6 @@ struct cpu_task { extern struct cpu_task cpu_tasks[]; -extern unsigned long low_physmem; extern unsigned long high_physmem; extern unsigned long uml_physmem; extern unsigned long uml_reserved; @@ -52,15 +51,14 @@ extern unsigned long end_vm; extern unsigned long start_vm; extern unsigned long long highmem; -extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end; -extern unsigned long _unprotected_end; extern unsigned long brk_start; extern unsigned long host_task_size; extern int linux_main(int argc, char **argv); -extern void (*sig_info[])(int, struct uml_pt_regs *); +struct siginfo; +extern void (*sig_info[])(int, struct siginfo *si, struct uml_pt_regs *); #endif diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h index 72009c7e321..c9230680902 100644 --- a/arch/um/include/shared/common-offsets.h +++ b/arch/um/include/shared/common-offsets.h @@ -2,24 +2,11 @@ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE); -OFFSET(HOST_TASK_REGS, task_struct, thread.regs); -OFFSET(HOST_TASK_PID, task_struct, pid); - DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE); DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); -DEFINE_STR(UM_KERN_EMERG, KERN_EMERG); -DEFINE_STR(UM_KERN_ALERT, KERN_ALERT); -DEFINE_STR(UM_KERN_CRIT, KERN_CRIT); -DEFINE_STR(UM_KERN_ERR, KERN_ERR); -DEFINE_STR(UM_KERN_WARNING, KERN_WARNING); -DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE); -DEFINE_STR(UM_KERN_INFO, KERN_INFO); -DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG); -DEFINE_STR(UM_KERN_CONT, KERN_CONT); - DEFINE(UM_ELF_CLASS, ELF_CLASS); DEFINE(UM_ELFCLASS32, ELFCLASS32); DEFINE(UM_ELFCLASS64, ELFCLASS64); @@ -43,8 +30,8 @@ DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC); #ifdef CONFIG_PRINTK DEFINE(UML_CONFIG_PRINTK, CONFIG_PRINTK); #endif -#ifdef CONFIG_NO_HZ -DEFINE(UML_CONFIG_NO_HZ, CONFIG_NO_HZ); +#ifdef CONFIG_NO_HZ_COMMON +DEFINE(UML_CONFIG_NO_HZ_COMMON, CONFIG_NO_HZ_COMMON); #endif #ifdef CONFIG_UML_X86 DEFINE(UML_CONFIG_UML_X86, CONFIG_UML_X86); diff --git a/arch/um/include/shared/frame_kern.h b/arch/um/include/shared/frame_kern.h index 76078490c25..f2ca5702a4e 100644 --- a/arch/um/include/shared/frame_kern.h +++ b/arch/um/include/shared/frame_kern.h @@ -6,16 +6,13 @@ #ifndef __FRAME_KERN_H_ #define __FRAME_KERN_H_ -#define _S(nr) (1<<((nr)-1)) -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) - -extern int setup_signal_stack_sc(unsigned long stack_top, int sig, +extern int setup_signal_stack_sc(unsigned long stack_top, int sig, struct k_sigaction *ka, - struct pt_regs *regs, + struct pt_regs *regs, sigset_t *mask); -extern int setup_signal_stack_si(unsigned long stack_top, int sig, +extern int setup_signal_stack_si(unsigned long stack_top, int sig, struct k_sigaction *ka, - struct pt_regs *regs, siginfo_t *info, + struct pt_regs *regs, struct siginfo *info, sigset_t *mask); #endif diff --git a/arch/um/include/shared/initrd.h b/arch/um/include/shared/initrd.h deleted file mode 100644 index 22673bcc273..00000000000 --- a/arch/um/include/shared/initrd.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __INITRD_USER_H__ -#define __INITRD_USER_H__ - -extern int load_initrd(char *filename, void *buf, int size); - -#endif - diff --git a/arch/um/include/shared/irq_kern.h b/arch/um/include/shared/irq_kern.h index b05d22f3d84..e05bd667de1 100644 --- a/arch/um/include/shared/irq_kern.h +++ b/arch/um/include/shared/irq_kern.h @@ -6,13 +6,13 @@ #ifndef __IRQ_KERN_H__ #define __IRQ_KERN_H__ -#include "linux/interrupt.h" -#include "asm/ptrace.h" +#include <linux/interrupt.h> +#include <asm/ptrace.h> extern int um_request_irq(unsigned int irq, int fd, int type, irq_handler_t handler, unsigned long irqflags, const char * devname, void *dev_id); - +void um_free_irq(unsigned int irq, void *dev); #endif diff --git a/arch/um/include/shared/irq_user.h b/arch/um/include/shared/irq_user.h index c6c784df267..df563305395 100644 --- a/arch/um/include/shared/irq_user.h +++ b/arch/um/include/shared/irq_user.h @@ -6,7 +6,7 @@ #ifndef __IRQ_USER_H__ #define __IRQ_USER_H__ -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> struct irq_fd { struct irq_fd *next; @@ -20,7 +20,8 @@ struct irq_fd { enum { IRQ_READ, IRQ_WRITE }; -extern void sigio_handler(int sig, struct uml_pt_regs *regs); +struct siginfo; +extern void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern void free_irq_by_fd(int fd); extern void reactivate_fd(int fd, int irqnum); extern void deactivate_fd(int fd, int irqnum); diff --git a/arch/um/include/shared/kern.h b/arch/um/include/shared/kern.h index 4ce3fc650e5..6cd01240bbf 100644 --- a/arch/um/include/shared/kern.h +++ b/arch/um/include/shared/kern.h @@ -13,28 +13,10 @@ * includes. */ -extern int errno; - -extern int clone(int (*proc)(void *), void *sp, int flags, void *data); -extern int sleep(int); extern int printf(const char *fmt, ...); -extern char *strerror(int errnum); -extern char *ptsname(int __fd); -extern int munmap(void *, int); extern void *sbrk(int increment); -extern void *malloc(int size); -extern void perror(char *err); -extern int kill(int pid, int sig); -extern int getuid(void); -extern int getgid(void); extern int pause(void); -extern int write(int, const void *, int); extern void exit(int); -extern int close(int); -extern int read(unsigned int, char *, int); -extern int pipe(int *); -extern int sched_yield(void); -extern int ptrace(int op, int pid, long addr, long data); #endif diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h index 3c341222d25..83a91f97633 100644 --- a/arch/um/include/shared/kern_util.h +++ b/arch/um/include/shared/kern_util.h @@ -6,8 +6,10 @@ #ifndef __KERN_UTIL_H__ #define __KERN_UTIL_H__ -#include "sysdep/ptrace.h" -#include "sysdep/faultinfo.h" +#include <sysdep/ptrace.h> +#include <sysdep/faultinfo.h> + +struct siginfo; extern int uml_exitcode; @@ -21,9 +23,8 @@ extern unsigned long alloc_stack(int order, int atomic); extern void free_stack(unsigned long stack, int order); extern int do_signal(void); -extern void copy_sc(struct uml_pt_regs *regs, void *from); extern void interrupt_end(void); -extern void relay_signal(int sig, struct uml_pt_regs *regs); +extern void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs); extern unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, struct uml_pt_regs *regs); @@ -34,9 +35,8 @@ extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs); extern int smp_sigio_handler(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); extern int is_syscall(unsigned long addr); -extern void timer_handler(int sig, struct uml_pt_regs *regs); -extern void timer_handler(int sig, struct uml_pt_regs *regs); +extern void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern int start_uml(void); extern void paging_init(void); @@ -49,7 +49,7 @@ extern void do_uml_exitcalls(void); * GFP_ATOMIC. */ extern int __cant_sleep(void); -extern void *get_current(void); +extern int get_current_pid(void); extern int copy_from_user_proc(void *to, void *from, int size); extern int cpu(void); extern char *uml_strdup(const char *string); @@ -60,9 +60,9 @@ extern unsigned long from_irq_stack(int nested); extern void syscall_trace(struct uml_pt_regs *regs, int entryexit); extern int singlestepping(void *t); -extern void segv_handler(int sig, struct uml_pt_regs *regs); -extern void bus_handler(int sig, struct uml_pt_regs *regs); -extern void winch(int sig, struct uml_pt_regs *regs); +extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); +extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs); +extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs); extern void fatal_sigsegv(void) __attribute__ ((noreturn)); diff --git a/arch/um/include/shared/ldt.h b/arch/um/include/shared/ldt.h deleted file mode 100644 index a7f999a5877..00000000000 --- a/arch/um/include/shared/ldt.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2004 Fujitsu Siemens Computers GmbH - * Licensed under the GPL - * - * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com> - */ - -#ifndef __ASM_LDT_H -#define __ASM_LDT_H - -#include <linux/mutex.h> -#include <sysdep/host_ldt.h> - -extern void ldt_host_info(void); - -#define LDT_PAGES_MAX \ - ((LDT_ENTRIES * LDT_ENTRY_SIZE)/PAGE_SIZE) -#define LDT_ENTRIES_PER_PAGE \ - (PAGE_SIZE/LDT_ENTRY_SIZE) -#define LDT_DIRECT_ENTRIES \ - ((LDT_PAGES_MAX*sizeof(void *))/LDT_ENTRY_SIZE) - -struct ldt_entry { - __u32 a; - __u32 b; -}; - -typedef struct uml_ldt { - int entry_count; - struct mutex lock; - union { - struct ldt_entry * pages[LDT_PAGES_MAX]; - struct ldt_entry entries[LDT_DIRECT_ENTRIES]; - } u; -} uml_ldt_t; - -#endif diff --git a/arch/um/include/shared/longjmp.h b/arch/um/include/shared/longjmp.h index e860bc5848e..9bdddf4c405 100644 --- a/arch/um/include/shared/longjmp.h +++ b/arch/um/include/shared/longjmp.h @@ -1,8 +1,8 @@ #ifndef __UML_LONGJMP_H #define __UML_LONGJMP_H -#include "sysdep/archsetjmp.h" -#include "os.h" +#include <sysdep/archsetjmp.h> +#include <os.h> extern int setjmp(jmp_buf); extern void longjmp(jmp_buf, int); diff --git a/arch/um/include/shared/mem_kern.h b/arch/um/include/shared/mem_kern.h deleted file mode 100644 index 69be0fd0ce4..00000000000 --- a/arch/um/include/shared/mem_kern.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __MEM_KERN_H__ -#define __MEM_KERN_H__ - -#include "linux/list.h" -#include "linux/types.h" - -struct remapper { - struct list_head list; - int (*proc)(int, unsigned long, int, __u64); -}; - -extern void register_remapper(struct remapper *info); - -#endif - diff --git a/arch/um/include/shared/net_kern.h b/arch/um/include/shared/net_kern.h index 5c367f22595..012ac87d490 100644 --- a/arch/um/include/shared/net_kern.h +++ b/arch/um/include/shared/net_kern.h @@ -18,7 +18,6 @@ struct uml_net { struct net_device *dev; struct platform_device pdev; int index; - unsigned char mac[ETH_ALEN]; }; struct uml_net_private { diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index c4617baaa4f..08eec0b691b 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -7,10 +7,9 @@ #define __OS_H__ #include <stdarg.h> -#include "irq_user.h" -#include "longjmp.h" -#include "mm_id.h" -#include "sysdep/tls.h" +#include <irq_user.h> +#include <longjmp.h> +#include <mm_id.h> #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR)) @@ -29,6 +28,12 @@ #define OS_ACC_R_OK 4 /* Test for read permission. */ #define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ +#ifdef CONFIG_64BIT +#define OS_LIB_PATH "/usr/lib64/" +#else +#define OS_LIB_PATH "/usr/lib/" +#endif + /* * types taken from stat_file() in hostfs_user.c * (if they are wrong here, they are wrong there...). @@ -131,11 +136,13 @@ extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); extern int os_get_ifname(int fd, char *namebuf); extern int os_set_slip(int fd); extern int os_mode_fd(int fd, int mode); +extern int os_fsync_file(int fd); extern int os_seek_file(int fd, unsigned long long offset); extern int os_open_file(const char *file, struct openflags flags, int mode); extern int os_read_file(int fd, void *buf, int len); extern int os_write_file(int fd, const void *buf, int count); +extern int os_sync_file(int fd); extern int os_file_size(const char *file, unsigned long long *size_out); extern int os_file_modtime(const char *file, unsigned long *modtime); extern int os_pipe(int *fd, int stream, int close_on_exec); @@ -186,7 +193,6 @@ extern int os_getpid(void); extern int os_getpgrp(void); extern void init_new_thread_signals(void); -extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr); extern int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x); @@ -196,12 +202,7 @@ extern int os_unmap_memory(void *addr, int len); extern int os_drop_memory(void *addr, int length); extern int can_drop_memory(void); extern void os_flush_stdout(void); - -/* uaccess.c */ -extern unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher, - void (*op)(void *to, const void *from, - int n), int *faulted_out); +extern int os_mincore(void *addr, unsigned long len); /* execvp.c */ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]); @@ -212,10 +213,6 @@ extern int run_helper_thread(int (*proc)(void *), void *arg, extern int helper_wait(int pid); -/* tls.c */ -extern int os_set_thread_area(user_desc_t *info, int pid); -extern int os_get_thread_area(user_desc_t *info, int pid); - /* umid.c */ extern int umid_file_name(char *name, char *buf, int len); extern int set_umid(char *name); @@ -225,12 +222,13 @@ extern char *get_umid(void); extern void timer_init(void); extern void set_sigstack(void *sig_stack, int size); extern void remove_sigstack(void); -extern void set_handler(int sig, void (*handler)(int), int flags, ...); +extern void set_handler(int sig); extern int change_sig(int signal, int on); extern void block_signals(void); extern void unblock_signals(void); extern int get_signals(void); extern int set_signals(int enable); +extern int os_is_signal_stack(void); /* util.c */ extern void stack_protections(unsigned long address); @@ -238,6 +236,8 @@ extern int raw(int fd); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(char *buf, int len); extern void os_dump_core(void) __attribute__ ((noreturn)); +extern void um_early_printk(const char *s, unsigned int n); +extern void os_fix_helper_signals(void); /* time.c */ extern void idle_sleep(unsigned long long nsecs); diff --git a/arch/um/include/shared/process.h b/arch/um/include/shared/process.h deleted file mode 100644 index bb873a51262..00000000000 --- a/arch/um/include/shared/process.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __PROCESS_H__ -#define __PROCESS_H__ - -#include <signal.h> - -/* Copied from linux/compiler-gcc.h since we can't include it directly */ -#define barrier() __asm__ __volatile__("": : :"memory") - -extern void sig_handler(int sig, struct sigcontext *sc); -extern void alarm_handler(int sig, struct sigcontext *sc); - -#endif diff --git a/arch/um/include/shared/ptrace_user.h b/arch/um/include/shared/ptrace_user.h index 7fd8539bc19..56b2f284b10 100644 --- a/arch/um/include/shared/ptrace_user.h +++ b/arch/um/include/shared/ptrace_user.h @@ -6,7 +6,8 @@ #ifndef __PTRACE_USER_H__ #define __PTRACE_USER_H__ -#include "sysdep/ptrace_user.h" +#include <sys/ptrace.h> +#include <sysdep/ptrace_user.h> extern int ptrace_getregs(long pid, unsigned long *regs_out); extern int ptrace_setregs(long pid, unsigned long *regs_in); diff --git a/arch/um/include/shared/registers.h b/arch/um/include/shared/registers.h index b0b4589e0eb..f5b76355ad7 100644 --- a/arch/um/include/shared/registers.h +++ b/arch/um/include/shared/registers.h @@ -6,8 +6,8 @@ #ifndef __REGISTERS_H #define __REGISTERS_H -#include "sysdep/ptrace.h" -#include "sysdep/archsetjmp.h" +#include <sysdep/ptrace.h> +#include <sysdep/archsetjmp.h> extern int save_fp_registers(int pid, unsigned long *fp_regs); extern int restore_fp_registers(int pid, unsigned long *fp_regs); @@ -16,7 +16,7 @@ extern int restore_fpx_registers(int pid, unsigned long *fp_regs); extern int save_registers(int pid, struct uml_pt_regs *regs); extern int restore_registers(int pid, struct uml_pt_regs *regs); extern int init_registers(int pid); -extern void get_safe_registers(unsigned long *regs); +extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs); extern unsigned long get_thread_reg(int reg, jmp_buf *buf); extern int get_fp_registers(int pid, unsigned long *regs); extern int put_fp_registers(int pid, unsigned long *regs); diff --git a/arch/um/include/shared/skas/skas.h b/arch/um/include/shared/skas/skas.h index 64d2c744330..c45df961c87 100644 --- a/arch/um/include/shared/skas/skas.h +++ b/arch/um/include/shared/skas/skas.h @@ -6,7 +6,7 @@ #ifndef __SKAS_H #define __SKAS_H -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> extern int userspace_pid[]; extern int proc_mm, ptrace_faultinfo, ptrace_ldt; diff --git a/arch/um/include/shared/skas_ptrace.h b/arch/um/include/shared/skas_ptrace.h index 3d31bbacd01..630a9c92b93 100644 --- a/arch/um/include/shared/skas_ptrace.h +++ b/arch/um/include/shared/skas_ptrace.h @@ -9,6 +9,6 @@ #define PTRACE_FAULTINFO 52 #define PTRACE_SWITCH_MM 55 -#include "sysdep/skas_ptrace.h" +#include <sysdep/skas_ptrace.h> #endif diff --git a/arch/um/include/shared/skas_ptregs.h b/arch/um/include/shared/skas_ptregs.h deleted file mode 100644 index 73db19e9c07..00000000000 --- a/arch/um/include/shared/skas_ptregs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __SKAS_PT_REGS_ -#define __SKAS_PT_REGS_ - -#include <user_constants.h> - -#endif diff --git a/arch/um/include/shared/syscall.h b/arch/um/include/shared/syscall.h deleted file mode 100644 index dda1df901a0..00000000000 --- a/arch/um/include/shared/syscall.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SYSCALL_USER_H -#define __SYSCALL_USER_H - -extern int record_syscall_start(int syscall); -extern void record_syscall_end(int index, long result); - -#endif diff --git a/arch/um/include/shared/task.h b/arch/um/include/shared/task.h deleted file mode 100644 index 3fe726b3cf4..00000000000 --- a/arch/um/include/shared/task.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __TASK_H -#define __TASK_H - -#include <kern_constants.h> - -#define TASK_REGS(task) ((struct uml_pt_regs *) &(((char *) (task))[HOST_TASK_REGS])) -#define TASK_PID(task) *((int *) &(((char *) (task))[HOST_TASK_PID])) - -#endif diff --git a/arch/um/include/shared/tlb.h b/arch/um/include/shared/tlb.h deleted file mode 100644 index ecd2265b301..00000000000 --- a/arch/um/include/shared/tlb.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TLB_H__ -#define __TLB_H__ - -#include "um_mmu.h" - -extern void force_flush_all(void); -extern int flush_tlb_kernel_range_common(unsigned long start, - unsigned long end); - -#endif diff --git a/arch/um/include/shared/um_malloc.h b/arch/um/include/shared/um_malloc.h index c554d706d10..6395fef6b69 100644 --- a/arch/um/include/shared/um_malloc.h +++ b/arch/um/include/shared/um_malloc.h @@ -6,7 +6,7 @@ #ifndef __UM_MALLOC_H__ #define __UM_MALLOC_H__ -#include "kern_constants.h" +#include <generated/asm-offsets.h> extern void *uml_kmalloc(int size, int flags); extern void kfree(const void *ptr); diff --git a/arch/um/include/shared/um_mmu.h b/arch/um/include/shared/um_mmu.h deleted file mode 100644 index b1a7e47d102..00000000000 --- a/arch/um/include/shared/um_mmu.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __ARCH_UM_MMU_H -#define __ARCH_UM_MMU_H - -#include "mm_id.h" -#include "ldt.h" - -typedef struct mm_context { - struct mm_id id; - struct uml_ldt ldt; - struct page **stub_pages; -} mm_context_t; - -extern void __switch_mm(struct mm_id * mm_idp); - -/* Avoid tangled inclusion with asm/ldt.h */ -extern long init_new_ldt(struct mm_context *to_mm, struct mm_context *from_mm); -extern void free_ldt(struct mm_context *mm); - -#endif diff --git a/arch/um/include/shared/um_uaccess.h b/arch/um/include/shared/um_uaccess.h deleted file mode 100644 index 45c04999d67..00000000000 --- a/arch/um/include/shared/um_uaccess.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __ARCH_UM_UACCESS_H -#define __ARCH_UM_UACCESS_H - -#include <asm/elf.h> -#include <asm/fixmap.h> -#include "sysdep/archsetjmp.h" - -#define __under_task_size(addr, size) \ - (((unsigned long) (addr) < TASK_SIZE) && \ - (((unsigned long) (addr) + (size)) < TASK_SIZE)) - -#define __access_ok_vsyscall(type, addr, size) \ - ((type == VERIFY_READ) && \ - ((unsigned long) (addr) >= FIXADDR_USER_START) && \ - ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ - ((unsigned long) (addr) + (size) >= (unsigned long)(addr))) - -#define __addr_range_nowrap(addr, size) \ - ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) - -#define access_ok(type, addr, size) \ - (__addr_range_nowrap(addr, size) && \ - (__under_task_size(addr, size) || \ - __access_ok_vsyscall(type, addr, size) || \ - segment_eq(get_fs(), KERNEL_DS))) - -extern int copy_from_user(void *to, const void __user *from, int n); -extern int copy_to_user(void __user *to, const void *from, int n); - -extern int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher); - -/* - * strncpy_from_user: - Copy a NUL terminated string from userspace. - * @dst: Destination address, in kernel space. This buffer must be at - * least @count bytes long. - * @src: Source address, in user space. - * @count: Maximum number of bytes to copy, including the trailing NUL. - * - * Copies a NUL-terminated string from userspace to kernel space. - * - * On success, returns the length of the string (not including the trailing - * NUL). - * - * If access to userspace fails, returns -EFAULT (some data may have been - * copied). - * - * If @count is smaller than the length of the string, copies @count bytes - * and returns @count. - */ - -extern int strncpy_from_user(char *dst, const char __user *src, int count); - -/* - * __clear_user: - Zero a block of memory in user space, with less checking. - * @to: Destination address, in user space. - * @n: Number of bytes to zero. - * - * Zero a block of memory in user space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be cleared. - * On success, this will be zero. - */ -extern int __clear_user(void __user *mem, int len); - -/* - * clear_user: - Zero a block of memory in user space. - * @to: Destination address, in user space. - * @n: Number of bytes to zero. - * - * Zero a block of memory in user space. - * - * Returns number of bytes that could not be cleared. - * On success, this will be zero. - */ -extern int clear_user(void __user *mem, int len); - -/* - * strlen_user: - Get the size of a string in user space. - * @str: The string to measure. - * @n: The maximum valid length - * - * Get the size of a NUL-terminated string in user space. - * - * Returns the size of the string INCLUDING the terminating NUL. - * On exception, returns 0. - * If the string is too long, returns a value greater than @n. - */ -extern int strnlen_user(const void __user *str, int len); - -#endif diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h index 293f7c794fa..cef06856333 100644 --- a/arch/um/include/shared/user.h +++ b/arch/um/include/shared/user.h @@ -6,7 +6,7 @@ #ifndef __USER_H__ #define __USER_H__ -#include "kern_constants.h" +#include <generated/asm-offsets.h> /* * The usual definition - copied here because the kernel provides its own, @@ -26,6 +26,17 @@ extern void panic(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +/* Requires preincluding include/linux/kern_levels.h */ +#define UM_KERN_EMERG KERN_EMERG +#define UM_KERN_ALERT KERN_ALERT +#define UM_KERN_CRIT KERN_CRIT +#define UM_KERN_ERR KERN_ERR +#define UM_KERN_WARNING KERN_WARNING +#define UM_KERN_NOTICE KERN_NOTICE +#define UM_KERN_INFO KERN_INFO +#define UM_KERN_DEBUG KERN_DEBUG +#define UM_KERN_CONT KERN_CONT + #ifdef UML_CONFIG_PRINTK extern int printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); @@ -36,10 +47,11 @@ static inline int printk(const char *fmt, ...) } #endif -extern void schedule(void); extern int in_aton(char *str); -extern int open_gdb_chan(void); extern size_t strlcpy(char *, const char *, size_t); extern size_t strlcat(char *, const char *, size_t); +/* Copied from linux/compiler-gcc.h since we can't include it directly */ +#define barrier() __asm__ __volatile__("": : :"memory") + #endif diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 1119233597a..d8b78a03855 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -3,20 +3,22 @@ # Licensed under the GPL # -CPPFLAGS_vmlinux.lds := -U$(SUBARCH) -DSTART=$(LDS_START) \ - -DELF_ARCH=$(LDS_ELF_ARCH) \ - -DELF_FORMAT=$(LDS_ELF_FORMAT) +CPPFLAGS_vmlinux.lds := -DSTART=$(LDS_START) \ + -DELF_ARCH=$(LDS_ELF_ARCH) \ + -DELF_FORMAT=$(LDS_ELF_FORMAT) \ + $(LDS_EXTRA) extra-y := vmlinux.lds 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 irq.o ksyms.o mem.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 \ - um_arch.o umid.o skas/ + signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \ + um_arch.o umid.o maccess.o skas/ obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o USER_OBJS := config.o diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c index 91ea538e161..1fb12235ab9 100644 --- a/arch/um/kernel/asm-offsets.c +++ b/arch/um/kernel/asm-offsets.c @@ -1 +1 @@ -#include "sysdep/kernel-offsets.h" +#include <sysdep/kernel-offsets.h> diff --git a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in index b7a43feafde..972bf165956 100644 --- a/arch/um/kernel/config.c.in +++ b/arch/um/kernel/config.c.in @@ -5,7 +5,7 @@ #include <stdio.h> #include <stdlib.h> -#include "init.h" +#include <init.h> static __initdata const char *config[] = { "CONFIG" diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index a3cab6d3ae0..adde088aeef 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -14,8 +14,6 @@ SECTIONS __binary_start = .; . = ALIGN(4096); /* Init code and data */ _text = .; - _stext = .; - __init_begin = .; INIT_TEXT_SECTION(PAGE_SIZE) . = ALIGN(PAGE_SIZE); @@ -67,6 +65,7 @@ SECTIONS } =0x90909090 .plt : { *(.plt) } .text : { + _stext = .; TEXT_TEXT SCHED_TEXT LOCK_TEXT @@ -89,9 +88,11 @@ SECTIONS .kstrtab : { *(.kstrtab) } - #include "asm/common.lds.S" + #include <asm/common.lds.S> + __init_begin = .; init.data : { INIT_DATA } + __init_end = .; /* Ensure the __preinit_array_start label is properly aligned. We could instead move the label definition inside the section, but @@ -155,6 +156,7 @@ SECTIONS . = ALIGN(32 / 8); . = ALIGN(32 / 8); } + __bss_stop = .; _end = .; PROVIDE (end = .); diff --git a/arch/um/kernel/early_printk.c b/arch/um/kernel/early_printk.c new file mode 100644 index 00000000000..4a0800bc37b --- /dev/null +++ b/arch/um/kernel/early_printk.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/console.h> +#include <linux/init.h> +#include <os.h> + +static void early_console_write(struct console *con, const char *s, unsigned int n) +{ + um_early_printk(s, n); +} + +static struct console early_console_dev = { + .name = "earlycon", + .write = early_console_write, + .flags = CON_BOOT, + .index = -1, +}; + +static int __init setup_early_printk(char *buf) +{ + if (!early_console) { + early_console = &early_console_dev; + register_console(&early_console_dev); + } + return 0; +} + +early_param("earlyprintk", setup_early_printk); diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index 09bd7b58572..0d7103c9eff 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c @@ -3,19 +3,19 @@ * Licensed under the GPL */ -#include "linux/stddef.h" -#include "linux/fs.h" -#include "linux/ptrace.h" -#include "linux/sched.h" -#include "linux/slab.h" -#include "asm/current.h" -#include "asm/processor.h" -#include "asm/uaccess.h" -#include "as-layout.h" -#include "mem_user.h" -#include "skas.h" -#include "os.h" -#include "internal.h" +#include <linux/stddef.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/ptrace.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <asm/current.h> +#include <asm/processor.h> +#include <asm/uaccess.h> +#include <as-layout.h> +#include <mem_user.h> +#include <skas.h> +#include <os.h> void flush_thread(void) { @@ -32,56 +32,19 @@ void flush_thread(void) "err = %d\n", ret); force_sig(SIGKILL, current); } + get_safe_registers(current_pt_regs()->regs.gp, + current_pt_regs()->regs.fp); __switch_mm(¤t->mm->context.id); } void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) { - set_fs(USER_DS); PT_REGS_IP(regs) = eip; PT_REGS_SP(regs) = esp; -} - -static long execve1(const char *file, - const char __user *const __user *argv, - const char __user *const __user *env) -{ - long error; - - error = do_execve(file, argv, env, ¤t->thread.regs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; + current->ptrace &= ~PT_DTRACE; #ifdef SUBARCH_EXECVE1 - SUBARCH_EXECVE1(¤t->thread.regs.regs); + SUBARCH_EXECVE1(regs->regs); #endif - task_unlock(current); - } - return error; -} - -long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) -{ - long err; - - err = execve1(file, argv, env); - if (!err) - UML_LONGJMP(current->thread.exec_buf, 1); - return err; -} - -long sys_execve(const char __user *file, const char __user *const __user *argv, - const char __user *const __user *env) -{ - long error; - char *filename; - - filename = getname(file); - error = PTR_ERR(filename); - if (IS_ERR(filename)) goto out; - error = execve1(filename, argv, env); - putname(filename); - out: - return error; } +EXPORT_SYMBOL(start_thread); diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 829df49dee9..41ebbfebb33 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -40,9 +40,11 @@ static ssize_t exitcode_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { char *end, buf[sizeof("nnnnn\0")]; + size_t size; int tmp; - if (copy_from_user(buf, buffer, count)) + size = min(count, sizeof(buf)); + if (copy_from_user(buf, buffer, size)) return -EFAULT; tmp = simple_strtol(buf, &end, 0); diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c index 72eccd2a411..1bf61266da8 100644 --- a/arch/um/kernel/gmon_syms.c +++ b/arch/um/kernel/gmon_syms.c @@ -3,22 +3,7 @@ * Licensed under the GPL */ -#include "linux/module.h" +#include <linux/module.h> extern void __bb_init_func(void *) __attribute__((weak)); EXPORT_SYMBOL(__bb_init_func); - -/* - * This is defined (and referred to in profiling stub code) only by some GCC - * versions in libgcov. - * - * Since SuSE backported the fix, we cannot handle it depending on GCC version. - * So, unconditionally export it. But also give it a weak declaration, which - * will be overridden by any other one. - */ - -extern void __gcov_init(void *) __attribute__((weak)); -EXPORT_SYMBOL(__gcov_init); - -extern void __gcov_merge_add(void *) __attribute__((weak)); -EXPORT_SYMBOL(__gcov_merge_add); diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c index e2f043d0de6..74ddb44288a 100644 --- a/arch/um/kernel/gprof_syms.c +++ b/arch/um/kernel/gprof_syms.c @@ -3,7 +3,7 @@ * Licensed under the GPL */ -#include "linux/module.h" +#include <linux/module.h> extern void mcount(void); EXPORT_SYMBOL(mcount); diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c deleted file mode 100644 index ddc9698b66e..00000000000 --- a/arch/um/kernel/init_task.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com) - * Licensed under the GPL - */ - -#include "linux/sched.h" -#include "linux/init_task.h" -#include "linux/fs.h" -#include "linux/module.h" -#include "linux/mqueue.h" -#include "asm/uaccess.h" - -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ - -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task); - -/* - * Initial thread structure. - * - * We need to make sure that this is aligned due to the - * way process stacks are handled. This is done by having a special - * "init_task" linker map entry.. - */ - -union thread_union init_thread_union __init_task_data = - { INIT_THREAD_INFO(init_task) }; - -union thread_union cpu0_irqstack - __attribute__((__section__(".data..init_irqstack"))) = - { INIT_THREAD_INFO(init_task) }; diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c index d386c75c88e..55cead809b1 100644 --- a/arch/um/kernel/initrd.c +++ b/arch/um/kernel/initrd.c @@ -3,16 +3,16 @@ * Licensed under the GPL */ -#include "linux/init.h" -#include "linux/bootmem.h" -#include "linux/initrd.h" -#include "asm/types.h" -#include "initrd.h" -#include "init.h" -#include "os.h" +#include <linux/init.h> +#include <linux/bootmem.h> +#include <linux/initrd.h> +#include <asm/types.h> +#include <init.h> +#include <os.h> /* Changed by uml_initrd_setup, which is a setup */ static char *initrd __initdata = NULL; +static int load_initrd(char *filename, void *buf, int size); static int __init read_initrd(void) { @@ -62,7 +62,7 @@ __uml_setup("initrd=", uml_initrd_setup, " name of the file containing the image.\n\n" ); -int load_initrd(char *filename, void *buf, int size) +static int load_initrd(char *filename, void *buf, int size) { int fd, n; diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h deleted file mode 100644 index 5bf97db24a0..00000000000 --- a/arch/um/kernel/internal.h +++ /dev/null @@ -1 +0,0 @@ -extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env); diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index 9e485c77030..1d8505b1e29 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -5,17 +5,17 @@ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar */ -#include "linux/cpumask.h" -#include "linux/hardirq.h" -#include "linux/interrupt.h" -#include "linux/kernel_stat.h" -#include "linux/module.h" -#include "linux/sched.h" -#include "linux/seq_file.h" -#include "linux/slab.h" -#include "as-layout.h" -#include "kern_util.h" -#include "os.h" +#include <linux/cpumask.h> +#include <linux/hardirq.h> +#include <linux/interrupt.h> +#include <linux/kernel_stat.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/seq_file.h> +#include <linux/slab.h> +#include <as-layout.h> +#include <kern_util.h> +#include <os.h> /* * This list is accessed under irq_lock, except in sigio_handler, @@ -30,7 +30,7 @@ static struct irq_fd **last_irq_ptr = &active_fds; extern void free_irqs(void); -void sigio_handler(int sig, struct uml_pt_regs *regs) +void sigio_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { struct irq_fd *irq_fd; int n; @@ -258,6 +258,7 @@ void deactivate_fd(int fd, int irqnum) ignore_sigio_fd(fd); } +EXPORT_SYMBOL(deactivate_fd); /* * Called just before shutdown in order to provide a clean exec @@ -296,6 +297,13 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs) return 1; } +void um_free_irq(unsigned int irq, void *dev) +{ + free_irq_by_irq_and_dev(irq, dev); + free_irq(irq, dev); +} +EXPORT_SYMBOL(um_free_irq); + int um_request_irq(unsigned int irq, int fd, int type, irq_handler_t handler, unsigned long irqflags, const char * devname, @@ -326,18 +334,20 @@ static void dummy(struct irq_data *d) /* This is used for everything else than the timer. */ static struct irq_chip normal_irq_type = { .name = "SIGIO", - .release = free_irq_by_irq_and_dev, .irq_disable = dummy, .irq_enable = dummy, .irq_ack = dummy, + .irq_mask = dummy, + .irq_unmask = dummy, }; static struct irq_chip SIGVTALRM_irq_type = { .name = "SIGVTALRM", - .release = free_irq_by_irq_and_dev, .irq_disable = dummy, .irq_enable = dummy, .irq_ack = dummy, + .irq_mask = dummy, + .irq_unmask = dummy, }; void __init init_IRQ(void) diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 0ae0dfcfbff..543c0475693 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -3,33 +3,11 @@ * Licensed under the GPL */ -#include "linux/module.h" -#include "linux/syscalls.h" -#include "asm/tlbflush.h" -#include "asm/uaccess.h" -#include "as-layout.h" -#include "kern_util.h" -#include "mem_user.h" -#include "os.h" +#include <linux/module.h> +#include <os.h> -EXPORT_SYMBOL(uml_physmem); EXPORT_SYMBOL(set_signals); EXPORT_SYMBOL(get_signals); -EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(sys_waitpid); -EXPORT_SYMBOL(flush_tlb_range); - -EXPORT_SYMBOL(high_physmem); -EXPORT_SYMBOL(empty_zero_page); -EXPORT_SYMBOL(handle_page_fault); -EXPORT_SYMBOL(find_iomem); - -EXPORT_SYMBOL(strnlen_user); -EXPORT_SYMBOL(strncpy_from_user); -EXPORT_SYMBOL(copy_to_user); -EXPORT_SYMBOL(copy_from_user); -EXPORT_SYMBOL(clear_user); -EXPORT_SYMBOL(uml_strdup); EXPORT_SYMBOL(os_stat_fd); EXPORT_SYMBOL(os_stat_file); @@ -57,24 +35,10 @@ EXPORT_SYMBOL(os_connect_socket); EXPORT_SYMBOL(os_accept_connection); EXPORT_SYMBOL(os_rcv_fd); EXPORT_SYMBOL(run_helper); -EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(os_major); EXPORT_SYMBOL(os_minor); EXPORT_SYMBOL(os_makedev); EXPORT_SYMBOL(add_sigio_fd); EXPORT_SYMBOL(ignore_sigio_fd); -EXPORT_SYMBOL(deactivate_fd); EXPORT_SYMBOL(sigio_broken); - -#ifdef CONFIG_SMP - -/* required for SMP */ - -extern void __write_lock_failed(rwlock_t *rw); -EXPORT_SYMBOL(__write_lock_failed); - -extern void __read_lock_failed(rwlock_t *rw); -EXPORT_SYMBOL(__read_lock_failed); - -#endif diff --git a/arch/um/kernel/maccess.c b/arch/um/kernel/maccess.c new file mode 100644 index 00000000000..1f3d5c4910d --- /dev/null +++ b/arch/um/kernel/maccess.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2013 Richard Weinberger <richrd@nod.at> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/uaccess.h> +#include <linux/kernel.h> +#include <os.h> + +long probe_kernel_read(void *dst, const void *src, size_t size) +{ + void *psrc = (void *)rounddown((unsigned long)src, PAGE_SIZE); + + if ((unsigned long)src < PAGE_SIZE || size <= 0) + return -EFAULT; + + if (os_mincore(psrc, size + src - psrc) <= 0) + return -EFAULT; + + return __probe_kernel_read(dst, src, size); +} diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 8137ccc9635..8636e905426 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -4,6 +4,7 @@ */ #include <linux/stddef.h> +#include <linux/module.h> #include <linux/bootmem.h> #include <linux/highmem.h> #include <linux/mm.h> @@ -11,15 +12,16 @@ #include <linux/slab.h> #include <asm/fixmap.h> #include <asm/page.h> -#include "as-layout.h" -#include "init.h" -#include "kern.h" -#include "kern_util.h" -#include "mem_user.h" -#include "os.h" +#include <as-layout.h> +#include <init.h> +#include <kern.h> +#include <kern_util.h> +#include <mem_user.h> +#include <os.h> /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ unsigned long *empty_zero_page = NULL; +EXPORT_SYMBOL(empty_zero_page); /* allocated in paging_init and unchanged thereafter */ static unsigned long *empty_bad_page = NULL; @@ -40,17 +42,12 @@ static unsigned long brk_end; static void setup_highmem(unsigned long highmem_start, unsigned long highmem_len) { - struct page *page; unsigned long highmem_pfn; int i; highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; - for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) { - page = &mem_map[highmem_pfn + i]; - ClearPageReserved(page); - init_page_count(page); - __free_page(page); - } + for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) + free_highmem_page(&mem_map[highmem_pfn + i]); } #endif @@ -68,21 +65,14 @@ void __init mem_init(void) uml_reserved = brk_end; /* this will put all low memory onto the freelists */ - totalram_pages = free_all_bootmem(); + free_all_bootmem(); max_low_pfn = totalram_pages; #ifdef CONFIG_HIGHMEM - totalhigh_pages = highmem >> PAGE_SHIFT; - totalram_pages += totalhigh_pages; + setup_highmem(end_iomem, highmem); #endif - num_physpages = totalram_pages; max_pfn = totalram_pages; - printk(KERN_INFO "Memory: %luk available\n", - nr_free_pages() << (PAGE_SHIFT-10)); + mem_init_print_info(NULL); kmalloc_ok = 1; - -#ifdef CONFIG_HIGHMEM - setup_highmem(end_iomem, highmem); -#endif } /* @@ -252,15 +242,7 @@ void free_initmem(void) #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - if (start < end) - printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", - (end - start) >> 10); - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - init_page_count(virt_to_page(start)); - free_page(start); - totalram_pages++; - } + free_reserved_area((void *)start, (void *)end, -1, "initrd"); } #endif @@ -297,8 +279,12 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) struct page *pte; pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO); - if (pte) - pgtable_page_ctor(pte); + if (!pte) + return NULL; + if (!pgtable_page_ctor(pte)) { + __free_page(pte); + return NULL; + } return pte; } diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index a1a9090254c..30fdd5d0067 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -3,20 +3,22 @@ * Licensed under the GPL */ -#include "linux/bootmem.h" -#include "linux/mm.h" -#include "linux/pfn.h" -#include "asm/page.h" -#include "as-layout.h" -#include "init.h" -#include "kern.h" -#include "mem_user.h" -#include "os.h" +#include <linux/module.h> +#include <linux/bootmem.h> +#include <linux/mm.h> +#include <linux/pfn.h> +#include <asm/page.h> +#include <as-layout.h> +#include <init.h> +#include <kern.h> +#include <mem_user.h> +#include <os.h> static int physmem_fd = -1; /* Changed during early boot */ unsigned long high_physmem; +EXPORT_SYMBOL(high_physmem); extern unsigned long long physmem_size; @@ -101,6 +103,7 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, */ os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE); + os_fsync_file(physmem_fd); bootmap_size = init_bootmem(pfn, pfn + delta); free_bootmem(__pa(reserve_end) + bootmap_size, @@ -184,6 +187,7 @@ unsigned long find_iomem(char *driver, unsigned long *len_out) return 0; } +EXPORT_SYMBOL(find_iomem); static int setup_iomem(void) { diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index fab4371184f..f17bca8ed2c 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -18,14 +18,15 @@ #include <linux/seq_file.h> #include <linux/tick.h> #include <linux/threads.h> +#include <linux/tracehook.h> #include <asm/current.h> #include <asm/pgtable.h> +#include <asm/mmu_context.h> #include <asm/uaccess.h> -#include "as-layout.h" -#include "kern_util.h" -#include "os.h" -#include "skas.h" -#include "tlb.h" +#include <as-layout.h> +#include <kern_util.h> +#include <os.h> +#include <skas.h> /* * This is a per-cpu array. A processor only modifies its entry and it only @@ -68,17 +69,6 @@ unsigned long alloc_stack(int order, int atomic) return page; } -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - int pid; - - current->thread.request.u.thread.proc = fn; - current->thread.request.u.thread.arg = arg; - pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, - ¤t->thread.regs, 0, NULL, NULL); - return pid; -} - static inline void set_current(struct task_struct *task) { cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) @@ -87,47 +77,34 @@ static inline void set_current(struct task_struct *task) extern void arch_switch_to(struct task_struct *to); -void *_switch_to(void *prev, void *next, void *last) +void *__switch_to(struct task_struct *from, struct task_struct *to) { - struct task_struct *from = prev; - struct task_struct *to = next; - to->thread.prev_sched = from; set_current(to); - do { - current->thread.saved_task = NULL; - - switch_threads(&from->thread.switch_buf, - &to->thread.switch_buf); - - arch_switch_to(current); - - if (current->thread.saved_task) - show_regs(&(current->thread.regs)); - to = current->thread.saved_task; - from = current; - } while (current->thread.saved_task); + switch_threads(&from->thread.switch_buf, &to->thread.switch_buf); + arch_switch_to(current); return current->thread.prev_sched; - } void interrupt_end(void) { if (need_resched()) schedule(); - if (test_tsk_thread_flag(current, TIF_SIGPENDING)) + if (test_thread_flag(TIF_SIGPENDING)) do_signal(); + if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) + tracehook_notify_resume(¤t->thread.regs); } void exit_thread(void) { } -void *get_current(void) +int get_current_pid(void) { - return current; + return task_pid_nr(current); } /* @@ -147,16 +124,10 @@ void new_thread_handler(void) arg = current->thread.request.u.thread.arg; /* - * The return value is 1 if the kernel thread execs a process, - * 0 if it just exits + * callback returns only if the kernel thread execs a process */ - n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); - if (n == 1) { - /* Handle any immediate reschedules or signals */ - interrupt_end(); - userspace(¤t->thread.regs.regs); - } - else do_exit(0); + n = fn(arg); + userspace(¤t->thread.regs.regs); } /* Called magically, see new_thread_handler above */ @@ -175,41 +146,38 @@ void fork_handler(void) current->thread.prev_sched = NULL; - /* Handle any immediate reschedules or signals */ - interrupt_end(); - userspace(¤t->thread.regs.regs); } int copy_thread(unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, - struct pt_regs *regs) + unsigned long arg, struct task_struct * p) { void (*handler)(void); + int kthread = current->flags & PF_KTHREAD; int ret = 0; p->thread = (struct thread_struct) INIT_THREAD; - if (current->thread.forking) { - memcpy(&p->thread.regs.regs, ®s->regs, + if (!kthread) { + memcpy(&p->thread.regs.regs, current_pt_regs(), sizeof(p->thread.regs.regs)); - REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.gp, 0); + PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); if (sp != 0) REGS_SP(p->thread.regs.regs.gp) = sp; handler = fork_handler; arch_copy_thread(¤t->thread.arch, &p->thread.arch); - } - else { - get_safe_registers(p->thread.regs.regs.gp); - p->thread.request.u.thread = current->thread.request.u.thread; + } else { + get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); + p->thread.request.u.thread.proc = (int (*)(void *))sp; + p->thread.request.u.thread.arg = (void *)arg; handler = new_thread_handler; } new_thread(task_stack_page(p), &p->thread.switch_buf, handler); - if (current->thread.forking) { + if (!kthread) { clear_flushed_tls(p); /* @@ -231,31 +199,14 @@ void initial_thread_cb(void (*proc)(void *), void *arg) kmalloc_ok = save_kmalloc_ok; } -void default_idle(void) +void arch_cpu_idle(void) { unsigned long long nsecs; - while (1) { - /* endless idle loop with no priority at all */ - - /* - * although we are an idle CPU, we do not want to - * get into the scheduler unnecessarily. - */ - if (need_resched()) - schedule(); - - tick_nohz_stop_sched_tick(1); - nsecs = disable_timer(); - idle_sleep(nsecs); - tick_nohz_restart_sched_tick(); - } -} - -void cpu_idle(void) -{ cpu_tasks[current_thread_info()->cpu].pid = os_getpid(); - default_idle(); + nsecs = disable_timer(); + idle_sleep(nsecs); + local_irq_enable(); } int __cant_sleep(void) { @@ -286,6 +237,7 @@ char *uml_strdup(const char *string) { return kstrdup(string, GFP_KERNEL); } +EXPORT_SYMBOL(uml_strdup); int copy_to_user_proc(void __user *to, void *from, int size) { @@ -407,7 +359,7 @@ int singlestepping(void * t) /* * Only x86 and x86_64 have an arch_align_stack(). * All other arches have "#define arch_align_stack(x) (x)" - * in their asm/system.h + * in their asm/exec.h * As this is included in UML from asm-um/system-generic.h, * we can use it to behave as the subarch does. */ diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 701b672c112..694d551c889 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -3,11 +3,12 @@ * Licensed under the GPL */ -#include "linux/audit.h" -#include "linux/ptrace.h" -#include "linux/sched.h" -#include "asm/uaccess.h" -#include "skas_ptrace.h" +#include <linux/audit.h> +#include <linux/ptrace.h> +#include <linux/sched.h> +#include <linux/tracehook.h> +#include <asm/uaccess.h> +#include <skas_ptrace.h> @@ -50,23 +51,11 @@ long arch_ptrace(struct task_struct *child, long request, void __user *vp = p; switch (request) { - /* read word at location addr. */ - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: ret = peek_user(child, addr, data); break; - /* write the word at location addr. */ - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - /* write the word at location addr in the USER area */ case PTRACE_POKEUSR: ret = poke_user(child, addr, data); @@ -107,16 +96,6 @@ long arch_ptrace(struct task_struct *child, long request, break; } #endif -#ifdef PTRACE_GETFPREGS - case PTRACE_GETFPREGS: /* Get the child FPU state. */ - ret = get_fpregs(vp, child); - break; -#endif -#ifdef PTRACE_SETFPREGS - case PTRACE_SETFPREGS: /* Set the child FPU state. */ - ret = set_fpregs(vp, child); - break; -#endif case PTRACE_GET_THREAD_AREA: ret = ptrace_get_thread_area(child, addr, vp); break; @@ -154,12 +133,6 @@ long arch_ptrace(struct task_struct *child, long request, break; } #endif -#ifdef PTRACE_ARCH_PRCTL - case PTRACE_ARCH_PRCTL: - /* XXX Calls ptrace on the host - needs some SMP thinking */ - ret = arch_prctl(child, data, (void __user *) addr); - break; -#endif default: ret = ptrace_request(child, request, addr, data); if (ret == -EIO) @@ -190,50 +163,36 @@ static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check */ -void syscall_trace(struct uml_pt_regs *regs, int entryexit) +void syscall_trace_enter(struct pt_regs *regs) { - int is_singlestep = (current->ptrace & PT_DTRACE) && entryexit; - int tracesysgood; - - if (unlikely(current->audit_context)) { - if (!entryexit) - audit_syscall_entry(HOST_AUDIT_ARCH, - UPT_SYSCALL_NR(regs), - UPT_SYSCALL_ARG1(regs), - UPT_SYSCALL_ARG2(regs), - UPT_SYSCALL_ARG3(regs), - UPT_SYSCALL_ARG4(regs)); - else audit_syscall_exit(AUDITSC_RESULT(UPT_SYSCALL_RET(regs)), - UPT_SYSCALL_RET(regs)); - } - - /* Fake a debug trap */ - if (is_singlestep) - send_sigtrap(current, regs, 0); + audit_syscall_entry(HOST_AUDIT_ARCH, + UPT_SYSCALL_NR(®s->regs), + UPT_SYSCALL_ARG1(®s->regs), + UPT_SYSCALL_ARG2(®s->regs), + UPT_SYSCALL_ARG3(®s->regs), + UPT_SYSCALL_ARG4(®s->regs)); if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; - if (!(current->ptrace & PT_PTRACED)) - return; + tracehook_report_syscall_entry(regs); +} - /* - * the 0x80 provides a way for the tracing parent to distinguish - * between a syscall stop and SIGTRAP delivery - */ - tracesysgood = (current->ptrace & PT_TRACESYSGOOD); - ptrace_notify(SIGTRAP | (tracesysgood ? 0x80 : 0)); +void syscall_trace_leave(struct pt_regs *regs) +{ + int ptraced = current->ptrace; - if (entryexit) /* force do_signal() --> is_syscall() */ - set_thread_flag(TIF_SIGPENDING); + audit_syscall_exit(regs); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } + /* Fake a debug trap */ + if (ptraced & PT_DTRACE) + send_sigtrap(current, ®s->regs, 0); + + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + + tracehook_report_syscall_exit(regs, 0); + /* force do_signal() --> is_syscall() */ + if (ptraced & PT_PTRACED) + set_thread_flag(TIF_SIGPENDING); } diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 869bec9f251..ced8903921a 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -3,11 +3,13 @@ * Licensed under the GPL */ -#include "linux/sched.h" -#include "linux/slab.h" -#include "kern_util.h" -#include "os.h" -#include "skas.h" +#include <linux/sched.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/oom.h> +#include <kern_util.h> +#include <os.h> +#include <skas.h> void (*pm_power_off)(void); @@ -20,16 +22,20 @@ static void kill_off_processes(void) os_kill_ptraced_process(userspace_pid[0], 1); else { struct task_struct *p; - int pid, me; + int pid; - me = os_getpid(); + read_lock(&tasklist_lock); for_each_process(p) { - if (p->mm == NULL) - continue; + struct task_struct *t; - pid = p->mm->context.id.u.pid; + t = find_lock_task_mm(p); + if (!t) + continue; + pid = t->mm->context.id.u.pid; + task_unlock(t); os_kill_ptraced_process(pid, 1); } + read_unlock(&tasklist_lock); } } diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c index 2b272b63b51..b5e0cbb3438 100644 --- a/arch/um/kernel/sigio.c +++ b/arch/um/kernel/sigio.c @@ -4,9 +4,9 @@ */ #include <linux/interrupt.h> -#include "irq_kern.h" -#include "os.h" -#include "sigio.h" +#include <irq_kern.h> +#include <os.h> +#include <sigio.h> /* Protected by sigio_lock() called from write_sigio_workaround */ static int sigio_irq_fd = -1; @@ -25,8 +25,7 @@ int write_sigio_irq(int fd) int err; err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, - IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio", - NULL); + 0, "write sigio", NULL); if (err) { printk(KERN_ERR "write_sigio_irq : um_request_irq failed, " "err = %d\n", err); diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index b5c094c4ade..f57e02e7910 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c @@ -9,29 +9,25 @@ #include <asm/siginfo.h> #include <asm/signal.h> #include <asm/unistd.h> -#include "frame_kern.h" -#include "kern_util.h" -#include <sysdep/sigcontext.h> +#include <frame_kern.h> +#include <kern_util.h> EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(unblock_signals); -#define _S(nr) (1<<((nr)-1)) - -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) - /* * OK, we're invoking a handler */ -static int handle_signal(struct pt_regs *regs, unsigned long signr, - struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset) +static void handle_signal(struct pt_regs *regs, unsigned long signr, + struct k_sigaction *ka, struct siginfo *info) { + sigset_t *oldset = sigmask_to_save(); + int singlestep = 0; unsigned long sp; int err; - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; + if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) + singlestep = 1; /* Did we come from a system call? */ if (PT_REGS_SYSCALL_NR(regs) >= 0) { @@ -66,51 +62,22 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, #endif err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); - if (err) { - spin_lock_irq(¤t->sighand->siglock); - current->blocked = *oldset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + if (err) force_sigsegv(signr, current); - } else { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - - return err; + else + signal_delivered(signr, info, ka, regs, singlestep); } static int kern_do_signal(struct pt_regs *regs) { struct k_sigaction ka_copy; - siginfo_t info; - sigset_t *oldset; + struct siginfo info; int sig, handled_sig = 0; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { handled_sig = 1; /* Whee! Actually deliver the signal. */ - if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) { - /* - * a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - break; - } + handle_signal(regs, sig, &ka_copy, &info); } /* Did we come from a system call? */ @@ -146,10 +113,8 @@ static int kern_do_signal(struct pt_regs *regs) * if there's no signal to deliver, we just put the saved sigmask * back */ - if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } + if (!handled_sig) + restore_saved_sigmask(); return handled_sig; } @@ -157,26 +122,3 @@ int do_signal(void) { return kern_do_signal(¤t->thread.regs); } - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -long sys_sigsuspend(int history0, int history1, old_sigset_t mask) -{ - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - -long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) -{ - return do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)); -} diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 2c8583c1a34..289771dadf8 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -7,11 +7,10 @@ #include <sched.h> #include <asm/unistd.h> #include <sys/time.h> -#include "as-layout.h" -#include "kern_constants.h" -#include "ptrace_user.h" -#include "stub-data.h" -#include "sysdep/stub.h" +#include <as-layout.h> +#include <ptrace_user.h> +#include <stub-data.h> +#include <sysdep/stub.h> /* * This is in a separate file because it needs to be compiled with any diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 1aee587e9c5..007d5503f49 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -3,14 +3,14 @@ * Licensed under the GPL */ -#include "linux/mm.h" -#include "linux/sched.h" -#include "linux/slab.h" -#include "asm/pgalloc.h" -#include "asm/pgtable.h" -#include "as-layout.h" -#include "os.h" -#include "skas.h" +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/slab.h> +#include <asm/pgalloc.h> +#include <asm/pgtable.h> +#include <as-layout.h> +#include <os.h> +#include <skas.h> extern int __syscall_stub_start; @@ -92,8 +92,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) goto out_free; } - to_mm->stub_pages = NULL; - return 0; out_free: @@ -103,9 +101,8 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) return ret; } -void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) +void uml_setup_stubs(struct mm_struct *mm) { - struct page **pages; int err, ret; if (!skas_needs_stub) @@ -120,29 +117,20 @@ void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) if (ret) goto out; - pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL); - if (pages == NULL) { - printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page " - "pointers\n"); - goto out; - } - - pages[0] = virt_to_page(&__syscall_stub_start); - pages[1] = virt_to_page(mm->context.id.stack); - mm->context.stub_pages = pages; + mm->context.stub_pages[0] = virt_to_page(&__syscall_stub_start); + mm->context.stub_pages[1] = virt_to_page(mm->context.id.stack); /* dup_mmap already holds mmap_sem */ err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START, VM_READ | VM_MAYREAD | VM_EXEC | - VM_MAYEXEC | VM_DONTCOPY, pages); + VM_MAYEXEC | VM_DONTCOPY | VM_PFNMAP, + mm->context.stub_pages); if (err) { printk(KERN_ERR "install_special_mapping returned %d\n", err); - goto out_free; + goto out; } return; -out_free: - kfree(pages); out: force_sigsegv(SIGSEGV, current); } @@ -151,8 +139,6 @@ void arch_exit_mmap(struct mm_struct *mm) { pte_t *pte; - if (mm->context.stub_pages != NULL) - kfree(mm->context.stub_pages); pte = virt_to_pte(mm, STUB_CODE); if (pte != NULL) pte_clear(mm, STUB_CODE, pte); diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 2e9852c0d48..4da11b3c8dd 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -3,12 +3,12 @@ * Licensed under the GPL */ -#include "linux/init.h" -#include "linux/sched.h" -#include "as-layout.h" -#include "kern.h" -#include "os.h" -#include "skas.h" +#include <linux/init.h> +#include <linux/sched.h> +#include <as-layout.h> +#include <kern.h> +#include <os.h> +#include <skas.h> int new_mm(unsigned long stack) { @@ -41,7 +41,7 @@ static int __init start_kernel_proc(void *unused) cpu_tasks[0].pid = pid; cpu_tasks[0].task = current; #ifdef CONFIG_SMP - cpu_online_map = cpumask_of_cpu(0); + init_cpu_online(get_cpu_mask(0)); #endif start_kernel(); return 0; diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index f5173e1ec3a..c0681e09743 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -3,11 +3,11 @@ * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/ptrace.h" -#include "kern_util.h" -#include "sysdep/ptrace.h" -#include "sysdep/syscalls.h" +#include <linux/kernel.h> +#include <linux/ptrace.h> +#include <kern_util.h> +#include <sysdep/ptrace.h> +#include <sysdep/syscalls.h> extern int syscall_table_size; #define NR_SYSCALLS (syscall_table_size / sizeof(void *)) @@ -18,7 +18,7 @@ void handle_syscall(struct uml_pt_regs *r) long result; int syscall; - syscall_trace(r, 0); + syscall_trace_enter(regs); /* * This should go in the declaration of syscall, but when I do that, @@ -34,7 +34,7 @@ void handle_syscall(struct uml_pt_regs *r) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); - REGS_SET_SYSCALL_RETURN(r->gp, result); + PT_REGS_SET_SYSCALL_RETURN(regs, result); - syscall_trace(r, 1); + syscall_trace_leave(regs); } diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 696634214dc..4ffb644d6c0 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -6,12 +6,13 @@ #include <linux/err.h> #include <linux/highmem.h> #include <linux/mm.h> +#include <linux/module.h> #include <linux/sched.h> #include <asm/current.h> #include <asm/page.h> #include <asm/pgtable.h> -#include "kern_util.h" -#include "os.h" +#include <kern_util.h> +#include <os.h> pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr) { @@ -68,7 +69,7 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, return -1; page = pte_page(*pte); - addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) + + addr = (unsigned long) kmap_atomic(page) + (addr & ~PAGE_MASK); current->thread.fault_catcher = &buf; @@ -81,7 +82,7 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, current->thread.fault_catcher = NULL; - kunmap_atomic((void *)addr, KM_UML_USERCOPY); + kunmap_atomic((void *)addr); return n; } @@ -149,6 +150,7 @@ int copy_from_user(void *to, const void __user *from, int n) buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): n; } +EXPORT_SYMBOL(copy_from_user); static int copy_chunk_to_user(unsigned long to, int len, void *arg) { @@ -170,6 +172,7 @@ int copy_to_user(void __user *to, const void *from, int n) buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : n; } +EXPORT_SYMBOL(copy_to_user); static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) { @@ -204,6 +207,7 @@ int strncpy_from_user(char *dst, const char __user *src, int count) return -EFAULT; return strnlen(dst, count); } +EXPORT_SYMBOL(strncpy_from_user); static int clear_chunk(unsigned long addr, int len, void *unused) { @@ -226,6 +230,7 @@ int clear_user(void __user *mem, int len) return access_ok(VERIFY_WRITE, mem, len) ? buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; } +EXPORT_SYMBOL(clear_user); static int strnlen_chunk(unsigned long str, int len, void *arg) { @@ -249,5 +254,6 @@ int strnlen_user(const void __user *str, int len) n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); if (n == 0) return count + 1; - return -EFAULT; + return 0; } +EXPORT_SYMBOL(strnlen_user); diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 106bf27e2a9..5c8c3ea7db7 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c @@ -3,27 +3,24 @@ * Licensed under the GPL */ -#include "linux/percpu.h" -#include "asm/pgalloc.h" -#include "asm/tlb.h" - -/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +#include <linux/percpu.h> +#include <asm/pgalloc.h> +#include <asm/tlb.h> #ifdef CONFIG_SMP -#include "linux/sched.h" -#include "linux/module.h" -#include "linux/threads.h" -#include "linux/interrupt.h" -#include "linux/err.h" -#include "linux/hardirq.h" -#include "asm/smp.h" -#include "asm/processor.h" -#include "asm/spinlock.h" -#include "kern.h" -#include "irq_user.h" -#include "os.h" +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/threads.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/hardirq.h> +#include <asm/smp.h> +#include <asm/processor.h> +#include <asm/spinlock.h> +#include <kern.h> +#include <irq_user.h> +#include <os.h> /* Per CPU bogomips and other parameters * The only piece used here is the ipi pipe, which is set before SMP is @@ -79,7 +76,7 @@ static int idle_proc(void *cpup) cpu_relax(); notify_cpu_starting(cpu); - cpu_set(cpu, cpu_online_map); + set_cpu_online(cpu, true); default_idle(); return 0; } @@ -113,8 +110,7 @@ void smp_prepare_cpus(unsigned int maxcpus) for (i = 0; i < ncpus; ++i) set_cpu_possible(i, true); - cpu_clear(me, cpu_online_map); - cpu_set(me, cpu_online_map); + set_cpu_online(me, true); cpu_set(me, cpu_callin_map); err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); @@ -141,13 +137,13 @@ void smp_prepare_cpus(unsigned int maxcpus) void smp_prepare_boot_cpu(void) { - cpu_set(smp_processor_id(), cpu_online_map); + set_cpu_online(smp_processor_id(), true); } -int __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu, struct task_struct *tidle) { cpu_set(cpu, smp_commenced_mask); - while (!cpu_isset(cpu, cpu_online_map)) + while (!cpu_online(cpu)) mb(); return 0; } @@ -173,7 +169,7 @@ void IPI_handler(int cpu) break; case 'R': - set_tsk_need_resched(current); + scheduler_ipi(); break; case 'S': diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index f958cb876ee..c1d0ae069b5 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -3,40 +3,16 @@ * Licensed under the GPL */ -#include "linux/file.h" -#include "linux/fs.h" -#include "linux/mm.h" -#include "linux/sched.h" -#include "linux/utsname.h" -#include "linux/syscalls.h" -#include "asm/current.h" -#include "asm/mman.h" -#include "asm/uaccess.h" -#include "asm/unistd.h" -#include "internal.h" - -long sys_fork(void) -{ - long ret; - - current->thread.forking = 1; - ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), - ¤t->thread.regs, 0, NULL, NULL); - current->thread.forking = 0; - return ret; -} - -long sys_vfork(void) -{ - long ret; - - current->thread.forking = 1; - ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, - UPT_SP(¤t->thread.regs.regs), - ¤t->thread.regs, 0, NULL, NULL); - current->thread.forking = 0; - return ret; -} +#include <linux/file.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/utsname.h> +#include <linux/syscalls.h> +#include <asm/current.h> +#include <asm/mman.h> +#include <asm/uaccess.h> +#include <asm/unistd.h> long old_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, @@ -50,19 +26,3 @@ long old_mmap(unsigned long addr, unsigned long len, out: return err; } - -int kernel_execve(const char *filename, - const char *const argv[], - const char *const envp[]) -{ - mm_segment_t fs; - int ret; - - fs = get_fs(); - set_fs(KERNEL_DS); - ret = um_execve(filename, (const char __user *const __user *)argv, - (const char __user *const __user *) envp); - set_fs(fs); - - return ret; -} diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index 0960de54495..799d7e413bf 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -1,78 +1,98 @@ /* * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL + * Copyright (C) 2013 Richard Weinberger <richrd@nod.at> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ #include <linux/kallsyms.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h> -#include "sysrq.h" +#include <asm/sysrq.h> +#include <os.h> -/* Catch non-i386 SUBARCH's. */ -#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT) -void show_trace(struct task_struct *task, unsigned long * stack) +struct stack_frame { + struct stack_frame *next_frame; + unsigned long return_address; +}; + +static void do_stack_trace(unsigned long *sp, unsigned long bp) { + int reliable; unsigned long addr; + struct stack_frame *frame = (struct stack_frame *)bp; - if (!stack) { - stack = (unsigned long*) &stack; - WARN_ON(1); - } - - printk(KERN_INFO "Call Trace: \n"); - while (((long) stack & (THREAD_SIZE-1)) != 0) { - addr = *stack; + printk(KERN_INFO "Call Trace:\n"); + while (((long) sp & (THREAD_SIZE-1)) != 0) { + addr = *sp; if (__kernel_text_address(addr)) { - printk(KERN_INFO "%08lx: [<%08lx>]", - (unsigned long) stack, addr); - print_symbol(KERN_CONT " %s", addr); + reliable = 0; + if ((unsigned long) sp == bp + sizeof(long)) { + frame = frame ? frame->next_frame : NULL; + bp = (unsigned long)frame; + reliable = 1; + } + + printk(KERN_INFO " [<%08lx>]", addr); + printk(KERN_CONT " %s", reliable ? "" : "? "); + print_symbol(KERN_CONT "%s", addr); printk(KERN_CONT "\n"); } - stack++; + sp++; } printk(KERN_INFO "\n"); } -#endif -/* - * stack dumps generator - this is used by arch-independent code. - * And this is identical to i386 currently. - */ -void dump_stack(void) +static unsigned long get_frame_pointer(struct task_struct *task, + struct pt_regs *segv_regs) { - unsigned long stack; - - show_trace(current, &stack); + if (!task || task == current) + return segv_regs ? PT_REGS_BP(segv_regs) : current_bp(); + else + return KSTK_EBP(task); } -EXPORT_SYMBOL(dump_stack); -/*Stolen from arch/i386/kernel/traps.c */ -static const int kstack_depth_to_print = 24; +static unsigned long *get_stack_pointer(struct task_struct *task, + struct pt_regs *segv_regs) +{ + if (!task || task == current) + return segv_regs ? (unsigned long *)PT_REGS_SP(segv_regs) : current_sp(); + else + return (unsigned long *)KSTK_ESP(task); +} -/* This recently started being used in arch-independent code too, as in - * kernel/sched.c.*/ -void show_stack(struct task_struct *task, unsigned long *esp) +void show_stack(struct task_struct *task, unsigned long *stack) { - unsigned long *stack; + unsigned long *sp = stack, bp = 0; + struct pt_regs *segv_regs = current->thread.segv_regs; int i; - if (esp == NULL) { - if (task != current && task != NULL) { - esp = (unsigned long *) KSTK_ESP(task); - } else { - esp = (unsigned long *) &esp; - } + if (!segv_regs && os_is_signal_stack()) { + printk(KERN_ERR "Received SIGSEGV in SIGSEGV handler," + " aborting stack trace!\n"); + return; } - stack = esp; - for (i = 0; i < kstack_depth_to_print; i++) { +#ifdef CONFIG_FRAME_POINTER + bp = get_frame_pointer(task, segv_regs); +#endif + + if (!stack) + sp = get_stack_pointer(task, segv_regs); + + printk(KERN_INFO "Stack:\n"); + stack = sp; + for (i = 0; i < 3 * STACKSLOTS_PER_LINE; i++) { if (kstack_end(stack)) break; - if (i && ((i % 8) == 0)) - printk(KERN_INFO " "); - printk(KERN_CONT "%08lx ", *stack++); + if (i && ((i % STACKSLOTS_PER_LINE) == 0)) + printk(KERN_CONT "\n"); + printk(KERN_CONT " %08lx", *stack++); } + printk(KERN_CONT "\n"); - show_trace(task, esp); + do_stack_trace(sp, bp); } diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index a08d9fab81f..117568d4f64 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -10,10 +10,10 @@ #include <linux/threads.h> #include <asm/irq.h> #include <asm/param.h> -#include "kern_util.h" -#include "os.h" +#include <kern_util.h> +#include <os.h> -void timer_handler(int sig, struct uml_pt_regs *regs) +void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { unsigned long flags; @@ -75,8 +75,6 @@ static struct clocksource itimer_clocksource = { .rating = 300, .read = itimer_read, .mask = CLOCKSOURCE_MASK(64), - .mult = 1000, - .shift = 0, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -84,7 +82,7 @@ static void __init setup_itimer(void) { int err; - err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); + err = request_irq(TIMER_IRQ, um_timer, 0, "timer", NULL); if (err != 0) printk(KERN_ERR "register_timer : request_irq failed - " "errno = %d\n", -err); @@ -94,9 +92,9 @@ static void __init setup_itimer(void) clockevent_delta2ns(60 * HZ, &itimer_clockevent); itimer_clockevent.min_delta_ns = clockevent_delta2ns(1, &itimer_clockevent); - err = clocksource_register(&itimer_clocksource); + err = clocksource_register_hz(&itimer_clocksource, USEC_PER_SEC); if (err) { - printk(KERN_ERR "clocksource_register returned %d\n", err); + printk(KERN_ERR "clocksource_register_hz returned %d\n", err); return; } clockevents_register_device(&itimer_clockevent); diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index d175d0566af..f1b3eb14b85 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -4,14 +4,15 @@ */ #include <linux/mm.h> +#include <linux/module.h> #include <linux/sched.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> -#include "as-layout.h" -#include "mem_user.h" -#include "os.h" -#include "skas.h" -#include "tlb.h" +#include <as-layout.h> +#include <mem_user.h> +#include <os.h> +#include <skas.h> +#include <kern_util.h> struct host_vm_change { struct host_vm_op { @@ -75,6 +76,7 @@ static int do_ops(struct host_vm_change *hvc, int end, default: printk(KERN_ERR "Unknown op type %d in do_ops\n", op->type); + BUG(); break; } } @@ -123,6 +125,9 @@ static int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *last; int ret = 0; + if ((addr >= STUB_START) && (addr < STUB_END)) + return -EINVAL; + if (hvc->index != 0) { last = &hvc->ops[hvc->index - 1]; if ((last->type == MUNMAP) && @@ -282,12 +287,15 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, /* This is not an else because ret is modified above */ if (ret) { printk(KERN_ERR "fix_range_common: failed, killing current " - "process\n"); + "process: %d\n", task_tgid_vnr(current)); + /* We are under mmap_sem, release it such that current can terminate */ + up_write(¤t->mm->mmap_sem); force_sig(SIGKILL, current); + do_signal(); } } -int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) +static int flush_tlb_kernel_range_common(unsigned long start, unsigned long end) { struct mm_struct *mm; pgd_t *pgd; @@ -499,6 +507,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, flush_tlb_kernel_range_common(start, end); else fix_range(vma->vm_mm, start, end, 0); } +EXPORT_SYMBOL(flush_tlb_range); void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start, unsigned long end) diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 637c6505dc0..5678c3571e7 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -6,15 +6,15 @@ #include <linux/mm.h> #include <linux/sched.h> #include <linux/hardirq.h> +#include <linux/module.h> #include <asm/current.h> #include <asm/pgtable.h> #include <asm/tlbflush.h> -#include "arch.h" -#include "as-layout.h" -#include "kern_util.h" -#include "os.h" -#include "skas.h" -#include "sysdep/sigcontext.h" +#include <arch.h> +#include <as-layout.h> +#include <kern_util.h> +#include <os.h> +#include <skas.h> /* * Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by @@ -30,6 +30,7 @@ int handle_page_fault(unsigned long address, unsigned long ip, pmd_t *pmd; pte_t *pte; int err = -EFAULT; + unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; *code_out = SEGV_MAPERR; @@ -40,6 +41,9 @@ int handle_page_fault(unsigned long address, unsigned long ip, if (in_atomic()) goto out_nosemaphore; + if (is_user) + flags |= FAULT_FLAG_USER; +retry: down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -55,17 +59,24 @@ int handle_page_fault(unsigned long address, unsigned long ip, good_area: *code_out = SEGV_ACCERR; - if (is_write && !(vma->vm_flags & VM_WRITE)) - goto out; - - /* Don't require VM_READ|VM_EXEC for write faults! */ - if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC))) - goto out; + if (is_write) { + if (!(vma->vm_flags & VM_WRITE)) + goto out; + flags |= FAULT_FLAG_WRITE; + } else { + /* Don't require VM_READ|VM_EXEC for write faults! */ + if (!(vma->vm_flags & (VM_READ | VM_EXEC))) + goto out; + } do { int fault; - fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); + fault = handle_mm_fault(mm, vma, address, flags); + + if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) + goto out_nosemaphore; + if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) { goto out_of_memory; @@ -75,10 +86,18 @@ good_area: } BUG(); } - if (fault & VM_FAULT_MAJOR) - current->maj_flt++; - else - current->min_flt++; + if (flags & FAULT_FLAG_ALLOW_RETRY) { + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; + if (fault & VM_FAULT_RETRY) { + flags &= ~FAULT_FLAG_ALLOW_RETRY; + flags |= FAULT_FLAG_TRIED; + + goto retry; + } + } pgd = pgd_offset(mm, address); pud = pud_offset(pgd, address); @@ -109,9 +128,33 @@ out_of_memory: * (which will retry the fault, or kill us if we got oom-killed). */ up_read(&mm->mmap_sem); + if (!is_user) + goto out_nosemaphore; pagefault_out_of_memory(); return 0; } +EXPORT_SYMBOL(handle_page_fault); + +static void show_segv_info(struct uml_pt_regs *regs) +{ + struct task_struct *tsk = current; + struct faultinfo *fi = UPT_FAULTINFO(regs); + + if (!unhandled_signal(tsk, SIGSEGV)) + return; + + if (!printk_ratelimit()) + return; + + printk("%s%s[%d]: segfault at %lx ip %p sp %p error %x", + task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG, + tsk->comm, task_pid_nr(tsk), FAULT_ADDRESS(*fi), + (void *)UPT_IP(regs), (void *)UPT_SP(regs), + fi->error_code); + + print_vma_addr(KERN_CONT " in ", UPT_IP(regs)); + printk(KERN_CONT "\n"); +} static void bad_segv(struct faultinfo fi, unsigned long ip) { @@ -136,11 +179,12 @@ void fatal_sigsegv(void) os_dump_core(); } -void segv_handler(int sig, struct uml_pt_regs *regs) +void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { struct faultinfo * fi = UPT_FAULTINFO(regs); if (UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)) { + show_segv_info(regs); bad_segv(*fi, UPT_IP(regs)); return; } @@ -162,9 +206,12 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, int is_write = FAULT_WRITE(fi); unsigned long address = FAULT_ADDRESS(fi); + if (!is_user && regs) + current->thread.segv_regs = container_of(regs, struct pt_regs, regs); + if (!is_user && (address >= start_vm) && (address < end_vm)) { flush_tlb_kernel_vm(); - return 0; + goto out; } else if (current->mm == NULL) { show_regs(container_of(regs, struct pt_regs, regs)); @@ -186,7 +233,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, catcher = current->thread.fault_catcher; if (!err) - return 0; + goto out; else if (catcher != NULL) { current->thread.fault_addr = (void *) address; UML_LONGJMP(catcher, 1); @@ -194,7 +241,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, else if (current->thread.fault_addr != NULL) panic("fault_addr set but no fault catcher"); else if (!is_user && arch_fixup(ip, regs)) - return 0; + goto out; if (!is_user) { show_regs(container_of(regs, struct pt_regs, regs)); @@ -202,6 +249,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, address, ip); } + show_segv_info(regs); + if (err == -EACCES) { si.si_signo = SIGBUS; si.si_errno = 0; @@ -216,11 +265,19 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, current->thread.arch.faultinfo = fi; force_sig_info(SIGSEGV, &si, current); } + +out: + if (regs) + current->thread.segv_regs = NULL; + return 0; } -void relay_signal(int sig, struct uml_pt_regs *regs) +void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs) { + struct faultinfo *fi; + struct siginfo clean_si; + if (!UPT_IS_USER(regs)) { if (sig == SIGBUS) printk(KERN_ERR "Bus error - the host /dev/shm or /tmp " @@ -230,18 +287,40 @@ void relay_signal(int sig, struct uml_pt_regs *regs) arch_examine_signal(sig, regs); - current->thread.arch.faultinfo = *UPT_FAULTINFO(regs); - force_sig(sig, current); + memset(&clean_si, 0, sizeof(clean_si)); + clean_si.si_signo = si->si_signo; + clean_si.si_errno = si->si_errno; + clean_si.si_code = si->si_code; + switch (sig) { + case SIGILL: + case SIGFPE: + case SIGSEGV: + case SIGBUS: + case SIGTRAP: + fi = UPT_FAULTINFO(regs); + clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi); + current->thread.arch.faultinfo = *fi; +#ifdef __ARCH_SI_TRAPNO + clean_si.si_trapno = si->si_trapno; +#endif + break; + default: + printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n", + sig, si->si_code); + } + + force_sig_info(sig, &clean_si, current); } -void bus_handler(int sig, struct uml_pt_regs *regs) +void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs) { if (current->thread.fault_catcher != NULL) UML_LONGJMP(current->thread.fault_catcher, 1); - else relay_signal(sig, regs); + else + relay_signal(sig, si, regs); } -void winch(int sig, struct uml_pt_regs *regs) +void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs) { do_IRQ(WINCH_IRQ, regs); } diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c deleted file mode 100644 index dd33f040c52..00000000000 --- a/arch/um/kernel/uaccess.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -/* - * These are here rather than tt/uaccess.c because skas mode needs them in - * order to do SIGBUS recovery when a tmpfs mount runs out of room. - */ - -#include <linux/string.h> -#include "os.h" - -static void __do_copy(void *to, const void *from, int n) -{ - memcpy(to, from, n); -} - - -int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher) -{ - unsigned long fault; - int faulted; - - fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, - __do_copy, &faulted); - if (!faulted) - return 0; - else - return n - (fault - (unsigned long) to); -} diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 8d84250324b..016adf0985d 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -10,16 +10,18 @@ #include <linux/seq_file.h> #include <linux/string.h> #include <linux/utsname.h> +#include <linux/sched.h> #include <asm/pgtable.h> #include <asm/processor.h> +#include <asm/sections.h> #include <asm/setup.h> -#include "as-layout.h" -#include "arch.h" -#include "init.h" -#include "kern.h" -#include "kern_util.h" -#include "mem_user.h" -#include "os.h" +#include <as-layout.h> +#include <arch.h> +#include <init.h> +#include <kern.h> +#include <kern_util.h> +#include <mem_user.h> +#include <os.h> #define DEFAULT_COMMAND_LINE "root=98:0" @@ -47,6 +49,10 @@ struct cpuinfo_um boot_cpu_data = { .ipi_pipe = { -1, -1 } }; +union thread_union cpu0_irqstack + __attribute__((__section__(".data..init_irqstack"))) = + { INIT_THREAD_INFO(init_task) }; + unsigned long thread_saved_pc(struct task_struct *task) { /* FIXME: Need to look up userspace_pid by cpu */ @@ -102,6 +108,8 @@ const struct seq_operations cpuinfo_op = { /* Set in linux_main */ unsigned long uml_physmem; +EXPORT_SYMBOL(uml_physmem); + unsigned long uml_reserved; /* Also modified in mem_init */ unsigned long start_vm; unsigned long end_vm; @@ -227,7 +235,6 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1, void *unused2) { bust_spinlocks(1); - show_regs(&(current->thread.regs)); bust_spinlocks(0); uml_exitcode = 1; os_dump_core(); diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 81e07e2be3a..f6cc3bd6178 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -4,9 +4,9 @@ */ #include <asm/errno.h> -#include "init.h" -#include "kern.h" -#include "os.h" +#include <init.h> +#include <kern.h> +#include <os.h> /* Changed by set_umid_arg */ static int umid_inited = 0; diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index fbd99402d4d..6899195602b 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -20,13 +20,12 @@ SECTIONS . = START + SIZEOF_HEADERS; _text = .; - _stext = .; - __init_begin = .; INIT_TEXT_SECTION(0) . = ALIGN(PAGE_SIZE); .text : { + _stext = .; TEXT_TEXT SCHED_TEXT LOCK_TEXT @@ -60,9 +59,12 @@ SECTIONS PROVIDE_HIDDEN(__rela_iplt_end = .); } - #include "asm/common.lds.S" + #include <asm/common.lds.S> + __init_begin = .; init.data : { INIT_DATA } + __init_end = .; + .data : { INIT_TASK_DATA(KERNEL_STACK_SIZE) @@ -97,6 +99,7 @@ SECTIONS PROVIDE(_bss_start = .); SBSS(0) BSS(0) + __bss_stop = .; _end = .; PROVIDE (end = .); diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index d66f0388f09..08ff5094fcd 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,15 +3,15 @@ # Licensed under the GPL # -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 tty.o uaccess.o \ - umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/ +obj-y = aio.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 tty.o \ + umid.o user_syms.o util.o drivers/ skas/ + +obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o USER_OBJS := $(user-objs-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 \ - tty.o tls.o uaccess.o umid.o util.o - -CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH) + tty.o umid.o util.o HAVE_AIO_ABI := $(shell [ -r /usr/include/linux/aio_abi.h ] && \ echo -DHAVE_AIO_ABI ) diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c index 57e3d46c989..014eb35fd13 100644 --- a/arch/um/os-Linux/aio.c +++ b/arch/um/os-Linux/aio.c @@ -9,12 +9,10 @@ #include <errno.h> #include <sys/time.h> #include <asm/unistd.h> -#include "aio.h" -#include "init.h" -#include "kern_constants.h" -#include "kern_util.h" -#include "os.h" -#include "user.h" +#include <aio.h> +#include <init.h> +#include <kern_util.h> +#include <os.h> struct aio_thread_req { enum aio_type type; @@ -106,8 +104,7 @@ static int aio_thread(void *arg) struct io_event event; int err, n, reply_fd; - signal(SIGWINCH, SIG_IGN); - + os_fix_helper_signals(); while (1) { n = io_getevents(ctx, 1, 1, &event, NULL); if (n < 0) { @@ -175,7 +172,7 @@ static int not_aio_thread(void *arg) struct aio_thread_reply reply; int err; - signal(SIGWINCH, SIG_IGN); + os_fix_helper_signals(); while (1) { err = read(aio_req_fd_r, &req, sizeof(req)); if (err != sizeof(req)) { diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h index ddffd41c3f3..54183a679fd 100644 --- a/arch/um/os-Linux/drivers/etap.h +++ b/arch/um/os-Linux/drivers/etap.h @@ -6,7 +6,7 @@ #ifndef __DRIVERS_ETAP_H #define __DRIVERS_ETAP_H -#include "net_user.h" +#include <net_user.h> struct ethertap_data { char *dev_name; diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c index 7f6f9a71aae..f424600a583 100644 --- a/arch/um/os-Linux/drivers/ethertap_kern.c +++ b/arch/um/os-Linux/drivers/ethertap_kern.c @@ -9,7 +9,7 @@ #include <linux/init.h> #include <linux/netdevice.h> #include "etap.h" -#include "net_kern.h" +#include <net_kern.h> struct ethertap_init { char *dev_name; diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index cc72cb2c1af..b39b6696ac5 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -13,11 +13,9 @@ #include <sys/socket.h> #include <sys/wait.h> #include "etap.h" -#include "kern_constants.h" -#include "os.h" -#include "net_user.h" -#include "um_malloc.h" -#include "user.h" +#include <os.h> +#include <net_user.h> +#include <um_malloc.h> #define MAX_PACKET ETH_MAX_PACKET diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h index f17c31586c8..7367354ac8d 100644 --- a/arch/um/os-Linux/drivers/tuntap.h +++ b/arch/um/os-Linux/drivers/tuntap.h @@ -6,7 +6,7 @@ #ifndef __UM_TUNTAP_H #define __UM_TUNTAP_H -#include "net_user.h" +#include <net_user.h> struct tuntap_data { char *dev_name; diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c index 4048800e469..d9d56e5810f 100644 --- a/arch/um/os-Linux/drivers/tuntap_kern.c +++ b/arch/um/os-Linux/drivers/tuntap_kern.c @@ -7,7 +7,7 @@ #include <linux/init.h> #include <linux/skbuff.h> #include <asm/errno.h> -#include "net_kern.h" +#include <net_kern.h> #include "tuntap.h" struct tuntap_init { diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 2448be03fd7..14126d9176a 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -13,11 +13,9 @@ #include <sys/socket.h> #include <sys/wait.h> #include <sys/uio.h> -#include "kern_constants.h" -#include "kern_util.h" -#include "os.h" +#include <kern_util.h> +#include <os.h> #include "tuntap.h" -#include "user.h" static int tuntap_user_init(void *data, void *dev) { diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c index 608784d4ec5..1a365ddc4d0 100644 --- a/arch/um/os-Linux/elf_aux.c +++ b/arch/um/os-Linux/elf_aux.c @@ -9,21 +9,15 @@ */ #include <elf.h> #include <stddef.h> -#include "init.h" -#include "elf_user.h" -#include "mem_user.h" -#include <kern_constants.h> +#include <init.h> +#include <elf_user.h> +#include <mem_user.h> -/* Use the one from the kernel - the host may miss it, if having old headers. */ -#if UM_ELF_CLASS == UM_ELFCLASS32 typedef Elf32_auxv_t elf_auxv_t; -#else -typedef Elf64_auxv_t elf_auxv_t; -#endif /* These are initialized very early in boot and never changed */ char * elf_aux_platform; -long elf_aux_hwcap; +extern long elf_aux_hwcap; unsigned long vsyscall_ehdr; unsigned long vsyscall_end; unsigned long __kernel_vsyscall; diff --git a/arch/um/os-Linux/execvp.c b/arch/um/os-Linux/execvp.c index 66e583a4031..8fb25ca07c4 100644 --- a/arch/um/os-Linux/execvp.c +++ b/arch/um/os-Linux/execvp.c @@ -27,12 +27,12 @@ #include <limits.h> #ifndef TEST -#include "um_malloc.h" +#include <um_malloc.h> #else #include <stdio.h> #define um_kmalloc malloc #endif -#include "os.h" +#include <os.h> /* Execute FILE, searching in the `PATH' environment variable if it contains no slashes, with arguments ARGV and environment from `environ'. */ diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index 140e587bc0a..08d90fba952 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -13,9 +13,7 @@ #include <sys/socket.h> #include <sys/stat.h> #include <sys/un.h> -#include "kern_constants.h" -#include "os.h" -#include "user.h" +#include <os.h> static void copy_stat(struct uml_stat *dst, const struct stat64 *src) { @@ -239,6 +237,12 @@ void os_close_file(int fd) { close(fd); } +int os_fsync_file(int fd) +{ + if (fsync(fd) < 0) + return -errno; + return 0; +} int os_seek_file(int fd, unsigned long long offset) { @@ -268,6 +272,15 @@ int os_write_file(int fd, const void *buf, int len) return n; } +int os_sync_file(int fd) +{ + int n = fsync(fd); + + if (n < 0) + return -errno; + return n; +} + int os_file_size(const char *file, unsigned long long *size_out) { struct uml_stat buf; diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index b6b1096152a..e3ee4a51ef6 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -10,11 +10,9 @@ #include <linux/limits.h> #include <sys/socket.h> #include <sys/wait.h> -#include "kern_constants.h" -#include "kern_util.h" -#include "os.h" -#include "um_malloc.h" -#include "user.h" +#include <kern_util.h> +#include <os.h> +#include <um_malloc.h> struct helper_data { void (*pre_exec)(void*); @@ -28,14 +26,14 @@ static int helper_child(void *arg) { struct helper_data *data = arg; char **argv = data->argv; - int err; + int err, ret; if (data->pre_exec != NULL) (*data->pre_exec)(data->pre_data); err = execvp_noalloc(data->buf, argv[0], argv); /* If the exec succeeds, we don't get here */ - write(data->fd, &err, sizeof(err)); + CATCH_EINTR(ret = write(data->fd, &err, sizeof(err))); return 0; } diff --git a/arch/um/os-Linux/internal.h b/arch/um/os-Linux/internal.h new file mode 100644 index 00000000000..0dc2c9f135f --- /dev/null +++ b/arch/um/os-Linux/internal.h @@ -0,0 +1 @@ +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc); diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index 0348b975e81..b9afb74b79a 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c @@ -8,12 +8,9 @@ #include <poll.h> #include <signal.h> #include <string.h> -#include "irq_user.h" -#include "kern_constants.h" -#include "os.h" -#include "process.h" -#include "um_malloc.h" -#include "user.h" +#include <irq_user.h> +#include <os.h> +#include <um_malloc.h> /* * Locked by irq_lock in arch/um/kernel/irq.c. Changed by os_create_pollfd diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index eee69b9f52c..df9191acd92 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -10,17 +10,18 @@ #include <signal.h> #include <string.h> #include <sys/resource.h> -#include "as-layout.h" -#include "init.h" -#include "kern_constants.h" -#include "kern_util.h" -#include "os.h" -#include "um_malloc.h" +#include <as-layout.h> +#include <init.h> +#include <kern_util.h> +#include <os.h> +#include <um_malloc.h> #define PGD_BOUND (4 * 1024 * 1024) #define STACKSIZE (8 * 1024 * 1024) #define THREAD_NAME_LEN (256) +long elf_aux_hwcap; + static void set_stklim(void) { struct rlimit lim; @@ -78,7 +79,7 @@ static void install_fatal_handler(int sig) } } -#define UML_LIB_PATH ":/usr/lib/uml" +#define UML_LIB_PATH ":" OS_LIB_PATH "/uml" static void setup_env_path(void) { @@ -122,6 +123,8 @@ int __init main(int argc, char **argv, char **envp) setup_env_path(); + setsid(); + new_argv = malloc((argc + 1) * sizeof(char *)); if (new_argv == NULL) { perror("Mallocing argv"); @@ -142,11 +145,13 @@ int __init main(int argc, char **argv, char **envp) */ install_fatal_handler(SIGINT); install_fatal_handler(SIGTERM); - install_fatal_handler(SIGHUP); +#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA scan_elf_aux(envp); +#endif do_uml_initcalls(); + change_sig(SIGPIPE, 0); ret = linux_main(argc, argv); /* diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c index e696144d2be..897e9ad0c10 100644 --- a/arch/um/os-Linux/mem.c +++ b/arch/um/os-Linux/mem.c @@ -12,205 +12,133 @@ #include <string.h> #include <sys/stat.h> #include <sys/mman.h> -#include <sys/param.h> -#include "init.h" -#include "kern_constants.h" -#include "os.h" -#include "user.h" +#include <sys/vfs.h> +#include <linux/magic.h> +#include <init.h> +#include <os.h> -/* Modified by which_tmpdir, which is called during early boot */ -static char *default_tmpdir = "/tmp"; - -/* - * Modified when creating the physical memory file and when checking - * the tmp filesystem for usability, both happening during early boot. - */ +/* Set by make_tempfile() during early boot. */ static char *tempdir = NULL; -static void __init find_tempdir(void) +/* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */ +static int __init check_tmpfs(const char *dir) { - const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; - int i; - char *dir = NULL; - - if (tempdir != NULL) - /* We've already been called */ - return; - for (i = 0; dirs[i]; i++) { - dir = getenv(dirs[i]); - if ((dir != NULL) && (*dir != '\0')) - break; + struct statfs st; + + printf("Checking if %s is on tmpfs...", dir); + if (statfs(dir, &st) < 0) { + printf("%s\n", strerror(errno)); + } else if (st.f_type != TMPFS_MAGIC) { + printf("no\n"); + } else { + printf("OK\n"); + return 0; } - if ((dir == NULL) || (*dir == '\0')) - dir = default_tmpdir; - - tempdir = malloc(strlen(dir) + 2); - if (tempdir == NULL) { - fprintf(stderr, "Failed to malloc tempdir, " - "errno = %d\n", errno); - return; - } - strcpy(tempdir, dir); - strcat(tempdir, "/"); + return -1; } /* - * This will return 1, with the first character in buf being the - * character following the next instance of c in the file. This will - * read the file as needed. If there's an error, -errno is returned; - * if the end of the file is reached, 0 is returned. + * Choose the tempdir to use. We want something on tmpfs so that our memory is + * not subject to the host's vm.dirty_ratio. If a tempdir is specified in the + * environment, we use that even if it's not on tmpfs, but we warn the user. + * Otherwise, we try common tmpfs locations, and if no tmpfs directory is found + * then we fall back to /tmp. */ -static int next(int fd, char *buf, size_t size, char c) +static char * __init choose_tempdir(void) { - ssize_t n; - size_t len; - char *ptr; - - while ((ptr = strchr(buf, c)) == NULL) { - n = read(fd, buf, size - 1); - if (n == 0) - return 0; - else if (n < 0) - return -errno; - - buf[n] = '\0'; + static const char * const vars[] = { + "TMPDIR", + "TMP", + "TEMP", + NULL + }; + static const char fallback_dir[] = "/tmp"; + static const char * const tmpfs_dirs[] = { + "/dev/shm", + fallback_dir, + NULL + }; + int i; + const char *dir; + + printf("Checking environment variables for a tempdir..."); + for (i = 0; vars[i]; i++) { + dir = getenv(vars[i]); + if ((dir != NULL) && (*dir != '\0')) { + printf("%s\n", dir); + if (check_tmpfs(dir) >= 0) + goto done; + else + goto warn; + } } + printf("none found\n"); - ptr++; - len = strlen(ptr); - memmove(buf, ptr, len + 1); - - /* - * Refill the buffer so that if there's a partial string that we care - * about, it will be completed, and we can recognize it. - */ - n = read(fd, &buf[len], size - len - 1); - if (n < 0) - return -errno; + for (i = 0; tmpfs_dirs[i]; i++) { + dir = tmpfs_dirs[i]; + if (check_tmpfs(dir) >= 0) + goto done; + } - buf[len + n] = '\0'; - return 1; + dir = fallback_dir; +warn: + printf("Warning: tempdir %s is not on tmpfs\n", dir); +done: + /* Make a copy since getenv results may not remain valid forever. */ + return strdup(dir); } -/* which_tmpdir is called only during early boot */ -static int checked_tmpdir = 0; - /* - * Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner - * way to do this than to parse /proc/mounts. statfs will return the - * same filesystem magic number and fs id for both /dev and /dev/shm - * when they are both tmpfs, so you can't tell if they are different - * filesystems. Also, there seems to be no other way of finding the - * mount point of a filesystem from within it. - * - * If a /dev/shm tmpfs entry is found, then we switch to using it. - * Otherwise, we stay with the default /tmp. + * Create an unlinked tempfile in a suitable tempdir. template must be the + * basename part of the template with a leading '/'. */ -static void which_tmpdir(void) -{ - int fd, found; - char buf[128] = { '\0' }; - - if (checked_tmpdir) - return; - - checked_tmpdir = 1; - - printf("Checking for tmpfs mount on /dev/shm..."); - - fd = open("/proc/mounts", O_RDONLY); - if (fd < 0) { - printf("failed to open /proc/mounts, errno = %d\n", errno); - return; - } - - while (1) { - found = next(fd, buf, ARRAY_SIZE(buf), ' '); - if (found != 1) - break; - - if (!strncmp(buf, "/dev/shm", strlen("/dev/shm"))) - goto found; - - found = next(fd, buf, ARRAY_SIZE(buf), '\n'); - if (found != 1) - break; - } - -err: - if (found == 0) - printf("nothing mounted on /dev/shm\n"); - else if (found < 0) - printf("read returned errno %d\n", -found); - -out: - close(fd); - - return; - -found: - found = next(fd, buf, ARRAY_SIZE(buf), ' '); - if (found != 1) - goto err; - - if (strncmp(buf, "tmpfs", strlen("tmpfs"))) { - printf("not tmpfs\n"); - goto out; - } - - printf("OK\n"); - default_tmpdir = "/dev/shm"; - goto out; -} - -static int __init make_tempfile(const char *template, char **out_tempname, - int do_unlink) +static int __init make_tempfile(const char *template) { char *tempname; int fd; - which_tmpdir(); - tempname = malloc(MAXPATHLEN); - if (tempname == NULL) - return -1; + if (tempdir == NULL) { + tempdir = choose_tempdir(); + if (tempdir == NULL) { + fprintf(stderr, "Failed to choose tempdir: %s\n", + strerror(errno)); + return -1; + } + } - find_tempdir(); - if ((tempdir == NULL) || (strlen(tempdir) >= MAXPATHLEN)) + tempname = malloc(strlen(tempdir) + strlen(template) + 1); + if (tempname == NULL) return -1; - if (template[0] != '/') - strcpy(tempname, tempdir); - else - tempname[0] = '\0'; - strncat(tempname, template, MAXPATHLEN-1-strlen(tempname)); + strcpy(tempname, tempdir); + strcat(tempname, template); fd = mkstemp(tempname); if (fd < 0) { fprintf(stderr, "open - cannot create %s: %s\n", tempname, strerror(errno)); goto out; } - if (do_unlink && (unlink(tempname) < 0)) { + if (unlink(tempname) < 0) { perror("unlink"); - goto out; + goto close; } - if (out_tempname) { - *out_tempname = tempname; - } else - free(tempname); + free(tempname); return fd; +close: + close(fd); out: free(tempname); return -1; } -#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" +#define TEMPNAME_TEMPLATE "/vm_file-XXXXXX" static int __init create_tmp_file(unsigned long long len) { int fd, err; char zero; - fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); + fd = make_tempfile(TEMPNAME_TEMPLATE); if (fd < 0) exit(1); @@ -254,7 +182,6 @@ int __init create_mem_file(unsigned long long len) return fd; } - void __init check_tmpexec(void) { void *addr; @@ -262,14 +189,13 @@ void __init check_tmpexec(void) addr = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0); - printf("Checking PROT_EXEC mmap in %s...",tempdir); - fflush(stdout); + printf("Checking PROT_EXEC mmap in %s...", tempdir); if (addr == MAP_FAILED) { err = errno; - perror("failed"); + printf("%s\n", strerror(err)); close(fd); if (err == EPERM) - printf("%s must be not mounted noexec\n",tempdir); + printf("%s must be not mounted noexec\n", tempdir); exit(1); } printf("OK\n"); diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index e0477c3ee89..33496fe2bb5 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -4,6 +4,7 @@ */ #include <stdio.h> +#include <stdlib.h> #include <unistd.h> #include <errno.h> #include <signal.h> @@ -12,13 +13,10 @@ #include <sys/ptrace.h> #include <sys/wait.h> #include <asm/unistd.h> -#include "init.h" -#include "kern_constants.h" -#include "longjmp.h" -#include "os.h" -#include "process.h" -#include "skas_ptrace.h" -#include "user.h" +#include <init.h> +#include <longjmp.h> +#include <os.h> +#include <skas_ptrace.h> #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -235,35 +233,65 @@ out: return ok; } -void init_new_thread_signals(void) +static int os_page_mincore(void *addr) { - set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK, - SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); - signal(SIGHUP, SIG_IGN); + char vec[2]; + int ret; - set_handler(SIGIO, (__sighandler_t) sig_handler, - SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, - SIGVTALRM, -1); - signal(SIGWINCH, SIG_IGN); + ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); + if (ret < 0) { + if (errno == ENOMEM || errno == EINVAL) + return 0; + else + return -errno; + } + + return vec[0] & 1; } -int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) +int os_mincore(void *addr, unsigned long len) { - jmp_buf buf; - int n; - - *jmp_ptr = &buf; - n = UML_SETJMP(&buf); - if (n != 0) - return n; - (*fn)(arg); - return 0; + char *vec; + int ret, i; + + if (len <= UM_KERN_PAGE_SIZE) + return os_page_mincore(addr); + + vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); + if (!vec) + return -ENOMEM; + + ret = mincore(addr, UM_KERN_PAGE_SIZE, vec); + if (ret < 0) { + if (errno == ENOMEM || errno == EINVAL) + ret = 0; + else + ret = -errno; + + goto out; + } + + for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) { + if (!(vec[i] & 1)) { + ret = 0; + goto out; + } + } + + ret = 1; +out: + free(vec); + return ret; +} + +void init_new_thread_signals(void) +{ + set_handler(SIGSEGV); + set_handler(SIGTRAP); + set_handler(SIGFPE); + set_handler(SIGILL); + set_handler(SIGBUS); + signal(SIGHUP, SIG_IGN); + set_handler(SIGIO); + signal(SIGWINCH, SIG_IGN); } diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c index 830fe6a1518..2ff8d4fe83c 100644 --- a/arch/um/os-Linux/registers.c +++ b/arch/um/os-Linux/registers.c @@ -7,7 +7,9 @@ #include <errno.h> #include <string.h> #include <sys/ptrace.h> -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> +#include <sysdep/ptrace_user.h> +#include <registers.h> int save_registers(int pid, struct uml_pt_regs *regs) { @@ -32,6 +34,7 @@ int restore_registers(int pid, struct uml_pt_regs *regs) /* This is set once at boot time and not changed thereafter */ static unsigned long exec_regs[MAX_REG_NR]; +static unsigned long exec_fp_regs[FP_SIZE]; int init_registers(int pid) { @@ -42,10 +45,14 @@ int init_registers(int pid) return -errno; arch_init_registers(pid); + get_fp_registers(pid, exec_fp_regs); return 0; } -void get_safe_registers(unsigned long *regs) +void get_safe_registers(unsigned long *regs, unsigned long *fp_regs) { memcpy(regs, exec_regs, sizeof(exec_regs)); + + if (fp_regs) + memcpy(fp_regs, exec_fp_regs, sizeof(exec_fp_regs)); } diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 63d299df152..46e762f926e 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -11,14 +11,11 @@ #include <sched.h> #include <signal.h> #include <string.h> -#include "kern_constants.h" -#include "kern_util.h" -#include "init.h" -#include "os.h" -#include "process.h" -#include "sigio.h" -#include "um_malloc.h" -#include "user.h" +#include <kern_util.h> +#include <init.h> +#include <os.h> +#include <sigio.h> +#include <um_malloc.h> /* * Protected by sigio_lock(), also used by sigio_cleanup, which is an @@ -58,7 +55,7 @@ static int write_sigio_thread(void *unused) int i, n, respond_fd; char c; - signal(SIGWINCH, SIG_IGN); + os_fix_helper_signals(); fds = ¤t_poll; while (1) { n = poll(fds->poll, fds->used, -1); diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 6ae180703a6..7b605e4dfff 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -9,18 +9,13 @@ #include <errno.h> #include <signal.h> #include <strings.h> -#include "as-layout.h" -#include "kern_util.h" -#include "os.h" -#include "process.h" -#include "sysdep/barrier.h" -#include "sysdep/sigcontext.h" -#include "user.h" - -/* Copied from linux/compiler-gcc.h since we can't include it directly */ -#define barrier() __asm__ __volatile__("": : :"memory") - -void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { +#include <as-layout.h> +#include <kern_util.h> +#include <os.h> +#include <sysdep/mcontext.h> +#include "internal.h" + +void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = { [SIGTRAP] = relay_signal, [SIGFPE] = relay_signal, [SIGILL] = relay_signal, @@ -30,7 +25,7 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { [SIGIO] = sigio_handler, [SIGVTALRM] = timer_handler }; -static void sig_handler_common(int sig, struct sigcontext *sc) +static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc) { struct uml_pt_regs r; int save_errno = errno; @@ -38,15 +33,15 @@ static void sig_handler_common(int sig, struct sigcontext *sc) r.is_user = 0; if (sig == SIGSEGV) { /* For segfaults, we want the data from the sigcontext. */ - copy_sc(&r, sc); - GET_FAULTINFO_FROM_SC(r.faultinfo, sc); + get_regs_from_mc(&r, mc); + GET_FAULTINFO_FROM_MC(r.faultinfo, mc); } /* enable signals if sig isn't IRQ signal */ if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) unblock_signals(); - (*sig_info[sig])(sig, &r); + (*sig_info[sig])(sig, si, &r); errno = save_errno; } @@ -66,7 +61,7 @@ static void sig_handler_common(int sig, struct sigcontext *sc) static int signals_enabled; static unsigned int signals_pending; -void sig_handler(int sig, struct sigcontext *sc) +void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) { int enabled; @@ -78,23 +73,23 @@ void sig_handler(int sig, struct sigcontext *sc) block_signals(); - sig_handler_common(sig, sc); + sig_handler_common(sig, si, mc); set_signals(enabled); } -static void real_alarm_handler(struct sigcontext *sc) +static void real_alarm_handler(mcontext_t *mc) { struct uml_pt_regs regs; - if (sc != NULL) - copy_sc(®s, sc); + if (mc != NULL) + get_regs_from_mc(®s, mc); regs.is_user = 0; unblock_signals(); - timer_handler(SIGVTALRM, ®s); + timer_handler(SIGVTALRM, NULL, ®s); } -void alarm_handler(int sig, struct sigcontext *sc) +void alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc) { int enabled; @@ -106,14 +101,13 @@ void alarm_handler(int sig, struct sigcontext *sc) block_signals(); - real_alarm_handler(sc); + real_alarm_handler(mc); set_signals(enabled); } void timer_init(void) { - set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, - SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1); + set_handler(SIGVTALRM); } void set_sigstack(void *sig_stack, int size) @@ -126,10 +120,23 @@ void set_sigstack(void *sig_stack, int size) panic("enabling signal stack failed, errno = %d\n", errno); } -static void (*handlers[_NSIG])(int sig, struct sigcontext *sc); +static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = { + [SIGSEGV] = sig_handler, + [SIGBUS] = sig_handler, + [SIGILL] = sig_handler, + [SIGFPE] = sig_handler, + [SIGTRAP] = sig_handler, + + [SIGIO] = sig_handler, + [SIGWINCH] = sig_handler, + [SIGVTALRM] = alarm_handler +}; + -void handle_signal(int sig, struct sigcontext *sc) +static void hard_handler(int sig, siginfo_t *si, void *p) { + struct ucontext *uc = p; + mcontext_t *mc = &uc->uc_mcontext; unsigned long pending = 1UL << sig; do { @@ -155,7 +162,7 @@ void handle_signal(int sig, struct sigcontext *sc) while ((sig = ffs(pending)) != 0){ sig--; pending &= ~(1 << sig); - (*handlers[sig])(sig, sc); + (*handlers[sig])(sig, (struct siginfo *)si, mc); } /* @@ -169,28 +176,26 @@ void handle_signal(int sig, struct sigcontext *sc) } while (pending); } -extern void hard_handler(int sig); - -void set_handler(int sig, void (*handler)(int), int flags, ...) +void set_handler(int sig) { struct sigaction action; - va_list ap; + int flags = SA_SIGINFO | SA_ONSTACK; sigset_t sig_mask; - int mask; - handlers[sig] = (void (*)(int, struct sigcontext *)) handler; - action.sa_handler = hard_handler; + action.sa_sigaction = hard_handler; + /* block irq ones */ sigemptyset(&action.sa_mask); - - va_start(ap, flags); - while ((mask = va_arg(ap, int)) != -1) - sigaddset(&action.sa_mask, mask); - va_end(ap); + sigaddset(&action.sa_mask, SIGVTALRM); + sigaddset(&action.sa_mask, SIGIO); + sigaddset(&action.sa_mask, SIGWINCH); if (sig == SIGSEGV) flags |= SA_NODEFER; + if (sigismember(&action.sa_mask, sig)) + flags |= SA_RESTART; /* if it's an irq signal */ + action.sa_flags = flags; action.sa_restorer = NULL; if (sigaction(sig, &action, NULL) < 0) @@ -269,9 +274,12 @@ void unblock_signals(void) * Deal with SIGIO first because the alarm handler might * schedule, leaving the pending SIGIO stranded until we come * back here. + * + * SIGIO's handler doesn't use siginfo or mcontext, + * so they can be NULL. */ if (save_pending & SIGIO_MASK) - sig_handler_common(SIGIO, NULL); + sig_handler_common(SIGIO, NULL, NULL); if (save_pending & SIGVTALRM_MASK) real_alarm_handler(NULL); @@ -296,3 +304,11 @@ int set_signals(int enable) return ret; } + +int os_is_signal_stack(void) +{ + stack_t ss; + sigaltstack(NULL, &ss); + + return ss.ss_flags & SS_ONSTACK; +} diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index d261f170d12..689b18db798 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -8,18 +8,16 @@ #include <errno.h> #include <string.h> #include <sys/mman.h> -#include "init.h" -#include "kern_constants.h" -#include "as-layout.h" -#include "mm_id.h" -#include "os.h" -#include "proc_mm.h" -#include "ptrace_user.h" -#include "registers.h" -#include "skas.h" -#include "user.h" -#include "sysdep/ptrace.h" -#include "sysdep/stub.h" +#include <init.h> +#include <as-layout.h> +#include <mm_id.h> +#include <os.h> +#include <proc_mm.h> +#include <ptrace_user.h> +#include <registers.h> +#include <skas.h> +#include <sysdep/ptrace.h> +#include <sysdep/stub.h> extern unsigned long batch_syscall_stub, __syscall_stub_start; @@ -39,7 +37,7 @@ static unsigned long syscall_regs[MAX_REG_NR]; static int __init init_syscall_regs(void) { - get_safe_registers(syscall_regs); + get_safe_registers(syscall_regs, NULL); syscall_regs[REGS_IP_INDEX] = STUB_CODE + ((unsigned long) &batch_syscall_stub - (unsigned long) &__syscall_stub_start); @@ -50,10 +48,6 @@ __initcall(init_syscall_regs); extern int proc_mm; -int single_count = 0; -int multi_count = 0; -int multi_op_count = 0; - static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) { int n, i; @@ -66,8 +60,6 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) /* FIXME: Need to look up userspace_pid by cpu */ pid = userspace_pid[0]; - multi_count++; - n = ptrace_setregs(pid, syscall_regs); if (n < 0) { printk(UM_KERN_ERR "Registers - \n"); @@ -128,9 +120,6 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, { unsigned long *stack = check_init_stack(mm_idp, *addr); - if (done && *addr == NULL) - single_count++; - *stack += sizeof(long); stack += *stack / sizeof(long); @@ -143,7 +132,6 @@ long run_syscall_stub(struct mm_id * mm_idp, int syscall, *stack++ = args[5]; *stack++ = expected; *stack = 0; - multi_op_count++; if (!done && ((((unsigned long) stack) & ~UM_KERN_PAGE_MASK) < UM_KERN_PAGE_SIZE - 10 * sizeof(long))) { diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index d6e0a2234b8..908579f2b0a 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -9,31 +9,23 @@ #include <errno.h> #include <string.h> #include <sys/mman.h> -#include <sys/ptrace.h> #include <sys/wait.h> #include <asm/unistd.h> -#include "as-layout.h" -#include "chan_user.h" -#include "kern_constants.h" -#include "kern_util.h" -#include "mem.h" -#include "os.h" -#include "process.h" -#include "proc_mm.h" -#include "ptrace_user.h" -#include "registers.h" -#include "skas.h" -#include "skas_ptrace.h" -#include "user.h" -#include "sysdep/stub.h" +#include <as-layout.h> +#include <init.h> +#include <kern_util.h> +#include <mem.h> +#include <os.h> +#include <proc_mm.h> +#include <ptrace_user.h> +#include <registers.h> +#include <skas.h> +#include <skas_ptrace.h> +#include <sysdep/stub.h> int is_skas_winch(int pid, int fd, void *data) { - if (pid != getpgrp()) - return 0; - - register_winch_irq(-1, fd, -1, data, 0); - return 1; + return pid == getpgrp(); } static int ptrace_dump_regs(int pid) @@ -169,7 +161,7 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, if (!local_using_sysemu) { - err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, + err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); if (err < 0) { printk(UM_KERN_ERR "handle_trap - nullifying syscall " @@ -257,8 +249,8 @@ static int userspace_tramp(void *stack) set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_ONSTACK | SA_NODEFER; - sa.sa_handler = (void *) v; + sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO; + sa.sa_sigaction = (void *) v; sa.sa_restorer = NULL; if (sigaction(SIGSEGV, &sa, NULL) < 0) { printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV " @@ -354,6 +346,10 @@ void userspace(struct uml_pt_regs *regs) int err, status, op, pid = userspace_pid[0]; /* To prevent races if using_sysemu changes under us.*/ int local_using_sysemu; + siginfo_t si; + + /* Handle any immediate reschedules or signals */ + interrupt_end(); if (getitimer(ITIMER_VIRTUAL, &timer)) printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); @@ -373,6 +369,9 @@ void userspace(struct uml_pt_regs *regs) if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp)) fatal_sigsegv(); + if (put_fp_registers(pid, regs->fp)) + fatal_sigsegv(); + /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); @@ -399,17 +398,27 @@ void userspace(struct uml_pt_regs *regs) fatal_sigsegv(); } + if (get_fp_registers(pid, regs->fp)) { + printk(UM_KERN_ERR "userspace - get_fp_registers failed, " + "errno = %d\n", errno); + fatal_sigsegv(); + } + UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); + + ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si); + switch (sig) { case SIGSEGV: if (PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) { get_skas_faultinfo(pid, ®s->faultinfo); - (*sig_info[SIGSEGV])(SIGSEGV, regs); + (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, + regs); } else handle_segv(pid, regs); break; @@ -417,14 +426,14 @@ void userspace(struct uml_pt_regs *regs) handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: - relay_signal(SIGTRAP, regs); + relay_signal(SIGTRAP, (struct siginfo *)&si, regs); break; case SIGVTALRM: now = os_nsecs(); if (now < nsecs) break; block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, (struct siginfo *)&si, regs); unblock_signals(); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + @@ -438,7 +447,7 @@ void userspace(struct uml_pt_regs *regs) case SIGFPE: case SIGWINCH: block_signals(); - (*sig_info[sig])(sig, regs); + (*sig_info[sig])(sig, (struct siginfo *)&si, regs); unblock_signals(); break; default: @@ -457,10 +466,11 @@ void userspace(struct uml_pt_regs *regs) } static unsigned long thread_regs[MAX_REG_NR]; +static unsigned long thread_fp_regs[FP_SIZE]; static int __init init_thread_regs(void) { - get_safe_registers(thread_regs); + get_safe_registers(thread_regs, thread_fp_regs); /* Set parent's instruction pointer to start of clone-stub */ thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - @@ -503,6 +513,13 @@ int copy_context_skas0(unsigned long new_stack, int pid) return err; } + err = put_fp_registers(pid, thread_fp_regs); + if (err < 0) { + printk(UM_KERN_ERR "copy_context_skas0 : put_fp_registers " + "failed, pid = %d, err = %d\n", pid, err); + return err; + } + /* set a well known return code for detection of child write failure */ child_data->err = 12345678; @@ -644,8 +661,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) { int n; - set_handler(SIGWINCH, (__sighandler_t) sig_handler, - SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1); + set_handler(SIGWINCH); /* * Can't use UML_SETJMP or UML_LONGJMP here because they save diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 02ee9adff54..337518c5042 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -13,18 +13,18 @@ #include <signal.h> #include <string.h> #include <sys/mman.h> -#include <sys/ptrace.h> #include <sys/stat.h> #include <sys/wait.h> +#include <sys/time.h> +#include <sys/resource.h> #include <asm/unistd.h> -#include "init.h" -#include "kern_constants.h" -#include "os.h" -#include "mem_user.h" -#include "ptrace_user.h" -#include "registers.h" -#include "skas.h" -#include "skas_ptrace.h" +#include <init.h> +#include <os.h> +#include <mem_user.h> +#include <ptrace_user.h> +#include <registers.h> +#include <skas.h> +#include <skas_ptrace.h> static void ptrace_child(void) { @@ -225,7 +225,7 @@ static void __init check_sysemu(void) goto fail; } - n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); + n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); if (n < 0) { non_fatal("check_sysemu : failed to modify system call " "return"); @@ -261,7 +261,7 @@ static void __init check_sysemu(void) "doesn't singlestep"); goto fail; } - n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, + n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); if (n < 0) fatal_perror("check_sysemu : failed to modify " @@ -317,10 +317,10 @@ static void __init check_ptrace(void) fatal("check_ptrace : expected (SIGTRAP|0x80), " "got status = %d", status); - syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, + syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 0); if (syscall == __NR_getpid) { - n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, + n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getppid); if (n < 0) fatal_perror("check_ptrace : failed to modify " diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile deleted file mode 100644 index b4bc6ac4f30..00000000000 --- a/arch/um/os-Linux/sys-i386/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) -# Licensed under the GPL -# - -obj-y = registers.o signal.o task_size.o tls.o - -USER_OBJS := $(obj-y) - -include arch/um/scripts/Makefile.rules diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c deleted file mode 100644 index 229f7a53d8d..00000000000 --- a/arch/um/os-Linux/sys-i386/registers.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2004 PathScale, Inc - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <errno.h> -#include <sys/ptrace.h> -#include <sys/user.h> -#include "kern_constants.h" -#include "longjmp.h" -#include "user.h" -#include "sysdep/ptrace_user.h" - -int save_fp_registers(int pid, unsigned long *fp_regs) -{ - if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) - return -errno; - return 0; -} - -int restore_fp_registers(int pid, unsigned long *fp_regs) -{ - if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) - return -errno; - return 0; -} - -int save_fpx_registers(int pid, unsigned long *fp_regs) -{ - if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0) - return -errno; - return 0; -} - -int restore_fpx_registers(int pid, unsigned long *fp_regs) -{ - if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0) - return -errno; - return 0; -} - -unsigned long get_thread_reg(int reg, jmp_buf *buf) -{ - switch (reg) { - case EIP: - return buf[0]->__eip; - case UESP: - return buf[0]->__esp; - case EBP: - return buf[0]->__ebp; - default: - printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", - reg); - return 0; - } -} - -int have_fpx_regs = 1; - -int get_fp_registers(int pid, unsigned long *regs) -{ - if (have_fpx_regs) - return save_fpx_registers(pid, regs); - else - return save_fp_registers(pid, regs); -} - -int put_fp_registers(int pid, unsigned long *regs) -{ - if (have_fpx_regs) - return restore_fpx_registers(pid, regs); - else - return restore_fp_registers(pid, regs); -} - -void arch_init_registers(int pid) -{ - struct user_fpxregs_struct fpx_regs; - int err; - - err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); - if (!err) - return; - - if (errno != EIO) - panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", - errno); - - have_fpx_regs = 0; -} diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c deleted file mode 100644 index f311609f93d..00000000000 --- a/arch/um/os-Linux/sys-i386/signal.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <signal.h> - -extern void handle_signal(int sig, struct sigcontext *sc); - -void hard_handler(int sig) -{ - handle_signal(sig, (struct sigcontext *) (&sig + 1)); -} diff --git a/arch/um/os-Linux/sys-i386/task_size.c b/arch/um/os-Linux/sys-i386/task_size.c deleted file mode 100644 index be04c1e183b..00000000000 --- a/arch/um/os-Linux/sys-i386/task_size.c +++ /dev/null @@ -1,139 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <sys/mman.h> -#include "longjmp.h" -#include "kern_constants.h" - -static jmp_buf buf; - -static void segfault(int sig) -{ - longjmp(buf, 1); -} - -static int page_ok(unsigned long page) -{ - unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT); - unsigned long n = ~0UL; - void *mapped = NULL; - int ok = 0; - - /* - * First see if the page is readable. If it is, it may still - * be a VDSO, so we go on to see if it's writable. If not - * then try mapping memory there. If that fails, then we're - * still in the kernel area. As a sanity check, we'll fail if - * the mmap succeeds, but gives us an address different from - * what we wanted. - */ - if (setjmp(buf) == 0) - n = *address; - else { - mapped = mmap(address, UM_KERN_PAGE_SIZE, - PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (mapped == MAP_FAILED) - return 0; - if (mapped != address) - goto out; - } - - /* - * Now, is it writeable? If so, then we're in user address - * space. If not, then try mprotecting it and try the write - * again. - */ - if (setjmp(buf) == 0) { - *address = n; - ok = 1; - goto out; - } else if (mprotect(address, UM_KERN_PAGE_SIZE, - PROT_READ | PROT_WRITE) != 0) - goto out; - - if (setjmp(buf) == 0) { - *address = n; - ok = 1; - } - - out: - if (mapped != NULL) - munmap(mapped, UM_KERN_PAGE_SIZE); - return ok; -} - -unsigned long os_get_top_address(void) -{ - struct sigaction sa, old; - unsigned long bottom = 0; - /* - * A 32-bit UML on a 64-bit host gets confused about the VDSO at - * 0xffffe000. It is mapped, is readable, can be reprotected writeable - * and written. However, exec discovers later that it can't be - * unmapped. So, just set the highest address to be checked to just - * below it. This might waste some address space on 4G/4G 32-bit - * hosts, but shouldn't hurt otherwise. - */ - unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT; - unsigned long test, original; - - printf("Locating the bottom of the address space ... "); - fflush(stdout); - - /* - * We're going to be longjmping out of the signal handler, so - * SA_DEFER needs to be set. - */ - sa.sa_handler = segfault; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_NODEFER; - if (sigaction(SIGSEGV, &sa, &old)) { - perror("os_get_top_address"); - exit(1); - } - - /* Manually scan the address space, bottom-up, until we find - * the first valid page (or run out of them). - */ - for (bottom = 0; bottom < top; bottom++) { - if (page_ok(bottom)) - break; - } - - /* If we've got this far, we ran out of pages. */ - if (bottom == top) { - fprintf(stderr, "Unable to determine bottom of address " - "space.\n"); - exit(1); - } - - printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT); - printf("Locating the top of the address space ... "); - fflush(stdout); - - original = bottom; - - /* This could happen with a 4G/4G split */ - if (page_ok(top)) - goto out; - - do { - test = bottom + (top - bottom) / 2; - if (page_ok(test)) - bottom = test; - else - top = test; - } while (top - bottom > 1); - -out: - /* Restore the old SIGSEGV handling */ - if (sigaction(SIGSEGV, &old, NULL)) { - perror("os_get_top_address"); - exit(1); - } - top <<= UM_KERN_PAGE_SHIFT; - printf("0x%x\n", top); - - return top; -} diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c deleted file mode 100644 index 32ed41ec1a3..00000000000 --- a/arch/um/os-Linux/sys-i386/tls.c +++ /dev/null @@ -1,36 +0,0 @@ -#include <errno.h> -#include <linux/unistd.h> - -#include <sys/syscall.h> -#include <unistd.h> - -#include "sysdep/tls.h" -#include "user.h" - -/* Checks whether host supports TLS, and sets *tls_min according to the value - * valid on the host. - * i386 host have it == 6; x86_64 host have it == 12, for i386 emulation. */ -void check_host_supports_tls(int *supports_tls, int *tls_min) { - /* Values for x86 and x86_64.*/ - int val[] = {GDT_ENTRY_TLS_MIN_I386, GDT_ENTRY_TLS_MIN_X86_64}; - int i; - - for (i = 0; i < ARRAY_SIZE(val); i++) { - user_desc_t info; - info.entry_number = val[i]; - - if (syscall(__NR_get_thread_area, &info) == 0) { - *tls_min = val[i]; - *supports_tls = 1; - return; - } else { - if (errno == EINVAL) - continue; - else if (errno == ENOSYS) - *supports_tls = 0; - return; - } - } - - *supports_tls = 0; -} diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile deleted file mode 100644 index a44a47f8f57..00000000000 --- a/arch/um/os-Linux/sys-x86_64/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) -# Licensed under the GPL -# - -obj-y = registers.o prctl.o signal.o task_size.o - -USER_OBJS := $(obj-y) - -include arch/um/scripts/Makefile.rules diff --git a/arch/um/os-Linux/sys-x86_64/prctl.c b/arch/um/os-Linux/sys-x86_64/prctl.c deleted file mode 100644 index 9d34eddb517..00000000000 --- a/arch/um/os-Linux/sys-x86_64/prctl.c +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (C) 2007 Jeff Dike (jdike@{addtoit.com,linux.intel.com}) - * Licensed under the GPL - */ - -#include <sys/ptrace.h> -#include <linux/ptrace.h> - -int os_arch_prctl(int pid, int code, unsigned long *addr) -{ - return ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long) addr, code); -} diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c deleted file mode 100644 index 594d97ad02b..00000000000 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2006 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <errno.h> -#include <sys/ptrace.h> -#define __FRAME_OFFSETS -#include <asm/ptrace.h> -#include "kern_constants.h" -#include "longjmp.h" -#include "user.h" - -int save_fp_registers(int pid, unsigned long *fp_regs) -{ - if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) - return -errno; - return 0; -} - -int restore_fp_registers(int pid, unsigned long *fp_regs) -{ - if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) - return -errno; - return 0; -} - -unsigned long get_thread_reg(int reg, jmp_buf *buf) -{ - switch (reg) { - case RIP: - return buf[0]->__rip; - case RSP: - return buf[0]->__rsp; - case RBP: - return buf[0]->__rbp; - default: - printk(UM_KERN_ERR "get_thread_regs - unknown register %d\n", - reg); - return 0; - } -} - -int get_fp_registers(int pid, unsigned long *regs) -{ - return save_fp_registers(pid, regs); -} - -int put_fp_registers(int pid, unsigned long *regs) -{ - return restore_fp_registers(pid, regs); -} diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c deleted file mode 100644 index 82a388822cd..00000000000 --- a/arch/um/os-Linux/sys-x86_64/signal.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <signal.h> - -extern void handle_signal(int sig, struct sigcontext *sc); - -void hard_handler(int sig) -{ - struct ucontext *uc; - asm("movq %%rdx, %0" : "=r" (uc)); - - handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext); -} diff --git a/arch/um/os-Linux/sys-x86_64/task_size.c b/arch/um/os-Linux/sys-x86_64/task_size.c deleted file mode 100644 index 26a0dd1f349..00000000000 --- a/arch/um/os-Linux/sys-x86_64/task_size.c +++ /dev/null @@ -1,5 +0,0 @@ -unsigned long os_get_top_address(unsigned long shift) -{ - /* The old value of CONFIG_TOP_ADDR */ - return 0x7fc0000000; -} diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index 6e3359d6a83..e9824d5dd7d 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -8,11 +8,9 @@ #include <signal.h> #include <time.h> #include <sys/time.h> -#include "kern_constants.h" -#include "kern_util.h" -#include "os.h" -#include "process.h" -#include "user.h" +#include <kern_util.h> +#include <os.h> +#include "internal.h" int set_interval(void) { @@ -81,7 +79,7 @@ long long os_nsecs(void) return timeval_to_ns(&tv); } -#ifdef UML_CONFIG_NO_HZ +#ifdef UML_CONFIG_NO_HZ_COMMON static int after_sleep_interval(struct timespec *ts) { return 0; @@ -89,7 +87,7 @@ static int after_sleep_interval(struct timespec *ts) static void deliver_alarm(void) { - alarm_handler(SIGVTALRM, NULL); + alarm_handler(SIGVTALRM, NULL, NULL); } static unsigned long long sleep_time(unsigned long long nsecs) @@ -116,7 +114,7 @@ static void deliver_alarm(void) skew += this_tick - last_tick; while (skew >= one_tick) { - alarm_handler(SIGVTALRM, NULL); + alarm_handler(SIGVTALRM, NULL, NULL); skew -= one_tick; } diff --git a/arch/um/os-Linux/tls.c b/arch/um/os-Linux/tls.c deleted file mode 100644 index 73277801ef1..00000000000 --- a/arch/um/os-Linux/tls.c +++ /dev/null @@ -1,35 +0,0 @@ -#include <errno.h> -#include <sys/ptrace.h> -#include "sysdep/tls.h" - -/* TLS support - we basically rely on the host's one.*/ - -#ifndef PTRACE_GET_THREAD_AREA -#define PTRACE_GET_THREAD_AREA 25 -#endif - -#ifndef PTRACE_SET_THREAD_AREA -#define PTRACE_SET_THREAD_AREA 26 -#endif - -int os_set_thread_area(user_desc_t *info, int pid) -{ - int ret; - - ret = ptrace(PTRACE_SET_THREAD_AREA, pid, info->entry_number, - (unsigned long) info); - if (ret < 0) - ret = -errno; - return ret; -} - -int os_get_thread_area(user_desc_t *info, int pid) -{ - int ret; - - ret = ptrace(PTRACE_GET_THREAD_AREA, pid, info->entry_number, - (unsigned long) info); - if (ret < 0) - ret = -errno; - return ret; -} diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c index b09ff66a77e..721d8afa329 100644 --- a/arch/um/os-Linux/tty.c +++ b/arch/um/os-Linux/tty.c @@ -7,10 +7,8 @@ #include <unistd.h> #include <errno.h> #include <fcntl.h> -#include "kern_constants.h" -#include "kern_util.h" -#include "os.h" -#include "user.h" +#include <kern_util.h> +#include <os.h> struct grantpt_info { int fd; diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c deleted file mode 100644 index 087ed74ffca..00000000000 --- a/arch/um/os-Linux/uaccess.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <stddef.h> -#include "longjmp.h" - -unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, jmp_buf **fault_catcher, - void (*op)(void *to, const void *from, - int n), int *faulted_out) -{ - unsigned long *faddrp = (unsigned long *) fault_addr, ret; - - jmp_buf jbuf; - *fault_catcher = &jbuf; - if (UML_SETJMP(&jbuf) == 0) { - (*op)(to, from, n); - ret = 0; - *faulted_out = 0; - } - else { - ret = *faddrp; - *faulted_out = 1; - } - *fault_addr = NULL; - *fault_catcher = NULL; - return ret; -} - diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c index a27defb8188..c1dc89261f6 100644 --- a/arch/um/os-Linux/umid.c +++ b/arch/um/os-Linux/umid.c @@ -12,10 +12,8 @@ #include <string.h> #include <unistd.h> #include <sys/stat.h> -#include "init.h" -#include "kern_constants.h" -#include "os.h" -#include "user.h" +#include <init.h> +#include <os.h> #define UML_DIR "~/.uml/" diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 05f5ea8e83d..db4a034aeee 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -1,5 +1,5 @@ -#include "linux/types.h" -#include "linux/module.h" +#include <linux/types.h> +#include <linux/module.h> /* Some of this are builtin function (some are not but could in the future), * so I *must* declare good prototypes for them and then EXPORT them. @@ -45,7 +45,7 @@ EXPORT_SYMBOL(readdir64); extern void truncate64(void) __attribute__((weak)); EXPORT_SYMBOL(truncate64); -#ifdef SUBARCH_i386 +#ifdef CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA EXPORT_SYMBOL(vsyscall_ehdr); EXPORT_SYMBOL(vsyscall_end); #endif @@ -113,3 +113,8 @@ EXPORT_SYMBOL(__stack_smash_handler); extern long __guard __attribute__((weak)); EXPORT_SYMBOL(__guard); + +#ifdef _FORTIFY_SOURCE +extern int __sprintf_chk(char *str, int flag, size_t strlen, const char *format); +EXPORT_SYMBOL(__sprintf_chk); +#endif diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index 6ea77979531..faee55ef6d2 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -5,6 +5,7 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <errno.h> #include <signal.h> #include <string.h> @@ -12,9 +13,7 @@ #include <wait.h> #include <sys/mman.h> #include <sys/utsname.h> -#include "kern_constants.h" -#include "os.h" -#include "user.h" +#include <os.h> void stack_protections(unsigned long address) { @@ -75,6 +74,36 @@ void setup_hostinfo(char *buf, int len) host.release, host.version, host.machine); } +/* + * We cannot use glibc's abort(). It makes use of tgkill() which + * has no effect within UML's kernel threads. + * After that glibc would execute an invalid instruction to kill + * the calling process and UML crashes with SIGSEGV. + */ +static inline void __attribute__ ((noreturn)) uml_abort(void) +{ + sigset_t sig; + + fflush(NULL); + + if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT)) + sigprocmask(SIG_UNBLOCK, &sig, 0); + + for (;;) + if (kill(getpid(), SIGABRT) < 0) + exit(127); +} + +/* + * UML helper threads must not handle SIGWINCH/INT/TERM + */ +void os_fix_helper_signals(void) +{ + signal(SIGWINCH, SIG_IGN); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); +} + void os_dump_core(void) { int pid; @@ -116,5 +145,10 @@ void os_dump_core(void) while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0) os_kill_ptraced_process(pid, 0); - abort(); + uml_abort(); +} + +void um_early_printk(const char *s, unsigned int n) +{ + printf("%.*s", n, s); } diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index 61107b68e05..15889df9b46 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -8,9 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS:.o=.%): \ - c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) $(CFLAGS_$(basetarget).o) -$(USER_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ - -Dunix -D__unix__ -D__$(SUBARCH)__ $(CF) + c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o) # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of # using it directly. @@ -18,15 +16,11 @@ UNPROFILE_OBJS := $(foreach file,$(UNPROFILE_OBJS),$(obj)/$(file)) $(UNPROFILE_OBJS:.o=.%): \ c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS)) $(CFLAGS_$(basetarget).o) -$(UNPROFILE_OBJS) : CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ \ - -Dunix -D__unix__ -D__$(SUBARCH)__ $(CF) + +$(USER_OBJS) $(UNPROFILE_OBJS): \ + CHECKFLAGS := $(patsubst $(NOSTDINC_FLAGS),,$(CHECKFLAGS)) # The stubs can't try to call mcount or update basic block data define unprofile $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) endef - -ifdef subarch-obj-y -obj-y += subarch.o -subarch-y = $(addprefix ../../$(HEADER_ARCH)/,$(subarch-obj-y)) -endif diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile deleted file mode 100644 index 804b28dd032..00000000000 --- a/arch/um/sys-i386/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) -# - -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 stub.o stub_segv.o syscalls.o sysrq.o \ - sys_call_table.o tls.o - -obj-$(CONFIG_BINFMT_ELF) += elfcore.o - -subarch-obj-y = lib/semaphore_32.o lib/string_32.o -subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o -subarch-obj-$(CONFIG_MODULES) += kernel/module.o - -USER_OBJS := bugs.o ptrace_user.o fault.o - -USER_OBJS += user-offsets.s -extra-y += user-offsets.s - -UNPROFILE_OBJS := stub_segv.o -CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) - -include arch/um/scripts/Makefile.rules diff --git a/arch/um/sys-i386/asm/archparam.h b/arch/um/sys-i386/asm/archparam.h deleted file mode 100644 index 2a18a884ca1..00000000000 --- a/arch/um/sys-i386/asm/archparam.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __UM_ARCHPARAM_I386_H -#define __UM_ARCHPARAM_I386_H - -#ifdef CONFIG_X86_PAE -#define LAST_PKMAP 512 -#else -#define LAST_PKMAP 1024 -#endif - -#endif - diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h deleted file mode 100644 index d964a4111ac..00000000000 --- a/arch/um/sys-i386/asm/elf.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ -#ifndef __UM_ELF_I386_H -#define __UM_ELF_I386_H - -#include <asm/user.h> -#include "skas.h" - -#define R_386_NONE 0 -#define R_386_32 1 -#define R_386_PC32 2 -#define R_386_GOT32 3 -#define R_386_PLT32 4 -#define R_386_COPY 5 -#define R_386_GLOB_DAT 6 -#define R_386_JMP_SLOT 7 -#define R_386_RELATIVE 8 -#define R_386_GOTOFF 9 -#define R_386_GOTPC 10 -#define R_386_NUM 11 - -typedef unsigned long elf_greg_t; - -#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct user_i387_struct elf_fpregset_t; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) \ - (((x)->e_machine == EM_386) || ((x)->e_machine == EM_486)) - -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2LSB -#define ELF_ARCH EM_386 - -#define ELF_PLAT_INIT(regs, load_addr) do { \ - PT_REGS_EBX(regs) = 0; \ - PT_REGS_ECX(regs) = 0; \ - PT_REGS_EDX(regs) = 0; \ - PT_REGS_ESI(regs) = 0; \ - PT_REGS_EDI(regs) = 0; \ - PT_REGS_EBP(regs) = 0; \ - PT_REGS_EAX(regs) = 0; \ -} while (0) - -#define ELF_EXEC_PAGESIZE 4096 - -#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) - -/* Shamelessly stolen from include/asm-i386/elf.h */ - -#define ELF_CORE_COPY_REGS(pr_reg, regs) do { \ - pr_reg[0] = PT_REGS_EBX(regs); \ - pr_reg[1] = PT_REGS_ECX(regs); \ - pr_reg[2] = PT_REGS_EDX(regs); \ - pr_reg[3] = PT_REGS_ESI(regs); \ - pr_reg[4] = PT_REGS_EDI(regs); \ - pr_reg[5] = PT_REGS_EBP(regs); \ - pr_reg[6] = PT_REGS_EAX(regs); \ - pr_reg[7] = PT_REGS_DS(regs); \ - pr_reg[8] = PT_REGS_ES(regs); \ - /* fake once used fs and gs selectors? */ \ - pr_reg[9] = PT_REGS_DS(regs); \ - pr_reg[10] = PT_REGS_DS(regs); \ - pr_reg[11] = PT_REGS_SYSCALL_NR(regs); \ - pr_reg[12] = PT_REGS_IP(regs); \ - pr_reg[13] = PT_REGS_CS(regs); \ - pr_reg[14] = PT_REGS_EFLAGS(regs); \ - pr_reg[15] = PT_REGS_SP(regs); \ - pr_reg[16] = PT_REGS_SS(regs); \ -} while (0); - -#define task_pt_regs(t) (&(t)->thread.regs) - -struct task_struct; - -extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu); - -#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu) - -extern long elf_aux_hwcap; -#define ELF_HWCAP (elf_aux_hwcap) - -extern char * elf_aux_platform; -#define ELF_PLATFORM (elf_aux_platform) - -#define SET_PERSONALITY(ex) do { } while (0) - -extern unsigned long vsyscall_ehdr; -extern unsigned long vsyscall_end; -extern unsigned long __kernel_vsyscall; - -#define VSYSCALL_BASE vsyscall_ehdr -#define VSYSCALL_END vsyscall_end - -/* - * This is the range that is readable by user mode, and things - * acting like user mode such as get_user_pages. - */ -#define FIXADDR_USER_START VSYSCALL_BASE -#define FIXADDR_USER_END VSYSCALL_END - -/* - * Architecture-neutral AT_ values in 0-17, leave some room - * for more of them, start the x86-specific ones at 32. - */ -#define AT_SYSINFO 32 -#define AT_SYSINFO_EHDR 33 - -#define ARCH_DLINFO \ -do { \ - if ( vsyscall_ehdr ) { \ - NEW_AUX_ENT(AT_SYSINFO, __kernel_vsyscall); \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, vsyscall_ehdr); \ - } \ -} while (0) - -#endif diff --git a/arch/um/sys-i386/asm/module.h b/arch/um/sys-i386/asm/module.h deleted file mode 100644 index 5ead4a0b2e3..00000000000 --- a/arch/um/sys-i386/asm/module.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __UM_MODULE_I386_H -#define __UM_MODULE_I386_H - -/* UML is simple */ -struct mod_arch_specific -{ -}; - -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr - -#endif diff --git a/arch/um/sys-i386/asm/processor.h b/arch/um/sys-i386/asm/processor.h deleted file mode 100644 index 82a9061ab5b..00000000000 --- a/arch/um/sys-i386/asm/processor.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __UM_PROCESSOR_I386_H -#define __UM_PROCESSOR_I386_H - -#include "linux/string.h" -#include <sysdep/host_ldt.h> -#include "asm/segment.h" - -extern int host_has_cmov; - -/* include faultinfo structure */ -#include "sysdep/faultinfo.h" - -struct uml_tls_struct { - struct user_desc tls; - unsigned flushed:1; - unsigned present:1; -}; - -struct arch_thread { - struct uml_tls_struct tls_array[GDT_ENTRY_TLS_ENTRIES]; - unsigned long debugregs[8]; - int debugregs_seq; - struct faultinfo faultinfo; -}; - -#define INIT_ARCH_THREAD { \ - .tls_array = { [ 0 ... GDT_ENTRY_TLS_ENTRIES - 1 ] = \ - { .present = 0, .flushed = 0 } }, \ - .debugregs = { [ 0 ... 7 ] = 0 }, \ - .debugregs_seq = 0, \ - .faultinfo = { 0, 0, 0 } \ -} - -static inline void arch_flush_thread(struct arch_thread *thread) -{ - /* Clear any TLS still hanging */ - memset(&thread->tls_array, 0, sizeof(thread->tls_array)); -} - -static inline void arch_copy_thread(struct arch_thread *from, - struct arch_thread *to) -{ - memcpy(&to->tls_array, &from->tls_array, sizeof(from->tls_array)); -} - -#include <asm/user.h> - -/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ -static inline void rep_nop(void) -{ - __asm__ __volatile__("rep;nop": : :"memory"); -} - -#define cpu_relax() rep_nop() - -/* - * Default implementation of macro that returns current - * instruction pointer ("program counter"). Stolen - * from asm-i386/processor.h - */ -#define current_text_addr() \ - ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; }) - -#define ARCH_IS_STACKGROW(address) \ - (address + 32 >= UPT_SP(¤t->thread.regs.regs)) - -#define KSTK_EIP(tsk) KSTK_REG(tsk, EIP) -#define KSTK_ESP(tsk) KSTK_REG(tsk, UESP) -#define KSTK_EBP(tsk) KSTK_REG(tsk, EBP) - -#include "asm/processor-generic.h" - -#endif diff --git a/arch/um/sys-i386/asm/ptrace.h b/arch/um/sys-i386/asm/ptrace.h deleted file mode 100644 index 0273e4d09af..00000000000 --- a/arch/um/sys-i386/asm/ptrace.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __UM_PTRACE_I386_H -#define __UM_PTRACE_I386_H - -#define HOST_AUDIT_ARCH AUDIT_ARCH_I386 - -#include "linux/compiler.h" -#include "asm/ptrace-generic.h" - -#define PT_REGS_EAX(r) UPT_EAX(&(r)->regs) -#define PT_REGS_EBX(r) UPT_EBX(&(r)->regs) -#define PT_REGS_ECX(r) UPT_ECX(&(r)->regs) -#define PT_REGS_EDX(r) UPT_EDX(&(r)->regs) -#define PT_REGS_ESI(r) UPT_ESI(&(r)->regs) -#define PT_REGS_EDI(r) UPT_EDI(&(r)->regs) -#define PT_REGS_EBP(r) UPT_EBP(&(r)->regs) - -#define PT_REGS_CS(r) UPT_CS(&(r)->regs) -#define PT_REGS_SS(r) UPT_SS(&(r)->regs) -#define PT_REGS_DS(r) UPT_DS(&(r)->regs) -#define PT_REGS_ES(r) UPT_ES(&(r)->regs) -#define PT_REGS_FS(r) UPT_FS(&(r)->regs) -#define PT_REGS_GS(r) UPT_GS(&(r)->regs) - -#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) - -#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_EAX(r) -#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r) -#define PT_FIX_EXEC_STACK(sp) do ; while(0) - -#define profile_pc(regs) PT_REGS_IP(regs) - -#define user_mode(r) UPT_IS_USER(&(r)->regs) - -/* - * Forward declaration to avoid including sysdep/tls.h, which causes a - * circular include, and compilation failures. - */ -struct user_desc; - -extern int get_fpxregs(struct user_fxsr_struct __user *buf, - struct task_struct *child); -extern int set_fpxregs(struct user_fxsr_struct __user *buf, - struct task_struct *tsk); - -extern int ptrace_get_thread_area(struct task_struct *child, int idx, - struct user_desc __user *user_desc); - -extern int ptrace_set_thread_area(struct task_struct *child, int idx, - struct user_desc __user *user_desc); - -#endif diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c deleted file mode 100644 index 8d4f273f121..00000000000 --- a/arch/um/sys-i386/bug.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL V2 - */ - -#include <linux/uaccess.h> -#include <asm/errno.h> - -/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because - * that's not relevant in skas mode. - */ - -int is_valid_bugaddr(unsigned long eip) -{ - unsigned short ud2; - - if (probe_kernel_address((unsigned short __user *)eip, ud2)) - return 0; - - return ud2 == 0x0b0f; -} diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c deleted file mode 100644 index 2c6d0d731c1..00000000000 --- a/arch/um/sys-i386/bugs.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <signal.h> -#include "kern_constants.h" -#include "kern_util.h" -#include "longjmp.h" -#include "task.h" -#include "user.h" -#include "sysdep/ptrace.h" - -/* Set during early boot */ -static int host_has_cmov = 1; -static jmp_buf cmov_test_return; - -static void cmov_sigill_test_handler(int sig) -{ - host_has_cmov = 0; - longjmp(cmov_test_return, 1); -} - -void arch_check_bugs(void) -{ - struct sigaction old, new; - - printk(UM_KERN_INFO "Checking for host processor cmov support..."); - new.sa_handler = cmov_sigill_test_handler; - - /* Make sure that SIGILL is enabled after the handler longjmps back */ - new.sa_flags = SA_NODEFER; - sigemptyset(&new.sa_mask); - sigaction(SIGILL, &new, &old); - - if (setjmp(cmov_test_return) == 0) { - unsigned long foo = 0; - __asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo)); - printk(UM_KERN_CONT "Yes\n"); - } else - printk(UM_KERN_CONT "No\n"); - - sigaction(SIGILL, &old, &new); -} - -void arch_examine_signal(int sig, struct uml_pt_regs *regs) -{ - unsigned char tmp[2]; - - /* - * This is testing for a cmov (0x0f 0x4x) instruction causing a - * SIGILL in init. - */ - if ((sig != SIGILL) || (TASK_PID(get_current()) != 1)) - return; - - if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) { - printk(UM_KERN_ERR "SIGILL in init, could not read " - "instructions!\n"); - return; - } - - if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40)) - return; - - if (host_has_cmov == 0) - printk(UM_KERN_ERR "SIGILL caused by cmov, which this " - "processor doesn't implement. Boot a filesystem " - "compiled for older processors"); - else if (host_has_cmov == 1) - printk(UM_KERN_ERR "SIGILL caused by cmov, which this " - "processor claims to implement"); - else - printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)", - host_has_cmov); -} diff --git a/arch/um/sys-i386/checksum.S b/arch/um/sys-i386/checksum.S deleted file mode 100644 index f058d2f82e1..00000000000 --- a/arch/um/sys-i386/checksum.S +++ /dev/null @@ -1,458 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * IP/TCP/UDP checksumming routines - * - * Authors: Jorge Cwik, <jorge@laser.satlink.net> - * Arnt Gulbrandsen, <agulbra@nvg.unit.no> - * Tom May, <ftom@netcom.com> - * Pentium Pro/II routines: - * Alexander Kjeldaas <astor@guardian.no> - * Finn Arne Gangstad <finnag@guardian.no> - * Lots of code moved from tcp.c and ip.c; see those files - * for more names. - * - * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception - * handling. - * Andi Kleen, add zeroing on error - * converted to pure assembler - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <asm/errno.h> - -/* - * computes a partial checksum, e.g. for TCP/UDP fragments - */ - -/* -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) - */ - -.text -.align 4 -.globl csum_partial - -#ifndef CONFIG_X86_USE_PPRO_CHECKSUM - - /* - * Experiments with Ethernet and SLIP connections show that buff - * is aligned on either a 2-byte or 4-byte boundary. We get at - * least a twofold speedup on 486 and Pentium if it is 4-byte aligned. - * Fortunately, it is easy to convert 2-byte alignment to 4-byte - * alignment for the unrolled loop. - */ -csum_partial: - pushl %esi - pushl %ebx - movl 20(%esp),%eax # Function arg: unsigned int sum - movl 16(%esp),%ecx # Function arg: int len - movl 12(%esp),%esi # Function arg: unsigned char *buff - testl $2, %esi # Check alignment. - jz 2f # Jump if alignment is ok. - subl $2, %ecx # Alignment uses up two bytes. - jae 1f # Jump if we had at least two bytes. - addl $2, %ecx # ecx was < 2. Deal with it. - jmp 4f -1: movw (%esi), %bx - addl $2, %esi - addw %bx, %ax - adcl $0, %eax -2: - movl %ecx, %edx - shrl $5, %ecx - jz 2f - testl %esi, %esi -1: movl (%esi), %ebx - adcl %ebx, %eax - movl 4(%esi), %ebx - adcl %ebx, %eax - movl 8(%esi), %ebx - adcl %ebx, %eax - movl 12(%esi), %ebx - adcl %ebx, %eax - movl 16(%esi), %ebx - adcl %ebx, %eax - movl 20(%esi), %ebx - adcl %ebx, %eax - movl 24(%esi), %ebx - adcl %ebx, %eax - movl 28(%esi), %ebx - adcl %ebx, %eax - lea 32(%esi), %esi - dec %ecx - jne 1b - adcl $0, %eax -2: movl %edx, %ecx - andl $0x1c, %edx - je 4f - shrl $2, %edx # This clears CF -3: adcl (%esi), %eax - lea 4(%esi), %esi - dec %edx - jne 3b - adcl $0, %eax -4: andl $3, %ecx - jz 7f - cmpl $2, %ecx - jb 5f - movw (%esi),%cx - leal 2(%esi),%esi - je 6f - shll $16,%ecx -5: movb (%esi),%cl -6: addl %ecx,%eax - adcl $0, %eax -7: - popl %ebx - popl %esi - ret - -#else - -/* Version for PentiumII/PPro */ - -csum_partial: - pushl %esi - pushl %ebx - movl 20(%esp),%eax # Function arg: unsigned int sum - movl 16(%esp),%ecx # Function arg: int len - movl 12(%esp),%esi # Function arg: const unsigned char *buf - - testl $2, %esi - jnz 30f -10: - movl %ecx, %edx - movl %ecx, %ebx - andl $0x7c, %ebx - shrl $7, %ecx - addl %ebx,%esi - shrl $2, %ebx - negl %ebx - lea 45f(%ebx,%ebx,2), %ebx - testl %esi, %esi - jmp *%ebx - - # Handle 2-byte-aligned regions -20: addw (%esi), %ax - lea 2(%esi), %esi - adcl $0, %eax - jmp 10b - -30: subl $2, %ecx - ja 20b - je 32f - movzbl (%esi),%ebx # csumming 1 byte, 2-aligned - addl %ebx, %eax - adcl $0, %eax - jmp 80f -32: - addw (%esi), %ax # csumming 2 bytes, 2-aligned - adcl $0, %eax - jmp 80f - -40: - addl -128(%esi), %eax - adcl -124(%esi), %eax - adcl -120(%esi), %eax - adcl -116(%esi), %eax - adcl -112(%esi), %eax - adcl -108(%esi), %eax - adcl -104(%esi), %eax - adcl -100(%esi), %eax - adcl -96(%esi), %eax - adcl -92(%esi), %eax - adcl -88(%esi), %eax - adcl -84(%esi), %eax - adcl -80(%esi), %eax - adcl -76(%esi), %eax - adcl -72(%esi), %eax - adcl -68(%esi), %eax - adcl -64(%esi), %eax - adcl -60(%esi), %eax - adcl -56(%esi), %eax - adcl -52(%esi), %eax - adcl -48(%esi), %eax - adcl -44(%esi), %eax - adcl -40(%esi), %eax - adcl -36(%esi), %eax - adcl -32(%esi), %eax - adcl -28(%esi), %eax - adcl -24(%esi), %eax - adcl -20(%esi), %eax - adcl -16(%esi), %eax - adcl -12(%esi), %eax - adcl -8(%esi), %eax - adcl -4(%esi), %eax -45: - lea 128(%esi), %esi - adcl $0, %eax - dec %ecx - jge 40b - movl %edx, %ecx -50: andl $3, %ecx - jz 80f - - # Handle the last 1-3 bytes without jumping - notl %ecx # 1->2, 2->1, 3->0, higher bits are masked - movl $0xffffff,%ebx # by the shll and shrl instructions - shll $3,%ecx - shrl %cl,%ebx - andl -128(%esi),%ebx # esi is 4-aligned so should be ok - addl %ebx,%eax - adcl $0,%eax -80: - popl %ebx - popl %esi - ret - -#endif - -/* -unsigned int csum_partial_copy_generic (const char *src, char *dst, - int len, int sum, int *src_err_ptr, int *dst_err_ptr) - */ - -/* - * Copy from ds while checksumming, otherwise like csum_partial - * - * The macros SRC and DST specify the type of access for the instruction. - * thus we can call a custom exception handler for all access types. - * - * FIXME: could someone double-check whether I haven't mixed up some SRC and - * DST definitions? It's damn hard to trigger all cases. I hope I got - * them all but there's no guarantee. - */ - -#define SRC(y...) \ - 9999: y; \ - .section __ex_table, "a"; \ - .long 9999b, 6001f ; \ - .previous - -#define DST(y...) \ - 9999: y; \ - .section __ex_table, "a"; \ - .long 9999b, 6002f ; \ - .previous - -.align 4 - -#ifndef CONFIG_X86_USE_PPRO_CHECKSUM - -#define ARGBASE 16 -#define FP 12 - -csum_partial_copy_generic_i386: - subl $4,%esp - pushl %edi - pushl %esi - pushl %ebx - movl ARGBASE+16(%esp),%eax # sum - movl ARGBASE+12(%esp),%ecx # len - movl ARGBASE+4(%esp),%esi # src - movl ARGBASE+8(%esp),%edi # dst - - testl $2, %edi # Check alignment. - jz 2f # Jump if alignment is ok. - subl $2, %ecx # Alignment uses up two bytes. - jae 1f # Jump if we had at least two bytes. - addl $2, %ecx # ecx was < 2. Deal with it. - jmp 4f -SRC(1: movw (%esi), %bx ) - addl $2, %esi -DST( movw %bx, (%edi) ) - addl $2, %edi - addw %bx, %ax - adcl $0, %eax -2: - movl %ecx, FP(%esp) - shrl $5, %ecx - jz 2f - testl %esi, %esi -SRC(1: movl (%esi), %ebx ) -SRC( movl 4(%esi), %edx ) - adcl %ebx, %eax -DST( movl %ebx, (%edi) ) - adcl %edx, %eax -DST( movl %edx, 4(%edi) ) - -SRC( movl 8(%esi), %ebx ) -SRC( movl 12(%esi), %edx ) - adcl %ebx, %eax -DST( movl %ebx, 8(%edi) ) - adcl %edx, %eax -DST( movl %edx, 12(%edi) ) - -SRC( movl 16(%esi), %ebx ) -SRC( movl 20(%esi), %edx ) - adcl %ebx, %eax -DST( movl %ebx, 16(%edi) ) - adcl %edx, %eax -DST( movl %edx, 20(%edi) ) - -SRC( movl 24(%esi), %ebx ) -SRC( movl 28(%esi), %edx ) - adcl %ebx, %eax -DST( movl %ebx, 24(%edi) ) - adcl %edx, %eax -DST( movl %edx, 28(%edi) ) - - lea 32(%esi), %esi - lea 32(%edi), %edi - dec %ecx - jne 1b - adcl $0, %eax -2: movl FP(%esp), %edx - movl %edx, %ecx - andl $0x1c, %edx - je 4f - shrl $2, %edx # This clears CF -SRC(3: movl (%esi), %ebx ) - adcl %ebx, %eax -DST( movl %ebx, (%edi) ) - lea 4(%esi), %esi - lea 4(%edi), %edi - dec %edx - jne 3b - adcl $0, %eax -4: andl $3, %ecx - jz 7f - cmpl $2, %ecx - jb 5f -SRC( movw (%esi), %cx ) - leal 2(%esi), %esi -DST( movw %cx, (%edi) ) - leal 2(%edi), %edi - je 6f - shll $16,%ecx -SRC(5: movb (%esi), %cl ) -DST( movb %cl, (%edi) ) -6: addl %ecx, %eax - adcl $0, %eax -7: -5000: - -# Exception handler: -.section .fixup, "ax" - -6001: - movl ARGBASE+20(%esp), %ebx # src_err_ptr - movl $-EFAULT, (%ebx) - - # zero the complete destination - computing the rest - # is too much work - movl ARGBASE+8(%esp), %edi # dst - movl ARGBASE+12(%esp), %ecx # len - xorl %eax,%eax - rep ; stosb - - jmp 5000b - -6002: - movl ARGBASE+24(%esp), %ebx # dst_err_ptr - movl $-EFAULT,(%ebx) - jmp 5000b - -.previous - - popl %ebx - popl %esi - popl %edi - popl %ecx # equivalent to addl $4,%esp - ret - -#else - -/* Version for PentiumII/PPro */ - -#define ROUND1(x) \ - SRC(movl x(%esi), %ebx ) ; \ - addl %ebx, %eax ; \ - DST(movl %ebx, x(%edi) ) ; - -#define ROUND(x) \ - SRC(movl x(%esi), %ebx ) ; \ - adcl %ebx, %eax ; \ - DST(movl %ebx, x(%edi) ) ; - -#define ARGBASE 12 - -csum_partial_copy_generic_i386: - pushl %ebx - pushl %edi - pushl %esi - movl ARGBASE+4(%esp),%esi #src - movl ARGBASE+8(%esp),%edi #dst - movl ARGBASE+12(%esp),%ecx #len - movl ARGBASE+16(%esp),%eax #sum -# movl %ecx, %edx - movl %ecx, %ebx - movl %esi, %edx - shrl $6, %ecx - andl $0x3c, %ebx - negl %ebx - subl %ebx, %esi - subl %ebx, %edi - lea -1(%esi),%edx - andl $-32,%edx - lea 3f(%ebx,%ebx), %ebx - testl %esi, %esi - jmp *%ebx -1: addl $64,%esi - addl $64,%edi - SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl) - ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52) - ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36) - ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20) - ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4) -3: adcl $0,%eax - addl $64, %edx - dec %ecx - jge 1b -4: movl ARGBASE+12(%esp),%edx #len - andl $3, %edx - jz 7f - cmpl $2, %edx - jb 5f -SRC( movw (%esi), %dx ) - leal 2(%esi), %esi -DST( movw %dx, (%edi) ) - leal 2(%edi), %edi - je 6f - shll $16,%edx -5: -SRC( movb (%esi), %dl ) -DST( movb %dl, (%edi) ) -6: addl %edx, %eax - adcl $0, %eax -7: -.section .fixup, "ax" -6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr - movl $-EFAULT, (%ebx) - # zero the complete destination (computing the rest is too much work) - movl ARGBASE+8(%esp),%edi # dst - movl ARGBASE+12(%esp),%ecx # len - xorl %eax,%eax - rep; stosb - jmp 7b -6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr - movl $-EFAULT, (%ebx) - jmp 7b -.previous - - popl %esi - popl %edi - popl %ebx - ret - -#undef ROUND -#undef ROUND1 - -#endif diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c deleted file mode 100644 index d623e074f41..00000000000 --- a/arch/um/sys-i386/delay.c +++ /dev/null @@ -1,29 +0,0 @@ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <asm/param.h> - -void __delay(unsigned long time) -{ - /* Stolen from the i386 __loop_delay */ - int d0; - __asm__ __volatile__( - "\tjmp 1f\n" - ".align 16\n" - "1:\tjmp 2f\n" - ".align 16\n" - "2:\tdecl %0\n\tjns 2b" - :"=&a" (d0) - :"0" (time)); -} - -void __udelay(unsigned long usecs) -{ - int i, n; - - n = (loops_per_jiffy * HZ * usecs) / MILLION; - for(i=0;i<n;i++) - cpu_relax(); -} - -EXPORT_SYMBOL(__udelay); diff --git a/arch/um/sys-i386/elfcore.c b/arch/um/sys-i386/elfcore.c deleted file mode 100644 index 6bb49b687c9..00000000000 --- a/arch/um/sys-i386/elfcore.c +++ /dev/null @@ -1,83 +0,0 @@ -#include <linux/elf.h> -#include <linux/coredump.h> -#include <linux/fs.h> -#include <linux/mm.h> - -#include <asm/elf.h> - - -Elf32_Half elf_core_extra_phdrs(void) -{ - return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0; -} - -int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size, - unsigned long limit) -{ - if ( vsyscall_ehdr ) { - const struct elfhdr *const ehdrp = - (struct elfhdr *) vsyscall_ehdr; - const struct elf_phdr *const phdrp = - (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); - int i; - Elf32_Off ofs = 0; - - for (i = 0; i < ehdrp->e_phnum; ++i) { - struct elf_phdr phdr = phdrp[i]; - - if (phdr.p_type == PT_LOAD) { - ofs = phdr.p_offset = offset; - offset += phdr.p_filesz; - } else { - phdr.p_offset += ofs; - } - phdr.p_paddr = 0; /* match other core phdrs */ - *size += sizeof(phdr); - if (*size > limit - || !dump_write(file, &phdr, sizeof(phdr))) - return 0; - } - } - return 1; -} - -int elf_core_write_extra_data(struct file *file, size_t *size, - unsigned long limit) -{ - if ( vsyscall_ehdr ) { - const struct elfhdr *const ehdrp = - (struct elfhdr *) vsyscall_ehdr; - const struct elf_phdr *const phdrp = - (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); - int i; - - for (i = 0; i < ehdrp->e_phnum; ++i) { - if (phdrp[i].p_type == PT_LOAD) { - void *addr = (void *) phdrp[i].p_vaddr; - size_t filesz = phdrp[i].p_filesz; - - *size += filesz; - if (*size > limit - || !dump_write(file, addr, filesz)) - return 0; - } - } - } - return 1; -} - -size_t elf_core_extra_data_size(void) -{ - if ( vsyscall_ehdr ) { - const struct elfhdr *const ehdrp = - (struct elfhdr *)vsyscall_ehdr; - const struct elf_phdr *const phdrp = - (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); - int i; - - for (i = 0; i < ehdrp->e_phnum; ++i) - if (phdrp[i].p_type == PT_LOAD) - return (size_t) phdrp[i].p_filesz; - } - return 0; -} diff --git a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c deleted file mode 100644 index d670f68532f..00000000000 --- a/arch/um/sys-i386/fault.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include "sysdep/ptrace.h" - -/* These two are from asm-um/uaccess.h and linux/module.h, check them. */ -struct exception_table_entry -{ - unsigned long insn; - unsigned long fixup; -}; - -const struct exception_table_entry *search_exception_tables(unsigned long add); - -/* Compare this to arch/i386/mm/extable.c:fixup_exception() */ -int arch_fixup(unsigned long address, struct uml_pt_regs *regs) -{ - const struct exception_table_entry *fixup; - - fixup = search_exception_tables(address); - if (fixup != 0) { - UPT_IP(regs) = fixup->fixup; - return 1; - } - return 0; -} diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c deleted file mode 100644 index bfbefd30db8..00000000000 --- a/arch/um/sys-i386/ksyms.c +++ /dev/null @@ -1,5 +0,0 @@ -#include "linux/module.h" -#include "asm/checksum.h" - -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial); diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c deleted file mode 100644 index 3f2bf208d88..00000000000 --- a/arch/um/sys-i386/ldt.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <asm/unistd.h> -#include "os.h" -#include "proc_mm.h" -#include "skas.h" -#include "skas_ptrace.h" -#include "sysdep/tls.h" - -extern int modify_ldt(int func, void *ptr, unsigned long bytecount); - -static long write_ldt_entry(struct mm_id *mm_idp, int func, - struct user_desc *desc, void **addr, int done) -{ - long res; - - if (proc_mm) { - /* - * This is a special handling for the case, that the mm to - * modify isn't current->active_mm. - * If this is called directly by modify_ldt, - * (current->active_mm->context.skas.u == mm_idp) - * will be true. So no call to __switch_mm(mm_idp) is done. - * If this is called in case of init_new_ldt or PTRACE_LDT, - * mm_idp won't belong to current->active_mm, but child->mm. - * So we need to switch child's mm into our userspace, then - * later switch back. - * - * Note: I'm unsure: should interrupts be disabled here? - */ - if (!current->active_mm || current->active_mm == &init_mm || - mm_idp != ¤t->active_mm->context.id) - __switch_mm(mm_idp); - } - - if (ptrace_ldt) { - struct ptrace_ldt ldt_op = (struct ptrace_ldt) { - .func = func, - .ptr = desc, - .bytecount = sizeof(*desc)}; - u32 cpu; - int pid; - - if (!proc_mm) - pid = mm_idp->u.pid; - else { - cpu = get_cpu(); - pid = userspace_pid[cpu]; - } - - res = os_ptrace_ldt(pid, 0, (unsigned long) &ldt_op); - - if (proc_mm) - put_cpu(); - } - else { - void *stub_addr; - res = syscall_stub_data(mm_idp, (unsigned long *)desc, - (sizeof(*desc) + sizeof(long) - 1) & - ~(sizeof(long) - 1), - addr, &stub_addr); - if (!res) { - unsigned long args[] = { func, - (unsigned long)stub_addr, - sizeof(*desc), - 0, 0, 0 }; - res = run_syscall_stub(mm_idp, __NR_modify_ldt, args, - 0, addr, done); - } - } - - if (proc_mm) { - /* - * This is the second part of special handling, that makes - * PTRACE_LDT possible to implement. - */ - if (current->active_mm && current->active_mm != &init_mm && - mm_idp != ¤t->active_mm->context.id) - __switch_mm(¤t->active_mm->context.id); - } - - return res; -} - -static long read_ldt_from_host(void __user * ptr, unsigned long bytecount) -{ - int res, n; - struct ptrace_ldt ptrace_ldt = (struct ptrace_ldt) { - .func = 0, - .bytecount = bytecount, - .ptr = kmalloc(bytecount, GFP_KERNEL)}; - u32 cpu; - - if (ptrace_ldt.ptr == NULL) - return -ENOMEM; - - /* - * This is called from sys_modify_ldt only, so userspace_pid gives - * us the right number - */ - - cpu = get_cpu(); - res = os_ptrace_ldt(userspace_pid[cpu], 0, (unsigned long) &ptrace_ldt); - put_cpu(); - if (res < 0) - goto out; - - n = copy_to_user(ptr, ptrace_ldt.ptr, res); - if (n != 0) - res = -EFAULT; - - out: - kfree(ptrace_ldt.ptr); - - return res; -} - -/* - * In skas mode, we hold our own ldt data in UML. - * Thus, the code implementing sys_modify_ldt_skas - * is very similar to (and mostly stolen from) sys_modify_ldt - * for arch/i386/kernel/ldt.c - * The routines copied and modified in part are: - * - read_ldt - * - read_default_ldt - * - write_ldt - * - sys_modify_ldt_skas - */ - -static int read_ldt(void __user * ptr, unsigned long bytecount) -{ - int i, err = 0; - unsigned long size; - uml_ldt_t * ldt = ¤t->mm->context.ldt; - - if (!ldt->entry_count) - goto out; - if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES) - bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES; - err = bytecount; - - if (ptrace_ldt) - return read_ldt_from_host(ptr, bytecount); - - mutex_lock(&ldt->lock); - if (ldt->entry_count <= LDT_DIRECT_ENTRIES) { - size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; - if (size > bytecount) - size = bytecount; - if (copy_to_user(ptr, ldt->u.entries, size)) - err = -EFAULT; - bytecount -= size; - ptr += size; - } - else { - for (i=0; i<ldt->entry_count/LDT_ENTRIES_PER_PAGE && bytecount; - i++) { - size = PAGE_SIZE; - if (size > bytecount) - size = bytecount; - if (copy_to_user(ptr, ldt->u.pages[i], size)) { - err = -EFAULT; - break; - } - bytecount -= size; - ptr += size; - } - } - mutex_unlock(&ldt->lock); - - if (bytecount == 0 || err == -EFAULT) - goto out; - - if (clear_user(ptr, bytecount)) - err = -EFAULT; - -out: - return err; -} - -static int read_default_ldt(void __user * ptr, unsigned long bytecount) -{ - int err; - - if (bytecount > 5*LDT_ENTRY_SIZE) - bytecount = 5*LDT_ENTRY_SIZE; - - err = bytecount; - /* - * UML doesn't support lcall7 and lcall27. - * So, we don't really have a default ldt, but emulate - * an empty ldt of common host default ldt size. - */ - if (clear_user(ptr, bytecount)) - err = -EFAULT; - - return err; -} - -static int write_ldt(void __user * ptr, unsigned long bytecount, int func) -{ - uml_ldt_t * ldt = ¤t->mm->context.ldt; - struct mm_id * mm_idp = ¤t->mm->context.id; - int i, err; - struct user_desc ldt_info; - struct ldt_entry entry0, *ldt_p; - void *addr = NULL; - - err = -EINVAL; - if (bytecount != sizeof(ldt_info)) - goto out; - err = -EFAULT; - if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info))) - goto out; - - err = -EINVAL; - if (ldt_info.entry_number >= LDT_ENTRIES) - goto out; - if (ldt_info.contents == 3) { - if (func == 1) - goto out; - if (ldt_info.seg_not_present == 0) - goto out; - } - - if (!ptrace_ldt) - mutex_lock(&ldt->lock); - - err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1); - if (err) - goto out_unlock; - else if (ptrace_ldt) { - /* With PTRACE_LDT available, this is used as a flag only */ - ldt->entry_count = 1; - goto out; - } - - if (ldt_info.entry_number >= ldt->entry_count && - ldt_info.entry_number >= LDT_DIRECT_ENTRIES) { - for (i=ldt->entry_count/LDT_ENTRIES_PER_PAGE; - i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; - i++) { - if (i == 0) - memcpy(&entry0, ldt->u.entries, - sizeof(entry0)); - ldt->u.pages[i] = (struct ldt_entry *) - __get_free_page(GFP_KERNEL|__GFP_ZERO); - if (!ldt->u.pages[i]) { - err = -ENOMEM; - /* Undo the change in host */ - memset(&ldt_info, 0, sizeof(ldt_info)); - write_ldt_entry(mm_idp, 1, &ldt_info, &addr, 1); - goto out_unlock; - } - if (i == 0) { - memcpy(ldt->u.pages[0], &entry0, - sizeof(entry0)); - memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, - sizeof(entry0)*(LDT_DIRECT_ENTRIES-1)); - } - ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; - } - } - if (ldt->entry_count <= ldt_info.entry_number) - ldt->entry_count = ldt_info.entry_number + 1; - - if (ldt->entry_count <= LDT_DIRECT_ENTRIES) - ldt_p = ldt->u.entries + ldt_info.entry_number; - else - ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + - ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; - - if (ldt_info.base_addr == 0 && ldt_info.limit == 0 && - (func == 1 || LDT_empty(&ldt_info))) { - ldt_p->a = 0; - ldt_p->b = 0; - } - else{ - if (func == 1) - ldt_info.useable = 0; - ldt_p->a = LDT_entry_a(&ldt_info); - ldt_p->b = LDT_entry_b(&ldt_info); - } - err = 0; - -out_unlock: - mutex_unlock(&ldt->lock); -out: - return err; -} - -static long do_modify_ldt_skas(int func, void __user *ptr, - unsigned long bytecount) -{ - int ret = -ENOSYS; - - switch (func) { - case 0: - ret = read_ldt(ptr, bytecount); - break; - case 1: - case 0x11: - ret = write_ldt(ptr, bytecount, func); - break; - case 2: - ret = read_default_ldt(ptr, bytecount); - break; - } - return ret; -} - -static DEFINE_SPINLOCK(host_ldt_lock); -static short dummy_list[9] = {0, -1}; -static short * host_ldt_entries = NULL; - -static void ldt_get_host_info(void) -{ - long ret; - struct ldt_entry * ldt; - short *tmp; - int i, size, k, order; - - spin_lock(&host_ldt_lock); - - if (host_ldt_entries != NULL) { - spin_unlock(&host_ldt_lock); - return; - } - host_ldt_entries = dummy_list+1; - - spin_unlock(&host_ldt_lock); - - for (i = LDT_PAGES_MAX-1, order=0; i; i>>=1, order++) - ; - - ldt = (struct ldt_entry *) - __get_free_pages(GFP_KERNEL|__GFP_ZERO, order); - if (ldt == NULL) { - printk(KERN_ERR "ldt_get_host_info: couldn't allocate buffer " - "for host ldt\n"); - return; - } - - ret = modify_ldt(0, ldt, (1<<order)*PAGE_SIZE); - if (ret < 0) { - printk(KERN_ERR "ldt_get_host_info: couldn't read host ldt\n"); - goto out_free; - } - if (ret == 0) { - /* default_ldt is active, simply write an empty entry 0 */ - host_ldt_entries = dummy_list; - goto out_free; - } - - for (i=0, size=0; i<ret/LDT_ENTRY_SIZE; i++) { - if (ldt[i].a != 0 || ldt[i].b != 0) - size++; - } - - if (size < ARRAY_SIZE(dummy_list)) - host_ldt_entries = dummy_list; - else { - size = (size + 1) * sizeof(dummy_list[0]); - tmp = kmalloc(size, GFP_KERNEL); - if (tmp == NULL) { - printk(KERN_ERR "ldt_get_host_info: couldn't allocate " - "host ldt list\n"); - goto out_free; - } - host_ldt_entries = tmp; - } - - for (i=0, k=0; i<ret/LDT_ENTRY_SIZE; i++) { - if (ldt[i].a != 0 || ldt[i].b != 0) - host_ldt_entries[k++] = i; - } - host_ldt_entries[k] = -1; - -out_free: - free_pages((unsigned long)ldt, order); -} - -long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) -{ - struct user_desc desc; - short * num_p; - int i; - long page, err=0; - void *addr = NULL; - struct proc_mm_op copy; - - - if (!ptrace_ldt) - mutex_init(&new_mm->ldt.lock); - - if (!from_mm) { - memset(&desc, 0, sizeof(desc)); - /* - * We have to initialize a clean ldt. - */ - if (proc_mm) { - /* - * If the new mm was created using proc_mm, host's - * default-ldt currently is assigned, which normally - * contains the call-gates for lcall7 and lcall27. - * To remove these gates, we simply write an empty - * entry as number 0 to the host. - */ - err = write_ldt_entry(&new_mm->id, 1, &desc, &addr, 1); - } - else{ - /* - * Now we try to retrieve info about the ldt, we - * inherited from the host. All ldt-entries found - * will be reset in the following loop - */ - ldt_get_host_info(); - for (num_p=host_ldt_entries; *num_p != -1; num_p++) { - desc.entry_number = *num_p; - err = write_ldt_entry(&new_mm->id, 1, &desc, - &addr, *(num_p + 1) == -1); - if (err) - break; - } - } - new_mm->ldt.entry_count = 0; - - goto out; - } - - if (proc_mm) { - /* - * We have a valid from_mm, so we now have to copy the LDT of - * from_mm to new_mm, because using proc_mm an new mm with - * an empty/default LDT was created in new_mm() - */ - copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, - .u = - { .copy_segments = - from_mm->id.u.mm_fd } } ); - i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); - if (i != sizeof(copy)) - printk(KERN_ERR "new_mm : /proc/mm copy_segments " - "failed, err = %d\n", -i); - } - - if (!ptrace_ldt) { - /* - * Our local LDT is used to supply the data for - * modify_ldt(READLDT), if PTRACE_LDT isn't available, - * i.e., we have to use the stub for modify_ldt, which - * can't handle the big read buffer of up to 64kB. - */ - mutex_lock(&from_mm->ldt.lock); - if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES) - memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, - sizeof(new_mm->ldt.u.entries)); - else { - i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; - while (i-->0) { - page = __get_free_page(GFP_KERNEL|__GFP_ZERO); - if (!page) { - err = -ENOMEM; - break; - } - new_mm->ldt.u.pages[i] = - (struct ldt_entry *) page; - memcpy(new_mm->ldt.u.pages[i], - from_mm->ldt.u.pages[i], PAGE_SIZE); - } - } - new_mm->ldt.entry_count = from_mm->ldt.entry_count; - mutex_unlock(&from_mm->ldt.lock); - } - - out: - return err; -} - - -void free_ldt(struct mm_context *mm) -{ - int i; - - if (!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES) { - i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; - while (i-- > 0) - free_page((long) mm->ldt.u.pages[i]); - } - mm->ldt.entry_count = 0; -} - -int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) -{ - return do_modify_ldt_skas(func, ptr, bytecount); -} diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c deleted file mode 100644 index d23b2d3ea38..00000000000 --- a/arch/um/sys-i386/ptrace.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include "linux/mm.h" -#include "linux/sched.h" -#include "asm/uaccess.h" -#include "skas.h" - -extern int arch_switch_tls(struct task_struct *to); - -void arch_switch_to(struct task_struct *to) -{ - int err = arch_switch_tls(to); - if (!err) - return; - - if (err != -EINVAL) - printk(KERN_WARNING "arch_switch_tls failed, errno %d, " - "not EINVAL\n", -err); - else - printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n"); -} - -int is_syscall(unsigned long addr) -{ - unsigned short instr; - int n; - - n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if (n) { - /* access_process_vm() grants access to vsyscall and stub, - * while copy_from_user doesn't. Maybe access_process_vm is - * slow, but that doesn't matter, since it will be called only - * in case of singlestepping, if copy_from_user failed. - */ - n = access_process_vm(current, addr, &instr, sizeof(instr), 0); - if (n != sizeof(instr)) { - printk(KERN_ERR "is_syscall : failed to read " - "instruction from 0x%lx\n", addr); - return 1; - } - } - /* int 0x80 or sysenter */ - return (instr == 0x80cd) || (instr == 0x340f); -} - -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x00044dd5 - -int putreg(struct task_struct *child, int regno, unsigned long value) -{ - regno >>= 2; - switch (regno) { - case FS: - if (value && (value & 3) != 3) - return -EIO; - PT_REGS_FS(&child->thread.regs) = value; - return 0; - case GS: - if (value && (value & 3) != 3) - return -EIO; - PT_REGS_GS(&child->thread.regs) = value; - return 0; - case DS: - case ES: - if (value && (value & 3) != 3) - return -EIO; - value &= 0xffff; - break; - case SS: - case CS: - if ((value & 3) != 3) - return -EIO; - value &= 0xffff; - break; - case EFL: - value &= FLAG_MASK; - value |= PT_REGS_EFLAGS(&child->thread.regs); - break; - } - PT_REGS_SET(&child->thread.regs, regno, value); - return 0; -} - -int poke_user(struct task_struct *child, long addr, long data) -{ - if ((addr & 3) || addr < 0) - return -EIO; - - if (addr < MAX_REG_OFFSET) - return putreg(child, addr, data); - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))) { - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - if ((addr == 4) || (addr == 5)) - return -EIO; - child->thread.arch.debugregs[addr] = data; - return 0; - } - return -EIO; -} - -unsigned long getreg(struct task_struct *child, int regno) -{ - unsigned long retval = ~0UL; - - regno >>= 2; - switch (regno) { - case FS: - case GS: - case DS: - case ES: - case SS: - case CS: - retval = 0xffff; - /* fall through */ - default: - retval &= PT_REG(&child->thread.regs, regno); - } - return retval; -} - -/* read the word at location addr in the USER area. */ -int peek_user(struct task_struct *child, long addr, long data) -{ - unsigned long tmp; - - if ((addr & 3) || addr < 0) - return -EIO; - - tmp = 0; /* Default return condition */ - if (addr < MAX_REG_OFFSET) { - tmp = getreg(child, addr); - } - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))) { - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - tmp = child->thread.arch.debugregs[addr]; - } - return put_user(tmp, (unsigned long __user *) data); -} - -int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) -{ - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_i387_struct fpregs; - - err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs); - if (err) - return err; - - n = copy_to_user(buf, &fpregs, sizeof(fpregs)); - if(n > 0) - return -EFAULT; - - return n; -} - -int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) -{ - int n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_i387_struct fpregs; - - n = copy_from_user(&fpregs, buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; - - return restore_fp_registers(userspace_pid[cpu], - (unsigned long *) &fpregs); -} - -int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) -{ - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_fxsr_struct fpregs; - - err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs); - if (err) - return err; - - n = copy_to_user(buf, &fpregs, sizeof(fpregs)); - if(n > 0) - return -EFAULT; - - return n; -} - -int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) -{ - int n, cpu = ((struct thread_info *) child->stack)->cpu; - struct user_fxsr_struct fpregs; - - n = copy_from_user(&fpregs, buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; - - return restore_fpx_registers(userspace_pid[cpu], - (unsigned long *) &fpregs); -} - -long subarch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - return -EIO; -} diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c deleted file mode 100644 index 0b10c3e7402..00000000000 --- a/arch/um/sys-i386/ptrace_user.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <errno.h> -#include <sys/ptrace.h> - -int ptrace_getregs(long pid, unsigned long *regs_out) -{ - if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) - return -errno; - return 0; -} - -int ptrace_setregs(long pid, unsigned long *regs) -{ - if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0) - return -errno; - return 0; -} diff --git a/arch/um/sys-i386/setjmp.S b/arch/um/sys-i386/setjmp.S deleted file mode 100644 index b766792c993..00000000000 --- a/arch/um/sys-i386/setjmp.S +++ /dev/null @@ -1,58 +0,0 @@ -# -# arch/i386/setjmp.S -# -# setjmp/longjmp for the i386 architecture -# - -# -# The jmp_buf is assumed to contain the following, in order: -# %ebx -# %esp -# %ebp -# %esi -# %edi -# <return address> -# - - .text - .align 4 - .globl setjmp - .type setjmp, @function -setjmp: -#ifdef _REGPARM - movl %eax,%edx -#else - movl 4(%esp),%edx -#endif - popl %ecx # Return address, and adjust the stack - xorl %eax,%eax # Return value - movl %ebx,(%edx) - movl %esp,4(%edx) # Post-return %esp! - pushl %ecx # Make the call/return stack happy - movl %ebp,8(%edx) - movl %esi,12(%edx) - movl %edi,16(%edx) - movl %ecx,20(%edx) # Return address - ret - - .size setjmp,.-setjmp - - .text - .align 4 - .globl longjmp - .type longjmp, @function -longjmp: -#ifdef _REGPARM - xchgl %eax,%edx -#else - movl 4(%esp),%edx # jmp_ptr address - movl 8(%esp),%eax # Return value -#endif - movl (%edx),%ebx - movl 4(%edx),%esp - movl 8(%edx),%ebp - movl 12(%edx),%esi - movl 16(%edx),%edi - jmp *20(%edx) - - .size longjmp,.-longjmp diff --git a/arch/um/sys-i386/shared/sysdep/archsetjmp.h b/arch/um/sys-i386/shared/sysdep/archsetjmp.h deleted file mode 100644 index 0f312085ce1..00000000000 --- a/arch/um/sys-i386/shared/sysdep/archsetjmp.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * arch/um/include/sysdep-i386/archsetjmp.h - */ - -#ifndef _KLIBC_ARCHSETJMP_H -#define _KLIBC_ARCHSETJMP_H - -struct __jmp_buf { - unsigned int __ebx; - unsigned int __esp; - unsigned int __ebp; - unsigned int __esi; - unsigned int __edi; - unsigned int __eip; -}; - -typedef struct __jmp_buf jmp_buf[1]; - -#define JB_IP __eip -#define JB_SP __esp - -#endif /* _SETJMP_H */ diff --git a/arch/um/sys-i386/shared/sysdep/barrier.h b/arch/um/sys-i386/shared/sysdep/barrier.h deleted file mode 100644 index b58d52c5b2f..00000000000 --- a/arch/um/sys-i386/shared/sysdep/barrier.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __SYSDEP_I386_BARRIER_H -#define __SYSDEP_I386_BARRIER_H - -/* Copied from include/asm-i386 for use by userspace. i386 has the option - * of using mfence, but I'm just using this, which works everywhere, for now. - */ -#define mb() asm volatile("lock; addl $0,0(%esp)") - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/checksum.h b/arch/um/sys-i386/shared/sysdep/checksum.h deleted file mode 100644 index ed47445f390..00000000000 --- a/arch/um/sys-i386/shared/sysdep/checksum.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Licensed under the GPL - */ - -#ifndef __UM_SYSDEP_CHECKSUM_H -#define __UM_SYSDEP_CHECKSUM_H - -#include "linux/in6.h" -#include "linux/string.h" - -/* - * computes the checksum of a memory block at buff, length len, - * and adds in "sum" (32-bit) - * - * returns a 32-bit number suitable for feeding into itself - * or csum_tcpudp_magic - * - * this function must be called with even lengths, except - * for the last fragment, which may be odd - * - * it's best to have buff aligned on a 32-bit boundary - */ -__wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * Note: when you get a NULL pointer exception here this means someone - * passed in an incorrect kernel address to one of these functions. - * - * If you use these functions directly please don't forget the - * access_ok(). - */ - -static __inline__ -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum) -{ - memcpy(dst, src, len); - return csum_partial(dst, len, sum); -} - -/* - * the same as csum_partial, but copies from src while it - * checksums, and handles user-space pointer exceptions correctly, when needed. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ - -static __inline__ -__wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *err_ptr) -{ - if (copy_from_user(dst, src, len)) { - *err_ptr = -EFAULT; - return (__force __wsum)-1; - } - - return csum_partial(dst, len, sum); -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - * - * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by - * Arnt Gulbrandsen. - */ -static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - unsigned int sum; - - __asm__ __volatile__( - "movl (%1), %0 ;\n" - "subl $4, %2 ;\n" - "jbe 2f ;\n" - "addl 4(%1), %0 ;\n" - "adcl 8(%1), %0 ;\n" - "adcl 12(%1), %0 ;\n" -"1: adcl 16(%1), %0 ;\n" - "lea 4(%1), %1 ;\n" - "decl %2 ;\n" - "jne 1b ;\n" - "adcl $0, %0 ;\n" - "movl %0, %2 ;\n" - "shrl $16, %0 ;\n" - "addw %w2, %w0 ;\n" - "adcl $0, %0 ;\n" - "notl %0 ;\n" -"2: ;\n" - /* Since the input registers which are loaded with iph and ipl - are modified, we must also specify them as outputs, or gcc - will assume they contain their original values. */ - : "=r" (sum), "=r" (iph), "=r" (ihl) - : "1" (iph), "2" (ihl) - : "memory"); - return (__force __sum16)sum; -} - -/* - * Fold a partial checksum - */ - -static inline __sum16 csum_fold(__wsum sum) -{ - __asm__( - "addl %1, %0 ;\n" - "adcl $0xffff, %0 ;\n" - : "=r" (sum) - : "r" ((__force u32)sum << 16), - "0" ((__force u32)sum & 0xffff0000) - ); - return (__force __sum16)(~(__force u32)sum >> 16); -} - -static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) -{ - __asm__( - "addl %1, %0 ;\n" - "adcl %2, %0 ;\n" - "adcl %3, %0 ;\n" - "adcl $0, %0 ;\n" - : "=r" (sum) - : "g" (daddr), "g"(saddr), "g"((len + proto) << 8), "0"(sum)); - return sum; -} - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ - -static inline __sum16 ip_compute_csum(const void *buff, int len) -{ - return csum_fold (csum_partial(buff, len, 0)); -} - -#define _HAVE_ARCH_IPV6_CSUM -static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr, - const struct in6_addr *daddr, - __u32 len, unsigned short proto, - __wsum sum) -{ - __asm__( - "addl 0(%1), %0 ;\n" - "adcl 4(%1), %0 ;\n" - "adcl 8(%1), %0 ;\n" - "adcl 12(%1), %0 ;\n" - "adcl 0(%2), %0 ;\n" - "adcl 4(%2), %0 ;\n" - "adcl 8(%2), %0 ;\n" - "adcl 12(%2), %0 ;\n" - "adcl %3, %0 ;\n" - "adcl %4, %0 ;\n" - "adcl $0, %0 ;\n" - : "=&r" (sum) - : "r" (saddr), "r" (daddr), - "r"(htonl(len)), "r"(htonl(proto)), "0"(sum)); - - return csum_fold(sum); -} - -/* - * Copy and checksum to user - */ -#define HAVE_CSUM_COPY_USER -static __inline__ __wsum csum_and_copy_to_user(const void *src, - void __user *dst, - int len, __wsum sum, int *err_ptr) -{ - if (access_ok(VERIFY_WRITE, dst, len)) { - if (copy_to_user(dst, src, len)) { - *err_ptr = -EFAULT; - return (__force __wsum)-1; - } - - return csum_partial(src, len, sum); - } - - if (len) - *err_ptr = -EFAULT; - - return (__force __wsum)-1; /* invalid checksum */ -} - -#endif - diff --git a/arch/um/sys-i386/shared/sysdep/faultinfo.h b/arch/um/sys-i386/shared/sysdep/faultinfo.h deleted file mode 100644 index db437cc373b..00000000000 --- a/arch/um/sys-i386/shared/sysdep/faultinfo.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2004 Fujitsu Siemens Computers GmbH - * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com> - * Licensed under the GPL - */ - -#ifndef __FAULTINFO_I386_H -#define __FAULTINFO_I386_H - -/* this structure contains the full arch-specific faultinfo - * from the traps. - * On i386, ptrace_faultinfo unfortunately doesn't provide - * all the info, since trap_no is missing. - * All common elements are defined at the same position in - * both structures, thus making it easy to copy the - * contents without knowledge about the structure elements. - */ -struct faultinfo { - int error_code; /* in ptrace_faultinfo misleadingly called is_write */ - unsigned long cr2; /* in ptrace_faultinfo called addr */ - int trap_no; /* missing in ptrace_faultinfo */ -}; - -#define FAULT_WRITE(fi) ((fi).error_code & 2) -#define FAULT_ADDRESS(fi) ((fi).cr2) - -#define PTRACE_FULL_FAULTINFO 0 - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/host_ldt.h b/arch/um/sys-i386/shared/sysdep/host_ldt.h deleted file mode 100644 index 0953cc4df65..00000000000 --- a/arch/um/sys-i386/shared/sysdep/host_ldt.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __ASM_HOST_LDT_I386_H -#define __ASM_HOST_LDT_I386_H - -#include <asm/ldt.h> - -/* - * macros stolen from include/asm-i386/desc.h - */ -#define LDT_entry_a(info) \ - ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) - -#define LDT_entry_b(info) \ - (((info)->base_addr & 0xff000000) | \ - (((info)->base_addr & 0x00ff0000) >> 16) | \ - ((info)->limit & 0xf0000) | \ - (((info)->read_exec_only ^ 1) << 9) | \ - ((info)->contents << 10) | \ - (((info)->seg_not_present ^ 1) << 15) | \ - ((info)->seg_32bit << 22) | \ - ((info)->limit_in_pages << 23) | \ - ((info)->useable << 20) | \ - 0x7000) - -#define LDT_empty(info) (\ - (info)->base_addr == 0 && \ - (info)->limit == 0 && \ - (info)->contents == 0 && \ - (info)->read_exec_only == 1 && \ - (info)->seg_32bit == 0 && \ - (info)->limit_in_pages == 0 && \ - (info)->seg_not_present == 1 && \ - (info)->useable == 0 ) - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/kernel-offsets.h b/arch/um/sys-i386/shared/sysdep/kernel-offsets.h deleted file mode 100644 index 5868526b5ee..00000000000 --- a/arch/um/sys-i386/shared/sysdep/kernel-offsets.h +++ /dev/null @@ -1,21 +0,0 @@ -#include <linux/stddef.h> -#include <linux/sched.h> -#include <linux/elf.h> -#include <linux/crypto.h> -#include <asm/mman.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define STR(x) #x -#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : ) - -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - -void foo(void) -{ -#include <common-offsets.h> -} diff --git a/arch/um/sys-i386/shared/sysdep/ptrace.h b/arch/um/sys-i386/shared/sysdep/ptrace.h deleted file mode 100644 index d50e62e0707..00000000000 --- a/arch/um/sys-i386/shared/sysdep/ptrace.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __SYSDEP_I386_PTRACE_H -#define __SYSDEP_I386_PTRACE_H - -#include "user_constants.h" -#include "sysdep/faultinfo.h" - -#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long)) -#define MAX_REG_OFFSET (UM_FRAME_SIZE) - -static inline void update_debugregs(int seq) {} - -/* syscall emulation path in ptrace */ - -#ifndef PTRACE_SYSEMU -#define PTRACE_SYSEMU 31 -#endif - -void set_using_sysemu(int value); -int get_using_sysemu(void); -extern int sysemu_supported; - -#include "skas_ptregs.h" - -#define REGS_IP(r) ((r)[HOST_IP]) -#define REGS_SP(r) ((r)[HOST_SP]) -#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) -#define REGS_EAX(r) ((r)[HOST_EAX]) -#define REGS_EBX(r) ((r)[HOST_EBX]) -#define REGS_ECX(r) ((r)[HOST_ECX]) -#define REGS_EDX(r) ((r)[HOST_EDX]) -#define REGS_ESI(r) ((r)[HOST_ESI]) -#define REGS_EDI(r) ((r)[HOST_EDI]) -#define REGS_EBP(r) ((r)[HOST_EBP]) -#define REGS_CS(r) ((r)[HOST_CS]) -#define REGS_SS(r) ((r)[HOST_SS]) -#define REGS_DS(r) ((r)[HOST_DS]) -#define REGS_ES(r) ((r)[HOST_ES]) -#define REGS_FS(r) ((r)[HOST_FS]) -#define REGS_GS(r) ((r)[HOST_GS]) - -#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res) - -#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) - -#ifndef PTRACE_SYSEMU_SINGLESTEP -#define PTRACE_SYSEMU_SINGLESTEP 32 -#endif - -struct uml_pt_regs { - unsigned long gp[MAX_REG_NR]; - struct faultinfo faultinfo; - long syscall; - int is_user; -}; - -#define EMPTY_UML_PT_REGS { } - -#define UPT_IP(r) REGS_IP((r)->gp) -#define UPT_SP(r) REGS_SP((r)->gp) -#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) -#define UPT_EAX(r) REGS_EAX((r)->gp) -#define UPT_EBX(r) REGS_EBX((r)->gp) -#define UPT_ECX(r) REGS_ECX((r)->gp) -#define UPT_EDX(r) REGS_EDX((r)->gp) -#define UPT_ESI(r) REGS_ESI((r)->gp) -#define UPT_EDI(r) REGS_EDI((r)->gp) -#define UPT_EBP(r) REGS_EBP((r)->gp) -#define UPT_ORIG_EAX(r) ((r)->syscall) -#define UPT_CS(r) REGS_CS((r)->gp) -#define UPT_SS(r) REGS_SS((r)->gp) -#define UPT_DS(r) REGS_DS((r)->gp) -#define UPT_ES(r) REGS_ES((r)->gp) -#define UPT_FS(r) REGS_FS((r)->gp) -#define UPT_GS(r) REGS_GS((r)->gp) - -#define UPT_SYSCALL_ARG1(r) UPT_EBX(r) -#define UPT_SYSCALL_ARG2(r) UPT_ECX(r) -#define UPT_SYSCALL_ARG3(r) UPT_EDX(r) -#define UPT_SYSCALL_ARG4(r) UPT_ESI(r) -#define UPT_SYSCALL_ARG5(r) UPT_EDI(r) -#define UPT_SYSCALL_ARG6(r) UPT_EBP(r) - -extern int user_context(unsigned long sp); - -#define UPT_IS_USER(r) ((r)->is_user) - -struct syscall_args { - unsigned long args[6]; -}; - -#define SYSCALL_ARGS(r) ((struct syscall_args) \ - { .args = { UPT_SYSCALL_ARG1(r), \ - UPT_SYSCALL_ARG2(r), \ - UPT_SYSCALL_ARG3(r), \ - UPT_SYSCALL_ARG4(r), \ - UPT_SYSCALL_ARG5(r), \ - UPT_SYSCALL_ARG6(r) } } ) - -#define UPT_REG(regs, reg) \ - ({ unsigned long val; \ - switch(reg){ \ - case EIP: val = UPT_IP(regs); break; \ - case UESP: val = UPT_SP(regs); break; \ - case EAX: val = UPT_EAX(regs); break; \ - case EBX: val = UPT_EBX(regs); break; \ - case ECX: val = UPT_ECX(regs); break; \ - case EDX: val = UPT_EDX(regs); break; \ - case ESI: val = UPT_ESI(regs); break; \ - case EDI: val = UPT_EDI(regs); break; \ - case EBP: val = UPT_EBP(regs); break; \ - case ORIG_EAX: val = UPT_ORIG_EAX(regs); break; \ - case CS: val = UPT_CS(regs); break; \ - case SS: val = UPT_SS(regs); break; \ - case DS: val = UPT_DS(regs); break; \ - case ES: val = UPT_ES(regs); break; \ - case FS: val = UPT_FS(regs); break; \ - case GS: val = UPT_GS(regs); break; \ - case EFL: val = UPT_EFLAGS(regs); break; \ - default : \ - panic("Bad register in UPT_REG : %d\n", reg); \ - val = -1; \ - } \ - val; \ - }) - -#define UPT_SET(regs, reg, val) \ - do { \ - switch(reg){ \ - case EIP: UPT_IP(regs) = val; break; \ - case UESP: UPT_SP(regs) = val; break; \ - case EAX: UPT_EAX(regs) = val; break; \ - case EBX: UPT_EBX(regs) = val; break; \ - case ECX: UPT_ECX(regs) = val; break; \ - case EDX: UPT_EDX(regs) = val; break; \ - case ESI: UPT_ESI(regs) = val; break; \ - case EDI: UPT_EDI(regs) = val; break; \ - case EBP: UPT_EBP(regs) = val; break; \ - case ORIG_EAX: UPT_ORIG_EAX(regs) = val; break; \ - case CS: UPT_CS(regs) = val; break; \ - case SS: UPT_SS(regs) = val; break; \ - case DS: UPT_DS(regs) = val; break; \ - case ES: UPT_ES(regs) = val; break; \ - case FS: UPT_FS(regs) = val; break; \ - case GS: UPT_GS(regs) = val; break; \ - case EFL: UPT_EFLAGS(regs) = val; break; \ - default : \ - panic("Bad register in UPT_SET : %d\n", reg); \ - break; \ - } \ - } while (0) - -#define UPT_SET_SYSCALL_RETURN(r, res) \ - REGS_SET_SYSCALL_RETURN((r)->regs, (res)) - -#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) - -#define UPT_ORIG_SYSCALL(r) UPT_EAX(r) -#define UPT_SYSCALL_NR(r) UPT_ORIG_EAX(r) -#define UPT_SYSCALL_RET(r) UPT_EAX(r) - -#define UPT_FAULTINFO(r) (&(r)->faultinfo) - -extern void arch_init_registers(int pid); - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/ptrace_user.h b/arch/um/sys-i386/shared/sysdep/ptrace_user.h deleted file mode 100644 index ef56247e414..00000000000 --- a/arch/um/sys-i386/shared/sysdep/ptrace_user.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SYSDEP_I386_PTRACE_USER_H__ -#define __SYSDEP_I386_PTRACE_USER_H__ - -#include <sys/ptrace.h> -#include <linux/ptrace.h> -#include <asm/ptrace.h> -#include "user_constants.h" - -#define PT_OFFSET(r) ((r) * sizeof(long)) - -#define PT_SYSCALL_NR(regs) ((regs)[ORIG_EAX]) -#define PT_SYSCALL_NR_OFFSET PT_OFFSET(ORIG_EAX) - -#define PT_SYSCALL_ARG1_OFFSET PT_OFFSET(EBX) -#define PT_SYSCALL_ARG2_OFFSET PT_OFFSET(ECX) -#define PT_SYSCALL_ARG3_OFFSET PT_OFFSET(EDX) -#define PT_SYSCALL_ARG4_OFFSET PT_OFFSET(ESI) -#define PT_SYSCALL_ARG5_OFFSET PT_OFFSET(EDI) -#define PT_SYSCALL_ARG6_OFFSET PT_OFFSET(EBP) - -#define PT_SYSCALL_RET_OFFSET PT_OFFSET(EAX) - -#define REGS_SYSCALL_NR EAX /* This is used before a system call */ -#define REGS_SYSCALL_ARG1 EBX -#define REGS_SYSCALL_ARG2 ECX -#define REGS_SYSCALL_ARG3 EDX -#define REGS_SYSCALL_ARG4 ESI -#define REGS_SYSCALL_ARG5 EDI -#define REGS_SYSCALL_ARG6 EBP - -#define REGS_IP_INDEX EIP -#define REGS_SP_INDEX UESP - -#define PT_IP_OFFSET PT_OFFSET(EIP) -#define PT_IP(regs) ((regs)[EIP]) -#define PT_SP_OFFSET PT_OFFSET(UESP) -#define PT_SP(regs) ((regs)[UESP]) - -#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE) - -#ifndef FRAME_SIZE -#define FRAME_SIZE (17) -#endif - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/sc.h b/arch/um/sys-i386/shared/sysdep/sc.h deleted file mode 100644 index c57d1780ad3..00000000000 --- a/arch/um/sys-i386/shared/sysdep/sc.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __SYSDEP_I386_SC_H -#define __SYSDEP_I386_SC_H - -#include <user_constants.h> - -#define SC_OFFSET(sc, field) \ - *((unsigned long *) &(((char *) (sc))[HOST_##field])) -#define SC_FP_OFFSET(sc, field) \ - *((unsigned long *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field])) -#define SC_FP_OFFSET_PTR(sc, field, type) \ - ((type *) &(((char *) (SC_FPSTATE(sc)))[HOST_##field])) - -#define SC_IP(sc) SC_OFFSET(sc, SC_IP) -#define SC_SP(sc) SC_OFFSET(sc, SC_SP) -#define SC_FS(sc) SC_OFFSET(sc, SC_FS) -#define SC_GS(sc) SC_OFFSET(sc, SC_GS) -#define SC_DS(sc) SC_OFFSET(sc, SC_DS) -#define SC_ES(sc) SC_OFFSET(sc, SC_ES) -#define SC_SS(sc) SC_OFFSET(sc, SC_SS) -#define SC_CS(sc) SC_OFFSET(sc, SC_CS) -#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS) -#define SC_EAX(sc) SC_OFFSET(sc, SC_EAX) -#define SC_EBX(sc) SC_OFFSET(sc, SC_EBX) -#define SC_ECX(sc) SC_OFFSET(sc, SC_ECX) -#define SC_EDX(sc) SC_OFFSET(sc, SC_EDX) -#define SC_EDI(sc) SC_OFFSET(sc, SC_EDI) -#define SC_ESI(sc) SC_OFFSET(sc, SC_ESI) -#define SC_EBP(sc) SC_OFFSET(sc, SC_EBP) -#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO) -#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR) -#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2) -#define SC_FPSTATE(sc) SC_OFFSET(sc, SC_FPSTATE) -#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK) -#define SC_FP_CW(sc) SC_FP_OFFSET(sc, SC_FP_CW) -#define SC_FP_SW(sc) SC_FP_OFFSET(sc, SC_FP_SW) -#define SC_FP_TAG(sc) SC_FP_OFFSET(sc, SC_FP_TAG) -#define SC_FP_IPOFF(sc) SC_FP_OFFSET(sc, SC_FP_IPOFF) -#define SC_FP_CSSEL(sc) SC_FP_OFFSET(sc, SC_FP_CSSEL) -#define SC_FP_DATAOFF(sc) SC_FP_OFFSET(sc, SC_FP_DATAOFF) -#define SC_FP_DATASEL(sc) SC_FP_OFFSET(sc, SC_FP_DATASEL) -#define SC_FP_ST(sc) SC_FP_OFFSET_PTR(sc, SC_FP_ST, struct _fpstate) -#define SC_FXSR_ENV(sc) SC_FP_OFFSET_PTR(sc, SC_FXSR_ENV, void) - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/sigcontext.h b/arch/um/sys-i386/shared/sysdep/sigcontext.h deleted file mode 100644 index f583c87111a..00000000000 --- a/arch/um/sys-i386/shared/sysdep/sigcontext.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#ifndef __SYS_SIGCONTEXT_I386_H -#define __SYS_SIGCONTEXT_I386_H - -#include "sysdep/sc.h" - -#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) - -#define GET_FAULTINFO_FROM_SC(fi, sc) \ - { \ - (fi).cr2 = SC_CR2(sc); \ - (fi).error_code = SC_ERR(sc); \ - (fi).trap_no = SC_TRAPNO(sc); \ - } - -/* This is Page Fault */ -#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) - -/* SKAS3 has no trap_no on i386, but get_skas_faultinfo() sets it to 0. */ -#define SEGV_MAYBE_FIXABLE(fi) ((fi)->trap_no == 0 && ptrace_faultinfo) - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/skas_ptrace.h b/arch/um/sys-i386/shared/sysdep/skas_ptrace.h deleted file mode 100644 index e27b8a79177..00000000000 --- a/arch/um/sys-i386/shared/sysdep/skas_ptrace.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SYSDEP_I386_SKAS_PTRACE_H -#define __SYSDEP_I386_SKAS_PTRACE_H - -struct ptrace_faultinfo { - int is_write; - unsigned long addr; -}; - -struct ptrace_ldt { - int func; - void *ptr; - unsigned long bytecount; -}; - -#define PTRACE_LDT 54 - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/stub.h b/arch/um/sys-i386/shared/sysdep/stub.h deleted file mode 100644 index 977dedd9221..00000000000 --- a/arch/um/sys-i386/shared/sysdep/stub.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __SYSDEP_STUB_H -#define __SYSDEP_STUB_H - -#include <sys/mman.h> -#include <asm/ptrace.h> -#include <asm/unistd.h> -#include "as-layout.h" -#include "stub-data.h" -#include "kern_constants.h" - -extern void stub_segv_handler(int sig); -extern void stub_clone_handler(void); - -#define STUB_SYSCALL_RET EAX -#define STUB_MMAP_NR __NR_mmap2 -#define MMAP_OFFSET(o) ((o) >> UM_KERN_PAGE_SHIFT) - -static inline long stub_syscall0(long syscall) -{ - long ret; - - __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall)); - - return ret; -} - -static inline long stub_syscall1(long syscall, long arg1) -{ - long ret; - - __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1)); - - return ret; -} - -static inline long stub_syscall2(long syscall, long arg1, long arg2) -{ - long ret; - - __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), - "c" (arg2)); - - return ret; -} - -static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3) -{ - long ret; - - __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), - "c" (arg2), "d" (arg3)); - - return ret; -} - -static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3, - long arg4) -{ - long ret; - - __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), - "c" (arg2), "d" (arg3), "S" (arg4)); - - return ret; -} - -static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, - long arg4, long arg5) -{ - long ret; - - __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall), "b" (arg1), - "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)); - - return ret; -} - -static inline void trap_myself(void) -{ - __asm("int3"); -} - -static inline void remap_stack(int fd, unsigned long offset) -{ - __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;" - "movl %7, %%ebx ; movl %%eax, (%%ebx)" - : : "g" (STUB_MMAP_NR), "b" (STUB_DATA), - "c" (UM_KERN_PAGE_SIZE), - "d" (PROT_READ | PROT_WRITE), - "S" (MAP_FIXED | MAP_SHARED), "D" (fd), - "a" (offset), - "i" (&((struct stub_data *) STUB_DATA)->err) - : "memory"); -} - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/syscalls.h b/arch/um/sys-i386/shared/sysdep/syscalls.h deleted file mode 100644 index 05cb796aecb..00000000000 --- a/arch/um/sys-i386/shared/sysdep/syscalls.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include "asm/unistd.h" -#include "sysdep/ptrace.h" - -typedef long syscall_handler_t(struct pt_regs); - -/* Not declared on x86, incompatible declarations on x86_64, so these have - * to go here rather than in sys_call_table.c - */ -extern syscall_handler_t sys_rt_sigaction; - -extern syscall_handler_t *sys_call_table[]; - -#define EXECUTE_SYSCALL(syscall, regs) \ - ((long (*)(struct syscall_args)) \ - (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) diff --git a/arch/um/sys-i386/shared/sysdep/system.h b/arch/um/sys-i386/shared/sysdep/system.h deleted file mode 100644 index d1b93c43620..00000000000 --- a/arch/um/sys-i386/shared/sysdep/system.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef _ASM_X86_SYSTEM_H_ -#define _ASM_X86_SYSTEM_H_ - -#include <asm/asm.h> -#include <asm/segment.h> -#include <asm/cpufeature.h> -#include <asm/cmpxchg.h> -#include <asm/nops.h> - -#include <linux/kernel.h> -#include <linux/irqflags.h> - -/* entries in ARCH_DLINFO: */ -#ifdef CONFIG_IA32_EMULATION -# define AT_VECTOR_SIZE_ARCH 2 -#else -# define AT_VECTOR_SIZE_ARCH 1 -#endif - -extern unsigned long arch_align_stack(unsigned long sp); - -void default_idle(void); - -/* - * Force strict CPU ordering. - * And yes, this is required on UP too when we're talking - * to devices. - */ -#ifdef CONFIG_X86_32 -/* - * Some non-Intel clones support out of order store. wmb() ceases to be a - * nop for these. - */ -#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) -#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) -#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) -#else -#define mb() asm volatile("mfence":::"memory") -#define rmb() asm volatile("lfence":::"memory") -#define wmb() asm volatile("sfence" ::: "memory") -#endif - -/** - * read_barrier_depends - Flush all pending reads that subsequents reads - * depend on. - * - * No data-dependent reads from memory-like regions are ever reordered - * over this barrier. All reads preceding this primitive are guaranteed - * to access memory (but not necessarily other CPUs' caches) before any - * reads following this primitive that depend on the data return by - * any of the preceding reads. This primitive is much lighter weight than - * rmb() on most CPUs, and is never heavier weight than is - * rmb(). - * - * These ordering constraints are respected by both the local CPU - * and the compiler. - * - * Ordering is not guaranteed by anything other than these primitives, - * not even by data dependencies. See the documentation for - * memory_barrier() for examples and URLs to more information. - * - * For example, the following code would force ordering (the initial - * value of "a" is zero, "b" is one, and "p" is "&a"): - * - * <programlisting> - * CPU 0 CPU 1 - * - * b = 2; - * memory_barrier(); - * p = &b; q = p; - * read_barrier_depends(); - * d = *q; - * </programlisting> - * - * because the read of "*q" depends on the read of "p" and these - * two reads are separated by a read_barrier_depends(). However, - * the following code, with the same initial values for "a" and "b": - * - * <programlisting> - * CPU 0 CPU 1 - * - * a = 2; - * memory_barrier(); - * b = 3; y = b; - * read_barrier_depends(); - * x = a; - * </programlisting> - * - * does not enforce ordering, since there is no data dependency between - * the read of "a" and the read of "b". Therefore, on some CPUs, such - * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() - * in cases like this where there are no data dependencies. - **/ - -#define read_barrier_depends() do { } while (0) - -#ifdef CONFIG_SMP -#define smp_mb() mb() -#ifdef CONFIG_X86_PPRO_FENCE -# define smp_rmb() rmb() -#else -# define smp_rmb() barrier() -#endif -#ifdef CONFIG_X86_OOSTORE -# define smp_wmb() wmb() -#else -# define smp_wmb() barrier() -#endif -#define smp_read_barrier_depends() read_barrier_depends() -#define set_mb(var, value) do { (void)xchg(&var, value); } while (0) -#else -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#define smp_read_barrier_depends() do { } while (0) -#define set_mb(var, value) do { var = value; barrier(); } while (0) -#endif - -/* - * Stop RDTSC speculation. This is needed when you need to use RDTSC - * (or get_cycles or vread that possibly accesses the TSC) in a defined - * code region. - * - * (Could use an alternative three way for this if there was one.) - */ -static inline void rdtsc_barrier(void) -{ - alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC); - alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC); -} - -#endif diff --git a/arch/um/sys-i386/shared/sysdep/tls.h b/arch/um/sys-i386/shared/sysdep/tls.h deleted file mode 100644 index 34550755b2a..00000000000 --- a/arch/um/sys-i386/shared/sysdep/tls.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _SYSDEP_TLS_H -#define _SYSDEP_TLS_H - -# ifndef __KERNEL__ - -/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which - * may be named user_desc (but in 2.4 and in header matching its API was named - * modify_ldt_ldt_s). */ - -typedef struct um_dup_user_desc { - unsigned int entry_number; - unsigned int base_addr; - unsigned int limit; - unsigned int seg_32bit:1; - unsigned int contents:2; - unsigned int read_exec_only:1; - unsigned int limit_in_pages:1; - unsigned int seg_not_present:1; - unsigned int useable:1; -} user_desc_t; - -# else /* __KERNEL__ */ - -# include <ldt.h> -typedef struct user_desc user_desc_t; - -# endif /* __KERNEL__ */ - -#define GDT_ENTRY_TLS_MIN_I386 6 -#define GDT_ENTRY_TLS_MIN_X86_64 12 - -#endif /* _SYSDEP_TLS_H */ diff --git a/arch/um/sys-i386/shared/sysdep/vm-flags.h b/arch/um/sys-i386/shared/sysdep/vm-flags.h deleted file mode 100644 index e0d24c568db..00000000000 --- a/arch/um/sys-i386/shared/sysdep/vm-flags.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __VM_FLAGS_I386_H -#define __VM_FLAGS_I386_H - -#define VM_DATA_DEFAULT_FLAGS \ - (VM_READ | VM_WRITE | \ - ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -#endif diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c deleted file mode 100644 index 129647375a6..00000000000 --- a/arch/um/sys-i386/signal.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <linux/ptrace.h> -#include <asm/unistd.h> -#include <asm/uaccess.h> -#include <asm/ucontext.h> -#include "frame_kern.h" -#include "skas.h" - -void copy_sc(struct uml_pt_regs *regs, void *from) -{ - struct sigcontext *sc = from; - - REGS_GS(regs->gp) = sc->gs; - REGS_FS(regs->gp) = sc->fs; - REGS_ES(regs->gp) = sc->es; - REGS_DS(regs->gp) = sc->ds; - REGS_EDI(regs->gp) = sc->di; - REGS_ESI(regs->gp) = sc->si; - REGS_EBP(regs->gp) = sc->bp; - REGS_SP(regs->gp) = sc->sp; - REGS_EBX(regs->gp) = sc->bx; - REGS_EDX(regs->gp) = sc->dx; - REGS_ECX(regs->gp) = sc->cx; - REGS_EAX(regs->gp) = sc->ax; - REGS_IP(regs->gp) = sc->ip; - REGS_CS(regs->gp) = sc->cs; - REGS_EFLAGS(regs->gp) = sc->flags; - REGS_SS(regs->gp) = sc->ss; -} - -/* - * FPU tag word conversions. - */ - -static inline unsigned short twd_i387_to_fxsr(unsigned short twd) -{ - unsigned int tmp; /* to avoid 16 bit prefixes in the code */ - - /* Transform each pair of bits into 01 (valid) or 00 (empty) */ - tmp = ~twd; - tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */ - /* and move the valid bits to the lower byte. */ - tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */ - tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */ - tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */ - return tmp; -} - -static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave) -{ - struct _fpxreg *st = NULL; - unsigned long twd = (unsigned long) fxsave->twd; - unsigned long tag; - unsigned long ret = 0xffff0000; - int i; - -#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16); - - for (i = 0; i < 8; i++) { - if (twd & 0x1) { - st = (struct _fpxreg *) FPREG_ADDR(fxsave, i); - - switch (st->exponent & 0x7fff) { - case 0x7fff: - tag = 2; /* Special */ - break; - case 0x0000: - if ( !st->significand[0] && - !st->significand[1] && - !st->significand[2] && - !st->significand[3] ) { - tag = 1; /* Zero */ - } else { - tag = 2; /* Special */ - } - break; - default: - if (st->significand[3] & 0x8000) { - tag = 0; /* Valid */ - } else { - tag = 2; /* Special */ - } - break; - } - } else { - tag = 3; /* Empty */ - } - ret |= (tag << (2 * i)); - twd = twd >> 1; - } - return ret; -} - -static int convert_fxsr_to_user(struct _fpstate __user *buf, - struct user_fxsr_struct *fxsave) -{ - unsigned long env[7]; - struct _fpreg __user *to; - struct _fpxreg *from; - int i; - - env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul; - env[1] = (unsigned long)fxsave->swd | 0xffff0000ul; - 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++) { - unsigned long __user *t = (unsigned long __user *)to; - unsigned long *f = (unsigned long *)from; - - if (__put_user(*f, t) || - __put_user(*(f + 1), t + 1) || - __put_user(from->exponent, &to->exponent)) - return 1; - } - return 0; -} - -static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave, - struct _fpstate __user *buf) -{ - 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] & 0xffff0000ul) >> 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++) { - unsigned long *t = (unsigned long *)to; - unsigned long __user *f = (unsigned long __user *)from; - - if (__get_user(*t, f) || - __get_user(*(t + 1), f + 1) || - __get_user(to->exponent, &from->exponent)) - return 1; - } - return 0; -} - -extern int have_fpx_regs; - -static int copy_sc_from_user(struct pt_regs *regs, - struct sigcontext __user *from) -{ - struct sigcontext sc; - int err, pid; - - err = copy_from_user(&sc, from, sizeof(sc)); - if (err) - return err; - - pid = userspace_pid[current_thread_info()->cpu]; - copy_sc(®s->regs, &sc); - if (have_fpx_regs) { - struct user_fxsr_struct fpx; - - err = copy_from_user(&fpx, - &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0], - sizeof(struct user_fxsr_struct)); - if (err) - return 1; - - err = convert_fxsr_from_user(&fpx, sc.fpstate); - if (err) - return 1; - - err = restore_fpx_registers(pid, (unsigned long *) &fpx); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - " - "restore_fpx_registers failed, errno = %d\n", - -err); - return 1; - } - } - else { - struct user_i387_struct fp; - - err = copy_from_user(&fp, sc.fpstate, - sizeof(struct user_i387_struct)); - if (err) - return 1; - - err = restore_fp_registers(pid, (unsigned long *) &fp); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - " - "restore_fp_registers failed, errno = %d\n", - -err); - return 1; - } - } - - return 0; -} - -static int copy_sc_to_user(struct sigcontext __user *to, - struct _fpstate __user *to_fp, struct pt_regs *regs, - unsigned long sp) -{ - struct sigcontext sc; - struct faultinfo * fi = ¤t->thread.arch.faultinfo; - int err, pid; - - sc.gs = REGS_GS(regs->regs.gp); - sc.fs = REGS_FS(regs->regs.gp); - sc.es = REGS_ES(regs->regs.gp); - sc.ds = REGS_DS(regs->regs.gp); - sc.di = REGS_EDI(regs->regs.gp); - sc.si = REGS_ESI(regs->regs.gp); - sc.bp = REGS_EBP(regs->regs.gp); - sc.sp = sp; - sc.bx = REGS_EBX(regs->regs.gp); - sc.dx = REGS_EDX(regs->regs.gp); - sc.cx = REGS_ECX(regs->regs.gp); - sc.ax = REGS_EAX(regs->regs.gp); - sc.ip = REGS_IP(regs->regs.gp); - sc.cs = REGS_CS(regs->regs.gp); - sc.flags = REGS_EFLAGS(regs->regs.gp); - sc.sp_at_signal = regs->regs.gp[UESP]; - sc.ss = regs->regs.gp[SS]; - sc.cr2 = fi->cr2; - sc.err = fi->error_code; - sc.trapno = fi->trap_no; - - to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1)); - sc.fpstate = to_fp; - - pid = userspace_pid[current_thread_info()->cpu]; - if (have_fpx_regs) { - struct user_fxsr_struct fpx; - - err = save_fpx_registers(pid, (unsigned long *) &fpx); - if (err < 0){ - printk(KERN_ERR "copy_sc_to_user - save_fpx_registers " - "failed, errno = %d\n", err); - return 1; - } - - err = convert_fxsr_to_user(to_fp, &fpx); - if (err) - return 1; - - err |= __put_user(fpx.swd, &to_fp->status); - err |= __put_user(X86_FXSR_MAGIC, &to_fp->magic); - if (err) - return 1; - - if (copy_to_user(&to_fp->_fxsr_env[0], &fpx, - sizeof(struct user_fxsr_struct))) - return 1; - } - else { - struct user_i387_struct fp; - - err = save_fp_registers(pid, (unsigned long *) &fp); - if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) - return 1; - } - - return copy_to_user(to, &sc, sizeof(sc)); -} - -static int copy_ucontext_to_user(struct ucontext __user *uc, - struct _fpstate __user *fp, sigset_t *set, - unsigned long sp) -{ - int err = 0; - - err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); - err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); - err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); - err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, sp); - err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); - return err; -} - -struct sigframe -{ - char __user *pretcode; - int sig; - struct sigcontext sc; - struct _fpstate fpstate; - unsigned long extramask[_NSIG_WORDS-1]; - char retcode[8]; -}; - -struct rt_sigframe -{ - char __user *pretcode; - int sig; - struct siginfo __user *pinfo; - void __user *puc; - struct siginfo info; - struct ucontext uc; - struct _fpstate fpstate; - char retcode[8]; -}; - -int setup_signal_stack_sc(unsigned long stack_top, int sig, - struct k_sigaction *ka, struct pt_regs *regs, - sigset_t *mask) -{ - struct sigframe __user *frame; - void __user *restorer; - unsigned long save_sp = PT_REGS_SP(regs); - int err = 0; - - /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */ - stack_top = ((stack_top + 4) & -16UL) - 4; - frame = (struct sigframe __user *) stack_top - 1; - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return 1; - - restorer = frame->retcode; - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - - /* Update SP now because the page fault handler refuses to extend - * the stack if the faulting address is too far below the current - * SP, which frame now certainly is. If there's an error, the original - * value is restored on the way out. - * When writing the sigcontext to the stack, we have to write the - * original value, so that's passed to copy_sc_to_user, which does - * the right thing with it. - */ - PT_REGS_SP(regs) = (unsigned long) frame; - - err |= __put_user(restorer, &frame->pretcode); - err |= __put_user(sig, &frame->sig); - err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp); - err |= __put_user(mask->sig[0], &frame->sc.oldmask); - if (_NSIG_WORDS > 1) - err |= __copy_to_user(&frame->extramask, &mask->sig[1], - sizeof(frame->extramask)); - - /* - * This is popl %eax ; movl $,%eax ; int $0x80 - * - * WE DO NOT USE IT ANY MORE! It's only left here for historical - * reasons and because gdb uses it as a signature to notice - * signal handler stack frames. - */ - err |= __put_user(0xb858, (short __user *)(frame->retcode+0)); - err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2)); - err |= __put_user(0x80cd, (short __user *)(frame->retcode+6)); - - if (err) - goto err; - - PT_REGS_SP(regs) = (unsigned long) frame; - PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; - PT_REGS_EAX(regs) = (unsigned long) sig; - PT_REGS_EDX(regs) = (unsigned long) 0; - PT_REGS_ECX(regs) = (unsigned long) 0; - - if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) - ptrace_notify(SIGTRAP); - return 0; - -err: - PT_REGS_SP(regs) = save_sp; - return err; -} - -int setup_signal_stack_si(unsigned long stack_top, int sig, - struct k_sigaction *ka, struct pt_regs *regs, - siginfo_t *info, sigset_t *mask) -{ - struct rt_sigframe __user *frame; - void __user *restorer; - unsigned long save_sp = PT_REGS_SP(regs); - int err = 0; - - stack_top &= -8UL; - frame = (struct rt_sigframe __user *) stack_top - 1; - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return 1; - - restorer = frame->retcode; - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - - /* See comment above about why this is here */ - PT_REGS_SP(regs) = (unsigned long) frame; - - err |= __put_user(restorer, &frame->pretcode); - err |= __put_user(sig, &frame->sig); - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, info); - err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, - save_sp); - - /* - * This is movl $,%eax ; int $0x80 - * - * WE DO NOT USE IT ANY MORE! It's only left here for historical - * reasons and because gdb uses it as a signature to notice - * signal handler stack frames. - */ - err |= __put_user(0xb8, (char __user *)(frame->retcode+0)); - err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1)); - err |= __put_user(0x80cd, (short __user *)(frame->retcode+5)); - - if (err) - goto err; - - PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; - PT_REGS_EAX(regs) = (unsigned long) sig; - PT_REGS_EDX(regs) = (unsigned long) &frame->info; - PT_REGS_ECX(regs) = (unsigned long) &frame->uc; - - if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED)) - ptrace_notify(SIGTRAP); - return 0; - -err: - PT_REGS_SP(regs) = save_sp; - return err; -} - -long sys_sigreturn(struct pt_regs regs) -{ - unsigned long sp = PT_REGS_SP(¤t->thread.regs); - struct sigframe __user *frame = (struct sigframe __user *)(sp - 8); - sigset_t set; - struct sigcontext __user *sc = &frame->sc; - unsigned long __user *oldmask = &sc->oldmask; - unsigned long __user *extramask = frame->extramask; - int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); - - if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) || - copy_from_user(&set.sig[1], extramask, sig_size)) - goto segfault; - - sigdelsetmask(&set, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (copy_sc_from_user(¤t->thread.regs, sc)) - goto segfault; - - /* Avoid ERESTART handling */ - PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; - return PT_REGS_SYSCALL_RET(¤t->thread.regs); - - segfault: - force_sig(SIGSEGV, current); - return 0; -} - -long sys_rt_sigreturn(struct pt_regs regs) -{ - unsigned long sp = PT_REGS_SP(¤t->thread.regs); - struct rt_sigframe __user *frame = - (struct rt_sigframe __user *) (sp - 4); - sigset_t set; - struct ucontext __user *uc = &frame->uc; - int sig_size = _NSIG_WORDS * sizeof(unsigned long); - - if (copy_from_user(&set, &uc->uc_sigmask, sig_size)) - goto segfault; - - sigdelsetmask(&set, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext)) - goto segfault; - - /* Avoid ERESTART handling */ - PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; - return PT_REGS_SYSCALL_RET(¤t->thread.regs); - - segfault: - force_sig(SIGSEGV, current); - return 0; -} diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S deleted file mode 100644 index 54a36ec20cb..00000000000 --- a/arch/um/sys-i386/stub.S +++ /dev/null @@ -1,51 +0,0 @@ -#include "as-layout.h" - - .globl syscall_stub -.section .__syscall_stub, "ax" - - .globl batch_syscall_stub -batch_syscall_stub: - /* load pointer to first operation */ - mov $(STUB_DATA+8), %esp - -again: - /* load length of additional data */ - mov 0x0(%esp), %eax - - /* if(length == 0) : end of list */ - /* write possible 0 to header */ - mov %eax, STUB_DATA+4 - cmpl $0, %eax - jz done - - /* save current pointer */ - mov %esp, STUB_DATA+4 - - /* skip additional data */ - add %eax, %esp - - /* load syscall-# */ - pop %eax - - /* load syscall params */ - pop %ebx - pop %ecx - pop %edx - pop %esi - pop %edi - pop %ebp - - /* execute syscall */ - int $0x80 - - /* check return value */ - pop %ebx - cmp %ebx, %eax - je again - -done: - /* save return value */ - mov %eax, STUB_DATA - - /* stop */ - int3 diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c deleted file mode 100644 index 28ccf737a79..00000000000 --- a/arch/um/sys-i386/stub_segv.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include "sysdep/stub.h" -#include "sysdep/sigcontext.h" - -void __attribute__ ((__section__ (".__syscall_stub"))) -stub_segv_handler(int sig) -{ - struct sigcontext *sc = (struct sigcontext *) (&sig + 1); - - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc); - - trap_myself(); -} diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S deleted file mode 100644 index de274071455..00000000000 --- a/arch/um/sys-i386/sys_call_table.S +++ /dev/null @@ -1,28 +0,0 @@ -#include <linux/linkage.h> -/* Steal i386 syscall table for our purposes, but with some slight changes.*/ - -#define sys_iopl sys_ni_syscall -#define sys_ioperm sys_ni_syscall - -#define sys_vm86old sys_ni_syscall -#define sys_vm86 sys_ni_syscall - -#define old_mmap sys_old_mmap - -#define ptregs_fork sys_fork -#define ptregs_execve sys_execve -#define ptregs_iopl sys_iopl -#define ptregs_vm86old sys_vm86old -#define ptregs_sigreturn sys_sigreturn -#define ptregs_clone sys_clone -#define ptregs_vm86 sys_vm86 -#define ptregs_rt_sigreturn sys_rt_sigreturn -#define ptregs_sigaltstack sys_sigaltstack -#define ptregs_vfork sys_vfork - -.section .rodata,"a" - -#include "../../x86/kernel/syscall_table_32.S" - -ENTRY(syscall_table_size) -.long .-sys_call_table diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c deleted file mode 100644 index 70ca357393b..00000000000 --- a/arch/um/sys-i386/syscalls.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/sched.h" -#include "linux/shm.h" -#include "linux/ipc.h" -#include "linux/syscalls.h" -#include "asm/mman.h" -#include "asm/uaccess.h" -#include "asm/unistd.h" - -/* - * The prototype on i386 is: - * - * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) - * - * and the "newtls" arg. on i386 is read by copy_thread directly from the - * register saved on the stack. - */ -long sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tid, void *newtls, int __user *child_tid) -{ - long ret; - - if (!newsp) - newsp = UPT_SP(¤t->thread.regs.regs); - - current->thread.forking = 1; - ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, - child_tid); - current->thread.forking = 0; - return ret; -} - -long sys_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} diff --git a/arch/um/sys-i386/sysrq.c b/arch/um/sys-i386/sysrq.c deleted file mode 100644 index 171b3e9dc86..00000000000 --- a/arch/um/sys-i386/sysrq.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/kernel.h" -#include "linux/smp.h" -#include "linux/sched.h" -#include "linux/kallsyms.h" -#include "asm/ptrace.h" -#include "sysrq.h" - -/* This is declared by <linux/sched.h> */ -void show_regs(struct pt_regs *regs) -{ - printk("\n"); - printk("EIP: %04lx:[<%08lx>] CPU: %d %s", - 0xffff & PT_REGS_CS(regs), PT_REGS_IP(regs), - smp_processor_id(), print_tainted()); - if (PT_REGS_CS(regs) & 3) - printk(" ESP: %04lx:%08lx", 0xffff & PT_REGS_SS(regs), - PT_REGS_SP(regs)); - printk(" EFLAGS: %08lx\n %s\n", PT_REGS_EFLAGS(regs), - print_tainted()); - printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", - PT_REGS_EAX(regs), PT_REGS_EBX(regs), - PT_REGS_ECX(regs), - PT_REGS_EDX(regs)); - printk("ESI: %08lx EDI: %08lx EBP: %08lx", - PT_REGS_ESI(regs), PT_REGS_EDI(regs), - PT_REGS_EBP(regs)); - printk(" DS: %04lx ES: %04lx\n", - 0xffff & PT_REGS_DS(regs), - 0xffff & PT_REGS_ES(regs)); - - show_trace(NULL, (unsigned long *) ®s); -} - -/* Copied from i386. */ -static inline int valid_stack_ptr(struct thread_info *tinfo, void *p) -{ - return p > (void *)tinfo && - p < (void *)tinfo + THREAD_SIZE - 3; -} - -/* Adapted from i386 (we also print the address we read from). */ -static inline unsigned long print_context_stack(struct thread_info *tinfo, - unsigned long *stack, unsigned long ebp) -{ - unsigned long addr; - -#ifdef CONFIG_FRAME_POINTER - while (valid_stack_ptr(tinfo, (void *)ebp)) { - addr = *(unsigned long *)(ebp + 4); - printk("%08lx: [<%08lx>]", ebp + 4, addr); - print_symbol(" %s", addr); - printk("\n"); - ebp = *(unsigned long *)ebp; - } -#else - while (valid_stack_ptr(tinfo, stack)) { - addr = *stack; - if (__kernel_text_address(addr)) { - printk("%08lx: [<%08lx>]", (unsigned long) stack, addr); - print_symbol(" %s", addr); - printk("\n"); - } - stack++; - } -#endif - return ebp; -} - -void show_trace(struct task_struct* task, unsigned long * stack) -{ - unsigned long ebp; - struct thread_info *context; - - /* Turn this into BUG_ON if possible. */ - if (!stack) { - stack = (unsigned long*) &stack; - printk("show_trace: got NULL stack, implicit assumption task == current"); - WARN_ON(1); - } - - if (!task) - task = current; - - if (task != current) { - ebp = (unsigned long) KSTK_EBP(task); - } else { - asm ("movl %%ebp, %0" : "=r" (ebp) : ); - } - - context = (struct thread_info *) - ((unsigned long)stack & (~(THREAD_SIZE - 1))); - print_context_stack(context, stack, ebp); - - printk("\n"); -} - diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c deleted file mode 100644 index c6c7131e563..00000000000 --- a/arch/um/sys-i386/tls.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (C) 2005 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> - * Licensed under the GPL - */ - -#include "linux/percpu.h" -#include "linux/sched.h" -#include "asm/uaccess.h" -#include "os.h" -#include "skas.h" -#include "sysdep/tls.h" - -/* - * If needed we can detect when it's uninitialized. - * - * These are initialized in an initcall and unchanged thereafter. - */ -static int host_supports_tls = -1; -int host_gdt_entry_tls_min; - -int do_set_thread_area(struct user_desc *info) -{ - int ret; - u32 cpu; - - cpu = get_cpu(); - ret = os_set_thread_area(info, userspace_pid[cpu]); - put_cpu(); - - if (ret) - printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, " - "index = %d\n", ret, info->entry_number); - - return ret; -} - -int do_get_thread_area(struct user_desc *info) -{ - int ret; - u32 cpu; - - cpu = get_cpu(); - ret = os_get_thread_area(info, userspace_pid[cpu]); - put_cpu(); - - if (ret) - printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, " - "index = %d\n", ret, info->entry_number); - - return ret; -} - -/* - * sys_get_thread_area: get a yet unused TLS descriptor index. - * XXX: Consider leaving one free slot for glibc usage at first place. This must - * be done here (and by changing GDT_ENTRY_TLS_* macros) and nowhere else. - * - * Also, this must be tested when compiling in SKAS mode with dynamic linking - * and running against NPTL. - */ -static int get_free_idx(struct task_struct* task) -{ - struct thread_struct *t = &task->thread; - int idx; - - if (!t->arch.tls_array) - return GDT_ENTRY_TLS_MIN; - - for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) - if (!t->arch.tls_array[idx].present) - return idx + GDT_ENTRY_TLS_MIN; - return -ESRCH; -} - -static inline void clear_user_desc(struct user_desc* info) -{ - /* Postcondition: LDT_empty(info) returns true. */ - memset(info, 0, sizeof(*info)); - - /* - * Check the LDT_empty or the i386 sys_get_thread_area code - we obtain - * indeed an empty user_desc. - */ - info->read_exec_only = 1; - info->seg_not_present = 1; -} - -#define O_FORCE 1 - -static int load_TLS(int flags, struct task_struct *to) -{ - int ret = 0; - int idx; - - for (idx = GDT_ENTRY_TLS_MIN; idx < GDT_ENTRY_TLS_MAX; idx++) { - struct uml_tls_struct* curr = - &to->thread.arch.tls_array[idx - GDT_ENTRY_TLS_MIN]; - - /* - * Actually, now if it wasn't flushed it gets cleared and - * flushed to the host, which will clear it. - */ - if (!curr->present) { - if (!curr->flushed) { - clear_user_desc(&curr->tls); - curr->tls.entry_number = idx; - } else { - WARN_ON(!LDT_empty(&curr->tls)); - continue; - } - } - - if (!(flags & O_FORCE) && curr->flushed) - continue; - - ret = do_set_thread_area(&curr->tls); - if (ret) - goto out; - - curr->flushed = 1; - } -out: - return ret; -} - -/* - * Verify if we need to do a flush for the new process, i.e. if there are any - * present desc's, only if they haven't been flushed. - */ -static inline int needs_TLS_update(struct task_struct *task) -{ - int i; - int ret = 0; - - for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { - struct uml_tls_struct* curr = - &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; - - /* - * Can't test curr->present, we may need to clear a descriptor - * which had a value. - */ - if (curr->flushed) - continue; - ret = 1; - break; - } - return ret; -} - -/* - * On a newly forked process, the TLS descriptors haven't yet been flushed. So - * we mark them as such and the first switch_to will do the job. - */ -void clear_flushed_tls(struct task_struct *task) -{ - int i; - - for (i = GDT_ENTRY_TLS_MIN; i < GDT_ENTRY_TLS_MAX; i++) { - struct uml_tls_struct* curr = - &task->thread.arch.tls_array[i - GDT_ENTRY_TLS_MIN]; - - /* - * Still correct to do this, if it wasn't present on the host it - * will remain as flushed as it was. - */ - if (!curr->present) - continue; - - curr->flushed = 0; - } -} - -/* - * In SKAS0 mode, currently, multiple guest threads sharing the same ->mm have a - * common host process. So this is needed in SKAS0 too. - * - * However, if each thread had a different host process (and this was discussed - * for SMP support) this won't be needed. - * - * And this will not need be used when (and if) we'll add support to the host - * SKAS patch. - */ - -int arch_switch_tls(struct task_struct *to) -{ - if (!host_supports_tls) - return 0; - - /* - * We have no need whatsoever to switch TLS for kernel threads; beyond - * that, that would also result in us calling os_set_thread_area with - * userspace_pid[cpu] == 0, which gives an error. - */ - if (likely(to->mm)) - return load_TLS(O_FORCE, to); - - return 0; -} - -static int set_tls_entry(struct task_struct* task, struct user_desc *info, - int idx, int flushed) -{ - struct thread_struct *t = &task->thread; - - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls = *info; - t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present = 1; - t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed = flushed; - - return 0; -} - -int arch_copy_tls(struct task_struct *new) -{ - struct user_desc info; - int idx, ret = -EFAULT; - - if (copy_from_user(&info, - (void __user *) UPT_ESI(&new->thread.regs.regs), - sizeof(info))) - goto out; - - ret = -EINVAL; - if (LDT_empty(&info)) - goto out; - - idx = info.entry_number; - - ret = set_tls_entry(new, &info, idx, 0); -out: - return ret; -} - -/* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */ -static int get_tls_entry(struct task_struct *task, struct user_desc *info, - int idx) -{ - struct thread_struct *t = &task->thread; - - if (!t->arch.tls_array) - goto clear; - - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - if (!t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].present) - goto clear; - - *info = t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].tls; - -out: - /* - * Temporary debugging check, to make sure that things have been - * flushed. This could be triggered if load_TLS() failed. - */ - if (unlikely(task == current && - !t->arch.tls_array[idx - GDT_ENTRY_TLS_MIN].flushed)) { - printk(KERN_ERR "get_tls_entry: task with pid %d got here " - "without flushed TLS.", current->pid); - } - - return 0; -clear: - /* - * When the TLS entry has not been set, the values read to user in the - * tls_array are 0 (because it's cleared at boot, see - * arch/i386/kernel/head.S:cpu_gdt_table). Emulate that. - */ - clear_user_desc(info); - info->entry_number = idx; - goto out; -} - -int sys_set_thread_area(struct user_desc __user *user_desc) -{ - struct user_desc info; - int idx, ret; - - if (!host_supports_tls) - return -ENOSYS; - - if (copy_from_user(&info, user_desc, sizeof(info))) - return -EFAULT; - - idx = info.entry_number; - - if (idx == -1) { - idx = get_free_idx(current); - if (idx < 0) - return idx; - info.entry_number = idx; - /* Tell the user which slot we chose for him.*/ - if (put_user(idx, &user_desc->entry_number)) - return -EFAULT; - } - - ret = do_set_thread_area(&info); - if (ret) - return ret; - return set_tls_entry(current, &info, idx, 1); -} - -/* - * Perform set_thread_area on behalf of the traced child. - * Note: error handling is not done on the deferred load, and this differ from - * i386. However the only possible error are caused by bugs. - */ -int ptrace_set_thread_area(struct task_struct *child, int idx, - struct user_desc __user *user_desc) -{ - struct user_desc info; - - if (!host_supports_tls) - return -EIO; - - if (copy_from_user(&info, user_desc, sizeof(info))) - return -EFAULT; - - return set_tls_entry(child, &info, idx, 0); -} - -int sys_get_thread_area(struct user_desc __user *user_desc) -{ - struct user_desc info; - int idx, ret; - - if (!host_supports_tls) - return -ENOSYS; - - if (get_user(idx, &user_desc->entry_number)) - return -EFAULT; - - ret = get_tls_entry(current, &info, idx); - if (ret < 0) - goto out; - - if (copy_to_user(user_desc, &info, sizeof(info))) - ret = -EFAULT; - -out: - return ret; -} - -/* - * Perform get_thread_area on behalf of the traced child. - */ -int ptrace_get_thread_area(struct task_struct *child, int idx, - struct user_desc __user *user_desc) -{ - struct user_desc info; - int ret; - - if (!host_supports_tls) - return -EIO; - - ret = get_tls_entry(child, &info, idx); - if (ret < 0) - goto out; - - if (copy_to_user(user_desc, &info, sizeof(info))) - ret = -EFAULT; -out: - return ret; -} - -/* - * This code is really i386-only, but it detects and logs x86_64 GDT indexes - * if a 32-bit UML is running on a 64-bit host. - */ -static int __init __setup_host_supports_tls(void) -{ - check_host_supports_tls(&host_supports_tls, &host_gdt_entry_tls_min); - if (host_supports_tls) { - printk(KERN_INFO "Host TLS support detected\n"); - printk(KERN_INFO "Detected host type: "); - switch (host_gdt_entry_tls_min) { - case GDT_ENTRY_TLS_MIN_I386: - printk(KERN_CONT "i386"); - break; - case GDT_ENTRY_TLS_MIN_X86_64: - printk(KERN_CONT "x86_64"); - break; - } - printk(KERN_CONT " (GDT indexes %d to %d)\n", - host_gdt_entry_tls_min, - host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES); - } else - printk(KERN_ERR " Host TLS support NOT detected! " - "TLS support inside UML will not work\n"); - return 0; -} - -__initcall(__setup_host_supports_tls); diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c deleted file mode 100644 index 5f883bfe773..00000000000 --- a/arch/um/sys-i386/user-offsets.c +++ /dev/null @@ -1,53 +0,0 @@ -#include <stdio.h> -#include <stddef.h> -#include <signal.h> -#include <sys/poll.h> -#include <sys/user.h> -#include <sys/mman.h> -#include <asm/ptrace.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define DEFINE_LONGS(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long))) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - -void foo(void) -{ - OFFSET(HOST_SC_TRAPNO, sigcontext, trapno); - OFFSET(HOST_SC_ERR, sigcontext, err); - OFFSET(HOST_SC_CR2, sigcontext, cr2); - - DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct)); - DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct)); - - DEFINE(HOST_IP, EIP); - DEFINE(HOST_SP, UESP); - DEFINE(HOST_EFLAGS, EFL); - DEFINE(HOST_EAX, EAX); - DEFINE(HOST_EBX, EBX); - DEFINE(HOST_ECX, ECX); - DEFINE(HOST_EDX, EDX); - DEFINE(HOST_ESI, ESI); - DEFINE(HOST_EDI, EDI); - DEFINE(HOST_EBP, EBP); - DEFINE(HOST_CS, CS); - DEFINE(HOST_SS, SS); - DEFINE(HOST_DS, DS); - DEFINE(HOST_FS, FS); - DEFINE(HOST_ES, ES); - DEFINE(HOST_GS, GS); - DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); - - /* XXX Duplicated between i386 and x86_64 */ - DEFINE(UM_POLLIN, POLLIN); - DEFINE(UM_POLLPRI, POLLPRI); - DEFINE(UM_POLLOUT, POLLOUT); - - DEFINE(UM_PROT_READ, PROT_READ); - DEFINE(UM_PROT_WRITE, PROT_WRITE); - DEFINE(UM_PROT_EXEC, PROT_EXEC); -} diff --git a/arch/um/sys-ppc/miscthings.c b/arch/um/sys-ppc/miscthings.c index 1c11aed9c71..25908d26ce0 100644 --- a/arch/um/sys-ppc/miscthings.c +++ b/arch/um/sys-ppc/miscthings.c @@ -1,6 +1,6 @@ -#include "linux/threads.h" -#include "linux/stddef.h" // for NULL -#include "linux/elf.h" // for AT_NULL +#include <linux/threads.h> +#include <linux/stddef.h> // for NULL +#include <linux/elf.h> // for AT_NULL /* The following function nicked from arch/ppc/kernel/process.c and * adapted slightly */ diff --git a/arch/um/sys-ppc/ptrace.c b/arch/um/sys-ppc/ptrace.c index 66ef155248f..8245df41b20 100644 --- a/arch/um/sys-ppc/ptrace.c +++ b/arch/um/sys-ppc/ptrace.c @@ -1,4 +1,4 @@ -#include "linux/sched.h" +#include <linux/sched.h> #include "asm/ptrace.h" int putreg(struct task_struct *child, unsigned long regno, diff --git a/arch/um/sys-ppc/ptrace_user.c b/arch/um/sys-ppc/ptrace_user.c index 224d2403c37..4601b9296aa 100644 --- a/arch/um/sys-ppc/ptrace_user.c +++ b/arch/um/sys-ppc/ptrace_user.c @@ -1,6 +1,6 @@ #include <errno.h> #include <asm/ptrace.h> -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> int ptrace_getregs(long pid, unsigned long *regs_out) { diff --git a/arch/um/sys-ppc/shared/sysdep/ptrace.h b/arch/um/sys-ppc/shared/sysdep/ptrace.h index 0e3230e937e..efe0c1a3ea9 100644 --- a/arch/um/sys-ppc/shared/sysdep/ptrace.h +++ b/arch/um/sys-ppc/shared/sysdep/ptrace.h @@ -5,7 +5,7 @@ #ifndef __SYS_PTRACE_PPC_H #define __SYS_PTRACE_PPC_H -#include "linux/types.h" +#include <linux/types.h> /* the following taken from <asm-ppc/ptrace.h> */ diff --git a/arch/um/sys-ppc/sigcontext.c b/arch/um/sys-ppc/sigcontext.c index 40694d0f3d1..aac6c83fe44 100644 --- a/arch/um/sys-ppc/sigcontext.c +++ b/arch/um/sys-ppc/sigcontext.c @@ -1,4 +1,4 @@ #include "asm/ptrace.h" #include "asm/sigcontext.h" -#include "sysdep/ptrace.h" +#include <sysdep/ptrace.h> diff --git a/arch/um/sys-ppc/sysrq.c b/arch/um/sys-ppc/sysrq.c index 2f816f1a0ff..1ff1ad7f27d 100644 --- a/arch/um/sys-ppc/sysrq.c +++ b/arch/um/sys-ppc/sysrq.c @@ -3,14 +3,16 @@ * Licensed under the GPL */ -#include "linux/kernel.h" -#include "linux/smp.h" +#include <linux/kernel.h> +#include <linux/smp.h> #include "asm/ptrace.h" #include "sysrq.h" void show_regs(struct pt_regs_subarch *regs) { printk("\n"); + show_regs_print_info(KERN_DEFAULT); + printk("show_regs(): insert regs here.\n"); #if 0 printk("\n"); diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile deleted file mode 100644 index c1ea9eb0446..00000000000 --- a/arch/um/sys-x86_64/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# -# Copyright 2003 PathScale, Inc. -# -# Licensed under the GPL -# - -obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ - setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ - sysrq.o ksyms.o tls.o - -subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \ - lib/rwsem_64.o -subarch-obj-$(CONFIG_MODULES) += kernel/module.o - -ldt-y = ../sys-i386/ldt.o - -USER_OBJS := ptrace_user.o - -USER_OBJS += user-offsets.s -extra-y += user-offsets.s - -UNPROFILE_OBJS := stub_segv.o -CFLAGS_stub_segv.o := $(CFLAGS_NO_HARDENING) - -include arch/um/scripts/Makefile.rules diff --git a/arch/um/sys-x86_64/asm/archparam.h b/arch/um/sys-x86_64/asm/archparam.h deleted file mode 100644 index 6c083663b8d..00000000000 --- a/arch/um/sys-x86_64/asm/archparam.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __UM_ARCHPARAM_X86_64_H -#define __UM_ARCHPARAM_X86_64_H - - -/* No user-accessible fixmap addresses, i.e. vsyscall */ -#define FIXADDR_USER_START 0 -#define FIXADDR_USER_END 0 - -#endif - diff --git a/arch/um/sys-x86_64/asm/elf.h b/arch/um/sys-x86_64/asm/elf.h deleted file mode 100644 index d6d5af37625..00000000000 --- a/arch/um/sys-x86_64/asm/elf.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * - * Licensed under the GPL - */ -#ifndef __UM_ELF_X86_64_H -#define __UM_ELF_X86_64_H - -#include <asm/user.h> -#include "skas.h" - -/* x86-64 relocation types, taken from asm-x86_64/elf.h */ -#define R_X86_64_NONE 0 /* No reloc */ -#define R_X86_64_64 1 /* Direct 64 bit */ -#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ -#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ -#define R_X86_64_PLT32 4 /* 32 bit PLT address */ -#define R_X86_64_COPY 5 /* Copy symbol at runtime */ -#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ -#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ -#define R_X86_64_RELATIVE 8 /* Adjust by program base */ -#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative - offset to GOT */ -#define R_X86_64_32 10 /* Direct 32 bit zero extended */ -#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ -#define R_X86_64_16 12 /* Direct 16 bit zero extended */ -#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ -#define R_X86_64_8 14 /* Direct 8 bit sign extended */ -#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ - -#define R_X86_64_NUM 16 - -typedef unsigned long elf_greg_t; - -#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef struct user_i387_struct elf_fpregset_t; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) \ - ((x)->e_machine == EM_X86_64) - -#define ELF_CLASS ELFCLASS64 -#define ELF_DATA ELFDATA2LSB -#define ELF_ARCH EM_X86_64 - -#define ELF_PLAT_INIT(regs, load_addr) do { \ - PT_REGS_RBX(regs) = 0; \ - PT_REGS_RCX(regs) = 0; \ - PT_REGS_RDX(regs) = 0; \ - PT_REGS_RSI(regs) = 0; \ - PT_REGS_RDI(regs) = 0; \ - PT_REGS_RBP(regs) = 0; \ - PT_REGS_RAX(regs) = 0; \ - PT_REGS_R8(regs) = 0; \ - PT_REGS_R9(regs) = 0; \ - PT_REGS_R10(regs) = 0; \ - PT_REGS_R11(regs) = 0; \ - PT_REGS_R12(regs) = 0; \ - PT_REGS_R13(regs) = 0; \ - PT_REGS_R14(regs) = 0; \ - PT_REGS_R15(regs) = 0; \ -} while (0) - -#define ELF_CORE_COPY_REGS(pr_reg, _regs) \ - (pr_reg)[0] = (_regs)->regs.gp[0]; \ - (pr_reg)[1] = (_regs)->regs.gp[1]; \ - (pr_reg)[2] = (_regs)->regs.gp[2]; \ - (pr_reg)[3] = (_regs)->regs.gp[3]; \ - (pr_reg)[4] = (_regs)->regs.gp[4]; \ - (pr_reg)[5] = (_regs)->regs.gp[5]; \ - (pr_reg)[6] = (_regs)->regs.gp[6]; \ - (pr_reg)[7] = (_regs)->regs.gp[7]; \ - (pr_reg)[8] = (_regs)->regs.gp[8]; \ - (pr_reg)[9] = (_regs)->regs.gp[9]; \ - (pr_reg)[10] = (_regs)->regs.gp[10]; \ - (pr_reg)[11] = (_regs)->regs.gp[11]; \ - (pr_reg)[12] = (_regs)->regs.gp[12]; \ - (pr_reg)[13] = (_regs)->regs.gp[13]; \ - (pr_reg)[14] = (_regs)->regs.gp[14]; \ - (pr_reg)[15] = (_regs)->regs.gp[15]; \ - (pr_reg)[16] = (_regs)->regs.gp[16]; \ - (pr_reg)[17] = (_regs)->regs.gp[17]; \ - (pr_reg)[18] = (_regs)->regs.gp[18]; \ - (pr_reg)[19] = (_regs)->regs.gp[19]; \ - (pr_reg)[20] = (_regs)->regs.gp[20]; \ - (pr_reg)[21] = current->thread.arch.fs; \ - (pr_reg)[22] = 0; \ - (pr_reg)[23] = 0; \ - (pr_reg)[24] = 0; \ - (pr_reg)[25] = 0; \ - (pr_reg)[26] = 0; - -#define task_pt_regs(t) (&(t)->thread.regs) - -struct task_struct; - -extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu); - -#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu) - -#ifdef TIF_IA32 /* XXX */ -#error XXX, indeed - clear_thread_flag(TIF_IA32); -#endif - -#define ELF_EXEC_PAGESIZE 4096 - -#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) - -extern long elf_aux_hwcap; -#define ELF_HWCAP (elf_aux_hwcap) - -#define ELF_PLATFORM "x86_64" - -#define SET_PERSONALITY(ex) do ; while(0) - -#endif diff --git a/arch/um/sys-x86_64/asm/module.h b/arch/um/sys-x86_64/asm/module.h deleted file mode 100644 index 8eb79c2d07d..00000000000 --- a/arch/um/sys-x86_64/asm/module.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __UM_MODULE_X86_64_H -#define __UM_MODULE_X86_64_H - -/* UML is simple */ -struct mod_arch_specific -{ -}; - -#define Elf_Shdr Elf64_Shdr -#define Elf_Sym Elf64_Sym -#define Elf_Ehdr Elf64_Ehdr - -#endif - diff --git a/arch/um/sys-x86_64/asm/processor.h b/arch/um/sys-x86_64/asm/processor.h deleted file mode 100644 index 875a26a6261..00000000000 --- a/arch/um/sys-x86_64/asm/processor.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __UM_PROCESSOR_X86_64_H -#define __UM_PROCESSOR_X86_64_H - -/* include faultinfo structure */ -#include "sysdep/faultinfo.h" - -struct arch_thread { - unsigned long debugregs[8]; - int debugregs_seq; - unsigned long fs; - struct faultinfo faultinfo; -}; - -/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ -static inline void rep_nop(void) -{ - __asm__ __volatile__("rep;nop": : :"memory"); -} - -#define cpu_relax() rep_nop() - -#define INIT_ARCH_THREAD { .debugregs = { [ 0 ... 7 ] = 0 }, \ - .debugregs_seq = 0, \ - .fs = 0, \ - .faultinfo = { 0, 0, 0 } } - -static inline void arch_flush_thread(struct arch_thread *thread) -{ -} - -static inline void arch_copy_thread(struct arch_thread *from, - struct arch_thread *to) -{ - to->fs = from->fs; -} - -#include <asm/user.h> - -#define current_text_addr() \ - ({ void *pc; __asm__("movq $1f,%0\n1:":"=g" (pc)); pc; }) - -#define ARCH_IS_STACKGROW(address) \ - (address + 128 >= UPT_SP(¤t->thread.regs.regs)) - -#define KSTK_EIP(tsk) KSTK_REG(tsk, RIP) -#define KSTK_ESP(tsk) KSTK_REG(tsk, RSP) - -#include "asm/processor-generic.h" - -#endif diff --git a/arch/um/sys-x86_64/asm/ptrace.h b/arch/um/sys-x86_64/asm/ptrace.h deleted file mode 100644 index 83d8c473b90..00000000000 --- a/arch/um/sys-x86_64/asm/ptrace.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __UM_PTRACE_X86_64_H -#define __UM_PTRACE_X86_64_H - -#include "linux/compiler.h" -#include "asm/errno.h" - -#define __FRAME_OFFSETS /* Needed to get the R* macros */ -#include "asm/ptrace-generic.h" - -#define HOST_AUDIT_ARCH AUDIT_ARCH_X86_64 - -#define PT_REGS_RBX(r) UPT_RBX(&(r)->regs) -#define PT_REGS_RCX(r) UPT_RCX(&(r)->regs) -#define PT_REGS_RDX(r) UPT_RDX(&(r)->regs) -#define PT_REGS_RSI(r) UPT_RSI(&(r)->regs) -#define PT_REGS_RDI(r) UPT_RDI(&(r)->regs) -#define PT_REGS_RBP(r) UPT_RBP(&(r)->regs) -#define PT_REGS_RAX(r) UPT_RAX(&(r)->regs) -#define PT_REGS_R8(r) UPT_R8(&(r)->regs) -#define PT_REGS_R9(r) UPT_R9(&(r)->regs) -#define PT_REGS_R10(r) UPT_R10(&(r)->regs) -#define PT_REGS_R11(r) UPT_R11(&(r)->regs) -#define PT_REGS_R12(r) UPT_R12(&(r)->regs) -#define PT_REGS_R13(r) UPT_R13(&(r)->regs) -#define PT_REGS_R14(r) UPT_R14(&(r)->regs) -#define PT_REGS_R15(r) UPT_R15(&(r)->regs) - -#define PT_REGS_FS(r) UPT_FS(&(r)->regs) -#define PT_REGS_GS(r) UPT_GS(&(r)->regs) -#define PT_REGS_DS(r) UPT_DS(&(r)->regs) -#define PT_REGS_ES(r) UPT_ES(&(r)->regs) -#define PT_REGS_SS(r) UPT_SS(&(r)->regs) -#define PT_REGS_CS(r) UPT_CS(&(r)->regs) - -#define PT_REGS_ORIG_RAX(r) UPT_ORIG_RAX(&(r)->regs) -#define PT_REGS_RIP(r) UPT_IP(&(r)->regs) -#define PT_REGS_RSP(r) UPT_SP(&(r)->regs) - -#define PT_REGS_EFLAGS(r) UPT_EFLAGS(&(r)->regs) - -/* XXX */ -#define user_mode(r) UPT_IS_USER(&(r)->regs) -#define PT_REGS_ORIG_SYSCALL(r) PT_REGS_RAX(r) -#define PT_REGS_SYSCALL_RET(r) PT_REGS_RAX(r) - -#define PT_FIX_EXEC_STACK(sp) do ; while(0) - -#define profile_pc(regs) PT_REGS_IP(regs) - -struct user_desc; - -static inline int ptrace_get_thread_area(struct task_struct *child, int idx, - struct user_desc __user *user_desc) -{ - return -ENOSYS; -} - -static inline int ptrace_set_thread_area(struct task_struct *child, int idx, - struct user_desc __user *user_desc) -{ - return -ENOSYS; -} - -extern long arch_prctl(struct task_struct *task, int code, - unsigned long __user *addr); -#endif diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c deleted file mode 100644 index e8034e363d8..00000000000 --- a/arch/um/sys-x86_64/bug.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL V2 - */ - -#include <linux/uaccess.h> - -/* - * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because - * that's not relevant in skas mode. - */ - -int is_valid_bugaddr(unsigned long eip) -{ - unsigned short ud2; - - if (probe_kernel_address((unsigned short __user *)eip, ud2)) - return 0; - - return ud2 == 0x0b0f; -} diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c deleted file mode 100644 index 44e02ba2a26..00000000000 --- a/arch/um/sys-x86_64/bugs.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include "sysdep/ptrace.h" - -void arch_check_bugs(void) -{ -} - -void arch_examine_signal(int sig, struct uml_pt_regs *regs) -{ -} diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c deleted file mode 100644 index dee5be66da8..00000000000 --- a/arch/um/sys-x86_64/delay.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * Copied from arch/x86_64 - * - * Licensed under the GPL - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <asm/processor.h> -#include <asm/param.h> - -void __delay(unsigned long loops) -{ - unsigned long i; - - for(i = 0; i < loops; i++) - cpu_relax(); -} - -void __udelay(unsigned long usecs) -{ - unsigned long i, n; - - n = (loops_per_jiffy * HZ * usecs) / MILLION; - for(i=0;i<n;i++) - cpu_relax(); -} - -EXPORT_SYMBOL(__udelay); diff --git a/arch/um/sys-x86_64/fault.c b/arch/um/sys-x86_64/fault.c deleted file mode 100644 index ce85117fc64..00000000000 --- a/arch/um/sys-x86_64/fault.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include "sysdep/ptrace.h" - -/* These two are from asm-um/uaccess.h and linux/module.h, check them. */ -struct exception_table_entry -{ - unsigned long insn; - unsigned long fixup; -}; - -const struct exception_table_entry *search_exception_tables(unsigned long add); - -int arch_fixup(unsigned long address, struct uml_pt_regs *regs) -{ - const struct exception_table_entry *fixup; - - fixup = search_exception_tables(address); - if (fixup != 0) { - UPT_IP(regs) = fixup->fixup; - return 1; - } - return 0; -} diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c deleted file mode 100644 index 1db2fce0094..00000000000 --- a/arch/um/sys-x86_64/ksyms.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <linux/module.h> -#include <asm/string.h> -#include <asm/checksum.h> - -/*XXX: we need them because they would be exported by x86_64 */ -#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) || __GNUC__ > 4 -EXPORT_SYMBOL(memcpy); -#else -EXPORT_SYMBOL(__memcpy); -#endif -EXPORT_SYMBOL(csum_partial); diff --git a/arch/um/sys-x86_64/mem.c b/arch/um/sys-x86_64/mem.c deleted file mode 100644 index 3f8df8abf34..00000000000 --- a/arch/um/sys-x86_64/mem.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include "linux/mm.h" -#include "asm/page.h" -#include "asm/mman.h" - -unsigned long vm_stack_flags = __VM_STACK_FLAGS; -unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; -unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; -unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; -unsigned long vm_force_exec32 = PROT_EXEC; - diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c deleted file mode 100644 index f43613643cd..00000000000 --- a/arch/um/sys-x86_64/ptrace.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * - * Licensed under the GPL - */ - -#include <linux/mm.h> -#include <linux/sched.h> -#include <linux/errno.h> -#define __FRAME_OFFSETS -#include <asm/ptrace.h> -#include <asm/uaccess.h> - -/* - * determines which flags the user has access to. - * 1 = access 0 = no access - */ -#define FLAG_MASK 0x44dd5UL - -int putreg(struct task_struct *child, int regno, unsigned long value) -{ - unsigned long tmp; - -#ifdef TIF_IA32 - /* - * Some code in the 64bit emulation may not be 64bit clean. - * Don't take any chances. - */ - if (test_tsk_thread_flag(child, TIF_IA32)) - value &= 0xffffffff; -#endif - switch (regno) { - case FS: - case GS: - case DS: - case ES: - case SS: - case CS: - if (value && (value & 3) != 3) - return -EIO; - value &= 0xffff; - break; - - case FS_BASE: - case GS_BASE: - if (!((value >> 48) == 0 || (value >> 48) == 0xffff)) - return -EIO; - break; - - case EFLAGS: - value &= FLAG_MASK; - tmp = PT_REGS_EFLAGS(&child->thread.regs) & ~FLAG_MASK; - value |= tmp; - break; - } - - PT_REGS_SET(&child->thread.regs, regno, value); - return 0; -} - -int poke_user(struct task_struct *child, long addr, long data) -{ - if ((addr & 3) || addr < 0) - return -EIO; - - if (addr < MAX_REG_OFFSET) - return putreg(child, addr, data); - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))) { - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - if ((addr == 4) || (addr == 5)) - return -EIO; - child->thread.arch.debugregs[addr] = data; - return 0; - } - return -EIO; -} - -unsigned long getreg(struct task_struct *child, int regno) -{ - unsigned long retval = ~0UL; - switch (regno) { - case FS: - case GS: - case DS: - case ES: - case SS: - case CS: - retval = 0xffff; - /* fall through */ - default: - retval &= PT_REG(&child->thread.regs, regno); -#ifdef TIF_IA32 - if (test_tsk_thread_flag(child, TIF_IA32)) - retval &= 0xffffffff; -#endif - } - return retval; -} - -int peek_user(struct task_struct *child, long addr, long data) -{ - /* read the word at location addr in the USER area. */ - unsigned long tmp; - - if ((addr & 3) || addr < 0) - return -EIO; - - tmp = 0; /* Default return condition */ - if (addr < MAX_REG_OFFSET) - tmp = getreg(child, addr); - else if ((addr >= offsetof(struct user, u_debugreg[0])) && - (addr <= offsetof(struct user, u_debugreg[7]))) { - addr -= offsetof(struct user, u_debugreg[0]); - addr = addr >> 2; - tmp = child->thread.arch.debugregs[addr]; - } - return put_user(tmp, (unsigned long *) data); -} - -/* XXX Mostly copied from sys-i386 */ -int is_syscall(unsigned long addr) -{ - unsigned short instr; - int n; - - n = copy_from_user(&instr, (void __user *) addr, sizeof(instr)); - if (n) { - /* - * access_process_vm() grants access to vsyscall and stub, - * while copy_from_user doesn't. Maybe access_process_vm is - * slow, but that doesn't matter, since it will be called only - * in case of singlestepping, if copy_from_user failed. - */ - n = access_process_vm(current, addr, &instr, sizeof(instr), 0); - if (n != sizeof(instr)) { - printk("is_syscall : failed to read instruction from " - "0x%lx\n", addr); - return 1; - } - } - /* sysenter */ - return instr == 0x050f; -} - -int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) -{ - int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; - - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fp_registers(userspace_pid[cpu], fpregs); - if (err) - return err; - - n = copy_to_user(buf, fpregs, sizeof(fpregs)); - if (n > 0) - return -EFAULT; - - return n; -} - -int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) -{ - int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; - - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, buf, sizeof(fpregs)); - if (n > 0) - return -EFAULT; - - return restore_fp_registers(userspace_pid[cpu], fpregs); -} - -long subarch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret = -EIO; - void __user *datap = (void __user *) data; - - switch (request) { - case PTRACE_GETFPXREGS: /* Get the child FPU state. */ - ret = get_fpregs(datap, child); - break; - case PTRACE_SETFPXREGS: /* Set the child FPU state. */ - ret = set_fpregs(datap, child); - break; - } - - return ret; -} diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c deleted file mode 100644 index c57a496d3f5..00000000000 --- a/arch/um/sys-x86_64/ptrace_user.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include <errno.h> -#include "ptrace_user.h" - -int ptrace_getregs(long pid, unsigned long *regs_out) -{ - if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0) - return -errno; - return(0); -} - -int ptrace_setregs(long pid, unsigned long *regs_out) -{ - if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0) - return -errno; - return(0); -} diff --git a/arch/um/sys-x86_64/setjmp.S b/arch/um/sys-x86_64/setjmp.S deleted file mode 100644 index 45f547b4043..00000000000 --- a/arch/um/sys-x86_64/setjmp.S +++ /dev/null @@ -1,54 +0,0 @@ -# -# arch/x86_64/setjmp.S -# -# setjmp/longjmp for the x86-64 architecture -# - -# -# The jmp_buf is assumed to contain the following, in order: -# %rbx -# %rsp (post-return) -# %rbp -# %r12 -# %r13 -# %r14 -# %r15 -# <return address> -# - - .text - .align 4 - .globl setjmp - .type setjmp, @function -setjmp: - pop %rsi # Return address, and adjust the stack - xorl %eax,%eax # Return value - movq %rbx,(%rdi) - movq %rsp,8(%rdi) # Post-return %rsp! - push %rsi # Make the call/return stack happy - movq %rbp,16(%rdi) - movq %r12,24(%rdi) - movq %r13,32(%rdi) - movq %r14,40(%rdi) - movq %r15,48(%rdi) - movq %rsi,56(%rdi) # Return address - ret - - .size setjmp,.-setjmp - - .text - .align 4 - .globl longjmp - .type longjmp, @function -longjmp: - movl %esi,%eax # Return value (int) - movq (%rdi),%rbx - movq 8(%rdi),%rsp - movq 16(%rdi),%rbp - movq 24(%rdi),%r12 - movq 32(%rdi),%r13 - movq 40(%rdi),%r14 - movq 48(%rdi),%r15 - jmp *56(%rdi) - - .size longjmp,.-longjmp diff --git a/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h b/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h deleted file mode 100644 index 2af8f12ca16..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/archsetjmp.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * arch/um/include/sysdep-x86_64/archsetjmp.h - */ - -#ifndef _KLIBC_ARCHSETJMP_H -#define _KLIBC_ARCHSETJMP_H - -struct __jmp_buf { - unsigned long __rbx; - unsigned long __rsp; - unsigned long __rbp; - unsigned long __r12; - unsigned long __r13; - unsigned long __r14; - unsigned long __r15; - unsigned long __rip; -}; - -typedef struct __jmp_buf jmp_buf[1]; - -#define JB_IP __rip -#define JB_SP __rsp - -#endif /* _SETJMP_H */ diff --git a/arch/um/sys-x86_64/shared/sysdep/barrier.h b/arch/um/sys-x86_64/shared/sysdep/barrier.h deleted file mode 100644 index 7b610befdc8..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/barrier.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __SYSDEP_X86_64_BARRIER_H -#define __SYSDEP_X86_64_BARRIER_H - -/* Copied from include/asm-x86_64 for use by userspace. */ -#define mb() asm volatile("mfence":::"memory") - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/checksum.h b/arch/um/sys-x86_64/shared/sysdep/checksum.h deleted file mode 100644 index a5be9031ea8..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/checksum.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Licensed under the GPL - */ - -#ifndef __UM_SYSDEP_CHECKSUM_H -#define __UM_SYSDEP_CHECKSUM_H - -#include "linux/string.h" -#include "linux/in6.h" -#include "asm/uaccess.h" - -extern __wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * Note: when you get a NULL pointer exception here this means someone - * passed in an incorrect kernel address to one of these functions. - * - * If you use these functions directly please don't forget the - * access_ok(). - */ - -static __inline__ -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum) -{ - memcpy(dst, src, len); - return(csum_partial(dst, len, sum)); -} - -static __inline__ -__wsum csum_partial_copy_from_user(const void __user *src, - void *dst, int len, __wsum sum, - int *err_ptr) -{ - if (copy_from_user(dst, src, len)) { - *err_ptr = -EFAULT; - return (__force __wsum)-1; - } - return csum_partial(dst, len, sum); -} - -/** - * csum_fold - Fold and invert a 32bit checksum. - * sum: 32bit unfolded sum - * - * Fold a 32bit running checksum to 16bit and invert it. This is usually - * the last step before putting a checksum into a packet. - * Make sure not to mix with 64bit checksums. - */ -static inline __sum16 csum_fold(__wsum sum) -{ - __asm__( - " addl %1,%0\n" - " adcl $0xffff,%0" - : "=r" (sum) - : "r" ((__force u32)sum << 16), - "0" ((__force u32)sum & 0xffff0000) - ); - return (__force __sum16)(~(__force u32)sum >> 16); -} - -/** - * csum_tcpup_nofold - Compute an IPv4 pseudo header checksum. - * @saddr: source address - * @daddr: destination address - * @len: length of packet - * @proto: ip protocol of packet - * @sum: initial sum to be added in (32bit unfolded) - * - * Returns the pseudo header checksum the input data. Result is - * 32bit unfolded. - */ -static inline __wsum -csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, - unsigned short proto, __wsum sum) -{ - asm(" addl %1, %0\n" - " adcl %2, %0\n" - " adcl %3, %0\n" - " adcl $0, %0\n" - : "=r" (sum) - : "g" (daddr), "g" (saddr), "g" ((len + proto) << 8), "0" (sum)); - return sum; -} - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -} - -/** - * ip_fast_csum - Compute the IPv4 header checksum efficiently. - * iph: ipv4 header - * ihl: length of header / 4 - */ -static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - unsigned int sum; - - asm( " movl (%1), %0\n" - " subl $4, %2\n" - " jbe 2f\n" - " addl 4(%1), %0\n" - " adcl 8(%1), %0\n" - " adcl 12(%1), %0\n" - "1: adcl 16(%1), %0\n" - " lea 4(%1), %1\n" - " decl %2\n" - " jne 1b\n" - " adcl $0, %0\n" - " movl %0, %2\n" - " shrl $16, %0\n" - " addw %w2, %w0\n" - " adcl $0, %0\n" - " notl %0\n" - "2:" - /* Since the input registers which are loaded with iph and ipl - are modified, we must also specify them as outputs, or gcc - will assume they contain their original values. */ - : "=r" (sum), "=r" (iph), "=r" (ihl) - : "1" (iph), "2" (ihl) - : "memory"); - return (__force __sum16)sum; -} - -static inline unsigned add32_with_carry(unsigned a, unsigned b) -{ - asm("addl %2,%0\n\t" - "adcl $0,%0" - : "=r" (a) - : "0" (a), "r" (b)); - return a; -} - -extern __sum16 ip_compute_csum(const void *buff, int len); - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/faultinfo.h b/arch/um/sys-x86_64/shared/sysdep/faultinfo.h deleted file mode 100644 index cb917b0d566..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/faultinfo.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2004 Fujitsu Siemens Computers GmbH - * Author: Bodo Stroesser <bstroesser@fujitsu-siemens.com> - * Licensed under the GPL - */ - -#ifndef __FAULTINFO_X86_64_H -#define __FAULTINFO_X86_64_H - -/* this structure contains the full arch-specific faultinfo - * from the traps. - * On i386, ptrace_faultinfo unfortunately doesn't provide - * all the info, since trap_no is missing. - * All common elements are defined at the same position in - * both structures, thus making it easy to copy the - * contents without knowledge about the structure elements. - */ -struct faultinfo { - int error_code; /* in ptrace_faultinfo misleadingly called is_write */ - unsigned long cr2; /* in ptrace_faultinfo called addr */ - int trap_no; /* missing in ptrace_faultinfo */ -}; - -#define FAULT_WRITE(fi) ((fi).error_code & 2) -#define FAULT_ADDRESS(fi) ((fi).cr2) - -#define PTRACE_FULL_FAULTINFO 1 - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/host_ldt.h b/arch/um/sys-x86_64/shared/sysdep/host_ldt.h deleted file mode 100644 index e8b1be1e154..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/host_ldt.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __ASM_HOST_LDT_X86_64_H -#define __ASM_HOST_LDT_X86_64_H - -#include <asm/ldt.h> - -/* - * macros stolen from include/asm-x86_64/desc.h - */ -#define LDT_entry_a(info) \ - ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff)) - -/* Don't allow setting of the lm bit. It is useless anyways because - * 64bit system calls require __USER_CS. */ -#define LDT_entry_b(info) \ - (((info)->base_addr & 0xff000000) | \ - (((info)->base_addr & 0x00ff0000) >> 16) | \ - ((info)->limit & 0xf0000) | \ - (((info)->read_exec_only ^ 1) << 9) | \ - ((info)->contents << 10) | \ - (((info)->seg_not_present ^ 1) << 15) | \ - ((info)->seg_32bit << 22) | \ - ((info)->limit_in_pages << 23) | \ - ((info)->useable << 20) | \ - /* ((info)->lm << 21) | */ \ - 0x7000) - -#define LDT_empty(info) (\ - (info)->base_addr == 0 && \ - (info)->limit == 0 && \ - (info)->contents == 0 && \ - (info)->read_exec_only == 1 && \ - (info)->seg_32bit == 0 && \ - (info)->limit_in_pages == 0 && \ - (info)->seg_not_present == 1 && \ - (info)->useable == 0 && \ - (info)->lm == 0) - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h b/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h deleted file mode 100644 index a307237b796..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/kernel-offsets.h +++ /dev/null @@ -1,23 +0,0 @@ -#include <linux/stddef.h> -#include <linux/sched.h> -#include <linux/time.h> -#include <linux/elf.h> -#include <linux/crypto.h> -#include <asm/page.h> -#include <asm/mman.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define DEFINE_STR1(x) #x -#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " DEFINE_STR1(val) " " #val: : ) - -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - -void foo(void) -{ -#include <common-offsets.h> -} diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace.h b/arch/um/sys-x86_64/shared/sysdep/ptrace.h deleted file mode 100644 index fdba5457947..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/ptrace.h +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * - * Licensed under the GPL - */ - -#ifndef __SYSDEP_X86_64_PTRACE_H -#define __SYSDEP_X86_64_PTRACE_H - -#include "user_constants.h" -#include "sysdep/faultinfo.h" - -#define MAX_REG_OFFSET (UM_FRAME_SIZE) -#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long)) - -#include "skas_ptregs.h" - -#define REGS_IP(r) ((r)[HOST_IP]) -#define REGS_SP(r) ((r)[HOST_SP]) - -#define REGS_RBX(r) ((r)[HOST_RBX]) -#define REGS_RCX(r) ((r)[HOST_RCX]) -#define REGS_RDX(r) ((r)[HOST_RDX]) -#define REGS_RSI(r) ((r)[HOST_RSI]) -#define REGS_RDI(r) ((r)[HOST_RDI]) -#define REGS_RBP(r) ((r)[HOST_RBP]) -#define REGS_RAX(r) ((r)[HOST_RAX]) -#define REGS_R8(r) ((r)[HOST_R8]) -#define REGS_R9(r) ((r)[HOST_R9]) -#define REGS_R10(r) ((r)[HOST_R10]) -#define REGS_R11(r) ((r)[HOST_R11]) -#define REGS_R12(r) ((r)[HOST_R12]) -#define REGS_R13(r) ((r)[HOST_R13]) -#define REGS_R14(r) ((r)[HOST_R14]) -#define REGS_R15(r) ((r)[HOST_R15]) -#define REGS_CS(r) ((r)[HOST_CS]) -#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS]) -#define REGS_SS(r) ((r)[HOST_SS]) - -#define HOST_FS_BASE 21 -#define HOST_GS_BASE 22 -#define HOST_DS 23 -#define HOST_ES 24 -#define HOST_FS 25 -#define HOST_GS 26 - -/* Also defined in asm/ptrace-x86_64.h, but not in libc headers. So, these - * are already defined for kernel code, but not for userspace code. - */ -#ifndef FS_BASE -/* These aren't defined in ptrace.h, but exist in struct user_regs_struct, - * which is what x86_64 ptrace actually uses. - */ -#define FS_BASE (HOST_FS_BASE * sizeof(long)) -#define GS_BASE (HOST_GS_BASE * sizeof(long)) -#define DS (HOST_DS * sizeof(long)) -#define ES (HOST_ES * sizeof(long)) -#define FS (HOST_FS * sizeof(long)) -#define GS (HOST_GS * sizeof(long)) -#endif - -#define REGS_FS_BASE(r) ((r)[HOST_FS_BASE]) -#define REGS_GS_BASE(r) ((r)[HOST_GS_BASE]) -#define REGS_DS(r) ((r)[HOST_DS]) -#define REGS_ES(r) ((r)[HOST_ES]) -#define REGS_FS(r) ((r)[HOST_FS]) -#define REGS_GS(r) ((r)[HOST_GS]) - -#define REGS_ORIG_RAX(r) ((r)[HOST_ORIG_RAX]) - -#define REGS_SET_SYSCALL_RETURN(r, res) REGS_RAX(r) = (res) - -#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r)) - -#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type) - -#define REGS_FAULT_ADDR(r) ((r)->fault_addr) - -#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type) - -#define REGS_TRAP(r) ((r)->trap_type) - -#define REGS_ERR(r) ((r)->fault_type) - -struct uml_pt_regs { - unsigned long gp[MAX_REG_NR]; - struct faultinfo faultinfo; - long syscall; - int is_user; -}; - -#define EMPTY_UML_PT_REGS { } - -#define UPT_RBX(r) REGS_RBX((r)->gp) -#define UPT_RCX(r) REGS_RCX((r)->gp) -#define UPT_RDX(r) REGS_RDX((r)->gp) -#define UPT_RSI(r) REGS_RSI((r)->gp) -#define UPT_RDI(r) REGS_RDI((r)->gp) -#define UPT_RBP(r) REGS_RBP((r)->gp) -#define UPT_RAX(r) REGS_RAX((r)->gp) -#define UPT_R8(r) REGS_R8((r)->gp) -#define UPT_R9(r) REGS_R9((r)->gp) -#define UPT_R10(r) REGS_R10((r)->gp) -#define UPT_R11(r) REGS_R11((r)->gp) -#define UPT_R12(r) REGS_R12((r)->gp) -#define UPT_R13(r) REGS_R13((r)->gp) -#define UPT_R14(r) REGS_R14((r)->gp) -#define UPT_R15(r) REGS_R15((r)->gp) -#define UPT_CS(r) REGS_CS((r)->gp) -#define UPT_FS_BASE(r) REGS_FS_BASE((r)->gp) -#define UPT_FS(r) REGS_FS((r)->gp) -#define UPT_GS_BASE(r) REGS_GS_BASE((r)->gp) -#define UPT_GS(r) REGS_GS((r)->gp) -#define UPT_DS(r) REGS_DS((r)->gp) -#define UPT_ES(r) REGS_ES((r)->gp) -#define UPT_CS(r) REGS_CS((r)->gp) -#define UPT_SS(r) REGS_SS((r)->gp) -#define UPT_ORIG_RAX(r) REGS_ORIG_RAX((r)->gp) - -#define UPT_IP(r) REGS_IP((r)->gp) -#define UPT_SP(r) REGS_SP((r)->gp) - -#define UPT_EFLAGS(r) REGS_EFLAGS((r)->gp) -#define UPT_SYSCALL_NR(r) ((r)->syscall) -#define UPT_SYSCALL_RET(r) UPT_RAX(r) - -extern int user_context(unsigned long sp); - -#define UPT_IS_USER(r) ((r)->is_user) - -#define UPT_SYSCALL_ARG1(r) UPT_RDI(r) -#define UPT_SYSCALL_ARG2(r) UPT_RSI(r) -#define UPT_SYSCALL_ARG3(r) UPT_RDX(r) -#define UPT_SYSCALL_ARG4(r) UPT_R10(r) -#define UPT_SYSCALL_ARG5(r) UPT_R8(r) -#define UPT_SYSCALL_ARG6(r) UPT_R9(r) - -struct syscall_args { - unsigned long args[6]; -}; - -#define SYSCALL_ARGS(r) ((struct syscall_args) \ - { .args = { UPT_SYSCALL_ARG1(r), \ - UPT_SYSCALL_ARG2(r), \ - UPT_SYSCALL_ARG3(r), \ - UPT_SYSCALL_ARG4(r), \ - UPT_SYSCALL_ARG5(r), \ - UPT_SYSCALL_ARG6(r) } } ) - -#define UPT_REG(regs, reg) \ - ({ unsigned long val; \ - switch(reg){ \ - case R8: val = UPT_R8(regs); break; \ - case R9: val = UPT_R9(regs); break; \ - case R10: val = UPT_R10(regs); break; \ - case R11: val = UPT_R11(regs); break; \ - case R12: val = UPT_R12(regs); break; \ - case R13: val = UPT_R13(regs); break; \ - case R14: val = UPT_R14(regs); break; \ - case R15: val = UPT_R15(regs); break; \ - case RIP: val = UPT_IP(regs); break; \ - case RSP: val = UPT_SP(regs); break; \ - case RAX: val = UPT_RAX(regs); break; \ - case RBX: val = UPT_RBX(regs); break; \ - case RCX: val = UPT_RCX(regs); break; \ - case RDX: val = UPT_RDX(regs); break; \ - case RSI: val = UPT_RSI(regs); break; \ - case RDI: val = UPT_RDI(regs); break; \ - case RBP: val = UPT_RBP(regs); break; \ - case ORIG_RAX: val = UPT_ORIG_RAX(regs); break; \ - case CS: val = UPT_CS(regs); break; \ - case SS: val = UPT_SS(regs); break; \ - case FS_BASE: val = UPT_FS_BASE(regs); break; \ - case GS_BASE: val = UPT_GS_BASE(regs); break; \ - case DS: val = UPT_DS(regs); break; \ - case ES: val = UPT_ES(regs); break; \ - case FS : val = UPT_FS (regs); break; \ - case GS: val = UPT_GS(regs); break; \ - case EFLAGS: val = UPT_EFLAGS(regs); break; \ - default : \ - panic("Bad register in UPT_REG : %d\n", reg); \ - val = -1; \ - } \ - val; \ - }) - - -#define UPT_SET(regs, reg, val) \ - ({ unsigned long __upt_val = val; \ - switch(reg){ \ - case R8: UPT_R8(regs) = __upt_val; break; \ - case R9: UPT_R9(regs) = __upt_val; break; \ - case R10: UPT_R10(regs) = __upt_val; break; \ - case R11: UPT_R11(regs) = __upt_val; break; \ - case R12: UPT_R12(regs) = __upt_val; break; \ - case R13: UPT_R13(regs) = __upt_val; break; \ - case R14: UPT_R14(regs) = __upt_val; break; \ - case R15: UPT_R15(regs) = __upt_val; break; \ - case RIP: UPT_IP(regs) = __upt_val; break; \ - case RSP: UPT_SP(regs) = __upt_val; break; \ - case RAX: UPT_RAX(regs) = __upt_val; break; \ - case RBX: UPT_RBX(regs) = __upt_val; break; \ - case RCX: UPT_RCX(regs) = __upt_val; break; \ - case RDX: UPT_RDX(regs) = __upt_val; break; \ - case RSI: UPT_RSI(regs) = __upt_val; break; \ - case RDI: UPT_RDI(regs) = __upt_val; break; \ - case RBP: UPT_RBP(regs) = __upt_val; break; \ - case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \ - case CS: UPT_CS(regs) = __upt_val; break; \ - case SS: UPT_SS(regs) = __upt_val; break; \ - case FS_BASE: UPT_FS_BASE(regs) = __upt_val; break; \ - case GS_BASE: UPT_GS_BASE(regs) = __upt_val; break; \ - case DS: UPT_DS(regs) = __upt_val; break; \ - case ES: UPT_ES(regs) = __upt_val; break; \ - case FS: UPT_FS(regs) = __upt_val; break; \ - case GS: UPT_GS(regs) = __upt_val; break; \ - case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \ - default : \ - panic("Bad register in UPT_SET : %d\n", reg); \ - break; \ - } \ - __upt_val; \ - }) - -#define UPT_SET_SYSCALL_RETURN(r, res) \ - REGS_SET_SYSCALL_RETURN((r)->regs, (res)) - -#define UPT_RESTART_SYSCALL(r) REGS_RESTART_SYSCALL((r)->gp) - -#define UPT_SEGV_IS_FIXABLE(r) REGS_SEGV_IS_FIXABLE(&r->skas) - -#define UPT_FAULTINFO(r) (&(r)->faultinfo) - -static inline void arch_init_registers(int pid) -{ -} - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h b/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h deleted file mode 100644 index 4dbccdb58f4..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/ptrace_user.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __SYSDEP_X86_64_PTRACE_USER_H__ -#define __SYSDEP_X86_64_PTRACE_USER_H__ - -#define __FRAME_OFFSETS -#include <sys/ptrace.h> -#include <linux/ptrace.h> -#include <asm/ptrace.h> -#undef __FRAME_OFFSETS -#include "user_constants.h" - -#define PT_INDEX(off) ((off) / sizeof(unsigned long)) - -#define PT_SYSCALL_NR(regs) ((regs)[PT_INDEX(ORIG_RAX)]) -#define PT_SYSCALL_NR_OFFSET (ORIG_RAX) - -#define PT_SYSCALL_ARG1(regs) (((unsigned long *) (regs))[PT_INDEX(RDI)]) -#define PT_SYSCALL_ARG1_OFFSET (RDI) - -#define PT_SYSCALL_ARG2(regs) (((unsigned long *) (regs))[PT_INDEX(RSI)]) -#define PT_SYSCALL_ARG2_OFFSET (RSI) - -#define PT_SYSCALL_ARG3(regs) (((unsigned long *) (regs))[PT_INDEX(RDX)]) -#define PT_SYSCALL_ARG3_OFFSET (RDX) - -#define PT_SYSCALL_ARG4(regs) (((unsigned long *) (regs))[PT_INDEX(RCX)]) -#define PT_SYSCALL_ARG4_OFFSET (RCX) - -#define PT_SYSCALL_ARG5(regs) (((unsigned long *) (regs))[PT_INDEX(R8)]) -#define PT_SYSCALL_ARG5_OFFSET (R8) - -#define PT_SYSCALL_ARG6(regs) (((unsigned long *) (regs))[PT_INDEX(R9)]) -#define PT_SYSCALL_ARG6_OFFSET (R9) - -#define PT_SYSCALL_RET_OFFSET (RAX) - -#define PT_IP_OFFSET (RIP) -#define PT_IP(regs) ((regs)[PT_INDEX(RIP)]) - -#define PT_SP_OFFSET (RSP) -#define PT_SP(regs) ((regs)[PT_INDEX(RSP)]) - -#define PT_ORIG_RAX_OFFSET (ORIG_RAX) -#define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)]) - -/* - * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though - * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the - * 2.4 name and value for 2.4 host compatibility. - */ -#ifndef PTRACE_OLDSETOPTIONS -#define PTRACE_OLDSETOPTIONS 21 -#endif - -/* - * These are before the system call, so the system call number is RAX - * rather than ORIG_RAX, and arg4 is R10 rather than RCX - */ -#define REGS_SYSCALL_NR PT_INDEX(RAX) -#define REGS_SYSCALL_ARG1 PT_INDEX(RDI) -#define REGS_SYSCALL_ARG2 PT_INDEX(RSI) -#define REGS_SYSCALL_ARG3 PT_INDEX(RDX) -#define REGS_SYSCALL_ARG4 PT_INDEX(R10) -#define REGS_SYSCALL_ARG5 PT_INDEX(R8) -#define REGS_SYSCALL_ARG6 PT_INDEX(R9) - -#define REGS_IP_INDEX PT_INDEX(RIP) -#define REGS_SP_INDEX PT_INDEX(RSP) - -#define FP_SIZE (HOST_FP_SIZE) - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/sc.h b/arch/um/sys-x86_64/shared/sysdep/sc.h deleted file mode 100644 index 8aee45b0743..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/sc.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __SYSDEP_X86_64_SC_H -#define __SYSDEP_X86_64_SC_H - -/* Copyright (C) 2003 - 2004 PathScale, Inc - * Released under the GPL - */ - -#include <user_constants.h> - -#define SC_OFFSET(sc, field) \ - *((unsigned long *) &(((char *) (sc))[HOST_##field])) - -#define SC_RBX(sc) SC_OFFSET(sc, SC_RBX) -#define SC_RCX(sc) SC_OFFSET(sc, SC_RCX) -#define SC_RDX(sc) SC_OFFSET(sc, SC_RDX) -#define SC_RSI(sc) SC_OFFSET(sc, SC_RSI) -#define SC_RDI(sc) SC_OFFSET(sc, SC_RDI) -#define SC_RBP(sc) SC_OFFSET(sc, SC_RBP) -#define SC_RAX(sc) SC_OFFSET(sc, SC_RAX) -#define SC_R8(sc) SC_OFFSET(sc, SC_R8) -#define SC_R9(sc) SC_OFFSET(sc, SC_R9) -#define SC_R10(sc) SC_OFFSET(sc, SC_R10) -#define SC_R11(sc) SC_OFFSET(sc, SC_R11) -#define SC_R12(sc) SC_OFFSET(sc, SC_R12) -#define SC_R13(sc) SC_OFFSET(sc, SC_R13) -#define SC_R14(sc) SC_OFFSET(sc, SC_R14) -#define SC_R15(sc) SC_OFFSET(sc, SC_R15) -#define SC_IP(sc) SC_OFFSET(sc, SC_IP) -#define SC_SP(sc) SC_OFFSET(sc, SC_SP) -#define SC_CR2(sc) SC_OFFSET(sc, SC_CR2) -#define SC_ERR(sc) SC_OFFSET(sc, SC_ERR) -#define SC_TRAPNO(sc) SC_OFFSET(sc, SC_TRAPNO) -#define SC_CS(sc) SC_OFFSET(sc, SC_CS) -#define SC_FS(sc) SC_OFFSET(sc, SC_FS) -#define SC_GS(sc) SC_OFFSET(sc, SC_GS) -#define SC_EFLAGS(sc) SC_OFFSET(sc, SC_EFLAGS) -#define SC_SIGMASK(sc) SC_OFFSET(sc, SC_SIGMASK) -#define SC_SS(sc) SC_OFFSET(sc, SC_SS) -#if 0 -#define SC_ORIG_RAX(sc) SC_OFFSET(sc, SC_ORIG_RAX) -#define SC_DS(sc) SC_OFFSET(sc, SC_DS) -#define SC_ES(sc) SC_OFFSET(sc, SC_ES) -#endif - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/sigcontext.h b/arch/um/sys-x86_64/shared/sysdep/sigcontext.h deleted file mode 100644 index 0155133b145..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/sigcontext.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __SYSDEP_X86_64_SIGCONTEXT_H -#define __SYSDEP_X86_64_SIGCONTEXT_H - -#include <sysdep/sc.h> - -#define IP_RESTART_SYSCALL(ip) ((ip) -= 2) - -#define GET_FAULTINFO_FROM_SC(fi, sc) \ - { \ - (fi).cr2 = SC_CR2(sc); \ - (fi).error_code = SC_ERR(sc); \ - (fi).trap_no = SC_TRAPNO(sc); \ - } - -/* This is Page Fault */ -#define SEGV_IS_FIXABLE(fi) ((fi)->trap_no == 14) - -/* No broken SKAS API, which doesn't pass trap_no, here. */ -#define SEGV_MAYBE_FIXABLE(fi) 0 - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h b/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h deleted file mode 100644 index 95db4be786e..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/skas_ptrace.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SYSDEP_X86_64_SKAS_PTRACE_H -#define __SYSDEP_X86_64_SKAS_PTRACE_H - -struct ptrace_faultinfo { - int is_write; - unsigned long addr; -}; - -struct ptrace_ldt { - int func; - void *ptr; - unsigned long bytecount; -}; - -#define PTRACE_LDT 54 - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/stub.h b/arch/um/sys-x86_64/shared/sysdep/stub.h deleted file mode 100644 index 3432aa24997..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/stub.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __SYSDEP_STUB_H -#define __SYSDEP_STUB_H - -#include <sys/mman.h> -#include <asm/unistd.h> -#include <sysdep/ptrace_user.h> -#include "as-layout.h" -#include "stub-data.h" -#include "kern_constants.h" - -extern void stub_segv_handler(int sig); -extern void stub_clone_handler(void); - -#define STUB_SYSCALL_RET PT_INDEX(RAX) -#define STUB_MMAP_NR __NR_mmap -#define MMAP_OFFSET(o) (o) - -#define __syscall_clobber "r11","rcx","memory" -#define __syscall "syscall" - -static inline long stub_syscall0(long syscall) -{ - long ret; - - __asm__ volatile (__syscall - : "=a" (ret) - : "0" (syscall) : __syscall_clobber ); - - return ret; -} - -static inline long stub_syscall2(long syscall, long arg1, long arg2) -{ - long ret; - - __asm__ volatile (__syscall - : "=a" (ret) - : "0" (syscall), "D" (arg1), "S" (arg2) : __syscall_clobber ); - - return ret; -} - -static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3) -{ - long ret; - - __asm__ volatile (__syscall - : "=a" (ret) - : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3) - : __syscall_clobber ); - - return ret; -} - -static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3, - long arg4) -{ - long ret; - - __asm__ volatile ("movq %5,%%r10 ; " __syscall - : "=a" (ret) - : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3), - "g" (arg4) - : __syscall_clobber, "r10" ); - - return ret; -} - -static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, - long arg4, long arg5) -{ - long ret; - - __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall - : "=a" (ret) - : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3), - "g" (arg4), "g" (arg5) - : __syscall_clobber, "r10", "r8" ); - - return ret; -} - -static inline void trap_myself(void) -{ - __asm("int3"); -} - -static inline void remap_stack(long fd, unsigned long offset) -{ - __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; " - "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; " - "movq %%rax, (%%rbx)": - : "a" (STUB_MMAP_NR), "D" (STUB_DATA), - "S" (UM_KERN_PAGE_SIZE), - "d" (PROT_READ | PROT_WRITE), - "g" (MAP_FIXED | MAP_SHARED), "g" (fd), - "g" (offset), - "i" (&((struct stub_data *) STUB_DATA)->err) - : __syscall_clobber, "r10", "r8", "r9" ); -} - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/syscalls.h b/arch/um/sys-x86_64/shared/sysdep/syscalls.h deleted file mode 100644 index 7cfb0b08565..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/syscalls.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#ifndef __SYSDEP_X86_64_SYSCALLS_H__ -#define __SYSDEP_X86_64_SYSCALLS_H__ - -#include <linux/msg.h> -#include <linux/shm.h> -#include <kern_constants.h> - -typedef long syscall_handler_t(void); - -extern syscall_handler_t *sys_call_table[]; - -#define EXECUTE_SYSCALL(syscall, regs) \ - (((long (*)(long, long, long, long, long, long)) \ - (*sys_call_table[syscall]))(UPT_SYSCALL_ARG1(®s->regs), \ - UPT_SYSCALL_ARG2(®s->regs), \ - UPT_SYSCALL_ARG3(®s->regs), \ - UPT_SYSCALL_ARG4(®s->regs), \ - UPT_SYSCALL_ARG5(®s->regs), \ - UPT_SYSCALL_ARG6(®s->regs))) - -extern long old_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff); -extern syscall_handler_t sys_modify_ldt; -extern syscall_handler_t sys_arch_prctl; - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/system.h b/arch/um/sys-x86_64/shared/sysdep/system.h deleted file mode 100644 index d1b93c43620..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/system.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef _ASM_X86_SYSTEM_H_ -#define _ASM_X86_SYSTEM_H_ - -#include <asm/asm.h> -#include <asm/segment.h> -#include <asm/cpufeature.h> -#include <asm/cmpxchg.h> -#include <asm/nops.h> - -#include <linux/kernel.h> -#include <linux/irqflags.h> - -/* entries in ARCH_DLINFO: */ -#ifdef CONFIG_IA32_EMULATION -# define AT_VECTOR_SIZE_ARCH 2 -#else -# define AT_VECTOR_SIZE_ARCH 1 -#endif - -extern unsigned long arch_align_stack(unsigned long sp); - -void default_idle(void); - -/* - * Force strict CPU ordering. - * And yes, this is required on UP too when we're talking - * to devices. - */ -#ifdef CONFIG_X86_32 -/* - * Some non-Intel clones support out of order store. wmb() ceases to be a - * nop for these. - */ -#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) -#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) -#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) -#else -#define mb() asm volatile("mfence":::"memory") -#define rmb() asm volatile("lfence":::"memory") -#define wmb() asm volatile("sfence" ::: "memory") -#endif - -/** - * read_barrier_depends - Flush all pending reads that subsequents reads - * depend on. - * - * No data-dependent reads from memory-like regions are ever reordered - * over this barrier. All reads preceding this primitive are guaranteed - * to access memory (but not necessarily other CPUs' caches) before any - * reads following this primitive that depend on the data return by - * any of the preceding reads. This primitive is much lighter weight than - * rmb() on most CPUs, and is never heavier weight than is - * rmb(). - * - * These ordering constraints are respected by both the local CPU - * and the compiler. - * - * Ordering is not guaranteed by anything other than these primitives, - * not even by data dependencies. See the documentation for - * memory_barrier() for examples and URLs to more information. - * - * For example, the following code would force ordering (the initial - * value of "a" is zero, "b" is one, and "p" is "&a"): - * - * <programlisting> - * CPU 0 CPU 1 - * - * b = 2; - * memory_barrier(); - * p = &b; q = p; - * read_barrier_depends(); - * d = *q; - * </programlisting> - * - * because the read of "*q" depends on the read of "p" and these - * two reads are separated by a read_barrier_depends(). However, - * the following code, with the same initial values for "a" and "b": - * - * <programlisting> - * CPU 0 CPU 1 - * - * a = 2; - * memory_barrier(); - * b = 3; y = b; - * read_barrier_depends(); - * x = a; - * </programlisting> - * - * does not enforce ordering, since there is no data dependency between - * the read of "a" and the read of "b". Therefore, on some CPUs, such - * as Alpha, "y" could be set to 3 and "x" to 0. Use rmb() - * in cases like this where there are no data dependencies. - **/ - -#define read_barrier_depends() do { } while (0) - -#ifdef CONFIG_SMP -#define smp_mb() mb() -#ifdef CONFIG_X86_PPRO_FENCE -# define smp_rmb() rmb() -#else -# define smp_rmb() barrier() -#endif -#ifdef CONFIG_X86_OOSTORE -# define smp_wmb() wmb() -#else -# define smp_wmb() barrier() -#endif -#define smp_read_barrier_depends() read_barrier_depends() -#define set_mb(var, value) do { (void)xchg(&var, value); } while (0) -#else -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#define smp_read_barrier_depends() do { } while (0) -#define set_mb(var, value) do { var = value; barrier(); } while (0) -#endif - -/* - * Stop RDTSC speculation. This is needed when you need to use RDTSC - * (or get_cycles or vread that possibly accesses the TSC) in a defined - * code region. - * - * (Could use an alternative three way for this if there was one.) - */ -static inline void rdtsc_barrier(void) -{ - alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC); - alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC); -} - -#endif diff --git a/arch/um/sys-x86_64/shared/sysdep/tls.h b/arch/um/sys-x86_64/shared/sysdep/tls.h deleted file mode 100644 index 18c000d0357..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/tls.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _SYSDEP_TLS_H -#define _SYSDEP_TLS_H - -# ifndef __KERNEL__ - -/* Change name to avoid conflicts with the original one from <asm/ldt.h>, which - * may be named user_desc (but in 2.4 and in header matching its API was named - * modify_ldt_ldt_s). */ - -typedef struct um_dup_user_desc { - unsigned int entry_number; - unsigned int base_addr; - unsigned int limit; - unsigned int seg_32bit:1; - unsigned int contents:2; - unsigned int read_exec_only:1; - unsigned int limit_in_pages:1; - unsigned int seg_not_present:1; - unsigned int useable:1; - unsigned int lm:1; -} user_desc_t; - -# else /* __KERNEL__ */ - -# include <ldt.h> -typedef struct user_desc user_desc_t; - -# endif /* __KERNEL__ */ -#endif /* _SYSDEP_TLS_H */ diff --git a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h b/arch/um/sys-x86_64/shared/sysdep/vm-flags.h deleted file mode 100644 index 3213edfa788..00000000000 --- a/arch/um/sys-x86_64/shared/sysdep/vm-flags.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2004 Jeff Dike (jdike@addtoit.com) - * Copyright 2003 PathScale, Inc. - * Licensed under the GPL - */ - -#ifndef __VM_FLAGS_X86_64_H -#define __VM_FLAGS_X86_64_H - -#define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -#define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | \ - VM_EXEC | VM_MAYREAD | VM_MAYWRITE | \ - VM_MAYEXEC) - -extern unsigned long vm_stack_flags, vm_stack_flags32; -extern unsigned long vm_data_default_flags, vm_data_default_flags32; -extern unsigned long vm_force_exec32; - -#ifdef TIF_IA32 -#define VM_DATA_DEFAULT_FLAGS \ - (test_thread_flag(TIF_IA32) ? vm_data_default_flags32 : \ - vm_data_default_flags) - -#define VM_STACK_DEFAULT_FLAGS \ - (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) -#endif - -#define VM_DATA_DEFAULT_FLAGS vm_data_default_flags - -#define VM_STACK_DEFAULT_FLAGS vm_stack_flags - -#endif diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c deleted file mode 100644 index b6b65c7c7a7..00000000000 --- a/arch/um/sys-x86_64/signal.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) 2003 PathScale, Inc. - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <linux/personality.h> -#include <linux/ptrace.h> -#include <linux/kernel.h> -#include <asm/unistd.h> -#include <asm/uaccess.h> -#include <asm/ucontext.h> -#include "frame_kern.h" -#include "skas.h" - -void copy_sc(struct uml_pt_regs *regs, void *from) -{ - struct sigcontext *sc = from; - -#define GETREG(regs, regno, sc, regname) \ - (regs)->gp[(regno) / sizeof(unsigned long)] = (sc)->regname - - GETREG(regs, R8, sc, r8); - GETREG(regs, R9, sc, r9); - GETREG(regs, R10, sc, r10); - GETREG(regs, R11, sc, r11); - GETREG(regs, R12, sc, r12); - GETREG(regs, R13, sc, r13); - GETREG(regs, R14, sc, r14); - GETREG(regs, R15, sc, r15); - GETREG(regs, RDI, sc, di); - GETREG(regs, RSI, sc, si); - GETREG(regs, RBP, sc, bp); - GETREG(regs, RBX, sc, bx); - GETREG(regs, RDX, sc, dx); - GETREG(regs, RAX, sc, ax); - GETREG(regs, RCX, sc, cx); - GETREG(regs, RSP, sc, sp); - GETREG(regs, RIP, sc, ip); - GETREG(regs, EFLAGS, sc, flags); - GETREG(regs, CS, sc, cs); - -#undef GETREG -} - -static int copy_sc_from_user(struct pt_regs *regs, - struct sigcontext __user *from, - struct _fpstate __user *fpp) -{ - struct user_i387_struct fp; - int err = 0; - -#define GETREG(regs, regno, sc, regname) \ - __get_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ - &(sc)->regname) - - err |= GETREG(regs, R8, from, r8); - err |= GETREG(regs, R9, from, r9); - err |= GETREG(regs, R10, from, r10); - err |= GETREG(regs, R11, from, r11); - err |= GETREG(regs, R12, from, r12); - err |= GETREG(regs, R13, from, r13); - err |= GETREG(regs, R14, from, r14); - err |= GETREG(regs, R15, from, r15); - err |= GETREG(regs, RDI, from, di); - err |= GETREG(regs, RSI, from, si); - err |= GETREG(regs, RBP, from, bp); - err |= GETREG(regs, RBX, from, bx); - err |= GETREG(regs, RDX, from, dx); - err |= GETREG(regs, RAX, from, ax); - err |= GETREG(regs, RCX, from, cx); - err |= GETREG(regs, RSP, from, sp); - err |= GETREG(regs, RIP, from, ip); - err |= GETREG(regs, EFLAGS, from, flags); - err |= GETREG(regs, CS, from, cs); - if (err) - return 1; - -#undef GETREG - - err = copy_from_user(&fp, fpp, sizeof(struct user_i387_struct)); - if (err) - return 1; - - err = restore_fp_registers(userspace_pid[current_thread_info()->cpu], - (unsigned long *) &fp); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - " - "restore_fp_registers failed, errno = %d\n", - -err); - return 1; - } - - return 0; -} - -static int copy_sc_to_user(struct sigcontext __user *to, - struct _fpstate __user *to_fp, struct pt_regs *regs, - unsigned long mask, unsigned long sp) -{ - struct faultinfo * fi = ¤t->thread.arch.faultinfo; - struct user_i387_struct fp; - int err = 0; - - err |= __put_user(0, &to->gs); - err |= __put_user(0, &to->fs); - -#define PUTREG(regs, regno, sc, regname) \ - __put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)], \ - &(sc)->regname) - - err |= PUTREG(regs, RDI, to, di); - err |= PUTREG(regs, RSI, to, si); - err |= PUTREG(regs, RBP, to, bp); - /* - * Must use original RSP, which is passed in, rather than what's in - * the pt_regs, because that's already been updated to point at the - * signal frame. - */ - err |= __put_user(sp, &to->sp); - err |= PUTREG(regs, RBX, to, bx); - err |= PUTREG(regs, RDX, to, dx); - err |= PUTREG(regs, RCX, to, cx); - err |= PUTREG(regs, RAX, to, ax); - err |= PUTREG(regs, R8, to, r8); - err |= PUTREG(regs, R9, to, r9); - err |= PUTREG(regs, R10, to, r10); - err |= PUTREG(regs, R11, to, r11); - err |= PUTREG(regs, R12, to, r12); - err |= PUTREG(regs, R13, to, r13); - err |= PUTREG(regs, R14, to, r14); - err |= PUTREG(regs, R15, to, r15); - err |= PUTREG(regs, CS, to, cs); /* XXX x86_64 doesn't do this */ - - err |= __put_user(fi->cr2, &to->cr2); - err |= __put_user(fi->error_code, &to->err); - err |= __put_user(fi->trap_no, &to->trapno); - - err |= PUTREG(regs, RIP, to, ip); - err |= PUTREG(regs, EFLAGS, to, flags); -#undef PUTREG - - err |= __put_user(mask, &to->oldmask); - if (err) - return 1; - - err = save_fp_registers(userspace_pid[current_thread_info()->cpu], - (unsigned long *) &fp); - if (err < 0) { - printk(KERN_ERR "copy_sc_from_user - restore_fp_registers " - "failed, errno = %d\n", -err); - return 1; - } - - if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct))) - return 1; - - return err; -} - -struct rt_sigframe -{ - char __user *pretcode; - struct ucontext uc; - struct siginfo info; - struct _fpstate fpstate; -}; - -int setup_signal_stack_si(unsigned long stack_top, int sig, - struct k_sigaction *ka, struct pt_regs * regs, - siginfo_t *info, sigset_t *set) -{ - struct rt_sigframe __user *frame; - unsigned long save_sp = PT_REGS_RSP(regs); - int err = 0; - struct task_struct *me = current; - - frame = (struct rt_sigframe __user *) - round_down(stack_top - sizeof(struct rt_sigframe), 16); - /* Subtract 128 for a red zone and 8 for proper alignment */ - frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto out; - - if (ka->sa.sa_flags & SA_SIGINFO) { - err |= copy_siginfo_to_user(&frame->info, info); - if (err) - goto out; - } - - /* - * Update SP now because the page fault handler refuses to extend - * the stack if the faulting address is too far below the current - * SP, which frame now certainly is. If there's an error, the original - * value is restored on the way out. - * When writing the sigcontext to the stack, we have to write the - * original value, so that's passed to copy_sc_to_user, which does - * the right thing with it. - */ - PT_REGS_RSP(regs) = (unsigned long) frame; - - /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(save_sp), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs, - set->sig[0], save_sp); - err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate); - if (sizeof(*set) == 16) { - __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); - __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); - } - else - err |= __copy_to_user(&frame->uc.uc_sigmask, set, - sizeof(*set)); - - /* - * Set up to return from userspace. If provided, use a stub - * already in userspace. - */ - /* x86-64 should always use SA_RESTORER. */ - if (ka->sa.sa_flags & SA_RESTORER) - err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); - else - /* could use a vstub here */ - goto restore_sp; - - if (err) - goto restore_sp; - - /* Set up registers for signal handler */ - { - struct exec_domain *ed = current_thread_info()->exec_domain; - if (unlikely(ed && ed->signal_invmap && sig < 32)) - sig = ed->signal_invmap[sig]; - } - - PT_REGS_RDI(regs) = sig; - /* In case the signal handler was declared without prototypes */ - PT_REGS_RAX(regs) = 0; - - /* - * This also works for non SA_SIGINFO handlers because they expect the - * next argument after the signal number on the stack. - */ - PT_REGS_RSI(regs) = (unsigned long) &frame->info; - PT_REGS_RDX(regs) = (unsigned long) &frame->uc; - PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; - out: - return err; - -restore_sp: - PT_REGS_RSP(regs) = save_sp; - return err; -} - -long sys_rt_sigreturn(struct pt_regs *regs) -{ - unsigned long sp = PT_REGS_SP(¤t->thread.regs); - struct rt_sigframe __user *frame = - (struct rt_sigframe __user *)(sp - 8); - struct ucontext __user *uc = &frame->uc; - sigset_t set; - - if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) - goto segfault; - - sigdelsetmask(&set, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, - &frame->fpstate)) - goto segfault; - - /* Avoid ERESTART handling */ - PT_REGS_SYSCALL_NR(¤t->thread.regs) = -1; - return PT_REGS_SYSCALL_RET(¤t->thread.regs); - - segfault: - force_sig(SIGSEGV, current); - return 0; -} diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S deleted file mode 100644 index 20e4a96a6dc..00000000000 --- a/arch/um/sys-x86_64/stub.S +++ /dev/null @@ -1,66 +0,0 @@ -#include "as-layout.h" - - .globl syscall_stub -.section .__syscall_stub, "ax" -syscall_stub: - syscall - /* We don't have 64-bit constants, so this constructs the address - * we need. - */ - movq $(STUB_DATA >> 32), %rbx - salq $32, %rbx - movq $(STUB_DATA & 0xffffffff), %rcx - or %rcx, %rbx - movq %rax, (%rbx) - int3 - - .globl batch_syscall_stub -batch_syscall_stub: - mov $(STUB_DATA >> 32), %rbx - sal $32, %rbx - mov $(STUB_DATA & 0xffffffff), %rax - or %rax, %rbx - /* load pointer to first operation */ - mov %rbx, %rsp - add $0x10, %rsp -again: - /* load length of additional data */ - mov 0x0(%rsp), %rax - - /* if(length == 0) : end of list */ - /* write possible 0 to header */ - mov %rax, 8(%rbx) - cmp $0, %rax - jz done - - /* save current pointer */ - mov %rsp, 8(%rbx) - - /* skip additional data */ - add %rax, %rsp - - /* load syscall-# */ - pop %rax - - /* load syscall params */ - pop %rdi - pop %rsi - pop %rdx - pop %r10 - pop %r8 - pop %r9 - - /* execute syscall */ - syscall - - /* check return value */ - pop %rcx - cmp %rcx, %rax - je again - -done: - /* save return value */ - mov %rax, (%rbx) - - /* stop */ - int3 diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c deleted file mode 100644 index ced051afc70..00000000000 --- a/arch/um/sys-x86_64/stub_segv.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include <signal.h> -#include "as-layout.h" -#include "sysdep/stub.h" -#include "sysdep/faultinfo.h" -#include "sysdep/sigcontext.h" - -void __attribute__ ((__section__ (".__syscall_stub"))) -stub_segv_handler(int sig) -{ - struct ucontext *uc; - - __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :); - GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), - &uc->uc_mcontext); - trap_myself(); -} - diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c deleted file mode 100644 index 47d469e7e7c..00000000000 --- a/arch/um/sys-x86_64/syscall_table.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c - * with some changes for UML. - */ - -#include <linux/linkage.h> -#include <linux/sys.h> -#include <linux/cache.h> -#include <kern_constants.h> - -#define __NO_STUBS - -/* - * Below you can see, in terms of #define's, the differences between the x86-64 - * and the UML syscall table. - */ - -/* Not going to be implemented by UML, since we have no hardware. */ -#define stub_iopl sys_ni_syscall -#define sys_ioperm sys_ni_syscall - -/* - * The UML TLS problem. Note that x86_64 does not implement this, so the below - * is needed only for the ia32 compatibility. - */ - -/* On UML we call it this way ("old" means it's not mmap2) */ -#define sys_mmap old_mmap - -#define stub_clone sys_clone -#define stub_fork sys_fork -#define stub_vfork sys_vfork -#define stub_execve sys_execve -#define stub_rt_sigsuspend sys_rt_sigsuspend -#define stub_sigaltstack sys_sigaltstack -#define stub_rt_sigreturn sys_rt_sigreturn - -#define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; -#undef _ASM_X86_UNISTD_64_H -#include "../../x86/include/asm/unistd_64.h" - -#undef __SYSCALL -#define __SYSCALL(nr, sym) [ nr ] = sym, -#undef _ASM_X86_UNISTD_64_H - -typedef void (*sys_call_ptr_t)(void); - -extern void sys_ni_syscall(void); - -/* - * We used to have a trick here which made sure that holes in the - * x86_64 table were filled in with sys_ni_syscall, but a comment in - * unistd_64.h says that holes aren't allowed, so the trick was - * removed. - * The trick looked like this - * [0 ... UM_NR_syscall_max] = &sys_ni_syscall - * before including unistd_64.h - the later initializations overwrote - * the sys_ni_syscall filler. - */ - -sys_call_ptr_t sys_call_table[] __cacheline_aligned = { -#include "../../x86/include/asm/unistd_64.h" -}; - -int syscall_table_size = sizeof(sys_call_table); diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c deleted file mode 100644 index f3d82bb6e15..00000000000 --- a/arch/um/sys-x86_64/syscalls.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include "linux/linkage.h" -#include "linux/personality.h" -#include "linux/utsname.h" -#include "asm/prctl.h" /* XXX This should get the constants from libc */ -#include "asm/uaccess.h" -#include "os.h" - -long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) -{ - unsigned long *ptr = addr, tmp; - long ret; - int pid = task->mm->context.id.u.pid; - - /* - * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to - * be safe), we need to call arch_prctl on the host because - * setting %fs may result in something else happening (like a - * GDT or thread.fs being set instead). So, we let the host - * fiddle the registers and thread struct and restore the - * registers afterwards. - * - * So, the saved registers are stored to the process (this - * needed because a stub may have been the last thing to run), - * arch_prctl is run on the host, then the registers are read - * back. - */ - switch (code) { - case ARCH_SET_FS: - case ARCH_SET_GS: - ret = restore_registers(pid, ¤t->thread.regs.regs); - if (ret) - return ret; - break; - case ARCH_GET_FS: - case ARCH_GET_GS: - /* - * With these two, we read to a local pointer and - * put_user it to the userspace pointer that we were - * given. If addr isn't valid (because it hasn't been - * faulted in or is just bogus), we want put_user to - * fault it in (or return -EFAULT) instead of having - * the host return -EFAULT. - */ - ptr = &tmp; - } - - ret = os_arch_prctl(pid, code, ptr); - if (ret) - return ret; - - switch (code) { - case ARCH_SET_FS: - current->thread.arch.fs = (unsigned long) ptr; - ret = save_registers(pid, ¤t->thread.regs.regs); - break; - case ARCH_SET_GS: - ret = save_registers(pid, ¤t->thread.regs.regs); - break; - case ARCH_GET_FS: - ret = put_user(tmp, addr); - break; - case ARCH_GET_GS: - ret = put_user(tmp, addr); - break; - } - - return ret; -} - -long sys_arch_prctl(int code, unsigned long addr) -{ - return arch_prctl(current, code, (unsigned long __user *) addr); -} - -long sys_clone(unsigned long clone_flags, unsigned long newsp, - void __user *parent_tid, void __user *child_tid) -{ - long ret; - - if (!newsp) - newsp = UPT_SP(¤t->thread.regs.regs); - current->thread.forking = 1; - ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, - child_tid); - current->thread.forking = 0; - return ret; -} - -void arch_switch_to(struct task_struct *to) -{ - if ((to->thread.arch.fs == 0) || (to->mm == NULL)) - return; - - arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs); -} diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c deleted file mode 100644 index f4f82beb350..00000000000 --- a/arch/um/sys-x86_64/sysrq.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/utsname.h> -#include <asm/current.h> -#include <asm/ptrace.h> -#include "sysrq.h" - -void __show_regs(struct pt_regs *regs) -{ - printk("\n"); - print_modules(); - printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current), - current->comm, print_tainted(), init_utsname()->release); - printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff, - PT_REGS_RIP(regs)); - printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_RSP(regs), - PT_REGS_EFLAGS(regs)); - printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", - PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs)); - printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n", - PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs)); - printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n", - PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs)); - printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n", - PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs)); - printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n", - PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs)); -} - -void show_regs(struct pt_regs *regs) -{ - __show_regs(regs); - show_trace(current, (unsigned long *) ®s); -} diff --git a/arch/um/sys-x86_64/tls.c b/arch/um/sys-x86_64/tls.c deleted file mode 100644 index f7ba46200ec..00000000000 --- a/arch/um/sys-x86_64/tls.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "linux/sched.h" - -void clear_flushed_tls(struct task_struct *task) -{ -} - -int arch_copy_tls(struct task_struct *t) -{ - /* - * If CLONE_SETTLS is set, we need to save the thread id - * (which is argument 5, child_tid, of clone) so it can be set - * during context switches. - */ - t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)]; - - return 0; -} diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c deleted file mode 100644 index 973585414a6..00000000000 --- a/arch/um/sys-x86_64/user-offsets.c +++ /dev/null @@ -1,65 +0,0 @@ -#include <stdio.h> -#include <stddef.h> -#include <signal.h> -#include <sys/poll.h> -#include <sys/mman.h> -#include <sys/user.h> -#define __FRAME_OFFSETS -#include <asm/ptrace.h> -#include <asm/types.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define DEFINE_LONGS(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val/sizeof(unsigned long))) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - -void foo(void) -{ - OFFSET(HOST_SC_CR2, sigcontext, cr2); - OFFSET(HOST_SC_ERR, sigcontext, err); - OFFSET(HOST_SC_TRAPNO, sigcontext, trapno); - - DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); - DEFINE_LONGS(HOST_RBX, RBX); - DEFINE_LONGS(HOST_RCX, RCX); - DEFINE_LONGS(HOST_RDI, RDI); - DEFINE_LONGS(HOST_RSI, RSI); - DEFINE_LONGS(HOST_RDX, RDX); - DEFINE_LONGS(HOST_RBP, RBP); - DEFINE_LONGS(HOST_RAX, RAX); - DEFINE_LONGS(HOST_R8, R8); - DEFINE_LONGS(HOST_R9, R9); - DEFINE_LONGS(HOST_R10, R10); - DEFINE_LONGS(HOST_R11, R11); - DEFINE_LONGS(HOST_R12, R12); - DEFINE_LONGS(HOST_R13, R13); - DEFINE_LONGS(HOST_R14, R14); - DEFINE_LONGS(HOST_R15, R15); - DEFINE_LONGS(HOST_ORIG_RAX, ORIG_RAX); - DEFINE_LONGS(HOST_CS, CS); - DEFINE_LONGS(HOST_SS, SS); - DEFINE_LONGS(HOST_EFLAGS, EFLAGS); -#if 0 - DEFINE_LONGS(HOST_FS, FS); - DEFINE_LONGS(HOST_GS, GS); - DEFINE_LONGS(HOST_DS, DS); - DEFINE_LONGS(HOST_ES, ES); -#endif - - DEFINE_LONGS(HOST_IP, RIP); - DEFINE_LONGS(HOST_SP, RSP); - DEFINE(UM_FRAME_SIZE, sizeof(struct user_regs_struct)); - - /* XXX Duplicated between i386 and x86_64 */ - DEFINE(UM_POLLIN, POLLIN); - DEFINE(UM_POLLPRI, POLLPRI); - DEFINE(UM_POLLOUT, POLLOUT); - - DEFINE(UM_PROT_READ, PROT_READ); - DEFINE(UM_PROT_WRITE, PROT_WRITE); - DEFINE(UM_PROT_EXEC, PROT_EXEC); -} |
