diff options
Diffstat (limited to 'arch/frv')
202 files changed, 10802 insertions, 4784 deletions
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index 60a617aff8b..34aa19352dc 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -1,10 +1,23 @@ -# -# For a description of the syntax of this configuration file, -# see Documentation/kbuild/kconfig-language.txt. -# config FRV bool default y + select HAVE_IDE + select HAVE_ARCH_TRACEHOOK + select HAVE_PERF_EVENTS + select HAVE_UID16 + select VIRT_TO_BUS + select GENERIC_IRQ_SHOW + select HAVE_DEBUG_BUGVERBOSE + select ARCH_HAVE_NMI_SAFE_CMPXCHG + select GENERIC_CPU_DEVICES + select ARCH_WANT_IPC_PARSE_VERSION + select OLD_SIGSUSPEND3 + select OLD_SIGACTION + select HAVE_DEBUG_STACKOVERFLOW + +config ZONE_DMA + bool + default y config RWSEM_GENERIC_SPINLOCK bool @@ -13,7 +26,7 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool -config GENERIC_FIND_NEXT_BIT +config GENERIC_HWEIGHT bool default y @@ -21,14 +34,30 @@ config GENERIC_CALIBRATE_DELAY bool default n -config GENERIC_HARDIRQS +config TIME_LOW_RES bool - default n + default y + +config QUICKLIST + bool + default y + +config ARCH_HAS_ILOG2_U32 + bool + default y + +config ARCH_HAS_ILOG2_U64 + bool + default y -mainmenu "Fujitsu FR-V Kernel Configuration" +config HZ + int + default 1000 source "init/Kconfig" +source "kernel/Kconfig.freezer" + menu "Fujitsu FR-V system setup" @@ -47,7 +76,7 @@ config FRV_OUTOFLINE_ATOMIC_OPS Setting this option causes the FR-V atomic operations to be mostly implemented out-of-line. - See Documentation/fujitsu/frv/atomic-ops.txt for more information. + See Documentation/frv/atomic-ops.txt for more information. config HIGHMEM bool "High memory support" @@ -106,6 +135,15 @@ config UCPAGE_OFFSET_C0000000 endchoice +config PAGE_OFFSET + hex + default 0x20000000 if UCPAGE_OFFSET_20000000 + default 0x40000000 if UCPAGE_OFFSET_40000000 + default 0x60000000 if UCPAGE_OFFSET_60000000 + default 0x80000000 if UCPAGE_OFFSET_80000000 + default 0xA0000000 if UCPAGE_OFFSET_A0000000 + default 0xC0000000 + config PROTECT_KERNEL bool "Protect core kernel against userspace" depends on !MMU @@ -239,6 +277,12 @@ config MB93091_NO_MB endchoice endif +config FUJITSU_MB93493 + bool "MB93493 Multimedia chip" + help + Select this option if the MB93493 multimedia chip is going to be + used. + choice prompt "GP-Relative data support" default GPREL_DATA_8 @@ -279,16 +323,12 @@ config PCI bool "Use PCI" depends on MB93090_MB00 default y + select GENERIC_PCI_IOMAP help Some FR-V systems (such as the MB93090-MB00 VDK) have PCI onboard. If you have one of these boards and you wish to use the PCI facilities, say Y here. - The PCI-HOWTO, available from - <http://www.tldp.org/docs.html#howto>, contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - config RESERVE_DMA_COHERENT bool "Reserve DMA coherent memory" depends on PCI && !MMU @@ -308,17 +348,11 @@ source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" -#config MATH_EMULATION -# bool "Math emulation support (EXPERIMENTAL)" -# depends on EXPERIMENTAL -# help -# At some point in the future, this will cause floating-point math -# instructions to be emulated by the kernel on machines that lack a -# floating-point math coprocessor. Thrill-seekers and chronically -# sleep-deprived psychotic hacker types can say Y now, everyone else -# should probably wait a while. - menu "Power management options" + +config ARCH_SUSPEND_POSSIBLE + def_bool y + source kernel/power/Kconfig endmenu diff --git a/arch/frv/Kconfig.debug b/arch/frv/Kconfig.debug index 211f01bc4ca..98c99a3ed2b 100644 --- a/arch/frv/Kconfig.debug +++ b/arch/frv/Kconfig.debug @@ -2,10 +2,6 @@ menu "Kernel hacking" source "lib/Kconfig.debug" -config DEBUG_STACKOVERFLOW - bool "Check for stack overflows" - depends on DEBUG_KERNEL - config GDBSTUB bool "Remote GDB kernel debugging" depends on DEBUG_KERNEL diff --git a/arch/frv/Makefile b/arch/frv/Makefile index 90c0fb8d9dc..2a8fb730d1c 100644 --- a/arch/frv/Makefile +++ b/arch/frv/Makefile @@ -23,29 +23,23 @@ # Copyright (C) 1994 by Hamish Macdonald # -CCSPECS := $(shell $(CC) -v 2>&1 | grep "^Reading specs from " | head -1 | cut -c20-) -CCDIR := $(strip $(patsubst %/specs,%,$(CCSPECS))) -CPUCLASS := fr400 - -# test for cross compiling -COMPILE_ARCH = $(shell uname -m) - ifdef CONFIG_MMU UTS_SYSNAME = -DUTS_SYSNAME=\"Linux\" else UTS_SYSNAME = -DUTS_SYSNAME=\"uClinux\" endif -ARCHMODFLAGS += -G0 -mlong-calls +KBUILD_AFLAGS_MODULE += -G0 -mlong-calls +KBUILD_CFLAGS_MODULE += -G0 -mlong-calls ifdef CONFIG_GPREL_DATA_8 -CFLAGS += -G8 +KBUILD_CFLAGS += -G8 else ifdef CONFIG_GPREL_DATA_4 -CFLAGS += -G4 +KBUILD_CFLAGS += -G4 else ifdef CONFIG_GPREL_DATA_NONE -CFLAGS += -G0 +KBUILD_CFLAGS += -G0 endif endif endif @@ -53,47 +47,34 @@ endif #LDFLAGS_vmlinux := -Map linkmap.txt ifdef CONFIG_GC_SECTIONS -CFLAGS += -ffunction-sections -fdata-sections -LINKFLAGS += --gc-sections +KBUILD_CFLAGS += -ffunction-sections -fdata-sections endif ifndef CONFIG_FRAME_POINTER -CFLAGS += -mno-linked-fp +KBUILD_CFLAGS += -mno-linked-fp endif ifdef CONFIG_CPU_FR451_COMPILE -CFLAGS += -mcpu=fr450 -AFLAGS += -mcpu=fr450 -ASFLAGS += -mcpu=fr450 +KBUILD_CFLAGS += -mcpu=fr450 +KBUILD_AFLAGS += -mcpu=fr450 else ifdef CONFIG_CPU_FR551_COMPILE -CFLAGS += -mcpu=fr550 -AFLAGS += -mcpu=fr550 -ASFLAGS += -mcpu=fr550 +KBUILD_CFLAGS += -mcpu=fr550 +KBUILD_AFLAGS += -mcpu=fr550 else -CFLAGS += -mcpu=fr400 -AFLAGS += -mcpu=fr400 -ASFLAGS += -mcpu=fr400 +KBUILD_CFLAGS += -mcpu=fr400 +KBUILD_AFLAGS += -mcpu=fr400 endif endif # pretend the kernel is going to run on an FR400 with no media-fp unit # - reserve CC3 for use with atomic ops # - all the extra registers are dealt with only at context switch time -CFLAGS += -mno-fdpic -mgpr-32 -msoft-float -mno-media -CFLAGS += -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15 -AFLAGS += -mno-fdpic -ASFLAGS += -mno-fdpic - -# make sure the .S files get compiled with debug info -# and disable optimisations that are unhelpful whilst debugging -ifdef CONFIG_DEBUG_INFO -CFLAGS += -O1 -AFLAGS += -Wa,--gdwarf2 -ASFLAGS += -Wa,--gdwarf2 -endif +KBUILD_CFLAGS += -mno-fdpic -mgpr-32 -msoft-float -mno-media +KBUILD_CFLAGS += -ffixed-fcc3 -ffixed-cc3 -ffixed-gr15 -ffixed-icc2 +KBUILD_AFLAGS += -mno-fdpic -head-y := arch/frv/kernel/head.o arch/frv/kernel/init_task.o +head-y := arch/frv/kernel/head.o core-y += arch/frv/kernel/ arch/frv/mm/ libs-y += arch/frv/lib/ @@ -105,14 +86,5 @@ all: Image Image: vmlinux $(Q)$(MAKE) $(build)=arch/frv/boot $@ -bootstrap: - $(Q)$(MAKEBOOT) bootstrap - -archmrproper: - $(Q)$(MAKE) $(build)=arch/frv/boot mrproper - archclean: - $(Q)$(MAKE) $(build)=arch/frv/boot clean - -archdep: scripts/mkdep symlinks - $(Q)$(MAKE) $(build)=arch/frv/boot dep + $(Q)$(MAKE) $(clean)=arch/frv/boot diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile index 5dfc93fd945..636d5bbcd53 100644 --- a/arch/frv/boot/Makefile +++ b/arch/frv/boot/Makefile @@ -8,13 +8,17 @@ # Copyright (C) 1995-2000 Russell King # -SYSTEM =$(TOPDIR)/$(LINUX) +targets := Image zImage bootpImage + +SYSTEM =$(LINUX) ZTEXTADDR = 0x02080000 PARAMS_PHYS = 0x0207c000 INITRD_PHYS = 0x02180000 INITRD_VIRT = 0x02180000 +OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment + # # If you don't define ZRELADDR above, # then it defaults to ZTEXTADDR @@ -30,20 +34,20 @@ Image: $(obj)/Image targets: $(obj)/Image $(obj)/Image: vmlinux FORCE - $(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@ + $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@ #$(obj)/Image: $(CONFIGURE) $(SYSTEM) -# $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@ +# $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@ bzImage: zImage zImage: $(CONFIGURE) compressed/$(LINUX) - $(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@ + $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@ bootpImage: bootp/bootp - $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ + $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@ -compressed/$(LINUX): $(TOPDIR)/$(LINUX) dep +compressed/$(LINUX): $(LINUX) dep @$(MAKE) -C compressed $(LINUX) bootp/bootp: zImage initrd @@ -57,16 +61,15 @@ initrd: # installation # install: $(CONFIGURE) Image - sh ./install.sh $(KERNELRELEASE) Image $(TOPDIR)/System.map "$(INSTALL_PATH)" + sh ./install.sh $(KERNELRELEASE) Image System.map "$(INSTALL_PATH)" zinstall: $(CONFIGURE) zImage - sh ./install.sh $(KERNELRELEASE) zImage $(TOPDIR)/System.map "$(INSTALL_PATH)" + sh ./install.sh $(KERNELRELEASE) zImage System.map "$(INSTALL_PATH)" # # miscellany # mrproper clean: - $(RM) Image zImage bootpImage # @$(MAKE) -C compressed clean # @$(MAKE) -C bootp clean diff --git a/arch/frv/defconfig b/arch/frv/defconfig index b6e4ca5efb5..b1b792610fd 100644 --- a/arch/frv/defconfig +++ b/arch/frv/defconfig @@ -1,627 +1,39 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.11.8 -# Fri May 13 17:16:03 2005 -# -CONFIG_FRV=y -CONFIG_UID16=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -# CONFIG_GENERIC_CALIBRATE_DELAY is not set -# CONFIG_GENERIC_HARDIRQS is not set - -# -# Code maturity level options -# CONFIG_EXPERIMENTAL=y -CONFIG_CLEAN_COMPILE=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# -CONFIG_LOCALVERSION="" -CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_AUDIT is not set -# CONFIG_HOTPLUG is not set -# CONFIG_KOBJECT_UEVENT is not set -# CONFIG_IKCONFIG is not set -CONFIG_EMBEDDED=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 - -# -# Loadable module support -# -# CONFIG_MODULES is not set - -# -# Fujitsu FR-V system setup -# +CONFIG_EXPERT=y +# CONFIG_HOTPLUG is not set CONFIG_MMU=y CONFIG_FRV_OUTOFLINE_ATOMIC_OPS=y -CONFIG_HIGHMEM=y -CONFIG_HIGHPTE=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_FRV_DEFL_CACHE_WBACK is not set -# CONFIG_FRV_DEFL_CACHE_WBEHIND is not set CONFIG_FRV_DEFL_CACHE_WTHRU=y -# CONFIG_FRV_DEFL_CACHE_DISABLED is not set - -# -# CPU core support -# -CONFIG_CPU_FR451=y -CONFIG_CPU_FR451_COMPILE=y -CONFIG_FRV_L1_CACHE_SHIFT=5 -CONFIG_MB93091_VDK=y -# CONFIG_MB93093_PDK is not set -CONFIG_MB93090_MB00=y -# CONFIG_MB93091_NO_MB is not set -# CONFIG_GPREL_DATA_8 is not set CONFIG_GPREL_DATA_4=y -# CONFIG_GPREL_DATA_NONE is not set -CONFIG_PCI=y -# CONFIG_PCI_LEGACY_PROC is not set -# CONFIG_PCI_NAMES is not set -# CONFIG_PCI_DEBUG is not set -# CONFIG_PCMCIA is not set - -# -# Power management options -# -# CONFIG_PM is not set - -# -# Executable formats -# -# CONFIG_BINFMT_ELF is not set -CONFIG_BINFMT_ELF_FDPIC=y -# CONFIG_BINFMT_MISC is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -# CONFIG_STANDALONE is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set - -# -# Connector - unified userspace <-> kernelspace linker -# -# CONFIG_CONNECTOR is not set -# CONFIG_FORK_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Plug and Play support -# - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set -# CONFIG_BLK_DEV_RAM is not set -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CDROM_PKTCDVD is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_ATA_OVER_ETH is not set - -# -# ATA/ATAPI/MFM/RLL support -# -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_SCSI is not set - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# Fusion MPT device support -# -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set - -# -# Networking support -# CONFIG_NET=y - -# -# Networking options -# CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y -# CONFIG_NET_KEY is not set CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set # CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_KGDBOE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NETPOLL_RX is not set -# CONFIG_NETPOLL_TRAP is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_IEEE80211 is not set +# CONFIG_STANDALONE is not set +# CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_NETDEVICES=y -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set - -# -# Ethernet (10 or 100Mbit) -# CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set - -# -# Tulip family network device support -# -# CONFIG_NET_TULIP is not set -# CONFIG_HP100 is not set CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_AMD8111_ETH is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_B44 is not set -# CONFIG_FORCEDETH is not set -# CONFIG_DGRS is not set -# CONFIG_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set CONFIG_NE2K_PCI=y -# CONFIG_8139CP is not set -# CONFIG_8139TOO is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SKGE is not set -# CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_TIGON3 is not set - -# -# Ethernet (10000 Mbit) -# -# CONFIG_CHELSIO_T1 is not set -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set - -# -# Input device support -# # CONFIG_INPUT is not set - -# -# Hardware I/O ports -# # CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# # CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 CONFIG_SERIAL_8250_EXTENDED=y -# CONFIG_SERIAL_8250_MANY_PORTS is not set CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_RSA is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Misc devices -# - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -# CONFIG_USB is not set - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# InfiniBand support -# -# CONFIG_INFINIBAND is not set - -# -# File systems -# -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_REISER4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set - -# -# XFS support -# -# CONFIG_XFS_FS is not set -# CONFIG_MINIX_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_INOTIFY=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set -# CONFIG_FUSE_FS is not set - -# -# CD-ROM/DVD Filesystems -# -# CONFIG_ISO9660_FS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y -# CONFIG_PROC_KCORE is not set -CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y -# CONFIG_TMPFS_XATTR is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Network File Systems -# CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -# CONFIG_NFS_V4 is not set -# CONFIG_NFS_DIRECTIO is not set -# CONFIG_NFSD is not set CONFIG_ROOT_NFS=y -CONFIG_LOCKD=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_RPCSEC_GSS_KRB5 is not set -# CONFIG_RPCSEC_GSS_SPKM3 is not set -# CONFIG_SMB_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y - -# -# Native Language Support -# -# CONFIG_NLS is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set CONFIG_DEBUG_KERNEL=y -# CONFIG_MAGIC_SYSRQ is not set -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_KOBJECT is not set -# CONFIG_DEBUG_HIGHMEM is not set # CONFIG_DEBUG_BUGVERBOSE is not set -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_FS is not set -# CONFIG_FRAME_POINTER is not set -# CONFIG_EARLY_PRINTK is not set CONFIG_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_PAGEALLOC is not set -# CONFIG_GDBSTUB is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set - -# -# Cryptographic options -# -# CONFIG_CRYPTO is not set - -# -# Hardware crypto devices -# - -# -# Library routines -# -# CONFIG_CRC_CCITT is not set -CONFIG_CRC32=y -# CONFIG_LIBCRC32C is not set diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild new file mode 100644 index 00000000000..87b95eb8aee --- /dev/null +++ b/arch/frv/include/asm/Kbuild @@ -0,0 +1,8 @@ + +generic-y += clkdev.h +generic-y += cputime.h +generic-y += exec.h +generic-y += hash.h +generic-y += mcs_spinlock.h +generic-y += preempt.h +generic-y += trace_clock.h diff --git a/arch/frv/include/asm/asm-offsets.h b/arch/frv/include/asm/asm-offsets.h new file mode 100644 index 00000000000..d370ee36a18 --- /dev/null +++ b/arch/frv/include/asm/asm-offsets.h @@ -0,0 +1 @@ +#include <generated/asm-offsets.h> diff --git a/arch/frv/include/asm/atomic.h b/arch/frv/include/asm/atomic.h new file mode 100644 index 00000000000..f6c3a169010 --- /dev/null +++ b/arch/frv/include/asm/atomic.h @@ -0,0 +1,200 @@ +/* atomic.h: atomic operation emulation for FR-V + * + * For an explanation of how atomic ops work in this arch, see: + * Documentation/frv/atomic-ops.txt + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_ATOMIC_H +#define _ASM_ATOMIC_H + +#include <linux/types.h> +#include <asm/spr-regs.h> +#include <asm/cmpxchg.h> +#include <asm/barrier.h> + +#ifdef CONFIG_SMP +#error not SMP safe +#endif + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + * + * We do not have SMP systems, so we don't have to deal with that. + */ + +#define ATOMIC_INIT(i) { (i) } +#define atomic_read(v) (*(volatile int *)&(v)->counter) +#define atomic_set(v, i) (((v)->counter) = (i)) + +#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS +static inline int atomic_add_return(int i, atomic_t *v) +{ + unsigned long val; + + asm("0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + " ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " add%I2 %1,%2,%1 \n" + " cst.p %1,%M0 ,cc3,#1 \n" + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ + " beq icc3,#0,0b \n" + : "+U"(v->counter), "=&r"(val) + : "NPr"(i) + : "memory", "cc7", "cc3", "icc3" + ); + + return val; +} + +static inline int atomic_sub_return(int i, atomic_t *v) +{ + unsigned long val; + + asm("0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + " ld.p %M0,%1 \n" /* LD.P/ORCR must be atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " sub%I2 %1,%2,%1 \n" + " cst.p %1,%M0 ,cc3,#1 \n" + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* clear ICC3.Z if store happens */ + " beq icc3,#0,0b \n" + : "+U"(v->counter), "=&r"(val) + : "NPr"(i) + : "memory", "cc7", "cc3", "icc3" + ); + + return val; +} + +#else + +extern int atomic_add_return(int i, atomic_t *v); +extern int atomic_sub_return(int i, atomic_t *v); + +#endif + +static inline int atomic_add_negative(int i, atomic_t *v) +{ + return atomic_add_return(i, v) < 0; +} + +static inline void atomic_add(int i, atomic_t *v) +{ + atomic_add_return(i, v); +} + +static inline void atomic_sub(int i, atomic_t *v) +{ + atomic_sub_return(i, v); +} + +static inline void atomic_inc(atomic_t *v) +{ + atomic_add_return(1, v); +} + +static inline void atomic_dec(atomic_t *v) +{ + atomic_sub_return(1, v); +} + +#define atomic_dec_return(v) atomic_sub_return(1, (v)) +#define atomic_inc_return(v) atomic_add_return(1, (v)) + +#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0) +#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0) +#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0) + +/* + * 64-bit atomic ops + */ +typedef struct { + volatile long long counter; +} atomic64_t; + +#define ATOMIC64_INIT(i) { (i) } + +static inline long long atomic64_read(atomic64_t *v) +{ + long long counter; + + asm("ldd%I1 %M1,%0" + : "=e"(counter) + : "m"(v->counter)); + return counter; +} + +static inline void atomic64_set(atomic64_t *v, long long i) +{ + asm volatile("std%I0 %1,%M0" + : "=m"(v->counter) + : "e"(i)); +} + +extern long long atomic64_inc_return(atomic64_t *v); +extern long long atomic64_dec_return(atomic64_t *v); +extern long long atomic64_add_return(long long i, atomic64_t *v); +extern long long atomic64_sub_return(long long i, atomic64_t *v); + +static inline long long atomic64_add_negative(long long i, atomic64_t *v) +{ + return atomic64_add_return(i, v) < 0; +} + +static inline void atomic64_add(long long i, atomic64_t *v) +{ + atomic64_add_return(i, v); +} + +static inline void atomic64_sub(long long i, atomic64_t *v) +{ + atomic64_sub_return(i, v); +} + +static inline void atomic64_inc(atomic64_t *v) +{ + atomic64_inc_return(v); +} + +static inline void atomic64_dec(atomic64_t *v) +{ + atomic64_dec_return(v); +} + +#define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0) +#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0) +#define atomic64_inc_and_test(v) (atomic64_inc_return((v)) == 0) + +#define atomic_cmpxchg(v, old, new) (cmpxchg(&(v)->counter, old, new)) +#define atomic_xchg(v, new) (xchg(&(v)->counter, new)) +#define atomic64_cmpxchg(v, old, new) (__cmpxchg_64(old, new, &(v)->counter)) +#define atomic64_xchg(v, new) (__xchg_64(new, &(v)->counter)) + +static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) +{ + int c, old; + c = atomic_read(v); + for (;;) { + if (unlikely(c == (u))) + break; + old = atomic_cmpxchg((v), c, c + (a)); + if (likely(old == c)) + break; + c = old; + } + return c; +} + + +#endif /* _ASM_ATOMIC_H */ diff --git a/arch/frv/include/asm/ax88796.h b/arch/frv/include/asm/ax88796.h new file mode 100644 index 00000000000..637e980393c --- /dev/null +++ b/arch/frv/include/asm/ax88796.h @@ -0,0 +1,22 @@ +/* ax88796.h: access points to the driver for the AX88796 NE2000 clone + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_AX88796_H +#define _ASM_AX88796_H + +#include <asm/mb-regs.h> + +#define AX88796_IOADDR (__region_CS1 + 0x200) +#define AX88796_IRQ IRQ_CPU_EXTERNAL7 +#define AX88796_FULL_DUPLEX 0 /* force full duplex */ +#define AX88796_BUS_INFO "CS1#+0x200" /* bus info for ethtool */ + +#endif /* _ASM_AX88796_H */ diff --git a/arch/frv/include/asm/barrier.h b/arch/frv/include/asm/barrier.h new file mode 100644 index 00000000000..abbef470154 --- /dev/null +++ b/arch/frv/include/asm/barrier.h @@ -0,0 +1,23 @@ +/* FR-V CPU memory barrier definitions + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_BARRIER_H +#define _ASM_BARRIER_H + +#define nop() asm volatile ("nop"::) + +#define mb() asm volatile ("membar" : : :"memory") +#define rmb() asm volatile ("membar" : : :"memory") +#define wmb() asm volatile ("membar" : : :"memory") + +#include <asm-generic/barrier.h> + +#endif /* _ASM_BARRIER_H */ diff --git a/arch/frv/include/asm/bitops.h b/arch/frv/include/asm/bitops.h new file mode 100644 index 00000000000..96de220ef13 --- /dev/null +++ b/arch/frv/include/asm/bitops.h @@ -0,0 +1,404 @@ +/* bitops.h: bit operations for the Fujitsu FR-V CPUs + * + * For an explanation of how atomic ops work in this arch, see: + * Documentation/frv/atomic-ops.txt + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_BITOPS_H +#define _ASM_BITOPS_H + +#include <linux/compiler.h> +#include <asm/byteorder.h> + +#ifdef __KERNEL__ + +#ifndef _LINUX_BITOPS_H +#error only <linux/bitops.h> can be included directly +#endif + +#include <asm-generic/bitops/ffz.h> + +#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS +static inline +unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v) +{ + unsigned long old, tmp; + + asm volatile( + "0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " and%I3 %1,%3,%2 \n" + " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */ + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */ + " beq icc3,#0,0b \n" + : "+U"(*v), "=&r"(old), "=r"(tmp) + : "NPr"(~mask) + : "memory", "cc7", "cc3", "icc3" + ); + + return old; +} + +static inline +unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v) +{ + unsigned long old, tmp; + + asm volatile( + "0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " or%I3 %1,%3,%2 \n" + " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */ + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */ + " beq icc3,#0,0b \n" + : "+U"(*v), "=&r"(old), "=r"(tmp) + : "NPr"(mask) + : "memory", "cc7", "cc3", "icc3" + ); + + return old; +} + +static inline +unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v) +{ + unsigned long old, tmp; + + asm volatile( + "0: \n" + " orcc gr0,gr0,gr0,icc3 \n" /* set ICC3.Z */ + " ckeq icc3,cc7 \n" + " ld.p %M0,%1 \n" /* LD.P/ORCR are atomic */ + " orcr cc7,cc7,cc3 \n" /* set CC3 to true */ + " xor%I3 %1,%3,%2 \n" + " cst.p %2,%M0 ,cc3,#1 \n" /* if store happens... */ + " corcc gr29,gr29,gr0 ,cc3,#1 \n" /* ... clear ICC3.Z */ + " beq icc3,#0,0b \n" + : "+U"(*v), "=&r"(old), "=r"(tmp) + : "NPr"(mask) + : "memory", "cc7", "cc3", "icc3" + ); + + return old; +} + +#else + +extern unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v); +extern unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v); +extern unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v); + +#endif + +#define atomic_clear_mask(mask, v) atomic_test_and_ANDNOT_mask((mask), (v)) +#define atomic_set_mask(mask, v) atomic_test_and_OR_mask((mask), (v)) + +static inline int test_and_clear_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *ptr = addr; + unsigned long mask = 1UL << (nr & 31); + ptr += nr >> 5; + return (atomic_test_and_ANDNOT_mask(mask, ptr) & mask) != 0; +} + +static inline int test_and_set_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *ptr = addr; + unsigned long mask = 1UL << (nr & 31); + ptr += nr >> 5; + return (atomic_test_and_OR_mask(mask, ptr) & mask) != 0; +} + +static inline int test_and_change_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *ptr = addr; + unsigned long mask = 1UL << (nr & 31); + ptr += nr >> 5; + return (atomic_test_and_XOR_mask(mask, ptr) & mask) != 0; +} + +static inline void clear_bit(unsigned long nr, volatile void *addr) +{ + test_and_clear_bit(nr, addr); +} + +static inline void set_bit(unsigned long nr, volatile void *addr) +{ + test_and_set_bit(nr, addr); +} + +static inline void change_bit(unsigned long nr, volatile void *addr) +{ + test_and_change_bit(nr, addr); +} + +static inline void __clear_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *a = addr; + int mask; + + a += nr >> 5; + mask = 1 << (nr & 31); + *a &= ~mask; +} + +static inline void __set_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *a = addr; + int mask; + + a += nr >> 5; + mask = 1 << (nr & 31); + *a |= mask; +} + +static inline void __change_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *a = addr; + int mask; + + a += nr >> 5; + mask = 1 << (nr & 31); + *a ^= mask; +} + +static inline int __test_and_clear_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *a = addr; + int mask, retval; + + a += nr >> 5; + mask = 1 << (nr & 31); + retval = (mask & *a) != 0; + *a &= ~mask; + return retval; +} + +static inline int __test_and_set_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *a = addr; + int mask, retval; + + a += nr >> 5; + mask = 1 << (nr & 31); + retval = (mask & *a) != 0; + *a |= mask; + return retval; +} + +static inline int __test_and_change_bit(unsigned long nr, volatile void *addr) +{ + volatile unsigned long *a = addr; + int mask, retval; + + a += nr >> 5; + mask = 1 << (nr & 31); + retval = (mask & *a) != 0; + *a ^= mask; + return retval; +} + +/* + * This routine doesn't need to be atomic. + */ +static inline int +__constant_test_bit(unsigned long nr, const volatile void *addr) +{ + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; +} + +static inline int __test_bit(unsigned long nr, const volatile void *addr) +{ + int * a = (int *) addr; + int mask; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + return ((mask & *a) != 0); +} + +#define test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + __constant_test_bit((nr),(addr)) : \ + __test_bit((nr),(addr))) + +#include <asm-generic/bitops/find.h> + +/** + * fls - find last bit set + * @x: the word to search + * + * This is defined the same way as ffs: + * - return 32..1 to indicate bit 31..0 most significant bit set + * - return 0 to indicate no bits set + */ +#define fls(x) \ +({ \ + int bit; \ + \ + asm(" subcc %1,gr0,gr0,icc0 \n" \ + " ckne icc0,cc4 \n" \ + " cscan.p %1,gr0,%0 ,cc4,#1 \n" \ + " csub %0,%0,%0 ,cc4,#0 \n" \ + " csub %2,%0,%0 ,cc4,#1 \n" \ + : "=&r"(bit) \ + : "r"(x), "r"(32) \ + : "icc0", "cc4" \ + ); \ + \ + bit; \ +}) + +/** + * fls64 - find last bit set in a 64-bit value + * @n: the value to search + * + * This is defined the same way as ffs: + * - return 64..1 to indicate bit 63..0 most significant bit set + * - return 0 to indicate no bits set + */ +static inline __attribute__((const)) +int fls64(u64 n) +{ + union { + u64 ll; + struct { u32 h, l; }; + } _; + int bit, x, y; + + _.ll = n; + + asm(" subcc.p %3,gr0,gr0,icc0 \n" + " subcc %4,gr0,gr0,icc1 \n" + " ckne icc0,cc4 \n" + " ckne icc1,cc5 \n" + " norcr cc4,cc5,cc6 \n" + " csub.p %0,%0,%0 ,cc6,1 \n" + " orcr cc5,cc4,cc4 \n" + " andcr cc4,cc5,cc4 \n" + " cscan.p %3,gr0,%0 ,cc4,0 \n" + " setlos #64,%1 \n" + " cscan.p %4,gr0,%0 ,cc4,1 \n" + " setlos #32,%2 \n" + " csub.p %1,%0,%0 ,cc4,0 \n" + " csub %2,%0,%0 ,cc4,1 \n" + : "=&r"(bit), "=r"(x), "=r"(y) + : "0r"(_.h), "r"(_.l) + : "icc0", "icc1", "cc4", "cc5", "cc6" + ); + return bit; + +} + +/** + * ffs - find first bit set + * @x: the word to search + * + * - return 32..1 to indicate bit 31..0 most least significant bit set + * - return 0 to indicate no bits set + */ +static inline __attribute__((const)) +int ffs(int x) +{ + /* Note: (x & -x) gives us a mask that is the least significant + * (rightmost) 1-bit of the value in x. + */ + return fls(x & -x); +} + +/** + * __ffs - find first bit set + * @x: the word to search + * + * - return 31..0 to indicate bit 31..0 most least significant bit set + * - if no bits are set in x, the result is undefined + */ +static inline __attribute__((const)) +int __ffs(unsigned long x) +{ + int bit; + asm("scan %1,gr0,%0" : "=r"(bit) : "r"(x & -x)); + return 31 - bit; +} + +/** + * __fls - find last (most-significant) set bit in a long word + * @word: the word to search + * + * Undefined if no set bit exists, so code should check against 0 first. + */ +static inline unsigned long __fls(unsigned long word) +{ + unsigned long bit; + asm("scan %1,gr0,%0" : "=r"(bit) : "r"(word)); + return bit; +} + +/* + * special slimline version of fls() for calculating ilog2_u32() + * - note: no protection against n == 0 + */ +#define ARCH_HAS_ILOG2_U32 +static inline __attribute__((const)) +int __ilog2_u32(u32 n) +{ + int bit; + asm("scan %1,gr0,%0" : "=r"(bit) : "r"(n)); + return 31 - bit; +} + +/* + * special slimline version of fls64() for calculating ilog2_u64() + * - note: no protection against n == 0 + */ +#define ARCH_HAS_ILOG2_U64 +static inline __attribute__((const)) +int __ilog2_u64(u64 n) +{ + union { + u64 ll; + struct { u32 h, l; }; + } _; + int bit, x, y; + + _.ll = n; + + asm(" subcc %3,gr0,gr0,icc0 \n" + " ckeq icc0,cc4 \n" + " cscan.p %3,gr0,%0 ,cc4,0 \n" + " setlos #63,%1 \n" + " cscan.p %4,gr0,%0 ,cc4,1 \n" + " setlos #31,%2 \n" + " csub.p %1,%0,%0 ,cc4,0 \n" + " csub %2,%0,%0 ,cc4,1 \n" + : "=&r"(bit), "=r"(x), "=r"(y) + : "0r"(_.h), "r"(_.l) + : "icc0", "cc4" + ); + return bit; +} + +#include <asm-generic/bitops/sched.h> +#include <asm-generic/bitops/hweight.h> +#include <asm-generic/bitops/lock.h> + +#include <asm-generic/bitops/le.h> + +#include <asm-generic/bitops/ext2-atomic-setbit.h> + +#endif /* __KERNEL__ */ + +#endif /* _ASM_BITOPS_H */ diff --git a/arch/frv/include/asm/bug.h b/arch/frv/include/asm/bug.h new file mode 100644 index 00000000000..dd01bcf42ee --- /dev/null +++ b/arch/frv/include/asm/bug.h @@ -0,0 +1,56 @@ +/* bug.h: FRV bug trapping + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_BUG_H +#define _ASM_BUG_H + +#include <linux/linkage.h> + +#ifdef CONFIG_BUG +/* + * Tell the user there is some problem. + */ +extern asmlinkage void __debug_bug_trap(int signr); + +#ifdef CONFIG_NO_KERNEL_MSG +#define _debug_bug_printk() +#else +extern void __debug_bug_printk(const char *file, unsigned line); +#define _debug_bug_printk() __debug_bug_printk(__FILE__, __LINE__) +#endif + +#define _debug_bug_trap(signr) \ +do { \ + __debug_bug_trap(signr); \ + asm volatile("nop"); \ +} while(1) + +#define HAVE_ARCH_BUG +#define BUG() \ +do { \ + _debug_bug_printk(); \ + _debug_bug_trap(6 /*SIGABRT*/); \ +} while (0) + +#ifdef CONFIG_GDBSTUB +#define HAVE_ARCH_KGDB_RAISE +#define kgdb_raise(signr) do { _debug_bug_trap(signr); } while(0) + +#define HAVE_ARCH_KGDB_BAD_PAGE +#define kgdb_bad_page(page) do { kgdb_raise(SIGABRT); } while(0) +#endif + +#endif /* CONFIG_BUG */ + +#include <asm-generic/bug.h> + +extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2))); + +#endif diff --git a/arch/frv/include/asm/bugs.h b/arch/frv/include/asm/bugs.h new file mode 100644 index 00000000000..f2382be2b46 --- /dev/null +++ b/arch/frv/include/asm/bugs.h @@ -0,0 +1,14 @@ +/* bugs.h: arch bug checking entry + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +static inline void check_bugs(void) +{ +} diff --git a/arch/frv/include/asm/busctl-regs.h b/arch/frv/include/asm/busctl-regs.h new file mode 100644 index 00000000000..bb0ff4816e2 --- /dev/null +++ b/arch/frv/include/asm/busctl-regs.h @@ -0,0 +1,41 @@ +/* busctl-regs.h: FR400-series CPU bus controller registers + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_BUSCTL_REGS_H +#define _ASM_BUSCTL_REGS_H + +/* bus controller registers */ +#define __get_LGCR() ({ *(volatile unsigned long *)(0xfe000010); }) +#define __get_LMAICR() ({ *(volatile unsigned long *)(0xfe000030); }) +#define __get_LEMBR() ({ *(volatile unsigned long *)(0xfe000040); }) +#define __get_LEMAM() ({ *(volatile unsigned long *)(0xfe000048); }) +#define __get_LCR(R) ({ *(volatile unsigned long *)(0xfe000100 + 8*(R)); }) +#define __get_LSBR(R) ({ *(volatile unsigned long *)(0xfe000c00 + 8*(R)); }) +#define __get_LSAM(R) ({ *(volatile unsigned long *)(0xfe000d00 + 8*(R)); }) + +#define __set_LGCR(V) do { *(volatile unsigned long *)(0xfe000010) = (V); } while(0) +#define __set_LMAICR(V) do { *(volatile unsigned long *)(0xfe000030) = (V); } while(0) +#define __set_LEMBR(V) do { *(volatile unsigned long *)(0xfe000040) = (V); } while(0) +#define __set_LEMAM(V) do { *(volatile unsigned long *)(0xfe000048) = (V); } while(0) +#define __set_LCR(R,V) do { *(volatile unsigned long *)(0xfe000100 + 8*(R)) = (V); } while(0) +#define __set_LSBR(R,V) do { *(volatile unsigned long *)(0xfe000c00 + 8*(R)) = (V); } while(0) +#define __set_LSAM(R,V) do { *(volatile unsigned long *)(0xfe000d00 + 8*(R)) = (V); } while(0) + +/* FR401 SDRAM controller registers */ +#define __get_DBR(R) ({ *(volatile unsigned long *)(0xfe000e00 + 8*(R)); }) +#define __get_DAM(R) ({ *(volatile unsigned long *)(0xfe000f00 + 8*(R)); }) + +/* FR551 SDRAM controller registers */ +#define __get_DARS(R) ({ *(volatile unsigned long *)(0xfeff0100 + 8*(R)); }) +#define __get_DAMK(R) ({ *(volatile unsigned long *)(0xfeff0110 + 8*(R)); }) + + +#endif /* _ASM_BUSCTL_REGS_H */ diff --git a/arch/frv/include/asm/cache.h b/arch/frv/include/asm/cache.h new file mode 100644 index 00000000000..2797163b8f4 --- /dev/null +++ b/arch/frv/include/asm/cache.h @@ -0,0 +1,23 @@ +/* cache.h: FRV cache definitions + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __ASM_CACHE_H +#define __ASM_CACHE_H + + +/* bytes per L1 cache line */ +#define L1_CACHE_SHIFT (CONFIG_FRV_L1_CACHE_SHIFT) +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#define __cacheline_aligned __attribute__((aligned(L1_CACHE_BYTES))) +#define ____cacheline_aligned __attribute__((aligned(L1_CACHE_BYTES))) + +#endif diff --git a/arch/frv/include/asm/cacheflush.h b/arch/frv/include/asm/cacheflush.h new file mode 100644 index 00000000000..edbac54ae01 --- /dev/null +++ b/arch/frv/include/asm/cacheflush.h @@ -0,0 +1,105 @@ +/* cacheflush.h: FRV cache flushing routines + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_CACHEFLUSH_H +#define _ASM_CACHEFLUSH_H + +/* Keep includes the same across arches. */ +#include <linux/mm.h> + +/* + * virtually-indexed cache management (our cache is physically indexed) + */ +#define flush_cache_all() do {} while(0) +#define flush_cache_mm(mm) do {} while(0) +#define flush_cache_dup_mm(mm) do {} while(0) +#define flush_cache_range(mm, start, end) do {} while(0) +#define flush_cache_page(vma, vmaddr, pfn) do {} while(0) +#define flush_cache_vmap(start, end) do {} while(0) +#define flush_cache_vunmap(start, end) do {} while(0) +#define flush_dcache_mmap_lock(mapping) do {} while(0) +#define flush_dcache_mmap_unlock(mapping) do {} while(0) + +/* + * physically-indexed cache management + * - see arch/frv/lib/cache.S + */ +extern void frv_dcache_writeback(unsigned long start, unsigned long size); +extern void frv_cache_invalidate(unsigned long start, unsigned long size); +extern void frv_icache_invalidate(unsigned long start, unsigned long size); +extern void frv_cache_wback_inv(unsigned long start, unsigned long size); + +static inline void __flush_cache_all(void) +{ + asm volatile(" dcef @(gr0,gr0),#1 \n" + " icei @(gr0,gr0),#1 \n" + " membar \n" + : : : "memory" + ); +} + +/* dcache/icache coherency... */ +#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 +#ifdef CONFIG_MMU +extern void flush_dcache_page(struct page *page); +#else +static inline void flush_dcache_page(struct page *page) +{ + unsigned long addr = page_to_phys(page); + frv_dcache_writeback(addr, addr + PAGE_SIZE); +} +#endif + +static inline void flush_page_to_ram(struct page *page) +{ + flush_dcache_page(page); +} + +static inline void flush_icache(void) +{ + __flush_cache_all(); +} + +static inline void flush_icache_range(unsigned long start, unsigned long end) +{ + frv_cache_wback_inv(start, end); +} + +#ifdef CONFIG_MMU +extern void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, + unsigned long start, unsigned long len); +#else +static inline void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, + unsigned long start, unsigned long len) +{ + frv_cache_wback_inv(start, start + len); +} +#endif + +static inline void flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + flush_icache_user_range(vma, page, page_to_phys(page), PAGE_SIZE); +} + +/* + * permit ptrace to access another process's address space through the icache + * and the dcache + */ +#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ +do { \ + memcpy((dst), (src), (len)); \ + flush_icache_user_range((vma), (page), (vaddr), (len)); \ +} while(0) + +#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ + memcpy((dst), (src), (len)) + +#endif /* _ASM_CACHEFLUSH_H */ diff --git a/arch/frv/include/asm/checksum.h b/arch/frv/include/asm/checksum.h new file mode 100644 index 00000000000..269da09ff63 --- /dev/null +++ b/arch/frv/include/asm/checksum.h @@ -0,0 +1,180 @@ +/* checksum.h: FRV checksumming + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_CHECKSUM_H +#define _ASM_CHECKSUM_H + +#include <linux/in6.h> + +/* + * computes the checksum of a memory block at buff, length len, + * and adds in "sum" (32-bit) + * + * returns a 32-bit number suitable for feeding into itself + * or csum_tcpudp_magic + * + * this function must be called with even lengths, except + * for the last fragment, which may be odd + * + * it's best to have buff aligned on a 32-bit boundary + */ +__wsum csum_partial(const void *buff, int len, __wsum sum); + +/* + * the same as csum_partial, but copies from src while it + * checksums + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ +__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum); + +/* + * the same as csum_partial_copy, but copies from user space. + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ +extern __wsum csum_partial_copy_from_user(const void __user *src, void *dst, + int len, __wsum sum, int *csum_err); + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + * + */ +static inline +__sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + unsigned int tmp, inc, sum = 0; + + asm(" addcc gr0,gr0,gr0,icc0\n" /* clear icc0.C */ + " subi %1,#4,%1 \n" + "0: \n" + " ldu.p @(%1,%3),%4 \n" + " subicc %2,#1,%2,icc1 \n" + " addxcc.p %4,%0,%0,icc0 \n" + " bhi icc1,#2,0b \n" + + /* fold the 33-bit result into 16-bits */ + " addxcc gr0,%0,%0,icc0 \n" + " srli %0,#16,%1 \n" + " sethi #0,%0 \n" + " add %1,%0,%0 \n" + " srli %0,#16,%1 \n" + " add %1,%0,%0 \n" + + : "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (inc), "=&r"(tmp) + : "0" (sum), "1" (iph), "2" (ihl), "3" (4), + "m"(*(volatile struct { int _[100]; } *)iph) + : "icc0", "icc1", "memory" + ); + + return (__force __sum16)~sum; +} + +/* + * Fold a partial checksum + */ +static inline __sum16 csum_fold(__wsum sum) +{ + unsigned int tmp; + + asm(" srli %0,#16,%1 \n" + " sethi #0,%0 \n" + " add %1,%0,%0 \n" + " srli %0,#16,%1 \n" + " add %1,%0,%0 \n" + : "=r"(sum), "=&r"(tmp) + : "0"(sum) + ); + + return (__force __sum16)~sum; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline __wsum +csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len, + unsigned short proto, __wsum sum) +{ + asm(" addcc %1,%0,%0,icc0 \n" + " addxcc %2,%0,%0,icc0 \n" + " addxcc %3,%0,%0,icc0 \n" + " addxcc gr0,%0,%0,icc0 \n" + : "=r" (sum) + : "r" (daddr), "r" (saddr), "r" (len + proto), "0"(sum) + : "icc0" + ); + return sum; +} + +static inline __sum16 +csum_tcpudp_magic(__be32 saddr, __be32 daddr, unsigned short len, + unsigned short proto, __wsum sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +extern __sum16 ip_compute_csum(const void *buff, int len); + +#define _HAVE_ARCH_IPV6_CSUM +static inline __sum16 +csum_ipv6_magic(const struct in6_addr *saddr, const struct in6_addr *daddr, + __u32 len, unsigned short proto, __wsum sum) +{ + unsigned long tmp, tmp2; + + asm(" addcc %2,%0,%0,icc0 \n" + + /* add up the source addr */ + " ldi @(%3,0),%1 \n" + " addxcc %1,%0,%0,icc0 \n" + " ldi @(%3,4),%2 \n" + " addxcc %2,%0,%0,icc0 \n" + " ldi @(%3,8),%1 \n" + " addxcc %1,%0,%0,icc0 \n" + " ldi @(%3,12),%2 \n" + " addxcc %2,%0,%0,icc0 \n" + + /* add up the dest addr */ + " ldi @(%4,0),%1 \n" + " addxcc %1,%0,%0,icc0 \n" + " ldi @(%4,4),%2 \n" + " addxcc %2,%0,%0,icc0 \n" + " ldi @(%4,8),%1 \n" + " addxcc %1,%0,%0,icc0 \n" + " ldi @(%4,12),%2 \n" + " addxcc %2,%0,%0,icc0 \n" + + /* fold the 33-bit result into 16-bits */ + " addxcc gr0,%0,%0,icc0 \n" + " srli %0,#16,%1 \n" + " sethi #0,%0 \n" + " add %1,%0,%0 \n" + " srli %0,#16,%1 \n" + " add %1,%0,%0 \n" + + : "=r" (sum), "=&r" (tmp), "=r" (tmp2) + : "r" (saddr), "r" (daddr), "0" (sum), "2" (len + proto) + : "icc0" + ); + + return (__force __sum16)~sum; +} + +#endif /* _ASM_CHECKSUM_H */ diff --git a/arch/frv/include/asm/cmpxchg.h b/arch/frv/include/asm/cmpxchg.h new file mode 100644 index 00000000000..5b04dd0aeca --- /dev/null +++ b/arch/frv/include/asm/cmpxchg.h @@ -0,0 +1,172 @@ +/* xchg and cmpxchg operation emulation for FR-V + * + * For an explanation of how atomic ops work in this arch, see: + * Documentation/frv/atomic-ops.txt + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_CMPXCHG_H +#define _ASM_CMPXCHG_H + +#include <linux/types.h> + +/*****************************************************************************/ +/* + * exchange value with memory + */ +extern uint64_t __xchg_64(uint64_t i, volatile void *v); + +#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS + +#define xchg(ptr, x) \ +({ \ + __typeof__(ptr) __xg_ptr = (ptr); \ + __typeof__(*(ptr)) __xg_orig; \ + \ + switch (sizeof(__xg_orig)) { \ + case 4: \ + asm volatile( \ + "swap%I0 %M0,%1" \ + : "+m"(*__xg_ptr), "=r"(__xg_orig) \ + : "1"(x) \ + : "memory" \ + ); \ + break; \ + \ + default: \ + __xg_orig = (__typeof__(__xg_orig))0; \ + asm volatile("break"); \ + break; \ + } \ + \ + __xg_orig; \ +}) + +#else + +extern uint32_t __xchg_32(uint32_t i, volatile void *v); + +#define xchg(ptr, x) \ +({ \ + __typeof__(ptr) __xg_ptr = (ptr); \ + __typeof__(*(ptr)) __xg_orig; \ + \ + switch (sizeof(__xg_orig)) { \ + case 4: __xg_orig = (__typeof__(*(ptr))) __xchg_32((uint32_t) x, __xg_ptr); break; \ + default: \ + __xg_orig = (__typeof__(__xg_orig))0; \ + asm volatile("break"); \ + break; \ + } \ + __xg_orig; \ +}) + +#endif + +#define tas(ptr) (xchg((ptr), 1)) + +/*****************************************************************************/ +/* + * compare and conditionally exchange value with memory + * - if (*ptr == test) then orig = *ptr; *ptr = test; + * - if (*ptr != test) then orig = *ptr; + */ +extern uint64_t __cmpxchg_64(uint64_t test, uint64_t new, volatile uint64_t *v); + +#ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS + +#define cmpxchg(ptr, test, new) \ +({ \ + __typeof__(ptr) __xg_ptr = (ptr); \ + __typeof__(*(ptr)) __xg_orig, __xg_tmp; \ + __typeof__(*(ptr)) __xg_test = (test); \ + __typeof__(*(ptr)) __xg_new = (new); \ + \ + switch (sizeof(__xg_orig)) { \ + case 4: \ + asm volatile( \ + "0: \n" \ + " orcc gr0,gr0,gr0,icc3 \n" \ + " ckeq icc3,cc7 \n" \ + " ld.p %M0,%1 \n" \ + " orcr cc7,cc7,cc3 \n" \ + " sub%I4cc %1,%4,%2,icc0 \n" \ + " bne icc0,#0,1f \n" \ + " cst.p %3,%M0 ,cc3,#1 \n" \ + " corcc gr29,gr29,gr0 ,cc3,#1 \n" \ + " beq icc3,#0,0b \n" \ + "1: \n" \ + : "+U"(*__xg_ptr), "=&r"(__xg_orig), "=&r"(__xg_tmp) \ + : "r"(__xg_new), "NPr"(__xg_test) \ + : "memory", "cc7", "cc3", "icc3", "icc0" \ + ); \ + break; \ + \ + default: \ + __xg_orig = (__typeof__(__xg_orig))0; \ + asm volatile("break"); \ + break; \ + } \ + \ + __xg_orig; \ +}) + +#else + +extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new); + +#define cmpxchg(ptr, test, new) \ +({ \ + __typeof__(ptr) __xg_ptr = (ptr); \ + __typeof__(*(ptr)) __xg_orig; \ + __typeof__(*(ptr)) __xg_test = (test); \ + __typeof__(*(ptr)) __xg_new = (new); \ + \ + switch (sizeof(__xg_orig)) { \ + case 4: __xg_orig = (__force __typeof__(*ptr)) \ + __cmpxchg_32((__force uint32_t *)__xg_ptr, \ + (__force uint32_t)__xg_test, \ + (__force uint32_t)__xg_new); break; \ + default: \ + __xg_orig = (__typeof__(__xg_orig))0; \ + asm volatile("break"); \ + break; \ + } \ + \ + __xg_orig; \ +}) + +#endif + +#include <asm-generic/cmpxchg-local.h> + +static inline unsigned long __cmpxchg_local(volatile void *ptr, + unsigned long old, + unsigned long new, int size) +{ + switch (size) { + case 4: + return cmpxchg((unsigned long *)ptr, old, new); + default: + return __cmpxchg_local_generic(ptr, old, new, size); + } + + return old; +} + +/* + * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make + * them available. + */ +#define cmpxchg_local(ptr, o, n) \ + ((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o), \ + (unsigned long)(n), sizeof(*(ptr)))) +#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) + +#endif /* _ASM_CMPXCHG_H */ diff --git a/arch/frv/include/asm/cpu-irqs.h b/arch/frv/include/asm/cpu-irqs.h new file mode 100644 index 00000000000..478f3498fcf --- /dev/null +++ b/arch/frv/include/asm/cpu-irqs.h @@ -0,0 +1,81 @@ +/* cpu-irqs.h: on-CPU peripheral irqs + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_CPU_IRQS_H +#define _ASM_CPU_IRQS_H + +#ifndef __ASSEMBLY__ + +/* IRQ to level mappings */ +#define IRQ_GDBSTUB_LEVEL 15 +#define IRQ_UART_LEVEL 13 + +#ifdef CONFIG_GDBSTUB_UART0 +#define IRQ_UART0_LEVEL IRQ_GDBSTUB_LEVEL +#else +#define IRQ_UART0_LEVEL IRQ_UART_LEVEL +#endif + +#ifdef CONFIG_GDBSTUB_UART1 +#define IRQ_UART1_LEVEL IRQ_GDBSTUB_LEVEL +#else +#define IRQ_UART1_LEVEL IRQ_UART_LEVEL +#endif + +#define IRQ_DMA0_LEVEL 14 +#define IRQ_DMA1_LEVEL 14 +#define IRQ_DMA2_LEVEL 14 +#define IRQ_DMA3_LEVEL 14 +#define IRQ_DMA4_LEVEL 14 +#define IRQ_DMA5_LEVEL 14 +#define IRQ_DMA6_LEVEL 14 +#define IRQ_DMA7_LEVEL 14 + +#define IRQ_TIMER0_LEVEL 12 +#define IRQ_TIMER1_LEVEL 11 +#define IRQ_TIMER2_LEVEL 10 + +#define IRQ_XIRQ0_LEVEL 1 +#define IRQ_XIRQ1_LEVEL 2 +#define IRQ_XIRQ2_LEVEL 3 +#define IRQ_XIRQ3_LEVEL 4 +#define IRQ_XIRQ4_LEVEL 5 +#define IRQ_XIRQ5_LEVEL 6 +#define IRQ_XIRQ6_LEVEL 7 +#define IRQ_XIRQ7_LEVEL 8 + +/* IRQ IDs presented to drivers */ +#define IRQ_CPU__UNUSED IRQ_BASE_CPU +#define IRQ_CPU_UART0 (IRQ_BASE_CPU + IRQ_UART0_LEVEL) +#define IRQ_CPU_UART1 (IRQ_BASE_CPU + IRQ_UART1_LEVEL) +#define IRQ_CPU_TIMER0 (IRQ_BASE_CPU + IRQ_TIMER0_LEVEL) +#define IRQ_CPU_TIMER1 (IRQ_BASE_CPU + IRQ_TIMER1_LEVEL) +#define IRQ_CPU_TIMER2 (IRQ_BASE_CPU + IRQ_TIMER2_LEVEL) +#define IRQ_CPU_DMA0 (IRQ_BASE_CPU + IRQ_DMA0_LEVEL) +#define IRQ_CPU_DMA1 (IRQ_BASE_CPU + IRQ_DMA1_LEVEL) +#define IRQ_CPU_DMA2 (IRQ_BASE_CPU + IRQ_DMA2_LEVEL) +#define IRQ_CPU_DMA3 (IRQ_BASE_CPU + IRQ_DMA3_LEVEL) +#define IRQ_CPU_DMA4 (IRQ_BASE_CPU + IRQ_DMA4_LEVEL) +#define IRQ_CPU_DMA5 (IRQ_BASE_CPU + IRQ_DMA5_LEVEL) +#define IRQ_CPU_DMA6 (IRQ_BASE_CPU + IRQ_DMA6_LEVEL) +#define IRQ_CPU_DMA7 (IRQ_BASE_CPU + IRQ_DMA7_LEVEL) +#define IRQ_CPU_EXTERNAL0 (IRQ_BASE_CPU + IRQ_XIRQ0_LEVEL) +#define IRQ_CPU_EXTERNAL1 (IRQ_BASE_CPU + IRQ_XIRQ1_LEVEL) +#define IRQ_CPU_EXTERNAL2 (IRQ_BASE_CPU + IRQ_XIRQ2_LEVEL) +#define IRQ_CPU_EXTERNAL3 (IRQ_BASE_CPU + IRQ_XIRQ3_LEVEL) +#define IRQ_CPU_EXTERNAL4 (IRQ_BASE_CPU + IRQ_XIRQ4_LEVEL) +#define IRQ_CPU_EXTERNAL5 (IRQ_BASE_CPU + IRQ_XIRQ5_LEVEL) +#define IRQ_CPU_EXTERNAL6 (IRQ_BASE_CPU + IRQ_XIRQ6_LEVEL) +#define IRQ_CPU_EXTERNAL7 (IRQ_BASE_CPU + IRQ_XIRQ7_LEVEL) + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_CPU_IRQS_H */ diff --git a/arch/frv/include/asm/current.h b/arch/frv/include/asm/current.h new file mode 100644 index 00000000000..86b027491b0 --- /dev/null +++ b/arch/frv/include/asm/current.h @@ -0,0 +1,30 @@ +/* current.h: FRV current task pointer + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_CURRENT_H +#define _ASM_CURRENT_H + +#ifndef __ASSEMBLY__ + +/* + * dedicate GR29 to keeping the current task pointer + */ +register struct task_struct *current asm("gr29"); + +#define get_current() current + +#else + +#define CURRENT gr29 + +#endif + +#endif /* _ASM_CURRENT_H */ diff --git a/arch/frv/include/asm/delay.h b/arch/frv/include/asm/delay.h new file mode 100644 index 00000000000..597b4ebf03b --- /dev/null +++ b/arch/frv/include/asm/delay.h @@ -0,0 +1,50 @@ +/* delay.h: FRV delay code + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_DELAY_H +#define _ASM_DELAY_H + +#include <asm/param.h> +#include <asm/timer-regs.h> + +/* + * delay loop - runs at __core_clock_speed_HZ / 2 [there are 2 insns in the loop] + */ +extern unsigned long __delay_loops_MHz; + +static inline void __delay(unsigned long loops) +{ + asm volatile("1: subicc %0,#1,%0,icc0 \n" + " bnc icc0,#2,1b \n" + : "=r" (loops) + : "0" (loops) + : "icc0" + ); +} + +/* + * Use only for very small delays ( < 1 msec). Should probably use a + * lookup table, really, as the multiplications take much too long with + * short delays. This is a "reasonable" implementation, though (and the + * first constant multiplications gets optimized away if the delay is + * a constant) + */ + +extern unsigned long loops_per_jiffy; + +static inline void udelay(unsigned long usecs) +{ + __delay(usecs * __delay_loops_MHz); +} + +#define ndelay(n) udelay((n) * 5) + +#endif /* _ASM_DELAY_H */ diff --git a/arch/frv/include/asm/device.h b/arch/frv/include/asm/device.h new file mode 100644 index 00000000000..d8f9872b0e2 --- /dev/null +++ b/arch/frv/include/asm/device.h @@ -0,0 +1,7 @@ +/* + * Arch specific extensions to struct device + * + * This file is released under the GPLv2 + */ +#include <asm-generic/device.h> + diff --git a/arch/frv/include/asm/div64.h b/arch/frv/include/asm/div64.h new file mode 100644 index 00000000000..6cd978cefb2 --- /dev/null +++ b/arch/frv/include/asm/div64.h @@ -0,0 +1 @@ +#include <asm-generic/div64.h> diff --git a/arch/frv/include/asm/dm9000.h b/arch/frv/include/asm/dm9000.h new file mode 100644 index 00000000000..f6f48fd9ec6 --- /dev/null +++ b/arch/frv/include/asm/dm9000.h @@ -0,0 +1,37 @@ +/* dm9000.h: Davicom DM9000 adapter configuration + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_DM9000_H +#define _ASM_DM9000_H + +#include <asm/mb-regs.h> + +#define DM9000_ARCH_IOBASE (__region_CS6 + 0x300) +#define DM9000_ARCH_IRQ IRQ_CPU_EXTERNAL3 /* XIRQ #3 (shared with FPGA) */ +#undef DM9000_ARCH_IRQ_ACTLOW /* IRQ pin active high */ +#define DM9000_ARCH_BUS_INFO "CS6#+0x300" /* bus info for ethtool */ + +#undef __is_PCI_IO +#define __is_PCI_IO(addr) 0 /* not PCI */ + +#undef inl +#define inl(addr) \ +({ \ + unsigned long __ioaddr = (unsigned long) addr; \ + uint32_t x = readl(__ioaddr); \ + ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff); \ +}) + +#undef insl +#define insl(a,b,l) __insl(a,b,l,0) /* don't byte-swap */ + + +#endif /* _ASM_DM9000_H */ diff --git a/arch/frv/include/asm/dma-mapping.h b/arch/frv/include/asm/dma-mapping.h new file mode 100644 index 00000000000..1746a2b8e6e --- /dev/null +++ b/arch/frv/include/asm/dma-mapping.h @@ -0,0 +1,150 @@ +#ifndef _ASM_DMA_MAPPING_H +#define _ASM_DMA_MAPPING_H + +#include <linux/device.h> +#include <asm/cache.h> +#include <asm/cacheflush.h> +#include <asm/scatterlist.h> +#include <asm/io.h> + +/* + * See Documentation/DMA-API.txt for the description of how the + * following DMA API should work. + */ + +#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) + +extern unsigned long __nongprelbss dma_coherent_mem_start; +extern unsigned long __nongprelbss dma_coherent_mem_end; + +void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t gfp); +void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle); + +extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, + enum dma_data_direction direction); + +static inline +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction); + +static inline +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + +extern +dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, + size_t size, enum dma_data_direction direction); + +static inline +void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); +} + + +static inline +void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ +} + +static inline +void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + flush_write_buffers(); +} + +static inline +void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ +} + +static inline +void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + flush_write_buffers(); +} + +static inline +void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ +} + +static inline +void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + flush_write_buffers(); +} + +static inline +int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ + return 0; +} + +static inline +int dma_supported(struct device *dev, u64 mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA.. + */ + if (mask < 0x00ffffff) + return 0; + + return 1; +} + +static inline +int dma_set_mask(struct device *dev, u64 mask) +{ + if (!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + + *dev->dma_mask = mask; + + return 0; +} + +static inline +void dma_cache_sync(struct device *dev, void *vaddr, size_t size, + enum dma_data_direction direction) +{ + flush_write_buffers(); +} + +/* Not supported for now */ +static inline int dma_mmap_coherent(struct device *dev, + struct vm_area_struct *vma, void *cpu_addr, + dma_addr_t dma_addr, size_t size) +{ + return -EINVAL; +} + +static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt, + void *cpu_addr, dma_addr_t dma_addr, + size_t size) +{ + return -EINVAL; +} + +#endif /* _ASM_DMA_MAPPING_H */ diff --git a/arch/frv/include/asm/dma.h b/arch/frv/include/asm/dma.h new file mode 100644 index 00000000000..683c47d48a5 --- /dev/null +++ b/arch/frv/include/asm/dma.h @@ -0,0 +1,125 @@ +/* dma.h: FRV DMA controller management + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_DMA_H +#define _ASM_DMA_H + +//#define DMA_DEBUG 1 + +#include <linux/interrupt.h> + +#undef MAX_DMA_CHANNELS /* don't use kernel/dma.c */ + +/* under 2.4 this is actually needed by the new bootmem allocator */ +#define MAX_DMA_ADDRESS PAGE_OFFSET + +/* + * FRV DMA controller management + */ +typedef irqreturn_t (*dma_irq_handler_t)(int dmachan, unsigned long cstr, void *data); + +extern void frv_dma_init(void); + +extern int frv_dma_open(const char *devname, + unsigned long dmamask, + int dmacap, + dma_irq_handler_t handler, + unsigned long irq_flags, + void *data); + +/* channels required */ +#define FRV_DMA_MASK_ANY ULONG_MAX /* any channel */ + +/* capabilities required */ +#define FRV_DMA_CAP_DREQ 0x01 /* DMA request pin */ +#define FRV_DMA_CAP_DACK 0x02 /* DMA ACK pin */ +#define FRV_DMA_CAP_DONE 0x04 /* DMA done pin */ + +extern void frv_dma_close(int dma); + +extern void frv_dma_config(int dma, unsigned long ccfr, unsigned long cctr, unsigned long apr); + +extern void frv_dma_start(int dma, + unsigned long sba, unsigned long dba, + unsigned long pix, unsigned long six, unsigned long bcl); + +extern void frv_dma_restart_circular(int dma, unsigned long six); + +extern void frv_dma_stop(int dma); + +extern int is_frv_dma_interrupting(int dma); + +extern void frv_dma_dump(int dma); + +extern void frv_dma_status_clear(int dma); + +#define FRV_DMA_NCHANS 8 +#define FRV_DMA_4CHANS 4 +#define FRV_DMA_8CHANS 8 + +#define DMAC_CCFRx 0x00 /* channel configuration reg */ +#define DMAC_CCFRx_CM_SHIFT 16 +#define DMAC_CCFRx_CM_DA 0x00000000 +#define DMAC_CCFRx_CM_SCA 0x00010000 +#define DMAC_CCFRx_CM_DCA 0x00020000 +#define DMAC_CCFRx_CM_2D 0x00030000 +#define DMAC_CCFRx_ATS_SHIFT 8 +#define DMAC_CCFRx_RS_INTERN 0x00000000 +#define DMAC_CCFRx_RS_EXTERN 0x00000001 +#define DMAC_CCFRx_RS_SHIFT 0 + +#define DMAC_CSTRx 0x08 /* channel status reg */ +#define DMAC_CSTRx_FS 0x0000003f +#define DMAC_CSTRx_NE 0x00000100 +#define DMAC_CSTRx_FED 0x00000200 +#define DMAC_CSTRx_WER 0x00000800 +#define DMAC_CSTRx_RER 0x00001000 +#define DMAC_CSTRx_CE 0x00002000 +#define DMAC_CSTRx_INT 0x00800000 +#define DMAC_CSTRx_BUSY 0x80000000 + +#define DMAC_CCTRx 0x10 /* channel control reg */ +#define DMAC_CCTRx_DSIZ_1 0x00000000 +#define DMAC_CCTRx_DSIZ_2 0x00000001 +#define DMAC_CCTRx_DSIZ_4 0x00000002 +#define DMAC_CCTRx_DSIZ_32 0x00000005 +#define DMAC_CCTRx_DAU_HOLD 0x00000000 +#define DMAC_CCTRx_DAU_INC 0x00000010 +#define DMAC_CCTRx_DAU_DEC 0x00000020 +#define DMAC_CCTRx_SSIZ_1 0x00000000 +#define DMAC_CCTRx_SSIZ_2 0x00000100 +#define DMAC_CCTRx_SSIZ_4 0x00000200 +#define DMAC_CCTRx_SSIZ_32 0x00000500 +#define DMAC_CCTRx_SAU_HOLD 0x00000000 +#define DMAC_CCTRx_SAU_INC 0x00001000 +#define DMAC_CCTRx_SAU_DEC 0x00002000 +#define DMAC_CCTRx_FC 0x08000000 +#define DMAC_CCTRx_ICE 0x10000000 +#define DMAC_CCTRx_IE 0x40000000 +#define DMAC_CCTRx_ACT 0x80000000 + +#define DMAC_SBAx 0x18 /* source base address reg */ +#define DMAC_DBAx 0x20 /* data base address reg */ +#define DMAC_PIXx 0x28 /* primary index reg */ +#define DMAC_SIXx 0x30 /* secondary index reg */ +#define DMAC_BCLx 0x38 /* byte count limit reg */ +#define DMAC_APRx 0x40 /* alternate pointer reg */ + +/* + * required for PCI + MODULES + */ +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy (0) +#endif + +#endif /* _ASM_DMA_H */ diff --git a/arch/frv/include/asm/elf.h b/arch/frv/include/asm/elf.h new file mode 100644 index 00000000000..2bac6446db4 --- /dev/null +++ b/arch/frv/include/asm/elf.h @@ -0,0 +1,140 @@ +/* elf.h: FR-V ELF definitions + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * - Derived from include/asm-m68knommu/elf.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef __ASM_ELF_H +#define __ASM_ELF_H + +#include <asm/ptrace.h> +#include <asm/user.h> + +struct elf32_hdr; + +/* + * ELF header e_flags defines. + */ +#define EF_FRV_GPR_MASK 0x00000003 /* mask for # of gprs */ +#define EF_FRV_GPR32 0x00000001 /* Only uses GR on 32-register */ +#define EF_FRV_GPR64 0x00000002 /* Only uses GR on 64-register */ +#define EF_FRV_FPR_MASK 0x0000000c /* mask for # of fprs */ +#define EF_FRV_FPR32 0x00000004 /* Only uses FR on 32-register */ +#define EF_FRV_FPR64 0x00000008 /* Only uses FR on 64-register */ +#define EF_FRV_FPR_NONE 0x0000000C /* Uses software floating-point */ +#define EF_FRV_DWORD_MASK 0x00000030 /* mask for dword support */ +#define EF_FRV_DWORD_YES 0x00000010 /* Assumes stack aligned to 8-byte boundaries. */ +#define EF_FRV_DWORD_NO 0x00000020 /* Assumes stack aligned to 4-byte boundaries. */ +#define EF_FRV_DOUBLE 0x00000040 /* Uses double instructions. */ +#define EF_FRV_MEDIA 0x00000080 /* Uses media instructions. */ +#define EF_FRV_PIC 0x00000100 /* Uses position independent code. */ +#define EF_FRV_NON_PIC_RELOCS 0x00000200 /* Does not use position Independent code. */ +#define EF_FRV_MULADD 0x00000400 /* -mmuladd */ +#define EF_FRV_BIGPIC 0x00000800 /* -fPIC */ +#define EF_FRV_LIBPIC 0x00001000 /* -mlibrary-pic */ +#define EF_FRV_G0 0x00002000 /* -G 0, no small data ptr */ +#define EF_FRV_NOPACK 0x00004000 /* -mnopack */ +#define EF_FRV_FDPIC 0x00008000 /* -mfdpic */ +#define EF_FRV_CPU_MASK 0xff000000 /* specific cpu bits */ +#define EF_FRV_CPU_GENERIC 0x00000000 /* Set CPU type is FR-V */ +#define EF_FRV_CPU_FR500 0x01000000 /* Set CPU type is FR500 */ +#define EF_FRV_CPU_FR300 0x02000000 /* Set CPU type is FR300 */ +#define EF_FRV_CPU_SIMPLE 0x03000000 /* SIMPLE */ +#define EF_FRV_CPU_TOMCAT 0x04000000 /* Tomcat, FR500 prototype */ +#define EF_FRV_CPU_FR400 0x05000000 /* Set CPU type is FR400 */ +#define EF_FRV_CPU_FR550 0x06000000 /* Set CPU type is FR550 */ +#define EF_FRV_CPU_FR405 0x07000000 /* Set CPU type is FR405 */ +#define EF_FRV_CPU_FR450 0x08000000 /* Set CPU type is FR450 */ + +/* + * FR-V ELF relocation types + */ + + +/* + * ELF register definitions.. + */ +typedef unsigned long elf_greg_t; + +#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct user_fpmedia_regs elf_fpregset_t; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +extern int elf_check_arch(const struct elf32_hdr *hdr); + +#define elf_check_fdpic(x) ((x)->e_flags & EF_FRV_FDPIC && !((x)->e_flags & EF_FRV_NON_PIC_RELOCS)) +#define elf_check_const_displacement(x) ((x)->e_flags & EF_FRV_PIC) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_FRV + +#define ELF_PLAT_INIT(_r) \ +do { \ + __kernel_frame0_ptr->gr16 = 0; \ + __kernel_frame0_ptr->gr17 = 0; \ + __kernel_frame0_ptr->gr18 = 0; \ + __kernel_frame0_ptr->gr19 = 0; \ + __kernel_frame0_ptr->gr20 = 0; \ + __kernel_frame0_ptr->gr21 = 0; \ + __kernel_frame0_ptr->gr22 = 0; \ + __kernel_frame0_ptr->gr23 = 0; \ + __kernel_frame0_ptr->gr24 = 0; \ + __kernel_frame0_ptr->gr25 = 0; \ + __kernel_frame0_ptr->gr26 = 0; \ + __kernel_frame0_ptr->gr27 = 0; \ + __kernel_frame0_ptr->gr29 = 0; \ +} while(0) + +#define ELF_FDPIC_PLAT_INIT(_regs, _exec_map_addr, _interp_map_addr, _dynamic_addr) \ +do { \ + __kernel_frame0_ptr->gr16 = _exec_map_addr; \ + __kernel_frame0_ptr->gr17 = _interp_map_addr; \ + __kernel_frame0_ptr->gr18 = _dynamic_addr; \ + __kernel_frame0_ptr->gr19 = 0; \ + __kernel_frame0_ptr->gr20 = 0; \ + __kernel_frame0_ptr->gr21 = 0; \ + __kernel_frame0_ptr->gr22 = 0; \ + __kernel_frame0_ptr->gr23 = 0; \ + __kernel_frame0_ptr->gr24 = 0; \ + __kernel_frame0_ptr->gr25 = 0; \ + __kernel_frame0_ptr->gr26 = 0; \ + __kernel_frame0_ptr->gr27 = 0; \ + __kernel_frame0_ptr->gr29 = 0; \ +} while(0) + +#define CORE_DUMP_USE_REGSET +#define ELF_FDPIC_CORE_EFLAGS EF_FRV_FDPIC +#define ELF_EXEC_PAGESIZE 16384 + +/* This is the location that an ET_DYN program is loaded if exec'ed. Typical + use of this is to invoke "./ld.so someprog" to test out a new version of + the loader. We need to make sure that it is out of the way of the program + that it will "exec", and that there is sufficient room for the brk. */ + +#define ELF_ET_DYN_BASE 0x08000000UL + +/* This yields a mask that user programs can use to figure out what + instruction set this cpu supports. */ + +#define ELF_HWCAP (0) + +/* This yields a string that ld.so will use to load implementation + specific libraries for optimization. This is more specific in + intent than poking at uname or /proc/cpuinfo. */ + +#define ELF_PLATFORM (NULL) + +#endif diff --git a/arch/frv/include/asm/emergency-restart.h b/arch/frv/include/asm/emergency-restart.h new file mode 100644 index 00000000000..108d8c48e42 --- /dev/null +++ b/arch/frv/include/asm/emergency-restart.h @@ -0,0 +1,6 @@ +#ifndef _ASM_EMERGENCY_RESTART_H +#define _ASM_EMERGENCY_RESTART_H + +#include <asm-generic/emergency-restart.h> + +#endif /* _ASM_EMERGENCY_RESTART_H */ diff --git a/arch/frv/include/asm/fb.h b/arch/frv/include/asm/fb.h new file mode 100644 index 00000000000..c7df3803099 --- /dev/null +++ b/arch/frv/include/asm/fb.h @@ -0,0 +1,12 @@ +#ifndef _ASM_FB_H_ +#define _ASM_FB_H_ +#include <linux/fb.h> + +#define fb_pgprotect(...) do {} while (0) + +static inline int fb_is_primary_device(struct fb_info *info) +{ + return 0; +} + +#endif /* _ASM_FB_H_ */ diff --git a/arch/frv/include/asm/fpu.h b/arch/frv/include/asm/fpu.h new file mode 100644 index 00000000000..d73c60b5664 --- /dev/null +++ b/arch/frv/include/asm/fpu.h @@ -0,0 +1,11 @@ +#ifndef __ASM_FPU_H +#define __ASM_FPU_H + + +/* + * MAX floating point unit state size (FSAVE/FRESTORE) + */ + +#define kernel_fpu_end() do { asm volatile("bar":::"memory"); preempt_enable(); } while(0) + +#endif /* __ASM_FPU_H */ diff --git a/arch/frv/include/asm/ftrace.h b/arch/frv/include/asm/ftrace.h new file mode 100644 index 00000000000..40a8c178f10 --- /dev/null +++ b/arch/frv/include/asm/ftrace.h @@ -0,0 +1 @@ +/* empty */ diff --git a/arch/frv/include/asm/futex.h b/arch/frv/include/asm/futex.h new file mode 100644 index 00000000000..4bea27f50a7 --- /dev/null +++ b/arch/frv/include/asm/futex.h @@ -0,0 +1,20 @@ +#ifndef _ASM_FUTEX_H +#define _ASM_FUTEX_H + +#ifdef __KERNEL__ + +#include <linux/futex.h> +#include <asm/errno.h> +#include <asm/uaccess.h> + +extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr); + +static inline int +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, + u32 oldval, u32 newval) +{ + return -ENOSYS; +} + +#endif +#endif diff --git a/arch/frv/include/asm/gdb-stub.h b/arch/frv/include/asm/gdb-stub.h new file mode 100644 index 00000000000..e6bedd0cd9a --- /dev/null +++ b/arch/frv/include/asm/gdb-stub.h @@ -0,0 +1,146 @@ +/* gdb-stub.h: FRV GDB stub + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * - Derived from asm-mips/gdb-stub.h (c) 1995 Andreas Busse + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef __ASM_GDB_STUB_H +#define __ASM_GDB_STUB_H + +#undef GDBSTUB_DEBUG_IO +#undef GDBSTUB_DEBUG_PROTOCOL + +#include <asm/ptrace.h> + +/* + * important register numbers in GDB protocol + * - GR0, GR1, GR2, GR3, GR4, GR5, GR6, GR7, + * - GR8, GR9, GR10, GR11, GR12, GR13, GR14, GR15, + * - GR16, GR17, GR18, GR19, GR20, GR21, GR22, GR23, + * - GR24, GR25, GR26, GR27, GR28, GR29, GR30, GR31, + * - GR32, GR33, GR34, GR35, GR36, GR37, GR38, GR39, + * - GR40, GR41, GR42, GR43, GR44, GR45, GR46, GR47, + * - GR48, GR49, GR50, GR51, GR52, GR53, GR54, GR55, + * - GR56, GR57, GR58, GR59, GR60, GR61, GR62, GR63, + * - FR0, FR1, FR2, FR3, FR4, FR5, FR6, FR7, + * - FR8, FR9, FR10, FR11, FR12, FR13, FR14, FR15, + * - FR16, FR17, FR18, FR19, FR20, FR21, FR22, FR23, + * - FR24, FR25, FR26, FR27, FR28, FR29, FR30, FR31, + * - FR32, FR33, FR34, FR35, FR36, FR37, FR38, FR39, + * - FR40, FR41, FR42, FR43, FR44, FR45, FR46, FR47, + * - FR48, FR49, FR50, FR51, FR52, FR53, FR54, FR55, + * - FR56, FR57, FR58, FR59, FR60, FR61, FR62, FR63, + * - PC, PSR, CCR, CCCR, + * - _X132, _X133, _X134 + * - TBR, BRR, DBAR0, DBAR1, DBAR2, DBAR3, + * - SCR0, SCR1, SCR2, SCR3, + * - LR, LCR, + * - IACC0H, IACC0L, + * - FSR0, + * - ACC0, ACC1, ACC2, ACC3, ACC4, ACC5, ACC6, ACC7, + * - ACCG0123, ACCG4567, + * - MSR0, MSR1, + * - GNER0, GNER1, + * - FNER0, FNER1, + */ +#define GDB_REG_GR(N) (N) +#define GDB_REG_FR(N) (64+(N)) +#define GDB_REG_PC 128 +#define GDB_REG_PSR 129 +#define GDB_REG_CCR 130 +#define GDB_REG_CCCR 131 +#define GDB_REG_TBR 135 +#define GDB_REG_BRR 136 +#define GDB_REG_DBAR(N) (137+(N)) +#define GDB_REG_SCR(N) (141+(N)) +#define GDB_REG_LR 145 +#define GDB_REG_LCR 146 +#define GDB_REG_FSR0 149 +#define GDB_REG_ACC(N) (150+(N)) +#define GDB_REG_ACCG(N) (158+(N)/4) +#define GDB_REG_MSR(N) (160+(N)) +#define GDB_REG_GNER(N) (162+(N)) +#define GDB_REG_FNER(N) (164+(N)) + +#define GDB_REG_SP GDB_REG_GR(1) +#define GDB_REG_FP GDB_REG_GR(2) + +#ifndef _LANGUAGE_ASSEMBLY + +/* + * Prototypes + */ +extern void show_registers_only(struct pt_regs *regs); + +extern void gdbstub_init(void); +extern void gdbstub(int type); +extern void gdbstub_exit(int status); + +extern void gdbstub_io_init(void); +extern void gdbstub_set_baud(unsigned baud); +extern int gdbstub_rx_char(unsigned char *_ch, int nonblock); +extern void gdbstub_tx_char(unsigned char ch); +extern void gdbstub_tx_flush(void); +extern void gdbstub_do_rx(void); + +extern asmlinkage void __debug_stub_init_break(void); +extern asmlinkage void __break_hijack_kernel_event(void); +extern asmlinkage void __break_hijack_kernel_event_breaks_here(void); + +extern asmlinkage void gdbstub_rx_handler(void); +extern asmlinkage void gdbstub_rx_irq(void); +extern asmlinkage void gdbstub_intercept(void); + +extern uint32_t __entry_usertrap_table[]; +extern uint32_t __entry_kerneltrap_table[]; + +extern volatile u8 gdbstub_rx_buffer[PAGE_SIZE]; +extern volatile u32 gdbstub_rx_inp; +extern volatile u32 gdbstub_rx_outp; +extern volatile u8 gdbstub_rx_overflow; +extern u8 gdbstub_rx_unget; + +extern void gdbstub_printk(const char *fmt, ...); +extern void debug_to_serial(const char *p, int n); +extern void console_set_baud(unsigned baud); + +#ifdef GDBSTUB_DEBUG_IO +#define gdbstub_io(FMT,...) gdbstub_printk(FMT, ##__VA_ARGS__) +#else +#define gdbstub_io(FMT,...) ({ 0; }) +#endif + +#ifdef GDBSTUB_DEBUG_PROTOCOL +#define gdbstub_proto(FMT,...) gdbstub_printk(FMT,##__VA_ARGS__) +#else +#define gdbstub_proto(FMT,...) ({ 0; }) +#endif + +/* + * we dedicate GR31 to keeping a pointer to the gdbstub exception frame + * - gr31 is destroyed on entry to the gdbstub if !MMU + * - gr31 is saved in scr3 on entry to the gdbstub if in !MMU + */ +register struct frv_frame0 *__debug_frame0 asm("gr31"); + +#define __debug_frame (&__debug_frame0->regs) +#define __debug_user_context (&__debug_frame0->uc) +#define __debug_regs (&__debug_frame0->debug) +#define __debug_reg(X) ((unsigned long *) ((unsigned long) &__debug_frame0 + (X))) + +struct frv_debug_status { + unsigned long bpsr; + unsigned long dcr; + unsigned long brr; + unsigned long nmar; +}; + +extern struct frv_debug_status __debug_status; + +#endif /* _LANGUAGE_ASSEMBLY */ +#endif /* __ASM_GDB_STUB_H */ diff --git a/arch/frv/include/asm/gpio-regs.h b/arch/frv/include/asm/gpio-regs.h new file mode 100644 index 00000000000..9edf5d5d4d3 --- /dev/null +++ b/arch/frv/include/asm/gpio-regs.h @@ -0,0 +1,116 @@ +/* gpio-regs.h: on-chip general purpose I/O registers + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_GPIO_REGS +#define _ASM_GPIO_REGS + +#define __reg(ADDR) (*(volatile unsigned long *)(ADDR)) + +#define __get_PDR() ({ __reg(0xfeff0400); }) +#define __set_PDR(V) do { __reg(0xfeff0400) = (V); mb(); } while(0) + +#define __get_GPDR() ({ __reg(0xfeff0408); }) +#define __set_GPDR(V) do { __reg(0xfeff0408) = (V); mb(); } while(0) + +#define __get_SIR() ({ __reg(0xfeff0410); }) +#define __set_SIR(V) do { __reg(0xfeff0410) = (V); mb(); } while(0) + +#define __get_SOR() ({ __reg(0xfeff0418); }) +#define __set_SOR(V) do { __reg(0xfeff0418) = (V); mb(); } while(0) + +#define __set_PDSR(V) do { __reg(0xfeff0420) = (V); mb(); } while(0) + +#define __set_PDCR(V) do { __reg(0xfeff0428) = (V); mb(); } while(0) + +#define __get_RSTR() ({ __reg(0xfeff0500); }) +#define __set_RSTR(V) do { __reg(0xfeff0500) = (V); mb(); } while(0) + + + +/* PDR definitions */ +#define PDR_GPIO_DATA(X) (1 << (X)) + +/* GPDR definitions */ +#define GPDR_INPUT 0 +#define GPDR_OUTPUT 1 +#define GPDR_DREQ0_BIT 0x00001000 +#define GPDR_DREQ1_BIT 0x00008000 +#define GPDR_DREQ2_BIT 0x00040000 +#define GPDR_DREQ3_BIT 0x00080000 +#define GPDR_DREQ4_BIT 0x00004000 +#define GPDR_DREQ5_BIT 0x00020000 +#define GPDR_DREQ6_BIT 0x00100000 +#define GPDR_DREQ7_BIT 0x00200000 +#define GPDR_DACK0_BIT 0x00002000 +#define GPDR_DACK1_BIT 0x00010000 +#define GPDR_DACK2_BIT 0x00100000 +#define GPDR_DACK3_BIT 0x00200000 +#define GPDR_DONE0_BIT 0x00004000 +#define GPDR_DONE1_BIT 0x00020000 +#define GPDR_GPIO_DIR(X,D) ((D) << (X)) + +/* SIR definitions */ +#define SIR_GPIO_INPUT 0 +#define SIR_DREQ7_INPUT 0x00200000 +#define SIR_DREQ6_INPUT 0x00100000 +#define SIR_DREQ3_INPUT 0x00080000 +#define SIR_DREQ2_INPUT 0x00040000 +#define SIR_DREQ5_INPUT 0x00020000 +#define SIR_DREQ1_INPUT 0x00008000 +#define SIR_DREQ4_INPUT 0x00004000 +#define SIR_DREQ0_INPUT 0x00001000 +#define SIR_RXD1_INPUT 0x00000400 +#define SIR_CTS0_INPUT 0x00000100 +#define SIR_RXD0_INPUT 0x00000040 +#define SIR_GATE1_INPUT 0x00000020 +#define SIR_GATE0_INPUT 0x00000010 +#define SIR_IRQ3_INPUT 0x00000008 +#define SIR_IRQ2_INPUT 0x00000004 +#define SIR_IRQ1_INPUT 0x00000002 +#define SIR_IRQ0_INPUT 0x00000001 +#define SIR_DREQ_BITS (SIR_DREQ0_INPUT | SIR_DREQ1_INPUT | \ + SIR_DREQ2_INPUT | SIR_DREQ3_INPUT | \ + SIR_DREQ4_INPUT | SIR_DREQ5_INPUT | \ + SIR_DREQ6_INPUT | SIR_DREQ7_INPUT) + +/* SOR definitions */ +#define SOR_GPIO_OUTPUT 0 +#define SOR_DACK3_OUTPUT 0x00200000 +#define SOR_DACK2_OUTPUT 0x00100000 +#define SOR_DONE1_OUTPUT 0x00020000 +#define SOR_DACK1_OUTPUT 0x00010000 +#define SOR_DONE0_OUTPUT 0x00004000 +#define SOR_DACK0_OUTPUT 0x00002000 +#define SOR_TXD1_OUTPUT 0x00000800 +#define SOR_RTS0_OUTPUT 0x00000200 +#define SOR_TXD0_OUTPUT 0x00000080 +#define SOR_TOUT1_OUTPUT 0x00000020 +#define SOR_TOUT0_OUTPUT 0x00000010 +#define SOR_DONE_BITS (SOR_DONE0_OUTPUT | SOR_DONE1_OUTPUT) +#define SOR_DACK_BITS (SOR_DACK0_OUTPUT | SOR_DACK1_OUTPUT | \ + SOR_DACK2_OUTPUT | SOR_DACK3_OUTPUT) + +/* PDSR definitions */ +#define PDSR_UNCHANGED 0 +#define PDSR_SET_BIT(X) (1 << (X)) + +/* PDCR definitions */ +#define PDCR_UNCHANGED 0 +#define PDCR_CLEAR_BIT(X) (1 << (X)) + +/* RSTR definitions */ +/* Read Only */ +#define RSTR_POWERON 0x00000400 +#define RSTR_SOFTRESET_STATUS 0x00000100 +/* Write Only */ +#define RSTR_SOFTRESET 0x00000001 + +#endif /* _ASM_GPIO_REGS */ diff --git a/arch/frv/include/asm/hardirq.h b/arch/frv/include/asm/hardirq.h new file mode 100644 index 00000000000..c62833d6ebb --- /dev/null +++ b/arch/frv/include/asm/hardirq.h @@ -0,0 +1,26 @@ +/* hardirq.h: FRV hardware IRQ management + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef __ASM_HARDIRQ_H +#define __ASM_HARDIRQ_H + +#include <linux/atomic.h> + +extern atomic_t irq_err_count; +static inline void ack_bad_irq(int irq) +{ + atomic_inc(&irq_err_count); +} +#define ack_bad_irq ack_bad_irq + +#include <asm-generic/hardirq.h> + +#endif diff --git a/arch/frv/include/asm/highmem.h b/arch/frv/include/asm/highmem.h new file mode 100644 index 00000000000..b3adc93611f --- /dev/null +++ b/arch/frv/include/asm/highmem.h @@ -0,0 +1,151 @@ +/* highmem.h: virtual kernel memory mappings for high memory + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * - Derived from include/asm-i386/highmem.h + * + * See Documentation/frv/mmu-layout.txt for more information. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_HIGHMEM_H +#define _ASM_HIGHMEM_H + +#ifdef __KERNEL__ + +#include <linux/init.h> +#include <linux/highmem.h> +#include <asm/mem-layout.h> +#include <asm/spr-regs.h> +#include <asm/mb-regs.h> + +#define NR_TLB_LINES 64 /* number of lines in the TLB */ + +#ifndef __ASSEMBLY__ + +#include <linux/interrupt.h> +#include <asm/kmap_types.h> +#include <asm/pgtable.h> + +#ifdef CONFIG_DEBUG_HIGHMEM +#define HIGHMEM_DEBUG 1 +#else +#define HIGHMEM_DEBUG 0 +#endif + +/* declarations for highmem.c */ +extern unsigned long highstart_pfn, highend_pfn; + +#define kmap_prot PAGE_KERNEL +#define kmap_pte ______kmap_pte_in_TLB +extern pte_t *pkmap_page_table; + +#define flush_cache_kmaps() do { } while (0) + +/* + * Right now we initialize only a single pte table. It can be extended + * easily, subsequent pte tables have to be allocated in one physical + * chunk of RAM. + */ +#define LAST_PKMAP PTRS_PER_PTE +#define LAST_PKMAP_MASK (LAST_PKMAP - 1) +#define PKMAP_NR(virt) ((virt - PKMAP_BASE) >> PAGE_SHIFT) +#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) + +extern void *kmap_high(struct page *page); +extern void kunmap_high(struct page *page); + +extern void *kmap(struct page *page); +extern void kunmap(struct page *page); + +extern struct page *kmap_atomic_to_page(void *ptr); + +#endif /* !__ASSEMBLY__ */ + +/* + * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap + * gives a more generic (and caching) interface. But kmap_atomic can + * be used in IRQ contexts, so in some (very limited) cases we need + * it. + */ +#define KMAP_ATOMIC_CACHE_DAMR 8 + +#ifndef __ASSEMBLY__ + +#define __kmap_atomic_primary(cached, paddr, ampr) \ +({ \ + unsigned long damlr, dampr; \ + \ + dampr = paddr | xAMPRx_L | xAMPRx_M | xAMPRx_S | xAMPRx_SS_16Kb | xAMPRx_V; \ + \ + if (!cached) \ + asm volatile("movgs %0,dampr"#ampr :: "r"(dampr) : "memory"); \ + else \ + /* cache flush page attachment point */ \ + asm volatile("movgs %0,iampr"#ampr"\n" \ + "movgs %0,dampr"#ampr"\n" \ + :: "r"(dampr) : "memory" \ + ); \ + \ + asm("movsg damlr"#ampr",%0" : "=r"(damlr)); \ + \ + /*printk("DAMR"#ampr": PRIM sl=%d L=%08lx P=%08lx\n", type, damlr, dampr);*/ \ + \ + (void *) damlr; \ +}) + +#define __kmap_atomic_secondary(slot, paddr) \ +({ \ + unsigned long damlr = KMAP_ATOMIC_SECONDARY_FRAME + (slot) * PAGE_SIZE; \ + unsigned long dampr = paddr | xAMPRx_L | xAMPRx_M | xAMPRx_S | xAMPRx_SS_16Kb | xAMPRx_V; \ + \ + asm volatile("movgs %0,tplr \n" \ + "movgs %1,tppr \n" \ + "tlbpr %0,gr0,#2,#1" \ + : : "r"(damlr), "r"(dampr) : "memory"); \ + \ + /*printk("TLB: SECN sl=%d L=%08lx P=%08lx\n", slot, damlr, dampr);*/ \ + \ + (void *) damlr; \ +}) + +static inline void *kmap_atomic_primary(struct page *page) +{ + unsigned long paddr; + + pagefault_disable(); + paddr = page_to_phys(page); + + return __kmap_atomic_primary(1, paddr, 2); +} + +#define __kunmap_atomic_primary(cached, ampr) \ +do { \ + asm volatile("movgs gr0,dampr"#ampr"\n" ::: "memory"); \ + if (cached) \ + asm volatile("movgs gr0,iampr"#ampr"\n" ::: "memory"); \ +} while(0) + +#define __kunmap_atomic_secondary(slot, vaddr) \ +do { \ + asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory"); \ +} while(0) + +static inline void kunmap_atomic_primary(void *kvaddr) +{ + __kunmap_atomic_primary(1, 2); + pagefault_enable(); +} + +void *kmap_atomic(struct page *page); +void __kunmap_atomic(void *kvaddr); + +#endif /* !__ASSEMBLY__ */ + +#endif /* __KERNEL__ */ + +#endif /* _ASM_HIGHMEM_H */ diff --git a/arch/frv/include/asm/hw_irq.h b/arch/frv/include/asm/hw_irq.h new file mode 100644 index 00000000000..522ad37923d --- /dev/null +++ b/arch/frv/include/asm/hw_irq.h @@ -0,0 +1,16 @@ +/* hw_irq.h: FR-V specific h/w IRQ stuff + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_HW_IRQ_H +#define _ASM_HW_IRQ_H + + +#endif /* _ASM_HW_IRQ_H */ diff --git a/arch/frv/include/asm/io.h b/arch/frv/include/asm/io.h new file mode 100644 index 00000000000..8cb50a2fbcb --- /dev/null +++ b/arch/frv/include/asm/io.h @@ -0,0 +1,392 @@ +/* io.h: FRV I/O operations + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This gets interesting when talking to the PCI bus - the CPU is in big endian + * mode, the PCI bus is little endian and the hardware in the middle can do + * byte swapping + */ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <asm/virtconvert.h> +#include <asm/string.h> +#include <asm/mb-regs.h> +#include <asm-generic/pci_iomap.h> +#include <linux/delay.h> + +/* + * swap functions are sometimes needed to interface little-endian hardware + */ + +static inline unsigned short _swapw(unsigned short v) +{ + return ((v << 8) | (v >> 8)); +} + +static inline unsigned long _swapl(unsigned long v) +{ + return ((v << 24) | ((v & 0xff00) << 8) | ((v & 0xff0000) >> 8) | (v >> 24)); +} + +//#define __iormb() asm volatile("membar") +//#define __iowmb() asm volatile("membar") + +#define __raw_readb __builtin_read8 +#define __raw_readw __builtin_read16 +#define __raw_readl __builtin_read32 + +#define __raw_writeb(datum, addr) __builtin_write8(addr, datum) +#define __raw_writew(datum, addr) __builtin_write16(addr, datum) +#define __raw_writel(datum, addr) __builtin_write32(addr, datum) + +static inline void io_outsb(unsigned int addr, const void *buf, int len) +{ + unsigned long __ioaddr = (unsigned long) addr; + const uint8_t *bp = buf; + + while (len--) + __builtin_write8((volatile void __iomem *) __ioaddr, *bp++); +} + +static inline void io_outsw(unsigned int addr, const void *buf, int len) +{ + unsigned long __ioaddr = (unsigned long) addr; + const uint16_t *bp = buf; + + while (len--) + __builtin_write16((volatile void __iomem *) __ioaddr, (*bp++)); +} + +extern void __outsl_ns(unsigned int addr, const void *buf, int len); +extern void __outsl_sw(unsigned int addr, const void *buf, int len); +static inline void __outsl(unsigned int addr, const void *buf, int len, int swap) +{ + unsigned long __ioaddr = (unsigned long) addr; + + if (!swap) + __outsl_ns(__ioaddr, buf, len); + else + __outsl_sw(__ioaddr, buf, len); +} + +static inline void io_insb(unsigned long addr, void *buf, int len) +{ + uint8_t *bp = buf; + + while (len--) + *bp++ = __builtin_read8((volatile void __iomem *) addr); +} + +static inline void io_insw(unsigned long addr, void *buf, int len) +{ + uint16_t *bp = buf; + + while (len--) + *bp++ = __builtin_read16((volatile void __iomem *) addr); +} + +extern void __insl_ns(unsigned long addr, void *buf, int len); +extern void __insl_sw(unsigned long addr, void *buf, int len); +static inline void __insl(unsigned long addr, void *buf, int len, int swap) +{ + if (!swap) + __insl_ns(addr, buf, len); + else + __insl_sw(addr, buf, len); +} + +#define mmiowb() mb() + +/* + * make the short names macros so specific devices + * can override them as required + */ + +static inline void memset_io(volatile void __iomem *addr, unsigned char val, int count) +{ + memset((void __force *) addr, val, count); +} + +static inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count) +{ + memcpy(dst, (void __force *) src, count); +} + +static inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count) +{ + memcpy((void __force *) dst, src, count); +} + +static inline uint8_t inb(unsigned long addr) +{ + return __builtin_read8((void __iomem *)addr); +} + +static inline uint16_t inw(unsigned long addr) +{ + uint16_t ret = __builtin_read16((void __iomem *)addr); + + if (__is_PCI_IO(addr)) + ret = _swapw(ret); + + return ret; +} + +static inline uint32_t inl(unsigned long addr) +{ + uint32_t ret = __builtin_read32((void __iomem *)addr); + + if (__is_PCI_IO(addr)) + ret = _swapl(ret); + + return ret; +} + +static inline void outb(uint8_t datum, unsigned long addr) +{ + __builtin_write8((void __iomem *)addr, datum); +} + +static inline void outw(uint16_t datum, unsigned long addr) +{ + if (__is_PCI_IO(addr)) + datum = _swapw(datum); + __builtin_write16((void __iomem *)addr, datum); +} + +static inline void outl(uint32_t datum, unsigned long addr) +{ + if (__is_PCI_IO(addr)) + datum = _swapl(datum); + __builtin_write32((void __iomem *)addr, datum); +} + +#define inb_p(addr) inb(addr) +#define inw_p(addr) inw(addr) +#define inl_p(addr) inl(addr) +#define outb_p(x,addr) outb(x,addr) +#define outw_p(x,addr) outw(x,addr) +#define outl_p(x,addr) outl(x,addr) + +#define outsb(a,b,l) io_outsb(a,b,l) +#define outsw(a,b,l) io_outsw(a,b,l) +#define outsl(a,b,l) __outsl(a,b,l,0) + +#define insb(a,b,l) io_insb(a,b,l) +#define insw(a,b,l) io_insw(a,b,l) +#define insl(a,b,l) __insl(a,b,l,0) + +#define IO_SPACE_LIMIT 0xffffffff + +static inline uint8_t readb(const volatile void __iomem *addr) +{ + return __builtin_read8((__force void volatile __iomem *) addr); +} + +static inline uint16_t readw(const volatile void __iomem *addr) +{ + uint16_t ret = __builtin_read16((__force void volatile __iomem *)addr); + + if (__is_PCI_MEM(addr)) + ret = _swapw(ret); + return ret; +} + +static inline uint32_t readl(const volatile void __iomem *addr) +{ + uint32_t ret = __builtin_read32((__force void volatile __iomem *)addr); + + if (__is_PCI_MEM(addr)) + ret = _swapl(ret); + + return ret; +} + +#define readb_relaxed readb +#define readw_relaxed readw +#define readl_relaxed readl + +static inline void writeb(uint8_t datum, volatile void __iomem *addr) +{ + __builtin_write8(addr, datum); + if (__is_PCI_MEM(addr)) + __flush_PCI_writes(); +} + +static inline void writew(uint16_t datum, volatile void __iomem *addr) +{ + if (__is_PCI_MEM(addr)) + datum = _swapw(datum); + + __builtin_write16(addr, datum); + if (__is_PCI_MEM(addr)) + __flush_PCI_writes(); +} + +static inline void writel(uint32_t datum, volatile void __iomem *addr) +{ + if (__is_PCI_MEM(addr)) + datum = _swapl(datum); + + __builtin_write32(addr, datum); + if (__is_PCI_MEM(addr)) + __flush_PCI_writes(); +} + + +/* Values for nocacheflag and cmode */ +#define IOMAP_FULL_CACHING 0 +#define IOMAP_NOCACHE_SER 1 +#define IOMAP_NOCACHE_NONSER 2 +#define IOMAP_WRITETHROUGH 3 + +extern void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag); + +static inline void __iomem *ioremap(unsigned long physaddr, unsigned long size) +{ + return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); +} + +static inline void __iomem *ioremap_nocache(unsigned long physaddr, unsigned long size) +{ + return __ioremap(physaddr, size, IOMAP_NOCACHE_SER); +} + +static inline void __iomem *ioremap_writethrough(unsigned long physaddr, unsigned long size) +{ + return __ioremap(physaddr, size, IOMAP_WRITETHROUGH); +} + +static inline void __iomem *ioremap_fullcache(unsigned long physaddr, unsigned long size) +{ + return __ioremap(physaddr, size, IOMAP_FULL_CACHING); +} + +#define ioremap_wc ioremap_nocache + +extern void iounmap(void volatile __iomem *addr); + +static inline void __iomem *ioport_map(unsigned long port, unsigned int nr) +{ + return (void __iomem *) port; +} + +static inline void ioport_unmap(void __iomem *p) +{ +} + +static inline void flush_write_buffers(void) +{ + __asm__ __volatile__ ("membar" : : :"memory"); +} + +/* + * do appropriate I/O accesses for token type + */ +static inline unsigned int ioread8(void __iomem *p) +{ + return __builtin_read8(p); +} + +static inline unsigned int ioread16(void __iomem *p) +{ + uint16_t ret = __builtin_read16(p); + if (__is_PCI_addr(p)) + ret = _swapw(ret); + return ret; +} + +static inline unsigned int ioread32(void __iomem *p) +{ + uint32_t ret = __builtin_read32(p); + if (__is_PCI_addr(p)) + ret = _swapl(ret); + return ret; +} + +static inline void iowrite8(u8 val, void __iomem *p) +{ + __builtin_write8(p, val); + if (__is_PCI_MEM(p)) + __flush_PCI_writes(); +} + +static inline void iowrite16(u16 val, void __iomem *p) +{ + if (__is_PCI_addr(p)) + val = _swapw(val); + __builtin_write16(p, val); + if (__is_PCI_MEM(p)) + __flush_PCI_writes(); +} + +static inline void iowrite32(u32 val, void __iomem *p) +{ + if (__is_PCI_addr(p)) + val = _swapl(val); + __builtin_write32(p, val); + if (__is_PCI_MEM(p)) + __flush_PCI_writes(); +} + +static inline void ioread8_rep(void __iomem *p, void *dst, unsigned long count) +{ + io_insb((unsigned long) p, dst, count); +} + +static inline void ioread16_rep(void __iomem *p, void *dst, unsigned long count) +{ + io_insw((unsigned long) p, dst, count); +} + +static inline void ioread32_rep(void __iomem *p, void *dst, unsigned long count) +{ + __insl_ns((unsigned long) p, dst, count); +} + +static inline void iowrite8_rep(void __iomem *p, const void *src, unsigned long count) +{ + io_outsb((unsigned long) p, src, count); +} + +static inline void iowrite16_rep(void __iomem *p, const void *src, unsigned long count) +{ + io_outsw((unsigned long) p, src, count); +} + +static inline void iowrite32_rep(void __iomem *p, const void *src, unsigned long count) +{ + __outsl_ns((unsigned long) p, src, count); +} + +/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ +struct pci_dev; +static inline void pci_iounmap(struct pci_dev *dev, void __iomem *p) +{ +} + + +/* + * Convert a physical pointer to a virtual kernel pointer for /dev/mem + * access + */ +#define xlate_dev_mem_ptr(p) __va(p) + +/* + * Convert a virtual cached pointer to an uncached pointer + */ +#define xlate_dev_kmem_ptr(p) p + +#endif /* __KERNEL__ */ + +#endif /* _ASM_IO_H */ diff --git a/arch/frv/include/asm/irc-regs.h b/arch/frv/include/asm/irc-regs.h new file mode 100644 index 00000000000..afa30aeacc8 --- /dev/null +++ b/arch/frv/include/asm/irc-regs.h @@ -0,0 +1,53 @@ +/* irc-regs.h: on-chip interrupt controller registers + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_IRC_REGS +#define _ASM_IRC_REGS + +#define __reg(ADDR) (*(volatile unsigned long *)(ADDR)) + +#define __get_TM0() ({ __reg(0xfeff9800); }) +#define __get_TM1() ({ __reg(0xfeff9808); }) +#define __set_TM1(V) do { __reg(0xfeff9808) = (V); mb(); } while(0) + +#define __set_TM1x(XI,V) \ +do { \ + int shift = (XI) * 2 + 16; \ + unsigned long tm1 = __reg(0xfeff9808); \ + tm1 &= ~(0x3 << shift); \ + tm1 |= (V) << shift; \ + __reg(0xfeff9808) = tm1; \ + mb(); \ +} while(0) + +#define __get_RS(C) ({ (__reg(0xfeff9810) >> ((C)+16)) & 1; }) + +#define __clr_RC(C) do { __reg(0xfeff9818) = 1 << ((C)+16); mb(); } while(0) + +#define __get_MASK(C) ({ (__reg(0xfeff9820) >> ((C)+16)) & 1; }) +#define __set_MASK(C) do { __reg(0xfeff9820) |= 1 << ((C)+16); mb(); } while(0) +#define __clr_MASK(C) do { __reg(0xfeff9820) &= ~(1 << ((C)+16)); mb(); } while(0) + +#define __get_MASK_all() __get_MASK(0) +#define __set_MASK_all() __set_MASK(0) +#define __clr_MASK_all() __clr_MASK(0) + +#define __get_IRL() ({ (__reg(0xfeff9828) >> 16) & 0xf; }) +#define __clr_IRL() do { __reg(0xfeff9828) = 0x100000; mb(); } while(0) + +#define __get_IRR(N) ({ __reg(0xfeff9840 + (N) * 8); }) +#define __set_IRR(N,V) do { __reg(0xfeff9840 + (N) * 8) = (V); } while(0) + +#define __get_IITMR(N) ({ __reg(0xfeff9880 + (N) * 8); }) +#define __set_IITMR(N,V) do { __reg(0xfeff9880 + (N) * 8) = (V); } while(0) + + +#endif /* _ASM_IRC_REGS */ diff --git a/arch/frv/include/asm/irq.h b/arch/frv/include/asm/irq.h new file mode 100644 index 00000000000..3a66ebd754b --- /dev/null +++ b/arch/frv/include/asm/irq.h @@ -0,0 +1,30 @@ +/* irq.h: FRV IRQ definitions + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_IRQ_H_ +#define _ASM_IRQ_H_ + +#define NR_IRQS 48 +#define IRQ_BASE_CPU (0 * 16) +#define IRQ_BASE_FPGA (1 * 16) +#define IRQ_BASE_MB93493 (2 * 16) + +/* probe returns a 32-bit IRQ mask:-/ */ +#define MIN_PROBE_IRQ (NR_IRQS - 32) + +#ifndef __ASSEMBLY__ +static inline int irq_canonicalize(int irq) +{ + return irq; +} +#endif + +#endif /* _ASM_IRQ_H_ */ diff --git a/arch/frv/include/asm/irq_regs.h b/arch/frv/include/asm/irq_regs.h new file mode 100644 index 00000000000..d22e83289ad --- /dev/null +++ b/arch/frv/include/asm/irq_regs.h @@ -0,0 +1,27 @@ +/* FRV per-CPU frame pointer holder + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_IRQ_REGS_H +#define _ASM_IRQ_REGS_H + +/* + * Per-cpu current frame pointer - the location of the last exception frame on + * the stack + * - on FRV, GR28 is dedicated to keeping a pointer to the current exception + * frame + */ +#define ARCH_HAS_OWN_IRQ_REGS + +#ifndef __ASSEMBLY__ +#define get_irq_regs() (__frame) +#endif + +#endif /* _ASM_IRQ_REGS_H */ diff --git a/arch/frv/include/asm/irqflags.h b/arch/frv/include/asm/irqflags.h new file mode 100644 index 00000000000..82f0b5363f4 --- /dev/null +++ b/arch/frv/include/asm/irqflags.h @@ -0,0 +1,158 @@ +/* FR-V interrupt handling + * + * Copyright (C) 2010 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_IRQFLAGS_H +#define _ASM_IRQFLAGS_H + +/* + * interrupt flag manipulation + * - use virtual interrupt management since touching the PSR is slow + * - ICC2.Z: T if interrupts virtually disabled + * - ICC2.C: F if interrupts really disabled + * - if Z==1 upon interrupt: + * - C is set to 0 + * - interrupts are really disabled + * - entry.S returns immediately + * - uses TIHI (TRAP if Z==0 && C==0) #2 to really reenable interrupts + * - if taken, the trap: + * - sets ICC2.C + * - enables interrupts + */ +static inline void arch_local_irq_disable(void) +{ + /* set Z flag, but don't change the C flag */ + asm volatile(" andcc gr0,gr0,gr0,icc2 \n" + : + : + : "memory", "icc2" + ); +} + +static inline void arch_local_irq_enable(void) +{ + /* clear Z flag and then test the C flag */ + asm volatile(" oricc gr0,#1,gr0,icc2 \n" + " tihi icc2,gr0,#2 \n" + : + : + : "memory", "icc2" + ); +} + +static inline unsigned long arch_local_save_flags(void) +{ + unsigned long flags; + + asm volatile("movsg ccr,%0" + : "=r"(flags) + : + : "memory"); + + /* shift ICC2.Z to bit 0 */ + flags >>= 26; + + /* make flags 1 if interrupts disabled, 0 otherwise */ + return flags & 1UL; + +} + +static inline unsigned long arch_local_irq_save(void) +{ + unsigned long flags = arch_local_save_flags(); + arch_local_irq_disable(); + return flags; +} + +static inline void arch_local_irq_restore(unsigned long flags) +{ + /* load the Z flag by turning 1 if disabled into 0 if disabled + * and thus setting the Z flag but not the C flag */ + asm volatile(" xoricc %0,#1,gr0,icc2 \n" + /* then trap if Z=0 and C=0 */ + " tihi icc2,gr0,#2 \n" + : + : "r"(flags) + : "memory", "icc2" + ); + +} + +static inline bool arch_irqs_disabled_flags(unsigned long flags) +{ + return flags; +} + +static inline bool arch_irqs_disabled(void) +{ + return arch_irqs_disabled_flags(arch_local_save_flags()); +} + +/* + * real interrupt flag manipulation + */ +#define __arch_local_irq_disable() \ +do { \ + unsigned long psr; \ + asm volatile(" movsg psr,%0 \n" \ + " andi %0,%2,%0 \n" \ + " ori %0,%1,%0 \n" \ + " movgs %0,psr \n" \ + : "=r"(psr) \ + : "i" (PSR_PIL_14), "i" (~PSR_PIL) \ + : "memory"); \ +} while (0) + +#define __arch_local_irq_enable() \ +do { \ + unsigned long psr; \ + asm volatile(" movsg psr,%0 \n" \ + " andi %0,%1,%0 \n" \ + " movgs %0,psr \n" \ + : "=r"(psr) \ + : "i" (~PSR_PIL) \ + : "memory"); \ +} while (0) + +#define __arch_local_save_flags(flags) \ +do { \ + typecheck(unsigned long, flags); \ + asm("movsg psr,%0" \ + : "=r"(flags) \ + : \ + : "memory"); \ +} while (0) + +#define __arch_local_irq_save(flags) \ +do { \ + unsigned long npsr; \ + typecheck(unsigned long, flags); \ + asm volatile(" movsg psr,%0 \n" \ + " andi %0,%3,%1 \n" \ + " ori %1,%2,%1 \n" \ + " movgs %1,psr \n" \ + : "=r"(flags), "=r"(npsr) \ + : "i" (PSR_PIL_14), "i" (~PSR_PIL) \ + : "memory"); \ +} while (0) + +#define __arch_local_irq_restore(flags) \ +do { \ + typecheck(unsigned long, flags); \ + asm volatile(" movgs %0,psr \n" \ + : \ + : "r" (flags) \ + : "memory"); \ +} while (0) + +#define __arch_irqs_disabled() \ + ((__get_PSR() & PSR_PIL) >= PSR_PIL_14) + +#endif /* _ASM_IRQFLAGS_H */ diff --git a/arch/frv/include/asm/kdebug.h b/arch/frv/include/asm/kdebug.h new file mode 100644 index 00000000000..6ece1b03766 --- /dev/null +++ b/arch/frv/include/asm/kdebug.h @@ -0,0 +1 @@ +#include <asm-generic/kdebug.h> diff --git a/arch/frv/include/asm/kmap_types.h b/arch/frv/include/asm/kmap_types.h new file mode 100644 index 00000000000..43901f22096 --- /dev/null +++ b/arch/frv/include/asm/kmap_types.h @@ -0,0 +1,7 @@ + +#ifndef _ASM_KMAP_TYPES_H +#define _ASM_KMAP_TYPES_H + +#define KM_TYPE_NR 17 + +#endif diff --git a/arch/frv/include/asm/linkage.h b/arch/frv/include/asm/linkage.h new file mode 100644 index 00000000000..636c1bced7d --- /dev/null +++ b/arch/frv/include/asm/linkage.h @@ -0,0 +1,7 @@ +#ifndef __ASM_LINKAGE_H +#define __ASM_LINKAGE_H + +#define __ALIGN .align 4 +#define __ALIGN_STR ".align 4" + +#endif diff --git a/arch/frv/include/asm/local.h b/arch/frv/include/asm/local.h new file mode 100644 index 00000000000..c27bdf04630 --- /dev/null +++ b/arch/frv/include/asm/local.h @@ -0,0 +1,6 @@ +#ifndef _ASM_LOCAL_H +#define _ASM_LOCAL_H + +#include <asm-generic/local.h> + +#endif /* _ASM_LOCAL_H */ diff --git a/arch/frv/include/asm/local64.h b/arch/frv/include/asm/local64.h new file mode 100644 index 00000000000..36c93b5cc23 --- /dev/null +++ b/arch/frv/include/asm/local64.h @@ -0,0 +1 @@ +#include <asm-generic/local64.h> diff --git a/arch/frv/include/asm/math-emu.h b/arch/frv/include/asm/math-emu.h new file mode 100644 index 00000000000..0c8f731b218 --- /dev/null +++ b/arch/frv/include/asm/math-emu.h @@ -0,0 +1,301 @@ +#ifndef _ASM_MATH_EMU_H +#define _ASM_MATH_EMU_H + +#include <asm/setup.h> +#include <linux/linkage.h> + +/* Status Register bits */ + +/* accrued exception bits */ +#define FPSR_AEXC_INEX 3 +#define FPSR_AEXC_DZ 4 +#define FPSR_AEXC_UNFL 5 +#define FPSR_AEXC_OVFL 6 +#define FPSR_AEXC_IOP 7 + +/* exception status bits */ +#define FPSR_EXC_INEX1 8 +#define FPSR_EXC_INEX2 9 +#define FPSR_EXC_DZ 10 +#define FPSR_EXC_UNFL 11 +#define FPSR_EXC_OVFL 12 +#define FPSR_EXC_OPERR 13 +#define FPSR_EXC_SNAN 14 +#define FPSR_EXC_BSUN 15 + +/* quotient byte, assumes big-endian, of course */ +#define FPSR_QUOTIENT(fpsr) (*((signed char *) &(fpsr) + 1)) + +/* condition code bits */ +#define FPSR_CC_NAN 24 +#define FPSR_CC_INF 25 +#define FPSR_CC_Z 26 +#define FPSR_CC_NEG 27 + + +/* Control register bits */ + +/* rounding mode */ +#define FPCR_ROUND_RN 0 /* round to nearest/even */ +#define FPCR_ROUND_RZ 1 /* round to zero */ +#define FPCR_ROUND_RM 2 /* minus infinity */ +#define FPCR_ROUND_RP 3 /* plus infinity */ + +/* rounding precision */ +#define FPCR_PRECISION_X 0 /* long double */ +#define FPCR_PRECISION_S 1 /* double */ +#define FPCR_PRECISION_D 2 /* float */ + + +/* Flags to select the debugging output */ +#define PDECODE 0 +#define PEXECUTE 1 +#define PCONV 2 +#define PNORM 3 +#define PREGISTER 4 +#define PINSTR 5 +#define PUNIMPL 6 +#define PMOVEM 7 + +#define PMDECODE (1<<PDECODE) +#define PMEXECUTE (1<<PEXECUTE) +#define PMCONV (1<<PCONV) +#define PMNORM (1<<PNORM) +#define PMREGISTER (1<<PREGISTER) +#define PMINSTR (1<<PINSTR) +#define PMUNIMPL (1<<PUNIMPL) +#define PMMOVEM (1<<PMOVEM) + +#ifndef __ASSEMBLY__ + +#include <linux/kernel.h> +#include <linux/sched.h> + +union fp_mant64 { + unsigned long long m64; + unsigned long m32[2]; +}; + +union fp_mant128 { + unsigned long long m64[2]; + unsigned long m32[4]; +}; + +/* internal representation of extended fp numbers */ +struct fp_ext { + unsigned char lowmant; + unsigned char sign; + unsigned short exp; + union fp_mant64 mant; +}; + +/* C representation of FPU registers */ +/* NOTE: if you change this, you have to change the assembler offsets + below and the size in <asm/fpu.h>, too */ +struct fp_data { + struct fp_ext fpreg[8]; + unsigned int fpcr; + unsigned int fpsr; + unsigned int fpiar; + unsigned short prec; + unsigned short rnd; + struct fp_ext temp[2]; +}; + +#if FPU_EMU_DEBUG +extern unsigned int fp_debugprint; + +#define dprint(bit, fmt, args...) ({ \ + if (fp_debugprint & (1 << (bit))) \ + printk(fmt, ## args); \ +}) +#else +#define dprint(bit, fmt, args...) +#endif + +#define uprint(str) ({ \ + static int __count = 3; \ + \ + if (__count > 0) { \ + printk("You just hit an unimplemented " \ + "fpu instruction (%s)\n", str); \ + printk("Please report this to ....\n"); \ + __count--; \ + } \ +}) + +#define FPDATA ((struct fp_data *)current->thread.fp) + +#else /* __ASSEMBLY__ */ + +#define FPDATA %a2 + +/* offsets from the base register to the floating point data in the task struct */ +#define FPD_FPREG (TASK_THREAD+THREAD_FPREG+0) +#define FPD_FPCR (TASK_THREAD+THREAD_FPREG+96) +#define FPD_FPSR (TASK_THREAD+THREAD_FPREG+100) +#define FPD_FPIAR (TASK_THREAD+THREAD_FPREG+104) +#define FPD_PREC (TASK_THREAD+THREAD_FPREG+108) +#define FPD_RND (TASK_THREAD+THREAD_FPREG+110) +#define FPD_TEMPFP1 (TASK_THREAD+THREAD_FPREG+112) +#define FPD_TEMPFP2 (TASK_THREAD+THREAD_FPREG+124) +#define FPD_SIZEOF (TASK_THREAD+THREAD_FPREG+136) + +/* offsets on the stack to access saved registers, + * these are only used during instruction decoding + * where we always know how deep we're on the stack. + */ +#define FPS_DO (PT_D0) +#define FPS_D1 (PT_D1) +#define FPS_D2 (PT_D2) +#define FPS_A0 (PT_A0) +#define FPS_A1 (PT_A1) +#define FPS_A2 (PT_A2) +#define FPS_SR (PT_SR) +#define FPS_PC (PT_PC) +#define FPS_EA (PT_PC+6) +#define FPS_PC2 (PT_PC+10) + +.macro fp_get_fp_reg + lea (FPD_FPREG,FPDATA,%d0.w*4),%a0 + lea (%a0,%d0.w*8),%a0 +.endm + +/* Macros used to get/put the current program counter. + * 020/030 use a different stack frame then 040/060, for the + * 040/060 the return pc points already to the next location, + * so this only needs to be modified for jump instructions. + */ +.macro fp_get_pc dest + move.l (FPS_PC+4,%sp),\dest +.endm + +.macro fp_put_pc src,jump=0 + move.l \src,(FPS_PC+4,%sp) +.endm + +.macro fp_get_instr_data f,s,dest,label + getuser \f,%sp@(FPS_PC+4)@(0),\dest,\label,%sp@(FPS_PC+4) + addq.l #\s,%sp@(FPS_PC+4) +.endm + +.macro fp_get_instr_word dest,label,addr + fp_get_instr_data w,2,\dest,\label,\addr +.endm + +.macro fp_get_instr_long dest,label,addr + fp_get_instr_data l,4,\dest,\label,\addr +.endm + +/* These macros are used to read from/write to user space + * on error we jump to the fixup section, load the fault + * address into %a0 and jump to the exit. + * (derived from <asm/uaccess.h>) + */ +.macro getuser size,src,dest,label,addr +| printf ,"[\size<%08x]",1,\addr +.Lu1\@: moves\size \src,\dest + + .section .fixup,"ax" + .even +.Lu2\@: move.l \addr,%a0 + jra \label + .previous + + .section __ex_table,"a" + .align 4 + .long .Lu1\@,.Lu2\@ + .previous +.endm + +.macro putuser size,src,dest,label,addr +| printf ,"[\size>%08x]",1,\addr +.Lu1\@: moves\size \src,\dest +.Lu2\@: + + .section .fixup,"ax" + .even +.Lu3\@: move.l \addr,%a0 + jra \label + .previous + + .section __ex_table,"a" + .align 4 + .long .Lu1\@,.Lu3\@ + .long .Lu2\@,.Lu3\@ + .previous +.endm + + +.macro movestack nr,arg1,arg2,arg3,arg4,arg5 + .if \nr + movestack (\nr-1),\arg2,\arg3,\arg4,\arg5 + move.l \arg1,-(%sp) + .endif +.endm + +.macro printf bit=-1,string,nr=0,arg1,arg2,arg3,arg4,arg5 +#ifdef FPU_EMU_DEBUG + .data +.Lpdata\@: + .string "\string" + .previous + + movem.l %d0/%d1/%a0/%a1,-(%sp) + .if \bit+1 +#if 0 + moveq #\bit,%d0 + andw #7,%d0 + btst %d0,fp_debugprint+((31-\bit)/8) +#else + btst #\bit,fp_debugprint+((31-\bit)/8) +#endif + jeq .Lpskip\@ + .endif + movestack \nr,\arg1,\arg2,\arg3,\arg4,\arg5 + pea .Lpdata\@ + jsr printk + lea ((\nr+1)*4,%sp),%sp +.Lpskip\@: + movem.l (%sp)+,%d0/%d1/%a0/%a1 +#endif +.endm + +.macro printx bit,fp +#ifdef FPU_EMU_DEBUG + movem.l %d0/%a0,-(%sp) + lea \fp,%a0 +#if 0 + moveq #'+',%d0 + tst.w (%a0) + jeq .Lx1\@ + moveq #'-',%d0 +.Lx1\@: printf \bit," %c",1,%d0 + move.l (4,%a0),%d0 + bclr #31,%d0 + jne .Lx2\@ + printf \bit,"0." + jra .Lx3\@ +.Lx2\@: printf \bit,"1." +.Lx3\@: printf \bit,"%08x%08x",2,%d0,%a0@(8) + move.w (2,%a0),%d0 + ext.l %d0 + printf \bit,"E%04x",1,%d0 +#else + printf \bit," %08x%08x%08x",3,%a0@,%a0@(4),%a0@(8) +#endif + movem.l (%sp)+,%d0/%a0 +#endif +.endm + +.macro debug instr,args +#ifdef FPU_EMU_DEBUG + \instr \args +#endif +.endm + + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_FRV_MATH_EMU_H */ + diff --git a/arch/frv/include/asm/mb-regs.h b/arch/frv/include/asm/mb-regs.h new file mode 100644 index 00000000000..219e5f926f1 --- /dev/null +++ b/arch/frv/include/asm/mb-regs.h @@ -0,0 +1,200 @@ +/* mb-regs.h: motherboard registers + * + * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MB_REGS_H +#define _ASM_MB_REGS_H + +#include <asm/cpu-irqs.h> +#include <asm/sections.h> +#include <asm/mem-layout.h> + +#ifndef __ASSEMBLY__ +/* gcc builtins, annotated */ + +unsigned long __builtin_read8(volatile void __iomem *); +unsigned long __builtin_read16(volatile void __iomem *); +unsigned long __builtin_read32(volatile void __iomem *); +void __builtin_write8(volatile void __iomem *, unsigned char); +void __builtin_write16(volatile void __iomem *, unsigned short); +void __builtin_write32(volatile void __iomem *, unsigned long); +#endif + +#define __region_IO KERNEL_IO_START /* the region from 0xe0000000 to 0xffffffff has suitable + * protection laid over the top for use in memory-mapped + * I/O + */ + +#define __region_CS0 0xff000000 /* Boot ROMs area */ + +#ifdef CONFIG_MB93091_VDK +/* + * VDK motherboard and CPU card specific stuff + */ + +#include <asm/mb93091-fpga-irqs.h> + +#define IRQ_CPU_MB93493_0 IRQ_CPU_EXTERNAL0 +#define IRQ_CPU_MB93493_1 IRQ_CPU_EXTERNAL1 + +#define __region_CS2 0xe0000000 /* SLBUS/PCI I/O space */ +#define __region_CS2_M 0x0fffffff /* mask */ +#define __region_CS2_C 0x00000000 /* control */ +#define __region_CS5 0xf0000000 /* MB93493 CSC area (DAV daughter board) */ +#define __region_CS5_M 0x00ffffff +#define __region_CS5_C 0x00010000 +#define __region_CS7 0xf1000000 /* CB70 CPU-card PCMCIA port I/O space */ +#define __region_CS7_M 0x00ffffff +#define __region_CS7_C 0x00410701 +#define __region_CS1 0xfc000000 /* SLBUS/PCI bridge control registers */ +#define __region_CS1_M 0x000fffff +#define __region_CS1_C 0x00000000 +#define __region_CS6 0xfc100000 /* CB70 CPU-card DM9000 LAN I/O space */ +#define __region_CS6_M 0x000fffff +#define __region_CS6_C 0x00400707 +#define __region_CS3 0xfc200000 /* MB93493 CSR area (DAV daughter board) */ +#define __region_CS3_M 0x000fffff +#define __region_CS3_C 0xc8100000 +#define __region_CS4 0xfd000000 /* CB70 CPU-card extra flash space */ +#define __region_CS4_M 0x00ffffff +#define __region_CS4_C 0x00000f07 + +#define __region_PCI_IO (__region_CS2 + 0x04000000UL) +#define __region_PCI_MEM (__region_CS2 + 0x08000000UL) +#define __flush_PCI_writes() \ +do { \ + __builtin_write8((volatile void __iomem *) __region_PCI_MEM, 0); \ +} while(0) + +#define __is_PCI_IO(addr) \ + (((unsigned long)(addr) >> 24) - (__region_PCI_IO >> 24) < (0x04000000UL >> 24)) + +#define __is_PCI_MEM(addr) \ + ((unsigned long)(addr) - __region_PCI_MEM < 0x08000000UL) + +#define __is_PCI_addr(addr) \ + ((unsigned long)(addr) - __region_PCI_IO < 0x0c000000UL) + +#define __get_CLKSW() ({ *(volatile unsigned long *)(__region_CS2 + 0x0130000cUL) & 0xffUL; }) +#define __get_CLKIN() (__get_CLKSW() * 125U * 100000U / 24U) + +#ifndef __ASSEMBLY__ +extern int __nongprelbss mb93090_mb00_detected; +#endif + +#define __addr_LEDS() (__region_CS2 + 0x01200004UL) +#ifdef CONFIG_MB93090_MB00 +#define __set_LEDS(X) \ +do { \ + if (mb93090_mb00_detected) \ + __builtin_write32((void __iomem *) __addr_LEDS(), ~(X)); \ +} while (0) +#else +#define __set_LEDS(X) +#endif + +#define __addr_LCD() (__region_CS2 + 0x01200008UL) +#define __get_LCD(B) __builtin_read32((volatile void __iomem *) (B)) +#define __set_LCD(B,X) __builtin_write32((volatile void __iomem *) (B), (X)) + +#define LCD_D 0x000000ff /* LCD data bus */ +#define LCD_RW 0x00000100 /* LCD R/W signal */ +#define LCD_RS 0x00000200 /* LCD Register Select */ +#define LCD_E 0x00000400 /* LCD Start Enable Signal */ + +#define LCD_CMD_CLEAR (LCD_E|0x001) +#define LCD_CMD_HOME (LCD_E|0x002) +#define LCD_CMD_CURSOR_INC (LCD_E|0x004) +#define LCD_CMD_SCROLL_INC (LCD_E|0x005) +#define LCD_CMD_CURSOR_DEC (LCD_E|0x006) +#define LCD_CMD_SCROLL_DEC (LCD_E|0x007) +#define LCD_CMD_OFF (LCD_E|0x008) +#define LCD_CMD_ON(CRSR,BLINK) (LCD_E|0x00c|(CRSR<<1)|BLINK) +#define LCD_CMD_CURSOR_MOVE_L (LCD_E|0x010) +#define LCD_CMD_CURSOR_MOVE_R (LCD_E|0x014) +#define LCD_CMD_DISPLAY_SHIFT_L (LCD_E|0x018) +#define LCD_CMD_DISPLAY_SHIFT_R (LCD_E|0x01c) +#define LCD_CMD_FUNCSET(DL,N,F) (LCD_E|0x020|(DL<<4)|(N<<3)|(F<<2)) +#define LCD_CMD_SET_CG_ADDR(X) (LCD_E|0x040|X) +#define LCD_CMD_SET_DD_ADDR(X) (LCD_E|0x080|X) +#define LCD_CMD_READ_BUSY (LCD_E|LCD_RW) +#define LCD_DATA_WRITE(X) (LCD_E|LCD_RS|(X)) +#define LCD_DATA_READ (LCD_E|LCD_RS|LCD_RW) + +#else +/* + * PDK unit specific stuff + */ + +#include <asm/mb93093-fpga-irqs.h> + +#define IRQ_CPU_MB93493_0 IRQ_CPU_EXTERNAL0 +#define IRQ_CPU_MB93493_1 IRQ_CPU_EXTERNAL1 + +#define __region_CS5 0xf0000000 /* MB93493 CSC area (DAV daughter board) */ +#define __region_CS5_M 0x00ffffff /* mask */ +#define __region_CS5_C 0x00010000 /* control */ +#define __region_CS2 0x20000000 /* FPGA registers */ +#define __region_CS2_M 0x000fffff +#define __region_CS2_C 0x00000000 +#define __region_CS1 0xfc100000 /* LAN registers */ +#define __region_CS1_M 0x000fffff +#define __region_CS1_C 0x00010404 +#define __region_CS3 0xfc200000 /* MB93493 CSR area (DAV daughter board) */ +#define __region_CS3_M 0x000fffff +#define __region_CS3_C 0xc8000000 +#define __region_CS4 0xfd000000 /* extra ROMs area */ +#define __region_CS4_M 0x00ffffff +#define __region_CS4_C 0x00000f07 + +#define __region_CS6 0xfe000000 /* not used - hide behind CPU resource I/O regs */ +#define __region_CS6_M 0x000fffff +#define __region_CS6_C 0x00000f07 +#define __region_CS7 0xfe000000 /* not used - hide behind CPU resource I/O regs */ +#define __region_CS7_M 0x000fffff +#define __region_CS7_C 0x00000f07 + +#define __is_PCI_IO(addr) 0 /* no PCI */ +#define __is_PCI_MEM(addr) 0 +#define __is_PCI_addr(addr) 0 +#define __region_PCI_IO 0 +#define __region_PCI_MEM 0 +#define __flush_PCI_writes() do { } while(0) + +#define __get_CLKSW() 0UL +#define __get_CLKIN() 66000000UL + +#define __addr_LEDS() (__region_CS2 + 0x00000023UL) +#define __set_LEDS(X) __builtin_write8((volatile void __iomem *) __addr_LEDS(), (X)) + +#define __addr_FPGATR() (__region_CS2 + 0x00000030UL) +#define __set_FPGATR(X) __builtin_write32((volatile void __iomem *) __addr_FPGATR(), (X)) +#define __get_FPGATR() __builtin_read32((volatile void __iomem *) __addr_FPGATR()) + +#define MB93093_FPGA_FPGATR_AUDIO_CLK 0x00000003 + +#define __set_FPGATR_AUDIO_CLK(V) \ + __set_FPGATR((__get_FPGATR() & ~MB93093_FPGA_FPGATR_AUDIO_CLK) | (V)) + +#define MB93093_FPGA_FPGATR_AUDIO_CLK_OFF 0x0 +#define MB93093_FPGA_FPGATR_AUDIO_CLK_11MHz 0x1 +#define MB93093_FPGA_FPGATR_AUDIO_CLK_12MHz 0x2 +#define MB93093_FPGA_FPGATR_AUDIO_CLK_02MHz 0x3 + +#define MB93093_FPGA_SWR_PUSHSWMASK (0x1F<<26) +#define MB93093_FPGA_SWR_PUSHSW4 (1<<29) + +#define __addr_FPGA_SWR ((volatile void __iomem *)(__region_CS2 + 0x28UL)) +#define __get_FPGA_PUSHSW1_5() (__builtin_read32(__addr_FPGA_SWR) & MB93093_FPGA_SWR_PUSHSWMASK) + + +#endif + +#endif /* _ASM_MB_REGS_H */ diff --git a/arch/frv/include/asm/mb86943a.h b/arch/frv/include/asm/mb86943a.h new file mode 100644 index 00000000000..e87ef924bfb --- /dev/null +++ b/arch/frv/include/asm/mb86943a.h @@ -0,0 +1,42 @@ +/* mb86943a.h: MB86943 SPARClite <-> PCI bridge registers + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MB86943A_H +#define _ASM_MB86943A_H + +#include <asm/mb-regs.h> + +#define __reg_MB86943_sl_ctl *(volatile uint32_t *) (__region_CS1 + 0x00) + +#define MB86943_SL_CTL_BUS_WIDTH_64 0x00000001 +#define MB86943_SL_CTL_AS_HOST 0x00000002 +#define MB86943_SL_CTL_DRCT_MASTER_SWAP 0x00000004 +#define MB86943_SL_CTL_DRCT_SLAVE_SWAP 0x00000008 +#define MB86943_SL_CTL_PCI_CONFIG_SWAP 0x00000010 +#define MB86943_SL_CTL_ECS0_ENABLE 0x00000020 +#define MB86943_SL_CTL_ECS1_ENABLE 0x00000040 +#define MB86943_SL_CTL_ECS2_ENABLE 0x00000080 + +#define __reg_MB86943_ecs_ctl(N) *(volatile uint32_t *) (__region_CS1 + 0x08 + (0x08*(N))) +#define __reg_MB86943_ecs_range(N) *(volatile uint32_t *) (__region_CS1 + 0x20 + (0x10*(N))) +#define __reg_MB86943_ecs_base(N) *(volatile uint32_t *) (__region_CS1 + 0x28 + (0x10*(N))) + +#define __reg_MB86943_sl_pci_io_range *(volatile uint32_t *) (__region_CS1 + 0x50) +#define __reg_MB86943_sl_pci_io_base *(volatile uint32_t *) (__region_CS1 + 0x58) +#define __reg_MB86943_sl_pci_mem_range *(volatile uint32_t *) (__region_CS1 + 0x60) +#define __reg_MB86943_sl_pci_mem_base *(volatile uint32_t *) (__region_CS1 + 0x68) +#define __reg_MB86943_pci_sl_io_base *(volatile uint32_t *) (__region_CS1 + 0x70) +#define __reg_MB86943_pci_sl_mem_base *(volatile uint32_t *) (__region_CS1 + 0x78) + +#define __reg_MB86943_pci_arbiter *(volatile uint32_t *) (__region_CS2 + 0x01300014) +#define MB86943_PCIARB_EN 0x00000001 + +#endif /* _ASM_MB86943A_H */ diff --git a/arch/frv/include/asm/mb93091-fpga-irqs.h b/arch/frv/include/asm/mb93091-fpga-irqs.h new file mode 100644 index 00000000000..19778c5ba9d --- /dev/null +++ b/arch/frv/include/asm/mb93091-fpga-irqs.h @@ -0,0 +1,42 @@ +/* mb93091-fpga-irqs.h: MB93091 CPU board FPGA IRQs + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MB93091_FPGA_IRQS_H +#define _ASM_MB93091_FPGA_IRQS_H + +#include <asm/irq.h> + +#ifndef __ASSEMBLY__ + +/* IRQ IDs presented to drivers */ +enum { + IRQ_FPGA__UNUSED = IRQ_BASE_FPGA, + IRQ_FPGA_SYSINT_BUS_EXPANSION_1, + IRQ_FPGA_SL_BUS_EXPANSION_2, + IRQ_FPGA_PCI_INTD, + IRQ_FPGA_PCI_INTC, + IRQ_FPGA_PCI_INTB, + IRQ_FPGA_PCI_INTA, + IRQ_FPGA_SL_BUS_EXPANSION_7, + IRQ_FPGA_SYSINT_BUS_EXPANSION_8, + IRQ_FPGA_SL_BUS_EXPANSION_9, + IRQ_FPGA_MB86943_PCI_INTA, + IRQ_FPGA_MB86943_SLBUS_SIDE, + IRQ_FPGA_RTL8029_INTA, + IRQ_FPGA_SYSINT_BUS_EXPANSION_13, + IRQ_FPGA_SL_BUS_EXPANSION_14, + IRQ_FPGA_NMI, +}; + + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_MB93091_FPGA_IRQS_H */ diff --git a/arch/frv/include/asm/mb93093-fpga-irqs.h b/arch/frv/include/asm/mb93093-fpga-irqs.h new file mode 100644 index 00000000000..590266b1a6d --- /dev/null +++ b/arch/frv/include/asm/mb93093-fpga-irqs.h @@ -0,0 +1,29 @@ +/* mb93093-fpga-irqs.h: MB93093 CPU board FPGA IRQs + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MB93093_FPGA_IRQS_H +#define _ASM_MB93093_FPGA_IRQS_H + +#include <asm/irq.h> + +#ifndef __ASSEMBLY__ + +/* IRQ IDs presented to drivers */ +enum { + IRQ_FPGA_PUSH_BUTTON_SW1_5 = IRQ_BASE_FPGA + 8, + IRQ_FPGA_ROCKER_C_SW8 = IRQ_BASE_FPGA + 9, + IRQ_FPGA_ROCKER_C_SW9 = IRQ_BASE_FPGA + 10, +}; + + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_MB93093_FPGA_IRQS_H */ diff --git a/arch/frv/include/asm/mb93493-irqs.h b/arch/frv/include/asm/mb93493-irqs.h new file mode 100644 index 00000000000..82c7aeddd33 --- /dev/null +++ b/arch/frv/include/asm/mb93493-irqs.h @@ -0,0 +1,50 @@ +/* mb93493-irqs.h: MB93493 companion chip IRQs + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MB93493_IRQS_H +#define _ASM_MB93493_IRQS_H + +#include <asm/irq.h> + +#ifndef __ASSEMBLY__ + +/* IRQ IDs presented to drivers */ +enum { + IRQ_MB93493_VDC = IRQ_BASE_MB93493 + 0, + IRQ_MB93493_VCC = IRQ_BASE_MB93493 + 1, + IRQ_MB93493_AUDIO_OUT = IRQ_BASE_MB93493 + 2, + IRQ_MB93493_I2C_0 = IRQ_BASE_MB93493 + 3, + IRQ_MB93493_I2C_1 = IRQ_BASE_MB93493 + 4, + IRQ_MB93493_USB = IRQ_BASE_MB93493 + 5, + IRQ_MB93493_LOCAL_BUS = IRQ_BASE_MB93493 + 7, + IRQ_MB93493_PCMCIA = IRQ_BASE_MB93493 + 8, + IRQ_MB93493_GPIO = IRQ_BASE_MB93493 + 9, + IRQ_MB93493_AUDIO_IN = IRQ_BASE_MB93493 + 10, +}; + +/* IRQ multiplexor mappings */ +#define ROUTE_VIA_IRQ0 0 /* route IRQ by way of CPU external IRQ 0 */ +#define ROUTE_VIA_IRQ1 1 /* route IRQ by way of CPU external IRQ 1 */ + +#define IRQ_MB93493_VDC_ROUTE ROUTE_VIA_IRQ0 +#define IRQ_MB93493_VCC_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_AUDIO_OUT_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_I2C_0_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_I2C_1_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_USB_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_LOCAL_BUS_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_PCMCIA_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_GPIO_ROUTE ROUTE_VIA_IRQ1 +#define IRQ_MB93493_AUDIO_IN_ROUTE ROUTE_VIA_IRQ1 + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_MB93493_IRQS_H */ diff --git a/arch/frv/include/asm/mb93493-regs.h b/arch/frv/include/asm/mb93493-regs.h new file mode 100644 index 00000000000..8a1f6aac8cf --- /dev/null +++ b/arch/frv/include/asm/mb93493-regs.h @@ -0,0 +1,281 @@ +/* mb93493-regs.h: MB93493 companion chip registers + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MB93493_REGS_H +#define _ASM_MB93493_REGS_H + +#include <asm/mb-regs.h> +#include <asm/mb93493-irqs.h> + +#define __addr_MB93493(X) ((volatile unsigned long *)(__region_CS3 + (X))) +#define __get_MB93493(X) ({ *(volatile unsigned long *)(__region_CS3 + (X)); }) + +#define __set_MB93493(X,V) \ +do { \ + *(volatile unsigned long *)(__region_CS3 + (X)) = (V); mb(); \ +} while(0) + +#define __get_MB93493_STSR(X) __get_MB93493(0x3c0 + (X) * 4) +#define __set_MB93493_STSR(X,V) __set_MB93493(0x3c0 + (X) * 4, (V)) +#define MB93493_STSR_EN + +#define __addr_MB93493_IQSR(X) __addr_MB93493(0x3d0 + (X) * 4) +#define __get_MB93493_IQSR(X) __get_MB93493(0x3d0 + (X) * 4) +#define __set_MB93493_IQSR(X,V) __set_MB93493(0x3d0 + (X) * 4, (V)) + +#define __get_MB93493_DQSR(X) __get_MB93493(0x3e0 + (X) * 4) +#define __set_MB93493_DQSR(X,V) __set_MB93493(0x3e0 + (X) * 4, (V)) + +#define __get_MB93493_LBSER() __get_MB93493(0x3f0) +#define __set_MB93493_LBSER(V) __set_MB93493(0x3f0, (V)) + +#define MB93493_LBSER_VDC 0x00010000 +#define MB93493_LBSER_VCC 0x00020000 +#define MB93493_LBSER_AUDIO 0x00040000 +#define MB93493_LBSER_I2C_0 0x00080000 +#define MB93493_LBSER_I2C_1 0x00100000 +#define MB93493_LBSER_USB 0x00200000 +#define MB93493_LBSER_GPIO 0x00800000 +#define MB93493_LBSER_PCMCIA 0x01000000 + +#define __get_MB93493_LBSR() __get_MB93493(0x3fc) +#define __set_MB93493_LBSR(V) __set_MB93493(0x3fc, (V)) + +/* + * video display controller + */ +#define __get_MB93493_VDC(X) __get_MB93493(MB93493_VDC_##X) +#define __set_MB93493_VDC(X,V) __set_MB93493(MB93493_VDC_##X, (V)) + +#define MB93493_VDC_RCURSOR 0x140 /* cursor position */ +#define MB93493_VDC_RCT1 0x144 /* cursor colour 1 */ +#define MB93493_VDC_RCT2 0x148 /* cursor colour 2 */ +#define MB93493_VDC_RHDC 0x150 /* horizontal display period */ +#define MB93493_VDC_RH_MARGINS 0x154 /* horizontal margin sizes */ +#define MB93493_VDC_RVDC 0x158 /* vertical display period */ +#define MB93493_VDC_RV_MARGINS 0x15c /* vertical margin sizes */ +#define MB93493_VDC_RC 0x170 /* VDC control */ +#define MB93493_VDC_RCLOCK 0x174 /* clock divider, DMA req delay */ +#define MB93493_VDC_RBLACK 0x178 /* black insert sizes */ +#define MB93493_VDC_RS 0x17c /* VDC status */ + +#define __addr_MB93493_VDC_BCI(X) ({ (volatile unsigned long *)(__region_CS3 + 0x000 + (X)); }) +#define __addr_MB93493_VDC_TPO(X) (__region_CS3 + 0x1c0 + (X)) + +#define VDC_TPO_WIDTH 32 + +#define VDC_RC_DSR 0x00000080 /* VDC master reset */ + +#define VDC_RS_IT 0x00060000 /* interrupt indicators */ +#define VDC_RS_IT_UNDERFLOW 0x00040000 /* - underflow event */ +#define VDC_RS_IT_VSYNC 0x00020000 /* - VSYNC event */ +#define VDC_RS_DFI 0x00010000 /* current interlace field number */ +#define VDC_RS_DFI_TOP 0x00000000 /* - top field */ +#define VDC_RS_DFI_BOTTOM 0x00010000 /* - bottom field */ +#define VDC_RS_DCSR 0x00000010 /* cursor state */ +#define VDC_RS_DCM 0x00000003 /* display mode */ +#define VDC_RS_DCM_DISABLED 0x00000000 /* - display disabled */ +#define VDC_RS_DCM_STOPPED 0x00000001 /* - VDC stopped */ +#define VDC_RS_DCM_FREERUNNING 0x00000002 /* - VDC free-running */ +#define VDC_RS_DCM_TRANSFERRING 0x00000003 /* - data being transferred to VDC */ + +/* + * video capture controller + */ +#define __get_MB93493_VCC(X) __get_MB93493(MB93493_VCC_##X) +#define __set_MB93493_VCC(X,V) __set_MB93493(MB93493_VCC_##X, (V)) + +#define MB93493_VCC_RREDUCT 0x104 /* reduction rate */ +#define MB93493_VCC_RHY 0x108 /* horizontal brightness filter coefficients */ +#define MB93493_VCC_RHC 0x10c /* horizontal colour-difference filter coefficients */ +#define MB93493_VCC_RHSIZE 0x110 /* horizontal cycle sizes */ +#define MB93493_VCC_RHBC 0x114 /* horizontal back porch size */ +#define MB93493_VCC_RVCC 0x118 /* vertical capture period */ +#define MB93493_VCC_RVBC 0x11c /* vertical back porch period */ +#define MB93493_VCC_RV 0x120 /* vertical filter coefficients */ +#define MB93493_VCC_RDTS 0x128 /* DMA transfer size */ +#define MB93493_VCC_RDTS_4B 0x01000000 /* 4-byte transfer */ +#define MB93493_VCC_RDTS_32B 0x03000000 /* 32-byte transfer */ +#define MB93493_VCC_RDTS_SHIFT 24 +#define MB93493_VCC_RCC 0x130 /* VCC control */ +#define MB93493_VCC_RIS 0x134 /* VCC interrupt status */ + +#define __addr_MB93493_VCC_TPI(X) (__region_CS3 + 0x180 + (X)) + +#define VCC_RHSIZE_RHCC 0x000007ff +#define VCC_RHSIZE_RHCC_SHIFT 0 +#define VCC_RHSIZE_RHTCC 0x0fff0000 +#define VCC_RHSIZE_RHTCC_SHIFT 16 + +#define VCC_RVBC_RVBC 0x00003f00 +#define VCC_RVBC_RVBC_SHIFT 8 + +#define VCC_RREDUCT_RHR 0x07ff0000 +#define VCC_RREDUCT_RHR_SHIFT 16 +#define VCC_RREDUCT_RVR 0x000007ff +#define VCC_RREDUCT_RVR_SHIFT 0 + +#define VCC_RCC_CE 0x00000001 /* VCC enable */ +#define VCC_RCC_CS 0x00000002 /* request video capture start */ +#define VCC_RCC_CPF 0x0000000c /* pixel format */ +#define VCC_RCC_CPF_YCBCR_16 0x00000000 /* - YCbCr 4:2:2 16-bit format */ +#define VCC_RCC_CPF_RGB 0x00000004 /* - RGB 4:4:4 format */ +#define VCC_RCC_CPF_YCBCR_24 0x00000008 /* - YCbCr 4:2:2 24-bit format */ +#define VCC_RCC_CPF_BT656 0x0000000c /* - ITU R-BT.656 format */ +#define VCC_RCC_CPF_SHIFT 2 +#define VCC_RCC_CSR 0x00000080 /* request reset */ +#define VCC_RCC_HSIP 0x00000100 /* HSYNC polarity */ +#define VCC_RCC_HSIP_LOACT 0x00000000 /* - low active */ +#define VCC_RCC_HSIP_HIACT 0x00000100 /* - high active */ +#define VCC_RCC_VSIP 0x00000200 /* VSYNC polarity */ +#define VCC_RCC_VSIP_LOACT 0x00000000 /* - low active */ +#define VCC_RCC_VSIP_HIACT 0x00000200 /* - high active */ +#define VCC_RCC_CIE 0x00000800 /* interrupt enable */ +#define VCC_RCC_CFP 0x00001000 /* RGB pixel packing */ +#define VCC_RCC_CFP_4TO3 0x00000000 /* - pack 4 pixels into 3 words */ +#define VCC_RCC_CFP_1TO1 0x00001000 /* - pack 1 pixel into 1 words */ +#define VCC_RCC_CSM 0x00006000 /* interlace specification */ +#define VCC_RCC_CSM_ONEPASS 0x00002000 /* - non-interlaced */ +#define VCC_RCC_CSM_INTERLACE 0x00004000 /* - interlaced */ +#define VCC_RCC_CSM_SHIFT 13 +#define VCC_RCC_ES 0x00008000 /* capture start polarity */ +#define VCC_RCC_ES_NEG 0x00000000 /* - negative edge */ +#define VCC_RCC_ES_POS 0x00008000 /* - positive edge */ +#define VCC_RCC_IFI 0x00080000 /* inferlace field evaluation reverse */ +#define VCC_RCC_FDTS 0x00300000 /* interlace field start */ +#define VCC_RCC_FDTS_3_8 0x00000000 /* - 3/8 of horizontal entire cycle */ +#define VCC_RCC_FDTS_1_4 0x00100000 /* - 1/4 of horizontal entire cycle */ +#define VCC_RCC_FDTS_7_16 0x00200000 /* - 7/16 of horizontal entire cycle */ +#define VCC_RCC_FDTS_SHIFT 20 +#define VCC_RCC_MOV 0x00400000 /* test bit - always set to 1 */ +#define VCC_RCC_STP 0x00800000 /* request video capture stop */ +#define VCC_RCC_TO 0x01000000 /* input during top-field only */ + +#define VCC_RIS_VSYNC 0x01000000 /* VSYNC interrupt */ +#define VCC_RIS_OV 0x02000000 /* overflow interrupt */ +#define VCC_RIS_BOTTOM 0x08000000 /* interlace bottom field */ +#define VCC_RIS_STARTED 0x10000000 /* capture started */ + +/* + * I2C + */ +#define MB93493_I2C_BSR 0x340 /* bus status */ +#define MB93493_I2C_BCR 0x344 /* bus control */ +#define MB93493_I2C_CCR 0x348 /* clock control */ +#define MB93493_I2C_ADR 0x34c /* address */ +#define MB93493_I2C_DTR 0x350 /* data */ +#define MB93493_I2C_BC2R 0x35c /* bus control 2 */ + +#define __addr_MB93493_I2C(port,X) (__region_CS3 + MB93493_I2C_##X + ((port)*0x20)) +#define __get_MB93493_I2C(port,X) __get_MB93493(MB93493_I2C_##X + ((port)*0x20)) +#define __set_MB93493_I2C(port,X,V) __set_MB93493(MB93493_I2C_##X + ((port)*0x20), (V)) + +#define I2C_BSR_BB (1 << 7) + +/* + * audio controller (I2S) registers + */ +#define __get_MB93493_I2S(X) __get_MB93493(MB93493_I2S_##X) +#define __set_MB93493_I2S(X,V) __set_MB93493(MB93493_I2S_##X, (V)) + +#define MB93493_I2S_ALDR 0x300 /* L-channel data */ +#define MB93493_I2S_ARDR 0x304 /* R-channel data */ +#define MB93493_I2S_APDR 0x308 /* 16-bit packed data */ +#define MB93493_I2S_AISTR 0x310 /* status */ +#define MB93493_I2S_AICR 0x314 /* control */ + +#define __addr_MB93493_I2S_ALDR(X) (__region_CS3 + MB93493_I2S_ALDR + (X)) +#define __addr_MB93493_I2S_ARDR(X) (__region_CS3 + MB93493_I2S_ARDR + (X)) +#define __addr_MB93493_I2S_APDR(X) (__region_CS3 + MB93493_I2S_APDR + (X)) +#define __addr_MB93493_I2S_ADR(X) (__region_CS3 + 0x320 + (X)) + +#define I2S_AISTR_OTST 0x00000003 /* status of output data transfer */ +#define I2S_AISTR_OTR 0x00000010 /* output transfer request pending */ +#define I2S_AISTR_OUR 0x00000020 /* output FIFO underrun detected */ +#define I2S_AISTR_OOR 0x00000040 /* output FIFO overrun detected */ +#define I2S_AISTR_ODS 0x00000100 /* output DMA transfer size */ +#define I2S_AISTR_ODE 0x00000400 /* output DMA transfer request enable */ +#define I2S_AISTR_OTRIE 0x00001000 /* output transfer request interrupt enable */ +#define I2S_AISTR_OURIE 0x00002000 /* output FIFO underrun interrupt enable */ +#define I2S_AISTR_OORIE 0x00004000 /* output FIFO overrun interrupt enable */ +#define I2S_AISTR__OUT_MASK 0x00007570 +#define I2S_AISTR_ITST 0x00030000 /* status of input data transfer */ +#define I2S_AISTR_ITST_SHIFT 16 +#define I2S_AISTR_ITR 0x00100000 /* input transfer request pending */ +#define I2S_AISTR_IUR 0x00200000 /* input FIFO underrun detected */ +#define I2S_AISTR_IOR 0x00400000 /* input FIFO overrun detected */ +#define I2S_AISTR_IDS 0x01000000 /* input DMA transfer size */ +#define I2S_AISTR_IDE 0x04000000 /* input DMA transfer request enable */ +#define I2S_AISTR_ITRIE 0x10000000 /* input transfer request interrupt enable */ +#define I2S_AISTR_IURIE 0x20000000 /* input FIFO underrun interrupt enable */ +#define I2S_AISTR_IORIE 0x40000000 /* input FIFO overrun interrupt enable */ +#define I2S_AISTR__IN_MASK 0x75700000 + +#define I2S_AICR_MI 0x00000001 /* mono input requested */ +#define I2S_AICR_AMI 0x00000002 /* relation between LRCKI/FS1 and SDI */ +#define I2S_AICR_LRI 0x00000004 /* function of LRCKI pin */ +#define I2S_AICR_SDMI 0x00000070 /* format of input audio data */ +#define I2S_AICR_SDMI_SHIFT 4 +#define I2S_AICR_CLI 0x00000080 /* input FIFO clearing control */ +#define I2S_AICR_IM 0x00000300 /* input state control */ +#define I2S_AICR_IM_SHIFT 8 +#define I2S_AICR__IN_MASK 0x000003f7 +#define I2S_AICR_MO 0x00001000 /* mono output requested */ +#define I2S_AICR_AMO 0x00002000 /* relation between LRCKO/FS0 and SDO */ +#define I2S_AICR_AMO_SHIFT 13 +#define I2S_AICR_LRO 0x00004000 /* function of LRCKO pin */ +#define I2S_AICR_SDMO 0x00070000 /* format of output audio data */ +#define I2S_AICR_SDMO_SHIFT 16 +#define I2S_AICR_CLO 0x00080000 /* output FIFO clearing control */ +#define I2S_AICR_OM 0x00100000 /* output state control */ +#define I2S_AICR__OUT_MASK 0x001f7000 +#define I2S_AICR_DIV 0x03000000 /* frequency division rate */ +#define I2S_AICR_DIV_SHIFT 24 +#define I2S_AICR_FL 0x20000000 /* frame length */ +#define I2S_AICR_FS 0x40000000 /* frame sync method */ +#define I2S_AICR_ME 0x80000000 /* master enable */ + +/* + * PCMCIA + */ +#define __addr_MB93493_PCMCIA(X) ((volatile unsigned long *)(__region_CS5 + (X))) + +/* + * GPIO + */ +#define __get_MB93493_GPIO_PDR(X) __get_MB93493(0x380 + (X) * 0xc0) +#define __set_MB93493_GPIO_PDR(X,V) __set_MB93493(0x380 + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_GPDR(X) __get_MB93493(0x384 + (X) * 0xc0) +#define __set_MB93493_GPIO_GPDR(X,V) __set_MB93493(0x384 + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_SIR(X) __get_MB93493(0x388 + (X) * 0xc0) +#define __set_MB93493_GPIO_SIR(X,V) __set_MB93493(0x388 + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_SOR(X) __get_MB93493(0x38c + (X) * 0xc0) +#define __set_MB93493_GPIO_SOR(X,V) __set_MB93493(0x38c + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_PDSR(X) __get_MB93493(0x390 + (X) * 0xc0) +#define __set_MB93493_GPIO_PDSR(X,V) __set_MB93493(0x390 + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_PDCR(X) __get_MB93493(0x394 + (X) * 0xc0) +#define __set_MB93493_GPIO_PDCR(X,V) __set_MB93493(0x394 + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_INTST(X) __get_MB93493(0x398 + (X) * 0xc0) +#define __set_MB93493_GPIO_INTST(X,V) __set_MB93493(0x398 + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_IEHL(X) __get_MB93493(0x39c + (X) * 0xc0) +#define __set_MB93493_GPIO_IEHL(X,V) __set_MB93493(0x39c + (X) * 0xc0, (V)) + +#define __get_MB93493_GPIO_IELH(X) __get_MB93493(0x3a0 + (X) * 0xc0) +#define __set_MB93493_GPIO_IELH(X,V) __set_MB93493(0x3a0 + (X) * 0xc0, (V)) + +#endif /* _ASM_MB93493_REGS_H */ diff --git a/arch/frv/include/asm/mc146818rtc.h b/arch/frv/include/asm/mc146818rtc.h new file mode 100644 index 00000000000..90dfb7a633d --- /dev/null +++ b/arch/frv/include/asm/mc146818rtc.h @@ -0,0 +1,16 @@ +/* mc146818rtc.h: RTC defs + * + * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MC146818RTC_H +#define _ASM_MC146818RTC_H + + +#endif /* _ASM_MC146818RTC_H */ diff --git a/arch/frv/include/asm/mem-layout.h b/arch/frv/include/asm/mem-layout.h new file mode 100644 index 00000000000..e9a0ec85a40 --- /dev/null +++ b/arch/frv/include/asm/mem-layout.h @@ -0,0 +1,86 @@ +/* mem-layout.h: memory layout + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MEM_LAYOUT_H +#define _ASM_MEM_LAYOUT_H + +#ifndef __ASSEMBLY__ +#define __UL(X) ((unsigned long) (X)) +#else +#define __UL(X) (X) +#endif + +/* + * PAGE_SHIFT determines the page size + */ +#define PAGE_SHIFT 14 + +#ifndef __ASSEMBLY__ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#else +#define PAGE_SIZE (1 << PAGE_SHIFT) +#endif + +#define PAGE_MASK (~(PAGE_SIZE-1)) + +/* + * the slab must be aligned such that load- and store-double instructions don't + * fault if used + */ +#define ARCH_DMA_MINALIGN L1_CACHE_BYTES +#define ARCH_SLAB_MINALIGN L1_CACHE_BYTES + +/*****************************************************************************/ +/* + * virtual memory layout from kernel's point of view + */ +#define PAGE_OFFSET ((unsigned long) &__page_offset) + +#ifdef CONFIG_MMU + +/* see Documentation/frv/mmu-layout.txt */ +#define KERNEL_LOWMEM_START __UL(0xc0000000) +#define KERNEL_LOWMEM_END __UL(0xd0000000) +#define VMALLOC_START __UL(0xd0000000) +#define VMALLOC_END __UL(0xd8000000) +#define PKMAP_BASE __UL(0xd8000000) +#define PKMAP_END __UL(0xdc000000) +#define KMAP_ATOMIC_SECONDARY_FRAME __UL(0xdc000000) +#define KMAP_ATOMIC_PRIMARY_FRAME __UL(0xdd000000) + +#endif + +#define KERNEL_IO_START __UL(0xe0000000) + + +/*****************************************************************************/ +/* + * memory layout from userspace's point of view + */ +#define BRK_BASE __UL(2 * 1024 * 1024 + PAGE_SIZE) +#define STACK_TOP __UL(2 * 1024 * 1024) +#define STACK_TOP_MAX __UL(0xc0000000) + +/* userspace process size */ +#ifdef CONFIG_MMU +#define TASK_SIZE (PAGE_OFFSET) +#else +#define TASK_SIZE __UL(0xFFFFFFFFUL) +#endif + +/* base of area at which unspecified mmaps will start */ +#ifdef CONFIG_BINFMT_ELF_FDPIC +#define TASK_UNMAPPED_BASE __UL(16 * 1024 * 1024) +#else +#define TASK_UNMAPPED_BASE __UL(TASK_SIZE / 3) +#endif + +#endif /* _ASM_MEM_LAYOUT_H */ diff --git a/arch/frv/include/asm/mmu.h b/arch/frv/include/asm/mmu.h new file mode 100644 index 00000000000..86ca0e86e7d --- /dev/null +++ b/arch/frv/include/asm/mmu.h @@ -0,0 +1,41 @@ +/* mmu.h: memory management context for FR-V with or without MMU support + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_MMU_H +#define _ASM_MMU_H + +typedef struct { +#ifdef CONFIG_MMU + struct list_head id_link; /* link in list of context ID owners */ + unsigned short id; /* MMU context ID */ + unsigned short id_busy; /* true if ID is in CXNR */ + unsigned long itlb_cached_pge; /* [SCR0] PGE cached for insn TLB handler */ + unsigned long itlb_ptd_mapping; /* [DAMR4] PTD mapping for itlb cached PGE */ + unsigned long dtlb_cached_pge; /* [SCR1] PGE cached for data TLB handler */ + unsigned long dtlb_ptd_mapping; /* [DAMR5] PTD mapping for dtlb cached PGE */ + +#else + unsigned long end_brk; + +#endif + +#ifdef CONFIG_BINFMT_ELF_FDPIC + unsigned long exec_fdpic_loadmap; + unsigned long interp_fdpic_loadmap; +#endif + +} mm_context_t; + +#ifdef CONFIG_MMU +extern int __nongpreldata cxn_pinned; +extern int cxn_pin_by_pid(pid_t pid); +#endif + +#endif /* _ASM_MMU_H */ diff --git a/arch/frv/include/asm/mmu_context.h b/arch/frv/include/asm/mmu_context.h new file mode 100644 index 00000000000..c7daa395156 --- /dev/null +++ b/arch/frv/include/asm/mmu_context.h @@ -0,0 +1,50 @@ +/* mmu_context.h: MMU context management routines + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_MMU_CONTEXT_H +#define _ASM_MMU_CONTEXT_H + +#include <asm/setup.h> +#include <asm/page.h> +#include <asm/pgalloc.h> +#include <asm-generic/mm_hooks.h> + +static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) +{ +} + +#ifdef CONFIG_MMU +extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); +extern void change_mm_context(mm_context_t *old, mm_context_t *ctx, pgd_t *_pgd); +extern void destroy_context(struct mm_struct *mm); + +#else +#define init_new_context(tsk, mm) ({ 0; }) +#define change_mm_context(old, ctx, _pml4) do {} while(0) +#define destroy_context(mm) do {} while(0) +#endif + +#define switch_mm(prev, next, tsk) \ +do { \ + if (prev != next) \ + change_mm_context(&prev->context, &next->context, next->pgd); \ +} while(0) + +#define activate_mm(prev, next) \ +do { \ + change_mm_context(&prev->context, &next->context, next->pgd); \ +} while(0) + +#define deactivate_mm(tsk, mm) \ +do { \ +} while(0) + +#endif diff --git a/arch/frv/include/asm/module.h b/arch/frv/include/asm/module.h new file mode 100644 index 00000000000..a8848f09a21 --- /dev/null +++ b/arch/frv/include/asm/module.h @@ -0,0 +1,22 @@ +/* module.h: FRV module stuff + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_MODULE_H +#define _ASM_MODULE_H + +#include <asm-generic/module.h> + +/* + * Include the architecture version. + */ +#define MODULE_ARCH_VERMAGIC __stringify(PROCESSOR_MODEL_NAME) " " + +#endif /* _ASM_MODULE_H */ + diff --git a/arch/frv/include/asm/mutex.h b/arch/frv/include/asm/mutex.h new file mode 100644 index 00000000000..458c1f7fbc1 --- /dev/null +++ b/arch/frv/include/asm/mutex.h @@ -0,0 +1,9 @@ +/* + * Pull in the generic implementation for the mutex fastpath. + * + * TODO: implement optimized primitives instead, or leave the generic + * implementation in place, or pick the atomic_xchg() based generic + * implementation. (see asm-generic/mutex-xchg.h for details) + */ + +#include <asm-generic/mutex-dec.h> diff --git a/arch/frv/include/asm/page.h b/arch/frv/include/asm/page.h new file mode 100644 index 00000000000..8c97068ac8f --- /dev/null +++ b/arch/frv/include/asm/page.h @@ -0,0 +1,76 @@ +#ifndef _ASM_PAGE_H +#define _ASM_PAGE_H + +#include <asm/virtconvert.h> +#include <asm/mem-layout.h> +#include <asm/sections.h> +#include <asm/setup.h> + +#ifndef __ASSEMBLY__ + +#define get_user_page(vaddr) __get_free_page(GFP_KERNEL) +#define free_user_page(page, addr) free_page(addr) + +#define clear_page(pgaddr) memset((pgaddr), 0, PAGE_SIZE) +#define copy_page(to,from) memcpy((to), (from), PAGE_SIZE) + +#define clear_user_page(pgaddr, vaddr, page) memset((pgaddr), 0, PAGE_SIZE) +#define copy_user_page(vto, vfrom, vaddr, topg) memcpy((vto), (vfrom), PAGE_SIZE) + +/* + * These are used to make use of C type-checking.. + */ +typedef struct { unsigned long pte; } pte_t; +typedef struct { unsigned long ste[64];} pmd_t; +typedef struct { pmd_t pue[1]; } pud_t; +typedef struct { pud_t pge[1]; } pgd_t; +typedef struct { unsigned long pgprot; } pgprot_t; +typedef struct page *pgtable_t; + +#define pte_val(x) ((x).pte) +#define pmd_val(x) ((x).ste[0]) +#define pud_val(x) ((x).pue[0]) +#define pgd_val(x) ((x).pge[0]) +#define pgprot_val(x) ((x).pgprot) + +#define __pte(x) ((pte_t) { (x) } ) +#define __pmd(x) ((pmd_t) { (x) } ) +#define __pud(x) ((pud_t) { (x) } ) +#define __pgd(x) ((pgd_t) { (x) } ) +#define __pgprot(x) ((pgprot_t) { (x) } ) +#define PTE_MASK PAGE_MASK + +#define devmem_is_allowed(pfn) 1 + +#define __pa(vaddr) virt_to_phys((void *) (unsigned long) (vaddr)) +#define __va(paddr) phys_to_virt((unsigned long) (paddr)) + +#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) + +extern unsigned long max_low_pfn; +extern unsigned long min_low_pfn; +extern unsigned long max_pfn; + +#ifdef CONFIG_MMU +#define pfn_valid(pfn) ((pfn) < max_mapnr) +#else +#define ARCH_PFN_OFFSET (PAGE_OFFSET >> PAGE_SHIFT) +#define pfn_valid(pfn) ((pfn) >= min_low_pfn && (pfn) < max_low_pfn) + +#endif + +#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) +#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) + + +#define VM_DATA_DEFAULT_FLAGS \ + (VM_READ | VM_WRITE | \ + ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +#endif /* __ASSEMBLY__ */ + +#include <asm-generic/memory_model.h> +#include <asm-generic/getorder.h> + +#endif /* _ASM_PAGE_H */ diff --git a/arch/frv/include/asm/pci.h b/arch/frv/include/asm/pci.h new file mode 100644 index 00000000000..2035a4d3f9b --- /dev/null +++ b/arch/frv/include/asm/pci.h @@ -0,0 +1,61 @@ +/* pci.h: FR-V specific PCI declarations + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * - Derived from include/asm-m68k/pci.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_FRV_PCI_H +#define _ASM_FRV_PCI_H + +#include <linux/mm.h> +#include <asm/scatterlist.h> +#include <asm-generic/pci-dma-compat.h> +#include <asm-generic/pci.h> + +struct pci_dev; + +#define pcibios_assign_all_busses() 0 + +extern void pcibios_set_master(struct pci_dev *dev); + +#ifdef CONFIG_MMU +extern void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle); +extern void consistent_free(void *vaddr); +extern void consistent_sync(void *vaddr, size_t size, int direction); +extern void consistent_sync_page(struct page *page, unsigned long offset, + size_t size, int direction); +#endif + +extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle); + +extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle); + +/* Return the index of the PCI controller for device PDEV. */ +#define pci_controller_num(PDEV) (0) + +#ifdef CONFIG_PCI +static inline void pci_dma_burst_advice(struct pci_dev *pdev, + enum pci_dma_burst_strategy *strat, + unsigned long *strategy_parameter) +{ + *strat = PCI_DMA_BURST_INFINITY; + *strategy_parameter = ~0UL; +} +#endif + +/* + * These are pretty much arbitrary with the CoMEM implementation. + * We have the whole address space to ourselves. + */ +#define PCIBIOS_MIN_IO 0x100 +#define PCIBIOS_MIN_MEM 0x00010000 + +#endif /* _ASM_FRV_PCI_H */ diff --git a/arch/frv/include/asm/percpu.h b/arch/frv/include/asm/percpu.h new file mode 100644 index 00000000000..2cad3f874de --- /dev/null +++ b/arch/frv/include/asm/percpu.h @@ -0,0 +1,6 @@ +#ifndef __ASM_PERCPU_H +#define __ASM_PERCPU_H + +#include <asm-generic/percpu.h> + +#endif /* __ASM_PERCPU_H */ diff --git a/arch/frv/include/asm/perf_event.h b/arch/frv/include/asm/perf_event.h new file mode 100644 index 00000000000..c52ea5546b5 --- /dev/null +++ b/arch/frv/include/asm/perf_event.h @@ -0,0 +1,15 @@ +/* FRV performance event support + * + * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_PERF_EVENT_H +#define _ASM_PERF_EVENT_H + +#endif /* _ASM_PERF_EVENT_H */ diff --git a/arch/frv/include/asm/pgalloc.h b/arch/frv/include/asm/pgalloc.h new file mode 100644 index 00000000000..416d19a632f --- /dev/null +++ b/arch/frv/include/asm/pgalloc.h @@ -0,0 +1,69 @@ +/* pgalloc.h: Page allocation routines for FRV + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Derived from: + * include/asm-m68knommu/pgalloc.h + * include/asm-i386/pgalloc.h + */ +#ifndef _ASM_PGALLOC_H +#define _ASM_PGALLOC_H + +#include <asm/setup.h> +#include <asm/virtconvert.h> + +#ifdef CONFIG_MMU + +#define pmd_populate_kernel(mm, pmd, pte) __set_pmd(pmd, __pa(pte) | _PAGE_TABLE) +#define pmd_populate(MM, PMD, PAGE) \ +do { \ + __set_pmd((PMD), page_to_pfn(PAGE) << PAGE_SHIFT | _PAGE_TABLE); \ +} while(0) +#define pmd_pgtable(pmd) pmd_page(pmd) + +/* + * Allocate and free page tables. + */ + +extern pgd_t *pgd_alloc(struct mm_struct *); +extern void pgd_free(struct mm_struct *mm, pgd_t *); + +extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long); + +extern pgtable_t pte_alloc_one(struct mm_struct *, unsigned long); + +static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) +{ + free_page((unsigned long)pte); +} + +static inline void pte_free(struct mm_struct *mm, pgtable_t pte) +{ + pgtable_page_dtor(pte); + __free_page(pte); +} + +#define __pte_free_tlb(tlb,pte,address) \ +do { \ + pgtable_page_dtor(pte); \ + tlb_remove_page((tlb),(pte)); \ +} while (0) + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + * (In the PAE case we free the pmds as part of the pgd.) + */ +#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *) 2); }) +#define pmd_free(mm, x) do { } while (0) +#define __pmd_free_tlb(tlb,x,a) do { } while (0) + +#endif /* CONFIG_MMU */ + +#endif /* _ASM_PGALLOC_H */ diff --git a/arch/frv/include/asm/pgtable.h b/arch/frv/include/asm/pgtable.h new file mode 100644 index 00000000000..eb0110acd19 --- /dev/null +++ b/arch/frv/include/asm/pgtable.h @@ -0,0 +1,541 @@ +/* pgtable.h: FR-V page table mangling + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Derived from: + * include/asm-m68knommu/pgtable.h + * include/asm-i386/pgtable.h + */ + +#ifndef _ASM_PGTABLE_H +#define _ASM_PGTABLE_H + +#include <asm/mem-layout.h> +#include <asm/setup.h> +#include <asm/processor.h> + +#ifndef __ASSEMBLY__ +#include <linux/threads.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/sched.h> +struct vm_area_struct; +#endif + +#ifndef __ASSEMBLY__ +#if defined(CONFIG_HIGHPTE) +typedef unsigned long pte_addr_t; +#else +typedef pte_t *pte_addr_t; +#endif +#endif + +/*****************************************************************************/ +/* + * MMU-less operation case first + */ +#ifndef CONFIG_MMU + +#define pgd_present(pgd) (1) /* pages are always present on NO_MM */ +#define pgd_none(pgd) (0) +#define pgd_bad(pgd) (0) +#define pgd_clear(pgdp) +#define kern_addr_valid(addr) (1) +#define pmd_offset(a, b) ((void *) 0) + +#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */ +#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */ +#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */ +#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */ +#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */ + +#define __swp_type(x) (0) +#define __swp_offset(x) (0) +#define __swp_entry(typ,off) ((swp_entry_t) { ((typ) | ((off) << 7)) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + +#ifndef __ASSEMBLY__ +static inline int pte_file(pte_t pte) { return 0; } +#endif + +#define ZERO_PAGE(vaddr) ({ BUG(); NULL; }) + +#define swapper_pg_dir ((pgd_t *) NULL) + +#define pgtable_cache_init() do {} while (0) + +#include <asm-generic/pgtable.h> + +#else /* !CONFIG_MMU */ +/*****************************************************************************/ +/* + * then MMU operation + */ + +/* + * ZERO_PAGE is a global shared page that is always zero: used + * for zero-mapped memory areas etc.. + */ +#ifndef __ASSEMBLY__ +extern unsigned long empty_zero_page; +#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page) +#endif + +/* + * we use 2-level page tables, folding the PMD (mid-level table) into the PGE (top-level entry) + * [see Documentation/frv/mmu-layout.txt] + * + * Page Directory: + * - Size: 16KB + * - 64 PGEs per PGD + * - Each PGE holds 1 PUD and covers 64MB + * + * Page Upper Directory: + * - Size: 256B + * - 1 PUE per PUD + * - Each PUE holds 1 PMD and covers 64MB + * + * Page Mid-Level Directory + * - Size: 256B + * - 1 PME per PMD + * - Each PME holds 64 STEs, all of which point to separate chunks of the same Page Table + * - All STEs are instantiated at the same time + * + * Page Table + * - Size: 16KB + * - 4096 PTEs per PT + * - Each Linux PT is subdivided into 64 FR451 PT's, each of which holds 64 entries + * + * Pages + * - Size: 4KB + * + * total PTEs + * = 1 PML4E * 64 PGEs * 1 PUEs * 1 PMEs * 4096 PTEs + * = 1 PML4E * 64 PGEs * 64 STEs * 64 PTEs/FR451-PT + * = 262144 (or 256 * 1024) + */ +#define PGDIR_SHIFT 26 +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) +#define PGDIR_MASK (~(PGDIR_SIZE - 1)) +#define PTRS_PER_PGD 64 + +#define PUD_SHIFT 26 +#define PTRS_PER_PUD 1 +#define PUD_SIZE (1UL << PUD_SHIFT) +#define PUD_MASK (~(PUD_SIZE - 1)) +#define PUE_SIZE 256 + +#define PMD_SHIFT 26 +#define PMD_SIZE (1UL << PMD_SHIFT) +#define PMD_MASK (~(PMD_SIZE - 1)) +#define PTRS_PER_PMD 1 +#define PME_SIZE 256 + +#define __frv_PT_SIZE 256 + +#define PTRS_PER_PTE 4096 + +#define USER_PGDS_IN_LAST_PML4 (TASK_SIZE / PGDIR_SIZE) +#define FIRST_USER_ADDRESS 0 + +#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT) +#define KERNEL_PGD_PTRS (PTRS_PER_PGD - USER_PGD_PTRS) + +#define TWOLEVEL_PGDIR_SHIFT 26 +#define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT) +#define BOOT_KERNEL_PGD_PTRS (PTRS_PER_PGD - BOOT_USER_PGD_PTRS) + +#ifndef __ASSEMBLY__ + +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte) +#define pmd_ERROR(e) \ + printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e)) +#define pud_ERROR(e) \ + printk("%s:%d: bad pud %08lx.\n", __FILE__, __LINE__, pmd_val(pud_val(e))) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pmd_val(pud_val(pgd_val(e)))) + +/* + * Certain architectures need to do special things when PTEs + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +#define set_pte(pteptr, pteval) \ +do { \ + *(pteptr) = (pteval); \ + asm volatile("dcf %M0" :: "U"(*pteptr)); \ +} while(0) +#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) + +/* + * 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 + pgd_index(address)) + +/* + * 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) + +/* + * The "pgd_xxx()" functions here are trivial for a folded two-level + * setup: the pud is never bad, and a pud always exists (as it's folded + * into the pgd entry) + */ +static inline int pgd_none(pgd_t pgd) { return 0; } +static inline int pgd_bad(pgd_t pgd) { return 0; } +static inline int pgd_present(pgd_t pgd) { return 1; } +static inline void pgd_clear(pgd_t *pgd) { } + +#define pgd_populate(mm, pgd, pud) do { } while (0) +/* + * (puds are folded into pgds so this doesn't get actually called, + * but the define is needed for a generic inline function.) + */ +#define set_pgd(pgdptr, pgdval) \ +do { \ + memcpy((pgdptr), &(pgdval), sizeof(pgd_t)); \ + asm volatile("dcf %M0" :: "U"(*(pgdptr))); \ +} while(0) + +static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address) +{ + return (pud_t *) pgd; +} + +#define pgd_page(pgd) (pud_page((pud_t){ pgd })) +#define pgd_page_vaddr(pgd) (pud_page_vaddr((pud_t){ pgd })) + +/* + * allocating and freeing a pud is trivial: the 1-entry pud is + * inside the pgd, so has no extra memory associated with it. + */ +#define pud_alloc_one(mm, address) NULL +#define pud_free(mm, x) do { } while (0) +#define __pud_free_tlb(tlb, x, address) do { } while (0) + +/* + * The "pud_xxx()" functions here are trivial for a folded two-level + * setup: the pmd is never bad, and a pmd always exists (as it's folded + * into the pud entry) + */ +static inline int pud_none(pud_t pud) { return 0; } +static inline int pud_bad(pud_t pud) { return 0; } +static inline int pud_present(pud_t pud) { return 1; } +static inline void pud_clear(pud_t *pud) { } + +#define pud_populate(mm, pmd, pte) do { } while (0) + +/* + * (pmds are folded into puds so this doesn't get actually called, + * but the define is needed for a generic inline function.) + */ +#define set_pud(pudptr, pudval) set_pmd((pmd_t *)(pudptr), (pmd_t) { pudval }) + +#define pud_page(pud) (pmd_page((pmd_t){ pud })) +#define pud_page_vaddr(pud) (pmd_page_vaddr((pmd_t){ pud })) + +/* + * (pmds are folded into pgds so this doesn't get actually called, + * but the define is needed for a generic inline function.) + */ +extern void __set_pmd(pmd_t *pmdptr, unsigned long __pmd); + +#define set_pmd(pmdptr, pmdval) \ +do { \ + __set_pmd((pmdptr), (pmdval).ste[0]); \ +} while(0) + +#define __pmd_index(address) 0 + +static inline pmd_t *pmd_offset(pud_t *dir, unsigned long address) +{ + return (pmd_t *) dir + __pmd_index(address); +} + +#define pte_same(a, b) ((a).pte == (b).pte) +#define pte_page(x) (mem_map + ((unsigned long)(((x).pte >> PAGE_SHIFT)))) +#define pte_none(x) (!(x).pte) +#define pte_pfn(x) ((unsigned long)(((x).pte >> PAGE_SHIFT))) +#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) + +#define VMALLOC_VMADDR(x) ((unsigned long) (x)) + +#endif /* !__ASSEMBLY__ */ + +/* + * control flags in AMPR registers and TLB entries + */ +#define _PAGE_BIT_PRESENT xAMPRx_V_BIT +#define _PAGE_BIT_WP DAMPRx_WP_BIT +#define _PAGE_BIT_NOCACHE xAMPRx_C_BIT +#define _PAGE_BIT_SUPER xAMPRx_S_BIT +#define _PAGE_BIT_ACCESSED xAMPRx_RESERVED8_BIT +#define _PAGE_BIT_DIRTY xAMPRx_M_BIT +#define _PAGE_BIT_NOTGLOBAL xAMPRx_NG_BIT + +#define _PAGE_PRESENT xAMPRx_V +#define _PAGE_WP DAMPRx_WP +#define _PAGE_NOCACHE xAMPRx_C +#define _PAGE_SUPER xAMPRx_S +#define _PAGE_ACCESSED xAMPRx_RESERVED8 /* accessed if set */ +#define _PAGE_DIRTY xAMPRx_M +#define _PAGE_NOTGLOBAL xAMPRx_NG + +#define _PAGE_RESERVED_MASK (xAMPRx_RESERVED8 | xAMPRx_RESERVED13) + +#define _PAGE_FILE 0x002 /* set:pagecache unset:swap */ +#define _PAGE_PROTNONE 0x000 /* If not present */ + +#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) + +#define __PGPROT_BASE \ + (_PAGE_PRESENT | xAMPRx_SS_16Kb | xAMPRx_D | _PAGE_NOTGLOBAL | _PAGE_ACCESSED) + +#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) +#define PAGE_SHARED __pgprot(__PGPROT_BASE) +#define PAGE_COPY __pgprot(__PGPROT_BASE | _PAGE_WP) +#define PAGE_READONLY __pgprot(__PGPROT_BASE | _PAGE_WP) + +#define __PAGE_KERNEL (__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY) +#define __PAGE_KERNEL_NOCACHE (__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY | _PAGE_NOCACHE) +#define __PAGE_KERNEL_RO (__PGPROT_BASE | _PAGE_SUPER | _PAGE_DIRTY | _PAGE_WP) + +#define MAKE_GLOBAL(x) __pgprot((x) & ~_PAGE_NOTGLOBAL) + +#define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL) +#define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO) +#define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE) + +#define _PAGE_TABLE (_PAGE_PRESENT | xAMPRx_SS_16Kb) + +#ifndef __ASSEMBLY__ + +/* + * The FR451 can do execute protection by virtue of having separate TLB miss handlers for + * instruction access and for data access. However, we don't have enough reserved bits to say + * "execute only", so we don't bother. If you can read it, you can execute it and vice versa. + */ +#define __P000 PAGE_NONE +#define __P001 PAGE_READONLY +#define __P010 PAGE_COPY +#define __P011 PAGE_COPY +#define __P100 PAGE_READONLY +#define __P101 PAGE_READONLY +#define __P110 PAGE_COPY +#define __P111 PAGE_COPY + +#define __S000 PAGE_NONE +#define __S001 PAGE_READONLY +#define __S010 PAGE_SHARED +#define __S011 PAGE_SHARED +#define __S100 PAGE_READONLY +#define __S101 PAGE_READONLY +#define __S110 PAGE_SHARED +#define __S111 PAGE_SHARED + +/* + * Define this to warn about kernel memory accesses that are + * done without a 'access_ok(VERIFY_WRITE,..)' + */ +#undef TEST_ACCESS_OK + +#define pte_present(x) (pte_val(x) & _PAGE_PRESENT) +#define pte_clear(mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0) + +#define pmd_none(x) (!pmd_val(x)) +#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) +#define pmd_bad(x) (pmd_val(x) & xAMPRx_SS) +#define pmd_clear(xp) do { __set_pmd(xp, 0); } while(0) + +#define pmd_page_vaddr(pmd) \ + ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) + +#ifndef CONFIG_DISCONTIGMEM +#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) +#endif + +#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +static inline int pte_dirty(pte_t pte) { return (pte).pte & _PAGE_DIRTY; } +static inline int pte_young(pte_t pte) { return (pte).pte & _PAGE_ACCESSED; } +static inline int pte_write(pte_t pte) { return !((pte).pte & _PAGE_WP); } +static inline int pte_special(pte_t pte) { return 0; } + +static inline pte_t pte_mkclean(pte_t pte) { (pte).pte &= ~_PAGE_DIRTY; return pte; } +static inline pte_t pte_mkold(pte_t pte) { (pte).pte &= ~_PAGE_ACCESSED; return pte; } +static inline pte_t pte_wrprotect(pte_t pte) { (pte).pte |= _PAGE_WP; return pte; } +static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte |= _PAGE_DIRTY; return pte; } +static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte |= _PAGE_ACCESSED; return pte; } +static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte &= ~_PAGE_WP; return pte; } +static inline pte_t pte_mkspecial(pte_t pte) { return pte; } + +static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) +{ + int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); + asm volatile("dcf %M0" :: "U"(*ptep)); + return i; +} + +static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + unsigned long x = xchg(&ptep->pte, 0); + asm volatile("dcf %M0" :: "U"(*ptep)); + return __pte(x); +} + +static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) +{ + set_bit(_PAGE_BIT_WP, ptep); + asm volatile("dcf %M0" :: "U"(*ptep)); +} + +/* + * Macro to mark a page protection value as "uncacheable" + */ +#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_NOCACHE)) + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + */ + +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) +#define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE) + +/* This takes a physical page address that is used by the remapping functions */ +#define mk_pte_phys(physpage, pgprot) pfn_pte((physpage) >> PAGE_SHIFT, pgprot) + +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte.pte &= _PAGE_CHG_MASK; + pte.pte |= pgprot_val(newprot); + return pte; +} + +/* to find an entry in a page-table-directory. */ +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) +#define pgd_index_k(addr) pgd_index(addr) + +/* Find an entry in the bottom-level page table.. */ +#define __pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) + +/* + * 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_vaddr(*(dir)) + pte_index(address)) + +#if defined(CONFIG_HIGHPTE) +#define pte_offset_map(dir, address) \ + ((pte_t *)kmap_atomic(pmd_page(*(dir))) + pte_index(address)) +#define pte_unmap(pte) kunmap_atomic(pte) +#else +#define pte_offset_map(dir, address) \ + ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) +#define pte_unmap(pte) do { } while (0) +#endif + +/* + * Handle swap and file entries + * - the PTE is encoded in the following format: + * bit 0: Must be 0 (!_PAGE_PRESENT) + * bit 1: Type: 0 for swap, 1 for file (_PAGE_FILE) + * bits 2-7: Swap type + * bits 8-31: Swap offset + * bits 2-31: File pgoff + */ +#define __swp_type(x) (((x).val >> 2) & 0x1f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 8) }) +#define __pte_to_swp_entry(_pte) ((swp_entry_t) { (_pte).pte }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + +static inline int pte_file(pte_t pte) +{ + return pte.pte & _PAGE_FILE; +} + +#define PTE_FILE_MAX_BITS 29 + +#define pte_to_pgoff(PTE) ((PTE).pte >> 2) +#define pgoff_to_pte(off) __pte((off) << 2 | _PAGE_FILE) + +/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ +#define PageSkip(page) (0) +#define kern_addr_valid(addr) (1) + +#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG +#define __HAVE_ARCH_PTEP_GET_AND_CLEAR +#define __HAVE_ARCH_PTEP_SET_WRPROTECT +#define __HAVE_ARCH_PTE_SAME +#include <asm-generic/pgtable.h> + +/* + * preload information about a newly instantiated PTE into the SCR0/SCR1 PGE cache + */ +static inline void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) +{ + struct mm_struct *mm; + unsigned long ampr; + + mm = current->mm; + if (mm) { + pgd_t *pge = pgd_offset(mm, address); + pud_t *pue = pud_offset(pge, address); + pmd_t *pme = pmd_offset(pue, address); + + ampr = pme->ste[0] & 0xffffff00; + ampr |= xAMPRx_L | xAMPRx_SS_16Kb | xAMPRx_S | xAMPRx_C | + xAMPRx_V; + } else { + address = ULONG_MAX; + ampr = 0; + } + + asm volatile("movgs %0,scr0\n" + "movgs %0,scr1\n" + "movgs %1,dampr4\n" + "movgs %1,dampr5\n" + : + : "r"(address), "r"(ampr) + ); +} + +#ifdef CONFIG_PROC_FS +extern char *proc_pid_status_frv_cxnr(struct mm_struct *mm, char *buffer); +#endif + +extern void __init pgtable_cache_init(void); + +#endif /* !__ASSEMBLY__ */ +#endif /* !CONFIG_MMU */ + +#ifndef __ASSEMBLY__ +extern void __init paging_init(void); +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_PGTABLE_H */ diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h new file mode 100644 index 00000000000..a34f309e580 --- /dev/null +++ b/arch/frv/include/asm/processor.h @@ -0,0 +1,142 @@ +/* processor.h: FRV processor definitions + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_PROCESSOR_H +#define _ASM_PROCESSOR_H + +#include <asm/mem-layout.h> + +#ifndef __ASSEMBLY__ +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l;}) + +#include <linux/compiler.h> +#include <linux/linkage.h> +#include <asm/sections.h> +#include <asm/segment.h> +#include <asm/fpu.h> +#include <asm/registers.h> +#include <asm/ptrace.h> +#include <asm/current.h> +#include <asm/cache.h> + +/* Forward declaration, a strange C thing */ +struct task_struct; + +/* + * CPU type and hardware bug flags. Kept separately for each CPU. + */ +struct cpuinfo_frv { +#ifdef CONFIG_MMU + unsigned long *pgd_quick; + unsigned long *pte_quick; + unsigned long pgtable_cache_sz; +#endif +} __cacheline_aligned; + +extern struct cpuinfo_frv __nongprelbss boot_cpu_data; + +#define cpu_data (&boot_cpu_data) +#define current_cpu_data boot_cpu_data + +/* + * Bus types + */ +#define EISA_bus 0 + +struct thread_struct { + struct pt_regs *frame; /* [GR28] exception frame ptr for this thread */ + struct task_struct *curr; /* [GR29] current pointer for this thread */ + unsigned long sp; /* [GR1 ] kernel stack pointer */ + unsigned long fp; /* [GR2 ] kernel frame pointer */ + unsigned long lr; /* link register */ + unsigned long pc; /* program counter */ + unsigned long gr[12]; /* [GR16-GR27] */ + unsigned long sched_lr; /* LR from schedule() */ + + union { + struct pt_regs *frame0; /* top (user) stack frame */ + struct user_context *user; /* userspace context */ + }; +} __attribute__((aligned(8))); + +extern struct pt_regs *__kernel_frame0_ptr; +extern struct task_struct *__kernel_current_task; + +#endif + +#ifndef __ASSEMBLY__ +#define INIT_THREAD_FRAME0 \ + ((struct pt_regs *) \ + (sizeof(init_stack) + (unsigned long) init_stack - sizeof(struct user_context))) + +#define INIT_THREAD { \ + NULL, \ + (struct task_struct *) init_stack, \ + 0, 0, 0, 0, \ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, \ + 0, \ + { INIT_THREAD_FRAME0 }, \ +} + +/* + * do necessary setup to start up a newly executed thread. + */ +#define start_thread(_regs, _pc, _usp) \ +do { \ + _regs->pc = (_pc); \ + _regs->psr &= ~PSR_S; \ + _regs->sp = (_usp); \ +} while(0) + +/* Free all resources held by a thread. */ +static inline void release_thread(struct task_struct *dead_task) +{ +} + +extern asmlinkage void save_user_regs(struct user_context *target); +extern asmlinkage void *restore_user_regs(const struct user_context *target, ...); + +#define copy_segments(tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) +#define forget_segments() do { } while (0) + +/* + * Free current thread data structures etc.. + */ +static inline void exit_thread(void) +{ +} + +/* + * Return saved PC of a blocked thread. + */ +extern unsigned long thread_saved_pc(struct task_struct *tsk); + +unsigned long get_wchan(struct task_struct *p); + +#define KSTK_EIP(tsk) ((tsk)->thread.frame0->pc) +#define KSTK_ESP(tsk) ((tsk)->thread.frame0->sp) + +#define cpu_relax() barrier() + +/* data cache prefetch */ +#define ARCH_HAS_PREFETCH +static inline void prefetch(const void *x) +{ + asm volatile("dcpl %0,gr0,#0" : : "r"(x)); +} + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_PROCESSOR_H */ diff --git a/arch/frv/include/asm/ptrace.h b/arch/frv/include/asm/ptrace.h new file mode 100644 index 00000000000..034f1793419 --- /dev/null +++ b/arch/frv/include/asm/ptrace.h @@ -0,0 +1,41 @@ +/* ptrace.h: ptrace() relevant definitions + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_PTRACE_H +#define _ASM_PTRACE_H + +#include <asm/irq_regs.h> +#include <uapi/asm/ptrace.h> + +#define in_syscall(regs) (((regs)->tbr & TBR_TT) == TBR_TT_TRAP0) +#ifndef __ASSEMBLY__ + +struct task_struct; + +/* + * we dedicate GR28 to keeping a pointer to the current exception frame + * - gr28 is destroyed on entry to the kernel from userspace + */ +register struct pt_regs *__frame asm("gr28"); + +#define user_mode(regs) (!((regs)->psr & PSR_S)) +#define instruction_pointer(regs) ((regs)->pc) +#define user_stack_pointer(regs) ((regs)->sp) +#define current_pt_regs() (__frame) + +extern unsigned long user_stack(const struct pt_regs *); +#define profile_pc(regs) ((regs)->pc) + +#define task_pt_regs(task) ((task)->thread.frame0) + +#define arch_has_single_step() (1) + +#endif /* !__ASSEMBLY__ */ +#endif /* _ASM_PTRACE_H */ diff --git a/arch/frv/include/asm/scatterlist.h b/arch/frv/include/asm/scatterlist.h new file mode 100644 index 00000000000..0e5eb301846 --- /dev/null +++ b/arch/frv/include/asm/scatterlist.h @@ -0,0 +1,6 @@ +#ifndef _ASM_SCATTERLIST_H +#define _ASM_SCATTERLIST_H + +#include <asm-generic/scatterlist.h> + +#endif /* !_ASM_SCATTERLIST_H */ diff --git a/arch/frv/include/asm/sections.h b/arch/frv/include/asm/sections.h new file mode 100644 index 00000000000..17d0fb171bb --- /dev/null +++ b/arch/frv/include/asm/sections.h @@ -0,0 +1,46 @@ +/* sections.h: linkage layout variables + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_SECTIONS_H +#define _ASM_SECTIONS_H + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> +#include <asm-generic/sections.h> + +#ifdef __KERNEL__ + +/* + * we don't want to put variables in the GP-REL section if they're not used very much - that would + * be waste since GP-REL addressing is limited to GP16+/-2048 + */ +#define __nongpreldata __attribute__((section(".data"))) +#define __nongprelbss __attribute__((section(".bss"))) + +/* + * linker symbols + */ +extern const void __kernel_image_start, __kernel_image_end, __page_offset; + +extern unsigned long __nongprelbss memory_start; +extern unsigned long __nongprelbss memory_end; +extern unsigned long __nongprelbss rom_length; + +/* determine if we're running from ROM */ +static inline int is_in_rom(unsigned long addr) +{ + return 0; /* default case: not in ROM */ +} + +#endif +#endif +#endif /* _ASM_SECTIONS_H */ diff --git a/arch/frv/include/asm/segment.h b/arch/frv/include/asm/segment.h new file mode 100644 index 00000000000..a2320a4a004 --- /dev/null +++ b/arch/frv/include/asm/segment.h @@ -0,0 +1,45 @@ +/* segment.h: MMU segment settings + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_SEGMENT_H +#define _ASM_SEGMENT_H + + +#ifndef __ASSEMBLY__ + +typedef struct { + unsigned long seg; +} mm_segment_t; + +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) + +#ifdef CONFIG_MMU +#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) +#define KERNEL_DS MAKE_MM_SEG(0xdfffffffUL) +#else +#define USER_DS MAKE_MM_SEG(memory_end) +#define KERNEL_DS MAKE_MM_SEG(0xe0000000UL) +#endif + +#define get_ds() (KERNEL_DS) +#define get_fs() (__current_thread_info->addr_limit) +#define segment_eq(a,b) ((a).seg == (b).seg) +#define __kernel_ds_p() segment_eq(get_fs(), KERNEL_DS) +#define get_addr_limit() (get_fs().seg) + +#define set_fs(_x) \ +do { \ + __current_thread_info->addr_limit = (_x); \ +} while(0) + + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_SEGMENT_H */ diff --git a/arch/frv/include/asm/serial-regs.h b/arch/frv/include/asm/serial-regs.h new file mode 100644 index 00000000000..e1286bda00e --- /dev/null +++ b/arch/frv/include/asm/serial-regs.h @@ -0,0 +1,44 @@ +/* serial-regs.h: serial port registers + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_SERIAL_REGS_H +#define _ASM_SERIAL_REGS_H + +#include <linux/serial_reg.h> +#include <asm/irc-regs.h> + +#define SERIAL_ICLK 33333333 /* the target serial input clock */ +#define UART0_BASE 0xfeff9c00 +#define UART1_BASE 0xfeff9c40 + +#define __get_UART0(R) ({ __reg(UART0_BASE + (R) * 8) >> 24; }) +#define __get_UART1(R) ({ __reg(UART1_BASE + (R) * 8) >> 24; }) +#define __set_UART0(R,V) do { __reg(UART0_BASE + (R) * 8) = (V) << 24; } while(0) +#define __set_UART1(R,V) do { __reg(UART1_BASE + (R) * 8) = (V) << 24; } while(0) + +#define __get_UART0_LSR() ({ __get_UART0(UART_LSR); }) +#define __get_UART1_LSR() ({ __get_UART1(UART_LSR); }) + +#define __set_UART0_IER(V) __set_UART0(UART_IER,(V)) +#define __set_UART1_IER(V) __set_UART1(UART_IER,(V)) + +/* serial prescaler select register */ +#define __get_UCPSR() ({ *(volatile unsigned long *)(0xfeff9c90); }) +#define __set_UCPSR(V) do { *(volatile unsigned long *)(0xfeff9c90) = (V); } while(0) +#define UCPSR_SELECT0 0x07000000 +#define UCPSR_SELECT1 0x38000000 + +/* serial prescaler base value register */ +#define __get_UCPVR() ({ *(volatile unsigned long *)(0xfeff9c98); mb(); }) +#define __set_UCPVR(V) do { *(volatile unsigned long *)(0xfeff9c98) = (V) << 24; mb(); } while(0) + + +#endif /* _ASM_SERIAL_REGS_H */ diff --git a/arch/frv/include/asm/serial.h b/arch/frv/include/asm/serial.h new file mode 100644 index 00000000000..dbb82599868 --- /dev/null +++ b/arch/frv/include/asm/serial.h @@ -0,0 +1,18 @@ +/* + * serial.h + * + * Copyright (C) 2003 Develer S.r.l. (http://www.develer.com/) + * Author: Bernardo Innocenti <bernie@codewiz.org> + * + * Based on linux/include/asm-i386/serial.h + */ +#include <asm/serial-regs.h> + +/* + * the base baud is derived from the clock speed and so is variable + */ +#define BASE_BAUD 0 + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +#define SERIAL_PORT_DFNS diff --git a/arch/frv/include/asm/setup.h b/arch/frv/include/asm/setup.h new file mode 100644 index 00000000000..aa76f2eac09 --- /dev/null +++ b/arch/frv/include/asm/setup.h @@ -0,0 +1,26 @@ +/* setup.h: setup stuff + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_SETUP_H +#define _ASM_SETUP_H + + +#include <linux/init.h> +#include <uapi/asm/setup.h> + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_MMU +extern unsigned long __initdata num_mappedpages; +#endif + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_SETUP_H */ diff --git a/arch/frv/include/asm/shmparam.h b/arch/frv/include/asm/shmparam.h new file mode 100644 index 00000000000..ab711009cfa --- /dev/null +++ b/arch/frv/include/asm/shmparam.h @@ -0,0 +1,7 @@ +#ifndef _ASM_SHMPARAM_H +#define _ASM_SHMPARAM_H + +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ + +#endif /* _ASM_SHMPARAM_H */ + diff --git a/arch/frv/include/asm/signal.h b/arch/frv/include/asm/signal.h new file mode 100644 index 00000000000..eca0abcb79d --- /dev/null +++ b/arch/frv/include/asm/signal.h @@ -0,0 +1,6 @@ +#ifndef _ASM_SIGNAL_H +#define _ASM_SIGNAL_H + +#include <uapi/asm/signal.h> + +#endif /* _ASM_SIGNAL_H */ diff --git a/arch/frv/include/asm/smp.h b/arch/frv/include/asm/smp.h new file mode 100644 index 00000000000..38349ec8b61 --- /dev/null +++ b/arch/frv/include/asm/smp.h @@ -0,0 +1,9 @@ +#ifndef __ASM_SMP_H +#define __ASM_SMP_H + + +#ifdef CONFIG_SMP +#error SMP not supported +#endif + +#endif diff --git a/arch/frv/include/asm/spinlock.h b/arch/frv/include/asm/spinlock.h new file mode 100644 index 00000000000..fe385f45d1f --- /dev/null +++ b/arch/frv/include/asm/spinlock.h @@ -0,0 +1,17 @@ +/* spinlock.h: spinlocks for FR-V + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_SPINLOCK_H +#define _ASM_SPINLOCK_H + +#error no spinlocks for FR-V yet + +#endif /* _ASM_SPINLOCK_H */ diff --git a/arch/frv/include/asm/spr-regs.h b/arch/frv/include/asm/spr-regs.h new file mode 100644 index 00000000000..d3883021f23 --- /dev/null +++ b/arch/frv/include/asm/spr-regs.h @@ -0,0 +1,416 @@ +/* spr-regs.h: special-purpose registers on the FRV + * + * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_SPR_REGS_H +#define _ASM_SPR_REGS_H + +/* + * PSR - Processor Status Register + */ +#define PSR_ET 0x00000001 /* enable interrupts/exceptions flag */ +#define PSR_PS 0x00000002 /* previous supervisor mode flag */ +#define PSR_S 0x00000004 /* supervisor mode flag */ +#define PSR_PIL 0x00000078 /* processor external interrupt level */ +#define PSR_PIL_0 0x00000000 /* - no interrupt in progress */ +#define PSR_PIL_13 0x00000068 /* - debugging only */ +#define PSR_PIL_14 0x00000070 /* - debugging in progress */ +#define PSR_PIL_15 0x00000078 /* - NMI in progress */ +#define PSR_EM 0x00000080 /* enable media operation */ +#define PSR_EF 0x00000100 /* enable FPU operation */ +#define PSR_BE 0x00001000 /* endianness mode */ +#define PSR_BE_LE 0x00000000 /* - little endian mode */ +#define PSR_BE_BE 0x00001000 /* - big endian mode */ +#define PSR_CM 0x00002000 /* conditional mode */ +#define PSR_NEM 0x00004000 /* non-excepting mode */ +#define PSR_ICE 0x00010000 /* in-circuit emulation mode */ +#define PSR_VERSION_SHIFT 24 /* CPU silicon ID */ +#define PSR_IMPLE_SHIFT 28 /* CPU core ID */ + +#define PSR_VERSION(psr) (((psr) >> PSR_VERSION_SHIFT) & 0xf) +#define PSR_IMPLE(psr) (((psr) >> PSR_IMPLE_SHIFT) & 0xf) + +#define PSR_IMPLE_FR401 0x2 +#define PSR_VERSION_FR401_MB93401 0x0 +#define PSR_VERSION_FR401_MB93401A 0x1 +#define PSR_VERSION_FR401_MB93403 0x2 + +#define PSR_IMPLE_FR405 0x4 +#define PSR_VERSION_FR405_MB93405 0x0 + +#define PSR_IMPLE_FR451 0x5 +#define PSR_VERSION_FR451_MB93451 0x0 + +#define PSR_IMPLE_FR501 0x1 +#define PSR_VERSION_FR501_MB93501 0x1 +#define PSR_VERSION_FR501_MB93501A 0x2 + +#define PSR_IMPLE_FR551 0x3 +#define PSR_VERSION_FR551_MB93555 0x1 + +#define __get_PSR() ({ unsigned long x; asm volatile("movsg psr,%0" : "=r"(x)); x; }) +#define __set_PSR(V) do { asm volatile("movgs %0,psr" : : "r"(V)); } while(0) + +/* + * TBR - Trap Base Register + */ +#define TBR_TT 0x00000ff0 +#define TBR_TT_INSTR_MMU_MISS (0x01 << 4) +#define TBR_TT_INSTR_ACC_ERROR (0x02 << 4) +#define TBR_TT_INSTR_ACC_EXCEP (0x03 << 4) +#define TBR_TT_PRIV_INSTR (0x06 << 4) +#define TBR_TT_ILLEGAL_INSTR (0x07 << 4) +#define TBR_TT_FP_EXCEPTION (0x0d << 4) +#define TBR_TT_MP_EXCEPTION (0x0e << 4) +#define TBR_TT_DATA_ACC_ERROR (0x11 << 4) +#define TBR_TT_DATA_MMU_MISS (0x12 << 4) +#define TBR_TT_DATA_ACC_EXCEP (0x13 << 4) +#define TBR_TT_DATA_STR_ERROR (0x14 << 4) +#define TBR_TT_DIVISION_EXCEP (0x17 << 4) +#define TBR_TT_COMMIT_EXCEP (0x19 << 4) +#define TBR_TT_INSTR_TLB_MISS (0x1a << 4) +#define TBR_TT_DATA_TLB_MISS (0x1b << 4) +#define TBR_TT_DATA_DAT_EXCEP (0x1d << 4) +#define TBR_TT_DECREMENT_TIMER (0x1f << 4) +#define TBR_TT_COMPOUND_EXCEP (0x20 << 4) +#define TBR_TT_INTERRUPT_1 (0x21 << 4) +#define TBR_TT_INTERRUPT_2 (0x22 << 4) +#define TBR_TT_INTERRUPT_3 (0x23 << 4) +#define TBR_TT_INTERRUPT_4 (0x24 << 4) +#define TBR_TT_INTERRUPT_5 (0x25 << 4) +#define TBR_TT_INTERRUPT_6 (0x26 << 4) +#define TBR_TT_INTERRUPT_7 (0x27 << 4) +#define TBR_TT_INTERRUPT_8 (0x28 << 4) +#define TBR_TT_INTERRUPT_9 (0x29 << 4) +#define TBR_TT_INTERRUPT_10 (0x2a << 4) +#define TBR_TT_INTERRUPT_11 (0x2b << 4) +#define TBR_TT_INTERRUPT_12 (0x2c << 4) +#define TBR_TT_INTERRUPT_13 (0x2d << 4) +#define TBR_TT_INTERRUPT_14 (0x2e << 4) +#define TBR_TT_INTERRUPT_15 (0x2f << 4) +#define TBR_TT_TRAP0 (0x80 << 4) +#define TBR_TT_TRAP1 (0x81 << 4) +#define TBR_TT_TRAP2 (0x82 << 4) +#define TBR_TT_TRAP3 (0x83 << 4) +#define TBR_TT_TRAP120 (0xf8 << 4) +#define TBR_TT_TRAP121 (0xf9 << 4) +#define TBR_TT_TRAP122 (0xfa << 4) +#define TBR_TT_TRAP123 (0xfb << 4) +#define TBR_TT_TRAP124 (0xfc << 4) +#define TBR_TT_TRAP125 (0xfd << 4) +#define TBR_TT_TRAP126 (0xfe << 4) +#define TBR_TT_BREAK (0xff << 4) + +#define TBR_TT_ATOMIC_CMPXCHG32 TBR_TT_TRAP120 +#define TBR_TT_ATOMIC_XCHG32 TBR_TT_TRAP121 +#define TBR_TT_ATOMIC_XOR TBR_TT_TRAP122 +#define TBR_TT_ATOMIC_OR TBR_TT_TRAP123 +#define TBR_TT_ATOMIC_AND TBR_TT_TRAP124 +#define TBR_TT_ATOMIC_SUB TBR_TT_TRAP125 +#define TBR_TT_ATOMIC_ADD TBR_TT_TRAP126 + +#define __get_TBR() ({ unsigned long x; asm volatile("movsg tbr,%0" : "=r"(x)); x; }) + +/* + * HSR0 - Hardware Status Register 0 + */ +#define HSR0_PDM 0x00000007 /* power down mode */ +#define HSR0_PDM_NORMAL 0x00000000 /* - normal mode */ +#define HSR0_PDM_CORE_SLEEP 0x00000001 /* - CPU core sleep mode */ +#define HSR0_PDM_BUS_SLEEP 0x00000003 /* - bus sleep mode */ +#define HSR0_PDM_PLL_RUN 0x00000005 /* - PLL run */ +#define HSR0_PDM_PLL_STOP 0x00000007 /* - PLL stop */ +#define HSR0_GRLE 0x00000040 /* GR lower register set enable */ +#define HSR0_GRHE 0x00000080 /* GR higher register set enable */ +#define HSR0_FRLE 0x00000100 /* FR lower register set enable */ +#define HSR0_FRHE 0x00000200 /* FR higher register set enable */ +#define HSR0_GRN 0x00000400 /* GR quantity */ +#define HSR0_GRN_64 0x00000000 /* - 64 GR registers */ +#define HSR0_GRN_32 0x00000400 /* - 32 GR registers */ +#define HSR0_FRN 0x00000800 /* FR quantity */ +#define HSR0_FRN_64 0x00000000 /* - 64 FR registers */ +#define HSR0_FRN_32 0x00000800 /* - 32 FR registers */ +#define HSR0_SA 0x00001000 /* start address (RAMBOOT#) */ +#define HSR0_ETMI 0x00008000 /* enable TIMERI (64-bit up timer) */ +#define HSR0_ETMD 0x00004000 /* enable TIMERD (32-bit down timer) */ +#define HSR0_PEDAT 0x00010000 /* previous DAT mode */ +#define HSR0_XEDAT 0x00020000 /* exception DAT mode */ +#define HSR0_EDAT 0x00080000 /* enable DAT mode */ +#define HSR0_RME 0x00400000 /* enable RAM mode */ +#define HSR0_EMEM 0x00800000 /* enable MMU_Miss mask */ +#define HSR0_EXMMU 0x01000000 /* enable extended MMU mode */ +#define HSR0_EDMMU 0x02000000 /* enable data MMU */ +#define HSR0_EIMMU 0x04000000 /* enable instruction MMU */ +#define HSR0_CBM 0x08000000 /* copy back mode */ +#define HSR0_CBM_WRITE_THRU 0x00000000 /* - write through */ +#define HSR0_CBM_COPY_BACK 0x08000000 /* - copy back */ +#define HSR0_NWA 0x10000000 /* no write allocate */ +#define HSR0_DCE 0x40000000 /* data cache enable */ +#define HSR0_ICE 0x80000000 /* instruction cache enable */ + +#define __get_HSR(R) ({ unsigned long x; asm volatile("movsg hsr"#R",%0" : "=r"(x)); x; }) +#define __set_HSR(R,V) do { asm volatile("movgs %0,hsr"#R : : "r"(V)); } while(0) + +/* + * CCR - Condition Codes Register + */ +#define CCR_FCC0 0x0000000f /* FP/Media condition 0 (fcc0 reg) */ +#define CCR_FCC1 0x000000f0 /* FP/Media condition 1 (fcc1 reg) */ +#define CCR_FCC2 0x00000f00 /* FP/Media condition 2 (fcc2 reg) */ +#define CCR_FCC3 0x0000f000 /* FP/Media condition 3 (fcc3 reg) */ +#define CCR_ICC0 0x000f0000 /* Integer condition 0 (icc0 reg) */ +#define CCR_ICC0_C 0x00010000 /* - Carry flag */ +#define CCR_ICC0_V 0x00020000 /* - Overflow flag */ +#define CCR_ICC0_Z 0x00040000 /* - Zero flag */ +#define CCR_ICC0_N 0x00080000 /* - Negative flag */ +#define CCR_ICC1 0x00f00000 /* Integer condition 1 (icc1 reg) */ +#define CCR_ICC2 0x0f000000 /* Integer condition 2 (icc2 reg) */ +#define CCR_ICC3 0xf0000000 /* Integer condition 3 (icc3 reg) */ + +/* + * CCCR - Condition Codes for Conditional Instructions Register + */ +#define CCCR_CC0 0x00000003 /* condition 0 (cc0 reg) */ +#define CCCR_CC0_FALSE 0x00000002 /* - condition is false */ +#define CCCR_CC0_TRUE 0x00000003 /* - condition is true */ +#define CCCR_CC1 0x0000000c /* condition 1 (cc1 reg) */ +#define CCCR_CC2 0x00000030 /* condition 2 (cc2 reg) */ +#define CCCR_CC3 0x000000c0 /* condition 3 (cc3 reg) */ +#define CCCR_CC4 0x00000300 /* condition 4 (cc4 reg) */ +#define CCCR_CC5 0x00000c00 /* condition 5 (cc5 reg) */ +#define CCCR_CC6 0x00003000 /* condition 6 (cc6 reg) */ +#define CCCR_CC7 0x0000c000 /* condition 7 (cc7 reg) */ + +/* + * ISR - Integer Status Register + */ +#define ISR_EMAM 0x00000001 /* memory misaligned access handling */ +#define ISR_EMAM_EXCEPTION 0x00000000 /* - generate exception */ +#define ISR_EMAM_FUDGE 0x00000001 /* - mask out invalid address bits */ +#define ISR_AEXC 0x00000004 /* accrued [overflow] exception */ +#define ISR_DTT 0x00000018 /* division type trap */ +#define ISR_DTT_IGNORE 0x00000000 /* - ignore division error */ +#define ISR_DTT_DIVBYZERO 0x00000008 /* - generate exception */ +#define ISR_DTT_OVERFLOW 0x00000010 /* - record overflow */ +#define ISR_EDE 0x00000020 /* enable division exception */ +#define ISR_PLI 0x20000000 /* pre-load instruction information */ +#define ISR_QI 0x80000000 /* quad data implementation information */ + +/* + * EPCR0 - Exception PC Register + */ +#define EPCR0_V 0x00000001 /* register content validity indicator */ +#define EPCR0_PC 0xfffffffc /* faulting instruction address */ + +/* + * ESR0/14/15 - Exception Status Register + */ +#define ESRx_VALID 0x00000001 /* register content validity indicator */ +#define ESRx_EC 0x0000003e /* exception type */ +#define ESRx_EC_DATA_STORE 0x00000000 /* - data_store_error */ +#define ESRx_EC_INSN_ACCESS 0x00000006 /* - instruction_access_error */ +#define ESRx_EC_PRIV_INSN 0x00000008 /* - privileged_instruction */ +#define ESRx_EC_ILL_INSN 0x0000000a /* - illegal_instruction */ +#define ESRx_EC_MP_EXCEP 0x0000001c /* - mp_exception */ +#define ESRx_EC_DATA_ACCESS 0x00000020 /* - data_access_error */ +#define ESRx_EC_DIVISION 0x00000026 /* - division_exception */ +#define ESRx_EC_ITLB_MISS 0x00000034 /* - instruction_access_TLB_miss */ +#define ESRx_EC_DTLB_MISS 0x00000036 /* - data_access_TLB_miss */ +#define ESRx_EC_DATA_ACCESS_DAT 0x0000003a /* - data_access_DAT_exception */ + +#define ESR0_IAEC 0x00000100 /* info for instruction-access-exception */ +#define ESR0_IAEC_RESV 0x00000000 /* - reserved */ +#define ESR0_IAEC_PROT_VIOL 0x00000100 /* - protection violation */ + +#define ESR0_ATXC 0x00f00000 /* address translation exception code */ +#define ESR0_ATXC_MMU_MISS 0x00000000 /* - MMU miss exception and more (?) */ +#define ESR0_ATXC_MULTI_DAT 0x00800000 /* - multiple DAT entry hit */ +#define ESR0_ATXC_MULTI_SAT 0x00900000 /* - multiple SAT entry hit */ +#define ESR0_ATXC_AMRTLB_MISS 0x00a00000 /* - MMU/TLB miss exception */ +#define ESR0_ATXC_PRIV_EXCEP 0x00c00000 /* - privilege protection fault */ +#define ESR0_ATXC_WP_EXCEP 0x00d00000 /* - write protection fault */ + +#define ESR0_EAV 0x00000800 /* true if EAR0 register valid */ +#define ESR15_EAV 0x00000800 /* true if EAR15 register valid */ + +/* + * ESFR1 - Exception Status Valid Flag Register + */ +#define ESFR1_ESR0 0x00000001 /* true if ESR0 is valid */ +#define ESFR1_ESR14 0x00004000 /* true if ESR14 is valid */ +#define ESFR1_ESR15 0x00008000 /* true if ESR15 is valid */ + +/* + * MSR - Media Status Register + */ +#define MSR0_AOVF 0x00000001 /* overflow exception accrued */ +#define MSRx_OVF 0x00000002 /* overflow exception detected */ +#define MSRx_SIE 0x0000003c /* last SIMD instruction exception detected */ +#define MSRx_SIE_NONE 0x00000000 /* - none detected */ +#define MSRx_SIE_FRkHI_ACCk 0x00000020 /* - exception at FRkHI or ACCk */ +#define MSRx_SIE_FRkLO_ACCk1 0x00000010 /* - exception at FRkLO or ACCk+1 */ +#define MSRx_SIE_FRk1HI_ACCk2 0x00000008 /* - exception at FRk+1HI or ACCk+2 */ +#define MSRx_SIE_FRk1LO_ACCk3 0x00000004 /* - exception at FRk+1LO or ACCk+3 */ +#define MSR0_MTT 0x00007000 /* type of last media trap detected */ +#define MSR0_MTT_NONE 0x00000000 /* - none detected */ +#define MSR0_MTT_OVERFLOW 0x00001000 /* - overflow detected */ +#define MSR0_HI 0x00c00000 /* hardware implementation */ +#define MSR0_HI_ROUNDING 0x00000000 /* - rounding mode */ +#define MSR0_HI_NONROUNDING 0x00c00000 /* - non-rounding mode */ +#define MSR0_EMCI 0x01000000 /* enable media custom instructions */ +#define MSR0_SRDAV 0x10000000 /* select rounding mode of MAVEH */ +#define MSR0_SRDAV_RDAV 0x00000000 /* - controlled by MSR.RDAV */ +#define MSR0_SRDAV_RD 0x10000000 /* - controlled by MSR.RD */ +#define MSR0_RDAV 0x20000000 /* rounding mode of MAVEH */ +#define MSR0_RDAV_NEAREST_MI 0x00000000 /* - round to nearest minus */ +#define MSR0_RDAV_NEAREST_PL 0x20000000 /* - round to nearest plus */ +#define MSR0_RD 0xc0000000 /* rounding mode */ +#define MSR0_RD_NEAREST 0x00000000 /* - nearest */ +#define MSR0_RD_ZERO 0x40000000 /* - zero */ +#define MSR0_RD_POS_INF 0x80000000 /* - positive infinity */ +#define MSR0_RD_NEG_INF 0xc0000000 /* - negative infinity */ + +/* + * IAMPR0-7 - Instruction Address Mapping Register + * DAMPR0-7 - Data Address Mapping Register + */ +#define xAMPRx_V 0x00000001 /* register content validity indicator */ +#define DAMPRx_WP 0x00000002 /* write protect */ +#define DAMPRx_WP_RW 0x00000000 /* - read/write */ +#define DAMPRx_WP_RO 0x00000002 /* - read-only */ +#define xAMPRx_C 0x00000004 /* cached/uncached */ +#define xAMPRx_C_CACHED 0x00000000 /* - cached */ +#define xAMPRx_C_UNCACHED 0x00000004 /* - uncached */ +#define xAMPRx_S 0x00000008 /* supervisor only */ +#define xAMPRx_S_USER 0x00000000 /* - userspace can access */ +#define xAMPRx_S_KERNEL 0x00000008 /* - kernel only */ +#define xAMPRx_SS 0x000000f0 /* segment size */ +#define xAMPRx_SS_16Kb 0x00000000 /* - 16 kilobytes */ +#define xAMPRx_SS_64Kb 0x00000010 /* - 64 kilobytes */ +#define xAMPRx_SS_256Kb 0x00000020 /* - 256 kilobytes */ +#define xAMPRx_SS_1Mb 0x00000030 /* - 1 megabyte */ +#define xAMPRx_SS_2Mb 0x00000040 /* - 2 megabytes */ +#define xAMPRx_SS_4Mb 0x00000050 /* - 4 megabytes */ +#define xAMPRx_SS_8Mb 0x00000060 /* - 8 megabytes */ +#define xAMPRx_SS_16Mb 0x00000070 /* - 16 megabytes */ +#define xAMPRx_SS_32Mb 0x00000080 /* - 32 megabytes */ +#define xAMPRx_SS_64Mb 0x00000090 /* - 64 megabytes */ +#define xAMPRx_SS_128Mb 0x000000a0 /* - 128 megabytes */ +#define xAMPRx_SS_256Mb 0x000000b0 /* - 256 megabytes */ +#define xAMPRx_SS_512Mb 0x000000c0 /* - 512 megabytes */ +#define xAMPRx_RESERVED8 0x00000100 /* reserved bit */ +#define xAMPRx_NG 0x00000200 /* non-global */ +#define xAMPRx_L 0x00000400 /* locked */ +#define xAMPRx_M 0x00000800 /* modified */ +#define xAMPRx_D 0x00001000 /* DAT entry */ +#define xAMPRx_RESERVED13 0x00002000 /* reserved bit */ +#define xAMPRx_PPFN 0xfff00000 /* physical page frame number */ + +#define xAMPRx_V_BIT 0 +#define DAMPRx_WP_BIT 1 +#define xAMPRx_C_BIT 2 +#define xAMPRx_S_BIT 3 +#define xAMPRx_RESERVED8_BIT 8 +#define xAMPRx_NG_BIT 9 +#define xAMPRx_L_BIT 10 +#define xAMPRx_M_BIT 11 +#define xAMPRx_D_BIT 12 +#define xAMPRx_RESERVED13_BIT 13 + +#define __get_IAMPR(R) ({ unsigned long x; asm volatile("movsg iampr"#R",%0" : "=r"(x)); x; }) +#define __get_DAMPR(R) ({ unsigned long x; asm volatile("movsg dampr"#R",%0" : "=r"(x)); x; }) + +#define __get_IAMLR(R) ({ unsigned long x; asm volatile("movsg iamlr"#R",%0" : "=r"(x)); x; }) +#define __get_DAMLR(R) ({ unsigned long x; asm volatile("movsg damlr"#R",%0" : "=r"(x)); x; }) + +#define __set_IAMPR(R,V) do { asm volatile("movgs %0,iampr"#R : : "r"(V)); } while(0) +#define __set_DAMPR(R,V) do { asm volatile("movgs %0,dampr"#R : : "r"(V)); } while(0) + +#define __set_IAMLR(R,V) do { asm volatile("movgs %0,iamlr"#R : : "r"(V)); } while(0) +#define __set_DAMLR(R,V) do { asm volatile("movgs %0,damlr"#R : : "r"(V)); } while(0) + +#define save_dampr(R, _dampr) \ +do { \ + asm volatile("movsg dampr"R",%0" : "=r"(_dampr)); \ +} while(0) + +#define restore_dampr(R, _dampr) \ +do { \ + asm volatile("movgs %0,dampr"R :: "r"(_dampr)); \ +} while(0) + +/* + * AMCR - Address Mapping Control Register + */ +#define AMCR_IAMRN 0x000000ff /* quantity of IAMPR registers */ +#define AMCR_DAMRN 0x0000ff00 /* quantity of DAMPR registers */ + +/* + * TTBR - Address Translation Table Base Register + */ +#define __get_TTBR() ({ unsigned long x; asm volatile("movsg ttbr,%0" : "=r"(x)); x; }) + +/* + * TPXR - TLB Probe Extend Register + */ +#define TPXR_E 0x00000001 +#define TPXR_LMAX_SHIFT 20 +#define TPXR_LMAX_SMASK 0xf +#define TPXR_WMAX_SHIFT 24 +#define TPXR_WMAX_SMASK 0xf +#define TPXR_WAY_SHIFT 28 +#define TPXR_WAY_SMASK 0xf + +/* + * DCR - Debug Control Register + */ +#define DCR_IBCE3 0x00000001 /* break on conditional insn pointed to by IBAR3 */ +#define DCR_IBE3 0x00000002 /* break on insn pointed to by IBAR3 */ +#define DCR_IBCE1 0x00000004 /* break on conditional insn pointed to by IBAR2 */ +#define DCR_IBE1 0x00000008 /* break on insn pointed to by IBAR2 */ +#define DCR_IBCE2 0x00000010 /* break on conditional insn pointed to by IBAR1 */ +#define DCR_IBE2 0x00000020 /* break on insn pointed to by IBAR1 */ +#define DCR_IBCE0 0x00000040 /* break on conditional insn pointed to by IBAR0 */ +#define DCR_IBE0 0x00000080 /* break on insn pointed to by IBAR0 */ + +#define DCR_DDBE1 0x00004000 /* use DBDR1x when checking DBAR1 */ +#define DCR_DWBE1 0x00008000 /* break on store to address in DBAR1/DBMR1x */ +#define DCR_DRBE1 0x00010000 /* break on load from address in DBAR1/DBMR1x */ +#define DCR_DDBE0 0x00020000 /* use DBDR0x when checking DBAR0 */ +#define DCR_DWBE0 0x00040000 /* break on store to address in DBAR0/DBMR0x */ +#define DCR_DRBE0 0x00080000 /* break on load from address in DBAR0/DBMR0x */ + +#define DCR_EIM 0x0c000000 /* external interrupt disable */ +#define DCR_IBM 0x10000000 /* instruction break disable */ +#define DCR_SE 0x20000000 /* single step enable */ +#define DCR_EBE 0x40000000 /* exception break enable */ + +/* + * BRR - Break Interrupt Request Register + */ +#define BRR_ST 0x00000001 /* single-step detected */ +#define BRR_SB 0x00000002 /* break instruction detected */ +#define BRR_BB 0x00000004 /* branch with hint detected */ +#define BRR_CBB 0x00000008 /* branch to LR detected */ +#define BRR_IBx 0x000000f0 /* hardware breakpoint detected */ +#define BRR_DBx 0x00000f00 /* hardware watchpoint detected */ +#define BRR_DBNEx 0x0000f000 /* ? */ +#define BRR_EBTT 0x00ff0000 /* trap type of exception break */ +#define BRR_TB 0x10000000 /* external break request detected */ +#define BRR_CB 0x20000000 /* ICE break command detected */ +#define BRR_EB 0x40000000 /* exception break detected */ + +/* + * BPSR - Break PSR Save Register + */ +#define BPSR_BET 0x00000001 /* former PSR.ET */ +#define BPSR_BS 0x00001000 /* former PSR.S */ + +#endif /* _ASM_SPR_REGS_H */ diff --git a/arch/frv/include/asm/string.h b/arch/frv/include/asm/string.h new file mode 100644 index 00000000000..5ed310f64b7 --- /dev/null +++ b/arch/frv/include/asm/string.h @@ -0,0 +1,51 @@ +/* string.h: FRV string handling + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_STRING_H_ +#define _ASM_STRING_H_ + +#ifdef __KERNEL__ /* only set these up for kernel code */ + +#define __HAVE_ARCH_MEMSET 1 +#define __HAVE_ARCH_MEMCPY 1 + +extern void *memset(void *, int, __kernel_size_t); +extern void *memcpy(void *, const void *, __kernel_size_t); + +#else /* KERNEL */ + +/* + * let user libraries deal with these, + * IMHO the kernel has no place defining these functions for user apps + */ + +#define __HAVE_ARCH_STRCPY 1 +#define __HAVE_ARCH_STRNCPY 1 +#define __HAVE_ARCH_STRCAT 1 +#define __HAVE_ARCH_STRNCAT 1 +#define __HAVE_ARCH_STRCMP 1 +#define __HAVE_ARCH_STRNCMP 1 +#define __HAVE_ARCH_STRNICMP 1 +#define __HAVE_ARCH_STRCHR 1 +#define __HAVE_ARCH_STRRCHR 1 +#define __HAVE_ARCH_STRSTR 1 +#define __HAVE_ARCH_STRLEN 1 +#define __HAVE_ARCH_STRNLEN 1 +#define __HAVE_ARCH_MEMSET 1 +#define __HAVE_ARCH_MEMCPY 1 +#define __HAVE_ARCH_MEMMOVE 1 +#define __HAVE_ARCH_MEMSCAN 1 +#define __HAVE_ARCH_MEMCMP 1 +#define __HAVE_ARCH_MEMCHR 1 +#define __HAVE_ARCH_STRTOK 1 + +#endif /* KERNEL */ +#endif /* _ASM_STRING_H_ */ diff --git a/arch/frv/include/asm/switch_to.h b/arch/frv/include/asm/switch_to.h new file mode 100644 index 00000000000..2cf0f6a7fbb --- /dev/null +++ b/arch/frv/include/asm/switch_to.h @@ -0,0 +1,35 @@ +/* FR-V CPU basic task switching + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_SWITCH_TO_H +#define _ASM_SWITCH_TO_H + +#include <linux/thread_info.h> + +/* + * switch_to(prev, next) should switch from task `prev' to `next' + * `prev' will never be the same as `next'. + * The `mb' is to tell GCC not to cache `current' across this call. + */ +extern asmlinkage +struct task_struct *__switch_to(struct thread_struct *prev_thread, + struct thread_struct *next_thread, + struct task_struct *prev); + +#define switch_to(prev, next, last) \ +do { \ + (prev)->thread.sched_lr = \ + (unsigned long) __builtin_return_address(0); \ + (last) = __switch_to(&(prev)->thread, &(next)->thread, (prev)); \ + mb(); \ +} while(0) + +#endif /* _ASM_SWITCH_TO_H */ diff --git a/arch/frv/include/asm/syscall.h b/arch/frv/include/asm/syscall.h new file mode 100644 index 00000000000..70689eb29b9 --- /dev/null +++ b/arch/frv/include/asm/syscall.h @@ -0,0 +1,123 @@ +/* syscall parameter access functions + * + * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#ifndef _ASM_SYSCALL_H +#define _ASM_SYSCALL_H + +#include <linux/err.h> +#include <asm/ptrace.h> + +/* + * Get the system call number or -1 + */ +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->syscallno; +} + +/* + * Restore the clobbered GR8 register + * (1st syscall arg was overwritten with syscall return or error) + */ +static inline void syscall_rollback(struct task_struct *task, + struct pt_regs *regs) +{ + regs->gr8 = regs->orig_gr8; +} + +/* + * See if the syscall return value is an error, returning it if it is and 0 if + * not + */ +static inline long syscall_get_error(struct task_struct *task, + struct pt_regs *regs) +{ + return IS_ERR_VALUE(regs->gr8) ? regs->gr8 : 0; +} + +/* + * Get the syscall return value + */ +static inline long syscall_get_return_value(struct task_struct *task, + struct pt_regs *regs) +{ + return regs->gr8; +} + +/* + * Set the syscall return value + */ +static inline void syscall_set_return_value(struct task_struct *task, + struct pt_regs *regs, + int error, long val) +{ + if (error) + regs->gr8 = -error; + else + regs->gr8 = val; +} + +/* + * Retrieve the system call arguments + */ +static inline void syscall_get_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args) +{ + /* + * Do this simply for now. If we need to start supporting + * fetching arguments from arbitrary indices, this will need some + * extra logic. Presently there are no in-tree users that depend + * on this behaviour. + */ + BUG_ON(i); + + /* Argument pattern is: GR8, GR9, GR10, GR11, GR12, GR13 */ + switch (n) { + case 6: args[5] = regs->gr13; + case 5: args[4] = regs->gr12; + case 4: args[3] = regs->gr11; + case 3: args[2] = regs->gr10; + case 2: args[1] = regs->gr9; + case 1: args[0] = regs->gr8; + break; + default: + BUG(); + } +} + +/* + * Alter the system call arguments + */ +static inline void syscall_set_arguments(struct task_struct *task, + struct pt_regs *regs, + unsigned int i, unsigned int n, + const unsigned long *args) +{ + /* Same note as above applies */ + BUG_ON(i); + + switch (n) { + case 6: regs->gr13 = args[5]; + case 5: regs->gr12 = args[4]; + case 4: regs->gr11 = args[3]; + case 3: regs->gr10 = args[2]; + case 2: regs->gr9 = args[1]; + case 1: regs->gr8 = args[0]; + break; + default: + BUG(); + } +} + +#endif /* _ASM_SYSCALL_H */ diff --git a/arch/frv/include/asm/termios.h b/arch/frv/include/asm/termios.h new file mode 100644 index 00000000000..9f753fc0953 --- /dev/null +++ b/arch/frv/include/asm/termios.h @@ -0,0 +1,14 @@ +#ifndef _ASM_TERMIOS_H +#define _ASM_TERMIOS_H + +#include <uapi/asm/termios.h> + +/* intr=^C quit=^| erase=del kill=^U + eof=^D vtime=\0 vmin=\1 sxtc=\0 + start=^Q stop=^S susp=^Z eol=\0 + reprint=^R discard=^U werase=^W lnext=^V + eol2=\0 +*/ +#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0" +#include <asm-generic/termios-base.h> +#endif /* _ASM_TERMIOS_H */ diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h new file mode 100644 index 00000000000..af29e17c018 --- /dev/null +++ b/arch/frv/include/asm/thread_info.h @@ -0,0 +1,125 @@ +/* thread_info.h: description + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * Derived from include/asm-i386/thread_info.h + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_THREAD_INFO_H +#define _ASM_THREAD_INFO_H + +#ifdef __KERNEL__ + +#ifndef __ASSEMBLY__ +#include <asm/processor.h> +#endif + +#define THREAD_SIZE 8192 + +/* + * low level task data that entry.S needs immediate access to + * - this struct should fit entirely inside of one cache line + * - this struct shares the supervisor stack pages + * - if the contents of this structure are changed, the assembly constants must also be changed + */ +#ifndef __ASSEMBLY__ + +struct thread_info { + struct task_struct *task; /* main task structure */ + struct exec_domain *exec_domain; /* execution domain */ + unsigned long flags; /* low level flags */ + unsigned long status; /* thread-synchronous flags */ + __u32 cpu; /* current CPU */ + int preempt_count; /* 0 => preemptable, <0 => BUG */ + + mm_segment_t addr_limit; /* thread address space: + * 0-0xBFFFFFFF for user-thead + * 0-0xFFFFFFFF for kernel-thread + */ + struct restart_block restart_block; + + __u8 supervisor_stack[0]; +}; + +#else /* !__ASSEMBLY__ */ + +#include <asm/asm-offsets.h> + +#endif + +/* + * macros/functions for gaining access to the thread information structure + */ +#ifndef __ASSEMBLY__ + +#define INIT_THREAD_INFO(tsk) \ +{ \ + .task = &tsk, \ + .exec_domain = &default_exec_domain, \ + .flags = 0, \ + .cpu = 0, \ + .preempt_count = INIT_PREEMPT_COUNT, \ + .addr_limit = KERNEL_DS, \ + .restart_block = { \ + .fn = do_no_restart_syscall, \ + }, \ +} + +#define init_thread_info (init_thread_union.thread_info) +#define init_stack (init_thread_union.stack) + +/* how to get the thread information struct from C */ +register struct thread_info *__current_thread_info asm("gr15"); + +#define current_thread_info() ({ __current_thread_info; }) + +#endif /* __ASSEMBLY__ */ + +/* + * thread information flags + * - these are process state flags that various assembly files may need to access + * - pending work-to-be-done flags are in LSW + * - other flags in MSW + */ +#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ +#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ +#define TIF_SIGPENDING 2 /* signal pending */ +#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ +#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ +#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ +#define TIF_MEMDIE 7 /* is terminating due to OOM killer */ + +#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) +#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) +#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) +#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) + +/* work to do on interrupt/exception return */ +#define _TIF_WORK_MASK \ + (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP) + +/* work to do on any return to u-space */ +#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE) + +#if _TIF_ALLWORK_MASK >= 0x2000 +#error "_TIF_ALLWORK_MASK won't fit in an ANDI now (see entry.S)" +#endif + +/* + * Thread-synchronous status. + * + * This is different from the flags in that nobody else + * ever touches our thread-synchronous status, so we don't + * have to worry about atomic accesses. + */ +#define TS_USEDFPM 0x0001 /* FPU/Media was used by this task this quantum (SMP) */ + +#endif /* __KERNEL__ */ + +#endif /* _ASM_THREAD_INFO_H */ diff --git a/arch/frv/include/asm/timer-regs.h b/arch/frv/include/asm/timer-regs.h new file mode 100644 index 00000000000..6c5a871ce5e --- /dev/null +++ b/arch/frv/include/asm/timer-regs.h @@ -0,0 +1,106 @@ +/* timer-regs.h: hardware timer register definitions + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_TIMER_REGS_H +#define _ASM_TIMER_REGS_H + +#include <asm/sections.h> + +extern unsigned long __nongprelbss __clkin_clock_speed_HZ; +extern unsigned long __nongprelbss __ext_bus_clock_speed_HZ; +extern unsigned long __nongprelbss __res_bus_clock_speed_HZ; +extern unsigned long __nongprelbss __sdram_clock_speed_HZ; +extern unsigned long __nongprelbss __core_bus_clock_speed_HZ; +extern unsigned long __nongprelbss __core_clock_speed_HZ; +extern unsigned long __nongprelbss __dsu_clock_speed_HZ; +extern unsigned long __nongprelbss __serial_clock_speed_HZ; + +#define __get_CLKC() ({ *(volatile unsigned long *)(0xfeff9a00); }) + +static inline void __set_CLKC(unsigned long v) +{ + int tmp; + + asm volatile(" st%I0.p %2,%M0 \n" + " setlos %3,%1 \n" + " membar \n" + "0: \n" + " subicc %1,#1,%1,icc0 \n" + " bnc icc0,#1,0b \n" + : "=m"(*(volatile unsigned long *) 0xfeff9a00), "=r"(tmp) + : "r"(v), "i"(256) + : "icc0"); +} + +#define __get_TCTR() ({ *(volatile unsigned long *)(0xfeff9418); }) +#define __get_TPRV() ({ *(volatile unsigned long *)(0xfeff9420); }) +#define __get_TPRCKSL() ({ *(volatile unsigned long *)(0xfeff9428); }) +#define __get_TCSR(T) ({ *(volatile unsigned long *)(0xfeff9400 + 8 * (T)); }) +#define __get_TxCKSL(T) ({ *(volatile unsigned long *)(0xfeff9430 + 8 * (T)); }) + +#define __get_TCSR_DATA(T) ({ __get_TCSR(T) >> 24; }) + +#define __set_TCTR(V) do { *(volatile unsigned long *)(0xfeff9418) = (V); mb(); } while(0) +#define __set_TPRV(V) do { *(volatile unsigned long *)(0xfeff9420) = (V) << 24; mb(); } while(0) +#define __set_TPRCKSL(V) do { *(volatile unsigned long *)(0xfeff9428) = (V); mb(); } while(0) +#define __set_TCSR(T,V) \ +do { *(volatile unsigned long *)(0xfeff9400 + 8 * (T)) = (V); mb(); } while(0) + +#define __set_TxCKSL(T,V) \ +do { *(volatile unsigned long *)(0xfeff9430 + 8 * (T)) = (V); mb(); } while(0) + +#define __set_TCSR_DATA(T,V) __set_TCSR(T, (V) << 24) +#define __set_TxCKSL_DATA(T,V) __set_TxCKSL(T, TxCKSL_EIGHT | __TxCKSL_SELECT((V))) + +/* clock control register */ +#define CLKC_CMODE 0x0f000000 +#define CLKC_SLPL 0x000f0000 +#define CLKC_P0 0x00000100 +#define CLKC_CM 0x00000003 + +#define CLKC_CMODE_s 24 + +/* timer control register - non-readback mode */ +#define TCTR_MODE_0 0x00000000 +#define TCTR_MODE_2 0x04000000 +#define TCTR_MODE_4 0x08000000 +#define TCTR_MODE_5 0x0a000000 +#define TCTR_RL_LATCH 0x00000000 +#define TCTR_RL_RW_LOW8 0x10000000 +#define TCTR_RL_RW_HIGH8 0x20000000 +#define TCTR_RL_RW_LH8 0x30000000 +#define TCTR_SC_CTR0 0x00000000 +#define TCTR_SC_CTR1 0x40000000 +#define TCTR_SC_CTR2 0x80000000 + +/* timer control register - readback mode */ +#define TCTR_CNT0 0x02000000 +#define TCTR_CNT1 0x04000000 +#define TCTR_CNT2 0x08000000 +#define TCTR_NSTATUS 0x10000000 +#define TCTR_NCOUNT 0x20000000 +#define TCTR_SC_READBACK 0xc0000000 + +/* timer control status registers - non-readback mode */ +#define TCSRx_DATA 0xff000000 + +/* timer control status registers - readback mode */ +#define TCSRx_OUTPUT 0x80000000 +#define TCSRx_NULLCOUNT 0x40000000 +#define TCSRx_RL 0x30000000 +#define TCSRx_MODE 0x07000000 + +/* timer clock select registers */ +#define TxCKSL_SELECT 0x0f000000 +#define __TxCKSL_SELECT(X) ((X) << 24) +#define TxCKSL_EIGHT 0xf0000000 + +#endif /* _ASM_TIMER_REGS_H */ diff --git a/arch/frv/include/asm/timex.h b/arch/frv/include/asm/timex.h new file mode 100644 index 00000000000..a89bddefdac --- /dev/null +++ b/arch/frv/include/asm/timex.h @@ -0,0 +1,20 @@ +/* timex.h: FR-V architecture timex specifications + */ +#ifndef _ASM_TIMEX_H +#define _ASM_TIMEX_H + +#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ + +typedef unsigned long cycles_t; + +static inline cycles_t get_cycles(void) +{ + return 0; +} + +#define vxtime_lock() do {} while (0) +#define vxtime_unlock() do {} while (0) + +#endif + diff --git a/arch/frv/include/asm/tlb.h b/arch/frv/include/asm/tlb.h new file mode 100644 index 00000000000..cd458eb6d75 --- /dev/null +++ b/arch/frv/include/asm/tlb.h @@ -0,0 +1,27 @@ +#ifndef _ASM_TLB_H +#define _ASM_TLB_H + +#include <asm/tlbflush.h> + +#ifdef CONFIG_MMU +extern void check_pgt_cache(void); +#else +#define check_pgt_cache() do {} while(0) +#endif + +/* + * we don't need any special per-pte or per-vma handling... + */ +#define tlb_start_vma(tlb, vma) do { } while (0) +#define tlb_end_vma(tlb, vma) do { } while (0) +#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0) + +/* + * .. because we flush the whole mm when it fills up + */ +#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) + +#include <asm-generic/tlb.h> + +#endif /* _ASM_TLB_H */ + diff --git a/arch/frv/include/asm/tlbflush.h b/arch/frv/include/asm/tlbflush.h new file mode 100644 index 00000000000..7ac5eafc5d9 --- /dev/null +++ b/arch/frv/include/asm/tlbflush.h @@ -0,0 +1,73 @@ +/* tlbflush.h: TLB flushing functions + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_TLBFLUSH_H +#define _ASM_TLBFLUSH_H + +#include <linux/mm.h> +#include <asm/processor.h> + +#ifdef CONFIG_MMU + +#ifndef __ASSEMBLY__ +extern void asmlinkage __flush_tlb_all(void); +extern void asmlinkage __flush_tlb_mm(unsigned long contextid); +extern void asmlinkage __flush_tlb_page(unsigned long contextid, unsigned long start); +extern void asmlinkage __flush_tlb_range(unsigned long contextid, + unsigned long start, unsigned long end); +#endif /* !__ASSEMBLY__ */ + +#define flush_tlb_all() \ +do { \ + preempt_disable(); \ + __flush_tlb_all(); \ + preempt_enable(); \ +} while(0) + +#define flush_tlb_mm(mm) \ +do { \ + preempt_disable(); \ + __flush_tlb_mm((mm)->context.id); \ + preempt_enable(); \ +} while(0) + +#define flush_tlb_range(vma,start,end) \ +do { \ + preempt_disable(); \ + __flush_tlb_range((vma)->vm_mm->context.id, start, end); \ + preempt_enable(); \ +} while(0) + +#define flush_tlb_page(vma,addr) \ +do { \ + preempt_disable(); \ + __flush_tlb_page((vma)->vm_mm->context.id, addr); \ + preempt_enable(); \ +} while(0) + + +#define __flush_tlb_global() flush_tlb_all() +#define flush_tlb() flush_tlb_all() +#define flush_tlb_kernel_range(start, end) flush_tlb_all() + +#else + +#define flush_tlb() BUG() +#define flush_tlb_all() BUG() +#define flush_tlb_mm(mm) BUG() +#define flush_tlb_page(vma,addr) BUG() +#define flush_tlb_range(mm,start,end) BUG() +#define flush_tlb_kernel_range(start, end) BUG() + +#endif + + +#endif /* _ASM_TLBFLUSH_H */ diff --git a/arch/frv/include/asm/topology.h b/arch/frv/include/asm/topology.h new file mode 100644 index 00000000000..94272435270 --- /dev/null +++ b/arch/frv/include/asm/topology.h @@ -0,0 +1,12 @@ +#ifndef _ASM_TOPOLOGY_H +#define _ASM_TOPOLOGY_H + +#ifdef CONFIG_NUMA + +#error NUMA not supported yet + +#endif /* CONFIG_NUMA */ + +#include <asm-generic/topology.h> + +#endif /* _ASM_TOPOLOGY_H */ diff --git a/arch/frv/include/asm/types.h b/arch/frv/include/asm/types.h new file mode 100644 index 00000000000..6bc63650d83 --- /dev/null +++ b/arch/frv/include/asm/types.h @@ -0,0 +1,22 @@ +/* types.h: FRV types + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_TYPES_H +#define _ASM_TYPES_H + +#include <uapi/asm/types.h> + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ + +#define BITS_PER_LONG 32 + +#endif /* _ASM_TYPES_H */ diff --git a/arch/frv/include/asm/uaccess.h b/arch/frv/include/asm/uaccess.h new file mode 100644 index 00000000000..3ac9a59d65d --- /dev/null +++ b/arch/frv/include/asm/uaccess.h @@ -0,0 +1,319 @@ +/* uaccess.h: userspace accessor functions + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_UACCESS_H +#define _ASM_UACCESS_H + +/* + * User space memory access functions + */ +#include <linux/sched.h> +#include <linux/mm.h> +#include <asm/segment.h> +#include <asm/sections.h> + +#define HAVE_ARCH_UNMAPPED_AREA /* we decide where to put mmaps */ + +#define __ptr(x) ((unsigned long __force *)(x)) + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * check that a range of addresses falls within the current address limit + */ +static inline int ___range_ok(unsigned long addr, unsigned long size) +{ +#ifdef CONFIG_MMU + int flag = -EFAULT, tmp; + + asm volatile ( + " addcc %3,%2,%1,icc0 \n" /* set C-flag if addr+size>4GB */ + " subcc.p %1,%4,gr0,icc1 \n" /* jump if addr+size>limit */ + " bc icc0,#0,0f \n" + " bhi icc1,#0,0f \n" + " setlos #0,%0 \n" /* mark okay */ + "0: \n" + : "=r"(flag), "=&r"(tmp) + : "r"(addr), "r"(size), "r"(get_addr_limit()), "0"(flag) + ); + + return flag; + +#else + + if (addr < memory_start || + addr > memory_end || + size > memory_end - memory_start || + addr + size > memory_end) + return -EFAULT; + + return 0; +#endif +} + +#define __range_ok(addr,size) ___range_ok((unsigned long) (addr), (unsigned long) (size)) + +#define access_ok(type,addr,size) (__range_ok((void __user *)(addr), (size)) == 0) +#define __access_ok(addr,size) (__range_ok((addr), (size)) == 0) + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ +struct exception_table_entry +{ + unsigned long insn, fixup; +}; + +/* Returns 0 if exception not found and fixup otherwise. */ +extern unsigned long search_exception_table(unsigned long); + + +/* + * These are the main single-value transfer routines. They automatically + * use the right size if we just have the right pointer type. + */ +#define __put_user(x, ptr) \ +({ \ + int __pu_err = 0; \ + \ + typeof(*(ptr)) __pu_val = (x); \ + __chk_user_ptr(ptr); \ + \ + switch (sizeof (*(ptr))) { \ + case 1: \ + __put_user_asm(__pu_err, __pu_val, ptr, "b", "r"); \ + break; \ + case 2: \ + __put_user_asm(__pu_err, __pu_val, ptr, "h", "r"); \ + break; \ + case 4: \ + __put_user_asm(__pu_err, __pu_val, ptr, "", "r"); \ + break; \ + case 8: \ + __put_user_asm(__pu_err, __pu_val, ptr, "d", "e"); \ + break; \ + default: \ + __pu_err = __put_user_bad(); \ + break; \ + } \ + __pu_err; \ +}) + +#define put_user(x, ptr) \ +({ \ + typeof(*(ptr)) __user *_p = (ptr); \ + int _e; \ + \ + _e = __range_ok(_p, sizeof(*_p)); \ + if (_e == 0) \ + _e = __put_user((x), _p); \ + _e; \ +}) + +extern int __put_user_bad(void); + +/* + * Tell gcc we read from memory instead of writing: this is because + * we do not write to any memory gcc knows about, so there are no + * aliasing issues. + */ + +#ifdef CONFIG_MMU + +#define __put_user_asm(err,x,ptr,dsize,constraint) \ +do { \ + asm volatile("1: st"dsize"%I1 %2,%M1 \n" \ + "2: \n" \ + ".subsection 2 \n" \ + "3: setlos %3,%0 \n" \ + " bra 2b \n" \ + ".previous \n" \ + ".section __ex_table,\"a\" \n" \ + " .balign 8 \n" \ + " .long 1b,3b \n" \ + ".previous" \ + : "=r" (err) \ + : "m" (*__ptr(ptr)), constraint (x), "i"(-EFAULT), "0"(err) \ + : "memory"); \ +} while (0) + +#else + +#define __put_user_asm(err,x,ptr,bwl,con) \ +do { \ + asm(" st"bwl"%I0 %1,%M0 \n" \ + " membar \n" \ + : \ + : "m" (*__ptr(ptr)), con (x) \ + : "memory"); \ +} while (0) + +#endif + +/*****************************************************************************/ +/* + * + */ +#define __get_user(x, ptr) \ +({ \ + int __gu_err = 0; \ + __chk_user_ptr(ptr); \ + \ + switch (sizeof(*(ptr))) { \ + case 1: { \ + unsigned char __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "ub", "=r"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ + break; \ + } \ + case 2: { \ + unsigned short __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "uh", "=r"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ + break; \ + } \ + case 4: { \ + unsigned int __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "", "=r"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ + break; \ + } \ + case 8: { \ + unsigned long long __gu_val; \ + __get_user_asm(__gu_err, __gu_val, ptr, "d", "=e"); \ + (x) = *(__force __typeof__(*(ptr)) *) &__gu_val; \ + break; \ + } \ + default: \ + __gu_err = __get_user_bad(); \ + break; \ + } \ + __gu_err; \ +}) + +#define get_user(x, ptr) \ +({ \ + const typeof(*(ptr)) __user *_p = (ptr);\ + int _e; \ + \ + _e = __range_ok(_p, sizeof(*_p)); \ + if (likely(_e == 0)) \ + _e = __get_user((x), _p); \ + else \ + (x) = (typeof(x)) 0; \ + _e; \ +}) + +extern int __get_user_bad(void); + +#ifdef CONFIG_MMU + +#define __get_user_asm(err,x,ptr,dtype,constraint) \ +do { \ + asm("1: ld"dtype"%I2 %M2,%1 \n" \ + "2: \n" \ + ".subsection 2 \n" \ + "3: setlos %3,%0 \n" \ + " setlos #0,%1 \n" \ + " bra 2b \n" \ + ".previous \n" \ + ".section __ex_table,\"a\" \n" \ + " .balign 8 \n" \ + " .long 1b,3b \n" \ + ".previous" \ + : "=r" (err), constraint (x) \ + : "m" (*__ptr(ptr)), "i"(-EFAULT), "0"(err) \ + ); \ +} while(0) + +#else + +#define __get_user_asm(err,x,ptr,bwl,con) \ + asm(" ld"bwl"%I1 %M1,%0 \n" \ + " membar \n" \ + : con(x) \ + : "m" (*__ptr(ptr))) + +#endif + +/*****************************************************************************/ +/* + * + */ +#define ____force(x) (__force void *)(void __user *)(x) +#ifdef CONFIG_MMU +extern long __memset_user(void *dst, unsigned long count); +extern long __memcpy_user(void *dst, const void *src, unsigned long count); + +#define clear_user(dst,count) __memset_user(____force(dst), (count)) +#define __copy_from_user_inatomic(to, from, n) __memcpy_user((to), ____force(from), (n)) +#define __copy_to_user_inatomic(to, from, n) __memcpy_user(____force(to), (from), (n)) + +#else + +#define clear_user(dst,count) (memset(____force(dst), 0, (count)), 0) +#define __copy_from_user_inatomic(to, from, n) (memcpy((to), ____force(from), (n)), 0) +#define __copy_to_user_inatomic(to, from, n) (memcpy(____force(to), (from), (n)), 0) + +#endif + +#define __clear_user clear_user + +static inline unsigned long __must_check +__copy_to_user(void __user *to, const void *from, unsigned long n) +{ + might_fault(); + return __copy_to_user_inatomic(to, from, n); +} + +static inline unsigned long +__copy_from_user(void *to, const void __user *from, unsigned long n) +{ + might_fault(); + return __copy_from_user_inatomic(to, from, n); +} + +static inline long copy_from_user(void *to, const void __user *from, unsigned long n) +{ + unsigned long ret = n; + + if (likely(__access_ok(from, n))) + ret = __copy_from_user(to, from, n); + + if (unlikely(ret != 0)) + memset(to + (n - ret), 0, ret); + + return ret; +} + +static inline long copy_to_user(void __user *to, const void *from, unsigned long n) +{ + return likely(__access_ok(to, n)) ? __copy_to_user(to, from, n) : n; +} + +extern long strncpy_from_user(char *dst, const char __user *src, long count); +extern long strnlen_user(const char __user *src, long count); + +#define strlen_user(str) strnlen_user(str, 32767) + +extern unsigned long search_exception_table(unsigned long addr); + +#endif /* _ASM_UACCESS_H */ diff --git a/arch/frv/include/asm/ucontext.h b/arch/frv/include/asm/ucontext.h new file mode 100644 index 00000000000..8d8c0c94800 --- /dev/null +++ b/arch/frv/include/asm/ucontext.h @@ -0,0 +1,12 @@ +#ifndef _ASM_UCONTEXT_H +#define _ASM_UCONTEXT_H + +struct ucontext { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +}; + +#endif diff --git a/arch/frv/include/asm/unaligned.h b/arch/frv/include/asm/unaligned.h new file mode 100644 index 00000000000..6c61c05b2e0 --- /dev/null +++ b/arch/frv/include/asm/unaligned.h @@ -0,0 +1,22 @@ +/* unaligned.h: unaligned access handler + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_UNALIGNED_H +#define _ASM_UNALIGNED_H + +#include <linux/unaligned/le_byteshift.h> +#include <linux/unaligned/be_struct.h> +#include <linux/unaligned/generic.h> + +#define get_unaligned __get_unaligned_be +#define put_unaligned __put_unaligned_be + +#endif /* _ASM_UNALIGNED_H */ diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h new file mode 100644 index 00000000000..17b5df8fc28 --- /dev/null +++ b/arch/frv/include/asm/unistd.h @@ -0,0 +1,33 @@ +#ifndef _ASM_UNISTD_H_ +#define _ASM_UNISTD_H_ + +#include <uapi/asm/unistd.h> + + +#define NR_syscalls 338 + +/* #define __ARCH_WANT_OLD_READDIR */ +#define __ARCH_WANT_OLD_STAT +#define __ARCH_WANT_STAT64 +#define __ARCH_WANT_SYS_ALARM +/* #define __ARCH_WANT_SYS_GETHOSTNAME */ +#define __ARCH_WANT_SYS_IPC +#define __ARCH_WANT_SYS_PAUSE +/* #define __ARCH_WANT_SYS_SIGNAL */ +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_SYS_UTIME +#define __ARCH_WANT_SYS_WAITPID +#define __ARCH_WANT_SYS_SOCKETCALL +#define __ARCH_WANT_SYS_FADVISE64 +#define __ARCH_WANT_SYS_GETPGRP +#define __ARCH_WANT_SYS_LLSEEK +#define __ARCH_WANT_SYS_NICE +/* #define __ARCH_WANT_SYS_OLD_GETRLIMIT */ +#define __ARCH_WANT_SYS_OLDUMOUNT +/* #define __ARCH_WANT_SYS_SIGPENDING */ +#define __ARCH_WANT_SYS_SIGPROCMASK +#define __ARCH_WANT_SYS_FORK +#define __ARCH_WANT_SYS_VFORK +#define __ARCH_WANT_SYS_CLONE + +#endif /* _ASM_UNISTD_H_ */ diff --git a/arch/frv/include/asm/user.h b/arch/frv/include/asm/user.h new file mode 100644 index 00000000000..82fa8fab64a --- /dev/null +++ b/arch/frv/include/asm/user.h @@ -0,0 +1,80 @@ +/* user.h: FR-V core file format stuff + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_USER_H +#define _ASM_USER_H + +#include <asm/page.h> +#include <asm/registers.h> + +/* Core file format: The core file is written in such a way that gdb + * can understand it and provide useful information to the user (under + * linux we use the 'trad-core' bfd). There are quite a number of + * obstacles to being able to view the contents of the floating point + * registers, and until these are solved you will not be able to view + * the contents of them. Actually, you can read in the core file and + * look at the contents of the user struct to find out what the + * floating point registers contain. + * + * The actual file contents are as follows: + * UPAGE: + * 1 page consisting of a user struct that tells gdb what is present + * in the file. Directly after this is a copy of the task_struct, + * which is currently not used by gdb, but it may come in useful at + * some point. All of the registers are stored as part of the + * upage. The upage should always be only one page. + * + * DATA: + * The data area is stored. We use current->end_text to + * current->brk to pick up all of the user variables, plus any + * memory that may have been malloced. No attempt is made to + * determine if a page is demand-zero or if a page is totally + * unused, we just cover the entire range. All of the addresses are + * rounded in such a way that an integral number of pages is + * written. + * + * STACK: + * We need the stack information in order to get a meaningful + * backtrace. We need to write the data from (esp) to + * current->start_stack, so we round each of these off in order to + * be able to write an integer number of pages. The minimum core + * file size is 3 pages, or 12288 bytes. + */ + +/* When the kernel dumps core, it starts by dumping the user struct - + * this will be used by gdb to figure out where the data and stack segments + * are within the file, and what virtual addresses to use. + */ +struct user { + /* We start with the registers, to mimic the way that "memory" is returned + * from the ptrace(3,...) function. */ + struct user_context regs; + + /* The rest of this junk is to help gdb figure out what goes where */ + unsigned long u_tsize; /* Text segment size (pages). */ + unsigned long u_dsize; /* Data segment size (pages). */ + unsigned long u_ssize; /* Stack segment size (pages). */ + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack area. + * This is actually the bottom of the stack, + * the top of the stack is always found in the + * esp register. */ + long int signal; /* Signal that caused the core dump. */ + + unsigned long magic; /* To uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif diff --git a/arch/frv/include/asm/vga.h b/arch/frv/include/asm/vga.h new file mode 100644 index 00000000000..a702c800a22 --- /dev/null +++ b/arch/frv/include/asm/vga.h @@ -0,0 +1,17 @@ +/* vga.h: VGA register stuff + * + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _ASM_VGA_H +#define _ASM_VGA_H + + + +#endif /* _ASM_VGA_H */ diff --git a/arch/frv/include/asm/virtconvert.h b/arch/frv/include/asm/virtconvert.h new file mode 100644 index 00000000000..b26d70ab911 --- /dev/null +++ b/arch/frv/include/asm/virtconvert.h @@ -0,0 +1,41 @@ +/* virtconvert.h: virtual/physical/page address conversion + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_VIRTCONVERT_H +#define _ASM_VIRTCONVERT_H + +/* + * Macros used for converting between virtual and physical mappings. + */ + +#ifdef __KERNEL__ + +#include <asm/setup.h> + +#ifdef CONFIG_MMU + +#define phys_to_virt(vaddr) ((void *) ((unsigned long)(vaddr) + PAGE_OFFSET)) +#define virt_to_phys(vaddr) ((unsigned long) (vaddr) - PAGE_OFFSET) + +#else + +#define phys_to_virt(vaddr) ((void *) (vaddr)) +#define virt_to_phys(vaddr) ((unsigned long) (vaddr)) + +#endif + +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt + +#define __page_address(page) (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT)) +#define page_to_phys(page) virt_to_phys((void *)__page_address(page)) + +#endif +#endif diff --git a/arch/frv/include/asm/xor.h b/arch/frv/include/asm/xor.h new file mode 100644 index 00000000000..c82eb12a5b1 --- /dev/null +++ b/arch/frv/include/asm/xor.h @@ -0,0 +1 @@ +#include <asm-generic/xor.h> diff --git a/arch/frv/include/uapi/asm/Kbuild b/arch/frv/include/uapi/asm/Kbuild new file mode 100644 index 00000000000..42a2b33461c --- /dev/null +++ b/arch/frv/include/uapi/asm/Kbuild @@ -0,0 +1,35 @@ +# UAPI Header export list +include include/uapi/asm-generic/Kbuild.asm + +header-y += auxvec.h +header-y += bitsperlong.h +header-y += byteorder.h +header-y += errno.h +header-y += fcntl.h +header-y += ioctl.h +header-y += ioctls.h +header-y += ipcbuf.h +header-y += kvm_para.h +header-y += mman.h +header-y += msgbuf.h +header-y += param.h +header-y += poll.h +header-y += posix_types.h +header-y += ptrace.h +header-y += registers.h +header-y += resource.h +header-y += sembuf.h +header-y += setup.h +header-y += shmbuf.h +header-y += sigcontext.h +header-y += siginfo.h +header-y += signal.h +header-y += socket.h +header-y += sockios.h +header-y += stat.h +header-y += statfs.h +header-y += swab.h +header-y += termbits.h +header-y += termios.h +header-y += types.h +header-y += unistd.h diff --git a/arch/frv/include/uapi/asm/auxvec.h b/arch/frv/include/uapi/asm/auxvec.h new file mode 100644 index 00000000000..07710778fa1 --- /dev/null +++ b/arch/frv/include/uapi/asm/auxvec.h @@ -0,0 +1,4 @@ +#ifndef __FRV_AUXVEC_H +#define __FRV_AUXVEC_H + +#endif diff --git a/arch/frv/include/uapi/asm/bitsperlong.h b/arch/frv/include/uapi/asm/bitsperlong.h new file mode 100644 index 00000000000..6dc0bb0c13b --- /dev/null +++ b/arch/frv/include/uapi/asm/bitsperlong.h @@ -0,0 +1 @@ +#include <asm-generic/bitsperlong.h> diff --git a/arch/frv/include/uapi/asm/byteorder.h b/arch/frv/include/uapi/asm/byteorder.h new file mode 100644 index 00000000000..f29b7593e08 --- /dev/null +++ b/arch/frv/include/uapi/asm/byteorder.h @@ -0,0 +1,6 @@ +#ifndef _ASM_BYTEORDER_H +#define _ASM_BYTEORDER_H + +#include <linux/byteorder/big_endian.h> + +#endif /* _ASM_BYTEORDER_H */ diff --git a/arch/frv/include/uapi/asm/errno.h b/arch/frv/include/uapi/asm/errno.h new file mode 100644 index 00000000000..d010795ceef --- /dev/null +++ b/arch/frv/include/uapi/asm/errno.h @@ -0,0 +1,7 @@ +#ifndef _ASM_ERRNO_H +#define _ASM_ERRNO_H + +#include <asm-generic/errno.h> + +#endif /* _ASM_ERRNO_H */ + diff --git a/arch/frv/include/uapi/asm/fcntl.h b/arch/frv/include/uapi/asm/fcntl.h new file mode 100644 index 00000000000..46ab12db573 --- /dev/null +++ b/arch/frv/include/uapi/asm/fcntl.h @@ -0,0 +1 @@ +#include <asm-generic/fcntl.h> diff --git a/arch/frv/include/uapi/asm/ioctl.h b/arch/frv/include/uapi/asm/ioctl.h new file mode 100644 index 00000000000..b279fe06dfe --- /dev/null +++ b/arch/frv/include/uapi/asm/ioctl.h @@ -0,0 +1 @@ +#include <asm-generic/ioctl.h> diff --git a/arch/frv/include/uapi/asm/ioctls.h b/arch/frv/include/uapi/asm/ioctls.h new file mode 100644 index 00000000000..2f9fb436ec3 --- /dev/null +++ b/arch/frv/include/uapi/asm/ioctls.h @@ -0,0 +1,10 @@ +#ifndef __ASM_IOCTLS_H__ +#define __ASM_IOCTLS_H__ + +#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define FIOQSIZE 0x545E + +#include <asm-generic/ioctls.h> + +#endif /* __ASM_IOCTLS_H__ */ + diff --git a/arch/frv/include/uapi/asm/ipcbuf.h b/arch/frv/include/uapi/asm/ipcbuf.h new file mode 100644 index 00000000000..84c7e51cb6d --- /dev/null +++ b/arch/frv/include/uapi/asm/ipcbuf.h @@ -0,0 +1 @@ +#include <asm-generic/ipcbuf.h> diff --git a/arch/frv/include/uapi/asm/kvm_para.h b/arch/frv/include/uapi/asm/kvm_para.h new file mode 100644 index 00000000000..14fab8f0b95 --- /dev/null +++ b/arch/frv/include/uapi/asm/kvm_para.h @@ -0,0 +1 @@ +#include <asm-generic/kvm_para.h> diff --git a/arch/frv/include/uapi/asm/mman.h b/arch/frv/include/uapi/asm/mman.h new file mode 100644 index 00000000000..8eebf89f5ab --- /dev/null +++ b/arch/frv/include/uapi/asm/mman.h @@ -0,0 +1 @@ +#include <asm-generic/mman.h> diff --git a/arch/frv/include/uapi/asm/msgbuf.h b/arch/frv/include/uapi/asm/msgbuf.h new file mode 100644 index 00000000000..97ceb55a06f --- /dev/null +++ b/arch/frv/include/uapi/asm/msgbuf.h @@ -0,0 +1,32 @@ +#ifndef _ASM_MSGBUF_H +#define _ASM_MSGBUF_H + +/* + * The msqid64_ds structure for FR-V architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct msqid64_ds { + struct ipc64_perm msg_perm; + __kernel_time_t msg_stime; /* last msgsnd time */ + unsigned long __unused1; + __kernel_time_t msg_rtime; /* last msgrcv time */ + unsigned long __unused2; + __kernel_time_t msg_ctime; /* last change time */ + unsigned long __unused3; + unsigned long msg_cbytes; /* current number of bytes on queue */ + unsigned long msg_qnum; /* number of messages in queue */ + unsigned long msg_qbytes; /* max number of bytes on queue */ + __kernel_pid_t msg_lspid; /* pid of last msgsnd */ + __kernel_pid_t msg_lrpid; /* last receive pid */ + unsigned long __unused4; + unsigned long __unused5; +}; + +#endif /* _ASM_MSGBUF_H */ + diff --git a/arch/frv/include/uapi/asm/param.h b/arch/frv/include/uapi/asm/param.h new file mode 100644 index 00000000000..a52dca9a956 --- /dev/null +++ b/arch/frv/include/uapi/asm/param.h @@ -0,0 +1,8 @@ +#ifndef _ASM_PARAM_H +#define _ASM_PARAM_H + +#define EXEC_PAGESIZE 16384 + +#include <asm-generic/param.h> + +#endif /* _ASM_PARAM_H */ diff --git a/arch/frv/include/uapi/asm/poll.h b/arch/frv/include/uapi/asm/poll.h new file mode 100644 index 00000000000..0d01479ccc5 --- /dev/null +++ b/arch/frv/include/uapi/asm/poll.h @@ -0,0 +1,12 @@ +#ifndef _ASM_POLL_H +#define _ASM_POLL_H + +#define POLLWRNORM POLLOUT +#define POLLWRBAND 256 + +#include <asm-generic/poll.h> + +#undef POLLREMOVE + +#endif + diff --git a/arch/frv/include/uapi/asm/posix_types.h b/arch/frv/include/uapi/asm/posix_types.h new file mode 100644 index 00000000000..fe512af74a5 --- /dev/null +++ b/arch/frv/include/uapi/asm/posix_types.h @@ -0,0 +1,26 @@ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned short __kernel_mode_t; +#define __kernel_mode_t __kernel_mode_t + +typedef unsigned short __kernel_ipc_pid_t; +#define __kernel_ipc_pid_t __kernel_ipc_pid_t + +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +#define __kernel_uid_t __kernel_uid_t + +typedef unsigned short __kernel_old_dev_t; +#define __kernel_old_dev_t __kernel_old_dev_t + +#include <asm-generic/posix_types.h> + +#endif + diff --git a/arch/frv/include/uapi/asm/ptrace.h b/arch/frv/include/uapi/asm/ptrace.h new file mode 100644 index 00000000000..3887e493468 --- /dev/null +++ b/arch/frv/include/uapi/asm/ptrace.h @@ -0,0 +1,60 @@ +/* ptrace.h: ptrace() relevant definitions + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _UAPI_ASM_PTRACE_H +#define _UAPI_ASM_PTRACE_H + +#include <asm/registers.h> + + +#define PT_PSR 0 +#define PT_ISR 1 +#define PT_CCR 2 +#define PT_CCCR 3 +#define PT_LR 4 +#define PT_LCR 5 +#define PT_PC 6 + +#define PT__STATUS 7 /* exception status */ +#define PT_SYSCALLNO 8 /* syscall number or -1 */ +#define PT_ORIG_GR8 9 /* saved GR8 for signal handling */ +#define PT_GNER0 10 +#define PT_GNER1 11 +#define PT_IACC0H 12 +#define PT_IACC0L 13 + +#define PT_GR(j) ( 14 + (j)) /* GRj for 0<=j<=63 */ +#define PT_FR(j) ( 78 + (j)) /* FRj for 0<=j<=63 */ +#define PT_FNER(j) (142 + (j)) /* FNERj for 0<=j<=1 */ +#define PT_MSR(j) (144 + (j)) /* MSRj for 0<=j<=2 */ +#define PT_ACC(j) (146 + (j)) /* ACCj for 0<=j<=7 */ +#define PT_ACCG(jklm) (154 + (jklm)) /* ACCGjklm for 0<=jklm<=1 (reads four regs per slot) */ +#define PT_FSR(j) (156 + (j)) /* FSRj for 0<=j<=0 */ +#define PT__GPEND 78 +#define PT__END 157 + +#define PT_TBR PT_GR(0) +#define PT_SP PT_GR(1) +#define PT_FP PT_GR(2) +#define PT_PREV_FRAME PT_GR(28) /* previous exception frame pointer (old gr28 value) */ +#define PT_CURR_TASK PT_GR(29) /* current task */ + + +/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */ +#define PTRACE_GETREGS 12 +#define PTRACE_SETREGS 13 +#define PTRACE_GETFPREGS 14 +#define PTRACE_SETFPREGS 15 +#define PTRACE_GETFDPIC 31 /* get the ELF fdpic loadmap address */ + +#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */ +#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */ + +#endif /* _UAPI_ASM_PTRACE_H */ diff --git a/arch/frv/include/uapi/asm/registers.h b/arch/frv/include/uapi/asm/registers.h new file mode 100644 index 00000000000..9666119fcf6 --- /dev/null +++ b/arch/frv/include/uapi/asm/registers.h @@ -0,0 +1,232 @@ +/* registers.h: register frame declarations + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* + * notes: + * + * (1) that the members of all these structures are carefully aligned to permit + * usage of STD/STDF instructions + * + * (2) if you change these structures, you must change the code in + * arch/frvnommu/kernel/{break.S,entry.S,switch_to.S,gdb-stub.c} + * + * + * the kernel stack space block looks like this: + * + * +0x2000 +---------------------- + * | union { + * | struct frv_frame0 { + * | struct user_context { + * | struct user_int_regs + * | struct user_fpmedia_regs + * | } + * | struct frv_debug_regs + * | } + * | struct pt_regs [user exception] + * | } + * +---------------------- <-- __kernel_frame0_ptr (maybe GR28) + * | + * | kernel stack + * | + * |...................... + * | struct pt_regs [kernel exception] + * |...................... <-- __kernel_frame0_ptr (maybe GR28) + * | + * | kernel stack + * | + * |...................... <-- stack pointer (GR1) + * | + * | unused stack space + * | + * +---------------------- + * | struct thread_info + * +0x0000 +---------------------- <-- __current_thread_info (GR15); + * + * note that GR28 points to the current exception frame + */ + +#ifndef _ASM_REGISTERS_H +#define _ASM_REGISTERS_H + +#ifndef __ASSEMBLY__ +#define __OFFSET(X,N) ((X)+(N)*4) +#define __OFFSETC(X,N) xxxxxxxxxxxxxxxxxxxxxxxx +#else +#define __OFFSET(X,N) ((X)+(N)*4) +#define __OFFSETC(X,N) ((X)+(N)) +#endif + +/*****************************************************************************/ +/* + * Exception/Interrupt frame + * - held on kernel stack + * - 8-byte aligned on stack (old SP is saved in frame) + * - GR0 is fixed 0, so we don't save it + */ +#ifndef __ASSEMBLY__ + +struct pt_regs { + unsigned long psr; /* Processor Status Register */ + unsigned long isr; /* Integer Status Register */ + unsigned long ccr; /* Condition Code Register */ + unsigned long cccr; /* Condition Code for Conditional Insns Register */ + unsigned long lr; /* Link Register */ + unsigned long lcr; /* Loop Count Register */ + unsigned long pc; /* Program Counter Register */ + unsigned long __status; /* exception status */ + unsigned long syscallno; /* syscall number or -1 */ + unsigned long orig_gr8; /* original syscall arg #1 */ + unsigned long gner0; + unsigned long gner1; + unsigned long long iacc0; + unsigned long tbr; /* GR0 is fixed zero, so we use this for TBR */ + unsigned long sp; /* GR1: USP/KSP */ + unsigned long fp; /* GR2: FP */ + unsigned long gr3; + unsigned long gr4; + unsigned long gr5; + unsigned long gr6; + unsigned long gr7; /* syscall number */ + unsigned long gr8; /* 1st syscall param; syscall return */ + unsigned long gr9; /* 2nd syscall param */ + unsigned long gr10; /* 3rd syscall param */ + unsigned long gr11; /* 4th syscall param */ + unsigned long gr12; /* 5th syscall param */ + unsigned long gr13; /* 6th syscall param */ + unsigned long gr14; + unsigned long gr15; + unsigned long gr16; /* GP pointer */ + unsigned long gr17; /* small data */ + unsigned long gr18; /* PIC/PID */ + unsigned long gr19; + unsigned long gr20; + unsigned long gr21; + unsigned long gr22; + unsigned long gr23; + unsigned long gr24; + unsigned long gr25; + unsigned long gr26; + unsigned long gr27; + struct pt_regs *next_frame; /* GR28 - next exception frame */ + unsigned long gr29; /* GR29 - OS reserved */ + unsigned long gr30; /* GR30 - OS reserved */ + unsigned long gr31; /* GR31 - OS reserved */ +} __attribute__((aligned(8))); + +#endif + +#define REG__STATUS_STEP 0x00000001 /* - reenable single stepping on return */ +#define REG__STATUS_STEPPED 0x00000002 /* - single step caused exception */ +#define REG__STATUS_BROKE 0x00000004 /* - BREAK insn caused exception */ +#define REG__STATUS_SYSC_ENTRY 0x40000000 /* - T on syscall entry (ptrace.c only) */ +#define REG__STATUS_SYSC_EXIT 0x80000000 /* - T on syscall exit (ptrace.c only) */ + +#define REG_GR(R) __OFFSET(REG_GR0, (R)) + +#define REG_SP REG_GR(1) +#define REG_FP REG_GR(2) +#define REG_PREV_FRAME REG_GR(28) /* previous exception frame pointer (old gr28 value) */ +#define REG_CURR_TASK REG_GR(29) /* current task */ + +/*****************************************************************************/ +/* + * debugging registers + */ +#ifndef __ASSEMBLY__ + +struct frv_debug_regs +{ + unsigned long dcr; + unsigned long ibar[4] __attribute__((aligned(8))); + unsigned long dbar[4] __attribute__((aligned(8))); + unsigned long dbdr[4][4] __attribute__((aligned(8))); + unsigned long dbmr[4][4] __attribute__((aligned(8))); +} __attribute__((aligned(8))); + +#endif + +/*****************************************************************************/ +/* + * userspace registers + */ +#ifndef __ASSEMBLY__ + +struct user_int_regs +{ + /* integer registers + * - up to gr[31] mirror pt_regs + * - total size must be multiple of 8 bytes + */ + unsigned long psr; /* Processor Status Register */ + unsigned long isr; /* Integer Status Register */ + unsigned long ccr; /* Condition Code Register */ + unsigned long cccr; /* Condition Code for Conditional Insns Register */ + unsigned long lr; /* Link Register */ + unsigned long lcr; /* Loop Count Register */ + unsigned long pc; /* Program Counter Register */ + unsigned long __status; /* exception status */ + unsigned long syscallno; /* syscall number or -1 */ + unsigned long orig_gr8; /* original syscall arg #1 */ + unsigned long gner[2]; + unsigned long long iacc[1]; + + union { + unsigned long tbr; + unsigned long gr[64]; + }; +}; + +struct user_fpmedia_regs +{ + /* FP/Media registers */ + unsigned long fr[64]; + unsigned long fner[2]; + unsigned long msr[2]; + unsigned long acc[8]; + unsigned char accg[8]; + unsigned long fsr[1]; +}; + +struct user_context +{ + struct user_int_regs i; + struct user_fpmedia_regs f; + + /* we provide a context extension so that we can save the regs for CPUs that + * implement many more of Fujitsu's lavish register spec + */ + void *extension; +} __attribute__((aligned(8))); + +struct frv_frame0 { + union { + struct pt_regs regs; + struct user_context uc; + }; + + struct frv_debug_regs debug; + +} __attribute__((aligned(32))); + +#endif + +#define __INT_GR(R) __OFFSET(__INT_GR0, (R)) + +#define __FPMEDIA_FR(R) __OFFSET(__FPMEDIA_FR0, (R)) +#define __FPMEDIA_FNER(R) __OFFSET(__FPMEDIA_FNER0, (R)) +#define __FPMEDIA_MSR(R) __OFFSET(__FPMEDIA_MSR0, (R)) +#define __FPMEDIA_ACC(R) __OFFSET(__FPMEDIA_ACC0, (R)) +#define __FPMEDIA_ACCG(R) __OFFSETC(__FPMEDIA_ACCG0, (R)) +#define __FPMEDIA_FSR(R) __OFFSET(__FPMEDIA_FSR0, (R)) + +#define __THREAD_GR(R) __OFFSET(__THREAD_GR16, (R) - 16) + +#endif /* _ASM_REGISTERS_H */ diff --git a/arch/frv/include/uapi/asm/resource.h b/arch/frv/include/uapi/asm/resource.h new file mode 100644 index 00000000000..5fc60548fd0 --- /dev/null +++ b/arch/frv/include/uapi/asm/resource.h @@ -0,0 +1,7 @@ +#ifndef _ASM_RESOURCE_H +#define _ASM_RESOURCE_H + +#include <asm-generic/resource.h> + +#endif /* _ASM_RESOURCE_H */ + diff --git a/arch/frv/include/uapi/asm/sembuf.h b/arch/frv/include/uapi/asm/sembuf.h new file mode 100644 index 00000000000..164b12786d6 --- /dev/null +++ b/arch/frv/include/uapi/asm/sembuf.h @@ -0,0 +1,26 @@ +#ifndef _ASM_SEMBUF_H +#define _ASM_SEMBUF_H + +/* + * The semid64_ds structure for FR-V architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct semid64_ds { + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ + __kernel_time_t sem_otime; /* last semop time */ + unsigned long __unused1; + __kernel_time_t sem_ctime; /* last change time */ + unsigned long __unused2; + unsigned long sem_nsems; /* no. of semaphores in array */ + unsigned long __unused3; + unsigned long __unused4; +}; + +#endif /* _ASM_SEMBUF_H */ + diff --git a/arch/frv/include/uapi/asm/setup.h b/arch/frv/include/uapi/asm/setup.h new file mode 100644 index 00000000000..fbf3fc96aae --- /dev/null +++ b/arch/frv/include/uapi/asm/setup.h @@ -0,0 +1,18 @@ +/* setup.h: setup stuff + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _UAPI_ASM_SETUP_H +#define _UAPI_ASM_SETUP_H + +#define COMMAND_LINE_SIZE 512 + + +#endif /* _UAPI_ASM_SETUP_H */ diff --git a/arch/frv/include/uapi/asm/shmbuf.h b/arch/frv/include/uapi/asm/shmbuf.h new file mode 100644 index 00000000000..4c6e711a477 --- /dev/null +++ b/arch/frv/include/uapi/asm/shmbuf.h @@ -0,0 +1,43 @@ +#ifndef _ASM_SHMBUF_H +#define _ASM_SHMBUF_H + +/* + * The shmid64_ds structure for FR-V architecture. + * Note extra padding because this structure is passed back and forth + * between kernel and user space. + * + * Pad space is left for: + * - 64-bit time_t to solve y2038 problem + * - 2 miscellaneous 32-bit values + */ + +struct shmid64_ds { + struct ipc64_perm shm_perm; /* operation perms */ + size_t shm_segsz; /* size of segment (bytes) */ + __kernel_time_t shm_atime; /* last attach time */ + unsigned long __unused1; + __kernel_time_t shm_dtime; /* last detach time */ + unsigned long __unused2; + __kernel_time_t shm_ctime; /* last change time */ + unsigned long __unused3; + __kernel_pid_t shm_cpid; /* pid of creator */ + __kernel_pid_t shm_lpid; /* pid of last operator */ + unsigned long shm_nattch; /* no. of current attaches */ + unsigned long __unused4; + unsigned long __unused5; +}; + +struct shminfo64 { + unsigned long shmmax; + unsigned long shmmin; + unsigned long shmmni; + unsigned long shmseg; + unsigned long shmall; + unsigned long __unused1; + unsigned long __unused2; + unsigned long __unused3; + unsigned long __unused4; +}; + +#endif /* _ASM_SHMBUF_H */ + diff --git a/arch/frv/include/uapi/asm/sigcontext.h b/arch/frv/include/uapi/asm/sigcontext.h new file mode 100644 index 00000000000..3b263f3cc96 --- /dev/null +++ b/arch/frv/include/uapi/asm/sigcontext.h @@ -0,0 +1,26 @@ +/* sigcontext.h: FRV signal context + * + * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#ifndef _ASM_SIGCONTEXT_H +#define _ASM_SIGCONTEXT_H + +#include <asm/registers.h> + +/* + * Signal context structure - contains all info to do with the state + * before the signal handler was invoked. Note: only add new entries + * to the end of the structure. + */ +struct sigcontext { + struct user_context sc_context; + unsigned long sc_oldmask; /* old sigmask */ +} __attribute__((aligned(8))); + +#endif diff --git a/arch/frv/include/uapi/asm/siginfo.h b/arch/frv/include/uapi/asm/siginfo.h new file mode 100644 index 00000000000..d3fd1ca4565 --- /dev/null +++ b/arch/frv/include/uapi/asm/siginfo.h @@ -0,0 +1,12 @@ +#ifndef _ASM_SIGINFO_H +#define _ASM_SIGINFO_H + +#include <linux/types.h> +#include <asm-generic/siginfo.h> + +#define FPE_MDAOVF (__SI_FAULT|9) /* media overflow */ +#undef NSIGFPE +#define NSIGFPE 9 + +#endif + diff --git a/arch/frv/include/uapi/asm/signal.h b/arch/frv/include/uapi/asm/signal.h new file mode 100644 index 00000000000..bf3b162f9be --- /dev/null +++ b/arch/frv/include/uapi/asm/signal.h @@ -0,0 +1,36 @@ +#ifndef _UAPI_ASM_SIGNAL_H +#define _UAPI_ASM_SIGNAL_H + +#include <linux/types.h> + +#ifndef __KERNEL__ +/* Here we must cater to libcs that poke about in kernel headers. */ + +#define NSIG 32 +typedef unsigned long sigset_t; + +#endif /* !__KERNEL__ */ + +#define SA_RESTORER 0x04000000 /* to get struct sigaction correct */ + +#include <asm-generic/signal.h> + +#ifndef __KERNEL__ +/* Here we must cater to libcs that poke about in kernel headers. */ + +struct sigaction { + union { + __sighandler_t _sa_handler; + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; + +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + +#endif /* __KERNEL__ */ + +#endif /* _UAPI_ASM_SIGNAL_H */ diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h new file mode 100644 index 00000000000..ca2c6e6f31c --- /dev/null +++ b/arch/frv/include/uapi/asm/socket.h @@ -0,0 +1,84 @@ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +#include <asm/sockios.h> + +/* For setsockopt(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_SNDBUFFORCE 32 +#define SO_RCVBUFFORCE 33 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +#define SO_REUSEPORT 15 +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 +#define SO_GET_FILTER SO_ATTACH_FILTER + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 +#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS + +#define SO_MARK 36 + +#define SO_TIMESTAMPING 37 +#define SCM_TIMESTAMPING SO_TIMESTAMPING + +#define SO_PROTOCOL 38 +#define SO_DOMAIN 39 + +#define SO_RXQ_OVFL 40 + +#define SO_WIFI_STATUS 41 +#define SCM_WIFI_STATUS SO_WIFI_STATUS +#define SO_PEEK_OFF 42 + +/* Instruct lower device to use last 4-bytes of skb data as FCS */ +#define SO_NOFCS 43 + +#define SO_LOCK_FILTER 44 + +#define SO_SELECT_ERR_QUEUE 45 + +#define SO_BUSY_POLL 46 + +#define SO_MAX_PACING_RATE 47 + +#define SO_BPF_EXTENSIONS 48 + +#endif /* _ASM_SOCKET_H */ + diff --git a/arch/frv/include/uapi/asm/sockios.h b/arch/frv/include/uapi/asm/sockios.h new file mode 100644 index 00000000000..5dbdd13e6de --- /dev/null +++ b/arch/frv/include/uapi/asm/sockios.h @@ -0,0 +1,14 @@ +#ifndef _ASM_SOCKIOS__ +#define _ASM_SOCKIOS__ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ +#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ + +#endif /* _ASM_SOCKIOS__ */ + diff --git a/arch/frv/include/uapi/asm/stat.h b/arch/frv/include/uapi/asm/stat.h new file mode 100644 index 00000000000..ce56de9b37b --- /dev/null +++ b/arch/frv/include/uapi/asm/stat.h @@ -0,0 +1,100 @@ +#ifndef _ASM_STAT_H +#define _ASM_STAT_H + +struct __old_kernel_stat { + unsigned short st_dev; + unsigned short st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned long st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; +}; + +/* This matches struct stat in uClibc/glibc. */ +struct stat { + unsigned char __pad1[6]; + unsigned short st_dev; + + unsigned long __pad2; + unsigned long st_ino; + + unsigned short __pad3; + unsigned short st_mode; + unsigned short __pad4; + unsigned short st_nlink; + + unsigned short __pad5; + unsigned short st_uid; + unsigned short __pad6; + unsigned short st_gid; + + unsigned char __pad7[6]; + unsigned short st_rdev; + + unsigned long __pad8; + unsigned long st_size; + + unsigned long __pad9; /* align 64-bit st_blocks to 2-word */ + unsigned long st_blksize; + + unsigned long __pad10; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long __unused1; + unsigned long st_atime; + + unsigned long __unused2; + unsigned long st_mtime; + + unsigned long __unused3; + unsigned long st_ctime; + + unsigned long long __unused4; +}; + +/* This matches struct stat64 in uClibc/glibc. The layout is exactly + the same as that of struct stat above, with 64-bit types taking up + space that was formerly used by padding. stat syscalls are still + different from stat64, though, in that the former tests for + overflow. */ +struct stat64 { + unsigned char __pad1[6]; + unsigned short st_dev; + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned char __pad2[6]; + unsigned short st_rdev; + + long long st_size; + + unsigned long __pad3; /* align 64-bit st_blocks to 2-word */ + unsigned long st_blksize; + + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long st_atime_nsec; + unsigned long st_atime; + + unsigned int st_mtime_nsec; + unsigned long st_mtime; + + unsigned long st_ctime_nsec; + unsigned long st_ctime; + + unsigned long long __unused4; +}; + +#endif /* _ASM_STAT_H */ diff --git a/arch/frv/include/uapi/asm/statfs.h b/arch/frv/include/uapi/asm/statfs.h new file mode 100644 index 00000000000..741f586045b --- /dev/null +++ b/arch/frv/include/uapi/asm/statfs.h @@ -0,0 +1,7 @@ +#ifndef _ASM_STATFS_H +#define _ASM_STATFS_H + +#include <asm-generic/statfs.h> + +#endif /* _ASM_STATFS_H */ + diff --git a/arch/frv/include/uapi/asm/swab.h b/arch/frv/include/uapi/asm/swab.h new file mode 100644 index 00000000000..f305834b479 --- /dev/null +++ b/arch/frv/include/uapi/asm/swab.h @@ -0,0 +1,10 @@ +#ifndef _ASM_SWAB_H +#define _ASM_SWAB_H + +#include <linux/types.h> + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__) +# define __SWAB_64_THRU_32__ +#endif + +#endif /* _ASM_SWAB_H */ diff --git a/arch/frv/include/uapi/asm/termbits.h b/arch/frv/include/uapi/asm/termbits.h new file mode 100644 index 00000000000..7722e19cc34 --- /dev/null +++ b/arch/frv/include/uapi/asm/termbits.h @@ -0,0 +1,203 @@ +#ifndef _ASM_TERMBITS_H__ +#define _ASM_TERMBITS_H__ + +#include <linux/posix_types.h> + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 19 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ +}; + +struct termios2 { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +struct ktermios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#define NLDLY 0000400 +#define NL0 0000000 +#define NL1 0000400 +#define CRDLY 0003000 +#define CR0 0000000 +#define CR1 0001000 +#define CR2 0002000 +#define CR3 0003000 +#define TABDLY 0014000 +#define TAB0 0000000 +#define TAB1 0004000 +#define TAB2 0010000 +#define TAB3 0014000 +#define XTABS 0014000 +#define BSDLY 0020000 +#define BS0 0000000 +#define BS1 0020000 +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 +#define FFDLY 0100000 +#define FF0 0000000 +#define FF1 0100000 + +/* c_cflag bit meaning */ +#define CBAUD 0010017 +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#define EXTA B19200 +#define EXTB B38400 +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#define CBAUDEX 0010000 +#define BOTHER 0010000 +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define CIBAUD 002003600000 /* Input baud rate */ +#define CTVB 004000000000 /* VisioBraille Terminal flow control */ +#define CMSPAR 010000000000 /* mark or space (stick) parity */ +#define CRTSCTS 020000000000 /* flow control */ + +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#define XCASE 0000004 +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#define ECHOCTL 0001000 +#define ECHOPRT 0002000 +#define ECHOKE 0004000 +#define FLUSHO 0010000 +#define PENDIN 0040000 +#define IEXTEN 0100000 +#define EXTPROC 0200000 + + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +#endif /* _ASM_TERMBITS_H__ */ + diff --git a/arch/frv/include/uapi/asm/termios.h b/arch/frv/include/uapi/asm/termios.h new file mode 100644 index 00000000000..edcc08a2238 --- /dev/null +++ b/arch/frv/include/uapi/asm/termios.h @@ -0,0 +1,46 @@ +#ifndef _UAPI_ASM_TERMIOS_H +#define _UAPI_ASM_TERMIOS_H + +#include <asm/termbits.h> +#include <asm/ioctls.h> + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 8 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +#define TIOCM_MODEM_BITS TIOCM_OUT2 /* IRDA support */ + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + + +#endif /* _UAPI_ASM_TERMIOS_H */ diff --git a/arch/frv/include/uapi/asm/types.h b/arch/frv/include/uapi/asm/types.h new file mode 100644 index 00000000000..cf23149943f --- /dev/null +++ b/arch/frv/include/uapi/asm/types.h @@ -0,0 +1,11 @@ +/* types.h: FRV types + * + * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <asm-generic/int-ll64.h> diff --git a/arch/frv/include/uapi/asm/unistd.h b/arch/frv/include/uapi/asm/unistd.h new file mode 100644 index 00000000000..9e2612ff1c9 --- /dev/null +++ b/arch/frv/include/uapi/asm/unistd.h @@ -0,0 +1,348 @@ +#ifndef _UAPI_ASM_UNISTD_H_ +#define _UAPI_ASM_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +#define __NR_restart_syscall 0 +#define __NR_exit 1 +#define __NR_fork 2 +#define __NR_read 3 +#define __NR_write 4 +#define __NR_open 5 +#define __NR_close 6 +#define __NR_waitpid 7 +#define __NR_creat 8 +#define __NR_link 9 +#define __NR_unlink 10 +#define __NR_execve 11 +#define __NR_chdir 12 +#define __NR_time 13 +#define __NR_mknod 14 +#define __NR_chmod 15 +#define __NR_lchown 16 +#define __NR_break 17 +#define __NR_oldstat 18 +#define __NR_lseek 19 +#define __NR_getpid 20 +#define __NR_mount 21 +#define __NR_umount 22 +#define __NR_setuid 23 +#define __NR_getuid 24 +#define __NR_stime 25 +#define __NR_ptrace 26 +#define __NR_alarm 27 +#define __NR_oldfstat 28 +#define __NR_pause 29 +#define __NR_utime 30 +#define __NR_stty 31 +#define __NR_gtty 32 +#define __NR_access 33 +#define __NR_nice 34 +#define __NR_ftime 35 +#define __NR_sync 36 +#define __NR_kill 37 +#define __NR_rename 38 +#define __NR_mkdir 39 +#define __NR_rmdir 40 +#define __NR_dup 41 +#define __NR_pipe 42 +#define __NR_times 43 +#define __NR_prof 44 +#define __NR_brk 45 +#define __NR_setgid 46 +#define __NR_getgid 47 +#define __NR_signal 48 +#define __NR_geteuid 49 +#define __NR_getegid 50 +#define __NR_acct 51 +#define __NR_umount2 52 +#define __NR_lock 53 +#define __NR_ioctl 54 +#define __NR_fcntl 55 +#define __NR_mpx 56 +#define __NR_setpgid 57 +#define __NR_ulimit 58 +// #define __NR_oldolduname /* 59 */ obsolete +#define __NR_umask 60 +#define __NR_chroot 61 +#define __NR_ustat 62 +#define __NR_dup2 63 +#define __NR_getppid 64 +#define __NR_getpgrp 65 +#define __NR_setsid 66 +#define __NR_sigaction 67 +#define __NR_sgetmask 68 +#define __NR_ssetmask 69 +#define __NR_setreuid 70 +#define __NR_setregid 71 +#define __NR_sigsuspend 72 +#define __NR_sigpending 73 +#define __NR_sethostname 74 +#define __NR_setrlimit 75 +#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */ +#define __NR_getrusage 77 +#define __NR_gettimeofday 78 +#define __NR_settimeofday 79 +#define __NR_getgroups 80 +#define __NR_setgroups 81 +#define __NR_select 82 +#define __NR_symlink 83 +#define __NR_oldlstat 84 +#define __NR_readlink 85 +#define __NR_uselib 86 +#define __NR_swapon 87 +#define __NR_reboot 88 +#define __NR_readdir 89 +// #define __NR_mmap 90 /* obsolete - not implemented */ +#define __NR_munmap 91 +#define __NR_truncate 92 +#define __NR_ftruncate 93 +#define __NR_fchmod 94 +#define __NR_fchown 95 +#define __NR_getpriority 96 +#define __NR_setpriority 97 +// #define __NR_profil /* 98 */ obsolete +#define __NR_statfs 99 +#define __NR_fstatfs 100 +// #define __NR_ioperm /* 101 */ not supported +#define __NR_socketcall 102 +#define __NR_syslog 103 +#define __NR_setitimer 104 +#define __NR_getitimer 105 +#define __NR_stat 106 +#define __NR_lstat 107 +#define __NR_fstat 108 +// #define __NR_olduname /* 109 */ obsolete +// #define __NR_iopl /* 110 */ not supported +#define __NR_vhangup 111 +// #define __NR_idle /* 112 */ Obsolete +// #define __NR_vm86old /* 113 */ not supported +#define __NR_wait4 114 +#define __NR_swapoff 115 +#define __NR_sysinfo 116 +#define __NR_ipc 117 +#define __NR_fsync 118 +#define __NR_sigreturn 119 +#define __NR_clone 120 +#define __NR_setdomainname 121 +#define __NR_uname 122 +// #define __NR_modify_ldt /* 123 */ not supported +#define __NR_cacheflush 123 +#define __NR_adjtimex 124 +#define __NR_mprotect 125 +#define __NR_sigprocmask 126 +#define __NR_create_module 127 +#define __NR_init_module 128 +#define __NR_delete_module 129 +#define __NR_get_kernel_syms 130 +#define __NR_quotactl 131 +#define __NR_getpgid 132 +#define __NR_fchdir 133 +#define __NR_bdflush 134 +#define __NR_sysfs 135 +#define __NR_personality 136 +#define __NR_afs_syscall 137 /* Syscall for Andrew File System */ +#define __NR_setfsuid 138 +#define __NR_setfsgid 139 +#define __NR__llseek 140 +#define __NR_getdents 141 +#define __NR__newselect 142 +#define __NR_flock 143 +#define __NR_msync 144 +#define __NR_readv 145 +#define __NR_writev 146 +#define __NR_getsid 147 +#define __NR_fdatasync 148 +#define __NR__sysctl 149 +#define __NR_mlock 150 +#define __NR_munlock 151 +#define __NR_mlockall 152 +#define __NR_munlockall 153 +#define __NR_sched_setparam 154 +#define __NR_sched_getparam 155 +#define __NR_sched_setscheduler 156 +#define __NR_sched_getscheduler 157 +#define __NR_sched_yield 158 +#define __NR_sched_get_priority_max 159 +#define __NR_sched_get_priority_min 160 +#define __NR_sched_rr_get_interval 161 +#define __NR_nanosleep 162 +#define __NR_mremap 163 +#define __NR_setresuid 164 +#define __NR_getresuid 165 +// #define __NR_vm86 /* 166 */ not supported +#define __NR_query_module 167 +#define __NR_poll 168 +#define __NR_nfsservctl 169 +#define __NR_setresgid 170 +#define __NR_getresgid 171 +#define __NR_prctl 172 +#define __NR_rt_sigreturn 173 +#define __NR_rt_sigaction 174 +#define __NR_rt_sigprocmask 175 +#define __NR_rt_sigpending 176 +#define __NR_rt_sigtimedwait 177 +#define __NR_rt_sigqueueinfo 178 +#define __NR_rt_sigsuspend 179 +#define __NR_pread64 180 +#define __NR_pwrite64 181 +#define __NR_chown 182 +#define __NR_getcwd 183 +#define __NR_capget 184 +#define __NR_capset 185 +#define __NR_sigaltstack 186 +#define __NR_sendfile 187 +#define __NR_getpmsg 188 /* some people actually want streams */ +#define __NR_putpmsg 189 /* some people actually want streams */ +#define __NR_vfork 190 +#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */ +#define __NR_mmap2 192 +#define __NR_truncate64 193 +#define __NR_ftruncate64 194 +#define __NR_stat64 195 +#define __NR_lstat64 196 +#define __NR_fstat64 197 +#define __NR_lchown32 198 +#define __NR_getuid32 199 +#define __NR_getgid32 200 +#define __NR_geteuid32 201 +#define __NR_getegid32 202 +#define __NR_setreuid32 203 +#define __NR_setregid32 204 +#define __NR_getgroups32 205 +#define __NR_setgroups32 206 +#define __NR_fchown32 207 +#define __NR_setresuid32 208 +#define __NR_getresuid32 209 +#define __NR_setresgid32 210 +#define __NR_getresgid32 211 +#define __NR_chown32 212 +#define __NR_setuid32 213 +#define __NR_setgid32 214 +#define __NR_setfsuid32 215 +#define __NR_setfsgid32 216 +#define __NR_pivot_root 217 +#define __NR_mincore 218 +#define __NR_madvise 219 + +#define __NR_getdents64 220 +#define __NR_fcntl64 221 +#define __NR_security 223 /* syscall for security modules */ +#define __NR_gettid 224 +#define __NR_readahead 225 +#define __NR_setxattr 226 +#define __NR_lsetxattr 227 +#define __NR_fsetxattr 228 +#define __NR_getxattr 229 +#define __NR_lgetxattr 230 +#define __NR_fgetxattr 231 +#define __NR_listxattr 232 +#define __NR_llistxattr 233 +#define __NR_flistxattr 234 +#define __NR_removexattr 235 +#define __NR_lremovexattr 236 +#define __NR_fremovexattr 237 +#define __NR_tkill 238 +#define __NR_sendfile64 239 +#define __NR_futex 240 +#define __NR_sched_setaffinity 241 +#define __NR_sched_getaffinity 242 +#define __NR_set_thread_area 243 +#define __NR_get_thread_area 244 +#define __NR_io_setup 245 +#define __NR_io_destroy 246 +#define __NR_io_getevents 247 +#define __NR_io_submit 248 +#define __NR_io_cancel 249 +#define __NR_fadvise64 250 + +#define __NR_exit_group 252 +#define __NR_lookup_dcookie 253 +#define __NR_epoll_create 254 +#define __NR_epoll_ctl 255 +#define __NR_epoll_wait 256 +#define __NR_remap_file_pages 257 +#define __NR_set_tid_address 258 +#define __NR_timer_create 259 +#define __NR_timer_settime (__NR_timer_create+1) +#define __NR_timer_gettime (__NR_timer_create+2) +#define __NR_timer_getoverrun (__NR_timer_create+3) +#define __NR_timer_delete (__NR_timer_create+4) +#define __NR_clock_settime (__NR_timer_create+5) +#define __NR_clock_gettime (__NR_timer_create+6) +#define __NR_clock_getres (__NR_timer_create+7) +#define __NR_clock_nanosleep (__NR_timer_create+8) +#define __NR_statfs64 268 +#define __NR_fstatfs64 269 +#define __NR_tgkill 270 +#define __NR_utimes 271 +#define __NR_fadvise64_64 272 +#define __NR_vserver 273 +#define __NR_mbind 274 +#define __NR_get_mempolicy 275 +#define __NR_set_mempolicy 276 +#define __NR_mq_open 277 +#define __NR_mq_unlink (__NR_mq_open+1) +#define __NR_mq_timedsend (__NR_mq_open+2) +#define __NR_mq_timedreceive (__NR_mq_open+3) +#define __NR_mq_notify (__NR_mq_open+4) +#define __NR_mq_getsetattr (__NR_mq_open+5) +#define __NR_kexec_load 283 +#define __NR_waitid 284 +/* #define __NR_sys_setaltroot 285 */ +#define __NR_add_key 286 +#define __NR_request_key 287 +#define __NR_keyctl 288 +#define __NR_ioprio_set 289 +#define __NR_ioprio_get 290 +#define __NR_inotify_init 291 +#define __NR_inotify_add_watch 292 +#define __NR_inotify_rm_watch 293 +#define __NR_migrate_pages 294 +#define __NR_openat 295 +#define __NR_mkdirat 296 +#define __NR_mknodat 297 +#define __NR_fchownat 298 +#define __NR_futimesat 299 +#define __NR_fstatat64 300 +#define __NR_unlinkat 301 +#define __NR_renameat 302 +#define __NR_linkat 303 +#define __NR_symlinkat 304 +#define __NR_readlinkat 305 +#define __NR_fchmodat 306 +#define __NR_faccessat 307 +#define __NR_pselect6 308 +#define __NR_ppoll 309 +#define __NR_unshare 310 +#define __NR_set_robust_list 311 +#define __NR_get_robust_list 312 +#define __NR_splice 313 +#define __NR_sync_file_range 314 +#define __NR_tee 315 +#define __NR_vmsplice 316 +#define __NR_move_pages 317 +#define __NR_getcpu 318 +#define __NR_epoll_pwait 319 +#define __NR_utimensat 320 +#define __NR_signalfd 321 +#define __NR_timerfd_create 322 +#define __NR_eventfd 323 +#define __NR_fallocate 324 +#define __NR_timerfd_settime 325 +#define __NR_timerfd_gettime 326 +#define __NR_signalfd4 327 +#define __NR_eventfd2 328 +#define __NR_epoll_create1 329 +#define __NR_dup3 330 +#define __NR_pipe2 331 +#define __NR_inotify_init1 332 +#define __NR_preadv 333 +#define __NR_pwritev 334 +#define __NR_rt_tgsigqueueinfo 335 +#define __NR_perf_event_open 336 +#define __NR_setns 337 + +#endif /* _UAPI_ASM_UNISTD_H_ */ diff --git a/arch/frv/kernel/Makefile b/arch/frv/kernel/Makefile index 5a827b349b5..3cbb3294b9f 100644 --- a/arch/frv/kernel/Makefile +++ b/arch/frv/kernel/Makefile @@ -5,20 +5,19 @@ heads-y := head-uc-fr401.o head-uc-fr451.o head-uc-fr555.o heads-$(CONFIG_MMU) := head-mmu-fr451.o -extra-y:= head.o init_task.o vmlinux.lds +extra-y:= head.o vmlinux.lds -obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \ +obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o \ process.o traps.o ptrace.o signal.o dma.o \ - sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \ - debug-stub.o irq.o irq-routing.o sleep.o uaccess.o + sys_frv.o time.o setup.o frv_ksyms.o \ + debug-stub.o irq.o sleep.o uaccess.o obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-io.o obj-$(CONFIG_MB93091_VDK) += irq-mb93091.o -obj-$(CONFIG_MB93093_PDK) += irq-mb93093.o -obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o obj-$(CONFIG_PM) += pm.o cmode.o obj-$(CONFIG_MB93093_PDK) += pm-mb93093.o +obj-$(CONFIG_FUJITSU_MB93493) += irq-mb93493.o obj-$(CONFIG_SYSCTL) += sysctl.o obj-$(CONFIG_FUTEX) += futex.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c index 9e263112a6e..9de96843a27 100644 --- a/arch/frv/kernel/asm-offsets.c +++ b/arch/frv/kernel/asm-offsets.c @@ -1 +1,108 @@ -/* Dummy asm-offsets.c file. Required by kbuild and ready to be used - hint! */ +/* + * Generate definitions needed by assembly language modules. + * This code generates raw asm output which is post-processed + * to extract and format the required data. + */ + +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/personality.h> +#include <linux/kbuild.h> +#include <asm/registers.h> +#include <asm/ucontext.h> +#include <asm/processor.h> +#include <asm/thread_info.h> +#include <asm/gdb-stub.h> + +#define DEF_PTREG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \ + : : "i" (offsetof(struct pt_regs, reg))) + +#define DEF_IREG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \ + : : "i" (offsetof(struct user_context, reg))) + +#define DEF_FREG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \ + : : "i" (offsetof(struct user_context, reg))) + +#define DEF_0REG(sym, reg) \ + asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \ + : : "i" (offsetof(struct frv_frame0, reg))) + +void foo(void) +{ + /* offsets into the thread_info structure */ + OFFSET(TI_TASK, thread_info, task); + OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain); + OFFSET(TI_FLAGS, thread_info, flags); + OFFSET(TI_STATUS, thread_info, status); + OFFSET(TI_CPU, thread_info, cpu); + OFFSET(TI_PREEMPT_COUNT, thread_info, preempt_count); + OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit); + OFFSET(TI_RESTART_BLOCK, thread_info, restart_block); + BLANK(); + + /* offsets into register file storage */ + DEF_PTREG(REG_PSR, psr); + DEF_PTREG(REG_ISR, isr); + DEF_PTREG(REG_CCR, ccr); + DEF_PTREG(REG_CCCR, cccr); + DEF_PTREG(REG_LR, lr); + DEF_PTREG(REG_LCR, lcr); + DEF_PTREG(REG_PC, pc); + DEF_PTREG(REG__STATUS, __status); + DEF_PTREG(REG_SYSCALLNO, syscallno); + DEF_PTREG(REG_ORIG_GR8, orig_gr8); + DEF_PTREG(REG_GNER0, gner0); + DEF_PTREG(REG_GNER1, gner1); + DEF_PTREG(REG_IACC0, iacc0); + DEF_PTREG(REG_TBR, tbr); + DEF_PTREG(REG_GR0, tbr); + DEFINE(REG__END, sizeof(struct pt_regs)); + BLANK(); + + DEF_0REG(REG_DCR, debug.dcr); + DEF_0REG(REG_IBAR0, debug.ibar[0]); + DEF_0REG(REG_DBAR0, debug.dbar[0]); + DEF_0REG(REG_DBDR00, debug.dbdr[0][0]); + DEF_0REG(REG_DBMR00, debug.dbmr[0][0]); + BLANK(); + + DEF_IREG(__INT_GR0, i.gr[0]); + DEF_FREG(__USER_FPMEDIA, f); + DEF_FREG(__FPMEDIA_FR0, f.fr[0]); + DEF_FREG(__FPMEDIA_FNER0, f.fner[0]); + DEF_FREG(__FPMEDIA_MSR0, f.msr[0]); + DEF_FREG(__FPMEDIA_ACC0, f.acc[0]); + DEF_FREG(__FPMEDIA_ACCG0, f.accg[0]); + DEF_FREG(__FPMEDIA_FSR0, f.fsr[0]); + BLANK(); + + DEFINE(NR_PT_REGS, sizeof(struct pt_regs) / 4); + DEFINE(NR_USER_INT_REGS, sizeof(struct user_int_regs) / 4); + DEFINE(NR_USER_FPMEDIA_REGS, sizeof(struct user_fpmedia_regs) / 4); + DEFINE(NR_USER_CONTEXT, sizeof(struct user_context) / 4); + DEFINE(FRV_FRAME0_SIZE, sizeof(struct frv_frame0)); + BLANK(); + + /* offsets into thread_struct */ + OFFSET(__THREAD_FRAME, thread_struct, frame); + OFFSET(__THREAD_CURR, thread_struct, curr); + OFFSET(__THREAD_SP, thread_struct, sp); + OFFSET(__THREAD_FP, thread_struct, fp); + OFFSET(__THREAD_LR, thread_struct, lr); + OFFSET(__THREAD_PC, thread_struct, pc); + OFFSET(__THREAD_GR16, thread_struct, gr[0]); + OFFSET(__THREAD_SCHED_LR, thread_struct, sched_lr); + OFFSET(__THREAD_FRAME0, thread_struct, frame0); + OFFSET(__THREAD_USER, thread_struct, user); + BLANK(); + + /* offsets into frv_debug_status */ + OFFSET(DEBUG_BPSR, frv_debug_status, bpsr); + OFFSET(DEBUG_DCR, frv_debug_status, dcr); + OFFSET(DEBUG_BRR, frv_debug_status, brr); + OFFSET(DEBUG_NMAR, frv_debug_status, nmar); + BLANK(); +} diff --git a/arch/frv/kernel/break.S b/arch/frv/kernel/break.S index 33233dc23e2..cbb6958a314 100644 --- a/arch/frv/kernel/break.S +++ b/arch/frv/kernel/break.S @@ -9,12 +9,11 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/setup.h> #include <asm/segment.h> #include <asm/ptrace.h> +#include <asm/thread_info.h> #include <asm/spr-regs.h> #include <asm/errno.h> @@ -22,15 +21,13 @@ # # the break handler has its own stack # - .section .bss.stack + .section .bss..stack .globl __break_user_context - .balign 8192 + .balign THREAD_SIZE __break_stack: - .space (8192 - (USER_CONTEXT_SIZE + REG__DEBUG_XTRA)) & ~7 -__break_stack_tos: - .space REG__DEBUG_XTRA -__break_user_context: - .space USER_CONTEXT_SIZE + .space THREAD_SIZE - FRV_FRAME0_SIZE +__break_frame_0: + .space FRV_FRAME0_SIZE # # miscellaneous variables @@ -66,7 +63,7 @@ __break_trace_through_exceptions: # entry point for Break Exceptions/Interrupts # ############################################################################### - .text + .section .text..break .balign 4 .globl __entry_break __entry_break: @@ -75,8 +72,8 @@ __entry_break: #endif LEDS 0x1001,gr31 - sethi.p %hi(__break_user_context),gr31 - setlo %lo(__break_user_context),gr31 + sethi.p %hi(__break_frame_0),gr31 + setlo %lo(__break_frame_0),gr31 stdi gr2,@(gr31,#REG_GR(2)) movsg ccr,gr3 @@ -200,12 +197,20 @@ __break_step: movsg bpcsr,gr2 sethi.p %hi(__entry_kernel_external_interrupt),gr3 setlo %lo(__entry_kernel_external_interrupt),gr3 - subcc gr2,gr3,gr0,icc0 + subcc.p gr2,gr3,gr0,icc0 + sethi %hi(__entry_uspace_external_interrupt),gr3 + setlo.p %lo(__entry_uspace_external_interrupt),gr3 beq icc0,#2,__break_step_kernel_external_interrupt - sethi.p %hi(__entry_uspace_external_interrupt),gr3 - setlo %lo(__entry_uspace_external_interrupt),gr3 - subcc gr2,gr3,gr0,icc0 + subcc.p gr2,gr3,gr0,icc0 + sethi %hi(__entry_kernel_external_interrupt_virtually_disabled),gr3 + setlo.p %lo(__entry_kernel_external_interrupt_virtually_disabled),gr3 beq icc0,#2,__break_step_uspace_external_interrupt + subcc.p gr2,gr3,gr0,icc0 + sethi %hi(__entry_kernel_external_interrupt_virtual_reenable),gr3 + setlo.p %lo(__entry_kernel_external_interrupt_virtual_reenable),gr3 + beq icc0,#2,__break_step_kernel_external_interrupt_virtually_disabled + subcc gr2,gr3,gr0,icc0 + beq icc0,#2,__break_step_kernel_external_interrupt_virtual_reenable LEDS 0x2007,gr2 @@ -254,6 +259,9 @@ __break_step_kernel_softprog_interrupt: # step through an external interrupt from kernel mode .globl __break_step_kernel_external_interrupt __break_step_kernel_external_interrupt: + # deal with virtual interrupt disablement + beq icc2,#0,__break_step_kernel_external_interrupt_virtually_disabled + sethi.p %hi(__entry_kernel_external_interrupt_reentry),gr3 setlo %lo(__entry_kernel_external_interrupt_reentry),gr3 @@ -294,6 +302,64 @@ __break_return_as_kernel_prologue: #endif rett #1 +# we single-stepped into an interrupt handler whilst interrupts were merely virtually disabled +# need to really disable interrupts, set flag, fix up and return +__break_step_kernel_external_interrupt_virtually_disabled: + movsg psr,gr2 + andi gr2,#~PSR_PIL,gr2 + ori gr2,#PSR_PIL_14,gr2 /* debugging interrupts only */ + movgs gr2,psr + + ldi @(gr31,#REG_CCR),gr3 + movgs gr3,ccr + subcc.p gr0,gr0,gr0,icc2 /* leave Z set, clear C */ + + # exceptions must've been enabled and we must've been in supervisor mode + setlos BPSR_BET|BPSR_BS,gr3 + movgs gr3,bpsr + + # return to where the interrupt happened + movsg pcsr,gr2 + movgs gr2,bpcsr + + lddi.p @(gr31,#REG_GR(2)),gr2 + + xor gr31,gr31,gr31 + movgs gr0,brr +#ifdef CONFIG_MMU + movsg scr3,gr31 +#endif + rett #1 + +# we stepped through into the virtual interrupt reenablement trap +# +# we also want to single step anyway, but after fixing up so that we get an event on the +# instruction after the broken-into exception returns + .globl __break_step_kernel_external_interrupt_virtual_reenable +__break_step_kernel_external_interrupt_virtual_reenable: + movsg psr,gr2 + andi gr2,#~PSR_PIL,gr2 + movgs gr2,psr + + ldi @(gr31,#REG_CCR),gr3 + movgs gr3,ccr + subicc gr0,#1,gr0,icc2 /* clear Z, set C */ + + # save the adjusted ICC2 + movsg ccr,gr3 + sti gr3,@(gr31,#REG_CCR) + + # exceptions must've been enabled and we must've been in supervisor mode + setlos BPSR_BET|BPSR_BS,gr3 + movgs gr3,bpsr + + # return to where the trap happened + movsg pcsr,gr2 + movgs gr2,bpcsr + + # and then process the single step + bra __break_continue + # step through an internal exception from uspace mode .globl __break_step_uspace_softprog_interrupt __break_step_uspace_softprog_interrupt: @@ -517,8 +583,8 @@ __break_continue: # set up the kernel stack pointer sti sp,@(gr31,#REG_SP) - sethi.p %hi(__break_stack_tos),sp - setlo %lo(__break_stack_tos),sp + sethi.p %hi(__break_frame_0),sp + setlo %lo(__break_frame_0),sp # finish building the exception frame stdi gr4 ,@(gr31,#REG_GR(4)) @@ -583,9 +649,12 @@ __break_continue: movsg nmar,gr5 movsg dcr,gr6 - stdi gr4 ,@(gr31,#REG_BRR) - sti gr19,@(gr31,#REG_BPSR) - sti.p gr6 ,@(gr31,#REG_DCR) + sethi.p %hi(__debug_status),gr7 + setlo %lo(__debug_status),gr7 + + stdi gr4 ,@(gr7,#DEBUG_BRR) + sti gr19,@(gr7,#DEBUG_BPSR) + sti.p gr6 ,@(gr7,#DEBUG_DCR) # trap exceptions during break handling and disable h/w breakpoints/watchpoints sethi %hi(DCR_EBE),gr5 @@ -630,7 +699,10 @@ __break_continue: lddi @(gr31,#REG_PSR) ,gr22 ldi @(gr31,#REG_PC) ,gr21 ldi @(gr31,#REG_TBR) ,gr20 - ldi.p @(gr31,#REG_DCR) ,gr6 + + sethi.p %hi(__debug_status),gr6 + setlo %lo(__debug_status),gr6 + ldi.p @(gr6,#DEBUG_DCR) ,gr6 andi gr22,#PSR_S,gr19 /* rebuild BPSR */ andi.p gr22,#PSR_ET,gr5 diff --git a/arch/frv/kernel/cmode.S b/arch/frv/kernel/cmode.S index 6591e6a37ae..53deeb5d7e8 100644 --- a/arch/frv/kernel/cmode.S +++ b/arch/frv/kernel/cmode.S @@ -1,7 +1,7 @@ /* cmode.S: clock mode management * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Woodhouse (dwmw2@redhat.com) + * Written by David Woodhouse (dwmw2@infradead.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,7 +11,6 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/setup.h> #include <asm/segment.h> diff --git a/arch/frv/kernel/debug-stub.c b/arch/frv/kernel/debug-stub.c index 4761cc4b4a9..a0228f717ef 100644 --- a/arch/frv/kernel/debug-stub.c +++ b/arch/frv/kernel/debug-stub.c @@ -15,8 +15,8 @@ #include <linux/sched.h> #include <linux/init.h> #include <linux/serial_reg.h> +#include <linux/start_kernel.h> -#include <asm/system.h> #include <asm/serial-regs.h> #include <asm/timer-regs.h> #include <asm/irc-regs.h> @@ -39,10 +39,9 @@ do { \ gdbstub_do_rx(); \ } while(!FLOWCTL_QUERY(LINE)) -static void __init debug_stub_init(void); +struct frv_debug_status __debug_status; -extern asmlinkage void __break_hijack_kernel_event(void); -extern asmlinkage void __break_hijack_kernel_event_breaks_here(void); +static void __init debug_stub_init(void); /*****************************************************************************/ /* @@ -67,7 +66,7 @@ asmlinkage void debug_stub(void) __set_HSR(0, hsr0 & ~HSR0_ETMD); /* disable single stepping */ - __debug_regs->dcr &= ~DCR_SE; + __debug_status.dcr &= ~DCR_SE; /* kernel mode can propose an exception be handled in debug mode by jumping to a special * location */ @@ -76,8 +75,8 @@ asmlinkage void debug_stub(void) * the top kernel context */ *__debug_frame = *__frame; __frame = __debug_frame->next_frame; - __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; - __debug_regs->brr |= BRR_EB; + __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12; + __debug_status.brr |= BRR_EB; } if (__debug_frame->pc == (unsigned long) __debug_bug_trap + 4) { @@ -124,7 +123,7 @@ static void __init debug_stub_init(void) __debug_frame->pc = (unsigned long) start_kernel; /* enable the debug events we want to trap */ - __debug_regs->dcr = DCR_EBE; + __debug_status.dcr = DCR_EBE; #ifdef CONFIG_GDBSTUB gdbstub_init(); diff --git a/arch/frv/kernel/dma.c b/arch/frv/kernel/dma.c index f5de6cf7df4..156184e17e5 100644 --- a/arch/frv/kernel/dma.c +++ b/arch/frv/kernel/dma.c @@ -121,15 +121,14 @@ unsigned long frv_dma_inprogress; /* * DMA irq handler - determine channel involved, grab status and call real handler */ -static irqreturn_t dma_irq_handler(int irq, void *_channel, struct pt_regs *regs) +static irqreturn_t dma_irq_handler(int irq, void *_channel) { struct frv_dma_channel *channel = _channel; frv_clear_dma_inprogress(channel - frv_dma_channels); return channel->handler(channel - frv_dma_channels, __get_DMAC(channel->ioaddr, CSTR), - channel->data, - regs); + channel->data); } /* end dma_irq_handler() */ diff --git a/arch/frv/kernel/entry-table.S b/arch/frv/kernel/entry-table.S index 9b9243e2103..06c5ae191e5 100644 --- a/arch/frv/kernel/entry-table.S +++ b/arch/frv/kernel/entry-table.S @@ -11,7 +11,6 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/spr-regs.h> @@ -87,7 +86,7 @@ __break_usertrap_fixup_table: .globl __break_kerneltrap_fixup_table __break_kerneltrap_fixup_table: - # handler declaration for a sofware or program interrupt + # handler declaration for a software or program interrupt .macro VECTOR_SOFTPROG tbr_tt, vec .section .trap.user .org \tbr_tt @@ -116,6 +115,8 @@ __break_kerneltrap_fixup_table: .long __break_step_uspace_external_interrupt .section .trap.kernel .org \tbr_tt + # deal with virtual interrupt disablement + beq icc2,#0,__entry_kernel_external_interrupt_virtually_disabled bra __entry_kernel_external_interrupt .section .trap.fixup.kernel .org \tbr_tt >> 2 @@ -144,7 +145,7 @@ __break_kerneltrap_fixup_table: .long \vec .endm - # handler declaration for an MMU only sofware or program interrupt + # handler declaration for an MMU only software or program interrupt .macro VECTOR_SP_MMU tbr_tt, vec #ifdef CONFIG_MMU VECTOR_SOFTPROG \tbr_tt, \vec @@ -259,25 +260,52 @@ __trap_fixup_kernel_data_tlb_miss: .org TBR_TT_TRAP0 .rept 127 bra __entry_uspace_softprog_interrupt - bra __break_step_uspace_softprog_interrupt - .long 0,0 + .long 0,0,0 .endr .org TBR_TT_BREAK bra __entry_break .long 0,0,0 + .section .trap.fixup.user + .org TBR_TT_TRAP0 >> 2 + .rept 127 + .long __break_step_uspace_softprog_interrupt + .endr + .org TBR_TT_BREAK >> 2 + .long 0 + # miscellaneous kernel mode entry points .section .trap.kernel .org TBR_TT_TRAP0 - .rept 127 bra __entry_kernel_softprog_interrupt - bra __break_step_kernel_softprog_interrupt - .long 0,0 + .org TBR_TT_TRAP1 + bra __entry_kernel_softprog_interrupt + + # trap #2 in kernel - reenable interrupts + .org TBR_TT_TRAP2 + bra __entry_kernel_external_interrupt_virtual_reenable + + # miscellaneous kernel traps + .org TBR_TT_TRAP3 + .rept 124 + bra __entry_kernel_softprog_interrupt + .long 0,0,0 .endr .org TBR_TT_BREAK bra __entry_break .long 0,0,0 + .section .trap.fixup.kernel + .org TBR_TT_TRAP0 >> 2 + .long __break_step_kernel_softprog_interrupt + .long __break_step_kernel_softprog_interrupt + .long __break_step_kernel_external_interrupt_virtual_reenable + .rept 124 + .long __break_step_kernel_softprog_interrupt + .endr + .org TBR_TT_BREAK >> 2 + .long 0 + # miscellaneous debug mode entry points .section .trap.break .org TBR_TT_BREAK @@ -288,8 +316,14 @@ __trap_fixup_kernel_data_tlb_miss: .section .trap.vector .org TBR_TT_TRAP0 >> 2 .long system_call - .rept 126 + .rept 119 .long __entry_unsupported_trap .endr + + # userspace atomic op emulation, traps 120-126 + .rept 7 + .long __entry_atomic_op + .endr + .org TBR_TT_BREAK >> 2 .long __entry_debug_exception diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index 5f6548388b7..dfcd263c051 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -27,8 +27,6 @@ * */ -#include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/thread_info.h> #include <asm/setup.h> @@ -40,7 +38,7 @@ #define nr_syscalls ((syscall_table_size)/4) - .text + .section .text..entry .balign 4 .macro LEDS val @@ -141,7 +139,10 @@ __entry_uspace_external_interrupt_reentry: movsg gner0,gr4 movsg gner1,gr5 - stdi gr4,@(gr28,#REG_GNER0) + stdi.p gr4,@(gr28,#REG_GNER0) + + # interrupts start off fully disabled in the interrupt handler + subcc gr0,gr0,gr0,icc2 /* set Z and clear C */ # set up kernel global registers sethi.p %hi(__kernel_current_task),gr5 @@ -193,9 +194,8 @@ __entry_uspace_external_interrupt_reentry: .type __entry_kernel_external_interrupt,@function __entry_kernel_external_interrupt: LEDS 0x6210 - - sub sp,gr15,gr31 - LEDS32 +// sub sp,gr15,gr31 +// LEDS32 # set up the stack pointer or.p sp,gr0,gr30 @@ -231,7 +231,10 @@ __entry_kernel_external_interrupt_reentry: stdi gr24,@(gr28,#REG_GR(24)) stdi gr26,@(gr28,#REG_GR(26)) sti gr29,@(gr28,#REG_GR(29)) - stdi gr30,@(gr28,#REG_GR(30)) + stdi.p gr30,@(gr28,#REG_GR(30)) + + # note virtual interrupts will be fully enabled upon return + subicc gr0,#1,gr0,icc2 /* clear Z, set C */ movsg tbr ,gr20 movsg psr ,gr22 @@ -250,7 +253,7 @@ __entry_kernel_external_interrupt_reentry: andi.p gr5,#~PSR_ET,gr5 # set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel - # - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt + # - for an explanation of how it works, see: Documentation/frv/atomic-ops.txt andi gr25,#~0xc0,gr25 sti gr20,@(gr28,#REG_TBR) @@ -267,7 +270,10 @@ __entry_kernel_external_interrupt_reentry: movsg gner0,gr4 movsg gner1,gr5 - stdi gr4,@(gr28,#REG_GNER0) + stdi.p gr4,@(gr28,#REG_GNER0) + + # interrupts start off fully disabled in the interrupt handler + subcc gr0,gr0,gr0,icc2 /* set Z and clear C */ # set the return address sethi.p %hi(__entry_return_from_kernel_interrupt),gr4 @@ -291,6 +297,45 @@ __entry_kernel_external_interrupt_reentry: .size __entry_kernel_external_interrupt,.-__entry_kernel_external_interrupt +############################################################################### +# +# deal with interrupts that were actually virtually disabled +# - we need to really disable them, flag the fact and return immediately +# - if you change this, you must alter break.S also +# +############################################################################### + .balign L1_CACHE_BYTES + .globl __entry_kernel_external_interrupt_virtually_disabled + .type __entry_kernel_external_interrupt_virtually_disabled,@function +__entry_kernel_external_interrupt_virtually_disabled: + movsg psr,gr30 + andi gr30,#~PSR_PIL,gr30 + ori gr30,#PSR_PIL_14,gr30 ; debugging interrupts only + movgs gr30,psr + subcc gr0,gr0,gr0,icc2 ; leave Z set, clear C + rett #0 + + .size __entry_kernel_external_interrupt_virtually_disabled,.-__entry_kernel_external_interrupt_virtually_disabled + +############################################################################### +# +# deal with re-enablement of interrupts that were pending when virtually re-enabled +# - set ICC2.C, re-enable the real interrupts and return +# - we can clear ICC2.Z because we shouldn't be here if it's not 0 [due to TIHI] +# - if you change this, you must alter break.S also +# +############################################################################### + .balign L1_CACHE_BYTES + .globl __entry_kernel_external_interrupt_virtual_reenable + .type __entry_kernel_external_interrupt_virtual_reenable,@function +__entry_kernel_external_interrupt_virtual_reenable: + movsg psr,gr30 + andi gr30,#~PSR_PIL,gr30 ; re-enable interrupts + movgs gr30,psr + subicc gr0,#1,gr0,icc2 ; clear Z, set C + rett #0 + + .size __entry_kernel_external_interrupt_virtual_reenable,.-__entry_kernel_external_interrupt_virtual_reenable ############################################################################### # @@ -335,6 +380,7 @@ __entry_uspace_softprog_interrupt_reentry: sethi.p %hi(__entry_return_from_user_exception),gr23 setlo %lo(__entry_return_from_user_exception),gr23 + bra __entry_common .size __entry_uspace_softprog_interrupt,.-__entry_uspace_softprog_interrupt @@ -399,7 +445,7 @@ __entry_kernel_softprog_interrupt_reentry: sti gr22,@(sp,#REG_SP) # set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel - # - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt + # - for an explanation of how it works, see: Documentation/frv/atomic-ops.txt movsg cccr,gr20 andi gr20,#~0xc0,gr20 movgs gr20,cccr @@ -495,7 +541,10 @@ __entry_common: movsg gner0,gr4 movsg gner1,gr5 - stdi gr4,@(gr28,#REG_GNER0) + stdi.p gr4,@(gr28,#REG_GNER0) + + # set up virtual interrupt disablement + subicc gr0,#1,gr0,icc2 /* clear Z flag, set C flag */ # set up kernel global registers sethi.p %hi(__kernel_current_task),gr5 @@ -607,6 +656,26 @@ __entry_debug_exception: ############################################################################### # +# handle atomic operation emulation for userspace +# +############################################################################### + .globl __entry_atomic_op +__entry_atomic_op: + LEDS 0x6012 + sethi.p %hi(atomic_operation),gr5 + setlo %lo(atomic_operation),gr5 + movsg esfr1,gr8 + movsg epcr0,gr9 + movsg esr0,gr10 + + # now that we've accessed the exception regs, we can enable exceptions + movsg psr,gr4 + ori gr4,#PSR_ET,gr4 + movgs gr4,psr + jmpl @(gr5,gr0) ; call atomic_operation(esfr1,epcr0,esr0) + +############################################################################### +# # handle media exception # ############################################################################### @@ -794,6 +863,14 @@ ret_from_fork: setlos.p #0,gr8 bra __syscall_exit + .globl ret_from_kernel_thread +ret_from_kernel_thread: + lddi.p @(gr28,#REG_GR(8)),gr20 + call schedule_tail + calll.p @(gr21,gr0) + or gr20,gr20,gr8 + bra __syscall_exit + ################################################################################################### # # Return to user mode is not as complex as all this looks, @@ -817,7 +894,6 @@ system_call: bnc icc0,#0,__syscall_badsys ldi @(gr15,#TI_FLAGS),gr4 - ori gr4,#_TIF_SYSCALL_TRACE,gr4 andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 bne icc0,#0,__syscall_trace_entry @@ -837,18 +913,19 @@ __syscall_call: __syscall_exit: LEDS 0x6300 - sti gr8,@(gr28,#REG_GR(8)) ; save return value + # keep current PSR in GR23 + movsg psr,gr23 - # rebuild saved psr - execve will change it for init/main.c ldi @(gr28,#REG_PSR),gr22 + + sti.p gr8,@(gr28,#REG_GR(8)) ; save return value + + # rebuild saved psr - execve will change it for init/main.c srli gr22,#1,gr5 andi.p gr22,#~PSR_PS,gr22 andi gr5,#PSR_PS,gr5 or gr5,gr22,gr22 - ori gr22,#PSR_S,gr22 - - # keep current PSR in GR23 - movsg psr,gr23 + ori.p gr22,#PSR_S,gr22 # make sure we don't miss an interrupt setting need_resched or sigpending between # sampling and the RETT @@ -856,9 +933,7 @@ __syscall_exit: movgs gr23,psr ldi @(gr15,#TI_FLAGS),gr4 - sethi.p %hi(_TIF_ALLWORK_MASK),gr5 - setlo %lo(_TIF_ALLWORK_MASK),gr5 - andcc gr4,gr5,gr0,icc0 + andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0 bne icc0,#0,__syscall_exit_work # restore all registers and return @@ -1000,27 +1075,10 @@ __entry_return_from_kernel_interrupt: subicc gr5,#0,gr0,icc0 beq icc0,#0,__entry_return_direct -__entry_preempt_need_resched: - ldi @(gr15,#TI_FLAGS),gr4 - andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 - beq icc0,#1,__entry_return_direct - - setlos #PREEMPT_ACTIVE,gr5 - sti gr5,@(gr15,#TI_FLAGS) - - andi gr23,#~PSR_PIL,gr23 - movgs gr23,psr - - call schedule - sti gr0,@(gr15,#TI_PRE_COUNT) - - movsg psr,gr23 - ori gr23,#PSR_PIL_14,gr23 - movgs gr23,psr - bra __entry_preempt_need_resched -#else - bra __entry_return_direct + subcc gr0,gr0,gr0,icc2 /* set Z and clear C */ + call preempt_schedule_irq #endif + bra __entry_return_direct ############################################################################### @@ -1043,9 +1101,7 @@ __entry_resume_userspace: __entry_return_from_user_interrupt: LEDS 0x6402 ldi @(gr15,#TI_FLAGS),gr4 - sethi.p %hi(_TIF_WORK_MASK),gr5 - setlo %lo(_TIF_WORK_MASK),gr5 - andcc gr4,gr5,gr0,icc0 + andicc gr4,#_TIF_WORK_MASK,gr0,icc0 beq icc0,#1,__entry_return_direct __entry_work_pending: @@ -1065,9 +1121,7 @@ __entry_work_resched: LEDS 0x6401 ldi @(gr15,#TI_FLAGS),gr4 - sethi.p %hi(_TIF_WORK_MASK),gr5 - setlo %lo(_TIF_WORK_MASK),gr5 - andcc gr4,gr5,gr0,icc0 + andicc gr4,#_TIF_WORK_MASK,gr0,icc0 beq icc0,#1,__entry_return_direct andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 bne icc0,#1,__entry_work_resched @@ -1081,11 +1135,10 @@ __entry_work_notifysig: # perform syscall entry tracing __syscall_trace_entry: LEDS 0x6320 - setlos.p #0,gr8 - call do_syscall_trace + call syscall_trace_entry - ldi @(gr28,#REG_SYSCALLNO),gr7 - lddi @(gr28,#REG_GR(8)) ,gr8 + lddi.p @(gr28,#REG_GR(8)) ,gr8 + ori gr8,#0,gr7 ; syscall_trace_entry() returned new syscallno lddi @(gr28,#REG_GR(10)),gr10 lddi.p @(gr28,#REG_GR(12)),gr12 @@ -1096,15 +1149,16 @@ __syscall_trace_entry: # perform syscall exit tracing __syscall_exit_work: LEDS 0x6340 - andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 + andicc gr22,#PSR_PS,gr0,icc1 ; don't handle on return to kernel mode + andicc.p gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 + bne icc1,#0,__entry_return_direct beq icc0,#1,__entry_work_pending movsg psr,gr23 - andi gr23,#~PSR_PIL,gr23 ; could let do_syscall_trace() call schedule() + andi gr23,#~PSR_PIL,gr23 ; could let syscall_trace_exit() call schedule() movgs gr23,psr - setlos.p #1,gr8 - call do_syscall_trace + call syscall_trace_exit bra __entry_resume_userspace __syscall_badsys: @@ -1119,12 +1173,6 @@ __syscall_badsys: # syscall vector table # ############################################################################### -#ifdef CONFIG_MMU -#define __MMU(X) X -#else -#define __MMU(X) sys_ni_syscall -#endif - .section .rodata ALIGN .globl sys_call_table @@ -1254,7 +1302,7 @@ sys_call_table: .long sys_newuname .long sys_ni_syscall /* old "cacheflush" */ .long sys_adjtimex - .long __MMU(sys_mprotect) /* 125 */ + .long sys_mprotect /* 125 */ .long sys_sigprocmask .long sys_ni_syscall /* old "create_module" */ .long sys_init_module @@ -1273,16 +1321,16 @@ sys_call_table: .long sys_getdents .long sys_select .long sys_flock - .long __MMU(sys_msync) + .long sys_msync .long sys_readv /* 145 */ .long sys_writev .long sys_getsid .long sys_fdatasync .long sys_sysctl - .long __MMU(sys_mlock) /* 150 */ - .long __MMU(sys_munlock) - .long __MMU(sys_mlockall) - .long __MMU(sys_munlockall) + .long sys_mlock /* 150 */ + .long sys_munlock + .long sys_mlockall + .long sys_munlockall .long sys_sched_setparam .long sys_sched_getparam /* 155 */ .long sys_sched_setscheduler @@ -1292,13 +1340,13 @@ sys_call_table: .long sys_sched_get_priority_min /* 160 */ .long sys_sched_rr_get_interval .long sys_nanosleep - .long __MMU(sys_mremap) + .long sys_mremap .long sys_setresuid16 .long sys_getresuid16 /* 165 */ .long sys_ni_syscall /* for vm86 */ .long sys_ni_syscall /* Old sys_query_module */ .long sys_poll - .long sys_nfsservctl + .long sys_ni_syscall /* Old nfsservctl */ .long sys_setresgid16 /* 170 */ .long sys_getresgid16 .long sys_prctl @@ -1347,8 +1395,8 @@ sys_call_table: .long sys_setfsuid /* 215 */ .long sys_setfsgid .long sys_pivot_root - .long __MMU(sys_mincore) - .long __MMU(sys_madvise) + .long sys_mincore + .long sys_madvise .long sys_getdents64 /* 220 */ .long sys_fcntl64 .long sys_ni_syscall /* reserved for TUX */ @@ -1386,7 +1434,7 @@ sys_call_table: .long sys_epoll_create .long sys_epoll_ctl /* 255 */ .long sys_epoll_wait - .long __MMU(sys_remap_file_pages) + .long sys_remap_file_pages .long sys_set_tid_address .long sys_timer_create .long sys_timer_settime /* 260 */ @@ -1418,11 +1466,54 @@ sys_call_table: .long sys_add_key .long sys_request_key .long sys_keyctl - .long sys_ni_syscall // sys_vperfctr_open - .long sys_ni_syscall // sys_vperfctr_control /* 290 */ - .long sys_ni_syscall // sys_vperfctr_unlink - .long sys_ni_syscall // sys_vperfctr_iresume - .long sys_ni_syscall // sys_vperfctr_read - + .long sys_ioprio_set + .long sys_ioprio_get /* 290 */ + .long sys_inotify_init + .long sys_inotify_add_watch + .long sys_inotify_rm_watch + .long sys_migrate_pages + .long sys_openat /* 295 */ + .long sys_mkdirat + .long sys_mknodat + .long sys_fchownat + .long sys_futimesat + .long sys_fstatat64 /* 300 */ + .long sys_unlinkat + .long sys_renameat + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat /* 305 */ + .long sys_fchmodat + .long sys_faccessat + .long sys_pselect6 + .long sys_ppoll + .long sys_unshare /* 310 */ + .long sys_set_robust_list + .long sys_get_robust_list + .long sys_splice + .long sys_sync_file_range + .long sys_tee /* 315 */ + .long sys_vmsplice + .long sys_move_pages + .long sys_getcpu + .long sys_epoll_pwait + .long sys_utimensat /* 320 */ + .long sys_signalfd + .long sys_timerfd_create + .long sys_eventfd + .long sys_fallocate + .long sys_timerfd_settime /* 325 */ + .long sys_timerfd_gettime + .long sys_signalfd4 + .long sys_eventfd2 + .long sys_epoll_create1 + .long sys_dup3 /* 330 */ + .long sys_pipe2 + .long sys_inotify_init1 + .long sys_preadv + .long sys_pwritev + .long sys_rt_tgsigqueueinfo /* 335 */ + .long sys_perf_event_open + .long sys_setns syscall_table_size = (. - sys_call_table) diff --git a/arch/frv/kernel/frv_ksyms.c b/arch/frv/kernel/frv_ksyms.c index 0f1c6cbc4f5..86c516d96dc 100644 --- a/arch/frv/kernel/frv_ksyms.c +++ b/arch/frv/kernel/frv_ksyms.c @@ -7,13 +7,11 @@ #include <linux/elfcore.h> #include <linux/in6.h> #include <linux/interrupt.h> -#include <linux/config.h> #include <asm/setup.h> #include <asm/pgalloc.h> #include <asm/irq.h> #include <asm/io.h> -#include <asm/semaphore.h> #include <asm/checksum.h> #include <asm/hardirq.h> #include <asm/cacheflush.h> @@ -26,26 +24,13 @@ extern long __memset_user(void *dst, const void *src, size_t count); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); -EXPORT_SYMBOL(strnlen); -EXPORT_SYMBOL(strrchr); -EXPORT_SYMBOL(strstr); -EXPORT_SYMBOL(strchr); -EXPORT_SYMBOL(strcat); -EXPORT_SYMBOL(strlen); -EXPORT_SYMBOL(strcmp); -EXPORT_SYMBOL(strncmp); -EXPORT_SYMBOL(strncpy); - EXPORT_SYMBOL(ip_fast_csum); #if 0 EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(local_bh_count); #endif -EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(__res_bus_clock_speed_HZ); EXPORT_SYMBOL(__page_offset); EXPORT_SYMBOL(__memcpy_user); @@ -62,24 +47,16 @@ EXPORT_SYMBOL(memory_end); EXPORT_SYMBOL(__debug_bug_trap); -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy); - /* The following are special because they're not called explicitly (the C compiler generates them). Fortunately, their interface isn't gonna change any time soon now, so it's OK to leave it out of version control. */ EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL(memscan); -EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(__outsl_ns); EXPORT_SYMBOL(__insl_ns); -EXPORT_SYMBOL(get_wchan); - #ifdef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS EXPORT_SYMBOL(atomic_test_and_ANDNOT_mask); EXPORT_SYMBOL(atomic_test_and_OR_mask); @@ -89,6 +66,10 @@ EXPORT_SYMBOL(atomic_sub_return); EXPORT_SYMBOL(__xchg_32); EXPORT_SYMBOL(__cmpxchg_32); #endif +EXPORT_SYMBOL(atomic64_add_return); +EXPORT_SYMBOL(atomic64_sub_return); +EXPORT_SYMBOL(__xchg_64); +EXPORT_SYMBOL(__cmpxchg_64); EXPORT_SYMBOL(__debug_bug_printk); EXPORT_SYMBOL(__delay_loops_MHz); diff --git a/arch/frv/kernel/futex.c b/arch/frv/kernel/futex.c index eae874a970c..d155ca9e509 100644 --- a/arch/frv/kernel/futex.c +++ b/arch/frv/kernel/futex.c @@ -10,15 +10,15 @@ */ #include <linux/futex.h> +#include <linux/uaccess.h> #include <asm/futex.h> #include <asm/errno.h> -#include <asm/uaccess.h> /* * the various futex operations; MMU fault checking is ignored under no-MMU * conditions */ -static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval) +static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval) { int oldval, ret; @@ -50,7 +50,7 @@ static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_o return ret; } -static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval) +static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval) { int oldval, ret; @@ -83,7 +83,7 @@ static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_o return ret; } -static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval) +static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval) { int oldval, ret; @@ -116,7 +116,7 @@ static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_ol return ret; } -static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval) +static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval) { int oldval, ret; @@ -149,7 +149,7 @@ static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_o return ret; } -static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval) +static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval) { int oldval, ret; @@ -186,7 +186,7 @@ static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_o /* * do the futex operations */ -int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) +int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) { int op = (encoded_op >> 28) & 7; int cmp = (encoded_op >> 24) & 15; @@ -197,10 +197,10 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) oparg = 1 << oparg; - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) + if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; - inc_preempt_count(); + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -223,7 +223,7 @@ int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) break; } - dec_preempt_count(); + pagefault_enable(); if (!ret) { switch (cmp) { diff --git a/arch/frv/kernel/gdb-io.c b/arch/frv/kernel/gdb-io.c index c997bccb922..0707d35079b 100644 --- a/arch/frv/kernel/gdb-io.c +++ b/arch/frv/kernel/gdb-io.c @@ -19,7 +19,6 @@ #include <linux/serial_reg.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/irc-regs.h> #include <asm/timer-regs.h> #include <asm/gdb-stub.h> @@ -171,11 +170,11 @@ int gdbstub_rx_char(unsigned char *_ch, int nonblock) return -EINTR; } else if (st & (UART_LSR_FE|UART_LSR_OE|UART_LSR_PE)) { - gdbstub_proto("### GDB Rx Error (st=%02x) ###\n",st); + gdbstub_io("### GDB Rx Error (st=%02x) ###\n",st); return -EIO; } else { - gdbstub_proto("### GDB Rx %02x (st=%02x) ###\n",ch,st); + gdbstub_io("### GDB Rx %02x (st=%02x) ###\n",ch,st); *_ch = ch & 0x7f; return 0; } diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c index 8f860d9c494..bbe78b0bffe 100644 --- a/arch/frv/kernel/gdb-stub.c +++ b/arch/frv/kernel/gdb-stub.c @@ -87,7 +87,7 @@ * Example: * $ cd ~/linux * $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging> - * $ make dep; make vmlinux + * $ make vmlinux * * Step 3: * Download the kernel to the remote target and start @@ -124,8 +124,8 @@ #include <linux/slab.h> #include <linux/nmi.h> +#include <asm/asm-offsets.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/gdb-stub.h> #define LEDS(x) do { /* *(u32*)0xe1200004 = ~(x); mb(); */ } while(0) @@ -136,7 +136,6 @@ extern void debug_to_serial(const char *p, int n); extern void gdbstub_console_write(struct console *co, const char *p, unsigned n); extern volatile uint32_t __break_error_detect[3]; /* ESFR1, ESR15, EAR15 */ -extern struct user_context __break_user_context; struct __debug_amr { unsigned long L, P; @@ -182,8 +181,6 @@ extern volatile u32 __attribute__((section(".bss"))) gdbstub_trace_through_excep static char input_buffer[BUFMAX]; static char output_buffer[BUFMAX]; -static const char hexchars[] = "0123456789abcdef"; - static const char *regnames[] = { "PSR ", "ISR ", "CCR ", "CCCR", "LR ", "LCR ", "PC ", "_stt", @@ -383,8 +380,8 @@ static int gdbstub_send_packet(char *buffer) } gdbstub_tx_char('#'); - gdbstub_tx_char(hexchars[checksum >> 4]); - gdbstub_tx_char(hexchars[checksum & 0xf]); + gdbstub_tx_char(hex_asc_hi(checksum)); + gdbstub_tx_char(hex_asc_lo(checksum)); } while (gdbstub_rx_char(&ch,0), #ifdef GDBSTUB_DEBUG_PROTOCOL @@ -647,17 +644,11 @@ void debug_to_serial(const char *p, int n) } #endif -#ifdef CONFIG_GDBSTUB_CONSOLE - -static kdev_t gdbstub_console_dev(struct console *con) -{ - return MKDEV(1,3); /* /dev/null */ -} +#ifdef CONFIG_GDB_CONSOLE static struct console gdbstub_console = { .name = "gdb", .write = gdbstub_console_write, /* in break.S */ - .device = gdbstub_console_dev, .flags = CON_PRINTBUFFER, .index = -1, }; @@ -680,8 +671,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa if ((uint32_t)mem&1 && count>=1) { if (!gdbstub_read_byte(mem,ch)) return NULL; - *buf++ = hexchars[ch[0] >> 4]; - *buf++ = hexchars[ch[0] & 0xf]; + buf = hex_byte_pack(buf, ch[0]); mem++; count--; } @@ -689,10 +679,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa if ((uint32_t)mem&3 && count>=2) { if (!gdbstub_read_word(mem,(uint16_t *)ch)) return NULL; - *buf++ = hexchars[ch[0] >> 4]; - *buf++ = hexchars[ch[0] & 0xf]; - *buf++ = hexchars[ch[1] >> 4]; - *buf++ = hexchars[ch[1] & 0xf]; + buf = hex_byte_pack(buf, ch[0]); + buf = hex_byte_pack(buf, ch[1]); mem += 2; count -= 2; } @@ -700,14 +688,10 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa while (count>=4) { if (!gdbstub_read_dword(mem,(uint32_t *)ch)) return NULL; - *buf++ = hexchars[ch[0] >> 4]; - *buf++ = hexchars[ch[0] & 0xf]; - *buf++ = hexchars[ch[1] >> 4]; - *buf++ = hexchars[ch[1] & 0xf]; - *buf++ = hexchars[ch[2] >> 4]; - *buf++ = hexchars[ch[2] & 0xf]; - *buf++ = hexchars[ch[3] >> 4]; - *buf++ = hexchars[ch[3] & 0xf]; + buf = hex_byte_pack(buf, ch[0]); + buf = hex_byte_pack(buf, ch[1]); + buf = hex_byte_pack(buf, ch[2]); + buf = hex_byte_pack(buf, ch[3]); mem += 4; count -= 4; } @@ -715,10 +699,8 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa if (count>=2) { if (!gdbstub_read_word(mem,(uint16_t *)ch)) return NULL; - *buf++ = hexchars[ch[0] >> 4]; - *buf++ = hexchars[ch[0] & 0xf]; - *buf++ = hexchars[ch[1] >> 4]; - *buf++ = hexchars[ch[1] & 0xf]; + buf = hex_byte_pack(buf, ch[0]); + buf = hex_byte_pack(buf, ch[1]); mem += 2; count -= 2; } @@ -726,8 +708,7 @@ static unsigned char *mem2hex(const void *_mem, char *buf, int count, int may_fa if (count>=1) { if (!gdbstub_read_byte(mem,ch)) return NULL; - *buf++ = hexchars[ch[0] >> 4]; - *buf++ = hexchars[ch[0] & 0xf]; + buf = hex_byte_pack(buf, ch[0]); } *buf = 0; @@ -926,6 +907,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE0)) { //gdbstub_printk("set h/w break 0: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE0; + __debug_regs->ibar[0] = addr; asm volatile("movgs %0,ibar0" : : "r"(addr)); return 0; } @@ -933,6 +915,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE1)) { //gdbstub_printk("set h/w break 1: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE1; + __debug_regs->ibar[1] = addr; asm volatile("movgs %0,ibar1" : : "r"(addr)); return 0; } @@ -940,6 +923,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE2)) { //gdbstub_printk("set h/w break 2: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE2; + __debug_regs->ibar[2] = addr; asm volatile("movgs %0,ibar2" : : "r"(addr)); return 0; } @@ -947,6 +931,7 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & DCR_IBE3)) { //gdbstub_printk("set h/w break 3: %08lx\n", addr); __debug_regs->dcr |= DCR_IBE3; + __debug_regs->ibar[3] = addr; asm volatile("movgs %0,ibar3" : : "r"(addr)); return 0; } @@ -971,7 +956,14 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & (DCR_DRBE0|DCR_DWBE0))) { //gdbstub_printk("set h/w watchpoint 0 type %ld: %08lx\n", type, addr); tmp = type==2 ? DCR_DWBE0 : type==3 ? DCR_DRBE0 : DCR_DRBE0|DCR_DWBE0; + __debug_regs->dcr |= tmp; + __debug_regs->dbar[0] = addr; + __debug_regs->dbmr[0][0] = dbmr.mask0; + __debug_regs->dbmr[0][1] = dbmr.mask1; + __debug_regs->dbdr[0][0] = 0; + __debug_regs->dbdr[0][1] = 0; + asm volatile(" movgs %0,dbar0 \n" " movgs %1,dbmr00 \n" " movgs %2,dbmr01 \n" @@ -984,7 +976,14 @@ static int gdbstub_set_breakpoint(unsigned long type, unsigned long addr, unsign if (!(__debug_regs->dcr & (DCR_DRBE1|DCR_DWBE1))) { //gdbstub_printk("set h/w watchpoint 1 type %ld: %08lx\n", type, addr); tmp = type==2 ? DCR_DWBE1 : type==3 ? DCR_DRBE1 : DCR_DRBE1|DCR_DWBE1; + __debug_regs->dcr |= tmp; + __debug_regs->dbar[1] = addr; + __debug_regs->dbmr[1][0] = dbmr.mask0; + __debug_regs->dbmr[1][1] = dbmr.mask1; + __debug_regs->dbdr[1][0] = 0; + __debug_regs->dbdr[1][1] = 0; + asm volatile(" movgs %0,dbar1 \n" " movgs %1,dbmr10 \n" " movgs %2,dbmr11 \n" @@ -1047,6 +1046,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE0 && __get_ibar(0) == addr) { //gdbstub_printk("clear h/w break 0: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE0; + __debug_regs->ibar[0] = 0; asm volatile("movgs gr0,ibar0"); return 0; } @@ -1054,6 +1054,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE1 && __get_ibar(1) == addr) { //gdbstub_printk("clear h/w break 1: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE1; + __debug_regs->ibar[1] = 0; asm volatile("movgs gr0,ibar1"); return 0; } @@ -1061,6 +1062,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE2 && __get_ibar(2) == addr) { //gdbstub_printk("clear h/w break 2: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE2; + __debug_regs->ibar[2] = 0; asm volatile("movgs gr0,ibar2"); return 0; } @@ -1068,6 +1070,7 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo if (__debug_regs->dcr & DCR_IBE3 && __get_ibar(3) == addr) { //gdbstub_printk("clear h/w break 3: %08lx\n", addr); __debug_regs->dcr &= ~DCR_IBE3; + __debug_regs->ibar[3] = 0; asm volatile("movgs gr0,ibar3"); return 0; } @@ -1104,6 +1107,12 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo //gdbstub_printk("clear h/w watchpoint 0 type %ld: %08lx\n", type, addr); __debug_regs->dcr &= ~(DCR_DRBE0|DCR_DWBE0); + __debug_regs->dbar[0] = 0; + __debug_regs->dbmr[0][0] = 0; + __debug_regs->dbmr[0][1] = 0; + __debug_regs->dbdr[0][0] = 0; + __debug_regs->dbdr[0][1] = 0; + asm volatile(" movgs gr0,dbar0 \n" " movgs gr0,dbmr00 \n" " movgs gr0,dbmr01 \n" @@ -1123,6 +1132,12 @@ int gdbstub_clear_breakpoint(unsigned long type, unsigned long addr, unsigned lo //gdbstub_printk("clear h/w watchpoint 1 type %ld: %08lx\n", type, addr); __debug_regs->dcr &= ~(DCR_DRBE1|DCR_DWBE1); + __debug_regs->dbar[1] = 0; + __debug_regs->dbmr[1][0] = 0; + __debug_regs->dbmr[1][1] = 0; + __debug_regs->dbdr[1][0] = 0; + __debug_regs->dbdr[1][1] = 0; + asm volatile(" movgs gr0,dbar1 \n" " movgs gr0,dbmr10 \n" " movgs gr0,dbmr11 \n" @@ -1161,9 +1176,9 @@ static void gdbstub_check_breakpoint(void) /* * */ -static void __attribute__((unused)) gdbstub_show_regs(void) +static void __maybe_unused gdbstub_show_regs(void) { - uint32_t *reg; + unsigned long *reg; int loop; gdbstub_printk("\n"); @@ -1172,11 +1187,11 @@ static void __attribute__((unused)) gdbstub_show_regs(void) __debug_frame, __debug_frame->psr & PSR_S ? "kernel" : "user"); - reg = (uint32_t *) __debug_frame; - for (loop = 0; loop < REG__END; loop++) { - printk("%s %08x", regnames[loop + 0], reg[loop + 0]); + reg = (unsigned long *) __debug_frame; + for (loop = 0; loop < NR_PT_REGS; loop++) { + printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); - if (loop == REG__END - 1 || loop % 5 == 4) + if (loop == NR_PT_REGS - 1 || loop % 5 == 4) printk("\n"); else printk(" | "); @@ -1189,15 +1204,10 @@ static void __attribute__((unused)) gdbstub_show_regs(void) /* * dump debugging regs */ -static void __attribute__((unused)) gdbstub_dump_debugregs(void) +static void __maybe_unused gdbstub_dump_debugregs(void) { - unsigned long x; - - x = __debug_regs->dcr; - gdbstub_printk("DCR %08lx ", x); - - x = __debug_regs->brr; - gdbstub_printk("BRR %08lx\n", x); + gdbstub_printk("DCR %08lx ", __debug_status.dcr); + gdbstub_printk("BRR %08lx\n", __debug_status.brr); gdbstub_printk("IBAR0 %08lx ", __get_ibar(0)); gdbstub_printk("IBAR1 %08lx ", __get_ibar(1)); @@ -1333,6 +1343,44 @@ void gdbstub_get_mmu_state(void) } /* end gdbstub_get_mmu_state() */ +/* + * handle general query commands of the form 'qXXXXX' + */ +static void gdbstub_handle_query(void) +{ + if (strcmp(input_buffer, "qAttached") == 0) { + /* return current thread ID */ + sprintf(output_buffer, "1"); + return; + } + + if (strcmp(input_buffer, "qC") == 0) { + /* return current thread ID */ + sprintf(output_buffer, "QC 0"); + return; + } + + if (strcmp(input_buffer, "qOffsets") == 0) { + /* return relocation offset of text and data segments */ + sprintf(output_buffer, "Text=0;Data=0;Bss=0"); + return; + } + + if (strcmp(input_buffer, "qSymbol::") == 0) { + sprintf(output_buffer, "OK"); + return; + } + + if (strcmp(input_buffer, "qSupported") == 0) { + /* query of supported features */ + sprintf(output_buffer, "PacketSize=%u;ReverseContinue-;ReverseStep-", + sizeof(input_buffer)); + return; + } + + gdbstub_strcpy(output_buffer,"E01"); +} + /*****************************************************************************/ /* * handle event interception and GDB remote protocol processing @@ -1360,7 +1408,7 @@ void gdbstub(int sigval) #endif } - save_user_regs(&__break_user_context); + save_user_regs(&__debug_frame0->uc); #if 0 gdbstub_printk("--> gdbstub() %08x %p %08x %08x\n", @@ -1389,8 +1437,8 @@ void gdbstub(int sigval) __debug_frame->psr &= ~PSR_S; if (__debug_frame->psr & PSR_PS) __debug_frame->psr |= PSR_S; - __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; - __debug_regs->brr |= BRR_EB; + __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12; + __debug_status.brr |= BRR_EB; sigval = SIGINT; } @@ -1404,15 +1452,15 @@ void gdbstub(int sigval) __debug_frame->psr &= ~PSR_S; if (__debug_frame->psr & PSR_PS) __debug_frame->psr |= PSR_S; - __debug_regs->brr = (__debug_frame->tbr & TBR_TT) << 12; - __debug_regs->brr |= BRR_EB; - sigval = SIGXCPU;; + __debug_status.brr = (__debug_frame->tbr & TBR_TT) << 12; + __debug_status.brr |= BRR_EB; + sigval = SIGXCPU; } LEDS(0x5002); /* after a BREAK insn, the PC lands on the far side of it */ - if (__debug_regs->brr & BRR_SB) + if (__debug_status.brr & BRR_SB) gdbstub_check_breakpoint(); LEDS(0x5003); @@ -1431,7 +1479,7 @@ void gdbstub(int sigval) } if (!sigval) - sigval = gdbstub_compute_signal(__debug_regs->brr); + sigval = gdbstub_compute_signal(__debug_status.brr); LEDS(0x5004); @@ -1441,29 +1489,29 @@ void gdbstub(int sigval) if (sigval != SIGINT && sigval != SIGTRAP && sigval != SIGILL) { static const char title[] = "Break "; static const char crlf[] = "\r\n"; - unsigned long brr = __debug_regs->brr; + unsigned long brr = __debug_status.brr; char hx; ptr = output_buffer; *ptr++ = 'O'; ptr = mem2hex(title, ptr, sizeof(title) - 1,0); - hx = hexchars[(brr & 0xf0000000) >> 28]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; - hx = hexchars[(brr & 0x0f000000) >> 24]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; - hx = hexchars[(brr & 0x00f00000) >> 20]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; - hx = hexchars[(brr & 0x000f0000) >> 16]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; - hx = hexchars[(brr & 0x0000f000) >> 12]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; - hx = hexchars[(brr & 0x00000f00) >> 8]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; - hx = hexchars[(brr & 0x000000f0) >> 4]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; - hx = hexchars[(brr & 0x0000000f)]; - *ptr++ = hexchars[hx >> 4]; *ptr++ = hexchars[hx & 0xf]; + hx = hex_asc_hi(brr >> 24); + ptr = hex_byte_pack(ptr, hx); + hx = hex_asc_lo(brr >> 24); + ptr = hex_byte_pack(ptr, hx); + hx = hex_asc_hi(brr >> 16); + ptr = hex_byte_pack(ptr, hx); + hx = hex_asc_lo(brr >> 16); + ptr = hex_byte_pack(ptr, hx); + hx = hex_asc_hi(brr >> 8); + ptr = hex_byte_pack(ptr, hx); + hx = hex_asc_lo(brr >> 8); + ptr = hex_byte_pack(ptr, hx); + hx = hex_asc_hi(brr); + ptr = hex_byte_pack(ptr, hx); + hx = hex_asc_lo(brr); + ptr = hex_byte_pack(ptr, hx); ptr = mem2hex(crlf, ptr, sizeof(crlf) - 1, 0); *ptr = 0; @@ -1477,12 +1525,10 @@ void gdbstub(int sigval) /* Send trap type (converted to signal) */ *ptr++ = 'T'; - *ptr++ = hexchars[sigval >> 4]; - *ptr++ = hexchars[sigval & 0xf]; + ptr = hex_byte_pack(ptr, sigval); /* Send Error PC */ - *ptr++ = hexchars[GDB_REG_PC >> 4]; - *ptr++ = hexchars[GDB_REG_PC & 0xf]; + ptr = hex_byte_pack(ptr, GDB_REG_PC); *ptr++ = ':'; ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0); *ptr++ = ';'; @@ -1490,8 +1536,7 @@ void gdbstub(int sigval) /* * Send frame pointer */ - *ptr++ = hexchars[GDB_REG_FP >> 4]; - *ptr++ = hexchars[GDB_REG_FP & 0xf]; + ptr = hex_byte_pack(ptr, GDB_REG_FP); *ptr++ = ':'; ptr = mem2hex(&__debug_frame->fp, ptr, 4, 0); *ptr++ = ';'; @@ -1499,8 +1544,7 @@ void gdbstub(int sigval) /* * Send stack pointer */ - *ptr++ = hexchars[GDB_REG_SP >> 4]; - *ptr++ = hexchars[GDB_REG_SP & 0xf]; + ptr = hex_byte_pack(ptr, GDB_REG_SP); *ptr++ = ':'; ptr = mem2hex(&__debug_frame->sp, ptr, 4, 0); *ptr++ = ';'; @@ -1525,8 +1569,8 @@ void gdbstub(int sigval) /* request repeat of last signal number */ case '?': output_buffer[0] = 'S'; - output_buffer[1] = hexchars[sigval >> 4]; - output_buffer[2] = hexchars[sigval & 0xf]; + output_buffer[1] = hex_asc_hi(sigval); + output_buffer[2] = hex_asc_lo(sigval); output_buffer[3] = 0; break; @@ -1565,28 +1609,24 @@ void gdbstub(int sigval) ptr = mem2hex(&zero, ptr, 4, 0); for (loop = 1; loop <= 27; loop++) - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[loop], ptr, 4, 0); temp = (unsigned long) __frame; ptr = mem2hex(&temp, ptr, 4, 0); - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(29), ptr, 4, 0); - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(30), ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[29], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[30], ptr, 4, 0); #ifdef CONFIG_MMU - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(31), ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[31], ptr, 4, 0); #else temp = (unsigned long) __debug_frame; ptr = mem2hex(&temp, ptr, 4, 0); #endif for (loop = 32; loop <= 63; loop++) - ptr = mem2hex((unsigned long *)__debug_frame + REG_GR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->i.gr[loop], ptr, 4, 0); /* deal with FR0-FR63 */ for (loop = 0; loop <= 63; loop++) - ptr = mem2hex((unsigned long *)&__break_user_context + - __FPMEDIA_FR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fr[loop], ptr, 4, 0); /* deal with special registers */ ptr = mem2hex(&__debug_frame->pc, ptr, 4, 0); @@ -1597,7 +1637,7 @@ void gdbstub(int sigval) ptr = mem2hex(&zero, ptr, 4, 0); ptr = mem2hex(&zero, ptr, 4, 0); ptr = mem2hex(&__debug_frame->tbr, ptr, 4, 0); - ptr = mem2hex(&__debug_regs->brr , ptr, 4, 0); + ptr = mem2hex(&__debug_status.brr , ptr, 4, 0); asm volatile("movsg dbar0,%0" : "=r"(dbar)); ptr = mem2hex(&dbar, ptr, 4, 0); @@ -1622,21 +1662,21 @@ void gdbstub(int sigval) ptr = mem2hex(&__debug_frame->iacc0, ptr, 8, 0); - ptr = mem2hex(&__break_user_context.f.fsr[0], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fsr[0], ptr, 4, 0); for (loop = 0; loop <= 7; loop++) - ptr = mem2hex(&__break_user_context.f.acc[loop], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.acc[loop], ptr, 4, 0); - ptr = mem2hex(&__break_user_context.f.accg, ptr, 8, 0); + ptr = mem2hex(&__debug_user_context->f.accg, ptr, 8, 0); for (loop = 0; loop <= 1; loop++) - ptr = mem2hex(&__break_user_context.f.msr[loop], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.msr[loop], ptr, 4, 0); ptr = mem2hex(&__debug_frame->gner0, ptr, 4, 0); ptr = mem2hex(&__debug_frame->gner1, ptr, 4, 0); - ptr = mem2hex(&__break_user_context.f.fner[0], ptr, 4, 0); - ptr = mem2hex(&__break_user_context.f.fner[1], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fner[0], ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fner[1], ptr, 4, 0); break; @@ -1648,8 +1688,7 @@ void gdbstub(int sigval) ptr = hex2mem(ptr, &temp, 4); for (loop = 1; loop <= 27; loop++) - ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop), - 4); + ptr = hex2mem(ptr, &__debug_user_context->i.gr[loop], 4); ptr = hex2mem(ptr, &temp, 4); __frame = (struct pt_regs *) temp; @@ -1662,14 +1701,11 @@ void gdbstub(int sigval) #endif for (loop = 32; loop <= 63; loop++) - ptr = hex2mem(ptr, (unsigned long *)__debug_frame + REG_GR(loop), - 4); + ptr = hex2mem(ptr, &__debug_user_context->i.gr[loop], 4); /* deal with FR0-FR63 */ for (loop = 0; loop <= 63; loop++) - ptr = mem2hex((unsigned long *)&__break_user_context + - __FPMEDIA_FR(loop), - ptr, 4, 0); + ptr = mem2hex(&__debug_user_context->f.fr[loop], ptr, 4, 0); /* deal with special registers */ ptr = hex2mem(ptr, &__debug_frame->pc, 4); @@ -1694,21 +1730,21 @@ void gdbstub(int sigval) ptr = hex2mem(ptr, &__debug_frame->iacc0, 8); - ptr = hex2mem(ptr, &__break_user_context.f.fsr[0], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.fsr[0], 4); for (loop = 0; loop <= 7; loop++) - ptr = hex2mem(ptr, &__break_user_context.f.acc[loop], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.acc[loop], 4); - ptr = hex2mem(ptr, &__break_user_context.f.accg, 8); + ptr = hex2mem(ptr, &__debug_user_context->f.accg, 8); for (loop = 0; loop <= 1; loop++) - ptr = hex2mem(ptr, &__break_user_context.f.msr[loop], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.msr[loop], 4); ptr = hex2mem(ptr, &__debug_frame->gner0, 4); ptr = hex2mem(ptr, &__debug_frame->gner1, 4); - ptr = hex2mem(ptr, &__break_user_context.f.fner[0], 4); - ptr = hex2mem(ptr, &__break_user_context.f.fner[1], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.fner[0], 4); + ptr = hex2mem(ptr, &__debug_user_context->f.fner[1], 4); gdbstub_strcpy(output_buffer,"OK"); break; @@ -1752,6 +1788,12 @@ void gdbstub(int sigval) flush_cache = 1; break; + /* pNN: Read value of reg N and return it */ + case 'p': + /* return no value, indicating that we don't support + * this command and that gdb should use 'g' instead */ + break; + /* PNN,=RRRRRRRR: Write value R to reg N return OK */ case 'P': ptr = &input_buffer[1]; @@ -1769,52 +1811,52 @@ void gdbstub(int sigval) case GDB_REG_GR(0): break; case GDB_REG_GR(1) ... GDB_REG_GR(63): - __break_user_context.i.gr[addr - GDB_REG_GR(0)] = temp; + __debug_user_context->i.gr[addr - GDB_REG_GR(0)] = temp; break; case GDB_REG_FR(0) ... GDB_REG_FR(63): - __break_user_context.f.fr[addr - GDB_REG_FR(0)] = temp; + __debug_user_context->f.fr[addr - GDB_REG_FR(0)] = temp; break; case GDB_REG_PC: - __break_user_context.i.pc = temp; + __debug_user_context->i.pc = temp; break; case GDB_REG_PSR: - __break_user_context.i.psr = temp; + __debug_user_context->i.psr = temp; break; case GDB_REG_CCR: - __break_user_context.i.ccr = temp; + __debug_user_context->i.ccr = temp; break; case GDB_REG_CCCR: - __break_user_context.i.cccr = temp; + __debug_user_context->i.cccr = temp; break; case GDB_REG_BRR: - __debug_regs->brr = temp; + __debug_status.brr = temp; break; case GDB_REG_LR: - __break_user_context.i.lr = temp; + __debug_user_context->i.lr = temp; break; case GDB_REG_LCR: - __break_user_context.i.lcr = temp; + __debug_user_context->i.lcr = temp; break; case GDB_REG_FSR0: - __break_user_context.f.fsr[0] = temp; + __debug_user_context->f.fsr[0] = temp; break; case GDB_REG_ACC(0) ... GDB_REG_ACC(7): - __break_user_context.f.acc[addr - GDB_REG_ACC(0)] = temp; + __debug_user_context->f.acc[addr - GDB_REG_ACC(0)] = temp; break; case GDB_REG_ACCG(0): - *(uint32_t *) &__break_user_context.f.accg[0] = temp; + *(uint32_t *) &__debug_user_context->f.accg[0] = temp; break; case GDB_REG_ACCG(4): - *(uint32_t *) &__break_user_context.f.accg[4] = temp; + *(uint32_t *) &__debug_user_context->f.accg[4] = temp; break; case GDB_REG_MSR(0) ... GDB_REG_MSR(1): - __break_user_context.f.msr[addr - GDB_REG_MSR(0)] = temp; + __debug_user_context->f.msr[addr - GDB_REG_MSR(0)] = temp; break; case GDB_REG_GNER(0) ... GDB_REG_GNER(1): - __break_user_context.i.gner[addr - GDB_REG_GNER(0)] = temp; + __debug_user_context->i.gner[addr - GDB_REG_GNER(0)] = temp; break; case GDB_REG_FNER(0) ... GDB_REG_FNER(1): - __break_user_context.f.fner[addr - GDB_REG_FNER(0)] = temp; + __debug_user_context->f.fner[addr - GDB_REG_FNER(0)] = temp; break; default: temp2 = 0; @@ -1841,6 +1883,10 @@ void gdbstub(int sigval) case 'k' : goto done; /* just continue */ + /* detach */ + case 'D': + gdbstub_strcpy(output_buffer, "OK"); + break; /* reset the whole machine (FIXME: system dependent) */ case 'r': @@ -1850,8 +1896,17 @@ void gdbstub(int sigval) /* step to next instruction */ case 's': __debug_regs->dcr |= DCR_SE; + __debug_status.dcr |= DCR_SE; goto done; + /* extended command */ + case 'v': + if (strcmp(input_buffer, "vCont?") == 0) { + output_buffer[0] = 0; + break; + } + goto unsupported_cmd; + /* set baud rate (bBB) */ case 'b': ptr = &input_buffer[1]; @@ -1923,8 +1978,19 @@ void gdbstub(int sigval) gdbstub_strcpy(output_buffer,"OK"); break; + /* Thread-setting packet */ + case 'H': + gdbstub_strcpy(output_buffer, "OK"); + break; + + case 'q': + gdbstub_handle_query(); + break; + default: + unsupported_cmd: gdbstub_proto("### GDB Unsupported Cmd '%s'\n",input_buffer); + gdbstub_strcpy(output_buffer,"E01"); break; } @@ -1934,7 +2000,7 @@ void gdbstub(int sigval) } done: - restore_user_regs(&__break_user_context); + restore_user_regs(&__debug_frame0->uc); //gdbstub_dump_debugregs(); //gdbstub_printk("<-- gdbstub() %08x\n", __debug_frame->pc); @@ -1966,7 +2032,6 @@ void __init gdbstub_init(void) #endif gdbstub_printk("%s", gdbstub_banner); - gdbstub_printk("DCR: %x\n", __debug_regs->dcr); gdbstub_io_init(); @@ -2000,7 +2065,7 @@ void __init gdbstub_init(void) ptr = mem2hex(gdbstub_banner, ptr, sizeof(gdbstub_banner) - 1, 0); gdbstub_send_packet(output_buffer); #endif -#if defined(CONFIG_GDBSTUB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE) +#if defined(CONFIG_GDB_CONSOLE) && defined(CONFIG_GDBSTUB_IMMEDIATE) register_console(&gdbstub_console); #endif @@ -2010,7 +2075,7 @@ void __init gdbstub_init(void) /* * register the console at a more appropriate time */ -#if defined (CONFIG_GDBSTUB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE) +#if defined (CONFIG_GDB_CONSOLE) && !defined(CONFIG_GDBSTUB_IMMEDIATE) static int __init gdbstub_postinit(void) { printk("registering console\n"); @@ -2044,8 +2109,8 @@ void gdbstub_exit(int status) } gdbstub_tx_char('#'); - gdbstub_tx_char(hexchars[checksum >> 4]); - gdbstub_tx_char(hexchars[checksum & 0xf]); + gdbstub_tx_char(hex_asc_hi(checksum)); + gdbstub_tx_char(hex_asc_lo(checksum)); /* make sure the output is flushed, or else RedBoot might clobber it */ gdbstub_tx_char('-'); @@ -2058,25 +2123,25 @@ void gdbstub_exit(int status) * GDB wants to call malloc() and free() to allocate memory for calling kernel * functions directly from its command line */ -static void *malloc(size_t size) __attribute__((unused)); +static void *malloc(size_t size) __maybe_unused; static void *malloc(size_t size) { return kmalloc(size, GFP_ATOMIC); } -static void free(void *p) __attribute__((unused)); +static void free(void *p) __maybe_unused; static void free(void *p) { kfree(p); } -static uint32_t ___get_HSR0(void) __attribute__((unused)); +static uint32_t ___get_HSR0(void) __maybe_unused; static uint32_t ___get_HSR0(void) { return __get_HSR(0); } -static uint32_t ___set_HSR0(uint32_t x) __attribute__((unused)); +static uint32_t ___set_HSR0(uint32_t x) __maybe_unused; static uint32_t ___set_HSR0(uint32_t x) { __set_HSR(0, x); diff --git a/arch/frv/kernel/head-mmu-fr451.S b/arch/frv/kernel/head-mmu-fr451.S index a143c2f66ee..98f87d586e5 100644 --- a/arch/frv/kernel/head-mmu-fr451.S +++ b/arch/frv/kernel/head-mmu-fr451.S @@ -9,7 +9,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/init.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> @@ -32,7 +32,7 @@ #define __400_LCR 0xfe000100 #define __400_LSBR 0xfe000c00 - .section .text.init,"ax" + __INIT .balign 4 ############################################################################### diff --git a/arch/frv/kernel/head-uc-fr401.S b/arch/frv/kernel/head-uc-fr401.S index 4ccf8414ae4..438643cfa38 100644 --- a/arch/frv/kernel/head-uc-fr401.S +++ b/arch/frv/kernel/head-uc-fr401.S @@ -9,7 +9,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/init.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> @@ -31,7 +31,7 @@ #define __400_LCR 0xfe000100 #define __400_LSBR 0xfe000c00 - .section .text.init,"ax" + __INIT .balign 4 ############################################################################### diff --git a/arch/frv/kernel/head-uc-fr451.S b/arch/frv/kernel/head-uc-fr451.S index 31cb54a6f08..b2a76c4a178 100644 --- a/arch/frv/kernel/head-uc-fr451.S +++ b/arch/frv/kernel/head-uc-fr451.S @@ -9,7 +9,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/init.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> @@ -31,7 +31,7 @@ #define __400_LCR 0xfe000100 #define __400_LSBR 0xfe000c00 - .section .text.init,"ax" + __INIT .balign 4 ############################################################################### diff --git a/arch/frv/kernel/head-uc-fr555.S b/arch/frv/kernel/head-uc-fr555.S index d088db2699b..5497aaf34f7 100644 --- a/arch/frv/kernel/head-uc-fr555.S +++ b/arch/frv/kernel/head-uc-fr555.S @@ -9,7 +9,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/init.h> #include <linux/threads.h> #include <linux/linkage.h> #include <asm/ptrace.h> @@ -30,7 +30,7 @@ #define __551_LCR 0xfeff1100 #define __551_LSBR 0xfeff1c00 - .section .text.init,"ax" + __INIT .balign 4 ############################################################################### diff --git a/arch/frv/kernel/head.S b/arch/frv/kernel/head.S index c73b4fe9f6c..a7d0bea9c03 100644 --- a/arch/frv/kernel/head.S +++ b/arch/frv/kernel/head.S @@ -9,9 +9,10 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/init.h> #include <linux/threads.h> #include <linux/linkage.h> +#include <asm/thread_info.h> #include <asm/ptrace.h> #include <asm/page.h> #include <asm/spr-regs.h> @@ -27,7 +28,7 @@ # command line string # ############################################################################### - .section .text.head,"ax" + __HEAD .balign 4 .globl _boot, __head_reference @@ -478,11 +479,6 @@ __head_mmu_enabled: LEDS 0x000c - # initialise the processor and the peripherals - #call SYMBOL_NAME(processor_init) - #call SYMBOL_NAME(unit_init) - #LEDS 0x0aff - sethi.p #0xe5e5,gr3 setlo #0xe5e5,gr3 or.p gr3,gr0,gr4 @@ -513,6 +509,9 @@ __head_mmu_enabled: movgs gr0,ccr movgs gr0,cccr + # initialise the virtual interrupt handling + subcc gr0,gr0,gr0,icc2 /* set Z, clear C */ + #ifdef CONFIG_MMU movgs gr3,scr2 movgs gr3,scr3 @@ -538,7 +537,7 @@ __head_end: .size _boot, .-_boot # provide a point for GDB to place a break - .section .text.start,"ax" + .section .text..start,"ax" .globl _start .balign 4 _start: diff --git a/arch/frv/kernel/head.inc b/arch/frv/kernel/head.inc index d424cd2eb21..bff66628b99 100644 --- a/arch/frv/kernel/head.inc +++ b/arch/frv/kernel/head.inc @@ -46,5 +46,5 @@ #ifdef CONFIG_MMU __sdram_base = 0x00000000 /* base address to which SDRAM relocated */ #else -__sdram_base = 0xc0000000 /* base address to which SDRAM relocated */ +__sdram_base = __page_offset /* base address to which SDRAM relocated */ #endif diff --git a/arch/frv/kernel/init_task.c b/arch/frv/kernel/init_task.c deleted file mode 100644 index 22993932b3f..00000000000 --- a/arch/frv/kernel/init_task.c +++ /dev/null @@ -1,39 +0,0 @@ -#include <linux/mm.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/init_task.h> -#include <linux/fs.h> -#include <linux/mqueue.h> - -#include <asm/uaccess.h> -#include <asm/pgtable.h> - - -static struct fs_struct init_fs = INIT_FS; -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); -struct mm_struct init_mm = INIT_MM(init_mm); - -EXPORT_SYMBOL(init_mm); - -/* - * Initial thread structure. - * - * We need to make sure that this is THREAD_SIZE aligned due to the - * way process stacks are handled. This is done by having a special - * "init_task" linker map entry.. - */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = - { INIT_THREAD_INFO(init_task) }; - -/* - * Initial task structure. - * - * All other task structs will be allocated on slabs in fork.c - */ -struct task_struct init_task = INIT_TASK(init_task); - -EXPORT_SYMBOL(init_task); diff --git a/arch/frv/kernel/irq-mb93091.c b/arch/frv/kernel/irq-mb93091.c index 9778e0ff7c1..2cc327a1ca4 100644 --- a/arch/frv/kernel/irq-mb93091.c +++ b/arch/frv/kernel/irq-mb93091.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -18,14 +17,12 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/irq.h> +#include <linux/bitops.h> #include <asm/io.h> -#include <asm/system.h> -#include <asm/bitops.h> #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #define __reg16(ADDR) (*(volatile unsigned short *)(ADDR)) @@ -34,83 +31,127 @@ #define __get_IFR() ({ __reg16(0xffc0000c); }) #define __clr_IFR(M) do { __reg16(0xffc0000c) = ~(M); wmb(); } while(0) -static void frv_fpga_doirq(struct irq_source *source); -static void frv_fpga_control(struct irq_group *group, int irq, int on); -/*****************************************************************************/ /* - * FPGA IRQ multiplexor + * on-motherboard FPGA PIC operations */ -static struct irq_source frv_fpga[4] = { -#define __FPGA(X, M) \ - [X] = { \ - .muxname = "fpga."#X, \ - .irqmask = M, \ - .doirq = frv_fpga_doirq, \ - } +static void frv_fpga_mask(struct irq_data *d) +{ + uint16_t imr = __get_IMR(); - __FPGA(0, 0x0028), - __FPGA(1, 0x0050), - __FPGA(2, 0x1c00), - __FPGA(3, 0x6386), -}; + imr |= 1 << (d->irq - IRQ_BASE_FPGA); -static struct irq_group frv_fpga_irqs = { - .first_irq = IRQ_BASE_FPGA, - .control = frv_fpga_control, - .sources = { - [ 1] = &frv_fpga[3], - [ 2] = &frv_fpga[3], - [ 3] = &frv_fpga[0], - [ 4] = &frv_fpga[1], - [ 5] = &frv_fpga[0], - [ 6] = &frv_fpga[1], - [ 7] = &frv_fpga[3], - [ 8] = &frv_fpga[3], - [ 9] = &frv_fpga[3], - [10] = &frv_fpga[2], - [11] = &frv_fpga[2], - [12] = &frv_fpga[2], - [13] = &frv_fpga[3], - [14] = &frv_fpga[3], - }, -}; + __set_IMR(imr); +} +static void frv_fpga_ack(struct irq_data *d) +{ + __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA)); +} -static void frv_fpga_control(struct irq_group *group, int index, int on) +static void frv_fpga_mask_ack(struct irq_data *d) { uint16_t imr = __get_IMR(); - if (on) - imr &= ~(1 << index); - else - imr |= 1 << index; + imr |= 1 << (d->irq - IRQ_BASE_FPGA); + __set_IMR(imr); + + __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA)); +} + +static void frv_fpga_unmask(struct irq_data *d) +{ + uint16_t imr = __get_IMR(); + + imr &= ~(1 << (d->irq - IRQ_BASE_FPGA)); __set_IMR(imr); } -static void frv_fpga_doirq(struct irq_source *source) +static struct irq_chip frv_fpga_pic = { + .name = "mb93091", + .irq_ack = frv_fpga_ack, + .irq_mask = frv_fpga_mask, + .irq_mask_ack = frv_fpga_mask_ack, + .irq_unmask = frv_fpga_unmask, +}; + +/* + * FPGA PIC interrupt handler + */ +static irqreturn_t fpga_interrupt(int irq, void *_mask) { - uint16_t mask, imr; + uint16_t imr, mask = (unsigned long) _mask; imr = __get_IMR(); - mask = source->irqmask & ~imr & __get_IFR(); - if (mask) { - __set_IMR(imr | mask); - __clr_IFR(mask); - distribute_irqs(&frv_fpga_irqs, mask); - __set_IMR(imr); + mask = mask & ~imr & __get_IFR(); + + /* poll all the triggered IRQs */ + while (mask) { + int irq; + + asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask)); + irq = 31 - irq; + mask &= ~(1 << irq); + + generic_handle_irq(IRQ_BASE_FPGA + irq); } + + return IRQ_HANDLED; } +/* + * define an interrupt action for each FPGA PIC output + * - use dev_id to indicate the FPGA PIC input to output mappings + */ +static struct irqaction fpga_irq[4] = { + [0] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .name = "fpga.0", + .dev_id = (void *) 0x0028UL, + }, + [1] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .name = "fpga.1", + .dev_id = (void *) 0x0050UL, + }, + [2] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .name = "fpga.2", + .dev_id = (void *) 0x1c00UL, + }, + [3] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .name = "fpga.3", + .dev_id = (void *) 0x6386UL, + } +}; + +/* + * initialise the motherboard FPGA's PIC + */ void __init fpga_init(void) { + int irq; + + /* all PIC inputs are all set to be low-level driven, apart from the + * NMI button (15) which is fixed at falling-edge + */ __set_IMR(0x7ffe); __clr_IFR(0x0000); - frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL0); - frv_irq_route_external(&frv_fpga[1], IRQ_CPU_EXTERNAL1); - frv_irq_route_external(&frv_fpga[2], IRQ_CPU_EXTERNAL2); - frv_irq_route_external(&frv_fpga[3], IRQ_CPU_EXTERNAL3); - frv_irq_set_group(&frv_fpga_irqs); + for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++) + irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq); + + irq_set_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq); + + /* the FPGA drives the first four external IRQ inputs on the CPU PIC */ + setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]); + setup_irq(IRQ_CPU_EXTERNAL1, &fpga_irq[1]); + setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[2]); + setup_irq(IRQ_CPU_EXTERNAL3, &fpga_irq[3]); } diff --git a/arch/frv/kernel/irq-mb93093.c b/arch/frv/kernel/irq-mb93093.c index 21ca2b29824..95e4eb4f1f3 100644 --- a/arch/frv/kernel/irq-mb93093.c +++ b/arch/frv/kernel/irq-mb93093.c @@ -1,6 +1,6 @@ /* irq-mb93093.c: MB93093 FPGA interrupt handling * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -18,14 +17,12 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/irq.h> +#include <linux/bitops.h> #include <asm/io.h> -#include <asm/system.h> -#include <asm/bitops.h> #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR))) @@ -34,66 +31,100 @@ #define __get_IFR() ({ __reg16(0x02); }) #define __clr_IFR(M) do { __reg16(0x02) = ~(M); wmb(); } while(0) -static void frv_fpga_doirq(struct irq_source *source); -static void frv_fpga_control(struct irq_group *group, int irq, int on); - -/*****************************************************************************/ /* - * FPGA IRQ multiplexor + * off-CPU FPGA PIC operations */ -static struct irq_source frv_fpga[4] = { -#define __FPGA(X, M) \ - [X] = { \ - .muxname = "fpga."#X, \ - .irqmask = M, \ - .doirq = frv_fpga_doirq, \ - } +static void frv_fpga_mask(struct irq_data *d) +{ + uint16_t imr = __get_IMR(); - __FPGA(0, 0x0700), -}; + imr |= 1 << (d->irq - IRQ_BASE_FPGA); + __set_IMR(imr); +} -static struct irq_group frv_fpga_irqs = { - .first_irq = IRQ_BASE_FPGA, - .control = frv_fpga_control, - .sources = { - [ 8] = &frv_fpga[0], - [ 9] = &frv_fpga[0], - [10] = &frv_fpga[0], - }, -}; +static void frv_fpga_ack(struct irq_data *d) +{ + __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA)); +} + +static void frv_fpga_mask_ack(struct irq_data *d) +{ + uint16_t imr = __get_IMR(); + imr |= 1 << (d->irq - IRQ_BASE_FPGA); + __set_IMR(imr); + + __clr_IFR(1 << (d->irq - IRQ_BASE_FPGA)); +} -static void frv_fpga_control(struct irq_group *group, int index, int on) +static void frv_fpga_unmask(struct irq_data *d) { uint16_t imr = __get_IMR(); - if (on) - imr &= ~(1 << index); - else - imr |= 1 << index; + imr &= ~(1 << (d->irq - IRQ_BASE_FPGA)); __set_IMR(imr); } -static void frv_fpga_doirq(struct irq_source *source) +static struct irq_chip frv_fpga_pic = { + .name = "mb93093", + .irq_ack = frv_fpga_ack, + .irq_mask = frv_fpga_mask, + .irq_mask_ack = frv_fpga_mask_ack, + .irq_unmask = frv_fpga_unmask, +}; + +/* + * FPGA PIC interrupt handler + */ +static irqreturn_t fpga_interrupt(int irq, void *_mask) { - uint16_t mask, imr; + uint16_t imr, mask = (unsigned long) _mask; imr = __get_IMR(); - mask = source->irqmask & ~imr & __get_IFR(); - if (mask) { - __set_IMR(imr | mask); - __clr_IFR(mask); - distribute_irqs(&frv_fpga_irqs, mask); - __set_IMR(imr); + mask = mask & ~imr & __get_IFR(); + + /* poll all the triggered IRQs */ + while (mask) { + int irq; + + asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask)); + irq = 31 - irq; + mask &= ~(1 << irq); + + generic_handle_irq(IRQ_BASE_FPGA + irq); } + + return IRQ_HANDLED; } +/* + * define an interrupt action for each FPGA PIC output + * - use dev_id to indicate the FPGA PIC input to output mappings + */ +static struct irqaction fpga_irq[1] = { + [0] = { + .handler = fpga_interrupt, + .flags = IRQF_DISABLED, + .name = "fpga.0", + .dev_id = (void *) 0x0700UL, + } +}; + +/* + * initialise the motherboard FPGA's PIC + */ void __init fpga_init(void) { + int irq; + + /* all PIC inputs are all set to be edge triggered */ __set_IMR(0x0700); __clr_IFR(0x0000); - frv_irq_route_external(&frv_fpga[0], IRQ_CPU_EXTERNAL2); - frv_irq_set_group(&frv_fpga_irqs); + for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++) + irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq); + + /* the FPGA drives external IRQ input #2 on the CPU PIC */ + setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]); } diff --git a/arch/frv/kernel/irq-mb93493.c b/arch/frv/kernel/irq-mb93493.c index c003ae5e2b3..ba648da0932 100644 --- a/arch/frv/kernel/irq-mb93493.c +++ b/arch/frv/kernel/irq-mb93493.c @@ -1,6 +1,6 @@ /* irq-mb93493.c: MB93493 companion chip interrupt handler * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -18,91 +17,131 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/irq.h> +#include <linux/bitops.h> #include <asm/io.h> -#include <asm/system.h> -#include <asm/bitops.h> #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #include <asm/mb93493-irqs.h> +#include <asm/mb93493-regs.h> -static void frv_mb93493_doirq(struct irq_source *source); +#define IRQ_ROUTE_ONE(X) (X##_ROUTE << (X - IRQ_BASE_MB93493)) + +#define IRQ_ROUTING \ + (IRQ_ROUTE_ONE(IRQ_MB93493_VDC) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_VCC) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_OUT) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_I2C_0) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_I2C_1) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_USB) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_LOCAL_BUS) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_PCMCIA) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_GPIO) | \ + IRQ_ROUTE_ONE(IRQ_MB93493_AUDIO_IN)) -/*****************************************************************************/ /* - * MB93493 companion chip IRQ multiplexor + * daughter board PIC operations + * - there is no way to ACK interrupts in the MB93493 chip */ -static struct irq_source frv_mb93493[2] = { - [0] = { - .muxname = "mb93493.0", - .muxdata = __region_CS3 + 0x3d0, - .doirq = frv_mb93493_doirq, - .irqmask = 0x0000, - }, - [1] = { - .muxname = "mb93493.1", - .muxdata = __region_CS3 + 0x3d4, - .doirq = frv_mb93493_doirq, - .irqmask = 0x0000, - }, -}; - -static void frv_mb93493_control(struct irq_group *group, int index, int on) +static void frv_mb93493_mask(struct irq_data *d) { - struct irq_source *source; uint32_t iqsr; + volatile void *piqsr; - if ((frv_mb93493[0].irqmask & (1 << index))) - source = &frv_mb93493[0]; + if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493))) + piqsr = __addr_MB93493_IQSR(1); else - source = &frv_mb93493[1]; + piqsr = __addr_MB93493_IQSR(0); + + iqsr = readl(piqsr); + iqsr &= ~(1 << (d->irq - IRQ_BASE_MB93493 + 16)); + writel(iqsr, piqsr); +} - iqsr = readl(source->muxdata); - if (on) - iqsr |= 1 << (index + 16); +static void frv_mb93493_ack(struct irq_data *d) +{ +} + +static void frv_mb93493_unmask(struct irq_data *d) +{ + uint32_t iqsr; + volatile void *piqsr; + + if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493))) + piqsr = __addr_MB93493_IQSR(1); else - iqsr &= ~(1 << (index + 16)); + piqsr = __addr_MB93493_IQSR(0); - writel(iqsr, source->muxdata); + iqsr = readl(piqsr); + iqsr |= 1 << (d->irq - IRQ_BASE_MB93493 + 16); + writel(iqsr, piqsr); } -static struct irq_group frv_mb93493_irqs = { - .first_irq = IRQ_BASE_MB93493, - .control = frv_mb93493_control, +static struct irq_chip frv_mb93493_pic = { + .name = "mb93093", + .irq_ack = frv_mb93493_ack, + .irq_mask = frv_mb93493_mask, + .irq_mask_ack = frv_mb93493_mask, + .irq_unmask = frv_mb93493_unmask, }; -static void frv_mb93493_doirq(struct irq_source *source) +/* + * MB93493 PIC interrupt handler + */ +static irqreturn_t mb93493_interrupt(int irq, void *_piqsr) { - uint32_t mask = readl(source->muxdata); - mask = mask & (mask >> 16) & 0xffff; + volatile void *piqsr = _piqsr; + uint32_t iqsr; - if (mask) - distribute_irqs(&frv_mb93493_irqs, mask); -} + iqsr = readl(piqsr); + iqsr = iqsr & (iqsr >> 16) & 0xffff; -static void __init mb93493_irq_route(int irq, int source) -{ - frv_mb93493[source].irqmask |= 1 << (irq - IRQ_BASE_MB93493); - frv_mb93493_irqs.sources[irq - IRQ_BASE_MB93493] = &frv_mb93493[source]; + /* poll all the triggered IRQs */ + while (iqsr) { + int irq; + + asm("scan %1,gr0,%0" : "=r"(irq) : "r"(iqsr)); + irq = 31 - irq; + iqsr &= ~(1 << irq); + + generic_handle_irq(IRQ_BASE_MB93493 + irq); + } + + return IRQ_HANDLED; } -void __init route_mb93493_irqs(void) +/* + * define an interrupt action for each MB93493 PIC output + * - use dev_id to indicate the MB93493 PIC input to output mappings + */ +static struct irqaction mb93493_irq[2] = { + [0] = { + .handler = mb93493_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .name = "mb93493.0", + .dev_id = (void *) __addr_MB93493_IQSR(0), + }, + [1] = { + .handler = mb93493_interrupt, + .flags = IRQF_DISABLED | IRQF_SHARED, + .name = "mb93493.1", + .dev_id = (void *) __addr_MB93493_IQSR(1), + } +}; + +/* + * initialise the motherboard MB93493's PIC + */ +void __init mb93493_init(void) { - frv_irq_route_external(&frv_mb93493[0], IRQ_CPU_MB93493_0); - frv_irq_route_external(&frv_mb93493[1], IRQ_CPU_MB93493_1); - - frv_irq_set_group(&frv_mb93493_irqs); - - mb93493_irq_route(IRQ_MB93493_VDC, IRQ_MB93493_VDC_ROUTE); - mb93493_irq_route(IRQ_MB93493_VCC, IRQ_MB93493_VCC_ROUTE); - mb93493_irq_route(IRQ_MB93493_AUDIO_IN, IRQ_MB93493_AUDIO_IN_ROUTE); - mb93493_irq_route(IRQ_MB93493_I2C_0, IRQ_MB93493_I2C_0_ROUTE); - mb93493_irq_route(IRQ_MB93493_I2C_1, IRQ_MB93493_I2C_1_ROUTE); - mb93493_irq_route(IRQ_MB93493_USB, IRQ_MB93493_USB_ROUTE); - mb93493_irq_route(IRQ_MB93493_LOCAL_BUS, IRQ_MB93493_LOCAL_BUS_ROUTE); - mb93493_irq_route(IRQ_MB93493_PCMCIA, IRQ_MB93493_PCMCIA_ROUTE); - mb93493_irq_route(IRQ_MB93493_GPIO, IRQ_MB93493_GPIO_ROUTE); - mb93493_irq_route(IRQ_MB93493_AUDIO_OUT, IRQ_MB93493_AUDIO_OUT_ROUTE); + int irq; + + for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++) + irq_set_chip_and_handler(irq, &frv_mb93493_pic, + handle_edge_irq); + + /* the MB93493 drives external IRQ inputs on the CPU PIC */ + setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]); + setup_irq(IRQ_CPU_MB93493_1, &mb93493_irq[1]); } diff --git a/arch/frv/kernel/irq-routing.c b/arch/frv/kernel/irq-routing.c deleted file mode 100644 index d4776d1f4e8..00000000000 --- a/arch/frv/kernel/irq-routing.c +++ /dev/null @@ -1,291 +0,0 @@ -/* irq-routing.c: IRQ routing - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/sched.h> -#include <linux/random.h> -#include <linux/init.h> -#include <linux/serial_reg.h> -#include <asm/io.h> -#include <asm/irq-routing.h> -#include <asm/irc-regs.h> -#include <asm/serial-regs.h> -#include <asm/dma.h> - -struct irq_level frv_irq_levels[16] = { - [0 ... 15] = { - .lock = SPIN_LOCK_UNLOCKED, - } -}; - -struct irq_group *irq_groups[NR_IRQ_GROUPS]; - -extern struct irq_group frv_cpu_irqs; - -void __init frv_irq_route(struct irq_source *source, int irqlevel) -{ - source->level = &frv_irq_levels[irqlevel]; - source->next = frv_irq_levels[irqlevel].sources; - frv_irq_levels[irqlevel].sources = source; -} - -void __init frv_irq_route_external(struct irq_source *source, int irq) -{ - int irqlevel = 0; - - switch (irq) { - case IRQ_CPU_EXTERNAL0: irqlevel = IRQ_XIRQ0_LEVEL; break; - case IRQ_CPU_EXTERNAL1: irqlevel = IRQ_XIRQ1_LEVEL; break; - case IRQ_CPU_EXTERNAL2: irqlevel = IRQ_XIRQ2_LEVEL; break; - case IRQ_CPU_EXTERNAL3: irqlevel = IRQ_XIRQ3_LEVEL; break; - case IRQ_CPU_EXTERNAL4: irqlevel = IRQ_XIRQ4_LEVEL; break; - case IRQ_CPU_EXTERNAL5: irqlevel = IRQ_XIRQ5_LEVEL; break; - case IRQ_CPU_EXTERNAL6: irqlevel = IRQ_XIRQ6_LEVEL; break; - case IRQ_CPU_EXTERNAL7: irqlevel = IRQ_XIRQ7_LEVEL; break; - default: BUG(); - } - - source->level = &frv_irq_levels[irqlevel]; - source->next = frv_irq_levels[irqlevel].sources; - frv_irq_levels[irqlevel].sources = source; -} - -void __init frv_irq_set_group(struct irq_group *group) -{ - irq_groups[group->first_irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP] = group; -} - -void distribute_irqs(struct irq_group *group, unsigned long irqmask) -{ - struct irqaction *action; - int irq; - - while (irqmask) { - asm("scan %1,gr0,%0" : "=r"(irq) : "r"(irqmask)); - if (irq < 0 || irq > 31) - asm volatile("break"); - irq = 31 - irq; - - irqmask &= ~(1 << irq); - action = group->actions[irq]; - - irq += group->first_irq; - - if (action) { - int status = 0; - -// if (!(action->flags & SA_INTERRUPT)) -// local_irq_enable(); - - do { - status |= action->flags; - action->handler(irq, action->dev_id, __frame); - action = action->next; - } while (action); - - if (status & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - } - } -} - -/*****************************************************************************/ -/* - * CPU UART interrupts - */ -static void frv_cpuuart_doirq(struct irq_source *source) -{ -// uint8_t iir = readb(source->muxdata + UART_IIR * 8); -// if ((iir & 0x0f) != UART_IIR_NO_INT) - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cpuuart[2] = { -#define __CPUUART(X, A) \ - [X] = { \ - .muxname = "uart", \ - .muxdata = (volatile void __iomem *) A, \ - .irqmask = 1 << IRQ_CPU_UART##X, \ - .doirq = frv_cpuuart_doirq, \ - } - - __CPUUART(0, UART0_BASE), - __CPUUART(1, UART1_BASE), -}; - -/*****************************************************************************/ -/* - * CPU DMA interrupts - */ -static void frv_cpudma_doirq(struct irq_source *source) -{ - uint32_t cstr = readl(source->muxdata + DMAC_CSTRx); - if (cstr & DMAC_CSTRx_INT) - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cpudma[8] = { -#define __CPUDMA(X, A) \ - [X] = { \ - .muxname = "dma", \ - .muxdata = (volatile void __iomem *) A, \ - .irqmask = 1 << IRQ_CPU_DMA##X, \ - .doirq = frv_cpudma_doirq, \ - } - - __CPUDMA(0, 0xfe000900), - __CPUDMA(1, 0xfe000980), - __CPUDMA(2, 0xfe000a00), - __CPUDMA(3, 0xfe000a80), - __CPUDMA(4, 0xfe001000), - __CPUDMA(5, 0xfe001080), - __CPUDMA(6, 0xfe001100), - __CPUDMA(7, 0xfe001180), -}; - -/*****************************************************************************/ -/* - * CPU timer interrupts - can't tell whether they've generated an interrupt or not - */ -static void frv_cputimer_doirq(struct irq_source *source) -{ - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cputimer[3] = { -#define __CPUTIMER(X) \ - [X] = { \ - .muxname = "timer", \ - .muxdata = 0, \ - .irqmask = 1 << IRQ_CPU_TIMER##X, \ - .doirq = frv_cputimer_doirq, \ - } - - __CPUTIMER(0), - __CPUTIMER(1), - __CPUTIMER(2), -}; - -/*****************************************************************************/ -/* - * external CPU interrupts - can't tell directly whether they've generated an interrupt or not - */ -static void frv_cpuexternal_doirq(struct irq_source *source) -{ - distribute_irqs(&frv_cpu_irqs, source->irqmask); -} - -struct irq_source frv_cpuexternal[8] = { -#define __CPUEXTERNAL(X) \ - [X] = { \ - .muxname = "ext", \ - .muxdata = 0, \ - .irqmask = 1 << IRQ_CPU_EXTERNAL##X, \ - .doirq = frv_cpuexternal_doirq, \ - } - - __CPUEXTERNAL(0), - __CPUEXTERNAL(1), - __CPUEXTERNAL(2), - __CPUEXTERNAL(3), - __CPUEXTERNAL(4), - __CPUEXTERNAL(5), - __CPUEXTERNAL(6), - __CPUEXTERNAL(7), -}; - -#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16)) - -struct irq_group frv_cpu_irqs = { - .sources = { - [IRQ_CPU_UART0] = &frv_cpuuart[0], - [IRQ_CPU_UART1] = &frv_cpuuart[1], - [IRQ_CPU_TIMER0] = &frv_cputimer[0], - [IRQ_CPU_TIMER1] = &frv_cputimer[1], - [IRQ_CPU_TIMER2] = &frv_cputimer[2], - [IRQ_CPU_DMA0] = &frv_cpudma[0], - [IRQ_CPU_DMA1] = &frv_cpudma[1], - [IRQ_CPU_DMA2] = &frv_cpudma[2], - [IRQ_CPU_DMA3] = &frv_cpudma[3], - [IRQ_CPU_DMA4] = &frv_cpudma[4], - [IRQ_CPU_DMA5] = &frv_cpudma[5], - [IRQ_CPU_DMA6] = &frv_cpudma[6], - [IRQ_CPU_DMA7] = &frv_cpudma[7], - [IRQ_CPU_EXTERNAL0] = &frv_cpuexternal[0], - [IRQ_CPU_EXTERNAL1] = &frv_cpuexternal[1], - [IRQ_CPU_EXTERNAL2] = &frv_cpuexternal[2], - [IRQ_CPU_EXTERNAL3] = &frv_cpuexternal[3], - [IRQ_CPU_EXTERNAL4] = &frv_cpuexternal[4], - [IRQ_CPU_EXTERNAL5] = &frv_cpuexternal[5], - [IRQ_CPU_EXTERNAL6] = &frv_cpuexternal[6], - [IRQ_CPU_EXTERNAL7] = &frv_cpuexternal[7], - }, -}; - -/*****************************************************************************/ -/* - * route the CPU's interrupt sources - */ -void __init route_cpu_irqs(void) -{ - frv_irq_set_group(&frv_cpu_irqs); - - __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 IRQ detect levels */ - __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 IRQ detect levels */ - - /* route UART and error interrupts */ - frv_irq_route(&frv_cpuuart[0], IRQ_UART0_LEVEL); - frv_irq_route(&frv_cpuuart[1], IRQ_UART1_LEVEL); - - set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, IRQ_UART1_LEVEL, IRQ_UART0_LEVEL); - - /* route DMA channel interrupts */ - frv_irq_route(&frv_cpudma[0], IRQ_DMA0_LEVEL); - frv_irq_route(&frv_cpudma[1], IRQ_DMA1_LEVEL); - frv_irq_route(&frv_cpudma[2], IRQ_DMA2_LEVEL); - frv_irq_route(&frv_cpudma[3], IRQ_DMA3_LEVEL); - frv_irq_route(&frv_cpudma[4], IRQ_DMA4_LEVEL); - frv_irq_route(&frv_cpudma[5], IRQ_DMA5_LEVEL); - frv_irq_route(&frv_cpudma[6], IRQ_DMA6_LEVEL); - frv_irq_route(&frv_cpudma[7], IRQ_DMA7_LEVEL); - - set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, IRQ_DMA0_LEVEL); - set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, IRQ_DMA4_LEVEL); - - /* route timer interrupts */ - frv_irq_route(&frv_cputimer[0], IRQ_TIMER0_LEVEL); - frv_irq_route(&frv_cputimer[1], IRQ_TIMER1_LEVEL); - frv_irq_route(&frv_cputimer[2], IRQ_TIMER2_LEVEL); - - set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL); - - /* route external interrupts */ - frv_irq_route(&frv_cpuexternal[0], IRQ_XIRQ0_LEVEL); - frv_irq_route(&frv_cpuexternal[1], IRQ_XIRQ1_LEVEL); - frv_irq_route(&frv_cpuexternal[2], IRQ_XIRQ2_LEVEL); - frv_irq_route(&frv_cpuexternal[3], IRQ_XIRQ3_LEVEL); - frv_irq_route(&frv_cpuexternal[4], IRQ_XIRQ4_LEVEL); - frv_irq_route(&frv_cpuexternal[5], IRQ_XIRQ5_LEVEL); - frv_irq_route(&frv_cpuexternal[6], IRQ_XIRQ6_LEVEL); - frv_irq_route(&frv_cpuexternal[7], IRQ_XIRQ7_LEVEL); - - set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, IRQ_XIRQ4_LEVEL); - set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, IRQ_XIRQ0_LEVEL); - -#if defined(CONFIG_MB93091_VDK) - __set_TM1(0x55550000); /* XIRQ7-0 all active low */ -#elif defined(CONFIG_MB93093_PDK) - __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */ -#else -#error dont know external IRQ trigger levels for this setup -#endif - -} /* end route_cpu_irqs() */ diff --git a/arch/frv/kernel/irq.c b/arch/frv/kernel/irq.c index 59580c59c62..2239346fa3d 100644 --- a/arch/frv/kernel/irq.c +++ b/arch/frv/kernel/irq.c @@ -1,6 +1,6 @@ /* irq.c: FRV IRQ handling * - * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Copyright (C) 2003, 2004, 2006 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or @@ -9,14 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -/* - * (mostly architecture independent, will move to kernel/irq.c in 2.5.) - * - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include <linux/config.h> #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/signal.h> @@ -24,758 +16,144 @@ #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/timex.h> -#include <linux/slab.h> #include <linux/random.h> -#include <linux/smp_lock.h> #include <linux/init.h> #include <linux/kernel_stat.h> #include <linux/irq.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/module.h> +#include <linux/bitops.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/io.h> #include <asm/smp.h> -#include <asm/system.h> -#include <asm/bitops.h> #include <asm/uaccess.h> #include <asm/pgalloc.h> #include <asm/delay.h> #include <asm/irq.h> #include <asm/irc-regs.h> -#include <asm/irq-routing.h> #include <asm/gdb-stub.h> -extern void __init fpga_init(void); -extern void __init route_mb93493_irqs(void); - -static void register_irq_proc (unsigned int irq); +#define set_IRR(N,A,B,C,D) __set_IRR(N, (A << 28) | (B << 24) | (C << 20) | (D << 16)) -/* - * Special irq handlers. - */ +extern void __init fpga_init(void); +#ifdef CONFIG_FUJITSU_MB93493 +extern void __init mb93493_init(void); +#endif -irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) { return IRQ_HANDLED; } +#define __reg16(ADDR) (*(volatile unsigned short *)(ADDR)) atomic_t irq_err_count; -/* - * Generic, controller-independent functions: - */ -int show_interrupts(struct seq_file *p, void *v) +int arch_show_interrupts(struct seq_file *p, int prec) { - struct irqaction *action; - struct irq_group *group; - unsigned long flags; - int level, grp, ix, i, j; - - i = *(loff_t *) v; - - switch (i) { - case 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'); - break; - - case 1 ... NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP: - local_irq_save(flags); - - grp = (i - 1) / NR_IRQ_ACTIONS_PER_GROUP; - group = irq_groups[grp]; - if (!group) - goto skip; - - ix = (i - 1) % NR_IRQ_ACTIONS_PER_GROUP; - action = group->actions[ix]; - if (!action) - goto skip; - - seq_printf(p, "%3d: ", i - 1); - -#ifndef CONFIG_SMP - seq_printf(p, "%10u ", kstat_irqs(i)); -#else - for (j = 0; j < NR_CPUS; j++) - if (cpu_online(j)) - seq_printf(p, "%10u ", kstat_cpu(j).irqs[i - 1]); -#endif - - level = group->sources[ix]->level - frv_irq_levels; - - seq_printf(p, " %12s@%x", group->sources[ix]->muxname, level); - seq_printf(p, " %s", action->name); - - for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - - seq_putc(p, '\n'); -skip: - local_irq_restore(flags); - break; - - case NR_IRQ_GROUPS * NR_IRQ_ACTIONS_PER_GROUP + 1: - seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); - break; - - default: - break; - } - + seq_printf(p, "%*s: ", prec, "ERR"); + seq_printf(p, "%10u\n", atomic_read(&irq_err_count)); return 0; } - /* - * Generic enable/disable code: this just calls - * down into the PIC-specific version for the actual - * hardware disable after having gotten the irq - * controller lock. - */ - -/** - * disable_irq_nosync - disable an irq without waiting - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Disables and Enables are - * nested. - * Unlike disable_irq(), this function does not ensure existing - * instances of the IRQ handler have completed before returning. - * - * This function may be called from IRQ context. + * on-CPU PIC operations */ - -void disable_irq_nosync(unsigned int irq) +static void frv_cpupic_ack(struct irq_data *d) { - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - unsigned long flags; - int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1); - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[idx]; - if (!source) - BUG(); - - level = source->level; - - spin_lock_irqsave(&level->lock, flags); - - if (group->control) { - if (!group->disable_cnt[idx]++) - group->control(group, idx, 0); - } else if (!level->disable_count++) { - __set_MASK(level - frv_irq_levels); - } - - spin_unlock_irqrestore(&level->lock, flags); + __clr_RC(d->irq); + __clr_IRL(); } -EXPORT_SYMBOL(disable_irq_nosync); - -/** - * disable_irq - disable an irq and wait for completion - * @irq: Interrupt to disable - * - * Disable the selected interrupt line. Enables and Disables are - * nested. - * This function waits for any pending IRQ handlers for this interrupt - * to complete before returning. If you use this function while - * holding a resource the IRQ handler may need you will deadlock. - * - * This function may be called - with care - from IRQ context. - */ - -void disable_irq(unsigned int irq) +static void frv_cpupic_mask(struct irq_data *d) { - disable_irq_nosync(irq); - -#ifdef CONFIG_SMP - if (!local_irq_count(smp_processor_id())) { - do { - barrier(); - } while (irq_desc[irq].status & IRQ_INPROGRESS); - } -#endif + __set_MASK(d->irq); } -EXPORT_SYMBOL(disable_irq); - -/** - * enable_irq - enable handling of an irq - * @irq: Interrupt to enable - * - * Undoes the effect of one call to disable_irq(). If this - * matches the last disable, processing of interrupts on this - * IRQ line is re-enabled. - * - * This function may be called from IRQ context. - */ - -void enable_irq(unsigned int irq) +static void frv_cpupic_mask_ack(struct irq_data *d) { - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - unsigned long flags; - int idx = irq & (NR_IRQ_ACTIONS_PER_GROUP - 1); - int count; - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[idx]; - if (!source) - BUG(); - - level = source->level; - - spin_lock_irqsave(&level->lock, flags); - - if (group->control) - count = group->disable_cnt[idx]; - else - count = level->disable_count; - - switch (count) { - case 1: - if (group->control) { - if (group->actions[idx]) - group->control(group, idx, 1); - } else { - if (level->usage) - __clr_MASK(level - frv_irq_levels); - } - /* fall-through */ - - default: - count--; - break; - - case 0: - printk("enable_irq(%u) unbalanced from %p\n", irq, __builtin_return_address(0)); - } - - if (group->control) - group->disable_cnt[idx] = count; - else - level->disable_count = count; + __set_MASK(d->irq); + __clr_RC(d->irq); + __clr_IRL(); +} - spin_unlock_irqrestore(&level->lock, flags); +static void frv_cpupic_unmask(struct irq_data *d) +{ + __clr_MASK(d->irq); } -EXPORT_SYMBOL(enable_irq); +static struct irq_chip frv_cpu_pic = { + .name = "cpu", + .irq_ack = frv_cpupic_ack, + .irq_mask = frv_cpupic_mask, + .irq_mask_ack = frv_cpupic_mask_ack, + .irq_unmask = frv_cpupic_unmask, +}; -/*****************************************************************************/ /* - * handles all normal device IRQ's + * handles all normal device IRQs * - registers are referred to by the __frame variable (GR28) * - IRQ distribution is complicated in this arch because of the many PICs, the * way they work and the way they cascade */ asmlinkage void do_IRQ(void) { - struct irq_source *source; - int level, cpu; - - level = (__frame->tbr >> 4) & 0xf; - cpu = smp_processor_id(); - -#if 0 - { - static u32 irqcount; - *(volatile u32 *) 0xe1200004 = ~((irqcount++ << 8) | level); - *(volatile u16 *) 0xffc00100 = (u16) ~0x9999; - mb(); - } -#endif - - if ((unsigned long) __frame - (unsigned long) (current + 1) < 512) - BUG(); - - __set_MASK(level); - __clr_RC(level); - __clr_IRL(); - - kstat_this_cpu.irqs[level]++; - irq_enter(); - - for (source = frv_irq_levels[level].sources; source; source = source->next) - source->doirq(source); - + generic_handle_irq(__get_IRL()); irq_exit(); +} - __clr_MASK(level); - - /* only process softirqs if we didn't interrupt another interrupt handler */ - if ((__frame->psr & PSR_PIL) == PSR_PIL_0) - if (local_softirq_pending()) - do_softirq(); - -#ifdef CONFIG_PREEMPT - local_irq_disable(); - while (--current->preempt_count == 0) { - if (!(__frame->psr & PSR_S) || - current->need_resched == 0 || - in_interrupt()) - break; - current->preempt_count++; - local_irq_enable(); - preempt_schedule(); - local_irq_disable(); - } -#endif - -#if 0 - { - *(volatile u16 *) 0xffc00100 = (u16) ~0x6666; - mb(); - } -#endif - -} /* end do_IRQ() */ - -/*****************************************************************************/ /* * handles all NMIs when not co-opted by the debugger * - registers are referred to by the __frame variable (GR28) */ asmlinkage void do_NMI(void) { -} /* end do_NMI() */ - -/*****************************************************************************/ -/** - * request_irq - allocate an interrupt line - * @irq: Interrupt line to allocate - * @handler: Function to be called when the IRQ occurs - * @irqflags: Interrupt type flags - * @devname: An ascii name for the claiming device - * @dev_id: A cookie passed back to the handler function - * - * This call allocates interrupt resources and enables the - * interrupt line and IRQ handling. From the point this - * call is made your handler function may be invoked. Since - * your handler function must clear any interrupt the board - * raises, you must take care both to initialise your hardware - * and to set up the interrupt handler in the right order. - * - * Dev_id must be globally unique. Normally the address of the - * device data structure is used as the cookie. Since the handler - * receives this value it makes sense to use it. - * - * If your interrupt is shared you must pass a non NULL dev_id - * as this is required when freeing the interrupt. - * - * Flags: - * - * SA_SHIRQ Interrupt is shared - * - * SA_INTERRUPT Disable local interrupts while processing - * - * SA_SAMPLE_RANDOM The interrupt can be used for entropy - * - */ - -int request_irq(unsigned int irq, - irqreturn_t (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - int retval; - struct irqaction *action; - -#if 1 - /* - * Sanity-check: shared interrupts should REALLY pass in - * a real dev-ID, otherwise we'll have trouble later trying - * to figure out which interrupt is which (messes up the - * interrupt freeing logic etc). - */ - if (irqflags & SA_SHIRQ) { - if (!dev_id) - printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", - devname, (&irq)[-1]); - } -#endif - - if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = CPU_MASK_NONE; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - return retval; } -EXPORT_SYMBOL(request_irq); - -/** - * free_irq - free an interrupt - * @irq: Interrupt line to free - * @dev_id: Device identity to free - * - * Remove an interrupt handler. The handler is removed and if the - * interrupt line is no longer in use by any driver it is disabled. - * On a shared IRQ the caller must ensure the interrupt is disabled - * on the card it drives before calling this function. The function - * does not return until any executing interrupts for this IRQ - * have completed. - * - * This function may be called from interrupt context. - * - * Bugs: Attempting to free an irq in a handler for the same irq hangs - * the machine. - */ - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - struct irqaction **p, **pp; - unsigned long flags; - - if ((irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP) >= NR_IRQ_GROUPS) - return; - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - if (!source) - BUG(); - - level = source->level; - p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - - spin_lock_irqsave(&level->lock, flags); - - for (pp = p; *pp; pp = &(*pp)->next) { - struct irqaction *action = *pp; - - if (action->dev_id != dev_id) - continue; - - /* found it - remove from the list of entries */ - *pp = action->next; - - level->usage--; - - if (p == pp && group->control) - group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 0); - - if (level->usage == 0) - __set_MASK(level - frv_irq_levels); - - spin_unlock_irqrestore(&level->lock,flags); - -#ifdef CONFIG_SMP - /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) - barrier(); -#endif - kfree(action); - return; - } -} - -EXPORT_SYMBOL(free_irq); - /* - * IRQ autodetection code.. - * - * This depends on the fact that any interrupt that comes in on to an - * unassigned IRQ will cause GxICR_DETECT to be set - */ - -static DECLARE_MUTEX(probe_sem); - -/** - * probe_irq_on - begin an interrupt autodetect - * - * Commence probing for an interrupt. The interrupts are scanned - * and a mask of potential interrupt lines is returned. - * - */ - -unsigned long probe_irq_on(void) -{ - down(&probe_sem); - return 0; -} - -EXPORT_SYMBOL(probe_irq_on); - -/* - * Return a mask of triggered interrupts (this - * can handle only legacy ISA interrupts). - */ - -/** - * probe_irq_mask - scan a bitmap of interrupt lines - * @val: mask of interrupts to consider - * - * Scan the ISA bus interrupt lines and return a bitmap of - * active interrupts. The interrupt probe logic state is then - * returned to its previous value. - * - * Note: we need to scan all the irq's even though we will - * only return ISA irq numbers - just so that we reset them - * all to a known state. - */ -unsigned int probe_irq_mask(unsigned long xmask) -{ - up(&probe_sem); - return 0; -} - -EXPORT_SYMBOL(probe_irq_mask); - -/* - * Return the one interrupt that triggered (this can - * handle any interrupt source). - */ - -/** - * probe_irq_off - end an interrupt autodetect - * @xmask: mask of potential interrupts (unused) - * - * Scans the unused interrupt lines and returns the line which - * appears to have triggered the interrupt. If no interrupt was - * found then zero is returned. If more than one interrupt is - * found then minus the first candidate is returned to indicate - * their is doubt. - * - * The interrupt probe logic state is returned to its previous - * value. - * - * BUGS: When used in a module (which arguably shouldnt happen) - * nothing prevents two IRQ probe callers from overlapping. The - * results of this are non-optimal. + * initialise the interrupt system */ - -int probe_irq_off(unsigned long xmask) -{ - up(&probe_sem); - return -1; -} - -EXPORT_SYMBOL(probe_irq_off); - -/* this was setup_x86_irq but it seems pretty generic */ -int setup_irq(unsigned int irq, struct irqaction *new) -{ - struct irq_source *source; - struct irq_group *group; - struct irq_level *level; - struct irqaction **p, **pp; - unsigned long flags; - - group = irq_groups[irq >> NR_IRQ_LOG2_ACTIONS_PER_GROUP]; - if (!group) - BUG(); - - source = group->sources[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - if (!source) - BUG(); - - level = source->level; - - p = &group->actions[irq & (NR_IRQ_ACTIONS_PER_GROUP - 1)]; - - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & SA_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } - - /* must juggle the interrupt processing stuff with interrupts disabled */ - spin_lock_irqsave(&level->lock, flags); - - /* can't share interrupts unless all parties agree to */ - if (level->usage != 0 && !(level->flags & new->flags & SA_SHIRQ)) { - spin_unlock_irqrestore(&level->lock,flags); - return -EBUSY; - } - - /* add new interrupt at end of irq queue */ - pp = p; - while (*pp) - pp = &(*pp)->next; - - *pp = new; - - level->usage++; - level->flags = new->flags; - - /* turn the interrupts on */ - if (level->usage == 1) - __clr_MASK(level - frv_irq_levels); - - if (p == pp && group->control) - group->control(group, irq & (NR_IRQ_ACTIONS_PER_GROUP - 1), 1); - - spin_unlock_irqrestore(&level->lock, flags); - register_irq_proc(irq); - return 0; -} - -static struct proc_dir_entry * root_irq_dir; -static struct proc_dir_entry * irq_dir [NR_IRQS]; - -#define HEX_DIGITS 8 - -static unsigned int parse_hex_value (const char *buffer, - unsigned long count, unsigned long *ret) -{ - unsigned char hexnum [HEX_DIGITS]; - unsigned long value; - int i; - - if (!count) - return -EINVAL; - if (count > HEX_DIGITS) - count = HEX_DIGITS; - if (copy_from_user(hexnum, buffer, count)) - return -EFAULT; - - /* - * Parse the first 8 characters as a hex string, any non-hex char - * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. - */ - value = 0; - - for (i = 0; i < count; i++) { - unsigned int c = hexnum[i]; - - switch (c) { - case '0' ... '9': c -= '0'; break; - case 'a' ... 'f': c -= 'a'-10; break; - case 'A' ... 'F': c -= 'A'-10; break; - default: - goto out; - } - value = (value << 4) | c; - } -out: - *ret = value; - return 0; -} - - -static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - unsigned long *mask = (unsigned long *) data; - if (count < HEX_DIGITS+1) - return -EINVAL; - return sprintf (page, "%08lx\n", *mask); -} - -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, - unsigned long count, void *data) -{ - unsigned long *mask = (unsigned long *) data, full_count = count, err; - unsigned long new_value; - - show_state(); - err = parse_hex_value(buffer, count, &new_value); - if (err) - return err; - - *mask = new_value; - return full_count; -} - -#define MAX_NAMELEN 10 - -static void register_irq_proc (unsigned int irq) -{ - char name [MAX_NAMELEN]; - - if (!root_irq_dir || irq_dir[irq]) - return; - - memset(name, 0, MAX_NAMELEN); - sprintf(name, "%d", irq); - - /* create /proc/irq/1234 */ - irq_dir[irq] = proc_mkdir(name, root_irq_dir); -} - -unsigned long prof_cpu_mask = -1; - -void init_irq_proc (void) +void __init init_IRQ(void) { - struct proc_dir_entry *entry; - int i; - - /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", 0); + int level; - /* create /proc/irq/prof_cpu_mask */ - entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); - if (!entry) - return; + for (level = 1; level <= 14; level++) + irq_set_chip_and_handler(level, &frv_cpu_pic, + handle_level_irq); - entry->nlink = 1; - entry->data = (void *)&prof_cpu_mask; - entry->read_proc = prof_cpu_mask_read_proc; - entry->write_proc = prof_cpu_mask_write_proc; + irq_set_handler(IRQ_CPU_TIMER0, handle_edge_irq); - /* - * Create entries for all existing IRQs. + /* set the trigger levels for internal interrupt sources + * - timers all falling-edge + * - ERR0 is rising-edge + * - all others are high-level */ - for (i = 0; i < NR_IRQS; i++) - register_irq_proc(i); -} + __set_IITMR(0, 0x003f0000); /* DMA0-3, TIMER0-2 */ + __set_IITMR(1, 0x20000000); /* ERR0-1, UART0-1, DMA4-7 */ + + /* route internal interrupts */ + set_IRR(4, IRQ_DMA3_LEVEL, IRQ_DMA2_LEVEL, IRQ_DMA1_LEVEL, + IRQ_DMA0_LEVEL); + set_IRR(5, 0, IRQ_TIMER2_LEVEL, IRQ_TIMER1_LEVEL, IRQ_TIMER0_LEVEL); + set_IRR(6, IRQ_GDBSTUB_LEVEL, IRQ_GDBSTUB_LEVEL, + IRQ_UART1_LEVEL, IRQ_UART0_LEVEL); + set_IRR(7, IRQ_DMA7_LEVEL, IRQ_DMA6_LEVEL, IRQ_DMA5_LEVEL, + IRQ_DMA4_LEVEL); + + /* route external interrupts */ + set_IRR(2, IRQ_XIRQ7_LEVEL, IRQ_XIRQ6_LEVEL, IRQ_XIRQ5_LEVEL, + IRQ_XIRQ4_LEVEL); + set_IRR(3, IRQ_XIRQ3_LEVEL, IRQ_XIRQ2_LEVEL, IRQ_XIRQ1_LEVEL, + IRQ_XIRQ0_LEVEL); + +#if defined(CONFIG_MB93091_VDK) + __set_TM1(0x55550000); /* XIRQ7-0 all active low */ +#elif defined(CONFIG_MB93093_PDK) + __set_TM1(0x15550000); /* XIRQ7 active high, 6-0 all active low */ +#else +#error dont know external IRQ trigger levels for this setup +#endif -/*****************************************************************************/ -/* - * initialise the interrupt system - */ -void __init init_IRQ(void) -{ - route_cpu_irqs(); fpga_init(); #ifdef CONFIG_FUJITSU_MB93493 - route_mb93493_irqs(); + mb93493_init(); #endif -} /* end init_IRQ() */ +} diff --git a/arch/frv/kernel/kernel_thread.S b/arch/frv/kernel/kernel_thread.S deleted file mode 100644 index 4531c830d20..00000000000 --- a/arch/frv/kernel/kernel_thread.S +++ /dev/null @@ -1,77 +0,0 @@ -/* kernel_thread.S: kernel thread creation - * - * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/linkage.h> -#include <asm/unistd.h> - -#define CLONE_VM 0x00000100 /* set if VM shared between processes */ -#define KERN_ERR "<3>" - - .section .rodata -kernel_thread_emsg: - .asciz KERN_ERR "failed to create kernel thread: error=%d\n" - - .text - .balign 4 - -############################################################################### -# -# Create a kernel thread -# -# int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -# -############################################################################### - .globl kernel_thread - .type kernel_thread,@function -kernel_thread: - or.p gr8,gr0,gr4 - or gr9,gr0,gr5 - - # start by forking the current process, but with shared VM - setlos.p #__NR_clone,gr7 ; syscall number - ori gr10,#CLONE_VM,gr8 ; first syscall arg [clone_flags] - sethi.p #0xe4e4,gr9 ; second syscall arg [newsp] - setlo #0xe4e4,gr9 - setlos.p #0,gr10 ; third syscall arg [parent_tidptr] - setlos #0,gr11 ; fourth syscall arg [child_tidptr] - tira gr0,#0 - setlos.p #4095,gr7 - andcc gr8,gr8,gr0,icc0 - addcc.p gr8,gr7,gr0,icc1 - bnelr icc0,#2 - bc icc1,#0,kernel_thread_error - - # now invoke the work function - or gr5,gr0,gr8 - calll @(gr4,gr0) - - # and finally exit the thread - setlos #__NR_exit,gr7 ; syscall number - tira gr0,#0 - -kernel_thread_error: - subi sp,#8,sp - movsg lr,gr4 - sti gr8,@(sp,#0) - sti.p gr4,@(sp,#4) - - or gr8,gr0,gr9 - sethi.p %hi(kernel_thread_emsg),gr8 - setlo %lo(kernel_thread_emsg),gr8 - - call printk - - ldi @(sp,#4),gr4 - ldi @(sp,#0),gr8 - subi sp,#8,sp - jmpl @(gr4,gr0) - - .size kernel_thread,.-kernel_thread diff --git a/arch/frv/kernel/local.h b/arch/frv/kernel/local.h index e9471761d78..76606d13b1a 100644 --- a/arch/frv/kernel/local.h +++ b/arch/frv/kernel/local.h @@ -51,6 +51,9 @@ extern void (*__power_switch_wake_cleanup)(void); /* time.c */ extern void time_divisor_init(void); +/* cmode.S */ +extern asmlinkage void frv_change_cmode(int); + #endif /* __ASSEMBLY__ */ #endif /* _FRV_LOCAL_H */ diff --git a/arch/frv/kernel/local64.h b/arch/frv/kernel/local64.h new file mode 100644 index 00000000000..36c93b5cc23 --- /dev/null +++ b/arch/frv/kernel/local64.h @@ -0,0 +1 @@ +#include <asm-generic/local64.h> diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c index 850d168f69f..9d9835f1fe2 100644 --- a/arch/frv/kernel/module.c +++ b/arch/frv/kernel/module.c @@ -22,59 +22,6 @@ #define DEBUGP(fmt...) #endif -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - - return vmalloc_exec(size); -} - - -/* Free memory returned from module_alloc */ -void module_free(struct module *mod, void *module_region) -{ - vfree(module_region); - /* FIXME: If module_region == mod->init_region, trim exception - table entries. */ -} - -/* We don't need anything special. */ -int module_frob_arch_sections(Elf_Ehdr *hdr, - Elf_Shdr *sechdrs, - char *secstrings, - struct module *mod) -{ - return 0; -} - -int apply_relocate(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name); - return -ENOEXEC; -} - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", me->name); - return -ENOEXEC; -} - -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) -{ - return 0; -} - -void module_arch_cleanup(struct module *mod) -{ -} +/* TODO: At least one of apply_relocate or apply_relocate_add must be + * implemented in order to get working module support. + */ diff --git a/arch/frv/kernel/pm-mb93093.c b/arch/frv/kernel/pm-mb93093.c index 34d01d7dcc3..eaa7b582ef5 100644 --- a/arch/frv/kernel/pm-mb93093.c +++ b/arch/frv/kernel/pm-mb93093.c @@ -10,7 +10,6 @@ * */ -#include <linux/config.h> #include <linux/init.h> #include <linux/pm.h> #include <linux/sched.h> diff --git a/arch/frv/kernel/pm.c b/arch/frv/kernel/pm.c index f0b8fff3e73..ac767d94a88 100644 --- a/arch/frv/kernel/pm.c +++ b/arch/frv/kernel/pm.c @@ -11,11 +11,9 @@ * */ -#include <linux/config.h> #include <linux/init.h> #include <linux/module.h> #include <linux/pm.h> -#include <linux/pm_legacy.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/sysctl.h> @@ -27,11 +25,6 @@ #include "local.h" -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -extern void frv_change_cmode(int); - /* * Debug macros */ @@ -131,13 +124,12 @@ unsigned long sleep_phys_sp(void *sp) * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6 * when all the PM interfaces exist nicely. */ -#define CTL_PM 9899 #define CTL_PM_SUSPEND 1 #define CTL_PM_CMODE 2 #define CTL_PM_P0 4 #define CTL_PM_CM 5 -static int user_atoi(char *ubuf, size_t len) +static int user_atoi(char __user *ubuf, size_t len) { char buf[16]; unsigned long ret; @@ -158,29 +150,25 @@ static int user_atoi(char *ubuf, size_t len) /* * Send us to sleep. */ -static int sysctl_pm_do_suspend(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) +static int sysctl_pm_do_suspend(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *fpos) { - int retval, mode; + int mode; if (*lenp <= 0) return -EIO; mode = user_atoi(buffer, *lenp); - if ((mode != 1) && (mode != 5)) - return -EINVAL; + switch (mode) { + case 1: + return pm_do_suspend(); - retval = pm_send_all(PM_SUSPEND, (void *)3); + case 5: + return pm_do_bus_sleep(); - if (retval == 0) { - if (mode == 5) - retval = pm_do_bus_sleep(); - else - retval = pm_do_suspend(); - pm_send_all(PM_RESUME, (void *)0); + default: + return -EINVAL; } - - return retval; } static int try_set_cmode(int new_cmode) @@ -190,9 +178,6 @@ static int try_set_cmode(int new_cmode) if (!(clock_cmodes_permitted & (1<<new_cmode))) return -EINVAL; - /* tell all the drivers we're suspending */ - pm_send_all(PM_SUSPEND, (void *)3); - /* now change cmode */ local_irq_disable(); frv_dma_pause_all(); @@ -208,56 +193,23 @@ static int try_set_cmode(int new_cmode) frv_dma_resume_all(); local_irq_enable(); - /* tell all the drivers we're resuming */ - pm_send_all(PM_RESUME, (void *)0); return 0; } -static int cmode_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) +static int cmode_procctl(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_cmode; if (!write) - return proc_dointvec(ctl, write, filp, buffer, lenp, fpos); + return proc_dointvec(ctl, write, buffer, lenp, fpos); new_cmode = user_atoi(buffer, *lenp); return try_set_cmode(new_cmode)?:*lenp; } -static int cmode_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) -{ - if (oldval && oldlenp) { - size_t oldlen; - - if (get_user(oldlen, oldlenp)) - return -EFAULT; - - if (oldlen != sizeof(int)) - return -EINVAL; - - if (put_user(clock_cmode_current, (unsigned int *)oldval) || - put_user(sizeof(int), oldlenp)) - return -EFAULT; - } - if (newval && newlen) { - int new_cmode; - - if (newlen != sizeof(int)) - return -EINVAL; - - if (get_user(new_cmode, (int *)newval)) - return -EFAULT; - - return try_set_cmode(new_cmode)?:1; - } - return 1; -} - static int try_set_p0(int new_p0) { unsigned long flags, clkc; @@ -317,108 +269,73 @@ static int try_set_cm(int new_cm) return 0; } -static int p0_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) +static int p0_procctl(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_p0; if (!write) - return proc_dointvec(ctl, write, filp, buffer, lenp, fpos); + return proc_dointvec(ctl, write, buffer, lenp, fpos); new_p0 = user_atoi(buffer, *lenp); return try_set_p0(new_p0)?:*lenp; } -static int p0_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) -{ - if (oldval && oldlenp) { - size_t oldlen; - - if (get_user(oldlen, oldlenp)) - return -EFAULT; - - if (oldlen != sizeof(int)) - return -EINVAL; - - if (put_user(clock_p0_current, (unsigned int *)oldval) || - put_user(sizeof(int), oldlenp)) - return -EFAULT; - } - if (newval && newlen) { - int new_p0; - - if (newlen != sizeof(int)) - return -EINVAL; - - if (get_user(new_p0, (int *)newval)) - return -EFAULT; - - return try_set_p0(new_p0)?:1; - } - return 1; -} - -static int cm_procctl(ctl_table *ctl, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *fpos) +static int cm_procctl(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, loff_t *fpos) { int new_cm; if (!write) - return proc_dointvec(ctl, write, filp, buffer, lenp, fpos); + return proc_dointvec(ctl, write, buffer, lenp, fpos); new_cm = user_atoi(buffer, *lenp); return try_set_cm(new_cm)?:*lenp; } -static int cm_sysctl(ctl_table *table, int *name, int nlen, - void *oldval, size_t *oldlenp, - void *newval, size_t newlen, void **context) -{ - if (oldval && oldlenp) { - size_t oldlen; - - if (get_user(oldlen, oldlenp)) - return -EFAULT; - - if (oldlen != sizeof(int)) - return -EINVAL; - - if (put_user(clock_cm_current, (unsigned int *)oldval) || - put_user(sizeof(int), oldlenp)) - return -EFAULT; - } - if (newval && newlen) { - int new_cm; - - if (newlen != sizeof(int)) - return -EINVAL; - - if (get_user(new_cm, (int *)newval)) - return -EFAULT; - - return try_set_cm(new_cm)?:1; - } - return 1; -} - - static struct ctl_table pm_table[] = { - {CTL_PM_SUSPEND, "suspend", NULL, 0, 0200, NULL, &sysctl_pm_do_suspend}, - {CTL_PM_CMODE, "cmode", &clock_cmode_current, sizeof(int), 0644, NULL, &cmode_procctl, &cmode_sysctl, NULL}, - {CTL_PM_P0, "p0", &clock_p0_current, sizeof(int), 0644, NULL, &p0_procctl, &p0_sysctl, NULL}, - {CTL_PM_CM, "cm", &clock_cm_current, sizeof(int), 0644, NULL, &cm_procctl, &cm_sysctl, NULL}, - {0} + { + .procname = "suspend", + .data = NULL, + .maxlen = 0, + .mode = 0200, + .proc_handler = sysctl_pm_do_suspend, + }, + { + .procname = "cmode", + .data = &clock_cmode_current, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = cmode_procctl, + }, + { + .procname = "p0", + .data = &clock_p0_current, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = p0_procctl, + }, + { + .procname = "cm", + .data = &clock_cm_current, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = cm_procctl, + }, + { } }; static struct ctl_table pm_dir_table[] = { - {CTL_PM, "pm", NULL, 0, 0555, pm_table}, - {0} + { + .procname = "pm", + .mode = 0555, + .child = pm_table, + }, + { } }; /* @@ -426,7 +343,7 @@ static struct ctl_table pm_dir_table[] = */ static int __init pm_init(void) { - register_sysctl_table(pm_dir_table, 1); + register_sysctl_table(pm_dir_table); return 0; } diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 0fff8a61ef2..5d40aeb7712 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -10,13 +10,12 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> +#include <linux/module.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/stddef.h> #include <linux/unistd.h> #include <linux/ptrace.h> @@ -25,33 +24,26 @@ #include <linux/elf.h> #include <linux/reboot.h> #include <linux/interrupt.h> +#include <linux/pagemap.h> +#include <linux/rcupdate.h> +#include <asm/asm-offsets.h> #include <asm/uaccess.h> -#include <asm/system.h> #include <asm/setup.h> #include <asm/pgtable.h> +#include <asm/tlb.h> #include <asm/gdb-stub.h> #include <asm/mb-regs.h> #include "local.h" asmlinkage void ret_from_fork(void); +asmlinkage void ret_from_kernel_thread(void); #include <asm/pgalloc.h> -struct task_struct *alloc_task_struct(void) -{ - struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL); - if (p) - atomic_set((atomic_t *)(p+1), 1); - return p; -} - -void free_task_struct(struct task_struct *p) -{ - if (atomic_dec_and_test((atomic_t *)(p+1))) - kfree(p); -} +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); static void core_sleep_idle(void) { @@ -67,31 +59,12 @@ static void core_sleep_idle(void) mb(); } -void (*idle)(void) = core_sleep_idle; - -/* - * The idle thread. There's no useful work to be - * done, so just try to conserve power and have a - * low exit latency (ie sit in a loop waiting for - * somebody to say that they'd like to reschedule) - */ -void cpu_idle(void) +void arch_cpu_idle(void) { - int cpu = smp_processor_id(); - - /* endless idle loop with no priority at all */ - while (1) { - while (!need_resched()) { - irq_stat[cpu].idle_timestamp = jiffies; - - if (!frv_dma_inprogress && idle) - idle(); - } - - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } + if (!frv_dma_inprogress) + core_sleep_idle(); + else + local_irq_enable(); } void machine_restart(char * __unused) @@ -139,10 +112,7 @@ void machine_power_off(void) void flush_thread(void) { -#if 0 //ndef NO_FPU - unsigned long zero = 0; -#endif - set_fs(USER_DS); + /* nothing */ } inline unsigned long user_stack(const struct pt_regs *regs) @@ -152,87 +122,40 @@ inline unsigned long user_stack(const struct pt_regs *regs) return user_mode(regs) ? regs->sp : 0; } -asmlinkage int sys_fork(void) -{ -#ifndef CONFIG_MMU - /* fork almost works, enough to trick you into looking elsewhere:-( */ - return -EINVAL; -#else - return do_fork(SIGCHLD, user_stack(__frame), __frame, 0, NULL, NULL); -#endif -} - -asmlinkage int sys_vfork(void) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, user_stack(__frame), __frame, 0, - NULL, NULL); -} - -/*****************************************************************************/ -/* - * clone a process - * - tlsptr is retrieved by copy_thread() - */ -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, - int __user *parent_tidptr, int __user *child_tidptr, - int __user *tlsptr) -{ - if (!newsp) - newsp = user_stack(__frame); - return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr); -} /* end sys_clone() */ - -/*****************************************************************************/ -/* - * This gets called before we allocate a new thread and copy - * the current task into it. - */ -void prepare_to_copy(struct task_struct *tsk) -{ - //unlazy_fpu(tsk); -} /* end prepare_to_copy() */ - -/*****************************************************************************/ /* * set up the kernel stack and exception frames for a new process */ -int copy_thread(int nr, unsigned long clone_flags, - unsigned long usp, unsigned long topstk, - struct task_struct *p, struct pt_regs *regs) +int copy_thread(unsigned long clone_flags, + unsigned long usp, unsigned long arg, + struct task_struct *p) { - struct pt_regs *childregs0, *childregs, *regs0; + struct pt_regs *childregs; - regs0 = __kernel_frame0_ptr; - childregs0 = (struct pt_regs *) - (task_stack_page(p) + THREAD_SIZE - USER_CONTEXT_SIZE); - childregs = childregs0; + childregs = (struct pt_regs *) + (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); /* set up the userspace frame (the only place that the USP is stored) */ - *childregs0 = *regs0; - - childregs0->gr8 = 0; - childregs0->sp = usp; - childregs0->next_frame = NULL; - - /* set up the return kernel frame if called from kernel_thread() */ - if (regs != regs0) { - childregs--; - *childregs = *regs; - childregs->sp = (unsigned long) childregs0; - childregs->next_frame = childregs0; - childregs->gr15 = (unsigned long) task_thread_info(p); - childregs->gr29 = (unsigned long) p; - } - - p->set_child_tid = p->clear_child_tid = NULL; + *childregs = *current_pt_regs(); p->thread.frame = childregs; p->thread.curr = p; p->thread.sp = (unsigned long) childregs; p->thread.fp = 0; p->thread.lr = 0; - p->thread.pc = (unsigned long) ret_from_fork; - p->thread.frame0 = childregs0; + p->thread.frame0 = childregs; + + if (unlikely(p->flags & PF_KTHREAD)) { + childregs->gr9 = usp; /* function */ + childregs->gr8 = arg; + p->thread.pc = (unsigned long) ret_from_kernel_thread; + save_user_regs(p->thread.user); + return 0; + } + if (usp) + childregs->sp = usp; + childregs->next_frame = NULL; + + p->thread.pc = (unsigned long) ret_from_fork; /* the new TLS pointer is passed in as arg #5 to sys_clone() */ if (clone_flags & CLONE_SETTLS) @@ -243,26 +166,6 @@ int copy_thread(int nr, unsigned long clone_flags, return 0; } /* end copy_thread() */ -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(char *name, char **argv, char **envp) -{ - int error; - char * filename; - - lock_kernel(); - filename = getname(name); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - error = do_execve(filename, argv, envp, __frame); - putname(filename); - out: - unlock_kernel(); - return error; -} - unsigned long get_wchan(struct task_struct *p) { struct pt_regs *regs0; @@ -368,3 +271,11 @@ int elf_check_arch(const struct elf32_hdr *hdr) return 1; } + +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs) +{ + memcpy(fpregs, + ¤t->thread.user->f, + sizeof(current->thread.user->f)); + return 1; +} diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index f953484e7d5..3987ff88dab 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -14,18 +14,18 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/errno.h> #include <linux/ptrace.h> #include <linux/user.h> -#include <linux/config.h> #include <linux/security.h> #include <linux/signal.h> +#include <linux/regset.h> +#include <linux/elf.h> +#include <linux/tracehook.h> #include <asm/uaccess.h> #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/processor.h> #include <asm/unistd.h> @@ -35,6 +35,169 @@ */ /* + * retrieve the contents of FRV userspace general registers + */ +static int genregs_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + const struct user_int_regs *iregs = &target->thread.user->i; + int ret; + + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, + iregs, 0, sizeof(*iregs)); + if (ret < 0) + return ret; + + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, + sizeof(*iregs), -1); +} + +/* + * update the contents of the FRV userspace general registers + */ +static int genregs_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + struct user_int_regs *iregs = &target->thread.user->i; + unsigned int offs_gr0, offs_gr1; + int ret; + + /* not allowed to set PSR or __status */ + if (pos < offsetof(struct user_int_regs, psr) + sizeof(long) && + pos + count > offsetof(struct user_int_regs, psr)) + return -EIO; + + if (pos < offsetof(struct user_int_regs, __status) + sizeof(long) && + pos + count > offsetof(struct user_int_regs, __status)) + return -EIO; + + /* set the control regs */ + offs_gr0 = offsetof(struct user_int_regs, gr[0]); + offs_gr1 = offsetof(struct user_int_regs, gr[1]); + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + iregs, 0, offs_gr0); + if (ret < 0) + return ret; + + /* skip GR0/TBR */ + ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, + offs_gr0, offs_gr1); + if (ret < 0) + return ret; + + /* set the general regs */ + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + &iregs->gr[1], offs_gr1, sizeof(*iregs)); + if (ret < 0) + return ret; + + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, + sizeof(*iregs), -1); +} + +/* + * retrieve the contents of FRV userspace FP/Media registers + */ +static int fpmregs_get(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) +{ + const struct user_fpmedia_regs *fpregs = &target->thread.user->f; + int ret; + + ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, + fpregs, 0, sizeof(*fpregs)); + if (ret < 0) + return ret; + + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, + sizeof(*fpregs), -1); +} + +/* + * update the contents of the FRV userspace FP/Media registers + */ +static int fpmregs_set(struct task_struct *target, + const struct user_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) +{ + struct user_fpmedia_regs *fpregs = &target->thread.user->f; + int ret; + + ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, + fpregs, 0, sizeof(*fpregs)); + if (ret < 0) + return ret; + + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, + sizeof(*fpregs), -1); +} + +/* + * determine if the FP/Media registers have actually been used + */ +static int fpmregs_active(struct task_struct *target, + const struct user_regset *regset) +{ + return tsk_used_math(target) ? regset->n : 0; +} + +/* + * Define the register sets available on the FRV under Linux + */ +enum frv_regset { + REGSET_GENERAL, + REGSET_FPMEDIA, +}; + +static const struct user_regset frv_regsets[] = { + /* + * General register format is: + * PSR, ISR, CCR, CCCR, LR, LCR, PC, (STATUS), SYSCALLNO, ORIG_G8 + * GNER0-1, IACC0, TBR, GR1-63 + */ + [REGSET_GENERAL] = { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(long), + .align = sizeof(long), + .get = genregs_get, + .set = genregs_set, + }, + /* + * FPU/Media register format is: + * FR0-63, FNER0-1, MSR0-1, ACC0-7, ACCG0-8, FSR + */ + [REGSET_FPMEDIA] = { + .core_note_type = NT_PRFPREG, + .n = sizeof(struct user_fpmedia_regs) / sizeof(long), + .size = sizeof(long), + .align = sizeof(long), + .get = fpmregs_get, + .set = fpmregs_set, + .active = fpmregs_active, + }, +}; + +static const struct user_regset_view user_frv_native_view = { + .name = "frv", + .e_machine = EM_FRV, + .regsets = frv_regsets, + .n = ARRAY_SIZE(frv_regsets), +}; + +const struct user_regset_view *task_user_regset_view(struct task_struct *task) +{ + return &user_frv_native_view; +} + +/* * Get contents of register REGNO in task TASK. */ static inline long get_reg(struct task_struct *task, int regno) @@ -71,75 +234,45 @@ static inline int put_reg(struct task_struct *task, int regno, } /* - * check that an address falls within the bounds of the target process's memory mappings - */ -static inline int is_user_addr_valid(struct task_struct *child, - unsigned long start, unsigned long len) -{ -#ifdef CONFIG_MMU - if (start >= PAGE_OFFSET || len > PAGE_OFFSET - start) - return -EIO; - return 0; -#else - struct vm_list_struct *vml; - - for (vml = child->mm->context.vmlist; vml; vml = vml->next) - if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end) - return 0; - - return -EIO; -#endif -} - -/* * Called by kernel/ptrace.c when detaching.. * * Control h/w single stepping */ -void ptrace_disable(struct task_struct *child) +void user_enable_single_step(struct task_struct *child) +{ + child->thread.frame0->__status |= REG__STATUS_STEP; +} + +void user_disable_single_step(struct task_struct *child) { child->thread.frame0->__status &= ~REG__STATUS_STEP; } -void ptrace_enable(struct task_struct *child) +void ptrace_disable(struct task_struct *child) { - child->thread.frame0->__status |= REG__STATUS_STEP; + user_disable_single_step(child); } -long arch_ptrace(struct task_struct *child, long request, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data) { unsigned long tmp; int ret; + int regno = addr >> 2; + unsigned long __user *datap = (unsigned long __user *) data; switch (request) { - /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - int copied; - - ret = -EIO; - if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) - break; - - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - break; - - ret = put_user(tmp,(unsigned long *) data); - break; - } - /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { tmp = 0; ret = -EIO; - if ((addr & 3) || addr < 0) + if (addr & 3) break; ret = 0; - switch (addr >> 2) { + switch (regno) { case 0 ... PT__END - 1: - tmp = get_reg(child, addr >> 2); + tmp = get_reg(child, regno); break; case PT__END + 0: @@ -168,557 +301,77 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } if (ret == 0) - ret = put_user(tmp, (unsigned long *) data); + ret = put_user(tmp, datap); break; } - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - ret = -EIO; - if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) - break; - if (access_process_vm(child, addr, &data, sizeof(data), 1) != sizeof(data)) - break; - ret = 0; - break; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 3) || addr < 0) - break; - - ret = 0; - switch (addr >> 2) { - case 0 ... PT__END-1: - ret = put_reg(child, addr >> 2, data); - break; - - default: - ret = -EIO; - break; - } - break; - - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: /* restart after signal. */ - ret = -EIO; - if (!valid_signal(data)) - break; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - ptrace_disable(child); - wake_up_process(child); - ret = 0; - break; - - /* make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - case PTRACE_KILL: - ret = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ + if (addr & 3) break; - child->exit_code = SIGKILL; - clear_tsk_thread_flag(child, TIF_SINGLESTEP); - ptrace_disable(child); - wake_up_process(child); - break; - case PTRACE_SINGLESTEP: /* set the trap flag. */ - ret = -EIO; - if (!valid_signal(data)) + switch (regno) { + case 0 ... PT__END - 1: + ret = put_reg(child, regno, data); break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - ptrace_enable(child); - child->exit_code = data; - wake_up_process(child); - ret = 0; - break; - - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - - case PTRACE_GETREGS: { /* Get all integer regs from the child. */ - int i; - for (i = 0; i < PT__GPEND; i++) { - tmp = get_reg(child, i); - if (put_user(tmp, (unsigned long *) data)) { - ret = -EFAULT; - break; - } - data += sizeof(long); - } - ret = 0; - break; - } - - case PTRACE_SETREGS: { /* Set all integer regs in the child. */ - int i; - for (i = 0; i < PT__GPEND; i++) { - if (get_user(tmp, (unsigned long *) data)) { - ret = -EFAULT; - break; - } - put_reg(child, i, tmp); - data += sizeof(long); } - ret = 0; - break; - } - - case PTRACE_GETFPREGS: { /* Get the child FP/Media state. */ - ret = 0; - if (copy_to_user((void *) data, - &child->thread.user->f, - sizeof(child->thread.user->f))) - ret = -EFAULT; - break; - } - - case PTRACE_SETFPREGS: { /* Set the child FP/Media state. */ - ret = 0; - if (copy_from_user(&child->thread.user->f, - (void *) data, - sizeof(child->thread.user->f))) - ret = -EFAULT; break; - } - - case PTRACE_GETFDPIC: - tmp = 0; - switch (addr) { - case PTRACE_GETFDPIC_EXEC: - tmp = child->mm->context.exec_fdpic_loadmap; - break; - case PTRACE_GETFDPIC_INTERP: - tmp = child->mm->context.interp_fdpic_loadmap; - break; - default: - break; - } - ret = 0; - if (put_user(tmp, (unsigned long *) data)) { - ret = -EFAULT; - break; - } - break; + case PTRACE_GETREGS: /* Get all integer regs from the child. */ + return copy_regset_to_user(child, &user_frv_native_view, + REGSET_GENERAL, + 0, sizeof(child->thread.user->i), + datap); + + case PTRACE_SETREGS: /* Set all integer regs in the child. */ + return copy_regset_from_user(child, &user_frv_native_view, + REGSET_GENERAL, + 0, sizeof(child->thread.user->i), + datap); + + case PTRACE_GETFPREGS: /* Get the child FP/Media state. */ + return copy_regset_to_user(child, &user_frv_native_view, + REGSET_FPMEDIA, + 0, sizeof(child->thread.user->f), + datap); + + case PTRACE_SETFPREGS: /* Set the child FP/Media state. */ + return copy_regset_from_user(child, &user_frv_native_view, + REGSET_FPMEDIA, + 0, sizeof(child->thread.user->f), + datap); default: - ret = -EIO; + ret = ptrace_request(child, request, addr, data); break; } return ret; } -int __nongprelbss kstrace; - -static const struct { - const char *name; - unsigned argmask; -} __syscall_name_table[NR_syscalls] = { - [0] = { "restart_syscall" }, - [1] = { "exit", 0x000001 }, - [2] = { "fork", 0xffffff }, - [3] = { "read", 0x000141 }, - [4] = { "write", 0x000141 }, - [5] = { "open", 0x000235 }, - [6] = { "close", 0x000001 }, - [7] = { "waitpid", 0x000141 }, - [8] = { "creat", 0x000025 }, - [9] = { "link", 0x000055 }, - [10] = { "unlink", 0x000005 }, - [11] = { "execve", 0x000445 }, - [12] = { "chdir", 0x000005 }, - [13] = { "time", 0x000004 }, - [14] = { "mknod", 0x000325 }, - [15] = { "chmod", 0x000025 }, - [16] = { "lchown", 0x000025 }, - [17] = { "break" }, - [18] = { "oldstat", 0x000045 }, - [19] = { "lseek", 0x000131 }, - [20] = { "getpid", 0xffffff }, - [21] = { "mount", 0x043555 }, - [22] = { "umount", 0x000005 }, - [23] = { "setuid", 0x000001 }, - [24] = { "getuid", 0xffffff }, - [25] = { "stime", 0x000004 }, - [26] = { "ptrace", 0x004413 }, - [27] = { "alarm", 0x000001 }, - [28] = { "oldfstat", 0x000041 }, - [29] = { "pause", 0xffffff }, - [30] = { "utime", 0x000045 }, - [31] = { "stty" }, - [32] = { "gtty" }, - [33] = { "access", 0x000025 }, - [34] = { "nice", 0x000001 }, - [35] = { "ftime" }, - [36] = { "sync", 0xffffff }, - [37] = { "kill", 0x000011 }, - [38] = { "rename", 0x000055 }, - [39] = { "mkdir", 0x000025 }, - [40] = { "rmdir", 0x000005 }, - [41] = { "dup", 0x000001 }, - [42] = { "pipe", 0x000004 }, - [43] = { "times", 0x000004 }, - [44] = { "prof" }, - [45] = { "brk", 0x000004 }, - [46] = { "setgid", 0x000001 }, - [47] = { "getgid", 0xffffff }, - [48] = { "signal", 0x000041 }, - [49] = { "geteuid", 0xffffff }, - [50] = { "getegid", 0xffffff }, - [51] = { "acct", 0x000005 }, - [52] = { "umount2", 0x000035 }, - [53] = { "lock" }, - [54] = { "ioctl", 0x000331 }, - [55] = { "fcntl", 0x000331 }, - [56] = { "mpx" }, - [57] = { "setpgid", 0x000011 }, - [58] = { "ulimit" }, - [60] = { "umask", 0x000002 }, - [61] = { "chroot", 0x000005 }, - [62] = { "ustat", 0x000043 }, - [63] = { "dup2", 0x000011 }, - [64] = { "getppid", 0xffffff }, - [65] = { "getpgrp", 0xffffff }, - [66] = { "setsid", 0xffffff }, - [67] = { "sigaction" }, - [68] = { "sgetmask" }, - [69] = { "ssetmask" }, - [70] = { "setreuid" }, - [71] = { "setregid" }, - [72] = { "sigsuspend" }, - [73] = { "sigpending" }, - [74] = { "sethostname" }, - [75] = { "setrlimit" }, - [76] = { "getrlimit" }, - [77] = { "getrusage" }, - [78] = { "gettimeofday" }, - [79] = { "settimeofday" }, - [80] = { "getgroups" }, - [81] = { "setgroups" }, - [82] = { "select" }, - [83] = { "symlink" }, - [84] = { "oldlstat" }, - [85] = { "readlink" }, - [86] = { "uselib" }, - [87] = { "swapon" }, - [88] = { "reboot" }, - [89] = { "readdir" }, - [91] = { "munmap", 0x000034 }, - [92] = { "truncate" }, - [93] = { "ftruncate" }, - [94] = { "fchmod" }, - [95] = { "fchown" }, - [96] = { "getpriority" }, - [97] = { "setpriority" }, - [99] = { "statfs" }, - [100] = { "fstatfs" }, - [102] = { "socketcall" }, - [103] = { "syslog" }, - [104] = { "setitimer" }, - [105] = { "getitimer" }, - [106] = { "stat" }, - [107] = { "lstat" }, - [108] = { "fstat" }, - [111] = { "vhangup" }, - [114] = { "wait4" }, - [115] = { "swapoff" }, - [116] = { "sysinfo" }, - [117] = { "ipc" }, - [118] = { "fsync" }, - [119] = { "sigreturn" }, - [120] = { "clone" }, - [121] = { "setdomainname" }, - [122] = { "uname" }, - [123] = { "modify_ldt" }, - [123] = { "cacheflush" }, - [124] = { "adjtimex" }, - [125] = { "mprotect" }, - [126] = { "sigprocmask" }, - [127] = { "create_module" }, - [128] = { "init_module" }, - [129] = { "delete_module" }, - [130] = { "get_kernel_syms" }, - [131] = { "quotactl" }, - [132] = { "getpgid" }, - [133] = { "fchdir" }, - [134] = { "bdflush" }, - [135] = { "sysfs" }, - [136] = { "personality" }, - [137] = { "afs_syscall" }, - [138] = { "setfsuid" }, - [139] = { "setfsgid" }, - [140] = { "_llseek", 0x014331 }, - [141] = { "getdents" }, - [142] = { "_newselect", 0x000141 }, - [143] = { "flock" }, - [144] = { "msync" }, - [145] = { "readv" }, - [146] = { "writev" }, - [147] = { "getsid", 0x000001 }, - [148] = { "fdatasync", 0x000001 }, - [149] = { "_sysctl", 0x000004 }, - [150] = { "mlock" }, - [151] = { "munlock" }, - [152] = { "mlockall" }, - [153] = { "munlockall" }, - [154] = { "sched_setparam" }, - [155] = { "sched_getparam" }, - [156] = { "sched_setscheduler" }, - [157] = { "sched_getscheduler" }, - [158] = { "sched_yield" }, - [159] = { "sched_get_priority_max" }, - [160] = { "sched_get_priority_min" }, - [161] = { "sched_rr_get_interval" }, - [162] = { "nanosleep", 0x000044 }, - [163] = { "mremap" }, - [164] = { "setresuid" }, - [165] = { "getresuid" }, - [166] = { "vm86" }, - [167] = { "query_module" }, - [168] = { "poll" }, - [169] = { "nfsservctl" }, - [170] = { "setresgid" }, - [171] = { "getresgid" }, - [172] = { "prctl", 0x333331 }, - [173] = { "rt_sigreturn", 0xffffff }, - [174] = { "rt_sigaction", 0x001441 }, - [175] = { "rt_sigprocmask", 0x001441 }, - [176] = { "rt_sigpending", 0x000014 }, - [177] = { "rt_sigtimedwait", 0x001444 }, - [178] = { "rt_sigqueueinfo", 0x000411 }, - [179] = { "rt_sigsuspend", 0x000014 }, - [180] = { "pread", 0x003341 }, - [181] = { "pwrite", 0x003341 }, - [182] = { "chown", 0x000115 }, - [183] = { "getcwd" }, - [184] = { "capget" }, - [185] = { "capset" }, - [186] = { "sigaltstack" }, - [187] = { "sendfile" }, - [188] = { "getpmsg" }, - [189] = { "putpmsg" }, - [190] = { "vfork", 0xffffff }, - [191] = { "ugetrlimit" }, - [192] = { "mmap2", 0x313314 }, - [193] = { "truncate64" }, - [194] = { "ftruncate64" }, - [195] = { "stat64", 0x000045 }, - [196] = { "lstat64", 0x000045 }, - [197] = { "fstat64", 0x000041 }, - [198] = { "lchown32" }, - [199] = { "getuid32", 0xffffff }, - [200] = { "getgid32", 0xffffff }, - [201] = { "geteuid32", 0xffffff }, - [202] = { "getegid32", 0xffffff }, - [203] = { "setreuid32" }, - [204] = { "setregid32" }, - [205] = { "getgroups32" }, - [206] = { "setgroups32" }, - [207] = { "fchown32" }, - [208] = { "setresuid32" }, - [209] = { "getresuid32" }, - [210] = { "setresgid32" }, - [211] = { "getresgid32" }, - [212] = { "chown32" }, - [213] = { "setuid32" }, - [214] = { "setgid32" }, - [215] = { "setfsuid32" }, - [216] = { "setfsgid32" }, - [217] = { "pivot_root" }, - [218] = { "mincore" }, - [219] = { "madvise" }, - [220] = { "getdents64" }, - [221] = { "fcntl64" }, - [223] = { "security" }, - [224] = { "gettid" }, - [225] = { "readahead" }, - [226] = { "setxattr" }, - [227] = { "lsetxattr" }, - [228] = { "fsetxattr" }, - [229] = { "getxattr" }, - [230] = { "lgetxattr" }, - [231] = { "fgetxattr" }, - [232] = { "listxattr" }, - [233] = { "llistxattr" }, - [234] = { "flistxattr" }, - [235] = { "removexattr" }, - [236] = { "lremovexattr" }, - [237] = { "fremovexattr" }, - [238] = { "tkill" }, - [239] = { "sendfile64" }, - [240] = { "futex" }, - [241] = { "sched_setaffinity" }, - [242] = { "sched_getaffinity" }, - [243] = { "set_thread_area" }, - [244] = { "get_thread_area" }, - [245] = { "io_setup" }, - [246] = { "io_destroy" }, - [247] = { "io_getevents" }, - [248] = { "io_submit" }, - [249] = { "io_cancel" }, - [250] = { "fadvise64" }, - [252] = { "exit_group", 0x000001 }, - [253] = { "lookup_dcookie" }, - [254] = { "epoll_create" }, - [255] = { "epoll_ctl" }, - [256] = { "epoll_wait" }, - [257] = { "remap_file_pages" }, - [258] = { "set_tid_address" }, - [259] = { "timer_create" }, - [260] = { "timer_settime" }, - [261] = { "timer_gettime" }, - [262] = { "timer_getoverrun" }, - [263] = { "timer_delete" }, - [264] = { "clock_settime" }, - [265] = { "clock_gettime" }, - [266] = { "clock_getres" }, - [267] = { "clock_nanosleep" }, - [268] = { "statfs64" }, - [269] = { "fstatfs64" }, - [270] = { "tgkill" }, - [271] = { "utimes" }, - [272] = { "fadvise64_64" }, - [273] = { "vserver" }, - [274] = { "mbind" }, - [275] = { "get_mempolicy" }, - [276] = { "set_mempolicy" }, - [277] = { "mq_open" }, - [278] = { "mq_unlink" }, - [279] = { "mq_timedsend" }, - [280] = { "mq_timedreceive" }, - [281] = { "mq_notify" }, - [282] = { "mq_getsetattr" }, - [283] = { "sys_kexec_load" }, -}; - -asmlinkage void do_syscall_trace(int leaving) +/* + * handle tracing of system call entry + * - return the revised system call number or ULONG_MAX to cause ENOSYS + */ +asmlinkage unsigned long syscall_trace_entry(void) { -#if 0 - unsigned long *argp; - const char *name; - unsigned argmask; - char buffer[16]; - - if (!kstrace) - return; - - if (!current->mm) - return; - - if (__frame->gr7 == __NR_close) - return; - -#if 0 - if (__frame->gr7 != __NR_mmap2 && - __frame->gr7 != __NR_vfork && - __frame->gr7 != __NR_execve && - __frame->gr7 != __NR_exit) - return; -#endif - - argmask = 0; - name = NULL; - if (__frame->gr7 < NR_syscalls) { - name = __syscall_name_table[__frame->gr7].name; - argmask = __syscall_name_table[__frame->gr7].argmask; - } - if (!name) { - sprintf(buffer, "sys_%lx", __frame->gr7); - name = buffer; - } - - if (!leaving) { - if (!argmask) { - printk(KERN_CRIT "[%d] %s(%lx,%lx,%lx,%lx,%lx,%lx)\n", - current->pid, - name, - __frame->gr8, - __frame->gr9, - __frame->gr10, - __frame->gr11, - __frame->gr12, - __frame->gr13); - } - else if (argmask == 0xffffff) { - printk(KERN_CRIT "[%d] %s()\n", - current->pid, - name); - } - else { - printk(KERN_CRIT "[%d] %s(", - current->pid, - name); - - argp = &__frame->gr8; - - do { - switch (argmask & 0xf) { - case 1: - printk("%ld", (long) *argp); - break; - case 2: - printk("%lo", *argp); - break; - case 3: - printk("%lx", *argp); - break; - case 4: - printk("%p", (void *) *argp); - break; - case 5: - printk("\"%s\"", (char *) *argp); - break; - } - - argp++; - argmask >>= 4; - if (argmask) - printk(","); - - } while (argmask); - - printk(")\n"); - } - } - else { - if ((int)__frame->gr8 > -4096 && (int)__frame->gr8 < 4096) - printk(KERN_CRIT "[%d] %s() = %ld\n", current->pid, name, __frame->gr8); - else - printk(KERN_CRIT "[%d] %s() = %lx\n", current->pid, name, __frame->gr8); + __frame->__status |= REG__STATUS_SYSC_ENTRY; + if (tracehook_report_syscall_entry(__frame)) { + /* tracing decided this syscall should not happen, so + * We'll return a bogus call number to get an ENOSYS + * error, but leave the original number in + * __frame->syscallno + */ + return ULONG_MAX; } - return; -#endif - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - - if (!(current->ptrace & PT_PTRACED)) - return; - - /* we need to indicate entry or exit to strace */ - if (leaving) - __frame->__status |= REG__STATUS_SYSC_EXIT; - else - __frame->__status |= REG__STATUS_SYSC_ENTRY; - - ptrace_notify(SIGTRAP); + return __frame->syscallno; +} - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } +/* + * handle tracing of system call exit + */ +asmlinkage void syscall_trace_exit(void) +{ + __frame->__status |= REG__STATUS_SYSC_EXIT; + tracehook_report_syscall_exit(__frame, 0); } diff --git a/arch/frv/kernel/semaphore.c b/arch/frv/kernel/semaphore.c deleted file mode 100644 index 7971d680ae2..00000000000 --- a/arch/frv/kernel/semaphore.c +++ /dev/null @@ -1,156 +0,0 @@ -/* semaphore.c: FR-V semaphores - * - * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - Derived from lib/rwsem-spinlock.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/config.h> -#include <linux/sched.h> -#include <linux/module.h> -#include <asm/semaphore.h> - -struct sem_waiter { - struct list_head list; - struct task_struct *task; -}; - -#if SEMAPHORE_DEBUG -void semtrace(struct semaphore *sem, const char *str) -{ - if (sem->debug) - printk("[%d] %s({%d,%d})\n", - current->pid, - str, - sem->counter, - list_empty(&sem->wait_list) ? 0 : 1); -} -#else -#define semtrace(SEM,STR) do { } while(0) -#endif - -/* - * wait for a token to be granted from a semaphore - * - entered with lock held and interrupts disabled - */ -void __down(struct semaphore *sem, unsigned long flags) -{ - struct task_struct *tsk = current; - struct sem_waiter waiter; - - semtrace(sem, "Entering __down"); - - /* set up my own style of waitqueue */ - waiter.task = tsk; - get_task_struct(tsk); - - list_add_tail(&waiter.list, &sem->wait_list); - - /* we don't need to touch the semaphore struct anymore */ - spin_unlock_irqrestore(&sem->wait_lock, flags); - - /* wait to be given the semaphore */ - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - - for (;;) { - if (list_empty(&waiter.list)) - break; - schedule(); - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - } - - tsk->state = TASK_RUNNING; - semtrace(sem, "Leaving __down"); -} - -EXPORT_SYMBOL(__down); - -/* - * interruptibly wait for a token to be granted from a semaphore - * - entered with lock held and interrupts disabled - */ -int __down_interruptible(struct semaphore *sem, unsigned long flags) -{ - struct task_struct *tsk = current; - struct sem_waiter waiter; - int ret; - - semtrace(sem,"Entering __down_interruptible"); - - /* set up my own style of waitqueue */ - waiter.task = tsk; - get_task_struct(tsk); - - list_add_tail(&waiter.list, &sem->wait_list); - - /* we don't need to touch the semaphore struct anymore */ - set_task_state(tsk, TASK_INTERRUPTIBLE); - - spin_unlock_irqrestore(&sem->wait_lock, flags); - - /* wait to be given the semaphore */ - ret = 0; - for (;;) { - if (list_empty(&waiter.list)) - break; - if (unlikely(signal_pending(current))) - goto interrupted; - schedule(); - set_task_state(tsk, TASK_INTERRUPTIBLE); - } - - out: - tsk->state = TASK_RUNNING; - semtrace(sem, "Leaving __down_interruptible"); - return ret; - - interrupted: - spin_lock_irqsave(&sem->wait_lock, flags); - - if (!list_empty(&waiter.list)) { - list_del(&waiter.list); - ret = -EINTR; - } - - spin_unlock_irqrestore(&sem->wait_lock, flags); - if (ret == -EINTR) - put_task_struct(current); - goto out; -} - -EXPORT_SYMBOL(__down_interruptible); - -/* - * release a single token back to a semaphore - * - entered with lock held and interrupts disabled - */ -void __up(struct semaphore *sem) -{ - struct task_struct *tsk; - struct sem_waiter *waiter; - - semtrace(sem,"Entering __up"); - - /* grant the token to the process at the front of the queue */ - waiter = list_entry(sem->wait_list.next, struct sem_waiter, list); - - /* We must be careful not to touch 'waiter' after we set ->task = NULL. - * It is an allocated on the waiter's stack and may become invalid at - * any time after that point (due to a wakeup from another source). - */ - list_del_init(&waiter->list); - tsk = waiter->task; - mb(); - waiter->task = NULL; - wake_up_process(tsk); - put_task_struct(tsk); - - semtrace(sem,"Leaving __up"); -} - -EXPORT_SYMBOL(__up); diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 5908deae960..9f3a7a62d78 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -10,8 +10,7 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> -#include <linux/version.h> +#include <generated/utsrelease.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/delay.h> @@ -30,9 +29,9 @@ #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/serial_reg.h> +#include <linux/serial_8250.h> #include <asm/setup.h> -#include <asm/serial.h> #include <asm/irq.h> #include <asm/sections.h> #include <asm/pgalloc.h> @@ -44,11 +43,9 @@ #include <asm/mb-regs.h> #include <asm/mb93493-regs.h> #include <asm/gdb-stub.h> -#include <asm/irq-routing.h> #include <asm/io.h> #ifdef CONFIG_BLK_DEV_INITRD -#include <linux/blk.h> #include <asm/pgtable.h> #endif @@ -63,10 +60,6 @@ static void __init setup_linux_memory(void); static void __init setup_uclinux_memory(void); #endif -#ifdef CONFIG_CONSOLE -extern struct consw *conswitchp; -#endif - #ifdef CONFIG_MB93090_MB00 static char __initdata mb93090_banner[] = "FJ/RH FR-V Linux"; static char __initdata mb93090_version[] = UTS_RELEASE; @@ -113,15 +106,17 @@ unsigned long __initdata num_mappedpages; struct cpuinfo_frv __nongprelbss boot_cpu_data; -char command_line[COMMAND_LINE_SIZE]; +char __initdata command_line[COMMAND_LINE_SIZE]; char __initdata redboot_command_line[COMMAND_LINE_SIZE]; #ifdef CONFIG_PM #define __pminit #define __pminitdata +#define __pminitconst #else #define __pminit __init #define __pminitdata __initdata +#define __pminitconst __initconst #endif struct clock_cmode { @@ -191,10 +186,10 @@ static struct clock_cmode __pminitdata clock_cmodes_fr555[16] = { [6] = { _x1, _x1_5, _x1_5, _x4_5, _x0_375 }, }; -static const struct clock_cmode __pminitdata *clock_cmodes; +static const struct clock_cmode __pminitconst *clock_cmodes; static int __pminitdata clock_doubled; -static struct uart_port __initdata __frv_uart0 = { +static struct uart_port __pminitdata __frv_uart0 = { .uartclk = 0, .membase = (char *) UART0_BASE, .irq = IRQ_CPU_UART0, @@ -203,7 +198,7 @@ static struct uart_port __initdata __frv_uart0 = { .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, }; -static struct uart_port __initdata __frv_uart1 = { +static struct uart_port __pminitdata __frv_uart1 = { .uartclk = 0, .membase = (char *) UART1_BASE, .irq = IRQ_CPU_UART1, @@ -714,7 +709,7 @@ static void __init reserve_dma_coherent(void) /* * calibrate the delay loop */ -void __init calibrate_delay(void) +void calibrate_delay(void) { loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ); @@ -740,7 +735,7 @@ static void __init parse_cmdline_early(char *cmdline) /* "mem=XXX[kKmM]" sets SDRAM size to <mem>, overriding the value we worked * out from the SDRAM controller mask register */ - if (!memcmp(cmdline, "mem=", 4)) { + if (!strncmp(cmdline, "mem=", 4)) { unsigned long long mem_size; mem_size = memparse(cmdline + 4, &cmdline); @@ -765,7 +760,7 @@ void __init setup_arch(char **cmdline_p) printk("uClinux FR-V port done by Red Hat Inc <dhowells@redhat.com>\n"); #endif - memcpy(saved_command_line, redboot_command_line, COMMAND_LINE_SIZE); + memcpy(boot_command_line, redboot_command_line, COMMAND_LINE_SIZE); determine_cpu(); determine_clocks(1); @@ -798,15 +793,8 @@ void __init setup_arch(char **cmdline_p) #endif #endif -#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) - /* we need to initialize the Flashrom device here since we might - * do things with flash early on in the boot - */ - flash_probe(); -#endif - /* deal with the command line - RedBoot may have passed one to the kernel */ - memcpy(command_line, saved_command_line, sizeof(command_line)); + memcpy(command_line, boot_command_line, sizeof(command_line)); *cmdline_p = &command_line[0]; parse_cmdline_early(command_line); @@ -814,11 +802,11 @@ void __init setup_arch(char **cmdline_p) * - by now the stack is part of the init task */ printk("Memory %08lx-%08lx\n", memory_start, memory_end); - if (memory_start == memory_end) BUG(); + BUG_ON(memory_start == memory_end); - init_mm.start_code = (unsigned long) &_stext; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; + init_mm.start_code = (unsigned long) _stext; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; #if 0 /* DAVIDM - don't set brk just incase someone decides to use it */ init_mm.brk = (unsigned long) &_end; #else @@ -826,10 +814,8 @@ void __init setup_arch(char **cmdline_p) #endif #ifdef DEBUG - printk("KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x BSS=0x%06x-0x%06x\n", - (int) &_stext, (int) &_etext, - (int) &_sdata, (int) &_edata, - (int) &_sbss, (int) &_ebss); + printk("KERNEL -> TEXT=0x%p-0x%p DATA=0x%p-0x%p BSS=0x%p-0x%p\n", + _stext, _etext, _sdata, _edata, __bss_start, __bss_stop); #endif #ifdef CONFIG_VT @@ -840,11 +826,6 @@ void __init setup_arch(char **cmdline_p) #endif #endif -#ifdef CONFIG_BLK_DEV_BLKMEM - ROOT_DEV = MKDEV(BLKMEM_MAJOR,0); -#endif - /*rom_length = (unsigned long)&_flashend - (unsigned long)&_romvec;*/ - #ifdef CONFIG_MMU setup_linux_memory(); #else @@ -871,7 +852,7 @@ void __init setup_arch(char **cmdline_p) /* * */ -static int __devinit setup_arch_serial(void) +static int setup_arch_serial(void) { /* register those serial ports that are available */ #ifndef CONFIG_GDBSTUB_UART0 @@ -895,6 +876,7 @@ late_initcall(setup_arch_serial); static void __init setup_linux_memory(void) { unsigned long bootmap_size, low_top_pfn, kstart, kend, high_mem; + unsigned long physpages; kstart = (unsigned long) &__kernel_image_start - PAGE_OFFSET; kend = (unsigned long) &__kernel_image_end - PAGE_OFFSET; @@ -912,19 +894,19 @@ static void __init setup_linux_memory(void) ); /* pass the memory that the kernel can immediately use over to the bootmem allocator */ - max_mapnr = num_physpages = (memory_end - memory_start) >> PAGE_SHIFT; + max_mapnr = physpages = (memory_end - memory_start) >> PAGE_SHIFT; low_top_pfn = (KERNEL_LOWMEM_END - KERNEL_LOWMEM_START) >> PAGE_SHIFT; high_mem = 0; - if (num_physpages > low_top_pfn) { + if (physpages > low_top_pfn) { #ifdef CONFIG_HIGHMEM - high_mem = num_physpages - low_top_pfn; + high_mem = physpages - low_top_pfn; #else - max_mapnr = num_physpages = low_top_pfn; + max_mapnr = physpages = low_top_pfn; #endif } else { - low_top_pfn = num_physpages; + low_top_pfn = physpages; } min_low_pfn = memory_start >> PAGE_SHIFT; @@ -943,14 +925,16 @@ static void __init setup_linux_memory(void) #endif /* take back the memory occupied by the kernel image and the bootmem alloc map */ - reserve_bootmem(kstart, kend - kstart + bootmap_size); + reserve_bootmem(kstart, kend - kstart + bootmap_size, + BOOTMEM_DEFAULT); /* reserve the memory occupied by the initial ramdisk */ #ifdef CONFIG_BLK_DEV_INITRD if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (low_top_pfn << PAGE_SHIFT)) { - reserve_bootmem(INITRD_START, INITRD_SIZE); - initrd_start = INITRD_START ? INITRD_START + PAGE_OFFSET : 0; + reserve_bootmem(INITRD_START, INITRD_SIZE, + BOOTMEM_DEFAULT); + initrd_start = INITRD_START + PAGE_OFFSET; initrd_end = initrd_start + INITRD_SIZE; } else { @@ -996,7 +980,7 @@ static void __init setup_uclinux_memory(void) free_bootmem(memory_start, memory_end - memory_start); high_memory = (void *) (memory_end & PAGE_MASK); - max_mapnr = num_physpages = ((unsigned long) high_memory - PAGE_OFFSET) >> PAGE_SHIFT; + max_mapnr = ((unsigned long) high_memory - PAGE_OFFSET) >> PAGE_SHIFT; min_low_pfn = memory_start >> PAGE_SHIFT; max_low_pfn = memory_end >> PAGE_SHIFT; @@ -1004,9 +988,10 @@ static void __init setup_uclinux_memory(void) /* now take back the bits the core kernel is occupying */ #ifndef CONFIG_PROTECT_KERNEL - reserve_bootmem(kend, bootmap_size); + reserve_bootmem(kend, bootmap_size, BOOTMEM_DEFAULT); reserve_bootmem((unsigned long) &__kernel_image_start, - kend - (unsigned long) &__kernel_image_start); + kend - (unsigned long) &__kernel_image_start, + BOOTMEM_DEFAULT); #else dampr = __get_DAMPR(0); @@ -1014,14 +999,15 @@ static void __init setup_uclinux_memory(void) dampr = (dampr >> 4) + 17; dampr = 1 << dampr; - reserve_bootmem(__get_DAMPR(0) & xAMPRx_PPFN, dampr); + reserve_bootmem(__get_DAMPR(0) & xAMPRx_PPFN, dampr, BOOTMEM_DEFAULT); #endif /* reserve some memory to do uncached DMA through if requested */ #ifdef CONFIG_RESERVE_DMA_COHERENT if (dma_coherent_mem_start) reserve_bootmem(dma_coherent_mem_start, - dma_coherent_mem_end - dma_coherent_mem_start); + dma_coherent_mem_end - dma_coherent_mem_start, + BOOTMEM_DEFAULT); #endif } /* end setup_uclinux_memory() */ @@ -1127,7 +1113,7 @@ static void c_stop(struct seq_file *m, void *v) { } -struct seq_operations cpuinfo_op = { +const struct seq_operations cpuinfo_op = { .start = c_start, .next = c_next, .stop = c_stop, diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 679c1d5cc95..d822700d4f1 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -13,7 +13,6 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/kernel.h> #include <linux/signal.h> #include <linux/errno.h> @@ -21,84 +20,25 @@ #include <linux/ptrace.h> #include <linux/unistd.h> #include <linux/personality.h> -#include <linux/suspend.h> +#include <linux/tracehook.h> #include <asm/ucontext.h> #include <asm/uaccess.h> #include <asm/cacheflush.h> #define DEBUG_SIG 0 -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - struct fdpic_func_descriptor { unsigned long text; unsigned long GOT; }; /* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) -{ - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; -} - -asmlinkage 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 (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -asmlinkage -int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) -{ - return do_sigaltstack(uss, uoss, __frame->sp); -} - - -/* * Do a signal return; undo the signal stack. */ struct sigframe { - void (*pretcode)(void); + __sigrestore_t pretcode; int sig; struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; @@ -107,10 +47,10 @@ struct sigframe struct rt_sigframe { - void (*pretcode)(void); + __sigrestore_t pretcode; int sig; - struct siginfo *pinfo; - void *puc; + struct siginfo __user *pinfo; + void __user *puc; struct siginfo info; struct ucontext uc; uint32_t retcode[2]; @@ -121,6 +61,9 @@ static int restore_sigcontext(struct sigcontext __user *sc, int *_gr8) struct user_context *user = current->thread.user; unsigned long tbr, psr; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + tbr = user->i.tbr; psr = user->i.psr; if (copy_from_user(user, &sc->sc_context, sizeof(sc->sc_context))) @@ -154,11 +97,7 @@ asmlinkage int sys_sigreturn(void) __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(&frame->sc, &gr8)) goto badframe; @@ -180,16 +119,12 @@ asmlinkage int sys_rt_sigreturn(void) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) goto badframe; - if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT) + if (restore_altstack(&frame->uc.uc_stack)) goto badframe; return gr8; @@ -233,7 +168,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (! on_sig_stack(sp)) + if (! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; } @@ -250,6 +185,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) struct sigframe __user *frame; int rsig; + set_fs(USER_DS); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) @@ -284,7 +221,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ - if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) || + if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) goto give_sigsegv; @@ -293,26 +230,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) (unsigned long) (frame->retcode + 2)); } - /* set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; - - if (get_personality & FDPIC_FUNCPTRS) { + /* Set up registers for the signal handler */ + if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = - (struct fdpic_func_descriptor *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; + struct fdpic_func_descriptor desc; + if (copy_from_user(&desc, funcptr, sizeof(desc))) + goto give_sigsegv; + __frame->pc = desc.text; + __frame->gr15 = desc.GOT; } else { __frame->pc = (unsigned long) ka->sa.sa_handler; __frame->gr15 = 0; } - set_fs(USER_DS); - - /* the tracer may want to single-step inside the handler */ - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", @@ -323,7 +257,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } /* end setup_frame() */ @@ -338,6 +272,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, struct rt_sigframe __user *frame; int rsig; + set_fs(USER_DS); + frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) @@ -359,10 +295,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Create the ucontext. */ if (__put_user(0, &frame->uc.uc_flags) || - __put_user(0, &frame->uc.uc_link) || - __put_user((void*)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || - __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || - __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) + __put_user(NULL, &frame->uc.uc_link) || + __save_altstack(&frame->uc.uc_stack, __frame->sp)) goto give_sigsegv; if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0])) @@ -382,7 +316,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ - if (__put_user((void (*)(void))frame->retcode, &frame->pretcode) || + if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) goto give_sigsegv; @@ -392,26 +326,23 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } /* Set up registers for signal handler */ - __frame->sp = (unsigned long) frame; - __frame->lr = (unsigned long) &frame->retcode; - __frame->gr8 = sig; - __frame->gr9 = (unsigned long) &frame->info; - - if (get_personality & FDPIC_FUNCPTRS) { - struct fdpic_func_descriptor *funcptr = + if (current->personality & FDPIC_FUNCPTRS) { + struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; - __get_user(__frame->pc, &funcptr->text); - __get_user(__frame->gr15, &funcptr->GOT); + struct fdpic_func_descriptor desc; + if (copy_from_user(&desc, funcptr, sizeof(desc))) + goto give_sigsegv; + __frame->pc = desc.text; + __frame->gr15 = desc.GOT; } else { __frame->pc = (unsigned long) ka->sa.sa_handler; __frame->gr15 = 0; } - set_fs(USER_DS); - - /* the tracer may want to single-step inside the handler */ - if (test_thread_flag(TIF_SINGLESTEP)) - ptrace_notify(SIGTRAP); + __frame->sp = (unsigned long) frame; + __frame->lr = (unsigned long) &frame->retcode; + __frame->gr8 = sig; + __frame->gr9 = (unsigned long) &frame->info; #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", @@ -422,7 +353,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } /* end setup_rt_frame() */ @@ -431,13 +362,14 @@ give_sigsegv: /* * OK, we're invoking a handler */ -static int handle_signal(unsigned long sig, siginfo_t *info, - struct k_sigaction *ka, sigset_t *oldset) +static void handle_signal(unsigned long sig, siginfo_t *info, + struct k_sigaction *ka) { + sigset_t *oldset = sigmask_to_save(); int ret; /* Are we from a system call? */ - if (in_syscall(__frame)) { + if (__frame->syscallno != -1) { /* If so, check system call restarting.. */ switch (__frame->gr8) { case -ERESTART_RESTARTBLOCK: @@ -456,6 +388,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, __frame->gr8 = __frame->orig_gr8; __frame->pc -= 4; } + __frame->syscallno = -1; } /* Set up the stack frame */ @@ -464,18 +397,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, else ret = setup_frame(sig, ka, oldset); - if (ret == 0) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - - return ret; + if (ret) + return; + signal_delivered(sig, info, ka, __frame, + test_thread_flag(TIF_SINGLESTEP)); } /* end handle_signal() */ /*****************************************************************************/ @@ -488,43 +414,16 @@ static void do_signal(void) { struct k_sigaction ka; siginfo_t info; - sigset_t *oldset; int signr; - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(__frame)) - return; - - if (try_to_freeze()) - goto no_signal; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, __frame, NULL); if (signr > 0) { - if (handle_signal(signr, &info, &ka, oldset) == 0) { - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - } - + handle_signal(signr, &info, &ka); return; } -no_signal: /* Did we come from a system call? */ - if (__frame->syscallno >= 0) { + if (__frame->syscallno != -1) { /* Restart the system call - no handlers present */ switch (__frame->gr8) { case -ERESTARTNOHAND: @@ -535,19 +434,16 @@ no_signal: break; case -ERESTART_RESTARTBLOCK: - __frame->gr8 = __NR_restart_syscall; + __frame->gr7 = __NR_restart_syscall; __frame->pc -= 4; break; } + __frame->syscallno = -1; } /* if there's no signal to deliver, we just put the saved sigmask * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } - + restore_saved_sigmask(); } /* end do_signal() */ /*****************************************************************************/ @@ -562,7 +458,13 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) clear_thread_flag(TIF_SINGLESTEP); /* deal with pending signal delivery */ - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + if (thread_info_flags & _TIF_SIGPENDING) do_signal(); + /* deal with notification on about to resume userspace execution */ + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(__frame); + } + } /* end do_notify_resume() */ diff --git a/arch/frv/kernel/sleep.S b/arch/frv/kernel/sleep.S index e6079b8cac6..f67bf73cd2c 100644 --- a/arch/frv/kernel/sleep.S +++ b/arch/frv/kernel/sleep.S @@ -1,7 +1,7 @@ /* sleep.S: power saving mode entry * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Woodhouse (dwmw2@redhat.com) + * Written by David Woodhouse (dwmw2@infradead.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,7 +11,6 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/setup.h> #include <asm/segment.h> diff --git a/arch/frv/kernel/switch_to.S b/arch/frv/kernel/switch_to.S index 1703dc20174..b06668670fc 100644 --- a/arch/frv/kernel/switch_to.S +++ b/arch/frv/kernel/switch_to.S @@ -11,7 +11,7 @@ # 2 of the License, or (at your option) any later version. # ############################################################################### -#include <linux/config.h> + #include <linux/linkage.h> #include <asm/thread_info.h> #include <asm/processor.h> @@ -31,7 +31,7 @@ # address of frame 0 (userspace) on current kernel stack .globl __kernel_frame0_ptr __kernel_frame0_ptr: - .long init_thread_union + THREAD_SIZE - USER_CONTEXT_SIZE + .long init_thread_union + THREAD_SIZE - FRV_FRAME0_SIZE # address of current task .globl __kernel_current_task @@ -102,13 +102,6 @@ __switch_to: movgs gr14,lr bar - srli gr15,#28,gr5 - subicc gr5,#0xc,gr0,icc0 - beq icc0,#0,111f - break - nop -111: - # jump to __switch_back or ret_from_fork as appropriate # - move prev to GR8 movgs gr4,psr diff --git a/arch/frv/kernel/sys_frv.c b/arch/frv/kernel/sys_frv.c index 931aa6d895e..9c4980825bb 100644 --- a/arch/frv/kernel/sys_frv.c +++ b/arch/frv/kernel/sys_frv.c @@ -13,202 +13,32 @@ #include <linux/errno.h> #include <linux/sched.h> #include <linux/mm.h> +#include <linux/fs.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/sem.h> #include <linux/msg.h> #include <linux/shm.h> #include <linux/stat.h> #include <linux/mman.h> #include <linux/file.h> -#include <linux/utsname.h> #include <linux/syscalls.h> +#include <linux/ipc.h> #include <asm/setup.h> #include <asm/uaccess.h> -#include <asm/ipc.h> - -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -asmlinkage long sys_pipe(unsigned long * fildes) -{ - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; - } - return error; -} asmlinkage long sys_mmap2(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; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - /* As with sparc32, make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE we have.... */ /* But unlike sparc32, don't just silently break if we're trying to map something we can't */ - if (pgoff & ((1<<(PAGE_SHIFT-12))-1)) + if (pgoff & ((1 << (PAGE_SHIFT - 12)) - 1)) return -EINVAL; - pgoff >>= (PAGE_SHIFT - 12); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); -out: - return error; -} - -#if 0 /* DAVIDM - do we want this */ -struct mmap_arg_struct64 { - __u32 addr; - __u32 len; - __u32 prot; - __u32 flags; - __u64 offset; /* 64 bits */ - __u32 fd; -}; - -asmlinkage long sys_mmap64(struct mmap_arg_struct64 *arg) -{ - int error = -EFAULT; - struct file * file = NULL; - struct mmap_arg_struct64 a; - unsigned long pgoff; - - if (copy_from_user(&a, arg, sizeof(a))) - return -EFAULT; - - if ((long)a.offset & ~PAGE_MASK) - return -EINVAL; - - pgoff = a.offset >> PAGE_SHIFT; - if ((a.offset >> PAGE_SHIFT) != pgoff) - return -EINVAL; - - if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; - file = fget(a.fd); - if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, pgoff); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -out: - return error; -} -#endif - -/* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ -asmlinkage long sys_ipc(unsigned long call, - unsigned long first, - unsigned long second, - unsigned long third, - void __user *ptr, - unsigned long fifth) -{ - int version, ret; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - - switch (call) { - case SEMOP: - return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL); - case SEMTIMEDOP: - return sys_semtimedop(first, (struct sembuf __user *)ptr, second, - (const struct timespec __user *)fifth); - - case SEMGET: - return sys_semget (first, second, third); - case SEMCTL: { - union semun fourth; - if (!ptr) - return -EINVAL; - if (get_user(fourth.__pad, (void * __user *) ptr)) - return -EFAULT; - return sys_semctl (first, second, third, fourth); - } - - case MSGSND: - return sys_msgsnd (first, (struct msgbuf __user *) ptr, - second, third); - case MSGRCV: - switch (version) { - case 0: { - struct ipc_kludge tmp; - if (!ptr) - return -EINVAL; - - if (copy_from_user(&tmp, - (struct ipc_kludge __user *) ptr, - sizeof (tmp))) - return -EFAULT; - return sys_msgrcv (first, tmp.msgp, second, - tmp.msgtyp, third); - } - default: - return sys_msgrcv (first, - (struct msgbuf __user *) ptr, - second, fifth, third); - } - case MSGGET: - return sys_msgget ((key_t) first, second); - case MSGCTL: - return sys_msgctl (first, second, (struct msqid_ds __user *) ptr); - - case SHMAT: - switch (version) { - default: { - ulong raddr; - ret = do_shmat (first, (char __user *) ptr, second, &raddr); - if (ret) - return ret; - return put_user (raddr, (ulong __user *) third); - } - case 1: /* iBCS2 emulator entry point */ - if (!segment_eq(get_fs(), get_ds())) - return -EINVAL; - /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */ - return do_shmat (first, (char __user *) ptr, second, (ulong *) third); - } - case SHMDT: - return sys_shmdt ((char __user *)ptr); - case SHMGET: - return sys_shmget (first, second, third); - case SHMCTL: - return sys_shmctl (first, second, - (struct shmid_ds __user *) ptr); - default: - return -ENOSYS; - } + return sys_mmap_pgoff(addr, len, prot, flags, fd, + pgoff >> (PAGE_SHIFT - 12)); } diff --git a/arch/frv/kernel/sysctl.c b/arch/frv/kernel/sysctl.c index 408b0f382b4..f4dfae2c75a 100644 --- a/arch/frv/kernel/sysctl.c +++ b/arch/frv/kernel/sysctl.c @@ -9,8 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> -#include <linux/slab.h> #include <linux/sysctl.h> #include <linux/proc_fs.h> #include <linux/init.h> @@ -48,8 +46,9 @@ static void frv_change_dcache_mode(unsigned long newmode) /* * handle requests to dynamically switch the write caching mode delivered by /proc */ -static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) +static int procctl_frv_cachemode(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) { unsigned long hsr0; char buff[8]; @@ -86,7 +85,7 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp, } /* read the state */ - if (filp->f_pos > 0) { + if (*ppos > 0) { *lenp = 0; return 0; } @@ -112,7 +111,7 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp, return -EFAULT; *lenp = len; - filp->f_pos = len; + *ppos = len; return 0; } /* end procctl_frv_cachemode() */ @@ -122,8 +121,9 @@ static int procctl_frv_cachemode(ctl_table *table, int write, struct file *filp, * permit the mm_struct the nominated process is using have its MMU context ID pinned */ #ifdef CONFIG_MMU -static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp, - void *buffer, size_t *lenp, loff_t *ppos) +static int procctl_frv_pin_cxnr(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) { pid_t pid; char buff[16], *p; @@ -152,7 +152,7 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp, } /* read the currently pinned CXN */ - if (filp->f_pos > 0) { + if (*ppos > 0) { *lenp = 0; return 0; } @@ -165,7 +165,7 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp, return -EFAULT; *lenp = len; - filp->f_pos = len; + *ppos = len; return 0; } /* end procctl_frv_pin_cxnr() */ @@ -176,22 +176,37 @@ static int procctl_frv_pin_cxnr(ctl_table *table, int write, struct file *filp, */ static struct ctl_table frv_table[] = { - { 1, "cache-mode", NULL, 0, 0644, NULL, &procctl_frv_cachemode }, + { + .procname = "cache-mode", + .data = NULL, + .maxlen = 0, + .mode = 0644, + .proc_handler = procctl_frv_cachemode, + }, #ifdef CONFIG_MMU - { 2, "pin-cxnr", NULL, 0, 0644, NULL, &procctl_frv_pin_cxnr }, + { + .procname = "pin-cxnr", + .data = NULL, + .maxlen = 0, + .mode = 0644, + .proc_handler = procctl_frv_pin_cxnr + }, #endif - { 0 } + {} }; /* * Use a temporary sysctl number. Horrid, but will be cleaned up in 2.6 * when all the PM interfaces exist nicely. */ -#define CTL_FRV 9898 static struct ctl_table frv_dir_table[] = { - {CTL_FRV, "frv", NULL, 0, 0555, frv_table}, - {0} + { + .procname = "frv", + .mode = 0555, + .child = frv_table + }, + {} }; /* @@ -199,7 +214,7 @@ static struct ctl_table frv_dir_table[] = */ static int __init frv_sysctl_init(void) { - register_sysctl_table(frv_dir_table, 1); + register_sysctl_table(frv_dir_table); return 0; } diff --git a/arch/frv/kernel/time.c b/arch/frv/kernel/time.c index 24cf85f89e4..b457de496b7 100644 --- a/arch/frv/kernel/time.c +++ b/arch/frv/kernel/time.c @@ -10,7 +10,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> /* CONFIG_HEARTBEAT */ #include <linux/module.h> #include <linux/errno.h> #include <linux/sched.h> @@ -26,14 +25,11 @@ #include <asm/timer-regs.h> #include <asm/mb-regs.h> #include <asm/mb86943a.h> -#include <asm/irq-routing.h> #include <linux/timex.h> #define TICK_SIZE (tick_nsec / 1000) -extern unsigned long wall_jiffies; - unsigned long __nongprelbss __clkin_clock_speed_HZ; unsigned long __nongprelbss __ext_bus_clock_speed_HZ; unsigned long __nongprelbss __res_bus_clock_speed_HZ; @@ -44,54 +40,23 @@ unsigned long __nongprelbss __dsu_clock_speed_HZ; unsigned long __nongprelbss __serial_clock_speed_HZ; unsigned long __delay_loops_MHz; -static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs *regs); +static irqreturn_t timer_interrupt(int irq, void *dummy); static struct irqaction timer_irq = { - timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL + .handler = timer_interrupt, + .flags = IRQF_DISABLED, + .name = "timer", }; -static inline int set_rtc_mmss(unsigned long nowtime) -{ - return -1; -} - /* * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick + * as well as call the "xtime_update()" routine every clocktick */ -static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs) +static irqreturn_t timer_interrupt(int irq, void *dummy) { - /* last time the cmos clock got updated */ - static long last_rtc_update = 0; - - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_seqlock(&xtime_lock); - - do_timer(regs); - update_process_times(user_mode(regs)); - profile_tick(CPU_PROFILING, regs); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if (ntp_synced() && - xtime.tv_sec > last_rtc_update + 660 && - (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && - (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2 - ) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - } + profile_tick(CPU_PROFILING); + + xtime_update(1); #ifdef CONFIG_HEARTBEAT static unsigned short n; @@ -99,7 +64,8 @@ static irqreturn_t timer_interrupt(int irq, void *dummy, struct pt_regs * regs) __set_LEDS(n); #endif /* CONFIG_HEARTBEAT */ - write_sequnlock(&xtime_lock); + update_process_times(user_mode(get_irq_regs())); + return IRQ_HANDLED; } @@ -119,7 +85,8 @@ void time_divisor_init(void) __set_TCSR_DATA(0, base >> 8); } -void time_init(void) + +void read_persistent_clock(struct timespec *ts) { unsigned int year, mon, day, hour, min, sec; @@ -127,7 +94,7 @@ void time_init(void) /* FIX by dqg : Set to zero for platforms that don't have tod */ /* without this time is undefined and can overflow time_t, causing */ - /* very stange errors */ + /* very strange errors */ year = 1980; mon = day = 1; hour = min = sec = 0; @@ -135,9 +102,12 @@ void time_init(void) if ((year += 1900) < 1970) year += 100; - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_nsec = 0; + ts->tv_sec = mktime(year, mon, day, hour, min, sec); + ts->tv_nsec = 0; +} +void time_init(void) +{ /* install scheduling interrupt handler */ setup_irq(IRQ_CPU_TIMER0, &timer_irq); @@ -145,85 +115,6 @@ void time_init(void) } /* - * This version of gettimeofday has near microsecond resolution. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long seq; - unsigned long usec, sec; - unsigned long max_ntp_tick; - - do { - unsigned long lost; - - seq = read_seqbegin(&xtime_lock); - - usec = 0; - lost = jiffies - wall_jiffies; - - /* - * If time_adjust is negative then NTP is slowing the clock - * so make sure not to go into next possible interval. - * Better to lose some accuracy than have time go backwards.. - */ - if (unlikely(time_adjust < 0)) { - max_ntp_tick = (USEC_PER_SEC / HZ) - tickadj; - usec = min(usec, max_ntp_tick); - - if (lost) - usec += lost * max_ntp_tick; - } - else if (unlikely(lost)) - usec += lost * (USEC_PER_SEC / HZ); - - sec = xtime.tv_sec; - usec += (xtime.tv_nsec / 1000); - } while (read_seqretry(&xtime_lock, seq)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -EXPORT_SYMBOL(do_gettimeofday); - -int do_settimeofday(struct timespec *tv) -{ - time_t wtm_sec, sec = tv->tv_sec; - long wtm_nsec, nsec = tv->tv_nsec; - - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) - return -EINVAL; - - write_seqlock_irq(&xtime_lock); - /* - * This is revolting. We need to set "xtime" correctly. However, the - * value in this location is the value at the most recent update of - * wall time. Discover what correction gettimeofday() would have - * made, and then undo it! - */ - nsec -= 0 * NSEC_PER_USEC; - nsec -= (jiffies - wall_jiffies) * TICK_NSEC; - - wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); - wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); - - set_normalized_timespec(&xtime, sec, nsec); - set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - - ntp_clear(); - write_sequnlock_irq(&xtime_lock); - clock_was_set(); - return 0; -} - -EXPORT_SYMBOL(do_settimeofday); - -/* * Scheduler clock - returns current time in nanosec units. */ unsigned long long sched_clock(void) diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c index 9eb84b2e6ab..a6d105d61b2 100644 --- a/arch/frv/kernel/traps.c +++ b/arch/frv/kernel/traps.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/signal.h> #include <linux/kernel.h> @@ -21,9 +20,9 @@ #include <linux/init.h> #include <linux/module.h> +#include <asm/asm-offsets.h> #include <asm/setup.h> #include <asm/fpu.h> -#include <asm/system.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/siginfo.h> @@ -49,7 +48,7 @@ asmlinkage void insn_access_error(unsigned long esfr1, unsigned long epcr0, unsi info.si_signo = SIGSEGV; info.si_code = SEGV_ACCERR; info.si_errno = 0; - info.si_addr = (void *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); + info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); force_sig_info(info.si_signo, &info, current); } /* end insn_access_error() */ @@ -73,7 +72,7 @@ asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, un epcr0, esr0, esfr1); info.si_errno = 0; - info.si_addr = (void *) ((epcr0 & EPCR0_PC) ? (epcr0 & EPCR0_PC) : __frame->pc); + info.si_addr = (void __user *) ((epcr0 & EPCR0_V) ? (epcr0 & EPCR0_PC) : __frame->pc); switch (__frame->tbr & TBR_TT) { case TBR_TT_ILLEGAL_INSTR: @@ -102,6 +101,234 @@ asmlinkage void illegal_instruction(unsigned long esfr1, unsigned long epcr0, un /*****************************************************************************/ /* + * handle atomic operations with errors + * - arguments in gr8, gr9, gr10 + * - original memory value placed in gr5 + * - replacement memory value placed in gr9 + */ +asmlinkage void atomic_operation(unsigned long esfr1, unsigned long epcr0, + unsigned long esr0) +{ + static DEFINE_SPINLOCK(atomic_op_lock); + unsigned long x, y, z; + unsigned long __user *p; + mm_segment_t oldfs; + siginfo_t info; + int ret; + + y = 0; + z = 0; + + oldfs = get_fs(); + if (!user_mode(__frame)) + set_fs(KERNEL_DS); + + switch (__frame->tbr & TBR_TT) { + /* TIRA gr0,#120 + * u32 __atomic_user_cmpxchg32(u32 *ptr, u32 test, u32 new) + */ + case TBR_TT_ATOMIC_CMPXCHG32: + p = (unsigned long __user *) __frame->gr8; + x = __frame->gr9; + y = __frame->gr10; + + for (;;) { + ret = get_user(z, p); + if (ret < 0) + goto error; + + if (z != x) + goto done; + + spin_lock_irq(&atomic_op_lock); + + if (__get_user(z, p) == 0) { + if (z != x) + goto done2; + + if (__put_user(y, p) == 0) + goto done2; + goto error2; + } + + spin_unlock_irq(&atomic_op_lock); + } + + /* TIRA gr0,#121 + * u32 __atomic_kernel_xchg32(void *v, u32 new) + */ + case TBR_TT_ATOMIC_XCHG32: + p = (unsigned long __user *) __frame->gr8; + y = __frame->gr9; + + for (;;) { + ret = get_user(z, p); + if (ret < 0) + goto error; + + spin_lock_irq(&atomic_op_lock); + + if (__get_user(z, p) == 0) { + if (__put_user(y, p) == 0) + goto done2; + goto error2; + } + + spin_unlock_irq(&atomic_op_lock); + } + + /* TIRA gr0,#122 + * ulong __atomic_kernel_XOR_return(ulong i, ulong *v) + */ + case TBR_TT_ATOMIC_XOR: + p = (unsigned long __user *) __frame->gr8; + x = __frame->gr9; + + for (;;) { + ret = get_user(z, p); + if (ret < 0) + goto error; + + spin_lock_irq(&atomic_op_lock); + + if (__get_user(z, p) == 0) { + y = x ^ z; + if (__put_user(y, p) == 0) + goto done2; + goto error2; + } + + spin_unlock_irq(&atomic_op_lock); + } + + /* TIRA gr0,#123 + * ulong __atomic_kernel_OR_return(ulong i, ulong *v) + */ + case TBR_TT_ATOMIC_OR: + p = (unsigned long __user *) __frame->gr8; + x = __frame->gr9; + + for (;;) { + ret = get_user(z, p); + if (ret < 0) + goto error; + + spin_lock_irq(&atomic_op_lock); + + if (__get_user(z, p) == 0) { + y = x ^ z; + if (__put_user(y, p) == 0) + goto done2; + goto error2; + } + + spin_unlock_irq(&atomic_op_lock); + } + + /* TIRA gr0,#124 + * ulong __atomic_kernel_AND_return(ulong i, ulong *v) + */ + case TBR_TT_ATOMIC_AND: + p = (unsigned long __user *) __frame->gr8; + x = __frame->gr9; + + for (;;) { + ret = get_user(z, p); + if (ret < 0) + goto error; + + spin_lock_irq(&atomic_op_lock); + + if (__get_user(z, p) == 0) { + y = x & z; + if (__put_user(y, p) == 0) + goto done2; + goto error2; + } + + spin_unlock_irq(&atomic_op_lock); + } + + /* TIRA gr0,#125 + * int __atomic_user_sub_return(atomic_t *v, int i) + */ + case TBR_TT_ATOMIC_SUB: + p = (unsigned long __user *) __frame->gr8; + x = __frame->gr9; + + for (;;) { + ret = get_user(z, p); + if (ret < 0) + goto error; + + spin_lock_irq(&atomic_op_lock); + + if (__get_user(z, p) == 0) { + y = z - x; + if (__put_user(y, p) == 0) + goto done2; + goto error2; + } + + spin_unlock_irq(&atomic_op_lock); + } + + /* TIRA gr0,#126 + * int __atomic_user_add_return(atomic_t *v, int i) + */ + case TBR_TT_ATOMIC_ADD: + p = (unsigned long __user *) __frame->gr8; + x = __frame->gr9; + + for (;;) { + ret = get_user(z, p); + if (ret < 0) + goto error; + + spin_lock_irq(&atomic_op_lock); + + if (__get_user(z, p) == 0) { + y = z + x; + if (__put_user(y, p) == 0) + goto done2; + goto error2; + } + + spin_unlock_irq(&atomic_op_lock); + } + + default: + BUG(); + } + +done2: + spin_unlock_irq(&atomic_op_lock); +done: + if (!user_mode(__frame)) + set_fs(oldfs); + __frame->gr5 = z; + __frame->gr9 = y; + return; + +error2: + spin_unlock_irq(&atomic_op_lock); +error: + if (!user_mode(__frame)) + set_fs(oldfs); + __frame->pc -= 4; + + die_if_kernel("-- Atomic Op Error --\n"); + + info.si_signo = SIGSEGV; + info.si_code = SEGV_ACCERR; + info.si_errno = 0; + info.si_addr = (void __user *) __frame->pc; + + force_sig_info(info.si_signo, &info, current); +} + +/*****************************************************************************/ +/* * */ asmlinkage void media_exception(unsigned long msr0, unsigned long msr1) @@ -116,7 +343,7 @@ asmlinkage void media_exception(unsigned long msr0, unsigned long msr1) info.si_signo = SIGFPE; info.si_code = FPE_MDAOVF; info.si_errno = 0; - info.si_addr = (void *) __frame->pc; + info.si_addr = (void __user *) __frame->pc; force_sig_info(info.si_signo, &info, current); } /* end media_exception() */ @@ -134,11 +361,8 @@ asmlinkage void memory_access_exception(unsigned long esr0, #ifdef CONFIG_MMU unsigned long fixup; - if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS) - if (handle_misalignment(esr0, ear0, epcr0) == 0) - return; - - if ((fixup = search_exception_table(__frame->pc)) != 0) { + fixup = search_exception_table(__frame->pc); + if (fixup) { __frame->pc = fixup; return; } @@ -156,7 +380,7 @@ asmlinkage void memory_access_exception(unsigned long esr0, info.si_addr = NULL; if ((esr0 & (ESRx_VALID | ESR0_EAV)) == (ESRx_VALID | ESR0_EAV)) - info.si_addr = (void *) ear0; + info.si_addr = (void __user *) ear0; force_sig_info(info.si_signo, &info, current); @@ -185,7 +409,7 @@ asmlinkage void data_access_error(unsigned long esfr1, unsigned long esr15, unsi info.si_signo = SIGSEGV; info.si_code = SEGV_ACCERR; info.si_errno = 0; - info.si_addr = (void *) + info.si_addr = (void __user *) (((esr15 & (ESRx_VALID|ESR15_EAV)) == (ESRx_VALID|ESR15_EAV)) ? ear15 : 0); force_sig_info(info.si_signo, &info, current); @@ -219,7 +443,7 @@ asmlinkage void division_exception(unsigned long esfr1, unsigned long esr0, unsi info.si_signo = SIGFPE; info.si_code = FPE_INTDIV; info.si_errno = 0; - info.si_addr = (void *) __frame->pc; + info.si_addr = (void __user *) __frame->pc; force_sig_info(info.si_signo, &info, current); } /* end division_exception() */ @@ -242,17 +466,6 @@ asmlinkage void compound_exception(unsigned long esfr1, BUG(); } /* end compound_exception() */ -/*****************************************************************************/ -/* - * The architecture-independent backtrace generator - */ -void dump_stack(void) -{ - show_stack(NULL, NULL); -} - -EXPORT_SYMBOL(dump_stack); - void show_stack(struct task_struct *task, unsigned long *sp) { } @@ -280,26 +493,25 @@ static const char *regnames[] = { void show_regs(struct pt_regs *regs) { - uint32_t *reg; + unsigned long *reg; int loop; printk("\n"); + show_regs_print_info(KERN_DEFAULT); - printk("Frame: @%08x [%s]\n", - (uint32_t) regs, + printk("Frame: @%08lx [%s]\n", + (unsigned long) regs, regs->psr & PSR_S ? "kernel" : "user"); - reg = (uint32_t *) regs; - for (loop = 0; loop < REG__END; loop++) { - printk("%s %08x", regnames[loop + 0], reg[loop + 0]); + reg = (unsigned long *) regs; + for (loop = 0; loop < NR_PT_REGS; loop++) { + printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); - if (loop == REG__END - 1 || loop % 5 == 4) + if (loop == NR_PT_REGS - 1 || loop % 5 == 4) printk("\n"); else printk(" | "); } - - printk("Process %s (pid: %d)\n", current->comm, current->pid); } void die_if_kernel(const char *str, ...) @@ -311,7 +523,7 @@ void die_if_kernel(const char *str, ...) return; va_start(va, str); - vsprintf(buffer, str, va); + vsnprintf(buffer, sizeof(buffer), str, va); va_end(va); console_verbose(); @@ -329,7 +541,7 @@ void die_if_kernel(const char *str, ...) */ static void show_backtrace_regs(struct pt_regs *frame) { - uint32_t *reg; + unsigned long *reg; int loop; /* print the registers for this frame */ @@ -337,11 +549,11 @@ static void show_backtrace_regs(struct pt_regs *frame) frame->psr & PSR_S ? "Kernel Mode" : "User Mode", frame); - reg = (uint32_t *) frame; - for (loop = 0; loop < REG__END; loop++) { - printk("%s %08x", regnames[loop + 0], reg[loop + 0]); + reg = (unsigned long *) frame; + for (loop = 0; loop < NR_PT_REGS; loop++) { + printk("%s %08lx", regnames[loop + 0], reg[loop + 0]); - if (loop == REG__END - 1 || loop % 5 == 4) + if (loop == NR_PT_REGS - 1 || loop % 5 == 4) printk("\n"); else printk(" | "); diff --git a/arch/frv/kernel/uaccess.c b/arch/frv/kernel/uaccess.c index 9b751c0f0e8..374f88d6cc0 100644 --- a/arch/frv/kernel/uaccess.c +++ b/arch/frv/kernel/uaccess.c @@ -17,14 +17,13 @@ /* * copy a null terminated string from userspace */ -long strncpy_from_user(char *dst, const char *src, long count) +long strncpy_from_user(char *dst, const char __user *src, long count) { unsigned long max; char *p, ch; long err = -EFAULT; - if (count < 0) - BUG(); + BUG_ON(count < 0); p = dst; @@ -70,14 +69,13 @@ EXPORT_SYMBOL(strncpy_from_user); * * Return 0 on exception, a value greater than N if too long */ -long strnlen_user(const char *src, long count) +long strnlen_user(const char __user *src, long count) { - const char *p; + const char __user *p; long err = 0; char ch; - if (count < 0) - BUG(); + BUG_ON(count < 0); #ifndef CONFIG_MMU if ((unsigned long) src < memory_start) diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index f474534ba78..7e958d829ec 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S @@ -13,7 +13,7 @@ ENTRY(_start) jiffies = jiffies_64 + 4; -__page_offset = 0xc0000000; /* start of area covered by struct pages */ +__page_offset = CONFIG_PAGE_OFFSET; /* start of area covered by struct pages */ __kernel_image_start = __page_offset; /* address at which kernel image resides */ SECTIONS @@ -26,62 +26,22 @@ SECTIONS _sinittext = .; .init.text : { - *(.text.head) + HEAD_TEXT #ifndef CONFIG_DEBUG_INFO - *(.init.text) - *(.exit.text) - *(.exit.data) + INIT_TEXT + EXIT_TEXT + EXIT_DATA *(.exitcall.exit) #endif } _einittext = .; - .init.data : { *(.init.data) } - - . = ALIGN(8); - __setup_start = .; - .setup.init : { KEEP(*(.init.setup)) } - __setup_end = .; - - __initcall_start = .; - .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : { *(.con_initcall.init) } - __con_initcall_end = .; - SECURITY_INIT - . = ALIGN(4); - __alt_instructions = .; - .altinstructions : { *(.altinstructions) } - __alt_instructions_end = .; - .altinstr_replacement : { *(.altinstr_replacement) } - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } - __per_cpu_end = .; + INIT_DATA_SECTION(8) + PERCPU_SECTION(L1_CACHE_BYTES) - . = ALIGN(4096); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; - - . = ALIGN(THREAD_SIZE); + . = ALIGN(PAGE_SIZE); __init_end = .; - /* put sections together that have massive alignment issues */ - . = ALIGN(THREAD_SIZE); - .data.init_task : { - /* init task record & stack */ - *(.data.init_task) - } - .trap : { /* trap table management - read entry-table.S before modifying */ . = ALIGN(8192); @@ -92,27 +52,23 @@ SECTIONS *(.trap.break) } - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - . = ALIGN(L1_CACHE_BYTES); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - /* Text and read-only data */ . = ALIGN(4); _text = .; _stext = .; .text : { - *( - .text.start .text .text.* -#ifdef CONFIG_DEBUG_INFO - .init.text - .exit.text - .exitcall.exit -#endif - ) + *(.text..start) + *(.text..entry) + *(.text..break) + *(.text..tlbmiss) + TEXT_TEXT SCHED_TEXT LOCK_TEXT +#ifdef CONFIG_DEBUG_INFO + INIT_TEXT + EXIT_TEXT + *(.exitcall.exit) +#endif *(.fixup) *(.gnu.warning) *(.exitcall.exit) @@ -131,15 +87,15 @@ SECTIONS } - . = ALIGN(8); /* Exception table */ - __start___ex_table = .; - __ex_table : { KEEP(*(__ex_table)) } - __stop___ex_table = .; + EXCEPTION_TABLE(8) _sdata = .; .data : { /* Data */ - *(.data .data.*) - *(.exit.data) + INIT_TASK_DATA(THREAD_SIZE) + CACHELINE_ALIGNED_DATA(L1_CACHE_BYTES) + DATA_DATA + *(.data.*) + EXIT_DATA CONSTRUCTORS } @@ -158,31 +114,19 @@ SECTIONS .sbss : { *(.sbss .sbss.*) } .bss : { *(.bss .bss.*) } - .bss.stack : { *(.bss) } + .bss..stack : { *(.bss) } __bss_stop = .; _end = . ; . = ALIGN(PAGE_SIZE); __kernel_image_end = .; - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - - .debug_line 0 : { *(.debug_line) } - .debug_info 0 : { *(.debug_info) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_frame 0 : { *(.debug_frame) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_str 0 : { *(.debug_str) } - .debug_ranges 0 : { *(.debug_ranges) } + STABS_DEBUG + DWARF_DEBUG .comment 0 : { *(.comment) } + + DISCARDS } __kernel_image_size_no_bss = __bss_start - __kernel_image_start; diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile index 08be305c9f4..4ff2fb1e6b1 100644 --- a/arch/frv/lib/Makefile +++ b/arch/frv/lib/Makefile @@ -4,5 +4,5 @@ lib-y := \ __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o __ucmpdi2.o \ - checksum.o memcpy.o memset.o atomic-ops.o \ + checksum.o memcpy.o memset.o atomic-ops.o atomic64-ops.o \ outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o diff --git a/arch/frv/lib/atomic-ops.S b/arch/frv/lib/atomic-ops.S index 545cd325ac5..5e9e6ab5dd0 100644 --- a/arch/frv/lib/atomic-ops.S +++ b/arch/frv/lib/atomic-ops.S @@ -1,7 +1,7 @@ /* atomic-ops.S: kernel atomic operations * * For an explanation of how atomic ops work in this arch, see: - * Documentation/fujitsu/frv/atomic-ops.txt + * Documentation/frv/atomic-ops.txt * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) @@ -163,11 +163,10 @@ __cmpxchg_32: ld.p @(gr11,gr0),gr8 orcr cc7,cc7,cc3 subcc gr8,gr9,gr7,icc0 - bne icc0,#0,1f + bnelr icc0,#0 cst.p gr10,@(gr11,gr0) ,cc3,#1 corcc gr29,gr29,gr0 ,cc3,#1 beq icc3,#0,0b -1: bralr .size __cmpxchg_32, .-__cmpxchg_32 diff --git a/arch/frv/lib/atomic64-ops.S b/arch/frv/lib/atomic64-ops.S new file mode 100644 index 00000000000..b6194eeac12 --- /dev/null +++ b/arch/frv/lib/atomic64-ops.S @@ -0,0 +1,162 @@ +/* kernel atomic64 operations + * + * For an explanation of how atomic ops work in this arch, see: + * Documentation/frv/atomic-ops.txt + * + * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <asm/spr-regs.h> + + .text + .balign 4 + + +############################################################################### +# +# long long atomic64_inc_return(atomic64_t *v) +# +############################################################################### + .globl atomic64_inc_return + .type atomic64_inc_return,@function +atomic64_inc_return: + or.p gr8,gr8,gr10 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + addicc gr9,#1,gr9,icc0 + addxi gr8,#0,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_inc_return, .-atomic64_inc_return + +############################################################################### +# +# long long atomic64_dec_return(atomic64_t *v) +# +############################################################################### + .globl atomic64_dec_return + .type atomic64_dec_return,@function +atomic64_dec_return: + or.p gr8,gr8,gr10 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + subicc gr9,#1,gr9,icc0 + subxi gr8,#0,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_dec_return, .-atomic64_dec_return + +############################################################################### +# +# long long atomic64_add_return(long long i, atomic64_t *v) +# +############################################################################### + .globl atomic64_add_return + .type atomic64_add_return,@function +atomic64_add_return: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + addcc gr9,gr5,gr9,icc0 + addx gr8,gr4,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_add_return, .-atomic64_add_return + +############################################################################### +# +# long long atomic64_sub_return(long long i, atomic64_t *v) +# +############################################################################### + .globl atomic64_sub_return + .type atomic64_sub_return,@function +atomic64_sub_return: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + subcc gr9,gr5,gr9,icc0 + subx gr8,gr4,gr8,icc0 + cstd.p gr8,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size atomic64_sub_return, .-atomic64_sub_return + +############################################################################### +# +# uint64_t __xchg_64(uint64_t i, uint64_t *v) +# +############################################################################### + .globl __xchg_64 + .type __xchg_64,@function +__xchg_64: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr10,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 /* set CC3 to true */ + cstd.p gr4,@(gr10,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size __xchg_64, .-__xchg_64 + +############################################################################### +# +# uint64_t __cmpxchg_64(uint64_t test, uint64_t new, uint64_t *v) +# +############################################################################### + .globl __cmpxchg_64 + .type __cmpxchg_64,@function +__cmpxchg_64: + or.p gr8,gr8,gr4 + or gr9,gr9,gr5 +0: + orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */ + ckeq icc3,cc7 + ldd.p @(gr12,gr0),gr8 /* LDD.P/ORCR must be atomic */ + orcr cc7,cc7,cc3 + subcc gr8,gr4,gr0,icc0 + subcc.p gr9,gr5,gr0,icc1 + bnelr icc0,#0 + bnelr icc1,#0 + cstd.p gr10,@(gr12,gr0) ,cc3,#1 + corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */ + beq icc3,#0,0b + bralr + + .size __cmpxchg_64, .-__cmpxchg_64 + diff --git a/arch/frv/lib/cache.S b/arch/frv/lib/cache.S index 0e10ad8dc46..0c4fb204911 100644 --- a/arch/frv/lib/cache.S +++ b/arch/frv/lib/cache.S @@ -1,4 +1,4 @@ -/* cache.S: cache managment routines +/* cache.S: cache management routines * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) diff --git a/arch/frv/lib/checksum.c b/arch/frv/lib/checksum.c index 20e7dfc474e..44e16d59bc1 100644 --- a/arch/frv/lib/checksum.c +++ b/arch/frv/lib/checksum.c @@ -32,7 +32,6 @@ of the assembly has to go. */ #include <net/checksum.h> -#include <asm/checksum.h> #include <linux/module.h> static inline unsigned short from32to16(unsigned long x) @@ -105,15 +104,15 @@ out: * * it's best to have buff aligned on a 32-bit boundary */ -unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) +__wsum csum_partial(const void *buff, int len, __wsum sum) { unsigned int result = do_csum(buff, len); /* add in old sum, and carry.. */ - result += sum; - if (sum > result) + result += (__force u32)sum; + if ((__force u32)sum > result) result += 1; - return result; + return (__force __wsum)result; } EXPORT_SYMBOL(csum_partial); @@ -122,9 +121,9 @@ EXPORT_SYMBOL(csum_partial); * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c */ -unsigned short ip_compute_csum(const unsigned char * buff, int len) +__sum16 ip_compute_csum(const void *buff, int len) { - return ~do_csum(buff, len); + return (__force __sum16)~do_csum(buff, len); } EXPORT_SYMBOL(ip_compute_csum); @@ -132,9 +131,9 @@ EXPORT_SYMBOL(ip_compute_csum); /* * copy from fs while checksumming, otherwise like csum_partial */ -unsigned int -csum_partial_copy_from_user(const char __user *src, char *dst, - int len, int sum, int *csum_err) +__wsum +csum_partial_copy_from_user(const void __user *src, void *dst, + int len, __wsum sum, int *csum_err) { int rem; @@ -157,11 +156,11 @@ EXPORT_SYMBOL(csum_partial_copy_from_user); /* * copy from ds while checksumming, otherwise like csum_partial */ -unsigned int -csum_partial_copy(const char *src, char *dst, int len, int sum) +__wsum +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) { memcpy(dst, src, len); return csum_partial(dst, len, sum); } -EXPORT_SYMBOL(csum_partial_copy); +EXPORT_SYMBOL(csum_partial_copy_nocheck); diff --git a/arch/frv/mb93090-mb00/Makefile b/arch/frv/mb93090-mb00/Makefile index 76595e87073..21f1df1b378 100644 --- a/arch/frv/mb93090-mb00/Makefile +++ b/arch/frv/mb93090-mb00/Makefile @@ -3,7 +3,7 @@ # ifeq "$(CONFIG_PCI)" "y" -obj-y := pci-frv.o pci-irq.o pci-vdk.o pci-iomap.o +obj-y := pci-frv.o pci-irq.o pci-vdk.o ifeq "$(CONFIG_MMU)" "y" obj-y += pci-dma.o @@ -11,3 +11,5 @@ else obj-y += pci-dma-nommu.o endif endif + +obj-$(CONFIG_MTD) += flash.o diff --git a/arch/frv/mb93090-mb00/flash.c b/arch/frv/mb93090-mb00/flash.c new file mode 100644 index 00000000000..c0e3707c229 --- /dev/null +++ b/arch/frv/mb93090-mb00/flash.c @@ -0,0 +1,90 @@ +/* Flash mappings for the MB93090-MB00 motherboard + * + * Copyright (C) 2009 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/mtd/partitions.h> +#include <linux/mtd/physmap.h> + +#define MB93090_BOOTROM_ADDR 0xFF000000 /* Boot ROM */ +#define MB93090_BOOTROM_SIZE (2 * 1024 * 1024) +#define MB93090_USERROM_ADDR 0xFF200000 /* User ROM */ +#define MB93090_USERROM_SIZE (2 * 1024 * 1024) + +/* + * default MTD partition table for both main flash devices, expected to be + * overridden by RedBoot + */ +static struct mtd_partition mb93090_partitions[] = { + { + .name = "Filesystem", + .size = MTDPART_SIZ_FULL, + .offset = 0, + } +}; + +/* + * Definition of the MB93090 Boot ROM (on the CPU card) + */ +static struct physmap_flash_data mb93090_bootrom_data = { + .width = 2, + .nr_parts = 2, + .parts = mb93090_partitions, +}; + +static struct resource mb93090_bootrom_resource = { + .start = MB93090_BOOTROM_ADDR, + .end = MB93090_BOOTROM_ADDR + MB93090_BOOTROM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device mb93090_bootrom = { + .name = "physmap-flash", + .id = 0, + .dev.platform_data = &mb93090_bootrom_data, + .num_resources = 1, + .resource = &mb93090_bootrom_resource, +}; + +/* + * Definition of the MB93090 User ROM definition (on the motherboard) + */ +static struct physmap_flash_data mb93090_userrom_data = { + .width = 2, + .nr_parts = 2, + .parts = mb93090_partitions, +}; + +static struct resource mb93090_userrom_resource = { + .start = MB93090_USERROM_ADDR, + .end = MB93090_USERROM_ADDR + MB93090_USERROM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device mb93090_userrom = { + .name = "physmap-flash", + .id = 1, + .dev.platform_data = &mb93090_userrom_data, + .num_resources = 1, + .resource = &mb93090_userrom_resource, +}; + +/* + * register the MB93090 flashes + */ +static int __init mb93090_mtd_init(void) +{ + platform_device_register(&mb93090_bootrom); + platform_device_register(&mb93090_userrom); + return 0; +} + +module_init(mb93090_mtd_init); diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c index 4985466b1a7..b99c2a7cc7a 100644 --- a/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c @@ -1,7 +1,7 @@ /* pci-dma-nommu.c: Dynamic DMA mapping support for the FRV * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Woodhouse (dwmw2@redhat.com) + * Written by David Woodhouse (dwmw2@infradead.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -11,6 +11,7 @@ #include <linux/types.h> #include <linux/slab.h> +#include <linux/export.h> #include <linux/dma-mapping.h> #include <linux/list.h> #include <linux/pci.h> @@ -106,18 +107,10 @@ void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_ EXPORT_SYMBOL(dma_free_coherent); -/* - * Map a single buffer of the indicated size for DMA in streaming mode. - * The 32-bit bus address to use is returned. - * - * Once the device is given the dma address, the device owns this memory - * until either pci_unmap_single or pci_dma_sync_single is performed. - */ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction direction) { - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); frv_cache_wback_inv((unsigned long) ptr, (unsigned long) ptr + size); @@ -126,22 +119,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, EXPORT_SYMBOL(dma_map_single); -/* - * Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scather-gather version of the - * above pci_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are - * the same here. - */ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { @@ -151,10 +128,19 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, frv_cache_wback_inv(sg_dma_address(&sg[i]), sg_dma_address(&sg[i]) + sg_dma_len(&sg[i])); - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); return nents; } EXPORT_SYMBOL(dma_map_sg); + +dma_addr_t dma_map_page(struct device *dev, struct page *page, unsigned long offset, + size_t size, enum dma_data_direction direction) +{ + BUG_ON(direction == DMA_NONE); + flush_dcache_page(page); + return (dma_addr_t) page_to_phys(page) + offset; +} + +EXPORT_SYMBOL(dma_map_page); diff --git a/arch/frv/mb93090-mb00/pci-dma.c b/arch/frv/mb93090-mb00/pci-dma.c index 671ce1e8434..82478979ac9 100644 --- a/arch/frv/mb93090-mb00/pci-dma.c +++ b/arch/frv/mb93090-mb00/pci-dma.c @@ -10,11 +10,12 @@ */ #include <linux/types.h> -#include <linux/slab.h> #include <linux/dma-mapping.h> #include <linux/list.h> #include <linux/pci.h> +#include <linux/export.h> #include <linux/highmem.h> +#include <linux/scatterlist.h> #include <asm/io.h> void *dma_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t gfp) @@ -37,18 +38,10 @@ void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_ EXPORT_SYMBOL(dma_free_coherent); -/* - * Map a single buffer of the indicated size for DMA in streaming mode. - * The 32-bit bus address to use is returned. - * - * Once the device is given the dma address, the device owns this memory - * until either pci_unmap_single or pci_dma_sync_single is performed. - */ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction direction) { - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); frv_cache_wback_inv((unsigned long) ptr, (unsigned long) ptr + size); @@ -57,22 +50,6 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, EXPORT_SYMBOL(dma_map_single); -/* - * Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scather-gather version of the - * above pci_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are - * the same here. - */ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, enum dma_data_direction direction) { @@ -80,20 +57,19 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, void *vaddr; int i; - if (direction == DMA_NONE) - BUG(); + BUG_ON(direction == DMA_NONE); dampr2 = __get_DAMPR(2); for (i = 0; i < nents; i++) { - vaddr = kmap_atomic(sg[i].page, __KM_CACHE); + vaddr = kmap_atomic_primary(sg_page(&sg[i])); frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE); } - kunmap_atomic(vaddr, __KM_CACHE); + kunmap_atomic_primary(vaddr); if (dampr2) { __set_DAMPR(2, dampr2); __set_IAMPR(2, dampr2); diff --git a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c index 0a26bf6f1cd..67b1d168575 100644 --- a/arch/frv/mb93090-mb00/pci-frv.c +++ b/arch/frv/mb93090-mb00/pci-frv.c @@ -19,36 +19,6 @@ #include "pci-frv.h" -#if 0 -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= IORESOURCE_ROM_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", pci_name(dev), resource, - new, check); - } -} -#endif - /* * We need to avoid collisions with `mirrored' VGA ports * and other strange ISA hardware, so we always want the @@ -62,18 +32,16 @@ pcibios_update_resource(struct pci_dev *dev, struct resource *root, * but we want to try to avoid allocating at 0x2900-0x2bff * which might have be mirrored at 0x0100-0x03ff.. */ -void -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) +resource_size_t +pcibios_align_resource(void *data, const struct resource *res, + resource_size_t size, resource_size_t align) { - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; + resource_size_t start = res->start; - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } + if ((res->flags & IORESOURCE_IO) && (start & 0x300)) + start = (start + 0x3ff) & ~0x3ff; + + return start; } @@ -116,19 +84,17 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) struct pci_bus *bus; struct pci_dev *dev; int idx; - struct resource *r, *pr; + struct resource *r; /* Depth-First Search on bus tree */ for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); + bus = list_entry(ln, struct pci_bus, node); if ((dev = bus->self)) { for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { r = &dev->resource[idx]; if (!r->start) continue; - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) - printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev)); + pci_claim_resource(dev, idx); } } pcibios_allocate_bus_resources(&bus->children); @@ -140,7 +106,7 @@ static void __init pcibios_allocate_resources(int pass) struct pci_dev *dev = NULL; int idx, disabled; u16 command; - struct resource *r, *pr; + struct resource *r; for_each_pci_dev(dev) { pci_read_config_word(dev, PCI_COMMAND, &command); @@ -157,9 +123,7 @@ static void __init pcibios_allocate_resources(int pass) if (pass == disabled) { DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", r->start, r->end, r->flags, disabled, pass); - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev)); + if (pci_claim_resource(dev, idx) < 0) { /* We'll assign a new address later */ r->end -= r->start; r->start = 0; @@ -230,55 +194,3 @@ void __init pcibios_resource_survey(void) pcibios_allocate_resources(1); pcibios_assign_resources(); } - -int pcibios_enable_resources(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - /* Only set up the requested stuff */ - if (!(mask & (1<<idx))) - continue; - - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check the latency - * timer as certain crappy BIOSes forget to set it properly. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h index 7481797ab38..a7e487fe76e 100644 --- a/arch/frv/mb93090-mb00/pci-frv.h +++ b/arch/frv/mb93090-mb00/pci-frv.h @@ -17,8 +17,6 @@ #define PCI_PROBE_BIOS 0x0001 #define PCI_PROBE_CONF1 0x0002 #define PCI_PROBE_CONF2 0x0004 -#define PCI_NO_SORT 0x0100 -#define PCI_BIOS_SORT 0x0200 #define PCI_NO_CHECKS 0x0400 #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 @@ -28,15 +26,10 @@ extern unsigned int __nongpreldata pci_probe; /* pci-frv.c */ -extern unsigned int pcibios_max_latency; - void pcibios_resource_survey(void); -int pcibios_enable_resources(struct pci_dev *, int); /* pci-vdk.c */ -extern int __nongpreldata pcibios_last_bus; -extern struct pci_bus *__nongpreldata pci_root_bus; extern struct pci_ops *__nongpreldata pci_root_ops; /* pci-irq.c */ diff --git a/arch/frv/mb93090-mb00/pci-iomap.c b/arch/frv/mb93090-mb00/pci-iomap.c deleted file mode 100644 index 068fa04bd52..00000000000 --- a/arch/frv/mb93090-mb00/pci-iomap.c +++ /dev/null @@ -1,29 +0,0 @@ -/* pci-iomap.c: description - * - * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ -#include <linux/pci.h> -#include <linux/module.h> - -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) -{ - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); - unsigned long flags = pci_resource_flags(dev, bar); - - if (!len || !start) - return NULL; - - if ((flags & IORESOURCE_IO) || (flags & IORESOURCE_MEM)) - return (void __iomem *) start; - - return NULL; -} - -EXPORT_SYMBOL(pci_iomap); diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c index c4a1144c98b..1c35c93f942 100644 --- a/arch/frv/mb93090-mb00/pci-irq.c +++ b/arch/frv/mb93090-mb00/pci-irq.c @@ -5,18 +5,15 @@ * derived from: arch/i386/kernel/pci-irq.c: (c) 1999--2000 Martin Mares <mj@suse.cz> */ -#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/init.h> -#include <linux/slab.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <asm/io.h> #include <asm/smp.h> -#include <asm/irq-routing.h> #include "pci-frv.h" @@ -31,12 +28,12 @@ * */ -static const uint8_t __initdata pci_bus0_irq_routing[32][4] = { - [0 ] { IRQ_FPGA_MB86943_PCI_INTA }, - [16] { IRQ_FPGA_RTL8029_INTA }, - [17] { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB }, - [18] { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA }, - [19] { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD }, +static const uint8_t __initconst pci_bus0_irq_routing[32][4] = { + [0 ] = { IRQ_FPGA_MB86943_PCI_INTA }, + [16] = { IRQ_FPGA_RTL8029_INTA }, + [17] = { IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB }, + [18] = { IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD, IRQ_FPGA_PCI_INTA }, + [19] = { IRQ_FPGA_PCI_INTA, IRQ_FPGA_PCI_INTB, IRQ_FPGA_PCI_INTC, IRQ_FPGA_PCI_INTD }, }; void __init pcibios_irq_init(void) @@ -58,10 +55,6 @@ void __init pcibios_fixup_irqs(void) } } -void __init pcibios_penalize_isa_irq(int irq) -{ -} - void pcibios_enable_irq(struct pci_dev *dev) { pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index c8817f7b860..efa5d65b000 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -17,7 +16,6 @@ #include <linux/init.h> #include <linux/ioport.h> #include <linux/delay.h> -#include <linux/slab.h> #include <asm/segment.h> #include <asm/io.h> @@ -27,11 +25,32 @@ unsigned int __nongpreldata pci_probe = 1; -int __nongpreldata pcibios_last_bus = -1; -struct pci_bus *__nongpreldata pci_root_bus; struct pci_ops *__nongpreldata pci_root_ops; /* + * The accessible PCI window does not cover the entire CPU address space, but + * there are devices we want to access outside of that window, so we need to + * insert specific PCI bus resources instead of using the platform-level bus + * resources directly for the PCI root bus. + * + * These are configured and inserted by pcibios_init() and are attached to the + * root bus by pcibios_fixup_bus(). + */ +static struct resource pci_ioport_resource = { + .name = "PCI IO", + .start = 0, + .end = IO_SPACE_LIMIT, + .flags = IORESOURCE_IO, +}; + +static struct resource pci_iomem_resource = { + .name = "PCI mem", + .start = 0, + .end = -1, + .flags = IORESOURCE_MEM, +}; + +/* * Functions for accessing PCI configuration space */ @@ -200,89 +219,6 @@ static struct pci_ops * __init pci_check_direct(void) } /* - * Several buggy motherboards address only 16 devices and mirror - * them to next 16 IDs. We try to detect this `feature' on all - * primary buses (those containing host bridges as they are - * expected to be unique) and remove the ghost devices. - */ - -static void __init pcibios_fixup_ghosts(struct pci_bus *b) -{ - struct list_head *ln, *mn; - struct pci_dev *d, *e; - int mirror = PCI_DEVFN(16,0); - int seen_host_bridge = 0; - int i; - - for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { - d = pci_dev_b(ln); - if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST) - seen_host_bridge++; - for (mn=ln->next; mn != &b->devices; mn=mn->next) { - e = pci_dev_b(mn); - if (e->devfn != d->devfn + mirror || - e->vendor != d->vendor || - e->device != d->device || - e->class != d->class) - continue; - for(i=0; i<PCI_NUM_RESOURCES; i++) - if (e->resource[i].start != d->resource[i].start || - e->resource[i].end != d->resource[i].end || - e->resource[i].flags != d->resource[i].flags) - continue; - break; - } - if (mn == &b->devices) - return; - } - if (!seen_host_bridge) - return; - printk("PCI: Ignoring ghost devices on bus %02x\n", b->number); - - ln = &b->devices; - while (ln->next != &b->devices) { - d = pci_dev_b(ln->next); - if (d->devfn >= mirror) { - list_del(&d->global_list); - list_del(&d->bus_list); - kfree(d); - } else - ln = ln->next; - } -} - -/* - * Discover remaining PCI buses in case there are peer host bridges. - * We use the number of last PCI bus provided by the PCI BIOS. - */ -static void __init pcibios_fixup_peer_bridges(void) -{ - struct pci_bus bus; - struct pci_dev dev; - int n; - u16 l; - - if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) - return; - printk("PCI: Peer bridge fixup\n"); - for (n=0; n <= pcibios_last_bus; n++) { - if (pci_find_bus(0, n)) - continue; - bus.number = n; - bus.ops = pci_root_ops; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) - if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && - l != 0x0000 && l != 0xffff) { - printk("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); - printk("PCI: Discovered peer bus %02x\n", n); - pci_scan_bus(n, pci_root_ops, NULL); - break; - } - } -} - -/* * Exceptions for specific devices. Usually work-arounds for fatal design flaws. */ @@ -299,7 +235,7 @@ static void __init pci_fixup_umc_ide(struct pci_dev *d) d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO; } -static void __init pci_fixup_ide_bases(struct pci_dev *d) +static void pci_fixup_ide_bases(struct pci_dev *d) { int i; @@ -318,7 +254,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d) } } -static void __init pci_fixup_ide_trash(struct pci_dev *d) +static void pci_fixup_ide_trash(struct pci_dev *d) { int i; @@ -331,7 +267,7 @@ static void __init pci_fixup_ide_trash(struct pci_dev *d) d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0; } -static void __devinit pci_fixup_latency(struct pci_dev *d) +static void pci_fixup_latency(struct pci_dev *d) { /* * SiS 5597 and 5598 chipsets require latency timer set to @@ -352,19 +288,17 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); * are examined. */ -void __init pcibios_fixup_bus(struct pci_bus *bus) +void pcibios_fixup_bus(struct pci_bus *bus) { #if 0 printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number); #endif - pcibios_fixup_ghosts(bus); + pci_read_bridge_bases(bus); if (bus->number == 0) { - struct list_head *ln; struct pci_dev *dev; - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - dev = pci_dev_b(ln); + list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->devfn == 0) { dev->resource[0].start = 0; dev->resource[0].end = 0; @@ -383,6 +317,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) int __init pcibios_init(void) { struct pci_ops *dir = NULL; + LIST_HEAD(resources); if (!mb93090_mb00_detected) return -ENXIO; @@ -401,24 +336,38 @@ int __init pcibios_init(void) __reg_MB86943_pci_sl_mem_base = __region_CS2 + 0x08000000; mb(); - *(volatile unsigned long *)(__region_CS2+0x01300014) == 1; + /* enable PCI arbitration */ + __reg_MB86943_pci_arbiter = MB86943_PCIARB_EN; - ioport_resource.start = (__reg_MB86943_sl_pci_io_base << 9) & 0xfffffc00; - ioport_resource.end = (__reg_MB86943_sl_pci_io_range << 9) | 0x3ff; - ioport_resource.end += ioport_resource.start; + pci_ioport_resource.start = (__reg_MB86943_sl_pci_io_base << 9) & 0xfffffc00; + pci_ioport_resource.end = (__reg_MB86943_sl_pci_io_range << 9) | 0x3ff; + pci_ioport_resource.end += pci_ioport_resource.start; - printk("PCI IO window: %08lx-%08lx\n", ioport_resource.start, ioport_resource.end); + printk("PCI IO window: %08llx-%08llx\n", + (unsigned long long) pci_ioport_resource.start, + (unsigned long long) pci_ioport_resource.end); - iomem_resource.start = (__reg_MB86943_sl_pci_mem_base << 9) & 0xfffffc00; + pci_iomem_resource.start = (__reg_MB86943_sl_pci_mem_base << 9) & 0xfffffc00; + pci_iomem_resource.end = (__reg_MB86943_sl_pci_mem_range << 9) | 0x3ff; + pci_iomem_resource.end += pci_iomem_resource.start; - /* Reserve somewhere to write to flush posted writes. */ - iomem_resource.start += 0x400; + /* Reserve somewhere to write to flush posted writes. This is used by + * __flush_PCI_writes() from asm/io.h to force the write FIFO in the + * CPU-PCI bridge to flush as this doesn't happen automatically when a + * read is performed on the MB93090 development kit motherboard. + */ + pci_iomem_resource.start += 0x400; - iomem_resource.end = (__reg_MB86943_sl_pci_mem_range << 9) | 0x3ff; - iomem_resource.end += iomem_resource.start; + printk("PCI MEM window: %08llx-%08llx\n", + (unsigned long long) pci_iomem_resource.start, + (unsigned long long) pci_iomem_resource.end); + printk("PCI DMA memory: %08lx-%08lx\n", + dma_coherent_mem_start, dma_coherent_mem_end); - printk("PCI MEM window: %08lx-%08lx\n", iomem_resource.start, iomem_resource.end); - printk("PCI DMA memory: %08lx-%08lx\n", dma_coherent_mem_start, dma_coherent_mem_end); + if (insert_resource(&iomem_resource, &pci_iomem_resource) < 0) + panic("Unable to insert PCI IOMEM resource\n"); + if (insert_resource(&ioport_resource, &pci_ioport_resource) < 0) + panic("Unable to insert PCI IOPORT resource\n"); if (!pci_probe) return -ENXIO; @@ -432,10 +381,11 @@ int __init pcibios_init(void) } printk("PCI: Probing PCI hardware\n"); - pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); + pci_add_resource(&resources, &pci_ioport_resource); + pci_add_resource(&resources, &pci_iomem_resource); + pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); pcibios_irq_init(); - pcibios_fixup_peer_bridges(); pcibios_fixup_irqs(); pcibios_resource_survey(); @@ -449,9 +399,6 @@ char * __init pcibios_setup(char *str) if (!strcmp(str, "off")) { pci_probe = 0; return NULL; - } else if (!strncmp(str, "lastbus=", 8)) { - pcibios_last_bus = simple_strtol(str+8, NULL, 0); - return NULL; } return str; } @@ -460,8 +407,9 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) { int err; - if ((err = pcibios_enable_resources(dev, mask)) < 0) + if ((err = pci_enable_resources(dev, mask)) < 0) return err; - pcibios_enable_irq(dev); + if (!dev->msi_enabled) + pcibios_enable_irq(dev); return 0; } diff --git a/arch/frv/mm/Makefile b/arch/frv/mm/Makefile index fb8b1d860f4..1bca5ab8a6a 100644 --- a/arch/frv/mm/Makefile +++ b/arch/frv/mm/Makefile @@ -6,4 +6,4 @@ obj-y := init.o kmap.o obj-$(CONFIG_MMU) += \ pgalloc.o highmem.o fault.o extable.o cache-page.o tlb-flush.o tlb-miss.o \ - mmu-context.o dma-alloc.o unaligned.o elf-fdpic.o + mmu-context.o dma-alloc.o elf-fdpic.o diff --git a/arch/frv/mm/cache-page.c b/arch/frv/mm/cache-page.c index 0261cbe153b..8e09dae0ec3 100644 --- a/arch/frv/mm/cache-page.c +++ b/arch/frv/mm/cache-page.c @@ -26,11 +26,11 @@ void flush_dcache_page(struct page *page) dampr2 = __get_DAMPR(2); - vaddr = kmap_atomic(page, __KM_CACHE); + vaddr = kmap_atomic_primary(page); frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE); - kunmap_atomic(vaddr, __KM_CACHE); + kunmap_atomic_primary(vaddr); if (dampr2) { __set_DAMPR(2, dampr2); @@ -54,12 +54,12 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, dampr2 = __get_DAMPR(2); - vaddr = kmap_atomic(page, __KM_CACHE); + vaddr = kmap_atomic_primary(page); start = (start & ~PAGE_MASK) | (unsigned long) vaddr; frv_cache_wback_inv(start, start + len); - kunmap_atomic(vaddr, __KM_CACHE); + kunmap_atomic_primary(vaddr); if (dampr2) { __set_DAMPR(2, dampr2); diff --git a/arch/frv/mm/dma-alloc.c b/arch/frv/mm/dma-alloc.c index 342823aad75..7a73aaeae3a 100644 --- a/arch/frv/mm/dma-alloc.c +++ b/arch/frv/mm/dma-alloc.c @@ -21,7 +21,6 @@ * published by the Free Software Foundation. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/signal.h> #include <linux/sched.h> @@ -37,10 +36,11 @@ #include <linux/vmalloc.h> #include <linux/init.h> #include <linux/pci.h> +#include <linux/hardirq.h> +#include <linux/gfp.h> #include <asm/pgalloc.h> #include <asm/io.h> -#include <asm/hardirq.h> #include <asm/mmu_context.h> #include <asm/pgtable.h> #include <asm/mmu.h> @@ -115,9 +115,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle) */ if (order > 0) { struct page *rpage = virt_to_page(page); - - for (i = 1; i < (1 << order); i++) - set_page_count(rpage + i, 1); + split_page(rpage, order); } err = 0; diff --git a/arch/frv/mm/elf-fdpic.c b/arch/frv/mm/elf-fdpic.c index f5a653033fe..836f14707a6 100644 --- a/arch/frv/mm/elf-fdpic.c +++ b/arch/frv/mm/elf-fdpic.c @@ -13,6 +13,7 @@ #include <linux/mm.h> #include <linux/fs.h> #include <linux/elf-fdpic.h> +#include <asm/mman.h> /*****************************************************************************/ /* @@ -59,11 +60,15 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi unsigned long pgoff, unsigned long flags) { struct vm_area_struct *vma; - unsigned long limit; + struct vm_unmapped_area_info info; if (len > TASK_SIZE) return -ENOMEM; + /* handle MAP_FIXED */ + if (flags & MAP_FIXED) + return addr; + /* only honour a hint if we're not going to clobber something doing so */ if (addr) { addr = PAGE_ALIGN(addr); @@ -74,50 +79,35 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi } /* search between the bottom of user VM and the stack grow area */ - addr = PAGE_SIZE; - limit = (current->mm->start_stack - 0x00200000); - if (addr + len <= limit) { - limit -= len; - - if (addr <= limit) { - vma = find_vma(current->mm, PAGE_SIZE); - for (; vma; vma = vma->vm_next) { - if (addr > limit) - break; - if (addr + len <= vma->vm_start) - goto success; - addr = vma->vm_end; - } - } - } + info.flags = 0; + info.length = len; + info.low_limit = PAGE_SIZE; + info.high_limit = (current->mm->start_stack - 0x00200000); + info.align_mask = 0; + info.align_offset = 0; + addr = vm_unmapped_area(&info); + if (!(addr & ~PAGE_MASK)) + goto success; + VM_BUG_ON(addr != -ENOMEM); /* search from just above the WorkRAM area to the top of memory */ - addr = PAGE_ALIGN(0x80000000); - limit = TASK_SIZE - len; - if (addr <= limit) { - vma = find_vma(current->mm, addr); - for (; vma; vma = vma->vm_next) { - if (addr > limit) - break; - if (addr + len <= vma->vm_start) - goto success; - addr = vma->vm_end; - } - - if (!vma && addr <= limit) - goto success; - } + info.low_limit = PAGE_ALIGN(0x80000000); + info.high_limit = TASK_SIZE; + addr = vm_unmapped_area(&info); + if (!(addr & ~PAGE_MASK)) + goto success; + VM_BUG_ON(addr != -ENOMEM); #if 0 printk("[area] l=%lx (ENOMEM) f='%s'\n", - len, filp ? filp->f_dentry->d_name.name : ""); + len, filp ? filp->f_path.dentry->d_name.name : ""); #endif return -ENOMEM; success: #if 0 printk("[area] l=%lx ad=%lx f='%s'\n", - len, addr, filp ? filp->f_dentry->d_name.name : ""); + len, addr, filp ? filp->f_path.dentry->d_name.name : ""); #endif return addr; } /* end arch_get_unmapped_area() */ diff --git a/arch/frv/mm/extable.c b/arch/frv/mm/extable.c index caacf030ac7..6aea124f574 100644 --- a/arch/frv/mm/extable.c +++ b/arch/frv/mm/extable.c @@ -2,7 +2,6 @@ * linux/arch/frv/mm/extable.c */ -#include <linux/config.h> #include <linux/module.h> #include <linux/spinlock.h> #include <asm/uaccess.h> diff --git a/arch/frv/mm/fault.c b/arch/frv/mm/fault.c index 8b3eb50c510..9a66372fc7c 100644 --- a/arch/frv/mm/fault.c +++ b/arch/frv/mm/fault.c @@ -20,7 +20,6 @@ #include <linux/ptrace.h> #include <linux/hardirq.h> -#include <asm/system.h> #include <asm/pgtable.h> #include <asm/uaccess.h> #include <asm/gdb-stub.h> @@ -35,11 +34,12 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear struct vm_area_struct *vma; struct mm_struct *mm; unsigned long _pme, lrai, lrad, fixup; + unsigned long flags = 0; siginfo_t info; pgd_t *pge; pud_t *pue; pte_t *pte; - int write; + int fault; #if 0 const char *atxc[16] = { @@ -78,9 +78,12 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; + if (user_mode(__frame)) + flags |= FAULT_FLAG_USER; + down_read(&mm->mmap_sem); vma = find_vma(mm, ear0); @@ -129,7 +132,6 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear */ good_area: info.si_code = SEGV_ACCERR; - write = 0; switch (esr0 & ESR0_ATXC) { default: /* handle write to write protected page */ @@ -140,7 +142,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear #endif if (!(vma->vm_flags & VM_WRITE)) goto bad_area; - write = 1; + flags |= FAULT_FLAG_WRITE; break; /* handle read from protected page */ @@ -162,18 +164,18 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear * make sure we exit gracefully rather than endlessly redo * the fault. */ - switch (handle_mm_fault(mm, vma, ear0, write)) { - case VM_FAULT_MINOR: - current->min_flt++; - break; - case VM_FAULT_MAJOR: - current->maj_flt++; - break; - case VM_FAULT_SIGBUS: - goto do_sigbus; - default: - goto out_of_memory; + fault = handle_mm_fault(mm, vma, ear0, flags); + if (unlikely(fault & VM_FAULT_ERROR)) { + if (fault & VM_FAULT_OOM) + goto out_of_memory; + else if (fault & VM_FAULT_SIGBUS) + goto do_sigbus; + BUG(); } + if (fault & VM_FAULT_MAJOR) + current->maj_flt++; + else + current->min_flt++; up_read(&mm->mmap_sem); return; @@ -256,10 +258,10 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear */ out_of_memory: up_read(&mm->mmap_sem); - printk("VM: killing process %s\n", current->comm); - if (user_mode(__frame)) - do_exit(SIGKILL); - goto no_context; + if (!user_mode(__frame)) + goto no_context; + pagefault_out_of_memory(); + return; do_sigbus: up_read(&mm->mmap_sem); diff --git a/arch/frv/mm/highmem.c b/arch/frv/mm/highmem.c index 7f77db7fabc..bed9a9bd3c1 100644 --- a/arch/frv/mm/highmem.c +++ b/arch/frv/mm/highmem.c @@ -37,5 +37,53 @@ struct page *kmap_atomic_to_page(void *ptr) return virt_to_page(ptr); } +void *kmap_atomic(struct page *page) +{ + unsigned long paddr; + int type; + + pagefault_disable(); + type = kmap_atomic_idx_push(); + paddr = page_to_phys(page); + + switch (type) { + /* + * The first 4 primary maps are reserved for architecture code + */ + case 0: return __kmap_atomic_primary(0, paddr, 6); + case 1: return __kmap_atomic_primary(0, paddr, 7); + case 2: return __kmap_atomic_primary(0, paddr, 8); + case 3: return __kmap_atomic_primary(0, paddr, 9); + case 4: return __kmap_atomic_primary(0, paddr, 10); + + case 5 ... 5 + NR_TLB_LINES - 1: + return __kmap_atomic_secondary(type - 5, paddr); + + default: + BUG(); + return NULL; + } +} +EXPORT_SYMBOL(kmap_atomic); + +void __kunmap_atomic(void *kvaddr) +{ + int type = kmap_atomic_idx(); + switch (type) { + case 0: __kunmap_atomic_primary(0, 6); break; + case 1: __kunmap_atomic_primary(0, 7); break; + case 2: __kunmap_atomic_primary(0, 8); break; + case 3: __kunmap_atomic_primary(0, 9); break; + case 4: __kunmap_atomic_primary(0, 10); break; -EXPORT_SYMBOL(kmap_atomic_to_page); + case 5 ... 5 + NR_TLB_LINES - 1: + __kunmap_atomic_secondary(type - 5, kvaddr); + break; + + default: + BUG(); + } + kmap_atomic_idx_pop(); + pagefault_enable(); +} +EXPORT_SYMBOL(__kunmap_atomic); diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index 765088ea8a5..88a15974352 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -16,10 +16,10 @@ * - Copyright (C) 1995 Hamish Macdonald */ -#include <linux/config.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/pagemap.h> +#include <linux/gfp.h> #include <linux/swap.h> #include <linux/mm.h> #include <linux/kernel.h> @@ -27,12 +27,12 @@ #include <linux/types.h> #include <linux/bootmem.h> #include <linux/highmem.h> +#include <linux/module.h> #include <asm/setup.h> #include <asm/segment.h> #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/mmu_context.h> #include <asm/virtconvert.h> #include <asm/sections.h> @@ -40,8 +40,6 @@ #undef DEBUG -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - /* * BAD_PAGE is the page that is used for page faults when linux * is out-of-memory. Older versions of linux just did a @@ -57,38 +55,9 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); */ static unsigned long empty_bad_page_table; static unsigned long empty_bad_page; -unsigned long empty_zero_page; - -/*****************************************************************************/ -/* - * - */ -void show_mem(void) -{ - unsigned long i; - int free = 0, total = 0, reserved = 0, shared = 0; - - printk("\nMem-info:\n"); - show_free_areas(); - i = max_mapnr; - while (i-- > 0) { - struct page *page = &mem_map[i]; - - total++; - if (PageReserved(page)) - reserved++; - else if (!page_count(page)) - free++; - else - shared += page_count(page) - 1; - } - printk("%d pages of RAM\n",total); - printk("%d free pages\n",free); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - -} /* end show_mem() */ +unsigned long empty_zero_page; +EXPORT_SYMBOL(empty_zero_page); /*****************************************************************************/ /* @@ -99,7 +68,7 @@ void show_mem(void) */ void __init paging_init(void) { - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + unsigned long zones_size[MAX_NR_ZONES] = {0, }; /* allocate some pages for kernel housekeeping tasks */ empty_bad_page_table = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); @@ -109,15 +78,13 @@ void __init paging_init(void) memset((void *) empty_zero_page, 0, PAGE_SIZE); #ifdef CONFIG_HIGHMEM - if (num_physpages - num_mappedpages) { + if (get_num_physpages() - num_mappedpages) { pgd_t *pge; pud_t *pue; pmd_t *pme; pkmap_page_table = alloc_bootmem_pages(PAGE_SIZE); - memset(pkmap_page_table, 0, PAGE_SIZE); - pge = swapper_pg_dir + pgd_index_k(PKMAP_BASE); pue = pud_offset(pge, PKMAP_BASE); pme = pmd_offset(pue, PKMAP_BASE); @@ -127,10 +94,9 @@ void __init paging_init(void) /* distribute the allocatable pages across the various zones and pass them to the allocator */ - zones_size[ZONE_DMA] = max_low_pfn - min_low_pfn; - zones_size[ZONE_NORMAL] = 0; + zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; #ifdef CONFIG_HIGHMEM - zones_size[ZONE_HIGHMEM] = num_physpages - num_mappedpages; + zones_size[ZONE_HIGHMEM] = get_num_physpages() - num_mappedpages; #endif free_area_init(zones_size); @@ -148,75 +114,34 @@ void __init paging_init(void) */ void __init mem_init(void) { - unsigned long npages = (memory_end - memory_start) >> PAGE_SHIFT; - unsigned long tmp; -#ifdef CONFIG_MMU - unsigned long loop, pfn; - int datapages = 0; -#endif - int codek = 0, datak = 0; + unsigned long code_size = _etext - _stext; - /* this will put all memory onto the freelists */ - totalram_pages = free_all_bootmem(); + /* this will put all low memory onto the freelists */ + free_all_bootmem(); +#if defined(CONFIG_MMU) && defined(CONFIG_HIGHMEM) + { + unsigned long pfn; -#ifdef CONFIG_MMU - for (loop = 0 ; loop < npages ; loop++) - if (PageReserved(&mem_map[loop])) - datapages++; - -#ifdef CONFIG_HIGHMEM - for (pfn = num_physpages - 1; pfn >= num_mappedpages; pfn--) { - struct page *page = &mem_map[pfn]; - - ClearPageReserved(page); - set_page_count(page, 1); - __free_page(page); - totalram_pages++; + for (pfn = get_num_physpages() - 1; + pfn >= num_mappedpages; pfn--) + free_highmem_page(&mem_map[pfn]); } #endif - codek = ((unsigned long) &_etext - (unsigned long) &_stext) >> 10; - datak = datapages << (PAGE_SHIFT - 10); - -#else - codek = (_etext - _stext) >> 10; - datak = 0; //(_ebss - _sdata) >> 10; -#endif - - tmp = nr_free_pages() << PAGE_SHIFT; - printk("Memory available: %luKiB/%luKiB RAM, %luKiB/%luKiB ROM (%dKiB kernel code, %dKiB data)\n", - tmp >> 10, - npages << (PAGE_SHIFT - 10), - (rom_length > 0) ? ((rom_length >> 10) - codek) : 0, - rom_length >> 10, - codek, - datak - ); - + mem_init_print_info(NULL); + if (rom_length > 0 && rom_length >= code_size) + printk("Memory available: %luKiB/%luKiB ROM\n", + (rom_length - code_size) >> 10, rom_length >> 10); } /* end mem_init() */ /*****************************************************************************/ /* * free the memory that was only required for initialisation */ -void __init free_initmem(void) +void free_initmem(void) { #if defined(CONFIG_RAMKERNEL) && !defined(CONFIG_PROTECT_KERNEL) - unsigned long start, end, addr; - - start = PAGE_ALIGN((unsigned long) &__init_begin); /* round up */ - end = ((unsigned long) &__init_end) & PAGE_MASK; /* round down */ - - /* next to check that the page we free is not a partial page */ - for (addr = start; addr < end; addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - set_page_count(virt_to_page(addr), 1); - free_page(addr); - totalram_pages++; - } - - printk("Freeing unused kernel memory: %ldKiB freed (0x%lx - 0x%lx)\n", - (end - start) >> 10, start, end); + free_initmem_default(-1); #endif } /* end free_initmem() */ @@ -227,14 +152,6 @@ void __init free_initmem(void) #ifdef CONFIG_BLK_DEV_INITRD void __init free_initrd_mem(unsigned long start, unsigned long end) { - int pages = 0; - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(virt_to_page(start)); - set_page_count(virt_to_page(start), 1); - free_page(start); - totalram_pages++; - pages++; - } - printk("Freeing initrd memory: %dKiB freed\n", (pages * PAGE_SIZE) >> 10); + free_reserved_area((void *)start, (void *)end, -1, "initrd"); } /* end free_initrd_mem() */ #endif diff --git a/arch/frv/mm/kmap.c b/arch/frv/mm/kmap.c index 539f45e6d15..e9217e605aa 100644 --- a/arch/frv/mm/kmap.c +++ b/arch/frv/mm/kmap.c @@ -10,7 +10,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/mm.h> #include <linux/kernel.h> #include <linux/string.h> @@ -22,7 +21,6 @@ #include <asm/page.h> #include <asm/pgalloc.h> #include <asm/io.h> -#include <asm/system.h> #undef DEBUG @@ -31,24 +29,15 @@ * Map some physical address range into the kernel address space. */ -void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) +void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag) { - return (void *)physaddr; + return (void __iomem *)physaddr; } /* * Unmap a ioremap()ed region again */ -void iounmap(void *addr) -{ -} - -/* - * __iounmap unmaps nearly everything, so be careful - * it doesn't free currently pointer/page tables anymore but it - * wans't used anyway and might be added later. - */ -void __iounmap(void *addr, unsigned long size) +void iounmap(void volatile __iomem *addr) { } diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c index f2c6866fc88..81757d55a5b 100644 --- a/arch/frv/mm/mmu-context.c +++ b/arch/frv/mm/mmu-context.c @@ -54,9 +54,9 @@ static unsigned get_cxn(mm_context_t *ctx) /* find the first unallocated context number * - 0 is reserved for the kernel */ - cxn = find_next_zero_bit(&cxn_bitmap, NR_CXN, 1); + cxn = find_next_zero_bit(cxn_bitmap, NR_CXN, 1); if (cxn < NR_CXN) { - set_bit(cxn, &cxn_bitmap); + set_bit(cxn, cxn_bitmap); } else { /* none remaining - need to steal someone else's cxn */ @@ -138,7 +138,7 @@ void destroy_context(struct mm_struct *mm) cxn_pinned = -1; list_del_init(&ctx->id_link); - clear_bit(ctx->id, &cxn_bitmap); + clear_bit(ctx->id, cxn_bitmap); __flush_tlb_mm(ctx->id); ctx->id = 0; } @@ -181,7 +181,7 @@ int cxn_pin_by_pid(pid_t pid) /* get a handle on the mm_struct */ read_lock(&tasklist_lock); - tsk = find_task_by_pid(pid); + tsk = find_task_by_vpid(pid); if (tsk) { ret = -EINVAL; diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c index f76dd03ddd9..41907d25ed3 100644 --- a/arch/frv/mm/pgalloc.c +++ b/arch/frv/mm/pgalloc.c @@ -10,15 +10,15 @@ */ #include <linux/sched.h> -#include <linux/slab.h> +#include <linux/gfp.h> #include <linux/mm.h> #include <linux/highmem.h> +#include <linux/quicklist.h> #include <asm/pgalloc.h> #include <asm/page.h> #include <asm/cacheflush.h> pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((aligned(PAGE_SIZE))); -kmem_cache_t *pgd_cache; pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) { @@ -28,7 +28,7 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) return pte; } -struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) +pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) { struct page *page; @@ -37,8 +37,14 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address) #else page = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); #endif - if (page) - clear_highpage(page); + if (!page) + return NULL; + + clear_highpage(page); + if (!pgtable_page_ctor(page)) { + __free_page(page); + return NULL; + } flush_dcache_page(page); return page; } @@ -75,7 +81,7 @@ void __set_pmd(pmd_t *pmdptr, unsigned long pmd) * checks at dup_mmap(), exec(), and other mmlist addition points * could be used. The locking scheme was chosen on the basis of * manfred's recommendations and having no core impact whatsoever. - * -- wli + * -- nyc */ DEFINE_SPINLOCK(pgd_lock); struct page *pgd_list; @@ -100,7 +106,7 @@ static inline void pgd_list_del(pgd_t *pgd) set_page_private(next, (unsigned long) pprev); } -void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_ctor(void *pgd) { unsigned long flags; @@ -120,7 +126,7 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) } /* never called when PTRS_PER_PMD > 1 */ -void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) +void pgd_dtor(void *pgd) { unsigned long flags; /* can be called from interrupt context */ @@ -131,29 +137,21 @@ void pgd_dtor(void *pgd, kmem_cache_t *cache, unsigned long unused) pgd_t *pgd_alloc(struct mm_struct *mm) { - pgd_t *pgd; - - pgd = kmem_cache_alloc(pgd_cache, GFP_KERNEL); - if (!pgd) - return pgd; - - return pgd; + return quicklist_alloc(0, GFP_KERNEL, pgd_ctor); } -void pgd_free(pgd_t *pgd) +void pgd_free(struct mm_struct *mm, pgd_t *pgd) { /* in the non-PAE case, clear_page_tables() clears user pgd entries */ - kmem_cache_free(pgd_cache, pgd); + quicklist_free(0, pgd_dtor, pgd); } void __init pgtable_cache_init(void) { - pgd_cache = kmem_cache_create("pgd", - PTRS_PER_PGD * sizeof(pgd_t), - PTRS_PER_PGD * sizeof(pgd_t), - 0, - pgd_ctor, - pgd_dtor); - if (!pgd_cache) - panic("pgtable_cache_init(): Cannot create pgd cache"); } + +void check_pgt_cache(void) +{ + quicklist_trim(0, pgd_dtor, 25, 16); +} + diff --git a/arch/frv/mm/tlb-flush.S b/arch/frv/mm/tlb-flush.S index 6f43c74c5d9..79b3c70910a 100644 --- a/arch/frv/mm/tlb-flush.S +++ b/arch/frv/mm/tlb-flush.S @@ -10,7 +10,6 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/page.h> #include <asm/ptrace.h> diff --git a/arch/frv/mm/tlb-miss.S b/arch/frv/mm/tlb-miss.S index 8729f7d7c6e..f3ac019bb18 100644 --- a/arch/frv/mm/tlb-miss.S +++ b/arch/frv/mm/tlb-miss.S @@ -10,14 +10,12 @@ */ #include <linux/sys.h> -#include <linux/config.h> #include <linux/linkage.h> #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/highmem.h> #include <asm/spr-regs.h> - .section .text + .section .text..tlbmiss .balign 4 .globl __entry_insn_mmu_miss diff --git a/arch/frv/mm/unaligned.c b/arch/frv/mm/unaligned.c deleted file mode 100644 index 09b361443fc..00000000000 --- a/arch/frv/mm/unaligned.c +++ /dev/null @@ -1,218 +0,0 @@ -/* unaligned.c: unalignment fixup handler for CPUs on which it is supported (FR451 only) - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/config.h> -#include <linux/sched.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/types.h> -#include <linux/user.h> -#include <linux/string.h> -#include <linux/linkage.h> -#include <linux/init.h> - -#include <asm/setup.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -#if 0 -#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ ) -#else -#define kdebug(fmt, ...) do {} while(0) -#endif - -#define _MA_SIGNED 0x01 -#define _MA_HALF 0x02 -#define _MA_WORD 0x04 -#define _MA_DWORD 0x08 -#define _MA_SZ_MASK 0x0e -#define _MA_LOAD 0x10 -#define _MA_STORE 0x20 -#define _MA_UPDATE 0x40 -#define _MA_IMM 0x80 - -#define _MA_LDxU _MA_LOAD | _MA_UPDATE -#define _MA_LDxI _MA_LOAD | _MA_IMM -#define _MA_STxU _MA_STORE | _MA_UPDATE -#define _MA_STxI _MA_STORE | _MA_IMM - -static const uint8_t tbl_LDGRk_reg[0x40] = { - [0x02] = _MA_LOAD | _MA_HALF | _MA_SIGNED, /* LDSH @(GRi,GRj),GRk */ - [0x03] = _MA_LOAD | _MA_HALF, /* LDUH @(GRi,GRj),GRk */ - [0x04] = _MA_LOAD | _MA_WORD, /* LD @(GRi,GRj),GRk */ - [0x05] = _MA_LOAD | _MA_DWORD, /* LDD @(GRi,GRj),GRk */ - [0x12] = _MA_LDxU | _MA_HALF | _MA_SIGNED, /* LDSHU @(GRi,GRj),GRk */ - [0x13] = _MA_LDxU | _MA_HALF, /* LDUHU @(GRi,GRj),GRk */ - [0x14] = _MA_LDxU | _MA_WORD, /* LDU @(GRi,GRj),GRk */ - [0x15] = _MA_LDxU | _MA_DWORD, /* LDDU @(GRi,GRj),GRk */ -}; - -static const uint8_t tbl_STGRk_reg[0x40] = { - [0x01] = _MA_STORE | _MA_HALF, /* STH @(GRi,GRj),GRk */ - [0x02] = _MA_STORE | _MA_WORD, /* ST @(GRi,GRj),GRk */ - [0x03] = _MA_STORE | _MA_DWORD, /* STD @(GRi,GRj),GRk */ - [0x11] = _MA_STxU | _MA_HALF, /* STHU @(GRi,GRj),GRk */ - [0x12] = _MA_STxU | _MA_WORD, /* STU @(GRi,GRj),GRk */ - [0x13] = _MA_STxU | _MA_DWORD, /* STDU @(GRi,GRj),GRk */ -}; - -static const uint8_t tbl_LDSTGRk_imm[0x80] = { - [0x31] = _MA_LDxI | _MA_HALF | _MA_SIGNED, /* LDSHI @(GRi,d12),GRk */ - [0x32] = _MA_LDxI | _MA_WORD, /* LDI @(GRi,d12),GRk */ - [0x33] = _MA_LDxI | _MA_DWORD, /* LDDI @(GRi,d12),GRk */ - [0x36] = _MA_LDxI | _MA_HALF, /* LDUHI @(GRi,d12),GRk */ - [0x51] = _MA_STxI | _MA_HALF, /* STHI @(GRi,d12),GRk */ - [0x52] = _MA_STxI | _MA_WORD, /* STI @(GRi,d12),GRk */ - [0x53] = _MA_STxI | _MA_DWORD, /* STDI @(GRi,d12),GRk */ -}; - - -/*****************************************************************************/ -/* - * see if we can handle the exception by fixing up a misaligned memory access - */ -int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0) -{ - unsigned long insn, addr, *greg; - int GRi, GRj, GRk, D12, op; - - union { - uint64_t _64; - uint32_t _32[2]; - uint16_t _16; - uint8_t _8[8]; - } x; - - if (!(esr0 & ESR0_EAV) || !(epcr0 & EPCR0_V) || !(ear0 & 7)) - return -EAGAIN; - - epcr0 &= EPCR0_PC; - - if (__frame->pc != epcr0) { - kdebug("MISALIGN: Execution not halted on excepting instruction\n"); - BUG(); - } - - if (__get_user(insn, (unsigned long *) epcr0) < 0) - return -EFAULT; - - /* determine the instruction type first */ - switch ((insn >> 18) & 0x7f) { - case 0x2: - /* LDx @(GRi,GRj),GRk */ - op = tbl_LDGRk_reg[(insn >> 6) & 0x3f]; - break; - - case 0x3: - /* STx GRk,@(GRi,GRj) */ - op = tbl_STGRk_reg[(insn >> 6) & 0x3f]; - break; - - default: - op = tbl_LDSTGRk_imm[(insn >> 18) & 0x7f]; - break; - } - - if (!op) - return -EAGAIN; - - kdebug("MISALIGN: pc=%08lx insn=%08lx ad=%08lx op=%02x\n", epcr0, insn, ear0, op); - - memset(&x, 0xba, 8); - - /* validate the instruction parameters */ - greg = (unsigned long *) &__frame->tbr; - - GRi = (insn >> 12) & 0x3f; - GRk = (insn >> 25) & 0x3f; - - if (GRi > 31 || GRk > 31) - return -ENOENT; - - if (op & _MA_DWORD && GRk & 1) - return -EINVAL; - - if (op & _MA_IMM) { - D12 = insn & 0xfff; - asm ("slli %0,#20,%0 ! srai %0,#20,%0" : "=r"(D12) : "0"(D12)); /* sign extend */ - addr = (GRi ? greg[GRi] : 0) + D12; - } - else { - GRj = (insn >> 0) & 0x3f; - if (GRj > 31) - return -ENOENT; - addr = (GRi ? greg[GRi] : 0) + (GRj ? greg[GRj] : 0); - } - - if (addr != ear0) { - kdebug("MISALIGN: Calculated addr (%08lx) does not match EAR0 (%08lx)\n", - addr, ear0); - return -EFAULT; - } - - /* check the address is okay */ - if (user_mode(__frame) && ___range_ok(ear0, 8) < 0) - return -EFAULT; - - /* perform the memory op */ - if (op & _MA_STORE) { - /* perform a store */ - x._32[0] = 0; - if (GRk != 0) { - if (op & _MA_HALF) { - x._16 = greg[GRk]; - } - else { - x._32[0] = greg[GRk]; - } - } - if (op & _MA_DWORD) - x._32[1] = greg[GRk + 1]; - - kdebug("MISALIGN: Store GR%d { %08x:%08x } -> %08lx (%dB)\n", - GRk, x._32[1], x._32[0], addr, op & _MA_SZ_MASK); - - if (__memcpy_user((void *) addr, &x, op & _MA_SZ_MASK) != 0) - return -EFAULT; - } - else { - /* perform a load */ - if (__memcpy_user(&x, (void *) addr, op & _MA_SZ_MASK) != 0) - return -EFAULT; - - if (op & _MA_HALF) { - if (op & _MA_SIGNED) - asm ("slli %0,#16,%0 ! srai %0,#16,%0" - : "=r"(x._32[0]) : "0"(x._16)); - else - asm ("sethi #0,%0" - : "=r"(x._32[0]) : "0"(x._16)); - } - - kdebug("MISALIGN: Load %08lx (%dB) -> GR%d, { %08x:%08x }\n", - addr, op & _MA_SZ_MASK, GRk, x._32[1], x._32[0]); - - if (GRk != 0) - greg[GRk] = x._32[0]; - if (op & _MA_DWORD) - greg[GRk + 1] = x._32[1]; - } - - /* update the base pointer if required */ - if (op & _MA_UPDATE) - greg[GRi] = addr; - - /* well... we've done that insn */ - __frame->pc = __frame->pc + 4; - - return 0; -} /* end handle_misalignment() */ |
