config NET
bool "Networking support"
+ help
+ Unless you really know what you are doing, you should say Y here.
+ The reason is that some programs need kernel networking support even
+ when running on a stand-alone machine that isn't connected to any
+ other computer. If you are upgrading from an older kernel, you
+ should consider updating your networking tools too because changes
+ in the kernel and the tools often go hand in hand. The tools are
+ contained in the package net-tools, the location and version number
+ of which are given in Documentation/Changes.
+
+ For a general introduction to Linux networking, it is highly
+ recommended to read the NET-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
source "fs/Kconfig.binfmt"
If you'd like to be able to work with files stored on the host,
say Y or M here; otherwise say N.
+config HPPFS
+ tristate "HoneyPot ProcFS"
+ help
+ hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
+ entries to be overridden, removed, or fabricated from the host.
+ Its purpose is to allow a UML to appear to be a physical machine
+ by removing or changing anything in /proc which gives away the
+ identity of a UML.
+
+ See http://user-mode-linux.sf.net/hppfs.html for more information.
+
+ You only need this if you are setting up a UML honeypot. Otherwise,
+ it is safe to say 'N' here.
config MCONSOLE
bool "Management console"
config MAGIC_SYSRQ
bool "Magic SysRq key"
depends on MCONSOLE
+ help
+ If you say Y here, you will have some control over the system even
+ if the system crashes for example during kernel debugging (e.g., you
+ will be able to flush the buffer cache to disk, reboot the system
+ immediately or dump some status information). This is accomplished
+ by pressing various keys while holding SysRq (Alt+PrintScreen). It
+ also works on a serial console (on PC hardware at least), if you
+ send a BREAK and then within 5 seconds a command keypress. The
+ keys are documented in Documentation/sysrq.txt. Don't say Y
+ unless you really know what this hack does.
config HOST_2G_2G
bool "2G/2G host address space split"
config HIGHMEM
bool "Highmem support"
+config PROC_MM
+ bool "/proc/mm support"
+
config KERNEL_STACK_ORDER
int "Kernel stack size order"
default 2
be 1 << order pages. The default is OK unless you're running Valgrind
on UML, in which case, set this to 3.
+config UML_REAL_TIME_CLOCK
+ bool "Real-time Clock"
+ default y
+ help
+ This option makes UML time deltas match wall clock deltas. This should
+ normally be enabled. The exception would be if you are debugging with
+ UML and spend long times with UML stopped at a breakpoint. In this
+ case, when UML is restarted, it will call the timer enough times to make
+ up for the time spent at the breakpoint. This could result in a
+ noticable lag. If this is a problem, then disable this option.
+
endmenu
source "init/Kconfig"
config PT_PROXY
bool "Enable ptrace proxy"
depends on XTERM_CHAN && DEBUG_INFO
+ help
+ This option enables a debugging interface which allows gdb to debug
+ the kernel without needing to actually attach to kernel threads.
+ If you want to do kernel debugging, say Y here; otherwise say N.
config GPROF
bool "Enable gprof support"
wise choice too. In all other cases (for example, if you're just
playing around with User-Mode Linux) you can choose N.
+# Turn this back on when the driver actually works
+#
+#config BLK_DEV_COW
+# tristate "COW block device"
+# help
+# This is a layered driver which sits above two other block devices.
+# One is read-only, and the other is a read-write layer which stores
+# all changes. This provides the illusion that the read-only layer
+# can be mounted read-write and changed.
+
+config BLK_DEV_COW_COMMON
+ bool
+ default BLK_DEV_COW || BLK_DEV_UBD
+
config BLK_DEV_LOOP
tristate "Loopback device support"
-menu "Network Devices"
+menu "UML Network Devices"
depends on NET
# UML virtual driver
Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
-
-# Below are hardware-independent drivers mirrored from
-# drivers/net/Config.in. It would be nice if Linux
-# had HW independent drivers separated from the other
-# but it does not. Until then each non-ISA/PCI arch
-# needs to provide it's own menu of network drivers
-config DUMMY
- tristate "Dummy net driver support"
-
-config BONDING
- tristate "Bonding driver support"
-
-config EQUALIZER
- tristate "EQL (serial line load balancing) support"
-
-config TUN
- tristate "Universal TUN/TAP device driver support"
-
-config ETHERTAP
- tristate "Ethertap network tap (OBSOLETE)"
- depends on EXPERIMENTAL && NETLINK
-
-config PPP
- tristate "PPP (point-to-point protocol) support"
-
-config PPP_MULTILINK
- bool "PPP multilink support (EXPERIMENTAL)"
- depends on PPP && EXPERIMENTAL
-
-config PPP_FILTER
- bool "PPP filtering"
- depends on PPP && FILTER
-
-config PPP_ASYNC
- tristate "PPP support for async serial ports"
- depends on PPP
-
-config PPP_SYNC_TTY
- tristate "PPP support for sync tty ports"
- depends on PPP
-
-config PPP_DEFLATE
- tristate "PPP Deflate compression"
- depends on PPP
-
-config PPP_BSDCOMP
- tristate "PPP BSD-Compress compression"
- depends on PPP
-
-config PPPOE
- tristate "PPP over Ethernet (EXPERIMENTAL)"
- depends on PPP && EXPERIMENTAL
-
-config SLIP
- tristate "SLIP (serial line) support"
-
-config SLIP_COMPRESSED
- bool "CSLIP compressed headers"
- depends on SLIP=y
-
-config SLIP_SMART
- bool "Keepalive and linefill"
- depends on SLIP=y
-
-config SLIP_MODE_SLIP6
- bool "Six bit SLIP encapsulation"
- depends on SLIP=y
-
endmenu
$(ARCH_DIR)/sys-$(SUBARCH)/
# Have to precede the include because the included Makefiles reference them.
-SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
- include/asm-um/sigcontext.h include/asm-um/processor.h \
- include/asm-um/ptrace.h include/asm-um/arch-signal.h
+SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \
+ arch-signal.h module.h
+SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header))
ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
$(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
-include $(ARCH_DIR)/Makefile-$(SUBARCH)
-include $(ARCH_DIR)/Makefile-os-$(OS)
+# This target adds dependencies to "prepare". They are defined in the included
+# Makefiles (see Makefile-i386).
+
+.PHONY: sys_prepare
+sys_prepare:
+ @:
MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt
MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas
include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y))
endif
+include $(ARCH_DIR)/Makefile-$(SUBARCH)
+include $(ARCH_DIR)/Makefile-os-$(OS)
+
EXTRAVERSION := $(EXTRAVERSION)-1um
ARCH_INCLUDE = -I$(ARCH_DIR)/include
CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
- $(MODE_INCLUDE)
+ -Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
+# These are needed for clean and mrproper, since in that case .config is not
+# included; the values here are meaningless
+
+CONFIG_NEST_LEVEL ?= 0
+CONFIG_KERNEL_HALF_GIGS ?= 0
+
SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000)
ifeq ($(CONFIG_MODE_SKAS), y)
-$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+$(SYS_HEADERS) : $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
endif
include/linux/version.h: arch/$(ARCH)/Makefile
CONFIG_KERNEL_STACK_ORDER ?= 2
STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] )
-AFLAGS_vmlinux.lds.o = -U$(SUBARCH) \
+AFLAGS_vmlinux.lds.o = $(shell echo -U$(SUBARCH) \
-DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \
-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \
- -DKERNEL_STACK_SIZE=$(STACK_SIZE)
+ -DKERNEL_STACK_SIZE=$(STACK_SIZE))
-AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
+export AFLAGS_$(LD_SCRIPT-y:.s=).o = $(AFLAGS_vmlinux.lds.o) -P -C -Uum
LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y)
-$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
- $(call if_changed_dep,as_s_S)
+#$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE
+# $(call if_changed_dep,as_s_S)
linux: vmlinux $(LD_SCRIPT-y)
$(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \
USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
+USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS))
USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
$(MODE_INCLUDE)
# To get a definition of F_SETSIG
USER_CFLAGS += -D_GNU_SOURCE
+# From main Makefile, these options are set after including the ARCH makefile.
+# So copy them here.
+
+ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
+USER_CFLAGS += -Os
+else
+USER_CFLAGS += -O2
+endif
+
+ifndef CONFIG_FRAME_POINTER
+USER_CFLAGS += -fomit-frame-pointer
+endif
+
+ifdef CONFIG_DEBUG_INFO
+USER_CFLAGS += -g
+endif
+
CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds.s \
- $(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS)
+ $(ARCH_DIR)/dyn_link.ld.s $(ARCH_DIR)/include/uml-config.h \
+ $(GEN_HEADERS)
-$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
- $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \
+ $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
+
+$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c sys_prepare
+ @ echo ' MAIN $@'
+ @ $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
archmrproper:
- for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
- do \
- $(MAKE) -C $$d archmrproper; \
- done
- rm -f $(CLEAN_FILES) $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \
- $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS))
-
-archclean: sysclean
- for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \
- do \
- $(MAKE) -C $$d clean; \
- done
- find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
- -o -name '*.gcov' \) -type f -print | xargs rm -f
- rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
+ @:
-archdep:
- for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done
+archclean:
+ @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
+ -o -name '*.gcov' \) -type f -print | xargs rm -f
$(SYMLINK_HEADERS):
cd $(TOPDIR)/$(dir $@) ; \
$(ARCH_DIR)/os:
cd $(ARCH_DIR) && ln -sf os-$(OS) os
-$(ARCH_DIR)/include/uml-config.h :
- sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@
+# Generated files
+define filechk_umlconfig
+ sed 's/ CONFIG/ UML_CONFIG/'
+endef
+
+$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h
+ $(call filechk,umlconfig)
+
+filechk_gen_header = $<
$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
- $< > $@
+ $(call filechk,gen_header)
$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
- $< > $@
+ $(call filechk,gen_header)
-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
- $(ARCH_DIR)/util FORCE ;
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util \
+ sys_prepare FORCE ;
$(ARCH_DIR)/util: FORCE
- @$(call descend,$@,)
+ $(Q)$(MAKE) $(build)=$@
-export SUBARCH USER_CFLAGS OS
+export SUBARCH USER_CFLAGS OS
SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h
+sys_prepare: $(SYS_DIR)/sc.h
+
prepare: $(SYS_HEADERS)
+filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc
+
$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
- $< > $@
+ $(call filechk,$@)
+
+filechk_$(SYS_DIR)/thread.h := $(SYS_UTIL_DIR)/mk_thread
$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
- $< > $@
+ $(call filechk,$@)
-$(SYS_UTIL_DIR)/mk_sc: FORCE ;
- @$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_sc: scripts/basic/fixdep include/config/MARKER FORCE ;
+ $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
-$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ;
- @$(call descend,$(SYS_UTIL_DIR),$@)
+$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) sys_prepare FORCE ;
+ $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@
$(SYS_UTIL_DIR): include/asm FORCE
- @$(call descend,$@,)
+ $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR)
-sysclean :
- rm -f $(SYS_HEADERS)
+CLEAN_FILES += $(SYS_HEADERS)
LINK_SKAS = -Wl,-rpath,/lib
LD_SCRIPT_SKAS = dyn.lds.s
-GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+GEN_HEADERS += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h
-$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
- $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
+$(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h :
+ $(Q)$(MAKE) $(build)=$(ARCH_DIR)/kernel/skas $@
CONFIG_EXT2_FS=y
CONFIG_SYSV_FS=m
CONFIG_UDF_FS=m
-# CONFIG_UDF_RW is not set
CONFIG_UFS_FS=m
# CONFIG_UFS_FS_WRITE is not set
#
CONFIG_USERMODE=y
CONFIG_MMU=y
-CONFIG_SWAP=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_CONFIG_LOG_BUF_SHIFT=14
#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General Setup
+# UML-specific options
#
CONFIG_MODE_TT=y
CONFIG_MODE_SKAS=y
CONFIG_NET=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SYSCTL=y
-CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=y
CONFIG_HOSTFS=y
+CONFIG_HPPFS=y
CONFIG_MCONSOLE=y
CONFIG_MAGIC_SYSRQ=y
# CONFIG_HOST_2G_2G is not set
# CONFIG_HIGHMEM is not set
CONFIG_PROC_MM=y
CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_UML_REAL_TIME_CLOCK=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_SYSCTL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
#
# Loadable module support
#
-CONFIG_MODULES=y
-# CONFIG_KMOD is not set
+# CONFIG_MODULES is not set
+
+#
+# Generic Driver Options
+#
#
# Character Devices
#
CONFIG_BLK_DEV_UBD=y
# CONFIG_BLK_DEV_UBD_SYNC is not set
+CONFIG_BLK_DEV_COW_COMMON=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y
CONFIG_NETDEVICES=y
#
-# Network Devices
+# UML Network Devices
#
CONFIG_UML_NET=y
CONFIG_UML_NET_ETHERTAP=y
CONFIG_UML_NET_MCAST=y
# CONFIG_UML_NET_PCAP is not set
CONFIG_UML_NET_SLIRP=y
-CONFIG_DUMMY=y
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=y
-# CONFIG_ETHERTAP is not set
-CONFIG_PPP=y
-# CONFIG_PPP_MULTILINK 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_PPPOE is not set
-CONFIG_SLIP=y
-# CONFIG_SLIP_COMPRESSED is not set
-# CONFIG_SLIP_SMART is not set
-# CONFIG_SLIP_MODE_SLIP6 is not set
#
# Networking support
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
# CONFIG_SYN_COOKIES is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
-# CONFIG_XFRM_USER is not set
+# CONFIG_INET_IPCOMP is not set
# CONFIG_IPV6 is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE 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_NET_DIVERT is not set
# Network testing
#
# CONFIG_NET_PKTGEN is not set
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=y
#
# Ethernet (10 or 100Mbit)
# Ethernet (1000 Mbit)
#
+#
+# Ethernet (10000 Mbit)
+#
+CONFIG_PPP=y
+# 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_PPPOE is not set
+CONFIG_SLIP=y
+# CONFIG_SLIP_COMPRESSED is not set
+# CONFIG_SLIP_SMART is not set
+# CONFIG_SLIP_MODE_SLIP6 is not set
+
#
# Wireless LAN (non-hamradio)
#
# CONFIG_NET_RADIO is not set
#
-# Token Ring devices (depends on LLC=y)
+# Token Ring devices
#
# CONFIG_SHAPER is not set
#
# CONFIG_WAN is not set
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# Bluetooth support
+#
+# CONFIG_BT is not set
+
#
# File systems
#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_ROMFS_FS is not set
CONFIG_QUOTA=y
# CONFIG_QFMT_V1 is not set
# CONFIG_QFMT_V2 is not set
CONFIG_QUOTACTL=y
-CONFIG_AUTOFS_FS=m
-CONFIG_AUTOFS4_FS=m
-CONFIG_REISERFS_FS=m
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_EXT3_FS is not set
-# CONFIG_JBD is not set
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
# CONFIG_EFS_FS is not set
CONFIG_JFFS_FS=y
CONFIG_JFFS_FS_VERBOSE=0
-CONFIG_JFFS_PROC_FS=y
# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-CONFIG_ISO9660_FS=m
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_MINIX_FS=m
# CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
# CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-CONFIG_DEVFS_MOUNT=y
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
# CONFIG_UFS_FS is not set
-# CONFIG_XFS_FS is not set
#
# Network File Systems
#
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
# CONFIG_NFS_FS is not set
# CONFIG_NFSD is not set
# CONFIG_EXPORTFS is not set
-# CONFIG_CIFS 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
#
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-CONFIG_NLS=y
#
# Native Language Support
#
+CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
# CONFIG_NLS_CODEPAGE_737 is not set
#
# SCSI support
#
-CONFIG_SCSI=y
-CONFIG_GENERIC_ISA_DMA=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
-CONFIG_CHR_DEV_ST=y
-CONFIG_BLK_DEV_SR=y
-CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_DEBUG_QUEUES=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-CONFIG_SCSI_DEBUG=y
+# CONFIG_SCSI is not set
#
# Multi-device support (RAID and LVM)
CONFIG_MTD_BLOCK=y
# CONFIG_FTL is not set
# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
#
# RAM/ROM/Flash chip drivers
#
# Mapping drivers for chip access
#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_MTDRAM is not set
-CONFIG_MTD_BLKMTD=m
+CONFIG_MTD_BLKMTD=y
#
# Disk-On-Chip Device Drivers
#
-# CONFIG_MTD_DOC1000 is not set
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
#
-# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
obj-$(CONFIG_TTY_CHAN) += tty.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
obj-$(CONFIG_UML_WATCHDOG) += harddog.o
+obj-$(CONFIG_BLK_DEV_COW) += cow_kern.o
+obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
obj-y += stdio_console.o $(CHAN_OBJS)
USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
null.o pty.o tty.o xterm.o
-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
-
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/tty.h>
+#include <linux/string.h>
#include <linux/tty_flip.h>
#include <asm/irq.h>
#include "chan_kern.h"
{
int n = 0;
+ if(chan == NULL){
+ CONFIG_CHUNK(str, size, n, "none", 1);
+ return(n);
+ }
+
CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
if(chan->dev == NULL){
INIT_LIST_HEAD(chans);
}
- if((out = strchr(str, ',')) != NULL){
+ out = strchr(str, ',');
+ if(out != NULL){
in = str;
*out = '\0';
out++;
goto out;
}
err = chan->ops->read(chan->fd, &c, chan->data);
- if(err > 0) tty_receive_char(tty, c);
+ 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);
+ if(tty != NULL)
+ tty_hangup(tty);
line_disable(dev, irq);
close_chan(chans);
free_chan(chans);
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include <stdlib.h>
#include <errno.h>
#include <termios.h>
-#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
void generic_close(int fd, void *unused)
{
- close(fd);
+ os_close_file(fd);
}
int generic_read(int fd, char *c_out, void *unused)
{
int n;
- n = read(fd, c_out, sizeof(*c_out));
- if(n < 0){
- if(errno == EAGAIN) return(0);
- return(-errno);
- }
- else if(n == 0) return(-EIO);
- return(1);
+ n = os_read_file(fd, c_out, sizeof(*c_out));
+
+ if(n == -EAGAIN)
+ return(0);
+ else if(n == 0)
+ return(-EIO);
+ return(n);
}
+/* XXX Trivial wrapper around os_write_file */
+
int generic_write(int fd, const char *buf, int n, void *unused)
{
- int count;
-
- count = write(fd, buf, n);
- if(count < 0) return(-errno);
- return(count);
+ return(os_write_file(fd, buf, n));
}
int generic_console_write(int fd, const char *buf, int n, void *unused)
int generic_window_size(int fd, void *unused, unsigned short *rows_out,
unsigned short *cols_out)
{
- struct winsize size;
- int ret = 0;
-
- if(ioctl(fd, TIOCGWINSZ, &size) == 0){
- ret = ((*rows_out != size.ws_row) ||
- (*cols_out != size.ws_col));
- *rows_out = size.ws_row;
- *cols_out = size.ws_col;
- }
+ int rows, cols;
+ int ret;
+
+ ret = os_window_size(fd, &rows, &cols);
+ if(ret < 0)
+ return(ret);
+
+ ret = ((*rows_out != rows) || (*cols_out != cols));
+
+ *rows_out = rows;
+ *cols_out = cols;
+
return(ret);
}
struct winch_data *data = arg;
sigset_t sigs;
int pty_fd, pipe_fd;
+ int count, err;
char c = 1;
- close(data->close_me);
+ os_close_file(data->close_me);
pty_fd = data->pty_fd;
pipe_fd = data->pipe_fd;
- if(write(pipe_fd, &c, sizeof(c)) != sizeof(c))
+ count = os_write_file(pipe_fd, &c, sizeof(c));
+ if(count != sizeof(c))
printk("winch_thread : failed to write synchronization "
- "byte, errno = %d\n", errno);
+ "byte, err = %d\n", -count);
signal(SIGWINCH, winch_handler);
sigfillset(&sigs);
exit(1);
}
- if(ioctl(pty_fd, TIOCSCTTY, 0) < 0){
- printk("winch_thread : TIOCSCTTY failed, errno = %d\n", errno);
- exit(1);
- }
- if(tcsetpgrp(pty_fd, os_getpid()) < 0){
- printk("winch_thread : tcsetpgrp failed, errno = %d\n", errno);
+ err = os_new_tty_pgrp(pty_fd, os_getpid());
+ if(err < 0){
+ printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err);
exit(1);
}
- if(read(pipe_fd, &c, sizeof(c)) != sizeof(c))
+ count = os_read_file(pipe_fd, &c, sizeof(c));
+ if(count != sizeof(c))
printk("winch_thread : failed to read synchronization byte, "
- "errno = %d\n", errno);
+ "err = %d\n", -count);
while(1){
pause();
- if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){
- printk("winch_thread : write failed, errno = %d\n",
- errno);
- }
+ count = os_write_file(pipe_fd, &c, sizeof(c));
+ if(count != sizeof(c))
+ printk("winch_thread : write failed, err = %d\n",
+ -count);
}
}
char c;
err = os_pipe(fds, 1, 1);
- if(err){
- printk("winch_tramp : os_pipe failed, errno = %d\n", -err);
+ if(err < 0){
+ printk("winch_tramp : os_pipe failed, err = %d\n", -err);
return(err);
}
return(pid);
}
- close(fds[1]);
+ os_close_file(fds[1]);
*fd_out = fds[0];
- n = read(fds[0], &c, sizeof(c));
+ n = os_read_file(fds[0], &c, sizeof(c));
if(n != sizeof(c)){
printk("winch_tramp : failed to read synchronization byte\n");
- printk("read returned %d, errno = %d\n", n, errno);
+ printk("read failed, err = %d\n", -n);
printk("fd %d will not support SIGWINCH\n", fd);
*fd_out = -1;
}
void register_winch(int fd, void *device_data)
{
int pid, thread, thread_fd;
+ int count;
char c = 1;
- if(!isatty(fd)) return;
+ if(!isatty(fd))
+ return;
pid = tcgetpgrp(fd);
- if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) &&
- (pid == -1)){
+ if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
+ device_data) && (pid == -1)){
thread = winch_tramp(fd, device_data, &thread_fd);
if(fd != -1){
register_winch_irq(thread_fd, fd, thread, device_data);
- if(write(thread_fd, &c, sizeof(c)) != sizeof(c))
+ count = os_write_file(thread_fd, &c, sizeof(c));
+ if(count != sizeof(c))
printk("register_winch : failed to write "
- "synchronization byte\n");
+ "synchronization byte, err = %d\n",
+ -count);
}
}
}
struct request_v3 req;
int fd, n, err;
- if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
+ pri->control = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(pri->control < 0){
printk("daemon_open : control socket failed, errno = %d\n",
errno);
return(-errno);
goto out;
}
- if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){
+ fd = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if(fd < 0){
printk("daemon_open : data socket failed, errno = %d\n",
errno);
err = -errno;
req.version = SWITCH_VERSION;
req.type = REQ_NEW_CONTROL;
req.sock = *local_addr;
- n = write(pri->control, &req, sizeof(req));
+ n = os_write_file(pri->control, &req, sizeof(req));
if(n != sizeof(req)){
- printk("daemon_open : control setup request returned %d, "
- "errno = %d\n", n, errno);
+ printk("daemon_open : control setup request failed, err = %d\n",
+ -n);
err = -ENOTCONN;
goto out;
}
- n = read(pri->control, sun, sizeof(*sun));
+ n = os_read_file(pri->control, sun, sizeof(*sun));
if(n != sizeof(*sun)){
- printk("daemon_open : read of data socket returned %d, "
- "errno = %d\n", n, errno);
+ printk("daemon_open : read of data socket failed, err = %d\n",
+ -n);
err = -ENOTCONN;
goto out_close;
}
return(fd);
out_close:
- close(fd);
+ os_close_file(fd);
out:
- close(pri->control);
+ os_close_file(pri->control);
return(err);
}
{
struct daemon_data *pri = data;
- close(pri->fd);
- close(pri->control);
+ os_close_file(pri->fd);
+ os_close_file(pri->control);
if(pri->data_addr != NULL) kfree(pri->data_addr);
if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
if(pri->local_addr != NULL) kfree(pri->local_addr);
printk("fd_init : couldn't parse file descriptor '%s'\n", str);
return(NULL);
}
- if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+ data = um_kmalloc(sizeof(*data));
+ if(data == NULL) return(NULL);
*data = ((struct fd_chan) { .fd = n,
.raw = opts->raw });
return(data);
dup2(data->stdin, 0);
dup2(data->stdout, 1);
dup2(data->stdout, 2);
- close(data->stdin);
- close(data->stdout);
- close(data->close_me[0]);
- close(data->close_me[1]);
+ os_close_file(data->stdin);
+ os_close_file(data->stdout);
+ os_close_file(data->close_me[0]);
+ os_close_file(data->close_me[1]);
}
int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
char **args = NULL;
err = os_pipe(in_fds, 1, 0);
- if(err){
- printk("harddog_open - os_pipe failed, errno = %d\n", -err);
- return(err);
+ if(err < 0){
+ printk("harddog_open - os_pipe failed, err = %d\n", -err);
+ goto out;
}
err = os_pipe(out_fds, 1, 0);
- if(err){
- printk("harddog_open - os_pipe failed, errno = %d\n", -err);
- return(err);
+ if(err < 0){
+ printk("harddog_open - os_pipe failed, err = %d\n", -err);
+ goto out_close_in;
}
data.stdin = out_fds[0];
pid = run_helper(pre_exec, &data, args, NULL);
- close(out_fds[0]);
- close(in_fds[1]);
+ os_close_file(out_fds[0]);
+ os_close_file(in_fds[1]);
if(pid < 0){
err = -pid;
- printk("harddog_open - run_helper failed, errno = %d\n", err);
- goto out;
+ printk("harddog_open - run_helper failed, errno = %d\n", -err);
+ goto out_close_out;
}
- n = read(in_fds[0], &c, sizeof(c));
+ n = os_read_file(in_fds[0], &c, sizeof(c));
if(n == 0){
printk("harddog_open - EOF on watchdog pipe\n");
helper_wait(pid);
err = -EIO;
- goto out;
+ goto out_close_out;
}
else if(n < 0){
printk("harddog_open - read of watchdog pipe failed, "
- "errno = %d\n", errno);
+ "err = %d\n", -n);
helper_wait(pid);
- err = -errno;
- goto out;
+ err = n;
+ goto out_close_out;
}
*in_fd_ret = in_fds[0];
*out_fd_ret = out_fds[1];
return(0);
+
+ out_close_in:
+ os_close_file(in_fds[0]);
+ os_close_file(in_fds[1]);
+ out_close_out:
+ os_close_file(out_fds[0]);
+ os_close_file(out_fds[1]);
out:
- close(out_fds[1]);
- close(in_fds[0]);
return(err);
}
void stop_watchdog(int in_fd, int out_fd)
{
- close(in_fd);
- close(out_fd);
+ os_close_file(in_fd);
+ os_close_file(out_fd);
}
int ping_watchdog(int fd)
int n;
char c = '\n';
- n = write(fd, &c, sizeof(c));
- if(n < sizeof(c)){
- printk("ping_watchdog - write failed, errno = %d\n",
- errno);
- return(-errno);
+ n = os_write_file(fd, &c, sizeof(c));
+ if(n != sizeof(c)){
+ printk("ping_watchdog - write failed, err = %d\n", -n);
+ if(n < 0)
+ return(n);
+ return(-EIO);
}
return 1;
#include "linux/config.h"
#include "linux/module.h"
-#include "linux/version.h"
#include "linux/init.h"
#include "linux/slab.h"
#include "linux/fs.h"
#include "linux/sound.h"
#include "linux/soundcard.h"
+#include "asm/uaccess.h"
#include "kern_util.h"
#include "init.h"
#include "hostaudio.h"
char *dsp = HOSTAUDIO_DEV_DSP;
char *mixer = HOSTAUDIO_DEV_MIXER;
+#define DSP_HELP \
+" This is used to specify the host dsp device to the hostaudio driver.\n" \
+" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
+
+#define MIXER_HELP \
+" This is used to specify the host mixer device to the hostaudio driver.\n" \
+" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
+
#ifndef MODULE
static int set_dsp(char *name, int *add)
{
- dsp = uml_strdup(name);
+ dsp = name;
return(0);
}
-__uml_setup("dsp=", set_dsp,
-"dsp=<dsp device>\n"
-" This is used to specify the host dsp device to the hostaudio driver.\n"
-" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n"
-);
+__uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
static int set_mixer(char *name, int *add)
{
- mixer = uml_strdup(name);
+ mixer = name;
return(0);
}
-__uml_setup("mixer=", set_mixer,
-"mixer=<mixer device>\n"
-" This is used to specify the host mixer device to the hostaudio driver.\n"
-" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n"
-);
+__uml_setup("mixer=", set_mixer, "mixer=<mixer device>\n" MIXER_HELP);
+
+#else /*MODULE*/
+
+MODULE_PARM(dsp, "s");
+MODULE_PARM_DESC(dsp, DSP_HELP);
+
+MODULE_PARM(mixer, "s");
+MODULE_PARM_DESC(mixer, MIXER_HELP);
+
#endif
/* /dev/dsp file operations */
loff_t *ppos)
{
struct hostaudio_state *state = file->private_data;
+ void *kbuf;
+ int err;
#ifdef DEBUG
printk("hostaudio: read called, count = %d\n", count);
#endif
- return(hostaudio_read_user(state, buffer, count, ppos));
+ kbuf = kmalloc(count, GFP_KERNEL);
+ if(kbuf == NULL)
+ return(-ENOMEM);
+
+ err = hostaudio_read_user(state, kbuf, count, ppos);
+ if(err < 0)
+ goto out;
+
+ if(copy_to_user(buffer, kbuf, err))
+ err = -EFAULT;
+
+ out:
+ kfree(kbuf);
+ return(err);
}
static ssize_t hostaudio_write(struct file *file, const char *buffer,
size_t count, loff_t *ppos)
{
struct hostaudio_state *state = file->private_data;
+ void *kbuf;
+ int err;
#ifdef DEBUG
printk("hostaudio: write called, count = %d\n", count);
#endif
- return(hostaudio_write_user(state, buffer, count, ppos));
+
+ kbuf = kmalloc(count, GFP_KERNEL);
+ if(kbuf == NULL)
+ return(-ENOMEM);
+
+ err = -EFAULT;
+ if(copy_from_user(kbuf, buffer, count))
+ goto out;
+
+ err = hostaudio_write_user(state, kbuf, count, ppos);
+ if(err < 0)
+ goto out;
+
+ out:
+ kfree(kbuf);
+ return(err);
}
static unsigned int hostaudio_poll(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct hostaudio_state *state = file->private_data;
+ unsigned long data = 0;
+ int err;
#ifdef DEBUG
printk("hostaudio: ioctl called, cmd = %u\n", cmd);
#endif
-
- return(hostaudio_ioctl_user(state, cmd, arg));
+ switch(cmd){
+ case SNDCTL_DSP_SPEED:
+ case SNDCTL_DSP_STEREO:
+ case SNDCTL_DSP_GETBLKSIZE:
+ case SNDCTL_DSP_CHANNELS:
+ case SNDCTL_DSP_SUBDIVIDE:
+ case SNDCTL_DSP_SETFRAGMENT:
+ if(get_user(data, (int *) arg))
+ return(-EFAULT);
+ break;
+ default:
+ break;
+ }
+
+ err = hostaudio_ioctl_user(state, cmd, (unsigned long) &data);
+
+ switch(cmd){
+ case SNDCTL_DSP_SPEED:
+ case SNDCTL_DSP_STEREO:
+ case SNDCTL_DSP_GETBLKSIZE:
+ case SNDCTL_DSP_CHANNELS:
+ case SNDCTL_DSP_SUBDIVIDE:
+ case SNDCTL_DSP_SETFRAGMENT:
+ if(put_user(data, (int *) arg))
+ return(-EFAULT);
+ break;
+ default:
+ break;
+ }
+
+ return(err);
}
static int hostaudio_open(struct inode *inode, struct file *file)
static int __init hostaudio_init_module(void)
{
- printk(KERN_INFO "UML Audio Relay\n");
+ printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n",
+ dsp, mixer);
module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1);
if(module_data.dev_audio < 0){
*/
#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "hostaudio.h"
ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer,
size_t count, loff_t *ppos)
{
- ssize_t ret;
-
#ifdef DEBUG
printk("hostaudio: read_user called, count = %d\n", count);
#endif
- ret = read(state->fd, buffer, count);
-
- if(ret < 0) return(-errno);
- return(ret);
+ return(os_read_file(state->fd, buffer, count));
}
ssize_t hostaudio_write_user(struct hostaudio_state *state, const char *buffer,
size_t count, loff_t *ppos)
{
- ssize_t ret;
-
#ifdef DEBUG
printk("hostaudio: write_user called, count = %d\n", count);
#endif
- ret = write(state->fd, buffer, count);
-
- if(ret < 0) return(-errno);
- return(ret);
+ return(os_write_file(state->fd, buffer, count));
}
int hostaudio_ioctl_user(struct hostaudio_state *state, unsigned int cmd,
unsigned long arg)
{
- int ret;
#ifdef DEBUG
printk("hostaudio: ioctl_user called, cmd = %u\n", cmd);
#endif
- ret = ioctl(state->fd, cmd, arg);
-
- if(ret < 0) return(-errno);
- return(ret);
+ return(os_ioctl_generic(state->fd, cmd, arg));
}
int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp)
printk("hostaudio: open_user called\n");
#endif
- state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-
- if(state->fd >= 0) return(0);
+ state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
- printk("hostaudio_open_user failed to open '%s', errno = %d\n",
- dsp, errno);
+ if(state->fd < 0) {
+ printk("hostaudio_open_user failed to open '%s', err = %d\n",
+ dsp, -state->fd);
+ return(state->fd);
+ }
- return(-errno);
+ return(0);
}
int hostaudio_release_user(struct hostaudio_state *state)
#ifdef DEBUG
printk("hostaudio: release called\n");
#endif
- if(state->fd >= 0){
- close(state->fd);
- state->fd=-1;
- }
+ if(state->fd >= 0){
+ os_close_file(state->fd);
+ state->fd = -1;
+ }
return(0);
}
int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state,
unsigned int cmd, unsigned long arg)
{
- int ret;
#ifdef DEBUG
printk("hostmixer: ioctl_user called cmd = %u\n",cmd);
#endif
- ret = ioctl(state->fd, cmd, arg);
- if(ret < 0)
- return(-errno);
- return(ret);
+ return(os_ioctl_generic(state->fd, cmd, arg));
}
int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w,
state->fd = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
- if(state->fd >= 0) return(0);
-
- printk("hostaudio_open_mixdev_user failed to open '%s', errno = %d\n",
- mixer, errno);
+ if(state->fd < 0) {
+ printk("hostaudio_open_mixdev_user failed to open '%s', "
+ "err = %d\n", mixer, state->fd);
+ return(state->fd);
+ }
- return(-errno);
+ return(0);
}
int hostmixer_release_mixdev_user(struct hostmixer_state *state)
#endif
if(state->fd >= 0){
- close(state->fd);
+ os_close_file(state->fd);
state->fd = -1;
}
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/list.h"
+#include "linux/interrupt.h"
#include "linux/devfs_fs_kernel.h"
-#include "asm/irq.h"
#include "asm/uaccess.h"
#include "chan_kern.h"
#include "irq_user.h"
#include "user_util.h"
#include "kern_util.h"
#include "os.h"
+#include "irq_kern.h"
#define LINE_BUFSIZE 4096
-void line_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
{
struct line *dev = data;
if(dev->count > 0)
chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq,
dev);
+ return IRQ_HANDLED;
}
-void line_timer_cb(void *arg)
+static void line_timer_cb(void *arg)
{
struct line *dev = arg;
line_interrupt(dev->driver->read_irq, dev, NULL);
}
-static void buffer_data(struct line *line, const char *buf, int len)
+static int write_room(struct line *dev)
{
- int end;
+ int n;
+
+ if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
+
+ n = dev->head - dev->tail;
+ if(n <= 0) n = LINE_BUFSIZE + n;
+ return(n - 1);
+}
+
+static int buffer_data(struct line *line, const char *buf, int len)
+{
+ int end, room;
if(line->buffer == NULL){
line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
if(line->buffer == NULL){
printk("buffer_data - atomic allocation failed\n");
- return;
+ return(0);
}
line->head = line->buffer;
line->tail = line->buffer;
}
+
+ room = write_room(line);
+ len = (len > room) ? room : len;
+
end = line->buffer + LINE_BUFSIZE - line->tail;
if(len < end){
memcpy(line->tail, buf, len);
memcpy(line->buffer, buf, len);
line->tail = line->buffer + len;
}
+
+ return(len);
}
static int flush_buffer(struct line *line)
struct line *line;
char *new;
unsigned long flags;
- int n, err, i;
+ int n, err, i, ret = 0;
if(tty->stopped) return 0;
if(new == NULL)
return(0);
n = copy_from_user(new, buf, len);
- if(n == len)
- return(-EFAULT);
buf = new;
+ if(n == len){
+ len = -EFAULT;
+ goto out_free;
+ }
+
+ len -= n;
}
i = tty->index;
down(&line->sem);
if(line->head != line->tail){
local_irq_save(flags);
- buffer_data(line, buf, len);
+ ret += buffer_data(line, buf, len);
err = flush_buffer(line);
local_irq_restore(flags);
if(err <= 0)
- goto out;
+ goto out_up;
}
else {
n = write_chan(&line->chan_list, buf, len,
line->driver->write_irq);
if(n < 0){
- len = n;
- goto out;
+ ret = n;
+ goto out_up;
}
- if(n < len)
- buffer_data(line, buf + n, len - n);
+
+ len -= n;
+ ret += n;
+ if(len > 0)
+ ret += buffer_data(line, buf + n, len);
}
- out:
+ out_up:
up(&line->sem);
- return(len);
+ out_free:
+ if(from_user)
+ kfree(buf);
+ return(ret);
}
-void line_write_interrupt(int irq, void *data, struct pt_regs *unused)
+static irqreturn_t line_write_interrupt(int irq, void *data,
+ struct pt_regs *unused)
{
struct line *dev = data;
struct tty_struct *tty = dev->tty;
int err;
err = flush_buffer(dev);
- if(err == 0) return;
+ if(err == 0)
+ return(IRQ_NONE);
else if(err < 0){
dev->head = dev->buffer;
dev->tail = dev->buffer;
}
- if(tty == NULL) return;
+ if(tty == NULL)
+ return(IRQ_NONE);
if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
(tty->ldisc.write_wakeup != NULL))
* writes.
*/
- if (waitqueue_active(&tty->write_wait))
+ if(waitqueue_active(&tty->write_wait))
wake_up_interruptible(&tty->write_wait);
-
-}
-
-int line_write_room(struct tty_struct *tty)
-{
- struct line *dev = tty->driver_data;
- int n;
-
- if(dev->buffer == NULL) return(LINE_BUFSIZE - 1);
-
- n = dev->head - dev->tail;
- if(n <= 0) n = LINE_BUFSIZE + n;
- return(n - 1);
+ return(IRQ_HANDLED);
}
int line_setup_irq(int fd, int input, int output, void *data)
if(*end != '='){
printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
init);
- return(1);
+ return(0);
}
init = end;
}
if((n >= 0) && (n >= num)){
printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
n, num);
- return(1);
+ return(0);
}
else if(n >= 0){
if(lines[n].count > 0){
printk("line_setup - device %d is open\n", n);
- return(1);
+ return(0);
}
if(lines[n].init_pri <= INIT_ONE){
lines[n].init_pri = INIT_ONE;
else if(!all_allowed){
printk("line_setup - can't configure all devices from "
"mconsole\n");
- return(1);
+ return(0);
}
else {
for(i = 0; i < num; i++){
}
}
}
- return(0);
+ return(1);
}
int line_config(struct line *lines, int num, char *str)
printk("line_config - uml_strdup failed\n");
return(-ENOMEM);
}
- return(line_setup(lines, num, new, 0));
+ return(!line_setup(lines, num, new, 0));
}
int line_get_config(char *name, struct line *lines, int num, char *str,
dev = simple_strtoul(name, &end, 0);
if((*end != '\0') || (end == name)){
- *error_out = "line_setup failed to parse device number";
+ *error_out = "line_get_config failed to parse device number";
return(0);
}
}
line = &lines[dev];
+
down(&line->sem);
-
if(!line->valid)
CONFIG_CHUNK(str, size, n, "none", 1);
else if(line->count == 0)
CONFIG_CHUNK(str, size, n, line->init_str, 1);
else n = chan_config_string(&line->chan_list, str, size, error_out);
-
up(&line->sem);
+
return(n);
}
char config[sizeof("conxxxx=none\0")];
sprintf(config, "%s=none", str);
- return(line_setup(lines, num, config, 0));
+ return(!line_setup(lines, num, config, 0));
+}
+
+int line_write_room(struct tty_struct *tty)
+{
+ struct line *dev = tty->driver_data;
+
+ return(write_room(dev));
}
struct tty_driver *line_register_devfs(struct lines *set,
return NULL;
driver->driver_name = line_driver->name;
- driver->name = line_driver->devfs_name;
+ driver->name = line_driver->device_name;
+ driver->devfs_name = line_driver->devfs_name;
driver->major = line_driver->major;
driver->minor_start = line_driver->minor_start;
driver->type = line_driver->type;
for(i = 0; i < nlines; i++){
if(!lines[i].valid)
- tty_unregister_devfs(driver, i);
+ tty_unregister_device(driver, i);
}
mconsole_register_dev(&line_driver->mc);
struct line *line;
};
-void winch_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused)
{
struct winch *winch = data;
struct tty_struct *tty;
int err;
char c;
- err = generic_read(winch->fd, &c, NULL);
- if(err < 0){
- if(err != -EAGAIN){
- printk("winch_interrupt : read failed, errno = %d\n",
- -err);
- printk("fd %d is losing SIGWINCH support\n",
- winch->tty_fd);
- free_irq(irq, data);
- return;
+ if(winch->fd != -1){
+ err = generic_read(winch->fd, &c, NULL);
+ if(err < 0){
+ if(err != -EAGAIN){
+ printk("winch_interrupt : read failed, "
+ "errno = %d\n", -err);
+ printk("fd %d is losing SIGWINCH support\n",
+ winch->tty_fd);
+ return(IRQ_HANDLED);
+ }
+ goto out;
}
- goto out;
}
tty = winch->line->tty;
if(tty != NULL){
kill_pg(tty->pgrp, SIGWINCH, 1);
}
out:
- reactivate_fd(winch->fd, WINCH_IRQ);
+ if(winch->fd != -1)
+ reactivate_fd(winch->fd, WINCH_IRQ);
+ return(IRQ_HANDLED);
}
DECLARE_MUTEX(winch_handler_sem);
list_for_each(ele, &winch_handlers){
winch = list_entry(ele, struct winch, list);
- close(winch->fd);
+ if(winch->fd != -1){
+ deactivate_fd(winch->fd, WINCH_IRQ);
+ os_close_file(winch->fd);
+ }
if(winch->pid != -1)
os_kill_process(winch->pid, 1);
}
#include "kern_util.h"
#include "user_util.h"
#include "user.h"
+#include "os.h"
#define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER)
goto out;
}
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0){
printk("mcast_open : data socket failed, errno = %d\n",
errno);
fd = -ENOMEM;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
errno);
- close(fd);
+ os_close_file(fd);
fd = -EINVAL;
goto out;
}
sizeof(pri->ttl)) < 0) {
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
errno);
- close(fd);
+ os_close_file(fd);
fd = -EINVAL;
goto out;
}
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
errno);
- close(fd);
+ os_close_file(fd);
fd = -EINVAL;
goto out;
}
/* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
printk("mcast_open : data bind failed, errno = %d\n", errno);
- close(fd);
+ os_close_file(fd);
fd = -EINVAL;
goto out;
}
"interface on the host.\n");
printk("eth0 should be configured in order to use the "
"multicast transport.\n");
- close(fd);
+ os_close_file(fd);
fd = -EINVAL;
}
errno);
}
- close(fd);
+ os_close_file(fd);
}
int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri)
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include "linux/sysrq.h"
#include "linux/workqueue.h"
#include "linux/module.h"
+#include "linux/file.h"
+#include "linux/fs.h"
+#include "linux/namei.h"
#include "linux/proc_fs.h"
#include "asm/irq.h"
#include "asm/uaccess.h"
#include "init.h"
#include "os.h"
#include "umid.h"
+#include "irq_kern.h"
static int do_unlink_socket(struct notifier_block *notifier,
unsigned long what, void *data)
DECLARE_WORK(mconsole_work, mc_work_proc, NULL);
-void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int fd;
struct mconsole_entry *new;
fd = (int) dev_id;
while (mconsole_get_request(fd, &req)){
- if(req.cmd->as_interrupt) (*req.cmd->handler)(&req);
+ if(req.cmd->context == MCONSOLE_INTR)
+ (*req.cmd->handler)(&req);
else {
- new = kmalloc(sizeof(req), GFP_ATOMIC);
+ new = kmalloc(sizeof(*new), GFP_ATOMIC);
if(new == NULL)
mconsole_reply(&req, "Out of memory", 1, 0);
else {
}
if(!list_empty(&mc_requests)) schedule_work(&mconsole_work);
reactivate_fd(fd, MCONSOLE_IRQ);
+ return(IRQ_HANDLED);
}
void mconsole_version(struct mc_request *req)
mconsole_reply(req, version, 0, 0);
}
+void mconsole_log(struct mc_request *req)
+{
+ int len;
+ char *ptr = req->request.data;
+
+ ptr += strlen("log ");
+
+ len = req->len - (ptr - req->request.data);
+ printk("%.*s", len, ptr);
+ mconsole_reply(req, "", 0, 0);
+}
+
+void mconsole_proc(struct mc_request *req)
+{
+ struct nameidata nd;
+ struct file_system_type *proc;
+ struct super_block *super;
+ struct file *file;
+ int n, err;
+ char *ptr = req->request.data, *buf;
+
+ ptr += strlen("proc");
+ while(isspace(*ptr)) ptr++;
+
+ proc = get_fs_type("proc");
+ if(proc == NULL){
+ mconsole_reply(req, "procfs not registered", 1, 0);
+ goto out;
+ }
+
+ super = (*proc->get_sb)(proc, 0, NULL, NULL);
+ put_filesystem(proc);
+ if(super == NULL){
+ mconsole_reply(req, "Failed to get procfs superblock", 1, 0);
+ goto out;
+ }
+ up_write(&super->s_umount);
+
+ nd.dentry = super->s_root;
+ nd.mnt = NULL;
+ nd.flags = O_RDONLY + 1;
+ nd.last_type = LAST_ROOT;
+
+ err = link_path_walk(ptr, &nd);
+ if(err){
+ mconsole_reply(req, "Failed to look up file", 1, 0);
+ goto out_kill;
+ }
+
+ file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+ if(IS_ERR(file)){
+ mconsole_reply(req, "Failed to open file", 1, 0);
+ goto out_kill;
+ }
+
+ 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 != NULL) && (file->f_op->read != NULL)){
+ do {
+ n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1,
+ &file->f_pos);
+ 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_kill:
+ deactivate_super(super);
+ out: ;
+}
+
#define UML_MCONSOLE_HELPTEXT \
-"Commands:
- version - Get kernel version
- help - Print this message
- halt - Halt UML
- reboot - Reboot UML
- config <dev>=<config> - Add a new device to UML;
- same syntax as command line
- config <dev> - Query the configuration of a device
- remove <dev> - Remove a device from UML
- sysrq <letter> - Performs the SysRq action controlled by the letter
- cad - invoke the Ctl-Alt-Del handler
- stop - pause the UML; it will do nothing until it receives a 'go'
- go - continue the UML after a 'stop'
+"Commands: \n\
+ version - Get kernel version \n\
+ help - Print this message \n\
+ halt - Halt UML \n\
+ reboot - Reboot UML \n\
+ config <dev>=<config> - Add a new device to UML; \n\
+ same syntax as command line \n\
+ config <dev> - Query the configuration of a device \n\
+ remove <dev> - Remove a device from UML \n\
+ sysrq <letter> - Performs the SysRq action controlled by the letter \n\
+ cad - invoke the Ctl-Alt-Del handler \n\
+ stop - pause the UML; it will do nothing until it receives a 'go' \n\
+ go - continue the UML after a 'stop' \n\
+ log <string> - make UML enter <string> into the kernel log\n\
+ proc <file> - returns the contents of the UML's /proc/<file>\n\
"
void mconsole_help(struct mc_request *req)
if(umid_file_name("mconsole", file, sizeof(file))) return(-1);
snprintf(mconsole_socket_name, sizeof(file), "%s", file);
- sock = create_unix_socket(file, sizeof(file));
+ sock = os_create_unix_socket(file, sizeof(file), 1);
if (sock < 0){
printk("Failed to initialize management console\n");
return(1);
if(buf == NULL)
return(-ENOMEM);
- if(copy_from_user(buf, buffer, count))
- return(-EFAULT);
+ if(copy_from_user(buf, buffer, count)){
+ count = -EFAULT;
+ goto out;
+ }
+
buf[count] = '\0';
mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count);
+ out:
+ kfree(buf);
return(count);
}
/*
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include "umid.h"
static struct mconsole_command commands[] = {
- { "version", mconsole_version, 1 },
- { "halt", mconsole_halt, 0 },
- { "reboot", mconsole_reboot, 0 },
- { "config", mconsole_config, 0 },
- { "remove", mconsole_remove, 0 },
- { "sysrq", mconsole_sysrq, 1 },
- { "help", mconsole_help, 1 },
- { "cad", mconsole_cad, 1 },
- { "stop", mconsole_stop, 0 },
- { "go", mconsole_go, 1 },
+ { "version", mconsole_version, MCONSOLE_INTR },
+ { "halt", mconsole_halt, MCONSOLE_PROC },
+ { "reboot", mconsole_reboot, MCONSOLE_PROC },
+ { "config", mconsole_config, MCONSOLE_PROC },
+ { "remove", mconsole_remove, MCONSOLE_PROC },
+ { "sysrq", mconsole_sysrq, MCONSOLE_INTR },
+ { "help", mconsole_help, MCONSOLE_INTR },
+ { "cad", mconsole_cad, MCONSOLE_INTR },
+ { "stop", mconsole_stop, MCONSOLE_PROC },
+ { "go", mconsole_go, MCONSOLE_INTR },
+ { "log", mconsole_log, MCONSOLE_INTR },
+ { "proc", mconsole_proc, MCONSOLE_PROC },
};
/* Initialized in mconsole_init, which is an initcall */
memcpy(reply.data, str, len);
reply.data[len] = '\0';
total -= len;
+ str += len;
reply.len = len + 1;
len = sizeof(reply) + reply.len - sizeof(reply.data);
printk(KERN_INFO "Mapper v0.1\n");
v_buf = (char *) find_iomem("mmapper", &mmapper_size);
- if(mmapper_size == 0) return(0);
+ if(mmapper_size == 0){
+ printk(KERN_ERR "mmapper_init - find_iomem failed\n");
+ return(0);
+ }
p_buf = __pa(v_buf);
#include "mconsole_kern.h"
#include "init.h"
#include "irq_user.h"
+#include "irq_kern.h"
static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
LIST_HEAD(opened);
struct sk_buff *skb;
/* If we can't allocate memory, try again next round. */
- if ((skb = dev_alloc_skb(dev->mtu)) == NULL) {
+ skb = dev_alloc_skb(dev->mtu);
+ if (skb == NULL) {
lp->stats.rx_dropped++;
return 0;
}
return pkt_len;
}
-void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct uml_net_private *lp = dev->priv;
int err;
if(!netif_running(dev))
- return;
+ return(IRQ_NONE);
spin_lock(&lp->lock);
while((err = uml_net_rx(dev)) > 0) ;
out:
spin_unlock(&lp->lock);
+ return(IRQ_HANDLED);
}
static int uml_net_open(struct net_device *dev)
#endif
}
-/*
- * default do nothing hard header packet routines for struct net_device init.
- * real ethernet transports will overwrite with real routines.
- */
-static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr, void *saddr, unsigned len)
-{
- return(0); /* no change */
-}
-
-static int uml_net_rebuild_header(struct sk_buff *skb)
-{
- return(0); /* ignore */
-}
-
-static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
-{
- return(-1); /* fail */
-}
-
-static void uml_net_header_cache_update(struct hh_cache *hh,
- struct net_device *dev, unsigned char * haddr)
-{
- /* ignore */
-}
-
-static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
-{
- return(0); /* nothing */
-}
-
static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
static struct list_head devices = LIST_HEAD_INIT(devices);
struct uml_net *device;
struct net_device *dev;
struct uml_net_private *lp;
- int err, size;
+ int save, err, size;
size = transport->private_size + sizeof(struct uml_net_private) +
sizeof(((struct uml_net_private *) 0)->user);
snprintf(dev->name, sizeof(dev->name), "eth%d", n);
device->dev = dev;
- dev->hard_header = uml_net_hard_header;
- dev->rebuild_header = uml_net_rebuild_header;
- dev->hard_header_cache = uml_net_header_cache;
- dev->header_cache_update= uml_net_header_cache_update;
- dev->hard_header_parse = uml_net_header_parse;
-
(*transport->kern->init)(dev, init);
dev->mtu = transport->user->max_packet;
}
lp = dev->priv;
- INIT_LIST_HEAD(&lp->list);
- spin_lock_init(&lp->lock);
- lp->dev = dev;
- lp->fd = -1;
- lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 };
- lp->have_mac = device->have_mac;
- lp->protocol = transport->kern->protocol;
- lp->open = transport->user->open;
- lp->close = transport->user->close;
- lp->remove = transport->user->remove;
- lp->read = transport->kern->read;
- lp->write = transport->kern->write;
- lp->add_address = transport->user->add_address;
- lp->delete_address = transport->user->delete_address;
- lp->set_mtu = transport->user->set_mtu;
+ /* lp.user is the first four bytes of the transport data, which
+ * has already been initialized. This structure assignment will
+ * overwrite that, so we make sure that .user gets overwritten with
+ * what it already has.
+ */
+ save = lp->user[0];
+ *lp = ((struct uml_net_private)
+ { .list = LIST_HEAD_INIT(lp->list),
+ .lock = SPIN_LOCK_UNLOCKED,
+ .dev = dev,
+ .fd = -1,
+ .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0},
+ .have_mac = device->have_mac,
+ .protocol = transport->kern->protocol,
+ .open = transport->user->open,
+ .close = transport->user->close,
+ .remove = transport->user->remove,
+ .read = transport->kern->read,
+ .write = transport->kern->write,
+ .add_address = transport->user->add_address,
+ .delete_address = transport->user->delete_address,
+ .set_mtu = transport->user->set_mtu,
+ .user = { save } });
init_timer(&lp->tl);
lp->tl.function = uml_net_user_timer_expire;
unregister_netdev(dev);
list_del(&device->list);
- free_netdev(device);
+ kfree(device);
+ free_netdev(dev);
return(0);
}
if(gate_addr == NULL) return(0);
if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
&tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){
- printk("Invalid tap IP address - '%s'\n",
- gate_addr);
+ printk("Invalid tap IP address - '%s'\n", gate_addr);
return(-EINVAL);
}
return(0);
}
*output = '\0';
- if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){
- printk("read_output - read of length failed, errno = %d\n",
- errno);
+ n = os_read_file(fd, &remain, sizeof(remain));
+ if(n != sizeof(remain)){
+ printk("read_output - read of length failed, err = %d\n", -n);
return;
}
while(remain != 0){
n = (remain < len) ? remain : len;
- actual = read(fd, output, n);
+ actual = os_read_file(fd, output, n);
if(actual != n){
printk("read_output - read of data failed, "
- "errno = %d\n", errno);
+ "err = %d\n", -actual);
return;
}
remain -= actual;
{
int n;
- while(((n = read(fd, buf, len)) < 0) && (errno == EINTR)) ;
+ n = os_read_file(fd, buf, len);
- if(n < 0){
- if(errno == EAGAIN) return(0);
- return(-errno);
- }
- else if(n == 0) return(-ENOTCONN);
+ if(n == -EAGAIN)
+ return(0);
+ else if(n == 0)
+ return(-ENOTCONN);
return(n);
}
{
int n;
- while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ;
- if(n < 0){
- if(errno == EAGAIN) return(0);
- return(-errno);
- }
- else if(n == 0) return(-ENOTCONN);
- return(n);
+ n = os_write_file(fd, buf, len);
+
+ if(n == -EAGAIN)
+ return(0);
+ else if(n == 0)
+ return(-ENOTCONN);
+ return(n);
}
int net_send(int fd, void *buf, int len)
{
struct change_pre_exec_data *data = arg;
- close(data->close_me);
+ os_close_file(data->close_me);
dup2(data->stdout, 1);
}
struct change_pre_exec_data pe_data;
err = os_pipe(fds, 1, 0);
- if(err){
- printk("change_tramp - pipe failed, errno = %d\n", -err);
+ if(err < 0){
+ printk("change_tramp - pipe failed, err = %d\n", -err);
return(err);
}
pe_data.close_me = fds[0];
pe_data.stdout = fds[1];
pid = run_helper(change_pre_exec, &pe_data, argv, NULL);
- close(fds[1]);
+ os_close_file(fds[1]);
read_output(fds[0], output, output_len);
waitpid(pid, NULL, 0);
return(pid);
#include <stdlib.h>
#include <errno.h>
-#include <fcntl.h>
#include "chan_user.h"
#include "os.h"
#include "linux/list.h"
#include "linux/sched.h"
#include "linux/slab.h"
+#include "linux/interrupt.h"
#include "linux/irq.h"
#include "linux/spinlock.h"
#include "linux/errno.h"
#include "kern_util.h"
#include "kern.h"
#include "irq_user.h"
+#include "irq_kern.h"
#include "port.h"
#include "init.h"
#include "os.h"
struct connection {
struct list_head list;
int fd;
- int helper_pid;
+ int helper_pid;
int socket[2];
int telnetd_pid;
struct port_list *port;
};
-static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct connection *conn = data;
int fd;
- fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
+ fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
if(fd < 0){
if(fd == -EAGAIN)
- return;
+ return(IRQ_NONE);
printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
-fd);
list_add(&conn->list, &conn->port->connections);
up(&conn->port->sem);
+ return(IRQ_HANDLED);
}
static int port_accept(struct port_list *port)
}
list_add(&conn->list, &port->pending);
- ret = 1;
- goto out;
+ return(1);
out_free:
kfree(conn);
DECLARE_WORK(port_work, port_work_proc, NULL);
-static void port_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct port_list *port = data;
port->has_connection = 1;
schedule_work(&port_work);
+ return(IRQ_HANDLED);
}
void *port_data(int port_num)
return(NULL);
}
- if((kern_data = port_data(port)) == NULL)
+ kern_data = port_data(port);
+ if(kern_data == NULL)
return(NULL);
- if((data = um_kmalloc(sizeof(*data))) == NULL)
+ data = um_kmalloc(sizeof(*data));
+ if(data == NULL)
goto err;
*data = ((struct port_chan) { .raw = opts->raw,
struct port_chan *data = d;
port_remove_dev(data->kernel_data);
- close(fd);
+ os_close_file(fd);
}
int port_console_write(int fd, const char *buf, int n, void *d)
goto out;
}
- if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){
+ if(listen(fd, 1) < 0){
err = -errno;
goto out;
}
+ err = os_set_fd_block(fd, 0);
+ if(err < 0)
+ goto out;
+
return(fd);
out:
os_close_file(fd);
dup2(data->sock_fd, 0);
dup2(data->sock_fd, 1);
dup2(data->sock_fd, 2);
- close(data->sock_fd);
+ os_close_file(data->sock_fd);
dup2(data->pipe_fd, 3);
os_shutdown_socket(3, 1, 0);
- close(data->pipe_fd);
+ os_close_file(data->pipe_fd);
}
int port_connection(int fd, int *socket, int *pid_out)
"/usr/lib/uml/port-helper", NULL };
struct port_pre_exec_data data;
- if((new = os_accept_connection(fd)) < 0)
- return(-errno);
+ new = os_accept_connection(fd);
+ if(new < 0)
+ return(new);
err = os_pipe(socket, 0, 0);
- if(err)
+ if(err < 0)
goto out_close;
data = ((struct port_pre_exec_data)
out_shutdown:
os_shutdown_socket(socket[0], 1, 1);
- close(socket[0]);
+ os_close_file(socket[0]);
os_shutdown_socket(socket[1], 1, 1);
- close(socket[1]);
+ os_close_file(socket[1]);
out_close:
- close(new);
+ os_close_file(new);
return(err);
}
#include <unistd.h>
#include <string.h>
#include <errno.h>
-#include <fcntl.h>
#include <termios.h>
#include "chan_user.h"
#include "user.h"
#include "user_util.h"
#include "kern_util.h"
+#include "os.h"
struct pty_chan {
void (*announce)(char *dev_name, int dev);
{
struct pty_chan *data;
- if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+ data = um_kmalloc(sizeof(*data));
+ if(data == NULL) return(NULL);
*data = ((struct pty_chan) { .announce = opts->announce,
.dev = device,
.raw = opts->raw });
char *dev;
int fd;
- if((fd = get_pty()) < 0){
+ fd = get_pty();
+ if(fd < 0){
printk("open_pts : Failed to open pts\n");
return(-errno);
}
int getmaster(char *line)
{
- struct stat stb;
char *pty, *bank, *cp;
- int master;
+ int master, err;
pty = &line[strlen("/dev/ptyp")];
for (bank = "pqrs"; *bank; bank++) {
line[strlen("/dev/pty")] = *bank;
*pty = '0';
- if (stat(line, &stb) < 0)
+ if (os_stat_file(line, NULL) < 0)
break;
for (cp = "0123456789abcdef"; *cp; cp++) {
*pty = *cp;
- master = open(line, O_RDWR);
+ master = os_open_file(line, of_rdwr(OPENFLAGS()), 0);
if (master >= 0) {
char *tp = &line[strlen("/dev/")];
- int ok;
/* verify slave side is usable */
*tp = 't';
- ok = access(line, R_OK|W_OK) == 0;
+ err = os_access(line, OS_ACC_RW_OK);
*tp = 'p';
- if (ok) return(master);
- (void) close(master);
+ if(err == 0) return(master);
+ (void) os_close_file(master);
}
}
}
#include <stddef.h>
#include <sched.h>
#include <string.h>
-#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/termios.h>
#include <sys/wait.h>
-#include <sys/ioctl.h>
#include <sys/signal.h>
#include "user_util.h"
#include "kern_util.h"
{
struct slip_pre_exec_data *data = arg;
- if(data->stdin != -1) dup2(data->stdin, 0);
+ if(data->stdin >= 0) dup2(data->stdin, 0);
dup2(data->stdout, 1);
- if(data->close_me != -1) close(data->close_me);
+ if(data->close_me >= 0) os_close_file(data->close_me);
}
static int slip_tramp(char **argv, int fd)
int status, pid, fds[2], err, output_len;
err = os_pipe(fds, 1, 0);
- if(err){
- printk("slip_tramp : pipe failed, errno = %d\n", -err);
+ if(err < 0){
+ printk("slip_tramp : pipe failed, err = %d\n", -err);
return(err);
}
printk("slip_tramp : failed to allocate output "
"buffer\n");
- close(fds[1]);
+ os_close_file(fds[1]);
read_output(fds[0], output, output_len);
if(output != NULL){
printk("%s", output);
if(waitpid(pid, &status, 0) < 0) err = errno;
else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
printk("'%s' didn't exit with status 0\n", argv[0]);
- err = EINVAL;
+ err = -EINVAL;
}
}
return(err);
char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf,
NULL };
- int sfd, mfd, disc, sencap, err;
+ int sfd, mfd, err;
- if((mfd = get_pty()) < 0){
- printk("umn : Failed to open pty\n");
- return(-1);
+ mfd = get_pty();
+ if(mfd < 0){
+ printk("umn : Failed to open pty, err = %d\n", -mfd);
+ return(mfd);
}
- if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){
- printk("Couldn't open tty for slip line\n");
- return(-1);
+ sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
+ if(sfd < 0){
+ printk("Couldn't open tty for slip line, err = %d\n", -sfd);
+ return(sfd);
}
if(set_up_tty(sfd)) return(-1);
pri->slave = sfd;
err = slip_tramp(argv, sfd);
- if(err != 0){
- printk("slip_tramp failed - errno = %d\n", err);
- return(-err);
+ if(err < 0){
+ printk("slip_tramp failed - err = %d\n", -err);
+ return(err);
}
- if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){
- printk("SIOCGIFNAME failed, errno = %d\n", errno);
- return(-errno);
+ err = os_get_ifname(pri->slave, pri->name);
+ if(err < 0){
+ printk("get_ifname failed, err = %d\n", -err);
+ return(err);
}
iter_addresses(pri->dev, open_addr, pri->name);
}
else {
- disc = N_SLIP;
- if(ioctl(sfd, TIOCSETD, &disc) < 0){
- printk("Failed to set slip line discipline - "
- "errno = %d\n", errno);
- return(-errno);
- }
- sencap = 0;
- if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){
- printk("Failed to set slip encapsulation - "
- "errno = %d\n", errno);
- return(-errno);
+ err = os_set_slip(sfd);
+ if(err < 0){
+ printk("Failed to set slip discipline encapsulation - "
+ "err = %d\n", -err);
+ return(err);
}
}
return(mfd);
err = slip_tramp(argv, -1);
if(err != 0)
- printk("slip_tramp failed - errno = %d\n", err);
- close(fd);
- close(pri->slave);
+ printk("slip_tramp failed - errno = %d\n", -err);
+ os_close_file(fd);
+ os_close_file(pri->slave);
pri->slave = -1;
}
{
struct slip_data *pri = data;
- if(pri->slave == -1) return;
+ if(pri->slave < 0) return;
open_addr(addr, netmask, pri->name);
}
{
struct slip_data *pri = data;
- if(pri->slave == -1) return;
+ if(pri->slave < 0) return;
close_addr(addr, netmask, pri->name);
}
#include <stddef.h>
#include <sched.h>
#include <string.h>
-#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/wait.h>
#include <sys/signal.h>
return(pid);
}
-
+
+/* XXX This is just a trivial wrapper around os_pipe */
static int slirp_datachan(int *mfd, int *sfd)
{
int fds[2], err;
err = os_pipe(fds, 1, 1);
- if(err){
- printk("slirp_datachan: Failed to open pipe, errno = %d\n",
- -err);
+ if(err < 0){
+ printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
return(err);
}
pid = slirp_tramp(pri->argw.argv, sfd);
if(pid < 0){
- printk("slirp_tramp failed - errno = %d\n", pid);
+ printk("slirp_tramp failed - errno = %d\n", -pid);
os_close_file(sfd);
os_close_file(mfd);
return(pid);
struct slirp_data *pri = data;
int status,err;
- close(fd);
- close(pri->slave);
+ os_close_file(fd);
+ os_close_file(pri->slave);
pri->slave = -1;
#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"
static struct line_driver driver = {
.name = "UML serial line",
- .devfs_name = "tts/%d",
- .major = TTYAUX_MAJOR,
+ .device_name = "ttS",
+ .devfs_name = "tts/",
+ .major = TTY_MAJOR,
.minor_start = 64,
.type = TTY_DRIVER_TYPE_SERIAL,
.subtype = 0,
case TCSETSW:
case TCGETA:
case TIOCMGET:
+ case TCSBRK:
+ case TCSBRKP:
+ case TIOCMSET:
ret = -ENOIOCTLCMD;
break;
default:
*/
static int ssl_init_done = 0;
+static void ssl_console_write(struct console *c, const char *string,
+ unsigned len)
+{
+ struct line *line = &serial_lines[c->index];
+ if(ssl_init_done)
+ down(&line->sem);
+ console_write_chan(&line->chan_list, string, len);
+ if(ssl_init_done)
+ up(&line->sem);
+}
+
+static struct tty_driver *ssl_console_device(struct console *c, int *index)
+{
+ *index = c->index;
+ return ssl_driver;
+}
+
+static int ssl_console_setup(struct console *co, char *options)
+{
+ return(0);
+}
+
+static struct console ssl_cons = {
+ name: "ttyS",
+ write: ssl_console_write,
+ device: ssl_console_device,
+ setup: ssl_console_setup,
+ flags: CON_PRINTBUFFER,
+ index: -1,
+};
+
int ssl_init(void)
{
char *new_title;
new_title = add_xterm_umid(opts.xterm_title);
if(new_title != NULL) opts.xterm_title = new_title;
+ register_console(&ssl_cons);
ssl_init_done = 1;
return(0);
}
-__initcall(ssl_init);
+late_initcall(ssl_init);
static int ssl_chan_setup(char *str)
{
- line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]),
- str, 1);
- return(1);
+ return(line_setup(serial_lines,
+ sizeof(serial_lines)/sizeof(serial_lines[0]),
+ str, 1));
}
__setup("ssl", ssl_chan_setup);
static struct line_driver driver = {
.name = "UML console",
- .devfs_name = "vc/%d",
+ .device_name = "tty",
+ .devfs_name = "vc/",
.major = TTY_MAJOR,
.minor_start = 0,
.type = TTY_DRIVER_TYPE_CONSOLE,
static int con_init_done = 0;
+static struct tty_operations console_ops = {
+ .open = con_open,
+ .close = con_close,
+ .write = con_write,
+ .chars_in_buffer = chars_in_buffer,
+ .set_termios = set_termios,
+ .write_room = line_write_room,
+};
+
int stdio_init(void)
{
char *new_title;
printk(KERN_INFO "Initializing stdio console driver\n");
console_driver = line_register_devfs(&console_lines, &driver,
- &console_ops, vts, sizeof(vts)/sizeof(vts[0]));
+ &console_ops, vts,
+ sizeof(vts)/sizeof(vts[0]));
lines_init(vts, sizeof(vts)/sizeof(vts[0]));
return(0);
}
-__initcall(stdio_init);
+late_initcall(stdio_init);
static void console_write(struct console *console, const char *string,
unsigned len)
{
- if(con_init_done) down(&vts[console->index].sem);
- console_write_chan(&vts[console->index].chan_list, string, len);
- if(con_init_done) up(&vts[console->index].sem);
-}
+ struct line *line = &vts[console->index];
-static struct tty_operations console_ops = {
- .open = con_open,
- .close = con_close,
- .write = con_write,
- .chars_in_buffer = chars_in_buffer,
- .set_termios = set_termios,
- .write_room = line_write_room,
-};
+ if(con_init_done)
+ down(&line->sem);
+ console_write_chan(&line->chan_list, string, len);
+ if(con_init_done)
+ up(&line->sem);
+}
static struct tty_driver *console_device(struct console *c, int *index)
{
return(0);
}
-static struct console stdiocons = INIT_CONSOLE("tty", console_write,
- console_device, console_setup,
- CON_PRINTBUFFER);
+static struct console stdiocons = {
+ name: "tty",
+ write: console_write,
+ device: console_device,
+ setup: console_setup,
+ flags: CON_PRINTBUFFER,
+ index: -1,
+};
-static void __init stdio_console_init(void)
+static int __init stdio_console_init(void)
{
INIT_LIST_HEAD(&vts[0].chan_list);
list_add(&init_console_chan.list, &vts[0].chan_list);
register_console(&stdiocons);
+ return(0);
}
+
console_initcall(stdio_console_init);
static int console_chan_setup(char *str)
{
- line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1);
- return(1);
+ return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1));
}
__setup("con", console_chan_setup);
#include <stdio.h>
#include <termios.h>
-#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "chan_user.h"
}
str++;
- if((data = um_kmalloc(sizeof(*data))) == NULL)
+ data = um_kmalloc(sizeof(*data));
+ if(data == NULL)
return(NULL);
*data = ((struct tty_chan) { .dev = str,
.raw = opts->raw });
* old style ubd by setting UBD_SHIFT to 0
* 2002-09-27...2002-10-18 massive tinkering for 2.5
* partitions have changed in 2.5
+ * 2003-01-29 more tinkering for 2.5.59-1
+ * This should now address the sysfs problems and has
+ * the symlink for devfs to allow for booting with
+ * the common /dev/ubd/discX/... names rather than
+ * only /dev/ubdN/discN this version also has lots of
+ * clean ups preparing for ubd-many.
+ * James McMechan
*/
#define MAJOR_NR UBD_MAJOR
#include "mconsole_kern.h"
#include "init.h"
#include "irq_user.h"
+#include "irq_kern.h"
#include "ubd_user.h"
#include "2_5compat.h"
#include "os.h"
+#include "mem.h"
+#include "mem_kern.h"
static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED;
#define MAX_DEV (8)
+/* Changed in early boot */
+static int ubd_do_mmap = 0;
+#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
+
static struct block_device_operations ubd_blops = {
.owner = THIS_MODULE,
.open = ubd_open,
static request_queue_t *ubd_queue;
/* Protected by ubd_lock */
-static int fake_major = 0;
+static int fake_major = MAJOR_NR;
static struct gendisk *ubd_gendisk[MAX_DEV];
static struct gendisk *fake_gendisk[MAX_DEV];
struct ubd {
char *file;
- int is_dir;
int count;
int fd;
__u64 size;
struct openflags boot_openflags;
struct openflags openflags;
+ int no_cow;
struct cow cow;
+
+ int map_writes;
+ int map_reads;
+ int nomap_writes;
+ int nomap_reads;
+ int write_maps;
};
#define DEFAULT_COW { \
#define DEFAULT_UBD { \
.file = NULL, \
- .is_dir = 0, \
.count = 0, \
.fd = -1, \
.size = -1, \
.boot_openflags = OPEN_FLAGS, \
.openflags = OPEN_FLAGS, \
+ .no_cow = 0, \
.cow = DEFAULT_COW, \
+ .map_writes = 0, \
+ .map_reads = 0, \
+ .nomap_writes = 0, \
+ .nomap_reads = 0, \
+ .write_maps = 0, \
}
struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
static int ubd0_init(void)
{
- if(ubd_dev[0].file == NULL)
- ubd_dev[0].file = "root_fs";
+ struct ubd *dev = &ubd_dev[0];
+
+ if(dev->file == NULL)
+ dev->file = "root_fs";
return(0);
}
" Create ide0 entries that map onto ubd devices.\n\n"
);
+static int parse_unit(char **ptr)
+{
+ char *str = *ptr, *end;
+ int n = -1;
+
+ if(isdigit(*str)) {
+ n = simple_strtoul(str, &end, 0);
+ if(end == str)
+ return(-1);
+ *ptr = end;
+ }
+ else if (('a' <= *str) && (*str <= 'h')) {
+ n = *str - 'a';
+ str++;
+ *ptr = str;
+ }
+ return(n);
+}
+
static int ubd_setup_common(char *str, int *index_out)
{
+ struct ubd *dev;
struct openflags flags = global_openflags;
char *backing_file;
int n, err;
if(index_out) *index_out = -1;
- n = *str++;
+ n = *str;
if(n == '='){
- static int fake_major_allowed = 1;
char *end;
int major;
+ str++;
+ if(!strcmp(str, "mmap")){
+ CHOOSE_MODE(printk("mmap not supported by the ubd "
+ "driver in tt mode\n"),
+ ubd_do_mmap = 1);
+ return(0);
+ }
+
if(!strcmp(str, "sync")){
global_openflags.s = 1;
return(0);
return(1);
}
- if(!fake_major_allowed){
- printk(KERN_ERR "Can't assign a fake major twice\n");
- return(1);
- }
-
err = 1;
spin_lock(&ubd_lock);
- if(!fake_major_allowed){
+ if(fake_major != MAJOR_NR){
printk(KERN_ERR "Can't assign a fake major twice\n");
goto out1;
}
fake_major = major;
- fake_major_allowed = 0;
printk(KERN_INFO "Setting extra ubd major number to %d\n",
major);
return(err);
}
- if(n < '0'){
- printk(KERN_ERR "ubd_setup : index out of range\n"); }
-
- if((n >= '0') && (n <= '9')) n -= '0';
- else if((n >= 'a') && (n <= 'z')) n -= 'a';
- else {
- printk(KERN_ERR "ubd_setup : device syntax invalid\n");
+ n = parse_unit(&str);
+ if(n < 0){
+ printk(KERN_ERR "ubd_setup : couldn't parse unit number "
+ "'%s'\n", str);
return(1);
}
if(n >= MAX_DEV){
- printk(KERN_ERR "ubd_setup : index out of range "
- "(%d devices)\n", MAX_DEV);
+ printk(KERN_ERR "ubd_setup : index %d out of range "
+ "(%d devices)\n", n, MAX_DEV);
return(1);
}
err = 1;
spin_lock(&ubd_lock);
- if(ubd_dev[n].file != NULL){
+ dev = &ubd_dev[n];
+ if(dev->file != NULL){
printk(KERN_ERR "ubd_setup : device already configured\n");
goto out2;
}
flags.s = 1;
str++;
}
+ if (*str == 'd'){
+ dev->no_cow = 1;
+ str++;
+ }
+
if(*str++ != '='){
printk(KERN_ERR "ubd_setup : Expected '='\n");
goto out2;
err = 0;
backing_file = strchr(str, ',');
if(backing_file){
- *backing_file = '\0';
- backing_file++;
- }
- ubd_dev[n].file = str;
- if(ubd_is_dir(ubd_dev[n].file))
- ubd_dev[n].is_dir = 1;
- ubd_dev[n].cow.file = backing_file;
- ubd_dev[n].boot_openflags = flags;
+ if(dev->no_cow)
+ printk(KERN_ERR "Can't specify both 'd' and a "
+ "cow file\n");
+ else {
+ *backing_file = '\0';
+ backing_file++;
+ }
+ }
+ dev->file = str;
+ dev->cow.file = backing_file;
+ dev->boot_openflags = flags;
out2:
spin_unlock(&ubd_lock);
return(err);
static int fakehd_set = 0;
static int fakehd(char *str)
{
- printk(KERN_INFO
- "fakehd : Changing ubd name to \"hd\".\n");
+ printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
fakehd_set = 1;
return 1;
}
{
struct io_thread_req req;
struct request *rq = elv_next_request(ubd_queue);
- int n;
+ int n, err;
do_ubd = NULL;
intr_count++;
n = read_ubd_fs(thread_fd, &req, sizeof(req));
if(n != sizeof(req)){
printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
- "errno = %d\n", os_getpid(), -n);
+ "err = %d\n", os_getpid(), -n);
spin_lock(&ubd_io_lock);
end_request(rq, 0);
spin_unlock(&ubd_io_lock);
return;
}
- if((req.offset != ((__u64) (rq->sector)) << 9) ||
- (req.length != (rq->current_nr_sectors) << 9))
+ if((req.op != UBD_MMAP) &&
+ ((req.offset != ((__u64) (rq->sector)) << 9) ||
+ (req.length != (rq->current_nr_sectors) << 9)))
panic("I/O op mismatch");
+ if(req.map_fd != -1){
+ err = physmem_subst_mapping(req.buffer, req.map_fd,
+ req.map_offset, 1);
+ if(err)
+ printk("ubd_handler - physmem_subst_mapping failed, "
+ "err = %d\n", -err);
+ }
+
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue);
}
-static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
+static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused)
{
ubd_handler();
+ return(IRQ_HANDLED);
}
/* Only changed by ubd_init, which is an initcall. */
static void ubd_close(struct ubd *dev)
{
+ if(ubd_do_mmap)
+ physmem_forget_descriptor(dev->fd);
os_close_file(dev->fd);
if(dev->cow.file == NULL)
return;
+ if(ubd_do_mmap)
+ physmem_forget_descriptor(dev->cow.fd);
os_close_file(dev->cow.fd);
vfree(dev->cow.bitmap);
dev->cow.bitmap = NULL;
static int ubd_open_dev(struct ubd *dev)
{
struct openflags flags;
- int err, n, create_cow, *create_ptr;
+ char **back_ptr;
+ int err, create_cow, *create_ptr;
+ dev->openflags = dev->boot_openflags;
create_cow = 0;
create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL;
- dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file,
+ back_ptr = dev->no_cow ? NULL : &dev->cow.file;
+ dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr,
&dev->cow.bitmap_offset, &dev->cow.bitmap_len,
&dev->cow.data_offset, create_ptr);
if((dev->fd == -ENOENT) && create_cow){
- n = dev - ubd_dev;
dev->fd = create_cow_file(dev->file, dev->cow.file,
- dev->openflags, 1 << 9,
+ dev->openflags, 1 << 9, PAGE_SIZE,
&dev->cow.bitmap_offset,
&dev->cow.bitmap_len,
&dev->cow.data_offset);
if(dev->cow.file != NULL){
err = -ENOMEM;
dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len);
- if(dev->cow.bitmap == NULL) goto error;
+ if(dev->cow.bitmap == NULL){
+ printk(KERN_ERR "Failed to vmalloc COW bitmap\n");
+ goto error;
+ }
flush_tlb_kernel_vm();
err = read_cow_bitmap(dev->fd, dev->cow.bitmap,
dev->cow.bitmap_offset,
dev->cow.bitmap_len);
- if(err) goto error;
+ if(err < 0)
+ goto error;
flags = dev->openflags;
flags.w = 0;
{
struct gendisk *disk;
+ char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")];
+ int err;
disk = alloc_disk(1 << UBD_SHIFT);
- if (!disk)
- return -ENOMEM;
+ if(disk == NULL)
+ return(-ENOMEM);
disk->major = major;
disk->first_minor = unit << UBD_SHIFT;
disk->fops = &ubd_blops;
set_capacity(disk, size / 512);
- sprintf(disk->disk_name, "ubd");
- sprintf(disk->devfs_name, "ubd/disc%d", unit);
+ if(major == MAJOR_NR){
+ sprintf(disk->disk_name, "ubd%c", 'a' + unit);
+ sprintf(disk->devfs_name, "ubd/disc%d", unit);
+ sprintf(from, "ubd/%d", unit);
+ sprintf(to, "disc%d/disc", unit);
+ err = devfs_mk_symlink(from, to);
+ if(err)
+ printk("ubd_new_disk failed to make link from %s to "
+ "%s, error = %d\n", from, to, err);
+ }
+ else {
+ sprintf(disk->disk_name, "ubd_fake%d", unit);
+ sprintf(disk->devfs_name, "ubd_fake/disc%d", unit);
+ }
disk->private_data = &ubd_dev[unit];
disk->queue = ubd_queue;
struct ubd *dev = &ubd_dev[n];
int err;
- if(dev->is_dir)
- return(-EISDIR);
-
- if (!dev->file)
+ if(dev->file == NULL)
return(-ENODEV);
if (ubd_open_dev(dev))
return(-ENODEV);
err = ubd_file_size(dev, &dev->size);
- if(err)
+ if(err < 0)
return(err);
err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]);
if(err)
return(err);
- if(fake_major)
+ if(fake_major != MAJOR_NR)
ubd_new_disk(fake_major, dev->size, n,
&fake_gendisk[n]);
return(err);
}
-static int ubd_get_config(char *dev, char *str, int size, char **error_out)
+static int ubd_get_config(char *name, char *str, int size, char **error_out)
{
- struct ubd *ubd;
+ struct ubd *dev;
char *end;
- int major, n = 0;
+ int n, len = 0;
- major = simple_strtoul(dev, &end, 0);
- if((*end != '\0') || (end == dev)){
- *error_out = "ubd_get_config : didn't parse major number";
+ n = simple_strtoul(name, &end, 0);
+ if((*end != '\0') || (end == name)){
+ *error_out = "ubd_get_config : didn't parse device number";
return(-1);
}
- if((major >= MAX_DEV) || (major < 0)){
- *error_out = "ubd_get_config : major number out of range";
+ if((n >= MAX_DEV) || (n < 0)){
+ *error_out = "ubd_get_config : device number out of range";
return(-1);
}
- ubd = &ubd_dev[major];
+ dev = &ubd_dev[n];
spin_lock(&ubd_lock);
- if(ubd->file == NULL){
- CONFIG_CHUNK(str, size, n, "", 1);
+ if(dev->file == NULL){
+ CONFIG_CHUNK(str, size, len, "", 1);
goto out;
}
- CONFIG_CHUNK(str, size, n, ubd->file, 0);
+ CONFIG_CHUNK(str, size, len, dev->file, 0);
- if(ubd->cow.file != NULL){
- CONFIG_CHUNK(str, size, n, ",", 0);
- CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
+ if(dev->cow.file != NULL){
+ CONFIG_CHUNK(str, size, len, ",", 0);
+ CONFIG_CHUNK(str, size, len, dev->cow.file, 1);
}
- else CONFIG_CHUNK(str, size, n, "", 1);
+ else CONFIG_CHUNK(str, size, len, "", 1);
out:
spin_unlock(&ubd_lock);
- return(n);
+ return(len);
}
static int ubd_remove(char *str)
struct ubd *dev;
int n, err = -ENODEV;
- if(!isdigit(*str))
- return(err); /* it should be a number 0-7/a-h */
+ n = parse_unit(&str);
- n = *str - '0';
- if(n >= MAX_DEV)
+ if((n < 0) || (n >= MAX_DEV))
return(err);
dev = &ubd_dev[n];
elevator_init(ubd_queue, &elevator_noop);
- if (fake_major != 0) {
+ if (fake_major != MAJOR_NR) {
char name[sizeof("ubd_nnn\0")];
snprintf(name, sizeof(name), "ubd_%d", fake_major);
io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *),
&thread_fd);
if(io_pid < 0){
+ io_pid = -1;
printk(KERN_ERR
"ubd : Failed to start I/O thread (errno = %d) - "
"falling back to synchronous I/O\n", -io_pid);
}
err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr,
SA_INTERRUPT, "ubd", ubd_dev);
- if(err != 0) printk(KERN_ERR
- "um_request_irq failed - errno = %d\n", -err);
+ if(err != 0)
+ printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err);
return(err);
}
{
struct gendisk *disk = inode->i_bdev->bd_disk;
struct ubd *dev = disk->private_data;
- int err = -EISDIR;
-
- if(dev->is_dir == 1)
- goto out;
+ int err = 0;
- err = 0;
if(dev->count == 0){
- dev->openflags = dev->boot_openflags;
-
err = ubd_open_dev(dev);
if(err){
printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n",
return(0);
}
-void cowify_req(struct io_thread_req *req, struct ubd *dev)
+static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask,
+ __u64 *cow_offset, unsigned long *bitmap,
+ __u64 bitmap_offset, unsigned long *bitmap_words,
+ __u64 bitmap_len)
{
- int i, update_bitmap, sector = req->offset >> 9;
+ __u64 sector = io_offset >> 9;
+ int i, update_bitmap = 0;
+
+ for(i = 0; i < length >> 9; i++){
+ if(cow_mask != NULL)
+ ubd_set_bit(i, (unsigned char *) cow_mask);
+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
+ continue;
+
+ update_bitmap = 1;
+ ubd_set_bit(sector + i, (unsigned char *) bitmap);
+ }
+
+ if(!update_bitmap)
+ return;
+
+ *cow_offset = sector / (sizeof(unsigned long) * 8);
+
+ /* This takes care of the case where we're exactly at the end of the
+ * device, and *cow_offset + 1 is off the end. So, just back it up
+ * by one word. Thanks to Lynn Kerby for the fix and James McMechan
+ * for the original diagnosis.
+ */
+ if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) /
+ sizeof(unsigned long) - 1))
+ (*cow_offset)--;
+
+ bitmap_words[0] = bitmap[*cow_offset];
+ bitmap_words[1] = bitmap[*cow_offset + 1];
+
+ *cow_offset *= sizeof(unsigned long);
+ *cow_offset += bitmap_offset;
+}
+
+static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
+ __u64 bitmap_offset, __u64 bitmap_len)
+{
+ __u64 sector = req->offset >> 9;
+ int i;
if(req->length > (sizeof(req->sector_mask) * 8) << 9)
panic("Operation too long");
+
if(req->op == UBD_READ) {
for(i = 0; i < req->length >> 9; i++){
- if(ubd_test_bit(sector + i, (unsigned char *)
- dev->cow.bitmap)){
+ if(ubd_test_bit(sector + i, (unsigned char *) bitmap))
ubd_set_bit(i, (unsigned char *)
&req->sector_mask);
- }
}
- }
- else {
- update_bitmap = 0;
- for(i = 0; i < req->length >> 9; i++){
- ubd_set_bit(i, (unsigned char *)
- &req->sector_mask);
- if(!ubd_test_bit(sector + i, (unsigned char *)
- dev->cow.bitmap))
- update_bitmap = 1;
- ubd_set_bit(sector + i, (unsigned char *)
- dev->cow.bitmap);
- }
- if(update_bitmap){
- req->cow_offset = sector / (sizeof(unsigned long) * 8);
- req->bitmap_words[0] =
- dev->cow.bitmap[req->cow_offset];
- req->bitmap_words[1] =
- dev->cow.bitmap[req->cow_offset + 1];
- req->cow_offset *= sizeof(unsigned long);
- req->cow_offset += dev->cow.bitmap_offset;
+ }
+ else cowify_bitmap(req->offset, req->length, &req->sector_mask,
+ &req->cow_offset, bitmap, bitmap_offset,
+ req->bitmap_words, bitmap_len);
+}
+
+static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
+{
+ __u64 sector;
+ unsigned char *bitmap;
+ int bit, i;
+
+ /* mmap must have been requested on the command line */
+ if(!ubd_do_mmap)
+ return(-1);
+
+ /* The buffer must be page aligned */
+ if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
+ return(-1);
+
+ /* The request must be a page long */
+ if((req->current_nr_sectors << 9) != PAGE_SIZE)
+ return(-1);
+
+ if(dev->cow.file == NULL)
+ return(dev->fd);
+
+ sector = offset >> 9;
+ bitmap = (unsigned char *) dev->cow.bitmap;
+ bit = ubd_test_bit(sector, bitmap);
+
+ for(i = 1; i < req->current_nr_sectors; i++){
+ if(ubd_test_bit(sector + i, bitmap) != bit)
+ return(-1);
+ }
+
+ if(bit || (rq_data_dir(req) == WRITE))
+ offset += dev->cow.data_offset;
+
+ /* The data on disk must be page aligned */
+ if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
+ return(-1);
+
+ return(bit ? dev->fd : dev->cow.fd);
+}
+
+static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
+ struct request *req,
+ struct io_thread_req *io_req)
+{
+ int err;
+
+ if(rq_data_dir(req) == WRITE){
+ /* Writes are almost no-ops since the new data is already in the
+ * host page cache
+ */
+ dev->map_writes++;
+ if(dev->cow.file != NULL)
+ cowify_bitmap(io_req->offset, io_req->length,
+ &io_req->sector_mask, &io_req->cow_offset,
+ dev->cow.bitmap, dev->cow.bitmap_offset,
+ io_req->bitmap_words,
+ dev->cow.bitmap_len);
+ }
+ else {
+ int w;
+
+ if((dev->cow.file != NULL) && (fd == dev->cow.fd))
+ w = 0;
+ else w = dev->openflags.w;
+
+ if((dev->cow.file != NULL) && (fd == dev->fd))
+ offset += dev->cow.data_offset;
+
+ err = physmem_subst_mapping(req->buffer, fd, offset, w);
+ if(err){
+ printk("physmem_subst_mapping failed, err = %d\n",
+ -err);
+ return(1);
}
+ dev->map_reads++;
}
+ io_req->op = UBD_MMAP;
+ io_req->buffer = req->buffer;
+ return(0);
}
static int prepare_request(struct request *req, struct io_thread_req *io_req)
{
struct gendisk *disk = req->rq_disk;
struct ubd *dev = disk->private_data;
- __u64 block;
- int nsect;
+ __u64 offset;
+ int len, fd;
if(req->rq_status == RQ_INACTIVE) return(1);
- if(dev->is_dir){
- strcpy(req->buffer, "HOSTFS:");
- strcat(req->buffer, dev->file);
- spin_lock(&ubd_io_lock);
- end_request(req, 1);
- spin_unlock(&ubd_io_lock);
- return(1);
- }
-
if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
printk("Write attempted on readonly ubd device %s\n",
disk->disk_name);
return(1);
}
- block = req->sector;
- nsect = req->current_nr_sectors;
+ offset = ((__u64) req->sector) << 9;
+ len = req->current_nr_sectors << 9;
- io_req->op = rq_data_dir(req) == READ ? UBD_READ : UBD_WRITE;
io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
io_req->fds[1] = dev->fd;
+ io_req->map_fd = -1;
+ io_req->cow_offset = -1;
+ io_req->offset = offset;
+ io_req->length = len;
+ io_req->error = 0;
+ io_req->sector_mask = 0;
+
+ fd = mmap_fd(req, dev, io_req->offset);
+ if(fd > 0){
+ /* If mmapping is otherwise OK, but the first access to the
+ * page is a write, then it's not mapped in yet. So we have
+ * to write the data to disk first, then we can map the disk
+ * page in and continue normally from there.
+ */
+ if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
+ io_req->map_fd = dev->fd;
+ io_req->map_offset = io_req->offset +
+ dev->cow.data_offset;
+ dev->write_maps++;
+ }
+ else return(prepare_mmap_request(dev, fd, io_req->offset, req,
+ io_req));
+ }
+
+ if(rq_data_dir(req) == READ)
+ dev->nomap_reads++;
+ else dev->nomap_writes++;
+
+ io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
io_req->offsets[0] = 0;
io_req->offsets[1] = dev->cow.data_offset;
- io_req->offset = ((__u64) block) << 9;
- io_req->length = nsect << 9;
io_req->buffer = req->buffer;
io_req->sectorsize = 1 << 9;
- io_req->sector_mask = 0;
- io_req->cow_offset = -1;
- io_req->error = 0;
- if(dev->cow.file != NULL) cowify_req(io_req, dev);
+ if(dev->cow.file != NULL)
+ cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset,
+ dev->cow.bitmap_len);
+
return(0);
}
int err, n;
if(thread_fd == -1){
- while(!list_empty(&q->queue_head)){
+ while(!elv_queue_empty(q)){
req = elv_next_request(q);
err = prepare_request(req, &io_req);
if(!err){
}
}
else {
- if(do_ubd || list_empty(&q->queue_head)) return;
+ if(do_ubd || elv_queue_empty(q))
+ return;
req = elv_next_request(q);
err = prepare_request(req, &io_req);
if(!err){
g.heads = 128;
g.sectors = 32;
g.cylinders = dev->size / (128 * 32 * 512);
- g.start = 2;
+ g.start = get_start_sect(inode->i_bdev);
return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0);
case HDIO_SET_UNMASKINTR:
return(-EINVAL);
}
+static int ubd_check_remapped(int fd, unsigned long address, int is_write,
+ __u64 offset)
+{
+ __u64 bitmap_offset;
+ unsigned long new_bitmap[2];
+ int i, err, n;
+
+ /* If it's not a write access, we can't do anything about it */
+ if(!is_write)
+ return(0);
+
+ /* We have a write */
+ for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
+ struct ubd *dev = &ubd_dev[i];
+
+ if((dev->fd != fd) && (dev->cow.fd != fd))
+ continue;
+
+ /* It's a write to a ubd device */
+
+ if(!dev->openflags.w){
+ /* It's a write access on a read-only device - probably
+ * shouldn't happen. If the kernel is trying to change
+ * something with no intention of writing it back out,
+ * then this message will clue us in that this needs
+ * fixing
+ */
+ printk("Write access to mapped page from readonly ubd "
+ "device %d\n", i);
+ return(0);
+ }
+
+ /* It's a write to a writeable ubd device - it must be COWed
+ * because, otherwise, the page would have been mapped in
+ * writeable
+ */
+
+ if(!dev->cow.file)
+ panic("Write fault on writeable non-COW ubd device %d",
+ i);
+
+ /* It should also be an access to the backing file since the
+ * COW pages should be mapped in read-write
+ */
+
+ if(fd == dev->fd)
+ panic("Write fault on a backing page of ubd "
+ "device %d\n", i);
+
+ /* So, we do the write, copying the backing data to the COW
+ * file...
+ */
+
+ err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
+ if(err < 0)
+ panic("Couldn't seek to %lld in COW file of ubd "
+ "device %d, err = %d",
+ offset + dev->cow.data_offset, i, -err);
+
+ n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
+ if(n != PAGE_SIZE)
+ panic("Couldn't copy data to COW file of ubd "
+ "device %d, err = %d", i, -n);
+
+ /* ... updating the COW bitmap... */
+
+ cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
+ dev->cow.bitmap, dev->cow.bitmap_offset,
+ new_bitmap, dev->cow.bitmap_len);
+
+ err = os_seek_file(dev->fd, bitmap_offset);
+ if(err < 0)
+ panic("Couldn't seek to %lld in COW file of ubd "
+ "device %d, err = %d", bitmap_offset, i, -err);
+
+ n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
+ if(n != sizeof(new_bitmap))
+ panic("Couldn't update bitmap of ubd device %d, "
+ "err = %d", i, -n);
+
+ /* Maybe we can map the COW page in, and maybe we can't. If
+ * it is a pre-V3 COW file, we can't, since the alignment will
+ * be wrong. If it is a V3 or later COW file which has been
+ * moved to a system with a larger page size, then maybe we
+ * can't, depending on the exact location of the page.
+ */
+
+ offset += dev->cow.data_offset;
+
+ /* Remove the remapping, putting the original anonymous page
+ * back. If the COW file can be mapped in, that is done.
+ * Otherwise, the COW page is read in.
+ */
+
+ if(!physmem_remove_mapping((void *) address))
+ panic("Address 0x%lx not remapped by ubd device %d",
+ address, i);
+ if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
+ physmem_subst_mapping((void *) address, dev->fd,
+ offset, 1);
+ else {
+ err = os_seek_file(dev->fd, offset);
+ if(err < 0)
+ panic("Couldn't seek to %lld in COW file of "
+ "ubd device %d, err = %d", offset, i,
+ -err);
+
+ n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
+ if(n != PAGE_SIZE)
+ panic("Failed to read page from offset %llx of "
+ "COW file of ubd device %d, err = %d",
+ offset, i, -n);
+ }
+
+ return(1);
+ }
+
+ /* It's not a write on a ubd device */
+ return(0);
+}
+
+static struct remapper ubd_remapper = {
+ .list = LIST_HEAD_INIT(ubd_remapper.list),
+ .proc = ubd_check_remapped,
+};
+
+static int ubd_remapper_setup(void)
+{
+ if(ubd_do_mmap)
+ register_remapper(&ubd_remapper);
+
+ return(0);
+}
+
+__initcall(ubd_remapper_setup);
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
#include <signal.h>
#include <string.h>
#include <netinet/in.h>
-#include <sys/stat.h>
#include <sys/time.h>
-#include <sys/fcntl.h>
#include <sys/socket.h>
-#include <string.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>
-#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 "__BYTE_ORDER not defined"
-#endif
-
-#define PATH_LEN_V1 256
-
-struct cow_header_v1 {
- int magic;
- int version;
- char backing_file[PATH_LEN_V1];
- time_t mtime;
- __u64 size;
- int sectorsize;
-};
-
-#define PATH_LEN_V2 MAXPATHLEN
-
-struct cow_header_v2 {
- unsigned long magic;
- unsigned long version;
- char backing_file[PATH_LEN_V2];
- time_t mtime;
- __u64 size;
- int sectorsize;
-};
-
-union cow_header {
- struct cow_header_v1 v1;
- struct cow_header_v2 v2;
-};
-
-#define COW_MAGIC 0x4f4f4f4d /* MOOO */
-#define COW_VERSION 2
-
-static void sizes(__u64 size, int sectorsize, int bitmap_offset,
- unsigned long *bitmap_len_out, int *data_offset_out)
-{
- *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize);
-
- *data_offset_out = bitmap_offset + *bitmap_len_out;
- *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize;
- *data_offset_out *= sectorsize;
-}
-
-static int read_cow_header(int fd, int *magic_out, char **backing_file_out,
- time_t *mtime_out, __u64 *size_out,
- int *sectorsize_out, int *bitmap_offset_out)
-{
- union cow_header *header;
- char *file;
- int err, n;
- unsigned long version, magic;
-
- header = um_kmalloc(sizeof(*header));
- if(header == NULL){
- printk("read_cow_header - Failed to allocate header\n");
- return(-ENOMEM);
- }
- err = -EINVAL;
- n = read(fd, header, sizeof(*header));
- if(n < offsetof(typeof(header->v1), backing_file)){
- printk("read_cow_header - short header\n");
- goto out;
- }
-
- magic = header->v1.magic;
- if(magic == COW_MAGIC) {
- version = header->v1.version;
- }
- else if(magic == ntohl(COW_MAGIC)){
- version = ntohl(header->v1.version);
- }
- else goto out;
-
- *magic_out = COW_MAGIC;
-
- if(version == 1){
- if(n < sizeof(header->v1)){
- printk("read_cow_header - failed to read V1 header\n");
- goto out;
- }
- *mtime_out = header->v1.mtime;
- *size_out = header->v1.size;
- *sectorsize_out = header->v1.sectorsize;
- *bitmap_offset_out = sizeof(header->v1);
- file = header->v1.backing_file;
- }
- else if(version == 2){
- if(n < sizeof(header->v2)){
- printk("read_cow_header - failed to read V2 header\n");
- goto out;
- }
- *mtime_out = ntohl(header->v2.mtime);
- *size_out = ntohll(header->v2.size);
- *sectorsize_out = ntohl(header->v2.sectorsize);
- *bitmap_offset_out = sizeof(header->v2);
- file = header->v2.backing_file;
- }
- else {
- printk("read_cow_header - invalid COW version\n");
- goto out;
- }
- err = -ENOMEM;
- *backing_file_out = uml_strdup(file);
- if(*backing_file_out == NULL){
- printk("read_cow_header - failed to allocate backing file\n");
- goto out;
- }
- err = 0;
- out:
- kfree(header);
- return(err);
-}
static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
{
- struct stat buf1, buf2;
+ struct uml_stat buf1, buf2;
+ int err;
if(from_cmdline == NULL) return(1);
if(!strcmp(from_cmdline, from_cow)) return(1);
- if(stat(from_cmdline, &buf1) < 0){
- printk("Couldn't stat '%s', errno = %d\n", from_cmdline,
- errno);
+ err = os_stat_file(from_cmdline, &buf1);
+ if(err < 0){
+ printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err);
return(1);
}
- if(stat(from_cow, &buf2) < 0){
- printk("Couldn't stat '%s', errno = %d\n", from_cow, errno);
+ err = os_stat_file(from_cow, &buf2);
+ if(err < 0){
+ printk("Couldn't stat '%s', err = %d\n", from_cow, -err);
return(1);
}
- if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino))
+ if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino))
return(1);
printk("Backing file mismatch - \"%s\" requested,\n"
static int backing_file_mismatch(char *file, __u64 size, time_t mtime)
{
- struct stat64 buf;
+ unsigned long modtime;
long long actual;
int err;
- if(stat64(file, &buf) < 0){
- printk("Failed to stat backing file \"%s\", errno = %d\n",
- file, errno);
- return(-errno);
+ err = os_file_modtime(file, &modtime);
+ if(err < 0){
+ printk("Failed to get modification time of backing file "
+ "\"%s\", err = %d\n", file, -err);
+ return(err);
}
err = os_file_size(file, &actual);
- if(err){
+ if(err < 0){
printk("Failed to get size of backing file \"%s\", "
- "errno = %d\n", file, -err);
+ "err = %d\n", file, -err);
return(err);
}
"file\n", size, actual);
return(-EINVAL);
}
- if(buf.st_mtime != mtime){
+ if(modtime != mtime){
printk("mtime mismatch (%ld vs %ld) of COW header vs backing "
- "file\n", mtime, buf.st_mtime);
+ "file\n", mtime, modtime);
return(-EINVAL);
}
return(0);
int err;
err = os_seek_file(fd, offset);
- if(err != 0) return(-errno);
- err = read(fd, buf, len);
- if(err < 0) return(-errno);
- return(0);
-}
+ if(err < 0)
+ return(err);
-static int absolutize(char *to, int size, char *from)
-{
- char save_cwd[256], *slash;
- int remaining;
+ err = os_read_file(fd, buf, len);
+ if(err < 0)
+ return(err);
- if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) {
- printk("absolutize : unable to get cwd - errno = %d\n", errno);
- return(-1);
- }
- slash = strrchr(from, '/');
- if(slash != NULL){
- *slash = '\0';
- if(chdir(from)){
- *slash = '/';
- printk("absolutize : Can't cd to '%s' - errno = %d\n",
- from, errno);
- return(-1);
- }
- *slash = '/';
- if(getcwd(to, size) == NULL){
- printk("absolutize : unable to get cwd of '%s' - "
- "errno = %d\n", from, errno);
- return(-1);
- }
- remaining = size - strlen(to);
- if(strlen(slash) + 1 > remaining){
- printk("absolutize : unable to fit '%s' into %d "
- "chars\n", from, size);
- return(-1);
- }
- strcat(to, slash);
- }
- else {
- if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){
- printk("absolutize : unable to fit '%s' into %d "
- "chars\n", from, size);
- return(-1);
- }
- strcpy(to, save_cwd);
- strcat(to, "/");
- strcat(to, from);
- }
- chdir(save_cwd);
return(0);
}
-static int write_cow_header(char *cow_file, int fd, char *backing_file,
- int sectorsize, long long *size)
-{
- struct cow_header_v2 *header;
- struct stat64 buf;
- int err;
-
- err = os_seek_file(fd, 0);
- if(err != 0){
- printk("write_cow_header - lseek failed, errno = %d\n", errno);
- return(-errno);
- }
-
- err = -ENOMEM;
- header = um_kmalloc(sizeof(*header));
- if(header == NULL){
- printk("Failed to allocate COW V2 header\n");
- goto out;
- }
- header->magic = htonl(COW_MAGIC);
- header->version = htonl(COW_VERSION);
-
- err = -EINVAL;
- if(strlen(backing_file) > sizeof(header->backing_file) - 1){
- printk("Backing file name \"%s\" is too long - names are "
- "limited to %d characters\n", backing_file,
- sizeof(header->backing_file) - 1);
- goto out_free;
- }
-
- if(absolutize(header->backing_file, sizeof(header->backing_file),
- backing_file))
- goto out_free;
-
- err = stat64(header->backing_file, &buf);
- if(err < 0){
- printk("Stat of backing file '%s' failed, errno = %d\n",
- header->backing_file, errno);
- err = -errno;
- goto out_free;
- }
-
- err = os_file_size(header->backing_file, size);
- if(err){
- printk("Couldn't get size of backing file '%s', errno = %d\n",
- header->backing_file, -*size);
- goto out_free;
- }
-
- header->mtime = htonl(buf.st_mtime);
- header->size = htonll(*size);
- header->sectorsize = htonl(sectorsize);
-
- err = write(fd, header, sizeof(*header));
- if(err != sizeof(*header)){
- printk("Write of header to new COW file '%s' failed, "
- "errno = %d\n", cow_file, errno);
- goto out_free;
- }
- err = 0;
- out_free:
- kfree(header);
- out:
- return(err);
-}
-
int open_ubd_file(char *file, struct openflags *openflags,
char **backing_file_out, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out,
{
time_t mtime;
__u64 size;
+ __u32 version, align;
char *backing_file;
- int fd, err, sectorsize, magic, same, mode = 0644;
+ int fd, err, sectorsize, same, mode = 0644;
- if((fd = os_open_file(file, *openflags, mode)) < 0){
+ fd = os_open_file(file, *openflags, mode);
+ if(fd < 0){
if((fd == -ENOENT) && (create_cow_out != NULL))
*create_cow_out = 1;
if(!openflags->w ||
((errno != EROFS) && (errno != EACCES))) return(-errno);
openflags->w = 0;
- if((fd = os_open_file(file, *openflags, mode)) < 0)
+ fd = os_open_file(file, *openflags, mode);
+ if(fd < 0)
return(fd);
}
+
+ err = os_lock_file(fd, openflags->w);
+ if(err < 0){
+ printk("Failed to lock '%s', err = %d\n", file, -err);
+ goto out_close;
+ }
+
if(backing_file_out == NULL) return(fd);
- err = read_cow_header(fd, &magic, &backing_file, &mtime, &size,
- §orsize, bitmap_offset_out);
+ err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime,
+ &size, §orsize, &align, bitmap_offset_out);
if(err && (*backing_file_out != NULL)){
printk("Failed to read COW header from COW file \"%s\", "
- "errno = %d\n", file, err);
- goto error;
+ "errno = %d\n", file, -err);
+ goto out_close;
}
if(err) return(fd);
if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){
printk("Switching backing file to '%s'\n", *backing_file_out);
- err = write_cow_header(file, fd, *backing_file_out,
- sectorsize, &size);
+ err = write_cow_header(file, fd, *backing_file_out,
+ sectorsize, align, &size);
if(err){
- printk("Switch failed, errno = %d\n", err);
+ printk("Switch failed, errno = %d\n", -err);
return(err);
}
}
else {
*backing_file_out = backing_file;
err = backing_file_mismatch(*backing_file_out, size, mtime);
- if(err) goto error;
+ if(err) goto out_close;
}
- sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out,
- data_offset_out);
+ cow_sizes(version, size, sectorsize, align, *bitmap_offset_out,
+ bitmap_len_out, data_offset_out);
return(fd);
- error:
- close(fd);
+ out_close:
+ os_close_file(fd);
return(err);
}
int create_cow_file(char *cow_file, char *backing_file, struct openflags flags,
- int sectorsize, int *bitmap_offset_out,
+ int sectorsize, int alignment, int *bitmap_offset_out,
unsigned long *bitmap_len_out, int *data_offset_out)
{
- __u64 blocks;
- long zero;
- int err, fd, i;
- long long size;
+ int err, fd;
flags.c = 1;
fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL);
goto out;
}
- err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size);
- if(err) goto out_close;
-
- blocks = (size + sectorsize - 1) / sectorsize;
- blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8);
- zero = 0;
- for(i = 0; i < blocks; i++){
- err = write(fd, &zero, sizeof(zero));
- if(err != sizeof(zero)){
- printk("Write of bitmap to new COW file '%s' failed, "
- "errno = %d\n", cow_file, errno);
- goto out_close;
- }
- }
-
- sizes(size, sectorsize, sizeof(struct cow_header_v2),
- bitmap_len_out, data_offset_out);
- *bitmap_offset_out = sizeof(struct cow_header_v2);
-
- return(fd);
-
- out_close:
- close(fd);
+ err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment,
+ bitmap_offset_out, bitmap_len_out,
+ data_offset_out);
+ if(!err)
+ return(fd);
+ os_close_file(fd);
out:
return(err);
}
+/* XXX Just trivial wrappers around os_read_file and os_write_file */
int read_ubd_fs(int fd, void *buffer, int len)
{
- int n;
-
- n = read(fd, buffer, len);
- if(n < 0) return(-errno);
- else return(n);
+ return(os_read_file(fd, buffer, len));
}
int write_ubd_fs(int fd, char *buffer, int len)
{
- int n;
-
- n = write(fd, buffer, len);
- if(n < 0) return(-errno);
- else return(n);
+ return(os_write_file(fd, buffer, len));
}
-int ubd_is_dir(char *file)
+static int update_bitmap(struct io_thread_req *req)
{
- struct stat64 buf;
+ int n;
+
+ if(req->cow_offset == -1)
+ return(0);
+
+ n = os_seek_file(req->fds[1], req->cow_offset);
+ if(n < 0){
+ printk("do_io - bitmap lseek failed : err = %d\n", -n);
+ return(1);
+ }
+
+ n = os_write_file(req->fds[1], &req->bitmap_words,
+ sizeof(req->bitmap_words));
+ if(n != sizeof(req->bitmap_words)){
+ printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
+ req->fds[1]);
+ return(1);
+ }
- if(stat64(file, &buf) < 0) return(0);
- return(S_ISDIR(buf.st_mode));
+ return(0);
}
void do_io(struct io_thread_req *req)
char *buf;
unsigned long len;
int n, nsectors, start, end, bit;
+ int err;
__u64 off;
+ if(req->op == UBD_MMAP){
+ /* Touch the page to force the host to do any necessary IO to
+ * get it into memory
+ */
+ n = *((volatile int *) req->buffer);
+ req->error = update_bitmap(req);
+ return;
+ }
+
nsectors = req->length / req->sectorsize;
start = 0;
do {
&req->sector_mask) == bit))
end++;
- if(end != nsectors)
- printk("end != nsectors\n");
off = req->offset + req->offsets[bit] +
start * req->sectorsize;
len = (end - start) * req->sectorsize;
buf = &req->buffer[start * req->sectorsize];
- if(os_seek_file(req->fds[bit], off) != 0){
- printk("do_io - lseek failed : errno = %d\n", errno);
+ err = os_seek_file(req->fds[bit], off);
+ if(err < 0){
+ printk("do_io - lseek failed : err = %d\n", -err);
req->error = 1;
return;
}
do {
buf = &buf[n];
len -= n;
- n = read(req->fds[bit], buf, len);
+ n = os_read_file(req->fds[bit], buf, len);
if (n < 0) {
- printk("do_io - read returned %d : "
- "errno = %d fd = %d\n", n,
- errno, req->fds[bit]);
+ printk("do_io - read failed, err = %d "
+ "fd = %d\n", -n, req->fds[bit]);
req->error = 1;
return;
}
if (n < len) memset(&buf[n], 0, len - n);
}
else {
- n = write(req->fds[bit], buf, len);
+ n = os_write_file(req->fds[bit], buf, len);
if(n != len){
- printk("do_io - write returned %d : "
- "errno = %d fd = %d\n", n,
- errno, req->fds[bit]);
+ printk("do_io - write failed err = %d "
+ "fd = %d\n", -n, req->fds[bit]);
req->error = 1;
return;
}
start = end;
} while(start < nsectors);
- if(req->cow_offset != -1){
- if(os_seek_file(req->fds[1], req->cow_offset) != 0){
- printk("do_io - bitmap lseek failed : errno = %d\n",
- errno);
- req->error = 1;
- return;
- }
- n = write(req->fds[1], &req->bitmap_words,
- sizeof(req->bitmap_words));
- if(n != sizeof(req->bitmap_words)){
- printk("do_io - bitmap update returned %d : "
- "errno = %d fd = %d\n", n, errno, req->fds[1]);
- req->error = 1;
- return;
- }
- }
- req->error = 0;
- return;
+ req->error = update_bitmap(req);
}
/* Changed in start_io_thread, which is serialized by being called only
signal(SIGWINCH, SIG_IGN);
while(1){
- n = read(kernel_fd, &req, sizeof(req));
- if(n < 0) printk("io_thread - read returned %d, errno = %d\n",
- n, errno);
- else if(n < sizeof(req)){
- printk("io_thread - short read : length = %d\n", n);
+ n = os_read_file(kernel_fd, &req, sizeof(req));
+ if(n != sizeof(req)){
+ if(n < 0)
+ printk("io_thread - read failed, fd = %d, "
+ "err = %d\n", kernel_fd, -n);
+ else {
+ printk("io_thread - short read, fd = %d, "
+ "length = %d\n", kernel_fd, n);
+ }
continue;
}
io_count++;
do_io(&req);
- n = write(kernel_fd, &req, sizeof(req));
+ n = os_write_file(kernel_fd, &req, sizeof(req));
if(n != sizeof(req))
- printk("io_thread - write failed, errno = %d\n",
- errno);
+ printk("io_thread - write failed, fd = %d, err = %d\n",
+ kernel_fd, -n);
}
}
int pid, fds[2], err;
err = os_pipe(fds, 1, 1);
- if(err){
- printk("start_io_thread - os_pipe failed, errno = %d\n", -err);
- return(-1);
+ if(err < 0){
+ printk("start_io_thread - os_pipe failed, err = %d\n", -err);
+ goto out;
}
+
kernel_fd = fds[0];
*fd_out = fds[1];
NULL);
if(pid < 0){
printk("start_io_thread - clone failed : errno = %d\n", errno);
- return(-errno);
- }
- return(pid);
-}
-
-#ifdef notdef
-int start_io_thread(unsigned long sp, int *fd_out)
-{
- int pid;
-
- if((kernel_fd = get_pty()) < 0) return(-1);
- raw(kernel_fd, 0);
- if((*fd_out = open(ptsname(kernel_fd), O_RDWR)) < 0){
- printk("Couldn't open tty for IO\n");
- return(-1);
+ goto out_close;
}
- pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD,
- NULL);
- if(pid < 0){
- printk("start_io_thread - clone failed : errno = %d\n", errno);
- return(-errno);
- }
return(pid);
+
+ out_close:
+ os_close_file(fds[0]);
+ os_close_file(fds[1]);
+ kernel_fd = -1;
+ *fd_out = -1;
+ out:
+ return(err);
}
-#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
#include <unistd.h>
#include <string.h>
#include <errno.h>
-#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <sched.h>
{
struct xterm_chan *data;
- if((data = malloc(sizeof(*data))) == NULL) return(NULL);
+ data = malloc(sizeof(*data));
+ if(data == NULL) return(NULL);
*data = ((struct xterm_chan) { .pid = -1,
.helper_pid = -1,
.device = device,
"/usr/lib/uml/port-helper", "-uml-socket",
file, NULL };
- if(access(argv[4], X_OK))
+ if(os_access(argv[4], OS_ACC_X_OK) < 0)
argv[4] = "port-helper";
fd = mkstemp(file);
printk("xterm_open : unlink failed, errno = %d\n", errno);
return(-errno);
}
- close(fd);
+ os_close_file(fd);
- fd = create_unix_socket(file, sizeof(file));
+ fd = os_create_unix_socket(file, sizeof(file), 1);
if(fd < 0){
printk("xterm_open : create_unix_socket failed, errno = %d\n",
-fd);
- return(-fd);
+ return(fd);
}
sprintf(title, data->title, data->device);
if(data->direct_rcv)
new = os_rcv_fd(fd, &data->helper_pid);
else {
- if((err = os_set_fd_block(fd, 0)) != 0){
+ err = os_set_fd_block(fd, 0);
+ if(err < 0){
printk("xterm_open : failed to set descriptor "
- "non-blocking, errno = %d\n", err);
+ "non-blocking, err = %d\n", -err);
return(err);
}
new = xterm_fd(fd, &data->helper_pid);
}
if(new < 0){
- printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new);
+ printk("xterm_open : os_rcv_fd failed, err = %d\n", -new);
goto out;
}
if(data->helper_pid != -1)
os_kill_process(data->helper_pid, 0);
data->helper_pid = -1;
- close(fd);
+ os_close_file(fd);
}
void xterm_free(void *d)
#include "linux/errno.h"
#include "linux/slab.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
#include "asm/semaphore.h"
#include "asm/irq.h"
#include "irq_user.h"
+#include "irq_kern.h"
#include "kern_util.h"
#include "os.h"
#include "xterm.h"
int new_fd;
};
-static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct xterm_wait *xterm = data;
int fd;
fd = os_rcv_fd(xterm->fd, &xterm->pid);
if(fd == -EAGAIN)
- return;
+ return(IRQ_NONE);
xterm->new_fd = fd;
up(&xterm->sem);
+ return(IRQ_HANDLED);
}
int xterm_fd(int socket, int *pid_out)
if(err){
printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, "
"err = %d\n", err);
- return(err);
+ ret = err;
+ goto out;
}
down(&data->sem);
ret = data->new_fd;
*pid_out = data->pid;
+ out:
kfree(data);
return(ret);
+#include <asm-generic/vmlinux.lds.h>
+
OUTPUT_FORMAT(ELF_FORMAT)
OUTPUT_ARCH(ELF_ARCH)
ENTRY(_start)
{
. = START + SIZEOF_HEADERS;
.interp : { *(.interp) }
- . = ALIGN(4096);
__binary_start = .;
. = ALIGN(4096); /* Init code and data */
_stext = .;
__init_begin = .;
- .text.init : { *(.text.init) }
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
. = ALIGN(4096);
} =0x90909090
.plt : { *(.plt) }
.text : {
- *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.text)
+ SCHED_TEXT
+ *(.stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
#include "asm/common.lds.S"
- .data.init : { *(.data.init) }
+ init.data : { *(.init.data) }
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
#ifndef __2_5_COMPAT_H__
#define __2_5_COMPAT_H__
-#include "linux/version.h"
-
-#define INIT_CONSOLE(dev_name, write_proc, device_proc, setup_proc, f) { \
- name : dev_name, \
- write : write_proc, \
- read : NULL, \
- device : device_proc, \
- setup : setup_proc, \
- flags : f, \
- index : -1, \
- cflag : 0, \
- next : NULL \
-}
-
#define INIT_HARDSECT(arr, maj, sizes)
#define SET_PRI(task) do ; while(0)
extern void paging_init(void);
extern void init_flush_vm(void);
extern void *syscall_sp(void *t);
-extern void syscall_trace(void);
+extern void syscall_trace(union uml_pt_regs *regs, int entryexit);
extern int hz(void);
-extern void idle_timer(void);
+extern void uml_idle_timer(void);
extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs);
extern int external_pid(void *t);
-extern int pid_to_processor_id(int pid);
extern void boot_timer_handler(int sig);
extern void interrupt_end(void);
extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern char *uml_strdup(char *string);
extern void unprotect_kernel_mem(void);
extern void protect_kernel_mem(void);
-extern void set_kmem_end(unsigned long);
extern void uml_cleanup(void);
-extern int pid_to_processor_id(int pid);
extern void set_current(void *t);
extern void lock_signalled_task(void *t);
extern void IPI_handler(int cpu);
extern int clear_user_proc(void *buf, int size);
extern int copy_to_user_proc(void *to, void *from, int size);
extern int copy_from_user_proc(void *to, void *from, int size);
+extern int strlen_user_proc(char *str);
extern void bus_handler(int sig, union uml_pt_regs *regs);
+extern void winch(int sig, union uml_pt_regs *regs);
extern long execute_syscall(void *r);
extern int smp_sigio_handler(void);
extern void *get_current(void);
extern void free_irq(unsigned int, void *);
extern int um_in_interrupt(void);
extern int cpu(void);
+extern unsigned long long time_stamp(void);
+
#endif
/*
#include "linux/list.h"
#include "linux/workqueue.h"
#include "linux/tty.h"
+#include "linux/interrupt.h"
#include "asm/semaphore.h"
#include "chan_user.h"
#include "mconsole_kern.h"
struct line_driver {
char *name;
+ char *device_name;
char *devfs_name;
short major;
short minor_start;
#define LINES_INIT(n) { num : n }
-extern void line_interrupt(int irq, void *data, struct pt_regs *unused);
-extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
extern void line_close(struct line *lines, struct tty_struct *tty);
extern int line_open(struct line *lines, struct tty_struct *tty,
struct chan_opts *opts);
struct mc_request;
+enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC };
+
struct mconsole_command
{
char *command;
void (*handler)(struct mc_request *req);
- int as_interrupt;
+ enum mc_context context;
};
struct mc_request
extern void mconsole_cad(struct mc_request *req);
extern void mconsole_stop(struct mc_request *req);
extern void mconsole_go(struct mc_request *req);
+extern void mconsole_log(struct mc_request *req);
+extern void mconsole_proc(struct mc_request *req);
extern int mconsole_get_request(int fd, struct mc_request *req);
extern int mconsole_notify(char *sock_name, int type, const void *data,
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#ifndef __MEM_H__
#define __MEM_H__
-struct vm_reserved {
- struct list_head list;
- unsigned long start;
- unsigned long end;
-};
+#include "linux/types.h"
-extern void set_usable_vm(unsigned long start, unsigned long end);
-extern void set_kmem_end(unsigned long new);
+extern int phys_mapping(unsigned long phys, __u64 *offset_out);
+extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w);
+extern int is_remapped(void *virt);
+extern int physmem_remove_mapping(void *virt);
+extern void physmem_forget_descriptor(int fd);
#endif
#ifndef _MEM_USER_H
#define _MEM_USER_H
-struct mem_region {
+struct iomem_region {
+ struct iomem_region *next;
char *driver;
- unsigned long start_pfn;
- unsigned long start;
- unsigned long len;
- void *mem_map;
int fd;
+ int size;
+ unsigned long phys;
+ unsigned long virt;
};
-extern struct mem_region *regions[];
-extern struct mem_region physmem_region;
+extern struct iomem_region *iomem_regions;
+extern int iomem_size;
#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
extern unsigned long host_task_size;
extern unsigned long task_size;
+extern void check_devanon(void);
extern int init_mem_user(void);
extern int create_mem_file(unsigned long len);
-extern void setup_range(int fd, char *driver, unsigned long start,
- unsigned long pfn, unsigned long total, int need_vm,
- struct mem_region *region, void *reserved);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-extern int init_maps(struct mem_region *region);
-extern int nregions(void);
-extern int reserve_vm(unsigned long start, unsigned long end, void *e);
+extern int init_maps(unsigned long physmem, unsigned long iomem,
+ unsigned long highmem);
extern unsigned long get_vm(unsigned long len);
extern void setup_physmem(unsigned long start, unsigned long usable,
- unsigned long len);
-extern int setup_region(struct mem_region *region, void *entry);
+ unsigned long len, unsigned long highmem);
extern void add_iomem(char *name, int fd, unsigned long size);
-extern struct mem_region *phys_region(unsigned long phys);
extern unsigned long phys_offset(unsigned long phys);
extern void unmap_physmem(void);
-extern int map_memory(unsigned long virt, unsigned long phys,
- unsigned long len, int r, int w, int x);
+extern void map_memory(unsigned long virt, unsigned long phys,
+ unsigned long len, int r, int w, int x);
extern int protect_memory(unsigned long addr, unsigned long len,
int r, int w, int x, int must_succeed);
extern unsigned long get_kmem_end(void);
#define OS_TYPE_FIFO 6
#define OS_TYPE_SOCK 7
+/* os_access() flags */
+#define OS_ACC_F_OK 0 /* Test for existence. */
+#define OS_ACC_X_OK 1 /* Test for execute permission. */
+#define OS_ACC_W_OK 2 /* Test for write permission. */
+#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 */
+
+/*
+ * types taken from stat_file() in hostfs_user.c
+ * (if they are wrong here, they are wrong there...).
+ */
+struct uml_stat {
+ int ust_dev; /* device */
+ unsigned long long ust_ino; /* inode */
+ int ust_mode; /* protection */
+ int ust_nlink; /* number of hard links */
+ int ust_uid; /* user ID of owner */
+ int ust_gid; /* group ID of owner */
+ unsigned long long ust_size; /* total size, in bytes */
+ int ust_blksize; /* blocksize for filesystem I/O */
+ unsigned long long ust_blocks; /* number of blocks allocated */
+ unsigned long ust_atime; /* time of last access */
+ unsigned long ust_mtime; /* time of last modification */
+ unsigned long ust_ctime; /* time of last change */
+};
+
struct openflags {
unsigned int r : 1;
unsigned int w : 1;
flags.e = 1;
return(flags);
}
-
+
static inline struct openflags of_cloexec(struct openflags flags)
{
flags.cl = 1;
return(flags);
}
+extern int os_stat_file(const char *file_name, struct uml_stat *buf);
+extern int os_stat_fd(const int fd, struct uml_stat *buf);
+extern int os_access(const char *file, int mode);
+extern void os_print_error(int error, const char* str);
+extern int os_get_exec_close(int fd, int *close_on_exec);
+extern int os_set_exec_close(int fd, int close_on_exec);
+extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
+extern int os_window_size(int fd, int *rows, int *cols);
+extern int os_new_tty_pgrp(int fd, int pid);
+extern int os_get_ifname(int fd, char *namebuf);
+extern int os_set_slip(int fd);
+extern int os_set_owner(int fd, int pid);
+extern int os_sigio_async(int master, int slave);
+extern int os_mode_fd(int fd, int mode);
+
extern int os_seek_file(int fd, __u64 offset);
extern int os_open_file(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, void *buf, int count);
+extern int os_write_file(int fd, const void *buf, int count);
extern int os_file_size(char *file, long long *size_out);
+extern int os_file_modtime(char *file, unsigned long *modtime);
extern int os_pipe(int *fd, int stream, int close_on_exec);
extern int os_set_fd_async(int fd, int owner);
extern int os_set_fd_block(int fd, int blocking);
extern int os_accept_connection(int fd);
+extern int os_create_unix_socket(char *file, int len, int close_on_exec);
extern int os_shutdown_socket(int fd, int r, int w);
extern void os_close_file(int fd);
extern int os_rcv_fd(int fd, int *helper_pid_out);
-extern int create_unix_socket(char *file, int len);
+extern int create_unix_socket(char *file, int len, int close_on_exec);
extern int os_connect_socket(char *name);
extern int os_file_type(char *file);
extern int os_file_mode(char *file, struct openflags *mode_out);
+extern int os_lock_file(int fd, int excl);
extern unsigned long os_process_pc(int pid);
extern int os_process_parent(int pid);
extern void os_usr1_process(int pid);
extern int os_getpid(void);
-extern int os_map_memory(void *virt, int fd, unsigned long off,
+extern int os_map_memory(void *virt, int fd, unsigned long long off,
unsigned long len, int r, int w, int x);
extern int os_protect_memory(void *addr, unsigned long len,
int r, int w, int x);
extern int os_unmap_memory(void *addr, int len);
+extern void os_flush_stdout(void);
#endif
extern int change_sig(int signal, int on);
extern void set_sigstack(void *stack, int size);
extern void set_handler(int sig, void (*handler)(int), int flags, ...);
+extern int set_signals(int enable);
+extern int get_signals(void);
#endif
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
* it would have to be __builtin_frame_address(1).
*/
-static inline unsigned long frame_restorer(void)
-{
- unsigned long *fp;
-
- fp = __builtin_frame_address(0);
- return((unsigned long) (fp + 1));
-}
+#define frame_restorer() \
+({ \
+ unsigned long *fp; \
+\
+ fp = __builtin_frame_address(0); \
+ ((unsigned long) (fp + 1)); \
+})
/* Similarly, this returns the value of sp when the handler was first
* entered. This is used to calculate the proper sp when delivering
* signals.
*/
-static inline unsigned long frame_sp(void)
-{
- unsigned long *fp;
-
- fp = __builtin_frame_address(0);
- return((unsigned long) (fp + 1));
-}
+#define frame_sp() \
+({ \
+ unsigned long *fp; \
+\
+ fp = __builtin_frame_address(0); \
+ ((unsigned long) (fp + 1)); \
+})
#endif
*/
#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
-/* These are General Protection and Page Fault */
-#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
+/* This is Page Fault */
+#define SEGV_IS_FIXABLE(trap) (trap == 14)
#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
#define EXECUTE_SYSCALL(syscall, regs) \
((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs))
-extern syscall_handler_t sys_modify_ldt;
-extern syscall_handler_t old_mmap_i386;
-extern syscall_handler_t old_select;
-extern syscall_handler_t sys_ni_syscall;
-
#define ARCH_SYSCALLS \
- [ __NR_mmap ] = old_mmap_i386, \
- [ __NR_select ] = old_select, \
- [ __NR_vm86old ] = sys_ni_syscall, \
- [ __NR_modify_ldt ] = sys_modify_ldt, \
- [ __NR_lchown32 ] = sys_lchown, \
- [ __NR_getuid32 ] = sys_getuid, \
- [ __NR_getgid32 ] = sys_getgid, \
- [ __NR_geteuid32 ] = sys_geteuid, \
- [ __NR_getegid32 ] = sys_getegid, \
- [ __NR_setreuid32 ] = sys_setreuid, \
- [ __NR_setregid32 ] = sys_setregid, \
- [ __NR_getgroups32 ] = sys_getgroups, \
- [ __NR_setgroups32 ] = sys_setgroups, \
- [ __NR_fchown32 ] = sys_fchown, \
- [ __NR_setresuid32 ] = sys_setresuid, \
- [ __NR_getresuid32 ] = sys_getresuid, \
- [ __NR_setresgid32 ] = sys_setresgid, \
- [ __NR_getresgid32 ] = sys_getresgid, \
- [ __NR_chown32 ] = sys_chown, \
- [ __NR_setuid32 ] = sys_setuid, \
- [ __NR_setgid32 ] = sys_setgid, \
- [ __NR_setfsuid32 ] = sys_setfsuid, \
- [ __NR_setfsgid32 ] = sys_setfsgid, \
- [ __NR_pivot_root ] = sys_pivot_root, \
- [ __NR_mincore ] = sys_mincore, \
- [ __NR_madvise ] = sys_madvise, \
- [ 222 ] = sys_ni_syscall,
+ [ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \
+ [ __NR_select ] = (syscall_handler_t *) old_select, \
+ [ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \
+ [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \
+ [ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \
+ [ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \
+ [ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \
+ [ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \
+ [ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \
+ [ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \
+ [ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \
+ [ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \
+ [ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \
+ [ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \
+ [ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \
+ [ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \
+ [ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \
+ [ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \
+ [ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \
+ [ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \
+ [ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \
+ [ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \
+ [ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \
+ [ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \
+ [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \
+ [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \
+ [ 222 ] = (syscall_handler_t *) sys_ni_syscall,
/* 222 doesn't yet have a name in include/asm-i386/unistd.h */
#include "os.h"
-enum ubd_req { UBD_READ, UBD_WRITE };
+enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
struct io_thread_req {
enum ubd_req op;
char *buffer;
int sectorsize;
unsigned long sector_mask;
- unsigned long cow_offset;
+ unsigned long long cow_offset;
unsigned long bitmap_words[2];
+ int map_fd;
+ unsigned long long map_offset;
int error;
};
int *create_cow_out);
extern int create_cow_file(char *cow_file, char *backing_file,
struct openflags flags, int sectorsize,
- int *bitmap_offset_out,
+ int alignment, int *bitmap_offset_out,
unsigned long *bitmap_len_out,
int *data_offset_out);
extern int read_cow_bitmap(int fd, void *buf, int offset, int len);
extern int write_ubd_fs(int fd, char *buffer, int len);
extern int start_io_thread(unsigned long sp, int *fds_out);
extern void do_io(struct io_thread_req *req);
-extern int ubd_is_dir(char *file);
static inline int ubd_test_bit(__u64 bit, unsigned char *data)
{
from, 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.
+ */
+
static inline int strncpy_from_user(char *dst, const char *src, int count)
{
return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas,
dst, src, 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.
+ */
static inline int __clear_user(void *mem, int len)
{
return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, 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.
+ */
static inline int clear_user(void *mem, int len)
{
return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, 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.
+ */
static inline int strnlen_user(const void *str, int len)
{
return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len));
extern void kfree(void *ptr);
extern int in_aton(char *str);
extern int open_gdb_chan(void);
+extern int strlcpy(char *, const char *, int);
#endif
extern int unlockpt(int __fd);
extern char *ptsname(int __fd);
-enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
-
struct cpu_task {
int pid;
void *task;
extern void *add_signal_handler(int sig, void (*handler)(int));
extern int start_fork_tramp(void *arg, unsigned long temp_stack,
int clone_flags, int (*tramp)(void *));
-extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
extern int linux_main(int argc, char **argv);
extern void set_cmdline(char *cmd);
extern void input_cb(void (*proc)(void *), void *arg, int arg_len);
extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr);
extern void write_sigio_workaround(void);
extern void arch_check_bugs(void);
+extern int cpu_feature(char *what, char *buf, int len);
extern int arch_handle_signal(int sig, union uml_pt_regs *regs);
extern int arch_fixup(unsigned long address, void *sc_ptr);
extern void forward_pending_sigio(int target);
extern int can_do_skas(void);
-
+extern void arch_init_thread(void);
+
#endif
/*
obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \
- process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
- sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \
- syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \
- time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
- umid.o user_syms.o user_util.o
+ physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
+ sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
+ syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
+ time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
+ um_arch.o umid.o user_util.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
obj-$(CONFIG_GPROF) += gprof_syms.o
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
- process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
+ process.o tempfile.o time.o tty_log.o umid.o user_util.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
-DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
-
-
-CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
- -I/usr/include -I../include
-
CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
# This has to be separate because it needs be compiled with frame pointers
# regardless of how the rest of the kernel is built.
$(obj)/frame.o: $(src)/frame.c
$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
- $(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
+QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
$(obj)/config.o : $(obj)/config.c
-clean:
- rm -f config.c
- for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
-
-modules:
-
-fastdep:
-
-dep:
-
-archmrproper: clean
+quiet_cmd_quote = QUOTE $@
+cmd_quote = $(PERL) -e $(QUOTE) < $< > $@
+targets += config.c
+$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE
+ $(call if_changed,quote)
#include <stdlib.h>
#include "init.h"
-static __initdata char *config = "
-CONFIG
-";
+static __initdata char *config = "CONFIG";
static int __init print_config(char *line, int *add)
{
CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
}
+extern void log_exec(char **argv, void *tty);
+
static int execve1(char *file, char **argv, char **env)
{
int error;
+#ifdef CONFIG_TTY_LOG
+ log_exec(argv, current->tty);
+#endif
error = do_execve(file, argv, env, ¤t->thread.regs);
if (error == 0){
current->ptrace &= ~PT_DTRACE;
struct sc_frame_raw raw_sc;
struct si_frame_raw raw_si;
void *stack, *sigstack;
- unsigned long top, sig_top, base;
+ unsigned long top, base;
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
- sig_top = (unsigned long) sigstack + PAGE_SIZE;
/* Get the sigcontext, no sigrestorer layout */
raw_sc.restorer = 0;
#include "asm/ptrace.h"
#include "asm/uaccess.h"
#include "asm/signal.h"
-#include "asm/uaccess.h"
#include "asm/ucontext.h"
#include "frame_kern.h"
#include "sigcontext.h"
sizeof(restorer)));
}
+extern int userspace_pid[];
+
static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from,
struct arch_frame_data *arch)
{
return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
arch),
- copy_sc_to_user_skas(to, fp, &from->regs,
+ copy_sc_to_user_skas(userspace_pid[0], to, fp,
+ &from->regs,
current->thread.cr2,
current->thread.err)));
}
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
-#include <fcntl.h>
#include <sched.h>
#include <sys/signal.h>
#include <sys/wait.h>
{
struct helper_data *data = arg;
char **argv = data->argv;
+ int errval;
if(helper_pause){
signal(SIGHUP, helper_hup);
if(data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
+ errval = errno;
printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
- write(data->fd, &errno, sizeof(errno));
+ os_write_file(data->fd, &errval, sizeof(errval));
os_kill_process(os_getpid(), 0);
return(0);
}
if((stack_out != NULL) && (*stack_out != 0))
stack = *stack_out;
else stack = alloc_stack(0, um_in_interrupt());
- if(stack == 0) return(-ENOMEM);
+ if(stack == 0)
+ return(-ENOMEM);
err = os_pipe(fds, 1, 0);
- if(err){
- printk("run_helper : pipe failed, errno = %d\n", -err);
- return(err);
+ if(err < 0){
+ printk("run_helper : pipe failed, err = %d\n", -err);
+ goto out_free;
}
- if(fcntl(fds[1], F_SETFD, 1) != 0){
- printk("run_helper : setting FD_CLOEXEC failed, errno = %d\n",
- errno);
- return(-errno);
+
+ err = os_set_exec_close(fds[1], 1);
+ if(err < 0){
+ printk("run_helper : setting FD_CLOEXEC failed, err = %d\n",
+ -err);
+ goto out_close;
}
sp = stack + page_size() - sizeof(void *);
pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data);
if(pid < 0){
printk("run_helper : clone failed, errno = %d\n", errno);
- return(-errno);
+ err = -errno;
+ goto out_close;
}
- close(fds[1]);
- n = read(fds[0], &err, sizeof(err));
+
+ os_close_file(fds[1]);
+ n = os_read_file(fds[0], &err, sizeof(err));
if(n < 0){
- printk("run_helper : read on pipe failed, errno = %d\n",
- errno);
- return(-errno);
+ printk("run_helper : read on pipe failed, err = %d\n", -n);
+ err = n;
+ goto out_kill;
}
else if(n != 0){
waitpid(pid, NULL, 0);
- pid = -err;
+ pid = -errno;
}
if(stack_out == NULL) free_stack(stack, 0);
else *stack_out = stack;
return(pid);
+
+ out_kill:
+ os_kill_process(pid, 1);
+ out_close:
+ os_close_file(fds[0]);
+ os_close_file(fds[1]);
+ out_free:
+ free_stack(stack, 0);
+ return(err);
}
int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
}
if(stack_out == NULL){
pid = waitpid(pid, &status, 0);
- if(pid < 0)
+ if(pid < 0){
printk("run_helper_thread - wait failed, errno = %d\n",
- pid);
+ errno);
+ pid = -errno;
+ }
if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
printk("run_helper_thread - thread returned status "
"0x%x\n", status);
#include "linux/module.h"
#include "linux/sched.h"
#include "linux/init_task.h"
-#include "linux/version.h"
#include "asm/uaccess.h"
#include "asm/pgtable.h"
#include "user_util.h"
struct mm_struct init_mm = INIT_MM(init_mm);
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
EXPORT_SYMBOL(init_mm);
/*
__attribute__((__section__(".data.init_task"))) =
{ INIT_THREAD_INFO(init_task) };
-struct task_struct *alloc_task_struct(void)
-{
- return((struct task_struct *)
- __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER));
-}
-
void unprotect_stack(unsigned long stack)
{
protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
1, 1, 0, 1);
}
-void free_task_struct(struct task_struct *task)
-{
- /* free_pages decrements the page counter and only actually frees
- * the pages if they are now not accessed by anything.
- */
- free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER);
-}
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <fcntl.h>
#include <errno.h>
#include "user_util.h"
{
int fd, n;
- if((fd = os_open_file(filename, of_read(OPENFLAGS()), 0)) < 0){
- printk("Opening '%s' failed - errno = %d\n", filename, errno);
+ fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Opening '%s' failed - err = %d\n", filename, -fd);
return(-1);
}
- if((n = read(fd, buf, size)) != size){
- printk("Read of %d bytes from '%s' returned %d, errno = %d\n",
- size, filename, n, errno);
+ n = os_read_file(fd, buf, size);
+ if(n != size){
+ printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+ filename, -n);
return(-1);
}
return(0);
#include "user_util.h"
#include "kern_util.h"
#include "irq_user.h"
+#include "irq_kern.h"
static void register_irq_proc (unsigned int irq);
end_none
};
-/* Not changed */
-volatile unsigned long irq_err_count;
-
/*
* Generic, controller-independent functions:
*/
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
{
- int i, j;
- unsigned long flags;
+ int i = *(loff_t *) v, j;
struct irqaction * action;
- char *p = buf;
+ unsigned long flags;
- p += sprintf(p, " ");
- for (j=0; j<num_online_cpus(); j++)
- p += sprintf(p, "CPU%d ",j);
- *p++ = '\n';
+ if (i == 0) {
+ seq_printf(p, " ");
+ for (j=0; j<NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
+ }
- for (i = 0 ; i < NR_IRQS ; i++) {
+ if (i < NR_IRQS) {
spin_lock_irqsave(&irq_desc[i].lock, flags);
action = irq_desc[i].action;
if (!action)
- goto end;
- p += sprintf(p, "%3d: ",i);
+ goto skip;
+ seq_printf(p, "%3d: ",i);
#ifndef CONFIG_SMP
- p += sprintf(p, "%10u ", kstat_irqs(i));
+ seq_printf(p, "%10u ", kstat_irqs(i));
#else
- for (j = 0; j < num_online_cpus(); j++)
- p += sprintf(p, "%10u ",
- kstat_cpu(cpu_logical_map(j)).irqs[i]);
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
- p += sprintf(p, " %14s", irq_desc[i].handler->typename);
- p += sprintf(p, " %s", action->name);
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
for (action=action->next; action; action = action->next)
- p += sprintf(p, ", %s", action->name);
- *p++ = '\n';
- end:
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ } else if (i == NR_IRQS) {
+ seq_printf(p, "NMI: ");
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", nmi_count(j));
+ seq_putc(p, '\n');
}
- p += sprintf(p, "\n");
-#ifdef notdef
-#ifdef CONFIG_SMP
- p += sprintf(p, "LOC: ");
- for (j = 0; j < num_online_cpus(); j++)
- p += sprintf(p, "%10u ",
- apic_timer_irqs[cpu_logical_map(j)]);
- p += sprintf(p, "\n");
-#endif
-#endif
- p += sprintf(p, "ERR: %10lu\n", irq_err_count);
- return p - buf;
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
- return(0);
+ return 0;
}
/*
* 0 return value means that this irq is already being
* handled by some other CPU. (or is disabled)
*/
- int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq;
struct irqaction * action;
unsigned int status;
irq_enter();
- kstat_cpu(cpu).irqs[irq]++;
+ kstat_this_cpu.irqs[irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
/*
*/
int request_irq(unsigned int irq,
- void (*handler)(int, void *, struct pt_regs *),
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags,
const char * devname,
void *dev_id)
EXPORT_SYMBOL(request_irq);
int um_request_irq(unsigned int irq, int fd, int type,
- void (*handler)(int, void *, struct pt_regs *),
+ irqreturn_t (*handler)(int, void *, struct pt_regs *),
unsigned long irqflags, const char * devname,
void *dev_id)
{
- int retval;
+ int err;
+
+ err = request_irq(irq, handler, irqflags, devname, dev_id);
+ if(err)
+ return(err);
- retval = request_irq(irq, handler, irqflags, devname, dev_id);
- if(retval) return(retval);
- return(activate_fd(irq, fd, type, dev_id));
+ if(fd != -1)
+ err = activate_fd(irq, fd, type, dev_id);
+ return(err);
}
/* this was setup_x86_irq but it seems pretty generic */
*/
spin_lock_irqsave(&desc->lock,flags);
p = &desc->action;
- if ((old = *p) != NULL) {
+ old = *p;
+ if (old != NULL) {
/* Can't share interrupts unless both agree to */
if (!(old->flags & new->flags & SA_SHIRQ)) {
spin_unlock_irqrestore(&desc->lock,flags);
unsigned long count, void *data)
{
int irq = (long) data, full_count = count, err;
- cpumask_t new_value, tmp;
+ cpumask_t new_value;
if (!irq_desc[irq].handler->set_affinity)
return -EIO;
err = cpumask_parse(buffer, count, new_value);
+ if(err)
+ return(err);
#ifdef CONFIG_SMP
/*
* way to make the system unusable accidentally :-) At least
* one online CPU still has to be targeted.
*/
- cpus_and(tmp, new_value, cpu_online_map);
- if (cpus_empty(tmp))
- return -EINVAL;
+ { cpumask_t tmp;
+ cpus_and(tmp, new_value, cpu_online_map);
+ if (cpus_empty(tmp))
+ return -EINVAL;
+ }
#endif
irq_affinity[irq] = new_value;
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
-#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <sys/poll.h>
if(smp_sigio_handler()) return;
while(1){
- if((n = poll(pollfds, pollfds_num, 0)) < 0){
+ n = poll(pollfds, pollfds_num, 0);
+ if(n < 0){
if(errno == EINTR) continue;
printk("sigio_handler : poll returned %d, "
"errno = %d\n", n, errno);
void forward_ipi(int fd, int pid)
{
- if(fcntl(fd, F_SETOWN, pid) < 0){
- int save_errno = errno;
- if(fcntl(fd, F_GETOWN, 0) != pid){
- printk("forward_ipi: F_SETOWN failed, fd = %d, "
- "me = %d, target = %d, errno = %d\n", fd,
- os_getpid(), pid, save_errno);
- }
- }
+ int err;
+
+ err = os_set_owner(fd, pid);
+ if(err < 0)
+ printk("forward_ipi: set_owner failed, fd = %d, me = %d, "
+ "target = %d, err = %d\n", fd, os_getpid(), pid, -err);
}
void forward_interrupts(int pid)
{
struct irq_fd *irq;
unsigned long flags;
+ int err;
flags = irq_lock();
for(irq=active_fds;irq != NULL;irq = irq->next){
- if(fcntl(irq->fd, F_SETOWN, pid) < 0){
- int save_errno = errno;
- if(fcntl(irq->fd, F_GETOWN, 0) != pid){
- /* XXX Just remove the irq rather than
- * print out an infinite stream of these
- */
- printk("Failed to forward %d to pid %d, "
- "errno = %d\n", irq->fd, pid,
- save_errno);
- }
+ err = os_set_owner(irq->fd, pid);
+ if(err < 0){
+ /* XXX Just remove the irq rather than
+ * print out an infinite stream of these
+ */
+ printk("Failed to forward %d to pid %d, err = %d\n",
+ irq->fd, pid, -err);
}
+
irq->pid = pid;
}
irq_unlock(flags);
/*
- * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include "linux/string.h"
#include "linux/smp_lock.h"
#include "linux/spinlock.h"
-#include <linux/highmem.h>
+#include "linux/highmem.h"
#include "asm/current.h"
#include "asm/delay.h"
#include "asm/processor.h"
#include "asm/tlbflush.h"
#include "kern_util.h"
#include "user_util.h"
+#include "mem_user.h"
#include "os.h"
#include "helper.h"
EXPORT_SYMBOL(flush_tlb_range);
EXPORT_SYMBOL(host_task_size);
EXPORT_SYMBOL(arch_validate);
+EXPORT_SYMBOL(get_kmem_end);
-EXPORT_SYMBOL(region_pa);
-EXPORT_SYMBOL(region_va);
-EXPORT_SYMBOL(phys_mem_map);
-EXPORT_SYMBOL(page_mem_map);
EXPORT_SYMBOL(page_to_phys);
EXPORT_SYMBOL(phys_to_page);
EXPORT_SYMBOL(high_physmem);
EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(um_virt_to_phys);
+EXPORT_SYMBOL(__virt_to_page);
+EXPORT_SYMBOL(to_phys);
+EXPORT_SYMBOL(to_virt);
EXPORT_SYMBOL(mode_tt);
EXPORT_SYMBOL(handle_page_fault);
+EXPORT_SYMBOL(find_iomem);
+#ifdef CONFIG_MODE_TT
+EXPORT_SYMBOL(copy_from_user_tt);
+EXPORT_SYMBOL(copy_to_user_tt);
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+EXPORT_SYMBOL(copy_to_user_skas);
+EXPORT_SYMBOL(copy_from_user_skas);
+#endif
+
+EXPORT_SYMBOL(os_stat_fd);
+EXPORT_SYMBOL(os_stat_file);
+EXPORT_SYMBOL(os_access);
+EXPORT_SYMBOL(os_print_error);
+EXPORT_SYMBOL(os_get_exec_close);
+EXPORT_SYMBOL(os_set_exec_close);
EXPORT_SYMBOL(os_getpid);
EXPORT_SYMBOL(os_open_file);
EXPORT_SYMBOL(os_read_file);
EXPORT_SYMBOL(os_write_file);
EXPORT_SYMBOL(os_seek_file);
+EXPORT_SYMBOL(os_lock_file);
+EXPORT_SYMBOL(os_ioctl_generic);
EXPORT_SYMBOL(os_pipe);
EXPORT_SYMBOL(os_file_type);
+EXPORT_SYMBOL(os_file_mode);
+EXPORT_SYMBOL(os_file_size);
+EXPORT_SYMBOL(os_flush_stdout);
EXPORT_SYMBOL(os_close_file);
+EXPORT_SYMBOL(os_set_fd_async);
+EXPORT_SYMBOL(os_set_fd_block);
EXPORT_SYMBOL(helper_wait);
EXPORT_SYMBOL(os_shutdown_socket);
+EXPORT_SYMBOL(os_create_unix_socket);
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(dump_thread);
+EXPORT_SYMBOL(do_gettimeofday);
+EXPORT_SYMBOL(do_settimeofday);
+
/* This is here because UML expands open to sys_open, not to a system
* call instruction.
*/
EXPORT_SYMBOL(kmap_atomic_to_page);
#endif
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
-#include "linux/config.h"
-#include "linux/module.h"
-#include "linux/types.h"
+#include "linux/stddef.h"
+#include "linux/kernel.h"
#include "linux/mm.h"
-#include "linux/fs.h"
-#include "linux/init.h"
#include "linux/bootmem.h"
#include "linux/swap.h"
-#include "linux/slab.h"
-#include "linux/vmalloc.h"
#include "linux/highmem.h"
+#include "linux/gfp.h"
#include "asm/page.h"
-#include "asm/pgtable.h"
+#include "asm/fixmap.h"
#include "asm/pgalloc.h"
-#include "asm/bitops.h"
-#include "asm/uaccess.h"
-#include "asm/tlb.h"
#include "user_util.h"
#include "kern_util.h"
-#include "mem_user.h"
-#include "mem.h"
#include "kern.h"
-#include "init.h"
-#include "os.h"
-#include "mode_kern.h"
+#include "mem_user.h"
#include "uml_uaccess.h"
+#include "os.h"
+
+extern char __binary_start;
/* Changed during early boot */
-pgd_t swapper_pg_dir[1024];
-unsigned long high_physmem;
-unsigned long vm_start;
-unsigned long vm_end;
-unsigned long highmem;
unsigned long *empty_zero_page = NULL;
unsigned long *empty_bad_page = NULL;
-
-/* Not modified */
-const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
-
-extern char __init_begin, __init_end;
-extern long physmem_size;
-
-/* Not changed by UML */
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-/* Changed during early boot */
+pgd_t swapper_pg_dir[1024];
+unsigned long highmem;
int kmalloc_ok = 0;
-#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1)
-struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL };
-#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1)
-
-/* Changed during early boot */
static unsigned long brk_end;
+void unmap_physmem(void)
+{
+ os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
+}
+
static void map_cb(void *unused)
{
map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
}
-void unmap_physmem(void)
+#ifdef CONFIG_HIGHMEM
+static void setup_highmem(unsigned long highmem_start,
+ unsigned long highmem_len)
{
- os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
-}
+ struct page *page;
+ unsigned long highmem_pfn;
+ int i;
-extern char __binary_start;
+ highmem_start_page = virt_to_page(highmem_start);
+
+ highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
+ for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
+ page = &mem_map[highmem_pfn + i];
+ ClearPageReserved(page);
+ set_bit(PG_highmem, &page->flags);
+ atomic_set(&page->count, 1);
+ __free_page(page);
+ }
+}
+#endif
void mem_init(void)
{
totalhigh_pages = highmem >> PAGE_SHIFT;
totalram_pages += totalhigh_pages;
num_physpages = totalram_pages;
- max_mapnr = totalram_pages;
max_pfn = totalram_pages;
printk(KERN_INFO "Memory: %luk available\n",
(unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
kmalloc_ok = 1;
-}
-
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
- if(kmem_top == 0)
- kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
- return(kmem_top);
-}
-
-void set_kmem_end(unsigned long new)
-{
- kmem_top = new;
-}
#ifdef CONFIG_HIGHMEM
-/* Changed during early boot */
-pte_t *kmap_pte;
-pgprot_t kmap_prot;
-
-EXPORT_SYMBOL(kmap_prot);
-EXPORT_SYMBOL(kmap_pte);
-
-#define kmap_get_fixmap_pte(vaddr) \
- pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-
-void __init kmap_init(void)
-{
- unsigned long kmap_vstart;
-
- /* cache the first kmap pte */
- kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
- kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
-
- kmap_prot = PAGE_KERNEL;
+ setup_highmem(end_iomem, highmem);
+#endif
}
-#endif /* CONFIG_HIGHMEM */
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
}
}
-int init_maps(struct mem_region *region)
-{
- struct page *p, *map;
- int i, n, len;
-
- if(region == &physmem_region){
- region->mem_map = mem_map;
- return(0);
- }
- else if(region->mem_map != NULL) return(0);
-
- n = region->len >> PAGE_SHIFT;
- len = n * sizeof(struct page);
- if(kmalloc_ok){
- map = kmalloc(len, GFP_KERNEL);
- if(map == NULL) map = vmalloc(len);
- }
- else map = alloc_bootmem_low_pages(len);
-
- if(map == NULL)
- return(-ENOMEM);
- for(i = 0; i < n; i++){
- p = &map[i];
- set_page_count(p, 0);
- SetPageReserved(p);
- INIT_LIST_HEAD(&p->list);
- }
- region->mem_map = map;
- return(0);
-}
+#if CONFIG_HIGHMEM
+pte_t *kmap_pte;
+pgprot_t kmap_prot;
-DECLARE_MUTEX(regions_sem);
+#define kmap_get_fixmap_pte(vaddr) \
+ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
-static int setup_one_range(int fd, char *driver, unsigned long start,
- unsigned long pfn, int len,
- struct mem_region *region)
+void __init kmap_init(void)
{
- int i;
-
- down(®ions_sem);
- for(i = 0; i < NREGIONS; i++){
- if(regions[i] == NULL) break;
- }
- if(i == NREGIONS){
- printk("setup_range : no free regions\n");
- i = -1;
- goto out;
- }
-
- if(fd == -1)
- fd = create_mem_file(len);
+ unsigned long kmap_vstart;
- if(region == NULL){
- region = alloc_bootmem_low_pages(sizeof(*region));
- if(region == NULL)
- panic("Failed to allocating mem_region");
- }
+ /* cache the first kmap pte */
+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
- *region = ((struct mem_region) { .driver = driver,
- .start_pfn = pfn,
- .start = start,
- .len = len,
- .fd = fd } );
- regions[i] = region;
- out:
- up(®ions_sem);
- return(i);
+ kmap_prot = PAGE_KERNEL;
}
-#ifdef CONFIG_HIGHMEM
static void init_highmem(void)
{
pgd_t *pgd;
kmap_init();
}
-
-void setup_highmem(unsigned long len)
-{
- struct mem_region *region;
- struct page *page, *map;
- unsigned long phys;
- int i, cur, index;
-
- phys = physmem_size;
- do {
- cur = min(len, (unsigned long) REGION_SIZE);
- i = setup_one_range(-1, NULL, -1, phys >> PAGE_SHIFT, cur,
- NULL);
- if(i == -1){
- printk("setup_highmem - setup_one_range failed\n");
- return;
- }
- region = regions[i];
- index = phys / PAGE_SIZE;
- region->mem_map = &mem_map[index];
-
- map = region->mem_map;
- for(i = 0; i < (cur >> PAGE_SHIFT); i++){
- page = &map[i];
- ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
- atomic_set(&page->count, 1);
- __free_page(page);
- }
- phys += cur;
- len -= cur;
- } while(len > 0);
-}
-#endif
+#endif /* CONFIG_HIGHMEM */
void paging_init(void)
{
- struct mem_region *region;
- unsigned long zones_size[MAX_NR_ZONES], start, end, vaddr;
- int i, index;
+ unsigned long zones_size[MAX_NR_ZONES], vaddr;
+ int i;
empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++)
zones_size[i] = 0;
- zones_size[0] = (high_physmem >> PAGE_SHIFT) -
- (uml_physmem >> PAGE_SHIFT);
+ zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT);
zones_size[2] = highmem >> PAGE_SHIFT;
free_area_init(zones_size);
- start = phys_region_index(__pa(uml_physmem));
- end = phys_region_index(__pa(high_physmem - 1));
- for(i = start; i <= end; i++){
- region = regions[i];
- index = (region->start - uml_physmem) / PAGE_SIZE;
- region->mem_map = &mem_map[index];
- if(i > start) free_bootmem(__pa(region->start), region->len);
- }
/*
* Fixed mappings, only the page table structure has to be
#ifdef CONFIG_HIGHMEM
init_highmem();
- setup_highmem(highmem);
#endif
}
-pte_t __bad_page(void)
+struct page *arch_validate(struct page *page, int mask, int order)
{
- clear_page(empty_bad_page);
- return pte_mkdirty(mk_pte((struct page *) empty_bad_page,
- PAGE_SHARED));
+ unsigned long addr, zero = 0;
+ int i;
+
+ again:
+ if(page == NULL) return(page);
+ if(PageHighMem(page)) return(page);
+
+ addr = (unsigned long) page_address(page);
+ for(i = 0; i < (1 << order); i++){
+ current->thread.fault_addr = (void *) addr;
+ if(__do_copy_to_user((void *) addr, &zero,
+ sizeof(zero),
+ ¤t->thread.fault_addr,
+ ¤t->thread.fault_catcher)){
+ if(!(mask & __GFP_WAIT)) return(NULL);
+ else break;
+ }
+ addr += PAGE_SIZE;
+ }
+ if(i == (1 << order)) return(page);
+ page = alloc_pages(mask, order);
+ goto again;
}
/* This can't do anything because nothing in the kernel image can be freed
printk("%d pages swap cached\n", cached);
}
-static int __init uml_mem_setup(char *line, int *add)
-{
- char *retptr;
- physmem_size = memparse(line,&retptr);
- return 0;
-}
-__uml_setup("mem=", uml_mem_setup,
-"mem=<Amount of desired ram>\n"
-" This controls how much \"physical\" memory the kernel allocates\n"
-" for the system. The size is specified as a number followed by\n"
-" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n"
-" This is not related to the amount of memory in the physical\n"
-" machine. It can be more, and the excess, if it's ever used, will\n"
-" just be swapped out.\n Example: mem=64M\n\n"
-);
-
-struct page *arch_validate(struct page *page, int mask, int order)
-{
- unsigned long addr, zero = 0;
- int i;
-
- again:
- if(page == NULL) return(page);
- if(PageHighMem(page)) return(page);
-
- addr = (unsigned long) page_address(page);
- for(i = 0; i < (1 << order); i++){
- current->thread.fault_addr = (void *) addr;
- if(__do_copy_to_user((void *) addr, &zero,
- sizeof(zero),
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher)){
- if(!(mask & __GFP_WAIT)) return(NULL);
- else break;
- }
- addr += PAGE_SIZE;
- }
- if(i == (1 << order)) return(page);
- page = alloc_pages(mask, order);
- goto again;
-}
-
-DECLARE_MUTEX(vm_reserved_sem);
-static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved);
-
-/* Static structures, linked in to the list in early boot */
-static struct vm_reserved head = {
- .list = LIST_HEAD_INIT(head.list),
- .start = 0,
- .end = 0xffffffff
-};
-
-static struct vm_reserved tail = {
- .list = LIST_HEAD_INIT(tail.list),
- .start = 0,
- .end = 0xffffffff
-};
-
-void set_usable_vm(unsigned long start, unsigned long end)
-{
- list_add(&head.list, &vm_reserved);
- list_add(&tail.list, &head.list);
- head.end = start;
- tail.start = end;
-}
-
-int reserve_vm(unsigned long start, unsigned long end, void *e)
-
-{
- struct vm_reserved *entry = e, *reserved, *prev;
- struct list_head *ele;
- int err;
-
- down(&vm_reserved_sem);
- list_for_each(ele, &vm_reserved){
- reserved = list_entry(ele, struct vm_reserved, list);
- if(reserved->start >= end) goto found;
- }
- panic("Reserved vm out of range");
- found:
- prev = list_entry(ele->prev, struct vm_reserved, list);
- if(prev->end > start)
- panic("Can't reserve vm");
- if(entry == NULL)
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
- if(entry == NULL){
- printk("reserve_vm : Failed to allocate entry\n");
- err = -ENOMEM;
- goto out;
- }
- *entry = ((struct vm_reserved)
- { .list = LIST_HEAD_INIT(entry->list),
- .start = start,
- .end = end });
- list_add(&entry->list, &prev->list);
- err = 0;
- out:
- up(&vm_reserved_sem);
- return(0);
-}
-
-unsigned long get_vm(unsigned long len)
-{
- struct vm_reserved *this, *next;
- struct list_head *ele;
- unsigned long start;
- int err;
-
- down(&vm_reserved_sem);
- list_for_each(ele, &vm_reserved){
- this = list_entry(ele, struct vm_reserved, list);
- next = list_entry(ele->next, struct vm_reserved, list);
- if((this->start < next->start) &&
- (this->end + len + PAGE_SIZE <= next->start))
- goto found;
- }
- up(&vm_reserved_sem);
- return(0);
- found:
- up(&vm_reserved_sem);
- start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE;
- err = reserve_vm(start, start + len, NULL);
- if(err) return(0);
- return(start);
-}
-
-int nregions(void)
-{
- return(NREGIONS);
-}
-
-void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn,
- unsigned long len, int need_vm, struct mem_region *region,
- void *reserved)
-{
- int i, cur;
-
- do {
- cur = min(len, (unsigned long) REGION_SIZE);
- i = setup_one_range(fd, driver, start, pfn, cur, region);
- region = regions[i];
- if(need_vm && setup_region(region, reserved)){
- kfree(region);
- regions[i] = NULL;
- return;
- }
- start += cur;
- if(pfn != -1) pfn += cur;
- len -= cur;
- } while(len > 0);
-}
-
-struct iomem {
- char *name;
- int fd;
- unsigned long size;
-};
-
-/* iomem regions can only be added on the command line at the moment.
- * Locking will be needed when they can be added via mconsole.
- */
-
-struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] =
- { .name = NULL,
- .fd = -1,
- .size = 0 } };
-
-int num_iomem_regions = 0;
-
-void add_iomem(char *name, int fd, unsigned long size)
-{
- if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0]))
- return;
- size = (size + PAGE_SIZE - 1) & PAGE_MASK;
- iomem_regions[num_iomem_regions++] =
- ((struct iomem) { .name = name,
- .fd = fd,
- .size = size } );
-}
-
-int setup_iomem(void)
-{
- struct iomem *iomem;
- int i;
-
- for(i = 0; i < num_iomem_regions; i++){
- iomem = &iomem_regions[i];
- setup_range(iomem->fd, iomem->name, -1, -1, iomem->size, 1,
- NULL, NULL);
- }
- return(0);
-}
-
-__initcall(setup_iomem);
-
-#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-
-/* Changed during early boot */
-static struct mem_region physmem_region;
-static struct vm_reserved physmem_reserved;
-
-void setup_physmem(unsigned long start, unsigned long reserve_end,
- unsigned long len)
-{
- struct mem_region *region = &physmem_region;
- struct vm_reserved *reserved = &physmem_reserved;
- unsigned long cur, pfn = 0;
- int do_free = 1, bootmap_size;
-
- do {
- cur = min(len, (unsigned long) REGION_SIZE);
- if(region == NULL)
- region = alloc_bootmem_low_pages(sizeof(*region));
- if(reserved == NULL)
- reserved = alloc_bootmem_low_pages(sizeof(*reserved));
- if((region == NULL) || (reserved == NULL))
- panic("Couldn't allocate physmem region or vm "
- "reservation\n");
- setup_range(-1, NULL, start, pfn, cur, 1, region, reserved);
-
- if(do_free){
- unsigned long reserve = reserve_end - start;
- int pfn = PFN_UP(__pa(reserve_end));
- int delta = (len - reserve) >> PAGE_SHIFT;
-
- bootmap_size = init_bootmem(pfn, pfn + delta);
- free_bootmem(__pa(reserve_end) + bootmap_size,
- cur - bootmap_size - reserve);
- do_free = 0;
- }
- start += cur;
- pfn += cur >> PAGE_SHIFT;
- len -= cur;
- region = NULL;
- reserved = NULL;
- } while(len > 0);
-}
-
-struct mem_region *phys_region(unsigned long phys)
-{
- unsigned int n = phys_region_index(phys);
-
- if(regions[n] == NULL)
- panic("Physical address in uninitialized region");
- return(regions[n]);
-}
-
-unsigned long phys_offset(unsigned long phys)
-{
- return(phys_addr(phys));
-}
-
-struct page *phys_mem_map(unsigned long phys)
-{
- return((struct page *) phys_region(phys)->mem_map);
-}
-
-struct page *pte_mem_map(pte_t pte)
-{
- return(phys_mem_map(pte_val(pte)));
-}
-
-struct mem_region *page_region(struct page *page, int *index_out)
-{
- int i;
- struct mem_region *region;
- struct page *map;
-
- for(i = 0; i < NREGIONS; i++){
- region = regions[i];
- if(region == NULL) continue;
- map = region->mem_map;
- if((page >= map) && (page < &map[region->len >> PAGE_SHIFT])){
- if(index_out != NULL) *index_out = i;
- return(region);
- }
- }
- panic("No region found for page");
- return(NULL);
-}
-
-unsigned long page_to_pfn(struct page *page)
-{
- struct mem_region *region = page_region(page, NULL);
-
- return(region->start_pfn + (page - (struct page *) region->mem_map));
-}
-
-struct mem_region *pfn_to_region(unsigned long pfn, int *index_out)
-{
- struct mem_region *region;
- int i;
-
- for(i = 0; i < NREGIONS; i++){
- region = regions[i];
- if(region == NULL)
- continue;
-
- if((region->start_pfn <= pfn) &&
- (region->start_pfn + (region->len >> PAGE_SHIFT) > pfn)){
- if(index_out != NULL)
- *index_out = i;
- return(region);
- }
- }
- return(NULL);
-}
-
-struct page *pfn_to_page(unsigned long pfn)
-{
- struct mem_region *region = pfn_to_region(pfn, NULL);
- struct page *mem_map = (struct page *) region->mem_map;
-
- return(&mem_map[pfn - region->start_pfn]);
-}
-
-unsigned long phys_to_pfn(unsigned long p)
-{
- struct mem_region *region = regions[phys_region_index(p)];
-
- return(region->start_pfn + (phys_addr(p) >> PAGE_SHIFT));
-}
-
-unsigned long pfn_to_phys(unsigned long pfn)
-{
- int n;
- struct mem_region *region = pfn_to_region(pfn, &n);
-
- return(mk_phys((pfn - region->start_pfn) << PAGE_SHIFT, n));
-}
-
-struct page *page_mem_map(struct page *page)
-{
- return((struct page *) page_region(page, NULL)->mem_map);
-}
-
-extern unsigned long region_pa(void *virt)
-{
- struct mem_region *region;
- unsigned long addr = (unsigned long) virt;
- int i;
-
- for(i = 0; i < NREGIONS; i++){
- region = regions[i];
- if(region == NULL) continue;
- if((region->start <= addr) &&
- (addr <= region->start + region->len))
- return(mk_phys(addr - region->start, i));
- }
- panic("region_pa : no region for virtual address");
- return(0);
-}
-
-extern void *region_va(unsigned long phys)
-{
- return((void *) (phys_region(phys)->start + phys_addr(phys)));
-}
-
-unsigned long page_to_phys(struct page *page)
-{
- int n;
- struct mem_region *region = page_region(page, &n);
- struct page *map = region->mem_map;
- return(mk_phys((page - map) << PAGE_SHIFT, n));
-}
-
-struct page *phys_to_page(unsigned long phys)
-{
- struct page *mem_map;
-
- mem_map = phys_mem_map(phys);
- return(mem_map + (phys_offset(phys) >> PAGE_SHIFT));
-}
-
-static int setup_mem_maps(void)
-{
- struct mem_region *region;
- int i;
-
- for(i = 0; i < NREGIONS; i++){
- region = regions[i];
- if((region != NULL) && (region->fd > 0)) init_maps(region);
- }
- return(0);
-}
-
-__initcall(setup_mem_maps);
-
/*
* Allocate and free page tables.
*/
#include <stddef.h>
#include <stdarg.h>
#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include <string.h>
-#include <sys/stat.h>
+#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "kern_util.h"
#include "init.h"
#include "os.h"
#include "tempfile.h"
+#include "kern_constants.h"
extern struct mem_region physmem_region;
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
-int create_mem_file(unsigned long len)
+static int create_tmp_file(unsigned long len)
{
- int fd;
+ int fd, err;
char zero;
fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1);
- if (fchmod(fd, 0777) < 0){
- perror("fchmod");
+ if(fd < 0) {
+ os_print_error(fd, "make_tempfile");
+ exit(1);
+ }
+
+ err = os_mode_fd(fd, 0777);
+ if(err < 0){
+ os_print_error(err, "os_mode_fd");
exit(1);
}
- if(os_seek_file(fd, len) < 0){
- perror("lseek");
+ err = os_seek_file(fd, len);
+ if(err < 0){
+ os_print_error(err, "os_seek_file");
exit(1);
}
zero = 0;
- if(write(fd, &zero, 1) != 1){
- perror("write");
+ err = os_write_file(fd, &zero, 1);
+ if(err != 1){
+ os_print_error(err, "os_write_file");
exit(1);
}
- if(fcntl(fd, F_SETFD, 1) != 0)
- perror("Setting FD_CLOEXEC failed");
+
return(fd);
}
-int setup_region(struct mem_region *region, void *entry)
+static int have_devanon = 0;
+
+void check_devanon(void)
{
- void *loc, *start;
- char *driver;
- int err, offset;
-
- if(region->start != -1){
- err = reserve_vm(region->start,
- region->start + region->len, entry);
- if(err){
- printk("setup_region : failed to reserve "
- "0x%x - 0x%x for driver '%s'\n",
- region->start,
- region->start + region->len,
- region->driver);
- return(-1);
- }
- }
- else region->start = get_vm(region->len);
- if(region->start == 0){
- if(region->driver == NULL) driver = "physmem";
- else driver = region->driver;
- printk("setup_region : failed to find vm for "
- "driver '%s' (length %d)\n", driver, region->len);
- return(-1);
- }
- if(region->start == uml_physmem){
- start = (void *) uml_reserved;
- offset = uml_reserved - uml_physmem;
+ int fd;
+
+ printk("Checking for /dev/anon on the host...");
+ fd = open("/dev/anon", O_RDWR);
+ if(fd < 0){
+ printk("Not available (open failed with errno %d)\n", errno);
+ return;
}
- else {
- start = (void *) region->start;
- offset = 0;
+
+ printk("OK\n");
+ have_devanon = 1;
+}
+
+static int create_anon_file(unsigned long len)
+{
+ void *addr;
+ int fd;
+
+ fd = open("/dev/anon", O_RDWR);
+ if(fd < 0) {
+ os_print_error(fd, "opening /dev/anon");
+ exit(1);
}
- loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_FIXED, region->fd, offset);
- if(loc != start){
- perror("Mapping memory");
+ addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0);
+ if(addr == MAP_FAILED){
+ os_print_error((int) addr, "mapping physmem file");
exit(1);
}
- return(0);
+ munmap(addr, len);
+
+ return(fd);
}
+int create_mem_file(unsigned long len)
+{
+ int err, fd;
+
+ if(have_devanon)
+ fd = create_anon_file(len);
+ else fd = create_tmp_file(len);
+
+ err = os_set_exec_close(fd, 1);
+ if(err < 0)
+ os_print_error(err, "exec_close");
+ return(fd);
+}
+
+struct iomem_region *iomem_regions = NULL;
+int iomem_size = 0;
+
static int __init parse_iomem(char *str, int *add)
{
- struct stat buf;
+ struct iomem_region *new;
+ struct uml_stat buf;
char *file, *driver;
- int fd;
+ int fd, err;
driver = str;
file = strchr(str,',');
if(file == NULL){
- printk("parse_iomem : failed to parse iomem\n");
- return(1);
+ printf("parse_iomem : failed to parse iomem\n");
+ goto out;
}
*file = '\0';
file++;
fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
if(fd < 0){
- printk("parse_iomem - Couldn't open io file, errno = %d\n",
- errno);
- return(1);
+ os_print_error(fd, "parse_iomem - Couldn't open io file");
+ goto out;
}
- if(fstat(fd, &buf) < 0) {
- printk("parse_iomem - cannot fstat file, errno = %d\n", errno);
- return(1);
+
+ err = os_stat_fd(fd, &buf);
+ if(err < 0){
+ os_print_error(err, "parse_iomem - cannot stat_fd file");
+ goto out_close;
}
- add_iomem(driver, fd, buf.st_size);
+
+ new = malloc(sizeof(*new));
+ if(new == NULL){
+ perror("Couldn't allocate iomem_region struct");
+ goto out_close;
+ }
+
+ *new = ((struct iomem_region) { .next = iomem_regions,
+ .driver = driver,
+ .fd = fd,
+ .size = buf.ust_size,
+ .phys = 0,
+ .virt = 0 });
+ iomem_regions = new;
+ iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
return(0);
+ out_close:
+ os_close_file(fd);
+ out:
+ return(1);
}
__uml_setup("iomem=", parse_iomem,
" Configure <file> as an IO memory region named <name>.\n\n"
);
-#ifdef notdef
-int logging = 0;
-int logging_fd = -1;
-
-int logging_line = 0;
-char logging_buf[256];
-
-void log(char *fmt, ...)
-{
- va_list ap;
- struct timeval tv;
- struct openflags flags;
-
- if(logging == 0) return;
- if(logging_fd < 0){
- flags = of_create(of_trunc(of_rdrw(OPENFLAGS())));
- logging_fd = os_open_file("log", flags, 0644);
- }
- gettimeofday(&tv, NULL);
- sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec,
- tv.tv_usec);
- va_start(ap, fmt);
- vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap);
- va_end(ap);
- write(logging_fd, logging_buf, strlen(logging_buf));
-}
-#endif
-
-int map_memory(unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x)
-{
- struct mem_region *region = phys_region(phys);
-
- return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len,
- r, w, x));
-}
-
int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
int must_succeed)
{
- if(os_protect_memory((void *) addr, len, r, w, x) < 0){
+ int err;
+
+ err = os_protect_memory((void *) addr, len, r, w, x);
+ if(err < 0){
if(must_succeed)
- panic("protect failed, errno = %d", errno);
- else return(-errno);
+ panic("protect failed, err = %d", -err);
+ else return(err);
}
return(0);
}
-unsigned long find_iomem(char *driver, unsigned long *len_out)
-{
- struct mem_region *region;
- int i, n;
-
- n = nregions();
- for(i = 0; i < n; i++){
- region = regions[i];
- if(region == NULL) continue;
- if((region->driver != NULL) &&
- !strcmp(region->driver, driver)){
- *len_out = region->len;
- return(region->start);
- }
- }
- *len_out = 0;
- return 0;
-}
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
#include <sched.h>
#include <errno.h>
#include <stdarg.h>
-#include <fcntl.h>
#include <stdlib.h>
#include <setjmp.h>
#include <sys/time.h>
#include <sys/ptrace.h>
-#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <asm/ptrace.h>
{
int flags = altstack ? SA_ONSTACK : 0;
- set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+ /* NODEFER is set here because SEGV isn't turned back on when the
+ * handler is ready to receive signals. This causes any segfault
+ * during a copy_user to kill the process because the fault is blocked.
+ */
+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags | SA_NODEFER,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGUSR2, (__sighandler_t) sig_handler,
SA_NOMASK | flags, -1);
- (void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
signal(SIGHUP, SIG_IGN);
init_irq_signals(altstack);
/* Start the process and wait for it to kill itself */
new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg);
if(new_pid < 0) return(-errno);
- while((err = waitpid(new_pid, &status, 0) < 0) && (errno == EINTR)) ;
+ while(((err = waitpid(new_pid, &status, 0)) < 0) && (errno == EINTR)) ;
if(err < 0) panic("Waiting for outer trampoline failed - errno = %d",
errno);
if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL))
- panic("outer trampoline didn't exit with SIGKILL");
+ panic("outer trampoline didn't exit with SIGKILL, "
+ "status = %d", status);
return(arg.pid);
}
os_stop_process(os_getpid());
- if(read(fd, &c, sizeof(c)) != sizeof(c))
+ if(os_read_file(fd, &c, sizeof(c)) != sizeof(c))
panic("read failed in suspend_new_thread");
}
int n;
*jmp_ptr = &buf;
- n = setjmp(buf);
+ n = sigsetjmp(buf, 1);
if(n != 0)
return(n);
(*fn)(arg);
stop_ptraced_child(pid, stack, 1);
printf("Checking for /proc/mm...");
- if(access("/proc/mm", W_OK)){
+ if(os_access("/proc/mm", OS_ACC_W_OK) < 0){
printf("not found\n");
ret = 0;
}
#include "linux/module.h"
#include "linux/init.h"
#include "linux/capability.h"
+#include "linux/spinlock.h"
#include "asm/unistd.h"
#include "asm/mman.h"
#include "asm/segment.h"
#include "asm/pgtable.h"
#include "asm/processor.h"
#include "asm/tlbflush.h"
-#include "asm/spinlock.h"
#include "asm/uaccess.h"
#include "asm/user.h"
#include "user_util.h"
struct task_struct *get_task(int pid, int require)
{
- struct task_struct *task, *ret;
+ struct task_struct *ret;
- ret = NULL;
read_lock(&tasklist_lock);
- for_each_process(task){
- if(task->pid == pid){
- ret = task;
- break;
- }
- }
+ ret = find_task_by_pid(pid);
read_unlock(&tasklist_lock);
+
if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
return(ret);
}
int flags = GFP_KERNEL;
if(atomic) flags |= GFP_ATOMIC;
- if((page = __get_free_pages(flags, order)) == 0)
+ page = __get_free_pages(flags, order);
+ if(page == 0)
return(0);
stack_protections(page);
return(page);
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
- struct task_struct *p;
+ int pid;
current->thread.request.u.thread.proc = fn;
current->thread.request.u.thread.arg = arg;
- p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
- if(IS_ERR(p)) panic("do_fork failed in kernel_thread");
- return(p->pid);
+ pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL,
+ NULL);
+ if(pid < 0)
+ panic("do_fork failed in kernel_thread, errno = %d", pid);
+ return(pid);
}
void switch_mm(struct mm_struct *prev, struct mm_struct *next,
{ external_pid(task), task });
}
-void *switch_to(void *prev, void *next, void *last)
+void *_switch_to(void *prev, void *next, void *last)
{
return(CHOOSE_MODE(switch_to_tt(prev, next),
switch_to_skas(prev, next)));
void exit_thread(void)
{
CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
- unprotect_stack((unsigned long) current->thread_info);
+ unprotect_stack((unsigned long) current_thread);
}
void *get_current(void)
return(current);
}
+void prepare_to_copy(struct task_struct *tsk)
+{
+}
+
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
void default_idle(void)
{
- idle_timer();
+ uml_idle_timer();
atomic_inc(&init_mm.mm_count);
current->mm = &init_mm;
return(clear_user(buf, size));
}
+int strlen_user_proc(char *str)
+{
+ return(strlen_user(str));
+}
+
int smp_sigio_handler(void)
{
#ifdef CONFIG_SMP
- int cpu = current->thread_info->cpu;
+ int cpu = current_thread->cpu;
IPI_handler(cpu);
if(cpu != 0)
return(1);
int cpu(void)
{
- return(current->thread_info->cpu);
+ return(current_thread->cpu);
}
/*
return ret;
}
-void syscall_trace(void)
+void syscall_trace(union uml_pt_regs *regs, int entryexit)
{
+ if (unlikely(current->audit_context)) {
+ if (!entryexit)
+ audit_syscall_entry(current, regs->orig_eax,
+ regs->ebx, regs->ecx,
+ regs->edx, regs->esi);
+ else
+ audit_syscall_exit(current, regs->eax);
+ }
+
if (!test_thread_flag(TIF_SYSCALL_TRACE))
return;
if (!(current->ptrace & PT_PTRACED))
/* the 0x80 provides a way for the tracing parent to distinguish
between a syscall stop and SIGTRAP delivery */
- current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
- ? 0x80 : 0);
- current->state = TASK_STOPPED;
- notify_parent(current, SIGCHLD);
- schedule();
+ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+ ? 0x80 : 0));
/*
* this isn't the same as continuing with a signal, but it will do
#ifdef CONFIG_SMP
static void kill_idlers(int me)
{
+#ifdef CONFIG_MODE_TT
struct task_struct *p;
int i;
if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
os_kill_process(p->thread.mode.tt.extern_pid, 0);
}
+#endif
}
#endif
#include "linux/kernel.h"
#include "linux/list.h"
#include "linux/slab.h"
-#include "asm/irq.h"
+#include "linux/signal.h"
+#include "linux/interrupt.h"
#include "init.h"
#include "sigio.h"
#include "irq_user.h"
+#include "irq_kern.h"
/* Protected by sigio_lock() called from write_sigio_workaround */
static int sigio_irq_fd = -1;
-void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
+irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused)
{
read_sigio_fd(sigio_irq_fd);
reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ);
+ return(IRQ_HANDLED);
}
int write_sigio_irq(int fd)
#include <stdlib.h>
#include <termios.h>
#include <pty.h>
-#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
int pty_close_sigio = 0;
/* Used as a flag during SIGIO testing early in boot */
-static int got_sigio = 0;
+static volatile int got_sigio = 0;
void __init handler(int sig)
{
info->err = 0;
if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
- info->err = errno;
+ info->err = -errno;
}
void __init check_one_sigio(void (*proc)(int, int))
struct sigaction old, new;
struct termios tt;
struct openpty_arg pty = { .master = -1, .slave = -1 };
- int master, slave, flags;
+ int master, slave, err;
initial_thread_cb(openpty_cb, &pty);
if(pty.err){
- printk("openpty failed, errno = %d\n", pty.err);
+ printk("openpty failed, errno = %d\n", -pty.err);
return;
}
return;
}
+ /* XXX These can fail with EINTR */
if(tcgetattr(master, &tt) < 0)
panic("check_sigio : tcgetattr failed, errno = %d\n", errno);
cfmakeraw(&tt);
if(tcsetattr(master, TCSADRAIN, &tt) < 0)
panic("check_sigio : tcsetattr failed, errno = %d\n", errno);
- if((flags = fcntl(master, F_GETFL)) < 0)
- panic("tty_fds : fcntl F_GETFL failed, errno = %d\n", errno);
-
- if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
- (fcntl(master, F_SETOWN, os_getpid()) < 0))
- panic("check_sigio : fcntl F_SETFL or F_SETOWN failed, "
- "errno = %d\n", errno);
-
- if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
- panic("check_sigio : fcntl F_SETFL failed, errno = %d\n",
- errno);
+ err = os_sigio_async(master, slave);
+ if(err < 0)
+ panic("tty_fds : sigio_async failed, err = %d\n", -err);
if(sigaction(SIGIO, NULL, &old) < 0)
panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
got_sigio = 0;
(*proc)(master, slave);
- close(master);
- close(slave);
+ os_close_file(master);
+ os_close_file(slave);
if(sigaction(SIGIO, &old, NULL) < 0)
panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
printk("Checking that host ptys support output SIGIO...");
memset(buf, 0, sizeof(buf));
- while(write(master, buf, sizeof(buf)) > 0) ;
+
+ while(os_write_file(master, buf, sizeof(buf)) > 0) ;
if(errno != EAGAIN)
panic("check_sigio : write failed, errno = %d\n", errno);
-
- while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
+ while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
if(got_sigio){
printk("Yes\n");
pty_output_sigio = 1;
}
- else if(errno == EAGAIN) printk("No, enabling workaround\n");
- else panic("check_sigio : read failed, errno = %d\n", errno);
+ else if(n == -EAGAIN) printk("No, enabling workaround\n");
+ else panic("check_sigio : read failed, err = %d\n", n);
}
static void tty_close(int master, int slave)
{
printk("Checking that host ptys support SIGIO on close...");
- close(slave);
+ os_close_file(slave);
if(got_sigio){
printk("Yes\n");
pty_close_sigio = 1;
void __init check_sigio(void)
{
- if(access("/dev/ptmx", R_OK) && access("/dev/ptyp0", R_OK)){
+ if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+ (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
printk("No pseudo-terminals available - skipping pty SIGIO "
"check\n");
return;
p = &fds->poll[i];
if(p->revents == 0) continue;
if(p->fd == sigio_private[1]){
- n = read(sigio_private[1], &c, sizeof(c));
+ n = os_read_file(sigio_private[1], &c, sizeof(c));
if(n != sizeof(c))
printk("write_sigio_thread : "
- "read failed, errno = %d\n",
- errno);
+ "read failed, err = %d\n", -n);
tmp = current_poll;
current_poll = next_poll;
next_poll = tmp;
(fds->used - i) * sizeof(*fds->poll));
}
- n = write(respond_fd, &c, sizeof(c));
+ n = os_write_file(respond_fd, &c, sizeof(c));
if(n != sizeof(c))
printk("write_sigio_thread : write failed, "
- "errno = %d\n", errno);
+ "err = %d\n", -n);
}
}
}
char c;
flags = set_signals(0);
- n = write(sigio_private[0], &c, sizeof(c));
+ n = os_write_file(sigio_private[0], &c, sizeof(c));
if(n != sizeof(c)){
- printk("update_thread : write failed, errno = %d\n", errno);
+ printk("update_thread : write failed, err = %d\n", -n);
goto fail;
}
- n = read(sigio_private[0], &c, sizeof(c));
+ n = os_read_file(sigio_private[0], &c, sizeof(c));
if(n != sizeof(c)){
- printk("update_thread : read failed, errno = %d\n", errno);
+ printk("update_thread : read failed, err = %d\n", -n);
goto fail;
}
if(write_sigio_pid != -1)
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
- close(sigio_private[0]);
- close(sigio_private[1]);
- close(write_sigio_fds[0]);
- close(write_sigio_fds[1]);
+ os_close_file(sigio_private[0]);
+ os_close_file(sigio_private[1]);
+ os_close_file(write_sigio_fds[0]);
+ os_close_file(write_sigio_fds[1]);
sigio_unlock();
set_signals(flags);
}
goto out;
err = os_pipe(write_sigio_fds, 1, 1);
- if(err){
+ if(err < 0){
printk("write_sigio_workaround - os_pipe 1 failed, "
- "errno = %d\n", -err);
+ "err = %d\n", -err);
goto out;
}
err = os_pipe(sigio_private, 1, 1);
- if(err){
+ if(err < 0){
printk("write_sigio_workaround - os_pipe 2 failed, "
- "errno = %d\n", -err);
+ "err = %d\n", -err);
goto out_close1;
}
if(setup_initial_poll(sigio_private[1]))
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
out_close2:
- close(sigio_private[0]);
- close(sigio_private[1]);
+ os_close_file(sigio_private[0]);
+ os_close_file(sigio_private[1]);
out_close1:
- close(write_sigio_fds[0]);
- close(write_sigio_fds[1]);
+ os_close_file(write_sigio_fds[0]);
+ os_close_file(write_sigio_fds[1]);
sigio_unlock();
}
int n;
char c;
- n = read(fd, &c, sizeof(c));
+ n = os_read_file(fd, &c, sizeof(c));
if(n != sizeof(c)){
- printk("read_sigio_fd - read failed, errno = %d\n", errno);
- return(-errno);
+ if(n < 0) {
+ printk("read_sigio_fd - read failed, err = %d\n", -n);
+ return(n);
+ }
+ else {
+ printk("read_sigio_fd - short read, bytes = %d\n", n);
+ return(-EIO);
+ }
}
return(n);
}
if(sig == SIGSEGV){
struct k_sigaction *ka;
- ka = ¤t->sig->action[SIGSEGV - 1];
+ ka = ¤t->sighand->action[SIGSEGV - 1];
ka->sa.sa_handler = SIG_DFL;
}
force_sig(SIGSEGV, current);
int err, ret;
ret = 0;
+ /* Always make any pending restarted system calls return -EINTR */
+ current_thread_info()->restart_block.fn = do_no_restart_syscall;
switch(error){
case -ERESTART_RESTARTBLOCK:
- current_thread_info()->restart_block.fn =
- do_no_restart_syscall;
case -ERESTARTNOHAND:
ret = -EINTR;
break;
return(0);
/* Whee! Actually deliver the signal. */
- ka = ¤t->sig->action[sig -1 ];
+ ka = ¤t->sighand->action[sig -1 ];
err = handle_signal(regs, sig, ka, &info, oldset, error);
if(!err) return(1);
}
}
-int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
+int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
{
sigset_t saveset, newset;
}
}
+int 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 (verify_area(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 (verify_area(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;
+}
+
+int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+ return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
+}
+
+extern int userspace_pid[];
+
static int copy_sc_from_user(struct pt_regs *to, void *from,
struct arch_frame_data *arch)
{
int ret;
ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch),
- copy_sc_from_user_skas(&to->regs, from));
+ copy_sc_from_user_skas(userspace_pid[0],
+ &to->regs, from));
return(ret);
}
int sys_sigreturn(struct pt_regs regs)
{
- void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs));
- void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
+ void __user *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs));
+ void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs));
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
spin_lock_irq(¤t->sighand->siglock);
int sys_rt_sigreturn(struct pt_regs regs)
{
- struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs));
- void *fp;
+ unsigned long sp = PT_REGS_SP(¤t->thread.regs);
+ struct ucontext __user *uc = sp_to_uc(sp);
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
spin_lock_irq(¤t->sighand->siglock);
sigdelsetmask(¤t->blocked, ~_BLOCKABLE);
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext));
copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext,
&signal_frame_si.common.arch);
return(PT_REGS_SYSCALL_RET(¤t->thread.regs));
obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
- sys-$(SUBARCH)/
+ uaccess.o sys-$(SUBARCH)/
+
+host-progs := util/mk_ptregs
+clean-files := include/skas_ptregs.h
USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-include/skas_ptregs.h : util/mk_ptregs
- util/mk_ptregs > $@
-
-util/mk_ptregs :
- $(MAKE) -C util
+$(TOPDIR)/arch/um/include/skas_ptregs.h : $(src)/util/mk_ptregs
+ @echo -n ' Generating $@'
+ @$< > $@.tmp
+ @if [ -r $@ ] && cmp -s $@ $@.tmp; then \
+ echo ' (unchanged)'; \
+ rm -f $@.tmp; \
+ else \
+ echo ' (updated)'; \
+ mv -f $@.tmp $@; \
+ fi
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
- $(MAKE) -C util clean
- $(RM) -f include/skas_ptregs.h
extern int have_fpx_regs;
extern void user_time_init_skas(void);
-extern int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr);
-extern int copy_sc_to_user_skas(void *to_ptr, void *fp,
+extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs,
+ void *from_ptr);
+extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
union uml_pt_regs *regs,
unsigned long fault_addr, int fault_type);
extern void sig_handler_common_skas(int sig, void *sc_ptr);
extern void halt_skas(void);
extern void reboot_skas(void);
extern void kill_off_processes_skas(void);
+extern int is_skas_winch(int pid, int fd, void *data);
#endif
#include "sysdep/ptrace.h"
-extern int userspace_pid;
+extern int userspace_pid[];
extern void switch_threads(void *me, void *next);
extern void thread_wait(void *sw, void *fb);
extern int new_mm(int from);
extern void save_registers(union uml_pt_regs *regs);
extern void restore_registers(union uml_pt_regs *regs);
-extern void start_userspace(void);
+extern void start_userspace(int cpu);
extern void init_registers(int pid);
#endif
#ifndef __SKAS_UACCESS_H
#define __SKAS_UACCESS_H
-#include "linux/string.h"
-#include "linux/sched.h"
-#include "linux/err.h"
-#include "asm/processor.h"
-#include "asm/pgtable.h"
#include "asm/errno.h"
-#include "asm/current.h"
-#include "asm/a.out.h"
-#include "kern_util.h"
#define access_ok_skas(type, addr, size) \
((segment_eq(get_fs(), KERNEL_DS)) || \
(((unsigned long) (addr) < TASK_SIZE) && \
- ((unsigned long) (addr) + (size) < TASK_SIZE)))
+ ((unsigned long) (addr) + (size) <= TASK_SIZE)))
static inline int verify_area_skas(int type, const void * addr,
unsigned long size)
return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
}
-static inline unsigned long maybe_map(unsigned long virt, int is_write)
-{
- pte_t pte;
-
- void *phys = um_virt_to_phys(current, virt, &pte);
- int dummy_code;
-
- if(IS_ERR(phys) || (is_write && !pte_write(pte))){
- if(handle_page_fault(virt, 0, is_write, 0, &dummy_code))
- return(0);
- phys = um_virt_to_phys(current, virt, NULL);
- }
- return((unsigned long) __va((unsigned long) phys));
-}
-
-static inline int buffer_op(unsigned long addr, int len,
- int (*op)(unsigned long addr, int len, void *arg),
- void *arg)
-{
- int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
- int remain = len, n;
-
- n = (*op)(addr, size, arg);
- if(n != 0)
- return(n < 0 ? remain : 0);
-
- addr += size;
- remain -= size;
- if(remain == 0)
- return(0);
-
- while(addr < ((addr + remain) & PAGE_MASK)){
- n = (*op)(addr, PAGE_SIZE, arg);
- if(n != 0)
- return(n < 0 ? remain : 0);
-
- addr += PAGE_SIZE;
- remain -= PAGE_SIZE;
- }
- if(remain == 0)
- return(0);
-
- n = (*op)(addr, remain, arg);
- if(n != 0)
- return(n < 0 ? remain : 0);
- return(0);
-}
-
-static inline int copy_chunk_from_user(unsigned long from, int len, void *arg)
-{
- unsigned long *to_ptr = arg, to = *to_ptr;
-
- from = maybe_map(from, 0);
- if(from == 0)
- return(-1);
-
- memcpy((void *) to, (void *) from, len);
- *to_ptr += len;
- return(0);
-}
-
-static inline int copy_from_user_skas(void *to, const void *from, int n)
-{
- if(segment_eq(get_fs(), KERNEL_DS)){
- memcpy(to, from, n);
- return(0);
- }
-
- return(access_ok_skas(VERIFY_READ, from, n) ?
- buffer_op((unsigned long) from, n, copy_chunk_from_user, &to) :
- n);
-}
-
-static inline int copy_chunk_to_user(unsigned long to, int len, void *arg)
-{
- unsigned long *from_ptr = arg, from = *from_ptr;
-
- to = maybe_map(to, 1);
- if(to == 0)
- return(-1);
-
- memcpy((void *) to, (void *) from, len);
- *from_ptr += len;
- return(0);
-}
-
-static inline int copy_to_user_skas(void *to, const void *from, int n)
-{
- if(segment_eq(get_fs(), KERNEL_DS)){
- memcpy(to, from, n);
- return(0);
- }
-
- return(access_ok_skas(VERIFY_WRITE, to, n) ?
- buffer_op((unsigned long) to, n, copy_chunk_to_user, &from) :
- n);
-}
-
-static inline int strncpy_chunk_from_user(unsigned long from, int len,
- void *arg)
-{
- char **to_ptr = arg, *to = *to_ptr;
- int n;
-
- from = maybe_map(from, 0);
- if(from == 0)
- return(-1);
-
- strncpy(to, (void *) from, len);
- n = strnlen(to, len);
- *to_ptr += n;
-
- if(n < len)
- return(1);
- return(0);
-}
-
-static inline int strncpy_from_user_skas(char *dst, const char *src, int count)
-{
- int n;
- char *ptr = dst;
-
- if(segment_eq(get_fs(), KERNEL_DS)){
- strncpy(dst, src, count);
- return(strnlen(dst, count));
- }
-
- if(!access_ok_skas(VERIFY_READ, src, 1))
- return(-EFAULT);
-
- n = buffer_op((unsigned long) src, count, strncpy_chunk_from_user,
- &ptr);
- if(n != 0)
- return(-EFAULT);
- return(strnlen(dst, count));
-}
-
-static inline int clear_chunk(unsigned long addr, int len, void *unused)
-{
- addr = maybe_map(addr, 1);
- if(addr == 0)
- return(-1);
-
- memset((void *) addr, 0, len);
- return(0);
-}
-
-static inline int __clear_user_skas(void *mem, int len)
-{
- return(buffer_op((unsigned long) mem, len, clear_chunk, NULL));
-}
-
-static inline int clear_user_skas(void *mem, int len)
-{
- if(segment_eq(get_fs(), KERNEL_DS)){
- memset(mem, 0, len);
- return(0);
- }
-
- return(access_ok_skas(VERIFY_WRITE, mem, len) ?
- buffer_op((unsigned long) mem, len, clear_chunk, NULL) : len);
-}
-
-static inline int strnlen_chunk(unsigned long str, int len, void *arg)
-{
- int *len_ptr = arg, n;
-
- str = maybe_map(str, 0);
- if(str == 0)
- return(-1);
-
- n = strnlen((void *) str, len);
- *len_ptr += n;
-
- if(n < len)
- return(1);
- return(0);
-}
-
-static inline int strnlen_user_skas(const void *str, int len)
-{
- int count = 0, n;
-
- if(segment_eq(get_fs(), KERNEL_DS))
- return(strnlen(str, len) + 1);
-
- n = buffer_op((unsigned long) str, len, strnlen_chunk, &count);
- if(n == 0)
- return(count + 1);
- return(-EFAULT);
-}
+extern int copy_from_user_skas(void *to, const void *from, int n);
+extern int copy_to_user_skas(void *to, const void *from, int n);
+extern int strncpy_from_user_skas(char *dst, const char *src, int count);
+extern int __clear_user_skas(void *mem, int len);
+extern int clear_user_skas(void *mem, int len);
+extern int strnlen_user_skas(const void *str, int len);
#endif
#include <sys/mman.h>
#include <sys/ptrace.h>
#include "mem_user.h"
+#include "mem.h"
#include "user.h"
#include "os.h"
#include "proc_mm.h"
int r, int w, int x)
{
struct proc_mm_op map;
- struct mem_region *region;
- int prot, n;
+ __u64 offset;
+ int prot, n, phys_fd;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
- region = phys_region(phys);
+ phys_fd = phys_mapping(phys, &offset);
map = ((struct proc_mm_op) { .op = MM_MMAP,
.u =
.prot = prot,
.flags = MAP_SHARED |
MAP_FIXED,
- .fd = region->fd,
- .offset = phys_offset(phys)
+ .fd = phys_fd,
+ .offset = offset
} } } );
n = os_write_file(fd, &map, sizeof(map));
if(n != sizeof(map))
- printk("map : /proc/mm map failed, errno = %d\n", errno);
+ printk("map : /proc/mm map failed, err = %d\n", -n);
}
int unmap(int fd, void *addr, int len)
{ .addr = (unsigned long) addr,
.len = len } } } );
n = os_write_file(fd, &unmap, sizeof(unmap));
- if((n != 0) && (n != sizeof(unmap)))
- return(-errno);
+ if(n != sizeof(unmap)) {
+ if(n < 0)
+ return(n);
+ else if(n > 0)
+ return(-EIO);
+ }
+
return(0);
}
.prot = prot } } } );
n = os_write_file(fd, &protect, sizeof(protect));
- if((n != 0) && (n != sizeof(protect))){
+ if(n != sizeof(protect)) {
+ if(n == 0) return(0);
+
if(must_succeed)
- panic("protect failed, errno = %d", errno);
- return(-errno);
+ panic("protect failed, err = %d", -n);
+
+ return(-EIO);
}
+
return(0);
}
else from = -1;
mm->context.skas.mm_fd = new_mm(from);
- if(mm->context.skas.mm_fd < 0)
- panic("init_new_context_skas - new_mm failed, errno = %d\n",
- mm->context.skas.mm_fd);
+ if(mm->context.skas.mm_fd < 0){
+ printk("init_new_context_skas - new_mm failed, errno = %d\n",
+ mm->context.skas.mm_fd);
+ return(mm->context.skas.mm_fd);
+ }
return(0);
}
*/
#include <stdlib.h>
+#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include "os.h"
#include "proc_mm.h"
#include "skas_ptrace.h"
+#include "chan_user.h"
+#include "signal_user.h"
+
+int is_skas_winch(int pid, int fd, void *data)
+{
+ if(pid != getpid())
+ return(0);
+
+ register_winch_irq(-1, fd, -1, data);
+ return(1);
+}
+
+/* These are set once at boot time and not changed thereafter */
unsigned long exec_regs[FRAME_SIZE];
unsigned long exec_fp_regs[HOST_FP_SIZE];
int err, syscall_nr, status;
syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
+ UPT_SYSCALL_NR(regs) = syscall_nr;
if(syscall_nr < 1){
relay_signal(SIGTRAP, regs);
return;
}
- UPT_SYSCALL_NR(regs) = syscall_nr;
err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
if(err < 0)
handle_syscall(regs);
}
-int userspace_pid;
-
static int userspace_tramp(void *arg)
{
init_new_thread_signals(0);
return(0);
}
-void start_userspace(void)
+/* Each element set once, and only accessed by a single processor anyway */
+#define NR_CPUS 1
+int userspace_pid[NR_CPUS];
+
+void start_userspace(int cpu)
{
void *stack;
unsigned long sp;
if(munmap(stack, PAGE_SIZE) < 0)
panic("start_userspace : munmap failed, errno = %d\n", errno);
- userspace_pid = pid;
+ userspace_pid[cpu] = pid;
}
void userspace(union uml_pt_regs *regs)
{
- int err, status, op;
+ int err, status, op, pid = userspace_pid[0];
restore_registers(regs);
- err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0);
+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
if(err)
panic("userspace - PTRACE_SYSCALL failed, errno = %d\n",
errno);
while(1){
- err = waitpid(userspace_pid, &status, WUNTRACED);
+ err = waitpid(pid, &status, WUNTRACED);
if(err < 0)
panic("userspace - waitpid failed, errno = %d\n",
errno);
if(WIFSTOPPED(status)){
switch(WSTOPSIG(status)){
case SIGSEGV:
- handle_segv(userspace_pid);
+ handle_segv(pid);
break;
case SIGTRAP:
- handle_trap(userspace_pid, regs);
+ handle_trap(pid, regs);
break;
case SIGIO:
case SIGVTALRM:
case SIGILL:
case SIGBUS:
case SIGFPE:
+ case SIGWINCH:
user_signal(WSTOPSIG(status), regs);
break;
default:
op = singlestepping_skas() ? PTRACE_SINGLESTEP :
PTRACE_SYSCALL;
- err = ptrace(op, userspace_pid, 0, 0);
+ err = ptrace(op, pid, 0, 0);
if(err)
panic("userspace - PTRACE_SYSCALL failed, "
"errno = %d\n", errno);
void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int))
{
+ unsigned long flags;
jmp_buf switch_buf, fork_buf;
*switch_buf_ptr = &switch_buf;
*fork_buf_ptr = &fork_buf;
- if(setjmp(fork_buf) == 0)
+ /* Somewhat subtle - siglongjmp restores the signal mask before doing
+ * the longjmp. This means that when jumping from one stack to another
+ * when the target stack has interrupts enabled, an interrupt may occur
+ * on the source stack. This is bad when starting up a process because
+ * it's not supposed to get timer ticks until it has been scheduled.
+ * So, we disable interrupts around the sigsetjmp to ensure that
+ * they can't happen until we get back here where they are safe.
+ */
+ flags = get_signals();
+ block_signals();
+ if(sigsetjmp(fork_buf, 1) == 0)
new_thread_proc(stack, handler);
+ set_signals(flags);
remove_sigstack();
}
*switch_buf = &buf;
fork_buf = fb;
- if(setjmp(buf) == 0)
- longjmp(*fork_buf, 1);
+ if(sigsetjmp(buf, 1) == 0)
+ siglongjmp(*fork_buf, 1);
}
-static int move_registers(int int_op, int fp_op, union uml_pt_regs *regs,
- unsigned long *fp_regs)
+static int move_registers(int pid, int int_op, int fp_op,
+ union uml_pt_regs *regs, unsigned long *fp_regs)
{
- if(ptrace(int_op, userspace_pid, 0, regs->skas.regs) < 0)
+ if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
return(-errno);
- if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0)
+ if(ptrace(fp_op, pid, 0, fp_regs) < 0)
return(-errno);
return(0);
}
fp_regs = regs->skas.fp;
}
- err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs);
+ err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
+ fp_regs);
if(err)
panic("save_registers - saving registers failed, errno = %d\n",
- err);
+ -err);
}
void restore_registers(union uml_pt_regs *regs)
fp_regs = regs->skas.fp;
}
- err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs);
+ err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
+ fp_regs);
if(err)
panic("restore_registers - saving registers failed, "
- "errno = %d\n", err);
+ "errno = %d\n", -err);
}
void switch_threads(void *me, void *next)
jmp_buf my_buf, **me_ptr = me, *next_buf = next;
*me_ptr = &my_buf;
- if(setjmp(my_buf) == 0)
- longjmp(*next_buf, 1);
+ if(sigsetjmp(my_buf, 1) == 0)
+ siglongjmp(*next_buf, 1);
}
static jmp_buf initial_jmpbuf;
int n;
*fork_buf_ptr = &initial_jmpbuf;
- n = setjmp(initial_jmpbuf);
+ n = sigsetjmp(initial_jmpbuf, 1);
if(n == 0)
new_thread_proc((void *) stack, new_thread_handler);
else if(n == 1)
remove_sigstack();
else if(n == 2){
(*cb_proc)(cb_arg);
- longjmp(*cb_back, 1);
+ siglongjmp(*cb_back, 1);
}
else if(n == 3){
kmalloc_ok = 0;
kmalloc_ok = 0;
return(1);
}
- longjmp(**switch_buf, 1);
+ siglongjmp(**switch_buf, 1);
}
void remove_sigstack(void)
cb_back = &here;
block_signals();
- if(setjmp(here) == 0)
- longjmp(initial_jmpbuf, 2);
+ if(sigsetjmp(here, 1) == 0)
+ siglongjmp(initial_jmpbuf, 2);
unblock_signals();
cb_proc = NULL;
void halt_skas(void)
{
block_signals();
- longjmp(initial_jmpbuf, 3);
+ siglongjmp(initial_jmpbuf, 3);
}
void reboot_skas(void)
{
block_signals();
- longjmp(initial_jmpbuf, 4);
+ siglongjmp(initial_jmpbuf, 4);
}
int new_mm(int from)
{
struct proc_mm_op copy;
- int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
+ int n, fd = os_open_file("/proc/mm",
+ of_cloexec(of_write(OPENFLAGS())), 0);
if(fd < 0)
- return(-errno);
+ return(fd);
if(from != -1){
copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
n = os_write_file(fd, ©, sizeof(copy));
if(n != sizeof(copy))
printk("new_mm : /proc/mm copy_segments failed, "
- "errno = %d\n", errno);
+ "err = %d\n", -n);
}
+
return(fd);
}
{
int err;
- err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd);
+#warning need cpu pid in switch_mm_skas
+ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd);
if(err)
panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
errno);
void kill_off_processes_skas(void)
{
- os_kill_process(userspace_pid, 1);
+#warning need to loop over userspace_pids in kill_off_processes_skas
+ os_kill_process(userspace_pid[0], 1);
}
void init_registers(int pid)
thread_wait(¤t->thread.mode.skas.switch_buf,
current->thread.mode.skas.fork_buf);
-#ifdef CONFIG_SMP
- schedule_tail(NULL);
-#endif
+ if(current->thread.prev_sched != NULL)
+ schedule_tail(current->thread.prev_sched);
current->thread.prev_sched = NULL;
+ /* The return value is 1 if the kernel thread execs a process,
+ * 0 if it just exits
+ */
n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf);
if(n == 1)
userspace(¤t->thread.regs.regs);
current->thread.mode.skas.fork_buf);
force_flush_all();
-#ifdef CONFIG_SMP
+ if(current->thread.prev_sched == NULL)
+ panic("blech");
+
schedule_tail(current->thread.prev_sched);
-#endif
current->thread.prev_sched = NULL;
- unblock_signals();
userspace(¤t->thread.regs.regs);
}
void init_idle_skas(void)
{
- cpu_tasks[current->thread_info->cpu].pid = os_getpid();
+ cpu_tasks[current_thread->cpu].pid = os_getpid();
default_idle();
}
int start_uml_skas(void)
{
- start_userspace();
+ start_userspace(0);
capture_signal_stack();
+ uml_idle_timer();
init_new_thread_signals(1);
- idle_timer();
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
int external_pid_skas(struct task_struct *task)
{
- return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+ return(userspace_pid[0]);
}
int thread_pid_skas(struct task_struct *task)
{
- return(userspace_pid);
+#warning Need to look up userspace_pid by cpu
+ return(userspace_pid[0]);
}
/*
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
#include "kern_util.h"
#include "user.h"
#include "sigcontext.h"
+#include "mode.h"
-extern int userspace_pid;
-
-int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr)
+int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr)
{
struct sigcontext sc, *from = from_ptr;
unsigned long fpregs[FP_FRAME_SIZE];
regs->skas.regs[EIP] = sc.eip;
regs->skas.regs[CS] = sc.cs;
regs->skas.regs[EFL] = sc.eflags;
- regs->skas.regs[UESP] = sc.esp_at_signal;
regs->skas.regs[SS] = sc.ss;
regs->skas.fault_addr = sc.cr2;
regs->skas.fault_type = FAULT_WRITE(sc.err);
regs->skas.trap_type = sc.trapno;
- err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs);
+ err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs);
if(err < 0){
printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
"errno = %d\n", errno);
return(0);
}
-int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs,
- unsigned long fault_addr, int fault_type)
+int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp,
+ union uml_pt_regs *regs, unsigned long fault_addr,
+ int fault_type)
{
struct sigcontext sc, *to = to_ptr;
struct _fpstate *to_fp;
sc.err = TO_SC_ERR(fault_type);
sc.trapno = regs->skas.trap_type;
- err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs);
+ err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs);
if(err < 0){
printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
"errno = %d\n", errno);
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
index = record_syscall_start(UPT_SYSCALL_NR(regs));
- syscall_trace();
+ syscall_trace(regs, 1);
result = execute_syscall(regs);
REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
(result == -ERESTARTNOINTR))
do_signal(result);
- syscall_trace();
+ syscall_trace(regs, 0);
record_syscall_end(index, result);
}
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
errno = save_errno;
}
-extern int missed_ticks[];
-
void user_signal(int sig, union uml_pt_regs *regs)
{
struct signal_info *info;
- if(sig == SIGVTALRM)
- missed_ticks[cpu()]++;
regs->skas.is_user = 1;
regs->skas.fault_addr = 0;
regs->skas.fault_type = 0;
all: mk_ptregs
mk_ptregs : mk_ptregs.o
- $(CC) -o mk_ptregs mk_ptregs.o
+ $(HOSTCC) -o mk_ptregs mk_ptregs.o
mk_ptregs.o : mk_ptregs.c
- $(CC) -c $<
+ $(HOSTCC) -c $<
-clean :
- $(RM) -f mk_ptregs *.o *~
+clean-files := mk_ptregs *.o *~
+#include <stdio.h>
#include <asm/ptrace.h>
#include <asm/user.h>
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include "linux/config.h"
+#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);
#ifdef CONFIG_SMP
#include "os.h"
/* CPU online map, set by smp_boot_cpus */
-unsigned long cpu_online_map = cpumask_of_cpu(0);
+unsigned long cpu_online_map = CPU_MASK_NONE;
EXPORT_SYMBOL(cpu_online_map);
void smp_send_reschedule(int cpu)
{
- write(cpu_data[cpu].ipi_pipe[1], "R", 1);
+ os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1);
num_reschedules_sent++;
}
printk(KERN_INFO "Stopping all CPUs...");
for(i = 0; i < num_online_cpus(); i++){
- if(i == current->thread_info->cpu)
+ if(i == current_thread->cpu)
continue;
- write(cpu_data[i].ipi_pipe[1], "S", 1);
+ os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
}
printk("done\n");
}
-static cpumask_t smp_commenced_mask;
-static cpumask_t smp_callin_map = CPU_MASK_NONE;
+static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+static cpumask_t cpu_callin_map = CPU_MASK_NONE;
static int idle_proc(void *cpup)
{
int cpu = (int) cpup, err;
err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
- if(err)
- panic("CPU#%d failed to create IPI pipe, errno = %d", cpu,
- -err);
+ if(err < 0)
+ panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
activate_ipi(cpu_data[cpu].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
wmb();
- if (cpu_test_and_set(cpu, &smp_callin_map)) {
+ if (cpu_test_and_set(cpu, cpu_callin_map)) {
printk("huh, CPU#%d already present??\n", cpu);
BUG();
}
- while (!cpu_isset(cpu, &smp_commenced_mask))
+ while (!cpu_isset(cpu, smp_commenced_mask))
cpu_relax();
cpu_set(cpu, cpu_online_map);
current->thread.request.u.thread.proc = idle_proc;
current->thread.request.u.thread.arg = (void *) cpu;
- new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL);
- if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
+ new_task = copy_process(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL,
+ NULL);
+ if(IS_ERR(new_task))
+ panic("copy_process failed in idle_thread, error = %ld",
+ PTR_ERR(new_task));
cpu_tasks[cpu] = ((struct cpu_task)
{ .pid = new_task->thread.mode.tt.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
- CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c,
+ CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c,
sizeof(c)),
({ panic("skas mode doesn't support SMP"); }));
+ wake_up_forked_process(new_task);
return(new_task);
}
{
struct task_struct *idle;
unsigned long waittime;
- int err, cpu;
+ int err, cpu, me = smp_processor_id();
- cpu_set(0, cpu_online_map);
- cpu_set(0, smp_callin_map);
+ cpu_clear(me, cpu_online_map);
+ cpu_set(me, cpu_online_map);
+ cpu_set(me, cpu_callin_map);
- err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
- if(err) panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
+ err = os_pipe(cpu_data[me].ipi_pipe, 1, 1);
+ if(err < 0)
+ panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
- activate_ipi(cpu_data[0].ipi_pipe[0],
+ activate_ipi(cpu_data[me].ipi_pipe[0],
current->thread.mode.tt.extern_pid);
for(cpu = 1; cpu < ncpus; cpu++){
unhash_process(idle);
waittime = 200000000;
- while (waittime-- && !cpu_isset(cpu, smp_callin_map))
+ while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
cpu_relax();
- if (cpu_isset(cpu, smp_callin_map))
+ if (cpu_isset(cpu, cpu_callin_map))
printk("done\n");
else printk("failed\n");
}
int fd;
fd = cpu_data[cpu].ipi_pipe[0];
- while (read(fd, &c, 1) == 1) {
+ while (os_read_file(fd, &c, 1) == 1) {
switch (c) {
case 'C':
smp_call_function_slave(cpu);
info = _info;
for (i=0;i<NR_CPUS;i++)
- if((i != current->thread_info->cpu) &&
+ if((i != current_thread->cpu) &&
cpu_isset(i, cpu_online_map))
- write(cpu_data[i].ipi_pipe[1], "C", 1);
+ os_write_file(cpu_data[i].ipi_pipe[1], "C", 1);
while (atomic_read(&scf_started) != cpus)
barrier();
#include "linux/config.h"
#include "linux/unistd.h"
-#include "linux/version.h"
#include "linux/sys.h"
#include "linux/swap.h"
#include "linux/syscalls.h"
#include "sysdep/syscalls.h"
#include "kern_util.h"
-extern syscall_handler_t sys_restart_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_exit;
+#ifdef CONFIG_NFSD
+#define NFSSERVCTL sys_nfsservctl
+#else
+#define NFSSERVCTL sys_ni_syscall
+#endif
+
+#define LAST_GENERIC_SYSCALL __NR_vserver
+
+#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
+#define LAST_SYSCALL LAST_GENERIC_SYSCALL
+#else
+#define LAST_SYSCALL LAST_ARCH_SYSCALL
+#endif
+
extern syscall_handler_t sys_fork;
-extern syscall_handler_t sys_creat;
-extern syscall_handler_t sys_link;
-extern syscall_handler_t sys_unlink;
-extern syscall_handler_t sys_chdir;
-extern syscall_handler_t sys_mknod;
-extern syscall_handler_t sys_chmod;
-extern syscall_handler_t sys_lchown16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_stat;
-extern syscall_handler_t sys_getpid;
-extern syscall_handler_t sys_oldumount;
-extern syscall_handler_t sys_setuid16;
-extern syscall_handler_t sys_getuid16;
+extern syscall_handler_t sys_execve;
+extern syscall_handler_t um_time;
+extern syscall_handler_t um_mount;
+extern syscall_handler_t um_stime;
extern syscall_handler_t sys_ptrace;
-extern syscall_handler_t sys_alarm;
-extern syscall_handler_t sys_fstat;
-extern syscall_handler_t sys_pause;
-extern syscall_handler_t sys_utime;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_access;
-extern syscall_handler_t sys_nice;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_sync;
-extern syscall_handler_t sys_kill;
-extern syscall_handler_t sys_rename;
-extern syscall_handler_t sys_mkdir;
-extern syscall_handler_t sys_rmdir;
extern syscall_handler_t sys_pipe;
-extern syscall_handler_t sys_times;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_brk;
-extern syscall_handler_t sys_setgid16;
-extern syscall_handler_t sys_getgid16;
-extern syscall_handler_t sys_signal;
-extern syscall_handler_t sys_geteuid16;
-extern syscall_handler_t sys_getegid16;
-extern syscall_handler_t sys_acct;
-extern syscall_handler_t sys_umount;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ioctl;
-extern syscall_handler_t sys_fcntl;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setpgid;
-extern syscall_handler_t sys_ni_syscall;
extern syscall_handler_t sys_olduname;
-extern syscall_handler_t sys_umask;
-extern syscall_handler_t sys_chroot;
-extern syscall_handler_t sys_ustat;
-extern syscall_handler_t sys_dup2;
-extern syscall_handler_t sys_getppid;
-extern syscall_handler_t sys_getpgrp;
extern syscall_handler_t sys_sigaction;
-extern syscall_handler_t sys_sgetmask;
-extern syscall_handler_t sys_ssetmask;
-extern syscall_handler_t sys_setreuid16;
-extern syscall_handler_t sys_setregid16;
extern syscall_handler_t sys_sigsuspend;
-extern syscall_handler_t sys_sigpending;
-extern syscall_handler_t sys_sethostname;
-extern syscall_handler_t sys_setrlimit;
-extern syscall_handler_t sys_old_getrlimit;
-extern syscall_handler_t sys_getrusage;
-extern syscall_handler_t sys_gettimeofday;
-extern syscall_handler_t sys_settimeofday;
-extern syscall_handler_t sys_getgroups16;
-extern syscall_handler_t sys_setgroups16;
-extern syscall_handler_t sys_symlink;
-extern syscall_handler_t sys_lstat;
-extern syscall_handler_t sys_readlink;
-extern syscall_handler_t sys_swapon;
-extern syscall_handler_t sys_uselib;
-extern syscall_handler_t sys_reboot;
extern syscall_handler_t old_readdir;
-extern syscall_handler_t sys_munmap;
-extern syscall_handler_t sys_truncate;
-extern syscall_handler_t sys_ftruncate;
-extern syscall_handler_t sys_fchmod;
-extern syscall_handler_t sys_fchown16;
-extern syscall_handler_t sys_getpriority;
-extern syscall_handler_t sys_setpriority;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_statfs;
-extern syscall_handler_t sys_fstatfs;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_socketcall;
-extern syscall_handler_t sys_syslog;
-extern syscall_handler_t sys_setitimer;
-extern syscall_handler_t sys_getitimer;
-extern syscall_handler_t sys_newstat;
-extern syscall_handler_t sys_newlstat;
-extern syscall_handler_t sys_newfstat;
extern syscall_handler_t sys_uname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_vhangup;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_swapoff;
-extern syscall_handler_t sys_sysinfo;
extern syscall_handler_t sys_ipc;
-extern syscall_handler_t sys_fsync;
extern syscall_handler_t sys_sigreturn;
-extern syscall_handler_t sys_rt_sigreturn;
extern syscall_handler_t sys_clone;
-extern syscall_handler_t sys_setdomainname;
-extern syscall_handler_t sys_newuname;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_adjtimex;
-extern syscall_handler_t sys_mprotect;
-extern syscall_handler_t sys_sigprocmask;
-extern syscall_handler_t sys_init_module;
-extern syscall_handler_t sys_delete_module;
-extern syscall_handler_t sys_quotactl;
-extern syscall_handler_t sys_getpgid;
-extern syscall_handler_t sys_fchdir;
-extern syscall_handler_t sys_bdflush;
-extern syscall_handler_t sys_sysfs;
-extern syscall_handler_t sys_personality;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_setfsuid16;
-extern syscall_handler_t sys_setfsgid16;
-extern syscall_handler_t sys_llseek;
-extern syscall_handler_t sys_getdents;
-extern syscall_handler_t sys_flock;
-extern syscall_handler_t sys_msync;
-extern syscall_handler_t sys_readv;
-extern syscall_handler_t sys_writev;
-extern syscall_handler_t sys_getsid;
-extern syscall_handler_t sys_fdatasync;
-extern syscall_handler_t sys_mlock;
-extern syscall_handler_t sys_munlock;
-extern syscall_handler_t sys_mlockall;
-extern syscall_handler_t sys_munlockall;
-extern syscall_handler_t sys_sched_setparam;
-extern syscall_handler_t sys_sched_getparam;
-extern syscall_handler_t sys_sched_setscheduler;
-extern syscall_handler_t sys_sched_getscheduler;
-extern syscall_handler_t sys_sched_get_priority_max;
-extern syscall_handler_t sys_sched_get_priority_min;
-extern syscall_handler_t sys_sched_rr_get_interval;
-extern syscall_handler_t sys_nanosleep;
-extern syscall_handler_t sys_mremap;
-extern syscall_handler_t sys_setresuid16;
-extern syscall_handler_t sys_getresuid16;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_poll;
-extern syscall_handler_t sys_nfsservctl;
-extern syscall_handler_t sys_setresgid16;
-extern syscall_handler_t sys_getresgid16;
-extern syscall_handler_t sys_prctl;
-extern syscall_handler_t sys_ni_syscall;
+extern syscall_handler_t sys_rt_sigreturn;
extern syscall_handler_t sys_rt_sigaction;
-extern syscall_handler_t sys_rt_sigprocmask;
-extern syscall_handler_t sys_rt_sigpending;
-extern syscall_handler_t sys_rt_sigtimedwait;
-extern syscall_handler_t sys_rt_sigqueueinfo;
-extern syscall_handler_t sys_rt_sigsuspend;
-extern syscall_handler_t sys_pread64;
-extern syscall_handler_t sys_pwrite64;
-extern syscall_handler_t sys_chown16;
-extern syscall_handler_t sys_getcwd;
-extern syscall_handler_t sys_capget;
-extern syscall_handler_t sys_capset;
extern syscall_handler_t sys_sigaltstack;
-extern syscall_handler_t sys_sendfile;
-extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_ni_syscall;
extern syscall_handler_t sys_vfork;
-extern syscall_handler_t sys_getrlimit;
extern syscall_handler_t sys_mmap2;
-extern syscall_handler_t sys_truncate64;
-extern syscall_handler_t sys_ftruncate64;
-extern syscall_handler_t sys_stat64;
-extern syscall_handler_t sys_lstat64;
-extern syscall_handler_t sys_fstat64;
-extern syscall_handler_t sys_lchown;
-extern syscall_handler_t sys_getuid;
-extern syscall_handler_t sys_getgid;
-extern syscall_handler_t sys_geteuid;
-extern syscall_handler_t sys_getegid;
-extern syscall_handler_t sys_setreuid;
-extern syscall_handler_t sys_setregid;
-extern syscall_handler_t sys_getgroups;
-extern syscall_handler_t sys_setgroups;
-extern syscall_handler_t sys_fchown;
-extern syscall_handler_t sys_setresuid;
-extern syscall_handler_t sys_getresuid;
-extern syscall_handler_t sys_setresgid;
-extern syscall_handler_t sys_getresgid;
-extern syscall_handler_t sys_chown;
-extern syscall_handler_t sys_setuid;
-extern syscall_handler_t sys_setgid;
-extern syscall_handler_t sys_setfsuid;
-extern syscall_handler_t sys_setfsgid;
-extern syscall_handler_t sys_pivot_root;
-extern syscall_handler_t sys_mincore;
-extern syscall_handler_t sys_madvise;
-extern syscall_handler_t sys_fcntl64;
-extern syscall_handler_t sys_getdents64;
-extern syscall_handler_t sys_gettid;
-extern syscall_handler_t sys_readahead;
-extern syscall_handler_t sys_tkill;
-extern syscall_handler_t sys_sendfile64;
-extern syscall_handler_t sys_futex;
-extern syscall_handler_t sys_sched_setaffinity;
-extern syscall_handler_t sys_sched_getaffinity;
-extern syscall_handler_t sys_io_setup;
-extern syscall_handler_t sys_io_destroy;
-extern syscall_handler_t sys_io_getevents;
-extern syscall_handler_t sys_io_submit;
-extern syscall_handler_t sys_io_cancel;
-extern syscall_handler_t sys_exit_group;
-extern syscall_handler_t sys_lookup_dcookie;
-extern syscall_handler_t sys_epoll_create;
-extern syscall_handler_t sys_epoll_ctl;
-extern syscall_handler_t sys_epoll_wait;
-extern syscall_handler_t sys_remap_file_pages;
-extern syscall_handler_t sys_set_tid_address;
-
-#ifdef CONFIG_NFSD
-#define NFSSERVCTL sys_nfsservctl
-#else
-#define NFSSERVCTL sys_ni_syscall
-#endif
-
-extern syscall_handler_t um_mount;
-extern syscall_handler_t um_time;
-extern syscall_handler_t um_stime;
-
-#define LAST_GENERIC_SYSCALL __NR_set_tid_address
-
-#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
-#define LAST_SYSCALL LAST_GENERIC_SYSCALL
-#else
-#define LAST_SYSCALL LAST_ARCH_SYSCALL
-#endif
+extern syscall_handler_t sys_timer_create;
+extern syscall_handler_t old_mmap_i386;
+extern syscall_handler_t old_select;
+extern syscall_handler_t sys_modify_ldt;
+extern syscall_handler_t sys_rt_sigsuspend;
syscall_handler_t *sys_call_table[] = {
- [ __NR_restart_syscall ] = sys_restart_syscall,
- [ __NR_exit ] = sys_exit,
- [ __NR_fork ] = sys_fork,
+ [ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
+ [ __NR_exit ] (syscall_handler_t *) sys_exit,
+ [ __NR_fork ] (syscall_handler_t *) sys_fork,
[ __NR_read ] = (syscall_handler_t *) sys_read,
[ __NR_write ] = (syscall_handler_t *) sys_write,
[ __NR_open ] = (syscall_handler_t *) sys_open,
[ __NR_close ] = (syscall_handler_t *) sys_close,
[ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid,
- [ __NR_creat ] = sys_creat,
- [ __NR_link ] = sys_link,
- [ __NR_unlink ] = sys_unlink,
+ [ __NR_creat ] (syscall_handler_t *) sys_creat,
+ [ __NR_link ] (syscall_handler_t *) sys_link,
+ [ __NR_unlink ] (syscall_handler_t *) sys_unlink,
[ __NR_execve ] = (syscall_handler_t *) sys_execve,
/* declared differently in kern_util.h */
- [ __NR_chdir ] = sys_chdir,
+ [ __NR_chdir ] (syscall_handler_t *) sys_chdir,
[ __NR_time ] = um_time,
- [ __NR_mknod ] = sys_mknod,
- [ __NR_chmod ] = sys_chmod,
- [ __NR_lchown ] = sys_lchown16,
- [ __NR_break ] = sys_ni_syscall,
- [ __NR_oldstat ] = sys_stat,
+ [ __NR_mknod ] (syscall_handler_t *) sys_mknod,
+ [ __NR_chmod ] (syscall_handler_t *) sys_chmod,
+ [ __NR_lchown ] (syscall_handler_t *) sys_lchown16,
+ [ __NR_break ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_oldstat ] (syscall_handler_t *) sys_stat,
[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
- [ __NR_getpid ] = sys_getpid,
+ [ __NR_getpid ] (syscall_handler_t *) sys_getpid,
[ __NR_mount ] = um_mount,
- [ __NR_umount ] = sys_oldumount,
- [ __NR_setuid ] = sys_setuid16,
- [ __NR_getuid ] = sys_getuid16,
+ [ __NR_umount ] (syscall_handler_t *) sys_oldumount,
+ [ __NR_setuid ] (syscall_handler_t *) sys_setuid16,
+ [ __NR_getuid ] (syscall_handler_t *) sys_getuid16,
[ __NR_stime ] = um_stime,
- [ __NR_ptrace ] = sys_ptrace,
- [ __NR_alarm ] = sys_alarm,
- [ __NR_oldfstat ] = sys_fstat,
- [ __NR_pause ] = sys_pause,
- [ __NR_utime ] = sys_utime,
- [ __NR_stty ] = sys_ni_syscall,
- [ __NR_gtty ] = sys_ni_syscall,
- [ __NR_access ] = sys_access,
- [ __NR_nice ] = sys_nice,
- [ __NR_ftime ] = sys_ni_syscall,
- [ __NR_sync ] = sys_sync,
- [ __NR_kill ] = sys_kill,
- [ __NR_rename ] = sys_rename,
- [ __NR_mkdir ] = sys_mkdir,
- [ __NR_rmdir ] = sys_rmdir,
+ [ __NR_ptrace ] (syscall_handler_t *) sys_ptrace,
+ [ __NR_alarm ] (syscall_handler_t *) sys_alarm,
+ [ __NR_oldfstat ] (syscall_handler_t *) sys_fstat,
+ [ __NR_pause ] (syscall_handler_t *) sys_pause,
+ [ __NR_utime ] (syscall_handler_t *) sys_utime,
+ [ __NR_stty ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_access ] (syscall_handler_t *) sys_access,
+ [ __NR_nice ] (syscall_handler_t *) sys_nice,
+ [ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_sync ] (syscall_handler_t *) sys_sync,
+ [ __NR_kill ] (syscall_handler_t *) sys_kill,
+ [ __NR_rename ] (syscall_handler_t *) sys_rename,
+ [ __NR_mkdir ] (syscall_handler_t *) sys_mkdir,
+ [ __NR_rmdir ] (syscall_handler_t *) sys_rmdir,
/* Declared differently in asm/unistd.h */
[ __NR_dup ] = (syscall_handler_t *) sys_dup,
- [ __NR_pipe ] = sys_pipe,
- [ __NR_times ] = sys_times,
- [ __NR_prof ] = sys_ni_syscall,
- [ __NR_brk ] = sys_brk,
- [ __NR_setgid ] = sys_setgid16,
- [ __NR_getgid ] = sys_getgid16,
- [ __NR_signal ] = sys_signal,
- [ __NR_geteuid ] = sys_geteuid16,
- [ __NR_getegid ] = sys_getegid16,
- [ __NR_acct ] = sys_acct,
- [ __NR_umount2 ] = sys_umount,
- [ __NR_lock ] = sys_ni_syscall,
- [ __NR_ioctl ] = sys_ioctl,
- [ __NR_fcntl ] = sys_fcntl,
- [ __NR_mpx ] = sys_ni_syscall,
- [ __NR_setpgid ] = sys_setpgid,
- [ __NR_ulimit ] = sys_ni_syscall,
- [ __NR_oldolduname ] = sys_olduname,
- [ __NR_umask ] = sys_umask,
- [ __NR_chroot ] = sys_chroot,
- [ __NR_ustat ] = sys_ustat,
- [ __NR_dup2 ] = sys_dup2,
- [ __NR_getppid ] = sys_getppid,
- [ __NR_getpgrp ] = sys_getpgrp,
+ [ __NR_pipe ] (syscall_handler_t *) sys_pipe,
+ [ __NR_times ] (syscall_handler_t *) sys_times,
+ [ __NR_prof ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_brk ] (syscall_handler_t *) sys_brk,
+ [ __NR_setgid ] (syscall_handler_t *) sys_setgid16,
+ [ __NR_getgid ] (syscall_handler_t *) sys_getgid16,
+ [ __NR_signal ] (syscall_handler_t *) sys_signal,
+ [ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16,
+ [ __NR_getegid ] (syscall_handler_t *) sys_getegid16,
+ [ __NR_acct ] (syscall_handler_t *) sys_acct,
+ [ __NR_umount2 ] (syscall_handler_t *) sys_umount,
+ [ __NR_lock ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_ioctl ] (syscall_handler_t *) sys_ioctl,
+ [ __NR_fcntl ] (syscall_handler_t *) sys_fcntl,
+ [ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_setpgid ] (syscall_handler_t *) sys_setpgid,
+ [ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_oldolduname ] (syscall_handler_t *) sys_olduname,
+ [ __NR_umask ] (syscall_handler_t *) sys_umask,
+ [ __NR_chroot ] (syscall_handler_t *) sys_chroot,
+ [ __NR_ustat ] (syscall_handler_t *) sys_ustat,
+ [ __NR_dup2 ] (syscall_handler_t *) sys_dup2,
+ [ __NR_getppid ] (syscall_handler_t *) sys_getppid,
+ [ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp,
[ __NR_setsid ] = (syscall_handler_t *) sys_setsid,
- [ __NR_sigaction ] = sys_sigaction,
- [ __NR_sgetmask ] = sys_sgetmask,
- [ __NR_ssetmask ] = sys_ssetmask,
- [ __NR_setreuid ] = sys_setreuid16,
- [ __NR_setregid ] = sys_setregid16,
- [ __NR_sigsuspend ] = sys_sigsuspend,
- [ __NR_sigpending ] = sys_sigpending,
- [ __NR_sethostname ] = sys_sethostname,
- [ __NR_setrlimit ] = sys_setrlimit,
- [ __NR_getrlimit ] = sys_old_getrlimit,
- [ __NR_getrusage ] = sys_getrusage,
- [ __NR_gettimeofday ] = sys_gettimeofday,
- [ __NR_settimeofday ] = sys_settimeofday,
- [ __NR_getgroups ] = sys_getgroups16,
- [ __NR_setgroups ] = sys_setgroups16,
- [ __NR_symlink ] = sys_symlink,
- [ __NR_oldlstat ] = sys_lstat,
- [ __NR_readlink ] = sys_readlink,
- [ __NR_uselib ] = sys_uselib,
+ [ __NR_sigaction ] (syscall_handler_t *) sys_sigaction,
+ [ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask,
+ [ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask,
+ [ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16,
+ [ __NR_setregid ] (syscall_handler_t *) sys_setregid16,
+ [ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend,
+ [ __NR_sigpending ] (syscall_handler_t *) sys_sigpending,
+ [ __NR_sethostname ] (syscall_handler_t *) sys_sethostname,
+ [ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit,
+ [ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit,
+ [ __NR_getrusage ] (syscall_handler_t *) sys_getrusage,
+ [ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday,
+ [ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday,
+ [ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16,
+ [ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16,
+ [ __NR_symlink ] (syscall_handler_t *) sys_symlink,
+ [ __NR_oldlstat ] (syscall_handler_t *) sys_lstat,
+ [ __NR_readlink ] (syscall_handler_t *) sys_readlink,
+ [ __NR_uselib ] (syscall_handler_t *) sys_uselib,
[ __NR_swapon ] = (syscall_handler_t *) sys_swapon,
- [ __NR_reboot ] = sys_reboot,
+ [ __NR_reboot ] (syscall_handler_t *) sys_reboot,
[ __NR_readdir ] = old_readdir,
- [ __NR_munmap ] = sys_munmap,
- [ __NR_truncate ] = sys_truncate,
- [ __NR_ftruncate ] = sys_ftruncate,
- [ __NR_fchmod ] = sys_fchmod,
- [ __NR_fchown ] = sys_fchown16,
- [ __NR_getpriority ] = sys_getpriority,
- [ __NR_setpriority ] = sys_setpriority,
- [ __NR_profil ] = sys_ni_syscall,
- [ __NR_statfs ] = sys_statfs,
- [ __NR_fstatfs ] = sys_fstatfs,
- [ __NR_ioperm ] = sys_ni_syscall,
- [ __NR_socketcall ] = sys_socketcall,
- [ __NR_syslog ] = sys_syslog,
- [ __NR_setitimer ] = sys_setitimer,
- [ __NR_getitimer ] = sys_getitimer,
- [ __NR_stat ] = sys_newstat,
- [ __NR_lstat ] = sys_newlstat,
- [ __NR_fstat ] = sys_newfstat,
- [ __NR_olduname ] = sys_uname,
- [ __NR_iopl ] = sys_ni_syscall,
- [ __NR_vhangup ] = sys_vhangup,
- [ __NR_idle ] = sys_ni_syscall,
+ [ __NR_munmap ] (syscall_handler_t *) sys_munmap,
+ [ __NR_truncate ] (syscall_handler_t *) sys_truncate,
+ [ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate,
+ [ __NR_fchmod ] (syscall_handler_t *) sys_fchmod,
+ [ __NR_fchown ] (syscall_handler_t *) sys_fchown16,
+ [ __NR_getpriority ] (syscall_handler_t *) sys_getpriority,
+ [ __NR_setpriority ] (syscall_handler_t *) sys_setpriority,
+ [ __NR_profil ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_statfs ] (syscall_handler_t *) sys_statfs,
+ [ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs,
+ [ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_socketcall ] (syscall_handler_t *) sys_socketcall,
+ [ __NR_syslog ] (syscall_handler_t *) sys_syslog,
+ [ __NR_setitimer ] (syscall_handler_t *) sys_setitimer,
+ [ __NR_getitimer ] (syscall_handler_t *) sys_getitimer,
+ [ __NR_stat ] (syscall_handler_t *) sys_newstat,
+ [ __NR_lstat ] (syscall_handler_t *) sys_newlstat,
+ [ __NR_fstat ] (syscall_handler_t *) sys_newfstat,
+ [ __NR_olduname ] (syscall_handler_t *) sys_uname,
+ [ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_vhangup ] (syscall_handler_t *) sys_vhangup,
+ [ __NR_idle ] (syscall_handler_t *) sys_ni_syscall,
[ __NR_wait4 ] = (syscall_handler_t *) sys_wait4,
[ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff,
- [ __NR_sysinfo ] = sys_sysinfo,
- [ __NR_ipc ] = sys_ipc,
- [ __NR_fsync ] = sys_fsync,
- [ __NR_sigreturn ] = sys_sigreturn,
- [ __NR_clone ] = sys_clone,
- [ __NR_setdomainname ] = sys_setdomainname,
- [ __NR_uname ] = sys_newuname,
- [ __NR_adjtimex ] = sys_adjtimex,
- [ __NR_mprotect ] = sys_mprotect,
- [ __NR_sigprocmask ] = sys_sigprocmask,
- [ __NR_create_module ] = sys_ni_syscall,
- [ __NR_init_module ] = sys_init_module,
- [ __NR_delete_module ] = sys_delete_module,
- [ __NR_get_kernel_syms ] = sys_ni_syscall,
- [ __NR_quotactl ] = sys_quotactl,
- [ __NR_getpgid ] = sys_getpgid,
- [ __NR_fchdir ] = sys_fchdir,
- [ __NR_bdflush ] = sys_bdflush,
- [ __NR_sysfs ] = sys_sysfs,
- [ __NR_personality ] = sys_personality,
- [ __NR_afs_syscall ] = sys_ni_syscall,
- [ __NR_setfsuid ] = sys_setfsuid16,
- [ __NR_setfsgid ] = sys_setfsgid16,
- [ __NR__llseek ] = sys_llseek,
- [ __NR_getdents ] = sys_getdents,
+ [ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo,
+ [ __NR_ipc ] (syscall_handler_t *) sys_ipc,
+ [ __NR_fsync ] (syscall_handler_t *) sys_fsync,
+ [ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn,
+ [ __NR_clone ] (syscall_handler_t *) sys_clone,
+ [ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname,
+ [ __NR_uname ] (syscall_handler_t *) sys_newuname,
+ [ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex,
+ [ __NR_mprotect ] (syscall_handler_t *) sys_mprotect,
+ [ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask,
+ [ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_init_module ] (syscall_handler_t *) sys_init_module,
+ [ __NR_delete_module ] (syscall_handler_t *) sys_delete_module,
+ [ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_quotactl ] (syscall_handler_t *) sys_quotactl,
+ [ __NR_getpgid ] (syscall_handler_t *) sys_getpgid,
+ [ __NR_fchdir ] (syscall_handler_t *) sys_fchdir,
+ [ __NR_bdflush ] (syscall_handler_t *) sys_bdflush,
+ [ __NR_sysfs ] (syscall_handler_t *) sys_sysfs,
+ [ __NR_personality ] (syscall_handler_t *) sys_personality,
+ [ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16,
+ [ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16,
+ [ __NR__llseek ] (syscall_handler_t *) sys_llseek,
+ [ __NR_getdents ] (syscall_handler_t *) sys_getdents,
[ __NR__newselect ] = (syscall_handler_t *) sys_select,
- [ __NR_flock ] = sys_flock,
- [ __NR_msync ] = sys_msync,
- [ __NR_readv ] = sys_readv,
- [ __NR_writev ] = sys_writev,
- [ __NR_getsid ] = sys_getsid,
- [ __NR_fdatasync ] = sys_fdatasync,
+ [ __NR_flock ] (syscall_handler_t *) sys_flock,
+ [ __NR_msync ] (syscall_handler_t *) sys_msync,
+ [ __NR_readv ] (syscall_handler_t *) sys_readv,
+ [ __NR_writev ] (syscall_handler_t *) sys_writev,
+ [ __NR_getsid ] (syscall_handler_t *) sys_getsid,
+ [ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync,
[ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl,
- [ __NR_mlock ] = sys_mlock,
- [ __NR_munlock ] = sys_munlock,
- [ __NR_mlockall ] = sys_mlockall,
- [ __NR_munlockall ] = sys_munlockall,
- [ __NR_sched_setparam ] = sys_sched_setparam,
- [ __NR_sched_getparam ] = sys_sched_getparam,
- [ __NR_sched_setscheduler ] = sys_sched_setscheduler,
- [ __NR_sched_getscheduler ] = sys_sched_getscheduler,
+ [ __NR_mlock ] (syscall_handler_t *) sys_mlock,
+ [ __NR_munlock ] (syscall_handler_t *) sys_munlock,
+ [ __NR_mlockall ] (syscall_handler_t *) sys_mlockall,
+ [ __NR_munlockall ] (syscall_handler_t *) sys_munlockall,
+ [ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam,
+ [ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam,
+ [ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler,
+ [ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler,
[ __NR_sched_yield ] = (syscall_handler_t *) yield,
- [ __NR_sched_get_priority_max ] = sys_sched_get_priority_max,
- [ __NR_sched_get_priority_min ] = sys_sched_get_priority_min,
- [ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval,
- [ __NR_nanosleep ] = sys_nanosleep,
- [ __NR_mremap ] = sys_mremap,
- [ __NR_setresuid ] = sys_setresuid16,
- [ __NR_getresuid ] = sys_getresuid16,
- [ __NR_vm86 ] = sys_ni_syscall,
- [ __NR_query_module ] = sys_ni_syscall,
- [ __NR_poll ] = sys_poll,
- [ __NR_nfsservctl ] = NFSSERVCTL,
- [ __NR_setresgid ] = sys_setresgid16,
- [ __NR_getresgid ] = sys_getresgid16,
- [ __NR_prctl ] = sys_prctl,
- [ __NR_rt_sigreturn ] = sys_rt_sigreturn,
- [ __NR_rt_sigaction ] = sys_rt_sigaction,
- [ __NR_rt_sigprocmask ] = sys_rt_sigprocmask,
- [ __NR_rt_sigpending ] = sys_rt_sigpending,
- [ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait,
- [ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo,
- [ __NR_rt_sigsuspend ] = sys_rt_sigsuspend,
- [ __NR_pread64 ] = sys_pread64,
- [ __NR_pwrite64 ] = sys_pwrite64,
- [ __NR_chown ] = sys_chown16,
- [ __NR_getcwd ] = sys_getcwd,
- [ __NR_capget ] = sys_capget,
- [ __NR_capset ] = sys_capset,
- [ __NR_sigaltstack ] = sys_sigaltstack,
- [ __NR_sendfile ] = sys_sendfile,
- [ __NR_getpmsg ] = sys_ni_syscall,
- [ __NR_putpmsg ] = sys_ni_syscall,
- [ __NR_vfork ] = sys_vfork,
- [ __NR_ugetrlimit ] = sys_getrlimit,
- [ __NR_mmap2 ] = sys_mmap2,
- [ __NR_truncate64 ] = sys_truncate64,
- [ __NR_ftruncate64 ] = sys_ftruncate64,
- [ __NR_stat64 ] = sys_stat64,
- [ __NR_lstat64 ] = sys_lstat64,
- [ __NR_fstat64 ] = sys_fstat64,
- [ __NR_fcntl64 ] = sys_fcntl64,
- [ __NR_getdents64 ] = sys_getdents64,
- [ __NR_gettid ] = sys_gettid,
- [ __NR_readahead ] = sys_readahead,
- [ __NR_setxattr ] = sys_ni_syscall,
- [ __NR_lsetxattr ] = sys_ni_syscall,
- [ __NR_fsetxattr ] = sys_ni_syscall,
- [ __NR_getxattr ] = sys_ni_syscall,
- [ __NR_lgetxattr ] = sys_ni_syscall,
- [ __NR_fgetxattr ] = sys_ni_syscall,
- [ __NR_listxattr ] = sys_ni_syscall,
- [ __NR_llistxattr ] = sys_ni_syscall,
- [ __NR_flistxattr ] = sys_ni_syscall,
- [ __NR_removexattr ] = sys_ni_syscall,
- [ __NR_lremovexattr ] = sys_ni_syscall,
- [ __NR_fremovexattr ] = sys_ni_syscall,
- [ __NR_tkill ] = sys_tkill,
- [ __NR_sendfile64 ] = sys_sendfile64,
- [ __NR_futex ] = sys_futex,
- [ __NR_sched_setaffinity ] = sys_sched_setaffinity,
- [ __NR_sched_getaffinity ] = sys_sched_getaffinity,
- [ __NR_io_setup ] = sys_io_setup,
- [ __NR_io_destroy ] = sys_io_destroy,
- [ __NR_io_getevents ] = sys_io_getevents,
- [ __NR_io_submit ] = sys_io_submit,
- [ __NR_io_cancel ] = sys_io_cancel,
- [ __NR_exit_group ] = sys_exit_group,
- [ __NR_lookup_dcookie ] = sys_lookup_dcookie,
- [ __NR_epoll_create ] = sys_epoll_create,
- [ __NR_epoll_ctl ] = sys_epoll_ctl,
- [ __NR_epoll_wait ] = sys_epoll_wait,
- [ __NR_remap_file_pages ] = sys_remap_file_pages,
- [ __NR_set_tid_address ] = sys_set_tid_address,
+ [ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max,
+ [ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min,
+ [ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval,
+ [ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep,
+ [ __NR_mremap ] (syscall_handler_t *) sys_mremap,
+ [ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16,
+ [ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16,
+ [ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_poll ] (syscall_handler_t *) sys_poll,
+ [ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL,
+ [ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16,
+ [ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16,
+ [ __NR_prctl ] (syscall_handler_t *) sys_prctl,
+ [ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn,
+ [ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction,
+ [ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask,
+ [ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending,
+ [ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait,
+ [ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo,
+ [ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend,
+ [ __NR_pread64 ] (syscall_handler_t *) sys_pread64,
+ [ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64,
+ [ __NR_chown ] (syscall_handler_t *) sys_chown16,
+ [ __NR_getcwd ] (syscall_handler_t *) sys_getcwd,
+ [ __NR_capget ] (syscall_handler_t *) sys_capget,
+ [ __NR_capset ] (syscall_handler_t *) sys_capset,
+ [ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack,
+ [ __NR_sendfile ] (syscall_handler_t *) sys_sendfile,
+ [ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_vfork ] (syscall_handler_t *) sys_vfork,
+ [ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit,
+ [ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2,
+ [ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64,
+ [ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64,
+ [ __NR_stat64 ] (syscall_handler_t *) sys_stat64,
+ [ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64,
+ [ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64,
+ [ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64,
+ [ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64,
+ [ 223 ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_gettid ] (syscall_handler_t *) sys_gettid,
+ [ __NR_readahead ] (syscall_handler_t *) sys_readahead,
+ [ __NR_setxattr ] (syscall_handler_t *) sys_setxattr,
+ [ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr,
+ [ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr,
+ [ __NR_getxattr ] (syscall_handler_t *) sys_getxattr,
+ [ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr,
+ [ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr,
+ [ __NR_listxattr ] (syscall_handler_t *) sys_listxattr,
+ [ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr,
+ [ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr,
+ [ __NR_removexattr ] (syscall_handler_t *) sys_removexattr,
+ [ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr,
+ [ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr,
+ [ __NR_tkill ] (syscall_handler_t *) sys_tkill,
+ [ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64,
+ [ __NR_futex ] (syscall_handler_t *) sys_futex,
+ [ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity,
+ [ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity,
+ [ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_io_setup ] (syscall_handler_t *) sys_io_setup,
+ [ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy,
+ [ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents,
+ [ __NR_io_submit ] (syscall_handler_t *) sys_io_submit,
+ [ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel,
+ [ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64,
+ [ 251 ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_exit_group ] (syscall_handler_t *) sys_exit_group,
+ [ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie,
+ [ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create,
+ [ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl,
+ [ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait,
+ [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages,
+ [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address,
+ [ __NR_timer_create ] (syscall_handler_t *) sys_timer_create,
+ [ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime,
+ [ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime,
+ [ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun,
+ [ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete,
+ [ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime,
+ [ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime,
+ [ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres,
+ [ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep,
+ [ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64,
+ [ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64,
+ [ __NR_tgkill ] (syscall_handler_t *) sys_tgkill,
+ [ __NR_utimes ] (syscall_handler_t *) sys_utimes,
+ [ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64,
+ [ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
long sys_fork(void)
{
- struct task_struct *p;
+ long ret;
current->thread.forking = 1;
- p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+ ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
current->thread.forking = 0;
- return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+ return(ret);
}
-long sys_clone(unsigned long clone_flags, unsigned long newsp)
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ int *parent_tid, int *child_tid)
{
- struct task_struct *p;
+ long ret;
current->thread.forking = 1;
- p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
+ ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
current->thread.forking = 0;
- return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+ return(ret);
}
long sys_vfork(void)
{
- struct task_struct *p;
+ long ret;
current->thread.forking = 1;
- p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL);
+ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
+ NULL);
current->thread.forking = 0;
- return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
+ return(ret);
}
/* common code for old and new mmaps */
-static inline long do_mmap2(
- unsigned long addr, unsigned long len,
- unsigned long prot, unsigned long flags,
- unsigned long fd, unsigned long pgoff)
+long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags, unsigned long fd,
+ unsigned long pgoff)
{
int error = -EBADF;
struct file * file = NULL;
goto out;
}
- down_write(¤t->mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
- up_write(¤t->mm->mmap_sem);
+ down_write(&mm->mmap_sem);
+ error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
+ up_write(&mm->mmap_sem);
if (file)
fput(file);
unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff)
{
- return do_mmap2(addr, len, prot, flags, fd, pgoff);
+ return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
}
/*
if (offset & ~PAGE_MASK)
goto out;
- err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+ err = do_mmap2(current->mm, addr, len, prot, flags, fd,
+ offset >> PAGE_SHIFT);
out:
return err;
}
error = do_pipe(fd);
if (!error) {
- if (copy_to_user(fildes, fd, 2*sizeof(int)))
+ if (copy_to_user(fildes, fd, sizeof(fd)))
error = -EFAULT;
}
return error;
}
-int sys_sigaction(int sig, const struct old_sigaction *act,
- struct old_sigaction *oact)
-{
- struct k_sigaction new_ka, old_ka;
- int ret;
-
- if (act) {
- old_sigset_t mask;
- if (verify_area(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 (verify_area(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;
-}
-
/*
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
*
return sys_shmctl (first, second,
(struct shmid_ds *) ptr);
default:
- return -EINVAL;
+ return -ENOSYS;
}
}
return error;
}
-int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
-{
- return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs)));
-}
-
long execute_syscall(void *r)
{
return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
}
EXPORT_SYMBOL(dump_stack);
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+ show_trace(sp);
+}
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
}
if((dir == NULL) || (*dir == '\0'))
dir = "/tmp";
+
tempdir = malloc(strlen(dir) + 2);
if(tempdir == NULL){
fprintf(stderr, "Failed to malloc tempdir, "
else
*tempname = 0;
strcat(tempname, template);
- if((fd = mkstemp(tempname)) < 0){
+ fd = mkstemp(tempname);
+ if(fd < 0){
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
strerror(errno));
return -1;
return -1;
}
if(out_tempname){
- if((*out_tempname = strdup(tempname)) == NULL){
+ *out_tempname = strdup(tempname);
+ if(*out_tempname == NULL){
perror("strdup");
return -1;
}
*/
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
-#include "linux/module.h"
#include "user_util.h"
#include "kern_util.h"
#include "user.h"
#include "process.h"
#include "signal_user.h"
#include "time_user.h"
+#include "kern_constants.h"
+
+/* XXX This really needs to be declared and initialized in a kernel file since
+ * it's in <linux/time.h>
+ */
+extern struct timespec wall_to_monotonic;
extern struct timeval xtime;
+struct timeval local_offset = { 0, 0 };
+
void timer(void)
{
gettimeofday(&xtime, NULL);
+ timeradd(&xtime, &local_offset, &xtime);
}
void set_interval(int timer_type)
errno);
}
-void idle_timer(void)
+void uml_idle_timer(void)
{
if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
panic("Couldn't unset SIGVTALRM handler");
set_interval(ITIMER_REAL);
}
+static unsigned long long get_host_hz(void)
+{
+ char mhzline[16], *end;
+ unsigned long long mhz;
+ int ret, mult, rest, len;
+
+ ret = cpu_feature("cpu MHz", mhzline,
+ sizeof(mhzline) / sizeof(mhzline[0]));
+ if(!ret)
+ panic ("Could not get host MHZ");
+
+ mhz = strtoul(mhzline, &end, 10);
+
+ /* This business is to parse a floating point number without using
+ * floating types.
+ */
+
+ rest = 0;
+ mult = 0;
+ if(*end == '.'){
+ end++;
+ len = strlen(end);
+ if(len < 6)
+ mult = 6 - len;
+ else if(len > 6)
+ end[6] = '\0';
+ rest = strtoul(end, NULL, 10);
+ while(mult-- > 0)
+ rest *= 10;
+ }
+
+ return(1000000 * mhz + rest);
+}
+
+unsigned long long host_hz = 0;
+
+extern int do_posix_clock_monotonic_gettime(struct timespec *tp);
+
void time_init(void)
{
+ struct timespec now;
+
+ host_hz = get_host_hz();
if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
panic("Couldn't set SIGVTALRM handler");
set_interval(ITIMER_VIRTUAL);
+
+ do_posix_clock_monotonic_gettime(&now);
+ wall_to_monotonic.tv_sec = -now.tv_sec;
+ wall_to_monotonic.tv_nsec = -now.tv_nsec;
}
-struct timeval local_offset = { 0, 0 };
+/* Declared in linux/time.h, which can't be included here */
+extern void clock_was_set(void);
void do_gettimeofday(struct timeval *tv)
{
clock_was_set();
}
-EXPORT_SYMBOL(do_gettimeofday);
-
int do_settimeofday(struct timespec *tv)
{
struct timeval now;
unsigned long flags;
struct timeval tv_in;
- if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC)
return -EINVAL;
tv_in.tv_sec = tv->tv_sec;
gettimeofday(&now, NULL);
timersub(&tv_in, &now, &local_offset);
time_unlock(flags);
-}
-EXPORT_SYMBOL(do_settimeofday);
+ return(0);
+}
void idle_sleep(int secs)
{
return(HZ);
}
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+ return (unsigned long long)jiffies_64 * (1000000000 / HZ);
+}
+
/* Changed at early boot */
int timer_irq_inited = 0;
-/* missed_ticks will be modified after kernel memory has been
- * write-protected, so this puts it in a section which will be left
- * write-enabled.
- */
-int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
+static int first_tick;
+static unsigned long long prev_tsc;
+static long long delta; /* Deviation per interval */
+
+extern unsigned long long host_hz;
void timer_irq(union uml_pt_regs *regs)
{
- int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
+ unsigned long long ticks = 0;
+
+ if(!timer_irq_inited){
+ /* This is to ensure that ticks don't pile up when
+ * the timer handler is suspended */
+ first_tick = 0;
+ return;
+ }
+
+ if(first_tick){
+#if defined(CONFIG_UML_REAL_TIME_CLOCK)
+ unsigned long long tsc;
+ /* We've had 1 tick */
+ tsc = time_stamp();
- if(!timer_irq_inited) return;
- missed_ticks[cpu] = 0;
- while(ticks--) do_IRQ(TIMER_IRQ, regs);
+ delta += tsc - prev_tsc;
+ prev_tsc = tsc;
+
+ ticks += (delta * HZ) / host_hz;
+ delta -= (ticks * host_hz) / HZ;
+#else
+ ticks = 1;
+#endif
+ }
+ else {
+ prev_tsc = time_stamp();
+ first_tick = 1;
+ }
+
+ while(ticks > 0){
+ do_IRQ(TIMER_IRQ, regs);
+ ticks--;
+ }
}
void boot_timer_handler(int sig)
do_timer(®s);
}
-void um_timer(int irq, void *dev, struct pt_regs *regs)
+irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs)
{
+ unsigned long flags;
+
do_timer(regs);
- write_seqlock(&xtime_lock);
+ write_seqlock_irqsave(&xtime_lock, flags);
timer();
- write_sequnlock(&xtime_lock);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ return(IRQ_HANDLED);
}
long um_time(int * tloc)
long um_stime(int * tptr)
{
int value;
- struct timeval new;
+ struct timespec new;
if (get_user(value, tptr))
return -EFAULT;
new.tv_sec = value;
- new.tv_usec = 0;
+ new.tv_nsec = 0;
do_settimeofday(&new);
return 0;
}
void timer_handler(int sig, union uml_pt_regs *regs)
{
#ifdef CONFIG_SMP
+ local_irq_disable();
update_process_times(user_context(UPT_SP(regs)));
+ local_irq_enable();
#endif
- if(current->thread_info->cpu == 0)
+ if(current_thread->cpu == 0)
timer_irq(regs);
}
unsigned long time_lock(void)
{
unsigned long flags;
+
spin_lock_irqsave(&timer_spinlock, flags);
return(flags);
}
int err;
CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
- if((err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer",
- NULL)) != 0)
+ err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
+ if(err != 0)
printk(KERN_ERR "timer_init : request_irq failed - "
"errno = %d\n", -err);
timer_irq_inited = 1;
__initcall(timer_init);
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
#include "asm/tlbflush.h"
#include "asm/a.out.h"
#include "asm/current.h"
+#include "asm/irq.h"
#include "user_util.h"
#include "kern_util.h"
#include "kern.h"
#include "chan_kern.h"
#include "mconsole_kern.h"
#include "2_5compat.h"
+#include "mem.h"
+#include "mem_kern.h"
int handle_page_fault(unsigned long address, unsigned long ip,
int is_write, int is_user, int *code_out)
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
page = address & PAGE_MASK;
- if(page == (unsigned long) current->thread_info + PAGE_SIZE)
+ if(page == (unsigned long) current_thread + PAGE_SIZE)
panic("Kernel stack overflow");
pgd = pgd_offset(mm, page);
pmd = pmd_offset(pgd, page);
- survive:
do {
+ survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
case VM_FAULT_MINOR:
current->min_flt++;
err = -ENOMEM;
goto out_of_memory;
default:
- BUG();
+ if (current->pid == 1) {
+ up_read(&mm->mmap_sem);
+ yield();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
+ goto out;
}
pte = pte_offset_kernel(pmd, page);
} while(!pte_present(*pte));
+ err = 0;
*pte = pte_mkyoung(*pte);
if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
flush_tlb_page(vma, page);
- err = 0;
out:
up_read(&mm->mmap_sem);
return(err);
goto out;
}
+LIST_HEAD(physmem_remappers);
+
+void register_remapper(struct remapper *info)
+{
+ list_add(&info->list, &physmem_remappers);
+}
+
+static int check_remapped_addr(unsigned long address, int is_write)
+{
+ struct remapper *remapper;
+ struct list_head *ele;
+ __u64 offset;
+ int fd;
+
+ fd = phys_mapping(__pa(address), &offset);
+ if(fd == -1)
+ return(0);
+
+ list_for_each(ele, &physmem_remappers){
+ remapper = list_entry(ele, struct remapper, list);
+ if((*remapper->proc)(fd, address, is_write, offset))
+ return(1);
+ }
+
+ return(0);
+}
+
unsigned long segv(unsigned long address, unsigned long ip, int is_write,
int is_user, void *sc)
{
flush_tlb_kernel_vm();
return(0);
}
- if(current->mm == NULL)
+ else if(check_remapped_addr(address & PAGE_MASK, is_write))
+ return(0);
+ else if(current->mm == NULL)
panic("Segfault with no mm");
err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
current->thread.fault_addr = (void *) address;
do_longjmp(catcher, 1);
}
- else if(current->thread.fault_addr != NULL){
+ else if(current->thread.fault_addr != NULL)
panic("fault_addr set but no fault catcher");
- }
else if(arch_fixup(ip, sc))
return(0);
{
struct siginfo si;
- printk(KERN_ERR "Unfixable SEGV in '%s' (pid %d) at 0x%lx "
- "(ip 0x%lx)\n", current->comm, current->pid, address, ip);
si.si_signo = SIGSEGV;
si.si_code = SEGV_ACCERR;
si.si_addr = (void *) address;
else relay_signal(sig, regs);
}
+void winch(int sig, union uml_pt_regs *regs)
+{
+ do_IRQ(WINCH_IRQ, regs);
+}
+
void trap_init(void)
{
}
#include <stdlib.h>
#include <errno.h>
-#include <fcntl.h>
#include <setjmp.h>
#include <signal.h>
#include <sys/time.h>
-#include <sys/ioctl.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <asm/page.h>
.is_irq = 0 },
[ SIGILL ] { .handler = relay_signal,
.is_irq = 0 },
+ [ SIGWINCH ] { .handler = winch,
+ .is_irq = 1 },
[ SIGBUS ] { .handler = bus_handler,
.is_irq = 0 },
[ SIGSEGV] { .handler = segv_handler,
sig, &sc);
}
-extern int timer_irq_inited, missed_ticks[];
+extern int timer_irq_inited;
void alarm_handler(int sig, struct sigcontext sc)
{
if(!timer_irq_inited) return;
- missed_ticks[cpu()]++;
if(sig == SIGALRM)
switch_timers(0);
{
jmp_buf *buf = b;
- longjmp(*buf, val);
+ siglongjmp(*buf, val);
}
/*
#
-# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com)
# Licensed under the GPL
#
obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
- uaccess_user.o sys-$(SUBARCH)/
+ uaccess.o uaccess_user.o sys-$(SUBARCH)/
obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
$(obj)/unmap_fin.o : $(src)/unmap.o
ld -r -o $@ $< -lc -L/usr/lib
-
-clean :
#include "mem_user.h"
#include "os.h"
#include "tlb.h"
+#include "mode.h"
static int exec_tramp(void *sig_stack)
{
do_exit(SIGKILL);
}
- if(current->thread_info->cpu == 0)
+ if(current_thread->cpu == 0)
forward_interrupts(new_pid);
current->thread.request.op = OP_EXEC;
current->thread.request.u.exec.pid = new_pid;
- unprotect_stack((unsigned long) current->thread_info);
+ unprotect_stack((unsigned long) current_thread);
os_usr1_process(os_getpid());
enable_timer();
free_page(stack);
protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
- task_protections((unsigned long) current->thread_info);
+ task_protections((unsigned long) current_thread);
force_flush_all();
unblock_signals();
}
#include "sysdep/ptrace.h"
+enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
+
extern int tracing_pid;
extern int tracer(int (*init_proc)(void *), void *sp);
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
extern int __do_copy_from_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher);
-
-static inline int copy_from_user_tt(void *to, const void *from, int n)
-{
- return(access_ok_tt(VERIFY_READ, from, n) ?
- __do_copy_from_user(to, from, n,
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher) : n);
-}
-
-static inline int copy_to_user_tt(void *to, const void *from, int n)
-{
- return(access_ok_tt(VERIFY_WRITE, to, n) ?
- __do_copy_to_user(to, from, n,
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher) : n);
-}
-
extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
void **fault_addr, void **fault_catcher);
-
-static inline int strncpy_from_user_tt(char *dst, const char *src, int count)
-{
- int n;
-
- if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT);
- n = __do_strncpy_from_user(dst, src, count,
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher);
- if(n < 0) return(-EFAULT);
- return(n);
-}
-
extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
void **fault_catcher);
-
-static inline int __clear_user_tt(void *mem, int len)
-{
- return(__do_clear_user(mem, len,
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher));
-}
-
-static inline int clear_user_tt(void *mem, int len)
-{
- return(access_ok_tt(VERIFY_WRITE, mem, len) ?
- __do_clear_user(mem, len,
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher) : len);
-}
-
extern int __do_strnlen_user(const char *str, unsigned long n,
void **fault_addr, void **fault_catcher);
-static inline int strnlen_user_tt(const void *str, int len)
-{
- return(__do_strnlen_user(str, len,
- ¤t->thread.fault_addr,
- ¤t->thread.fault_catcher));
-}
+extern int copy_from_user_tt(void *to, const void *from, int n);
+extern int copy_to_user_tt(void *to, const void *from, int n);
+extern int strncpy_from_user_tt(char *dst, const char *src, int count);
+extern int __clear_user_tt(void *mem, int len);
+extern int clear_user_tt(void *mem, int len);
+extern int strnlen_user_tt(const void *str, int len);
#endif
size = (unsigned long) segment_end -
(unsigned long) segment_start;
data = create_mem_file(size);
- if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ,
- MAP_SHARED, data, 0)) == MAP_FAILED){
+ addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0);
+ if(addr == MAP_FAILED){
perror("mapping new data segment");
exit(1);
}
memcpy(addr, segment_start, size);
- if(switcheroo(data, prot, addr, segment_start,
- size) < 0){
+ if(switcheroo(data, prot, addr, segment_start, size) < 0){
printf("switcheroo failed\n");
exit(1);
}
reading = 0;
err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
if(err != sizeof(c))
- panic("write of switch_pipe failed, errno = %d", -err);
+ panic("write of switch_pipe failed, err = %d", -err);
reading = 1;
if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD))
void release_thread_tt(struct task_struct *task)
{
- os_kill_process(task->thread.mode.tt.extern_pid, 0);
+ int pid = task->thread.mode.tt.extern_pid;
+
+ if(os_getpid() != pid)
+ os_kill_process(pid, 0);
}
void exit_thread_tt(void)
{
- close(current->thread.mode.tt.switch_pipe[0]);
- close(current->thread.mode.tt.switch_pipe[1]);
+ os_close_file(current->thread.mode.tt.switch_pipe[0]);
+ os_close_file(current->thread.mode.tt.switch_pipe[1]);
}
void schedule_tail(task_t *prev);
static void new_thread_handler(int sig)
{
+ unsigned long disable;
int (*fn)(void *);
void *arg;
fn = current->thread.request.u.thread.proc;
arg = current->thread.request.u.thread.arg;
+
UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
+ disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) |
+ (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1));
+ SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable;
+
suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
- block_signals();
+ force_flush_all();
+ if(current->thread.prev_sched != NULL)
+ schedule_tail(current->thread.prev_sched);
+ current->thread.prev_sched = NULL;
+
init_new_thread_signals(1);
-#ifdef CONFIG_SMP
- schedule_tail(current->thread.prev_sched);
-#endif
enable_timer();
free_page(current->thread.temp_stack);
set_cmdline("(kernel thread)");
- force_flush_all();
- current->thread.prev_sched = NULL;
change_sig(SIGUSR1, 1);
change_sig(SIGVTALRM, 1);
change_sig(SIGPROF, 1);
- unblock_signals();
+ local_irq_enable();
if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf))
do_exit(0);
}
static int new_thread_proc(void *stack)
{
+ /* local_irq_disable is needed to block out signals until this thread is
+ * properly scheduled. Otherwise, the tracing thread will get mighty
+ * upset about any signals that arrive before that.
+ * This has the complication that it sets the saved signal mask in
+ * the sigcontext to block signals. This gets restored when this
+ * thread (or a descendant, since they get a copy of this sigcontext)
+ * returns to userspace.
+ * So, this is compensated for elsewhere.
+ * XXX There is still a small window until local_irq_disable() actually
+ * finishes where signals are possible - shouldn't be a problem in
+ * practice since SIGIO hasn't been forwarded here yet, and the
+ * local_irq_disable should finish before a SIGVTALRM has time to be
+ * delivered.
+ */
+
+ local_irq_disable();
init_new_thread_stack(stack, new_thread_handler);
os_usr1_process(os_getpid());
return(0);
* itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off,
* so it is blocked before it's called. They are re-enabled on sigreturn
* despite the fact that they were blocked when the SIGUSR1 was issued because
- * copy_thread copies the parent's signcontext, including the signal mask
+ * copy_thread copies the parent's sigcontext, including the signal mask
* onto the signal frame.
*/
UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1);
suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
-#ifdef CONFIG_SMP
- schedule_tail(NULL);
-#endif
+ force_flush_all();
+ if(current->thread.prev_sched != NULL)
+ schedule_tail(current->thread.prev_sched);
+ current->thread.prev_sched = NULL;
+
enable_timer();
change_sig(SIGVTALRM, 1);
local_irq_enable();
- force_flush_all();
if(current->mm != current->parent->mm)
protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
1, 0, 1);
- task_protections((unsigned long) current->thread_info);
-
- current->thread.prev_sched = NULL;
+ task_protections((unsigned long) current_thread);
free_page(current->thread.temp_stack);
+ local_irq_disable();
change_sig(SIGUSR1, 0);
set_user_mode(current);
}
-static int sigusr1 = SIGUSR1;
-
int fork_tramp(void *stack)
{
- int sig = sigusr1;
-
local_irq_disable();
+ arch_init_thread();
init_new_thread_stack(stack, finish_fork_handler);
- kill(os_getpid(), sig);
+ os_usr1_process(os_getpid());
return(0);
}
}
err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
- if(err){
- printk("copy_thread : pipe failed, errno = %d\n", -err);
+ if(err < 0){
+ printk("copy_thread : pipe failed, err = %d\n", -err);
return(err);
}
pages = (1 << CONFIG_KERNEL_STACK_ORDER);
- start = (unsigned long) current->thread_info + PAGE_SIZE;
- end = (unsigned long) current + PAGE_SIZE * pages;
+ start = (unsigned long) current_thread + PAGE_SIZE;
+ end = (unsigned long) current_thread + PAGE_SIZE * pages;
protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
protect_memory(end, high_physmem - end, 1, w, 1, 1);
init_task.thread.mode.tt.extern_pid = pid;
err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
- if(err) panic("Can't create switch pipe for init_task, errno = %d",
- err);
+ if(err)
+ panic("Can't create switch pipe for init_task, errno = %d",
+ -err);
}
int singlestepping_tt(void *t)
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
#include <unistd.h>
#include <signal.h>
#include <string.h>
-#include <fcntl.h>
#include <termios.h>
#include <sys/wait.h>
#include <sys/types.h>
}
char gdb_init_string[] =
-"att 1
-b panic
-b stop
-handle SIGWINCH nostop noprint pass
+"att 1 \n\
+b panic \n\
+b stop \n\
+handle SIGWINCH nostop noprint pass \n\
";
int start_debugger(char *prog, int startup, int stop, int *fd_out)
int slave, child;
slave = open_gdb_chan();
- if((child = fork()) == 0){
+ child = fork();
+ if(child == 0){
char *tempname = NULL;
int fd;
exit(1);
#endif
}
- if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){
- printk("start_debugger : make_tempfile failed, errno = %d\n",
- errno);
+ fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0);
+ if(fd < 0){
+ printk("start_debugger : make_tempfile failed,"
+ "err = %d\n", -fd);
exit(1);
}
- write(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
+ os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1);
if(startup){
if(stop){
- write(fd, "b start_kernel\n",
+ os_write_file(fd, "b start_kernel\n",
strlen("b start_kernel\n"));
}
- write(fd, "c\n", strlen("c\n"));
+ os_write_file(fd, "c\n", strlen("c\n"));
}
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
printk("start_debugger : PTRACE_TRACEME failed, "
#include <string.h>
#include <stdlib.h>
#include <signal.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
int real_wait_return(struct debugger *debugger)
{
unsigned long ip;
- int err, pid;
+ int pid;
pid = debugger->pid;
+
ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
- ip = IP_RESTART_SYSCALL(ip);
- err = ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip);
+ IP_RESTART_SYSCALL(ip);
+
if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0)
tracer_panic("real_wait_return : Failed to restart system "
- "call, errno = %d\n");
+ "call, errno = %d\n", errno);
+
if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) ||
(ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
(ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) ||
debugger_normal_return(debugger, -1))
tracer_panic("real_wait_return : gdb failed to wait, "
- "errno = %d\n");
+ "errno = %d\n", errno);
return(0);
}
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
SC_START_SYSCALL(sc);
index = record_syscall_start(syscall);
- syscall_trace();
+ syscall_trace(regs, 1);
result = execute_syscall(regs);
/* regs->sc may have changed while the system call ran (there may
(result == -ERESTARTNOINTR))
do_signal(result);
- syscall_trace();
+ syscall_trace(regs, 0);
record_syscall_end(index, result);
}
#include "asm/page.h"
#include "asm/pgtable.h"
#include "asm/uaccess.h"
+#include "asm/tlbflush.h"
#include "user_util.h"
#include "mem_user.h"
#include "os.h"
return(0);
register_winch_irq(tracer_winch[0], fd, -1, data);
- return(0);
+ return(1);
}
static void tracer_winch_handler(int sig)
{
+ int n;
char c = 1;
- if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c))
- printk("tracer_winch_handler - write failed, errno = %d\n",
- errno);
+ n = os_write_file(tracer_winch[1], &c, sizeof(c));
+ if(n != sizeof(c))
+ printk("tracer_winch_handler - write failed, err = %d\n", -n);
}
/* Called only by the tracing thread during initialization */
int err;
err = os_pipe(tracer_winch, 1, 1);
- if(err){
- printk("setup_tracer_winch : os_pipe failed, errno = %d\n",
- -err);
+ if(err < 0){
+ printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err);
return;
}
signal(SIGWINCH, tracer_winch_handler);
case SIGTSTP:
if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
tracer_panic("sleeping_process_signal : Failed to "
- "continue pid %d, errno = %d\n", pid,
- sig);
+ "continue pid %d, signal = %d, "
+ "errno = %d\n", pid, sig, errno);
break;
/* This happens when the debugger (e.g. strace) is doing system call
if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
tracer_panic("sleeping_process_signal : Failed to "
"PTRACE_SYSCALL pid %d, errno = %d\n",
- pid, sig);
+ pid, errno);
break;
case SIGSTOP:
break;
err = attach(debugger_parent);
if(err){
printf("Failed to attach debugger parent %d, "
- "errno = %d\n", debugger_parent, err);
+ "errno = %d\n", debugger_parent, -err);
debugger_parent = -1;
}
else {
}
set_cmdline("(tracing thread)");
while(1){
- if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){
+ pid = waitpid(-1, &status, WUNTRACED);
+ if(pid <= 0){
if(errno != ECHILD){
printf("wait failed - errno = %d\n", errno);
}
if(!strcmp(line, "go")) debug_stop = 0;
else if(!strcmp(line, "parent")) debug_parent = 1;
- else printk("Unknown debug option : '%s'\n", line);
+ else printf("Unknown debug option : '%s'\n", line);
line = next;
}
#include <string.h>
#include "user_util.h"
#include "uml_uaccess.h"
+#include "task.h"
+#include "kern_util.h"
int __do_copy_from_user(void *to, const void *from, int n,
void **fault_addr, void **fault_catcher)
{
+ struct tt_regs save = TASK_REGS(get_current())->tt;
unsigned long fault;
int faulted;
fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
__do_copy, &faulted);
+ TASK_REGS(get_current())->tt = save;
+
if(!faulted) return(0);
else return(n - (fault - (unsigned long) from));
}
int __do_strncpy_from_user(char *dst, const char *src, unsigned long count,
void **fault_addr, void **fault_catcher)
{
+ struct tt_regs save = TASK_REGS(get_current())->tt;
unsigned long fault;
int faulted;
fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher,
__do_strncpy, &faulted);
+ TASK_REGS(get_current())->tt = save;
+
if(!faulted) return(strlen(dst));
else return(-1);
}
int __do_clear_user(void *mem, unsigned long len,
void **fault_addr, void **fault_catcher)
{
+ struct tt_regs save = TASK_REGS(get_current())->tt;
unsigned long fault;
int faulted;
fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher,
__do_clear, &faulted);
+ TASK_REGS(get_current())->tt = save;
+
if(!faulted) return(0);
else return(len - (fault - (unsigned long) mem));
}
int __do_strnlen_user(const char *str, unsigned long n,
void **fault_addr, void **fault_catcher)
{
+ struct tt_regs save = TASK_REGS(get_current())->tt;
int ret;
unsigned long *faddrp = (unsigned long *)fault_addr;
jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(setjmp(jbuf) == 0){
+ if(sigsetjmp(jbuf, 1) == 0)
ret = strlen(str) + 1;
- }
- else {
- ret = *faddrp - (unsigned long) str;
- }
+ else ret = *faddrp - (unsigned long) str;
+
*fault_addr = NULL;
*fault_catcher = NULL;
+
+ TASK_REGS(get_current())->tt = save;
return ret;
}
* Licensed under the GPL
*/
-#include <stdio.h>
-#include <errno.h>
#include <sys/mman.h>
-#include "user.h"
int switcheroo(int fd, int prot, void *from, void *to, int size)
{
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
#include <sys/time.h>
#include "init.h"
#include "user.h"
+#include "kern_util.h"
#include "os.h"
#define TTY_LOG_DIR "./"
#define TTY_LOG_OPEN 1
#define TTY_LOG_CLOSE 2
#define TTY_LOG_WRITE 3
+#define TTY_LOG_EXEC 4
+
+#define TTY_READ 1
+#define TTY_WRITE 2
struct tty_log_buf {
int what;
unsigned long tty;
int len;
+ int direction;
+ unsigned long sec;
+ unsigned long usec;
};
-int open_tty_log(void *tty)
+int open_tty_log(void *tty, void *current_tty)
{
struct timeval tv;
struct tty_log_buf data;
char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
int fd;
+ gettimeofday(&tv, NULL);
if(tty_log_fd != -1){
- data = ((struct tty_log_buf) { what : TTY_LOG_OPEN,
- tty : (unsigned long) tty,
- len : 0 });
- write(tty_log_fd, &data, sizeof(data));
+ data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN,
+ .tty = (unsigned long) tty,
+ .len = sizeof(current_tty),
+ .direction = 0,
+ .sec = tv.tv_sec,
+ .usec = tv.tv_usec } );
+ os_write_file(tty_log_fd, &data, sizeof(data));
+ os_write_file(tty_log_fd, ¤t_tty, data.len);
return(tty_log_fd);
}
- gettimeofday(&tv, NULL);
sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
(unsigned int) tv.tv_usec);
void close_tty_log(int fd, void *tty)
{
struct tty_log_buf data;
+ struct timeval tv;
if(tty_log_fd != -1){
- data = ((struct tty_log_buf) { what : TTY_LOG_CLOSE,
- tty : (unsigned long) tty,
- len : 0 });
- write(tty_log_fd, &data, sizeof(data));
+ gettimeofday(&tv, NULL);
+ data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE,
+ .tty = (unsigned long) tty,
+ .len = 0,
+ .direction = 0,
+ .sec = tv.tv_sec,
+ .usec = tv.tv_usec } );
+ os_write_file(tty_log_fd, &data, sizeof(data));
return;
}
- close(fd);
+ os_close_file(fd);
+}
+
+static int log_chunk(int fd, const char *buf, int len)
+{
+ int total = 0, try, missed, n;
+ char chunk[64];
+
+ while(len > 0){
+ try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
+ missed = copy_from_user_proc(chunk, (char *) buf, try);
+ try -= missed;
+ n = os_write_file(fd, chunk, try);
+ if(n != try) {
+ if(n < 0)
+ return(n);
+ return(-EIO);
+ }
+ if(missed != 0)
+ return(-EFAULT);
+
+ len -= try;
+ total += try;
+ buf += try;
+ }
+
+ return(total);
}
-int write_tty_log(int fd, char *buf, int len, void *tty)
+int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
{
+ struct timeval tv;
struct tty_log_buf data;
+ int direction;
if(fd == tty_log_fd){
- data = ((struct tty_log_buf) { what : TTY_LOG_WRITE,
- tty : (unsigned long) tty,
- len : len });
- write(tty_log_fd, &data, sizeof(data));
+ gettimeofday(&tv, NULL);
+ direction = is_read ? TTY_READ : TTY_WRITE;
+ data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE,
+ .tty = (unsigned long) tty,
+ .len = len,
+ .direction = direction,
+ .sec = tv.tv_sec,
+ .usec = tv.tv_usec } );
+ os_write_file(tty_log_fd, &data, sizeof(data));
+ }
+
+ return(log_chunk(fd, buf, len));
+}
+
+void log_exec(char **argv, void *tty)
+{
+ struct timeval tv;
+ struct tty_log_buf data;
+ char **ptr,*arg;
+ int len;
+
+ if(tty_log_fd == -1) return;
+
+ gettimeofday(&tv, NULL);
+
+ len = 0;
+ for(ptr = argv; ; ptr++){
+ if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+ return;
+ if(arg == NULL) break;
+ len += strlen_user_proc(arg);
+ }
+
+ data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC,
+ .tty = (unsigned long) tty,
+ .len = len,
+ .direction = 0,
+ .sec = tv.tv_sec,
+ .usec = tv.tv_usec } );
+ os_write_file(tty_log_fd, &data, sizeof(data));
+
+ for(ptr = argv; ; ptr++){
+ if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
+ return;
+ if(arg == NULL) break;
+ log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
}
- return(write(fd, buf, len));
}
+extern void register_tty_logger(int (*opener)(void *, void *),
+ int (*writer)(int, const char *, int,
+ void *, int),
+ void (*closer)(int, void *));
+
+static int register_logger(void)
+{
+ register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
+ return(0);
+}
+
+__uml_initcall(register_logger);
+
static int __init set_tty_log_dir(char *name, int *add)
{
tty_log_dir = name;
tty_log_fd = strtoul(name, &end, 0);
if((*end != '\0') || (end == name)){
- printk("set_tty_log_fd - strtoul failed on '%s'\n", name);
+ printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
tty_log_fd = -1;
}
return 0;
jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(setjmp(jbuf) == 0){
+ if(sigsetjmp(jbuf, 1) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
#include "mode_kern.h"
#include "mode.h"
-#define DEFAULT_COMMAND_LINE "root=6200"
+#define DEFAULT_COMMAND_LINE "root=98:0"
struct cpuinfo_um boot_cpu_data = {
.loops_per_jiffy = 0,
.ipi_pipe = { -1, -1 }
};
+/* Placeholder to make UML link until the vsyscall stuff is actually
+ * implemented
+ */
+void *__kernel_vsyscall;
+
unsigned long thread_saved_pc(struct task_struct *task)
{
return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
static int show_cpuinfo(struct seq_file *m, void *v)
{
- int index;
+ int index = 0;
- index = (struct cpuinfo_um *)v - cpu_data;
#ifdef CONFIG_SMP
+ index = (struct cpuinfo_um *) v - cpu_data;
if (!cpu_online(index))
return 0;
#endif
- seq_printf(m, "bogomips\t: %lu.%02lu\n",
+ seq_printf(m, "processor\t: %d\n", index);
+ seq_printf(m, "vendor_id\t: User Mode Linux\n");
+ seq_printf(m, "model name\t: UML\n");
+ seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas"));
+ seq_printf(m, "host\t\t: %s\n", host_info);
+ seq_printf(m, "bogomips\t: %lu.%02lu\n\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100);
- seq_printf(m, "host\t\t: %s\n", host_info);
return(0);
}
if(umid != NULL){
snprintf(argv1_begin,
(argv1_end - argv1_begin) * sizeof(*ptr),
- "(%s)", umid);
+ "(%s) ", umid);
ptr = &argv1_begin[strlen(argv1_begin)];
}
else ptr = argv1_begin;
- snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd);
+ snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd);
memset(argv1_begin + strlen(argv1_begin), '\0',
argv1_end - argv1_begin - strlen(argv1_begin));
#endif
static int __init uml_ncpus_setup(char *line, int *add)
{
if (!sscanf(line, "%d", &ncpus)) {
- printk("Couldn't parse [%s]\n", line);
+ printf("Couldn't parse [%s]\n", line);
return -1;
}
static int __init mode_tt_setup(char *line, int *add)
{
- printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
+ printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n");
return(0);
}
static int __init mode_tt_setup(char *line, int *add)
{
- printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
+ printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n");
return(0);
}
/* Set during early boot */
unsigned long brk_start;
-static struct vm_reserved kernel_vm_reserved;
+unsigned long end_iomem;
#define MIN_VMALLOC (32 * 1024 * 1024)
{
unsigned long avail;
unsigned long virtmem_size, max_physmem;
- unsigned int i, add, err;
+ unsigned int i, add;
for (i = 1; i < argc; i++){
if((i == 1) && (argv[i][0] == ' ')) continue;
argv1_end = &argv[1][strlen(argv[1])];
#endif
- set_usable_vm(uml_physmem, get_kmem_end());
-
highmem = 0;
- max_physmem = get_kmem_end() - uml_physmem - MIN_VMALLOC;
- if(physmem_size > max_physmem){
- highmem = physmem_size - max_physmem;
+ iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
+ max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
+
+ /* Zones have to begin on a 1 << MAX_ORDER page boundary,
+ * so this makes sure that's true for highmem
+ */
+ max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1);
+ if(physmem_size + iomem_size > max_physmem){
+ highmem = physmem_size + iomem_size - max_physmem;
physmem_size -= highmem;
#ifndef CONFIG_HIGHMEM
highmem = 0;
}
high_physmem = uml_physmem + physmem_size;
- high_memory = (void *) high_physmem;
+ end_iomem = high_physmem + iomem_size;
+ high_memory = (void *) end_iomem;
start_vm = VMALLOC_START;
- setup_physmem(uml_physmem, uml_reserved, physmem_size);
+ setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
+ if(init_maps(physmem_size, iomem_size, highmem)){
+ printf("Failed to allocate mem_map for %ld bytes of physical "
+ "memory and %ld bytes of highmem\n", physmem_size,
+ highmem);
+ exit(1);
+ }
+
virtmem_size = physmem_size;
avail = get_kmem_end() - start_vm;
if(physmem_size > avail) virtmem_size = avail;
printf("Kernel virtual memory size shrunk to %ld bytes\n",
virtmem_size);
- err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved);
- if(err){
- printf("Failed to reserve VM area for kernel VM\n");
- exit(1);
- }
-
uml_postsetup();
init_task.thread.kernel_stack = (unsigned long) &init_thread_info +
2 * PAGE_SIZE;
task_protections((unsigned long) &init_thread_info);
+ os_flush_stdout();
return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
}
+extern int uml_exitcode;
+
static int panic_exit(struct notifier_block *self, unsigned long unused1,
void *unused2)
{
#ifdef CONFIG_MAGIC_SYSRQ
- handle_sysrq('p', ¤t->thread.regs, NULL, NULL);
+ handle_sysrq('p', ¤t->thread.regs, NULL);
#endif
+ uml_exitcode = 1;
machine_halt();
return(0);
}
arch_check_bugs();
check_ptrace();
check_sigio();
+ check_devanon();
+}
+
+void apply_alternatives(void *start, void *end)
+{
}
/*
#include <stdio.h>
#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
static int umid_is_random = 1;
static int umid_inited = 0;
-static int make_umid(void);
+static int make_umid(int (*printer)(const char *fmt, ...));
-static int __init set_umid(char *name, int is_random)
+static int __init set_umid(char *name, int is_random,
+ int (*printer)(const char *fmt, ...))
{
if(umid_inited){
- printk("Unique machine name can't be set twice\n");
+ (*printer)("Unique machine name can't be set twice\n");
return(-1);
}
if(strlen(name) > UMID_LEN - 1)
- printk("Unique machine name is being truncated to %s "
- "characters\n", UMID_LEN);
+ (*printer)("Unique machine name is being truncated to %s "
+ "characters\n", UMID_LEN);
strlcpy(umid, name, sizeof(umid));
umid_is_random = is_random;
static int __init set_umid_arg(char *name, int *add)
{
- return(set_umid(name, 0));
+ return(set_umid(name, 0, printf));
}
__uml_setup("umid=", set_umid_arg,
{
int n;
- if(!umid_inited && make_umid()) return(-1);
+ if(!umid_inited && make_umid(printk)) return(-1);
n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1;
if(n > len){
{
char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
char pid[sizeof("nnnnn\0")];
- int fd;
+ int fd, n;
if(umid_file_name("pid", file, sizeof(file))) return 0;
fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))),
0644);
if(fd < 0){
- printk("Open of machine pid file \"%s\" failed - "
- "errno = %d\n", file, -fd);
+ printf("Open of machine pid file \"%s\" failed - "
+ "err = %d\n", file, -fd);
return 0;
}
sprintf(pid, "%d\n", os_getpid());
- if(write(fd, pid, strlen(pid)) != strlen(pid))
- printk("Write of pid file failed - errno = %d\n", errno);
- close(fd);
+ n = os_write_file(fd, pid, strlen(pid));
+ if(n != strlen(pid))
+ printf("Write of pid file failed - err = %d\n", -n);
+ os_close_file(fd);
return 0;
}
int len;
char file[256];
- if((directory = opendir(dir)) == NULL){
+ directory = opendir(dir);
+ if(directory == NULL){
printk("actually_do_remove : couldn't open directory '%s', "
"errno = %d\n", dir, errno);
return(1);
{
char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
char pid[sizeof("nnnnn\0")], *end;
- int dead, fd, p;
+ int dead, fd, p, n;
sprintf(file, "%s/pid", dir);
dead = 0;
- if((fd = os_open_file(file, of_read(OPENFLAGS()), 0)) < 0){
+ fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+ if(fd < 0){
if(fd != -ENOENT){
printk("not_dead_yet : couldn't open pid file '%s', "
- "errno = %d\n", file, -fd);
+ "err = %d\n", file, -fd);
return(1);
}
dead = 1;
}
if(fd > 0){
- if(read(fd, pid, sizeof(pid)) < 0){
+ n = os_read_file(fd, pid, sizeof(pid));
+ if(n < 0){
printk("not_dead_yet : couldn't read pid file '%s', "
- "errno = %d\n", file, errno);
+ "err = %d\n", file, -n);
return(1);
}
p = strtoul(pid, &end, 0);
if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){
uml_dir = malloc(strlen(name) + 1);
if(uml_dir == NULL){
- printk("Failed to malloc uml_dir - error = %d\n",
+ printf("Failed to malloc uml_dir - error = %d\n",
errno);
uml_dir = name;
return(0);
char *home = getenv("HOME");
if(home == NULL){
- printk("make_uml_dir : no value in environment for "
+ printf("make_uml_dir : no value in environment for "
"$HOME\n");
exit(1);
}
dir[len + 1] = '\0';
}
- if((uml_dir = malloc(strlen(dir) + 1)) == NULL){
+ uml_dir = malloc(strlen(dir) + 1);
+ if(uml_dir == NULL){
printf("make_uml_dir : malloc failed, errno = %d\n", errno);
exit(1);
}
strcpy(uml_dir, dir);
if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){
- printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
+ printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno);
return(-1);
}
return 0;
}
-static int __init make_umid(void)
+static int __init make_umid(int (*printer)(const char *fmt, ...))
{
int fd, err;
char tmp[strlen(uml_dir) + UMID_LEN + 1];
strlcpy(tmp, uml_dir, sizeof(tmp));
- if(*umid == 0){
+ if(!umid_inited){
strcat(tmp, "XXXXXX");
fd = mkstemp(tmp);
if(fd < 0){
- printk("make_umid - mkstemp failed, errno = %d\n",
- errno);
+ (*printer)("make_umid - mkstemp failed, errno = %d\n",
+ errno);
return(1);
}
- close(fd);
+ os_close_file(fd);
/* There's a nice tiny little race between this unlink and
* the mkdir below. It'd be nice if there were a mkstemp
* for directories.
*/
unlink(tmp);
- set_umid(&tmp[strlen(uml_dir)], 1);
+ set_umid(&tmp[strlen(uml_dir)], 1, printer);
}
sprintf(tmp, "%s%s", uml_dir, umid);
- if((err = mkdir(tmp, 0777)) < 0){
+ err = mkdir(tmp, 0777);
+ if(err < 0){
if(errno == EEXIST){
if(not_dead_yet(tmp)){
- printk("umid '%s' is in use\n", umid);
+ (*printer)("umid '%s' is in use\n", umid);
return(-1);
}
err = mkdir(tmp, 0777);
}
}
if(err < 0){
- printk("Failed to create %s - errno = %d\n", umid, errno);
+ (*printer)("Failed to create %s - errno = %d\n", umid, errno);
return(-1);
}
);
__uml_postsetup(make_uml_dir);
-__uml_postsetup(make_umid);
+
+static int __init make_umid_setup(void)
+{
+ return(make_umid(printf));
+}
+
+__uml_postsetup(make_umid_setup);
__uml_postsetup(create_pid_file);
/*
#include <stdio.h>
#include <stdlib.h>
-#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <sys/mman.h>
int status, ret;
while(1){
- if(((ret = waitpid(pid, &status, WUNTRACED)) < 0) ||
+ ret = waitpid(pid, &status, WUNTRACED);
+ if((ret < 0) ||
!WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){
if(ret < 0){
if(errno == EINTR) continue;
}
}
-int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags)
-{
- int pid;
-
- pid = clone(fn, sp, flags, arg);
- if(pid < 0) return(-1);
- wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
- ptrace(PTRACE_CONT, pid, 0, 0);
- return(pid);
-}
-
int raw(int fd, int complain)
{
struct termios tt;
#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include <errno.h>
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/user.h>
set_stklim();
- if((new_argv = malloc((argc + 1) * sizeof(char *))) == NULL){
+ new_argv = malloc((argc + 1) * sizeof(char *));
+ if(new_argv == NULL){
perror("Mallocing argv");
exit(1);
}
for(i=0;i<argc;i++){
- if((new_argv[i] = strdup(argv[i])) == NULL){
+ new_argv[i] = strdup(argv[i]);
+ if(new_argv[i] == NULL){
perror("Mallocing an arg");
exit(1);
}
# Licensed under the GPL
#
-obj-y = file.o process.o tty.o drivers/
+obj-y = file.o process.o tty.o user_syms.o drivers/
USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file))
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-
-clean :
-
-archmrproper:
#include "linux/init.h"
#include "linux/netdevice.h"
#include "linux/etherdevice.h"
-#include "linux/init.h"
#include "net_kern.h"
#include "net_user.h"
#include "etap.h"
#include <stdio.h>
#include <unistd.h>
#include <stddef.h>
-#include <fcntl.h>
#include <stdlib.h>
#include <sys/errno.h>
#include <sys/socket.h>
{
struct addr_change change;
void *output;
+ int n;
change.what = op;
memcpy(change.addr, addr, sizeof(change.addr));
memcpy(change.netmask, netmask, sizeof(change.netmask));
- if(write(fd, &change, sizeof(change)) != sizeof(change))
- printk("etap_change - request failed, errno = %d\n",
- errno);
+ n = os_write_file(fd, &change, sizeof(change));
+ if(n != sizeof(change))
+ printk("etap_change - request failed, err = %d\n", -n);
output = um_kmalloc(page_size());
if(output == NULL)
printk("etap_change : Failed to allocate output buffer\n");
struct etap_pre_exec_data *data = arg;
dup2(data->control_remote, 1);
- close(data->data_me);
- close(data->control_me);
+ os_close_file(data->data_me);
+ os_close_file(data->control_me);
}
static int etap_tramp(char *dev, char *gate, int control_me,
int control_remote, int data_me, int data_remote)
{
struct etap_pre_exec_data pe_data;
- int pid, status, err;
+ int pid, status, err, n;
char version_buf[sizeof("nnnnn\0")];
char data_fd_buf[sizeof("nnnnnn\0")];
char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
pe_data.data_me = data_me;
pid = run_helper(etap_pre_exec, &pe_data, args, NULL);
- if(pid < 0) err = errno;
- close(data_remote);
- close(control_remote);
- if(read(control_me, &c, sizeof(c)) != sizeof(c)){
- printk("etap_tramp : read of status failed, errno = %d\n",
- errno);
- return(EINVAL);
+ if(pid < 0) err = pid;
+ os_close_file(data_remote);
+ os_close_file(control_remote);
+ n = os_read_file(control_me, &c, sizeof(c));
+ if(n != sizeof(c)){
+ printk("etap_tramp : read of status failed, err = %d\n", -n);
+ return(-EINVAL);
}
if(c != 1){
printk("etap_tramp : uml_net failed\n");
- err = EINVAL;
- if(waitpid(pid, &status, 0) < 0) err = errno;
- else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)){
+ err = -EINVAL;
+ if(waitpid(pid, &status, 0) < 0)
+ err = -errno;
+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1))
printk("uml_net didn't exit with status 1\n");
- }
}
return(err);
}
if(err) return(err);
err = os_pipe(data_fds, 0, 0);
- if(err){
- printk("data os_pipe failed - errno = %d\n", -err);
+ if(err < 0){
+ printk("data os_pipe failed - err = %d\n", -err);
return(err);
}
err = os_pipe(control_fds, 1, 0);
- if(err){
- printk("control os_pipe failed - errno = %d\n", -err);
+ if(err < 0){
+ printk("control os_pipe failed - err = %d\n", -err);
return(err);
}
kfree(output);
}
- if(err != 0){
- printk("etap_tramp failed - errno = %d\n", err);
- return(-err);
+ if(err < 0){
+ printk("etap_tramp failed - err = %d\n", -err);
+ return(err);
}
pri->data_fd = data_fds[0];
struct ethertap_data *pri = data;
iter_addresses(pri->dev, etap_close_addr, &pri->control_fd);
- close(fd);
+ os_close_file(fd);
os_shutdown_socket(pri->data_fd, 1, 1);
- close(pri->data_fd);
+ os_close_file(pri->data_fd);
pri->data_fd = -1;
- close(pri->control_fd);
+ os_close_file(pri->control_fd);
pri->control_fd = -1;
}
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
-#include <fcntl.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
struct tuntap_pre_exec_data *data = arg;
dup2(data->stdout, 1);
- close(data->close_me);
+ os_close_file(data->close_me);
}
static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
if(pid < 0) return(-pid);
- close(remote);
+ os_close_file(remote);
msg.msg_name = NULL;
msg.msg_namelen = 0;
if(n < 0){
printk("tuntap_open_tramp : recvmsg failed - errno = %d\n",
errno);
- return(errno);
+ return(-errno);
}
waitpid(pid, NULL, 0);
cmsg = CMSG_FIRSTHDR(&msg);
if(cmsg == NULL){
printk("tuntap_open_tramp : didn't receive a message\n");
- return(EINVAL);
+ return(-EINVAL);
}
if((cmsg->cmsg_level != SOL_SOCKET) ||
(cmsg->cmsg_type != SCM_RIGHTS)){
printk("tuntap_open_tramp : didn't receive a descriptor\n");
- return(EINVAL);
+ return(-EINVAL);
}
*fd_out = ((int *) CMSG_DATA(cmsg))[0];
return(0);
int err, fds[2], len, used;
err = tap_open_common(pri->dev, pri->gate_addr);
- if(err) return(err);
+ if(err < 0)
+ return(err);
if(pri->fixed_config){
- if((pri->fd = open("/dev/net/tun", O_RDWR)) < 0){
- printk("Failed to open /dev/net/tun, errno = %d\n",
- errno);
- return(-errno);
+ pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0);
+ if(pri->fd < 0){
+ printk("Failed to open /dev/net/tun, err = %d\n",
+ -pri->fd);
+ return(pri->fd);
}
memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_flags = IFF_TAP;
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){
- printk("TUNSETIFF failed, errno = %d", errno);
- close(pri->fd);
+ printk("TUNSETIFF failed, errno = %d\n", errno);
+ os_close_file(pri->fd);
return(-errno);
}
}
else {
err = os_pipe(fds, 0, 0);
- if(err){
- printk("tuntap_open : os_pipe failed - errno = %d\n",
+ if(err < 0){
+ printk("tuntap_open : os_pipe failed - err = %d\n",
-err);
return(err);
}
fds[1], buffer, len, &used);
output = buffer;
- if(err == 0){
- pri->dev_name = uml_strdup(buffer);
- output += IFNAMSIZ;
- printk(output);
- free_output_buffer(buffer);
- }
- else {
- printk(output);
+ if(err < 0) {
+ printk("%s", output);
free_output_buffer(buffer);
- printk("tuntap_open_tramp failed - errno = %d\n", err);
- return(-err);
+ printk("tuntap_open_tramp failed - err = %d\n", -err);
+ return(err);
}
- close(fds[0]);
+
+ pri->dev_name = uml_strdup(buffer);
+ output += IFNAMSIZ;
+ printk("%s", output);
+ free_output_buffer(buffer);
+
+ os_close_file(fds[0]);
iter_addresses(pri->dev, open_addr, pri->dev_name);
}
if(!pri->fixed_config)
iter_addresses(pri->dev, close_addr, pri->dev_name);
- close(fd);
+ os_close_file(fd);
pri->fd = -1;
}
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include "user.h"
#include "kern_util.h"
-int os_file_type(char *file)
+static void copy_stat(struct uml_stat *dst, struct stat64 *src)
+{
+ *dst = ((struct uml_stat) {
+ .ust_dev = src->st_dev, /* device */
+ .ust_ino = src->st_ino, /* inode */
+ .ust_mode = src->st_mode, /* protection */
+ .ust_nlink = src->st_nlink, /* number of hard links */
+ .ust_uid = src->st_uid, /* user ID of owner */
+ .ust_gid = src->st_gid, /* group ID of owner */
+ .ust_size = src->st_size, /* total size, in bytes */
+ .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */
+ .ust_blocks = src->st_blocks, /* number of blocks allocated */
+ .ust_atime = src->st_atime, /* time of last access */
+ .ust_mtime = src->st_mtime, /* time of last modification */
+ .ust_ctime = src->st_ctime, /* time of last change */
+ });
+}
+
+int os_stat_fd(const int fd, struct uml_stat *ubuf)
+{
+ struct stat64 sbuf;
+ int err;
+
+ do {
+ err = fstat64(fd, &sbuf);
+ } while((err < 0) && (errno == EINTR)) ;
+
+ if(err < 0)
+ return(-errno);
+
+ if(ubuf != NULL)
+ copy_stat(ubuf, &sbuf);
+ return(err);
+}
+
+int os_stat_file(const char *file_name, struct uml_stat *ubuf)
+{
+ struct stat64 sbuf;
+ int err;
+
+ do {
+ err = stat64(file_name, &sbuf);
+ } while((err < 0) && (errno == EINTR)) ;
+
+ if(err < 0)
+ return(-errno);
+
+ if(ubuf != NULL)
+ copy_stat(ubuf, &sbuf);
+ return(err);
+}
+
+int os_access(const char* file, int mode)
+{
+ int amode, err;
+
+ amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
+ (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
+
+ err = access(file, amode);
+ if(err < 0)
+ return(-errno);
+
+ return(0);
+}
+
+void os_print_error(int error, const char* str)
+{
+ errno = error < 0 ? -error : error;
+
+ perror(str);
+}
+
+/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */
+int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
+{
+ int err;
+
+ err = ioctl(fd, cmd, arg);
+ if(err < 0)
+ return(-errno);
+
+ return(err);
+}
+
+int os_window_size(int fd, int *rows, int *cols)
+{
+ struct winsize size;
+
+ if(ioctl(fd, TIOCGWINSZ, &size) < 0)
+ return(-errno);
+
+ *rows = size.ws_row;
+ *cols = size.ws_col;
+
+ return(0);
+}
+
+int os_new_tty_pgrp(int fd, int pid)
+{
+ if(ioctl(fd, TIOCSCTTY, 0) < 0){
+ printk("TIOCSCTTY failed, errno = %d\n", errno);
+ return(-errno);
+ }
+
+ if(tcsetpgrp(fd, pid) < 0){
+ printk("tcsetpgrp failed, errno = %d\n", errno);
+ return(-errno);
+ }
+
+ return(0);
+}
+
+/* FIXME: ensure namebuf in os_get_if_name is big enough */
+int os_get_ifname(int fd, char* namebuf)
+{
+ if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+ return(-errno);
+
+ return(0);
+}
+
+int os_set_slip(int fd)
+{
+ int disc, sencap;
+
+ disc = N_SLIP;
+ if(ioctl(fd, TIOCSETD, &disc) < 0){
+ printk("Failed to set slip line discipline - "
+ "errno = %d\n", errno);
+ return(-errno);
+ }
+
+ sencap = 0;
+ if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){
+ printk("Failed to set slip encapsulation - "
+ "errno = %d\n", errno);
+ return(-errno);
+ }
+
+ return(0);
+}
+
+int os_set_owner(int fd, int pid)
+{
+ if(fcntl(fd, F_SETOWN, pid) < 0){
+ int save_errno = errno;
+
+ if(fcntl(fd, F_GETOWN, 0) != pid)
+ return(-save_errno);
+ }
+
+ return(0);
+}
+
+/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
+int os_sigio_async(int master, int slave)
+{
+ int flags;
+
+ flags = fcntl(master, F_GETFL);
+ if(flags < 0) {
+ printk("fcntl F_GETFL failed, errno = %d\n", errno);
+ return(-errno);
+ }
+
+ if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+ (fcntl(master, F_SETOWN, os_getpid()) < 0)){
+ printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", errno);
+ return(-errno);
+ }
+
+ if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){
+ printk("fcntl F_SETFL failed, errno = %d\n", errno);
+ return(-errno);
+ }
+
+ return(0);
+}
+
+int os_mode_fd(int fd, int mode)
{
- struct stat64 buf;
+ int err;
+
+ do {
+ err = fchmod(fd, mode);
+ } while((err < 0) && (errno==EINTR)) ;
- if(stat64(file, &buf) == -1)
+ if(err < 0)
return(-errno);
- if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR);
- else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK);
- else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV);
- else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV);
- else if(S_ISFIFO(buf.st_mode)) return(OS_TYPE_FIFO);
- else if(S_ISSOCK(buf.st_mode)) return(OS_TYPE_SOCK);
+ return(0);
+}
+
+int os_file_type(char *file)
+{
+ struct uml_stat buf;
+ int err;
+
+ err = os_stat_file(file, &buf);
+ if(err < 0)
+ return(err);
+
+ if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
+ else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
+ else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
+ else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
+ else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
+ else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
else return(OS_TYPE_FILE);
}
int os_file_mode(char *file, struct openflags *mode_out)
{
+ int err;
+
*mode_out = OPENFLAGS();
- if(!access(file, W_OK)) *mode_out = of_write(*mode_out);
- else if(errno != EACCES)
- return(-errno);
+ err = os_access(file, OS_ACC_W_OK);
+ if((err < 0) && (err != -EACCES))
+ return(err);
- if(!access(file, R_OK)) *mode_out = of_read(*mode_out);
- else if(errno != EACCES)
- return(-errno);
+ *mode_out = of_write(*mode_out);
+
+ err = os_access(file, OS_ACC_R_OK);
+ if((err < 0) && (err != -EACCES))
+ return(err);
+
+ *mode_out = of_read(*mode_out);
return(0);
}
if(flags.e) f |= O_EXCL;
fd = open64(file, f, mode);
- if(fd < 0) return(-errno);
-
- if(flags.cl){
- if(fcntl(fd, F_SETFD, 1)){
- close(fd);
- return(-errno);
- }
+ if(fd < 0)
+ return(-errno);
+
+ if(flags.cl && fcntl(fd, F_SETFD, 1)){
+ os_close_file(fd);
+ return(-errno);
}
- return(fd);
return(fd);
}
err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
if(err)
- return(err);
+ return(-errno);
return(fd);
}
return(0);
}
-int os_read_file(int fd, void *buf, int len)
+static int fault_buffer(void *start, int len,
+ int (*copy_proc)(void *addr, void *buf, int len))
{
- int n;
+ int page = getpagesize(), i;
+ char c;
- /* Force buf into memory if it's not already. */
+ for(i = 0; i < len; i += page){
+ if((*copy_proc)(start + i, &c, sizeof(c)))
+ return(-EFAULT);
+ }
+ if((len % page) != 0){
+ if((*copy_proc)(start + len - 1, &c, sizeof(c)))
+ return(-EFAULT);
+ }
+ return(0);
+}
- /* XXX This fails if buf is kernel memory */
-#ifdef notdef
- if(copy_to_user_proc(buf, &c, sizeof(c)))
- return(-EFAULT);
-#endif
+static int file_io(int fd, void *buf, int len,
+ int (*io_proc)(int fd, void *buf, int len),
+ int (*copy_user_proc)(void *addr, void *buf, int len))
+{
+ int n, err;
+
+ do {
+ n = (*io_proc)(fd, buf, len);
+ if((n < 0) && (errno == EFAULT)){
+ err = fault_buffer(buf, len, copy_user_proc);
+ if(err)
+ return(err);
+ n = (*io_proc)(fd, buf, len);
+ }
+ } while((n < 0) && (errno == EINTR));
- n = read(fd, buf, len);
if(n < 0)
return(-errno);
return(n);
}
-int os_write_file(int fd, void *buf, int count)
+int os_read_file(int fd, void *buf, int len)
{
- int n;
-
- /* Force buf into memory if it's not already. */
-
- /* XXX This fails if buf is kernel memory */
-#ifdef notdef
- if(copy_to_user_proc(buf, buf, buf[0]))
- return(-EFAULT);
-#endif
+ return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
+ copy_from_user_proc));
+}
- n = write(fd, buf, count);
- if(n < 0)
- return(-errno);
- return(n);
+int os_write_file(int fd, const void *buf, int len)
+{
+ return(file_io(fd, (void *) buf, len,
+ (int (*)(int, void *, int)) write, copy_to_user_proc));
}
int os_file_size(char *file, long long *size_out)
{
- struct stat64 buf;
+ struct uml_stat buf;
+ int err;
- if(stat64(file, &buf) == -1){
- printk("Couldn't stat \"%s\" : errno = %d\n", file, errno);
- return(-errno);
+ err = os_stat_file(file, &buf);
+ if(err < 0){
+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ return(err);
}
- if(S_ISBLK(buf.st_mode)){
+
+ if(S_ISBLK(buf.ust_mode)){
int fd, blocks;
- if((fd = open64(file, O_RDONLY)) < 0){
- printk("Couldn't open \"%s\", errno = %d\n", file,
- errno);
- return(-errno);
+ fd = os_open_file(file, of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Couldn't open \"%s\", errno = %d\n", file, -fd);
+ return(fd);
}
if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
printk("Couldn't get the block size of \"%s\", "
"errno = %d\n", file, errno);
- close(fd);
- return(-errno);
+ err = -errno;
+ os_close_file(fd);
+ return(err);
}
*size_out = ((long long) blocks) * 512;
- close(fd);
+ os_close_file(fd);
return(0);
}
- *size_out = buf.st_size;
+ *size_out = buf.ust_size;
+ return(0);
+}
+
+int os_file_modtime(char *file, unsigned long *modtime)
+{
+ struct uml_stat buf;
+ int err;
+
+ err = os_stat_file(file, &buf);
+ if(err < 0){
+ printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
+ return(err);
+ }
+
+ *modtime = buf.ust_mtime;
return(0);
}
+int os_get_exec_close(int fd, int* close_on_exec)
+{
+ int ret;
+
+ do {
+ ret = fcntl(fd, F_GETFD);
+ } while((ret < 0) && (errno == EINTR)) ;
+
+ if(ret < 0)
+ return(-errno);
+
+ *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0;
+ return(ret);
+}
+
+int os_set_exec_close(int fd, int close_on_exec)
+{
+ int flag, err;
+
+ if(close_on_exec) flag = FD_CLOEXEC;
+ else flag = 0;
+
+ do {
+ err = fcntl(fd, F_SETFD, flag);
+ } while((err < 0) && (errno == EINTR)) ;
+
+ if(err < 0)
+ return(-errno);
+ return(err);
+}
+
int os_pipe(int *fds, int stream, int close_on_exec)
{
int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
err = socketpair(AF_UNIX, type, 0, fds);
- if(err)
+ if(err < 0)
return(-errno);
if(!close_on_exec)
return(0);
- if((fcntl(fds[0], F_SETFD, 1) < 0) || (fcntl(fds[1], F_SETFD, 1) < 0))
- printk("os_pipe : Setting FD_CLOEXEC failed, errno = %d",
- errno);
+ err = os_set_exec_close(fds[0], 1);
+ if(err < 0)
+ goto error;
+
+ err = os_set_exec_close(fds[1], 1);
+ if(err < 0)
+ goto error;
return(0);
+
+ error:
+ printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
+ os_close_file(fds[1]);
+ os_close_file(fds[0]);
+ return(err);
}
int os_set_fd_async(int fd, int owner)
return(-EINVAL);
}
err = shutdown(fd, what);
- if(err)
+ if(err < 0)
return(-errno);
return(0);
}
return(new);
}
-int create_unix_socket(char *file, int len)
+int os_create_unix_socket(char *file, int len, int close_on_exec)
{
struct sockaddr_un addr;
int sock, err;
return(-errno);
}
+ if(close_on_exec) {
+ err = os_set_exec_close(sock, 1);
+ if(err < 0)
+ printk("create_unix_socket : close_on_exec failed, "
+ "err = %d", -err);
+ }
+
addr.sun_family = AF_UNIX;
/* XXX Be more careful about overflow */
err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0){
- printk("create_listening_socket - bind failed, errno = %d\n",
- errno);
+ printk("create_listening_socket at '%s' - bind failed, "
+ "errno = %d\n", file, errno);
return(-errno);
}
return(sock);
}
+void os_flush_stdout(void)
+{
+ fflush(stdout);
+}
+
+int os_lock_file(int fd, int excl)
+{
+ int type = excl ? F_WRLCK : F_RDLCK;
+ struct flock lock = ((struct flock) { .l_type = type,
+ .l_whence = SEEK_SET,
+ .l_start = 0,
+ .l_len = 0 } );
+ int err, save;
+
+ err = fcntl(fd, F_SETLK, &lock);
+ if(!err)
+ goto out;
+
+ save = -errno;
+ err = fcntl(fd, F_GETLK, &lock);
+ if(err){
+ err = -errno;
+ goto out;
+ }
+
+ printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
+ err = save;
+ out:
+ return(err);
+}
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include <stdio.h>
#include <errno.h>
#include <signal.h>
+#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include "os.h"
#include "user.h"
+#define ARBITRARY_ADDR -1
+#define FAILURE_PID -1
+
unsigned long os_process_pc(int pid)
{
char proc_stat[sizeof("/proc/#####/stat\0")], buf[256];
unsigned long pc;
- int fd;
+ int fd, err;
sprintf(proc_stat, "/proc/%d/stat", pid);
fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0);
if(fd < 0){
- printk("os_process_pc - couldn't open '%s', errno = %d\n",
- proc_stat, errno);
- return(-1);
+ printk("os_process_pc - couldn't open '%s', err = %d\n",
+ proc_stat, -fd);
+ return(ARBITRARY_ADDR);
}
- if(read(fd, buf, sizeof(buf)) < 0){
- printk("os_process_pc - couldn't read '%s', errno = %d\n",
- proc_stat, errno);
- close(fd);
- return(-1);
+ err = os_read_file(fd, buf, sizeof(buf));
+ if(err < 0){
+ printk("os_process_pc - couldn't read '%s', err = %d\n",
+ proc_stat, -err);
+ os_close_file(fd);
+ return(ARBITRARY_ADDR);
}
- close(fd);
- pc = -1;
+ os_close_file(fd);
+ pc = ARBITRARY_ADDR;
if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d "
"%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
"%*d %*d %*d %*d %ld", &pc) != 1){
snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
fd = os_open_file(stat, of_read(OPENFLAGS()), 0);
if(fd < 0){
- printk("Couldn't open '%s', errno = %d\n", stat, -fd);
- return(-1);
+ printk("Couldn't open '%s', err = %d\n", stat, -fd);
+ return(FAILURE_PID);
}
- n = read(fd, data, sizeof(data));
- close(fd);
+ n = os_read_file(fd, data, sizeof(data));
+ os_close_file(fd);
if(n < 0){
- printk("Couldn't read '%s', errno = %d\n", stat);
- return(-1);
+ printk("Couldn't read '%s', err = %d\n", stat, -n);
+ return(FAILURE_PID);
}
- parent = -1;
+ parent = FAILURE_PID;
/* XXX This will break if there is a space in the command */
n = sscanf(data, "%*d %*s %*c %d", &parent);
- if(n != 1) printk("Failed to scan '%s'\n", data);
+ if(n != 1)
+ printk("Failed to scan '%s'\n", data);
return(parent);
}
void os_usr1_process(int pid)
{
- kill(pid, SIGUSR1);
+ syscall(__NR_tkill, pid, SIGUSR1);
+ /* kill(pid, SIGUSR1); */
}
int os_getpid(void)
return(getpid());
}
-int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len,
+int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
int r, int w, int x)
{
void *loc;
prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
(x ? PROT_EXEC : 0);
- loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
- fd, off);
+ loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
+ fd, off);
if(loc == MAP_FAILED)
return(-errno);
return(0);
int err;
err = munmap(addr, len);
- if(err < 0) return(-errno);
+ if(err < 0)
+ return(-errno);
return(0);
}
struct grantpt_info info;
int fd;
- if((fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0)) < 0){
- printk("get_pty : Couldn't open /dev/ptmx - errno = %d\n",
- errno);
- return(-1);
+ fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
+ return(fd);
}
info.fd = fd;
if(info.res < 0){
printk("get_pty : Couldn't grant pty - errno = %d\n",
- info.err);
+ -info.err);
return(-1);
}
if(unlockpt(fd) < 0){
-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \
- ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
+obj-y = bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o ptrace_user.o \
+ semaphore.o sigcontext.o syscalls.o sysrq.o time.o
obj-$(CONFIG_HIGHMEM) += highmem.o
+obj-$(CONFIG_MODULES) += module.o
USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
SYMLINKS = semaphore.c highmem.c module.c
SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f)
+clean-files := $(SYMLINKS)
+
semaphore.c-dir = kernel
highmem.c-dir = mm
module.c-dir = kernel
$(SYMLINKS):
$(call make_link,$@)
-clean:
- $(MAKE) -C util clean
-
-fastdep:
-
-dep:
-
-archmrproper:
- rm -f $(SYMLINKS)
-
-archclean:
-
-archdep:
-
-modules:
-
+subdir- := util
*/
#include <unistd.h>
-#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/signal.h>
+#include <asm/ldt.h>
#include "kern_util.h"
#include "user.h"
#include "sysdep/ptrace.h"
#include "task.h"
+#include "os.h"
#define MAXTOKEN 64
/* Set during early boot */
-int cpu_has_cmov = 1;
-int cpu_has_xmm = 0;
+int host_has_cmov = 1;
+int host_has_xmm = 0;
static char token(int fd, char *buf, int len, char stop)
{
ptr = buf;
end = &buf[len];
do {
- n = read(fd, ptr, sizeof(*ptr));
+ n = os_read_file(fd, ptr, sizeof(*ptr));
c = *ptr++;
- if(n == 0) return(0);
- else if(n != sizeof(*ptr)){
- printk("Reading /proc/cpuinfo failed, "
- "errno = %d\n", errno);
- return(-errno);
+ if(n != sizeof(*ptr)){
+ if(n == 0) return(0);
+ printk("Reading /proc/cpuinfo failed, err = %d\n", -n);
+ if(n < 0)
+ return(n);
+ else
+ return(-EIO);
}
} while((c != '\n') && (c != stop) && (ptr < end));
return(c);
}
-static int check_cpu_feature(char *feature, int *have_it)
+static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
{
- char buf[MAXTOKEN], c;
- int fd, len = sizeof(buf)/sizeof(buf[0]), n;
-
- printk("Checking for host processor %s support...", feature);
- fd = open("/proc/cpuinfo", O_RDONLY);
- if(fd < 0){
- printk("Couldn't open /proc/cpuinfo, errno = %d\n", errno);
- return(0);
- }
+ int n;
+ char c;
- *have_it = 0;
- buf[len - 1] = '\0';
+ scratch[len - 1] = '\0';
while(1){
- c = token(fd, buf, len - 1, ':');
- if(c <= 0) goto out;
+ c = token(fd, scratch, len - 1, ':');
+ if(c <= 0)
+ return(0);
else if(c != ':'){
printk("Failed to find ':' in /proc/cpuinfo\n");
- goto out;
+ return(0);
}
- if(!strncmp(buf, "flags", strlen("flags"))) break;
+ if(!strncmp(scratch, key, strlen(key)))
+ return(1);
do {
- n = read(fd, &c, sizeof(c));
+ n = os_read_file(fd, &c, sizeof(c));
if(n != sizeof(c)){
printk("Failed to find newline in "
- "/proc/cpuinfo, n = %d, errno = %d\n",
- n, errno);
- goto out;
+ "/proc/cpuinfo, err = %d\n", -n);
+ return(0);
}
} while(c != '\n');
}
+ return(0);
+}
+
+int cpu_feature(char *what, char *buf, int len)
+{
+ int fd, ret = 0;
+
+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+ return(0);
+ }
+
+ if(!find_cpuinfo_line(fd, what, buf, len)){
+ printk("Couldn't find '%s' line in /proc/cpuinfo\n", what);
+ goto out_close;
+ }
+
+ token(fd, buf, len, '\n');
+ ret = 1;
+
+ out_close:
+ os_close_file(fd);
+ return(ret);
+}
+
+static int check_cpu_flag(char *feature, int *have_it)
+{
+ char buf[MAXTOKEN], c;
+ int fd, len = sizeof(buf)/sizeof(buf[0]);
+
+ printk("Checking for host processor %s support...", feature);
+ fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd);
+ return(0);
+ }
+
+ *have_it = 0;
+ if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0])))
+ goto out;
c = token(fd, buf, len - 1, ' ');
if(c < 0) goto out;
else if(c != ' '){
- printk("Failed to find ':' in /proc/cpuinfo\n");
+ printk("Failed to find ' ' in /proc/cpuinfo\n");
goto out;
}
out:
if(*have_it == 0) printk("No\n");
else if(*have_it == 1) printk("Yes\n");
- close(fd);
+ os_close_file(fd);
return(1);
}
+#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems
+ * for some people.
+ */
+static void disable_lcall(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ int err;
+
+ bzero(&ldt, sizeof(ldt));
+ ldt.entry_number = 7;
+ ldt.base_addr = 0;
+ ldt.limit = 0;
+ err = modify_ldt(1, &ldt, sizeof(ldt));
+ if(err)
+ printk("Failed to disable lcall7 - errno = %d\n", errno);
+}
+#endif
+
+void arch_init_thread(void)
+{
+#if 0
+ disable_lcall();
+#endif
+}
+
void arch_check_bugs(void)
{
int have_it;
- if(access("/proc/cpuinfo", R_OK)){
+ if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){
printk("/proc/cpuinfo not available - skipping CPU capability "
"checks\n");
return;
}
- if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it;
- if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it;
+ if(check_cpu_flag("cmov", &have_it))
+ host_has_cmov = have_it;
+ if(check_cpu_flag("xmm", &have_it))
+ host_has_xmm = have_it;
}
int arch_handle_signal(int sig, union uml_pt_regs *regs)
if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40))
return(0);
- if(cpu_has_cmov == 0)
+ if(host_has_cmov == 0)
panic("SIGILL caused by cmov, which this processor doesn't "
"implement, boot a filesystem compiled for older "
"processors");
- else if(cpu_has_cmov == 1)
+ else if(host_has_cmov == 1)
panic("SIGILL caused by cmov, which this processor claims to "
"implement");
- else if(cpu_has_cmov == -1)
+ else if(host_has_cmov == -1)
panic("SIGILL caused by cmov, couldn't tell if this processor "
"implements it, boot a filesystem compiled for older "
"processors");
- else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov);
+ else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
return(0);
}
/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"
-extern unsigned long search_exception_table(unsigned long addr);
+/* 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, void *sc_ptr)
{
struct sigcontext *sc = sc_ptr;
- unsigned long fixup;
+ const struct exception_table_entry *fixup;
fixup = search_exception_tables(address);
if(fixup != 0){
- sc->eip = fixup;
+ sc->eip = fixup->fixup;
return(1);
}
return(0);
nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
for(i = 0; i < nregs; i++){
if((i == 4) || (i == 5)) continue;
- if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
+ if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i],
regs[i]) < 0)
- printk("write_debugregs - ptrace failed, "
- "errno = %d\n", errno);
+ printk("write_debugregs - ptrace failed on "
+ "register %d, errno = %d\n", errno);
}
}
dummy = NULL;
nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
for(i = 0; i < nregs; i++){
- regs[i] = ptrace(PTRACE_PEEKUSR, pid,
+ regs[i] = ptrace(PTRACE_PEEKUSER, pid,
&dummy->u_debugreg[i], 0);
}
}
+host-progs := mk_sc mk_thread
+always := $(host-progs)
-host-progs := mk_sc
-always := $(host-progs) mk_thread
-targets := mk_thread_kern.o mk_thread_user.o
+mk_thread-objs := mk_thread_kern.o mk_thread_user.o
-mk_sc-objs := mk_sc.o
-
-$(obj)/mk_thread : $(obj)/mk_thread_kern.o $(obj)/mk_thread_user.o
- $(CC) $(CFLAGS) -o $@ $^
-
-$(obj)/mk_thread_user.o : $(src)/mk_thread_user.c
- $(CC) $(USER_CFLAGS) -c -o $@ $<
+HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS)
clean :
$(RM) -f $(build-targets)
SC_OFFSET("SC_ERR", err);
SC_OFFSET("SC_CR2", cr2);
SC_OFFSET("SC_FPSTATE", fpstate);
+ SC_OFFSET("SC_SIGMASK", oldmask);
SC_FP_OFFSET("SC_FP_CW", cw);
SC_FP_OFFSET("SC_FP_SW", sw);
SC_FP_OFFSET("SC_FP_TAG", tag);
$(OBJ): $(OBJS)
rm -f $@
$(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
-clean:
- rm -f $(OBJS)
-fastdep:
-
-archmrproper:
-
-archclean:
- rm -f link.ld
- @$(MAKEBOOT) clean
-
-archdep:
- @$(MAKEBOOT) dep
-
-modules:
+clean-files := $(OBJS) link.ld
$(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
rm -f asm
-clean:
- rm -f $(OBJS)
- rm -f ppc_defs.h
- rm -f checksum.S semaphore.c mk_defs.c
-
-fastdep:
-
-dep:
-
-modules:
+clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c
{
. = START + SIZEOF_HEADERS;
- . = ALIGN(4096);
__binary_start = .;
#ifdef MODE_TT
.thread_private : {
. = ALIGN(4096); /* Init code and data */
_stext = .;
__init_begin = .;
- .text.init : { *(.text.init) }
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
. = ALIGN(4096);
.text :
{
*(.text)
+ SCHED_TEXT
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
#include "asm/common.lds.S"
- .data.init : { *(.data.init) }
+ init.data : { *(init.data) }
.data :
{
. = ALIGN(KERNEL_STACK_SIZE); /* init_task */
-always := mk_task mk_constants
-targets := mk_task_user.o mk_task_kern.o \
- mk_constants_user.o mk_constants_kern.o
+host-progs := mk_task mk_constants
+always := $(host-progs)
-$(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o
- $(CC) -o $@ $^
+mk_task-objs := mk_task_user.o mk_task_kern.o
+mk_constants-objs := mk_constants_user.o mk_constants_kern.o
-$(obj)/mk_task_user.o: $(src)/mk_task_user.c
- $(CC) -o $@ -c $<
-
-$(obj)/mk_constants : $(obj)/mk_constants_user.o $(obj)/mk_constants_kern.o
- $(CC) -o $@ $^
-
-$(obj)/mk_constants_user.o : $(src)/mk_constants_user.c
- $(CC) -c $< -o $@
-
-$(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c
- $(CC) $(CFLAGS) -c $< -o $@
-
-clean:
- $(RM) $(build-targets)
-
-archmrproper:
+HOSTCFLAGS_mk_task_kern.o := $(CFLAGS) $(CPPFLAGS)
+HOSTCFLAGS_mk_constants_kern.o := $(CFLAGS) $(CPPFLAGS)
#include "linux/kernel.h"
#include "linux/stringify.h"
+#include "linux/time.h"
#include "asm/page.h"
extern void print_head(void);
{
print_head();
print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
+
print_constant_str("UM_KERN_EMERG", KERN_EMERG);
print_constant_str("UM_KERN_ALERT", KERN_ALERT);
print_constant_str("UM_KERN_CRIT", KERN_CRIT);
print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
print_constant_str("UM_KERN_INFO", KERN_INFO);
print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
+
+ print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC);
print_tail();
return(0);
}
obj-$(CONFIG_XFS_FS) += xfs/
obj-$(CONFIG_AFS_FS) += afs/
obj-$(CONFIG_BEFS_FS) += befs/
+obj-$(CONFIG_HOSTFS) += hostfs/
+obj-$(CONFIG_HPPFS) += hppfs/
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
* Licensed under the GPL
*/
pr_reg[16] = PT_REGS_SS(regs); \
} while(0);
+#if 0 /* Turn this back on when UML has VSYSCALL working */
+#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
+#else
+#define VSYSCALL_BASE 0
+#endif
+
+#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
+#define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
+extern void *__kernel_vsyscall;
+
+/*
+ * 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 { \
+ NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \
+ NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE); \
+} while (0)
+
+/*
+ * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the vsyscall DSO contents. Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the vsyscall DSO was being used.
+ */
+#if 0
+#define ELF_CORE_EXTRA_PHDRS (VSYSCALL_EHDR->e_phnum)
+#endif
+
+#undef ELF_CORE_EXTRA_PHDRS
+
+#if 0
+#define ELF_CORE_WRITE_EXTRA_PHDRS \
+do { \
+ const struct elf_phdr *const vsyscall_phdrs = \
+ (const struct elf_phdr *) (VSYSCALL_BASE \
+ + VSYSCALL_EHDR->e_phoff); \
+ int i; \
+ Elf32_Off ofs = 0; \
+ for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
+ struct elf_phdr phdr = vsyscall_phdrs[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 */ \
+ DUMP_WRITE(&phdr, sizeof(phdr)); \
+ } \
+} while (0)
+#define ELF_CORE_WRITE_EXTRA_DATA \
+do { \
+ const struct elf_phdr *const vsyscall_phdrs = \
+ (const struct elf_phdr *) (VSYSCALL_BASE \
+ + VSYSCALL_EHDR->e_phoff); \
+ int i; \
+ for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \
+ if (vsyscall_phdrs[i].p_type == PT_LOAD) \
+ DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \
+ vsyscall_phdrs[i].p_filesz); \
+ } \
+} while (0)
+#endif
+
+#undef ELF_CORE_WRITE_EXTRA_PHDRS
+#undef ELF_CORE_WRITE_EXTRA_DATA
+
+#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
+
/********* Bits for asm-um/delay.h **********/
typedef unsigned long um_udelay_t;
+#include <asm-generic/vmlinux.lds.h>
+
.fini : { *(.fini) } =0x9090
_etext = .;
PROVIDE (etext = .);
RODATA
- __start___ksymtab = .; /* Kernel symbol table */
- __ksymtab : { *(__ksymtab) }
- __stop___ksymtab = .;
-
- __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */
- __gpl_ksymtab : { *(__gpl_ksymtab) }
- __stop___gpl_ksymtab = .;
-
- __start___kallsyms = .; /* All kernel symbols */
- __kallsyms : { *(__kallsyms) }
- __stop___kallsyms = .;
-
.unprotected : { *(.unprotected) }
. = ALIGN(4096);
PROVIDE (_unprotected_end = .);
}
__initcall_end = .;
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+
__uml_initcall_start = .;
.uml.initcall.init : { *(.uml.initcall.init) }
__uml_initcall_end = .;
__init_end = .;
+ SECURITY_INIT
+
__exitcall_begin = .;
.exitcall : { *(.exitcall.exit) }
__exitcall_end = .;
.uml.exitcall : { *(.uml.exitcall.exit) }
__uml_exitcall_end = .;
- . = ALIGN(4096);
+ . = ALIGN(4);
+ __alt_instructions = .;
+ .altinstructions : { *(.altinstructions) }
+ __alt_instructions_end = .;
+ .altinstr_replacement : { *(.altinstr_replacement) }
+ /* .exit.text is discard at runtime, not link time, to deal with references
+ from .altinstructions and .eh_frame */
+ .exit.text : { *(.exit.text) }
+ .exit.data : { *(.exit.data) }
+
+ __preinit_array_start = .;
+ .preinit_array : { *(.preinit_array) }
+ __preinit_array_end = .;
+ __init_array_start = .;
+ .init_array : { *(.init_array) }
+ __init_array_end = .;
+ __fini_array_start = .;
+ .fini_array : { *(.fini_array) }
+ __fini_array_end = .;
+
+ . = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exitcall.exit)
+ }
+
#define CURRENT_THREAD(dummy) (((unsigned long) &dummy) & \
(PAGE_MASK << CONFIG_KERNEL_STACK_ORDER))
-#define current ({ int dummy; \
- ((struct thread_info *) CURRENT_THREAD(dummy))->task; })
+#define current_thread \
+ ({ int dummy; ((struct thread_info *) CURRENT_THREAD(dummy)); })
+
+#define current (current_thread->task)
#endif /* __ASSEMBLY__ */
-#include <asm-generic/dma-mapping.h>
+#ifndef _ASM_DMA_MAPPING_H
+#define _ASM_DMA_MAPPING_H
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+ BUG();
+ return(0);
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 dma_mask)
+{
+ BUG();
+ return(0);
+}
+
+static inline void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
+ int flag)
+{
+ BUG();
+ return((void *) 0);
+}
+
+static inline void
+dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t dma_handle)
+{
+ BUG();
+}
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *cpu_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return(0);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return(0);
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ BUG();
+ return(0);
+}
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+#define dma_is_consistent(d) (1)
+
+static inline int
+dma_get_cache_alignment(void)
+{
+ BUG();
+ return(0);
+}
+
+static inline void
+dma_sync_single_range(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG();
+}
+
+#endif
#define USE_ELF_CORE_DUMP
+#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
+
#endif
FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
#endif
+ FIX_VSYSCALL,
__end_of_fixed_addresses
};
#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
+/*
+ * 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 (__fix_to_virt(FIX_VSYSCALL))
+#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE)
+
extern void __this_fixmap_does_not_exist(void);
/*
#ifndef __UM_IRQ_H
#define __UM_IRQ_H
-/* The i386 irq.h has a struct task_struct in a prototype without including
- * sched.h. This forward declaration kills the resulting warning.
- */
-struct task_struct;
-
-#include "asm/ptrace.h"
-
-#undef NR_IRQS
-
#define TIMER_IRQ 0
#define UMN_IRQ 1
#define CONSOLE_IRQ 2
#define LAST_IRQ XTERM_IRQ
#define NR_IRQS (LAST_IRQ + 1)
-extern int um_request_irq(unsigned int irq, int fd, int type,
- void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags, const char * devname,
- void *dev_id);
-
-struct irqaction;
-struct pt_regs;
-int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
-
#endif
+/*
+ * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
#ifndef __UM_PAGE_H
#define __UM_PAGE_H
struct page;
#include "asm/arch/page.h"
-#include "asm/bug.h"
#undef __pa
#undef __va
#define __va_space (8*1024*1024)
-extern unsigned long region_pa(void *virt);
-extern void *region_va(unsigned long phys);
-
-#define __pa(virt) region_pa((void *) (virt))
-#define __va(phys) region_va((unsigned long) (phys))
-
-extern unsigned long page_to_pfn(struct page *page);
-extern struct page *pfn_to_page(unsigned long pfn);
+extern unsigned long to_phys(void *virt);
+extern void *to_virt(unsigned long phys);
-extern struct page *phys_to_page(unsigned long phys);
+#define __pa(virt) to_phys((void *) virt)
+#define __va(phys) to_virt((unsigned long) phys)
-#define virt_to_page(v) (phys_to_page(__pa(v)))
+#define page_to_pfn(page) ((page) - mem_map)
+#define pfn_to_page(pfn) (mem_map + (pfn))
-extern struct page *page_mem_map(struct page *page);
+#define phys_to_pfn(p) ((p) >> PAGE_SHIFT)
+#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
-#define pfn_valid(pfn) (page_mem_map(pfn_to_page(pfn)) != NULL)
-#define virt_addr_valid(v) pfn_valid(__pa(v) >> PAGE_SHIFT)
+#define pfn_valid(pfn) ((pfn) < max_mapnr)
+#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
extern struct page *arch_validate(struct page *page, int mask, int order);
#define HAVE_ARCH_VALIDATE
+extern void arch_free_page(struct page *page, int order);
+#define HAVE_ARCH_FREE_PAGE
+
#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
#include "asm/page.h"
#include "asm/fixmap.h"
-extern pgd_t swapper_pg_dir[1024];
-
extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
pte_t *pte_out);
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
/*
* pgd entries used up by user/kernel:
*/
* area for the same reason. ;)
*/
-extern unsigned long high_physmem;
+extern unsigned long end_iomem;
#define VMALLOC_OFFSET (__va_space)
-#define VMALLOC_START (((unsigned long) high_physmem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
#ifdef CONFIG_HIGHMEM
# define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
#define _PAGE_PRESENT 0x001
#define _PAGE_NEWPAGE 0x002
-#define _PAGE_PROTNONE 0x004 /* If not present */
-#define _PAGE_RW 0x008
-#define _PAGE_USER 0x010
-#define _PAGE_ACCESSED 0x020
-#define _PAGE_DIRTY 0x040
-#define _PAGE_NEWPROT 0x080
+#define _PAGE_NEWPROT 0x004
+#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */
+#define _PAGE_PROTNONE 0x010 /* If not present */
+#define _PAGE_RW 0x020
+#define _PAGE_USER 0x040
+#define _PAGE_ACCESSED 0x080
+#define _PAGE_DIRTY 0x100
#define REGION_MASK 0xf0000000
#define REGION_SHIFT 28
#define BAD_PAGETABLE __bad_pagetable()
#define BAD_PAGE __bad_page()
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
/* number of bits that fit into a memory pointer */
#define BITS_PER_PTR (8*sizeof(unsigned long))
#define pte_clear(xp) do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
-#define phys_region_index(x) (((x) & REGION_MASK) >> REGION_SHIFT)
-#define pte_region_index(x) phys_region_index(pte_val(x))
-
#define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE))
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-extern struct page *pte_mem_map(pte_t pte);
-extern struct page *phys_mem_map(unsigned long phys);
-extern unsigned long phys_to_pfn(unsigned long p);
-extern unsigned long pfn_to_phys(unsigned long pfn);
+#define pte_page(pte) phys_to_page(pte_val(pte))
+#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
-#define pte_page(x) pfn_to_page(pte_pfn(x))
-#define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
-#define mk_phys(a, r) ((a) + (r << REGION_SHIFT))
-#define phys_addr(p) ((p) & ~REGION_MASK)
-#define phys_page(p) (phys_mem_map(p) + ((phys_addr(p)) >> PAGE_SHIFT))
#define pte_pfn(x) phys_to_pfn(pte_val(x))
#define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
-#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
+
+extern struct page *phys_to_page(const unsigned long phys);
+extern struct page *__virt_to_page(const unsigned long virt);
+#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
+
+/*
+ * Bits 0 through 3 are taken
+ */
+#define PTE_FILE_MAX_BITS 28
+
+#define pte_to_pgoff(pte) ((pte).pte_low >> 4)
+
+#define pgoff_to_pte(off) \
+ ((pte_t) { ((off) << 4) + _PAGE_FILE })
static inline pte_t pte_mknewprot(pte_t pte)
{
* The following only work if pte_present() is true.
* Undefined behaviour if not..
*/
+static inline int pte_user(pte_t pte)
+{
+ return((pte_val(pte) & _PAGE_USER) &&
+ !(pte_val(pte) & _PAGE_PROTNONE));
+}
+
static inline int pte_read(pte_t pte)
{
return((pte_val(pte) & _PAGE_USER) &&
!(pte_val(pte) & _PAGE_PROTNONE));
}
+/*
+ * The following only works if pte_present() is not true.
+ */
+static inline int pte_file(pte_t pte)
+{
+ return (pte).pte_low & _PAGE_FILE;
+}
+
static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; }
* and a page entry and page directory to the page they refer to.
*/
-#define mk_pte(page, pgprot) \
-({ \
- pte_t __pte; \
- \
- pte_val(__pte) = page_to_phys(page) + pgprot_val(pgprot);\
- if(pte_present(__pte)) pte_mknewprot(pte_mknewpage(__pte)); \
- __pte; \
-})
+extern pte_t mk_pte(struct page *page, pgprot_t pgprot);
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
}
#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
-#define pmd_page(pmd) (phys_mem_map(pmd_val(pmd) & PAGE_MASK) + \
- ((phys_addr(pmd_val(pmd)) >> PAGE_SHIFT)))
-/* to find an entry in a page-table-directory. */
+/*
+ * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+ *
+ * this macro returns the index of the entry in the pgd page which would
+ * control the given virtual address
+ */
#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
-/* to find an entry in a page-table-directory */
+/*
+ * pgd_offset() returns a (pgd_t *)
+ * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+ */
#define pgd_offset(mm, address) \
((mm)->pgd + ((address) >> PGDIR_SHIFT))
-/* to find an entry in a kernel page-table-directory */
+
+/*
+ * a shortcut which implies the use of the kernel's pgd, instead
+ * of a process's
+ */
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
#define pmd_index(address) \
return (pmd_t *) dir;
}
-/* Find an entry in the third-level page table.. */
+/*
+ * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+ *
+ * this macro returns the index of the entry in the pte page which would
+ * control the given virtual address
+ */
#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
#define pte_offset_kernel(dir, address) \
((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address))
#define update_mmu_cache(vma,address,pte) do ; while (0)
/* Encode and de-code a swap entry */
-#define __swp_type(x) (((x).val >> 3) & 0x7f)
-#define __swp_offset(x) ((x).val >> 10)
+#define __swp_type(x) (((x).val >> 4) & 0x3f)
+#define __swp_offset(x) ((x).val >> 11)
#define __swp_entry(type, offset) \
- ((swp_entry_t) { ((type) << 3) | ((offset) << 10) })
+ ((swp_entry_t) { ((type) << 4) | ((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 })
struct task_struct;
#include "linux/config.h"
-#include "linux/signal.h"
#include "asm/ptrace.h"
-#include "asm/siginfo.h"
#include "choose-mode.h"
struct mm_struct;
#define current_text_addr() ((void *) 0)
-#define cpu_relax() do ; while (0)
-
-#ifdef CONFIG_MODE_TT
-struct proc_tt_mode {
- int extern_pid;
- int tracing;
- int switch_pipe[2];
- int singlestep_syscall;
- int vm_seq;
-};
-#endif
-
-#ifdef CONFIG_MODE_SKAS
-struct proc_skas_mode {
- void *switch_buf;
- void *fork_buf;
-};
-#endif
+#define cpu_relax() barrier()
struct thread_struct {
int forking;
struct pt_regs regs;
unsigned long cr2;
int err;
+ unsigned long trap_no;
void *fault_addr;
void *fault_catcher;
struct task_struct *prev_sched;
struct arch_thread arch;
union {
#ifdef CONFIG_MODE_TT
- struct proc_tt_mode tt;
+ struct {
+ int extern_pid;
+ int tracing;
+ int switch_pipe[2];
+ int singlestep_syscall;
+ int vm_seq;
+ } tt;
#endif
#ifdef CONFIG_MODE_SKAS
- struct proc_skas_mode skas;
+ struct {
+ void *switch_buf;
+ void *fork_buf;
+ int mm_count;
+ } skas;
#endif
} mode;
struct {
} mm_segment_t;
extern struct task_struct *alloc_task_struct(void);
-extern void free_task_struct(struct task_struct *task);
extern void release_thread(struct task_struct *);
extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
extern void dump_thread(struct pt_regs *regs, struct user *u);
+extern 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,
+ struct mm_struct *new_mm)
+{
+}
+
#define init_stack (init_thread_union.stack)
/*
#ifndef __UM_PROCESSOR_I386_H
#define __UM_PROCESSOR_I386_H
-extern int cpu_has_xmm;
-extern int cpu_has_cmov;
+extern int host_has_xmm;
+extern int host_has_cmov;
struct arch_thread {
unsigned long debugregs[8];
extern cpumask_t cpu_online_map;
-#define smp_processor_id() (current->thread_info->cpu)
+#define 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 void block_signals(void);
extern void unblock_signals(void);
-#define local_save_flags(flags) do { (flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { set_signals(flags); } while(0)
+#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
+ (flags) = get_signals(); } while(0)
+#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
+ set_signals(flags); } while(0)
#define local_irq_save(flags) do { local_save_flags(flags); \
local_irq_disable(); } while(0)
(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
#define __UM_SYSTEM_I386_H
#include "asm/system-generic.h"
-
-static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
- unsigned long new, int size)
-{
- unsigned long prev;
- switch (size) {
- case 1:
- __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
- : "=a"(prev)
- : "q"(new), "m"(*__xg(ptr)), "0"(old)
- : "memory");
- return prev;
- case 2:
- __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
- : "=a"(prev)
- : "q"(new), "m"(*__xg(ptr)), "0"(old)
- : "memory");
- return prev;
- case 4:
- __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
- : "=a"(prev)
- : "q"(new), "m"(*__xg(ptr)), "0"(old)
- : "memory");
- return prev;
- }
- return old;
-}
-
-#define cmpxchg(ptr,o,n)\
- ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
- (unsigned long)(n),sizeof(*(ptr))))
#endif
#ifndef __ASSEMBLY__
#include <asm/processor.h>
+#include <asm/types.h>
struct thread_info {
struct task_struct *task; /* main task structure */
static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
- __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~16383UL));
+ unsigned long mask = PAGE_SIZE *
+ (1 << CONFIG_KERNEL_STACK_ORDER) - 1;
+ __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask));
return ti;
}
/* thread information allocation */
-#define THREAD_SIZE (4*PAGE_SIZE)
-#define alloc_thread_info(tsk) ((struct thread_info *) \
- __get_free_pages(GFP_KERNEL,2))
-#define free_thread_info(ti) free_pages((unsigned long) (ti), 2)
+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
+#define alloc_thread_info(tsk) \
+ ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
+#define free_thread_info(ti) kfree(ti)
+
#define get_thread_info(ti) get_task_struct((ti)->task)
#define put_thread_info(ti) put_task_struct((ti)->task)
#define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling
* TIF_NEED_RESCHED
*/
+#define TIF_RESTART_BLOCK 4
#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_RESTART_BLOCK (1 << TIF_RESTART_BLOCK)
#endif
#ifndef __UM_TIMEX_H
#define __UM_TIMEX_H
-#include "linux/time.h"
-
typedef unsigned long cycles_t;
#define cacheflush_time (0)
#ifndef __UM_UACCESS_H
#define __UM_UACCESS_H
+#include "linux/sched.h"
+
#define VERIFY_READ 0
#define VERIFY_WRITE 1
set_fs(KERNEL_DS); \
ret = sys(args); \
set_fs(fs); \
- return ret;
+ if (ret >= 0) \
+ return ret; \
+ errno = -(long)ret; \
+ return -1;
static inline long open(const char *pathname, int flags, int mode)
{
* For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets
* optimized to &contig_page_data at compile-time.
*/
+
+#ifndef HAVE_ARCH_FREE_PAGE
+static inline void arch_free_page(struct page *page, int order) { }
+#endif
+
extern struct page * FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *));
static inline struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order)
{
*/
typedef int (*shrinker_t)(int nr_to_scan, unsigned int gfp_mask);
+extern long do_mprotect(struct mm_struct *mm, unsigned long start,
+ size_t len, unsigned long prot);
+
/*
* Add an aging callback. The int is the number of 'seeks' it takes
* to recreate one of the objects that these functions age.
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
-extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
- unsigned long len, unsigned long prot,
- unsigned long flag, unsigned long pgoff);
+extern unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file *file,
+ unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flag,
+ unsigned long pgoff);
static inline unsigned long do_mmap(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
if ((offset + PAGE_ALIGN(len)) < offset)
goto out;
if (!(offset & ~PAGE_MASK))
- ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
+ ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag,
+ offset >> PAGE_SHIFT);
out:
return ret;
}
* Have the 32 bit jiffies value wrap 5 minutes after boot
* so jiffies wrap bugs show up earlier.
*/
-#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
+#define INITIAL_JIFFIES ((unsigned long)(0))
/*
* Change timeval to jiffies, trying to avoid the
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
+obj-$(CONFIG_PROC_MM) += proc_mm.o
* The caller must hold down_write(current->mm->mmap_sem).
*/
-unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
- unsigned long len, unsigned long prot,
- unsigned long flags, unsigned long pgoff)
+unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file,
+ unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long pgoff)
{
- struct mm_struct * mm = current->mm;
struct vm_area_struct * vma, * prev;
struct inode *inode;
unsigned int vm_flags;
}
asmlinkage long
-sys_mprotect(unsigned long start, size_t len, unsigned long prot)
+do_mprotect(struct mm_struct *mm, unsigned long start, size_t len,
+ unsigned long prot)
{
unsigned long vm_flags, nstart, end, tmp;
struct vm_area_struct * vma, * next, * prev;
vm_flags = calc_vm_prot_bits(prot);
- down_write(¤t->mm->mmap_sem);
+ down_write(&mm->mmap_sem);
- vma = find_vma_prev(current->mm, start, &prev);
+ vma = find_vma_prev(mm, start, &prev);
error = -ENOMEM;
if (!vma)
goto out;
prev->vm_mm->map_count--;
}
out:
- up_write(¤t->mm->mmap_sem);
+ up_write(&mm->mmap_sem);
return error;
}
+
+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
+{
+ return(do_mprotect(current->mm, start, len, prot));
+}
LIST_HEAD(list);
int i;
+ arch_free_page(page, order);
+
mod_page_state(pgfree, 1 << order);
for (i = 0 ; i < (1 << order) ; ++i)
free_pages_check(__FUNCTION__, page + i);
struct per_cpu_pages *pcp;
unsigned long flags;
+ arch_free_page(page, 0);
+
kernel_map_pages(page, 1, 0);
inc_page_state(pgfree);
free_pages_check(__FUNCTION__, page);